Created
October 26, 2012 10:40
-
-
Save freecnjet/3958117 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <WinSock2.h> | |
#include "HttpServer.hpp" | |
#define HTTP_HEADER_BUFSIZE 1024 | |
#define MAX_REQUEST_BACKLOG 64 | |
static DWORD WINAPI ListenThreadFunction( LPVOID lpParam ); | |
namespace WebServer | |
{ | |
class Win32HTTPServer : public HTTPServer | |
{ | |
public: | |
Win32HTTPServer(); | |
virtual ~Win32HTTPServer(); | |
int Start(unsigned short port); | |
int Stop(); | |
bool IsListening(); | |
void SetHTTPConnectResponser(HTTPConnectResponser* responser); | |
void SetHTTPGETResponser(HTTPGETResponser* responser); | |
/////////////////////////////////////////// | |
// call by listen thread | |
void WaitInternal(); | |
private: | |
SOCKET m_ListenSocket; | |
HANDLE m_hTread; | |
HTTPConnectResponser* m_ConnectResponser; | |
HTTPGETResponser* m_GETResponser; | |
void ResultInternal(SOCKET client, int result, const char* content_type, const char* content, size_t content_len ); | |
}; | |
Win32HTTPServer::Win32HTTPServer():m_ListenSocket(INVALID_SOCKET), m_hTread(NULL) | |
{ | |
} | |
Win32HTTPServer::~Win32HTTPServer() | |
{ | |
if( IsListening ) { | |
Stop(); | |
} | |
} | |
bool Win32HTTPServer::IsListening() | |
{ | |
return INVALID_SOCKET!=m_ListenSocket; | |
} | |
void Win32HTTPServer::ResultInternal(SOCKET client, int result, const char* content_type, const char* content, size_t content_len ) | |
{ | |
assert( INVALID_SOCKET!=client ); | |
char buffer[HTTP_HEADER_BUFSIZE+1]; | |
sprintf_s(buffer, HTTP_HEADER_BUFSIZE, "HTTP/1.1 200 OK\nServer: httpserver0.1\nContent-Length: %ld\nConnection: close\nContent-Type: %s\n\n%s", SizeToSend, "text/html", hello ); | |
return; | |
} | |
int Win32HTTPServer::Start(unsigned short port) | |
{ | |
if( IsListening ) { | |
Stop(); | |
} | |
int ret = 0; | |
while( true ) | |
{ | |
m_ListenSocket = socket( AF_INET, SOCK_STREAM, 0 ); | |
if( INVALID_SOCKET==m_ListenSocket ) | |
{ | |
ret = -1; | |
break; | |
} | |
struct sockaddr_in serv_addr; | |
memset(&serv_addr, 0, sizeof(serv_addr)); | |
serv_addr.sin_family = AF_INET; | |
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
serv_addr.sin_port = htons(port); | |
if( bind(m_ListenSocket, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0 ) { | |
ret = -2; | |
break; | |
} | |
if( listen(m_ListenSocket, MAX_REQUEST_BACKLOG) < 0 ) { | |
ret = -3; | |
break; | |
} | |
DWORD dwThreadID; | |
m_hTread = CreateThread(NULL, 0, ListenThreadFunction, static_cast<LPVOID(this), 0, &dwThreadID ); | |
if( NULL==m_hTread ) { | |
ret = -4; | |
break; | |
} | |
return 0; | |
} | |
// error | |
if( m_ListenSocket ) { | |
closesocket(m_ListenSocket); | |
m_ListenSocket = NULL; | |
} | |
return ret; | |
} | |
void Win32HTTPServer::WaitInternal() | |
{ | |
char geturl[MAX_HTTP_URL_PATH_SIZE+1]; | |
char buffer[HTTP_HEADER_BUFSIZE+1]; | |
struct sockaddr_in client_addr; | |
int length = sizeof(client_addr); | |
while( true ) | |
{ | |
Sleep(1); | |
SOCKET client_socket = accept(m_ListenSocket, (struct sockaddr *)&client_addr, &length); | |
if( INVALID_SOCKET==client_socket ) | |
continue; | |
m_ConnectResponser->ClientConnected(); | |
long recved = 0; | |
geturl[0] = '\0'; | |
char* pword = &geturl[0]; | |
bool got_get = false; | |
do { | |
recved = recv(client_socket, buffer, HTTP_HEADER_BUFSIZE, 0); | |
if( 0>=recved ) | |
break; | |
buffer[recved] = '\0'; | |
// parser HTTP header | |
for( char* pchar=&buffer[0]; *pchar; ++pchar ) | |
{ | |
if( '\r'==*pchar ) { | |
continue; | |
} | |
// end of a word | |
if( ' '==*pchar || '\n'==*pchar ) | |
{ | |
*pword = '\0'; | |
if( got_get ) { // this should be GET url path | |
break; // GET url path | |
} | |
// blank line, end of header | |
if( 0==strlen(geturl) ){ | |
break; | |
} | |
// GET head | |
if( 0==strncmp(geturl, "GET", 3) ) { | |
got_get = true; | |
} | |
geturl[0] = '\0'; | |
pword = &geturl[0]; | |
continue; | |
} | |
*(pword++) = *pchar; | |
} | |
} while( recved>0 ); | |
// no GET head or GET url path not set | |
if( 0==strlen(geturl) ) { | |
//logger(FORBIDDEN,"Only simple GET operation supported",buffer,fd); | |
} else { | |
HTTPGETContext get_context; | |
strcpy(get_context.m_Path, geturl); | |
int get_ret = m_GETResponser->Get(&get_context); | |
switch( get_ret ) | |
{ | |
case EWebServerStatus_OK: | |
break; | |
case EWebServerStatus_BadRequest: | |
break; | |
case EWebServerStatus_Forbidden: | |
break; | |
case EWebServerStatus_InternalServerError: | |
break; | |
} | |
} | |
closesocket(client_socket); | |
m_ConnectResponser->ClientDisconnected(); | |
} | |
} | |
int Win32HTTPServer::Stop() | |
{ | |
if( m_hTread ) { | |
TerminateThread(m_hTread); | |
m_hTread = NULL; | |
} | |
if( INVALID_SOCKET!=m_ListenSocket ) { | |
int ret = shutdown(m_ListenSocket, SD_BOTH); | |
assert(0==ret); | |
int ret = closesocket(m_ListenSocket); | |
assert(0==ret); | |
m_ListenSocket = INVALID_SOCKET; | |
} | |
return 0; | |
} | |
void Win32HTTPServer::SetHTTPConnectResponser(HTTPConnectResponser* responser) | |
{ | |
assert( NULL==m_hTread && INVALID_SOCKET==m_ListenSocket ); | |
m_ConnectResponser = responser; | |
} | |
void Win32HTTPServer::SetHTTPGETResponser(HTTPGETResponser* responser) | |
{ | |
assert( NULL==m_hTread && INVALID_SOCKET==m_ListenSocket ); | |
m_GETResponser = responser; | |
} | |
} //WebService | |
DWORD WINAPI ListenThreadFunction( LPVOID lpParam ) | |
{ | |
WebServer::Win32HTTPServer* pServer = static_cast<WebServer::Win32HTTPServer*>(lpParam); | |
pServer->WaitInternal(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment