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:
yjogol
2010-02-25 20:00:09 +00:00
parent eabc0f1644
commit bad0521f6c
30 changed files with 1711 additions and 1905 deletions

View File

@@ -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;
}