libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit e421dc4c64105540b24ee732e8887ee26c40276a
parent 62f53d643f796ad3a32d8eabfdceb985245ec15f
Author: Andrey Uzunov <andrey.uzunov@gmail.com>
Date:   Sun, 11 Aug 2013 19:35:43 +0000

spdy: simple POST support implemented; API changes; fixed warnings in spdy tests

Diffstat:
Msrc/examples/mhd2spdy.c | 2+-
Msrc/examples/mhd2spdy_http.c | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/examples/mhd2spdy_spdy.c | 112++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/examples/mhd2spdy_spdy.h | 3++-
Msrc/examples/mhd2spdy_structures.c | 20++++++++++++++++++++
Msrc/examples/mhd2spdy_structures.h | 7+++++++
Msrc/examples/spdy_event_loop.c | 21++++++++++++++++++---
Msrc/examples/spdy_fileserver.c | 16++++++++++++----
Msrc/examples/spdy_response_with_callback.c | 9++++++++-
Msrc/include/microspdy.h | 26++++++++++++++++++--------
Msrc/microspdy/applicationlayer.c | 25++++++++++++++++++++++---
Msrc/microspdy/daemon.c | 6++++--
Msrc/microspdy/daemon.h | 3++-
Msrc/microspdy/session.c | 45+++++++++++++++++++++++++++++++++++++++------
Msrc/microspdy/stream.c | 19++++++++++++++++++-
Msrc/microspdy/stream.h | 13++++++++++++-
Msrc/microspdy/structures.h | 36++++++++++++++++++++++++++++++++++--
Msrc/spdy2http/proxy.c | 245+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/testspdy/test_daemon_start_stop.c | 2+-
Msrc/testspdy/test_daemon_start_stop_many.c | 2+-
Msrc/testspdy/test_misc.c | 25++++++++++++++++++++-----
Msrc/testspdy/test_new_connection.c | 30+++++++++++++++++++++++++++---
Msrc/testspdy/test_notls.c | 36+++++++++++++++++++++++++++++++-----
Msrc/testspdy/test_request_response.c | 43+++++++++++++++++++++++++++++++++++++++----
Msrc/testspdy/test_request_response_with_callback.c | 27+++++++++++++++++++++------
Msrc/testspdy/test_requests_with_assets.c | 17++++++++++++++---
Msrc/testspdy/test_session_timeout.c | 32++++++++++++++++++++------------
Msrc/testspdy/test_struct_namevalue.c | 11++++++++---
28 files changed, 790 insertions(+), 103 deletions(-)

