| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #define USE_SAFE_MODE 1 |
| #define USE_LOGS_MODE 1 |
| |
| |
| #define HTTP_SERVER_NAME "Msp" |
| #define HTTP_SERVER_PORT 80 |
| #define HTTP_SERVER_ROOT "www" |
| #define HTTP_SERVER_PAGE "index.html" |
| |
| |
| #define MAX_BACKLOG_SIZE 1024*4 |
| #define MAX_THREAD_NUMBER 512 |
| #define KEEP_ALIVE_TIMEOUT 3 |
| #define MIN_HTTP_RPS 1 |
| |
| |
| #define IP_RPS_LEN 1024 |
| #define MAX_REQUESTS_PER_SECOND 128 |
| #define MIN_REQUESTS_PER_SECOND 8 |
| |
| |
| #define MAX_BUFF_SIZE 1024*4 |
| #define MIN_BUFF_SIZE 1024 |
| #define MAX_PATH_SIZE 1024 |
| #define HTTP_GENERAL_ERROR 1 |
| #define FILE_SEND_ERROR 1 |
| |
| |
| static const char* HTTP_SHILEDING_IPRange[][2] = |
| { |
| {"192.168.0.5", ""}, |
| {"192.168.0.1", "192.168.0.8"} |
| }; |
| |
| #if defined(_MSC_VER) |
| #pragma comment(lib,"Ws2_32.lib") |
| #else |
| #include <stdbool.h> |
| #endif |
| |
| #if defined(_MSC_VER) |
| |
| #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") |
| #endif |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <time.h> |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| #include <direct.h> |
| #include <Winsock2.h> |
| #include <sys\stat.h> |
| #define HTTP_SERVER_PATHCHARACTER "\\" |
| #else |
| #include <sys/socket.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <pthread.h> |
| #include <unistd.h> |
| #define HTTP_SERVER_PATHCHARACTER "/" |
| #define INVALID_SOCKET -1 |
| #define SOCKET_ERROR -1 |
| typedef int SOCKET; |
| typedef unsigned long DWORD; |
| typedef void *LPVOID; |
| typedef const struct sockaddr *LPSOCKADDR; |
| #endif |
| |
| #ifndef NULL |
| #define NULL (void*)0 |
| #endif |
| |
| #ifndef byte |
| typedef unsigned char byte; |
| #endif |
| |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| #if defined(_MSC_VER) |
| #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
| #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
| #endif |
| #define SLEEP(x) Sleep(x) |
| #define CLOSESOCKET closesocket |
| #else |
| #define SLEEP(x) usleep(x*1000) |
| #define CLOSESOCKET close |
| #endif |
| |
| |
| #define ISLOWERLETTER(x) ('a'<=(x)&&(x)<='z') |
| |
| |
| #define REVUINT(x) (unsigned int)(((x)&0x000000FF)<<24|((x)&0x0000FF00)<<8|((x)&0x00FF0000)>>8|((x)&0xFF000000)>>24) |
| |
| |
| static const char* HEADER_KEY_WORDS[] = {"GET", "POST", "HEAD", "EDIT", "If-Modified-Since", "Cache-Control", "Accept-Language", "Connection", "Keep-Alive", "Close", "Timeout", NULL}; |
| |
| #if defined(USE_SAFE_MODE) |
| |
| static const char* HTTP_SAFE_SUFFIX[] = {".html", ".htm", ".shtml", ".css", ".js", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico", ".bmp", ".swf", ".mp3", ".wma", ".wav", ".mp4", ".txt", ".xml", ".pdf", ".doc", ".xls", ".ppt", NULL}; |
| static const int HTTP_SAFE_CTYPEV[] = { 0, 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0}; |
| static const char* HTTP_CONTENT_TYPE[] = {"text/html", "text/css", "application/javascript", "image/png", "image/jpeg", "image/gif", "image/svg+xml", "image/x-icon", "application/x-bmp", "application/x-shockwave-flash", "audio/mp3", "audio/x-ms-wma", "audio/wav", "video/mpeg4", "text/plain", "text/xml", "application/pdf", "application/msword", "application/x-xls", "application/x-ppt", NULL}; |
| |
| static unsigned int IPRequestsPerSecond[IP_RPS_LEN][2]; |
| |
| static unsigned long HTTP_SHILEDING_IPulongRange[sizeof(HTTP_SHILEDING_IPRange) / sizeof(HTTP_SHILEDING_IPRange[0])][2]; |
| #define SHILEDING_IPRANGE_LEN (sizeof(HTTP_SHILEDING_IPRange)/sizeof(HTTP_SHILEDING_IPRange[0])) |
| #endif |
| |
| |
| static char nowTime[MIN_BUFF_SIZE]; |
| static const char* timeFormatGMT = "%a, %d %b %Y %H:%M:%S GMT"; |
| |
| |
| static unsigned int nowThreadNumber = 0; |
| |
| |
| static const char responseErrorPage[] = |
| "<html>" |
| "<head>" |
| "</head>" |
| "<title>%d %s</title>" |
| "<body>" |
| " <h1 align='center'><font color=#FF1493>Sorry,%d Error!</font></h1>" |
| " <script>" |
| " document.write('<hr/>' + '<font color=#9400D3>' + new Date() + '</font>' + '<hr/>' + '<font color=#FF1493>' + 'The %s server responded \"%s\".' + '</font>');" |
| " </script>" |
| "</body>" |
| "</html>"; |
| |
| |
| int HTTP_IdentifyKey(char* inStr, char** inKeyWords, const char* endChars, int SN) |
| { |
| if (inStr == NULL) |
| { |
| return -1; |
| } |
| |
| while(inKeyWords[SN] != NULL) |
| { |
| char *op=inStr, *kp=inKeyWords[SN]; |
| |
| while(*kp != '\0') |
| { |
| if( |
| ((ISLOWERLETTER(*op))?(*op-32):(*op)) != ((ISLOWERLETTER(*kp))?(*kp-32):(*kp)) |
| ) |
| { |
| break; |
| } |
| op++; |
| kp++; |
| } |
| |
| if(*kp == '\0') |
| { |
| if(*op == '\0') |
| { |
| return SN; |
| } |
| while(*endChars != '\0') |
| { |
| if(*op == *(endChars++)) |
| { |
| return SN; |
| } |
| } |
| } |
| |
| SN ++; |
| } |
| return -1; |
| } |
| |
| |
| int HTTP_PrintError(char* perr) |
| { |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| fprintf(stderr, "%s: %d\n", perr, WSAGetLastError()); |
| #else |
| perror(perr); |
| #endif |
| return 0; |
| } |
| |
| |
| int HTTP_ResponseGeneral(SOCKET soc, int responseNumber, const char* responseText, int httpMethodValue) |
| { |
| char responseBuf[MIN_BUFF_SIZE]; |
| sprintf |
| ( |
| responseBuf |
| , |
| "HTTP/1.1 %d %s\r\n" |
| "Date: %s\r\n" |
| "Server: %s\r\n\r\n" |
| , |
| responseNumber, responseText, nowTime, HTTP_SERVER_NAME |
| ); |
| send(soc, responseBuf, strlen(responseBuf), 0); |
| |
| if (httpMethodValue == 0) |
| { |
| sprintf |
| ( |
| responseBuf |
| , |
| responseErrorPage |
| , |
| responseNumber, responseText, responseNumber, HTTP_SERVER_NAME, responseText |
| ); |
| send(soc, responseBuf, strlen(responseBuf), 0); |
| |
| } |
| return 0; |
| } |
| |
| |
| int HTTP_Response200(SOCKET soc, int contentLength, int contentTypeValue, bool connectionFlag, const char* serverModifiDateStr) |
| { |
| char responseBuf[MIN_BUFF_SIZE]; |
| sprintf |
| ( |
| responseBuf |
| , |
| "HTTP/1.1 200 OK\r\n" |
| "Date: %s\r\n" |
| "Server: %s\r\n" |
| "Content-Length: %d\r\n" |
| "Connection: %s\r\n" |
| "Last-Modified: %s\r\n" |
| #if defined(USE_SAFE_MODE) |
| "Content-Type: %s\r\n\r\n" |
| , |
| nowTime, HTTP_SERVER_NAME, contentLength, (connectionFlag)?"Keep-Alive":"Close", serverModifiDateStr, HTTP_CONTENT_TYPE[HTTP_SAFE_CTYPEV[contentTypeValue]] |
| #else |
| "Content-Type: text/html\r\n\r\n" |
| , |
| nowTime, HTTP_SERVER_NAME, contentLength, (connectionFlag)?"Keep-Alive":"Close", serverModifiDateStr |
| #endif |
| ); |
| |
| send(soc, responseBuf, strlen(responseBuf), 0); |
| return 0; |
| } |
| |
| |
| int HTTP_Response301(SOCKET soc, const char* newURL, const char* suffixStr, bool connectionFlag) |
| { |
| char responseBuf[MIN_BUFF_SIZE]; |
| |
| sprintf |
| ( |
| responseBuf |
| , |
| "HTTP/1.1 301 Moved Permanently\r\n" |
| "Date: %s\r\n" |
| "Server: %s\r\n" |
| "Location: %s%s\r\n" |
| "Connection: %s\r\n" |
| "Content-Type: text/html\r\n\r\n" |
| , |
| nowTime, HTTP_SERVER_NAME, newURL, suffixStr, (connectionFlag)?"Keep-Alive":"Close" |
| ); |
| |
| send(soc, responseBuf, strlen(responseBuf), 0); |
| return 0; |
| } |
| |
| |
| int HTTP_Response304(SOCKET soc, const char* serverModifiDateStr, bool connectionFlag) |
| { |
| char responseBuf[MIN_BUFF_SIZE]; |
| |
| sprintf |
| ( |
| responseBuf |
| , |
| "HTTP/1.1 304 Not Modified\r\n" |
| "Date: %s\r\n" |
| "Server: %s\r\n" |
| "Connection: %s\r\n" |
| "Last-Modified: %s\r\n\r\n" |
| , |
| nowTime, HTTP_SERVER_NAME, (connectionFlag)?"Keep-Alive":"Close", serverModifiDateStr |
| ); |
| |
| send(soc, responseBuf, strlen(responseBuf), 0); |
| return 0; |
| } |
| |
| |
| int HTTP_SendFile(SOCKET soc, FILE *fp) |
| { |
| |
| rewind(fp); |
| |
| |
| byte pickUpBuf[MIN_BUFF_SIZE]; |
| |
| size_t freadSize = 0; |
| |
| |
| while (!feof(fp)) |
| { |
| freadSize = fread(pickUpBuf, sizeof(byte), MIN_BUFF_SIZE, fp); |
| if (send(soc, (const char*)pickUpBuf, freadSize, 0) == SOCKET_ERROR) |
| { |
| return FILE_SEND_ERROR; |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| DWORD |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| WINAPI |
| #endif |
| HTTP_ServerCore(LPVOID lpvsoc) |
| { |
| |
| nowThreadNumber ++; |
| |
| DWORD ret = 0; |
| SOCKET soc = (SOCKET)lpvsoc; |
| |
| |
| bool connectionFlag = true, timeoutAlready = false; |
| |
| |
| char receiveBuf[MIN_BUFF_SIZE]; |
| |
| |
| struct timeval timeoutKeepAlive = {KEEP_ALIVE_TIMEOUT, 0}; |
| |
| |
| setsockopt(soc, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeoutKeepAlive, sizeof(struct timeval)); |
| |
| while(true) |
| { |
| |
| int receiveCount = recv(soc, receiveBuf, MIN_BUFF_SIZE-1, 0); |
| if (receiveCount == SOCKET_ERROR) |
| { |
| |
| HTTP_ResponseGeneral(soc, 100, "Needs Request", 2); |
| ret = HTTP_GENERAL_ERROR; |
| break; |
| } |
| else |
| { |
| |
| receiveBuf[receiveCount]='\0'; |
| } |
| |
| |
| int httpMethodValue = -1; |
| char httpURL[MIN_BUFF_SIZE]; |
| char clientModifiDateStr[MIN_BUFF_SIZE]; |
| |
| |
| httpURL[0]='\0', clientModifiDateStr[0]='\0'; |
| |
| |
| int headerKeyBeginIndex = 0; |
| char cacheLine[MIN_BUFF_SIZE], *pBuf = receiveBuf, *tPer = NULL; |
| |
| while((*pBuf != '\0') && (*pBuf != '\r') && (*pBuf != '\n')) |
| { |
| char *pLine=(char*)cacheLine; |
| while((*pBuf != '\0') && (*pBuf != '\r') && (*pBuf != '\n')) |
| { |
| *(pLine ++) = *(pBuf ++); |
| } |
| |
| *pLine = '\0'; |
| |
| |
| if (*pBuf=='\r') |
| { |
| pBuf ++; |
| } |
| if (*pBuf=='\n') |
| { |
| pBuf ++; |
| } |
| |
| int headerKeyValue = HTTP_IdentifyKey(cacheLine, (char**)HEADER_KEY_WORDS, ": \t", headerKeyBeginIndex); |
| if (headerKeyValue == -1 && headerKeyBeginIndex == 0) |
| { |
| |
| HTTP_ResponseGeneral(soc, 400, "Bad request", 2); |
| |
| |
| CLOSESOCKET(soc); |
| nowThreadNumber --; |
| return HTTP_GENERAL_ERROR; |
| } |
| else if (headerKeyValue < 3 && headerKeyBeginIndex == 0) |
| { |
| |
| httpMethodValue = headerKeyValue; |
| |
| |
| headerKeyBeginIndex = 4; |
| |
| |
| strtok(cacheLine, " \t"); |
| tPer = strtok(NULL, " \t"); |
| if(tPer != NULL) |
| { |
| strcpy(httpURL, tPer); |
| } |
| else |
| { |
| |
| HTTP_ResponseGeneral(soc, 400, "Bad request", 2); |
| |
| |
| CLOSESOCKET(soc); |
| nowThreadNumber --; |
| return HTTP_GENERAL_ERROR; |
| } |
| } |
| else if (headerKeyValue == 4 && headerKeyBeginIndex != 0) |
| { |
| tPer = cacheLine; |
| if(*tPer != '\0') |
| { |
| while(*tPer!=':' && *tPer!='\0') |
| { |
| tPer ++; |
| } |
| if(*tPer==':') |
| { |
| tPer ++; |
| } |
| while(*tPer==' ' && *tPer!='\t') |
| { |
| tPer ++; |
| } |
| strcpy(clientModifiDateStr, tPer); |
| } |
| } |
| else if (headerKeyValue == 7 && headerKeyBeginIndex != 0) |
| { |
| tPer = cacheLine; |
| if(*tPer != '\0') |
| { |
| while(*tPer!=':' && *tPer!='\0') |
| { |
| tPer ++; |
| } |
| if(*tPer==':') |
| { |
| tPer ++; |
| } |
| while(*tPer==' ' && *tPer!='\t') |
| { |
| tPer ++; |
| } |
| |
| |
| if (HTTP_IdentifyKey(tPer, (char**)HEADER_KEY_WORDS, " \t,\0", 9) == 9) |
| { |
| connectionFlag = false; |
| } |
| } |
| } |
| else if (!timeoutAlready && connectionFlag && headerKeyValue == 8 && headerKeyBeginIndex != 0) |
| { |
| tPer = cacheLine; |
| if(*tPer != '\0') |
| { |
| while(*tPer!=':' && *tPer!='\0') |
| { |
| tPer ++; |
| } |
| if(*tPer==':') |
| { |
| tPer ++; |
| } |
| while(*tPer==' ' && *tPer!='\t') |
| { |
| tPer ++; |
| } |
| |
| |
| if (HTTP_IdentifyKey(tPer, (char**)HEADER_KEY_WORDS, " \t=", 10) == 10) |
| { |
| while(*tPer!='=' && *tPer!='\0') |
| { |
| tPer ++; |
| } |
| if(*tPer == '=') |
| { |
| |
| timeoutKeepAlive.tv_sec = atoi(++ tPer) % KEEP_ALIVE_TIMEOUT; |
| |
| |
| setsockopt(soc, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeoutKeepAlive, sizeof(struct timeval)); |
| |
| |
| timeoutAlready = true; |
| } |
| } |
| } |
| } |
| } |
| |
| |
| char* httpFilePath = (char*)httpURL; |
| char* p = httpFilePath; |
| |
| #if defined(USE_SAFE_MODE) || defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| while (*p != '\0') |
| { |
| #if defined(USE_SAFE_MODE) |
| if (*p == '.' && *(p+1) == '.') |
| { |
| |
| HTTP_ResponseGeneral(soc, 403, "Forbidden Directory Penetration", httpMethodValue); |
| |
| |
| CLOSESOCKET(soc); |
| nowThreadNumber --; |
| return HTTP_GENERAL_ERROR; |
| } |
| #endif |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| if (*p == '/') |
| { |
| *p = (HTTP_SERVER_PATHCHARACTER)[0]; |
| } |
| #endif |
| p++; |
| } |
| #endif |
| |
| |
| char requestFilePath[MAX_PATH_SIZE]; |
| sprintf |
| ( |
| requestFilePath |
| , |
| "%s%s%s%s%s" |
| , |
| ".", HTTP_SERVER_PATHCHARACTER, HTTP_SERVER_ROOT, HTTP_SERVER_PATHCHARACTER, httpFilePath |
| ); |
| |
| |
| #if defined(USE_SAFE_MODE) || defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| if(*(p-1) == (HTTP_SERVER_PATHCHARACTER)[0]) |
| { |
| #else |
| if(*(requestFilePath + strlen(requestFilePath) -1) == (HTTP_SERVER_PATHCHARACTER)[0]) |
| { |
| #endif |
| strcat(requestFilePath, HTTP_SERVER_PAGE); |
| } |
| |
| |
| struct stat fileStatBuf; |
| int rStat = stat(requestFilePath, &fileStatBuf); |
| |
| |
| if (rStat == 0 && S_ISDIR(fileStatBuf.st_mode)) |
| { |
| |
| HTTP_Response301(soc, (const char*)httpURL, "/", connectionFlag); |
| |
| |
| if (connectionFlag == false) |
| { |
| break; |
| } |
| continue; |
| } |
| |
| |
| int contentTypeValue = 0; |
| |
| #if defined(USE_SAFE_MODE) |
| |
| char* pSuffix = strrchr(requestFilePath, '.'); |
| |
| |
| contentTypeValue = HTTP_IdentifyKey(pSuffix, (char**)HTTP_SAFE_SUFFIX, "\0", 0); |
| |
| |
| if (contentTypeValue == -1) |
| { |
| |
| HTTP_ResponseGeneral(soc, 403, "Forbidden", httpMethodValue); |
| |
| |
| ret = HTTP_GENERAL_ERROR; |
| break; |
| } |
| #endif |
| |
| |
| char* serverModifiDateStr = nowTime; |
| |
| |
| if (rStat == 0 && S_ISREG(fileStatBuf.st_mode)) |
| { |
| char tmpModifiDate[MIN_BUFF_SIZE]; |
| strftime(tmpModifiDate, sizeof(tmpModifiDate), timeFormatGMT, gmtime(&fileStatBuf.st_mtime)); |
| serverModifiDateStr = (char*)tmpModifiDate; |
| |
| |
| if(strcmp(clientModifiDateStr, serverModifiDateStr) == 0) |
| { |
| |
| HTTP_Response304(soc, clientModifiDateStr, connectionFlag); |
| |
| |
| if (connectionFlag == false) |
| { |
| break; |
| } |
| continue; |
| } |
| } |
| |
| |
| FILE* fp = fopen(requestFilePath, "rb"); |
| |
| |
| if (fp == NULL) |
| { |
| |
| HTTP_ResponseGeneral(soc, 404, "Not Found", httpMethodValue); |
| |
| |
| ret = HTTP_GENERAL_ERROR; |
| break; |
| } |
| |
| |
| int fpSize = fileStatBuf.st_size; |
| |
| |
| HTTP_Response200(soc, fpSize, contentTypeValue, connectionFlag, serverModifiDateStr); |
| |
| |
| if (httpMethodValue == 0) |
| { |
| if (HTTP_SendFile(soc, fp) == FILE_SEND_ERROR) |
| { |
| |
| |
| } |
| } |
| |
| fclose(fp); |
| |
| |
| #if defined(ANDROID) || defined(_ANDROID) || defined(__ANDROID__) |
| break; |
| #endif |
| } |
| |
| |
| CLOSESOCKET(soc); |
| nowThreadNumber --; |
| return ret; |
| } |
| |
| #if defined(USE_SAFE_MODE) |
| |
| int initHTTP_SHILEDING_IPulongRange() |
| { |
| |
| struct in_addr tmpIPaddr; |
| unsigned int ulongTmp; |
| |
| int i; |
| for(i=0; i<SHILEDING_IPRANGE_LEN; i++) |
| { |
| if(HTTP_SHILEDING_IPRange[i][0] == NULL) |
| { |
| return HTTP_GENERAL_ERROR; |
| } |
| |
| tmpIPaddr.s_addr = inet_addr(HTTP_SHILEDING_IPRange[i][0]); |
| if (tmpIPaddr.s_addr == INADDR_NONE) |
| { |
| return HTTP_GENERAL_ERROR; |
| } |
| |
| HTTP_SHILEDING_IPulongRange[i][0] = REVUINT(tmpIPaddr.s_addr); |
| |
| if(*(HTTP_SHILEDING_IPRange[i][1]) == '\0') |
| { |
| HTTP_SHILEDING_IPulongRange[i][1] = 0; |
| } |
| else |
| { |
| tmpIPaddr.s_addr = inet_addr(HTTP_SHILEDING_IPRange[i][1]); |
| if |
| ( |
| tmpIPaddr.s_addr == INADDR_NONE || |
| HTTP_SHILEDING_IPulongRange[i][0] > REVUINT(tmpIPaddr.s_addr) |
| ) |
| { |
| return HTTP_GENERAL_ERROR; |
| } |
| HTTP_SHILEDING_IPulongRange[i][1] = REVUINT(tmpIPaddr.s_addr); |
| } |
| } |
| return 0; |
| } |
| |
| |
| bool isBelongHTTP_SHILEDING_IPulongRange(unsigned long clientIPulong) |
| { |
| int i; |
| for(i=0; i<SHILEDING_IPRANGE_LEN; i++) |
| { |
| if |
| ( |
| ( |
| HTTP_SHILEDING_IPulongRange[i][1] == 0 && |
| clientIPulong == HTTP_SHILEDING_IPulongRange[i][0] |
| ) || |
| ( |
| HTTP_SHILEDING_IPulongRange[i][0] <= clientIPulong && |
| clientIPulong <= HTTP_SHILEDING_IPulongRange[i][1] |
| ) |
| ) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| #endif |
| |
| |
| int main() |
| { |
| |
| int ret = 0; |
| |
| |
| time_t timeServerStart = time((time_t*)0); |
| strcpy(nowTime, ctime(&timeServerStart)); |
| |
| |
| fprintf |
| ( |
| stdout, |
| "%s" |
| "[===* Welcome to use %s *===]\n" |
| "[>>>]\n" |
| , |
| nowTime, HTTP_SERVER_NAME |
| ); |
| |
| #if defined(USE_SAFE_MODE) |
| |
| if (initHTTP_SHILEDING_IPulongRange() == HTTP_GENERAL_ERROR) |
| { |
| fprintf(stdout, "Failed to init shileding IP\n"); |
| ret = HTTP_GENERAL_ERROR; |
| return ret; |
| } |
| #endif |
| |
| #if defined(USE_LOGS_MODE) |
| |
| FILE* fp = fopen("." HTTP_SERVER_PATHCHARACTER "server" ".log", "a"); |
| if (fp == NULL) |
| { |
| fprintf(stdout, "Failed to create server log\n"); |
| ret = HTTP_GENERAL_ERROR; |
| return ret; |
| } |
| unsigned long preClientSockS_addr = 0; |
| time_t preClientSockVistTime = 0; |
| #endif |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| |
| WSADATA wsaData; |
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) |
| { |
| fprintf(stdout, "Failed to create win socket\n"); |
| ret = HTTP_GENERAL_ERROR; |
| goto MAIN_END3; |
| } |
| #endif |
| |
| |
| SOCKET socListen; |
| socListen = socket(AF_INET, SOCK_STREAM, 0); |
| if(socListen == INVALID_SOCKET) |
| { |
| HTTP_PrintError("Creat listen socket failed"); |
| ret = HTTP_GENERAL_ERROR; |
| goto MAIN_END2; |
| } |
| |
| |
| struct sockaddr_in serverSockaddrIn, clientSockaddrIn; |
| int clientSockaddrInLen = sizeof(clientSockaddrIn); |
| |
| |
| serverSockaddrIn.sin_family = AF_INET; |
| serverSockaddrIn.sin_port = htons(HTTP_SERVER_PORT); |
| serverSockaddrIn.sin_addr.s_addr = htonl(INADDR_ANY); |
| |
| |
| if (bind(socListen, (LPSOCKADDR)&serverSockaddrIn, sizeof(serverSockaddrIn)) == SOCKET_ERROR) |
| { |
| HTTP_PrintError("Blind server failed"); |
| ret = HTTP_GENERAL_ERROR; |
| goto MAIN_END1; |
| } |
| |
| |
| if (listen(socListen, MAX_BACKLOG_SIZE) == SOCKET_ERROR) |
| { |
| HTTP_PrintError("Listen socket failed"); |
| ret = HTTP_GENERAL_ERROR; |
| goto MAIN_END1; |
| } |
| |
| #if defined(USE_SAFE_MODE) || defined(ANDROID) || defined(_ANDROID) || defined(__ANDROID__) |
| |
| clock_t preClock = clock(); |
| int countTimes = 0; |
| int requestsPerSecond = 0; |
| #endif |
| |
| #if defined(USE_LOGS_MODE) |
| |
| fprintf(fp, "[*]Server start at %s", nowTime); |
| fflush(fp); |
| #endif |
| |
| |
| while(true) |
| { |
| |
| #if defined(USE_SAFE_MODE) |
| |
| while(nowThreadNumber > MAX_THREAD_NUMBER) |
| { |
| SLEEP(1); |
| } |
| #endif |
| |
| |
| SOCKET soc = accept(socListen, (struct sockaddr*)&clientSockaddrIn, &clientSockaddrInLen); |
| if (soc == INVALID_SOCKET) |
| { |
| HTTP_PrintError("Accept client failed"); |
| |
| SLEEP(1); |
| continue; |
| } |
| |
| |
| time_t timeNow = time((time_t*)0); |
| strftime(nowTime, sizeof(nowTime), timeFormatGMT, gmtime(&timeNow)); |
| |
| #if defined(USE_SAFE_MODE) |
| |
| bool alreadyFindClientIP = false, allowAcceptSocket = true, isBetterMarkI = false; |
| int i, markI=-1; |
| for(i=IP_RPS_LEN-1; i; i--) |
| { |
| if |
| ( |
| (markI == -1 && IPRequestsPerSecond[i][1] < MIN_REQUESTS_PER_SECOND) || |
| (isBetterMarkI = false && IPRequestsPerSecond[i][1] ==0) |
| ) |
| { |
| if (IPRequestsPerSecond[i][1] == 0) |
| { |
| isBetterMarkI = true; |
| } |
| markI = i; |
| } |
| |
| if (IPRequestsPerSecond[i][0] == clientSockaddrIn.sin_addr.s_addr) |
| { |
| alreadyFindClientIP = true; |
| if (IPRequestsPerSecond[i][1] > MAX_REQUESTS_PER_SECOND) |
| { |
| allowAcceptSocket = false; |
| if (IPRequestsPerSecond[i][1] != 0xFFFFFFFF) |
| { |
| IPRequestsPerSecond[i][1] = 0xFFFFFFFF; |
| #if defined(USE_LOGS_MODE) |
| |
| fprintf(fp, "[%s] [Blacklist user: %s]\n", nowTime, inet_ntoa(clientSockaddrIn.sin_addr)); |
| fflush(fp); |
| #endif |
| } |
| } |
| else |
| { |
| IPRequestsPerSecond[i][1] ++; |
| } |
| break; |
| } |
| } |
| |
| |
| if((! alreadyFindClientIP) && (markI != -1)) |
| { |
| IPRequestsPerSecond[markI][0] = clientSockaddrIn.sin_addr.s_addr; |
| IPRequestsPerSecond[markI][1] = 1; |
| } |
| |
| |
| if |
| ( |
| isBelongHTTP_SHILEDING_IPulongRange(REVUINT(clientSockaddrIn.sin_addr.s_addr)) || |
| allowAcceptSocket == false |
| ) |
| { |
| |
| CLOSESOCKET(soc); |
| continue; |
| } |
| #endif |
| |
| #if defined(USE_LOGS_MODE) |
| if |
| ( |
| preClientSockS_addr != clientSockaddrIn.sin_addr.s_addr || |
| preClientSockVistTime != timeNow |
| ) |
| { |
| preClientSockS_addr = clientSockaddrIn.sin_addr.s_addr; |
| preClientSockVistTime = timeNow; |
| |
| |
| fprintf(fp, "[%s] [Client: %s]\n", nowTime, inet_ntoa(clientSockaddrIn.sin_addr)); |
| fflush(fp); |
| } |
| #endif |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| |
| DWORD threadID; |
| CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)HTTP_ServerCore, (LPVOID)soc, 0, &threadID); |
| #else |
| pthread_t newPthreadT; |
| pthread_create(&newPthreadT, NULL, (void*)HTTP_ServerCore, (void*)(intptr_t)soc); |
| #endif |
| |
| |
| #if defined(USE_SAFE_MODE) || defined(ANDROID) || defined(_ANDROID) || defined(__ANDROID__) |
| |
| countTimes ++; |
| |
| |
| if (clock()-preClock > CLOCKS_PER_SEC*0.618) |
| { |
| requestsPerSecond = CLOCKS_PER_SEC * countTimes / (clock()-preClock); |
| countTimes = 0; |
| preClock = clock(); |
| |
| #if defined(USE_SAFE_MODE) |
| |
| for(i=IP_RPS_LEN-1; i; i--) |
| { |
| if (IPRequestsPerSecond[i][1] <= MAX_REQUESTS_PER_SECOND) |
| { |
| IPRequestsPerSecond[i][1] = 0; |
| } |
| } |
| #endif |
| } |
| |
| |
| #if defined(ANDROID) || defined(_ANDROID) || defined(__ANDROID__) |
| |
| if (requestsPerSecond < MIN_HTTP_RPS) |
| { |
| SLEEP(3); |
| } |
| #endif |
| |
| #endif |
| } |
| |
| MAIN_END1: |
| |
| CLOSESOCKET(socListen); |
| |
| MAIN_END2: |
| #if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER) |
| |
| WSACleanup(); |
| #endif |
| |
| MAIN_END3: |
| #if defined(USE_LOGS_MODE) |
| |
| fclose(fp); |
| #endif |
| |
| return ret; |
| }COPY |