207 lines
4.9 KiB
C++
207 lines
4.9 KiB
C++
|
|
#include "huslib.h"
|
|
#include "huslibex.h"
|
|
|
|
|
|
#define ARRAYCOUNT(array) ((unsigned)(sizeof(array)/sizeof(array[0])))
|
|
|
|
static struct {
|
|
const char * pszExtention;
|
|
const char * pszContentType;
|
|
} ContentTypeTab[] = {
|
|
{ ".htm", "text/html" },
|
|
{ ".html", "text/html" },
|
|
{ ".asp", "text/html" },
|
|
{ ".php", "text/html" },
|
|
{ ".jsp", "text/html" },
|
|
{ ".css", "text/css" },
|
|
{ ".js", "application/x-javascript" },
|
|
{ ".txt", "text/plain" },
|
|
{ ".ini", "text/plain" },
|
|
{ ".gif", "image/gif" },
|
|
{ ".jpg", "image/jpeg" },
|
|
{ ".png", "image/png" },
|
|
{ ".bmp", "image/bmp" },
|
|
{ ".swf", "application/x-shockwave-flash" },
|
|
{ ".zip", "application/zip" }
|
|
};
|
|
|
|
|
|
HWebServer::HWebServer()
|
|
{
|
|
m_pszResponse = (char *)malloc(g_nMaxHsHeaderSize);
|
|
m_pszResponseOffset = m_pszResponse;
|
|
m_nResponseRemainSize = 0;
|
|
|
|
m_pFileBuffer = (char *)malloc(WS_READ_BYTES + 1);
|
|
m_pFileBufferOffset = m_pFileBuffer;
|
|
m_nRemainBufferSize = 0;
|
|
}
|
|
|
|
HWebServer::~HWebServer()
|
|
{
|
|
free(m_pszResponse);
|
|
free(m_pFileBuffer);
|
|
}
|
|
|
|
const char * HWebServer::GetContentType(const char * pszRequestUri)
|
|
{
|
|
for (unsigned i = 0; i < ARRAYCOUNT(ContentTypeTab); i++)
|
|
{
|
|
if (stristr(pszRequestUri, ContentTypeTab[i].pszExtention))
|
|
return ContentTypeTab[i].pszContentType;
|
|
}
|
|
|
|
return "application/octet-stream";
|
|
}
|
|
|
|
void HWebServer::AddStaticDir(const char * pszDir)
|
|
{
|
|
m_listStaticDir.push_back(pszDir);
|
|
}
|
|
|
|
int HWebServer::SendResponse()
|
|
{
|
|
int nSentSize = SendToTransport(m_pszResponseOffset, m_nResponseRemainSize);
|
|
if (nSentSize <= 0)
|
|
return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock
|
|
else if (nSentSize < m_nResponseRemainSize)
|
|
{
|
|
m_pszResponseOffset += nSentSize;
|
|
m_nResponseRemainSize -= nSentSize;
|
|
return 0; // buffering because of wouldblock
|
|
}
|
|
|
|
return -1; // shutdown
|
|
}
|
|
|
|
int HWebServer::SendFileHeader()
|
|
{
|
|
int nSentSize = SendToTransport(m_pFileBufferOffset, m_nRemainBufferSize);
|
|
if (nSentSize <= 0)
|
|
return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock
|
|
else if (nSentSize < m_nRemainBufferSize)
|
|
{
|
|
m_pFileBufferOffset += nSentSize;
|
|
m_nRemainBufferSize -= nSentSize;
|
|
return 0; // buffering because of wouldblock
|
|
}
|
|
|
|
return 1; // continue
|
|
}
|
|
|
|
int HWebServer::SendOpenedFile()
|
|
{
|
|
int nSendSize;
|
|
int nSentSize;
|
|
int nReadSize = WS_READ_BYTES;
|
|
|
|
while (m_nFileSize > 0)
|
|
{
|
|
while (m_nRemainBufferSize)
|
|
{
|
|
if (m_nRemainBufferSize > (long)g_nSocketSendingBlockSize)
|
|
nSendSize = g_nSocketSendingBlockSize;
|
|
else
|
|
nSendSize = m_nRemainBufferSize;
|
|
|
|
nSentSize = SendToTransport(m_pFileBufferOffset, nSendSize);
|
|
if (nSentSize <= 0)
|
|
return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock
|
|
|
|
m_pFileBufferOffset += nSentSize;
|
|
m_nRemainBufferSize -= nSentSize;
|
|
|
|
if (nSentSize < nSendSize)
|
|
return 0;
|
|
}
|
|
|
|
if (nReadSize < WS_READ_BYTES)
|
|
break;
|
|
|
|
if ((nReadSize = m_file.Read(m_pFileBuffer, WS_READ_BYTES)) <= 0)
|
|
break;
|
|
|
|
m_pFileBufferOffset = m_pFileBuffer;
|
|
m_nRemainBufferSize = nReadSize;
|
|
}
|
|
|
|
m_file.Close();
|
|
m_pFileBufferOffset = m_pFileBuffer;
|
|
m_nRemainBufferSize = 0;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int HWebServer::OnSendRetryToTransport()
|
|
{
|
|
if (m_nResponseRemainSize > 0)
|
|
return SendResponse();
|
|
|
|
return SendOpenedFile();
|
|
}
|
|
|
|
int HWebServer::OnPacketProcessing(const char * pBodyData, int nBodySize)
|
|
{
|
|
int nResult = OnPrepareRequest(pBodyData, nBodySize);
|
|
if (nResult <= 0)
|
|
return nResult;
|
|
|
|
nResult = OnReceivedRequest(pBodyData, nBodySize);
|
|
if (nResult <= 0)
|
|
return nResult;
|
|
|
|
HDynamicArray<char> darrNewPath(strlen(m_pHttpParser->GetRequestUri()) + 1);
|
|
RealignPathDepth(m_pHttpParser->GetRequestUri(), darrNewPath.m_p);
|
|
|
|
int nCopySize = 0;
|
|
const char * pOffset = strchr(darrNewPath.m_p, '?');
|
|
if (pOffset)
|
|
nCopySize = pOffset - darrNewPath.m_p;
|
|
else
|
|
nCopySize = strlen(darrNewPath.m_p);
|
|
|
|
size_t nPathLength = m_strHomeDir.GetLength() + nCopySize;
|
|
if (nPathLength > (size_t)g_nMaxPathNameLength)
|
|
{
|
|
m_nResponseRemainSize = MakeResponse(m_pszResponse, "400 Bad Request", "<html><body>400 Bad Request</body></html>");
|
|
return SendResponse();
|
|
}
|
|
|
|
HString strCopyPath = darrNewPath.m_p;
|
|
HString strLastPath = strCopyPath.SubStr(0, nCopySize);
|
|
if (strLastPath == "/")
|
|
strLastPath = "/index.htm";
|
|
|
|
HString strPathName = m_strHomeDir;
|
|
strPathName += strLastPath;
|
|
|
|
if (m_file.Open(strPathName, HFile::FMODE_RDONLY))
|
|
{
|
|
m_nFileSize = HFile::GetSize(strPathName);
|
|
m_nRemainBufferSize = Make200Header(m_pFileBufferOffset, GetContentType(strPathName), m_nFileSize);
|
|
|
|
int nResult = SendFileHeader();
|
|
if (nResult <= 0)
|
|
return nResult;
|
|
|
|
m_nRemainBufferSize = 0;
|
|
return SendOpenedFile();
|
|
}
|
|
|
|
// 404 Not found
|
|
m_nResponseRemainSize = MakeResponse(m_pszResponse, "404 Not found", "<html><body>404 Not found</body></html>");
|
|
return SendResponse();
|
|
}
|
|
|
|
bool HWebServer::IsStaticRequest()
|
|
{
|
|
for (HStrList::iterator iter = m_listStaticDir.begin(); iter != m_listStaticDir.end(); iter++)
|
|
{
|
|
if (iter->StrNICmp(m_pHttpParser->GetRequestUri(), iter->GetLength()) == 0)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|