• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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