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 response_with_callback.c 21 * @brief shows how to create responses with callbacks 22 * @author Andrey Uzunov 23 */ 24 25 //for asprintf 26 #define _GNU_SOURCE 27 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <stdint.h> 31 #include <stdbool.h> 32 #include <string.h> 33 #include <stdio.h> 34 #include <ctype.h> 35 #include <errno.h> 36 #include "microspdy.h" 37 38 static int run = 1; 39 40 41 static ssize_t 42 response_callback (void *cls, 43 void *buffer, 44 size_t max, 45 bool *more) 46 { 47 FILE *fd =(FILE*)cls; 48 49 int ret = fread(buffer,1,max,fd); 50 *more = feof(fd) == 0; 51 52 if(!(*more)) 53 fclose(fd); 54 55 return ret; 56 } 57 58 59 static void 60 response_done_callback(void *cls, 61 struct SPDY_Response *response, 62 struct SPDY_Request *request, 63 enum SPDY_RESPONSE_RESULT status, 64 bool streamopened) 65 { 66 (void)streamopened; 67 (void)status; 68 69 printf("answer for %s was sent\n", (char *)cls); 70 71 SPDY_destroy_request(request); 72 SPDY_destroy_response(response); 73 free(cls); 74 } 75 76 77 static void 78 standard_request_handler(void *cls, 79 struct SPDY_Request * request, 80 uint8_t priority, 81 const char *method, 82 const char *path, 83 const char *version, 84 const char *host, 85 const char *scheme, 86 struct SPDY_NameValue * headers, 87 bool more) 88 { 89 (void)cls; 90 (void)request; 91 (void)priority; 92 (void)host; 93 (void)scheme; 94 (void)headers; 95 (void)more; 96 97 char *html; 98 struct SPDY_Response *response=NULL; 99 struct SPDY_NameValue *resp_headers; 100 101 printf("received request for '%s %s %s'\n", method, path, version); 102 if(strcmp(path,"/spdy-draft.txt")==0) 103 { 104 FILE *fd = fopen(DATA_DIR "spdy-draft.txt","r"); 105 106 if(NULL == (resp_headers = SPDY_name_value_create())) 107 { 108 fprintf(stdout,"SPDY_name_value_create failed\n"); 109 abort(); 110 } 111 if(SPDY_YES != SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_CONTENT_TYPE,"text/plain")) 112 { 113 fprintf(stdout,"SPDY_name_value_add failed\n"); 114 abort(); 115 } 116 117 response = SPDY_build_response_with_callback(200,NULL, 118 SPDY_HTTP_VERSION_1_1,resp_headers,&response_callback,fd,SPDY_MAX_SUPPORTED_FRAME_SIZE); 119 SPDY_name_value_destroy(resp_headers); 120 } 121 else 122 { 123 if(strcmp(path,"/close")==0) 124 { 125 asprintf(&html,"<html>" 126 "<body><b>Closing now!</body></html>"); 127 run = 0; 128 } 129 else 130 { 131 asprintf(&html,"<html>" 132 "<body><a href=\"/spdy-draft.txt\">/spdy-draft.txt</a><br></body></html>"); 133 } 134 135 response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html)); 136 free(html); 137 } 138 139 if(NULL==response){ 140 fprintf(stdout,"no response obj\n"); 141 abort(); 142 } 143 144 void *clspath = strdup(path); 145 146 if(SPDY_queue_response(request,response,true,false,&response_done_callback,clspath)!=SPDY_YES) 147 { 148 fprintf(stdout,"queue\n"); 149 abort(); 150 } 151 } 152 153 154 int 155 main (int argc, char *const *argv) 156 { 157 unsigned long long timeoutlong=0; 158 struct timeval timeout; 159 int ret; 160 fd_set read_fd_set; 161 fd_set write_fd_set; 162 fd_set except_fd_set; 163 int maxfd = -1; 164 struct SPDY_Daemon *daemon; 165 166 if(argc != 2) 167 { 168 return 1; 169 } 170 171 SPDY_init(); 172 173 daemon = SPDY_start_daemon(atoi(argv[1]), 174 DATA_DIR "cert-and-key.pem", 175 DATA_DIR "cert-and-key.pem", 176 NULL, 177 NULL, 178 &standard_request_handler, 179 NULL, 180 NULL, 181 SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 182 1800, 183 SPDY_DAEMON_OPTION_END); 184 185 if(NULL==daemon){ 186 printf("no daemon\n"); 187 return 1; 188 } 189 190 do 191 { 192 FD_ZERO(&read_fd_set); 193 FD_ZERO(&write_fd_set); 194 FD_ZERO(&except_fd_set); 195 196 ret = SPDY_get_timeout(daemon, &timeoutlong); 197 if(SPDY_NO == ret || timeoutlong > 1000) 198 { 199 timeout.tv_sec = 1; 200 timeout.tv_usec = 0; 201 } 202 else 203 { 204 timeout.tv_sec = timeoutlong / 1000; 205 timeout.tv_usec = (timeoutlong % 1000) * 1000; 206 } 207 208 maxfd = SPDY_get_fdset (daemon, 209 &read_fd_set, 210 &write_fd_set, 211 &except_fd_set); 212 213 ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); 214 215 switch(ret) { 216 case -1: 217 printf("select error: %i\n", errno); 218 break; 219 case 0: 220 221 break; 222 default: 223 SPDY_run(daemon); 224 225 break; 226 } 227 } 228 while(run); 229 230 SPDY_stop_daemon(daemon); 231 232 SPDY_deinit(); 233 234 return 0; 235 } 236 237