adding missing files

master
Steffen Pohle 2 weeks ago
parent eeb3a42da8
commit 622643fabf

@ -0,0 +1,85 @@
#ifndef _UDPTCPNETWORK_WEBUTILS_H_
#define _UDPTCPNETWORK_WEBUTILS_H_
#include "UDPTCPNetwork.h"
#include <string>
#include <list>
/*********************************************************************************/
#define WEB_READ_BUFFER_SIZE 0x10000
enum { // request types
WEB_REQEST_UNSUPPORTED,
WEB_REQEST_GET,
WEB_REQEST_POST,
WEB_REQEST_MAX // not set
};
/***************************************************************************************
* WebHeaderLine
*/
class WebHeaderLine {
public:
WebHeaderLine() { Clear(); };
~WebHeaderLine() {};
void Clear () { parameter = ""; value = ""; };
std::string parameter;
std::string value;
};
/***************************************************************************************
* WebRequestBuffer
*/
class WebRequestBuffer {
private:
char *buffer_ptr;
int buffer_size; // allocated size
int buffer_len; // current len
int request_type;
std::string request;
std::string protocol_version;
std::list<WebHeaderLine> headerlines;
int buffer_pos_data;
public:
WebRequestBuffer();
~WebRequestBuffer();
int AddBuffer (char *b, int len);
int GetBuffer (char **dstptr, int *max);
bool RequestComplete();
void Clear() { buffer_len = 0; };
int GetType() { return request_type; };
std::string GetRequestRaw() { return request; };
std::string GetRequest();
std::string GetProtocolVersion() { return protocol_version; };
int GetRequestCmdObj(std::string *cmd, std::string *obj, JSONParse *jp);
std::string GetCookie(std::string name);
};
class WebServerClient {
private:
std::string ssl_key;
std::string ssl_cert;
TCP *tcp;
SSLSocket *ssl; // only set if SSL is used
char buffer[WEB_READ_BUFFER_SIZE];
public:
WebServerClient();
~WebServerClient();
// will handle the request and send the response
// on error reply with ERROR 500
int Accept (TCP *socket, std::string _ssl_key, std::string _ssl_cert);
int Accept (TCP *socket);
virtual int HandleRequest (WebRequestBuffer *req) { return 0; };
virtual int Loop();
};
#endif

@ -0,0 +1,97 @@
#include <unistd.h>
#include "UDPTCPNetwork.h"
#define DEFAULT_HTTP_PORT 2222
#define DEFAULT_HTTPS_PORT 2223
#define DEFAULT_CERT "./cert.pem"
#define DEFAULT_KEY "./privkey.pem"
#define MAX_CLIENTS 10
int running = 1;
class SimpleWebSrvClient: public WebServerClient {
public:
SimpleWebSrvClient () {};
~SimpleWebSrvClient () {};
};
int main (int argc, char **argv) {
list<SimpleWebSrvClient*> webclients;
TCP http;
TCP https;
std::string ssl_cert = DEFAULT_CERT;
std::string ssl_key = DEFAULT_KEY;
if (http.Listen(DEFAULT_HTTP_PORT) != 1) {
printf ("error on listen\n");
exit (1);
}
printf ("test server is running on http://localhost:%d\n", DEFAULT_HTTP_PORT);
if (https.Listen(DEFAULT_HTTPS_PORT) != 1) {
printf ("error on listen\n");
exit (1);
}
printf ("test server is running on https://localhost:%d\n", DEFAULT_HTTPS_PORT);
while (running == 1) {
SimpleWebSrvClient *webclient = NULL;
list<SimpleWebSrvClient*>::iterator wci;
TCP *tcpclient = NULL;
int ssl_enabled = 1;
int res;
//
// any new connection?
if ((tcpclient = https.Accept()) == NULL) {
ssl_enabled = 0;
tcpclient = http.Accept();
}
if (tcpclient) {
printf ("new %s connection from %s\n", ssl_enabled ? "HTTPS" : "HTTP", tcpclient->GetRemoteAddr().c_str());
if (webclients.size() > MAX_CLIENTS) {
printf ("max connections reached. closing connection.\n");
tcpclient->Close();
delete tcpclient;
continue;
}
webclient = new SimpleWebSrvClient();
if (ssl_enabled) res = webclient->Accept(tcpclient, ssl_key, ssl_cert);
else res = webclient->Accept(tcpclient);
if (res == 0) {
printf ("webclient could not connect. closing connection\n");
delete webclient;
delete tcpclient;
continue;
}
webclients.push_back(webclient);
printf ("add new connection to client list\n");
}
//
// go through all the clients and check for new requests
for (wci = webclients.begin(); wci != webclients.end(); wci++) {
webclient = *wci;
if (webclient->Loop() == 0) {
// error on loop, remove and delete webclient.
printf ("remove connection\n");
webclients.remove(webclient);
delete webclient;
wci = webclients.begin();
if (wci == webclients.end()) continue;
}
}
usleep (1000);
}
};

