GNUNET_NETWORK_STRUCT_BEGIN
+
/**
- * Message for a client to register to the service
+ * Message for a client to create and destroy channels.
*/
-struct GNUNET_CADET_ClientConnect
+struct GNUNET_CADET_PortMessage
{
/**
- * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT
+ * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_[OPEN|CLOSE]
*
- * Size: sizeof(struct GNUNET_CADET_ClientConnect) +
- * sizeof(CADET_ApplicationType) * applications +
- * sizeof(uint16_t) * types
+ * Size: sizeof(struct GNUNET_CADET_ChannelMessage)
*/
struct GNUNET_MessageHeader header;
- /* uint32_t list_ports[] */
-};
+ /**
+ * Port to open/close.
+ */
+ struct GNUNET_HashCode port GNUNET_PACKED;
+};
/**
* Type for channel numbering.
/**
- * Message for a client to create and destroy channels.
+ * Message for a client to create channels.
*/
-struct GNUNET_CADET_ChannelMessage
+struct GNUNET_CADET_ChannelCreateMessage
{
/**
- * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_[CREATE|DESTROY]
+ * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_CREATE
*
- * Size: sizeof(struct GNUNET_CADET_ChannelMessage)
+ * Size: sizeof(struct GNUNET_CADET_ChannelCreateMessage)
*/
struct GNUNET_MessageHeader header;
/**
* Port of the channel.
*/
- uint32_t port GNUNET_PACKED;
+ struct GNUNET_HashCode port;
/**
* Options.
};
+/**
+ * Message for a client to destroy channels.
+ */
+struct GNUNET_CADET_ChannelDestroyMessage
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_DESTROY
+ *
+ * Size: sizeof(struct GNUNET_CADET_ChannelDestroyMessage)
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * ID of a channel controlled by this client.
+ */
+ CADET_ChannelNumber channel_id GNUNET_PACKED;
+};
+
+
/**
* Message for cadet data traffic.
*/
GNUNET_NETWORK_STRUCT_END
-
/**
* @brief Translate a fwd variable into a string representation, for logging.
*
/**
* Ports open.
*/
- const uint32_t *ports;
-
- /**
- * Number of ports.
- */
- unsigned int n_ports;
+ struct GNUNET_CONTAINER_MultiHashMap *ports;
/**
* Double linked list of the channels this client is connected to, head.
*/
struct GNUNET_CADET_Channel *channels_tail;
- /**
- * Callback for inbound channel creation
- */
- GNUNET_CADET_InboundChannelNotificationHandler *new_channel;
-
/**
* Callback for inbound channel disconnection
*/
*/
struct GNUNET_CADET_Channel
{
-
/**
* DLL next
*/
CADET_ChannelNumber chid;
/**
- * Port number.
+ * Channel's port, if any.
*/
- uint32_t port;
+ struct GNUNET_CADET_Port *port;
/**
* Other end of the channel.
};
+/**
+ * Opaque handle to a port.
+ */
+struct GNUNET_CADET_Port
+{
+ /**
+ * Handle to the CADET session this port belongs to.
+ */
+ struct GNUNET_CADET_Handle *cadet;
+
+ /**
+ * Port ID.
+ */
+ struct GNUNET_HashCode *hash;
+
+ /**
+ * Callback handler for incoming channels on this port.
+ */
+ GNUNET_CADET_InboundChannelNotificationHandler *handler;
+
+ /**
+ * Closure for @a handler.
+ */
+ void *cls;
+};
+
/**
* Implementation state for cadet's message queue.
}
+/**
+ * Find the Port struct for a hash.
+ *
+ * @param h CADET handle.
+ * @param hash HashCode for the port number.
+ *
+ * @return The port handle if known, NULL otherwise.
+ */
+static struct GNUNET_CADET_Port *
+find_port (const struct GNUNET_CADET_Handle *h,
+ const struct GNUNET_HashCode *hash)
+{
+ struct GNUNET_CADET_Port *p;
+
+ p = GNUNET_CONTAINER_multihashmap_get (h->ports, hash);
+
+ return p;
+}
+
/**
* Check whether there is any message ready in the queue and find the size.
*
reconnect_cbk (void *cls);
-/**
- * Send a connect packet to the service with the applications and types
- * requested by the user.
- *
- * @param h The cadet handle.
- *
- */
-static void
-send_connect (struct GNUNET_CADET_Handle *h)
-{
- size_t size;
-
- size = sizeof (struct GNUNET_CADET_ClientConnect);
- size += h->n_ports * sizeof (uint32_t);
- {
- char buf[size] GNUNET_ALIGN;
- struct GNUNET_CADET_ClientConnect *msg;
- uint32_t *ports;
- uint16_t i;
-
- /* build connection packet */
- msg = (struct GNUNET_CADET_ClientConnect *) buf;
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT);
- msg->header.size = htons (size);
- ports = (uint32_t *) &msg[1];
- for (i = 0; i < h->n_ports; i++)
- {
- ports[i] = htonl (h->ports[i]);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
- h->ports[i]);
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Sending %lu bytes long message with %u ports\n",
- ntohs (msg->header.size), h->n_ports);
- send_packet (h, &msg->header, NULL);
- }
-}
-
-
/**
* Reconnect to the service, retransmit all infomation to try to restore the
* original state.
{
h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
}
- send_connect (h);
return GNUNET_YES;
}
*/
static void
process_channel_created (struct GNUNET_CADET_Handle *h,
- const struct GNUNET_CADET_ChannelMessage *msg)
+ const struct GNUNET_CADET_ChannelCreateMessage *msg)
{
struct GNUNET_CADET_Channel *ch;
+ struct GNUNET_CADET_Port *port;
+ const struct GNUNET_HashCode *port_number;
CADET_ChannelNumber chid;
- uint32_t port;
chid = ntohl (msg->channel_id);
- port = ntohl (msg->port);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X:%u\n", chid, port);
+ port_number = &msg->port;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X [%s]\n",
+ chid, GNUNET_h2s (port_number));
if (chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
{
GNUNET_break (0);
return;
}
- if (NULL != h->new_channel)
+ port = find_port (h, port_number);
+ if (NULL != port)
{
void *ctx;
ch->options = ntohl (msg->opt);
LOG (GNUNET_ERROR_TYPE_DEBUG, " created channel %p\n", ch);
- ctx = h->new_channel (h->cls, ch, &msg->peer, ch->port, ch->options);
+ ctx = port->handler (port->cls, ch, &msg->peer, port->hash, ch->options);
if (NULL != ctx)
ch->ctx = ctx;
LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
}
else
{
- struct GNUNET_CADET_ChannelMessage d_msg;
+ struct GNUNET_CADET_ChannelDestroyMessage d_msg;
LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming channels\n");
d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
- d_msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
+ d_msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelDestroyMessage));
d_msg.channel_id = msg->channel_id;
- memset (&d_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
- d_msg.port = 0;
- d_msg.opt = 0;
send_packet (h, &d_msg.header, NULL);
}
*/
static void
process_channel_destroy (struct GNUNET_CADET_Handle *h,
- const struct GNUNET_CADET_ChannelMessage *msg)
+ const struct GNUNET_CADET_ChannelDestroyMessage *msg)
{
struct GNUNET_CADET_Channel *ch;
CADET_ChannelNumber chid;
{
/* Notify of a new incoming channel */
case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
- process_channel_created (h, (struct GNUNET_CADET_ChannelMessage *) msg);
+ process_channel_created (h,
+ (struct GNUNET_CADET_ChannelCreateMessage *) msg);
break;
/* Notify of a channel disconnection */
case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: /* TODO separate(gid problem)*/
case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
- process_channel_destroy (h, (struct GNUNET_CADET_ChannelMessage *) msg);
+ process_channel_destroy (h,
+ (struct GNUNET_CADET_ChannelDestroyMessage *) msg);
break;
case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA:
process_incoming_data (h, msg);
struct GNUNET_CADET_Handle *
GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
- GNUNET_CADET_InboundChannelNotificationHandler new_channel,
GNUNET_CADET_ChannelEndHandler cleaner,
- const struct GNUNET_CADET_MessageHandler *handlers,
- const uint32_t *ports)
+ const struct GNUNET_CADET_MessageHandler *handlers)
{
struct GNUNET_CADET_Handle *h;
h = GNUNET_new (struct GNUNET_CADET_Handle);
LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
h->cfg = cfg;
- h->new_channel = new_channel;
h->cleaner = cleaner;
+ h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES);
h->client = GNUNET_CLIENT_connect ("cadet", cfg);
if (h->client == NULL)
{
}
h->cls = cls;
h->message_handlers = handlers;
- h->ports = ports;
h->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
h->reconnect_task = NULL;
- if (NULL != ports && ports[0] != 0 && NULL == new_channel)
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "no new channel handler given, ports parameter is useless!!\n");
- }
- if ((NULL == ports || ports[0] == 0) && NULL != new_channel)
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "no ports given, new channel handler will never be called!!\n");
- }
/* count handlers */
for (h->n_handlers = 0;
handlers && handlers[h->n_handlers].type;
h->n_handlers++) ;
- for (h->n_ports = 0;
- ports && ports[h->n_ports];
- h->n_ports++) ;
- send_connect (h);
LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect() END\n");
return h;
}
msg = (struct GNUNET_MessageHeader *) &th[1];
switch (ntohs(msg->type))
{
- case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT:
case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+ case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN:
+ case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE:
case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
GNUNET_SCHEDULER_cancel(handle->reconnect_task);
handle->reconnect_task = NULL;
}
+
+ GNUNET_CONTAINER_multihashmap_destroy (handle->ports);
+ handle->ports = NULL;
GNUNET_free (handle);
}
+/**
+ * Open a port to receive incomming channels.
+ *
+ * @param h CADET handle.
+ * @param port Hash representing the port number.
+ * @param new_channel Function called when an channel is received.
+ * @param new_channel_cls Closure for @a new_channel.
+ *
+ * @return Port handle.
+ */
+struct GNUNET_CADET_Port *
+GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
+ const struct GNUNET_HashCode *port,
+ GNUNET_CADET_InboundChannelNotificationHandler
+ new_channel,
+ void *new_channel_cls)
+{
+ struct GNUNET_CADET_Port *p;
+ struct GNUNET_CADET_PortMessage msg;
+
+ GNUNET_assert (NULL != new_channel);
+ p = GNUNET_new (struct GNUNET_CADET_Port);
+ p->cadet = h;
+ p->hash = GNUNET_new (struct GNUNET_HashCode);
+ *p->hash = *port;
+ p->handler = new_channel;
+ p->cls = new_channel_cls;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (h->ports,
+ p->hash,
+ p,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
+ msg.port = *p->hash;
+ send_packet (p->cadet, &msg.header, NULL);
+
+ return p;
+}
+
+/**
+ * Close a port opened with @a GNUNET_CADET_open_port.
+ * The @a new_channel callback will no longer be called.
+ *
+ * @param p Port handle.
+ */
+void
+GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
+{
+ struct GNUNET_CADET_PortMessage msg;
+
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
+ msg.port = *p->hash;
+ send_packet (p->cadet, &msg.header, NULL);
+ GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, p->hash, p);
+ GNUNET_free (p->hash);
+ GNUNET_free (p);
+}
+
+
/**
* Create a new channel towards a remote peer.
*
* @param h cadet handle
* @param channel_ctx client's channel context to associate with the channel
* @param peer peer identity the channel should go to
- * @param port Port number.
+ * @param port Port hash (port number).
* @param options CadetOption flag field, with all desired option bits set to 1.
*
* @return handle to the channel
GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
void *channel_ctx,
const struct GNUNET_PeerIdentity *peer,
- uint32_t port,
+ const struct GNUNET_HashCode *port,
enum GNUNET_CADET_ChannelOption options)
{
struct GNUNET_CADET_Channel *ch;
- struct GNUNET_CADET_ChannelMessage msg;
+ struct GNUNET_CADET_ChannelCreateMessage msg;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Creating new channel to %s:%u\n",
LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", ch->chid);
ch->ctx = channel_ctx;
ch->peer = GNUNET_PEER_intern (peer);
+
msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
- msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
+ msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelCreateMessage));
msg.channel_id = htonl (ch->chid);
- msg.port = htonl (port);
+ msg.port = *port;
msg.peer = *peer;
msg.opt = htonl (options);
ch->allow_send = GNUNET_NO;
send_packet (h, &msg.header, ch);
+
return ch;
}
GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
{
struct GNUNET_CADET_Handle *h;
- struct GNUNET_CADET_ChannelMessage msg;
+ struct GNUNET_CADET_ChannelDestroyMessage msg;
struct GNUNET_CADET_TransmitHandle *th;
LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying channel\n");
h = channel->cadet;
msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
- msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
+ msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelDestroyMessage));
msg.channel_id = htonl (channel->chid);
- memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
- msg.port = 0;
- msg.opt = 0;
th = h->th_head;
while (th != NULL)
{
NULL); /* no handler cls */
return mq;
}
+
+
+/**
+ * Transitional function to convert an unsigned int port to a hash value.
+ * WARNING: local static value returned, NOT reentrant!
+ * WARNING: do not use this function for new code!
+ *
+ * @param port Numerical port (unsigned int format).
+ *
+ * @return A GNUNET_HashCode usable for the new CADET API.
+ */
+const struct GNUNET_HashCode *
+GC_u2h (uint32_t port)
+{
+ static struct GNUNET_HashCode hash;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "This is a transitional function, "
+ "use proper crypto hashes as CADET ports\n");
+ GNUNET_CRYPTO_hash (&port, sizeof (port), &hash);
+
+ return &hash;
+}
s = "KEEPALIVE";
break;
- /**
- * Connect to the cadet service, specifying subscriptions
+ /**
+ * Open port
+ */
+ case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN:
+ s = "OPEN_PORT";
+ break;
+
+ /**
+ * Close port
*/
- case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT:
- s = "LOC_CONNCT";
+ case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE:
+ s = "CLOSE_PORT";
break;
/**
/**
* Destination port.
*/
- uint32_t port GNUNET_PACKED;
+ struct GNUNET_HashCode port;
/**
* Channel options.
h = GNUNET_CADET_connect (cfg,
(void *) (long) actx->peer,
- ctx->new_channel,
ctx->cleaner,
- ctx->handlers,
- ctx->ports);
+ ctx->handlers);
return h;
}
*/
static void *
channel_incoming (void *cls,
- struct GNUNET_CADET_Channel * channel,
- const struct GNUNET_PeerIdentity * initiator,
- uint32_t port, enum GNUNET_CADET_ChannelOption options)
+ struct GNUNET_CADET_Channel *channel,
+ const struct GNUNET_PeerIdentity *initiator,
+ const struct GNUNET_HashCode *port,
+ enum GNUNET_CADET_ChannelOption options)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Incoming channel %p on port %u\n",
- channel, port);
+ "Incoming channel %p on port %s\n",
+ channel, GNUNET_h2s (port));
if (NULL != ch)
{
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"A channel already exists (%p)\n", ch);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Incoming channel %p on port %u\n", channel, port);
+ "Incoming channel %p on port %s\n", channel, GNUNET_h2s (port));
return NULL;
}
if (0 == listen_port)
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id);
opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
- ch = GNUNET_CADET_channel_create (mh, NULL, &pid, target_port, opt);
+ ch = GNUNET_CADET_channel_create (mh, NULL, &pid, GC_u2h (target_port), opt);
if (GNUNET_NO == echo)
listen_stdio ();
else
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- GNUNET_CADET_InboundChannelNotificationHandler *newch = NULL;
- GNUNET_CADET_ChannelEndHandler *endch = NULL;
static const struct GNUNET_CADET_MessageHandler handlers[] = {
{&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0},
{NULL, 0, 0} /* FIXME add option to monitor msg types */
};
- static uint32_t *ports = NULL;
+
/* FIXME add option to monitor apps */
target_id = args[0];
"Creating channel to %s\n",
target_id);
GNUNET_SCHEDULER_add_now (&create_channel, NULL);
- endch = &channel_ended;
- }
- else if (0 != listen_port)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Listen\n");
- newch = &channel_incoming;
- endch = &channel_ended;
- ports = GNUNET_malloc (sizeof (uint32_t) * 2);
- ports[0] = listen_port;
}
else if (NULL != peer_id)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to cadet\n");
mh = GNUNET_CADET_connect (cfg,
NULL, /* cls */
- newch, /* new channel */
- endch, /* cleaner */
- handlers,
- ports);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done\n");
+ &channel_ended, /* cleaner */
+ handlers);
if (NULL == mh)
GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
else
sd = GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+
+ if (0 != listen_port)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening listen port\n");
+ GNUNET_CADET_open_port (mh, GC_u2h (listen_port),
+ &channel_incoming, NULL);
+ }
}
/**
* Destination port of the channel.
*/
- uint32_t port;
+ struct GNUNET_HashCode port;
/**
* Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
opt = 0;
opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
- GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt,
+ GML_send_channel_create (ch->dest, ch->lid_dest, &ch->port, opt,
GCT_get_destination (ch->t));
}
msgcc.header.size = htons (sizeof (msgcc));
msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
msgcc.chid = htonl (ch->gid);
- msgcc.port = htonl (ch->port);
+ msgcc.port = ch->port;
msgcc.opt = htonl (channel_get_options (ch));
GCCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL);
*/
int
GCCH_handle_local_create (struct CadetClient *c,
- struct GNUNET_CADET_ChannelMessage *msg)
+ struct GNUNET_CADET_ChannelCreateMessage *msg)
{
struct CadetChannel *ch;
struct CadetTunnel *t;
CADET_ChannelNumber chid;
LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n",
- GNUNET_i2s (&msg->peer), ntohl (msg->port));
+ GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port));
chid = ntohl (msg->channel_id);
/* Sanity check for duplicate channel IDs */
GNUNET_break (0);
return GNUNET_SYSERR;
}
- ch->port = ntohl (msg->port);
+ ch->port = msg->port;
channel_set_options (ch, ntohl (msg->opt));
/* In unreliable channels, we'll use the DLL to buffer BCK data */
struct CadetChannel *ch;
struct CadetClient *c;
int new_channel;
- uint32_t port;
+ struct GNUNET_HashCode *port;
chid = ntohl (msg->chid);
{
new_channel = GNUNET_NO;
}
- port = ntohl (msg->port);
+ port = &msg->port;
LOG (GNUNET_ERROR_TYPE_INFO,
"<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
if (GNUNET_YES == new_channel || GCT_is_loopback (t))
{
/* Find a destination client */
- ch->port = port;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", ch->port);
- c = GML_client_get_by_port (ch->port);
+ ch->port = *port;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " port %s\n", GNUNET_h2s (port));
+ c = GML_client_get_by_port (port);
if (NULL == c)
{
LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n");
type = ntohs (message->type);
size = ntohs (message->size);
+ data_id = 0;
switch (type)
{
case GNUNET_MESSAGE_TYPE_CADET_DATA:
{
struct GNUNET_CADET_ChannelCreate *cc_msg;
cc_msg = (struct GNUNET_CADET_ChannelCreate *) message;
- data_id = ntohl (cc_msg->port);
SPRINTF (info, " 0x%08X", ntohl (cc_msg->chid));
break;
}
{
struct GNUNET_CADET_ChannelManage *m_msg;
m_msg = (struct GNUNET_CADET_ChannelManage *) message;
- data_id = 0;
SPRINTF (info, " 0x%08X", ntohl (m_msg->chid));
break;
}
default:
- data_id = 0;
info[0] = '\0';
}
LOG (GNUNET_ERROR_TYPE_INFO,
if (NULL == ch)
return "(NULL Channel)";
- SPRINTF (buf, "%s:%u gid:%X (%X / %X)",
- GCT_2s (ch->t), ch->port, ch->gid, ch->lid_root, ch->lid_dest);
+ SPRINTF (buf, "%s:%s gid:%X (%X / %X)",
+ GCT_2s (ch->t), GNUNET_h2s (&ch->port),
+ ch->gid, ch->lid_root, ch->lid_dest);
return buf;
}
*/
int
GCCH_handle_local_create (struct CadetClient *c,
- struct GNUNET_CADET_ChannelMessage *msg);
+ struct GNUNET_CADET_ChannelCreateMessage *msg);
/**
* Handler for cadet network payload traffic.
* Ports that this client has declared interest in.
* Indexed by port, contains *Client.
*/
- struct GNUNET_CONTAINER_MultiHashMap32 *ports;
+ struct GNUNET_CONTAINER_MultiHashMap *ports;
/**
* Whether the client is active or shutting down (don't send confirmations
/**
* All ports clients of this peer have opened.
*/
-static struct GNUNET_CONTAINER_MultiHashMap32 *ports;
+static struct GNUNET_CONTAINER_MultiHashMap *ports;
/**
* Notification context, to send messages to local clients.
*/
static int
client_release_ports (void *cls,
- uint32_t key,
+ const struct GNUNET_HashCode *key,
void *value)
{
int res;
- res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value);
+ res = GNUNET_CONTAINER_multihashmap_remove (ports, key, value);
if (GNUNET_YES != res)
{
GNUNET_break (0);
LOG (GNUNET_ERROR_TYPE_WARNING,
- "Port %u by client %p was not registered.\n",
- key, value);
+ "Port %s by client %p was not registered.\n",
+ GNUNET_h2s (key), value);
}
return GNUNET_OK;
}
}
if (NULL != c->ports)
{
- GNUNET_CONTAINER_multihashmap32_iterate (c->ports,
- &client_release_ports, c);
- GNUNET_CONTAINER_multihashmap32_destroy (c->ports);
+ GNUNET_CONTAINER_multihashmap_iterate (c->ports,
+ &client_release_ports, c);
+ GNUNET_CONTAINER_multihashmap_destroy (c->ports);
}
GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
/**
- * Handler for new clients
+ * Handler for port open requests.
*
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message, which includes messages the client wants
+ * @param cls Closure.
+ * @param client Identification of the client.
+ * @param message The actual message.
*/
static void
-handle_new_client (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+handle_port_open (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
{
- struct GNUNET_CADET_ClientConnect *cc_msg;
struct CadetClient *c;
- unsigned int size;
- uint32_t *p;
- unsigned int i;
+ struct GNUNET_CADET_PortMessage *pmsg;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "new client registering %p\n", client);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "open port requested\n");
- /* Check data sanity */
- size = ntohs (message->size);
- if (size < sizeof (struct GNUNET_CADET_ClientConnect))
+ /* Sanity check for client registration */
+ if (NULL == (c = GML_client_get (client)))
{
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- size -= sizeof (struct GNUNET_CADET_ClientConnect); /* Array size */
- if (0 != (size % sizeof (uint32_t)))
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
+
+ /* Message size sanity check */
+ if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size))
{
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- size /= sizeof (uint32_t); /* Number of ports */
- cc_msg = (struct GNUNET_CADET_ClientConnect *) message;
- /* Retrieve client structure */
- c = GNUNET_SERVER_client_get_user_context (client, struct CadetClient);
- if (NULL == c)
+ pmsg = (struct GNUNET_CADET_PortMessage *) message;
+ if (NULL == c->ports)
+ {
+ c->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO);
+ }
+ /* store in client's hashmap */
+ if (GNUNET_OK !=
+ GNUNET_CONTAINER_multihashmap_put (c->ports, &pmsg->port, c,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " client %u has %u ports\n", c-> id, size);
- if (size > 0)
- {
- uint32_t u32;
-
- p = (uint32_t *) &cc_msg[1];
- c->ports = GNUNET_CONTAINER_multihashmap32_create (size);
- for (i = 0; i < size; i++)
- {
- u32 = ntohl (p[i]);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32);
-
- /* store in client's hashmap */
- GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
- /* store in global hashmap */
- /* FIXME only allow one client to have the port open,
- * have a backup hashmap with waiting clients */
- GNUNET_CONTAINER_multihashmap32_put (ports, u32, c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- }
- }
+ /* store in global hashmap */
+ /* FIXME only allow one client to have the port open,
+ * have a backup hashmap with waiting clients */
+ GNUNET_CONTAINER_multihashmap_put (ports, &pmsg->port, c,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "new regitering processed\n");
}
/**
- * Handler for requests of new tunnels
+ * Handler for port close requests.
+ *
+ * @param cls Closure.
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_port_close (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+}
+
+
+/**
+ * Handler for requests of new channels.
*
* @param cls Closure.
* @param client Identification of the client.
LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
/* Message size sanity check */
- if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size))
+ if (sizeof (struct GNUNET_CADET_ChannelCreateMessage)
+ != ntohs (message->size))
{
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
if (GNUNET_OK !=
GCCH_handle_local_create (c,
- (struct GNUNET_CADET_ChannelMessage *) message))
+ (struct GNUNET_CADET_ChannelCreateMessage *)
+ message))
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
}
handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
- struct GNUNET_CADET_ChannelMessage *msg;
+ struct GNUNET_CADET_ChannelDestroyMessage *msg;
struct CadetClient *c;
struct CadetChannel *ch;
CADET_ChannelNumber chid;
LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
/* Message sanity check */
- if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size))
+ if (sizeof (struct GNUNET_CADET_ChannelDestroyMessage)
+ != ntohs (message->size))
{
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- msg = (struct GNUNET_CADET_ChannelMessage *) message;
+ msg = (struct GNUNET_CADET_ChannelDestroyMessage *) message;
/* Retrieve tunnel */
chid = ntohl (msg->channel_id);
c->id, c, c->handle);
if (NULL != c->ports)
LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u ports registered\n",
- GNUNET_CONTAINER_multihashmap32_size (c->ports));
+ GNUNET_CONTAINER_multihashmap_size (c->ports));
else
LOG (GNUNET_ERROR_TYPE_ERROR, "\t no ports registered\n");
LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u own channles\n",
* Functions to handle messages from clients
*/
static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
- {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT, 0},
+ {&handle_port_open, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
+ sizeof (struct GNUNET_CADET_PortMessage)},
+ {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
+ sizeof (struct GNUNET_CADET_PortMessage)},
{&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE,
- sizeof (struct GNUNET_CADET_ChannelMessage)},
+ sizeof (struct GNUNET_CADET_ChannelCreateMessage)},
{&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
- sizeof (struct GNUNET_CADET_ChannelMessage)},
+ sizeof (struct GNUNET_CADET_ChannelDestroyMessage)},
{&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
{&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
sizeof (struct GNUNET_CADET_LocalAck)},
LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
server_handle = handle;
GNUNET_SERVER_suspend (server_handle);
- ports = GNUNET_CONTAINER_multihashmap32_create (32);
+ ports = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
}
* @return non-NULL if a client has the port.
*/
struct CadetClient *
-GML_client_get_by_port (uint32_t port)
+GML_client_get_by_port (struct GNUNET_HashCode *port)
{
- return GNUNET_CONTAINER_multihashmap32_get (ports, port);
+ return GNUNET_CONTAINER_multihashmap_get (ports, port);
}
*/
void
GML_send_channel_create (struct CadetClient *c,
- uint32_t id, uint32_t port, uint32_t opt,
- const struct GNUNET_PeerIdentity *peer)
+ uint32_t id, struct GNUNET_HashCode *port,
+ uint32_t opt, const struct GNUNET_PeerIdentity *peer)
{
- struct GNUNET_CADET_ChannelMessage msg;
+ struct GNUNET_CADET_ChannelCreateMessage msg;
msg.header.size = htons (sizeof (msg));
msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
msg.channel_id = htonl (id);
- msg.port = htonl (port);
+ msg.port = *port;
msg.opt = htonl (opt);
msg.peer = *peer;
GNUNET_SERVER_notification_context_unicast (nc, c->handle,
void
GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
{
- struct GNUNET_CADET_ChannelMessage msg;
+ struct GNUNET_CADET_ChannelDestroyMessage msg;
if (NULL == c)
{
msg.header.size = htons (sizeof (msg));
msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
msg.channel_id = htonl (id);
- msg.port = htonl (0);
- memset (&msg.peer, 0, sizeof (msg.peer));
- msg.opt = htonl (0);
GNUNET_SERVER_notification_context_unicast (nc, c->handle,
&msg.header, GNUNET_NO);
}
* @return non-NULL if a client has the port.
*/
struct CadetClient *
-GML_client_get_by_port (uint32_t port);
+GML_client_get_by_port (struct GNUNET_HashCode *port);
/**
* Deletes a tunnel from a client (either owner or destination).
*/
void
GML_send_channel_create (struct CadetClient *c,
- uint32_t id, uint32_t port, uint32_t opt,
- const struct GNUNET_PeerIdentity *peer);
+ uint32_t id, struct GNUNET_HashCode *port,
+ uint32_t opt, const struct GNUNET_PeerIdentity *peer);
/**
* Build a local channel NACK message and send it to a local client.
#if !defined(GNUNET_CULL_LOGGING)
#define DUMP_KEYS_TO_STDERR GNUNET_YES
#else
-#define DUMP_KEYS_TO_STDERR GNUNET_NO
+#define DUMP_KEYS_TO_STDERR GNUNET_YES
#endif
#define MIN_TUNNEL_BUFFER 8
/**
* How many messages to send
*/
-#define TOTAL_PACKETS 200 /* Cannot exceed 64k! */
+#define TOTAL_PACKETS 5000 /* Cannot exceed 64k! */
/**
* How long until we give up on connecting the peers?
/**
* Version number of GNUnet-cadet API.
*/
-#define GNUNET_CADET_VERSION 0x00000003
+#define GNUNET_CADET_VERSION 0x00000004
/**
*/
struct GNUNET_CADET_Channel;
+/**
+ * Opaque handle to a port.
+ */
+struct GNUNET_CADET_Port;
+
/**
* Hash to be used in Cadet communication. Only 256 bits needed,
* instead of the 512 from `struct GNUNET_HashCode`.
(GNUNET_CADET_InboundChannelNotificationHandler) (void *cls,
struct GNUNET_CADET_Channel *channel,
const struct GNUNET_PeerIdentity *initiator,
- uint32_t port,
+ const struct GNUNET_HashCode *port,
enum GNUNET_CADET_ChannelOption options);
* @param cfg Configuration to use.
* @param cls Closure for the various callbacks that follow (including
* handlers in the handlers array).
- * @param new_channel Function called when an *incoming* channel is created.
- * Can be NULL if no inbound channels are desired.
- * See @a ports.
* @param cleaner Function called when a channel is destroyed.
* It is called immediately if #GNUNET_CADET_channel_destroy
* is called on the channel.
* one must call #GNUNET_CADET_receive_done on the channel to
* receive the next message. Messages of a type that is not
* in the handlers array are ignored if received.
- * @param ports NULL or 0-terminated array of port numbers for incoming channels.
- * See @a new_channel.
*
* @return handle to the cadet service NULL on error
* (in this case, init is never called)
struct GNUNET_CADET_Handle *
GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
void *cls,
- GNUNET_CADET_InboundChannelNotificationHandler new_channel,
GNUNET_CADET_ChannelEndHandler cleaner,
- const struct GNUNET_CADET_MessageHandler *handlers,
- const uint32_t *ports);
+ const struct GNUNET_CADET_MessageHandler *handlers);
/**
void
GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle);
+/**
+ * Open a port to receive incomming channels.
+ *
+ * @param h CADET handle.
+ * @param port Hash representing the port number.
+ * @param new_channel Function called when an channel is received.
+ * @param new_channel_cls Closure for @a new_channel.
+ *
+ * @return Port handle.
+ */
+struct GNUNET_CADET_Port *
+GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
+ const struct GNUNET_HashCode *port,
+ GNUNET_CADET_InboundChannelNotificationHandler
+ new_channel,
+ void *new_channel_cls);
+
+/**
+ * Close a port opened with @a GNUNET_CADET_open_port.
+ * The @a new_channel callback will no longer be called.
+ *
+ * @param p Port handle.
+ */
+void
+GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p);
/**
* Create a new channel towards a remote peer.
* @param h cadet handle
* @param channel_ctx client's channel context to associate with the channel
* @param peer peer identity the channel should go to
- * @param port Port number.
+ * @param port Port hash (port number).
* @param options CadetOption flag field, with all desired option bits set to 1.
*
* @return handle to the channel
*/
struct GNUNET_CADET_Channel *
GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
- void *channel_ctx,
- const struct GNUNET_PeerIdentity *peer,
- uint32_t port,
- enum GNUNET_CADET_ChannelOption options);
+ void *channel_ctx,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HashCode *port,
+ enum GNUNET_CADET_ChannelOption options);
/**
GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel);
+/**
+ * Transitional function to convert an unsigned int port to a hash value.
+ * WARNING: local static value returned, NOT reentrant!
+ * WARNING: do not use this function for new code!
+ *
+ * @param port Numerical port (unsigned int format).
+ *
+ * @return A GNUNET_HashCode usable for the new CADET API.
+ */
+const struct GNUNET_HashCode *
+GC_u2h (uint32_t port);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
*/
#define GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE 270
-/**
- * Connect to the cadet service, specifying subscriptions
- */
-#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT 272
/**
* Ask the cadet service to create a new channel.
*/
#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK 286
+/**
+ * Start listening on a port.
+ */
+#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN 287
+
+/**
+ * Stop listening on a port.
+ */
+#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE 288
+
/**
* Local information about all channels of service.
*/