From ce0233845fe376ada044e0af6723083631e00e51 Mon Sep 17 00:00:00 2001 From: Brian Demsky Date: Thu, 21 Jul 2016 14:24:15 -0700 Subject: [PATCH] Some code towards a FastCGI server --- src/server/Makefile | 6 +++ src/server/iotcloud.cpp | 110 +++++++++++++++++++++++++++++++++++++++ src/server/iotcloud.fcgi | Bin 0 -> 28912 bytes 3 files changed, 116 insertions(+) create mode 100644 src/server/Makefile create mode 100644 src/server/iotcloud.cpp create mode 100755 src/server/iotcloud.fcgi diff --git a/src/server/Makefile b/src/server/Makefile new file mode 100644 index 0000000..9b6231b --- /dev/null +++ b/src/server/Makefile @@ -0,0 +1,6 @@ +CPPFLAGS=-O0 -g + +all: iotcloud.fcgi + +iotcloud.fcgi: iotcloud.cpp + g++ $(CPPFLAGS) -o iotcloud.fcgi iotcloud.cpp -lfcgi -lfcgi++ diff --git a/src/server/iotcloud.cpp b/src/server/iotcloud.cpp new file mode 100644 index 0000000..16bb28e --- /dev/null +++ b/src/server/iotcloud.cpp @@ -0,0 +1,110 @@ +#include +#include "fcgio.h" +#include "fcgi_stdio.h" +#include +#include +#define MAX_VARS 31 + +const char * query_str="QUERY_STRING"; +const char * uri_str="REQUEST_URI"; +const char * method_str="REQUEST_METHOD"; +const char * iotcloudroot_str="IOTCLOUD_ROOT"; + +using namespace std; + +struct iotquery { + const char * uri; + const char * query; + const char * method; + const char * iotcloudroot; +}; + +void parsequery(struct iotquery *, FCGX_Request *); +char * getdirectory(struct iotquery *); + +int main(void) { + // Backup the stdio streambufs + streambuf * cin_streambuf = cin.rdbuf(); + streambuf * cout_streambuf = cout.rdbuf(); + streambuf * cerr_streambuf = cerr.rdbuf(); + + FCGX_Request request; + + FCGX_Init(); + FCGX_InitRequest(&request, 0, 0); + + while (FCGX_Accept_r(&request) == 0) { + fcgi_streambuf cin_fcgi_streambuf(request.in); + fcgi_streambuf cout_fcgi_streambuf(request.out); + fcgi_streambuf cerr_fcgi_streambuf(request.err); + + cin.rdbuf(&cin_fcgi_streambuf); + cout.rdbuf(&cout_fcgi_streambuf); + cerr.rdbuf(&cerr_fcgi_streambuf); + + struct iotquery query; + parsequery(&query, &request); + char * directory = getdirectory(&query); + + cout << "Content-type: text/html\r\n" + << "\r\n" + << "\n" + << " \n" + << " Hello, World!\n" + << " \n" + << " \n" + << "

Hello, World!

\n" + << " \n"; + char c[80]; + + cout << uri_str << " " << query.uri << "\n"; + cout << query_str << " " << query.query << "\n"; + cout << method_str << " " << query.method << "\n"; + cout << iotcloudroot_str << " " << query.iotcloudroot << "\n"; + + + do { + cin.read(c, 80); + c[cin.gcount()]=0; + cout << "[" << c << "]"; + } while(!cin.eof()); + + + + + cout << "\n"; + // Note: the fcgi_streambuf destructor will auto flush + + if (directory != NULL) + free(directory); + } + + // restore stdio streambufs + cin.rdbuf(cin_streambuf); + cout.rdbuf(cout_streambuf); + cerr.rdbuf(cerr_streambuf); + + return 0; +} + + +void parsequery(struct iotquery * query, FCGX_Request * request) { + query->uri = FCGX_GetParam(uri_str, request->envp); + query->query = FCGX_GetParam(query_str, request->envp); + query->method = FCGX_GetParam(method_str, request->envp); + query->iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp); +} + +char * getdirectory(struct iotquery * query) { + char * split = strchr((char *)query->uri, '?'); + if (split == NULL) + return NULL; + int split_len = (int) (split-query->uri); + int rootdir_len = strlen(query->iotcloudroot); + int directory_len = split_len + rootdir_len + 1; + char * directory = (char *) malloc(directory_len); + memcpy(directory, query->iotcloudroot, rootdir_len); + memcpy(directory + rootdir_len, query->uri, split_len); + directory[directory_len]=0; + return directory; +} diff --git a/src/server/iotcloud.fcgi b/src/server/iotcloud.fcgi new file mode 100755 index 0000000000000000000000000000000000000000..f5f828e7dd38a84274d9684bdf6a338f2046d04e GIT binary patch literal 28912 zcmeHwdwf*Ywf{adc^ncloQdETDKYnM{(AWG2pohfgYE zO{t1ntyO8Ux7Xf!s~21C<=R$JENbiZV(nE*Z7;3Xo2c!@S}nD<-0yeqb7oE^nOpAf z_xb$(_k5aa2`f0n5SgB{H+c3^Xuy>Vv&j(S#QcG?aI|_C8K3WHz4XMeoUV%o&{A z^yHg&Ufb0C@9!PCYTb-~x%GY5JFotitGxN&TTAbq+_bG_(|16cG2DRyiYLfD7dZC> z_=OqpkqmMkL&YbO|8xfYo(%Y|4DwwW^f{h^{$D^pkv{iiD0fu``Fk_SxibU4CWHL_ z8SoEh(0^wJdJaz$)$11-@HH9a4`h)4a0dL=4Dug@{30=3h}m7B5TXn)!)Hyr`>ZYr z7n=CDAiogw>*grD%*5jriHFylaxDB2lRh2)c@Pwfd~sy5*CLhi%@RLF{AB7_d^XCb z-G⩔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 ZA`z_lhvVx+