From 1d47d5af1a4b114cf3e56b7f4e174cb5878ba30d Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Thu, 26 Jan 2012 11:01:28 +0000 Subject: [PATCH] - new get_session functions --- src/transport/plugin_transport_http.c | 231 +++++++++++++++++++++++++- src/transport/plugin_transport_tcp.c | 57 +++---- 2 files changed, 251 insertions(+), 37 deletions(-) diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c index 684612617..ecf32c943 100644 --- a/src/transport/plugin_transport_http.c +++ b/src/transport/plugin_transport_http.c @@ -386,7 +386,7 @@ http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) } struct Session * -lookup_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, +lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, struct Session *session, const void *addr, size_t addrlen, int force_address) { @@ -462,6 +462,29 @@ lookup_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, return s; } +struct Session * +lookup_session (struct Plugin *plugin, + const struct GNUNET_HELLO_Address *address) +{ + struct Session *tmp = NULL; + + tmp = plugin->head; + if (tmp == NULL) + return NULL; + while (tmp != NULL) + { + if (0 != memcmp (&address->peer, &tmp->target, sizeof (struct GNUNET_PeerIdentity))) + continue; + if ((address->address_length != tmp->addrlen) && + (0 != memcmp (address->address, tmp->addr, tmp->addrlen))) + continue; + + return tmp; + } + return NULL; +} + + void delete_session (struct Session *s) { @@ -508,6 +531,198 @@ notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, delete_session (s); } +/** + * Creates a new session the transport service will use to send data to the + * peer + * + * @param cls the plugin + * @param address the address + * @return the session or NULL of max connections exceeded + */ + +static const struct Session * +http_get_session (void *cls, + const struct GNUNET_HELLO_Address *address) +{ + struct Plugin *plugin = cls; + struct Session * s = NULL; + struct GNUNET_ATS_Information ats; + size_t addrlen; + + GNUNET_assert (plugin != NULL); + GNUNET_assert (address != NULL); + + /* find existing session */ + s = lookup_session (plugin, address); + if (s != NULL) + return s; + + if (plugin->max_connections <= plugin->cur_connections) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name, + "Maximum number of connections reached, " + "cannot connect to peer `%s'\n", GNUNET_i2s (&address->peer)); + return NULL; + } + + /* create new session */ + addrlen = address->address_length; + + GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) || + (addrlen == sizeof (struct IPv4HttpAddress))); + + s = GNUNET_malloc (sizeof (struct Session)); + memcpy (&s->target, &address->peer, sizeof (struct GNUNET_PeerIdentity)); + s->plugin = plugin; + s->addr = GNUNET_malloc (address->address_length); + memcpy (s->addr, address->address, address->address_length); + s->addrlen = addrlen; + s->next = NULL; + s->next_receive = GNUNET_TIME_absolute_get_zero (); + + s->ats_address_network_type = htonl (GNUNET_ATS_NET_UNSPECIFIED); + + /* Get ATS type */ + if ((addrlen == sizeof (struct IPv4HttpAddress)) && (address->address != NULL)) + { + struct IPv4HttpAddress *a4 = (struct IPv4HttpAddress *) address->address; + struct sockaddr_in s4; + + s4.sin_family = AF_INET; + s4.sin_addr.s_addr = a4->ipv4_addr; + s4.sin_port = a4->u4_port; +#if HAVE_SOCKADDR_IN_SIN_LEN + s4.sin_len = sizeof (struct sockaddr_in); +#endif + ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in)); + } + if ((addrlen == sizeof (struct IPv6HttpAddress)) && (address->address != NULL)) + { + struct IPv6HttpAddress *a6 = (struct IPv6HttpAddress *) address->address; + struct sockaddr_in6 s6; + + s6.sin6_family = AF_INET6; + s6.sin6_addr = a6->ipv6_addr; + s6.sin6_port = a6->u6_port; +#if HAVE_SOCKADDR_IN_SIN_LEN + s6.sin6_len = sizeof (struct sockaddr_in6); +#endif + ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &s6, sizeof (struct sockaddr_in6)); + } + s->ats_address_network_type = ats.value; + + /* add new session */ + GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); + /* initiate new connection */ + if (GNUNET_SYSERR == client_connect (s)) + { + if (s != NULL) + { + GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); + delete_session (s); + } + return NULL; + } + + return s; +} + +/** + * Function that can be used by the transport service to transmit + * a message using the plugin. Note that in the case of a + * peer disconnecting, the continuation MUST be called + * prior to the disconnect notification itself. This function + * will be called with this peer's HELLO message to initiate + * a fresh connection to another peer. + * + * @param cls closure + * @param session which session must be used + * @param msgbuf the message to transmit + * @param msgbuf_size number of bytes in 'msgbuf' + * @param priority how important is the message (most plugins will + * ignore message priority and just FIFO) + * @param to how long to wait at most for the transmission (does not + * require plugins to discard the message after the timeout, + * just advisory for the desired delay; most plugins will ignore + * this as well) + * @param cont continuation to call once the message has + * been transmitted (or if the transport is ready + * for the next transmission call; or if the + * peer disconnected...); can be NULL + * @param cont_cls closure for cont + * @return number of bytes used (on the physical network, with overheads); + * -1 on hard errors (i.e. address invalid); 0 is a legal value + * and does NOT mean that the message was not transmitted (DV) + */ +static ssize_t +http_plugin_send (void *cls, + struct Session *session, + const char *msgbuf, size_t msgbuf_size, + unsigned int priority, + struct GNUNET_TIME_Relative to, + GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) +{ + struct Plugin *plugin = cls; + struct HTTP_Message *msg; + struct Session *tmp; + size_t res = -1; + + GNUNET_assert (plugin != NULL); + GNUNET_assert (session != NULL); + + /* lookup if session is really existing */ + tmp = plugin->head; + while (tmp != NULL) + { + if ((tmp == session) && + (0 == memcmp (&session->target, &tmp->target, sizeof (struct GNUNET_PeerIdentity))) && + (session->addrlen != tmp->addrlen) && + (0 != memcmp (session->addr, tmp->addr, tmp->addrlen))) + break; + tmp = tmp->next; + } + if (tmp == NULL) + { + GNUNET_break_op (0); + return res; + } + + /* create new message and schedule */ + + msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size); + msg->next = NULL; + msg->size = msgbuf_size; + msg->pos = 0; + msg->buf = (char *) &msg[1]; + msg->transmit_cont = cont; + msg->transmit_cont_cls = cont_cls; + memcpy (msg->buf, msgbuf, msgbuf_size); + + if (session->inbound == GNUNET_NO) + { +#if DEBUG_HTTP + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, + "Using outbound client session %p to send to `%session'\n", session, + GNUNET_i2s (&session->target)); +#endif + + client_send (session, msg); + res = msgbuf_size; + } + if (session->inbound == GNUNET_YES) + { +#if DEBUG_HTTP + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, + "Using inbound server %p session to send to `%session'\n", session, + GNUNET_i2s (&session->target)); +#endif + + server_send (session, msg); + res = msgbuf_size; + } + return res; + +} /** * Function that can be used by the transport service to transmit @@ -546,7 +761,7 @@ notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, * and does NOT mean that the message was not transmitted (DV) */ static ssize_t -http_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, +http_plugin_send_old (void *cls, const struct GNUNET_PeerIdentity *target, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, struct Session *session, const void *addr, size_t addrlen, int force_address, @@ -576,10 +791,8 @@ http_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, if (addrlen != 0) GNUNET_assert ((addrlen == sizeof (struct IPv4HttpAddress)) || (addrlen == sizeof (struct IPv6HttpAddress))); - - /* look for existing connection */ - s = lookup_session (plugin, target, session, addr, addrlen, 1); + s = lookup_session_old (plugin, target, session, addr, addrlen, 1); #if DEBUG_HTTP GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "%s existing session: %s\n", @@ -588,7 +801,6 @@ http_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, GNUNET_YES)) ? "inbound" : "outbound"); #endif - /* create new outbound connection */ if (s == NULL) { @@ -605,6 +817,7 @@ http_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, "Initiiating new connection to peer `%s'\n", GNUNET_i2s (target)); #endif +/* AAAAAAAAAAAAAAAAAAA */ int res = GNUNET_OK; struct GNUNET_ATS_Information ats; if ((addrlen == sizeof (struct IPv4HttpAddress)) && (addr != NULL)) @@ -658,6 +871,8 @@ http_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, } } + /* real sending */ + msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size); msg->next = NULL; msg->size = msgbuf_size; @@ -1380,11 +1595,13 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls) plugin->env = env; api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); api->cls = plugin; - api->send = &http_plugin_send; + api->send = &http_plugin_send_old; api->disconnect = &http_plugin_disconnect; api->address_pretty_printer = &http_plugin_address_pretty_printer; api->check_address = &http_plugin_address_suggested; api->address_to_string = &http_plugin_address_to_string; + api->get_session = &http_get_session; + api->send_with_session = &http_plugin_send; #if BUILD_HTTPS plugin->name = "transport-https"; diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index a51a5bff3..19bf8d304 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c @@ -1231,16 +1231,11 @@ tcp_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, */ static ssize_t tcp_plugin_send_new (void *cls, - const struct - GNUNET_PeerIdentity * - target, - const char *msg, - size_t msgbuf_size, - uint32_t priority, - struct GNUNET_TIME_Relative timeout, - struct Session * session, - GNUNET_TRANSPORT_TransmitContinuation - cont, void *cont_cls) + struct Session *session, + const char *msgbuf, size_t msgbuf_size, + unsigned int priority, + struct GNUNET_TIME_Relative to, + GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin * plugin = cls; struct PendingMessage *pm; @@ -1256,9 +1251,9 @@ tcp_plugin_send_new (void *cls, /* create new message entry */ pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); pm->msg = (const char *) &pm[1]; - memcpy (&pm[1], msg, msgbuf_size); + memcpy (&pm[1], msgbuf, msgbuf_size); pm->message_size = msgbuf_size; - pm->timeout = GNUNET_TIME_relative_to_absolute (timeout); + pm->timeout = GNUNET_TIME_relative_to_absolute (to); pm->transmit_cont = cont; pm->transmit_cont_cls = cont_cls; @@ -1310,10 +1305,8 @@ int session_it (void *cls, * @param addrlen length of addr * @return the session if the address is valid, NULL otherwise */ -const void * tcp_plugin_create_session (void *cls, - const struct GNUNET_PeerIdentity *target, - const void *addr, - size_t addrlen) +const const struct Session * tcp_plugin_create_session (void *cls, + const struct GNUNET_HELLO_Address *address) { struct Plugin * plugin = cls; struct Session * session = NULL; @@ -1327,11 +1320,15 @@ const void * tcp_plugin_create_session (void *cls, const struct IPv4TcpAddress *t4; const struct IPv6TcpAddress *t6; unsigned int is_natd = GNUNET_NO; + size_t addrlen = address->address_length; + + GNUNET_assert (plugin != NULL); + GNUNET_assert (address != NULL); if (addrlen == sizeof (struct IPv6TcpAddress)) { - GNUNET_assert (NULL != addr); /* make static analysis happy */ - t6 = addr; + GNUNET_assert (NULL != address->address); /* make static analysis happy */ + t6 = address->address; af = AF_INET6; memset (&a6, 0, sizeof (a6)); #if HAVE_SOCKADDR_IN_SIN_LEN @@ -1347,8 +1344,8 @@ const void * tcp_plugin_create_session (void *cls, } else if (addrlen == sizeof (struct IPv4TcpAddress)) { - GNUNET_assert (NULL != addr); /* make static analysis happy */ - t4 = addr; + GNUNET_assert (NULL != address->address); /* make static analysis happy */ + t4 = address->address; af = AF_INET; memset (&a4, 0, sizeof (a4)); #if HAVE_SOCKADDR_IN_SIN_LEN @@ -1371,12 +1368,12 @@ const void * tcp_plugin_create_session (void *cls, } /* look for existing session */ - if (GNUNET_CONTAINER_multihashmap_contains(plugin->sessionmap, &target->hashPubKey)) + if (GNUNET_CONTAINER_multihashmap_contains(plugin->sessionmap, &address->peer.hashPubKey)) { struct SessionItCtx si_ctx; si_ctx.addr = &sbs; si_ctx.addrlen = sbs; - GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessionmap, &target->hashPubKey, &session_it, &si_ctx); + GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessionmap, &address->peer.hashPubKey, &session_it, &si_ctx); if (si_ctx.result != NULL) session = si_ctx.result; return session; @@ -1391,23 +1388,23 @@ const void * tcp_plugin_create_session (void *cls, if ((is_natd == GNUNET_YES) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (plugin->nat_wait_conns, - &target->hashPubKey))) + &address->peer.hashPubKey))) return NULL; /* Only do one NAT punch attempt per peer identity */ if ((is_natd == GNUNET_YES) && (NULL != plugin->nat) && (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (plugin->nat_wait_conns, - &target->hashPubKey))) + &address->peer.hashPubKey))) { #if DEBUG_TCP_NAT GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", _("Found valid IPv4 NAT address (creating session)!\n")); #endif - session = create_session (plugin, target, NULL, GNUNET_YES); + session = create_session (plugin, &address->peer, NULL, GNUNET_YES); GNUNET_assert (session != NULL); GNUNET_assert (GNUNET_CONTAINER_multihashmap_put - (plugin->nat_wait_conns, &target->hashPubKey, session, + (plugin->nat_wait_conns, &address->peer.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) == GNUNET_OK); #if DEBUG_TCP_NAT GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", @@ -1437,11 +1434,11 @@ const void * tcp_plugin_create_session (void *cls, GNUNET_i2s (target), GNUNET_a2s (sb, sbs)); #endif session = create_session (plugin, - target, + &address->peer, GNUNET_SERVER_connect_socket (plugin->server, sa), GNUNET_NO); session->connect_addr = GNUNET_malloc (addrlen); - memcpy (session->connect_addr, addr, addrlen); + memcpy (session->connect_addr, address->address, addrlen); session->connect_alen = addrlen; if (addrlen != 0) { @@ -1452,7 +1449,7 @@ const void * tcp_plugin_create_session (void *cls, else GNUNET_break (0); - GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &address->peer.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); /* Send TCP Welcome */ process_pending_messages (session); @@ -2286,7 +2283,7 @@ libgnunet_plugin_transport_tcp_init (void *cls) api->send = &tcp_plugin_send; api->send_with_session = &tcp_plugin_send_new; - api->create_session = &tcp_plugin_create_session; + api->get_session = &tcp_plugin_create_session; api->disconnect = &tcp_plugin_disconnect; api->address_pretty_printer = &tcp_plugin_address_pretty_printer; -- 2.25.1