gws = GNUNET_NETWORK_fdset_create ();
GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
+
plugin->client_perform_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
GNUNET_SCHEDULER_NO_TASK,
{
#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Connection to '%s' %s ended\n", GNUNET_i2s(&s->target), http_plugin_address_to_string(s->plugin, s->addr, s->addrlen));
+ "Connection to '%s' %s ended\n", GNUNET_i2s(&s->target), http_plugin_address_to_string(plugin, s->addr, s->addrlen));
#endif
client_disconnect(s);
- notify_session_end (s->plugin, &s->target, s);
+ notify_session_end (plugin, &s->target, s);
}
}
{
int res = GNUNET_OK;
CURLMcode mret;
- struct Plugin *plugin = s->plugin;
+ struct Plugin *plugin = plugin;
#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
GNUNET_i2s (&s->target));
#endif
- mret = curl_multi_remove_handle (plugin->client_mh, s->client_put);
- if (mret != CURLM_OK)
+ if (s->client_put != NULL)
{
+ mret = curl_multi_remove_handle (plugin->client_mh, s->client_put);
+ if (mret != CURLM_OK)
+ {
+ curl_easy_cleanup (s->client_put);
+ res = GNUNET_SYSERR;
+ GNUNET_break (0);
+ }
curl_easy_cleanup (s->client_put);
- res = GNUNET_SYSERR;
- GNUNET_break (0);
+ s->client_put = NULL;
}
- curl_easy_cleanup (s->client_put);
#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
GNUNET_i2s (&s->target));
#endif
- mret = curl_multi_remove_handle (plugin->client_mh, s->client_get);
- if (mret != CURLM_OK)
+ if (s->client_get != NULL)
{
+ mret = curl_multi_remove_handle (plugin->client_mh, s->client_get);
+ if (mret != CURLM_OK)
+ {
+ curl_easy_cleanup (s->client_get);
+ res = GNUNET_SYSERR;
+ GNUNET_break (0);
+ }
curl_easy_cleanup (s->client_get);
- res = GNUNET_SYSERR;
- GNUNET_break (0);
+ s->client_get = NULL;
}
- curl_easy_cleanup (s->client_get);
- plugin->cur_connections += 2;
+
+ plugin->cur_connections -= 2;
/* Re-schedule since handles have changed */
if (plugin->client_perform_task!= GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
}
-
plugin->client_perform_task = GNUNET_SCHEDULER_add_now(client_run, plugin);
return res;
int
client_connect (struct Session *s)
{
+ struct Plugin *plugin = s->plugin;
int res = GNUNET_OK;
char *url;
CURLMcode mret;
-#if DEBUG_HTTP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
+#if VERBOSE_CLIENT
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Initiating outbound session peer `%s'\n",
GNUNET_i2s (&s->target));
#endif
s->inbound = GNUNET_NO;
- s->plugin->last_tag++;
+ plugin->last_tag++;
/* create url */
- GNUNET_asprintf (&url, "%s%s;%u", http_plugin_address_to_string (s->plugin, s->addr, s->addrlen), GNUNET_h2s_full (&s->plugin->env->my_identity->hashPubKey),s->plugin->last_tag);
+ GNUNET_asprintf (&url, "%s%s;%u", http_plugin_address_to_string (plugin, s->addr, s->addrlen), GNUNET_h2s_full (&plugin->env->my_identity->hashPubKey),plugin->last_tag);
#if 0
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"URL `%s'\n",
url);
#endif
GNUNET_free (url);
- mret = curl_multi_add_handle (s->plugin->client_mh, s->client_get);
+ mret = curl_multi_add_handle (plugin->client_mh, s->client_get);
if (mret != CURLM_OK)
{
curl_easy_cleanup (s->client_get);
GNUNET_break (0);
}
- mret = curl_multi_add_handle (s->plugin->client_mh, s->client_put);
+ mret = curl_multi_add_handle (plugin->client_mh, s->client_put);
if (mret != CURLM_OK)
{
- curl_multi_remove_handle (s->plugin->client_mh, s->client_get);
+ curl_multi_remove_handle (plugin->client_mh, s->client_get);
curl_easy_cleanup (s->client_get);
curl_easy_cleanup (s->client_put);
res = GNUNET_SYSERR;
}
/* Perform connect */
- s->plugin->cur_connections += 2;
- s->plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, s->plugin);
+ plugin->cur_connections += 2;
+
+ /* Re-schedule since handles have changed */
+ if (plugin->client_perform_task!= GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
+ plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, plugin);
return res;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "server: %s\n", text);
}
+struct ServerConnection
+{
+ /* _RECV or _SEND */
+ int direction;
+
+ /* should this connection get disconnected? GNUNET_YES/NO */
+ int disconnect;
+
+ struct Session *session;
+ struct MHD_Connection * mhd_conn;
+};
+
/**
* Check if incoming connection is accepted.
* NOTE: Here every connection is accepted
void **httpSessionCache)
{
struct Plugin *plugin = cls;
- struct Session *s = *httpSessionCache;
+ struct ServerConnection *sc = *httpSessionCache;
+ struct Session *s = NULL;
+
int res = MHD_YES;
struct MHD_Response *response;
GNUNET_assert (cls != NULL);
/* new connection */
- if (s == NULL)
- {
-
+ if (sc == NULL)
+ {
uint32_t tag;
const union MHD_ConnectionInfo *conn_info;
size_t addrlen;
if (t == NULL)
goto create;
- if ((direction == _SEND) && (t->server_get != NULL))
+#if VERBOSE_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "server: Found existing semi-session for `%s'\n", GNUNET_i2s (&target));
+#endif
+
+ if ((direction == _SEND) && (t->server_send != NULL))
{
#if VERBOSE_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "server: Duplicate GET session, dismissing new connection from peer `%s'\n", GNUNET_i2s (&target));
else
{
s = t;
- s->server_get = s;
GNUNET_CONTAINER_DLL_remove(plugin->server_semi_head, plugin->server_semi_tail, s);
GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, s);
#if VERBOSE_SERVER
goto found;
}
- if ((direction == _RECEIVE) && (t->server_put != NULL))
+ if ((direction == _RECEIVE) && (t->server_recv != NULL))
{
#if VERBOSE_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "server: Duplicate PUT session, dismissing new connection from peer `%s'\n", GNUNET_i2s (&target));
else
{
s = t;
- s->server_put = s;
GNUNET_CONTAINER_DLL_remove(plugin->server_semi_head, plugin->server_semi_tail, s);
GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, s);
#if VERBOSE_SERVER
s->inbound = GNUNET_YES;
s->tag= tag;
if (0 == strcmp (MHD_HTTP_METHOD_PUT, method))
- s->server_put = s;
+ s->server_recv = s;
if (0 == strcmp (MHD_HTTP_METHOD_GET, method))
- s->server_get = s;
+ s->server_send = s;
GNUNET_CONTAINER_DLL_insert (plugin->server_semi_head, plugin->server_semi_tail, s);
goto found;
found:
- (*httpSessionCache) = s;
- return MHD_YES;
+
+ sc = GNUNET_malloc (sizeof (struct ServerConnection));
+ sc->mhd_conn = mhd_connection;
+ sc->direction = direction;
+ sc->session = s;
+ if (direction == _SEND)
+ s->server_send = sc;
+ if (direction == _RECEIVE)
+ s->server_recv = sc;
+
+ (*httpSessionCache) = sc;
+ return MHD_YES;
}
+ /* existing connection */
+ sc = (*httpSessionCache);
+ s = sc->session;
+ /* connection is to be disconnected*/
+ if (sc->disconnect == GNUNET_YES)
+ {
+ response = MHD_create_response_from_data (strlen ("Thank you!"), "Thank you!", MHD_NO, MHD_NO);
+ res = MHD_queue_response (mhd_connection, MHD_HTTP_OK, response);
+#if VERBOSE_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sent HTTP/1.1: 200 OK as PUT Response\n");
+#endif
+ MHD_destroy_response (response);
+ return MHD_YES;
+ }
return res;
}
server_disconnect_cb (void *cls, struct MHD_Connection *connection,
void **httpSessionCache)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "server: server_disconnect_cb\n");
- /*
- struct Session *s = *httpSessionCache;
+ struct ServerConnection *sc = *httpSessionCache;
+ struct ServerConnection *tc = *httpSessionCache;
+ struct Session * s = NULL;
+ struct Session * t = NULL;
+ struct Plugin * plugin = NULL;
- if (s != NULL)
+ if (sc == NULL)
+ return;
+
+ s = sc->session;
+ plugin = s-> plugin;
+ if (sc->direction == _SEND)
+ {
+#if VERBOSE_SERVER
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Server: peer `%s' PUT on address `%s' disconnected\n",
+ GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen));
+#endif
+ s->server_send = NULL;
+ /* FIXME miminimize timeout here */
+ if (s->server_recv != NULL)
+ {
+ tc = s->server_recv;
+ tc->disconnect = GNUNET_YES;
+ }
+ }
+ if (sc->direction == _RECEIVE)
{
+#if VERBOSE_SERVER
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Server: peer `%s' GET on address `%s' disconnected\n",
+ GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen));
+#endif
+ s->server_recv = NULL;
+ //MHD_
+ if (s->server_send != NULL)
+ {
+ tc = s->server_send;
+ tc->disconnect = GNUNET_YES;
+ }
+ }
+ GNUNET_free (sc);
+
+ t = plugin->server_semi_head;
+ while (t != NULL)
+ {
+ if (t == s)
+ {
+ GNUNET_CONTAINER_DLL_remove(plugin->server_semi_head, plugin->server_semi_tail, s);
+ GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, s);
+ break;
+ }
+ t = t->next;
+ }
+
+ if ((s->server_send == NULL) && (s->server_recv == NULL))
+ {
+#if VERBOSE_SERVER
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Server: peer `%s' on address `%s' disconnected\n",
+ GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen));
+#endif
notify_session_end(s->plugin, &s->target, s);
}
-*/
}
int
server_disconnect (struct Session *s)
{
+ struct Plugin *plugin = s->plugin;
+ struct Session *t = plugin->head;
+
+ while (t != NULL)
+ {
+ if (t->inbound == GNUNET_YES)
+ {
+ if (t->server_send != NULL)
+ {
+ ((struct ServerConnection *) t->server_send)->disconnect = GNUNET_YES;
+ }
+ if (t->server_send != NULL)
+ {
+ ((struct ServerConnection *) t->server_send)->disconnect = GNUNET_YES;
+ }
+ }
+ t = t->next;
+ }
+
+
return GNUNET_OK;
}
void
server_stop (struct Plugin *plugin)
{
+ struct Session *s = NULL;
+ struct Session *t = NULL;
+
if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
plugin->server_v6 = NULL;
}
+ /* cleaning up semi-sessions never propagated */
+ s = plugin->server_semi_head;
+ while (s != NULL)
+ {
+ t = s->next;
+ delete_session (s);
+ s = t;
+ }
+
#if BUILD_HTTPS
GNUNET_free_non_null (plugin->crypto_init);
GNUNET_free_non_null (plugin->cert);