⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of GNUnet     (C) 2001, 2002, 2004, 2005, 2006, 2007 Christian Grothoff (and other contributing authors)     GNUnet is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published     by the Free Software Foundation; either version 2, or (at your     option) any later version.     GNUnet is distributed in the hope that it will be useful, but     WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     General Public License for more details.     You should have received a copy of the GNU General Public License     along with GNUnet; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file applications/transport/transport.c * @brief Methods to access the transport layer. * @author Christian Grothoff */#include "platform.h"#include "gnunet_util.h"#include "gnunet_protocols.h"#include "gnunet_core.h"#include "gnunet_identity_service.h"#include "gnunet_transport_service.h"#define DEBUG_TRANSPORT GNUNET_NOstatic GNUNET_CoreAPIForTransport ctapi;static GNUNET_CoreAPIForPlugins *coreAPI;static GNUNET_Identity_ServiceAPI *identity;/** * Note that this array MUST not be modified * (in size/NULLs) after gnunetd has started * to go multi-threaded! */static GNUNET_TransportAPI **tapis = NULL;static unsigned int tapis_count = 0;static unsigned long long hello_live;static struct GNUNET_Mutex *tapis_lock;static struct GNUNET_Mutex *lock;static struct GNUNET_GE_Context *ectx;#define HELLO_RECREATE_FREQ (5 * GNUNET_CRON_MINUTES)#define CHECK_IT GNUNET_NO#if CHECK_IT#include "check.c"#else#define CHECK(s) do {} while(0)#endif/** * Close the session with the remote node. * @return GNUNET_OK on success, GNUNET_SYSERR on error */static intassertAssociated (GNUNET_TSession * tsession, const char *token){  int i;  if (tsession == NULL)    {      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;    }  GNUNET_mutex_lock (lock);  for (i = 0; i < tsession->token_count; i++)    {      if (0 == strcmp (tsession->tokens[i], token))        {          i = -1;          break;        }    }  if (i != -1)    {      GNUNET_GE_BREAK (NULL, 0);      GNUNET_mutex_unlock (lock);      return GNUNET_SYSERR;    }  GNUNET_mutex_unlock (lock);  return GNUNET_OK;}/** * Create signed hello for this transport and put it into * the cache tapi->hello. */static voidcreateSignedhello (void *cls){  GNUNET_TransportAPI *tapi = cls;  GNUNET_mutex_lock (tapis_lock);  GNUNET_free_non_null (tapi->hello);  tapi->hello = tapi->hello_create ();  if (NULL == tapi->hello)    {      GNUNET_mutex_unlock (tapis_lock);      return;    }  memcpy (&tapi->hello->publicKey,          identity->getPublicPrivateKey (), sizeof (GNUNET_RSA_PublicKey));  memcpy (&tapi->hello->senderIdentity,          coreAPI->my_identity, sizeof (GNUNET_PeerIdentity));  tapi->hello->expiration_time =    htonl (GNUNET_get_time_int32 (NULL) + hello_live);  tapi->hello->header.type = htons (GNUNET_P2P_PROTO_HELLO);  tapi->hello->header.size = htons (GNUNET_sizeof_hello (tapi->hello));  if (GNUNET_SYSERR == identity->signData (&(tapi->hello)->senderIdentity,                                           GNUNET_sizeof_hello (tapi->hello) -                                           sizeof (GNUNET_RSA_Signature) -                                           sizeof (GNUNET_RSA_PublicKey) -                                           sizeof (GNUNET_MessageHeader),                                           &tapi->hello->signature))    {      GNUNET_free (tapi->hello);      tapi->hello = NULL;      GNUNET_GE_BREAK (ectx, 0);    }  GNUNET_mutex_unlock (tapis_lock);}/** * Is this transport mechanism available (for sending)? * @return GNUNET_YES or GNUNET_NO */static intisTransportAvailable (unsigned short ttype){  if (ttype >= tapis_count)    return GNUNET_NO;  if (NULL == tapis[ttype])    return GNUNET_NO;  return GNUNET_YES;}/** * Add an implementation of a transport protocol. */static intaddTransport (GNUNET_TransportAPI * tapi){  if (tapi->protocol_number >= tapis_count)    GNUNET_array_grow (tapis, tapis_count, tapi->protocol_number + 1);  if (tapis[tapi->protocol_number] != NULL)    {      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;    }  tapis[tapi->protocol_number] = tapi;  tapi->hello = NULL;  GNUNET_cron_add_job (coreAPI->cron,                       &createSignedhello,                       HELLO_RECREATE_FREQ, HELLO_RECREATE_FREQ, tapi);  return GNUNET_OK;}/** * Convert hello to string. */static inthelloToAddress (const GNUNET_MessageHello * hello,                void **sa, unsigned int *sa_len){  unsigned short prot;  prot = ntohs (hello->protocol);  if ((prot >= tapis_count) || (tapis[prot] == NULL))    {      GNUNET_GE_LOG (ectx,                     GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER,                     _                     ("Converting peer address to string failed, transport type %d not supported\n"),                     ntohs (hello->protocol));      return GNUNET_SYSERR;    }  return tapis[prot]->hello_to_address (hello, sa, sa_len);}/** * Iterate over all available transport mechanisms. * @param callback the method to call on each transport API implementation * @param data second argument to callback */static intforEachTransport (GNUNET_TransportCallback callback, void *data){  int i;  int ret;  ret = 0;  for (i = 0; i < tapis_count; i++)    {      if (tapis[i] != NULL)        {          ret++;          if (callback != NULL)            callback (tapis[i], data);        }    }  return ret;}/** * Connect to a remote host using the advertised * transport layer. This may fail if the appropriate * transport mechanism is not available. * * @param hello the hello of the target node * @param may_reuse can an existing connection be *        re-used? * @return session on success, NULL on error */static GNUNET_TSession *transportConnect (const GNUNET_MessageHello * hello,                  const char *token, int may_reuse){  unsigned short prot;  GNUNET_TSession *tsession;  prot = ntohs (hello->protocol);  if ((prot >= tapis_count) || (tapis[prot] == NULL))    {      GNUNET_GE_LOG (ectx,                     GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER |                     GNUNET_GE_ADMIN,                     _                     ("Transport connection attempt failed, transport type %d not supported\n"),                     prot);      return NULL;    }  tsession = NULL;  if (GNUNET_OK != tapis[prot]->connect (hello, &tsession, may_reuse))    return NULL;  tsession->ttype = prot;  GNUNET_mutex_lock (lock);  GNUNET_array_append (tsession->tokens, tsession->token_count, token);  CHECK (tsession);  GNUNET_mutex_unlock (lock);  GNUNET_GE_BREAK (NULL, GNUNET_OK == assertAssociated (tsession, token));  return tsession;}static GNUNET_TSession *transportConnectFreely (const GNUNET_PeerIdentity * peer, int useTempList,                        const char *token){  int i;  GNUNET_MessageHello *hello;  unsigned int *perm;  GNUNET_TSession *ret;  unsigned int hc;#if DEBUG_TRANSPORT  GNUNET_EncName enc;#endif  hc = 0;  ret = NULL;  perm = GNUNET_permute (GNUNET_RANDOM_QUALITY_WEAK, tapis_count);  for (i = 0; i < tapis_count; i++)    {      if (tapis[perm[i]] == NULL)        continue;      hello = identity->identity2Hello (peer, perm[i], useTempList);      if (hello == NULL)        continue;      hc++;      ret = transportConnect (hello, token, GNUNET_YES);      GNUNET_free (hello);      if (ret != NULL)        break;    }  GNUNET_free (perm);  if (ret == NULL)    {#if DEBUG_TRANSPORT      GNUNET_hash_to_enc (&peer->hashPubKey, &enc);      GNUNET_GE_LOG (ectx,                     GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_ADMIN,                     _                     ("Transport failed to connect to peer `%s' (%u HELLOs known, none worked)\n"),                     &enc, hc);#endif    }  return ret;}/** * A (core) Session is to be associated with a transport session. The * transport service may want to know in order to call back on the * core if the connection is being closed. * * @param tsession the session handle passed along *   from the call to receive that was made by the transport *   layer * @return GNUNET_OK if the session could be associated, *         GNUNET_SYSERR if not. */static inttransportAssociate (GNUNET_TSession * tsession, const char *token){  int ret;  if ((tsession == NULL) ||      (tsession->ttype >= tapis_count) || (tapis[tsession->ttype] == NULL))    return GNUNET_SYSERR;  ret = tapis[tsession->ttype]->associate (tsession);  GNUNET_mutex_lock (lock);  if (ret == GNUNET_OK)    GNUNET_array_append (tsession->tokens, tsession->token_count, token);  CHECK (tsession);  GNUNET_mutex_unlock (lock);  if (ret == GNUNET_OK)    GNUNET_GE_BREAK (NULL, GNUNET_OK == assertAssociated (tsession, token));  return ret;}/** * Get the cost of a message in for the given transport mechanism. */static unsigned inttransportGetCost (int ttype){  if ((ttype >= tapis_count) || (tapis[ttype] == NULL))    return GNUNET_SYSERR;       /* -1 = INFTY */  return tapis[ttype]->cost;}/** * Send a message. * @param tsession the transport session identifying the connection * @param msg the message to send * @param size the size of the message * @param important * @return GNUNET_OK on success, GNUNET_SYSERR on persistent error, GNUNET_NO on *         temporary error */static inttransportSend (GNUNET_TSession * tsession,               const void *msg, unsigned int size, int important){  if (tsession == NULL)    {      GNUNET_GE_LOG (ectx,                     GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_BULK,                     "Transmission attempted on uni-directional pipe, failing.\n");      return GNUNET_SYSERR;     /* can't do that, can happen for unidirectional pipes                                   that call core with GNUNET_TSession being NULL. */    }  GNUNET_mutex_lock (lock);  CHECK (tsession);  GNUNET_mutex_unlock (lock);  if ((tsession->ttype >= tapis_count) || (tapis[tsession->ttype] == NULL))    {      GNUNET_GE_LOG (ectx,                     GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,                     _                     ("Transmission attempt failed, transport type %d unknown.\n"),                     tsession->ttype);      return GNUNET_SYSERR;    }  return tapis[tsession->ttype]->send (tsession, msg, size, important);}/** * Close the session with the remote node. * @return GNUNET_OK on success, GNUNET_SYSERR on error */static inttransportDisconnect (GNUNET_TSession * tsession, const char *token){  int i;  if (tsession == NULL)    {      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;    }  if ((tsession->ttype >= tapis_count) || (tapis[tsession->ttype] == NULL))    {      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;    }  GNUNET_mutex_lock (lock);  CHECK (tsession);  for (i = 0; i < tsession->token_count; i++)    {      if (0 == strcmp (tsession->tokens[i], token))        {          tsession->tokens[i] = tsession->tokens[tsession->token_count - 1];          GNUNET_array_grow (tsession->tokens,                             tsession->token_count,                             tsession->token_count - 1);          i = -1;          break;        }    }  if (i != -1)    {      GNUNET_GE_BREAK (ectx, 0);      GNUNET_GE_LOG (ectx,                     GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_USER |                     GNUNET_GE_IMMEDIATE,                     "Illegal attempt to disconnect transport; do not have token `%s'\n",                     token);      GNUNET_mutex_unlock (lock);      return GNUNET_SYSERR;    }  GNUNET_mutex_unlock (lock);  i = tapis[tsession->ttype]->disconnect (tsession);  GNUNET_GE_BREAK (NULL, i == GNUNET_OK);       /* should never fail */  return i;}/** * Verify that a hello is ok. Call a method * if the verification was successful. * @return GNUNET_OK if the attempt to verify is on the way, *        GNUNET_SYSERR if the transport mechanism is not supported */static inttransportVerifyHello (const GNUNET_MessageHello * hello){  unsigned short prot;  if ((ntohs (hello->header.size) != GNUNET_sizeof_hello (hello)) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -