📄 pingpong.c
字号:
/* entry was valid for one time only */ memset (entry, 0, sizeof (PingPongEntry)); matched++; } } GNUNET_mutex_unlock (pingPongLock);#if DEBUG_PINGPONG GNUNET_hash_to_enc (&sender->hashPubKey, &enc); GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Received PONG from `%s' matched %u peers.\n", &enc, matched);#endif if (matched == 0) {#if DEBUG_PINGPONG GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_ADMIN, _("Could not match PONG against any PING. " "Try increasing MAX_PING_PONG constant.\n"));#endif } return GNUNET_OK;}/** * Handler for a pong. */static intplaintextPongReceived (const GNUNET_PeerIdentity * sender, const GNUNET_MessageHeader * msg, GNUNET_TSession * session){ int i; const P2P_pingpong_MESSAGE *pmsg; PingPongEntry *entry; int matched;#if DEBUG_PINGPONG GNUNET_EncName enc;#endif pmsg = (const P2P_pingpong_MESSAGE *) msg; if ((ntohs (msg->size) != sizeof (P2P_pingpong_MESSAGE)) || (0 != memcmp (sender, &pmsg->receiver, sizeof (GNUNET_PeerIdentity)))) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER | GNUNET_GE_DEVELOPER, _("Received malformed `%s' message. Dropping.\n"), "pong"); return GNUNET_SYSERR; /* bad pong */ } if (stats != NULL) stats->change (stat_plaintextPongReceived, 1); matched = 0; GNUNET_mutex_lock (pingPongLock); for (i = 0; i < MAX_PING_PONG; i++) { entry = &pingPongs[i]; if (((int) ntohl (pmsg->challenge) == entry->challenge) && (0 == memcmp (sender, &entry->receiverIdentity, sizeof (GNUNET_PeerIdentity))) && (entry->plaintext == GNUNET_YES)) { entry->method (entry->data); /* entry was valid for one time only */ memset (entry, 0, sizeof (PingPongEntry)); matched++; } } GNUNET_mutex_unlock (pingPongLock);#if DEBUG_PINGPONG GNUNET_hash_to_enc (&sender->hashPubKey, &enc); GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Received plaintext PONG from `%s' matched %u peers.\n", &enc, matched);#endif if (matched == 0) {#if DEBUG_PINGPONG GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_ADMIN, _("Could not match PONG against any PING. " "Try increasing MAX_PING_PONG constant.\n"));#endif } return GNUNET_OK;}/** * Create a ping a host an call a method if a reply comes back. * Does NOT send the ping message but rather returns it * to the caller. The caller is responsible for both sending * and freeing the message. * * @param receiver the peer that should be PINGed * @param method the method to call if a PONG comes back * @param data an argument to pass to the method. * @param plaintext is the PONG expected to be in plaintext (GNUNET_YES/GNUNET_NO) * @returns NULL on error, otherwise the PING message */static GNUNET_MessageHeader *createPing (const GNUNET_PeerIdentity * receiver, GNUNET_CronJob method, void *data, int plaintext, int challenge){ int i; int j; GNUNET_Int32Time min; PingPongEntry *entry; GNUNET_Int32Time now; P2P_pingpong_MESSAGE *pmsg; GNUNET_mutex_lock (pingPongLock); now = GNUNET_get_time_int32 (&min); /* set both, tricky... */ j = -1; for (i = 0; i < MAX_PING_PONG; i++) if (min > pingPongs[i].sendTime) { min = pingPongs[i].sendTime; j = i; } if (j == -1) { /* all send this second!? */ GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_ADMIN, _("Cannot create PING, table full. " "Try increasing MAX_PING_PONG.\n")); GNUNET_mutex_unlock (pingPongLock); return NULL; } entry = &pingPongs[j]; entry->sendTime = now; entry->method = method; entry->plaintext = plaintext; GNUNET_free_non_null (entry->data); entry->data = data; entry->receiverIdentity = *receiver; pmsg = GNUNET_malloc (sizeof (P2P_pingpong_MESSAGE)); pmsg->header.size = htons (sizeof (P2P_pingpong_MESSAGE)); pmsg->header.type = htons (GNUNET_P2P_PROTO_PING); pmsg->receiver = *receiver; entry->challenge = challenge; pmsg->challenge = htonl (challenge); GNUNET_mutex_unlock (pingPongLock); if (stats != NULL) stats->change (stat_pingCreated, 1); return &pmsg->header;}/** * Ping a host an call a method if a reply comes back. * * @param receiver the peer that should be PINGed * @param usePlaintext send the PING in plaintext (GNUNET_YES/GNUNET_NO) * @param method the method to call if a PONG comes back * @param data an argument to pass to the method. * @returns GNUNET_OK on success, GNUNET_SYSERR on error */static intinitiatePing (const GNUNET_PeerIdentity * receiver, GNUNET_CronJob method, void *data, int usePlaintext, int challenge){ GNUNET_MessageHeader *pmsg; pmsg = createPing (receiver, method, data, usePlaintext, challenge); if (pmsg == NULL) return GNUNET_SYSERR; if (usePlaintext == GNUNET_YES) { if (GNUNET_OK != connection_send_plaintext (receiver, (const P2P_pingpong_MESSAGE *) pmsg)) { GNUNET_free (pmsg); return GNUNET_SYSERR; } if (stats != NULL) stats->change (stat_plaintextPingSent, 1); } else { coreAPI->ciphertext_send (receiver, pmsg, GNUNET_EXTREME_PRIORITY, 0); if (stats != NULL) stats->change (stat_ciphertextPingSent, 1); } GNUNET_free (pmsg); return GNUNET_OK;}/** * Initialize the pingpong module. */GNUNET_Pingpong_ServiceAPI *provide_module_pingpong (GNUNET_CoreAPIForPlugins * capi){ static GNUNET_Pingpong_ServiceAPI ret; ectx = capi->ectx; GNUNET_GE_ASSERT (ectx, sizeof (P2P_pingpong_MESSAGE) == 72); coreAPI = capi; identity = capi->service_request ("identity"); if (identity == NULL) { GNUNET_GE_BREAK (capi->ectx, 0); return NULL; } transport = capi->service_request ("transport"); if (transport == NULL) { GNUNET_GE_BREAK (capi->ectx, 0); capi->service_release (identity); return NULL; } stats = capi->service_request ("stats"); if (stats != NULL) { stat_encryptedPongReceived = stats->create (gettext_noop ("# encrypted PONG messages received")); stat_plaintextPongReceived = stats->create (gettext_noop ("# plaintext PONG messages received")); stat_pingReceived = stats->create (gettext_noop ("# encrypted PING messages received")); stat_pingCreated = stats->create (gettext_noop ("# PING messages created")); stat_pongSent = stats->create (gettext_noop ("# encrypted PONG messages sent")); stat_plaintextPingSent = stats->create (gettext_noop ("# plaintext PING messages sent")); stat_ciphertextPingSent = stats->create (gettext_noop ("# encrypted PING messages sent")); stat_plaintextPongSent = stats->create (gettext_noop ("# plaintext PONG messages sent")); stat_plaintextPongFailed = stats->create (gettext_noop ("# plaintext PONG transmissions failed")); } pingPongLock = capi->global_lock_get (); pingPongs = (PingPongEntry *) GNUNET_malloc (sizeof (PingPongEntry) * MAX_PING_PONG); memset (pingPongs, 0, sizeof (PingPongEntry) * MAX_PING_PONG); GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_USER | GNUNET_GE_REQUEST, _ ("`%s' registering handlers %d %d (plaintext and ciphertext)\n"), "pingpong", GNUNET_P2P_PROTO_PING, GNUNET_P2P_PROTO_PONG); capi->p2p_ciphertext_handler_register (GNUNET_P2P_PROTO_PING, &pingReceived); capi->p2p_ciphertext_handler_register (GNUNET_P2P_PROTO_PONG, &pongReceived); capi->p2p_plaintext_handler_register (GNUNET_P2P_PROTO_PING, &plaintextPingReceived); capi->p2p_plaintext_handler_register (GNUNET_P2P_PROTO_PONG, &plaintextPongReceived); ret.ping = &initiatePing; ret.pingUser = &createPing; ret.ping_size = sizeof (P2P_pingpong_MESSAGE); return &ret;}/** * Shutdown the pingpong module. */intrelease_module_pingpong (){ int i; coreAPI->service_release (stats); stats = NULL; coreAPI->service_release (transport); transport = NULL; coreAPI->service_release (identity); identity = NULL; for (i = 0; i < MAX_PING_PONG; i++) GNUNET_free_non_null (pingPongs[i].data); GNUNET_free (pingPongs); coreAPI->p2p_ciphertext_handler_unregister (GNUNET_P2P_PROTO_PING, &pingReceived); coreAPI->p2p_ciphertext_handler_unregister (GNUNET_P2P_PROTO_PONG, &pongReceived); coreAPI->p2p_plaintext_handler_unregister (GNUNET_P2P_PROTO_PING, &plaintextPingReceived); coreAPI->p2p_plaintext_handler_unregister (GNUNET_P2P_PROTO_PONG, &plaintextPongReceived); coreAPI = NULL; return GNUNET_OK;}/* end of pingpong.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -