- struct Plugin *plugin = cls;
- static unsigned int handles_last_run;
- int running;
- struct CURLMsg *msg;
- CURLMcode mret;
- struct Session *ps = NULL;
- struct HTTP_PeerContext *pc = NULL;
- struct HTTP_Message * cur_msg = NULL;
- long http_result;
-
- GNUNET_assert(cls !=NULL);
-
- plugin->http_curl_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
-
- do
- {
- running = 0;
- mret = curl_multi_perform (plugin->multi_handle, &running);
- if ((running < handles_last_run) && (running>0))
- {
- do
- {
-
- msg = curl_multi_info_read (plugin->multi_handle, &running);
- if (running == 0)
- break;
- /* get session for affected curl handle */
- GNUNET_assert ( msg->easy_handle != NULL );
- curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char *) &ps);
- GNUNET_assert ( ps != NULL );
- pc = ps->peercontext;
- GNUNET_assert ( pc != NULL );
- switch (msg->msg)
- {
-
- case CURLMSG_DONE:
- if ( (msg->data.result != CURLE_OK) &&
- (msg->data.result != CURLE_GOT_NOTHING) )
- {
- /* sending msg failed*/
- if (msg->easy_handle == ps->send_endpoint)
- {
-#if DEBUG_CONNECTIONS
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- _("Connection %X: HTTP PUT to peer `%s' (`%s') failed: `%s' `%s'\n"),
- ps,
- GNUNET_i2s(&pc->identity),
- http_plugin_address_to_string(NULL, ps->addr, ps->addrlen),
- "curl_multi_perform",
- curl_easy_strerror (msg->data.result));
-#endif
- ps->send_connected = GNUNET_NO;
- ps->send_active = GNUNET_NO;
- curl_multi_remove_handle(plugin->multi_handle,ps->send_endpoint);
- curl_easy_cleanup(ps->send_endpoint);
- ps->send_endpoint=NULL;
- cur_msg = ps->pending_msgs_tail;
- if (( NULL != cur_msg) && ( NULL != cur_msg->transmit_cont))
- cur_msg->transmit_cont (cur_msg->transmit_cont_cls,&pc->identity,GNUNET_SYSERR);
- }
- /* GET connection failed */
- if (msg->easy_handle == ps->recv_endpoint)
- {
-#if DEBUG_CONNECTIONS
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- _("Connection %X: HTTP GET to peer `%s' (`%s') failed: `%s' `%s'\n"),
- ps,
- GNUNET_i2s(&pc->identity),
- http_plugin_address_to_string(NULL, ps->addr, ps->addrlen),
- "curl_multi_perform",
- curl_easy_strerror (msg->data.result));
-#endif
- ps->recv_connected = GNUNET_NO;
- ps->recv_active = GNUNET_NO;
- curl_multi_remove_handle(plugin->multi_handle,ps->recv_endpoint);
- curl_easy_cleanup(ps->recv_endpoint);
- ps->recv_endpoint=NULL;
- }
- }
- else
- {
- if (msg->easy_handle == ps->send_endpoint)
- {
- GNUNET_assert (CURLE_OK == curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &http_result));
-#if DEBUG_CONNECTIONS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connection %X: HTTP PUT connection to peer `%s' (`%s') was closed with HTTP code %u\n",
- ps,
- GNUNET_i2s(&pc->identity),
- http_plugin_address_to_string(NULL, ps->addr, ps->addrlen),
- http_result);
-#endif
- /* Calling transmit continuation */
- cur_msg = ps->pending_msgs_tail;
- if (( NULL != cur_msg) && (NULL != cur_msg->transmit_cont))
- {
- /* HTTP 1xx : Last message before here was informational */
- if ((http_result >=100) && (http_result < 200))
- cur_msg->transmit_cont (cur_msg->transmit_cont_cls,&pc->identity,GNUNET_OK);
- /* HTTP 2xx: successful operations */
- if ((http_result >=200) && (http_result < 300))
- cur_msg->transmit_cont (cur_msg->transmit_cont_cls,&pc->identity,GNUNET_OK);
- /* HTTP 3xx..5xx: error */
- if ((http_result >=300) && (http_result < 600))
- cur_msg->transmit_cont (cur_msg->transmit_cont_cls,&pc->identity,GNUNET_SYSERR);
- }
- ps->send_connected = GNUNET_NO;
- ps->send_active = GNUNET_NO;
- curl_multi_remove_handle(plugin->multi_handle,ps->send_endpoint);
- curl_easy_cleanup(ps->send_endpoint);
- ps->send_endpoint =NULL;
- }
- if (msg->easy_handle == ps->recv_endpoint)
- {
-#if DEBUG_CONNECTIONS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connection %X: HTTP GET connection to peer `%s' (`%s') was closed with HTTP code %u\n",
- ps,
- GNUNET_i2s(&pc->identity),
- http_plugin_address_to_string(NULL, ps->addr, ps->addrlen),
- http_result);
-#endif
- ps->recv_connected = GNUNET_NO;
- ps->recv_active = GNUNET_NO;
- curl_multi_remove_handle(plugin->multi_handle,ps->recv_endpoint);
- curl_easy_cleanup(ps->recv_endpoint);
- ps->recv_endpoint=NULL;
- }
- }
- if ((ps->recv_connected == GNUNET_NO) && (ps->send_connected == GNUNET_NO))
- remove_session (pc, ps, GNUNET_YES, GNUNET_SYSERR);
- return;
- default:
- break;
- }
-
- }
- while ( (running > 0) );
- }
- handles_last_run = running;
- }
- while (mret == CURLM_CALL_MULTI_PERFORM);
- curl_schedule(plugin, cls);
-}
-
-
-/**
- * Function setting up file descriptors and scheduling task to run
- * @param ses session to send data to
- * @return GNUNET_SYSERR for hard failure, GNUNET_OK for ok
- */
-static int curl_schedule(void *cls, struct Session* ses )
-{
- struct Plugin *plugin = cls;
- fd_set rs;
- fd_set ws;
- fd_set es;
- int max;
- struct GNUNET_NETWORK_FDSet *grs;
- struct GNUNET_NETWORK_FDSet *gws;
- long to;
- CURLMcode mret;
-
- GNUNET_assert(cls !=NULL);
- max = -1;
- FD_ZERO (&rs);
- FD_ZERO (&ws);
- FD_ZERO (&es);
- mret = curl_multi_fdset (plugin->multi_handle, &rs, &ws, &es, &max);
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_fdset", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- return GNUNET_SYSERR;
- }
- mret = curl_multi_timeout (plugin->multi_handle, &to);
- if (mret != CURLM_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("%s failed at %s:%d: `%s'\n"),
- "curl_multi_timeout", __FILE__, __LINE__,
- curl_multi_strerror (mret));
- return GNUNET_SYSERR;
- }
-
- grs = GNUNET_NETWORK_fdset_create ();
- gws = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
- GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
- plugin->http_curl_task = GNUNET_SCHEDULER_add_select (plugin->env->sched,
- GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 0),
- grs,
- gws,
- &curl_perform,
- plugin);
- GNUNET_NETWORK_fdset_destroy (gws);
- GNUNET_NETWORK_fdset_destroy (grs);
- return GNUNET_OK;
-}
-
+ struct Session * tmp = NULL;
+ int addr_given = GNUNET_NO;
+
+ if ((addr!=NULL) && (addrlen>0))
+ addr_given = GNUNET_YES;
+
+ if (force_address == GNUNET_YES)
+ {
+ /* check session given as argument */
+ if ((session != NULL) && (addr_given == GNUNET_YES))
+ {
+ if (0 == memcmp(session->addr, addr, addrlen))
+ {
+ /* connection can not be used, since it is disconnected */
+ if ((session->recv_force_disconnect==GNUNET_NO) && (session->send_force_disconnect==GNUNET_NO))
+ {
+#if DEBUG_SESSION_SELECTION
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session %X selected: Using session passed by transport to send to forced address \n", session);
+#endif
+ return session;
+ }
+ }
+ }
+ /* check last session used */
+ if ((pc->last_session != NULL)&& (addr_given == GNUNET_YES))
+ {
+ if (0 == memcmp(pc->last_session->addr, addr, addrlen))
+ {
+ /* connection can not be used, since it is disconnected */
+ if ((pc->last_session->recv_force_disconnect==GNUNET_NO) && (pc->last_session->send_force_disconnect==GNUNET_NO))
+ {
+#if DEBUG_SESSION_SELECTION
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session %X selected: Using last session used to send to forced address \n", pc->last_session);
+#endif
+ return pc->last_session;
+ }
+ }
+ }
+ /* find session in existing sessions */
+ tmp = pc->head;
+ while ((tmp!=NULL) && (addr_given == GNUNET_YES))
+ {
+
+ if (0 == memcmp(tmp->addr, addr, addrlen))
+ {
+ /* connection can not be used, since it is disconnected */
+ if ((tmp->recv_force_disconnect==GNUNET_NO) && (tmp->send_force_disconnect==GNUNET_NO))
+ {
+#if DEBUG_SESSION_SELECTION
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session %X selected: Using existing session to send to forced address \n", session);
+#endif
+ return session;
+ }
+
+ }
+ tmp=tmp->next;
+ }
+ /* no session to use */
+ return NULL;
+ }
+ if ((force_address == GNUNET_NO) || (force_address == GNUNET_SYSERR))
+ {
+ /* check session given as argument */
+ if (session != NULL)
+ {
+ /* connection can not be used, since it is disconnected */
+ if ((session->recv_force_disconnect==GNUNET_NO) && (session->send_force_disconnect==GNUNET_NO))
+ {
+#if DEBUG_SESSION_SELECTION
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session %X selected: Using session passed by transport to send not-forced address \n", session);
+#endif
+ return session;
+ }
+
+ }
+ /* check last session used */
+ if (pc->last_session != NULL)
+ {
+ /* connection can not be used, since it is disconnected */
+ if ((pc->last_session->recv_force_disconnect==GNUNET_NO) && (pc->last_session->send_force_disconnect==GNUNET_NO))
+ {
+#if DEBUG_SESSION_SELECTION
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session %X selected: Using last session to send to not-forced address \n", pc->last_session);
+#endif
+ return pc->last_session;
+ }
+ }
+ /* find session in existing sessions */
+ tmp = pc->head;
+ while (tmp!=NULL)
+ {
+ /* connection can not be used, since it is disconnected */
+ if ((tmp->recv_force_disconnect==GNUNET_NO) && (tmp->send_force_disconnect==GNUNET_NO))
+ {
+#if DEBUG_SESSION_SELECTION
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session %X selected: Using existing session to send to not-forced address \n", tmp);
+#endif
+ return tmp;
+ }
+ tmp=tmp->next;
+ }
+ return NULL;
+ }
+ return NULL;
+}