* @author Nathan Evans
*/
#include "platform.h"
-#include "gnunet_hello_lib.h"
#include "gnunet_util_lib.h"
+#include "gnunet_hello_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
size_t addrlen;
+ int inbound;
+
/**
* Session timeout task
*/
/**
* Sessions
*/
- struct GNUNET_CONTAINER_MultiHashMap *session_map;
+ struct GNUNET_CONTAINER_MultiPeerMap *session_map;
/**
* FD Read set
static const char *
unix_address_to_string (void *cls, const void *addr, size_t addrlen);
+static struct sockaddr_un *
+unix_address_to_sockaddr (const char *unixpath , socklen_t *sock_len)
+{
+ struct sockaddr_un *un;
+ size_t slen;
+
+ GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
+ un = GNUNET_new (struct sockaddr_un);
+ un->sun_family = AF_UNIX;
+ slen = strlen (unixpath);
+ if (slen >= sizeof (un->sun_path))
+ slen = sizeof (un->sun_path) - 1;
+ memcpy (un->sun_path, unixpath, slen);
+ un->sun_path[slen] = '\0';
+ slen = sizeof (struct sockaddr_un);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ un->sun_len = (u_char) slen;
+#endif
+#if LINUX
+ un->sun_path[0] = '\0';
+#endif
+
+ (*sock_len) = slen;
+ return un;
+}
+
/**
* Re-schedule the main 'select' callback (unix_plugin_select)
* for this plugin.
*/
static int
lookup_session_it (void *cls,
- const struct GNUNET_HashCode * key,
+ const struct GNUNET_PeerIdentity * key,
void *value)
{
struct LookupCtx *lctx = cls;
struct Session *t = value;
if (t->addrlen != lctx->ua_len)
+ {
+ GNUNET_break (0);
return GNUNET_YES;
+ }
- if (0 == memcmp (&t->addr, lctx->ua, lctx->ua_len))
+ if (0 == memcmp (t->addr, lctx->ua, lctx->ua_len))
{
lctx->s = t;
return GNUNET_NO;
}
+ GNUNET_break (0);
return GNUNET_YES;
}
*
* @param plugin the plugin
* @param sender for which peer should the session be?
- * @param addr address to look for
+ * @param ua address to look for
+ * @param ua_len length of the address
* @return NULL if session was not found
*/
static struct Session *
lctx.s = NULL;
lctx.ua = ua;
lctx.ua_len = ua_len;
- GNUNET_CONTAINER_multihashmap_get_multiple (plugin->session_map,
- &sender->hashPubKey,
+ GNUNET_CONTAINER_multipeermap_get_multiple (plugin->session_map,
+ sender,
&lookup_session_it, &lctx);
return lctx.s;
}
removed = GNUNET_YES;
}
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (plugin->session_map,
- &s->target.hashPubKey,
+ GNUNET_CONTAINER_multipeermap_remove (plugin->session_map,
+ &s->target,
s));
GNUNET_STATISTICS_set (plugin->env->stats,
"# UNIX sessions active",
- GNUNET_CONTAINER_multihashmap_size (plugin->session_map),
+ GNUNET_CONTAINER_multipeermap_size (plugin->session_map),
GNUNET_NO);
if ((GNUNET_YES == removed) && (NULL == plugin->msg_head))
reschedule_select (plugin);
{
struct Plugin *plugin = cls;
ssize_t sent;
- const void *sb;
- size_t sbs;
- struct sockaddr_un un;
- size_t slen;
- const char *unix_path;
+ struct sockaddr_un *un;
+ socklen_t un_len;
+ const char *unixpath;
GNUNET_assert (NULL != plugin);
}
/* Prepare address */
- unix_path = (const char *) &addr[1];
- memset (&un, 0, sizeof (un));
- un.sun_family = AF_UNIX;
- slen = strlen (unix_path);
- if (slen >= sizeof (un.sun_path))
- slen = sizeof (un.sun_path) - 1;
- GNUNET_assert (slen < sizeof (un.sun_path));
- memcpy (un.sun_path, unix_path, slen);
- un.sun_path[slen] = '\0';
- slen = sizeof (struct sockaddr_un);
-#if LINUX
- un.sun_path[0] = '\0';
-#endif
-#if HAVE_SOCKADDR_IN_SIN_LEN
- un.sun_len = (u_char) slen;
-#endif
- sb = (struct sockaddr *) &un;
- sbs = slen;
+ unixpath = (const char *) &addr[1];
+ if (NULL == (un = unix_address_to_sockaddr (unixpath, &un_len)))
+ {
+ GNUNET_break (0);
+ return -1;
+ }
resend:
/* Send the data */
- sent = 0;
- sent = GNUNET_NETWORK_socket_sendto (send_handle, msgbuf, msgbuf_size, sb, sbs);
-
+ sent = GNUNET_NETWORK_socket_sendto (send_handle, msgbuf, msgbuf_size,
+ (const struct sockaddr *) un, un_len);
if (GNUNET_SYSERR == sent)
{
if ( (EAGAIN == errno) ||
(ENOBUFS == errno) )
+ {
+ GNUNET_free (un);
return RETRY; /* We have to retry later */
+ }
if (EMSGSIZE == errno)
{
socklen_t size = 0;
{
/* Could not increase buffer size: error, no retry */
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt");
+ GNUNET_free (un);
return GNUNET_SYSERR;
}
}
/* Buffer is bigger than message: error, no retry
* This should never happen!*/
GNUNET_break (0);
+ GNUNET_free (un);
return GNUNET_SYSERR;
}
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"UNIX transmit %u-byte message to %s (%d: %s)\n",
(unsigned int) msgbuf_size,
- GNUNET_a2s (sb, sbs),
+ GNUNET_a2s ((const struct sockaddr *)un, un_len),
(int) sent,
(sent < 0) ? STRERROR (errno) : "ok");
+ GNUNET_free (un);
return sent;
}
*/
static int
get_session_it (void *cls,
- const struct GNUNET_HashCode *key,
+ const struct GNUNET_PeerIdentity *key,
void *value)
{
struct GetSessionIteratorContext *gsi = cls;
struct Session *s = value;
- if ( (gsi->addrlen == s->addrlen) &&
+ if ((GNUNET_NO == s->inbound) && (gsi->addrlen == s->addrlen) &&
(0 == memcmp (gsi->address, s->addr, s->addrlen)) )
{
gsi->res = s;
}
+/**
+ * Function obtain the network type for a session
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param session the session
+ * @return the network type in HBO or GNUNET_SYSERR
+ */
+static enum GNUNET_ATS_Network_Type
+unix_get_network (void *cls,
+ struct Session *session)
+{
+ GNUNET_assert (NULL != session);
+ return GNUNET_ATS_NET_LOOPBACK;
+}
+
+
/**
* Creates a new outbound session the transport service will use to send data to the
* peer
}
addrstr = (char *) &ua[1];
addr_str_len = ntohl (ua->addrlen);
- if (addr_str_len != address->address_length - sizeof (struct UnixAddress *))
+ if (addr_str_len != address->address_length - sizeof (struct UnixAddress))
{
/* This can be a legacy address */
return NULL;
gsi.address = (const char *) address->address;
gsi.addrlen = address->address_length;
gsi.res = NULL;
- GNUNET_CONTAINER_multihashmap_get_multiple (plugin->session_map,
- &address->peer.hashPubKey,
+ GNUNET_CONTAINER_multipeermap_get_multiple (plugin->session_map,
+ &address->peer,
&get_session_it, &gsi);
if (NULL != gsi.res)
{
s->addr = (struct UnixAddress *) &s[1];
s->addrlen = address->address_length;
s->plugin = plugin;
+ s->inbound = GNUNET_NO;
memcpy (s->addr, address->address, address->address_length);
memcpy (&s->target, &address->peer, sizeof (struct GNUNET_PeerIdentity));
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Creating a new session %p for address `%s'\n",
s, unix_address_to_string (NULL, address->address, address->address_length));
- (void) GNUNET_CONTAINER_multihashmap_put (plugin->session_map,
- &address->peer.hashPubKey, s,
+ (void) GNUNET_CONTAINER_multipeermap_put (plugin->session_map,
+ &address->peer, s,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
GNUNET_STATISTICS_set (plugin->env->stats,
"# UNIX sessions active",
- GNUNET_CONTAINER_multihashmap_size (plugin->session_map),
+ GNUNET_CONTAINER_multipeermap_size (plugin->session_map),
GNUNET_NO);
return s;
}
GNUNET_assert (NULL != session);
if (GNUNET_OK !=
- GNUNET_CONTAINER_multihashmap_contains_value (plugin->session_map,
- &session->target.hashPubKey,
+ GNUNET_CONTAINER_multipeermap_contains_value (plugin->session_map,
+ &session->target,
session))
{
LOG (GNUNET_ERROR_TYPE_ERROR,
* @param plugin the main plugin for this transport
* @param sender from which peer the message was received
* @param currhdr pointer to the header of the message
- * @param un the address from which the message was received
- * @param fromlen the length of the address
+ * @param ua address to look for
+ * @param ua_len length of the address
*/
static void
unix_demultiplexer (struct Plugin *plugin, struct GNUNET_PeerIdentity *sender,
GNUNET_assert (ua_len >= sizeof (struct UnixAddress));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received message from %s\n",
unix_address_to_string(NULL, ua, ua_len));
GNUNET_STATISTICS_update (plugin->env->stats,
ua_len);
s = lookup_session (plugin, sender, ua, ua_len);
if (NULL == s)
+ {
s = unix_plugin_get_session (plugin, addr);
+ s->inbound = GNUNET_YES;
+ /* Notify transport and ATS about new inbound session */
+ plugin->env->session_start (NULL, sender,
+ PLUGIN_NAME, NULL, 0, s, &plugin->ats_network, 1);
+ }
reschedule_session_timeout (s);
- plugin->env->receive (plugin->env->cls, sender, currhdr,
- s, (const char *) ua, ua_len);
+ plugin->env->receive (plugin->env->cls, sender, currhdr, s,
+ (GNUNET_YES == s->inbound) ? NULL : (const char *) ua,
+ (GNUNET_YES == s->inbound) ? 0 : ua_len);
- plugin->env->update_address_metrics (plugin->env->cls,
- sender,
- (const char *) ua, ua_len,
- s,
- &plugin->ats_network, 1);
+ plugin->env->update_address_metrics (plugin->env->cls, sender,
+ (GNUNET_YES == s->inbound) ? NULL : (const char *) ua,
+ (GNUNET_YES == s->inbound) ? 0 : ua_len,
+ s, &plugin->ats_network, 1);
GNUNET_free (addr);
}
if ((csize < sizeof (struct UNIXMessage)) || (csize > ret))
{
GNUNET_break_op (0);
+ GNUNET_free (ua);
return;
}
msgbuf = (char *) &msg[1];
while (NULL != (msgw = plugin->msg_tail))
{
- if (GNUNET_TIME_absolute_get_remaining (msgw->timeout).rel_value > 0)
+ if (GNUNET_TIME_absolute_get_remaining (msgw->timeout).rel_value_us > 0)
break; /* Message is ready for sending */
/* Message has a timeout */
LOG (GNUNET_ERROR_TYPE_DEBUG,
unix_transport_server_start (void *cls)
{
struct Plugin *plugin = cls;
- struct sockaddr *serverAddr;
- socklen_t addrlen;
- struct sockaddr_un un;
- size_t slen;
-
- memset (&un, 0, sizeof (un));
- un.sun_family = AF_UNIX;
- slen = strlen (plugin->unix_socket_path) + 1;
- if (slen >= sizeof (un.sun_path))
- slen = sizeof (un.sun_path) - 1;
-
- memcpy (un.sun_path, plugin->unix_socket_path, slen);
- un.sun_path[slen] = '\0';
- slen = sizeof (struct sockaddr_un);
-#if HAVE_SOCKADDR_IN_SIN_LEN
- un.sun_len = (u_char) slen;
-#endif
+ struct sockaddr_un *un;
+ socklen_t un_len;
- serverAddr = (struct sockaddr *) &un;
- addrlen = slen;
-#if LINUX
- un.sun_path[0] = '\0';
-#endif
- plugin->ats_network = plugin->env->get_address_type (plugin->env->cls, serverAddr, addrlen);
+ un = unix_address_to_sockaddr (plugin->unix_socket_path, &un_len);
+ plugin->ats_network = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) un, un_len);
plugin->unix_sock.desc =
GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
if (NULL == plugin->unix_sock.desc)
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
return GNUNET_SYSERR;
}
- if (GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, serverAddr, addrlen, 0)
+ if (GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, (const struct sockaddr *) un, un_len, 0)
!= GNUNET_OK)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
GNUNET_NETWORK_socket_close (plugin->unix_sock.desc);
plugin->unix_sock.desc = NULL;
+ GNUNET_free (un);
return GNUNET_SYSERR;
}
LOG (GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", plugin->unix_socket_path);
GNUNET_NETWORK_fdset_set (plugin->ws, plugin->unix_sock.desc);
reschedule_select (plugin);
-
+ GNUNET_free (un);
return 1;
}
static char rbuf[1024];
struct UnixAddress *ua = (struct UnixAddress *) addr;
char *addrstr;
- char *tmp;
size_t addr_str_len;
- if ((NULL == addr) || (0 == addrlen) || (sizeof (struct UnixAddress) > addrlen))
+ if (0 == addrlen)
+ {
+ GNUNET_snprintf(rbuf, sizeof (rbuf), "%s", TRANSPORT_SESSION_INBOUND_STRING);
+ }
+ if ((NULL == addr) || (sizeof (struct UnixAddress) > addrlen))
{
GNUNET_break (0);
return NULL;
addrstr = (char *) &ua[1];
addr_str_len = ntohl (ua->addrlen);
- if (addr_str_len != addrlen - sizeof (struct UnixAddress *))
+ if (addr_str_len != addrlen - sizeof (struct UnixAddress))
{
GNUNET_break (0);
return NULL;
return NULL;
}
- GNUNET_asprintf(&tmp, "%s.%u.%s", PLUGIN_NAME, ntohl (ua->options), addrstr);
- memcpy (rbuf, tmp, strlen (tmp) + 1);
- GNUNET_free (tmp);
+ GNUNET_snprintf(rbuf, sizeof (rbuf), "%s.%u.%s", PLUGIN_NAME, ntohl (ua->options), addrstr);
return rbuf;
}
{
asc (asc_cls, unix_address_to_string (NULL, addr, addrlen));
}
+ else if (0 == addrlen)
+ {
+ asc (asc_cls, TRANSPORT_SESSION_INBOUND_STRING);
+ }
else
{
GNUNET_break (0);
address = NULL;
plugin = NULL;
optionstr = NULL;
- options = 0;
+
if ((NULL == addr) || (addrlen == 0))
{
GNUNET_break (0);
* @return GNUNET_YES (always, continue to iterate)
*/
static int
-get_session_delete_it (void *cls, const struct GNUNET_HashCode * key, void *value)
+get_session_delete_it (void *cls,
+ const struct GNUNET_PeerIdentity *key,
+ void *value)
{
struct Session *s = value;
*
* @param cls closure for this call (should be handle to Plugin)
* @param target the peeridentity of the peer to disconnect
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the operation failed
*/
static void
unix_disconnect (void *cls,
struct Plugin *plugin = cls;
GNUNET_assert (plugin != NULL);
- GNUNET_CONTAINER_multihashmap_get_multiple (plugin->session_map,
- &target->hashPubKey,
+ GNUNET_CONTAINER_multipeermap_get_multiple (plugin->session_map,
+ target,
&get_session_delete_it, plugin);
}
api->address_to_string = &unix_address_to_string;
api->check_address = &unix_check_address;
api->string_to_address = &unix_string_to_address;
+ api->get_network = &unix_get_network;
sockets_created = unix_transport_server_start (plugin);
if (0 == sockets_created)
LOG (GNUNET_ERROR_TYPE_WARNING,
_("Failed to open UNIX listen socket\n"));
- plugin->session_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+ plugin->session_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
plugin->address_update_task = GNUNET_SCHEDULER_add_now (&address_notification, plugin);
return api;
}
plugin->unix_sock.desc = NULL;
plugin->with_ws = GNUNET_NO;
}
- GNUNET_CONTAINER_multihashmap_iterate (plugin->session_map,
+ GNUNET_CONTAINER_multipeermap_iterate (plugin->session_map,
&get_session_delete_it, plugin);
- GNUNET_CONTAINER_multihashmap_destroy (plugin->session_map);
+ GNUNET_CONTAINER_multipeermap_destroy (plugin->session_map);
if (NULL != plugin->rs)
GNUNET_NETWORK_fdset_destroy (plugin->rs);
if (NULL != plugin->ws)