aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/plugin_transport_http.c193
1 files changed, 130 insertions, 63 deletions
diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c
index 3421169ee..9f0f13e1c 100644
--- a/src/transport/plugin_transport_http.c
+++ b/src/transport/plugin_transport_http.c
@@ -42,7 +42,7 @@
42 42
43#define DEBUG_CURL GNUNET_NO 43#define DEBUG_CURL GNUNET_NO
44#define DEBUG_HTTP GNUNET_NO 44#define DEBUG_HTTP GNUNET_NO
45#define DEBUG_CONNECTIONS GNUNET_NO 45#define DEBUG_CONNECTIONS GNUNET_YES
46 46
47#define INBOUND GNUNET_NO 47#define INBOUND GNUNET_NO
48#define OUTBOUND GNUNET_YES 48#define OUTBOUND GNUNET_YES
@@ -153,6 +153,9 @@ struct HTTP_Message
153 153
154struct HTTP_PeerContext 154struct HTTP_PeerContext
155{ 155{
156 /**
157 * peer's identity
158 */
156 struct GNUNET_PeerIdentity identity; 159 struct GNUNET_PeerIdentity identity;
157 160
158 /** 161 /**
@@ -160,8 +163,22 @@ struct HTTP_PeerContext
160 */ 163 */
161 struct Plugin *plugin; 164 struct Plugin *plugin;
162 165
166 /**
167 * Linked list of connections with this peer
168 * head
169 */
163 struct Session * head; 170 struct Session * head;
171
172 /**
173 * Linked list of connections with this peer
174 * tail
175 */
164 struct Session * tail; 176 struct Session * tail;
177
178 /**
179 * id for next session
180 */
181 size_t session_id_counter;
165}; 182};
166 183
167 184
@@ -257,6 +274,11 @@ struct Session
257 unsigned int recv_force_disconnect; 274 unsigned int recv_force_disconnect;
258 275
259 /** 276 /**
277 * id for next session
278 */
279 size_t session_id;
280
281 /**
260 * entity managing sending data 282 * entity managing sending data
261 * outbound session: pointer to curl easy handle 283 * outbound session: pointer to curl easy handle
262 */ 284 */
@@ -337,16 +359,16 @@ http_plugin_address_to_string (void *cls,
337 const void *addr, 359 const void *addr,
338 size_t addrlen); 360 size_t addrlen);
339 361
340static char * create_url(void * cls, const void * addr, size_t addrlen) 362static char * create_url(void * cls, const void * addr, size_t addrlen, size_t id)
341{ 363{
342 struct Plugin *plugin = cls; 364 struct Plugin *plugin = cls;
343 char *url = NULL; 365 char *url = NULL;
344 366
345 GNUNET_assert ((addr!=NULL) && (addrlen != 0)); 367 GNUNET_assert ((addr!=NULL) && (addrlen != 0));
346 GNUNET_asprintf(&url, 368 GNUNET_asprintf(&url,
347 "http://%s/%s", 369 "http://%s/%s;%u",
348 http_plugin_address_to_string(NULL, addr, addrlen), 370 http_plugin_address_to_string(NULL, addr, addrlen),
349 (char *) (&plugin->my_ascii_hash_ident)); 371 (char *) (&plugin->my_ascii_hash_ident),id);
350 372
351 return url; 373 return url;
352} 374}
@@ -378,7 +400,9 @@ static struct Session * get_Session (void * cls, struct HTTP_PeerContext *pc, co
378 { 400 {
379 if (0 == memcmp(cc->addr, addr, addr_len)) 401 if (0 == memcmp(cc->addr, addr, addr_len))
380 { 402 {
381 con = cc; 403 /* connection can not be used, since it is disconnected */
404 if ((cc->recv_force_disconnect==GNUNET_NO) && (cc->send_force_disconnect==GNUNET_NO))
405 con = cc;
382 break; 406 break;
383 } 407 }
384 } 408 }
@@ -534,12 +558,14 @@ accessHandlerCallback (void *cls,
534 558
535 char address[INET6_ADDRSTRLEN+14]; 559 char address[INET6_ADDRSTRLEN+14];
536 struct GNUNET_PeerIdentity pi_in; 560 struct GNUNET_PeerIdentity pi_in;
561 size_t id_num = 0;
537 562
538 struct IPv4HttpAddress ipv4addr; 563 struct IPv4HttpAddress ipv4addr;
539 struct IPv6HttpAddress ipv6addr; 564 struct IPv6HttpAddress ipv6addr;
540 565
541 struct HTTP_PeerContext *pc; 566 struct HTTP_PeerContext *pc;
542 struct Session *ps; 567 struct Session *ps;
568 struct Session *ps_tmp;
543 569
544 int res = GNUNET_NO; 570 int res = GNUNET_NO;
545 int send_error_to_client; 571 int send_error_to_client;
@@ -552,7 +578,21 @@ accessHandlerCallback (void *cls,
552 if (NULL == *httpSessionCache) 578 if (NULL == *httpSessionCache)
553 { 579 {
554 /* check url for peer identity , if invalid send HTTP 404*/ 580 /* check url for peer identity , if invalid send HTTP 404*/
555 res = GNUNET_CRYPTO_hash_from_string ( &url[1], &(pi_in.hashPubKey)); 581 size_t len = strlen(&url[1]);
582 char * peer = GNUNET_malloc(104+1);
583
584 if ((len>104) && (url[104]==';'))
585 {
586 char * id = GNUNET_malloc((len-104)+1);
587 strcpy(id,&url[105]);
588 memcpy(peer,&url[1],103);
589 peer[103] = '\0';
590 id_num = strtoul ( id, NULL , 10);
591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"id is string %s num %u, peer is %s\n",id,id_num,peer);
592 GNUNET_free(id);
593 }
594 res = GNUNET_CRYPTO_hash_from_string (peer, &(pi_in.hashPubKey));
595 GNUNET_free(peer);
556 if ( GNUNET_SYSERR == res ) 596 if ( GNUNET_SYSERR == res )
557 { 597 {
558 response = MHD_create_response_from_data (strlen (HTTP_ERROR_RESPONSE),HTTP_ERROR_RESPONSE, MHD_NO, MHD_NO); 598 response = MHD_create_response_from_data (strlen (HTTP_ERROR_RESPONSE),HTTP_ERROR_RESPONSE, MHD_NO, MHD_NO);
@@ -580,6 +620,7 @@ accessHandlerCallback (void *cls,
580 { 620 {
581 pc = GNUNET_malloc(sizeof (struct HTTP_PeerContext)); 621 pc = GNUNET_malloc(sizeof (struct HTTP_PeerContext));
582 pc->plugin = plugin; 622 pc->plugin = plugin;
623 pc->session_id_counter=1;
583 memcpy(&pc->identity, &pi_in, sizeof(struct GNUNET_PeerIdentity)); 624 memcpy(&pc->identity, &pi_in, sizeof(struct GNUNET_PeerIdentity));
584 GNUNET_CONTAINER_multihashmap_put(plugin->peers, &pc->identity.hashPubKey, pc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 625 GNUNET_CONTAINER_multihashmap_put(plugin->peers, &pc->identity.hashPubKey, pc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
585 } 626 }
@@ -594,7 +635,6 @@ accessHandlerCallback (void *cls,
594 ipv4addr.u_port = addrin->sin_port; 635 ipv4addr.u_port = addrin->sin_port;
595 addr = &ipv4addr; 636 addr = &ipv4addr;
596 addr_len = sizeof(struct IPv4HttpAddress); 637 addr_len = sizeof(struct IPv4HttpAddress);
597 //con = session_check_inbound_address (plugin, cs, (const void *) &ipv4addr, sizeof (struct IPv4HttpAddress));
598 } 638 }
599 /* Incoming IPv6 connection */ 639 /* Incoming IPv6 connection */
600 if ( AF_INET6 == conn_info->client_addr->sin_family) 640 if ( AF_INET6 == conn_info->client_addr->sin_family)
@@ -606,10 +646,29 @@ accessHandlerCallback (void *cls,
606 addr = &ipv6addr; 646 addr = &ipv6addr;
607 addr_len = sizeof(struct IPv6HttpAddress); 647 addr_len = sizeof(struct IPv6HttpAddress);
608 } 648 }
609 /* Set closure and update current session*/ 649
650
610 ps = get_Session(plugin, pc, addr, addr_len); 651 ps = get_Session(plugin, pc, addr, addr_len);
652
653 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"SEARCHING HTTP SESSION\n");
654 ps_tmp = pc->head;
655 /*
656 while (ps_tmp!=NULL)
657 {
658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"SEARCHING HTTP SESSION II\n");
659 if ((ps_tmp->session_id == id_num) && (id_num!=0))
660 {
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP SESSION FOUND\n");
662 ps=ps_tmp;
663 break;
664 }
665 ps_tmp=ps_tmp->next;
666 }
667 */
668
611 if (ps==NULL) 669 if (ps==NULL)
612 { 670 {
671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"NO HTTP SESSION FOUND\n");
613 ps = GNUNET_malloc(sizeof (struct Session)); 672 ps = GNUNET_malloc(sizeof (struct Session));
614 ps->addr = GNUNET_malloc(addr_len); 673 ps->addr = GNUNET_malloc(addr_len);
615 memcpy(ps->addr,addr,addr_len); 674 memcpy(ps->addr,addr,addr_len);
@@ -622,7 +681,8 @@ accessHandlerCallback (void *cls,
622 ps->recv_connected=GNUNET_NO; 681 ps->recv_connected=GNUNET_NO;
623 ps->recv_active=GNUNET_NO; 682 ps->recv_active=GNUNET_NO;
624 ps->peercontext=pc; 683 ps->peercontext=pc;
625 ps->url = create_url (plugin, ps->addr, ps->addrlen); 684 ps->session_id =id_num;
685 ps->url = create_url (plugin, ps->addr, ps->addrlen, ps->session_id);
626 GNUNET_CONTAINER_DLL_insert(pc->head,pc->tail,ps); 686 GNUNET_CONTAINER_DLL_insert(pc->head,pc->tail,ps);
627 } 687 }
628 688
@@ -829,8 +889,7 @@ static void http_server_daemon_v6_run (void *cls,
829 * @param con connection 889 * @param con connection
830 * @return bytes sent to peer 890 * @return bytes sent to peer
831 */ 891 */
832static ssize_t send_check_connections (void *cls, struct Session* ses , struct Session *ps); 892static ssize_t send_check_connections (void *cls, struct Session *ps);
833
834 893
835static size_t curl_get_header_function( void *ptr, size_t size, size_t nmemb, void *stream) 894static size_t curl_get_header_function( void *ptr, size_t size, size_t nmemb, void *stream)
836{ 895{
@@ -855,7 +914,7 @@ static size_t curl_get_header_function( void *ptr, size_t size, size_t nmemb, vo
855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection %X: connected to recieve data\n",ps); 914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection %X: connected to recieve data\n",ps);
856#endif 915#endif
857 // Calling send_check_connections again since receive is established 916 // Calling send_check_connections again since receive is established
858 send_check_connections (ps->peercontext->plugin, NULL, ps); 917 send_check_connections (ps->peercontext->plugin, ps);
859 } 918 }
860 } 919 }
861 } 920 }
@@ -1016,7 +1075,6 @@ static size_t send_curl_receive_callback( void *stream, size_t size, size_t nmem
1016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection %X: %u bytes recieved\n",ps, size*nmemb); 1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection %X: %u bytes recieved\n",ps, size*nmemb);
1017#endif 1076#endif
1018 GNUNET_SERVER_mst_receive(ps->msgtok, ps, stream, size*nmemb, GNUNET_NO, GNUNET_NO); 1077 GNUNET_SERVER_mst_receive(ps->msgtok, ps, stream, size*nmemb, GNUNET_NO, GNUNET_NO);
1019
1020 return (size * nmemb); 1078 return (size * nmemb);
1021 1079
1022} 1080}
@@ -1038,7 +1096,7 @@ static size_t send_schedule(void *cls, struct Session* ses );
1038 * @param con connection 1096 * @param con connection
1039 * @return bytes sent to peer 1097 * @return bytes sent to peer
1040 */ 1098 */
1041static ssize_t send_check_connections (void *cls, struct Session* ses , struct Session *ps) 1099static ssize_t send_check_connections (void *cls, struct Session *ps)
1042{ 1100{
1043 struct Plugin *plugin = cls; 1101 struct Plugin *plugin = cls;
1044 int bytes_sent = 0; 1102 int bytes_sent = 0;
@@ -1434,10 +1492,9 @@ http_plugin_send (void *cls,
1434 struct HTTP_Message *msg; 1492 struct HTTP_Message *msg;
1435 1493
1436 struct HTTP_PeerContext * pc; 1494 struct HTTP_PeerContext * pc;
1437 struct Session * ps; 1495 struct Session * ps = NULL;
1438 1496
1439 GNUNET_assert(cls !=NULL); 1497 GNUNET_assert(cls !=NULL);
1440 GNUNET_assert ((addr!=NULL) && (addrlen != 0));
1441 1498
1442 pc = GNUNET_CONTAINER_multihashmap_get (plugin->peers, &target->hashPubKey); 1499 pc = GNUNET_CONTAINER_multihashmap_get (plugin->peers, &target->hashPubKey);
1443 /* Peer unknown */ 1500 /* Peer unknown */
@@ -1445,61 +1502,69 @@ http_plugin_send (void *cls,
1445 { 1502 {
1446 pc = GNUNET_malloc(sizeof (struct HTTP_PeerContext)); 1503 pc = GNUNET_malloc(sizeof (struct HTTP_PeerContext));
1447 pc->plugin = plugin; 1504 pc->plugin = plugin;
1505 pc->session_id_counter=1;
1448 memcpy(&pc->identity, target, sizeof(struct GNUNET_PeerIdentity)); 1506 memcpy(&pc->identity, target, sizeof(struct GNUNET_PeerIdentity));
1449 GNUNET_CONTAINER_multihashmap_put(plugin->peers, &pc->identity.hashPubKey, pc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1507 GNUNET_CONTAINER_multihashmap_put(plugin->peers, &pc->identity.hashPubKey, pc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1450 } 1508 }
1451 ps = get_Session(plugin, pc, addr, addrlen); 1509 if ((addr!=NULL) && (addrlen != 0))
1452
1453 /* session not existing, but address forced -> creating new session */
1454 if ((force_address == GNUNET_YES) && (ps==NULL))
1455 { 1510 {
1456 ps = GNUNET_malloc(sizeof (struct Session)); 1511 ps = get_Session(plugin, pc, addr, addrlen);
1457 ps->addr = GNUNET_malloc(addrlen);
1458 memcpy(ps->addr,addr,addrlen);
1459 ps->addrlen = addrlen;
1460 ps->direction=OUTBOUND;
1461 ps->recv_connected = GNUNET_NO;
1462 ps->send_connected = GNUNET_NO;
1463 ps->pending_msgs_head = NULL;
1464 ps->pending_msgs_tail = NULL;
1465 ps->peercontext=pc;
1466 ps->url = create_url (plugin, ps->addr, ps->addrlen);
1467 GNUNET_CONTAINER_DLL_insert(pc->head,pc->tail,ps);
1468 } 1512 }
1513 if (ps != NULL)
1514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Found existing connection to peer %s with given address, using %X\n", GNUNET_i2s(target), ps);
1515
1469 /* session not existing, address not forced -> looking for other session */ 1516 /* session not existing, address not forced -> looking for other session */
1470 if ((ps==NULL) && (force_address == GNUNET_NO)) 1517 if ((ps==NULL) && ((force_address == GNUNET_NO) || (force_address == GNUNET_SYSERR)))
1471 { 1518 {
1472 //struct PeerContext * tmp = pc->head; 1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"No existing connection, but free to choose existing, searching for existing connection to peer %s\n", GNUNET_i2s(target));
1473 1520 /* Choosing different session to peer when possible */
1474 1521 struct Session * tmp = pc->head;
1475 ps = GNUNET_malloc(sizeof (struct Session)); 1522 while (tmp!=NULL)
1476 ps->addr = GNUNET_malloc(addrlen); 1523 {
1477 memcpy(ps->addr,addr,addrlen); 1524 if ((tmp->recv_connected) && (tmp->send_connected) && (tmp->recv_force_disconnect==GNUNET_NO) && (tmp->send_force_disconnect==GNUNET_NO))
1478 ps->addrlen = addrlen; 1525 {
1479 ps->direction=OUTBOUND; 1526 ps = tmp;
1480 ps->recv_connected = GNUNET_NO; 1527 }
1481 ps->send_connected = GNUNET_NO; 1528 tmp = tmp->next;
1482 ps->pending_msgs_head = NULL; 1529 }
1483 ps->pending_msgs_tail = NULL; 1530 if (ps != NULL)
1484 ps->peercontext=pc; 1531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"No existing connection to peer %s, selected connection %X\n", GNUNET_i2s(target),ps);
1485 ps->url = create_url (plugin, ps->addr, ps->addrlen); 1532 else
1486 GNUNET_CONTAINER_DLL_insert(pc->head,pc->tail,ps); 1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"No existing connection to peer %s, no connection found\n", GNUNET_i2s(target));
1487 } 1534 }
1488 if ((ps==NULL) && (force_address == GNUNET_SYSERR)) 1535
1536 /* session not existing, but address forced -> creating new session */
1537 if ((ps==NULL) || ((ps==NULL) && (force_address == GNUNET_YES)))
1489 { 1538 {
1490 /* FIXME: CREATING SESSION, SHOULD CHOOSE EXISTING */ 1539 if ((addr!=NULL) && (addrlen!=0))
1491 ps = GNUNET_malloc(sizeof (struct Session)); 1540 {
1492 ps->addr = GNUNET_malloc(addrlen); 1541 if (force_address == GNUNET_YES)
1493 memcpy(ps->addr,addr,addrlen); 1542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"No existing connection & forced address: creating new connection to peer %s\n", GNUNET_i2s(target));
1494 ps->addrlen = addrlen; 1543 if (force_address != GNUNET_YES)
1495 ps->direction=OUTBOUND; 1544 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"No existing connection: creating new connection to peer %s\n", GNUNET_i2s(target));
1496 ps->recv_connected = GNUNET_NO; 1545
1497 ps->send_connected = GNUNET_NO; 1546 ps = GNUNET_malloc(sizeof (struct Session));
1498 ps->pending_msgs_head = NULL; 1547 ps->addr = GNUNET_malloc(addrlen);
1499 ps->pending_msgs_tail = NULL; 1548 memcpy(ps->addr,addr,addrlen);
1500 ps->peercontext=pc; 1549 ps->addrlen = addrlen;
1501 ps->url = create_url (plugin, ps->addr, ps->addrlen); 1550 ps->direction=OUTBOUND;
1502 GNUNET_CONTAINER_DLL_insert(pc->head,pc->tail,ps); 1551 ps->recv_connected = GNUNET_NO;
1552 ps->recv_force_disconnect = GNUNET_NO;
1553 ps->send_connected = GNUNET_NO;
1554 ps->send_force_disconnect = GNUNET_NO;
1555 ps->pending_msgs_head = NULL;
1556 ps->pending_msgs_tail = NULL;
1557 ps->peercontext=pc;
1558 ps->session_id = pc->session_id_counter;
1559 pc->session_id_counter++;
1560 ps->url = create_url (plugin, ps->addr, ps->addrlen, ps->session_id);
1561 GNUNET_CONTAINER_DLL_insert(pc->head,pc->tail,ps);
1562 }
1563 else
1564 {
1565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"No existing session & and no address given: no way to send this message to peer `%s'!\n", GNUNET_i2s(target));
1566 return -1;
1567 }
1503 } 1568 }
1504 1569
1505 char * force = GNUNET_malloc(30); 1570 char * force = GNUNET_malloc(30);
@@ -1528,7 +1593,7 @@ http_plugin_send (void *cls,
1528 memcpy (msg->buf,msgbuf, msgbuf_size); 1593 memcpy (msg->buf,msgbuf, msgbuf_size);
1529 GNUNET_CONTAINER_DLL_insert(ps->pending_msgs_head,ps->pending_msgs_tail,msg); 1594 GNUNET_CONTAINER_DLL_insert(ps->pending_msgs_head,ps->pending_msgs_tail,msg);
1530 1595
1531 return send_check_connections (plugin, session, ps); 1596 return send_check_connections (plugin, ps);
1532} 1597}
1533 1598
1534 1599
@@ -1565,12 +1630,14 @@ http_plugin_disconnect (void *cls,
1565 curl_multi_remove_handle(plugin->multi_handle,ps->send_endpoint); 1630 curl_multi_remove_handle(plugin->multi_handle,ps->send_endpoint);
1566 curl_easy_cleanup(ps->send_endpoint); 1631 curl_easy_cleanup(ps->send_endpoint);
1567 ps->send_endpoint=NULL; 1632 ps->send_endpoint=NULL;
1633 ps->send_force_disconnect = GNUNET_YES;
1568 } 1634 }
1569 if (ps->recv_endpoint!=NULL) 1635 if (ps->recv_endpoint!=NULL)
1570 { 1636 {
1571 curl_multi_remove_handle(plugin->multi_handle,ps->recv_endpoint); 1637 curl_multi_remove_handle(plugin->multi_handle,ps->recv_endpoint);
1572 curl_easy_cleanup(ps->recv_endpoint); 1638 curl_easy_cleanup(ps->recv_endpoint);
1573 ps->recv_endpoint=NULL; 1639 ps->recv_endpoint=NULL;
1640 ps->recv_force_disconnect = GNUNET_YES;
1574 } 1641 }
1575 } 1642 }
1576 if (ps->direction==INBOUND) 1643 if (ps->direction==INBOUND)