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
response_callback(void * cls,void * buffer,size_t max,bool * more)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
response_done_callback(void * cls,struct SPDY_Response * response,struct SPDY_Request * request,enum SPDY_RESPONSE_RESULT status,bool streamopened)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
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)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
main(int argc,char * const * argv)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