From: Christian Grothoff Date: Thu, 23 Feb 2012 16:41:30 +0000 (+0000) Subject: TG: attached are the following patches for GNUnet: X-Git-Tag: initial-import-from-subversion-38251~14692 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=151acb7d8657724bcb2334b636aa3aefc8273ddf;p=oweals%2Fgnunet.git TG: attached are the following patches for GNUnet: - 1: added GNUNET_i2s_full - full variant of GNUNET_i2s - 2: GNUNET_CRYPTO_hash_from_string2 with additional length parameter, useful to prevent an additional strlen call when the caller already knows the length - 3: custom mst callbacks for the server, enables using the server with a custom parser - 4: added GNUNET_SERVER_client_set_finish_pending_write - enables changing the server behavior to finish pending writes when closing the connection Best regards, Gabor Adam Toth --- diff --git a/AUTHORS b/AUTHORS index b4edb0e86..61de3fab0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -31,6 +31,7 @@ Enrico Scholz Eric Haumant Eric Noack Felix von Leitner [ diet libc snprintf for win32 ] +Gabor Adam Toth Gerd Knorr Glenn McGrath Hendrik Pagenhardt diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h index 487bd32da..3221ad868 100644 --- a/src/include/gnunet_common.h +++ b/src/include/gnunet_common.h @@ -438,6 +438,17 @@ GNUNET_h2s_full (const GNUNET_HashCode * hc); const char * GNUNET_i2s (const struct GNUNET_PeerIdentity *pid); +/** + * Convert a peer identity to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param pid the peer identity + * @return string form of the pid; will be overwritten by next + * call to GNUNET_i2s. + */ +const char * +GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid); /** * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 75aabe75f..6e37266a2 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -407,12 +407,25 @@ GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, /** * Convert ASCII encoding back to GNUNET_CRYPTO_hash + * * @param enc the encoding + * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing) * @param result where to store the GNUNET_CRYPTO_hash code * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding */ int -GNUNET_CRYPTO_hash_from_string (const char *enc, GNUNET_HashCode * result); +GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, + GNUNET_HashCode * result); + + +/** + * Convert ASCII encoding back to GNUNET_CRYPTO_hash + * @param enc the encoding + * @param result where to store the GNUNET_CRYPTO_hash code + * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding + */ +#define GNUNET_CRYPTO_hash_from_string(enc, result) \ + GNUNET_CRYPTO_hash_from_string2 (enc, strlen(enc), result) /** diff --git a/src/include/gnunet_server_lib.h b/src/include/gnunet_server_lib.h index 2856fd838..7fb8ae76c 100644 --- a/src/include/gnunet_server_lib.h +++ b/src/include/gnunet_server_lib.h @@ -239,6 +239,14 @@ GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client, struct GNUNET_TIME_Relative timeout); +/** + * Set if a client should finish a pending write when disconnecting. + */ +void +GNUNET_SERVER_client_set_finish_pending_write (struct GNUNET_SERVER_Client *client, + int finish); + + /** * Disable the warning the server issues if a message is not acknowledged * in a timely fashion. Use this call if a client is intentionally delayed @@ -636,6 +644,64 @@ void GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst); +/** + * Signature of a function to create a custom tokenizer. + * + * @param cls closure from 'GNUNET_SERVER_set_callbacks' + * @param client handle to client the tokenzier will be used for + * @return handle to custom tokenizer ('mst') + */ +typedef void* (*GNUNET_SERVER_MstCreateCallback) (void *cls, + struct GNUNET_SERVER_Client *client); + +/** + * Signature of a function to destroy a custom tokenizer. + * + * @param cls closure from 'GNUNET_SERVER_set_callbacks' + * @param mst custom tokenizer handle + */ +typedef void (*GNUNET_SERVER_MstDestroyCallback) (void *cls, void *mst); + +/** + * Signature of a function to destroy a custom tokenizer. + * + * @param cls closure from 'GNUNET_SERVER_set_callbacks' + * @param mst custom tokenizer handle + * @param client_identity ID of client for which this is a buffer, + * can be NULL (will be passed back to 'cb') + * @param buf input data to add + * @param size number of bytes in buf + * @param purge should any excess bytes in the buffer be discarded + * (i.e. for packet-based services like UDP) + * @param one_shot only call callback once, keep rest of message in buffer + * @return GNUNET_OK if we are done processing (need more data) + * GNUNET_NO if one_shot was set and we have another message ready + * GNUNET_SYSERR if the data stream is corrupt + */ +typedef int (*GNUNET_SERVER_MstReceiveCallback) (void *cls, void *mst, + struct GNUNET_SERVER_Client *client, + const char *buf, size_t size, + int purge, int one_shot); + + +/** + * Change functions used by the server to tokenize the message stream. + * (very rarely used). + * + * @param server server to modify + * @param create new tokenizer initialization function + * @param destroy new tokenizer destruction function + * @param receive new tokenizer receive function + * @param cls closure for 'create', 'receive', 'destroy' + */ +void +GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server, + GNUNET_SERVER_MstCreateCallback create, + GNUNET_SERVER_MstDestroyCallback destroy, + GNUNET_SERVER_MstReceiveCallback receive, + void *cls); + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/util/common_logging.c b/src/util/common_logging.c index 59de96226..e19aa8c7c 100644 --- a/src/util/common_logging.c +++ b/src/util/common_logging.c @@ -948,6 +948,23 @@ GNUNET_i2s (const struct GNUNET_PeerIdentity *pid) return (const char *) ret.encoding; } +/** + * Convert a peer identity to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param pid the peer identity + * @return string form of the pid; will be overwritten by next + * call to GNUNET_i2s. + */ +const char * +GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid) +{ + static struct GNUNET_CRYPTO_HashAsciiEncoded ret; + + GNUNET_CRYPTO_hash_to_enc (&pid->hashPubKey, &ret); + return (const char *) ret.encoding; +} /** diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index 0350df545..976c59992 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c @@ -322,7 +322,8 @@ GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding */ int -GNUNET_CRYPTO_hash_from_string (const char *enc, GNUNET_HashCode * result) +GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, + GNUNET_HashCode * result) { unsigned int rpos; unsigned int wpos; @@ -330,7 +331,7 @@ GNUNET_CRYPTO_hash_from_string (const char *enc, GNUNET_HashCode * result) unsigned int vbit; int ret; - if (strlen (enc) != sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1) + if (enclen != sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1) return GNUNET_SYSERR; vbit = 2; /* padding! */ diff --git a/src/util/server.c b/src/util/server.c index 6f1b8cdb4..24804d2d2 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -140,6 +140,10 @@ struct GNUNET_SERVER_Handle */ int clients_ignore_shutdown; + GNUNET_SERVER_MstCreateCallback mst_create; + GNUNET_SERVER_MstDestroyCallback mst_destroy; + GNUNET_SERVER_MstReceiveCallback mst_receive; + void *mst_cls; }; @@ -157,7 +161,7 @@ struct GNUNET_SERVER_Client /** * Processing of incoming data. */ - struct GNUNET_SERVER_MessageStreamTokenizer *mst; + void *mst; /** * Server that this client belongs to. @@ -242,6 +246,11 @@ struct GNUNET_SERVER_Client */ int receive_pending; + /** + * Finish pending write when disconnecting? + */ + int finish_pending_write; + /** * Persist the file handle for this client no matter what happens, * force the OS to close once the process actually dies. Should only @@ -597,6 +606,20 @@ GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server, } +void +GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server, + GNUNET_SERVER_MstCreateCallback create, + GNUNET_SERVER_MstDestroyCallback destroy, + GNUNET_SERVER_MstReceiveCallback receive, + void *cls) +{ + server->mst_create = create; + server->mst_destroy = destroy; + server->mst_receive = receive; + server->mst_cls = cls; +} + + /** * Task run to warn about missing calls to 'GNUNET_SERVER_receive_done'. * @@ -776,9 +799,14 @@ process_mst (struct GNUNET_SERVER_Client *client, int ret) LOG (GNUNET_ERROR_TYPE_DEBUG, "Server processes additional messages instantly.\n"); #endif - ret = - GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO, - GNUNET_YES); + if (client->server->mst_receive != NULL) + ret = + client->server->mst_receive (client->server->mst_cls, client->mst, + client, NULL, 0, GNUNET_NO, GNUNET_YES); + else + ret = + GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO, + GNUNET_YES); } #if DEBUG_SERVER LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -857,9 +885,16 @@ process_incoming (void *cls, const void *buf, size_t available, #endif GNUNET_SERVER_client_keep (client); client->last_activity = now; - ret = - GNUNET_SERVER_mst_receive (client->mst, client, buf, available, GNUNET_NO, - GNUNET_YES); + + if (server->mst_receive != NULL) + ret = + client->server->mst_receive (client->server->mst_cls, client->mst, + client, buf, available, GNUNET_NO, GNUNET_YES); + else + ret = + GNUNET_SERVER_mst_receive (client->mst, client, buf, available, GNUNET_NO, + GNUNET_YES); + process_mst (client, ret); } @@ -966,6 +1001,14 @@ GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server, client->receive_pending = GNUNET_YES; client->callback = NULL; client->callback_cls = NULL; + + if (server->mst_create != NULL) + client->mst = + server->mst_create (server->mst_cls, client); + else + client->mst = + GNUNET_SERVER_mst_create (&client_message_tokenizer_callback, server); + GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, client->idle_timeout, &process_incoming, client); @@ -989,6 +1032,14 @@ GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client, } +void +GNUNET_SERVER_client_set_finish_pending_write (struct GNUNET_SERVER_Client *client, + int finish) +{ + client->finish_pending_write = finish; +} + + /** * Notify the server that the given client handle should * be kept (keeps the connection up if possible, increments @@ -1137,10 +1188,9 @@ GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client) } rc = client->reference_count; - if (client->server != NULL) + if (client->shutdown_now != GNUNET_YES) { server = client->server; - client->server = NULL; client->shutdown_now = GNUNET_YES; prev = NULL; pos = server->clients; @@ -1190,8 +1240,13 @@ GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client) if (client->persist == GNUNET_YES) GNUNET_CONNECTION_persist_ (client->connection); - GNUNET_CONNECTION_destroy (client->connection, GNUNET_NO); - GNUNET_SERVER_mst_destroy (client->mst); + GNUNET_CONNECTION_destroy (client->connection, client->finish_pending_write); + + if (client->server->mst_destroy != NULL) + client->server->mst_destroy (client->server->mst_cls, client->mst); + else + GNUNET_SERVER_mst_destroy (client->mst); + GNUNET_free (client); } @@ -1326,7 +1381,7 @@ GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success) #endif return; } - if (client->server == NULL) + if ((client->server == NULL) || (GNUNET_YES == client->shutdown_now)) { GNUNET_SERVER_client_disconnect (client); return;