Home | History | Annotate | Download | only in examples
      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