diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-10-06 19:03:36 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-10-06 19:03:36 +0000 |
commit | d7591587eb28a40e44a3065c30ec1b60a9bcba68 (patch) | |
tree | efcd2ce887c1c333fd323e95ec83755075bc91d2 /src/core/gnunet-service-core_clients.c | |
parent | 0046468edaf3131f5f13b33b5672831e880ccbe7 (diff) | |
download | gnunet-d7591587eb28a40e44a3065c30ec1b60a9bcba68.tar.gz gnunet-d7591587eb28a40e44a3065c30ec1b60a9bcba68.zip |
finishing clients draft
Diffstat (limited to 'src/core/gnunet-service-core_clients.c')
-rw-r--r-- | src/core/gnunet-service-core_clients.c | 564 |
1 files changed, 150 insertions, 414 deletions
diff --git a/src/core/gnunet-service-core_clients.c b/src/core/gnunet-service-core_clients.c index 7d56a49a5..333bd5ad8 100644 --- a/src/core/gnunet-service-core_clients.c +++ b/src/core/gnunet-service-core_clients.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "gnunet_service_core_typemap.h" | 32 | #include "gnunet_service_core_typemap.h" |
33 | 33 | ||
34 | 34 | ||
35 | |||
36 | /** | 35 | /** |
37 | * Data structure for each client connected to the core service. | 36 | * Data structure for each client connected to the core service. |
38 | */ | 37 | */ |
@@ -145,6 +144,31 @@ send_to_client (struct GSC_Client *client, | |||
145 | 144 | ||
146 | 145 | ||
147 | /** | 146 | /** |
147 | * Send a message to one of our clients. | ||
148 | * | ||
149 | * @param client target for the message | ||
150 | * @param msg message to transmit | ||
151 | * @param can_drop could this message be dropped if the | ||
152 | * client's queue is getting too large? | ||
153 | */ | ||
154 | void | ||
155 | GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client, | ||
156 | const struct GNUNET_MessageHeader *msg, | ||
157 | int can_drop) | ||
158 | { | ||
159 | struct GSC_Client *c; | ||
160 | |||
161 | c = find_client (client); | ||
162 | if (NULL == c) | ||
163 | { | ||
164 | GNUNET_break (0); | ||
165 | return; | ||
166 | } | ||
167 | send_to_client (c, msg, can_drop); | ||
168 | } | ||
169 | |||
170 | |||
171 | /** | ||
148 | * Test if the client is interested in messages of the given type. | 172 | * Test if the client is interested in messages of the given type. |
149 | * | 173 | * |
150 | * @param type message type | 174 | * @param type message type |
@@ -183,9 +207,12 @@ send_to_all_clients (const struct GNUNET_MessageHeader *msg, | |||
183 | 207 | ||
184 | for (c = client_head; c != NULL; c = c->next) | 208 | for (c = client_head; c != NULL; c = c->next) |
185 | { | 209 | { |
210 | if ( (0 != (c->options & options)) && | ||
211 | (GNUNET_YES == type_match (type, c)) ) | ||
212 | continue; /* both match, wait for only type match */ | ||
186 | if ( (0 == (c->options & options)) && | 213 | if ( (0 == (c->options & options)) && |
187 | (GNUNET_YES != type_match (type, c)) ) | 214 | (GNUNET_YES != type_match (type, c)) ) |
188 | continue; | 215 | continue; /* neither match, skip entirely */ |
189 | #if DEBUG_CORE_CLIENT > 1 | 216 | #if DEBUG_CORE_CLIENT > 1 |
190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
191 | "Sending message of type %u to client.\n", | 218 | "Sending message of type %u to client.\n", |
@@ -500,136 +527,144 @@ GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car) | |||
500 | } | 527 | } |
501 | 528 | ||
502 | 529 | ||
503 | |||
504 | // FIXME from here....................................... | ||
505 | |||
506 | |||
507 | |||
508 | |||
509 | |||
510 | |||
511 | /** | 530 | /** |
512 | * Notify client about an existing connection to one of our neighbours. | 531 | * Notify a particular client about a change to existing connection to |
532 | * one of our neighbours (check if the client is interested). Called | ||
533 | * from 'GSC_SESSIONS_notify_client_about_sessions'. | ||
534 | * | ||
535 | * @param client client to notify | ||
536 | * @param neighbour identity of the neighbour that changed status | ||
537 | * @param atsi performance information about neighbour | ||
538 | * @param atsi_count number of entries in 'ats' array | ||
539 | * @param tmap_old previous type map for the neighbour, NULL for disconnect | ||
540 | * @param tmap_new updated type map for the neighbour, NULL for disconnect | ||
513 | */ | 541 | */ |
514 | static int | 542 | void |
515 | notify_client_about_neighbour (void *cls, const GNUNET_HashCode * key, | 543 | GDS_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, |
516 | void *value) | 544 | const struct GNUNET_PeerIdentity *neighbour, |
545 | const struct GNUNET_TRANSPORT_ATS_Information *atsi, | ||
546 | unsigned int atsi_count, | ||
547 | const struct GSC_TypeMap *tmap_old, | ||
548 | const struct GSC_TypeMap *tmap_new) | ||
517 | { | 549 | { |
518 | struct GSC_Client *c = cls; | 550 | struct ConnectNotifyMessage *cnm; |
519 | struct Neighbour *n = value; | ||
520 | size_t size; | 551 | size_t size; |
521 | char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; | 552 | char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; |
522 | struct GNUNET_TRANSPORT_ATS_Information *ats; | 553 | struct GNUNET_TRANSPORT_ATS_Information *a; |
523 | struct ConnectNotifyMessage *cnm; | 554 | struct DisconnectNotifyMessage dcm; |
524 | 555 | int old_match; | |
525 | size = | 556 | int new_match; |
526 | sizeof (struct ConnectNotifyMessage) + | 557 | |
527 | (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); | 558 | old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt); |
528 | if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | 559 | new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt); |
560 | if (old_match == new_match) | ||
561 | return; /* no change */ | ||
562 | if (old_match == GNUNET_NO) | ||
529 | { | 563 | { |
530 | GNUNET_break (0); | 564 | /* send connect */ |
531 | /* recovery strategy: throw away performance data */ | ||
532 | GNUNET_array_grow (n->ats, n->ats_count, 0); | ||
533 | size = | 565 | size = |
534 | sizeof (struct ConnectNotifyMessage) + | 566 | sizeof (struct ConnectNotifyMessage) + |
535 | (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); | 567 | (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); |
536 | } | 568 | if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) |
537 | cnm = (struct ConnectNotifyMessage *) buf; | 569 | { |
538 | cnm->header.size = htons (size); | 570 | GNUNET_break (0); |
539 | cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); | 571 | /* recovery strategy: throw away performance data */ |
540 | cnm->ats_count = htonl (n->ats_count); | 572 | GNUNET_array_grow (n->ats, n->ats_count, 0); |
541 | ats = &cnm->ats; | 573 | size = |
542 | memcpy (ats, n->ats, | 574 | sizeof (struct ConnectNotifyMessage) + |
543 | sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count); | 575 | (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); |
544 | ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); | 576 | } |
545 | ats[n->ats_count].value = htonl (0); | 577 | cnm = (struct ConnectNotifyMessage *) buf; |
546 | if (n->status == PEER_STATE_KEY_CONFIRMED) | 578 | cnm->header.size = htons (size); |
547 | { | 579 | cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); |
580 | cnm->ats_count = htonl (atsi); | ||
581 | a = &cnm->atsi; | ||
582 | memcpy (a, atsi, | ||
583 | sizeof (struct GNUNET_TRANSPORT_ATS_Information) * atsi_count); | ||
584 | a[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); | ||
585 | a[ats_count].value = htonl (0); | ||
548 | #if DEBUG_CORE_CLIENT | 586 | #if DEBUG_CORE_CLIENT |
549 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n", | 587 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
588 | "Sending `%s' message to client.\n", | ||
550 | "NOTIFY_CONNECT"); | 589 | "NOTIFY_CONNECT"); |
551 | #endif | 590 | #endif |
552 | cnm->peer = n->peer; | 591 | cnm->peer = n->peer; |
553 | send_to_client (c, &cnm->header, GNUNET_NO); | 592 | send_to_client (client, &cnm->header, GNUNET_NO); |
593 | } | ||
594 | else | ||
595 | { | ||
596 | /* send disconnect */ | ||
597 | dcm.header.size = htons (sizeof (struct DisconnectNotifyMessage)); | ||
598 | dcm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT); | ||
599 | dcm.reserved = htonl (0); | ||
600 | dcm.peer = *peer; | ||
601 | send_to_client (client, &cnm.header, GNUNET_NO); | ||
554 | } | 602 | } |
555 | return GNUNET_OK; | ||
556 | } | 603 | } |
557 | 604 | ||
558 | 605 | ||
559 | |||
560 | /** | 606 | /** |
561 | * Helper function for handle_client_iterate_peers. | 607 | * Notify all clients about a change to existing session. |
608 | * Called from SESSIONS whenever there is a change in sessions | ||
609 | * or types processed by the respective peer. | ||
562 | * | 610 | * |
563 | * @param cls the 'struct GNUNET_SERVER_TransmitContext' to queue replies | 611 | * @param neighbour identity of the neighbour that changed status |
564 | * @param key identity of the connected peer | 612 | * @param atsi performance information about neighbour |
565 | * @param value the 'struct Neighbour' for the peer | 613 | * @param atsi_count number of entries in 'ats' array |
566 | * @return GNUNET_OK (continue to iterate) | 614 | * @param tmap_old previous type map for the neighbour, NULL for disconnect |
615 | * @param tmap_new updated type map for the neighbour, NULL for disconnect | ||
567 | */ | 616 | */ |
568 | static int | 617 | void |
569 | queue_connect_message (void *cls, const GNUNET_HashCode * key, void *value) | 618 | GDS_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, |
619 | const struct GNUNET_TRANSPORT_ATS_Information *atsi, | ||
620 | unsigned int atsi_count, | ||
621 | const struct GSC_TypeMap *tmap_old, | ||
622 | const struct GSC_TypeMap *tmap_new) | ||
570 | { | 623 | { |
571 | struct GNUNET_SERVER_TransmitContext *tc = cls; | 624 | struct GSC_Client *c; |
572 | struct Neighbour *n = value; | ||
573 | char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; | ||
574 | struct GNUNET_TRANSPORT_ATS_Information *ats; | ||
575 | size_t size; | ||
576 | struct ConnectNotifyMessage *cnm; | ||
577 | 625 | ||
578 | cnm = (struct ConnectNotifyMessage *) buf; | 626 | for (c = client_head; c != NULL; c = c->next) |
579 | if (n->status != PEER_STATE_KEY_CONFIRMED) | 627 | GDS_CLIENTS_notify_client_about_neighbour (c, neighbour, atsi, |
580 | return GNUNET_OK; | 628 | atsi_count, |
581 | size = | 629 | tmap_old, tmap_new); |
582 | sizeof (struct ConnectNotifyMessage) + | ||
583 | (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); | ||
584 | if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | ||
585 | { | ||
586 | GNUNET_break (0); | ||
587 | /* recovery strategy: throw away performance data */ | ||
588 | GNUNET_array_grow (n->ats, n->ats_count, 0); | ||
589 | size = | ||
590 | sizeof (struct PeerStatusNotifyMessage) + | ||
591 | n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information); | ||
592 | } | ||
593 | cnm = (struct ConnectNotifyMessage *) buf; | ||
594 | cnm->header.size = htons (size); | ||
595 | cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); | ||
596 | cnm->ats_count = htonl (n->ats_count); | ||
597 | ats = &cnm->ats; | ||
598 | memcpy (ats, n->ats, | ||
599 | n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)); | ||
600 | ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); | ||
601 | ats[n->ats_count].value = htonl (0); | ||
602 | #if DEBUG_CORE_CLIENT | ||
603 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n", | ||
604 | "NOTIFY_CONNECT"); | ||
605 | #endif | ||
606 | cnm->peer = n->peer; | ||
607 | GNUNET_SERVER_transmit_context_append_message (tc, &cnm->header); | ||
608 | return GNUNET_OK; | ||
609 | } | 630 | } |
610 | 631 | ||
611 | 632 | ||
612 | |||
613 | |||
614 | /** | 633 | /** |
615 | * Send a P2P message to a client. | 634 | * Deliver P2P message to interested clients. Caller must have checked |
635 | * that the sending peer actually lists the given message type as one | ||
636 | * of its types. | ||
616 | * | 637 | * |
617 | * @param sender who sent us the message? | 638 | * @param sender peer who sent us the message |
618 | * @param client who should we give the message to? | 639 | * @param atsi performance information about neighbour |
619 | * @param m contains the message to transmit | 640 | * @param atsi_count number of entries in 'ats' array |
620 | * @param msize number of bytes in buf to transmit | 641 | * @param msg the message |
642 | * @param msize number of bytes to transmit | ||
643 | * @param options options for checking which clients should | ||
644 | * receive the message | ||
621 | */ | 645 | */ |
622 | static void | 646 | void |
623 | send_p2p_message_to_client (struct Neighbour *sender, struct GSC_Client *client, | 647 | GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, |
624 | const void *m, size_t msize) | 648 | const struct GNUNET_TRANSPORT_ATS_Information *atsi, |
649 | unsigned int atsi_count, | ||
650 | const struct GNUNET_MessageHeader *msg, | ||
651 | uint16_t msize, | ||
652 | int options) | ||
625 | { | 653 | { |
626 | size_t size = | 654 | size_t size = msize + sizeof (struct NotifyTrafficMessage) + |
627 | msize + sizeof (struct NotifyTrafficMessage) + | ||
628 | (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); | 655 | (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information); |
629 | char buf[size]; | 656 | char buf[size]; |
630 | struct NotifyTrafficMessage *ntm; | 657 | struct NotifyTrafficMessage *ntm; |
631 | struct GNUNET_TRANSPORT_ATS_Information *ats; | 658 | struct GNUNET_TRANSPORT_ATS_Information *a; |
659 | int dropped; | ||
632 | 660 | ||
661 | if (0 == options) | ||
662 | { | ||
663 | GNUNET_snprintf (buf, sizeof (buf), | ||
664 | gettext_noop ("# bytes of messages of type %u received"), | ||
665 | (unsigned int) ntohs (msg->type)); | ||
666 | GNUNET_STATISTICS_update (stats, buf, msize, GNUNET_NO); | ||
667 | } | ||
633 | GNUNET_assert (GNUNET_YES == sender->is_connected); | 668 | GNUNET_assert (GNUNET_YES == sender->is_connected); |
634 | GNUNET_break (sender->status == PEER_STATE_KEY_CONFIRMED); | 669 | GNUNET_break (sender->status == PEER_STATE_KEY_CONFIRMED); |
635 | if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | 670 | if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) |
@@ -644,324 +679,25 @@ send_p2p_message_to_client (struct Neighbour *sender, struct GSC_Client *client, | |||
644 | #if DEBUG_CORE | 679 | #if DEBUG_CORE |
645 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 680 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
646 | "Core service passes message from `%4s' of type %u to client.\n", | 681 | "Core service passes message from `%4s' of type %u to client.\n", |
647 | GNUNET_i2s (&sender->peer), | 682 | GNUNET_i2s (sender), |
648 | (unsigned int) | 683 | (unsigned int) ntohs (msg->type)); |
649 | ntohs (((const struct GNUNET_MessageHeader *) m)->type)); | ||
650 | #endif | 684 | #endif |
651 | ntm = (struct NotifyTrafficMessage *) buf; | 685 | ntm = (struct NotifyTrafficMessage *) buf; |
652 | ntm->header.size = htons (size); | 686 | ntm->header.size = htons (size); |
653 | ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND); | 687 | ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND); |
654 | ntm->ats_count = htonl (sender->ats_count); | 688 | ntm->ats_count = htonl (atsi_count); |
655 | ntm->peer = sender->peer; | 689 | ntm->peer = sender->peer; |
656 | ats = &ntm->ats; | 690 | a = &ntm->ats; |
657 | memcpy (ats, sender->ats, | 691 | memcpy (a, atsi, |
658 | sizeof (struct GNUNET_TRANSPORT_ATS_Information) * sender->ats_count); | 692 | sizeof (struct GNUNET_TRANSPORT_ATS_Information) * sender->atsi_count); |
659 | ats[sender->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); | 693 | a[atsi_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); |
660 | ats[sender->ats_count].value = htonl (0); | 694 | a[atsi_count].value = htonl (0); |
661 | memcpy (&ats[sender->ats_count + 1], m, msize); | 695 | memcpy (&ats[atsi_count + 1], msg, msize); |
662 | send_to_client (client, &ntm->header, GNUNET_YES); | 696 | send_to_all_clients (&ntm->header, GNUNET_YES, |
663 | } | 697 | options, ntohs (msg->type)); |
664 | |||
665 | |||
666 | |||
667 | /** | ||
668 | * Notify a particular client about a change to existing connection to | ||
669 | * one of our neighbours (check if the client is interested). Called | ||
670 | * from 'GSC_SESSIONS_notify_client_about_sessions'. | ||
671 | * | ||
672 | * @param client client to notify | ||
673 | * @param neighbour identity of the neighbour that changed status | ||
674 | * @param tmap_old previous type map for the neighbour, NULL for disconnect | ||
675 | * @param tmap_new updated type map for the neighbour, NULL for disconnect | ||
676 | */ | ||
677 | void | ||
678 | GDS_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, | ||
679 | const struct GNUNET_PeerIdentity *neighbour, | ||
680 | const struct GSC_TypeMap *tmap_old, | ||
681 | const struct GSC_TypeMap *tmap_new) | ||
682 | { | ||
683 | } | ||
684 | |||
685 | |||
686 | /** | ||
687 | * Notify client about a change to existing connection to one of our neighbours. | ||
688 | * | ||
689 | * @param neighbour identity of the neighbour that changed status | ||
690 | * @param tmap_old previous type map for the neighbour, NULL for disconnect | ||
691 | * @param tmap_new updated type map for the neighbour, NULL for disconnect | ||
692 | */ | ||
693 | void | ||
694 | GDS_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, | ||
695 | const struct GSC_TypeMap *tmap_old, | ||
696 | const struct GSC_TypeMap *tmap_new) | ||
697 | { | ||
698 | } | ||
699 | |||
700 | |||
701 | /** | ||
702 | * Deliver P2P message to interested clients. | ||
703 | * | ||
704 | * @param sender peer who sent us the message | ||
705 | * @param m the message | ||
706 | */ | ||
707 | void | ||
708 | GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, | ||
709 | const struct GNUNET_MessageHeader *m) | ||
710 | { | ||
711 | struct Neighbour *sender = client; | ||
712 | size_t msize = ntohs (m->size); | ||
713 | char buf[256]; | ||
714 | struct GSC_Client *cpos; | ||
715 | uint16_t type; | ||
716 | unsigned int tpos; | ||
717 | int deliver_full; | ||
718 | int dropped; | ||
719 | |||
720 | GNUNET_break (sender->status == PEER_STATE_KEY_CONFIRMED); | ||
721 | type = ntohs (m->type); | ||
722 | #if DEBUG_CORE > 1 | ||
723 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
724 | "Received encapsulated message of type %u and size %u from `%4s'\n", | ||
725 | (unsigned int) type, ntohs (m->size), GNUNET_i2s (&sender->peer)); | ||
726 | #endif | ||
727 | GNUNET_snprintf (buf, sizeof (buf), | ||
728 | gettext_noop ("# bytes of messages of type %u received"), | ||
729 | (unsigned int) type); | ||
730 | GNUNET_STATISTICS_update (stats, buf, msize, GNUNET_NO); | ||
731 | if ((GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP == type) || | ||
732 | (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP == type)) | ||
733 | { | ||
734 | /* FIXME: update message type map for 'Neighbour' */ | ||
735 | return; | ||
736 | } | ||
737 | dropped = GNUNET_YES; | ||
738 | cpos = clients; | ||
739 | while (cpos != NULL) | ||
740 | { | ||
741 | deliver_full = GNUNET_NO; | ||
742 | if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) | ||
743 | deliver_full = GNUNET_YES; | ||
744 | else | ||
745 | { | ||
746 | for (tpos = 0; tpos < cpos->tcnt; tpos++) | ||
747 | { | ||
748 | if (type != cpos->types[tpos]) | ||
749 | continue; | ||
750 | deliver_full = GNUNET_YES; | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | if (GNUNET_YES == deliver_full) | ||
755 | { | ||
756 | send_p2p_message_to_client (sender, cpos, m, msize); | ||
757 | dropped = GNUNET_NO; | ||
758 | } | ||
759 | else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND) | ||
760 | { | ||
761 | send_p2p_message_to_client (sender, cpos, m, | ||
762 | sizeof (struct GNUNET_MessageHeader)); | ||
763 | } | ||
764 | cpos = cpos->next; | ||
765 | } | ||
766 | if (dropped == GNUNET_YES) | ||
767 | { | ||
768 | #if DEBUG_CORE | ||
769 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
770 | "Message of type %u from `%4s' not delivered to any client.\n", | ||
771 | (unsigned int) type, GNUNET_i2s (&sender->peer)); | ||
772 | #endif | ||
773 | GNUNET_STATISTICS_update (stats, | ||
774 | gettext_noop | ||
775 | ("# messages not delivered to any client"), 1, | ||
776 | GNUNET_NO); | ||
777 | } | ||
778 | } | 698 | } |
779 | 699 | ||
780 | 700 | ||
781 | |||
782 | |||
783 | /** | ||
784 | * Handle CORE_ITERATE_PEERS request. | ||
785 | * | ||
786 | * @param cls unused | ||
787 | * @param client client sending the iteration request | ||
788 | * @param message iteration request message | ||
789 | */ | ||
790 | static void | ||
791 | handle_client_iterate_peers (void *cls, struct GNUNET_SERVER_Client *client, | ||
792 | const struct GNUNET_MessageHeader *message) | ||
793 | { | ||
794 | struct GNUNET_MessageHeader done_msg; | ||
795 | struct GNUNET_SERVER_TransmitContext *tc; | ||
796 | int msize; | ||
797 | |||
798 | /* notify new client about existing neighbours */ | ||
799 | |||
800 | msize = ntohs (message->size); | ||
801 | tc = GNUNET_SERVER_transmit_context_create (client); | ||
802 | if (msize == sizeof (struct GNUNET_MessageHeader)) | ||
803 | GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, | ||
804 | tc); | ||
805 | else | ||
806 | GNUNET_break (0); | ||
807 | |||
808 | done_msg.size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
809 | done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END); | ||
810 | GNUNET_SERVER_transmit_context_append_message (tc, &done_msg); | ||
811 | GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); | ||
812 | } | ||
813 | |||
814 | |||
815 | /** | ||
816 | * Handle CORE_PEER_CONNECTED request. Notify client about existing neighbours. | ||
817 | * | ||
818 | * @param cls unused | ||
819 | * @param client client sending the iteration request | ||
820 | * @param message iteration request message | ||
821 | */ | ||
822 | static void | ||
823 | handle_client_have_peer (void *cls, struct GNUNET_SERVER_Client *client, | ||
824 | const struct GNUNET_MessageHeader *message) | ||
825 | { | ||
826 | struct GNUNET_MessageHeader done_msg; | ||
827 | struct GNUNET_SERVER_TransmitContext *tc; | ||
828 | struct GNUNET_PeerIdentity *peer; | ||
829 | |||
830 | tc = GNUNET_SERVER_transmit_context_create (client); | ||
831 | peer = (struct GNUNET_PeerIdentity *) &message[1]; | ||
832 | GNUNET_CONTAINER_multihashmap_get_multiple (neighbours, &peer->hashPubKey, | ||
833 | &queue_connect_message, tc); | ||
834 | done_msg.size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
835 | done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END); | ||
836 | GNUNET_SERVER_transmit_context_append_message (tc, &done_msg); | ||
837 | GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); | ||
838 | } | ||
839 | |||
840 | |||
841 | /** | ||
842 | * Handle REQUEST_INFO request. | ||
843 | * | ||
844 | * @param cls unused | ||
845 | * @param client client sending the request | ||
846 | * @param message iteration request message | ||
847 | */ | ||
848 | static void | ||
849 | handle_client_request_info (void *cls, struct GNUNET_SERVER_Client *client, | ||
850 | const struct GNUNET_MessageHeader *message) | ||
851 | { | ||
852 | const struct RequestInfoMessage *rcm; | ||
853 | struct GSC_Client *pos; | ||
854 | struct Neighbour *n; | ||
855 | struct ConfigurationInfoMessage cim; | ||
856 | int32_t want_reserv; | ||
857 | int32_t got_reserv; | ||
858 | unsigned long long old_preference; | ||
859 | struct GNUNET_TIME_Relative rdelay; | ||
860 | |||
861 | rdelay = GNUNET_TIME_relative_get_zero (); | ||
862 | #if DEBUG_CORE_CLIENT | ||
863 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' request.\n", | ||
864 | "REQUEST_INFO"); | ||
865 | #endif | ||
866 | pos = clients; | ||
867 | while (pos != NULL) | ||
868 | { | ||
869 | if (client == pos->client_handle) | ||
870 | break; | ||
871 | pos = pos->next; | ||
872 | } | ||
873 | if (pos == NULL) | ||
874 | { | ||
875 | GNUNET_break (0); | ||
876 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | rcm = (const struct RequestInfoMessage *) message; | ||
881 | n = find_neighbour (&rcm->peer); | ||
882 | memset (&cim, 0, sizeof (cim)); | ||
883 | if ((n != NULL) && (GNUNET_YES == n->is_connected)) | ||
884 | { | ||
885 | want_reserv = ntohl (rcm->reserve_inbound); | ||
886 | if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__) | ||
887 | { | ||
888 | n->bw_out_internal_limit = rcm->limit_outbound; | ||
889 | if (n->bw_out.value__ != | ||
890 | GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit, | ||
891 | n->bw_out_external_limit).value__) | ||
892 | { | ||
893 | n->bw_out = | ||
894 | GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit, | ||
895 | n->bw_out_external_limit); | ||
896 | GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window, | ||
897 | n->bw_out); | ||
898 | GNUNET_TRANSPORT_set_quota (transport, &n->peer, n->bw_in, n->bw_out); | ||
899 | handle_peer_status_change (n); | ||
900 | } | ||
901 | } | ||
902 | if (want_reserv < 0) | ||
903 | { | ||
904 | got_reserv = want_reserv; | ||
905 | } | ||
906 | else if (want_reserv > 0) | ||
907 | { | ||
908 | rdelay = | ||
909 | GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window, | ||
910 | want_reserv); | ||
911 | if (rdelay.rel_value == 0) | ||
912 | got_reserv = want_reserv; | ||
913 | else | ||
914 | got_reserv = 0; /* all or nothing */ | ||
915 | } | ||
916 | else | ||
917 | got_reserv = 0; | ||
918 | GNUNET_BANDWIDTH_tracker_consume (&n->available_recv_window, got_reserv); | ||
919 | old_preference = n->current_preference; | ||
920 | n->current_preference += GNUNET_ntohll (rcm->preference_change); | ||
921 | if (old_preference > n->current_preference) | ||
922 | { | ||
923 | /* overflow; cap at maximum value */ | ||
924 | n->current_preference = ULLONG_MAX; | ||
925 | } | ||
926 | update_preference_sum (n->current_preference - old_preference); | ||
927 | #if DEBUG_CORE_QUOTA | ||
928 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
929 | "Received reservation request for %d bytes for peer `%4s', reserved %d bytes, suggesting delay of %llu ms\n", | ||
930 | (int) want_reserv, GNUNET_i2s (&rcm->peer), (int) got_reserv, | ||
931 | (unsigned long long) rdelay.rel_value); | ||
932 | #endif | ||
933 | cim.reserved_amount = htonl (got_reserv); | ||
934 | cim.reserve_delay = GNUNET_TIME_relative_hton (rdelay); | ||
935 | cim.bw_out = n->bw_out; | ||
936 | cim.preference = n->current_preference; | ||
937 | } | ||
938 | else | ||
939 | { | ||
940 | /* Technically, this COULD happen (due to asynchronous behavior), | ||
941 | * but it should be rare, so we should generate an info event | ||
942 | * to help diagnosis of serious errors that might be masked by this */ | ||
943 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
944 | _ | ||
945 | ("Client asked for preference change with peer `%s', which is not connected!\n"), | ||
946 | GNUNET_i2s (&rcm->peer)); | ||
947 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
948 | return; | ||
949 | } | ||
950 | cim.header.size = htons (sizeof (struct ConfigurationInfoMessage)); | ||
951 | cim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO); | ||
952 | cim.peer = rcm->peer; | ||
953 | cim.rim_id = rcm->rim_id; | ||
954 | #if DEBUG_CORE_CLIENT | ||
955 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n", | ||
956 | "CONFIGURATION_INFO"); | ||
957 | #endif | ||
958 | send_to_client (pos, &cim.header, GNUNET_NO); | ||
959 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
960 | } | ||
961 | |||
962 | |||
963 | |||
964 | |||
965 | /** | 701 | /** |
966 | * Initialize clients subsystem. | 702 | * Initialize clients subsystem. |
967 | * | 703 | * |
@@ -973,14 +709,14 @@ GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server) | |||
973 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | 709 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { |
974 | {&handle_client_init, NULL, | 710 | {&handle_client_init, NULL, |
975 | GNUNET_MESSAGE_TYPE_CORE_INIT, 0}, | 711 | GNUNET_MESSAGE_TYPE_CORE_INIT, 0}, |
976 | {&handle_client_iterate_peers, NULL, | 712 | {&GSC_SESSIONS_handle_client_iterate_peers, NULL, |
977 | GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS, | 713 | GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS, |
978 | sizeof (struct GNUNET_MessageHeader)}, | 714 | sizeof (struct GNUNET_MessageHeader)}, |
979 | {&handle_client_have_peer, NULL, | 715 | {&GSC_SESSIONS_handle_client_have_peer, NULL, |
980 | GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED, | 716 | GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED, |
981 | sizeof (struct GNUNET_MessageHeader) + | 717 | sizeof (struct GNUNET_MessageHeader) + |
982 | sizeof (struct GNUNET_PeerIdentity)}, | 718 | sizeof (struct GNUNET_PeerIdentity)}, |
983 | {&handle_client_request_info, NULL, | 719 | {&GSC_SESSIONS_handle_client_request_info, NULL, |
984 | GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO, | 720 | GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO, |
985 | sizeof (struct RequestInfoMessage)}, | 721 | sizeof (struct RequestInfoMessage)}, |
986 | {&handle_client_send_request, NULL, | 722 | {&handle_client_send_request, NULL, |