mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-31 01:11:12 +02:00
yWeb 2.8.a.4
- updated nhttpd - Code clean up - changes to nhttpd.conf - some changes for logo display git-svn-id: file:///home/bas/coolstream_public_svn/THIRDPARTY/applications/neutrino-experimental@416 e54a6e83-5905-42d5-8d5c-058d10e6a962
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
//=============================================================================
|
||||
|
||||
// c
|
||||
#include <cstdio> // printf prototype.
|
||||
#include <cstdlib> // calloc and free prototypes.
|
||||
#include <cstring> // str* and memset prototypes.
|
||||
#include <cstdio> // printf prototype.
|
||||
#include <cstdlib> // calloc and free prototypes.
|
||||
#include <cstring> // str* and memset prototypes.
|
||||
#include <cstdarg>
|
||||
|
||||
// yhttpd
|
||||
@@ -21,10 +21,11 @@
|
||||
//-------------------------------------------------------------------------
|
||||
// Check and set integer inside boundaries (min, max)
|
||||
//-------------------------------------------------------------------------
|
||||
int minmax(int value,int min, int max)
|
||||
{
|
||||
if(value < min) return min;
|
||||
if(value > max) return max;
|
||||
int minmax(int value, int min, int max) {
|
||||
if (value < min)
|
||||
return min;
|
||||
if (value > max)
|
||||
return max;
|
||||
return value;
|
||||
}
|
||||
//=============================================================================
|
||||
@@ -33,15 +34,14 @@ int minmax(int value,int min, int max)
|
||||
//-------------------------------------------------------------------------
|
||||
// Check and set Date/Time (tm*) inside boundaries
|
||||
//-------------------------------------------------------------------------
|
||||
void correctTime(struct tm *zt)
|
||||
{
|
||||
void correctTime(struct tm *zt) {
|
||||
|
||||
zt->tm_year = minmax(zt->tm_year,0,129);
|
||||
zt->tm_mon = minmax(zt->tm_mon,0,11);
|
||||
zt->tm_mday = minmax(zt->tm_mday,1,31); //-> eine etwas laxe pruefung, aber mktime biegt das wieder grade
|
||||
zt->tm_hour = minmax(zt->tm_hour,0,23);
|
||||
zt->tm_min = minmax(zt->tm_min,0,59);
|
||||
zt->tm_sec = minmax(zt->tm_sec,0,59);
|
||||
zt->tm_year = minmax(zt->tm_year, 0, 129);
|
||||
zt->tm_mon = minmax(zt->tm_mon, 0, 11);
|
||||
zt->tm_mday = minmax(zt->tm_mday, 1, 31); //-> eine etwas laxe pruefung, aber mktime biegt das wieder grade
|
||||
zt->tm_hour = minmax(zt->tm_hour, 0, 23);
|
||||
zt->tm_min = minmax(zt->tm_min, 0, 59);
|
||||
zt->tm_sec = minmax(zt->tm_sec, 0, 59);
|
||||
}
|
||||
//=============================================================================
|
||||
// Strings
|
||||
@@ -49,23 +49,20 @@ void correctTime(struct tm *zt)
|
||||
//-------------------------------------------------------------------------
|
||||
// Integer to Hexadecimal-String
|
||||
//-------------------------------------------------------------------------
|
||||
std::string itoh(unsigned int conv)
|
||||
{
|
||||
return string_printf("0x%06x",conv);
|
||||
std::string itoh(unsigned int conv) {
|
||||
return string_printf("0x%06x", conv);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// Integer to String
|
||||
//-------------------------------------------------------------------------
|
||||
std::string itoa(unsigned int conv)
|
||||
{
|
||||
return string_printf("%u",conv);
|
||||
std::string itoa(unsigned int conv) {
|
||||
return string_printf("%u", conv);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// convert timer_t to "<hour>:<minutes>" String
|
||||
//-------------------------------------------------------------------------
|
||||
std::string timeString(time_t time)
|
||||
{
|
||||
char tmp[7]={'\0'};
|
||||
std::string timeString(time_t time) {
|
||||
char tmp[7] = { '\0' };
|
||||
struct tm *tm = localtime(&time);
|
||||
if (strftime(tmp, 6, "%H:%M", tm))
|
||||
return std::string(tmp);
|
||||
@@ -77,13 +74,11 @@ std::string timeString(time_t time)
|
||||
// max length up to bufferlen -> then snip
|
||||
//-------------------------------------------------------------------------
|
||||
#define bufferlen 4*1024
|
||||
std::string string_printf(const char *fmt, ...)
|
||||
{
|
||||
std::string string_printf(const char *fmt, ...) {
|
||||
char buffer[bufferlen];
|
||||
va_list arglist;
|
||||
va_start( arglist, fmt );
|
||||
if(arglist)
|
||||
vsnprintf( buffer, bufferlen, fmt, arglist );
|
||||
va_start(arglist, fmt);
|
||||
vsnprintf(buffer, bufferlen, fmt, arglist);
|
||||
va_end(arglist);
|
||||
return std::string(buffer);
|
||||
}
|
||||
@@ -91,16 +86,13 @@ std::string string_printf(const char *fmt, ...)
|
||||
// ySplitString: spit string "str" in two strings "left" and "right" at
|
||||
// one of the chars in "delimiter" returns true if delimiter found
|
||||
//-------------------------------------------------------------------------
|
||||
bool ySplitString(std::string str, std::string delimiter, std::string& left, std::string& right)
|
||||
{
|
||||
bool ySplitString(std::string str, std::string delimiter, std::string& left,
|
||||
std::string& right) {
|
||||
std::string::size_type pos;
|
||||
if ((pos = str.find_first_of(delimiter)) != std::string::npos)
|
||||
{
|
||||
if ((pos = str.find_first_of(delimiter)) != std::string::npos) {
|
||||
left = str.substr(0, pos);
|
||||
right = str.substr(pos + 1, str.length() - (pos + 1 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
right = str.substr(pos + 1, str.length() - (pos + 1));
|
||||
} else {
|
||||
left = str; //default if not found
|
||||
right = "";
|
||||
}
|
||||
@@ -110,16 +102,14 @@ bool ySplitString(std::string str, std::string delimiter, std::string& left, std
|
||||
// ySplitString: spit string "str" in two strings "left" and "right" at
|
||||
// one of the chars in "delimiter" returns true if delimiter found
|
||||
//-------------------------------------------------------------------------
|
||||
bool ySplitStringExact(std::string str, std::string delimiter, std::string& left, std::string& right)
|
||||
{
|
||||
bool ySplitStringExact(std::string str, std::string delimiter,
|
||||
std::string& left, std::string& right) {
|
||||
std::string::size_type pos;
|
||||
if ((pos = str.find(delimiter)) != std::string::npos)
|
||||
{
|
||||
if ((pos = str.find(delimiter)) != std::string::npos) {
|
||||
left = str.substr(0, pos);
|
||||
right = str.substr(pos + delimiter.length(), str.length() - (pos + delimiter.length() ));
|
||||
}
|
||||
else
|
||||
{
|
||||
right = str.substr(pos + delimiter.length(), str.length() - (pos
|
||||
+ delimiter.length()));
|
||||
} else {
|
||||
left = str; //default if not found
|
||||
right = "";
|
||||
}
|
||||
@@ -129,16 +119,13 @@ bool ySplitStringExact(std::string str, std::string delimiter, std::string& left
|
||||
// ySplitStringRight: spit string "str" in two strings "left" and "right" at
|
||||
// one of the chars in "delimiter" returns true if delimiter found
|
||||
//-------------------------------------------------------------------------
|
||||
bool ySplitStringLast(std::string str, std::string delimiter, std::string& left, std::string& right)
|
||||
{
|
||||
bool ySplitStringLast(std::string str, std::string delimiter,
|
||||
std::string& left, std::string& right) {
|
||||
std::string::size_type pos;
|
||||
if ((pos = str.find_last_of(delimiter)) != std::string::npos)
|
||||
{
|
||||
if ((pos = str.find_last_of(delimiter)) != std::string::npos) {
|
||||
left = str.substr(0, pos);
|
||||
right = str.substr(pos + 1, str.length() - (pos + 1 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
right = str.substr(pos + 1, str.length() - (pos + 1));
|
||||
} else {
|
||||
left = str; //default if not found
|
||||
right = "";
|
||||
}
|
||||
@@ -147,33 +134,29 @@ bool ySplitStringLast(std::string str, std::string delimiter, std::string& left,
|
||||
//-------------------------------------------------------------------------
|
||||
// ySplitStringVector: spit string "str" and build vector of strings
|
||||
//-------------------------------------------------------------------------
|
||||
CStringArray ySplitStringVector(std::string str, std::string delimiter)
|
||||
{
|
||||
CStringArray ySplitStringVector(std::string str, std::string delimiter) {
|
||||
std::string left, right, rest;
|
||||
bool found;
|
||||
CStringArray split;
|
||||
rest = str;
|
||||
do
|
||||
{
|
||||
do {
|
||||
found = ySplitString(rest, delimiter, left, right);
|
||||
split.push_back(left);
|
||||
rest = right;
|
||||
}
|
||||
while(found);
|
||||
} while (found);
|
||||
return split;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// trim whitespaces
|
||||
//-------------------------------------------------------------------------
|
||||
std::string trim(std::string const& source, char const* delims)
|
||||
{
|
||||
std::string trim(std::string const& source, char const* delims) {
|
||||
std::string result(source);
|
||||
std::string::size_type index = result.find_last_not_of(delims);
|
||||
if(index != std::string::npos)
|
||||
if (index != std::string::npos)
|
||||
result.erase(++index);
|
||||
|
||||
index = result.find_first_not_of(delims);
|
||||
if(index != std::string::npos)
|
||||
if (index != std::string::npos)
|
||||
result.erase(0, index);
|
||||
else
|
||||
result.erase();
|
||||
@@ -182,53 +165,45 @@ std::string trim(std::string const& source, char const* delims)
|
||||
//-------------------------------------------------------------------------
|
||||
// replace all occurrences find_what
|
||||
//-------------------------------------------------------------------------
|
||||
void replace(std::string &str, const std::string &find_what, const std::string &replace_with)
|
||||
{
|
||||
std::string::size_type pos=0;
|
||||
while((pos=str.find(find_what, pos))!=std::string::npos)
|
||||
{
|
||||
void replace(std::string &str, const std::string &find_what,
|
||||
const std::string &replace_with) {
|
||||
std::string::size_type pos = 0;
|
||||
while ((pos = str.find(find_what, pos)) != std::string::npos) {
|
||||
str.erase(pos, find_what.length());
|
||||
str.insert(pos, replace_with);
|
||||
pos+=replace_with.length();
|
||||
pos += replace_with.length();
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// equal-function for case insensitive compare
|
||||
//-------------------------------------------------------------------------
|
||||
bool nocase_compare (char c1, char c2)
|
||||
{
|
||||
bool nocase_compare(char c1, char c2) {
|
||||
return toupper(c1) == toupper(c2);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Decode URLEncoded std::string
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string decodeString(std::string encodedString)
|
||||
{
|
||||
std::string decodeString(std::string encodedString) {
|
||||
const char *string = encodedString.c_str();
|
||||
unsigned int count=0;
|
||||
char hex[3]={'\0'};
|
||||
unsigned int count = 0;
|
||||
char hex[3] = { '\0' };
|
||||
unsigned long iStr;
|
||||
std::string result = "";
|
||||
count = 0;
|
||||
|
||||
while(count<encodedString.length()) /* use the null character as a loop terminator */
|
||||
while (count < encodedString.length()) /* use the null character as a loop terminator */
|
||||
{
|
||||
if(string[count] == '%' && count+2 <encodedString.length())
|
||||
{
|
||||
hex[0]=string[count+1];
|
||||
hex[1]=string[count+2];
|
||||
hex[2]='\0';
|
||||
iStr = strtoul(hex,NULL,16); /* convert to Hex char */
|
||||
result += (char)iStr;
|
||||
if (string[count] == '%' && count + 2 < encodedString.length()) {
|
||||
hex[0] = string[count + 1];
|
||||
hex[1] = string[count + 2];
|
||||
hex[2] = '\0';
|
||||
iStr = strtoul(hex, NULL, 16); /* convert to Hex char */
|
||||
result += (char) iStr;
|
||||
count += 3;
|
||||
}
|
||||
else if(string[count] == '+')
|
||||
{
|
||||
} else if (string[count] == '+') {
|
||||
result += ' ';
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
result += string[count];
|
||||
count++;
|
||||
}
|
||||
@@ -238,29 +213,27 @@ std::string decodeString(std::string encodedString)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Encode URLEncoded std::string
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string encodeString(std::string decodedString)
|
||||
{
|
||||
unsigned int len = sizeof(char) * decodedString.length()*5 + 1;
|
||||
std::string result( len, '\0' );
|
||||
char *newString = (char *)result.c_str();
|
||||
char *dstring = (char *)decodedString.c_str();
|
||||
std::string encodeString(std::string decodedString) {
|
||||
unsigned int len = sizeof(char) * decodedString.length() * 5 + 1;
|
||||
std::string result(len, '\0');
|
||||
char *newString = (char *) result.c_str();
|
||||
char *dstring = (char *) decodedString.c_str();
|
||||
char one_char;
|
||||
if(len == result.length()) // got memory needed
|
||||
if (len == result.length()) // got memory needed
|
||||
{
|
||||
while((one_char = *dstring++)) /* use the null character as a loop terminator */
|
||||
while ((one_char = *dstring++)) /* use the null character as a loop terminator */
|
||||
{
|
||||
if(isalnum(one_char))
|
||||
if (isalnum(one_char))
|
||||
*newString++ = one_char;
|
||||
else
|
||||
newString += sprintf(newString, "&#%d;", (unsigned char) one_char);
|
||||
newString += sprintf(newString, "&#%d;",
|
||||
(unsigned char) one_char);
|
||||
}
|
||||
|
||||
*newString='\0'; /* when done copying the string,need to terminate w/ null char */
|
||||
result.resize((unsigned int)(newString - result.c_str()), '\0');
|
||||
*newString = '\0'; /* when done copying the string,need to terminate w/ null char */
|
||||
result.resize((unsigned int) (newString - result.c_str()), '\0');
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -268,9 +241,8 @@ std::string encodeString(std::string decodedString)
|
||||
//-----------------------------------------------------------------------------
|
||||
// returns string in lower case
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string string_tolower(std::string str)
|
||||
{
|
||||
for(unsigned int i = 0; i < str.length(); i++)
|
||||
std::string string_tolower(std::string str) {
|
||||
for (unsigned int i = 0; i < str.length(); i++)
|
||||
str[i] = tolower(str[i]);
|
||||
return str;
|
||||
}
|
||||
@@ -278,16 +250,14 @@ std::string string_tolower(std::string str)
|
||||
//-----------------------------------------------------------------------------
|
||||
// write string to a file
|
||||
//-----------------------------------------------------------------------------
|
||||
bool write_to_file(std::string filename, std::string content)
|
||||
{
|
||||
bool write_to_file(std::string filename, std::string content) {
|
||||
FILE *fd = NULL;
|
||||
if((fd = fopen(filename.c_str(),"w")) != NULL) // open file
|
||||
if ((fd = fopen(filename.c_str(), "w")) != NULL) // open file
|
||||
{
|
||||
fwrite(content.c_str(), content.length(), 1, fd);
|
||||
fflush(fd); // flush and close file
|
||||
fflush(fd); // flush and close file
|
||||
fclose(fd);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
@@ -21,46 +21,43 @@ long CWebserverConnection::GConnectionNumber = 0;
|
||||
//=============================================================================
|
||||
// Constructor & Destructor & Initialization
|
||||
//=============================================================================
|
||||
CWebserverConnection::CWebserverConnection(CWebserver *pWebserver)
|
||||
{
|
||||
Webserver = pWebserver;
|
||||
Request.Webserver = pWebserver;
|
||||
Request.Connection = this;
|
||||
Response.Webserver = pWebserver;
|
||||
Response.Connection = this;
|
||||
Method = M_UNKNOWN;
|
||||
HttpStatus = 0;
|
||||
RequestCanceled = false;
|
||||
CWebserverConnection::CWebserverConnection(CWebserver *pWebserver) {
|
||||
Webserver = pWebserver;
|
||||
Request.Webserver = pWebserver;
|
||||
Request.Connection = this;
|
||||
Response.Webserver = pWebserver;
|
||||
Response.Connection = this;
|
||||
Method = M_UNKNOWN;
|
||||
HttpStatus = 0;
|
||||
RequestCanceled = false;
|
||||
#ifdef Y_CONFIG_FEATURE_KEEP_ALIVE
|
||||
keep_alive = true;
|
||||
keep_alive = true;
|
||||
#else
|
||||
keep_alive = false;
|
||||
keep_alive = false;
|
||||
#endif
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
CWebserverConnection::CWebserverConnection()
|
||||
{
|
||||
// aprintf("test CWebserverConnection::CWebserverConnection()\n");
|
||||
CWebserverConnection::CWebserverConnection() {
|
||||
// aprintf("test CWebserverConnection::CWebserverConnection()\n");
|
||||
ConnectionNumber = ++GConnectionNumber;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
CWebserverConnection::~CWebserverConnection(void)
|
||||
{
|
||||
CWebserverConnection::~CWebserverConnection(void) {
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// End The Connection. Request and Response allready handled.
|
||||
// do "after done" work, like create a www-Log entry.
|
||||
// Use "Hooks_EndConnection()" Handler to write own Hooks.
|
||||
//-------------------------------------------------------------------------
|
||||
void CWebserverConnection::EndConnection()
|
||||
{
|
||||
HookHandler.HookVarList["enlapsed_request"] = itoa(enlapsed_request/1000);
|
||||
HookHandler.HookVarList["enlapsed_response"] = itoa(enlapsed_response/1000);
|
||||
HookHandler.Hooks_EndConnection(); // Handle Hooks
|
||||
if(RequestCanceled) // Canceled
|
||||
void CWebserverConnection::EndConnection() {
|
||||
HookHandler.HookVarList["enlapsed_request"] = itoa(enlapsed_request / 1000);
|
||||
HookHandler.HookVarList["enlapsed_response"] = itoa(enlapsed_response
|
||||
/ 1000);
|
||||
HookHandler.Hooks_EndConnection(); // Handle Hooks
|
||||
if (RequestCanceled) // Canceled
|
||||
keep_alive = false;
|
||||
RequestCanceled = true;
|
||||
// sock->Flush();
|
||||
// sock->Flush();
|
||||
#ifndef Y_CONFIG_FEATURE_KEEP_ALIVE
|
||||
sock->close();
|
||||
#endif
|
||||
@@ -69,24 +66,25 @@ void CWebserverConnection::EndConnection()
|
||||
// Main
|
||||
// Handle the Request, Handle (Send) Response), End the Connection
|
||||
//-------------------------------------------------------------------------
|
||||
void CWebserverConnection::HandleConnection()
|
||||
{
|
||||
void CWebserverConnection::HandleConnection() {
|
||||
gettimeofday(&tv_connection_start, &tz_connection_start);
|
||||
|
||||
// get the request
|
||||
if (Request.HandleRequest())
|
||||
{
|
||||
if (Request.HandleRequest()) {
|
||||
// determine time from Connection creation until now
|
||||
gettimeofday(&tv_connection_Response_start, &tz_connection_Response_start);
|
||||
enlapsed_request = ((tv_connection_Response_start.tv_sec - tv_connection_start.tv_sec) * 1000000
|
||||
+ (tv_connection_Response_start.tv_usec - tv_connection_start.tv_usec));
|
||||
gettimeofday(&tv_connection_Response_start,
|
||||
&tz_connection_Response_start);
|
||||
enlapsed_request = ((tv_connection_Response_start.tv_sec
|
||||
- tv_connection_start.tv_sec) * 1000000
|
||||
+ (tv_connection_Response_start.tv_usec
|
||||
- tv_connection_start.tv_usec));
|
||||
|
||||
// Keep-Alive checking
|
||||
#ifdef Y_CONFIG_FEATURE_KEEP_ALIVE
|
||||
if(string_tolower(Request.HeaderList["Connection"]) == "close"
|
||||
|| (httprotocol != "HTTP/1.1" && string_tolower(Request.HeaderList["Connection"]) != "keep-alive")
|
||||
|| !Webserver->CheckKeepAliveAllowedByIP(sock->get_client_ip()))
|
||||
keep_alive = false;
|
||||
if(string_tolower(Request.HeaderList["Connection"]) == "close"
|
||||
|| (httprotocol != "HTTP/1.1" && string_tolower(Request.HeaderList["Connection"]) != "keep-alive")
|
||||
|| !Webserver->CheckKeepAliveAllowedByIP(sock->get_client_ip()))
|
||||
keep_alive = false;
|
||||
#else
|
||||
keep_alive = false;
|
||||
#endif
|
||||
@@ -95,40 +93,39 @@ void CWebserverConnection::HandleConnection()
|
||||
|
||||
// determine time for SendResponse
|
||||
gettimeofday(&tv_connection_Response_end, &tz_connection_Response_end);
|
||||
enlapsed_response = ((tv_connection_Response_end.tv_sec - tv_connection_Response_start.tv_sec) * 1000000
|
||||
+ (tv_connection_Response_end.tv_usec - tv_connection_Response_start.tv_usec));
|
||||
enlapsed_response = ((tv_connection_Response_end.tv_sec
|
||||
- tv_connection_Response_start.tv_sec) * 1000000
|
||||
+ (tv_connection_Response_end.tv_usec
|
||||
- tv_connection_Response_start.tv_usec));
|
||||
|
||||
// print production times
|
||||
log_level_printf(1,"enlapsed time request:%ld response:%ld url:%s\n",
|
||||
enlapsed_request, enlapsed_response, (Request.UrlData["fullurl"]).c_str());
|
||||
log_level_printf(1, "enlapsed time request:%ld response:%ld url:%s\n",
|
||||
enlapsed_request, enlapsed_response,
|
||||
(Request.UrlData["fullurl"]).c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
RequestCanceled = true;
|
||||
keep_alive = false; // close this connection socket
|
||||
// dperror("Error while parsing request\n");
|
||||
log_level_printf(1,"request canceled: %s\n", strerror(errno));
|
||||
keep_alive = false; // close this connection socket
|
||||
// dperror("Error while parsing request\n");
|
||||
log_level_printf(1, "request canceled: %s\n", strerror(errno));
|
||||
}
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void CWebserverConnection::ShowEnlapsedRequest(char *text)
|
||||
{
|
||||
void CWebserverConnection::ShowEnlapsedRequest(char *text) {
|
||||
|
||||
long enlapsed = GetEnlapsedRequestTime() / 1000;
|
||||
log_level_printf(1,"enlapsed-f-start (%s) t:%ld url:%s\n",
|
||||
text, enlapsed, (Request.UrlData["fullurl"]).c_str());
|
||||
long enlapsed = GetEnlapsedRequestTime() / 1000;
|
||||
log_level_printf(1, "enlapsed-f-start (%s) t:%ld url:%s\n", text, enlapsed,
|
||||
(Request.UrlData["fullurl"]).c_str());
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// Time from creation of socket until now in microseconds!
|
||||
//-------------------------------------------------------------------------
|
||||
long CWebserverConnection::GetEnlapsedRequestTime()
|
||||
{
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
long CWebserverConnection::GetEnlapsedRequestTime() {
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
return ((tv_now.tv_sec - tv_connection_start.tv_sec) * 1000000
|
||||
+ (tv_now.tv_usec - tv_connection_start.tv_usec));
|
||||
}
|
||||
@@ -136,11 +133,10 @@ long CWebserverConnection::GetEnlapsedRequestTime()
|
||||
//-------------------------------------------------------------------------
|
||||
// Time from beginning of response until now in microseconds!
|
||||
//-------------------------------------------------------------------------
|
||||
long CWebserverConnection::GetEnlapsedResponseTime()
|
||||
{
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
long CWebserverConnection::GetEnlapsedResponseTime() {
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
return ((tv_now.tv_sec - tv_connection_Response_start.tv_sec) * 1000000
|
||||
+ (tv_now.tv_usec - tv_connection_Response_start.tv_usec));
|
||||
}
|
||||
|
@@ -25,22 +25,22 @@ THookList CyhookHandler::HookList;
|
||||
// Hook Dispatcher for Session Hooks
|
||||
// Execute every Hook in HookList until State change != HANDLED_NONE
|
||||
//-----------------------------------------------------------------------------
|
||||
THandleStatus CyhookHandler::Hooks_SendResponse()
|
||||
{
|
||||
log_level_printf(4,"Response Hook-List Start\n");
|
||||
THandleStatus CyhookHandler::Hooks_SendResponse() {
|
||||
log_level_printf(4, "Response Hook-List Start\n");
|
||||
THandleStatus _status = HANDLED_NONE;
|
||||
THookList::iterator i = HookList.begin();
|
||||
for ( ; i!= HookList.end(); i++ )
|
||||
{
|
||||
log_level_printf(4,"Response Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
for (; i != HookList.end(); i++) {
|
||||
log_level_printf(4, "Response Hook-List (%s) Start\n",
|
||||
((*i)->getHookName()).c_str());
|
||||
// response Hook
|
||||
_status = (*i)->Hook_SendResponse(this);
|
||||
log_level_printf(4,"Response Hook-List (%s) End. Status (%d)\n", ((*i)->getHookName()).c_str(), status);
|
||||
if((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
log_level_printf(4, "Response Hook-List (%s) End. Status (%d)\n",
|
||||
((*i)->getHookName()).c_str(), status);
|
||||
if ((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
break;
|
||||
}
|
||||
log_level_printf(4,"Response Hook-List End\n");
|
||||
log_level_printf(8,"Response Hook-List Result:\n%s\n", yresult.c_str());
|
||||
log_level_printf(4, "Response Hook-List End\n");
|
||||
log_level_printf(8, "Response Hook-List Result:\n%s\n", yresult.c_str());
|
||||
status = _status;
|
||||
return _status;
|
||||
}
|
||||
@@ -48,22 +48,25 @@ THandleStatus CyhookHandler::Hooks_SendResponse()
|
||||
// Hook Dispatcher for Session Hooks
|
||||
// Execute every Hook in HookList until State change != HANDLED_NONE
|
||||
//-----------------------------------------------------------------------------
|
||||
THandleStatus CyhookHandler::Hooks_PrepareResponse()
|
||||
{
|
||||
log_level_printf(4,"PrepareResponse Hook-List Start\n");
|
||||
THandleStatus CyhookHandler::Hooks_PrepareResponse() {
|
||||
log_level_printf(4, "PrepareResponse Hook-List Start\n");
|
||||
THandleStatus _status = HANDLED_NONE;
|
||||
THookList::iterator i = HookList.begin();
|
||||
for ( ; i!= HookList.end(); i++ )
|
||||
{
|
||||
log_level_printf(4,"PrepareResponse Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
for (; i != HookList.end(); i++) {
|
||||
log_level_printf(4, "PrepareResponse Hook-List (%s) Start\n",
|
||||
((*i)->getHookName()).c_str());
|
||||
// response Hook
|
||||
_status = (*i)->Hook_PrepareResponse(this);
|
||||
log_level_printf(4,"PrepareResponse Hook-List (%s) End. Status (%d) HTTP Status (%d)\n", ((*i)->getHookName()).c_str(), status, httpStatus);
|
||||
if((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
log_level_printf(
|
||||
4,
|
||||
"PrepareResponse Hook-List (%s) End. Status (%d) HTTP Status (%d)\n",
|
||||
((*i)->getHookName()).c_str(), status, httpStatus);
|
||||
if ((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
break;
|
||||
}
|
||||
log_level_printf(4,"PrepareResponse Hook-List End\n");
|
||||
log_level_printf(8,"PrepareResponse Hook-List Result:\n%s\n", yresult.c_str());
|
||||
log_level_printf(4, "PrepareResponse Hook-List End\n");
|
||||
log_level_printf(8, "PrepareResponse Hook-List Result:\n%s\n",
|
||||
yresult.c_str());
|
||||
status = _status;
|
||||
return _status;
|
||||
}
|
||||
@@ -73,83 +76,86 @@ THandleStatus CyhookHandler::Hooks_PrepareResponse()
|
||||
// Execute every Hook in HookList until State change != HANDLED_NONE and
|
||||
// != HANDLED_CONTINUE
|
||||
//-----------------------------------------------------------------------------
|
||||
THandleStatus CyhookHandler::Hooks_ReadConfig(CConfigFile *Config, CStringList &ConfigList)
|
||||
{
|
||||
log_level_printf(4,"ReadConfig Hook-List Start\n");
|
||||
THandleStatus CyhookHandler::Hooks_ReadConfig(CConfigFile *Config,
|
||||
CStringList &ConfigList) {
|
||||
log_level_printf(4, "ReadConfig Hook-List Start\n");
|
||||
THandleStatus _status = HANDLED_NONE;
|
||||
THookList::iterator i = HookList.begin();
|
||||
for ( ; i!= HookList.end(); i++ )
|
||||
{
|
||||
// log_level_printf(4,"ReadConfig Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
for (; i != HookList.end(); i++) {
|
||||
// log_level_printf(4,"ReadConfig Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
// response Hook
|
||||
_status = (*i)->Hook_ReadConfig(Config, ConfigList);
|
||||
log_level_printf(4,"ReadConfig Hook-List (%s) Status (%d)\n", ((*i)->getHookName()).c_str(), _status);
|
||||
if((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
log_level_printf(4, "ReadConfig Hook-List (%s) Status (%d)\n",
|
||||
((*i)->getHookName()).c_str(), _status);
|
||||
if ((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
break;
|
||||
}
|
||||
log_level_printf(4,"ReadConfig Hook-List End\n");
|
||||
log_level_printf(4, "ReadConfig Hook-List End\n");
|
||||
return _status;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hook Dispatcher for EndConnection
|
||||
//-----------------------------------------------------------------------------
|
||||
THandleStatus CyhookHandler::Hooks_EndConnection()
|
||||
{
|
||||
log_level_printf(4,"EndConnection Hook-List Start\n");
|
||||
THandleStatus CyhookHandler::Hooks_EndConnection() {
|
||||
log_level_printf(4, "EndConnection Hook-List Start\n");
|
||||
THandleStatus _status = HANDLED_NONE;
|
||||
THookList::iterator i = HookList.begin();
|
||||
for ( ; i!= HookList.end(); i++ )
|
||||
{
|
||||
log_level_printf(4,"EndConnection Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
for (; i != HookList.end(); i++) {
|
||||
log_level_printf(4, "EndConnection Hook-List (%s) Start\n",
|
||||
((*i)->getHookName()).c_str());
|
||||
// response Hook
|
||||
_status = (*i)->Hook_EndConnection(this);
|
||||
log_level_printf(4,"EndConnection Hook-List (%s) End. Status (%d)\n", ((*i)->getHookName()).c_str(), _status);
|
||||
if((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
log_level_printf(4, "EndConnection Hook-List (%s) End. Status (%d)\n",
|
||||
((*i)->getHookName()).c_str(), _status);
|
||||
if ((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
break;
|
||||
}
|
||||
log_level_printf(4,"EndConnection Hook-List End\n");
|
||||
log_level_printf(4, "EndConnection Hook-List End\n");
|
||||
status = _status;
|
||||
return _status;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hook Dispatcher for UploadSetFilename
|
||||
//-----------------------------------------------------------------------------
|
||||
THandleStatus CyhookHandler::Hooks_UploadSetFilename(std::string &Filename)
|
||||
{
|
||||
log_level_printf(4,"UploadSetFilename Hook-List Start. Filename:(%s)\n", Filename.c_str());
|
||||
THandleStatus CyhookHandler::Hooks_UploadSetFilename(std::string &Filename) {
|
||||
log_level_printf(4, "UploadSetFilename Hook-List Start. Filename:(%s)\n",
|
||||
Filename.c_str());
|
||||
THandleStatus _status = HANDLED_NONE;
|
||||
THookList::iterator i = HookList.begin();
|
||||
for ( ; i!= HookList.end(); i++ )
|
||||
{
|
||||
log_level_printf(4,"UploadSetFilename Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
for (; i != HookList.end(); i++) {
|
||||
log_level_printf(4, "UploadSetFilename Hook-List (%s) Start\n",
|
||||
((*i)->getHookName()).c_str());
|
||||
// response Hook
|
||||
_status = (*i)->Hook_UploadSetFilename(this, Filename);
|
||||
log_level_printf(4,"UploadSetFilename Hook-List (%s) End. Status (%d)\n", ((*i)->getHookName()).c_str(), _status);
|
||||
if((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
log_level_printf(4,
|
||||
"UploadSetFilename Hook-List (%s) End. Status (%d)\n",
|
||||
((*i)->getHookName()).c_str(), _status);
|
||||
if ((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
break;
|
||||
}
|
||||
log_level_printf(4,"UploadSetFilename Hook-List End\n");
|
||||
log_level_printf(4, "UploadSetFilename Hook-List End\n");
|
||||
status = _status;
|
||||
return _status;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hook Dispatcher for UploadSetFilename
|
||||
//-----------------------------------------------------------------------------
|
||||
THandleStatus CyhookHandler::Hooks_UploadReady(const std::string& Filename)
|
||||
{
|
||||
log_level_printf(4,"UploadReady Hook-List Start. Filename:(%s)\n", Filename.c_str());
|
||||
THandleStatus CyhookHandler::Hooks_UploadReady(const std::string& Filename) {
|
||||
log_level_printf(4, "UploadReady Hook-List Start. Filename:(%s)\n",
|
||||
Filename.c_str());
|
||||
THandleStatus _status = HANDLED_NONE;
|
||||
THookList::iterator i = HookList.begin();
|
||||
for ( ; i!= HookList.end(); i++ )
|
||||
{
|
||||
log_level_printf(4,"UploadReady Hook-List (%s) Start\n", ((*i)->getHookName()).c_str());
|
||||
for (; i != HookList.end(); i++) {
|
||||
log_level_printf(4, "UploadReady Hook-List (%s) Start\n",
|
||||
((*i)->getHookName()).c_str());
|
||||
// response Hook
|
||||
_status = (*i)->Hook_UploadReady(this, Filename);
|
||||
log_level_printf(4,"UploadReady Hook-List (%s) End. Status (%d)\n", ((*i)->getHookName()).c_str(), _status);
|
||||
if((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
log_level_printf(4, "UploadReady Hook-List (%s) End. Status (%d)\n",
|
||||
((*i)->getHookName()).c_str(), _status);
|
||||
if ((_status != HANDLED_NONE) && (_status != HANDLED_CONTINUE))
|
||||
break;
|
||||
}
|
||||
log_level_printf(4,"UploadReady Hook-List End\n");
|
||||
log_level_printf(4, "UploadReady Hook-List End\n");
|
||||
status = _status;
|
||||
return _status;
|
||||
}
|
||||
@@ -157,19 +163,19 @@ THandleStatus CyhookHandler::Hooks_UploadReady(const std::string& Filename)
|
||||
//=============================================================================
|
||||
// Output helpers
|
||||
//=============================================================================
|
||||
void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData, CStringList _HeaderList,
|
||||
CStringList& _ConfigList, THttp_Method _Method, bool _keep_alive)
|
||||
{
|
||||
ParamList = _ParamList;
|
||||
UrlData = _UrlData;
|
||||
HeaderList = _HeaderList;
|
||||
WebserverConfigList = _ConfigList;
|
||||
Method = _Method;
|
||||
status = HANDLED_NONE;
|
||||
httpStatus = HTTP_OK;
|
||||
ContentLength = 0;
|
||||
LastModified = (time_t)-1;
|
||||
keep_alive = _keep_alive;
|
||||
void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData,
|
||||
CStringList _HeaderList, CStringList& _ConfigList,
|
||||
THttp_Method _Method, bool _keep_alive) {
|
||||
ParamList = _ParamList;
|
||||
UrlData = _UrlData;
|
||||
HeaderList = _HeaderList;
|
||||
WebserverConfigList = _ConfigList;
|
||||
Method = _Method;
|
||||
status = HANDLED_NONE;
|
||||
httpStatus = HTTP_OK;
|
||||
ContentLength = 0;
|
||||
LastModified = (time_t) - 1;
|
||||
keep_alive = _keep_alive;
|
||||
HookVarList.clear();
|
||||
}
|
||||
|
||||
@@ -202,113 +208,111 @@ void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData, C
|
||||
// | Via ; not implemented
|
||||
// | Warning ; not implemented
|
||||
//
|
||||
// response-header = Accept-Ranges ; not implemented
|
||||
// | Age ; not implemented
|
||||
// | ETag ; not implemented
|
||||
// | Location ; implemented (redirection / Object moved)
|
||||
// | Proxy-Authenticate ; not implemented
|
||||
// | Retry-After ; not implemented
|
||||
// | Server ; implemented
|
||||
// | Vary ; not implemented
|
||||
// | WWW-Authenticate ; implemented (by mod_auth and SendHeader)
|
||||
// response-header = Accept-Ranges ; not implemented
|
||||
// | Age ; not implemented
|
||||
// | ETag ; not implemented
|
||||
// | Location ; implemented (redirection / Object moved)
|
||||
// | Proxy-Authenticate ; not implemented
|
||||
// | Retry-After ; not implemented
|
||||
// | Server ; implemented
|
||||
// | Vary ; not implemented
|
||||
// | WWW-Authenticate ; implemented (by mod_auth and SendHeader)
|
||||
//
|
||||
// entity-header = Allow ; not implemented
|
||||
// | Content-Encoding ; not implemented
|
||||
// | Content-Language ; not implemented
|
||||
// | Content-Length ; implemented
|
||||
// | Content-Location ; not implemented
|
||||
// | Content-MD5 ; not implemented
|
||||
// | Content-Range ; not implemented
|
||||
// | Content-Type ; implemented
|
||||
// | Expires ; not implemented
|
||||
// | Last-Modified ; implemented for static files
|
||||
// | extension-header
|
||||
// entity-header = Allow ; not implemented
|
||||
// | Content-Encoding ; not implemented
|
||||
// | Content-Language ; not implemented
|
||||
// | Content-Length ; implemented
|
||||
// | Content-Location ; not implemented
|
||||
// | Content-MD5 ; not implemented
|
||||
// | Content-Range ; not implemented
|
||||
// | Content-Type ; implemented
|
||||
// | Expires ; not implemented
|
||||
// | Last-Modified ; implemented for static files
|
||||
// | extension-header
|
||||
//
|
||||
// extension-header = message-header
|
||||
// extension-header = message-header
|
||||
//=============================================================================
|
||||
std::string CyhookHandler::BuildHeader(bool cache)
|
||||
{
|
||||
std::string result="";
|
||||
std::string CyhookHandler::BuildHeader(bool cache) {
|
||||
std::string result = "";
|
||||
|
||||
const char *responseString = "";
|
||||
const char *infoString = 0;
|
||||
|
||||
// get Info Index
|
||||
for (unsigned int i = 0;i < (sizeof(httpResponseNames)/sizeof(httpResponseNames[0])); i++)
|
||||
if (httpResponseNames[i].type == httpStatus)
|
||||
{
|
||||
for (unsigned int i = 0; i < (sizeof(httpResponseNames)
|
||||
/ sizeof(httpResponseNames[0])); i++)
|
||||
if (httpResponseNames[i].type == httpStatus) {
|
||||
responseString = httpResponseNames[i].name;
|
||||
infoString = httpResponseNames[i].info;
|
||||
break;
|
||||
}
|
||||
// print Status-line
|
||||
result = string_printf(HTTP_PROTOCOL " %d %s\r\nContent-Type: %s\r\n",httpStatus, responseString, ResponseMimeType.c_str());
|
||||
log_level_printf(2,"Respose: HTTP/1.1 %d %s\r\nContent-Type: %s\r\n",httpStatus, responseString, ResponseMimeType.c_str());
|
||||
log_level_printf(2, "Respose: HTTP/1.1 %d %s\r\nContent-Type: %s\r\n",
|
||||
httpStatus, responseString, ResponseMimeType.c_str());
|
||||
|
||||
switch (httpStatus)
|
||||
{
|
||||
case HTTP_UNAUTHORIZED:
|
||||
result += "WWW-Authenticate: Basic realm=\"";
|
||||
result += AUTH_NAME_MSG "\r\n";
|
||||
break;
|
||||
switch (httpStatus) {
|
||||
case HTTP_UNAUTHORIZED:
|
||||
result += "WWW-Authenticate: Basic realm=\"";
|
||||
result += AUTH_NAME_MSG "\r\n";
|
||||
break;
|
||||
|
||||
case HTTP_MOVED_TEMPORARILY:
|
||||
case HTTP_MOVED_PERMANENTLY:
|
||||
// Status HTTP_*_TEMPORARILY (redirection)
|
||||
result += string_printf("Location: %s\r\n",NewURL.c_str());
|
||||
// NO break HERE !!!
|
||||
case HTTP_MOVED_TEMPORARILY:
|
||||
case HTTP_MOVED_PERMANENTLY:
|
||||
// Status HTTP_*_TEMPORARILY (redirection)
|
||||
result += string_printf("Location: %s\r\n", NewURL.c_str());
|
||||
// NO break HERE !!!
|
||||
|
||||
default:
|
||||
time_t timer = time(0);
|
||||
char timeStr[80];
|
||||
// cache
|
||||
if(!cache && (HookVarList["CacheCategory"]).empty() )
|
||||
result += "Cache-Control: no-cache\r\n";
|
||||
else
|
||||
{
|
||||
time_t x_time = time(NULL);
|
||||
struct tm *ptm = gmtime(&x_time);
|
||||
ptm->tm_mday+=1;
|
||||
x_time = mktime(ptm);
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&x_time));
|
||||
result += string_printf("Expires: %s\r\n", timeStr);
|
||||
}
|
||||
result += "Server: " WEBSERVERNAME "\r\n";
|
||||
// actual date
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
|
||||
result += string_printf("Date: %s\r\n", timeStr);
|
||||
// connection type
|
||||
default:
|
||||
time_t timer = time(0);
|
||||
char timeStr[80];
|
||||
// cache
|
||||
if (!cache && (HookVarList["CacheCategory"]).empty())
|
||||
result += "Cache-Control: no-cache\r\n";
|
||||
else {
|
||||
time_t x_time = time(NULL);
|
||||
struct tm *ptm = gmtime(&x_time);
|
||||
ptm->tm_mday += 1;
|
||||
x_time = mktime(ptm);
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&x_time));
|
||||
result += string_printf("Expires: %s\r\n", timeStr);
|
||||
}
|
||||
result += "Server: " WEBSERVERNAME "\r\n";
|
||||
// actual date
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
|
||||
result += string_printf("Date: %s\r\n", timeStr);
|
||||
// connection type
|
||||
#ifdef Y_CONFIG_FEATURE_KEEP_ALIVE
|
||||
if(keep_alive)
|
||||
result += "Connection: keep-alive\r\n";
|
||||
else
|
||||
result += "Connection: close\r\n";
|
||||
if(keep_alive)
|
||||
result += "Connection: keep-alive\r\n";
|
||||
else
|
||||
result += "Connection: close\r\n";
|
||||
#else
|
||||
result += "Connection: close\r\n";
|
||||
result += "Connection: close\r\n";
|
||||
#endif
|
||||
// gzipped ?
|
||||
if(UrlData["fileext"] == "gz")
|
||||
result += "Content-Encoding: gzip\r\n";
|
||||
// content-len, last-modified
|
||||
if(httpStatus == HTTP_NOT_MODIFIED ||httpStatus == HTTP_NOT_FOUND)
|
||||
result += "Content-Length: 0\r\n";
|
||||
else if(GetContentLength() >0)
|
||||
{
|
||||
time_t mod_time = time(NULL);
|
||||
if(LastModified != (time_t)-1)
|
||||
mod_time = LastModified;
|
||||
// gzipped ?
|
||||
if (UrlData["fileext"] == "gz")
|
||||
result += "Content-Encoding: gzip\r\n";
|
||||
// content-len, last-modified
|
||||
if (httpStatus == HTTP_NOT_MODIFIED || httpStatus == HTTP_NOT_FOUND)
|
||||
result += "Content-Length: 0\r\n";
|
||||
else if (GetContentLength() > 0) {
|
||||
time_t mod_time = time(NULL);
|
||||
if (LastModified != (time_t) - 1)
|
||||
mod_time = LastModified;
|
||||
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&mod_time));
|
||||
result += string_printf("Last-Modified: %s\r\nContent-Length: %ld\r\n", timeStr, GetContentLength());
|
||||
}
|
||||
result += "\r\n"; // End of Header
|
||||
break;
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&mod_time));
|
||||
result += string_printf(
|
||||
"Last-Modified: %s\r\nContent-Length: %ld\r\n", timeStr,
|
||||
GetContentLength());
|
||||
}
|
||||
result += "\r\n"; // End of Header
|
||||
break;
|
||||
}
|
||||
|
||||
// Body
|
||||
if (Method != M_HEAD)
|
||||
switch (httpStatus)
|
||||
{
|
||||
switch (httpStatus) {
|
||||
case HTTP_OK:
|
||||
case HTTP_NOT_MODIFIED:
|
||||
case HTTP_CONTINUE:
|
||||
@@ -321,13 +325,16 @@ std::string CyhookHandler::BuildHeader(bool cache)
|
||||
case HTTP_MOVED_TEMPORARILY:
|
||||
case HTTP_MOVED_PERMANENTLY:
|
||||
result += "<html><head><title>Object moved</title></head><body>";
|
||||
result += string_printf("302 : Object moved.<br/>If you dont get redirected click <a href=\"%s\">here</a></body></html>\n",NewURL.c_str());
|
||||
result
|
||||
+= string_printf(
|
||||
"302 : Object moved.<br/>If you dont get redirected click <a href=\"%s\">here</a></body></html>\n",
|
||||
NewURL.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
// Error pages
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -335,27 +342,24 @@ std::string CyhookHandler::BuildHeader(bool cache)
|
||||
// Output helpers
|
||||
//=============================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
void CyhookHandler::SendHTMLHeader(const std::string& Titel)
|
||||
{
|
||||
void CyhookHandler::SendHTMLHeader(const std::string& Titel) {
|
||||
WriteLn("<html>\n<head><title>" + Titel + "</title>\n");
|
||||
WriteLn("<meta http-equiv=\"cache-control\" content=\"no-cache\" />");
|
||||
WriteLn("<meta http-equiv=\"expires\" content=\"0\" />\n</head>\n<body>\n");
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void CyhookHandler::SendHTMLFooter(void)
|
||||
{
|
||||
void CyhookHandler::SendHTMLFooter(void) {
|
||||
WriteLn("</body>\n</html>\n\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#define OUTBUFSIZE 4096
|
||||
void CyhookHandler::printf ( const char *fmt, ... )
|
||||
{
|
||||
void CyhookHandler::printf(const char *fmt, ...) {
|
||||
char outbuf[OUTBUFSIZE];
|
||||
bzero(outbuf,OUTBUFSIZE);
|
||||
bzero(outbuf, OUTBUFSIZE);
|
||||
va_list arglist;
|
||||
va_start( arglist, fmt );
|
||||
vsnprintf( outbuf,OUTBUFSIZE, fmt, arglist );
|
||||
va_start(arglist, fmt);
|
||||
vsnprintf(outbuf, OUTBUFSIZE, fmt, arglist);
|
||||
va_end(arglist);
|
||||
Write(outbuf);
|
||||
}
|
||||
|
@@ -83,10 +83,10 @@ std::string CLanguage::getTranslation(std::string id){
|
||||
std::string CLanguage::getLanguageDir(void){
|
||||
std::string tmpfilename = "/"+Cyhttpd::ConfigList["Language.directory"],dir="";
|
||||
|
||||
if( access(std::string(Cyhttpd::ConfigList["PublicDocumentRoot"] + tmpfilename).c_str(),4) == 0)
|
||||
dir = Cyhttpd::ConfigList["PublicDocumentRoot"] + tmpfilename;
|
||||
else if(access(std::string(Cyhttpd::ConfigList["PrivatDocumentRoot"] + tmpfilename).c_str(),4) == 0)
|
||||
dir = Cyhttpd::ConfigList["PrivatDocumentRoot"] + tmpfilename;
|
||||
if( access(std::string(Cyhttpd::ConfigList["WebsiteMain.override_directory"] + tmpfilename).c_str(),4) == 0)
|
||||
dir = Cyhttpd::ConfigList["WebsiteMain.override_directory"] + tmpfilename;
|
||||
else if(access(std::string(Cyhttpd::ConfigList["WebsiteMain.directory"] + tmpfilename).c_str(),4) == 0)
|
||||
dir = Cyhttpd::ConfigList["WebsiteMain.directory"] + tmpfilename;
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
@@ -24,16 +24,14 @@ CLogging *CLogging::instance = NULL;
|
||||
//-----------------------------------------------------------------------------
|
||||
// There is only one Instance
|
||||
//-----------------------------------------------------------------------------
|
||||
CLogging *CLogging::getInstance(void)
|
||||
{
|
||||
CLogging *CLogging::getInstance(void) {
|
||||
if (!instance)
|
||||
instance = new CLogging();
|
||||
return instance;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLogging::deleteInstance(void)
|
||||
{
|
||||
void CLogging::deleteInstance(void) {
|
||||
if (instance)
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
@@ -42,30 +40,26 @@ void CLogging::deleteInstance(void)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CLogging::CLogging(void)
|
||||
{
|
||||
Debug = false;
|
||||
LogToFile = false; //not implemented
|
||||
LogLevel = 0;
|
||||
Logfile = NULL;
|
||||
CLogging::CLogging(void) {
|
||||
Debug = false;
|
||||
LogToFile = false; //not implemented
|
||||
LogLevel = 0;
|
||||
Logfile = NULL;
|
||||
pthread_mutex_init(&Log_mutex, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CLogging::~CLogging(void)
|
||||
{
|
||||
CLogging::~CLogging(void) {
|
||||
}
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLogging::setDebug(bool _debug)
|
||||
{
|
||||
Debug = _debug;
|
||||
void CLogging::setDebug(bool _debug) {
|
||||
Debug = _debug;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CLogging::getDebug(void)
|
||||
{
|
||||
return Debug;
|
||||
bool CLogging::getDebug(void) {
|
||||
return Debug;
|
||||
}
|
||||
//=============================================================================
|
||||
// Logging Calls
|
||||
@@ -74,22 +68,19 @@ bool CLogging::getDebug(void)
|
||||
//=============================================================================
|
||||
#define bufferlen 1024*8
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLogging::printf ( const char *fmt, ... )
|
||||
{
|
||||
void CLogging::printf(const char *fmt, ...) {
|
||||
char buffer[bufferlen];
|
||||
|
||||
|
||||
va_list arglist;
|
||||
va_start( arglist, fmt );
|
||||
if(arglist)
|
||||
vsnprintf( buffer, bufferlen, fmt, arglist );
|
||||
va_start(arglist, fmt);
|
||||
vsnprintf(buffer, bufferlen, fmt, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
pthread_mutex_lock( &Log_mutex );
|
||||
pthread_mutex_lock(&Log_mutex);
|
||||
::printf(buffer);
|
||||
if(LogToFile) {
|
||||
; //FIXME Logging to File
|
||||
if (LogToFile) {
|
||||
; //FIXME Logging to File
|
||||
}
|
||||
pthread_mutex_unlock( &Log_mutex );
|
||||
pthread_mutex_unlock(&Log_mutex);
|
||||
}
|
||||
|
||||
|
@@ -33,8 +33,7 @@
|
||||
//=============================================================================
|
||||
// Constructor & Destructor
|
||||
//=============================================================================
|
||||
CWebserverRequest::CWebserverRequest(CWebserver *pWebserver)
|
||||
{
|
||||
CWebserverRequest::CWebserverRequest(CWebserver *pWebserver) {
|
||||
Webserver = pWebserver;
|
||||
CWebserverRequest();
|
||||
}
|
||||
@@ -51,61 +50,53 @@ CWebserverRequest::CWebserverRequest(CWebserver *pWebserver)
|
||||
// [ message-body ]
|
||||
// start-line = Request-Line | Status-Line
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverRequest::HandleRequest(void)
|
||||
{
|
||||
bool CWebserverRequest::HandleRequest(void) {
|
||||
std::string start_line = "";
|
||||
// read first line
|
||||
do
|
||||
{
|
||||
do {
|
||||
start_line = Connection->sock->ReceiveLine();
|
||||
if(!Connection->sock->isValid)
|
||||
if (!Connection->sock->isValid)
|
||||
return false;
|
||||
if(start_line == "") // Socket empty
|
||||
if (start_line == "") // Socket empty
|
||||
{
|
||||
log_level_printf(1,"HandleRequest: End of line not found\n");
|
||||
log_level_printf(1, "HandleRequest: End of line not found\n");
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
Connection->RequestCanceled = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while(start_line == "\r\n"); // ignore empty lines at begin on start-line
|
||||
} while (start_line == "\r\n"); // ignore empty lines at begin on start-line
|
||||
|
||||
start_line = trim(start_line);
|
||||
log_level_printf(1,"Request: %s\n", start_line.c_str() );
|
||||
log_level_printf(1, "Request: %s\n", start_line.c_str());
|
||||
UrlData["startline"] = start_line;
|
||||
if(!ParseStartLine(start_line))
|
||||
if (!ParseStartLine(start_line))
|
||||
return false;
|
||||
|
||||
|
||||
if(Connection->Method == M_GET || Connection->Method == M_HEAD)
|
||||
{
|
||||
if (Connection->Method == M_GET || Connection->Method == M_HEAD) {
|
||||
std::string tmp_line;
|
||||
//read header (speed up: read rest of request in blockmode)
|
||||
tmp_line = Connection->sock->ReceiveBlock();
|
||||
if(!Connection->sock->isValid)
|
||||
{
|
||||
if (!Connection->sock->isValid) {
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tmp_line == "")
|
||||
{
|
||||
if (tmp_line == "") {
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
}
|
||||
ParseHeader(tmp_line);
|
||||
}
|
||||
// Other Methods
|
||||
if(Connection->Method == M_DELETE || Connection->Method == M_PUT || Connection->Method == M_TRACE)
|
||||
{
|
||||
if (Connection->Method == M_DELETE || Connection->Method == M_PUT
|
||||
|| Connection->Method == M_TRACE) {
|
||||
//todo: implement
|
||||
aprintf("HTTP Method not implemented :%d\n",Connection->Method);
|
||||
aprintf("HTTP Method not implemented :%d\n", Connection->Method);
|
||||
Connection->Response.SendError(HTTP_NOT_IMPLEMENTED);
|
||||
return false;
|
||||
}
|
||||
// handle POST (read header & body)
|
||||
if(Connection->Method == M_POST)
|
||||
{
|
||||
if (Connection->Method == M_POST) {
|
||||
Connection->Response.Write("HTTP/1.1 100 Continue\r\n\r\n"); // POST Requests requires CONTINUE in HTTP/1.1
|
||||
return HandlePost();
|
||||
}
|
||||
@@ -122,33 +113,29 @@ bool CWebserverRequest::HandleRequest(void)
|
||||
// Determine Reqest-Method, URL, HTTP-Version and Split Parameters
|
||||
// Split URL into path, filename, fileext .. UrlData[]
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverRequest::ParseStartLine(std::string start_line)
|
||||
{
|
||||
std::string method,url,http,tmp;
|
||||
bool CWebserverRequest::ParseStartLine(std::string start_line) {
|
||||
std::string method, url, http, tmp;
|
||||
|
||||
log_level_printf(8,"<ParseStartLine>: line: %s\n", start_line.c_str() );
|
||||
if(ySplitString(start_line," ",method,tmp))
|
||||
{
|
||||
if(ySplitStringLast(tmp," ",url,Connection->httprotocol))
|
||||
{
|
||||
log_level_printf(8, "<ParseStartLine>: line: %s\n", start_line.c_str());
|
||||
if (ySplitString(start_line, " ", method, tmp)) {
|
||||
if (ySplitStringLast(tmp, " ", url, Connection->httprotocol)) {
|
||||
analyzeURL(url);
|
||||
UrlData["httprotocol"] = Connection->httprotocol;
|
||||
// determine http Method
|
||||
if(method.compare("POST") == 0) Connection->Method = M_POST;
|
||||
else if(method.compare("GET") == 0) Connection->Method = M_GET;
|
||||
else if(method.compare("PUT") == 0) Connection->Method = M_PUT;
|
||||
else if(method.compare("HEAD") == 0) Connection->Method = M_HEAD;
|
||||
else if(method.compare("PUT") == 0) Connection->Method = M_PUT;
|
||||
else if(method.compare("DELETE") == 0) Connection->Method = M_DELETE;
|
||||
else if(method.compare("TRACE") == 0) Connection->Method = M_TRACE;
|
||||
else
|
||||
{
|
||||
log_level_printf(1,"Unknown Method or invalid request\n");
|
||||
if (method.compare("POST") == 0) Connection->Method = M_POST;
|
||||
else if (method.compare("GET") == 0) Connection->Method = M_GET;
|
||||
else if (method.compare("PUT") == 0) Connection->Method = M_PUT;
|
||||
else if (method.compare("HEAD") == 0) Connection->Method = M_HEAD;
|
||||
else if (method.compare("PUT") == 0) Connection->Method = M_PUT;
|
||||
else if (method.compare("DELETE") == 0) Connection->Method = M_DELETE;
|
||||
else if (method.compare("TRACE") == 0) Connection->Method = M_TRACE;
|
||||
else {
|
||||
log_level_printf(1, "Unknown Method or invalid request\n");
|
||||
Connection->Response.SendError(HTTP_NOT_IMPLEMENTED);
|
||||
log_level_printf(3,"Request: '%s'\n",rawbuffer.c_str());
|
||||
log_level_printf(3, "Request: '%s'\n", rawbuffer.c_str());
|
||||
return false;
|
||||
}
|
||||
log_level_printf(3,"Request: FullURL: %s\n",UrlData["fullurl"].c_str());
|
||||
log_level_printf(3, "Request: FullURL: %s\n", UrlData["fullurl"].c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -164,28 +151,24 @@ bool CWebserverRequest::ParseStartLine(std::string start_line)
|
||||
// If parameter attribute is multiple times given, the values are stored like this:
|
||||
// <attribute>=<value1>,<value2>,..,<value n>
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverRequest::ParseParams(std::string param_string)
|
||||
{
|
||||
bool CWebserverRequest::ParseParams(std::string param_string) {
|
||||
bool ende = false;
|
||||
std::string param, name="", value, number;
|
||||
std::string param, name = "", value, number;
|
||||
|
||||
while(!ende)
|
||||
{
|
||||
if(!ySplitStringExact(param_string,"&",param,param_string))
|
||||
while (!ende) {
|
||||
if (!ySplitStringExact(param_string, "&", param, param_string))
|
||||
ende = true;
|
||||
if(ySplitStringExact(param,"=",name,value))
|
||||
{
|
||||
if (ySplitStringExact(param, "=", name, value)) {
|
||||
value = trim(decodeString(value));
|
||||
if(ParameterList[name].empty())
|
||||
if (ParameterList[name].empty())
|
||||
ParameterList[name] = value;
|
||||
else
|
||||
{
|
||||
else {
|
||||
ParameterList[name] += ",";
|
||||
ParameterList[name] += value;
|
||||
}
|
||||
}
|
||||
number = string_printf("%d", ParameterList.size()+1);
|
||||
log_level_printf(7,"ParseParams: name: %s value: %s\n",name.c_str(), value.c_str());
|
||||
number = string_printf("%d", ParameterList.size() + 1);
|
||||
log_level_printf(7, "ParseParams: name: %s value: %s\n", name.c_str(), value.c_str());
|
||||
ParameterList[number] = name;
|
||||
}
|
||||
return true;
|
||||
@@ -201,19 +184,17 @@ bool CWebserverRequest::ParseParams(std::string param_string)
|
||||
// and consisting of either *TEXT or combinations
|
||||
// of token, separators, and quoted-string>
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverRequest::ParseHeader(std::string header)
|
||||
{
|
||||
bool CWebserverRequest::ParseHeader(std::string header) {
|
||||
bool ende = false;
|
||||
std::string sheader, name, value;
|
||||
HeaderList.clear();
|
||||
|
||||
while(!ende)
|
||||
{
|
||||
if(!ySplitStringExact(header,"\r\n",sheader,header))
|
||||
while (!ende) {
|
||||
if (!ySplitStringExact(header, "\r\n", sheader, header))
|
||||
ende = true;
|
||||
if(ySplitStringExact(sheader,":",name,value))
|
||||
if (ySplitStringExact(sheader, ":", name, value))
|
||||
HeaderList[name] = trim(value);
|
||||
log_level_printf(8,"ParseHeader: name: %s value: %s\n",name.c_str(), value.c_str());
|
||||
log_level_printf(8, "ParseHeader: name: %s value: %s\n", name.c_str(), value.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -225,66 +206,65 @@ bool CWebserverRequest::ParseHeader(std::string header)
|
||||
// http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
|
||||
// query data is splitted and stored in ParameterList
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWebserverRequest::analyzeURL(std::string url)
|
||||
{
|
||||
void CWebserverRequest::analyzeURL(std::string url) {
|
||||
ParameterList.clear();
|
||||
// URI decode
|
||||
url = decodeString(url);
|
||||
url = trim(url, "\r\n"); // non-HTTP-Standard: allow \r or \n in URL. Delete it.
|
||||
UrlData["fullurl"] = url;
|
||||
// split Params
|
||||
if(ySplitString(url,"?",UrlData["url"],UrlData["paramstring"])) // split pure URL and all Params
|
||||
ParseParams(UrlData["paramstring"]); // split params to ParameterList
|
||||
else // No Params
|
||||
if (ySplitString(url, "?", UrlData["url"], UrlData["paramstring"])) // split pure URL and all Params
|
||||
ParseParams( UrlData["paramstring"]); // split params to ParameterList
|
||||
else
|
||||
// No Params
|
||||
UrlData["url"] = url;
|
||||
|
||||
if(!ySplitStringLast(UrlData["url"],"/",UrlData["path"],UrlData["filename"]))
|
||||
{
|
||||
UrlData["path"] = "/"; // Set "/" if not contained
|
||||
}
|
||||
else
|
||||
if (!ySplitStringLast(UrlData["url"], "/", UrlData["path"],
|
||||
UrlData["filename"])) {
|
||||
UrlData["path"] = "/"; // Set "/" if not contained
|
||||
} else
|
||||
UrlData["path"] += "/";
|
||||
if(( UrlData["url"].length() == 1) || (UrlData["url"][UrlData["url"].length()-1] == '/' ))
|
||||
{ // if "/" at end use index.html
|
||||
if ((UrlData["url"].length() == 1)
|
||||
|| (UrlData["url"][UrlData["url"].length() - 1] == '/')) { // if "/" at end use index.html
|
||||
UrlData["path"] = UrlData["url"];
|
||||
UrlData["filename"] = "index.html";
|
||||
}
|
||||
ySplitStringLast(UrlData["filename"],".",UrlData["filenamepure"],UrlData["fileext"]);
|
||||
ySplitStringLast(UrlData["filename"], ".", UrlData["filenamepure"],
|
||||
UrlData["fileext"]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handle Post (Form and ONE file upload)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverRequest::HandlePost()
|
||||
{
|
||||
bool CWebserverRequest::HandlePost() {
|
||||
//read header: line by line
|
||||
std::string raw_header, tmp_line;
|
||||
do
|
||||
{
|
||||
do {
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
if(tmp_line == "") // Socket empty
|
||||
if (tmp_line == "") // Socket empty
|
||||
{
|
||||
log_level_printf(1,"HandleRequest: (Header) End of line not found: %s\n", strerror(errno));
|
||||
log_level_printf(1,
|
||||
"HandleRequest: (Header) End of line not found: %s\n",
|
||||
strerror(errno));
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
}
|
||||
raw_header.append(tmp_line);
|
||||
}
|
||||
while(tmp_line != "\r\n"); // header ends with first empty line
|
||||
} while (tmp_line != "\r\n"); // header ends with first empty line
|
||||
ParseHeader(raw_header);
|
||||
|
||||
// read meesage body
|
||||
unsigned int content_len = 0;
|
||||
if(HeaderList["Content-Length"] != "")
|
||||
content_len = atoi( HeaderList["Content-Length"].c_str() );
|
||||
if (HeaderList["Content-Length"] != "")
|
||||
content_len = atoi(HeaderList["Content-Length"].c_str());
|
||||
|
||||
// Get Rest of Request from Socket
|
||||
log_level_printf(2,"Connection->Method Post !\n");
|
||||
log_level_printf(9,"Conntent Type:%s\n",(HeaderList["Content-Type"]).c_str());
|
||||
log_level_printf(8,"Post Content-Length:%d as string:(%s)\n", content_len, HeaderList["Content-Length"].c_str());
|
||||
log_level_printf(2, "Connection->Method Post !\n");
|
||||
log_level_printf(9, "Conntent Type:%s\n", (HeaderList["Content-Type"]).c_str());
|
||||
log_level_printf(8, "Post Content-Length:%d as string:(%s)\n", content_len, HeaderList["Content-Length"].c_str());
|
||||
|
||||
static const std::string t = "multipart/form-data; boundary=";
|
||||
if(HeaderList["Content-Type"].compare(0,t.length(),t) == 0) // this a a multpart POST, normallly: file upload
|
||||
if (HeaderList["Content-Type"].compare(0, t.length(), t) == 0) // this a a multpart POST, normallly: file upload
|
||||
{
|
||||
#ifdef Y_CONFIG_FEATURE_UPLOAD
|
||||
std::string boundary = "--" + HeaderList["Content-Type"].substr(t.length(),HeaderList["Content-Type"].length() - t.length());
|
||||
@@ -298,21 +278,20 @@ bool CWebserverRequest::HandlePost()
|
||||
Connection->Response.SendError(HTTP_NOT_IMPLEMENTED);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else if(HeaderList["Content-Type"].compare("application/x-www-form-urlencoded") == 0) //this is a normal POST with form-data (no upload)
|
||||
} else if (HeaderList["Content-Type"].compare(
|
||||
"application/x-www-form-urlencoded") == 0) //this is a normal POST with form-data (no upload)
|
||||
{
|
||||
// handle normal form POST
|
||||
log_level_printf(6,"Handle POST application/x-www-form-urlencoded\n");
|
||||
log_level_printf(6, "Handle POST application/x-www-form-urlencoded\n");
|
||||
std::string post_header;
|
||||
// get message-body
|
||||
post_header = Connection->sock->ReceiveBlock();
|
||||
while(post_header.length() < content_len)
|
||||
{
|
||||
while (post_header.length() < content_len) {
|
||||
post_header += Connection->sock->ReceiveBlock();
|
||||
/* aprintf("POST form less data then expected\n");
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
*/
|
||||
/* aprintf("POST form less data then expected\n");
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
// parse the params in post_header (message-body) an add them to ParameterList
|
||||
ParseParams(post_header);
|
||||
@@ -401,35 +380,31 @@ bool CWebserverRequest::HandlePost()
|
||||
// where the original filename is known. This is useful or necessary in
|
||||
// many applications.
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigned int content_len)
|
||||
{
|
||||
unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary,
|
||||
unsigned int content_len) {
|
||||
std::string tmp_line;
|
||||
|
||||
// read boundary
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
|
||||
log_level_printf(2,"<POST Boundary> Start\n");
|
||||
if(tmp_line.find(boundary) != std::string::npos)
|
||||
{
|
||||
log_level_printf(2, "<POST Boundary> Start\n");
|
||||
if (tmp_line.find(boundary) != std::string::npos) {
|
||||
// is it the boudary end?
|
||||
if(tmp_line.find(boundary+"--") != std::string::npos)
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> Boundary END found\n");
|
||||
if (tmp_line.find(boundary + "--") != std::string::npos) {
|
||||
log_level_printf(7, "<POST Boundary> Boundary END found\n");
|
||||
return 0;
|
||||
}
|
||||
log_level_printf(7,"<POST Boundary> Boundary START found\n");
|
||||
log_level_printf(7, "<POST Boundary> Boundary START found\n");
|
||||
|
||||
// read content-disposition: ...
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
if(tmp_line.find("Content-Disposition:") == std::string::npos)
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> no content-disposition found. line:(%s)\n", tmp_line.c_str());
|
||||
if (tmp_line.find("Content-Disposition:") == std::string::npos) {
|
||||
log_level_printf(7, "<POST Boundary> no content-disposition found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
}
|
||||
if(tmp_line.find("filename") != std::string::npos)
|
||||
{
|
||||
if (tmp_line.find("filename") != std::string::npos) {
|
||||
#ifdef Y_CONFIG_FEATURE_UPLOAD
|
||||
// this part is a file
|
||||
log_level_printf(2,"<POST Boundary> disposition !!this is a file!! found. line:(%s)\n", tmp_line.c_str());
|
||||
@@ -473,7 +448,6 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
ParameterList[var_name+"_mime"] = var_value;
|
||||
log_level_printf(7,"<POST Boundary> Content-Type found. name:(%s_mime) value:(%s)\n", var_name.c_str(), var_value.c_str());
|
||||
|
||||
|
||||
//read empty line as separator
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
@@ -505,7 +479,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
// It only works, if no multipart/mixed is used (e.g. in file attachments). Not nessesary in embedded systems.
|
||||
// To speed up uploading, read content_len - SEARCH_BOUNDARY_LEN bytes in blockmode.
|
||||
// To save memory, write them direct into the file.
|
||||
#define SEARCH_BOUNDARY_LEN 2*RECEIVE_BLOCK_LEN // >= RECEIVE_BLOCK_LEN in ySocket
|
||||
#define SEARCH_BOUNDARY_LEN 2*RECEIVE_BLOCK_LEN // >= RECEIVE_BLOCK_LEN in ySocket
|
||||
unsigned int _readbytes = 0;
|
||||
if((int)content_len - SEARCH_BOUNDARY_LEN >0)
|
||||
{
|
||||
@@ -529,17 +503,17 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
if(tmp_line.find(boundary) != std::string::npos)
|
||||
{
|
||||
if(tmp_line.find(boundary+"--") != std::string::npos)
|
||||
found_end_boundary = true; // it is the end! of POST request!
|
||||
break; // boundary found. end of file.
|
||||
found_end_boundary = true; // it is the end! of POST request!
|
||||
break; // boundary found. end of file.
|
||||
}
|
||||
else // no Boundary: write CRFL if found in last line
|
||||
{
|
||||
if(is_CRLF)
|
||||
if ((unsigned int)write(fd, "\r\n", 2) != 2)
|
||||
{
|
||||
perror("write file failed\n");
|
||||
return 0;
|
||||
}
|
||||
if ((unsigned int)write(fd, "\r\n", 2) != 2)
|
||||
{
|
||||
perror("write file failed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// normal line: write it to file
|
||||
// CRLF at end? Maybe CRLF before boundary. Can not decide yet
|
||||
@@ -563,29 +537,25 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
return 0;
|
||||
}
|
||||
#endif // Y_CONFIG_FEATURE_UPLOAD
|
||||
}
|
||||
else
|
||||
} else
|
||||
// this part is a POST variable/parameter
|
||||
{
|
||||
// get var_name from 'content-disposition: form-data; name="var_name"'
|
||||
std::string left, right, var_name, var_value;
|
||||
if(!ySplitStringExact(tmp_line, "name=\"", left, right))
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> no var_name START found. line:(%s)\n", tmp_line.c_str());
|
||||
if (!ySplitStringExact(tmp_line, "name=\"", left, right)) {
|
||||
log_level_printf(7, "<POST Boundary> no var_name START found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
}
|
||||
if(!ySplitStringExact(right, "\"", var_name, right))
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> no var_name END found. line:(%s)\n", tmp_line.c_str());
|
||||
if (!ySplitStringExact(right, "\"", var_name, right)) {
|
||||
log_level_printf(7, "<POST Boundary> no var_name END found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
//read empty line as separator
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
if(tmp_line != "\r\n")
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> no empty line found. line:(%s)\n", tmp_line.c_str());
|
||||
if (tmp_line != "\r\n") {
|
||||
log_level_printf(7, "<POST Boundary> no empty line found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -596,7 +566,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
content_len -= tmp_line.length();
|
||||
var_value = trim(decodeString(var_value));
|
||||
ParameterList[var_name] = var_value;
|
||||
log_level_printf(7,"<POST Boundary> Parameter found. name:(%s) value:(%s)\n", var_name.c_str(), var_value.c_str());
|
||||
log_level_printf(7, "<POST Boundary> Parameter found. name:(%s) value:(%s)\n", var_name.c_str(), var_value.c_str());
|
||||
}
|
||||
}
|
||||
return content_len;
|
||||
|
@@ -29,14 +29,12 @@
|
||||
//=============================================================================
|
||||
// Constructor & Destructor
|
||||
//=============================================================================
|
||||
CWebserverResponse::CWebserverResponse(CWebserver *pWebserver)
|
||||
{
|
||||
CWebserverResponse::CWebserverResponse(CWebserver *pWebserver) {
|
||||
Webserver = pWebserver;
|
||||
CWebserverResponse();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
CWebserverResponse::CWebserverResponse()
|
||||
{
|
||||
CWebserverResponse::CWebserverResponse() {
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@@ -54,198 +52,177 @@ CWebserverResponse::CWebserverResponse()
|
||||
// CRLF ; generated by SendHeader
|
||||
// [ message-body ] ; by HOOK Handling Loop or Sendfile
|
||||
//=============================================================================
|
||||
bool CWebserverResponse::SendResponse()
|
||||
{
|
||||
bool CWebserverResponse::SendResponse() {
|
||||
// Init Hookhandler
|
||||
Connection->HookHandler.session_init(Connection->Request.ParameterList, Connection->Request.UrlData,
|
||||
(Connection->Request.HeaderList), (Cyhttpd::ConfigList), Connection->Method, Connection->keep_alive);
|
||||
Connection->HookHandler.session_init(Connection->Request.ParameterList,
|
||||
Connection->Request.UrlData, (Connection->Request.HeaderList),
|
||||
(Cyhttpd::ConfigList), Connection->Method, Connection->keep_alive);
|
||||
//--------------------------------------------------------------
|
||||
// HOOK Handling Loop [ PREPARE response hook ]
|
||||
// Checking and Preperation: Auth, static, cache, ...
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// move to mod_sendfile ???
|
||||
// move to mod_sendfile ???
|
||||
#ifdef Y_CONFIG_USE_HOSTEDWEB
|
||||
// for hosted webs: rewrite URL
|
||||
std::string _hosted="/hosted/";
|
||||
if((Connection->Request.UrlData["path"]).compare(0,_hosted.length(),"/hosted/") == 0) // hosted Web ?
|
||||
Connection->Request.UrlData["path"]=Cyhttpd::ConfigList["HostedDocumentRoot"]
|
||||
+(Connection->Request.UrlData["path"]).substr(_hosted.length()-1);
|
||||
if((Connection->Request.UrlData["path"]).compare(0,_hosted.length(),"/hosted/") == 0) // hosted Web ?
|
||||
Connection->Request.UrlData["path"]=Cyhttpd::ConfigList["WebsiteMain.hosted_directory"]
|
||||
+(Connection->Request.UrlData["path"]).substr(_hosted.length()-1);
|
||||
#endif //Y_CONFIG_USE_HOSTEDWEB
|
||||
|
||||
do
|
||||
{
|
||||
if(Connection->RequestCanceled)
|
||||
do {
|
||||
if (Connection->RequestCanceled)
|
||||
return false;
|
||||
|
||||
Connection->HookHandler.Hooks_PrepareResponse();
|
||||
if(Connection->HookHandler.status == HANDLED_ERROR || Connection->HookHandler.status == HANDLED_ABORT)
|
||||
{
|
||||
log_level_printf(2,"Response Prepare Hook found but Error\n");
|
||||
if (Connection->HookHandler.status == HANDLED_ERROR
|
||||
|| Connection->HookHandler.status == HANDLED_ABORT) {
|
||||
log_level_printf(2, "Response Prepare Hook found but Error\n");
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
Write(Connection->HookHandler.yresult);
|
||||
return false;
|
||||
}
|
||||
// URL has new value. Analyze new URL for SendFile
|
||||
else if(Connection->HookHandler.status == HANDLED_SENDFILE ||
|
||||
Connection->HookHandler.status == HANDLED_REWRITE)
|
||||
{
|
||||
else if (Connection->HookHandler.status == HANDLED_SENDFILE
|
||||
|| Connection->HookHandler.status == HANDLED_REWRITE) {
|
||||
Connection->Request.analyzeURL(Connection->HookHandler.NewURL);
|
||||
Connection->HookHandler.UrlData = Connection->Request.UrlData;
|
||||
}
|
||||
if(Connection->HookHandler.status == HANDLED_REDIRECTION)
|
||||
{
|
||||
if (Connection->HookHandler.status == HANDLED_REDIRECTION) {
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while(Connection->HookHandler.status == HANDLED_REWRITE);
|
||||
|
||||
} while (Connection->HookHandler.status == HANDLED_REWRITE);
|
||||
|
||||
// Prepare = NOT_MODIFIED ?
|
||||
if(Connection->HookHandler.httpStatus == HTTP_NOT_MODIFIED)
|
||||
{
|
||||
if (Connection->HookHandler.httpStatus == HTTP_NOT_MODIFIED) {
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// HOOK Handling Loop [ response hook ]
|
||||
// Production
|
||||
//--------------------------------------------------------------
|
||||
if(Connection->HookHandler.status != HANDLED_SENDFILE)
|
||||
do
|
||||
{
|
||||
if(Connection->RequestCanceled)
|
||||
return false;
|
||||
if (Connection->HookHandler.status != HANDLED_SENDFILE)
|
||||
do {
|
||||
if (Connection->RequestCanceled)
|
||||
return false;
|
||||
|
||||
Connection->HookHandler.Hooks_SendResponse();
|
||||
if((Connection->HookHandler.status == HANDLED_READY)||(Connection->HookHandler.status == HANDLED_CONTINUE))
|
||||
{
|
||||
log_level_printf(2,"Response Hook Output. Status:%d\n", Connection->HookHandler.status);
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
if(Connection->Method != M_HEAD)
|
||||
Write(Connection->HookHandler.yresult);
|
||||
if(Connection->HookHandler.status != HANDLED_CONTINUE)
|
||||
return true;
|
||||
}
|
||||
else if(Connection->HookHandler.status == HANDLED_ERROR)
|
||||
{
|
||||
log_level_printf(2,"Response Hook found but Error\n");
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
if(Connection->Method != M_HEAD)
|
||||
Write(Connection->HookHandler.yresult);
|
||||
return false;
|
||||
}
|
||||
else if(Connection->HookHandler.status == HANDLED_ABORT)
|
||||
return false;
|
||||
// URL has new value. Analyze new URL for SendFile
|
||||
else if(Connection->HookHandler.status == HANDLED_SENDFILE ||
|
||||
Connection->HookHandler.status == HANDLED_REWRITE)
|
||||
{
|
||||
Connection->Request.analyzeURL(Connection->HookHandler.NewURL);
|
||||
Connection->HookHandler.UrlData = Connection->Request.UrlData;
|
||||
}
|
||||
if(Connection->HookHandler.status == HANDLED_REDIRECTION)
|
||||
{
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while(Connection->HookHandler.status == HANDLED_REWRITE);
|
||||
Connection->HookHandler.Hooks_SendResponse();
|
||||
if ((Connection->HookHandler.status == HANDLED_READY)
|
||||
|| (Connection->HookHandler.status == HANDLED_CONTINUE)) {
|
||||
log_level_printf(2, "Response Hook Output. Status:%d\n", Connection->HookHandler.status);
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
if (Connection->Method != M_HEAD)
|
||||
Write(Connection->HookHandler.yresult);
|
||||
if (Connection->HookHandler.status != HANDLED_CONTINUE)
|
||||
return true;
|
||||
} else if (Connection->HookHandler.status == HANDLED_ERROR) {
|
||||
log_level_printf(2, "Response Hook found but Error\n");
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
if (Connection->Method != M_HEAD)
|
||||
Write(Connection->HookHandler.yresult);
|
||||
return false;
|
||||
} else if (Connection->HookHandler.status == HANDLED_ABORT)
|
||||
return false;
|
||||
// URL has new value. Analyze new URL for SendFile
|
||||
else if (Connection->HookHandler.status == HANDLED_SENDFILE
|
||||
|| Connection->HookHandler.status == HANDLED_REWRITE) {
|
||||
Connection->Request.analyzeURL(Connection->HookHandler.NewURL);
|
||||
Connection->HookHandler.UrlData = Connection->Request.UrlData;
|
||||
}
|
||||
if (Connection->HookHandler.status == HANDLED_REDIRECTION) {
|
||||
Write(Connection->HookHandler.BuildHeader());
|
||||
return false;
|
||||
}
|
||||
} while (Connection->HookHandler.status == HANDLED_REWRITE);
|
||||
|
||||
// Send static file
|
||||
if(Connection->HookHandler.status == HANDLED_SENDFILE && !Connection->RequestCanceled)
|
||||
{
|
||||
if (Connection->HookHandler.status == HANDLED_SENDFILE
|
||||
&& !Connection->RequestCanceled) {
|
||||
bool cache = true;
|
||||
// if(Connection->HookHandler.UrlData["path"] == "/tmp/")//TODO: un-cachable dirs
|
||||
// cache = false;
|
||||
// if(Connection->HookHandler.UrlData["path"] == "/tmp/")//TODO: un-cachable dirs
|
||||
// cache = false;
|
||||
Write(Connection->HookHandler.BuildHeader(cache));
|
||||
if(Connection->Method != M_HEAD)
|
||||
if (Connection->Method != M_HEAD)
|
||||
Sendfile(Connection->Request.UrlData["url"]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// arrived here? = error!
|
||||
SendError(HTTP_NOT_FOUND);
|
||||
SendError( HTTP_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Output
|
||||
//=============================================================================
|
||||
void CWebserverResponse::SendHeader(HttpResponseType responseType, bool cache, std::string ContentType)
|
||||
{
|
||||
Connection->HookHandler.SetHeader(responseType, ContentType);
|
||||
void CWebserverResponse::SendHeader(HttpResponseType responseType, bool cache,
|
||||
std::string ContentType) {
|
||||
Connection->HookHandler.SetHeader(responseType, ContentType);
|
||||
Write(Connection->HookHandler.BuildHeader(cache));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BASIC Send over Socket for Strings (char*)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverResponse::WriteData(char const * data, long length)
|
||||
{
|
||||
if(Connection->RequestCanceled)
|
||||
bool CWebserverResponse::WriteData(char const * data, long length) {
|
||||
if (Connection->RequestCanceled)
|
||||
return false;
|
||||
if(Connection->sock->Send(data, length) == -1)
|
||||
{
|
||||
log_level_printf(1,"response canceled: %s\n", strerror(errno));
|
||||
if (Connection->sock->Send(data, length) == -1) {
|
||||
log_level_printf(1, "response canceled: %s\n", strerror(errno));
|
||||
Connection->RequestCanceled = true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
#define bufferlen 4*1024
|
||||
void CWebserverResponse::printf ( const char *fmt, ... )
|
||||
{
|
||||
void CWebserverResponse::printf(const char *fmt, ...) {
|
||||
char buffer[bufferlen];
|
||||
va_list arglist;
|
||||
va_start( arglist, fmt );
|
||||
vsnprintf( buffer, bufferlen, fmt, arglist );
|
||||
va_start(arglist, fmt);
|
||||
vsnprintf(buffer, bufferlen, fmt, arglist);
|
||||
va_end(arglist);
|
||||
Write(buffer);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverResponse::Write(char const *text)
|
||||
{
|
||||
bool CWebserverResponse::Write(char const *text) {
|
||||
return WriteData(text, strlen(text));
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverResponse::WriteLn(char const *text)
|
||||
{
|
||||
if(!WriteData(text, strlen(text)))
|
||||
bool CWebserverResponse::WriteLn(char const *text) {
|
||||
if (!WriteData(text, strlen(text)))
|
||||
return false;
|
||||
return WriteData("\r\n",2);
|
||||
return WriteData("\r\n", 2);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverResponse::Sendfile(std::string filename)
|
||||
{
|
||||
if(Connection->RequestCanceled)
|
||||
bool CWebserverResponse::Sendfile(std::string filename) {
|
||||
if (Connection->RequestCanceled)
|
||||
return false;
|
||||
int filed = open( filename.c_str(), O_RDONLY );
|
||||
if(filed != -1 ) //can access file?
|
||||
int filed = open(filename.c_str(), O_RDONLY);
|
||||
if (filed != -1) //can access file?
|
||||
{
|
||||
if(!Connection->sock->SendFile(filed))
|
||||
if (!Connection->sock->SendFile(filed))
|
||||
Connection->RequestCanceled = true;
|
||||
close(filed);
|
||||
}
|
||||
return (filed != -1 );
|
||||
return (filed != -1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Send File: Determine MIME-Type fro File-Extention
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CWebserverResponse::GetContentType(std::string ext)
|
||||
{
|
||||
std::string CWebserverResponse::GetContentType(std::string ext) {
|
||||
std::string ctype = "text/plain";
|
||||
ext = string_tolower(ext);
|
||||
for (unsigned int i = 0;i < (sizeof(MimeFileExtensions)/sizeof(MimeFileExtensions[0])); i++)
|
||||
if (MimeFileExtensions[i].fileext == ext)
|
||||
{
|
||||
for (unsigned int i = 0; i < (sizeof(MimeFileExtensions)
|
||||
/ sizeof(MimeFileExtensions[0])); i++)
|
||||
if (MimeFileExtensions[i].fileext == ext) {
|
||||
ctype = MimeFileExtensions[i].mime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ctype;
|
||||
}
|
||||
|
@@ -32,46 +32,43 @@
|
||||
// Initialization of static variables
|
||||
//=============================================================================
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
SSL_CTX *CySocket::SSL_ctx;
|
||||
std::string CySocket::SSL_pemfile;
|
||||
std::string CySocket::SSL_CA_file;
|
||||
SSL_CTX *CySocket::SSL_ctx;
|
||||
std::string CySocket::SSL_pemfile;
|
||||
std::string CySocket::SSL_CA_file;
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// Constructor & Destructor & Initialization
|
||||
//=============================================================================
|
||||
CySocket::CySocket()
|
||||
: sock(0)
|
||||
{
|
||||
CySocket::CySocket() :
|
||||
sock(0) {
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
ssl = NULL;
|
||||
#endif
|
||||
tv_start_waiting.tv_sec = 0;
|
||||
tv_start_waiting.tv_usec = 0;
|
||||
BytesSend =0;
|
||||
sock = socket(AF_INET,SOCK_STREAM,0);
|
||||
BytesSend = 0;
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
init();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
CySocket::~CySocket()
|
||||
{
|
||||
CySocket::~CySocket() {
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(isSSLSocket && ssl != NULL)
|
||||
SSL_free(ssl);
|
||||
SSL_free(ssl);
|
||||
#endif
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// initialize
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::init(void)
|
||||
{
|
||||
handling = false;
|
||||
isOpened = false;
|
||||
isValid = true;
|
||||
addr_len = sizeof(addr);
|
||||
void CySocket::init(void) {
|
||||
handling = false;
|
||||
isOpened = false;
|
||||
isValid = true;
|
||||
addr_len = sizeof(addr);
|
||||
memset(&addr, 0, addr_len);
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
isSSLSocket = false;
|
||||
isSSLSocket = false;
|
||||
#endif
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -82,13 +79,13 @@ void CySocket::init(void)
|
||||
bool CySocket::initAsSSL(void)
|
||||
{
|
||||
isSSLSocket = true;
|
||||
if (NULL == (ssl = SSL_new(CySocket::SSL_ctx))) // create SSL-socket
|
||||
if (NULL == (ssl = SSL_new(CySocket::SSL_ctx))) // create SSL-socket
|
||||
{
|
||||
aprintf("ySocket:SSL Error: Create SSL_new : %s\n", ERR_error_string(ERR_get_error(), NULL) );
|
||||
return false;
|
||||
}
|
||||
SSL_set_accept_state(ssl); // accept connection
|
||||
if(1 != (SSL_set_fd(ssl, sock))) // associate socket descriptor
|
||||
SSL_set_accept_state(ssl); // accept connection
|
||||
if(1 != (SSL_set_fd(ssl, sock))) // associate socket descriptor
|
||||
if (NULL == (ssl = SSL_new(CySocket::SSL_ctx)))
|
||||
{
|
||||
aprintf("ySocket:SSL Error: Create SSL_new : %s\n", ERR_error_string(ERR_get_error(), NULL) );
|
||||
@@ -102,9 +99,9 @@ bool CySocket::initAsSSL(void)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CySocket::initSSL(void)
|
||||
{
|
||||
SSL_load_error_strings(); // Load SSL Error Strings
|
||||
SSL_library_init(); // Load SSL Library
|
||||
if (0 == RAND_status()) // set Random
|
||||
SSL_load_error_strings(); // Load SSL Error Strings
|
||||
SSL_library_init(); // Load SSL Library
|
||||
if (0 == RAND_status()) // set Random
|
||||
{
|
||||
aprintf("ySocket:SSL got no rand\n");
|
||||
return false;
|
||||
@@ -119,12 +116,12 @@ bool CySocket::initSSL(void)
|
||||
aprintf("ySocket:SSL Error: no pemfile given\n");
|
||||
return false;
|
||||
}
|
||||
if(SSL_CA_file != "") // have a CA?
|
||||
if(1 != SSL_CTX_load_verify_locations(SSL_ctx, SSL_CA_file.c_str(), NULL))
|
||||
{
|
||||
aprintf("ySocket:SSL Error: %s CA-File:%s\n",ERR_error_string(ERR_get_error(), NULL), SSL_CA_file.c_str());
|
||||
return false;
|
||||
}
|
||||
if(SSL_CA_file != "") // have a CA?
|
||||
if(1 != SSL_CTX_load_verify_locations(SSL_ctx, SSL_CA_file.c_str(), NULL))
|
||||
{
|
||||
aprintf("ySocket:SSL Error: %s CA-File:%s\n",ERR_error_string(ERR_get_error(), NULL), SSL_CA_file.c_str());
|
||||
return false;
|
||||
}
|
||||
if(SSL_CTX_use_certificate_file(SSL_ctx, SSL_pemfile.c_str(), SSL_FILETYPE_PEM) < 0)
|
||||
{
|
||||
aprintf("ySocket:SSL Error: %s PEM-File:%s\n",ERR_error_string(ERR_get_error(), NULL), SSL_pemfile.c_str());
|
||||
@@ -147,54 +144,48 @@ bool CySocket::initSSL(void)
|
||||
//=============================================================================
|
||||
// Socket handling
|
||||
//=============================================================================
|
||||
void CySocket::close(void)
|
||||
{
|
||||
if(sock != 0 && sock != INVALID_SOCKET)
|
||||
::close(sock);
|
||||
void CySocket::close(void) {
|
||||
if (sock != 0 && sock != INVALID_SOCKET)
|
||||
::close( sock);
|
||||
#ifndef Y_CONFIG_FEATURE_KEEP_ALIVE
|
||||
sock = 0;
|
||||
#endif
|
||||
isOpened = false;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::shutdown(void)
|
||||
{
|
||||
if(sock != 0 && sock != INVALID_SOCKET)
|
||||
::shutdown(sock,SHUT_RDWR);
|
||||
void CySocket::shutdown(void) {
|
||||
if (sock != 0 && sock != INVALID_SOCKET)
|
||||
::shutdown(sock, SHUT_RDWR);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CySocket::listen(int port, int max_connections)
|
||||
{
|
||||
if(sock == INVALID_SOCKET)
|
||||
bool CySocket::listen(int port, int max_connections) {
|
||||
if (sock == INVALID_SOCKET)
|
||||
return false;
|
||||
|
||||
// set sockaddr for listening
|
||||
sockaddr_in sai;
|
||||
memset(&sai, 0, sizeof(sai));
|
||||
sai.sin_family = AF_INET; // Protocol
|
||||
sai.sin_addr.s_addr = htonl(INADDR_ANY); // No Filter
|
||||
sai.sin_port = htons(port); // Listening Port
|
||||
memset(&sai, 0, sizeof(sai));
|
||||
sai.sin_family = AF_INET; // Protocol
|
||||
sai.sin_addr.s_addr = htonl(INADDR_ANY); // No Filter
|
||||
sai.sin_port = htons(port); // Listening Port
|
||||
|
||||
set_reuse_port(); // Re-Use Port
|
||||
set_reuse_addr(); // Re-Use IP
|
||||
if(bind(sock, (sockaddr *)&sai, sizeof(sockaddr_in)) != SOCKET_ERROR)
|
||||
if(::listen(sock, max_connections) == 0)
|
||||
set_reuse_port(); // Re-Use Port
|
||||
set_reuse_addr(); // Re-Use IP
|
||||
if (bind(sock, (sockaddr *) &sai, sizeof(sockaddr_in)) != SOCKET_ERROR)
|
||||
if (::listen(sock, max_connections) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
CySocket* CySocket::accept()
|
||||
{
|
||||
CySocket* CySocket::accept() {
|
||||
init();
|
||||
SOCKET newSock = ::accept(sock, (sockaddr *) &addr, &addr_len);
|
||||
if(newSock == INVALID_SOCKET)
|
||||
{
|
||||
if (newSock == INVALID_SOCKET) {
|
||||
dperror("accept: invalid socket\n");
|
||||
return NULL;
|
||||
}
|
||||
CySocket *new_ySocket = new CySocket(newSock);
|
||||
if(new_ySocket != NULL)
|
||||
{
|
||||
if (new_ySocket != NULL) {
|
||||
new_ySocket->setAddr(addr);
|
||||
#ifdef TCP_CORK
|
||||
new_ySocket->set_option(IPPROTO_TCP, TCP_CORK);
|
||||
@@ -203,75 +194,67 @@ CySocket* CySocket::accept()
|
||||
#endif
|
||||
}
|
||||
new_ySocket->isOpened = true;
|
||||
// handling = true;
|
||||
// handling = true;
|
||||
return new_ySocket;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CySocket::get_client_ip(void)
|
||||
{
|
||||
std::string CySocket::get_client_ip(void) {
|
||||
return inet_ntoa(addr.sin_addr);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int CySocket::get_accept_port(void)
|
||||
{
|
||||
return (int)ntohs(addr.sin_port);
|
||||
int CySocket::get_accept_port(void) {
|
||||
return (int) ntohs(addr.sin_port);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::setAddr(sockaddr_in _addr)
|
||||
{
|
||||
void CySocket::setAddr(sockaddr_in _addr) {
|
||||
addr = _addr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set Socket Option (return = false = error)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CySocket::set_option(int typ, int option)
|
||||
{
|
||||
bool CySocket::set_option(int typ, int option) {
|
||||
int on = 1;
|
||||
return (setsockopt(sock, typ, option, (char *)&on, sizeof(on)) >= 0);
|
||||
return (setsockopt(sock, typ, option, (char *) &on, sizeof(on)) >= 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set Re-Use Option for Port.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::set_reuse_port()
|
||||
{
|
||||
void CySocket::set_reuse_port() {
|
||||
#ifdef SO_REUSEPORT
|
||||
if(!set_option(SOL_SOCKET, SO_REUSEPORT))
|
||||
dperror("setsockopt(SO_REUSEPORT)\n");
|
||||
dperror("setsockopt(SO_REUSEPORT)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set Re-Use Option for Address.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::set_reuse_addr()
|
||||
{
|
||||
void CySocket::set_reuse_addr() {
|
||||
#ifdef SO_REUSEADDR
|
||||
if(!set_option(SOL_SOCKET, SO_REUSEADDR))
|
||||
dperror("setsockopt(SO_REUSEADDR)\n");
|
||||
dperror("setsockopt(SO_REUSEADDR)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set Keep-Alive Option for Socket.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::set_keep_alive()
|
||||
{
|
||||
void CySocket::set_keep_alive() {
|
||||
#ifdef SO_KEEPALIVE
|
||||
if(!set_option(SOL_SOCKET, SO_KEEPALIVE))
|
||||
dperror("setsockopt(SO_KEEPALIVE)\n");
|
||||
dperror("setsockopt(SO_KEEPALIVE)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set Keep-Alive Option for Socket.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CySocket::set_tcp_nodelay()
|
||||
{
|
||||
void CySocket::set_tcp_nodelay() {
|
||||
#ifdef TCP_NODELAY
|
||||
if(!set_option(IPPROTO_TCP, TCP_NODELAY))
|
||||
dperror("setsockopt(SO_KEEPALIVE)\n");
|
||||
dperror("setsockopt(SO_KEEPALIVE)\n");
|
||||
#endif
|
||||
}
|
||||
//=============================================================================
|
||||
@@ -280,37 +263,34 @@ void CySocket::set_tcp_nodelay()
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read a buffer (normal or SSL)
|
||||
//-----------------------------------------------------------------------------
|
||||
int CySocket::Read(char *buffer, unsigned int length)
|
||||
{
|
||||
int CySocket::Read(char *buffer, unsigned int length) {
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(isSSLSocket)
|
||||
return SSL_read(ssl, buffer, length);
|
||||
return SSL_read(ssl, buffer, length);
|
||||
else
|
||||
#endif
|
||||
return ::read(sock, buffer, length);
|
||||
return ::read(sock, buffer, length);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Send a buffer (normal or SSL)
|
||||
//-----------------------------------------------------------------------------
|
||||
int CySocket::Send(char const *buffer, unsigned int length)
|
||||
{
|
||||
int CySocket::Send(char const *buffer, unsigned int length) {
|
||||
unsigned int len = 0;
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(isSSLSocket)
|
||||
len = SSL_write(ssl, buffer, length);
|
||||
len = SSL_write(ssl, buffer, length);
|
||||
else
|
||||
#endif
|
||||
len = ::send(sock, buffer, length, MSG_NOSIGNAL);
|
||||
if(len > 0)
|
||||
len = ::send(sock, buffer, length, MSG_NOSIGNAL);
|
||||
if (len > 0)
|
||||
BytesSend += len;
|
||||
return len;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Check if Socket was closed by client
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CySocket::CheckSocketOpen()
|
||||
{
|
||||
char buffer[32]={0};
|
||||
bool CySocket::CheckSocketOpen() {
|
||||
char buffer[32] = { 0 };
|
||||
|
||||
#ifdef CONFIG_SYSTEM_CYGWIN
|
||||
return !(recv(sock, buffer, sizeof(buffer), MSG_PEEK | MSG_NOSIGNAL) == 0);
|
||||
@@ -327,9 +307,8 @@ bool CySocket::CheckSocketOpen()
|
||||
// BASIC Send File over Socket for FILE*
|
||||
// fd is an opened FILE-Descriptor
|
||||
//-----------------------------------------------------------------------------
|
||||
int CySocket::SendFile(int filed)
|
||||
{
|
||||
if(!isValid)
|
||||
int CySocket::SendFile(int filed) {
|
||||
if (!isValid)
|
||||
return false;
|
||||
#ifdef Y_CONFIG_HAVE_SENDFILE
|
||||
// does not work with SSL !!!
|
||||
@@ -339,23 +318,21 @@ int CySocket::SendFile(int filed)
|
||||
if((written = ::sendfile(sock,filed,&start,end)) == -1)
|
||||
{
|
||||
perror("sendfile failed\n");
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
BytesSend += written;
|
||||
BytesSend += written;
|
||||
#else
|
||||
char sbuf[1024];
|
||||
unsigned int r=0;
|
||||
while ((r=read(filed, sbuf, 1024)) > 0)
|
||||
{
|
||||
if (Send(sbuf, r) < 0)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
while ((r = read(filed, sbuf, 1024)) > 0) {
|
||||
if (Send(sbuf, r) < 0) {
|
||||
perror("sendfile failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // Y_CONFIG_HAVE_SENDFILE
|
||||
log_level_printf(9,"<Sock:SendFile>: Bytes:%ld\n", BytesSend);
|
||||
log_level_printf(9, "<Sock:SendFile>: Bytes:%ld\n", BytesSend);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -365,107 +342,100 @@ int CySocket::SendFile(int filed)
|
||||
// fd is an opened FILE-Descriptor
|
||||
//-----------------------------------------------------------------------------
|
||||
//TODO: Write upload Progress Informations into a file
|
||||
unsigned int CySocket::ReceiveFileGivenLength(int filed, unsigned int _length)
|
||||
{
|
||||
unsigned int CySocket::ReceiveFileGivenLength(int filed, unsigned int _length) {
|
||||
unsigned int _readbytes = 0;
|
||||
char buffer[RECEIVE_BLOCK_LEN];
|
||||
int retries=0;
|
||||
int retries = 0;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
// check bytes in Socket buffer
|
||||
u_long readarg = 0;
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(isSSLSocket)
|
||||
readarg = RECEIVE_BLOCK_LEN;
|
||||
readarg = RECEIVE_BLOCK_LEN;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(ioctl(sock, FIONREAD, &readarg) != 0)// How many bytes avaiable on socket?
|
||||
break;
|
||||
if(readarg > RECEIVE_BLOCK_LEN) // enough bytes to read
|
||||
readarg = RECEIVE_BLOCK_LEN; // read only given length
|
||||
if (ioctl(sock, FIONREAD, &readarg) != 0)// How many bytes avaiable on socket?
|
||||
break;
|
||||
if (readarg > RECEIVE_BLOCK_LEN) // enough bytes to read
|
||||
readarg = RECEIVE_BLOCK_LEN; // read only given length
|
||||
}
|
||||
if(readarg == 0) // nothing to read: sleep
|
||||
{
|
||||
retries++;
|
||||
if(retries >NON_BLOCKING_MAX_RETRIES)
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readarg == 0) // nothing to read: sleep
|
||||
{
|
||||
retries++;
|
||||
if (retries > NON_BLOCKING_MAX_RETRIES)
|
||||
break;
|
||||
sleep(1);
|
||||
} else {
|
||||
int bytes_gotten = Read(buffer, readarg);
|
||||
|
||||
if(bytes_gotten == -1 && errno == EINTR)// non-blocking
|
||||
continue;
|
||||
if(bytes_gotten <= 0) // ERROR Code gotten or Conection closed by peer
|
||||
if (bytes_gotten == -1 && errno == EINTR)// non-blocking
|
||||
continue;
|
||||
if (bytes_gotten <= 0) // ERROR Code gotten or Conection closed by peer
|
||||
{
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
_readbytes += bytes_gotten;
|
||||
if (write(filed, buffer, bytes_gotten) != bytes_gotten)
|
||||
{
|
||||
if (write(filed, buffer, bytes_gotten) != bytes_gotten) {
|
||||
perror("write file failed\n");
|
||||
return 0;
|
||||
}
|
||||
retries = 0;
|
||||
if(bytes_gotten < NON_BLOCKING_TRY_BYTES) // to few bytes gotten: sleep
|
||||
sleep(1);
|
||||
}
|
||||
log_level_printf(8,"Receive Block length:%d all:%d\n",_readbytes, _length);
|
||||
}
|
||||
while(_readbytes + RECEIVE_BLOCK_LEN < _length);
|
||||
return 0;
|
||||
}
|
||||
retries = 0;
|
||||
if (bytes_gotten < NON_BLOCKING_TRY_BYTES) // to few bytes gotten: sleep
|
||||
sleep(1);
|
||||
}
|
||||
log_level_printf(8, "Receive Block length:%d all:%d\n", _readbytes,
|
||||
_length);
|
||||
} while (_readbytes + RECEIVE_BLOCK_LEN < _length);
|
||||
return _readbytes;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// read all data avaiable on Socket
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CySocket::ReceiveBlock()
|
||||
{
|
||||
std::string CySocket::ReceiveBlock() {
|
||||
std::string result = "";
|
||||
char buffer[RECEIVE_BLOCK_LEN];
|
||||
|
||||
if(!isValid || !isOpened)
|
||||
if (!isValid || !isOpened)
|
||||
return "";
|
||||
// signal(SIGALRM, ytimeout);
|
||||
// signal(SIGALRM, ytimeout);
|
||||
alarm(1);
|
||||
|
||||
while(true)
|
||||
{
|
||||
while (true) {
|
||||
// check bytes in Socket buffer
|
||||
u_long readarg = 0;
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(isSSLSocket)
|
||||
readarg = RECEIVE_BLOCK_LEN;
|
||||
readarg = RECEIVE_BLOCK_LEN;
|
||||
else
|
||||
#endif
|
||||
// determine bytes that can be read
|
||||
{
|
||||
if(ioctl(sock, FIONREAD, &readarg) != 0)
|
||||
break;
|
||||
if(readarg == 0) // nothing to read
|
||||
break;
|
||||
if(readarg > RECEIVE_BLOCK_LEN) // need more loops
|
||||
readarg = RECEIVE_BLOCK_LEN;
|
||||
if (ioctl(sock, FIONREAD, &readarg) != 0)
|
||||
break;
|
||||
if (readarg == 0) // nothing to read
|
||||
break;
|
||||
if (readarg > RECEIVE_BLOCK_LEN) // need more loops
|
||||
readarg = RECEIVE_BLOCK_LEN;
|
||||
}
|
||||
// Read data
|
||||
int bytes_gotten = Read(buffer, readarg);
|
||||
|
||||
if(bytes_gotten == -1 && errno == EINTR)// non-blocking
|
||||
continue;
|
||||
if(bytes_gotten <= 0) // ERROR Code gotten or Conection closed by peer
|
||||
if (bytes_gotten == -1 && errno == EINTR)// non-blocking
|
||||
continue;
|
||||
if (bytes_gotten <= 0) // ERROR Code gotten or Conection closed by peer
|
||||
{
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
result.append(buffer, bytes_gotten);
|
||||
if((u_long)bytes_gotten < readarg) // no more bytes
|
||||
if ((u_long) bytes_gotten < readarg) // no more bytes
|
||||
break;
|
||||
}
|
||||
alarm(0);
|
||||
signal(SIGALRM,SIG_IGN);
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -473,28 +443,23 @@ std::string CySocket::ReceiveBlock()
|
||||
// Read on line (Ends with LF) or maximum MAX_LINE_BUFFER chars
|
||||
// Result Contains [CR]LF!
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CySocket::ReceiveLine()
|
||||
{
|
||||
std::string CySocket::ReceiveLine() {
|
||||
char buffer[MAX_LINE_BUFFER];
|
||||
int bytes_gotten = 0;
|
||||
std::string result="";
|
||||
std::string result = "";
|
||||
|
||||
while(true)
|
||||
{
|
||||
while (true) {
|
||||
// read one char
|
||||
if(Read(buffer+bytes_gotten, 1) == 1)
|
||||
{
|
||||
if(buffer[bytes_gotten] == '\n')
|
||||
if (Read(buffer + bytes_gotten, 1) == 1) {
|
||||
if (buffer[bytes_gotten] == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bytes_gotten < MAX_LINE_BUFFER-1)
|
||||
bytes_gotten ++;
|
||||
if (bytes_gotten < MAX_LINE_BUFFER - 1)
|
||||
bytes_gotten++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
@@ -30,21 +30,20 @@
|
||||
//=============================================================================
|
||||
// Initialization of static variables
|
||||
//=============================================================================
|
||||
bool CWebserver::is_threading = true;
|
||||
pthread_mutex_t CWebserver::mutex = PTHREAD_MUTEX_INITIALIZER;;
|
||||
bool CWebserver::is_threading = true;
|
||||
pthread_mutex_t CWebserver::mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
;
|
||||
|
||||
//=============================================================================
|
||||
// Constructor & Destructor & Initialization
|
||||
//=============================================================================
|
||||
CWebserver::CWebserver()
|
||||
{
|
||||
CWebserver::CWebserver() {
|
||||
terminate = false;
|
||||
for(int i=0;i<HTTPD_MAX_CONNECTIONS;i++)
|
||||
{
|
||||
Connection_Thread_List[i] = (pthread_t)NULL;
|
||||
for (int i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {
|
||||
Connection_Thread_List[i] = (pthread_t) NULL;
|
||||
SocketList[i] = NULL;
|
||||
}
|
||||
FD_ZERO(&master); // initialize FD_SETs
|
||||
FD_ZERO(&master); // initialize FD_SETs
|
||||
FD_ZERO(&read_fds);
|
||||
fdmax = 0;
|
||||
open_connections = 0;
|
||||
@@ -52,13 +51,11 @@ CWebserver::CWebserver()
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
#endif
|
||||
port=80;
|
||||
|
||||
port = 80;
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
CWebserver::~CWebserver()
|
||||
{
|
||||
CWebserver::~CWebserver() {
|
||||
listenSocket.close();
|
||||
}
|
||||
//=============================================================================
|
||||
@@ -118,10 +115,8 @@ CWebserver::~CWebserver()
|
||||
//=============================================================================
|
||||
#define MAX_TIMEOUTS_TO_CLOSE 10
|
||||
#define MAX_TIMEOUTS_TO_TEST 100
|
||||
bool CWebserver::run(void)
|
||||
{
|
||||
if(!listenSocket.listen(port, HTTPD_MAX_CONNECTIONS))
|
||||
{
|
||||
bool CWebserver::run(void) {
|
||||
if (!listenSocket.listen(port, HTTPD_MAX_CONNECTIONS)) {
|
||||
dperror("Socket cannot bind and listen. Abort.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -129,31 +124,31 @@ bool CWebserver::run(void)
|
||||
|
||||
// initialize values for select
|
||||
int listener = listenSocket.get_socket();// Open Listener
|
||||
struct timeval tv; // timeout struct
|
||||
FD_SET(listener, &master); // add the listener to the master set
|
||||
fdmax = listener; // init max fd
|
||||
fcntl(listener, F_SETFD , O_NONBLOCK); // listener master socket non-blocking
|
||||
int timeout_counter = 0; // Counter for Connection Timeout checking
|
||||
int test_counter = 0; // Counter for Testing long running Connections
|
||||
struct timeval tv; // timeout struct
|
||||
FD_SET(listener, &master); // add the listener to the master set
|
||||
fdmax = listener; // init max fd
|
||||
fcntl(listener, F_SETFD , O_NONBLOCK); // listener master socket non-blocking
|
||||
int timeout_counter = 0; // Counter for Connection Timeout checking
|
||||
int test_counter = 0; // Counter for Testing long running Connections
|
||||
|
||||
// main Webserver Loop
|
||||
while(!terminate)
|
||||
{
|
||||
// select : init vars
|
||||
read_fds = master; // copy it
|
||||
tv.tv_usec = 10000; // microsec: Timeout for select ! for re-use / keep-alive socket
|
||||
tv.tv_sec = 0; // seconds
|
||||
int fd = -1;
|
||||
read_fds = master; // copy it
|
||||
tv.tv_usec = 10000; // microsec: Timeout for select ! for re-use / keep-alive socket
|
||||
tv.tv_sec = 0; // seconds
|
||||
int fd = -1;
|
||||
|
||||
// select : wait for socket activity
|
||||
if(open_connections <= 0) // No open Connection. Wait in select.
|
||||
fd = select(fdmax+1,&read_fds, NULL, NULL, NULL);// wait for socket activity
|
||||
if(open_connections <= 0) // No open Connection. Wait in select.
|
||||
fd = select(fdmax+1,&read_fds, NULL, NULL, NULL);// wait for socket activity
|
||||
else
|
||||
fd = select(fdmax+1,&read_fds, NULL, NULL, &tv);// wait for socket activity or timeout
|
||||
fd = select(fdmax+1,&read_fds, NULL, NULL, &tv);// wait for socket activity or timeout
|
||||
|
||||
// too much to do : sleep
|
||||
if(open_connections >= HTTPD_MAX_CONNECTIONS-1)
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
|
||||
// Socket Error?
|
||||
if(fd == -1 && errno != EINTR)
|
||||
@@ -169,9 +164,9 @@ bool CWebserver::run(void)
|
||||
if(++test_counter >= MAX_TIMEOUTS_TO_TEST)
|
||||
{
|
||||
for(int j=0;j < HTTPD_MAX_CONNECTIONS;j++)
|
||||
if(SocketList[j] != NULL) // here is a socket
|
||||
log_level_printf(2,"FD-TEST sock:%d handle:%d open:%d\n",SocketList[j]->get_socket(),
|
||||
SocketList[j]->handling,SocketList[j]->isOpened);
|
||||
if(SocketList[j] != NULL) // here is a socket
|
||||
log_level_printf(2,"FD-TEST sock:%d handle:%d open:%d\n",SocketList[j]->get_socket(),
|
||||
SocketList[j]->handling,SocketList[j]->isOpened);
|
||||
test_counter=0;
|
||||
}
|
||||
// some connection closing previous missed?
|
||||
@@ -180,7 +175,7 @@ bool CWebserver::run(void)
|
||||
CloseConnectionSocketsByTimeout();
|
||||
timeout_counter=0;
|
||||
}
|
||||
continue; // main loop again
|
||||
continue; // main loop again
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Check all observed descriptors & check new or re-use Connections
|
||||
@@ -188,48 +183,48 @@ bool CWebserver::run(void)
|
||||
for(int i = listener; i <= fdmax; i++)
|
||||
{
|
||||
int slot = -1;
|
||||
if(FD_ISSET(i, &read_fds)) // Socket observed?
|
||||
if(FD_ISSET(i, &read_fds)) // Socket observed?
|
||||
{ // we got one!!
|
||||
if (i == listener) // handle new connections
|
||||
slot = AcceptNewConnectionSocket();
|
||||
else // Connection on an existing open Socket = reuse (keep-alive)
|
||||
if (i == listener) // handle new connections
|
||||
slot = AcceptNewConnectionSocket();
|
||||
else // Connection on an existing open Socket = reuse (keep-alive)
|
||||
{
|
||||
slot = SL_GetExistingSocket(i);
|
||||
if(slot>=0)
|
||||
log_level_printf(2,"FD: reuse con fd:%d\n",SocketList[slot]->get_socket());
|
||||
log_level_printf(2,"FD: reuse con fd:%d\n",SocketList[slot]->get_socket());
|
||||
}
|
||||
// prepare Connection handling
|
||||
if(slot>=0)
|
||||
if(SocketList[slot] != NULL && !SocketList[slot]->handling && SocketList[slot]->isValid)
|
||||
{
|
||||
log_level_printf(2,"FD: START CON HANDLING con fd:%d\n",SocketList[slot]->get_socket());
|
||||
FD_CLR(SocketList[slot]->get_socket(), &master); // remove from master set
|
||||
SocketList[slot]->handling = true; // prepares for thread-handling
|
||||
if(!handle_connection(SocketList[slot]))// handle this activity
|
||||
{ // Can not handle more threads
|
||||
char httpstr[]=HTTP_PROTOCOL " 503 Service Unavailable\r\n\r\n";
|
||||
SocketList[slot]->Send(httpstr, strlen(httpstr));
|
||||
SL_CloseSocketBySlot(slot);
|
||||
}
|
||||
if(SocketList[slot] != NULL && !SocketList[slot]->handling && SocketList[slot]->isValid)
|
||||
{
|
||||
log_level_printf(2,"FD: START CON HANDLING con fd:%d\n",SocketList[slot]->get_socket());
|
||||
FD_CLR(SocketList[slot]->get_socket(), &master); // remove from master set
|
||||
SocketList[slot]->handling = true; // prepares for thread-handling
|
||||
if(!handle_connection(SocketList[slot]))// handle this activity
|
||||
{ // Can not handle more threads
|
||||
char httpstr[]=HTTP_PROTOCOL " 503 Service Unavailable\r\n\r\n";
|
||||
SocketList[slot]->Send(httpstr, strlen(httpstr));
|
||||
SL_CloseSocketBySlot(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}// for
|
||||
CloseConnectionSocketsByTimeout(); // Check connections to close
|
||||
CloseConnectionSocketsByTimeout(); // Check connections to close
|
||||
|
||||
}//while
|
||||
#else
|
||||
while(!terminate)
|
||||
{
|
||||
while (!terminate) {
|
||||
CySocket *newConnectionSock;
|
||||
if(!(newConnectionSock = listenSocket.accept() )) //Now: Blocking wait
|
||||
if (!(newConnectionSock = listenSocket.accept())) //Now: Blocking wait
|
||||
{
|
||||
dperror("Socket accept error. Continue.\n");
|
||||
continue;
|
||||
}
|
||||
log_level_printf(3,"Socket connect from %s\n", (listenSocket.get_client_ip()).c_str() );
|
||||
log_level_printf(3, "Socket connect from %s\n",
|
||||
(listenSocket.get_client_ip()).c_str());
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(Cyhttpd::ConfigList["SSL"]=="true")
|
||||
newConnectionSock->initAsSSL(); // make it a SSL-socket
|
||||
if(Cyhttpd::ConfigList["SSL"]=="true")
|
||||
newConnectionSock->initAsSSL(); // make it a SSL-socket
|
||||
#endif
|
||||
handle_connection(newConnectionSock);
|
||||
}
|
||||
@@ -242,13 +237,12 @@ bool CWebserver::run(void)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accept new Connection
|
||||
//-----------------------------------------------------------------------------
|
||||
int CWebserver::AcceptNewConnectionSocket()
|
||||
{
|
||||
int CWebserver::AcceptNewConnectionSocket() {
|
||||
int slot = -1;
|
||||
CySocket *connectionSock = NULL;
|
||||
int newfd;
|
||||
|
||||
if(!(connectionSock = listenSocket.accept() )) // Blocking wait
|
||||
if (!(connectionSock = listenSocket.accept())) // Blocking wait
|
||||
{
|
||||
dperror("Socket accept error. Continue.\n");
|
||||
delete connectionSock;
|
||||
@@ -256,24 +250,22 @@ int CWebserver::AcceptNewConnectionSocket()
|
||||
}
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
if(Cyhttpd::ConfigList["SSL"]=="true")
|
||||
connectionSock->initAsSSL(); // make it a SSL-socket
|
||||
connectionSock->initAsSSL(); // make it a SSL-socket
|
||||
#endif
|
||||
log_level_printf(2,"FD: new con fd:%d on port:%d\n",connectionSock->get_socket(), connectionSock->get_accept_port());
|
||||
log_level_printf(2, "FD: new con fd:%d on port:%d\n",
|
||||
connectionSock->get_socket(), connectionSock->get_accept_port());
|
||||
|
||||
// Add Socket to List
|
||||
slot = SL_GetFreeSlot();
|
||||
if(slot < 0)
|
||||
{
|
||||
if (slot < 0) {
|
||||
connectionSock->close();
|
||||
aprintf("No free Slot in SocketList found. Open:%d\n",open_connections);
|
||||
}
|
||||
else
|
||||
{
|
||||
SocketList[slot] = connectionSock; // put it to list
|
||||
fcntl(connectionSock->get_socket() , F_SETFD , O_NONBLOCK); // set non-blocking
|
||||
open_connections++; // count open connectins
|
||||
aprintf("No free Slot in SocketList found. Open:%d\n", open_connections);
|
||||
} else {
|
||||
SocketList[slot] = connectionSock; // put it to list
|
||||
fcntl(connectionSock->get_socket(), F_SETFD, O_NONBLOCK); // set non-blocking
|
||||
open_connections++; // count open connectins
|
||||
newfd = connectionSock->get_socket();
|
||||
if (newfd > fdmax) // keep track of the maximum fd
|
||||
if (newfd > fdmax) // keep track of the maximum fd
|
||||
fdmax = newfd;
|
||||
}
|
||||
return slot;
|
||||
@@ -282,12 +274,11 @@ int CWebserver::AcceptNewConnectionSocket()
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get Index for Socket from SocketList
|
||||
//-----------------------------------------------------------------------------
|
||||
int CWebserver::SL_GetExistingSocket(SOCKET sock)
|
||||
{
|
||||
int CWebserver::SL_GetExistingSocket(SOCKET sock) {
|
||||
int slot = -1;
|
||||
for(int j=0;j < HTTPD_MAX_CONNECTIONS;j++)
|
||||
if(SocketList[j] != NULL // here is a socket
|
||||
&& SocketList[j]->get_socket() == sock) // we know that socket
|
||||
for (int j = 0; j < HTTPD_MAX_CONNECTIONS; j++)
|
||||
if (SocketList[j] != NULL // here is a socket
|
||||
&& SocketList[j]->get_socket() == sock) // we know that socket
|
||||
{
|
||||
slot = j;
|
||||
break;
|
||||
@@ -297,11 +288,10 @@ int CWebserver::SL_GetExistingSocket(SOCKET sock)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get Index for free Slot in SocketList
|
||||
//-----------------------------------------------------------------------------
|
||||
int CWebserver::SL_GetFreeSlot()
|
||||
{
|
||||
int CWebserver::SL_GetFreeSlot() {
|
||||
int slot = -1;
|
||||
for(int j=0;j < HTTPD_MAX_CONNECTIONS;j++)
|
||||
if(SocketList[j] == NULL) // here is a free slot
|
||||
for (int j = 0; j < HTTPD_MAX_CONNECTIONS; j++)
|
||||
if (SocketList[j] == NULL) // here is a free slot
|
||||
{
|
||||
slot = j;
|
||||
break;
|
||||
@@ -312,67 +302,65 @@ int CWebserver::SL_GetFreeSlot()
|
||||
//-----------------------------------------------------------------------------
|
||||
// Look for Sockets to close
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWebserver::CloseConnectionSocketsByTimeout()
|
||||
{
|
||||
void CWebserver::CloseConnectionSocketsByTimeout() {
|
||||
CySocket *connectionSock = NULL;
|
||||
for(int j=0;j < HTTPD_MAX_CONNECTIONS;j++)
|
||||
if(SocketList[j] != NULL // here is a socket
|
||||
&& !SocketList[j]->handling) // it is not handled
|
||||
{
|
||||
connectionSock = SocketList[j];
|
||||
SOCKET thisSocket = connectionSock->get_socket();
|
||||
bool shouldClose = true;
|
||||
|
||||
if(!connectionSock->isValid) // If not valid -> close
|
||||
; // close
|
||||
else if(connectionSock->tv_start_waiting.tv_sec != 0 || SocketList[j]->tv_start_waiting.tv_usec != 0)
|
||||
{ // calculate keep-alive timeout
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
int64_t tdiff = ((tv_now.tv_sec - connectionSock->tv_start_waiting.tv_sec) * 1000000
|
||||
+ (tv_now.tv_usec - connectionSock->tv_start_waiting.tv_usec));
|
||||
if(tdiff < HTTPD_KEEPALIVE_TIMEOUT || tdiff <0)
|
||||
shouldClose = false;
|
||||
}
|
||||
if(shouldClose)
|
||||
for (int j = 0; j < HTTPD_MAX_CONNECTIONS; j++)
|
||||
if (SocketList[j] != NULL // here is a socket
|
||||
&& !SocketList[j]->handling) // it is not handled
|
||||
{
|
||||
log_level_printf(2,"FD: close con Timeout fd:%d\n",thisSocket);
|
||||
SL_CloseSocketBySlot(j);
|
||||
connectionSock = SocketList[j];
|
||||
SOCKET thisSocket = connectionSock->get_socket();
|
||||
bool shouldClose = true;
|
||||
|
||||
if (!connectionSock->isValid) // If not valid -> close
|
||||
; // close
|
||||
else if (connectionSock->tv_start_waiting.tv_sec != 0
|
||||
|| SocketList[j]->tv_start_waiting.tv_usec != 0) { // calculate keep-alive timeout
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
int64_t tdiff = ((tv_now.tv_sec
|
||||
- connectionSock->tv_start_waiting.tv_sec) * 1000000
|
||||
+ (tv_now.tv_usec
|
||||
- connectionSock->tv_start_waiting.tv_usec));
|
||||
if (tdiff < HTTPD_KEEPALIVE_TIMEOUT || tdiff < 0)
|
||||
shouldClose = false;
|
||||
}
|
||||
if (shouldClose) {
|
||||
log_level_printf(2, "FD: close con Timeout fd:%d\n", thisSocket);
|
||||
SL_CloseSocketBySlot(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Add Socket fd to FD_SET again (for select-handling)
|
||||
// Add start-time for waiting for connection re-use / keep-alive
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWebserver::addSocketToMasterSet(SOCKET fd)
|
||||
{
|
||||
int slot = SL_GetExistingSocket(fd); // get slot/index for fd
|
||||
if(slot<0)
|
||||
void CWebserver::addSocketToMasterSet(SOCKET fd) {
|
||||
int slot = SL_GetExistingSocket(fd); // get slot/index for fd
|
||||
if (slot < 0)
|
||||
return;
|
||||
log_level_printf(2,"FD: add to master fd:%d\n",fd);
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
log_level_printf(2, "FD: add to master fd:%d\n", fd);
|
||||
struct timeval tv_now;
|
||||
struct timezone tz_now;
|
||||
gettimeofday(&tv_now, &tz_now);
|
||||
SocketList[slot]->tv_start_waiting = tv_now; // add keep-alive wait time
|
||||
FD_SET(fd, &master); // add fd to select-master-set
|
||||
SocketList[slot]->tv_start_waiting = tv_now; // add keep-alive wait time
|
||||
FD_SET(fd, &master); // add fd to select-master-set
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Close (FD_SET handled) Socket
|
||||
// Clear it from SocketList
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWebserver::SL_CloseSocketBySlot(int slot)
|
||||
{
|
||||
open_connections--; // count open connections
|
||||
if(SocketList[slot] == NULL)
|
||||
void CWebserver::SL_CloseSocketBySlot(int slot) {
|
||||
open_connections--; // count open connections
|
||||
if (SocketList[slot] == NULL)
|
||||
return;
|
||||
SocketList[slot]->handling = false; // no handling anymore
|
||||
SocketList[slot]->handling = false; // no handling anymore
|
||||
FD_CLR(SocketList[slot]->get_socket(), &master);// remove from master set
|
||||
SocketList[slot]->close(); // close the socket
|
||||
delete SocketList[slot]; // destroy ySocket
|
||||
SocketList[slot] = NULL; // free in list
|
||||
SocketList[slot]->close(); // close the socket
|
||||
delete SocketList[slot]; // destroy ySocket
|
||||
SocketList[slot] = NULL; // free in list
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@@ -381,38 +369,34 @@ void CWebserver::SL_CloseSocketBySlot(int slot)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Check if IP is allowed for keep-alive
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserver::CheckKeepAliveAllowedByIP(std::string client_ip)
|
||||
{
|
||||
pthread_mutex_lock( &mutex );
|
||||
bool CWebserver::CheckKeepAliveAllowedByIP(std::string client_ip) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
bool do_keep_alive = true;
|
||||
CStringVector::const_iterator it = conf_no_keep_alive_ips.begin();
|
||||
while(it != conf_no_keep_alive_ips.end())
|
||||
{
|
||||
if(trim(*it) == client_ip)
|
||||
while (it != conf_no_keep_alive_ips.end()) {
|
||||
if (trim(*it) == client_ip)
|
||||
do_keep_alive = false;
|
||||
it++;
|
||||
}
|
||||
pthread_mutex_unlock( &mutex );
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return do_keep_alive;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set Entry(number)to NULL in Threadlist
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWebserver::clear_Thread_List_Number(int number)
|
||||
{
|
||||
pthread_mutex_lock( &mutex );
|
||||
if(number <HTTPD_MAX_CONNECTIONS)
|
||||
Connection_Thread_List[number] = (pthread_t)NULL;
|
||||
void CWebserver::clear_Thread_List_Number(int number) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (number < HTTPD_MAX_CONNECTIONS)
|
||||
Connection_Thread_List[number] = (pthread_t) NULL;
|
||||
CloseConnectionSocketsByTimeout();
|
||||
pthread_mutex_unlock( &mutex );
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A new Connection is established to newSock. Create a (threaded) Connection
|
||||
// and handle the Request.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserver::handle_connection(CySocket *newSock)
|
||||
{
|
||||
bool CWebserver::handle_connection(CySocket *newSock) {
|
||||
void *WebThread(void *args); //forward declaration
|
||||
|
||||
// create arguments
|
||||
@@ -432,56 +416,56 @@ bool CWebserver::handle_connection(CySocket *newSock)
|
||||
pthread_mutex_lock( &mutex );
|
||||
// look for free Thread slot
|
||||
for(int i=0;i<HTTPD_MAX_CONNECTIONS;i++)
|
||||
if(Connection_Thread_List[i] == (pthread_t)NULL)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if(Connection_Thread_List[i] == (pthread_t)NULL)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if(index == -1)
|
||||
{
|
||||
dperror("Maximum Connection-Threads reached\n");
|
||||
pthread_mutex_unlock( &mutex );
|
||||
return false;
|
||||
}
|
||||
newConn->thread_number = index; //remember Index of Thread slot (for clean up)
|
||||
newConn->thread_number = index; //remember Index of Thread slot (for clean up)
|
||||
|
||||
// Create an orphan Thread. It is not joinable anymore
|
||||
pthread_mutex_unlock( &mutex );
|
||||
|
||||
// start connection Thread
|
||||
if(pthread_create(&Connection_Thread_List[index], &attr, WebThread, (void *)newConn) != 0)
|
||||
dperror("Could not create Connection-Thread\n");
|
||||
dperror("Could not create Connection-Thread\n");
|
||||
}
|
||||
else // non threaded
|
||||
else // non threaded
|
||||
#endif
|
||||
WebThread((void *)newConn);
|
||||
WebThread((void *) newConn);
|
||||
return ((index != -1) || !is_threading);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// Webserver-Thread for each connection
|
||||
//-------------------------------------------------------------------------
|
||||
void *WebThread(void *args)
|
||||
{
|
||||
void *WebThread(void *args) {
|
||||
CWebserverConnection *con;
|
||||
CWebserver *ws;
|
||||
TWebserverConnectionArgs *newConn = (TWebserverConnectionArgs *) args;
|
||||
ws = newConn->WebserverBackref;
|
||||
|
||||
bool is_threaded = newConn->is_treaded;
|
||||
if(is_threaded)
|
||||
log_level_printf(1,"++ Thread 0x06%X gestartet\n", (int) pthread_self());
|
||||
if (is_threaded)
|
||||
log_level_printf(1, "++ Thread 0x06%X gestartet\n",
|
||||
(int) pthread_self());
|
||||
|
||||
if (!newConn) {
|
||||
dperror("WebThread called without arguments!\n");
|
||||
if(newConn->is_treaded)
|
||||
pthread_exit(NULL);
|
||||
if (newConn->is_treaded)
|
||||
pthread_exit( NULL);
|
||||
}
|
||||
|
||||
// (1) create & init Connection
|
||||
con = new CWebserverConnection(ws);
|
||||
con->Request.UrlData["clientaddr"] = newConn->ySock->get_client_ip(); // TODO:here?
|
||||
con->sock = newConn->ySock; // give socket reference
|
||||
newConn->ySock->handling = true; // dont handle this socket now be webserver main loop
|
||||
con->sock = newConn->ySock; // give socket reference
|
||||
newConn->ySock->handling = true; // dont handle this socket now be webserver main loop
|
||||
|
||||
// (2) handle the connection
|
||||
con->HandleConnection();
|
||||
@@ -489,25 +473,24 @@ void *WebThread(void *args)
|
||||
// (3) end connection handling
|
||||
#ifdef Y_CONFIG_FEATURE_KEEP_ALIVE
|
||||
if(!con->keep_alive)
|
||||
log_level_printf(2,"FD SHOULD CLOSE sock:%d!!!\n",con->sock->get_socket());
|
||||
log_level_printf(2,"FD SHOULD CLOSE sock:%d!!!\n",con->sock->get_socket());
|
||||
else
|
||||
ws->addSocketToMasterSet(con->sock->get_socket()); // add to master set
|
||||
ws->addSocketToMasterSet(con->sock->get_socket()); // add to master set
|
||||
#else
|
||||
delete newConn->ySock;
|
||||
#endif
|
||||
if(!con->keep_alive)
|
||||
if (!con->keep_alive)
|
||||
con->sock->isValid = false;
|
||||
con->sock->handling = false; // socket can be handled by webserver main loop (select) again
|
||||
con->sock->handling = false; // socket can be handled by webserver main loop (select) again
|
||||
|
||||
// (4) end thread
|
||||
delete con;
|
||||
int thread_number = newConn->thread_number;
|
||||
delete newConn;
|
||||
if(is_threaded)
|
||||
{
|
||||
log_level_printf(1,"-- Thread 0x06%X beendet\n",(int)pthread_self());
|
||||
if (is_threaded) {
|
||||
log_level_printf(1, "-- Thread 0x06%X beendet\n", (int) pthread_self());
|
||||
ws->clear_Thread_List_Number(thread_number);
|
||||
pthread_exit(NULL);
|
||||
pthread_exit( NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user