📄 httpmt.c
字号:
return 0;
}
////////////////////////////////////////////////////////////
BOOL RecvRequest(LPREQUEST lpReq, LPBYTE pBuf, DWORD dwBufSize)
{
WSABUF wsabuf;
WSAOVERLAPPED over;
DWORD dwRecv;
DWORD dwFlags;
DWORD dwRet;
HANDLE hEvents[2];
BOOL fPending;
int nRet;
//
// Zero the buffer so the recv is null-terminated
//
memset(pBuf, 0, dwBufSize);
//
// Setup the WSABUF and WSAOVERLAPPED structures
//
wsabuf.buf = pBuf;
wsabuf.len = dwBufSize;
over.hEvent = WSACreateEvent();
dwFlags = 0;
fPending = FALSE;
nRet = WSARecv(lpReq->Socket, // Socket
&wsabuf, // WSABUF
1, // Number of buffers
&dwRecv, // Bytes received
&dwFlags, // Flags
&over, // WSAOVERLAPPED
NULL); // Completion function
if (nRet != 0)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
LogWinSockError(ghwnd,
"WSARecv()",
WSAGetLastError());
CloseHandle(over.hEvent);
return FALSE;
}
else
fPending = TRUE;
}
//
// If the I/O isn't finished...
//
if (fPending)
{
//
// Wait for the request to complete or the exit event
//
hEvents[0] = over.hEvent;
hEvents[1] = lpReq->hExit;
dwRet = WaitForMultipleObjects(2,
hEvents,
FALSE,
INFINITE);
//
// Was the recv event signaled?
//
if (dwRet != 0)
{
CloseHandle(over.hEvent);
return FALSE;
}
if (!WSAGetOverlappedResult(lpReq->Socket,
&over,
&dwRecv,
FALSE,
&dwFlags))
CloseHandle(over.hEvent);
return FALSE;
}
//
// Recv event is complete -- keep statistics
//
lpReq->dwRecv += dwRecv;
CloseHandle(over.hEvent);
return TRUE;
}
////////////////////////////////////////////////////////////
int ParseRequest(LPREQUEST lpReq, LPBYTE lpBuf)
{
char szSeps[] = " \n";
char *cpToken;
//
// Don't let requests include ".." characters
// in requests
//
if (strstr(lpBuf, "..") != NULL)
{
// Send "bad request" error
return(HTTP_STATUS_BADREQUEST);
}
//
// Determine request method
//
cpToken = strtok(lpBuf, szSeps);
if (!_stricmp(cpToken, "GET"))
lpReq->nMethod = METHOD_GET; //GET
else if(!_stricmp(cpToken, "POST"))
{
lpReq->nMethod = METHOD_POST; //post
}
else
{
// Send "not implemented" error
return(HTTP_STATUS_NOTIMPLEMENTED);
}
//
// Get the file name
//
cpToken = strtok(NULL, szSeps);
if (cpToken == NULL)
{
// Send "bad request" error
return(HTTP_STATUS_BADREQUEST);
}
strcpy(lpReq->szFileName, szWebRoot);
if (strlen(cpToken) > 1)
strcat(lpReq->szFileName, cpToken);
else
strcat(lpReq->szFileName, "/index.html");
return 0;
}
////////////////////////////////////////////////////////////
void CloseConnection(LPREQUEST lpReq)
{
HTTPSTATS stats;
int nRet;
//
// Log the event and close the socket
//
// LogEvent(ghwnd,
// "Closing socket: %d",
// lpReq->Socket);
nRet = closesocket(lpReq->Socket);
if (nRet == SOCKET_ERROR)
{
LogWinSockError(ghwnd,
"closesocket()",
WSAGetLastError());
}
//
// Give the user interface the stats
//
stats.dwElapsedTime =
(GetTickCount() - lpReq->dwConnectTime);
stats.dwRecv = lpReq->dwRecv;
stats.dwSend = lpReq->dwSend;
// SendMessage(ghwnd,
// guAppMsg,
// HTTP_STATS_MSG,
// (LPARAM)&stats);
}
////////////////////////////////////////////////////////////
void SendFile(LPREQUEST lpReq)
{
//
// Open the file for reading
//
lpReq->hFile = CreateFile(lpReq->szFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (lpReq->hFile == INVALID_HANDLE_VALUE)
{
SendMessage(ghwnd,
guAppMsg,
HTTP_FILENOTFOUND_MSG,
(LPARAM)(LPCSTR)lpReq->szFileName);
// Send "404 Not Found" error
SendError(lpReq, HTTP_STATUS_NOTFOUND);
return;
}
//
// Tell the user interface about the file hit
// (Sending just the request portion -- without
// the root web directory portion
//
SendMessage(ghwnd,
guAppMsg,
HTTP_FILEOK_MSG,
(LPARAM)(LPCSTR)&lpReq->szFileName[strlen(szWebRoot)]);
//
// Send the file contents to the client
//
SendFileContents(lpReq);
//
// Close the file
//
if (CloseHandle(lpReq->hFile))
lpReq->hFile = INVALID_HANDLE_VALUE;
else
LogEvent(ghwnd,
"Error closing file: %d",
GetLastError());
}
////////////////////////////////////////////////////////////
void SendFileContents(LPREQUEST lpReq)
{
static BYTE buf[1024];
DWORD dwRead;
BOOL fRet;
//
// Read and send data until EOF
//
while(1)
{
//
// Read a buffer full from the file
//
fRet = ReadFile(lpReq->hFile,
buf,
sizeof(buf),
&dwRead,
NULL);
if (!fRet)
{
// Send "404 Not Found" error
SendError(lpReq, HTTP_STATUS_SERVERERROR);
break;
}
if (dwRead == 0)
break;
//
// Send this buffer to the client
//
if (!SendBuffer(lpReq, buf, dwRead))
break;
//
// Add for statistics
//
lpReq->dwSend += dwRead;
}
}
////////////////////////////////////////////////////////////
BOOL SendBuffer(LPREQUEST lpReq, LPBYTE pBuf, DWORD dwBufSize)
{
WSABUF wsabuf;
WSAOVERLAPPED over;
DWORD dwRecv;
DWORD dwFlags;
DWORD dwRet;
HANDLE hEvents[2];
BOOL fPending;
int nRet;
//
// Setup the WSABUF and WSAOVERLAPPED structures
//
wsabuf.buf = pBuf;
wsabuf.len = dwBufSize;
over.hEvent = WSACreateEvent();
fPending = FALSE;
nRet = WSASend(lpReq->Socket, // Socket
&wsabuf, // WSABUF
1, // Number of buffers
&dwRecv, // Bytes received
0, // Flags
&over, // WSAOVERLAPPED
NULL); // Completion function
if (nRet != 0)
{
if (WSAGetLastError() == WSA_IO_PENDING)
fPending = TRUE;
else
{
LogWinSockError(ghwnd,
"WSASend()",
WSAGetLastError());
CloseHandle(over.hEvent);
return FALSE;
}
}
//
// If the I/O isn't finished...
//
if (fPending)
{
//
// Wait for the request to complete
// or the exit event to be signaled
//
hEvents[0] = over.hEvent;
hEvents[1] = lpReq->hExit;
dwRet = WaitForMultipleObjects(2,
hEvents,
FALSE,
INFINITE);
//
// Was the recv event signaled?
//
if (dwRet != 0)
{
CloseHandle(over.hEvent);
return FALSE;
}
//
// Get I/O result
//
if (!WSAGetOverlappedResult(lpReq->Socket,
&over,
&dwRecv,
FALSE,
&dwFlags))
{
LogWinSockError(ghwnd,
"WSAGetOverlappedResult()",
WSAGetLastError());
CloseHandle(over.hEvent);
return FALSE;
}
}
CloseHandle(over.hEvent);
return TRUE;
}
////////////////////////////////////////////////////////////
void SendError(LPREQUEST lpReq, UINT uError)
{
static char szMsg[512];
static char *szStatMsgs [] = {
"200 OK",
"201 Created",
"202 Accepted",
"204 No Content",
"301 Moved Permanently",
"302 Moved Temporarily",
"304 Not Modified",
"400 Bad Request",
"401 Unauthorized",
"403 Forbidden",
"404 Not Found",
"500 Internal Server Error",
"501 Not Implemented",
"502 Bad Gateway",
"503 Service Unavailable"
};
#define NUMSTATMSGS sizeof(szStatMsgs) / sizeof(szStatMsgs[0])
if (uError < 0 || uError > NUMSTATMSGS)
return;
wsprintf(szMsg, "<body><h1>%s</h1></body>",
szStatMsgs[uError]);
send(lpReq->Socket,
szMsg,
strlen(szMsg),
0);
}
////////////////////////////////////////////////////////////
void LogEvent(HWND hwnd, LPCSTR lpFormat, ...)
{
va_list Marker;
char szBuf[256];
// Write text to string
// and append to edit control
va_start(Marker, lpFormat);
vsprintf(szBuf, lpFormat, Marker);
va_end(Marker);
SendMessage(ghwnd,
guAppMsg,
HTTP_EVENT_MSG,
(LPARAM)szBuf);
}
////////////////////////////////////////////////////////////
void LogWinSockError(HWND hwnd, LPCSTR lpText, int nErrorCode)
{
char szBuf[256];
szBuf[0] = '\0';
LoadString(GetWindowInstance(hwnd),
nErrorCode,
szBuf,
sizeof(szBuf));
LogEvent(hwnd, "%s : %s", lpText, szBuf);
}
////////////////////////////////////////////////////////////
int GetLocalAddress(LPSTR lpStr, LPDWORD lpdwStrLen)
{
struct in_addr *pinAddr;
LPHOSTENT lpHostEnt;
int nRet;
int nLen;
//
// Get our local name
//
nRet = gethostname(lpStr, *lpdwStrLen);
if (nRet == SOCKET_ERROR)
{
lpStr[0] = '\0';
return SOCKET_ERROR;
}
//
// "Lookup" the local name
//
lpHostEnt = gethostbyname(lpStr);
if (lpHostEnt == NULL)
{
lpStr[0] = '\0';
return SOCKET_ERROR;
}
//
// Format first address in the list
//
pinAddr = ((LPIN_ADDR)lpHostEnt->h_addr);
nLen = strlen(inet_ntoa(*pinAddr));
if ((DWORD)nLen > *lpdwStrLen)
{
*lpdwStrLen = nLen;
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
*lpdwStrLen = nLen;
strcpy(lpStr, inet_ntoa(*pinAddr));
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -