/* 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; }