aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_http_client.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-06-23 18:16:32 +0000
committerChristian Grothoff <christian@grothoff.org>2014-06-23 18:16:32 +0000
commit889216c8f47d57a49a7eadd876c837a5df90c8f0 (patch)
tree360e64e22297aaf7c4dd563ea6516c36c7264e37 /src/transport/plugin_transport_http_client.c
parent85e0c60ee5c4bb74c0025f6f594687641a1dad93 (diff)
downloadgnunet-889216c8f47d57a49a7eadd876c837a5df90c8f0.tar.gz
gnunet-889216c8f47d57a49a7eadd876c837a5df90c8f0.zip
use session map instead of DLL
Diffstat (limited to 'src/transport/plugin_transport_http_client.c')
-rw-r--r--src/transport/plugin_transport_http_client.c227
1 files changed, 136 insertions, 91 deletions
diff --git a/src/transport/plugin_transport_http_client.c b/src/transport/plugin_transport_http_client.c
index 835df7cfc..fad7d2325 100644
--- a/src/transport/plugin_transport_http_client.c
+++ b/src/transport/plugin_transport_http_client.c
@@ -80,16 +80,6 @@ struct HTTP_Message
80 char *buf; 80 char *buf;
81 81
82 /** 82 /**
83 * amount of data already sent
84 */
85 size_t pos;
86
87 /**
88 * buffer length
89 */
90 size_t size;
91
92 /**
93 * Continuation function to call once the transmission buffer 83 * Continuation function to call once the transmission buffer
94 * has again space available. NULL if there is no 84 * has again space available. NULL if there is no
95 * continuation to call. 85 * continuation to call.
@@ -100,6 +90,17 @@ struct HTTP_Message
100 * Closure for @e transmit_cont. 90 * Closure for @e transmit_cont.
101 */ 91 */
102 void *transmit_cont_cls; 92 void *transmit_cont_cls;
93
94 /**
95 * amount of data already sent
96 */
97 size_t pos;
98
99 /**
100 * buffer length
101 */
102 size_t size;
103
103}; 104};
104 105
105 106
@@ -139,16 +140,6 @@ struct Session
139 struct GNUNET_PeerIdentity target; 140 struct GNUNET_PeerIdentity target;
140 141
141 /** 142 /**
142 * Stored in a linked list.
143 */
144 struct Session *next;
145
146 /**
147 * Stored in a linked list.
148 */
149 struct Session *prev;
150
151 /**
152 * The URL to connect to 143 * The URL to connect to
153 */ 144 */
154 char *url; 145 char *url;
@@ -273,14 +264,9 @@ struct HTTP_Client_Plugin
273 struct GNUNET_TRANSPORT_PluginEnvironment *env; 264 struct GNUNET_TRANSPORT_PluginEnvironment *env;
274 265
275 /** 266 /**
276 * Linked list head of open sessions. 267 * Open sessions.
277 */
278 struct Session *head;
279
280 /**
281 * Linked list tail of open sessions.
282 */ 268 */
283 struct Session *tail; 269 struct GNUNET_CONTAINER_MultiPeerMap *sessions;
284 270
285 /** 271 /**
286 * Plugin name 272 * Plugin name
@@ -587,25 +573,32 @@ client_delete_session (struct Session *s)
587 } 573 }
588 if (GNUNET_SCHEDULER_NO_TASK != s->put_disconnect_task) 574 if (GNUNET_SCHEDULER_NO_TASK != s->put_disconnect_task)
589 { 575 {
590 GNUNET_SCHEDULER_cancel (s->put_disconnect_task); 576 GNUNET_SCHEDULER_cancel (s->put_disconnect_task);
591 s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK; 577 s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK;
592 } 578 }
593 579 GNUNET_assert (GNUNET_OK ==
594 GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); 580 GNUNET_CONTAINER_multipeermap_remove (plugin->sessions,
581 &s->target,
582 s));
595 583
596 next = s->msg_head; 584 next = s->msg_head;
597 while (NULL != (pos = next)) 585 while (NULL != (pos = next))
598 { 586 {
599 next = pos->next; 587 next = pos->next;
600 GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, pos); 588 GNUNET_CONTAINER_DLL_remove (s->msg_head,
601 if (pos->transmit_cont != NULL) 589 s->msg_tail,
602 pos->transmit_cont (pos->transmit_cont_cls, &s->target, GNUNET_SYSERR, 590 pos);
603 pos->size, pos->pos + s->overhead); 591 if (NULL != pos->transmit_cont)
592 pos->transmit_cont (pos->transmit_cont_cls,
593 &s->target,
594 GNUNET_SYSERR,
595 pos->size,
596 pos->pos + s->overhead);
604 s->overhead = 0; 597 s->overhead = 0;
605 GNUNET_free (pos); 598 GNUNET_free (pos);
606 } 599 }
607 600
608 if (s->msg_tk != NULL) 601 if (NULL != s->msg_tk)
609 { 602 {
610 GNUNET_SERVER_mst_destroy (s->msg_tk); 603 GNUNET_SERVER_mst_destroy (s->msg_tk);
611 s->msg_tk = NULL; 604 s->msg_tk = NULL;
@@ -729,6 +722,27 @@ http_client_query_keepalive_factor (void *cls)
729 722
730 723
731/** 724/**
725 * Callback to destroys all sessions on exit.
726 *
727 * @param cls the `struct HTTP_Client_Plugin *`
728 * @param peer identity of the peer
729 * @param value the `struct Session *`
730 * @return #GNUNET_OK (continue iterating)
731 */
732static int
733destroy_session_cb (void *cls,
734 const struct GNUNET_PeerIdentity *peer,
735 void *value)
736{
737 struct HTTP_Client_Plugin *plugin = cls;
738 struct Session *session = value;
739
740 http_client_session_disconnect (plugin, session);
741 return GNUNET_OK;
742}
743
744
745/**
732 * Function that can be used to force the plugin to disconnect 746 * Function that can be used to force the plugin to disconnect
733 * from the given peer and cancel all previous transmissions 747 * from the given peer and cancel all previous transmissions
734 * (and their continuationc). 748 * (and their continuationc).
@@ -741,26 +755,57 @@ http_client_peer_disconnect (void *cls,
741 const struct GNUNET_PeerIdentity *target) 755 const struct GNUNET_PeerIdentity *target)
742{ 756{
743 struct HTTP_Client_Plugin *plugin = cls; 757 struct HTTP_Client_Plugin *plugin = cls;
744 struct Session *next = NULL;
745 struct Session *pos = NULL;
746 758
747 LOG (GNUNET_ERROR_TYPE_DEBUG, 759 LOG (GNUNET_ERROR_TYPE_DEBUG,
748 "Transport tells me to disconnect `%s'\n", 760 "Transport tells me to disconnect `%s'\n",
749 GNUNET_i2s (target)); 761 GNUNET_i2s (target));
762 GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions,
763 target,
764 &destroy_session_cb,
765 plugin);
766}
750 767
751 next = plugin->head; 768
752 while (NULL != (pos = next)) 769/**
770 * Closure for #session_lookup_client_by_address().
771 */
772struct SessionClientCtx
773{
774 /**
775 * Address we are looking for.
776 */
777 const struct GNUNET_HELLO_Address *address;
778
779 /**
780 * Session that was found.
781 */
782 struct Session *ret;
783};
784
785
786/**
787 * Locate the seession object for a given address.
788 *
789 * @param cls the `struct SessionClientCtx *`
790 * @param key peer identity
791 * @param value the `struct Session` to check
792 * @return #GNUNET_NO if found, #GNUNET_OK if not
793 */
794static int
795session_lookup_client_by_address (void *cls,
796 const struct GNUNET_PeerIdentity *key,
797 void *value)
798{
799 struct SessionClientCtx *sc_ctx = cls;
800 struct Session *s = value;
801
802 if (0 == GNUNET_HELLO_address_cmp (sc_ctx->address,
803 s->address))
753 { 804 {
754 next = pos->next; 805 sc_ctx->ret = s;
755 if (0 == memcmp (target, &pos->target, sizeof (struct GNUNET_PeerIdentity))) 806 return GNUNET_NO;
756 {
757 LOG (GNUNET_ERROR_TYPE_DEBUG,
758 "Disconnecting session %p to `%pos'\n",
759 pos, GNUNET_i2s (target));
760 GNUNET_assert (GNUNET_OK == http_client_session_disconnect (plugin,
761 pos));
762 }
763 } 807 }
808 return GNUNET_YES;
764} 809}
765 810
766 811
@@ -775,15 +820,14 @@ static struct Session *
775client_lookup_session (struct HTTP_Client_Plugin *plugin, 820client_lookup_session (struct HTTP_Client_Plugin *plugin,
776 const struct GNUNET_HELLO_Address *address) 821 const struct GNUNET_HELLO_Address *address)
777{ 822{
778 struct Session *pos; 823 struct SessionClientCtx sc_ctx;
779 824
780 for (pos = plugin->head; NULL != pos; pos = pos->next) 825 sc_ctx.address = address;
781 { 826 sc_ctx.ret = NULL;
782 if ((0 == memcmp (&address->peer, &pos->target, sizeof (struct GNUNET_PeerIdentity))) && 827 GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions,
783 (0 == GNUNET_HELLO_address_cmp(address, pos->address))) 828 &session_lookup_client_by_address,
784 return pos; 829 &sc_ctx);
785 } 830 return sc_ctx.ret;
786 return NULL;
787} 831}
788 832
789 833
@@ -893,7 +937,6 @@ client_wake_up (void *cls,
893 const struct GNUNET_SCHEDULER_TaskContext *tc) 937 const struct GNUNET_SCHEDULER_TaskContext *tc)
894{ 938{
895 struct Session *s = cls; 939 struct Session *s = cls;
896 struct HTTP_Client_Plugin *p = s->plugin;
897 940
898 s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK; 941 s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK;
899 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 942 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
@@ -918,7 +961,8 @@ client_wake_up (void *cls,
918 * @return always #GNUNET_OK 961 * @return always #GNUNET_OK
919 */ 962 */
920static int 963static int
921client_receive_mst_cb (void *cls, void *client, 964client_receive_mst_cb (void *cls,
965 void *client,
922 const struct GNUNET_MessageHeader *message) 966 const struct GNUNET_MessageHeader *message)
923{ 967{
924 struct Session *s = cls; 968 struct Session *s = cls;
@@ -1554,17 +1598,17 @@ http_client_plugin_get_session (void *cls,
1554 const struct GNUNET_HELLO_Address *address) 1598 const struct GNUNET_HELLO_Address *address)
1555{ 1599{
1556 struct HTTP_Client_Plugin *plugin = cls; 1600 struct HTTP_Client_Plugin *plugin = cls;
1557 struct Session * s = NULL; 1601 struct Session *s;
1558 struct sockaddr *sa; 1602 struct sockaddr *sa;
1559 struct GNUNET_ATS_Information ats; 1603 struct GNUNET_ATS_Information ats;
1560 size_t salen = 0; 1604 size_t salen = 0;
1561 int res; 1605 int res;
1562 1606
1563 GNUNET_assert (address->address != NULL); 1607 GNUNET_assert (NULL != address->address);
1564 1608
1565 /* find existing session */ 1609 /* find existing session */
1566 s = client_lookup_session (plugin, address); 1610 s = client_lookup_session (plugin, address);
1567 if (s != NULL) 1611 if (NULL != s)
1568 return s; 1612 return s;
1569 1613
1570 if (plugin->max_connections <= plugin->cur_connections) 1614 if (plugin->max_connections <= plugin->cur_connections)
@@ -1582,10 +1626,8 @@ http_client_plugin_get_session (void *cls,
1582 ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED); 1626 ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED);
1583 sa = http_common_socket_from_address (address->address, address->address_length, &res); 1627 sa = http_common_socket_from_address (address->address, address->address_length, &res);
1584 if (GNUNET_SYSERR == res) 1628 if (GNUNET_SYSERR == res)
1585 {
1586 return NULL; 1629 return NULL;
1587 } 1630 if (GNUNET_YES == res)
1588 else if (GNUNET_YES == res)
1589 { 1631 {
1590 GNUNET_assert (NULL != sa); 1632 GNUNET_assert (NULL != sa);
1591 if (AF_INET == sa->sa_family) 1633 if (AF_INET == sa->sa_family)
@@ -1630,8 +1672,10 @@ http_client_plugin_get_session (void *cls,
1630 GNUNET_i2s (&s->target)); 1672 GNUNET_i2s (&s->target));
1631 1673
1632 /* add new session */ 1674 /* add new session */
1633 GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); 1675 (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessions,
1634 1676 &s->target,
1677 s,
1678 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1635 /* initiate new connection */ 1679 /* initiate new connection */
1636 if (GNUNET_SYSERR == client_connect (s)) 1680 if (GNUNET_SYSERR == client_connect (s))
1637 { 1681 {
@@ -1727,8 +1771,6 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
1727{ 1771{
1728 struct GNUNET_TRANSPORT_PluginFunctions *api = cls; 1772 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1729 struct HTTP_Client_Plugin *plugin = api->cls; 1773 struct HTTP_Client_Plugin *plugin = api->cls;
1730 struct Session *pos;
1731 struct Session *next;
1732 1774
1733 if (NULL == api->cls) 1775 if (NULL == api->cls)
1734 { 1776 {
@@ -1736,39 +1778,30 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
1736 GNUNET_free (api); 1778 GNUNET_free (api);
1737 return NULL; 1779 return NULL;
1738 } 1780 }
1739
1740 LOG (GNUNET_ERROR_TYPE_DEBUG, 1781 LOG (GNUNET_ERROR_TYPE_DEBUG,
1741 _("Shutting down plugin `%s'\n"), 1782 _("Shutting down plugin `%s'\n"),
1742 plugin->name); 1783 plugin->name);
1743 1784 GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions,
1744 next = plugin->head; 1785 &destroy_session_cb,
1745 while (NULL != (pos = next)) 1786 plugin);
1746 {
1747 next = pos->next;
1748 http_client_session_disconnect (plugin, pos);
1749 }
1750 if (GNUNET_SCHEDULER_NO_TASK != plugin->client_perform_task) 1787 if (GNUNET_SCHEDULER_NO_TASK != plugin->client_perform_task)
1751 { 1788 {
1752 GNUNET_SCHEDULER_cancel (plugin->client_perform_task); 1789 GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
1753 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; 1790 plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
1754 } 1791 }
1755
1756
1757 if (NULL != plugin->curl_multi_handle) 1792 if (NULL != plugin->curl_multi_handle)
1758 { 1793 {
1759 curl_multi_cleanup (plugin->curl_multi_handle); 1794 curl_multi_cleanup (plugin->curl_multi_handle);
1760 plugin->curl_multi_handle = NULL; 1795 plugin->curl_multi_handle = NULL;
1761 } 1796 }
1762 curl_global_cleanup (); 1797 curl_global_cleanup ();
1763
1764 LOG (GNUNET_ERROR_TYPE_DEBUG, 1798 LOG (GNUNET_ERROR_TYPE_DEBUG,
1765 _("Shutdown for plugin `%s' complete\n"), 1799 _("Shutdown for plugin `%s' complete\n"),
1766 plugin->name); 1800 plugin->name);
1767 1801 GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions);
1768 GNUNET_free_non_null (plugin->proxy_hostname); 1802 GNUNET_free_non_null (plugin->proxy_hostname);
1769 GNUNET_free_non_null (plugin->proxy_username); 1803 GNUNET_free_non_null (plugin->proxy_username);
1770 GNUNET_free_non_null (plugin->proxy_password); 1804 GNUNET_free_non_null (plugin->proxy_password);
1771
1772 GNUNET_free (plugin); 1805 GNUNET_free (plugin);
1773 GNUNET_free (api); 1806 GNUNET_free (api);
1774 return NULL; 1807 return NULL;
@@ -1819,8 +1852,11 @@ client_configure_plugin (struct HTTP_Client_Plugin *plugin)
1819 } 1852 }
1820 1853
1821 /* proxy password */ 1854 /* proxy password */
1822 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, 1855 if (GNUNET_OK ==
1823 plugin->name, "PROXY_PASSWORD", &plugin->proxy_password)) 1856 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg,
1857 plugin->name,
1858 "PROXY_PASSWORD",
1859 &plugin->proxy_password))
1824 { 1860 {
1825 LOG (GNUNET_ERROR_TYPE_DEBUG, 1861 LOG (GNUNET_ERROR_TYPE_DEBUG,
1826 "Found proxy password name: `%s'\n", 1862 "Found proxy password name: `%s'\n",
@@ -1828,8 +1864,11 @@ client_configure_plugin (struct HTTP_Client_Plugin *plugin)
1828 } 1864 }
1829 1865
1830 /* proxy type */ 1866 /* proxy type */
1831 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, 1867 if (GNUNET_OK ==
1832 plugin->name, "PROXY_TYPE", &proxy_type)) 1868 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg,
1869 plugin->name,
1870 "PROXY_TYPE",
1871 &proxy_type))
1833 { 1872 {
1834 GNUNET_STRINGS_utf8_toupper (proxy_type, proxy_type); 1873 GNUNET_STRINGS_utf8_toupper (proxy_type, proxy_type);
1835 1874
@@ -1883,21 +1922,25 @@ http_plugin_address_to_string (void *cls,
1883 const void *addr, 1922 const void *addr,
1884 size_t addrlen) 1923 size_t addrlen)
1885{ 1924{
1886 return http_common_plugin_address_to_string (cls, PLUGIN_NAME, addr, addrlen); 1925 return http_common_plugin_address_to_string (cls,
1926 PLUGIN_NAME,
1927 addr,
1928 addrlen);
1887} 1929}
1888 1930
1889 1931
1890static void 1932static void
1891http_client_plugin_update_session_timeout (void *cls, 1933http_client_plugin_update_session_timeout (void *cls,
1892 const struct GNUNET_PeerIdentity *peer, 1934 const struct GNUNET_PeerIdentity *peer,
1893 struct Session *session) 1935 struct Session *session)
1894{ 1936{
1895 struct HTTP_Client_Plugin *plugin = cls; 1937 // struct HTTP_Client_Plugin *plugin = cls;
1896 1938
1897 /* lookup if session is really existing */ 1939 /* lookup if session is really existing */
1898 client_reschedule_session_timeout (session); 1940 client_reschedule_session_timeout (session);
1899} 1941}
1900 1942
1943
1901/** 1944/**
1902 * Entry point for the plugin. 1945 * Entry point for the plugin.
1903 */ 1946 */
@@ -1922,6 +1965,8 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
1922 1965
1923 plugin = GNUNET_new (struct HTTP_Client_Plugin); 1966 plugin = GNUNET_new (struct HTTP_Client_Plugin);
1924 plugin->env = env; 1967 plugin->env = env;
1968 plugin->sessions = GNUNET_CONTAINER_multipeermap_create (128,
1969 GNUNET_YES);
1925 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); 1970 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
1926 api->cls = plugin; 1971 api->cls = plugin;
1927 api->send = &http_client_plugin_send; 1972 api->send = &http_client_plugin_send;