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 31int 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 43pid_t parent; 44pid_t child; 45 46struct SPDY_Session *session1; 47struct SPDY_Session *session2; 48 49void 50killchild() 51{ 52 kill(child, SIGKILL); 53 exit(1); 54} 55 56void 57killparent() 58{ 59 kill(parent, SIGKILL); 60 _exit(1); 61} 62 63 64void 65create_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 96void 97response_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 152void 153standard_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 200int 201parentproc() 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 278int 279main() 280{ 281 port = get_port(13123); 282 SPDY_init(); 283 284 int ret = parentproc(); 285 286 SPDY_deinit(); 287 288 return ret; 289} 290