@ -0,0 +1,74 @@
#include "UDPTCPNetwork.h"
WebServerClient::WebServerClient () {
tcp = NULL;
ssl = NULL;
ssl_key = "";
ssl_cert = "";
};
WebServerClient::~WebServerClient () {
if (ssl) delete ssl;
ssl = NULL;
if (tcp) delete tcp;
tcp = NULL;
};
/// @brief
/// @param socket
/// @param _ssl_key
/// @param _ssl_cert
/// @return
int WebServerClient::Accept (TCP *socket, std::string _ssl_key, std::string _ssl_cert) {
if (ssl) delete ssl;
ssl = NULL;
if (tcp) delete tcp;
tcp = NULL;
tcp = socket;
ssl_key = _ssl_key;
ssl_cert = _ssl_cert;
ssl = new SSLSocket;
ssl->SetCertificat(ssl_cert, ssl_key);
ssl->Accept(tcp->GetSocket(),200);
return 1;
};
/// @brief
/// @param socket
/// @return
int WebServerClient::Accept (TCP *socket) {
if (ssl) delete ssl;
ssl = NULL;
if (tcp) delete tcp;
tcp = NULL;
tcp = socket;
return 1;
};
int WebServerClient::Loop () {
int len;
//
// read data
if (ssl) {
len = ssl->Read(buffer, WEB_READ_BUFFER_SIZE);
}
else {
len = tcp->ReadTimeout(buffer, WEB_READ_BUFFER_SIZE, 20);
}
if (len < 0) return 0;
if (len > 0) printf ("%s\n", buffer);
return 0;
};

