};
+/**
+ * Big "or" of all client options.
+ */
+static uint32_t all_client_options;
+
/**
* Head of linked list of our clients.
*/
send_to_client (struct GSC_Client *client,
const struct GNUNET_MessageHeader *msg, int can_drop)
{
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Preparing to send %u bytes of message of type %u to client.\n",
(unsigned int) ntohs (msg->size),
(unsigned int) ntohs (msg->type));
-#endif
GNUNET_SERVER_notification_context_unicast (notifier, client->client_handle,
msg, can_drop);
}
* Send a message to all of our current clients that have the right
* options set.
*
+ * @param partner origin (or destination) of the message (used to check that this peer is
+ * known to be connected to the respective client)
* @param msg message to multicast
* @param can_drop can this message be discarded if the queue is too long
* @param options mask to use
* @param type type of the embedded message, 0 for none
*/
static void
-send_to_all_clients (const struct GNUNET_PeerIdentity *sender,
+send_to_all_clients (const struct GNUNET_PeerIdentity *partner,
const struct GNUNET_MessageHeader *msg, int can_drop,
- int options, uint16_t type)
+ uint32_t options, uint16_t type)
{
struct GSC_Client *c;
+ int tm;
for (c = client_head; c != NULL; c = c->next)
{
- if ((0 == (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
- (GNUNET_YES == type_match (type, c)))
- continue; /* not the full message, but we'd like the full one! */
- if ((0 == (c->options & options)) && (GNUNET_YES != type_match (type, c)))
- continue; /* neither options nor type match permit the message */
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending message to client interested in messages of type %u.\n",
+ tm = type_match (type, c);
+ if (! ( (0 != (c->options & options)) ||
+ ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
+ (GNUNET_YES == tm) ) ) )
+ continue; /* neither options nor type match permit the message */
+ if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
+ ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
+ (GNUNET_YES == tm) ) )
+ continue;
+ if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
+ (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) )
+ continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending %u message with %u bytes to client interested in messages of type %u.\n",
+ options,
+ ntohs (msg->size),
(unsigned int) type);
-#endif
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_contains (c->connectmap,
- &sender->hashPubKey));
+ GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
+ (GNUNET_YES != tm) ||
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_contains (c->connectmap,
+ &partner->hashPubKey)) );
send_to_client (c, msg, can_drop);
}
}
c->client_handle = client;
c->tcnt = msize / sizeof (uint16_t);
c->options = ntohl (im->options);
+ all_client_options |= c->options;
c->types = (const uint16_t *) &c[1];
c->connectmap = GNUNET_CONTAINER_multihashmap_create (16);
GNUNET_assert (GNUNET_YES ==
wtypes[i] = ntohs (types[i]);
GSC_TYPEMAP_add (wtypes, c->tcnt);
GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c);
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client connecting to core service is interested in %u message types\n",
(unsigned int) c->tcnt);
-#endif
/* send init reply message */
irm.header.size = htons (sizeof (struct InitReplyMessage));
irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
}
if (c->requests == NULL)
c->requests = GNUNET_CONTAINER_multihashmap_create (16);
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client asked for transmission to `%s'\n",
GNUNET_i2s (&req->peer));
-#endif
- is_loopback = (0 ==
- memcmp (&req->peer, &GSC_my_identity,
- sizeof (struct GNUNET_PeerIdentity)));
- if ( (! is_loopback) &&
- (GNUNET_YES !=
- GNUNET_CONTAINER_multihashmap_contains (c->connectmap,
- &req->peer.hashPubKey)) )
+ is_loopback =
+ (0 ==
+ memcmp (&req->peer, &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)));
+ if ((!is_loopback) &&
+ (GNUNET_YES !=
+ GNUNET_CONTAINER_multihashmap_contains (c->connectmap,
+ &req->peer.hashPubKey)))
{
/* neighbour must have disconnected since request was issued,
* ignore (client will realize it once it processes the
GSC_CLIENTS_solicit_request (car);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
- }
- GSC_SESSIONS_queue_request (car);
+ }
+ GSC_SESSIONS_queue_request (car);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
&sm->peer.hashPubKey,
tc.car));
tc.cork = ntohl (sm->cork);
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client asked for transmission of %u bytes to `%s' %s\n", msize,
GNUNET_i2s (&sm->peer), tc.cork ? "now" : "");
-#endif
GNUNET_SERVER_mst_receive (client_mst, &tc, (const char *) &sm[1], msize,
GNUNET_YES, GNUNET_NO);
if (0 !=
* @param client reservation request ('struct GSC_ClientActiveRequest')
* @param message the actual message
*/
-static void
+static int
client_tokenizer_callback (void *cls, void *client,
const struct GNUNET_MessageHeader *message)
{
memcmp (&car->target, &GSC_my_identity,
sizeof (struct GNUNET_PeerIdentity)))
{
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Delivering message of type %u to myself\n",
ntohs (message->type));
-#endif
GSC_CLIENTS_deliver_message (&GSC_my_identity, NULL, 0, message,
- ntohs (message->size),
- GNUNET_CORE_OPTION_SEND_FULL_INBOUND |
- GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
+ ntohs (message->size),
+ GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
+ GSC_CLIENTS_deliver_message (&GSC_my_identity, NULL, 0, message,
+ sizeof (struct GNUNET_MessageHeader),
+ GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
GSC_CLIENTS_deliver_message (&GSC_my_identity, NULL, 0, message,
- sizeof (struct GNUNET_MessageHeader),
- GNUNET_CORE_OPTION_SEND_HDR_INBOUND |
- GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
+ ntohs (message->size),
+ GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
+ GSC_CLIENTS_deliver_message (&GSC_my_identity, NULL, 0, message,
+ sizeof (struct GNUNET_MessageHeader),
+ GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
}
else
{
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Delivering message of type %u to %s\n", ntohs (message->type),
GNUNET_i2s (&car->target));
-#endif
+ GSC_CLIENTS_deliver_message (&car->target, NULL, 0, message,
+ ntohs (message->size),
+ GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
+ GSC_CLIENTS_deliver_message (&car->target, NULL, 0, message,
+ sizeof (struct GNUNET_MessageHeader),
+ GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
GSC_SESSIONS_transmit (car, message, tc->cork);
}
+ return GNUNET_OK;
}
if (client == NULL)
return;
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client %p has disconnected from core service.\n", client);
-#endif
c = find_client (client);
if (c == NULL)
return; /* client never sent INIT */
c->connectmap = NULL;
GSC_TYPEMAP_remove (c->types, c->tcnt);
GNUNET_free (c);
+
+ /* recalculate 'all_client_options' */
+ all_client_options = 0;
+ for (c = client_head; NULL != c ; c = c->next)
+ all_client_options |= c->options;
}
struct SendMessageReady smr;
c = car->client_handle;
+ if (GNUNET_YES !=
+ GNUNET_CONTAINER_multihashmap_contains (c->connectmap,
+ &car->target.hashPubKey))
+ {
+ /* connection has gone down since, drop request */
+ GNUNET_assert (0 !=
+ memcmp (&car->target, &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)));
+ GSC_SESSIONS_dequeue_request (car);
+ GSC_CLIENTS_reject_request (car);
+ return;
+ }
smr.header.size = htons (sizeof (struct SendMessageReady));
smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
smr.size = htons (car->msize);
smr.smr_id = car->smr_id;
smr.peer = car->target;
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_contains (c->connectmap,
- &car->
- target.hashPubKey));
send_to_client (c, &smr.header, GNUNET_NO);
}
* @param atsi_count number of entries in 'ats' array
* @param tmap_old previous type map for the neighbour, NULL for disconnect
* @param tmap_new updated type map for the neighbour, NULL for disconnect
- * @param is_new GNUNET_YES if this is a completely new neighbour
*/
void
GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client,
{
struct ConnectNotifyMessage *cnm;
size_t size;
- char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+ char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
struct GNUNET_ATS_Information *a;
struct DisconnectNotifyMessage dcm;
int old_match;
cnm->ats_count = htonl (atsi_count);
a = (struct GNUNET_ATS_Information *) &cnm[1];
memcpy (a, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count);
-#if DEBUG_CORE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n",
"NOTIFY_CONNECT");
-#endif
cnm->peer = *neighbour;
send_to_client (client, &cnm->header, GNUNET_NO);
}
const struct GNUNET_ATS_Information *atsi,
unsigned int atsi_count,
const struct GNUNET_MessageHeader *msg,
- uint16_t msize, int options)
+ uint16_t msize,
+ uint32_t options)
{
size_t size =
msize + sizeof (struct NotifyTrafficMessage) +
atsi_count * sizeof (struct GNUNET_ATS_Information);
- char buf[size];
+ char buf[size] GNUNET_ALIGN;
struct NotifyTrafficMessage *ntm;
struct GNUNET_ATS_Information *a;
atsi_count = 0;
size = msize + sizeof (struct NotifyTrafficMessage);
}
-#if DEBUG_CORE
+ if (! ( (0 != (all_client_options & options)) ||
+ (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ))
+ return; /* no client cares about this message notification */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Core service passes message from `%4s' of type %u to client.\n",
GNUNET_i2s (sender), (unsigned int) ntohs (msg->type));
-#endif
GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type));
ntm = (struct NotifyTrafficMessage *) buf;
ntm->header.size = htons (size);
- ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
+ if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
+ ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
+ else
+ ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND);
ntm->ats_count = htonl (atsi_count);
ntm->peer = *sender;
- a = &ntm->ats;
+ a = (struct GNUNET_ATS_Information*) &ntm[1];
memcpy (a, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count);
- a[atsi_count].type = htonl (GNUNET_ATS_ARRAY_TERMINATOR);
- a[atsi_count].value = htonl (0);
- memcpy (&a[atsi_count + 1], msg, msize);
+ memcpy (&a[atsi_count], msg, msize);
send_to_all_clients (sender, &ntm->header, GNUNET_YES, options,
ntohs (msg->type));
}