GNUnet  0.10.x
gnunet-service-core_sessions.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2014, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet-service-core.h"
28 #include "gnunet-service-core_kx.h"
31 #include "gnunet_constants.h"
32 #include "core.h"
33 
34 
39 #define MAX_ENCRYPTED_MESSAGE_QUEUE_SIZE 4
40 
41 
51 
56 
61 
66 
71 
78 
84  size_t size;
85 };
86 
87 
91 struct Session {
95  const struct GNUNET_PeerIdentity *peer;
96 
101 
107 
113 
118 
123 
127  struct GSC_TypeMap *tmap;
128 
133 
138 
143  struct GNUNET_TIME_Relative typemap_delay;
144 
151 };
152 
153 
155 
163  struct GNUNET_MessageHeader header;
164 
169 
173  struct GNUNET_HashCode tm_hash;
174 };
175 
177 
178 
183 
184 
192 static struct Session *
194 {
195  if (NULL == sessions)
196  return NULL;
197  return GNUNET_CONTAINER_multipeermap_get(sessions, peer);
198 }
199 
200 
207 void
209 {
210  struct Session *session;
211  struct GSC_ClientActiveRequest *car;
212  struct SessionMessageEntry *sme;
213 
214  session = find_session(pid);
215  if (NULL == session)
216  return;
218  "Destroying session for peer `%s'\n",
219  GNUNET_i2s(session->peer));
220  if (NULL != session->cork_task)
221  {
223  session->cork_task = NULL;
224  }
225  while (NULL != (car = session->active_client_request_head))
226  {
229  car);
231  }
232  while (NULL != (sme = session->sme_head))
233  {
234  GNUNET_CONTAINER_DLL_remove(session->sme_head, session->sme_tail, sme);
235  GNUNET_free(sme);
236  }
237  if (NULL != session->typemap_task)
238  {
240  session->typemap_task = NULL;
241  }
243  session->tmap,
244  NULL);
246  GNUNET_YES ==
247  GNUNET_CONTAINER_multipeermap_remove(sessions, session->peer, session));
249  gettext_noop("# peers connected"),
251  GNUNET_NO);
252  GSC_TYPEMAP_destroy(session->tmap);
253  session->tmap = NULL;
254  GNUNET_free(session);
255 }
256 
257 
264 static void
266 {
267  struct Session *session = cls;
268  struct GNUNET_MessageHeader *hdr;
269  struct GNUNET_TIME_Relative delay;
270 
272  "Sending TYPEMAP to %s\n",
273  GNUNET_i2s(session->peer));
275  delay = session->typemap_delay;
276  /* randomize a bit to avoid spont. sync */
277  delay.rel_value_us +=
279  session->typemap_task =
282  gettext_noop("# type map refreshes sent"),
283  1,
284  GNUNET_NO);
286  GSC_KX_encrypt_and_transmit(session->kx, hdr, ntohs(hdr->size));
287  GNUNET_free(hdr);
288 }
289 
290 
296 static void
297 start_typemap_task(struct Session *session)
298 {
299  if (NULL != session->typemap_task)
304  session);
305 }
306 
307 
314 void
316  struct GSC_KeyExchangeInfo *kx)
317 {
318  struct Session *session;
319 
321  "Creating session for peer `%s'\n",
322  GNUNET_i2s(peer));
323  session = GNUNET_new(struct Session);
324  session->tmap = GSC_TYPEMAP_create();
325  session->peer = peer;
326  session->kx = kx;
329  sessions,
330  session->peer,
331  session,
334  gettext_noop("# peers connected"),
336  GNUNET_NO);
337  GSC_CLIENTS_notify_clients_about_neighbour(peer, NULL, session->tmap);
338  start_typemap_task(session);
339 }
340 
341 
349 void
351 {
352  struct Session *session;
353 
354  session = find_session(peer);
355  if (NULL == session)
356  {
357  /* KX/session is new for both sides; thus no need to restart what
358  has not yet begun */
359  return;
360  }
361  start_typemap_task(session);
362 }
363 
364 
372 void
374  const struct GNUNET_MessageHeader *msg)
375 {
376  const struct TypeMapConfirmationMessage *cmsg;
377  struct Session *session;
378 
379  session = find_session(peer);
380  if (NULL == session)
381  {
382  GNUNET_break(0);
383  return;
384  }
385  if (ntohs(msg->size) != sizeof(struct TypeMapConfirmationMessage))
386  {
387  GNUNET_break_op(0);
388  return;
389  }
390  cmsg = (const struct TypeMapConfirmationMessage *)msg;
392  {
393  /* our typemap has changed in the meantime, do not
394  accept confirmation */
396  gettext_noop(
397  "# outdated typemap confirmations received"),
398  1,
399  GNUNET_NO);
401  "Got outdated typemap confirmated from peer `%s'\n",
402  GNUNET_i2s(session->peer));
403  return;
404  }
406  "Got typemap confirmation from peer `%s'\n",
407  GNUNET_i2s(session->peer));
408  if (NULL != session->typemap_task)
409  {
411  session->typemap_task = NULL;
412  }
414  gettext_noop(
415  "# valid typemap confirmations received"),
416  1,
417  GNUNET_NO);
418 }
419 
420 
429 static int
431  const struct GNUNET_PeerIdentity *key,
432  void *value)
433 {
434  struct GSC_Client *client = cls;
435  struct Session *session = value;
436 
438  session->peer,
439  NULL, /* old TMAP: none */
440  session->tmap);
441  return GNUNET_OK;
442 }
443 
444 
450 void
452 {
453  /* notify new client about existing sessions */
456  client);
457 }
458 
459 
466 static void
467 try_transmission(struct Session *session);
468 
469 
479 void
481 {
482  struct Session *session;
483 
484  session = find_session(&car->target);
485  if (NULL == session)
486  {
488  "Dropped client request for transmission (am disconnected)\n");
489  GNUNET_break(0); /* should have been rejected earlier */
491  return;
492  }
494  {
495  GNUNET_break(0);
497  return;
498  }
500  "Received client transmission request. queueing\n");
503  car);
504  try_transmission(session);
505 }
506 
507 
514 void
516 {
517  struct Session *session;
518 
519  if (0 == memcmp(&car->target,
521  sizeof(struct GNUNET_PeerIdentity)))
522  return;
523  session = find_session(&car->target);
524  GNUNET_assert(NULL != session);
527  car);
528  /* dequeueing of 'high' priority messages may unblock
529  transmission for lower-priority messages, so we also
530  need to try in this case. */
531  try_transmission(session);
532 }
533 
534 
542 static void
543 solicit_messages(struct Session *session, size_t msize)
544 {
545  struct GSC_ClientActiveRequest *car;
546  struct GSC_ClientActiveRequest *nxt;
547  size_t so_size;
549 
550  so_size = msize;
552  for (car = session->active_client_request_head; NULL != car; car = car->next)
553  {
554  if (GNUNET_YES == car->was_solicited)
555  continue;
556  pmax = GNUNET_MAX(pmax, car->priority & GNUNET_MQ_PRIORITY_MASK);
557  }
558  nxt = session->active_client_request_head;
559  while (NULL != (car = nxt))
560  {
561  nxt = car->next;
562  if (car->priority < pmax)
563  continue;
565  break;
566  so_size += car->msize;
567  if (GNUNET_YES == car->was_solicited)
568  continue;
569  car->was_solicited = GNUNET_YES;
571  "Soliciting message with priority %u\n",
572  car->priority);
574  /* The above call may *dequeue* requests and thereby
575  clobber 'nxt'. Hence we need to restart from the
576  head of the list. */
577  nxt = session->active_client_request_head;
578  so_size = msize;
579  }
580 }
581 
582 
589 static void
590 pop_cork_task(void *cls)
591 {
592  struct Session *session = cls;
593 
594  session->cork_task = NULL;
595  try_transmission(session);
596 }
597 
598 
606 static void
607 try_transmission(struct Session *session)
608 {
609  struct SessionMessageEntry *pos;
610  size_t msize;
611  struct GNUNET_TIME_Absolute now;
612  struct GNUNET_TIME_Absolute min_deadline;
615  struct GSC_ClientActiveRequest *car;
616  int excess;
617 
618  msize = 0;
619  min_deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
620  /* if the peer has excess bandwidth, background traffic is allowed,
621  otherwise not */
624  {
626  "Transmission queue already very long, waiting...\n");
627  return; /* queue already too long */
628  }
629  excess = GSC_NEIGHBOURS_check_excess_bandwidth(session->kx);
630  if (GNUNET_YES == excess)
632  else
634  /* determine highest priority of 'ready' messages we already solicited from clients */
635  pos = session->sme_head;
636  while ((NULL != pos) &&
638  {
640  msize += pos->size;
641  maxp = GNUNET_MAX(maxp, pos->priority & GNUNET_MQ_PRIORITY_MASK);
642  min_deadline = GNUNET_TIME_absolute_min(min_deadline, pos->deadline);
643  pos = pos->next;
644  }
645  GNUNET_log(
647  "Calculating transmission set with %u priority (%s) and %s earliest deadline\n",
648  maxp,
649  (GNUNET_YES == excess) ? "excess bandwidth" : "limited bandwidth",
651  min_deadline),
652  GNUNET_YES));
653 
655  {
656  /* if highest already solicited priority from clients is not critical,
657  check if there are higher-priority messages to be solicited from clients */
658  if (GNUNET_YES == excess)
660  else
662  for (car = session->active_client_request_head; NULL != car;
663  car = car->next)
664  {
665  if (GNUNET_YES == car->was_solicited)
666  continue;
667  maxpc = GNUNET_MAX(maxpc, car->priority & GNUNET_MQ_PRIORITY_MASK);
668  }
669  if (maxpc > maxp)
670  {
671  /* we have messages waiting for solicitation that have a higher
672  priority than those that we already accepted; solicit the
673  high-priority messages first */
675  "Soliciting messages based on priority (%u > %u)\n",
676  maxpc,
677  maxp);
678  solicit_messages(session, 0);
679  return;
680  }
681  }
682  else
683  {
684  /* never solicit more, we have critical messages to process */
685  excess = GNUNET_NO;
687  }
688  now = GNUNET_TIME_absolute_get();
689  if (((GNUNET_YES == excess) || (maxpc >= GNUNET_MQ_PRIO_BEST_EFFORT)) &&
690  ((0 == msize) ||
692  (min_deadline.abs_value_us > now.abs_value_us))))
693  {
694  /* not enough ready yet (tiny message & cork possible), or no messages at all,
695  and either excess bandwidth or best-effort or higher message waiting at
696  client; in this case, we try to solicit more */
697  GNUNET_log(
699  "Soliciting messages (excess %d, maxpc %d, message size %u, deadline %s)\n",
700  excess,
701  maxpc,
702  (unsigned int)msize,
704  min_deadline),
705  GNUNET_YES));
706  solicit_messages(session, msize);
707  if (msize > 0)
708  {
709  /* if there is data to send, just not yet, make sure we do transmit
710  * it once the deadline is reached */
712  "Corking until %s\n",
715  GNUNET_YES));
716  if (NULL != session->cork_task)
718  session->cork_task =
719  GNUNET_SCHEDULER_add_at(min_deadline, &pop_cork_task, session);
720  }
721  else
722  {
724  "Queue empty, waiting for solicitations\n");
725  }
726  return;
727  }
729  "Building combined plaintext buffer to transmit message!\n");
730  /* create plaintext buffer of all messages (that fit), encrypt and
731  transmit */
732  {
733  static unsigned long long total_bytes;
734  static unsigned int total_msgs;
735  char pbuf[msize]; /* plaintext */
736  size_t used;
737 
738  used = 0;
739  while ((NULL != (pos = session->sme_head)) && (used + pos->size <= msize))
740  {
742  "Adding message of type %d (%d/%d) to payload for %s\n",
743  ntohs(((const struct GNUNET_MessageHeader *)&pos[1])->type),
744  pos->is_typemap,
745  pos->is_typemap_confirm,
746  GNUNET_i2s(session->peer));
747  GNUNET_memcpy(&pbuf[used], &pos[1], pos->size);
748  used += pos->size;
749  GNUNET_CONTAINER_DLL_remove(session->sme_head, session->sme_tail, pos);
750  GNUNET_free(pos);
751  }
752  /* compute average payload size */
753  total_bytes += used;
754  total_msgs++;
755  if (0 == total_msgs)
756  {
757  /* 2^32 messages, wrap around... */
758  total_msgs = 1;
759  total_bytes = used;
760  }
762  "# avg payload per encrypted message",
763  total_bytes / total_msgs,
764  GNUNET_NO);
765  /* now actually transmit... */
766  GSC_KX_encrypt_and_transmit(session->kx, pbuf, used);
767  }
768 }
769 
770 
780 static int
782  const struct GNUNET_PeerIdentity *key,
783  void *value)
784 {
785  const struct GNUNET_MessageHeader *hdr = cls;
786  struct Session *session = value;
787  struct SessionMessageEntry *sme;
788  uint16_t size;
789 
791  "Restarting sending TYPEMAP to %s\n",
792  GNUNET_i2s(session->peer));
793  size = ntohs(hdr->size);
794  for (sme = session->sme_head; NULL != sme; sme = sme->next)
795  {
796  if (GNUNET_YES == sme->is_typemap)
797  {
798  GNUNET_CONTAINER_DLL_remove(session->sme_head, session->sme_tail, sme);
799  GNUNET_free(sme);
800  break;
801  }
802  }
803  sme = GNUNET_malloc(sizeof(struct SessionMessageEntry) + size);
804  sme->is_typemap = GNUNET_YES;
805  GNUNET_memcpy(&sme[1], hdr, size);
806  sme->size = size;
808  GNUNET_CONTAINER_DLL_insert(session->sme_head, session->sme_tail, sme);
809  try_transmission(session);
810  start_typemap_task(session);
811  return GNUNET_OK;
812 }
813 
814 
821 void
823 {
824  if (NULL == sessions)
825  return;
828  (void *)msg);
829 }
830 
831 
839 void
841 {
842  struct Session *session;
843 
845  "Transport solicits for %s\n",
846  GNUNET_i2s(pid));
847  session = find_session(pid);
848  if (NULL == session)
849  return;
850  try_transmission(session);
851 }
852 
853 
862 void
864  const struct GNUNET_MessageHeader *msg,
866 {
867  struct Session *session;
868  struct SessionMessageEntry *sme;
869  struct SessionMessageEntry *pos;
870  size_t msize;
871 
872  session = find_session(&car->target);
873  if (NULL == session)
874  return;
875  msize = ntohs(msg->size);
876  sme = GNUNET_malloc(sizeof(struct SessionMessageEntry) + msize);
877  GNUNET_memcpy(&sme[1], msg, msize);
878  sme->size = msize;
879  sme->priority = priority;
880  if (0 != (GNUNET_MQ_PREF_CORK_ALLOWED & priority))
881  {
882  sme->deadline =
885  "Mesage corked, delaying transmission\n");
886  }
887  pos = session->sme_head;
888  while ((NULL != pos) && (pos->priority >= sme->priority))
889  pos = pos->next;
890  if (NULL == pos)
892  session->sme_tail,
893  sme);
894  else
896  session->sme_tail,
897  pos->prev,
898  sme);
899  try_transmission(session);
900 }
901 
902 
910 void
912  const struct GNUNET_MessageHeader *msg)
913 {
914  struct Session *session;
915  struct GSC_TypeMap *nmap;
916  struct SessionMessageEntry *sme;
917  struct TypeMapConfirmationMessage *tmc;
918 
919  nmap = GSC_TYPEMAP_get_from_message(msg);
920  if (NULL == nmap)
921  {
922  GNUNET_break_op(0);
923  return; /* malformed */
924  }
925  session = find_session(peer);
926  if (NULL == session)
927  {
928  GSC_TYPEMAP_destroy(nmap);
929  GNUNET_break(0);
930  return;
931  }
933  "Received TYPEMAP from %s\n",
934  GNUNET_i2s(session->peer));
935  for (sme = session->sme_head; NULL != sme; sme = sme->next)
936  {
937  if (GNUNET_YES == sme->is_typemap_confirm)
938  {
939  GNUNET_CONTAINER_DLL_remove(session->sme_head, session->sme_tail, sme);
940  GNUNET_free(sme);
941  break;
942  }
943  }
944  sme = GNUNET_malloc(sizeof(struct SessionMessageEntry) +
945  sizeof(struct TypeMapConfirmationMessage));
947  sme->size = sizeof(struct TypeMapConfirmationMessage);
950  tmc = (struct TypeMapConfirmationMessage *)&sme[1];
951  tmc->header.size = htons(sizeof(struct TypeMapConfirmationMessage));
953  tmc->reserved = htonl(0);
954  GSC_TYPEMAP_hash(nmap, &tmc->tm_hash);
955  GNUNET_CONTAINER_DLL_insert(session->sme_head, session->sme_tail, sme);
956  try_transmission(session);
957  GSC_CLIENTS_notify_clients_about_neighbour(peer, session->tmap, nmap);
958  GSC_TYPEMAP_destroy(session->tmap);
959  session->tmap = nmap;
960 }
961 
962 
971 void
973  uint16_t type)
974 {
975  struct Session *session;
976  struct GSC_TypeMap *nmap;
977 
978  if (0 == memcmp(peer, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
979  return;
980  session = find_session(peer);
981  GNUNET_assert(NULL != session);
982  if (GNUNET_YES == GSC_TYPEMAP_test_match(session->tmap, &type, 1))
983  return; /* already in it */
984  nmap = GSC_TYPEMAP_extend(session->tmap, &type, 1);
985  GSC_CLIENTS_notify_clients_about_neighbour(peer, session->tmap, nmap);
986  GSC_TYPEMAP_destroy(session->tmap);
987  session->tmap = nmap;
988 }
989 
990 
994 void
996 {
998 }
999 
1000 
1010 static int
1012  const struct GNUNET_PeerIdentity *key,
1013  void *value)
1014 {
1015  /* struct Session *session = value; */
1016 
1017  GSC_SESSIONS_end(key);
1018  return GNUNET_OK;
1019 }
1020 
1021 
1025 void
1027 {
1028  if (NULL != sessions)
1029  {
1032  NULL);
1034  sessions = NULL;
1035  }
1036 }
1037 
1038 /* end of gnunet-service-core_sessions.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct GNUNET_SCHEDULER_Task * cork_task
Task to transmit corked messages with a delay.
void GSC_SESSIONS_confirm_typemap(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg)
The other peer has confirmed receiving our type map, check if it is current and if so...
void GSC_SESSIONS_init()
Initialize sessions subsystem.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MessageHeader * GSC_TYPEMAP_compute_type_map_message()
Compute a type map message for this peer.
uint64_t rel_value_us
The actual value.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
size_t size
How long is the message? (number of bytes following the struct MessageEntry, but not including the si...
enum GNUNET_MQ_PriorityPreferences priority
How important is this message.
struct GSC_ClientActiveRequest * active_client_request_tail
Tail of list of requests from clients for transmission to this peer.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GSC_ClientActiveRequest * next
Active requests are kept in a doubly-linked list of the respective target peer.
#define GNUNET_TIME_UNIT_SECONDS
One second.
static void try_transmission(struct Session *session)
Try to perform a transmission on the given session.
int was_solicited
Has this request been solicited yet?
unsigned int GSC_NEIGHBOURS_get_queue_length(const struct GSC_KeyExchangeInfo *kxinfo)
Check how many messages are queued for the given neighbour.
common internal definitions for core service
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct SessionMessageEntry * sme_tail
Tail of list of messages ready for encryption.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Absolute deadline
Deadline for transmission, 1s after we received it (if we are not corking), otherwise "now"...
void GSC_SESSIONS_queue_request(struct GSC_ClientActiveRequest *car)
Queue a request from a client for transmission to a particular peer.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
#define GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
What is the maximum size for encrypted messages? Note that this number imposes a clear limit on the m...
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
management of map that specifies which message types this peer supports
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
Message ready for encryption.
void GSC_CLIENTS_reject_request(struct GSC_ClientActiveRequest *car, int drop_client)
We will never be ready to transmit the given message in (disconnect or invalid request).
Best-effort traffic (i.e.
Data structure for each client connected to the CORE service.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
void GSC_KX_encrypt_and_transmit(struct GSC_KeyExchangeInfo *kx, const void *payload, size_t payload_size)
Encrypt and transmit a message with the given payload.
static char * value
Value of the record to add/remove.
static void solicit_messages(struct Session *session, size_t msize)
Solicit messages for transmission, starting with those of the highest priority.
enum GNUNET_MQ_PriorityPreferences priority
How important is this request.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP
Other peer confirms having received the type map.
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
void GSC_SESSIONS_set_typemap(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg)
We have received a typemap message from a peer, update ours.
struct SessionMessageEntry * sme_head
Head of list of messages ready for encryption.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:686
static int do_restart_typemap_message(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Send an updated typemap message to the neighbour now, and restart typemap transmissions.
struct SessionMessageEntry * next
We keep messages in a doubly linked list.
Message sent to confirm that a typemap was received.
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
Record kept for each request for transmission issued by a client that is still pending.
void GSC_TYPEMAP_destroy(struct GSC_TypeMap *tmap)
Free the given type map.
Internal representation of the hash map.
struct SessionMessageEntry * prev
We keep messages in a doubly linked list.
static void pop_cork_task(void *cls)
Some messages were delayed (corked), but the timeout has now expired.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
struct GSC_TypeMap * tmap
Current type map for this peer.
Information about the status of a key exchange with another peer.
A 512-bit hashcode.
struct GSC_ClientActiveRequest * active_client_request_head
Head of list of requests from clients for transmission to this peer.
Globals for gnunet-service-core.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static struct Session * find_session(const struct GNUNET_PeerIdentity *peer)
Find the session for the given peer.
struct GNUNET_PeerIdentity GSC_my_identity
Our identity.
#define MAX_ENCRYPTED_MESSAGE_QUEUE_SIZE
How many encrypted messages do we queue at most? Needed to bound memory consumption.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
Data kept per session.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
void GSC_SESSIONS_solicit(const struct GNUNET_PeerIdentity *pid)
Traffic is being solicited for the given peer.
struct GNUNET_HashCode key
The key used in the DHT.
struct GSC_TypeMap * GSC_TYPEMAP_create()
Create an empty type map.
void GSC_CLIENTS_notify_client_about_neighbour(struct GSC_Client *client, const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new)
Notify a particular client about a change to existing connection to one of our neighbours (check if t...
Lowest priority, i.e.
void GSC_SESSIONS_create(const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx)
Create a session, a key exchange was just completed.
struct GNUNET_TIME_Relative typemap_delay
Retransmission delay we currently use for the typemap transmissions (if not confirmed).
const struct GNUNET_PeerIdentity * peer
Identity of the other peer.
static void transmit_typemap_task(void *cls)
Transmit our current typemap message to the other peer.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void GSC_SESSIONS_done()
Shutdown sessions subsystem.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
Bit mask to apply to extract the priority bits.
code for managing the key exchange (SET_KEY, PING, PONG) with other peers
static int free_session_helper(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Helper function for GSC_SESSIONS_done() to free all active sessions.
int is_typemap_confirm
Flag set to GNUNET_YES if this is a typemap confirmation message.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
void GSC_CLIENTS_solicit_request(struct GSC_ClientActiveRequest *car)
Tell a client that we are ready to receive the message.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
int GSC_TYPEMAP_check_hash(const struct GNUNET_HashCode *hc)
Check if the given hash matches our current type map.
The identity of the host (wraps the signing key of the peer).
int GSC_TYPEMAP_test_match(const struct GSC_TypeMap *tmap, const uint16_t *types, unsigned int tcnt)
Test if any of the types from the types array is in the given type map.
#define GNUNET_PACKED
gcc-ism to get packed structs.
void GSC_TYPEMAP_hash(const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
Hash the contents of a type map.
struct GNUNET_SCHEDULER_Task * typemap_task
Task to transmit our type map.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:302
void GSC_SESSIONS_notify_client_about_sessions(struct GSC_Client *client)
We have a new client, notify it about all current sessions.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
struct GNUNET_SERVICE_Client * client
Handle for the client with the server API.
struct GSC_TypeMap * GSC_TYPEMAP_extend(const struct GSC_TypeMap *tmap, const uint16_t *types, unsigned int tcnt)
Add additional types to a given typemap.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
void GSC_SESSIONS_transmit(struct GSC_ClientActiveRequest *car, const struct GNUNET_MessageHeader *msg, enum GNUNET_MQ_PriorityPreferences priority)
Transmit a message to a particular peer.
struct GSC_KeyExchangeInfo * kx
Key exchange state for this peer.
A type map describing which messages a given neighbour is able to process.
struct GNUNET_HashCode tm_hash
Hash of the (decompressed) type map that was received.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
void GSC_SESSIONS_dequeue_request(struct GSC_ClientActiveRequest *car)
Dequeue a request from a client from transmission to a particular peer.
Flag to indicate that CORKing is acceptable.
void GSC_SESSIONS_add_to_typemap(const struct GNUNET_PeerIdentity *peer, uint16_t type)
The given peer send a message of the specified type.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Header for all communications.
int is_typemap
Flag set to GNUNET_YES if this is a typemap message.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
uint32_t reserved
Reserved, always zero.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
void GSC_SESSIONS_broadcast_typemap(const struct GNUNET_MessageHeader *msg)
Broadcast an updated typemap message to all neighbours.
static unsigned long long reserved
How much space have we currently reserved?
int GSC_NEIGHBOURS_check_excess_bandwidth(const struct GSC_KeyExchangeInfo *kxinfo)
Check if the given neighbour has excess bandwidth available.
Highest priority, control traffic (i.e.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
#define GNUNET_CONSTANTS_MAX_CORK_DELAY
How long do we delay messages to get larger packet sizes (CORKing)?
static void start_typemap_task(struct Session *session)
Restart the typemap task for the given session.
struct GNUNET_PeerIdentity target
Which peer is the message going to be for?
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1214
static GNUNET_NETWORK_STRUCT_END struct GNUNET_CONTAINER_MultiPeerMap * sessions
Map of peer identities to struct Session.
int first_typemap
Is this the first time we&#39;re sending the typemap? If so, we want to send it a bit faster the second t...
void GSC_SESSIONS_end(const struct GNUNET_PeerIdentity *pid)
End the session with the given peer (we are no longer connected).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
uint16_t msize
How many bytes does the client intend to send?
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
void GSC_SESSIONS_reinit(const struct GNUNET_PeerIdentity *peer)
The other peer has indicated that it &#39;lost&#39; the session (KX down), reinitialize the session on our en...
struct GSC_TypeMap * GSC_TYPEMAP_get_from_message(const struct GNUNET_MessageHeader *msg)
Extract a type map from a TYPE_MAP message.
#define GNUNET_malloc(size)
Wrapper around malloc.
void GSC_CLIENTS_notify_clients_about_neighbour(const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new)
Notify all clients about a change to existing session.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static int notify_client_about_session(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Notify the given client about the session (client is new).
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956