@ -0,0 +1,209 @@
#include "UDPTCPNetwork.h"
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <list>
WebRequestBuffer::WebRequestBuffer () {
buffer_pos_data = -1;
buffer_size = 0;
buffer_ptr = NULL;
buffer_len = 0;
}
WebRequestBuffer::~WebRequestBuffer () {
if (buffer_ptr) {
free (buffer_ptr);
buffer_ptr = NULL;
buffer_size = 0;
buffer_len = 0;
buffer_pos_data = -1;
}
}
/// @brief add text to buffer
/// @param buffer
/// @param len
/// @return 0 on error, 1 on success
int WebRequestBuffer::AddBuffer (char *buffer, int len) {
//
// if needed allocate enought buffer, to the next kB
if (buffer_ptr == NULL || buffer_size <= buffer_len+len) {
buffer_size = 1024 * (1 + ((buffer_len + len) / 1024));
if (buffer_ptr == NULL) buffer_ptr = (char*) malloc (buffer_size);
else buffer_ptr = (char*) realloc (buffer_ptr, buffer_size);
}
if (buffer_ptr == NULL || buffer_size < buffer_len+len) {
fprintf (stderr, "%s:%d could not allocate enought memory. buffer_size:%d buffer_len+len:%d \n",
__FILE__, __LINE__, buffer_size, buffer_len + len);
return 0;
}
memcpy (buffer_ptr + buffer_len, buffer, len);
buffer_len += len;
buffer_ptr[buffer_len] = 0;
debug("buffer:'%s'\n", buffer_ptr);
return 1;
};
/// @brief copy the curren buffer to the dstination, resize destination if needed
/// @param dstptr pointer to the destination pointer, in case of a reallocation
/// @param max pointer to current allocated size of the pointer
/// @return > 0 - len in bytes of the buffer, = -1 error occured
int WebRequestBuffer::GetBuffer (char **dstptr, int *max) {
// check: valid pointers
if (dstptr == NULL || max == NULL) {
fprintf (stderr, "%s:%d not pointer to buffer or not pointer to a lenght set\n",
__FILE__, __LINE__);
return -1;
}
// check: size and reallocate
if (*max < buffer_len || *max < 0) {
char *tb = (char*) realloc (*dstptr, buffer_len);
*dstptr = tb;
*max = buffer_size;
}
// check: could alloc memory
if (*dstptr == NULL) {
fprintf (stderr, "%s:%d no destination pointer set\n",
__FILE__, __LINE__);
return -1;
}
memcpy (*dstptr, buffer_ptr, buffer_len);
return buffer_len;
};
/// @brief Check if the Request is Complete. In this case the request_type and the request can
/// @brief be read with GetRequest and GetType(). For a new request Clear() must be called.
/// @return 0 . not complete, 1 . request complete
bool WebRequestBuffer::RequestComplete() {
int i = 0;
int element = 0; // 0. Parameter 1. Value 2. Value n
int line = 0;
WebHeaderLine hl;
request = "";
protocol_version = "HTTP/1.0";
request_type = WEB_REQEST_UNSUPPORTED;
buffer_pos_data = -1;
if (buffer_ptr == NULL) return false;
hl.Clear();
for (i = 0, element = 0; i < buffer_len; i++) {
//
// check if line is complete
if (buffer_ptr[i] == '\n') {
if (hl.value.length() == 0 && hl.parameter.length() == 0) {
buffer_pos_data = i+1; // save position of first data byte
return true;
}
// the first line holds the request type and the location/path.
if (line == 0) {
hl.parameter = string_to_upper(hl.parameter);
if (hl.parameter.compare("GET") == 0) request_type = WEB_REQEST_GET;
if (hl.parameter.compare("POST") == 0) request_type = WEB_REQEST_POST;
request = string_to_lower(hl.value);
}
headerlines.push_back(hl);
hl.Clear();
element = 0;
line++;
continue;
}
// ignore some elements -> maybe it is not needed
else if (strchr ("\t ", buffer_ptr[i]) != NULL) {
element++;
if (element > 1) hl.value += buffer_ptr[i];
}
// ignore last CR
else if (buffer_ptr[i] != '\r') {
if (element == 0) hl.parameter += buffer_ptr[i];
// first line ignore protocol version
else if (line > 0 || element == 1) hl.value += buffer_ptr[i];
}
}
return false;
}
/// @brief get some information about the complete request
/// @param cmd propably get or set command
/// @param obj object related with this command
/// @param jp some json data
/// @return
int WebRequestBuffer::GetRequestCmdObj(std::string *cmd, std::string *obj, JSONParse *jp) {
std::string rq = GetRequest();
int secslash = 0;
if (cmd == NULL || obj == NULL || jp == NULL)
errorexit ("Fatal Error cmd:%p obj:%p jp:%p none of these should be NULL\n",
cmd, obj, jp);
secslash = rq.find ('/', 1);
*cmd = rq.substr(1, secslash-1);
*obj = rq.substr(secslash+1, std::string::npos);
if (buffer_pos_data > 0) (*jp).Set(buffer_ptr+buffer_pos_data);
else (*jp).Clear();
return 1;
}
std::string WebRequestBuffer::GetRequest() {
std::string rq = "";
char lastc = 0;
char c = 0;
//
// filter out /. .. ./
for (int i = 0; i < request.length(); i++) {
c = request[i];
if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || c == '/' || c == '.' || c == '-' ) &&
(!((c == '.' || c == '/' ) && (lastc == '/' || lastc == '.')))) {
rq += c;
lastc = c;
}
}
return rq;
}
std::string WebRequestBuffer::GetCookie(std::string name) {
std::list<WebHeaderLine>::iterator il;
std::size_t i;
for (il = headerlines.begin(); il != headerlines.end(); il++) {
if (string_to_lower(il->parameter).compare("cookie:") == 0) {
i = il->value.find('=');
if (i == std::string::npos) continue;
if (il->value.substr(0, i).compare(name) == 0)
return il->value.substr(i+1, std::string::npos);
}
}
return "";
};
Loading…
Cancel
Save