/*
This file is part of libmicrospdy
Copyright Copyright (C) 2013 Andrey Uzunov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file response_with_callback.c
* @brief shows how to create responses with callbacks
* @author Andrey Uzunov
*/
//for asprintf
#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "microspdy.h"
static int run = 1;
static ssize_t
response_callback (void *cls,
void *buffer,
size_t max,
bool *more)
{
FILE *fd =(FILE*)cls;
int ret = fread(buffer,1,max,fd);
*more = feof(fd) == 0;
if(!(*more))
fclose(fd);
return ret;
}
static void
response_done_callback(void *cls,
struct SPDY_Response *response,
struct SPDY_Request *request,
enum SPDY_RESPONSE_RESULT status,
bool streamopened)
{
(void)streamopened;
(void)status;
printf("answer for %s was sent\n", (char *)cls);
SPDY_destroy_request(request);
SPDY_destroy_response(response);
free(cls);
}
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)
{
(void)cls;
(void)request;
(void)priority;
(void)host;
(void)scheme;
(void)headers;
(void)more;
char *html;
struct SPDY_Response *response=NULL;
struct SPDY_NameValue *resp_headers;
printf("received request for '%s %s %s'\n", method, path, version);
if(strcmp(path,"/spdy-draft.txt")==0)
{
FILE *fd = fopen(DATA_DIR "spdy-draft.txt","r");
if(NULL == (resp_headers = SPDY_name_value_create()))
{
fprintf(stdout,"SPDY_name_value_create failed\n");
abort();
}
if(SPDY_YES != SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_CONTENT_TYPE,"text/plain"))
{
fprintf(stdout,"SPDY_name_value_add failed\n");
abort();
}
response = SPDY_build_response_with_callback(200,NULL,
SPDY_HTTP_VERSION_1_1,resp_headers,&response_callback,fd,SPDY_MAX_SUPPORTED_FRAME_SIZE);
SPDY_name_value_destroy(resp_headers);
}
else
{
if(strcmp(path,"/close")==0)
{
asprintf(&html,"<html>"
"<body><b>Closing now!</body></html>");
run = 0;
}
else
{
asprintf(&html,"<html>"
"<body><a href=\"/spdy-draft.txt\">/spdy-draft.txt</a><br></body></html>");
}
response = SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html));
free(html);
}
if(NULL==response){
fprintf(stdout,"no response obj\n");
abort();
}
void *clspath = strdup(path);
if(SPDY_queue_response(request,response,true,false,&response_done_callback,clspath)!=SPDY_YES)
{
fprintf(stdout,"queue\n");
abort();
}
}
int
main (int argc, char *const *argv)
{
unsigned long long timeoutlong=0;
struct timeval timeout;
int ret;
fd_set read_fd_set;
fd_set write_fd_set;
fd_set except_fd_set;
int maxfd = -1;
struct SPDY_Daemon *daemon;
if(argc != 2)
{
return 1;
}
SPDY_init();
daemon = SPDY_start_daemon(atoi(argv[1]),
DATA_DIR "cert-and-key.pem",
DATA_DIR "cert-and-key.pem",
NULL,
NULL,
&standard_request_handler,
NULL,
NULL,
SPDY_DAEMON_OPTION_SESSION_TIMEOUT,
1800,
SPDY_DAEMON_OPTION_END);
if(NULL==daemon){
printf("no daemon\n");
return 1;
}
do
{
FD_ZERO(&read_fd_set);
FD_ZERO(&write_fd_set);
FD_ZERO(&except_fd_set);
ret = SPDY_get_timeout(daemon, &timeoutlong);
if(SPDY_NO == ret || timeoutlong > 1000)
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
}
else
{
timeout.tv_sec = timeoutlong / 1000;
timeout.tv_usec = (timeoutlong % 1000) * 1000;
}
maxfd = SPDY_get_fdset (daemon,
&read_fd_set,
&write_fd_set,
&except_fd_set);
ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout);
switch(ret) {
case -1:
printf("select error: %i\n", errno);
break;
case 0:
break;
default:
SPDY_run(daemon);
break;
}
}
while(run);
SPDY_stop_daemon(daemon);
SPDY_deinit();
return 0;
}