Home | History | Annotate | Download | only in testspdy
      1 /*
      2     This file is part of libmicrospdy
      3     Copyright Copyright (C) 2013 Andrey Uzunov
      4 
      5     This program is free software: you can redistribute it and/or modify
      6     it under the terms of the GNU General Public License as published by
      7     the Free Software Foundation, either version 3 of the License, or
      8     (at your option) any later version.
      9 
     10     This program is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13     GNU General Public License for more details.
     14 
     15     You should have received a copy of the GNU General Public License
     16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 */
     18 
     19 /**
     20  * @file misc.c
     21  * @brief  tests a lot of small calls and callbacks. TODO mention what
     22  * @author Andrey Uzunov
     23  */
     24 
     25 #include "platform.h"
     26 #include "microspdy.h"
     27 #include "stdio.h"
     28 #include <sys/wait.h>
     29 #include "common.h"
     30 
     31 int port;
     32 
     33 #define HTML "<html><head>\
     34 <link href=\"main.css\" rel=\"stylesheet\" type=\"text/css\" />\
     35 </head><body>This is libmicrospdy</body></html>"
     36 
     37 #define CSS "body{font-size:15px}"
     38 
     39 #define SESSION_CLS "1234567890"
     40 
     41 #define REQUEST_CLS "1234567890REQ"
     42 
     43 pid_t parent;
     44 pid_t child;
     45 
     46 struct SPDY_Session *session1;
     47 struct SPDY_Session *session2;
     48 
     49 void
     50 killchild()
     51 {
     52 	kill(child, SIGKILL);
     53 	exit(1);
     54 }
     55 
     56 void
     57 killparent()
     58 {
     59 	kill(parent, SIGKILL);
     60 	_exit(1);
     61 }
     62 
     63 
     64 void
     65 create_child()
     66 {
     67 	parent = getpid();
     68 
     69 	child = fork();
     70 	if (-1 == child)
     71 	{
     72 		fprintf(stderr, "can't fork, error %d\n", errno);
     73 		exit(EXIT_FAILURE);
     74 	}
     75 
     76 	if (child == 0)
     77 	{
     78 		int devnull;
     79 		char *uri;
     80 		fflush(stdout);
     81 		devnull = open("/dev/null", O_WRONLY);
     82                 if (-1 == devnull)
     83                   abort ();
     84 		if (1 != devnull)
     85 		{
     86 			dup2(devnull, 1);
     87 			close(devnull);
     88 		}
     89 		asprintf(&uri,"https://127.0.0.1:%i/",port);
     90 		execlp("spdycat", "spdycat","-anv",uri,NULL );
     91 		printf("execlp failed\n");
     92 		killparent();
     93 	}
     94 }
     95 
     96 void
     97 response_done_callback(void *cls,
     98 								struct SPDY_Response * response,
     99 								struct SPDY_Request * request,
    100 								enum SPDY_RESPONSE_RESULT status,
    101 						bool streamopened)
    102 {
    103   (void)status;
    104   (void)streamopened;
    105 
    106 	if(strcmp(cls,"/main.css"))
    107 	{
    108 		session1 = SPDY_get_session_for_request(request);
    109 		if(NULL == session1)
    110 		{
    111 			printf("SPDY_get_session_for_request failed\n");
    112 			killchild();
    113 		}
    114 
    115 		char *session_cls = strdup(SESSION_CLS);
    116 		SPDY_set_cls_to_session(session1,session_cls);
    117 	}
    118 	else
    119 	{
    120 		session2 = SPDY_get_session_for_request(request);
    121 		if(session1 != session2)
    122 		{
    123 			printf("SPDY_get_session_for_request failed the second time\n");
    124 			killchild();
    125 		}
    126 		printf("SPDY_get_session_for_request tested...\n");
    127 
    128 		void *session_cls = SPDY_get_cls_from_session(session2);
    129 		if(NULL == session_cls || strcmp(session_cls, SESSION_CLS))
    130 		{
    131 			printf("SPDY_get_cls_from_session failed\n");
    132 			killchild();
    133 		}
    134 		printf("SPDY_set_cls_to_session tested...\n");
    135 		printf("SPDY_get_cls_from_session tested...\n");
    136 
    137 		void *request_cls = SPDY_get_cls_from_request(request);
    138 		if(NULL == request_cls || strcmp(request_cls, REQUEST_CLS))
    139 		{
    140 			printf("SPDY_get_cls_from_request failed\n");
    141 			killchild();
    142 		}
    143 		printf("SPDY_set_cls_to_request tested...\n");
    144 		printf("SPDY_get_cls_from_request tested...\n");
    145 	}
    146 
    147 	SPDY_destroy_request(request);
    148 	SPDY_destroy_response(response);
    149 	free(cls);
    150 }
    151 
    152 void
    153 standard_request_handler(void *cls,
    154 						struct SPDY_Request * request,
    155 						uint8_t priority,
    156                         const char *method,
    157                         const char *path,
    158                         const char *version,
    159                         const char *host,
    160                         const char *scheme,
    161 						struct SPDY_NameValue * headers,
    162             bool more)
    163 {
    164 	(void)cls;
    165 	(void)request;
    166 	(void)priority;
    167 	(void)host;
    168 	(void)scheme;
    169 	(void)headers;
    170 	(void)method;
    171 	(void)version;
    172 	(void)more;
    173 
    174 	struct SPDY_Response *response=NULL;
    175 	char *cls_path = strdup(path);
    176 
    177 	if(strcmp(path,"/main.css")==0)
    178 	{
    179 		char *request_cls = strdup(REQUEST_CLS);
    180 		SPDY_set_cls_to_request(request,request_cls);
    181 		response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,CSS,strlen(CSS));
    182 	}
    183 	else
    184 	{
    185 		response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,HTML,strlen(HTML));
    186 	}
    187 
    188 	if(NULL==response){
    189 		fprintf(stdout,"no response obj\n");
    190 		killchild();
    191 	}
    192 
    193 	if(SPDY_queue_response(request,response,true,false,&response_done_callback,cls_path)!=SPDY_YES)
    194 	{
    195 		fprintf(stdout,"queue\n");
    196 		killchild();
    197 	}
    198 }
    199 
    200 int
    201 parentproc()
    202 {
    203 	int childstatus;
    204 	unsigned long long timeoutlong=0;
    205 	struct timeval timeout;
    206 	int ret;
    207 	fd_set read_fd_set;
    208 	fd_set write_fd_set;
    209 	fd_set except_fd_set;
    210 	int maxfd = -1;
    211 	struct SPDY_Daemon *daemon;
    212 
    213 	daemon = SPDY_start_daemon(port,
    214 								DATA_DIR "cert-and-key.pem",
    215 								DATA_DIR "cert-and-key.pem",
    216 								NULL,
    217 								NULL,
    218 								&standard_request_handler,
    219 								NULL,
    220 								NULL,
    221 								SPDY_DAEMON_OPTION_SESSION_TIMEOUT,
    222 								1800,
    223 								SPDY_DAEMON_OPTION_END);
    224 
    225 	if(NULL==daemon){
    226 		printf("no daemon\n");
    227 		return 1;
    228 	}
    229 
    230 	create_child();
    231 
    232 	do
    233 	{
    234 		FD_ZERO(&read_fd_set);
    235 		FD_ZERO(&write_fd_set);
    236 		FD_ZERO(&except_fd_set);
    237 
    238 		ret = SPDY_get_timeout(daemon, &timeoutlong);
    239 		if(SPDY_NO == ret || timeoutlong > 1000)
    240 		{
    241 			timeout.tv_sec = 1;
    242       timeout.tv_usec = 0;
    243 		}
    244 		else
    245 		{
    246 			timeout.tv_sec = timeoutlong / 1000;
    247 			timeout.tv_usec = (timeoutlong % 1000) * 1000;
    248 		}
    249 
    250 		maxfd = SPDY_get_fdset (daemon,
    251 								&read_fd_set,
    252 								&write_fd_set,
    253 								&except_fd_set);
    254 
    255 		ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout);
    256 
    257 		switch(ret) {
    258 			case -1:
    259 				printf("select error: %i\n", errno);
    260 				break;
    261 			case 0:
    262 
    263 				break;
    264 			default:
    265 				SPDY_run(daemon);
    266 
    267 			break;
    268 		}
    269 	}
    270 	while(waitpid(child,&childstatus,WNOHANG) != child);
    271 
    272 	SPDY_stop_daemon(daemon);
    273 
    274 	return WEXITSTATUS(childstatus);
    275 }
    276 
    277 
    278 int
    279 main()
    280 {
    281 	port = get_port(13123);
    282 	SPDY_init();
    283 
    284 	int ret = parentproc();
    285 
    286 	SPDY_deinit();
    287 
    288 	return ret;
    289 }
    290