diff --git a/src/examples/mhd2spdy.c b/src/examples/mhd2spdy.c @@ -151,7 +151,7 @@ run_everything () glob_opt.spdy_data_received = false; ret = select(maxfd+1, &rs, &ws, &es, &timeout); - PRINT_INFO2("timeout now %lld %lld", (unsigned long long)timeout.tv_sec, (unsigned long long)timeout.tv_usec); + PRINT_INFO2("timeout now %lld %lld ret is %i", (unsigned long long)timeout.tv_sec, (unsigned long long)timeout.tv_usec, ret); switch(ret) { diff --git a/src/examples/mhd2spdy_http.c b/src/examples/mhd2spdy_http.c @@ -36,6 +36,7 @@ const char * uri) PRINT_INFO2("log uri '%s'\n", uri); + //TODO not freed once in a while if(NULL == (http_uri = au_malloc(sizeof(struct HTTP_URI )))) DIE("no memory"); http_uri->uri = strdup(uri); @@ -176,6 +177,7 @@ http_cb_request (void *cls, int ret; struct Proxy *proxy; struct SPDY_Headers spdy_headers; + bool with_body = false; //PRINT_INFO2("request cb %i; %s", *ptr,url); @@ -185,14 +187,14 @@ http_cb_request (void *cls, if(NULL == http_uri->proxy) { - if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) + if (0 != strcmp (method, MHD_HTTP_METHOD_GET) && 0 != strcmp (method, MHD_HTTP_METHOD_POST)) { free(http_uri->uri); free(http_uri); PRINT_INFO2("unexpected method %s", method); return MHD_NO; } - + if(NULL == (proxy = au_malloc(sizeof(struct Proxy)))) { PRINT_INFO("No memory"); @@ -211,14 +213,62 @@ http_cb_request (void *cls, if(proxy->spdy_active) { + if(0 == strcmp (method, MHD_HTTP_METHOD_POST)) + { + PRINT_INFO("POST processing"); + + int rc= spdylay_session_resume_data(proxy->spdy_connection->session, proxy->stream_id); + PRINT_INFO2("rc is %i stream is %i", rc, proxy->stream_id); + proxy->spdy_connection->want_io |= WANT_WRITE; + + if(0 == *upload_data_size) + { + PRINT_INFO("POST http EOF"); + proxy->receiving_done = true; + return MHD_YES; + } + + if(!copy_buffer(upload_data, *upload_data_size, &proxy->received_body, &proxy->received_body_size)) + { + //TODO handle it better? + PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); + return MHD_NO; + } + /* + if(NULL == proxy->received_body) + proxy->received_body = malloc(*upload_data_size); + else + proxy->received_body = realloc(proxy->received_body, proxy->received_body_size + *upload_data_size); + if(NULL == proxy->received_body) + { + //TODO handle it better? + PRINT_INFO("not enough memory (realloc returned NULL)"); + return MHD_NO; + } + + memcpy(proxy->received_body + proxy->received_body_size, upload_data, *upload_data_size); + proxy->received_body_size += *upload_data_size; + */ + *upload_data_size = 0; + + //raise(SIGINT); + + return MHD_YES; + } + //already handled PRINT_INFO("unnecessary call to http_cb_request"); return MHD_YES; } - PRINT_INFO2("received request for '%s %s %s'\n", method, http_uri->uri, version); + PRINT_INFO2("received request for '%s %s %s'", method, http_uri->uri, version); proxy->url = http_uri->uri; + + with_body = 0 == strcmp (method, MHD_HTTP_METHOD_POST) && 0 != strcmp ("0", + MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH)); + + PRINT_INFO2("body will be sent %i", with_body); ret = parse_uri(&glob_opt.uri_preg, proxy->url, &proxy->uri); if(ret != 0) @@ -232,7 +282,7 @@ http_cb_request (void *cls, NULL); if(NULL == (spdy_headers.nv = au_malloc(((spdy_headers.num + 5) * 2 + 1) * sizeof(char *)))) DIE("no memory"); - spdy_headers.nv[0] = ":method"; spdy_headers.nv[1] = "GET"; + spdy_headers.nv[0] = ":method"; spdy_headers.nv[1] = method; spdy_headers.nv[2] = ":path"; spdy_headers.nv[3] = proxy->uri->path_and_more; spdy_headers.nv[4] = ":version"; spdy_headers.nv[5] = (char *)version; spdy_headers.nv[6] = ":scheme"; spdy_headers.nv[7] = proxy->uri->scheme; @@ -248,7 +298,7 @@ http_cb_request (void *cls, if(NULL == spdy_headers.nv[9]) spdy_headers.nv[9] = proxy->uri->host_and_port; - if(0 != spdy_request(spdy_headers.nv, proxy)) + if(0 != spdy_request(spdy_headers.nv, proxy, with_body)) { free(spdy_headers.nv); free_proxy(proxy); diff --git a/src/examples/mhd2spdy_spdy.c b/src/examples/mhd2spdy_spdy.c @@ -63,6 +63,69 @@ spdy_diec(const char *func, } +static ssize_t +spdy_cb_data_source_read(spdylay_session *session, int32_t stream_id, uint8_t *buf, size_t length, int *eof, spdylay_data_source *source, void *user_data) +{ + (void)session; + (void)stream_id; + (void)user_data; + + ssize_t ret; + assert(NULL != source); + assert(NULL != source->ptr); + struct Proxy *proxy = (struct Proxy *)(source->ptr); + void *newbody; + + + if(length < 1) + { + PRINT_INFO("spdy_cb_data_source_read: length is 0"); + return 0; + } + + if(!proxy->received_body_size)//nothing to write now + { + if(proxy->receiving_done) + { + PRINT_INFO("POST spdy EOF"); + *eof = 1; + } + PRINT_INFO("POST SPDYLAY_ERR_DEFERRED"); + return SPDYLAY_ERR_DEFERRED;//TODO SPDYLAY_ERR_DEFERRED should be used + } + + if(length >= proxy->received_body_size) + { + ret = proxy->received_body_size; + newbody = NULL; + } + else + { + ret = length; + if(NULL == (newbody = malloc(proxy->received_body_size - length))) + { + PRINT_INFO("no memory"); + return SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE; + } + memcpy(newbody, proxy->received_body + length, proxy->received_body_size - length); + } + memcpy(buf, proxy->received_body, ret); + free(proxy->received_body); + proxy->received_body = newbody; + proxy->received_body_size -= ret; + + if(0 == proxy->received_body_size && proxy->receiving_done) + { + PRINT_INFO("POST spdy EOF"); + *eof = 1; + } + + PRINT_INFO2("given POST bytes to spdylay: %zd", ret); + + return ret; +} + + /* * The implementation of spdylay_send_callback type. Here we write * |data| with size |length| to the network and return the number of @@ -91,7 +154,7 @@ spdy_cb_send(spdylay_session *session, if(rv < 0) { int err = SSL_get_error(connection->ssl, rv); if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) { - connection->want_io = (err == SSL_ERROR_WANT_READ ? + connection->want_io |= (err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE); rv = SPDYLAY_ERR_WOULDBLOCK; } else { @@ -113,7 +176,7 @@ spdy_cb_send(spdylay_session *session, #if EAGAIN != EWOULDBLOCK case EWOULDBLOCK: #endif - connection->want_io = WANT_WRITE; + connection->want_io |= WANT_WRITE; rv = SPDYLAY_ERR_WOULDBLOCK; break; @@ -122,6 +185,9 @@ spdy_cb_send(spdylay_session *session, } } } + + PRINT_INFO2("%zd bytes written by spdy", rv); + return rv; } @@ -156,7 +222,7 @@ spdy_cb_recv(spdylay_session *session, if(rv < 0) { int err = SSL_get_error(connection->ssl, rv); if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) { - connection->want_io = (err == SSL_ERROR_WANT_READ ? + connection->want_io |= (err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE); rv = SPDYLAY_ERR_WOULDBLOCK; } else { @@ -180,7 +246,7 @@ spdy_cb_recv(spdylay_session *session, #if EAGAIN != EWOULDBLOCK case EWOULDBLOCK: #endif - connection->want_io = WANT_READ; + connection->want_io |= WANT_READ; rv = SPDYLAY_ERR_WOULDBLOCK; break; @@ -210,6 +276,7 @@ spdy_cb_on_ctrl_send(spdylay_session *session, case SPDYLAY_SYN_STREAM: stream_id = frame->syn_stream.stream_id; proxy = spdylay_session_get_stream_user_data(session, stream_id); + proxy->stream_id = stream_id; ++glob_opt.streams_opened; ++proxy->spdy_connection->streams_opened; PRINT_INFO2("opening stream: str open %i; %s", glob_opt.streams_opened, proxy->url); @@ -325,6 +392,13 @@ spdy_cb_on_data_chunk_recv(spdylay_session *session, struct Proxy *proxy; proxy = spdylay_session_get_stream_user_data(session, stream_id); + if(!copy_buffer(data, len, &proxy->http_body, &proxy->http_body_size)) + { + //TODO handle it better? + PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); + return; + } + /* if(NULL == proxy->http_body) proxy->http_body = au_malloc(len); else @@ -337,6 +411,7 @@ spdy_cb_on_data_chunk_recv(spdylay_session *session, memcpy(proxy->http_body + proxy->http_body_size, data, len); proxy->http_body_size += len; + */ PRINT_INFO2("received data for %s; %zu bytes", proxy->url, len); glob_opt.spdy_data_received = true; } @@ -533,12 +608,12 @@ spdy_ctl_poll(struct pollfd *pollfd, { pollfd->events = 0; if(spdylay_session_want_read(connection->session) || - connection->want_io == WANT_READ) + connection->want_io & WANT_READ) { pollfd->events |= POLLIN; } if(spdylay_session_want_write(connection->session) || - connection->want_io == WANT_WRITE) + connection->want_io & WANT_WRITE) { pollfd->events |= POLLOUT; } @@ -559,13 +634,13 @@ spdy_ctl_select(fd_set * read_fd_set, bool ret = false; if(spdylay_session_want_read(connection->session) || - connection->want_io == WANT_READ) + connection->want_io & WANT_READ) { FD_SET(connection->fd, read_fd_set); ret = true; } if(spdylay_session_want_write(connection->session) || - connection->want_io == WANT_WRITE) + connection->want_io & WANT_WRITE) { FD_SET(connection->fd, write_fd_set); ret = true; @@ -690,11 +765,13 @@ spdy_free_connection(struct SPDY_Connection * connection) int spdy_request(const char **nv, - struct Proxy *proxy) + struct Proxy *proxy, + bool with_body) { int ret; uint16_t port; struct SPDY_Connection *connection; + spdylay_data_provider post_data; if(glob_opt.only_proxy) { @@ -733,7 +810,15 @@ spdy_request(const char **nv, } proxy->spdy_connection = connection; - ret = spdylay_submit_request(connection->session, 0, nv, NULL, proxy); + if(with_body) + { + post_data.source.ptr = proxy; + post_data.read_callback = &spdy_cb_data_source_read; + ret = spdylay_submit_request(connection->session, 0, nv, &post_data, proxy); + } + else + ret = spdylay_submit_request(connection->session, 0, nv, NULL, proxy); + if(ret != 0) { spdy_diec("spdylay_spdy_submit_request", ret); } @@ -958,6 +1043,7 @@ spdy_run_select(fd_set * read_fd_set, // PRINT_INFO2("exec about to be called for %s", connections[i]->host); if(FD_ISSET(connections[i]->fd, read_fd_set) || FD_ISSET(connections[i]->fd, write_fd_set) || FD_ISSET(connections[i]->fd, except_fd_set)) { + //raise(SIGINT); ret = spdy_exec_io(connections[i]); if(0 != ret) @@ -981,6 +1067,12 @@ spdy_run_select(fd_set * read_fd_set, } } else + { PRINT_INFO("not called"); + PRINT_INFO2("connection->want_io %i",connections[i]->want_io); + PRINT_INFO2("read %i",spdylay_session_want_read(connections[i]->session)); + PRINT_INFO2("write %i",spdylay_session_want_write(connections[i]->session)); + //raise(SIGINT); + } } } diff --git a/src/examples/mhd2spdy_spdy.h b/src/examples/mhd2spdy_spdy.h @@ -56,7 +56,8 @@ spdy_diec(const char *func, int spdy_request(const char **nv, - struct Proxy *proxy); + struct Proxy *proxy, + bool with_body); void diff --git a/src/examples/mhd2spdy_structures.c b/src/examples/mhd2spdy_structures.c @@ -138,3 +138,23 @@ void *au_malloc(size_t size) } return new_memory; } + + +bool +copy_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size) +{ + if(0 == src_size) + return true; + + if(NULL == *dst) + *dst = malloc(src_size); + else + *dst = realloc(*dst, src_size + *dst_size); + if(NULL == *dst) + return false; + + memcpy(*dst + *dst_size, src, src_size); + *dst_size += src_size; + + return true; +} diff --git a/src/examples/mhd2spdy_structures.h b/src/examples/mhd2spdy_structures.h @@ -112,14 +112,18 @@ struct Proxy char *url; char *version; void *http_body; + void *received_body; size_t http_body_size; + size_t received_body_size; ssize_t length; int status; int id; + int32_t stream_id; bool done; bool error; bool http_active; bool spdy_active; + bool receiving_done; }; @@ -265,4 +269,7 @@ void * au_malloc(size_t size); +bool +copy_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size); + #endif diff --git a/src/examples/spdy_event_loop.c b/src/examples/spdy_event_loop.c @@ -199,7 +199,8 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { char *html; char *data; @@ -259,6 +260,20 @@ standard_request_handler(void *cls, } +static int +new_post_data_cb (void * cls, + struct SPDY_Request *request, + const void * buf, + size_t size, + bool more) +{ + printf("DATA:\n===============================\n"); + write(0, buf, size); + printf("\n===============================\n"); + return SPDY_YES; +} + + static void sig_handler(int signo) { @@ -288,7 +303,7 @@ main (int argc, char *const *argv) struct SPDY_Daemon *daemon = SPDY_start_daemon(atoi(argv[1]), DATA_DIR "cert-and-key.pem", DATA_DIR "cert-and-key.pem", - &new_session_callback,&session_closed_handler,&standard_request_handler,NULL,NULL, + &new_session_callback,&session_closed_handler,&standard_request_handler,&new_post_data_cb,NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 10, //SPDY_DAEMON_OPTION_SOCK_ADDR, (struct sockaddr *)&addr4, SPDY_DAEMON_OPTION_END); @@ -306,7 +321,7 @@ main (int argc, char *const *argv) struct SPDY_Daemon *daemon2 = SPDY_start_daemon(atoi(argv[1]) + 1, DATA_DIR "cert-and-key.pem", DATA_DIR "cert-and-key.pem", - &new_session_callback,NULL,&standard_request_handler,NULL,&main, + &new_session_callback,NULL,&standard_request_handler,&new_post_data_cb,&main, //SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 0, //SPDY_DAEMON_OPTION_SOCK_ADDR, (struct sockaddr *)&addr6, //SPDY_DAEMON_OPTION_FLAGS, SPDY_DAEMON_FLAG_ONLY_IPV6, diff --git a/src/examples/spdy_fileserver.c b/src/examples/spdy_fileserver.c @@ -22,7 +22,10 @@ * files directly read from the system * @author Andrey Uzunov */ - + +//for asprintf +#define _GNU_SOURCE + #include <unistd.h> #include <stdlib.h> #include <stdint.h> @@ -114,6 +117,7 @@ response_done_callback(void *cls, bool streamopened) { (void)streamopened; + (void)status; //printf("answer for %s was sent\n", (char *)cls); /*if(SPDY_RESPONSE_RESULT_SUCCESS != status) @@ -135,7 +139,8 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { (void)cls; (void)request; @@ -143,6 +148,9 @@ standard_request_handler(void *cls, (void)host; (void)scheme; (void)headers; + (void)method; + (void)version; + (void)more; struct SPDY_Response *response=NULL; struct SPDY_NameValue *resp_headers; @@ -165,7 +173,7 @@ standard_request_handler(void *cls, || -1 == (filesize = ftell(fd)) || 0 != (ret = fseek(fd, 0L, SEEK_SET))) { - printf("Error on opening %s\n%i %i %i\n",fname, fd, ret, filesize); + printf("Error on opening %s\n%p %i %zd\n",fname, fd, ret, filesize); response = SPDY_build_response(SPDY_HTTP_INTERNAL_SERVER_ERROR,NULL,SPDY_HTTP_VERSION_1_1,NULL,NULL,0); } else @@ -185,7 +193,7 @@ standard_request_handler(void *cls, } free(date); - if(-1 == asprintf(&fsize, "%i", filesize) + if(-1 == asprintf(&fsize, "%zd", filesize) || SPDY_YES != SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_CONTENT_LENGTH,fsize)) { printf("SPDY_name_value_add or asprintf failed\n"); diff --git a/src/examples/spdy_response_with_callback.c b/src/examples/spdy_response_with_callback.c @@ -22,6 +22,9 @@ * @author Andrey Uzunov */ +//for asprintf +#define _GNU_SOURCE + #include <unistd.h> #include <stdlib.h> #include <stdint.h> @@ -61,6 +64,8 @@ response_done_callback(void *cls, bool streamopened) { (void)streamopened; + (void)status; + printf("answer for %s was sent\n", (char *)cls); SPDY_destroy_request(request); @@ -78,7 +83,8 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { (void)cls; (void)request; @@ -86,6 +92,7 @@ standard_request_handler(void *cls, (void)host; (void)scheme; (void)headers; + (void)more; char *html; struct SPDY_Response *response=NULL; diff --git a/src/include/microspdy.h b/src/include/microspdy.h @@ -628,7 +628,9 @@ typedef int /** - * Callback for received SPDY request. + * Callback for received SPDY request. The functions is called whenever + * a reqest comes, but will also be called if more headers/trailers are + * received. * * @param cls client-defined closure * @param request handler. The request object is required for @@ -642,6 +644,11 @@ typedef int * @param host called host as in HTTP * @param scheme used ("http" or "https"). In SPDY 3 it is only "https". * @param headers other HTTP headers from the request + * @param more a flag saying if more data related to the request is + * expected to be received. HTTP body may arrive (e.g. POST data); + * then SPDY_NewDataCallback will be called for the connection. + * It is also possible that more headers/trailers may arrive; + * then the same callback will be invoked. */ typedef void (*SPDY_NewRequestCallback) (void * cls, struct SPDY_Request * request, @@ -651,24 +658,27 @@ typedef void (*SPDY_NewRequestCallback) (void * cls, const char * version, const char * host, const char * scheme, - struct SPDY_NameValue * headers); + struct SPDY_NameValue * headers, + bool more); /** - * Callback for received new data chunk from the POST data of a given - * request. + * Callback for received new data chunk (HTTP body) from a given + * request (e.g. POST data). * * @param cls client-defined closure * @param request handler * @param buf data chunk from the POST data - * @param size the size of the data chunk 'buf' in bytes - * @param more false if this is the last chunk from the POST data. Note: + * @param size the size of the data chunk 'buf' in bytes. Note that it + * may be 0. + * @param more false if this is the last chunk from the data. Note: * true does not mean that more data will come, exceptional * situation is possible * @return SPDY_YES to continue calling the function, * SPDY_NO to stop calling the function for this request */ -typedef int (*SPDY_NewPOSTDataCallback) (void * cls, +typedef int +(*SPDY_NewDataCallback) (void * cls, struct SPDY_Request *request, const void * buf, size_t size, @@ -855,7 +865,7 @@ SPDY_start_daemon (uint16_t port, SPDY_NewSessionCallback nscb, SPDY_SessionClosedCallback sccb, SPDY_NewRequestCallback nrcb, - SPDY_NewPOSTDataCallback npdcb, + SPDY_NewDataCallback npdcb, void * cls, ...); diff --git a/src/microspdy/applicationlayer.c b/src/microspdy/applicationlayer.c @@ -157,7 +157,7 @@ spdy_handler_new_stream (void *cls, } //ignore everything but GET - if(strcasecmp("GET",method)) + if(strcasecmp("GET",method) && strcasecmp("POST",method)) { SPDYF_DEBUG("received method '%s'", method); static char * html = "Method not implemented. libmicrospdy supports now only GET."; @@ -187,7 +187,10 @@ spdy_handler_new_stream (void *cls, version, host, scheme, - headers); + headers, + !stream->is_in_closed); + + stream->cls = request; return SPDY_YES; @@ -200,6 +203,21 @@ spdy_handler_new_stream (void *cls, /** + * TODO + */ +static int +spdy_handler_new_data (void * cls, + struct SPDYF_Stream *stream, + const void * buf, + size_t size, + bool more) +{ + return stream->session->daemon->received_data_cb(cls, stream->cls, buf, size, more); +} + + + +/** * Callback to be called when the response queue object was handled and * the data was already sent or discarded. * @@ -332,7 +350,7 @@ SPDY_start_daemon (uint16_t port, SPDY_NewSessionCallback nscb, SPDY_SessionClosedCallback sccb, SPDY_NewRequestCallback nrcb, - SPDY_NewPOSTDataCallback npdcb, + SPDY_NewDataCallback npdcb, void * cls, ...) { @@ -367,6 +385,7 @@ SPDY_start_daemon (uint16_t port, nrcb, npdcb, &spdy_handler_new_stream, + &spdy_handler_new_data, cls, NULL, valist diff --git a/src/microspdy/daemon.c b/src/microspdy/daemon.c @@ -173,8 +173,9 @@ SPDYF_start_daemon_va (uint16_t port, SPDY_NewSessionCallback nscb, SPDY_SessionClosedCallback sccb, SPDY_NewRequestCallback nrcb, - SPDY_NewPOSTDataCallback npdcb, + SPDY_NewDataCallback npdcb, SPDYF_NewStreamCallback fnscb, + SPDYF_NewDataCallback fndcb, void * cls, void * fcls, va_list valist) @@ -237,10 +238,11 @@ SPDYF_start_daemon_va (uint16_t port, daemon->new_session_cb = nscb; daemon->session_closed_cb = sccb; daemon->new_request_cb = nrcb; - daemon->new_post_data_cb = npdcb; + daemon->received_data_cb = npdcb; daemon->cls = cls; daemon->fcls = fcls; daemon->fnew_stream_cb = fnscb; + daemon->freceived_data_cb = fndcb; #if HAVE_INET6 //handling IPv6 diff --git a/src/microspdy/daemon.h b/src/microspdy/daemon.h @@ -62,8 +62,9 @@ SPDYF_start_daemon_va (uint16_t port, SPDY_NewSessionCallback nscb, SPDY_SessionClosedCallback sccb, SPDY_NewRequestCallback nrcb, - SPDY_NewPOSTDataCallback npdcb, + SPDY_NewDataCallback npdcb, SPDYF_NewStreamCallback fnscb, + SPDYF_NewDataCallback fndcb, void * cls, void * fcls, va_list valist); diff --git a/src/microspdy/session.c b/src/microspdy/session.c @@ -325,14 +325,15 @@ spdyf_handler_read_rst_stream (struct SPDY_Session *session) static void spdyf_handler_read_data (struct SPDY_Session *session) { - //just ignore the whole frame for now + int ret; struct SPDYF_Data_Frame * frame; + struct SPDYF_Stream * stream; SPDYF_ASSERT(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status || SPDY_SESSION_STATUS_WAIT_FOR_BODY == session->status, "the function is called wrong"); - SPDYF_DEBUG("DATA frame received (POST?). Ignoring"); + //SPDYF_DEBUG("DATA frame received (POST?). Ignoring"); //SPDYF_SIGINT(""); @@ -355,9 +356,41 @@ spdyf_handler_read_data (struct SPDY_Session *session) if(session->read_buffer_offset - session->read_buffer_beginning >= frame->length) { - session->read_buffer_beginning += frame->length; - session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER; - free(frame); + stream = SPDYF_stream_find(frame->stream_id, session); + + if(NULL == stream || stream->is_in_closed || NULL == session->daemon->received_data_cb) + { + if(NULL == session->daemon->received_data_cb) + SPDYF_DEBUG("No callback for DATA frame set"); + + SPDYF_DEBUG("Ignoring DATA frame!"); + + //TODO send error? + + //TODO for now ignore frame + session->read_buffer_beginning += frame->length; + session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER; + free(frame); + return; + } + + ret = session->daemon->freceived_data_cb(session->daemon->cls, + stream, + session->read_buffer + session->read_buffer_beginning, + frame->length, + 0 == (SPDY_DATA_FLAG_FIN & frame->flags)); + + session->read_buffer_beginning += frame->length; + + //TODO close in and send rst maybe + SPDYF_ASSERT(SPDY_YES == ret, "Cancel POST data is not yet implemented"); + + if(SPDY_DATA_FLAG_FIN & frame->flags) + { + stream->is_in_closed = true; + } + session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER; + free(frame); } } @@ -1020,7 +1053,7 @@ SPDYF_session_write (struct SPDY_Session *session, bool only_one_frame) } //set stream to closed if the frame's fin flag is set - SPDYF_stream_set_flags(queue_head); + SPDYF_stream_set_flags_on_write(queue_head); if(NULL != queue_head->frqcb) { diff --git a/src/microspdy/stream.c b/src/microspdy/stream.c @@ -122,7 +122,7 @@ SPDYF_stream_destroy(struct SPDYF_Stream *stream) void -SPDYF_stream_set_flags(struct SPDYF_Response_Queue *response_queue) +SPDYF_stream_set_flags_on_write(struct SPDYF_Response_Queue *response_queue) { struct SPDYF_Stream * stream = response_queue->stream; @@ -149,3 +149,20 @@ SPDYF_stream_set_flags(struct SPDYF_Response_Queue *response_queue) } } } + + +//TODO add function *on_read + + +struct SPDYF_Stream * +SPDYF_stream_find(uint32_t stream_id, struct SPDY_Session * session) +{ + struct SPDYF_Stream * stream = session->streams_head; + + while(NULL != stream && stream_id != stream->stream_id) + { + stream = stream->next; + } + + return stream; +} diff --git a/src/microspdy/stream.h b/src/microspdy/stream.h @@ -60,6 +60,17 @@ SPDYF_stream_destroy(struct SPDYF_Stream *stream); * @param response_queue sent for this stream */ void -SPDYF_stream_set_flags(struct SPDYF_Response_Queue *response_queue); +SPDYF_stream_set_flags_on_write(struct SPDYF_Response_Queue *response_queue); + + +/** + * Find and return a session's stream, based on stream's ID. + * + * @param stream_id to search for + * @param session whose streams are considered + * @return SPDY_Stream with the desired ID. Can be NULL. + */ +struct SPDYF_Stream * +SPDYF_stream_find(uint32_t stream_id, struct SPDY_Session * session); #endif diff --git a/src/microspdy/structures.h b/src/microspdy/structures.h @@ -317,6 +317,28 @@ struct SPDYF_Stream; struct SPDYF_Response_Queue; + +/** + * Callback for received new data chunk. + * + * @param cls client-defined closure + * @param stream handler + * @param buf data chunk from the data + * @param size the size of the data chunk 'buf' in bytes + * @param more false if this is the last frame received on this stream. Note: + * true does not mean that more data will come, exceptional + * situation is possible + * @return SPDY_YES to continue calling the function, + * SPDY_NO to stop calling the function for this stream + */ +typedef int +(*SPDYF_NewDataCallback) (void * cls, + struct SPDYF_Stream *stream, + const void * buf, + size_t size, + bool more); + + /** * Callback for new stream. To be used in the application layer of the * lib. @@ -515,6 +537,11 @@ struct SPDYF_Stream * Name value pairs, sent within the frame which created the stream. */ struct SPDY_NameValue *headers; + + /** + * Any object to be used by the application layer. + */ + void *cls; /** * This stream's ID. @@ -888,9 +915,14 @@ struct SPDY_Daemon /** * Callback called when HTTP POST params are received - * after request + * after request. To be used by the application layer + */ + SPDY_NewDataCallback received_data_cb; + + /** + * Callback called when DATA frame is received. */ - SPDY_NewPOSTDataCallback new_post_data_cb; + SPDYF_NewDataCallback freceived_data_cb; /** * Closure argument for all the callbacks that can be used by the client. diff --git a/src/spdy2http/proxy.c b/src/spdy2http/proxy.c @@ -163,11 +163,16 @@ struct Proxy char *version; char *status_msg; void *http_body; + void *received_body; bool *session_alive; size_t http_body_size; + size_t received_body_size; //ssize_t length; int status; bool done; + bool receiving_done; + bool is_curl_read_paused; + bool is_with_body_data; bool error; }; @@ -219,6 +224,7 @@ deinit_parse_uri(regex_t * preg) static int parse_uri(regex_t * preg, const char * full_uri, struct URI ** uri) { + //TODO memeory checks int ret; char *colon; long long port; @@ -277,7 +283,55 @@ parse_uri(regex_t * preg, const char * full_uri, struct URI ** uri) } -static void catch_signal(int signal) +static bool +store_in_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size) +{ + if(0 == src_size) + return true; + + if(NULL == *dst) + *dst = malloc(src_size); + else + *dst = realloc(*dst, src_size + *dst_size); + if(NULL == *dst) + return false; + + memcpy(*dst + *dst_size, src, src_size); + *dst_size += src_size; + + return true; +} + + +static ssize_t +get_from_buffer(void **src, size_t *src_size, void *dst, size_t max_size) +{ + size_t ret; + void *newbody; + + if(max_size >= *src_size) + { + ret = *src_size; + newbody = NULL; + } + else + { + ret = max_size; + if(NULL == (newbody = malloc(*src_size - max_size))) + return -1; + memcpy(newbody, *src + ret, *src_size - ret); + } + memcpy(dst, *src, ret); + free(*src); + *src = newbody; + *src_size -= ret; + + return ret; +} + + +static void +catch_signal(int signal) { (void)signal; @@ -319,7 +373,58 @@ session_closed_cb (void * cls, *session_alive = false; } - + + +static int +spdy_post_data_cb (void * cls, + struct SPDY_Request *request, + const void * buf, + size_t size, + bool more) +{ + (void)cls; + int ret; + struct Proxy *proxy = (struct Proxy *)SPDY_get_cls_from_request(request); + + if(!store_in_buffer(buf, size, &proxy->received_body, &proxy->received_body_size)) + { + PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); + return 0; + } + /* + if(NULL == proxy->received_body) + proxy->received_body = malloc(size); + else + proxy->received_body = realloc(proxy->received_body, proxy->received_body_size + size); + if(NULL == proxy->received_body) + { + PRINT_INFO("not enough memory (realloc returned NULL)"); + return 0; + } + + memcpy(proxy->received_body + proxy->received_body_size, buf, size); + proxy->received_body_size += size; + */ + + proxy->receiving_done = !more; + + PRINT_VERBOSE2("POST bytes from SPDY: %zu", size); + + call_curl_run = true; + + if(proxy->is_curl_read_paused) + { + if(CURLE_OK != (ret = curl_easy_pause(proxy->curl_handle, CURLPAUSE_CONT))) + { + PRINT_INFO2("curl_easy_pause returned %i", ret); + abort(); + } + PRINT_VERBOSE("curl_read_cb pause resumed"); + } + + return SPDY_YES; +} + ssize_t response_callback (void *cls, @@ -329,7 +434,7 @@ response_callback (void *cls, { ssize_t ret; struct Proxy *proxy = (struct Proxy *)cls; - void *newbody; + //void *newbody; //printf("response_callback\n"); @@ -347,6 +452,14 @@ response_callback (void *cls, return 0; } + ret = get_from_buffer(&(proxy->http_body), &(proxy->http_body_size), buffer, max); + if(ret < 0) + { + PRINT_INFO("no memory"); + return -1; + } + + /* if(max >= proxy->http_body_size) { ret = proxy->http_body_size; @@ -366,7 +479,7 @@ response_callback (void *cls, free(proxy->http_body); proxy->http_body = newbody; proxy->http_body_size -= ret; - + */ if(proxy->done && 0 == proxy->http_body_size) *more = false; PRINT_VERBOSE2("given bytes to microspdy: %zd", ret); @@ -407,6 +520,7 @@ response_done_callback(void *cls, } + static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) { @@ -560,6 +674,12 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) return 0; } + if(!store_in_buffer(contents, realsize, &proxy->http_body, &proxy->http_body_size)) + { + PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); + return 0; + } + /* if(NULL == proxy->http_body) proxy->http_body = malloc(realsize); else @@ -572,6 +692,7 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) memcpy(proxy->http_body + proxy->http_body_size, contents, realsize); proxy->http_body_size += realsize; + */ PRINT_VERBOSE2("received bytes from curl: %zu", realsize); @@ -581,6 +702,69 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) } +static size_t +curl_read_cb(void *ptr, size_t size, size_t nmemb, void *userp) +{ + ssize_t ret; + size_t max = size * nmemb; + struct Proxy *proxy = (struct Proxy *)userp; + //void *newbody; + + + if((proxy->receiving_done && !proxy->received_body_size) || !proxy->is_with_body_data || max < 1) + { + PRINT_VERBOSE("curl_read_cb last call"); + return 0; + } + + if(!*(proxy->session_alive)) + { + PRINT_VERBOSE("POST is still being sent, but session is dead"); + return CURL_READFUNC_ABORT; + } + + if(!proxy->received_body_size)//nothing to write now + { + PRINT_VERBOSE("curl_read_cb called paused"); + proxy->is_curl_read_paused = true; + return CURL_READFUNC_PAUSE;//TODO curl pause should be used + } + + ret = get_from_buffer(&(proxy->received_body), &(proxy->received_body_size), ptr, max); + if(ret < 0) + { + PRINT_INFO("no memory"); + return CURL_READFUNC_ABORT; + } + + /* + if(max >= proxy->received_body_size) + { + ret = proxy->received_body_size; + newbody = NULL; + } + else + { + ret = max; + if(NULL == (newbody = malloc(proxy->received_body_size - max))) + { + PRINT_INFO("no memory"); + return CURL_READFUNC_ABORT; + } + memcpy(newbody, proxy->received_body + max, proxy->received_body_size - max); + } + memcpy(ptr, proxy->received_body, ret); + free(proxy->received_body); + proxy->received_body = newbody; + proxy->received_body_size -= ret; + * */ + + PRINT_VERBOSE2("given POST bytes to curl: %zd", ret); + + return ret; +} + + static int iterate_cb (void *cls, const char *name, const char * const * value, int num_values) { @@ -630,7 +814,8 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { (void)cls; (void)priority; @@ -641,6 +826,13 @@ standard_request_handler(void *cls, int ret; struct URI *uri; struct SPDY_Session *session; + + proxy = SPDY_get_cls_from_request(request); + if(NULL != proxy) + { + //ignore trailers or more headers + return; + } PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version); @@ -654,7 +846,10 @@ standard_request_handler(void *cls, proxy->session_alive = SPDY_get_cls_from_session(session); assert(NULL != proxy->session_alive); + SPDY_set_cls_to_request(request, proxy); + proxy->request = request; + proxy->is_with_body_data = more; if(NULL == (proxy->headers = SPDY_name_value_create())) DIE("No memory"); @@ -703,6 +898,16 @@ standard_request_handler(void *cls, if(glob_opt.curl_verbose) CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); + + if(0 == strcmp(SPDY_HTTP_METHOD_POST,method)) + { + if(NULL == (proxy->curl_headers = curl_slist_append(proxy->curl_headers, "Expect:"))) + DIE("curl_slist_append failed"); + CURL_SETOPT(proxy->curl_handle, CURLOPT_POST, 1); + CURL_SETOPT(proxy->curl_handle, CURLOPT_READFUNCTION, curl_read_cb); + CURL_SETOPT(proxy->curl_handle, CURLOPT_READDATA, proxy); + } + if(glob_opt.timeout) CURL_SETOPT(proxy->curl_handle, CURLOPT_TIMEOUT, glob_opt.timeout); CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url); @@ -720,7 +925,7 @@ standard_request_handler(void *cls, CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); else if(glob_opt.ipv6 && !glob_opt.ipv4) CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); - + if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle))) { PRINT_INFO2("curl_multi_add_handle failed (%i)", ret); @@ -765,7 +970,7 @@ run () struct addrinfo *gai; enum SPDY_IO_SUBSYSTEM io = glob_opt.notls ? SPDY_IO_SUBSYSTEM_RAW : SPDY_IO_SUBSYSTEM_OPENSSL; enum SPDY_DAEMON_FLAG flags = SPDY_DAEMON_FLAG_NO; - struct SPDY_Response *error_response; + //struct SPDY_Response *error_response; char *curl_private; signal(SIGPIPE, SIG_IGN); @@ -790,7 +995,7 @@ run () &new_session_cb, &session_closed_cb, &standard_request_handler, - NULL, + &spdy_post_data_cb, NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 1800, @@ -819,7 +1024,7 @@ run () &new_session_cb, &session_closed_cb, &standard_request_handler, - NULL, + &spdy_post_data_cb, NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 1800, @@ -924,6 +1129,7 @@ run () while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { if (msg->msg == CURLMSG_DONE) { + PRINT_VERBOSE("A curl handler is done"); if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &curl_private))) { PRINT_INFO2("err %i",ret); @@ -944,7 +1150,7 @@ run () SPDY_name_value_destroy(proxy->headers); if(!*(proxy->session_alive)) { - if(NULL == (error_response = SPDY_build_response(SPDY_HTTP_BAD_GATEWAY, + /*if(NULL == (error_response = SPDY_build_response(SPDY_HTTP_BAD_GATEWAY, NULL, SPDY_HTTP_VERSION_1_1, NULL, @@ -961,7 +1167,24 @@ run () //clean and forget //TODO DIE("no queue"); - } + }*/ + + free(proxy->http_body); + proxy->http_body = NULL; + + if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle))) + { + PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret); + } + debug_num_curls--; + curl_slist_free_all(proxy->curl_headers); + curl_easy_cleanup(proxy->curl_handle); + + SPDY_destroy_request(proxy->request); + //SPDY_destroy_response(proxy->response); + free(proxy->url); + free(proxy); + } else proxy->error = true; diff --git a/src/testspdy/test_daemon_start_stop.c b/src/testspdy/test_daemon_start_stop.c @@ -21,7 +21,7 @@ * @brief starts and stops a SPDY daemon * @author Andrey Uzunov */ - + #include "platform.h" #include "microspdy.h" #include "common.h" diff --git a/src/testspdy/test_daemon_start_stop_many.c b/src/testspdy/test_daemon_start_stop_many.c @@ -21,7 +21,7 @@ * @brief starts and stops several SPDY daemons, reusing port numbers * @author Andrey Uzunov */ - + #include "platform.h" #include "microspdy.h" #include "common.h" diff --git a/src/testspdy/test_misc.c b/src/testspdy/test_misc.c @@ -21,7 +21,7 @@ * @brief tests a lot of small calls and callbacks. TODO mention what * @author Andrey Uzunov */ - + #include "platform.h" #include "microspdy.h" #include "stdio.h" @@ -93,10 +93,14 @@ create_child() void response_done_callback(void *cls, - struct SPDY_Response *response, - struct SPDY_Request *request, + struct SPDY_Response * response, + struct SPDY_Request * request, + enum SPDY_RESPONSE_RESULT status, bool streamopened) { + (void)status; + (void)streamopened; + if(strcmp(cls,"/main.css")) { session1 = SPDY_get_session_for_request(request); @@ -152,8 +156,19 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { + (void)cls; + (void)request; + (void)priority; + (void)host; + (void)scheme; + (void)headers; + (void)method; + (void)version; + (void)more; + struct SPDY_Response *response=NULL; char *cls_path = strdup(path); @@ -259,7 +274,7 @@ parentproc() int -main(int argc, char **argv) +main() { port = get_port(13123); SPDY_init(); diff --git a/src/testspdy/test_new_connection.c b/src/testspdy/test_new_connection.c @@ -24,7 +24,7 @@ * @author Tatsuhiro Tsujikawa */ - //TODO child exits with ret val 1 sometimes +//TODO child exits with ret val 1 sometimes #include "platform.h" #include "microspdy.h" @@ -44,12 +44,17 @@ pid_t child; int spdylay_printf(const char *format, ...) { + (void)format; + return 0; } int spdylay_fprintf(FILE *stream, const char *format, ...) { + (void)stream; + (void)format; + return 0; } @@ -215,6 +220,9 @@ static ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t length, int flags, void *user_data) { + (void)session; + (void)flags; + struct Connection *connection; ssize_t rv; connection = (struct Connection*)user_data; @@ -244,6 +252,9 @@ static ssize_t recv_callback(spdylay_session *session, uint8_t *buf, size_t length, int flags, void *user_data) { + (void)session; + (void)flags; + struct Connection *connection; ssize_t rv; connection = (struct Connection*)user_data; @@ -276,6 +287,8 @@ static void before_ctrl_send_callback(spdylay_session *session, spdylay_frame *frame, void *user_data) { + (void)user_data; + if(type == SPDYLAY_SYN_STREAM) { struct Request *req; int stream_id = frame->syn_stream.stream_id; @@ -291,6 +304,8 @@ static void on_ctrl_send_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { + (void)user_data; + char **nv; const char *name = NULL; int32_t stream_id; @@ -316,6 +331,8 @@ static void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { + (void)user_data; + struct Request *req; char **nv; const char *name = NULL; @@ -359,6 +376,8 @@ static void on_stream_close_callback(spdylay_session *session, spdylay_status_code status_code, void *user_data) { + (void)user_data; + (void)status_code; struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { @@ -381,6 +400,9 @@ static void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags, const uint8_t *data, size_t len, void *user_data) { + (void)user_data; + (void)flags; + struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { @@ -441,6 +463,8 @@ static int select_next_proto_cb(SSL* ssl, const unsigned char *in, unsigned int inlen, void *arg) { + (void)ssl; + int rv; uint16_t *spdy_proto_version; /* spdylay_select_next_protocol() selects SPDY protocol version the @@ -799,7 +823,7 @@ new_session_callback (void *cls, { char ipstr[1024]; - const struct sockaddr *addr; + struct sockaddr *addr; socklen_t addr_len = SPDY_get_remote_addr(session, &addr); if(!addr_len) @@ -955,7 +979,7 @@ parentproc(int child) return 0; } -int main(int argc, char **argv) +int main() { port = get_port(14123); parent = getpid(); diff --git a/src/testspdy/test_notls.c b/src/testspdy/test_notls.c @@ -199,6 +199,9 @@ static ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t length, int flags, void *user_data) { + (void)session; + (void)flags; + struct Connection *connection; ssize_t rv; connection = (struct Connection*)user_data; @@ -237,6 +240,9 @@ static ssize_t recv_callback(spdylay_session *session, uint8_t *buf, size_t length, int flags, void *user_data) { + (void)session; + (void)flags; + struct Connection *connection; ssize_t rv; connection = (struct Connection*)user_data; @@ -278,6 +284,8 @@ static void before_ctrl_send_callback(spdylay_session *session, spdylay_frame *frame, void *user_data) { + (void)user_data; + if(type == SPDYLAY_SYN_STREAM) { struct Request *req; int stream_id = frame->syn_stream.stream_id; @@ -293,6 +301,8 @@ static void on_ctrl_send_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { + (void)user_data; + char **nv; const char *name = NULL; int32_t stream_id; @@ -318,6 +328,8 @@ static void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { + (void)user_data; + struct Request *req; char **nv; const char *name = NULL; @@ -361,6 +373,9 @@ static void on_stream_close_callback(spdylay_session *session, spdylay_status_code status_code, void *user_data) { + (void)status_code; + (void)user_data; + struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { @@ -383,6 +398,9 @@ static void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags, const uint8_t *data, size_t len, void *user_data) { + (void)flags; + (void)user_data; + struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { @@ -743,8 +761,19 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { + (void)cls; + (void)request; + (void)priority; + (void)host; + (void)scheme; + (void)headers; + (void)method; + (void)version; + (void)more; + struct SPDY_Response *response=NULL; if(strcmp(CLS,cls)!=0) @@ -818,9 +847,6 @@ childproc(int port) if(NULL == (rcvbuf = malloc(strlen(RESPONSE_BODY)+1))) killparent(parent,"no memory"); - SSL_load_error_strings(); - SSL_library_init(); - rv = parse_uri(&uri, uristr); if(rv != 0) { killparent(parent,"parse_uri failed"); @@ -912,7 +938,7 @@ parentproc( int port) return WEXITSTATUS(childstatus); } -int main(int argc, char **argv) +int main() { int port = get_port(12123); parent = getpid(); diff --git a/src/testspdy/test_request_response.c b/src/testspdy/test_request_response.c @@ -23,7 +23,7 @@ * @author Andrey Uzunov * @author Tatsuhiro Tsujikawa */ - + #include "platform.h" #include "microspdy.h" #include <sys/wait.h> @@ -202,6 +202,9 @@ static ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t length, int flags, void *user_data) { + (void)session; + (void)flags; + struct Connection *connection; ssize_t rv; connection = (struct Connection*)user_data; @@ -231,6 +234,9 @@ static ssize_t recv_callback(spdylay_session *session, uint8_t *buf, size_t length, int flags, void *user_data) { + (void)session; + (void)flags; + struct Connection *connection; ssize_t rv; connection = (struct Connection*)user_data; @@ -263,6 +269,8 @@ static void before_ctrl_send_callback(spdylay_session *session, spdylay_frame *frame, void *user_data) { + (void)user_data; + if(type == SPDYLAY_SYN_STREAM) { struct Request *req; int stream_id = frame->syn_stream.stream_id; @@ -278,6 +286,8 @@ static void on_ctrl_send_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { + (void)user_data; + char **nv; const char *name = NULL; int32_t stream_id; @@ -303,6 +313,8 @@ static void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { + (void)user_data; + struct Request *req; char **nv; const char *name = NULL; @@ -346,6 +358,9 @@ static void on_stream_close_callback(spdylay_session *session, spdylay_status_code status_code, void *user_data) { + (void)user_data; + (void)status_code; + struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { @@ -368,6 +383,9 @@ static void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags, const uint8_t *data, size_t len, void *user_data) { + (void)user_data; + (void)flags; + struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { @@ -433,6 +451,8 @@ static int select_next_proto_cb(SSL* ssl, const unsigned char *in, unsigned int inlen, void *arg) { + (void)ssl; + int rv; uint16_t *spdy_proto_version; /* spdylay_select_next_protocol() selects SPDY protocol version the @@ -795,15 +815,30 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { + (void)cls; + (void)request; + (void)priority; + (void)host; + (void)scheme; + (void)headers; + (void)method; + (void)version; + struct SPDY_Response *response=NULL; if(strcmp(CLS,cls)!=0) { killchild(child,"wrong cls"); } - + + if(false != more){ + fprintf(stdout,"more has wrong value\n"); + exit(5); + } + response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,RESPONSE_BODY,strlen(RESPONSE_BODY)); if(NULL==response){ @@ -961,7 +996,7 @@ parentproc( int port) return WEXITSTATUS(childstatus); } -int main(int argc, char **argv) +int main() { int port = get_port(12123); parent = getpid(); diff --git a/src/testspdy/test_request_response_with_callback.c b/src/testspdy/test_request_response_with_callback.c @@ -21,7 +21,7 @@ * @brief tests responses with callbacks * @author Andrey Uzunov */ - + #include "platform.h" #include "microspdy.h" #include "stdio.h" @@ -85,10 +85,14 @@ response_callback (void *cls, void response_done_callback(void *cls, - struct SPDY_Response *response, - struct SPDY_Request *request, + struct SPDY_Response * response, + struct SPDY_Request * request, + enum SPDY_RESPONSE_RESULT status, bool streamopened) { + (void)status; + (void)streamopened; + printf("answer for %s was sent\n", (char*)cls); SPDY_destroy_request(request); @@ -107,8 +111,19 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { + (void)cls; + (void)request; + (void)priority; + (void)host; + (void)scheme; + (void)headers; + (void)method; + (void)version; + (void)more; + struct SPDY_Response *response=NULL; struct SPDY_NameValue *resp_headers; @@ -271,7 +286,7 @@ childproc() if(0 == ret && 0 == stat(DATA_DIR "spdy-draft.txt", &st)) { usecs = (uint64_t)1000000 * (uint64_t)(tv2.tv_sec - tv1.tv_sec) + tv2.tv_usec - tv1.tv_usec; - printf("%i bytes read in %i usecs\n", st.st_size, usecs); + printf("%lld bytes read in %llu usecs\n", (long long)st.st_size, (long long unsigned )usecs); } return ret; @@ -279,7 +294,7 @@ childproc() int -main(int argc, char **argv) +main() { port = get_port(11123); parent = getpid(); diff --git a/src/testspdy/test_requests_with_assets.c b/src/testspdy/test_requests_with_assets.c @@ -23,7 +23,7 @@ * libxml2. * @author Andrey Uzunov */ - + #include "platform.h" #include "microspdy.h" #include "common.h" @@ -133,8 +133,19 @@ standard_request_handler(void *cls, const char *version, const char *host, const char *scheme, - struct SPDY_NameValue * headers) + struct SPDY_NameValue * headers, + bool more) { + (void)cls; + (void)request; + (void)priority; + (void)host; + (void)scheme; + (void)headers; + (void)method; + (void)version; + (void)more; + struct SPDY_Response *response; if(NULL != strstr(path,".css")) @@ -279,7 +290,7 @@ parentproc() return html_resp_count != html_req_count; } -int main(int argc, char **argv) +int main() { parent = getpid(); port = get_port(10123); diff --git a/src/testspdy/test_session_timeout.c b/src/testspdy/test_session_timeout.c @@ -22,7 +22,7 @@ * client * @author Andrey Uzunov */ - + #include "platform.h" #include "microspdy.h" #include "stdio.h" @@ -66,6 +66,9 @@ void new_session_cb (void *cls, struct SPDY_Session * session) { + (void)cls; + (void)session; + if(!new_session)do_sleep = 1; new_session = 1; printf("new session\n"); @@ -76,6 +79,9 @@ closed_session_cb (void *cls, struct SPDY_Session * session, int by_client) { + (void)cls; + (void)session; + printf("closed_session_cb called\n"); if(SPDY_YES == by_client) @@ -150,20 +156,20 @@ parentproc() killchild("clock_gettime returned wrong value"); if(now - beginning > TIMEOUT*1000 + SELECT_MS_TIMEOUT) { - printf("Started at: %ims\n",beginning); - printf("Now is: %ims\n",now); + printf("Started at: %llums\n",beginning); + printf("Now is: %llums\n",now); printf("Timeout is: %i\n",TIMEOUT); printf("Select Timeout is: %ims\n",SELECT_MS_TIMEOUT); - printf("SPDY_get_timeout gave: %ims\n",timeoutlong); + printf("SPDY_get_timeout gave: %llums\n",timeoutlong); killchild("Timeout passed but session was not closed"); } if(timeoutlong > beginning + TIMEOUT *1000) { - printf("Started at: %ims\n",beginning); - printf("Now is: %ims\n",now); + printf("Started at: %llums\n",beginning); + printf("Now is: %llums\n",now); printf("Timeout is: %i\n",TIMEOUT); printf("Select Timeout is: %ims\n",SELECT_MS_TIMEOUT); - printf("SPDY_get_timeout gave: %ims\n",timeoutlong); + printf("SPDY_get_timeout gave: %llums\n",timeoutlong); killchild("SPDY_get_timeout returned wrong timeout"); } } @@ -210,10 +216,12 @@ parentproc() default: SPDY_run(daemon); if(0 == beginning) - if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) - beginning = ts.tv_nsec / 1000000 + ts.tv_sec*1000; - else - killchild("clock_gettime returned wrong number"); + { + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + beginning = ts.tv_nsec / 1000000 + ts.tv_sec*1000; + else + killchild("clock_gettime returned wrong number"); + } /*if(do_sleep) { sleep(TIMEOUT); @@ -283,7 +291,7 @@ childproc() int -main(int argc, char **argv) +main() { port = get_port(11123); parent = getpid(); diff --git a/src/testspdy/test_struct_namevalue.c b/src/testspdy/test_struct_namevalue.c @@ -37,6 +37,7 @@ int size2; int brake_at = 3; bool flag; + int iterate_cb (void *cls, const char *name, const char * const * value, int num_values) { @@ -68,6 +69,10 @@ iterate_cb (void *cls, const char *name, const char * const * value, int num_val int iterate_brake_cb (void *cls, const char *name, const char * const *value, int num_values) { + (void)name; + (void)value; + (void)num_values; + int *c = (int*)cls; if(*c < 0 || *c >= brake_at) @@ -102,7 +107,7 @@ main() struct SPDY_NameValue *container; struct SPDY_NameValue *container2; struct SPDY_NameValue *container3; - struct SPDY_NameValue *container_arr[1]; + struct SPDY_NameValue *container_arr[2]; size = sizeof(pairs)/sizeof(pairs[0]); @@ -144,7 +149,7 @@ main() value = SPDY_name_value_lookup(container,pairs[i], &ret); if(NULL == value || 1 !=ret || strcmp(value[0], pairs[i+1]) != 0) { - printf("%i; %i; %i\n", value, ret, strcmp(value[0], pairs[i+1])); + printf("%p; %i; %i\n", value, ret, strcmp(value[0], pairs[i+1])); FAIL_TEST("SPDY_name_value_lookup failed\n"); } } @@ -251,7 +256,7 @@ main() value = SPDY_name_value_lookup(container,pairs_with_empty[i], &ret); if(NULL == value || 1 != ret) { - printf("%i; %i\n", value, ret); + printf("%p; %i\n", value, ret); FAIL_TEST("SPDY_name_value_lookup failed\n"); } }