diff options
Diffstat (limited to 'src/examples/spdy_event_loop.c')
-rw-r--r-- | src/examples/spdy_event_loop.c | 487 |
1 files changed, 487 insertions, 0 deletions
diff --git a/src/examples/spdy_event_loop.c b/src/examples/spdy_event_loop.c new file mode 100644 index 00000000..6b7192c3 --- /dev/null +++ b/src/examples/spdy_event_loop.c @@ -0,0 +1,487 @@ +/* + This file is part of libmicrospdy + Copyright Copyright (C) 2012 Andrey Uzunov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file event_loop.c + * @brief shows how to use the daemon. THIS IS MAINLY A TEST AND DEBUG + * PROGRAM + * @author Andrey Uzunov + */ + +#include "platform.h" +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include "microspdy.h" +#include <sys/time.h> +#include <time.h> +#ifndef MINGW +#include <arpa/inet.h> +#endif +//#include "../framinglayer/structures.h" +//#include "../applicationlayer/alstructures.h" + +static int run = 1; + +static int run2 = 1; + + +static uint64_t loops; + +static time_t start; + + +static void +new_session_callback (void *cls, + struct SPDY_Session * session) +{ + (void)cls; + + char ipstr[1024]; + + struct sockaddr *addr; + socklen_t addr_len = SPDY_get_remote_addr(session, &addr); + + if(!addr_len) + { + printf("SPDY_get_remote_addr"); + abort(); + } + + if(AF_INET == addr->sa_family) + { + struct sockaddr_in * addr4 = (struct sockaddr_in *) addr; + if(NULL == inet_ntop(AF_INET, &(addr4->sin_addr), ipstr, sizeof(ipstr))) + { + printf("inet_ntop"); + abort(); + } + printf("New connection from: %s:%i\n", ipstr, ntohs(addr4->sin_port)); + + } + else if(AF_INET6 == addr->sa_family) + { + struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *) addr; + if(NULL == inet_ntop(AF_INET6, &(addr6->sin6_addr), ipstr, sizeof(ipstr))) + { + printf("inet_ntop"); + abort(); + } + printf("New connection from: %s:%i\n", ipstr, ntohs(addr6->sin6_port)); + + } +} + + +static void +session_closed_handler (void *cls, + struct SPDY_Session * session, + int by_client) +{ + (void)cls; + (void)session; + + //printf("session_closed_handler called\n"); + + if(SPDY_YES != by_client) + { + //killchild(child,"wrong by_client"); + printf("session closed by server\n"); + } + else + { + printf("session closed by client\n"); + } + + //session_closed_called = 1; +} + + +static void +response_done_callback(void *cls, + struct SPDY_Response *response, + struct SPDY_Request *request, + enum SPDY_RESPONSE_RESULT status, + bool streamopened) +{ + (void)streamopened; + if(strcmp(cls, "/close (daemon1)") == 0) + run = 0; + else { + if(strcmp(cls, "/close (daemon2)") == 0) run2 = 0; + loops = 0; + start = time(NULL); + } + if(SPDY_RESPONSE_RESULT_SUCCESS != status) + { + printf("not sent frame cause %i", status); + } + printf("answer for %s was sent\n", (char*)cls); + //printf("raw sent headers %s\n", (char *)(response->headers)+8); + + SPDY_destroy_request(request); + SPDY_destroy_response(response); + free(cls); +} + +/* +static int +print_headers (void *cls, + const char *name, const char *value) +{ + (void)cls; + printf("%s: %s\n",name,value); + return SPDY_YES; +} + */ + + +/* +void +new_request_cb (void *cls, + struct SPDY_Request * request, + uint8_t priority, + const char *method, + const char *path, + const char *version, + const char *host, + const char *scheme, + struct SPDY_NameValue * headers) +{ + (void)cls; + (void)request; + printf("Priority: %i\nHTTP headers, scheme: %s\n\n%s %s %s\nHost: %s\n", priority,scheme,method,path,version,host); + SPDY_name_value_iterate(headers, &print_headers, NULL); +} +*/ + + +static int +append_headers_to_data (void *cls, + const char *name, const char * const *value, int num_values) +{ + char **data = cls; + void *tofree = *data; + int i; + + if(num_values) + for(i=0;i<num_values;++i) + { + asprintf(data,"%s%s: %s\n", *data,name,value[i]); + } + else + asprintf(data,"%s%s: \n", *data,name); + + free(tofree); + return SPDY_YES; +} + + +static void +standard_request_handler(void *cls, + struct SPDY_Request * request, + uint8_t priority, + const char *method, + const char *path, + const char *version, + const char *host, + const char *scheme, + struct SPDY_NameValue * headers, + bool more) +{ + (void)more; + + char *html; + char *data; + struct SPDY_Response *response=NULL; + + printf("received request for '%s %s %s'\n", method, path, version); + if(strcmp(path,"/main.css")==0) + { + if(NULL != cls) + asprintf(&html,"body{color:green;}"); + else + asprintf(&html,"body{color:red;}"); + + //struct SPDY_NameValue *headers=SPDY_name_value_create(); + //SPDY_name_value_add(headers,"content-type","text/css"); + + response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html)); + free(html); + } + else + { + asprintf(&data,"Priority: %i\nHTTP headers, scheme: %s\n\n%s %s %s\nHost: %s\n", priority,scheme,method,path,version,host); + + SPDY_name_value_iterate(headers, &append_headers_to_data, &data); + + if(strcmp(path,"/close")==0) + { + asprintf(&html,"<html>" + "<body><b>Closing now!<br>This is an answer to the following " + "request:</b><br><br><pre>%s</pre></body></html>",data); + } + else + { + asprintf(&html,"<html><link href=\"main.css\" rel=\"stylesheet\" type=\"text/css\" />" + "<body><b>This is an answer to the following " + "request:</b><br><br><pre>%s</pre></body></html>",data); + } + + free(data); + + response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html)); + free(html); + } + + if(NULL==response){ + fprintf(stdout,"no response obj\n"); + abort(); + } + + char *pathcls; + asprintf(&pathcls, "%s (daemon%i)",path,NULL==cls ? 1 : 2); + if(SPDY_queue_response(request,response,true,false,&response_done_callback,pathcls)!=SPDY_YES) + { + fprintf(stdout,"queue\n"); + abort(); + } +} + + +static int +new_post_data_cb (void * cls, + struct SPDY_Request *request, + const void * buf, + size_t size, + bool more) +{ + (void)cls; + (void)request; + (void)more; + + printf("DATA:\n===============================\n"); + write(0, buf, size); + printf("\n===============================\n"); + return SPDY_YES; +} + + +static void +sig_handler(int signo) +{ + (void)signo; + + printf("received signal\n"); +} + + +int +main (int argc, char *const *argv) +{ + if(argc != 2) return 1; + + #ifndef MINGW + if (signal(SIGPIPE, sig_handler) == SIG_ERR) + printf("\ncan't catch SIGPIPE\n"); + #endif + + SPDY_init(); + + /* + struct sockaddr_in addr4; + struct in_addr inaddr4; + inaddr4.s_addr = htonl(INADDR_ANY); + addr4.sin_family = AF_INET; + addr4.sin_addr = inaddr4; + addr4.sin_port = htons(atoi(argv[1])); + */ + + 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,&new_post_data_cb,NULL, + SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 10, + //SPDY_DAEMON_OPTION_SOCK_ADDR, (struct sockaddr *)&addr4, + SPDY_DAEMON_OPTION_END); + + if(NULL==daemon){ + printf("no daemon\n"); + return 1; + } + + /* + struct sockaddr_in6 addr6; + addr6.sin6_family = AF_INET6; + addr6.sin6_addr = in6addr_any; + addr6.sin6_port = htons(atoi(argv[1]) + 1); + */ + + 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,&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, + SPDY_DAEMON_OPTION_END); + + if(NULL==daemon2){ + printf("no daemon\n"); + return 1; + } + + do + { + unsigned long long timeoutlong=0; + struct timeval timeout; + volatile int rc; /* select() return code */ + volatile int ret; + + fd_set read_fd_set; + fd_set write_fd_set; + fd_set except_fd_set; + int maxfd = -1; + + if(run && daemon != NULL) + { + loops++; + FD_ZERO(&read_fd_set); + FD_ZERO(&write_fd_set); + FD_ZERO(&except_fd_set); + + ret = SPDY_get_timeout(daemon, &timeoutlong); + if(SPDY_NO == ret || timeoutlong > 1000) + { + timeout.tv_sec = 1; + timeout.tv_usec = 0; + } + else + { + timeout.tv_sec = timeoutlong / 1000; + timeout.tv_usec = (timeoutlong % 1000) * 1000; + } + + printf("ret=%i; timeoutlong=%llu; sec=%llu; usec=%llu\n", ret, timeoutlong, (long long unsigned)timeout.tv_sec, (long long unsigned)timeout.tv_usec); + //raise(SIGINT); + + /* get file descriptors from the transfers */ + maxfd = SPDY_get_fdset (daemon, + &read_fd_set, + &write_fd_set, + &except_fd_set); + +//struct timeval ts1,ts2; + //gettimeofday(&ts1, NULL); + rc = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); + //gettimeofday(&ts2, NULL); + printf("rc %i\n",rc); + // printf("time for select %i\n",ts2.tv_usec - ts1.tv_usec); + // printf("%i %i %i %i\n",ts1.tv_sec, ts1.tv_usec,ts2.tv_sec, ts2.tv_usec); + + switch(rc) { + case -1: + /* select error */ + break; + case 0: + + break; + default: + SPDY_run(daemon); + + break; + } + } + else if(daemon != NULL){ + + printf("%lu loops in %llu secs\n", loops, (long long unsigned)(time(NULL) - start)); + SPDY_stop_daemon(daemon); + daemon=NULL; + } + + if(run2) + { + FD_ZERO(&read_fd_set); + FD_ZERO(&write_fd_set); + FD_ZERO(&except_fd_set); + + ret = SPDY_get_timeout(daemon2, &timeoutlong); + //printf("tout %i\n",timeoutlong); + if(SPDY_NO == ret || timeoutlong > 1) + { + //do sth else + //sleep(1); + + //try new connection + timeout.tv_sec = 1; + timeout.tv_usec = 0; + } + else + { + timeout.tv_sec = timeoutlong; + timeout.tv_usec = 0;//(timeoutlong % 1000) * 1000; + } + + //printf("ret=%i; timeoutlong=%i; sec=%i; usec=%i\n", ret, timeoutlong, timeout.tv_sec, timeout.tv_usec); + //raise(SIGINT); + + /* get file descriptors from the transfers */ + maxfd = SPDY_get_fdset (daemon2, + &read_fd_set, + &write_fd_set, + &except_fd_set); + + rc = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); + + switch(rc) { + case -1: + /* select error */ + break; + case 0: + + break; + default: + SPDY_run(daemon2); + + break; + } + } + else if(daemon2 != NULL){ + SPDY_stop_daemon(daemon2); + daemon2=NULL; + } + } + while(run || run2); + + if(daemon != NULL){ + SPDY_stop_daemon(daemon); + } + if(daemon2 != NULL){ + SPDY_stop_daemon(daemon2); + } + + SPDY_deinit(); + + return 0; +} + |