From 5678d731af5dae7ac8e6b63480ef6326e3b7f3f7 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Tue, 25 May 2010 15:49:23 +0000 Subject: [PATCH] --- src/transport/plugin_transport_http.c | 206 +++++++++++++++++++-- src/transport/test_plugin_transport_http.c | 189 +++++++++++++++++++ 2 files changed, 382 insertions(+), 13 deletions(-) diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c index 79ede78d1..2ddf74e9e 100644 --- a/src/transport/plugin_transport_http.c +++ b/src/transport/plugin_transport_http.c @@ -163,6 +163,11 @@ struct Plugin */ struct GNUNET_TRANSPORT_PluginEnvironment *env; + /** + * Handle to the network service. + */ + struct GNUNET_SERVICE_Context *service; + /** * List of open sessions. */ @@ -218,6 +223,30 @@ static char * hostname; */ static struct GNUNET_CRYPTO_HashAsciiEncoded my_ascii_hash_ident; +/** + * Message-Packet header. + */ +struct HTTPMessage +{ + /** + * size of the message, in bytes, including this header. + */ + struct GNUNET_MessageHeader header; + + /** + * What is the identity of the sender (GNUNET_hash of public key) + */ + struct GNUNET_PeerIdentity sender; + +}; + +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + /** * Finds a http session in our linked list using peer identity as a key @@ -350,6 +379,11 @@ accessHandlerCallback (void *cls, char * address = NULL; struct GNUNET_PeerIdentity pi_in; int res = GNUNET_NO; + size_t bytes_recv; + struct HTTPMessage msg; + struct GNUNET_MessageHeader * gn_msg; + + gn_msg = NULL; if ( NULL == *httpSessionCache) { @@ -446,7 +480,6 @@ accessHandlerCallback (void *cls, { cs = *httpSessionCache; } - /* Is it a PUT or a GET request */ if ( 0 == strcmp (MHD_HTTP_METHOD_PUT, method) ) { @@ -454,6 +487,7 @@ accessHandlerCallback (void *cls, if ((*upload_data_size == 0) && (cs->is_put_in_progress == GNUNET_NO)) { /* not yet ready */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Not ready"); cs->is_put_in_progress = GNUNET_YES; return MHD_YES; } @@ -462,8 +496,38 @@ accessHandlerCallback (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"PUT URL: `%s'\n",url); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"PUT Request: %lu bytes: `%s' \n", (*upload_data_size), upload_data); /* No data left */ + bytes_recv = *upload_data_size ; *upload_data_size = 0; - /* do something with the data */ + + /* checking size */ + if (bytes_recv < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message too small, is %u bytes, has to be at least %u '\n",bytes_recv, sizeof(struct GNUNET_MessageHeader)); + return MHD_NO; + } + + if ( bytes_recv > GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message too big, is %u bytes, maximum %u '\n",bytes_recv, GNUNET_SERVER_MAX_MESSAGE_SIZE); + return MHD_NO; + } + + struct GNUNET_MessageHeader * gn_msg = GNUNET_malloc (bytes_recv); + memcpy (gn_msg,&upload_data,bytes_recv); + + if ( ntohs(gn_msg->size) != bytes_recv ) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message has incorrect size, is %u bytes vs %u recieved'\n",ntohs(gn_msg->size) , bytes_recv); + GNUNET_free (gn_msg); + return MHD_NO; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message size: `%s'\n",ntohs (msg.header.size)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message type: `%s'\n",ntohs (msg.header.type)); + + + /* forwarding message to transport */ + plugin->env->receive(plugin->env, &pi_in, gn_msg, 1, cs , cs->ip, strlen(cs->ip) ); return MHD_YES; } if ((*upload_data_size == 0) && (cs->is_put_in_progress == GNUNET_YES)) @@ -580,13 +644,17 @@ http_daemon_run (void *cls, static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) { - size_t retcode; - /* - fprintf(stdout, "*** Read callback: size %u, size nmemb: %u \n", size, nmemb); - retcode = fread(ptr, size, nmemb, stream); - */ - retcode = 0; - return retcode; + unsigned int len; + + struct CBC * cbc = ptr; + + len = strlen(cbc->buf); + + if (( cbc->pos == len) && (len < (size * nmemb))) + return 0; + memcpy(stream, cbc->buf, len+1); + cbc->pos = len; + return len; } /** @@ -634,9 +702,11 @@ http_plugin_send (void *cls, struct Session* ses_temp; int bytes_sent = 0; unsigned int i_timeout; - /* struct Plugin *plugin = cls; */ + int still_running; + int msgs_left; CURL *curl_handle; - /* CURLcode res; */ + CURLMcode mret; + CURLMsg *msg; /* find session for peer */ ses = find_session_by_pi (target); @@ -694,6 +764,87 @@ http_plugin_send (void *cls, curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)msgbuf_size); + mret = curl_multi_add_handle(multi_handle, curl_handle); + if (mret != CURLM_OK) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("%s failed at %s:%d: `%s'\n"), + "curl_multi_add_handle", __FILE__, __LINE__, + curl_multi_strerror (mret)); + return -1; + } + + while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &still_running)); + + while(still_running) + { + struct timeval timeout; + int rc; /* select() return code */ + + fd_set fdread; + fd_set fdwrite; + fd_set fdexcep; + int maxfd = -1; + + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); + + /* set a suitable timeout to play around with */ + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + /* get file descriptors from the transfers */ + mret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); + 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 -1; + } + + rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); + + switch(rc) + { + case -1: + /* select error */ + break; + case 0: + /* timeout, do something else */ + break; + default: + /* one or more of curl's file descriptors say there's data to read + or write */ + while(CURLM_CALL_MULTI_PERFORM == + curl_multi_perform(multi_handle, &still_running)); + break; + } + } + + /* See how the transfers went */ + while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { + if (msg->msg == CURLMSG_DONE) { + int idx, found = 0; + + /* Find out which handle this message is about */ + for (idx=0; idx<1; idx++) { + found = (msg->easy_handle == curl_handle); + if(found) + break; + } + + switch (idx) { + case 0: + printf("HTTP transfer completed with status %d\n", msg->data.result); + break; + } + } + } + + return bytes_sent; } @@ -711,6 +862,7 @@ static void http_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_disconnect\n"); // struct Plugin *plugin = cls; // FIXME } @@ -740,6 +892,7 @@ http_plugin_address_pretty_printer (void *cls, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_address_pretty_printer\n"); asc (asc_cls, NULL); } @@ -765,6 +918,7 @@ http_plugin_address_suggested (void *cls, /* check if the address is plausible; if so, add it to our list! */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_address_suggested\n"); return GNUNET_OK; } @@ -785,6 +939,7 @@ http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_address_to_string\n"); GNUNET_break (0); return NULL; } @@ -840,6 +995,8 @@ libgnunet_plugin_transport_http_done (void *cls) cs = cs_next; } + /* GNUNET_SERVICE_stop (plugin->service); */ + GNUNET_free (plugin); GNUNET_free (api); return NULL; @@ -854,13 +1011,29 @@ libgnunet_plugin_transport_http_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; + struct GNUNET_SERVICE_Context *service; unsigned int timeout; struct GNUNET_TIME_Relative gn_timeout; long long unsigned int port; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Starting http plugin...\n"); + + service = NULL; + /* + service = GNUNET_SERVICE_start ("transport-http", env->sched, env->cfg); + if (service == NULL) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "", _ + ("Failed to start service for `%s' transport plugin.\n"), + "http"); + return NULL; + } + */ + plugin = GNUNET_malloc (sizeof (struct Plugin)); plugin->env = env; plugin->sessions = NULL; + plugin->service = service; api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); api->cls = plugin; api->send = &http_plugin_send; @@ -874,7 +1047,6 @@ libgnunet_plugin_transport_http_init (void *cls) /* Hashing our identity to use it in URLs */ GNUNET_CRYPTO_hash_to_enc ( &(plugin->env->my_identity->hashPubKey), &my_ascii_hash_ident); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Starting http plugin...\n"); /* Reading port number from config file */ if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, @@ -931,7 +1103,15 @@ libgnunet_plugin_transport_http_init (void *cls) /* Initializing cURL */ multi_handle = curl_multi_init(); - + if ( NULL == multi_handle ) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, + "http", + _("Could not initialize curl multi handle, failed to start http plugin!\n"), + "transport-http"); + libgnunet_plugin_transport_http_done (api); + return NULL; + } return api; } diff --git a/src/transport/test_plugin_transport_http.c b/src/transport/test_plugin_transport_http.c index 9793420ac..2e540bd54 100644 --- a/src/transport/test_plugin_transport_http.c +++ b/src/transport/test_plugin_transport_http.c @@ -111,6 +111,10 @@ static struct GNUNET_TRANSPORT_PluginFunctions *api; */ static GNUNET_SCHEDULER_TaskIdentifier ti_timeout; +#if 0 +static GNUNET_SCHEDULER_TaskIdentifier ti_download; +#endif + static unsigned int timeout_count; /** @@ -118,6 +122,8 @@ static unsigned int timeout_count; */ static int fail; +//static int done; + pid_t pid; /** @@ -272,6 +278,187 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) } #endif +struct CBC +{ + char *buf; + size_t pos; + size_t size; +}; + +#if 0 +static size_t +putBuffer (void *stream, size_t size, size_t nmemb, void *ptr) +{ + size_t len; + + struct CBC * cbc = ptr; + + len = strlen(cbc->buf); + + if (( cbc->pos == len) && (len < (size * nmemb))) + return 0; + memcpy(stream, cbc->buf, len+1); + cbc->pos = len; + return len; +} +#endif + +#if 0 +static int execute (char * url) +{ + done = 0; + CURLM *multi_handle; + CURL *curl_handle; + CURLMsg *msg; + int msgs_left; + FILE * hd_src ; + int hd ; + struct stat file_info; + int still_running; + char buf[2048]; + struct CBC cbc; + + char *file = "curl.c"; + + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + + const char * txt = "Hello World!"; + memcpy(cbc.buf,txt,strlen(txt)+1); + //fprintf(stderr,"%s %u\n",src,strlen(src)); + + /* get the file size of the local file */ + hd = open(file, O_RDONLY) ; + fstat(hd, &file_info); + close(hd) ; + + /* get a FILE * of the same file, could also be made with + fdopen() from the previous descriptor, but hey this is just + an example! */ + hd_src = fopen(file, "rb"); + //printf("size: %u \n", (curl_off_t) file_info.st_size); + + /* get a curl handle */ + curl_handle = curl_easy_init(); + if( NULL == curl_handle) + { + printf("easy_init failed \n"); + return 0; + } + curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); + //curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, ©Buffer); + //curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &putBuffer); + curl_easy_setopt (curl_handle, CURLOPT_READDATA, &cbc); + curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl_handle, CURLOPT_PUT, 1L); + curl_easy_setopt(curl_handle, CURLOPT_URL, url); + curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) strlen(txt)); + + //curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size); + + multi_handle = curl_multi_init(); + curl_multi_add_handle(multi_handle, curl_handle); + + while(CURLM_CALL_MULTI_PERFORM == + curl_multi_perform(multi_handle, &still_running)); + + while(still_running) + { + struct timeval timeout; + int rc; /* select() return code */ + + fd_set fdread; + fd_set fdwrite; + fd_set fdexcep; + int maxfd = -1; + + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); + + /* set a suitable timeout to play around with */ + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + /* get file descriptors from the transfers */ + curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); + + /* In a real-world program you OF COURSE check the return code of the + function calls. On success, the value of maxfd is guaranteed to be + greater or equal than -1. We call select(maxfd + 1, ...), specially in + case of (maxfd == -1), we call select(0, ...), which is basically equal + to sleep. */ + + rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); + + switch(rc) + { + case -1: + /* select error */ + break; + case 0: + /* timeout, do something else */ + break; + default: + /* one or more of curl's file descriptors say there's data to read + or write */ + while(CURLM_CALL_MULTI_PERFORM == + curl_multi_perform(multi_handle, &still_running)); + break; + } + } + + /* See how the transfers went */ + while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { + if (msg->msg == CURLMSG_DONE) { + int idx, found = 0; + + /* Find out which handle this message is about */ + for (idx=0; idx<1; idx++) { + found = (msg->easy_handle == curl_handle); + if(found) + break; + } + + switch (idx) { + case 0: + printf("HTTP transfer completed with status %d\n", msg->data.result); + break; + } + } + } + + curl_multi_cleanup(multi_handle); + + curl_easy_cleanup(curl_handle); + + fclose(hd_src); /* close the local file */ + return 0; +} +#endif + +#if 0 +/** + * Task that checks if we should try to download a hostlist. + * If so, we initiate the download, otherwise we schedule + * this task again for a later time. + */ +static void +task_download (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + ti_download = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + return; + + execute ("http://localhost:12389/Q7BO0ELEHAT8JNENQ90112G0TACH2H2HIR4IJ2JQ28U6FV14CK44EVP26FVAEALO7HIRJFLFE6709RP6IITM64B0FU7J4RA8KPNDKN8"); + + return; +} +#endif + /** * Runs the test. * @@ -349,6 +536,8 @@ run (void *cls, } ti_timeout = GNUNET_SCHEDULER_add_now (sched, &task_timeout, NULL); + //ti_download = GNUNET_SCHEDULER_add_now (sched, &task_download, NULL); + return; } -- 2.25.1