Files
smartservice_native/hdssd/huslib/WebServer.cpp
T
2026-05-20 03:08:08 +09:00

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