gnunet-service-transport_clients.c   gnunet-service-transport_clients.c 
skipping to change at line 117 skipping to change at line 117
*/ */
unsigned int message_count; unsigned int message_count;
/** /**
* Is this client interested in payload messages? * Is this client interested in payload messages?
*/ */
int send_payload; int send_payload;
}; };
/** /**
* Client monitoring changes of active addresses of our neighbours.
*/
struct MonitoringClient
{
/**
* This is a doubly-linked list.
*/
struct MonitoringClient *next;
/**
* This is a doubly-linked list.
*/
struct MonitoringClient *prev;
/**
* Handle to the client.
*/
struct GNUNET_SERVER_Client *client;
/**
* Peer identity to monitor the addresses of.
* Zero to monitor all neighrours.
*/
struct GNUNET_PeerIdentity peer;
};
/**
* Head of linked list of all clients to this service. * Head of linked list of all clients to this service.
*/ */
static struct TransportClient *clients_head; static struct TransportClient *clients_head;
/** /**
* Tail of linked list of all clients to this service. * Tail of linked list of all clients to this service.
*/ */
static struct TransportClient *clients_tail; static struct TransportClient *clients_tail;
/** /**
* Head of linked list of monitoring clients.
*/
static struct MonitoringClient *monitoring_clients_head;
/**
* Tail of linked list of monitoring clients.
*/
static struct MonitoringClient *monitoring_clients_tail;
/**
* Notification context, to send updates on changes to active addresses
* of our neighbours.
*/
struct GNUNET_SERVER_NotificationContext *nc = NULL;
/**
* Find the internal handle associated with the given client handle * Find the internal handle associated with the given client handle
* *
* @param client server's client handle to look up * @param client server's client handle to look up
* @return internal client handle * @return internal client handle
*/ */
static struct TransportClient * static struct TransportClient *
lookup_client (struct GNUNET_SERVER_Client *client) lookup_client (struct GNUNET_SERVER_Client *client)
{ {
struct TransportClient *tc; struct TransportClient *tc;
skipping to change at line 163 skipping to change at line 207
static struct TransportClient * static struct TransportClient *
setup_client (struct GNUNET_SERVER_Client *client) setup_client (struct GNUNET_SERVER_Client *client)
{ {
struct TransportClient *tc; struct TransportClient *tc;
GNUNET_assert (lookup_client (client) == NULL); GNUNET_assert (lookup_client (client) == NULL);
tc = GNUNET_malloc (sizeof (struct TransportClient)); tc = GNUNET_malloc (sizeof (struct TransportClient));
tc->client = client; tc->client = client;
#if DEBUG_TRANSPORT #if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %X connected\n", tc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
#endif #endif
return tc; return tc;
} }
/** /**
* Find the handle to the monitoring client associated with the given
* client handle
*
* @param client server's client handle to look up
* @return handle to the monitoring client
*/
static struct MonitoringClient *
lookup_monitoring_client (struct GNUNET_SERVER_Client *client)
{
struct MonitoringClient *mc;
mc = monitoring_clients_head;
while (mc != NULL)
{
if (mc->client == client)
return mc;
mc = mc->next;
}
return NULL;
}
/**
* Setup a new monitoring client using the given server client handle and
* the peer identity.
*
* @param client server's client handle to create our internal handle for
* @param peer identity of the peer to monitor the addresses of,
* zero to monitor all neighrours.
* @return handle to the new monitoring client
*/
static struct MonitoringClient *
setup_monitoring_client (struct GNUNET_SERVER_Client *client,
struct GNUNET_PeerIdentity *peer)
{
struct MonitoringClient *mc;
GNUNET_assert (lookup_monitoring_client (client) == NULL);
mc = GNUNET_malloc (sizeof (struct MonitoringClient));
mc->client = client;
mc->peer = *peer;
GNUNET_CONTAINER_DLL_insert (monitoring_clients_head,
monitoring_clients_tail,
mc);
GNUNET_SERVER_notification_context_add (nc, client);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client %p started monitoring of the peer `%s'\n",
mc, GNUNET_i2s (peer));
return mc;
}
/**
* Function called to notify a client about the socket being ready to * Function called to notify a client about the socket being ready to
* queue more data. "buf" will be NULL and "size" zero if the socket * queue more data. "buf" will be NULL and "size" zero if the socket
* was closed for writing in the meantime. * was closed for writing in the meantime.
* *
* @param cls closure * @param cls closure
* @param size number of bytes available in buf * @param size number of bytes available in buf
* @param buf where the callee should write the message * @param buf where the callee should write the message
* @return number of bytes written to buf * @return number of bytes written to buf
*/ */
static size_t static size_t
skipping to change at line 207 skipping to change at line 303
cbuf = buf; cbuf = buf;
tsize = 0; tsize = 0;
while (NULL != (q = tc->message_queue_head)) while (NULL != (q = tc->message_queue_head))
{ {
msg = (const struct GNUNET_MessageHeader *) &q[1]; msg = (const struct GNUNET_MessageHeader *) &q[1];
msize = ntohs (msg->size); msize = ntohs (msg->size);
if (msize + tsize > size) if (msize + tsize > size)
break; break;
#if DEBUG_TRANSPORT #if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Transmitting message of type %u to client %X.\n", "Transmitting message of type %u to client %p.\n",
ntohs (msg->type), tc); ntohs (msg->type), tc);
#endif #endif
GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_ tail, GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_ tail,
q); q);
tc->message_count--; tc->message_count--;
memcpy (&cbuf[tsize], msg, msize); memcpy (&cbuf[tsize], msg, msize);
GNUNET_free (q); GNUNET_free (q);
tsize += msize; tsize += msize;
} }
if (NULL != q) if (NULL != q)
skipping to change at line 283 skipping to change at line 379
* Called whenever a client is disconnected. Frees our * Called whenever a client is disconnected. Frees our
* resources associated with that client. * resources associated with that client.
* *
* @param cls closure * @param cls closure
* @param client identification of the client * @param client identification of the client
*/ */
static void static void
client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *cli ent) client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *cli ent)
{ {
struct TransportClient *tc; struct TransportClient *tc;
struct MonitoringClient *mc;
struct ClientMessageQueueEntry *mqe; struct ClientMessageQueueEntry *mqe;
if (client == NULL) if (client == NULL)
return; return;
mc = lookup_monitoring_client (client);
if (mc != NULL)
{
GNUNET_CONTAINER_DLL_remove (monitoring_clients_head,
monitoring_clients_tail,
mc);
GNUNET_free (mc);
}
tc = lookup_client (client); tc = lookup_client (client);
if (tc == NULL) if (tc == NULL)
return; return;
#if DEBUG_TRANSPORT #if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Client %X disconnected, cleaning up.\n", tc); "Client %p disconnected, cleaning up.\n", tc);
#endif #endif
while (NULL != (mqe = tc->message_queue_head)) while (NULL != (mqe = tc->message_queue_head))
{ {
GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_ tail, GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_ tail,
mqe); mqe);
tc->message_count--; tc->message_count--;
GNUNET_free (mqe); GNUNET_free (mqe);
} }
GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc); GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
if (tc->th != NULL) if (tc->th != NULL)
skipping to change at line 367 skipping to change at line 472
clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client, clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message) const struct GNUNET_MessageHeader *message)
{ {
const struct StartMessage *start; const struct StartMessage *start;
struct TransportClient *tc; struct TransportClient *tc;
uint32_t options; uint32_t options;
tc = lookup_client (client); tc = lookup_client (client);
#if DEBUG_TRANSPORT #if DEBUG_TRANSPORT
if (tc != NULL) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Client %p sent START\n", tc);
"Client %X sent START\n", tc);
else
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Client %X sent START\n", tc);
#endif #endif
if (tc != NULL) if (tc != NULL)
{ {
/* got 'start' twice from the same client, not allowed */ /* got 'start' twice from the same client, not allowed */
#if DEBUG_TRANSPORT #if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"TransportClient %X ServerClient %X sent multiple START me ssages\n", "TransportClient %p ServerClient %p sent multiple START mes sages\n",
tc, tc->client); tc, tc->client);
#endif #endif
GNUNET_break (0); GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return; return;
} }
start = (const struct StartMessage *) message; start = (const struct StartMessage *) message;
options = ntohl (start->options); options = ntohl (start->options);
if ((0 != (1 & options)) && if ((0 != (1 & options)) &&
(0 != (0 !=
skipping to change at line 675 skipping to change at line 776
GNUNET_SERVER_transmit_context_run (tc, rtimeout); GNUNET_SERVER_transmit_context_run (tc, rtimeout);
return; return;
} }
GNUNET_SERVER_disable_receive_done_warning (client); GNUNET_SERVER_disable_receive_done_warning (client);
papi->address_pretty_printer (papi->cls, plugin_name, address, address_le n, papi->address_pretty_printer (papi->cls, plugin_name, address, address_le n,
numeric, rtimeout, &transmit_address_to_cli ent, numeric, rtimeout, &transmit_address_to_cli ent,
tc); tc);
} }
/** /**
* Compose AddressIterateResponseMessage using the given peer and address.
*
* @param peer identity of the peer
* @param address the address, NULL on disconnect
* @return composed message
*/
static struct AddressIterateResponseMessage *
compose_address_iterate_response_message (const struct GNUNET_PeerIdentity
*peer,
const struct GNUNET_HELLO_Address
*address)
{
struct AddressIterateResponseMessage *msg;
size_t size;
size_t tlen;
size_t alen;
char *addr;
GNUNET_assert (NULL != peer);
if (NULL != address)
{
tlen = strlen (address->transport_name) + 1;
alen = address->address_length;
}
else
tlen = alen = 0;
size = (sizeof (struct AddressIterateResponseMessage) + alen + tlen);
msg = GNUNET_malloc (size);
msg->header.size = htons (size);
msg->header.type =
htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE);
msg->reserved = htonl (0);
msg->peer = *peer;
msg->addrlen = htonl (alen);
msg->pluginlen = htonl (tlen);
if (NULL != address)
{
addr = (char *) &msg[1];
memcpy (addr, address->address, alen);
memcpy (&addr[alen], address->transport_name, tlen);
}
return msg;
}
/**
* Output the active address of connected neighbours to the given client. * Output the active address of connected neighbours to the given client.
* *
* @param cls the 'struct GNUNET_SERVER_TransmitContext' for transmission t o the client * @param cls the 'struct GNUNET_SERVER_TransmitContext' for transmission t o the client
* @param peer identity of the neighbour * @param peer identity of the neighbour
* @param ats performance data * @param ats performance data
* @param ats_count number of entries in ats (excluding 0-termination) * @param ats_count number of entries in ats (excluding 0-termination)
* @param address the address * @param address the address
*/ */
static void static void
output_address (void *cls, const struct GNUNET_PeerIdentity *peer, output_address (void *cls, const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_ATS_Information *ats, uint32_t ats_coun t, const struct GNUNET_ATS_Information *ats, uint32_t ats_coun t,
const struct GNUNET_HELLO_Address *address) const struct GNUNET_HELLO_Address *address)
{ {
struct GNUNET_SERVER_TransmitContext *tc = cls; struct GNUNET_SERVER_TransmitContext *tc = cls;
struct AddressIterateResponseMessage *msg; struct AddressIterateResponseMessage *msg;
size_t size;
size_t tlen;
size_t alen;
char *addr;
tlen = strlen (address->transport_name) + 1;
alen = address->address_length;
size = (sizeof (struct AddressIterateResponseMessage) + alen + tlen);
{
char buf[size];
msg = (struct AddressIterateResponseMessage *) buf; msg = compose_address_iterate_response_message (peer, address);
msg->reserved = htonl (0); GNUNET_SERVER_transmit_context_append_message (tc, &msg->header);
msg->peer = *peer; GNUNET_free (msg);
msg->addrlen = htonl (alen);
msg->pluginlen = htonl (tlen);
addr = (char *) &msg[1];
memcpy (addr, address->address, alen);
memcpy (&addr[alen], address->transport_name, tlen);
GNUNET_SERVER_transmit_context_append_data (tc,
&buf[sizeof
(struct
GNUNET_MessageHeader)
],
size -
sizeof (struct
GNUNET_MessageHeade
r),
GNUNET_MESSAGE_TYPE_TRANSPO
RT_ADDRESS_ITERATE_RESPONSE);
}
} }
/** /**
* Client asked to obtain information about all actively used addresses * Client asked to obtain information about all actively used addresses
* of connected peers * of connected peers
* Process the request. * Process the request.
* *
* @param cls unused * @param cls unused
* @param client the client * @param client the client
* @param message the peer address information request * @param message the peer address information request
skipping to change at line 751 skipping to change at line 873
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return; return;
} }
if (ntohs (message->size) != sizeof (struct AddressIterateMessage)) if (ntohs (message->size) != sizeof (struct AddressIterateMessage))
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return; return;
} }
msg = (struct AddressIterateMessage *) message; msg = (struct AddressIterateMessage *) message;
if (GNUNET_YES != ntohl (msg->one_shot)) if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
(NULL != lookup_monitoring_client (client)) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Address monitoring not implemented\n"); "ServerClient %p tried to start monitoring twice\n",
client);
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return; return;
} }
GNUNET_SERVER_disable_receive_done_warning (client); GNUNET_SERVER_disable_receive_done_warning (client);
tc = GNUNET_SERVER_transmit_context_create (client); tc = GNUNET_SERVER_transmit_context_create (client);
if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdenti ty))) if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdenti ty)))
{ {
/* iterate over all neighbours */ /* iterate over all neighbours */
GST_neighbours_iterate (&output_address, tc); GST_neighbours_iterate (&output_address, tc);
} }
else else
{ {
/* just return one neighbour */ /* just return one neighbour */
address = GST_neighbour_get_current_address (&msg->peer); address = GST_neighbour_get_current_address (&msg->peer);
if (address != NULL) if (address != NULL)
output_address (tc, &msg->peer, NULL, 0, address); output_address (tc, &msg->peer, NULL, 0, address);
} }
GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, if (GNUNET_YES != ntohl (msg->one_shot))
GNUNET_MESSAGE_TYPE_TRANSPORT setup_monitoring_client (client, &msg->peer);
_ADDRESS_ITERATE_RESPONSE); else
GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
GNUNET_MESSAGE_TYPE_TRANSPOR
T_ADDRESS_ITERATE_RESPONSE);
GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
} }
/** /**
* Start handling requests from clients. * Start handling requests from clients.
* *
* @param server server used to accept clients from. * @param server server used to accept clients from.
*/ */
void void
GST_clients_start (struct GNUNET_SERVER_Handle *server) GST_clients_start (struct GNUNET_SERVER_Handle *server)
skipping to change at line 808 skipping to change at line 936
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE,
sizeof (struct AddressIterateMessage)}, sizeof (struct AddressIterateMessage)},
{&GST_blacklist_handle_init, NULL, {&GST_blacklist_handle_init, NULL,
GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
sizeof (struct GNUNET_MessageHeader)}, sizeof (struct GNUNET_MessageHeader)},
{&GST_blacklist_handle_reply, NULL, {&GST_blacklist_handle_reply, NULL,
GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY,
sizeof (struct BlacklistMessage)}, sizeof (struct BlacklistMessage)},
{NULL, NULL, 0, 0} {NULL, NULL, 0, 0}
}; };
nc = GNUNET_SERVER_notification_context_create (server, 0);
GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_add_handlers (server, handlers);
GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
NULL); NULL);
} }
/** /**
* Stop processing clients. * Stop processing clients.
*/ */
void void
GST_clients_stop () GST_clients_stop ()
{ {
/* nothing to do */ if (NULL != nc)
{
GNUNET_SERVER_notification_context_destroy (nc);
nc = NULL;
}
} }
/** /**
* Broadcast the given message to all of our clients. * Broadcast the given message to all of our clients.
* *
* @param msg message to broadcast * @param msg message to broadcast
* @param may_drop GNUNET_YES if the message can be dropped / is payload * @param may_drop GNUNET_YES if the message can be dropped / is payload
*/ */
void void
GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop ) GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop )
skipping to change at line 860 skipping to change at line 993
const struct GNUNET_MessageHeader *msg, int may_drop) const struct GNUNET_MessageHeader *msg, int may_drop)
{ {
struct TransportClient *tc; struct TransportClient *tc;
tc = lookup_client (client); tc = lookup_client (client);
if (NULL == tc) if (NULL == tc)
return; /* client got disconnected in the meantime, drop message */ return; /* client got disconnected in the meantime, drop message */
unicast (tc, msg, may_drop); unicast (tc, msg, may_drop);
} }
/**
* Broadcast the new active address to all clients monitoring the peer.
*
* @param peer peer this update is about (never NULL)
* @param address address, NULL on disconnect
*/
void
GST_clients_broadcast_address_notification (const struct GNUNET_PeerIdentit
y
*peer,
const struct GNUNET_HELLO_Addre
ss
*address)
{
struct AddressIterateResponseMessage *msg;
struct MonitoringClient *mc;
static struct GNUNET_PeerIdentity all_zeros;
msg = compose_address_iterate_response_message (peer, address);
mc = monitoring_clients_head;
while (mc != NULL)
{
if ((0 == memcmp (&mc->peer, &all_zeros,
sizeof (struct GNUNET_PeerIdentity))) ||
(0 == memcmp (&mc->peer, peer,
sizeof (struct GNUNET_PeerIdentity))))
{
GNUNET_SERVER_notification_context_unicast (nc, mc->client,
&msg->header, GNUNET_NO);
}
mc = mc->next;
}
GNUNET_free (msg);
}
/* end of file gnunet-service-transport_clients.c */ /* end of file gnunet-service-transport_clients.c */
 End of changes. 19 change blocks. 
47 lines changed or deleted 213 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/