#include "gnunet_container_lib.h"
#include "gnunet_transport_plugin.h"
#include "gnunet_os_lib.h"
+#include "gnunet_nat_lib.h"
#include "microhttpd.h"
#include <curl/curl.h>
*/
#define HTTP_CONNECT_TIMEOUT 30
-
/**
* Network format for IPv4 addresses.
*/
struct IPv4HttpAddress
{
- /**
- * Linked list next
- */
- struct IPv4HttpAddress * next;
-
- /**
- * Linked list previous
- */
- struct IPv4HttpAddress * prev;
-
/**
* IPv4 address, in network byte order.
*/
/**
* Port number, in network byte order.
*/
- uint16_t u_port GNUNET_PACKED;
-
+ uint16_t port GNUNET_PACKED;
};
-
/**
- * Network format for IPv6 addresses.
+ * Wrapper to manage IPv4 addresses
*/
-struct IPv6HttpAddress
+struct IPv4HttpAddressWrapper
{
/**
* Linked list next
*/
- struct IPv6HttpAddress * next;
+ struct IPv4HttpAddressWrapper * next;
/**
* Linked list previous
*/
- struct IPv6HttpAddress * prev;
+ struct IPv4HttpAddressWrapper * prev;
+ struct IPv4HttpAddress * addr;
+};
+
+/**
+ * Network format for IPv6 addresses.
+ */
+struct IPv6HttpAddress
+{
/**
* IPv6 address.
*/
/**
* Port number, in network byte order.
*/
- uint16_t u6_port GNUNET_PACKED;
+ uint16_t port GNUNET_PACKED;
};
+/**
+ * Wrapper for IPv4 addresses.
+ */
+struct IPv6HttpAddressWrapper
+{
+ /**
+ * Linked list next
+ */
+ struct IPv6HttpAddressWrapper * next;
+
+ /**
+ * Linked list previous
+ */
+ struct IPv6HttpAddressWrapper * prev;
+
+ struct IPv6HttpAddress * addr;
+};
/**
* Message to send using http
*/
CURLM * multi_handle;
+ /**
+ * Our handle to the NAT module.
+ */
+ struct GNUNET_NAT_Handle *nat;
+
/**
* ipv4 DLL head
*/
- struct IPv4HttpAddress * ipv4_addr_head;
+ struct IPv4HttpAddressWrapper * ipv4_addr_head;
/**
* ipv4 DLL tail
*/
- struct IPv4HttpAddress * ipv4_addr_tail;
+ struct IPv4HttpAddressWrapper * ipv4_addr_tail;
/**
* ipv6 DLL head
*/
- struct IPv6HttpAddress * ipv6_addr_head;
+ struct IPv6HttpAddressWrapper * ipv6_addr_head;
/**
* ipv6 DLL tail
*/
- struct IPv6HttpAddress * ipv6_addr_tail;
+ struct IPv6HttpAddressWrapper * ipv6_addr_tail;
/**
* Our ASCII encoded, hashed peer identity
*/
int use_ipv4;
+ /**
+ * use local addresses?
+ */
+ int use_localaddresses;
+
+ /**
+ * maximum number of connections
+ */
+ int max_connect_per_transport;
+
+ /**
+ * Current number of connections;
+ */
+ int current_connections;
+
/**
* Closure passed by MHD to the mhd_logger function
*/
#endif
};
+/**
+ * Context for address to string conversion.
+ */
+struct PrettyPrinterContext
+{
+ /**
+ * Function to call with the result.
+ */
+ GNUNET_TRANSPORT_AddressStringCallback asc;
+
+ /**
+ * Clsoure for 'asc'.
+ */
+ void *asc_cls;
+
+ /**
+ * Port to add after the IP address.
+ */
+ uint16_t port;
+};
+
/**
* Function called for a quick conversion of the binary address to
GNUNET_asprintf(&url,
"%s://%s/%s;%u", PROTOCOL_PREFIX, addr_str,
(char *) (&plugin->my_ascii_hash_ident),id);
- GNUNET_free_non_null(addr_str);
return url;
}
"Freeing context for peer `%s'\n",
GNUNET_i2s(&pc->identity));
#endif
- GNUNET_CONTAINER_multihashmap_remove (plugin->peers, &pc->identity.hashPubKey, pc);
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (plugin->peers,
+ &pc->identity.hashPubKey,
+ pc));
while (ps!=NULL)
{
plugin->env->session_end(plugin, &pc->identity, ps);
}
+#if 0
+static int check_localaddress (const struct sockaddr *addr, socklen_t addrlen)
+{
+ uint32_t res = 0;
+ int local = GNUNET_NO;
+ int af = addr->sa_family;
+ switch (af)
+ {
+ case AF_INET:
+ {
+ uint32_t netmask = 0x7F000000;
+ uint32_t address = ntohl (((struct sockaddr_in *) addr)->sin_addr.s_addr);
+ res = (address >> 24) ^ (netmask >> 24);
+ if (res != 0)
+ local = GNUNET_NO;
+ else
+ local = GNUNET_YES;
+#if DEBUG_HTTP
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking IPv4 address `%s': %s\n", GNUNET_a2s (addr, addrlen), (local==GNUNET_YES) ? "local" : "global");
+#endif
+ break;
+ }
+ case AF_INET6:
+ {
+ if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr) ||
+ IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
+ local = GNUNET_YES;
+ else
+ local = GNUNET_NO;
+#if DEBUG_HTTP
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking IPv6 address `%s' : %s\n", GNUNET_a2s (addr, addrlen), (local==GNUNET_YES) ? "local" : "global");
+#endif
+ break;
+ }
+ }
+ return local;
+}
+
+
/**
* Add the IP of our network interface to the list of
* our external IP addresses.
struct IPv6HttpAddress * t6;
int af;
+ if (plugin->use_localaddresses == GNUNET_NO)
+ {
+ if (GNUNET_YES == check_localaddress (addr, addrlen))
+ {
+#if DEBUG_HTTP
+ GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+ PROTOCOL_PREFIX,
+ "Not notifying transport of address `%s' (local address)\n",
+ GNUNET_a2s (addr, addrlen));
+#endif
+ return GNUNET_OK;
+ }
+ }
+
GNUNET_assert(cls !=NULL);
af = addr->sa_family;
- if ( (af == AF_INET) &&
- (plugin->use_ipv4 == GNUNET_YES) &&
- (plugin->bind6_address == NULL) )
- {
- struct in_addr bnd_cmp = ((struct sockaddr_in *) addr)->sin_addr;
+ if ((af == AF_INET) &&
+ (plugin->use_ipv4 == GNUNET_YES) &&
+ (plugin->bind6_address == NULL) ) {
+
+ struct in_addr bnd_cmp = ((struct sockaddr_in *) addr)->sin_addr;
t4 = GNUNET_malloc(sizeof(struct IPv4HttpAddress));
- /* Not skipping loopback addresses
- if (INADDR_LOOPBACK == ntohl(((struct sockaddr_in *) addr)->sin_addr.s_addr))
- {
+ // Not skipping loopback addresses
+
- return GNUNET_OK;
- }
- */
t4->ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
- t4->u_port = htons (plugin->port_inbound);
- if (plugin->bind4_address != NULL)
- {
- if (0 == memcmp(&plugin->bind4_address->sin_addr, &bnd_cmp, sizeof (struct in_addr)))
- {
- GNUNET_CONTAINER_DLL_insert(plugin->ipv4_addr_head,plugin->ipv4_addr_tail,t4);
- plugin->env->notify_address(plugin->env->cls,
- PROTOCOL_PREFIX,
- t4, sizeof (struct IPv4HttpAddress),
- GNUNET_TIME_UNIT_FOREVER_REL);
- return GNUNET_OK;
- }
- GNUNET_free (t4);
- return GNUNET_OK;
- }
+ t4->port = htons (plugin->port_inbound);
+ if (plugin->bind4_address != NULL) {
+ if (0 == memcmp(&plugin->bind4_address->sin_addr, &bnd_cmp, sizeof (struct in_addr)))
+ {
+ GNUNET_CONTAINER_DLL_insert(plugin->ipv4_addr_head,
+ plugin->ipv4_addr_tail,t4);
+ plugin->env->notify_address(plugin->env->cls,
+ GNUNET_YES,
+ t4, sizeof (struct IPv4HttpAddress));
+ return GNUNET_OK;
+ }
+ GNUNET_free (t4);
+ return GNUNET_OK;
+ }
else
- {
+ {
GNUNET_CONTAINER_DLL_insert (plugin->ipv4_addr_head,
plugin->ipv4_addr_tail,
t4);
- plugin->env->notify_address (plugin->env->cls,
- PROTOCOL_PREFIX,
- t4, sizeof (struct IPv4HttpAddress),
- GNUNET_TIME_UNIT_FOREVER_REL);
+ plugin->env->notify_address(plugin->env->cls,
+ GNUNET_YES,
+ t4, sizeof (struct IPv4HttpAddress));
return GNUNET_OK;
- }
- }
- else if ( (af == AF_INET6) &&
+ }
+ }
+ if ((af == AF_INET6) &&
(plugin->use_ipv6 == GNUNET_YES) &&
- (plugin->bind4_address == NULL) )
- {
- struct in6_addr bnd_cmp6 = ((struct sockaddr_in6 *) addr)->sin6_addr;
- if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
- {
- return GNUNET_OK;
- }
+ (plugin->bind4_address == NULL) ) {
+
+ struct in6_addr bnd_cmp6 = ((struct sockaddr_in6 *) addr)->sin6_addr;
+
t6 = GNUNET_malloc(sizeof(struct IPv6HttpAddress));
GNUNET_assert(t6 != NULL);
- if (plugin->bind6_address != NULL)
- {
+
+ if (plugin->bind6_address != NULL) {
if (0 == memcmp(&plugin->bind6_address->sin6_addr,
- &bnd_cmp6,
- sizeof (struct in6_addr)))
- {
+ &bnd_cmp6,
+ sizeof (struct in6_addr))) {
memcpy (&t6->ipv6_addr,
&((struct sockaddr_in6 *) addr)->sin6_addr,
sizeof (struct in6_addr));
- t6->u6_port = htons (plugin->port_inbound);
+ t6->port = htons (plugin->port_inbound);
plugin->env->notify_address(plugin->env->cls,
- PROTOCOL_PREFIX, t6,
- sizeof (struct IPv6HttpAddress),
- GNUNET_TIME_UNIT_FOREVER_REL);
+ GNUNET_YES,
+ t6, sizeof (struct IPv6HttpAddress));
GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,
plugin->ipv6_addr_tail,
t6);
- return GNUNET_OK;
- }
+ return GNUNET_OK;
+ }
GNUNET_free (t6);
return GNUNET_OK;
- }
+ }
memcpy (&t6->ipv6_addr,
- &((struct sockaddr_in6 *) addr)->sin6_addr,
- sizeof (struct in6_addr));
- t6->u6_port = htons (plugin->port_inbound);
+ &((struct sockaddr_in6 *) addr)->sin6_addr,
+ sizeof (struct in6_addr));
+ t6->port = htons (plugin->port_inbound);
GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,t6);
+
plugin->env->notify_address(plugin->env->cls,
- PROTOCOL_PREFIX,
- t6, sizeof (struct IPv6HttpAddress),
- GNUNET_TIME_UNIT_FOREVER_REL);
- }
+ GNUNET_YES,
+ t6, sizeof (struct IPv6HttpAddress));
+ }
return GNUNET_OK;
}
-
+#endif
/**
* External logging function for MHD
if (ps == NULL)
return;
struct HTTP_PeerContext * pc = ps->peercontext;
-
+ struct Plugin *plugin = cls;
+
+ GNUNET_assert (cls != NULL);
+ plugin->current_connections--;
+
if (connection==ps->recv_endpoint)
{
#if DEBUG_CONNECTIONS
const struct GNUNET_MessageHeader *message)
{
struct Session *ps = cls;
- struct HTTP_PeerContext *pc = ps->peercontext;
+ struct HTTP_PeerContext *pc;
struct GNUNET_TIME_Relative delay;
GNUNET_assert(ps != NULL);
+ pc = ps->peercontext;
GNUNET_assert(pc != NULL);
#if DEBUG_HTTP
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
const struct sockaddr *addr,
socklen_t addr_len)
{
-#if 0
struct Plugin *plugin = cls;
-#endif
- /* Every connection is accepted, nothing more to do here */
- return MHD_YES;
+ GNUNET_assert (cls != NULL);
+
+ if (plugin->max_connect_per_transport > plugin->current_connections)
+ {
+ plugin->current_connections ++;
+ return MHD_YES;
+ }
+ else return MHD_NO;
}
if (msg!=NULL)
{
+ /* sending */
if ((msg->size-msg->pos) <= max)
{
memcpy(buf,&msg->buf[msg->pos],(msg->size-msg->pos));
bytes_read = max;
}
+ /* removing message */
if (msg->pos==msg->size)
{
if (NULL!=msg->transmit_cont)
addrin = (const struct sockaddr_in*) client_addr;
inet_ntop(addrin->sin_family, &(addrin->sin_addr),address,INET_ADDRSTRLEN);
memcpy(&ipv4addr.ipv4_addr,&(addrin->sin_addr),sizeof(struct in_addr));
- ipv4addr.u_port = addrin->sin_port;
+ ipv4addr.port = addrin->sin_port;
addr = &ipv4addr;
addr_len = sizeof(struct IPv4HttpAddress);
}
addrin6 = (const struct sockaddr_in6 *) client_addr;
inet_ntop(addrin6->sin6_family, &(addrin6->sin6_addr),address,INET6_ADDRSTRLEN);
memcpy(&ipv6addr.ipv6_addr,&(addrin6->sin6_addr),sizeof(struct in6_addr));
- ipv6addr.u6_port = addrin6->sin6_port;
+ ipv6addr.port = addrin6->sin6_port;
addr = &ipv6addr;
addr_len = sizeof(struct IPv6HttpAddress);
}
ps->send_connected = GNUNET_NO;
ps->send_active = GNUNET_NO;
curl_multi_remove_handle(plugin->multi_handle,ps->send_endpoint);
- //curl_easy_cleanup(ps->send_endpoint);
- //ps->send_endpoint=NULL;
while (ps->pending_msgs_tail != NULL)
{
cur_msg = ps->pending_msgs_tail;
ps->recv_connected = GNUNET_NO;
ps->recv_active = GNUNET_NO;
curl_multi_remove_handle(plugin->multi_handle,ps->recv_endpoint);
- //curl_easy_cleanup(ps->recv_endpoint);
- //ps->recv_endpoint=NULL;
}
}
else
ps->send_connected = GNUNET_NO;
ps->send_active = GNUNET_NO;
curl_multi_remove_handle(plugin->multi_handle,ps->send_endpoint);
- //curl_easy_cleanup(ps->send_endpoint);
- //ps->send_endpoint =NULL;
}
if (msg->easy_handle == ps->recv_endpoint)
{
ps->recv_connected = GNUNET_NO;
ps->recv_active = GNUNET_NO;
curl_multi_remove_handle(plugin->multi_handle,ps->recv_endpoint);
- //curl_easy_cleanup(ps->recv_endpoint);
- //ps->recv_endpoint=NULL;
}
+ plugin->current_connections--;
}
if ((ps->recv_connected == GNUNET_NO) && (ps->send_connected == GNUNET_NO))
remove_session (pc, ps, GNUNET_YES, GNUNET_SYSERR);
CURLMcode mret;
struct GNUNET_TIME_Relative timeout = GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT;
- if (ps->direction == OUTBOUND)
+ if ((ps->direction == OUTBOUND) && (plugin->current_connections < plugin->max_connect_per_transport))
{
/* RECV DIRECTION */
/* Check if session is connected to receive data, otherwise connect to peer */
+
if (ps->recv_connected == GNUNET_NO)
{
int fresh = GNUNET_NO;
curl_easy_setopt(ps->recv_endpoint, CURLOPT_DEBUGDATA , ps->recv_endpoint);
#endif
#if BUILD_HTTPS
- curl_easy_setopt (ps->recv_endpoint, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
+ curl_easy_setopt(ps->recv_endpoint, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_easy_setopt(ps->recv_endpoint, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(ps->recv_endpoint, CURLOPT_SSL_VERIFYHOST, 0);
#endif
return GNUNET_SYSERR;
}
}
- if (plugin->http_curl_task != GNUNET_SCHEDULER_NO_TASK)
+ if (plugin->http_curl_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel(plugin->http_curl_task);
plugin->http_curl_task = GNUNET_SCHEDULER_NO_TASK;
}
+ plugin->current_connections ++;
plugin->http_curl_task = GNUNET_SCHEDULER_add_now (&curl_perform, plugin);
}
}
}
/* not connected, initiate connection */
- if (ps->send_connected==GNUNET_NO)
+ if ((ps->send_connected==GNUNET_NO) && (plugin->current_connections < plugin->max_connect_per_transport))
{
int fresh = GNUNET_NO;
if (NULL == ps->send_endpoint)
GNUNET_SCHEDULER_cancel(plugin->http_curl_task);
plugin->http_curl_task = GNUNET_SCHEDULER_NO_TASK;
}
+ plugin->current_connections++;
plugin->http_curl_task = GNUNET_SCHEDULER_add_now (&curl_perform, plugin);
return GNUNET_YES;
}
ps->send_force_disconnect = GNUNET_NO;
ps->pending_msgs_head = NULL;
ps->pending_msgs_tail = NULL;
- ps->peercontext=pc;
+ ps->peercontext = pc;
ps->session_id = pc->session_id_counter;
ps->queue_length_cur = 0;
ps->queue_length_max = GNUNET_SERVER_MAX_MESSAGE_SIZE;
}
+/**
+ * Append our port and forward the result.
+ *
+ * @param cls the 'struct PrettyPrinterContext*'
+ * @param hostname hostname part of the address
+ */
+static void
+append_port (void *cls, const char *hostname)
+{
+ struct PrettyPrinterContext *ppc = cls;
+ char *ret;
+
+ if (hostname == NULL)
+ {
+ ppc->asc (ppc->asc_cls, NULL);
+ GNUNET_free (ppc);
+ return;
+ }
+ GNUNET_asprintf (&ret, "%s://%s:%d", PROTOCOL_PREFIX, hostname, ppc->port);
+
+ ppc->asc (ppc->asc_cls, ret);
+ GNUNET_free (ret);
+}
+
+
+
/**
* Convert the transports address to a nice, human-readable
* format.
GNUNET_TRANSPORT_AddressStringCallback
asc, void *asc_cls)
{
+ struct PrettyPrinterContext *ppc;
+ const void *sb;
+ size_t sbs;
+ struct sockaddr_in a4;
+ struct sockaddr_in6 a6;
const struct IPv4HttpAddress *t4;
const struct IPv6HttpAddress *t6;
- struct sockaddr_in a4;
- struct sockaddr_in6 a6;
- char * address;
- char * ret;
- unsigned int port;
- unsigned int res;
+ uint16_t port;
- GNUNET_assert(cls !=NULL);
if (addrlen == sizeof (struct IPv6HttpAddress))
{
- address = GNUNET_malloc (INET6_ADDRSTRLEN);
t6 = addr;
- a6.sin6_addr = t6->ipv6_addr;
- inet_ntop(AF_INET6, &(a6.sin6_addr),address,INET6_ADDRSTRLEN);
- port = ntohs(t6->u6_port);
+ memset (&a6, 0, sizeof (a6));
+ a6.sin6_family = AF_INET6;
+ a6.sin6_port = t6->port;
+ memcpy (&a6.sin6_addr,
+ &t6->ipv6_addr,
+ sizeof (struct in6_addr));
+ port = ntohs (t6->port);
+ sb = &a6;
+ sbs = sizeof (a6);
}
else if (addrlen == sizeof (struct IPv4HttpAddress))
{
- address = GNUNET_malloc (INET_ADDRSTRLEN);
t4 = addr;
- a4.sin_addr.s_addr = t4->ipv4_addr;
- inet_ntop(AF_INET, &(a4.sin_addr),address,INET_ADDRSTRLEN);
- port = ntohs(t4->u_port);
+ memset (&a4, 0, sizeof (a4));
+ a4.sin_family = AF_INET;
+ a4.sin_port = t4->port;
+ a4.sin_addr.s_addr = t4->ipv4_addr;
+ port = ntohs (t4->ipv4_addr);
+ sb = &a4;
+ sbs = sizeof (a4);
}
else
{
asc (asc_cls, NULL);
return;
}
- res = GNUNET_asprintf(&ret,"%s://%s:%u/", PROTOCOL_PREFIX, address, port);
- GNUNET_free (address);
- GNUNET_assert(res != 0);
- asc (asc_cls, ret);
- GNUNET_free_non_null (ret);
+ ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
+ ppc->asc = asc;
+ ppc->asc_cls = asc_cls;
+ ppc->port = port;
+ GNUNET_RESOLVER_hostname_get (sb,
+ sbs,
+ !numeric, timeout, &append_port, ppc);
}
struct Plugin *plugin = cls;
struct IPv4HttpAddress *v4;
struct IPv6HttpAddress *v6;
- struct IPv4HttpAddress *tv4 = plugin->ipv4_addr_head;
- struct IPv6HttpAddress *tv6 = plugin->ipv6_addr_head;
+ struct IPv4HttpAddressWrapper *w_tv4 = plugin->ipv4_addr_head;
+ struct IPv6HttpAddressWrapper *w_tv6 = plugin->ipv6_addr_head;
GNUNET_assert(cls !=NULL);
if ((addrlen != sizeof (struct IPv4HttpAddress)) &&
else
return GNUNET_SYSERR;
}
- while (tv4!=NULL)
+ while (w_tv4!=NULL)
{
- if (0==memcmp (&tv4->ipv4_addr, &v4->ipv4_addr, sizeof(uint32_t)))
+ if (0==memcmp (&w_tv4->addr->ipv4_addr, &v4->ipv4_addr, sizeof(uint32_t)))
break;
- tv4 = tv4->next;
+ w_tv4 = w_tv4->next;
}
- if (tv4 != NULL)
+ if (w_tv4 != NULL)
return GNUNET_OK;
else
return GNUNET_SYSERR;
else
return GNUNET_SYSERR;
}
- while (tv6!=NULL)
+ while (w_tv6!=NULL)
{
- if (0 == memcmp (&tv6->ipv6_addr, &v6->ipv6_addr, sizeof(struct in6_addr)))
+ if (0 == memcmp (&w_tv6->addr->ipv6_addr, &v6->ipv6_addr, sizeof(struct in6_addr)))
break;
- tv6 = tv6->next;
+ w_tv6 = w_tv6->next;
}
- if (tv6 !=NULL)
+ if (w_tv6 !=NULL)
return GNUNET_OK;
else
return GNUNET_SYSERR;
struct sockaddr_in a4;
struct sockaddr_in6 a6;
char * address;
- char * ret;
+ static char rbuf[INET6_ADDRSTRLEN + 13];
uint16_t port;
- unsigned int res;
+ int res;
if (addrlen == sizeof (struct IPv6HttpAddress))
{
t6 = addr;
a6.sin6_addr = t6->ipv6_addr;
inet_ntop(AF_INET6, &(a6.sin6_addr),address,INET6_ADDRSTRLEN);
- port = ntohs(t6->u6_port);
+ port = ntohs(t6->port);
}
else if (addrlen == sizeof (struct IPv4HttpAddress))
{
t4 = addr;
a4.sin_addr.s_addr = t4->ipv4_addr;
inet_ntop(AF_INET, &(a4.sin_addr),address,INET_ADDRSTRLEN);
- port = ntohs(t4->u_port);
+ port = ntohs(t4->port);
}
else
{
/* invalid address */
return NULL;
}
- res = GNUNET_asprintf(&ret,"%s:%u",address,port);
+
+ res = GNUNET_snprintf (rbuf,
+ sizeof (rbuf),
+ "%s:%u",
+ address,
+ port);
+
GNUNET_free (address);
GNUNET_assert(res != 0);
- return ret;
+ return rbuf;
+}
+
+/**
+ * Function called by the NAT subsystem suggesting another peer wants
+ * to connect to us via connection reversal. Try to connect back to the
+ * given IP.
+ *
+ * @param cls closure
+ * @param addr address to try
+ * @param addrlen number of bytes in addr
+ */
+static void
+try_connection_reversal (void *cls,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+
+}
+
+static void
+tcp_nat_cb_add_addr (void *cls,
+ int add_remove,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ struct Plugin *plugin = cls;
+ struct IPv4HttpAddress * t4 = NULL;
+ struct IPv4HttpAddressWrapper * w_t4 = NULL;
+ struct IPv6HttpAddress * t6 = NULL;
+ struct IPv6HttpAddressWrapper * w_t6 = NULL;
+ int af;
+
+ af = addr->sa_family;
+ switch (af)
+ {
+ case AF_INET:
+ w_t4 = plugin->ipv4_addr_head;
+ while (w_t4 != NULL)
+ {
+ int res = memcmp(&w_t4->addr->ipv4_addr,
+ &((struct sockaddr_in *) addr)->sin_addr,
+ sizeof (struct in_addr));
+ if (0 == res)
+ break;
+ w_t4 = w_t4->next;
+ }
+ if (w_t4 == NULL)
+ {
+ w_t4 = GNUNET_malloc(sizeof(struct IPv4HttpAddressWrapper));
+ t4 = GNUNET_malloc(sizeof(struct IPv4HttpAddress));
+ memcpy (&t4->ipv4_addr,
+ &((struct sockaddr_in *) addr)->sin_addr,
+ sizeof (struct in_addr));
+ t4->port = htons (plugin->port_inbound);
+
+ w_t4->addr = t4;
+
+ GNUNET_CONTAINER_DLL_insert(plugin->ipv4_addr_head,
+ plugin->ipv4_addr_tail,w_t4);
+ }
+ plugin->env->notify_address(plugin->env->cls,
+ add_remove,
+ w_t4->addr, sizeof (struct IPv4HttpAddress));
+
+ break;
+ case AF_INET6:
+ w_t6 = plugin->ipv6_addr_head;
+ while (w_t6)
+ {
+ int res = memcmp(&w_t6->addr->ipv6_addr,
+ &((struct sockaddr_in6 *) addr)->sin6_addr,
+ sizeof (struct in6_addr));
+ if (0 == res)
+ break;
+ w_t6 = w_t6->next;
+ }
+ if (w_t6 == NULL)
+ {
+ w_t6 = GNUNET_malloc(sizeof(struct IPv6HttpAddressWrapper));
+ t6 = GNUNET_malloc(sizeof(struct IPv6HttpAddress));
+
+ memcpy (&t6->ipv6_addr,
+ &((struct sockaddr_in6 *) addr)->sin6_addr,
+ sizeof (struct in6_addr));
+ t6->port = htons (plugin->port_inbound);
+
+ w_t6->addr = t6;
+
+ GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,
+ plugin->ipv6_addr_tail,w_t6);
+ }
+ plugin->env->notify_address(plugin->env->cls,
+ add_remove,
+ w_t6->addr, sizeof (struct IPv6HttpAddress));
+ break;
+ default:
+ return;
+ }
+
+}
+
+static void
+tcp_nat_cb_remove_addr (void *cls,
+ int add_remove,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ struct Plugin *plugin = cls;
+ struct IPv4HttpAddressWrapper * w_t4 = NULL;
+ struct IPv6HttpAddressWrapper * w_t6 = NULL;
+ int af;
+
+ af = addr->sa_family;
+ switch (af)
+ {
+ case AF_INET:
+ w_t4 = plugin->ipv4_addr_head;
+ while (w_t4 != NULL)
+ {
+ int res = memcmp(&w_t4->addr->ipv4_addr,
+ &((struct sockaddr_in *) addr)->sin_addr,
+ sizeof (struct in_addr));
+ if (0 == res)
+ break;
+ w_t4 = w_t4->next;
+ }
+ if (w_t4 == NULL)
+ return;
+ plugin->env->notify_address(plugin->env->cls,
+ add_remove,
+ w_t4->addr, sizeof (struct IPv4HttpAddress));
+
+ GNUNET_CONTAINER_DLL_remove(plugin->ipv4_addr_head,
+ plugin->ipv4_addr_tail,w_t4);
+ GNUNET_free (w_t4->addr);
+ GNUNET_free (w_t4);
+ break;
+ case AF_INET6:
+ w_t6 = plugin->ipv6_addr_head;
+ while (w_t6 != NULL)
+ {
+ int res = memcmp(&w_t6->addr->ipv6_addr,
+ &((struct sockaddr_in6 *) addr)->sin6_addr,
+ sizeof (struct in6_addr));
+ if (0 == res)
+ break;
+ w_t6 = w_t6->next;
+ }
+ if (w_t6 == NULL)
+ return;
+ plugin->env->notify_address(plugin->env->cls,
+ add_remove,
+ w_t6->addr, sizeof (struct IPv6HttpAddress));
+
+ GNUNET_CONTAINER_DLL_remove(plugin->ipv6_addr_head,
+ plugin->ipv6_addr_tail,w_t6);
+ GNUNET_free (w_t6->addr);
+ GNUNET_free (w_t6);
+ break;
+ default:
+ return;
+ }
+
}
+/**
+ * Our external IP address/port mapping has changed.
+ *
+ * @param cls closure, the 'struct LocalAddrList'
+ * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
+ * the previous (now invalid) one
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual lenght of the address
+ */
+static void
+tcp_nat_port_map_callback (void *cls,
+ int add_remove,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ GNUNET_assert(cls !=NULL );
+#if DEBUG_HTTP
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "NPMC called to %s address `%s'\n",
+ (add_remove == GNUNET_YES) ? "remove" : "add",
+ GNUNET_a2s (addr, addrlen));
+#endif
+ /* convert 'addr' to our internal format */
+ switch (add_remove)
+ {
+ case GNUNET_YES:
+ tcp_nat_cb_add_addr (cls, add_remove, addr, addrlen);
+ break;
+ case GNUNET_NO:
+ tcp_nat_cb_remove_addr (cls, add_remove, addr, addrlen);
+ break;
+ }
+}
/**
* Exit point from the plugin.
struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
struct Plugin *plugin = api->cls;
CURLMcode mret;
- struct IPv4HttpAddress * ipv4addr;
- struct IPv6HttpAddress * ipv6addr;
+ struct IPv4HttpAddressWrapper * w_t4;
+ struct IPv6HttpAddressWrapper * w_t6;
GNUNET_assert(cls !=NULL);
+ if (plugin->nat != NULL)
+ GNUNET_NAT_unregister (plugin->nat);
+
if (plugin->http_server_daemon_v4 != NULL)
{
MHD_stop_daemon (plugin->http_server_daemon_v4);
GNUNET_SCHEDULER_cancel(plugin->http_server_task_v6);
plugin->http_server_task_v6 = GNUNET_SCHEDULER_NO_TASK;
}
-
+
while (plugin->ipv4_addr_head!=NULL)
{
- ipv4addr = plugin->ipv4_addr_head;
- GNUNET_CONTAINER_DLL_remove(plugin->ipv4_addr_head,plugin->ipv4_addr_tail,ipv4addr);
- GNUNET_free(ipv4addr);
+ w_t4 = plugin->ipv4_addr_head;
+ GNUNET_CONTAINER_DLL_remove(plugin->ipv4_addr_head,plugin->ipv4_addr_tail,w_t4);
+ GNUNET_free(w_t4->addr);
+ GNUNET_free(w_t4);
}
while (plugin->ipv6_addr_head!=NULL)
{
- ipv6addr = plugin->ipv6_addr_head;
- GNUNET_CONTAINER_DLL_remove(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,ipv6addr);
- GNUNET_free(ipv6addr);
+ w_t6 = plugin->ipv6_addr_head;
+ GNUNET_CONTAINER_DLL_remove(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,w_t6);
+ GNUNET_free(w_t6->addr);
+ GNUNET_free(w_t6);
}
/* free all peer information */
plugin->http_curl_task = GNUNET_SCHEDULER_NO_TASK;
}
+
GNUNET_free_non_null (plugin->bind4_address);
GNUNET_free_non_null (plugin->bind6_address);
- GNUNET_free_non_null(plugin->bind_hostname);
+ GNUNET_free_non_null (plugin->bind_hostname);
#if BUILD_HTTPS
GNUNET_free_non_null (plugin->crypto_init);
GNUNET_free_non_null (plugin->cert);
struct stat fstat;
char * text = NULL;
- if (0!=STAT(file, &fstat))
- return NULL;
+ if (0 != STAT(file, &fstat))
+ return NULL;
text = GNUNET_malloc (fstat.st_size+1);
gn_file = GNUNET_DISK_file_open(file, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ);
if (gn_file==NULL)
GNUNET_free(text);
return NULL;
}
- if (GNUNET_SYSERR == GNUNET_DISK_file_read(gn_file, text, fstat.st_size))
+ if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fstat.st_size))
{
- GNUNET_free(text);
- GNUNET_DISK_file_close(gn_file);
+ GNUNET_free (text);
+ GNUNET_DISK_file_close (gn_file);
return NULL;
}
text[fstat.st_size] = '\0';
- GNUNET_DISK_file_close(gn_file);
+ GNUNET_DISK_file_close (gn_file);
return text;
}
#endif
struct GNUNET_TRANSPORT_PluginFunctions *api;
struct GNUNET_TIME_Relative gn_timeout;
long long unsigned int port;
+ unsigned long long tneigh;
+ struct sockaddr **addrs;
+ socklen_t *addrlens;
+ int ret;
char * component_name;
#if BUILD_HTTPS
char * key_file = NULL;
plugin->env = env;
plugin->peers = NULL;
plugin->bind4_address = NULL;
+ plugin->bind6_address = NULL;
plugin->use_ipv6 = GNUNET_YES;
plugin->use_ipv4 = GNUNET_YES;
+ plugin->use_localaddresses = GNUNET_NO;
api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
api->cls = plugin;
GNUNET_CRYPTO_hash_to_enc (&(plugin->env->my_identity->hashPubKey),
&plugin->my_ascii_hash_ident);
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (env->cfg,
+ component_name,
+ "MAX_CONNECTIONS",
+ &tneigh))
+ tneigh = 128;
+ plugin->max_connect_per_transport = tneigh;
+
+
/* Use IPv6? */
if (GNUNET_CONFIGURATION_have_value (env->cfg,
component_name, "USE_IPv6"))
plugin->use_ipv4 = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
component_name,"USE_IPv4");
}
+ /* use local addresses? */
+
+ if (GNUNET_CONFIGURATION_have_value (env->cfg,
+ component_name, "USE_LOCALADDR"))
+ {
+ plugin->use_localaddresses = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
+ component_name,
+ "USE_LOCALADDR");
+ }
/* Reading port number from config file */
if ((GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (env->cfg,
#if BUILD_HTTPS
/* Reading HTTPS crypto related configuration */
- /* Get crypto init string from config */
- if (GNUNET_CONFIGURATION_have_value (env->cfg,
- "transport-https", "CRYPTO_INIT"))
- {
- GNUNET_CONFIGURATION_get_value_string (env->cfg,
- "transport-https",
- "CRYPTO_INIT",
- &plugin->crypto_init);
- }
- else
- {
- GNUNET_asprintf(&plugin->crypto_init,"NORMAL");
- }
-
- /* Get private key file from config */
- if (GNUNET_CONFIGURATION_have_value (env->cfg,
- "transport-https", "KEY_FILE"))
- {
- GNUNET_CONFIGURATION_get_value_string (env->cfg,
- "transport-https",
- "KEY_FILE",
- &key_file);
- }
- if (key_file==NULL)
- GNUNET_asprintf(&key_file,"https.key");
-
- /* Get private key file from config */
- if (GNUNET_CONFIGURATION_have_value (env->cfg,"transport-https", "CERT_FILE"))
+ /* Get crypto init string from config */
+ if ( (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (env->cfg,
+ "transport-https",
+ "CRYPTO_INIT",
+ &plugin->crypto_init)) ||
+ (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (env->cfg,
+ "transport-https",
+ "KEY_FILE",
+ &key_file)) ||
+ (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (env->cfg,
+ "transport-https",
+ "CERT_FILE",
+ &cert_file)) )
{
- GNUNET_CONFIGURATION_get_value_string (env->cfg,
- "transport-https",
- "CERT_FILE",
- &cert_file);
+ GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+ "https",
+ _("Required configuration options missing in section `%s'\n"),
+ "transport-https");
+ GNUNET_free (component_name);
+ GNUNET_free_non_null (key_file);
+ GNUNET_free_non_null (cert_file);
+ LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
+ return NULL;
}
- if (cert_file==NULL)
- GNUNET_asprintf(&cert_file,"https.cert");
-
+
/* read key & certificates from file */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Loading TLS certificate `%s' `%s'\n",
key_file, cert_file);
- plugin->key = load_certificate( key_file );
- plugin->cert = load_certificate( cert_file );
+ plugin->key = load_certificate (key_file);
+ plugin->cert = load_certificate (cert_file);
- if ((plugin->key==NULL) || (plugin->cert==NULL))
+ if ( (plugin->key==NULL) || (plugin->cert==NULL) )
{
- char * cmd;
- int ret = 0;
- GNUNET_asprintf(&cmd,
- "gnunet-transport-certificate-creation %s %s",
- key_file, cert_file);
+ struct GNUNET_OS_Process *certcreation;
+
+ GNUNET_free_non_null (plugin->key);
+ plugin->key = NULL;
+ GNUNET_free_non_null (plugin->cert);
+ plugin->cert = NULL;
+#if DEBUG_HTTP
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No usable TLS certificate found, creating certificate \n");
- ret = system(cmd);
- if (ret != 0)
+ "No usable TLS certificate found, creating certificate\n");
+#endif
+ errno = 0;
+ certcreation = GNUNET_OS_start_process (NULL, NULL,
+ "gnunet-transport-certificate-creation",
+ "gnunet-transport-certificate-creation",
+ key_file, cert_file,
+ NULL);
+ if (certcreation == NULL)
{
GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
"https",
- _("Could not create a new TLS certificate, shell script `%s' failed!\n"),cmd,
- "transport-https");
+ _("Could not create a new TLS certificate, program `gnunet-transport-certificate-creation' could not be started!\n"));
GNUNET_free (key_file);
GNUNET_free (cert_file);
GNUNET_free (component_name);
- LIBGNUNET_PLUGIN_TRANSPORT_DONE(api);
- GNUNET_free (cmd);
- return NULL;
- }
- GNUNET_free (cmd);
- plugin->key = load_certificate( key_file );
- plugin->cert = load_certificate( cert_file );
- if ((plugin->key==NULL) || (plugin->cert==NULL))
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
- "https",
- _("No usable TLS certificate found and creating one failed! \n"),
- "transport-https");
- GNUNET_free (key_file);
- GNUNET_free (cert_file);
- GNUNET_free (component_name);
-
- LIBGNUNET_PLUGIN_TRANSPORT_DONE(api);
+ LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
return NULL;
}
+ GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (certcreation));
+ GNUNET_OS_process_close (certcreation);
+ plugin->key = load_certificate (key_file);
+ plugin->cert = load_certificate (cert_file);
}
+ if ( (plugin->key==NULL) || (plugin->cert==NULL) )
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+ "https",
+ _("No usable TLS certificate found and creating one failed!\n"),
+ "transport-https");
+ GNUNET_free (key_file);
+ GNUNET_free (cert_file);
+ GNUNET_free (component_name);
+ LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
+ return NULL;
+ }
GNUNET_free (key_file);
GNUNET_free (cert_file);
-
- GNUNET_assert((plugin->key!=NULL) && (plugin->cert!=NULL));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n");
+#if DEBUG_HTTP
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TLS certificate loaded\n");
+#endif
#endif
GNUNET_assert ((port > 0) && (port <= 65535));
#endif
MHD_USE_IPv6,
port,
- &mhd_accept_cb,
- plugin , &mhd_access_cb, plugin,
+ &mhd_accept_cb, plugin,
+ &mhd_access_cb, plugin,
MHD_OPTION_SOCK_ADDR, tmp,
- MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 32,
- //MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 6,
+ MHD_OPTION_CONNECTION_LIMIT, (unsigned int) plugin->max_connect_per_transport,
#if BUILD_HTTPS
MHD_OPTION_HTTPS_PRIORITIES, plugin->crypto_init,
MHD_OPTION_HTTPS_MEM_KEY, plugin->key,
#endif
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) timeout,
MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (2 * GNUNET_SERVER_MAX_MESSAGE_SIZE),
- MHD_OPTION_NOTIFY_COMPLETED, &mhd_termination_cb, NULL,
+ MHD_OPTION_NOTIFY_COMPLETED, &mhd_termination_cb, plugin,
MHD_OPTION_EXTERNAL_LOGGER, mhd_logger, plugin->mhd_log,
MHD_OPTION_END);
}
#endif
MHD_NO_FLAG,
port,
- &mhd_accept_cb,
- plugin , &mhd_access_cb, plugin,
- MHD_OPTION_SOCK_ADDR, (struct sockaddr_in *)plugin->bind4_address,
- MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 32,
- //MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 6,
+ &mhd_accept_cb, plugin ,
+ &mhd_access_cb, plugin,
+ MHD_OPTION_SOCK_ADDR, (struct sockaddr_in *) plugin->bind4_address,
+ MHD_OPTION_CONNECTION_LIMIT, (unsigned int) plugin->max_connect_per_transport,
#if BUILD_HTTPS
MHD_OPTION_HTTPS_PRIORITIES, plugin->crypto_init,
+
MHD_OPTION_HTTPS_MEM_KEY, plugin->key,
MHD_OPTION_HTTPS_MEM_CERT, plugin->cert,
#endif
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) timeout,
MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (2 * GNUNET_SERVER_MAX_MESSAGE_SIZE),
- MHD_OPTION_NOTIFY_COMPLETED, &mhd_termination_cb, NULL,
+ MHD_OPTION_NOTIFY_COMPLETED, &mhd_termination_cb, plugin,
MHD_OPTION_EXTERNAL_LOGGER, mhd_logger, plugin->mhd_log,
MHD_OPTION_END);
}
return NULL;
}
+ ret = GNUNET_SERVICE_get_server_addresses (component_name,
+ env->cfg,
+ &addrs,
+ &addrlens);
+
+ if (ret != GNUNET_SYSERR)
+ {
+ plugin->nat = GNUNET_NAT_register (env->cfg,
+ GNUNET_YES,
+ port,
+ (unsigned int) ret,
+ (const struct sockaddr **) addrs,
+ addrlens,
+ &tcp_nat_port_map_callback,
+ &try_connection_reversal,
+ plugin);
+ while (ret > 0)
+ {
+ ret--;
+ GNUNET_assert (addrs[ret] != NULL);
+ GNUNET_free (addrs[ret]);
+ }
+ GNUNET_free_non_null (addrs);
+ GNUNET_free_non_null (addrlens);
+ }
+ else
+ {
+ plugin->nat = GNUNET_NAT_register (env->cfg,
+ GNUNET_YES,
+ 0,
+ 0, NULL, NULL,
+ NULL,
+ &try_connection_reversal,
+ plugin);
+ }
+
plugin->peers = GNUNET_CONTAINER_multihashmap_create (10);
- GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
GNUNET_free(component_name);
+ //GNUNET_SCHEDULER_add_now(address_notification, plugin);
return api;
}