aboutsummaryrefslogtreecommitdiff
path: root/src/core/gnunet-service-core_clients.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-10-06 19:03:36 +0000
committerChristian Grothoff <christian@grothoff.org>2011-10-06 19:03:36 +0000
commitd7591587eb28a40e44a3065c30ec1b60a9bcba68 (patch)
treeefcd2ce887c1c333fd323e95ec83755075bc91d2 /src/core/gnunet-service-core_clients.c
parent0046468edaf3131f5f13b33b5672831e880ccbe7 (diff)
downloadgnunet-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.c564
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 */
154void
155GSC_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 */
514static int 542void
515notify_client_about_neighbour (void *cls, const GNUNET_HashCode * key, 543GDS_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 */
568static int 617void
569queue_connect_message (void *cls, const GNUNET_HashCode * key, void *value) 618GDS_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 */
622static void 646void
623send_p2p_message_to_client (struct Neighbour *sender, struct GSC_Client *client, 647GSC_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 */
677void
678GDS_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 */
693void
694GDS_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 */
707void
708GSC_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 */
790static void
791handle_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 */
822static void
823handle_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 */
848static void
849handle_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,