Advertisement
captmicro

microserver

Aug 8th, 2010
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.02 KB | None | 0 0
  1.  
  2. #define _CRT_SECURE_NO_WARNINGS
  3.  
  4. #pragma comment(lib, "ws2_32.lib")
  5. #include <winsock2.h>
  6. #include <WS2tcpip.h>
  7.  
  8. #include <windows.h>
  9. #include <stdio.h>
  10.  
  11. #pragma comment(lib, "lua51.lib")
  12. extern "C"
  13. {
  14. #include "lua.h"
  15. #include "lauxlib.h"
  16. #include "lualib.h"
  17. }
  18.  
  19. #define LUA_FUNCTION(name) static int name(lua_State *L)
  20.  
  21. #define MAX_CONNECTIONS 32
  22. #define BUFFER_SIZE 1024
  23.  
  24. #define halloc(size) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size)
  25. #define hfree(ptr) HeapFree(GetProcessHeap(), 0, ptr);
  26.  
  27. #define B 1
  28. #define KB B * 1024
  29. #define MB KB * 1024
  30. #define GB MB * 1024
  31.  
  32. #define LUA_PRINTBUFFER_SIZE MB
  33. #define HTTP_DEFAULT_FILE "/index.html"
  34. #define HTTP_VER "HTTP/1.1 %s\r\n"
  35. #define HTTP_DATE "%a, %d %b %Y %I:%M:%S %Z\r\n"
  36. #define HTTP_SERVER "Server: microserver\r\n"
  37. #define HTTP_CACHECONTROL "Cache-Control: no-cache\r\n"
  38. #define HTTP_KEEPALIVE "Keep-Alive: timeout=15, max=800\r\n"
  39. #define HTTP_CONNECTION "Connection: Keep-Alive\r\n"
  40. #define HTTP_CONTENTTYPE "Content-Type: %s\r\n\r\n"
  41. #define HTTP_404_CONTENT "<html>\n<head>\n\t<title>Error! 404 Not Found</title>\n<head>\n<body>\n\t<h1 style=\"text-align:center\">Error! 404 Not Found</h1>\n</body>\n</html>"
  42.  
  43. int main(int argc, char *aargv[]);
  44.  
  45. void parsesendGET(SOCKET *cs, char *request);
  46.  
  47. char *ParseLuaTags(char *html);
  48. LUA_FUNCTION(l_print);
  49.  
  50. void ProfileSection2str(char *sec);
  51. int lstrcmpn(char *str1, char *str2, int size);
  52. int lstrcnt(char *str1, char chr);
  53.  
  54.  
  55.  
  56. WSADATA wsaData;
  57. SOCKET listenSocket;
  58.  
  59. char configFile[MAX_PATH] = {0};
  60. lua_State *luastate = NULL;
  61. char *lua_print_buffer = NULL;
  62.  
  63. int main(int argc, char *argv[])
  64. {
  65.     GetCurrentDirectoryA(MAX_PATH, configFile);
  66.     lstrcatA(configFile, "\\webcfg.ini");
  67.  
  68.     char port[16];
  69.     GetPrivateProfileStringA("MAIN", "port", "8080", port, 16, configFile);
  70.  
  71.     printf("Starting winsock...\n");
  72.     //Startup winsock
  73.     int startupResult = 0;
  74.     startupResult = WSAStartup(MAKEWORD(2,2), &wsaData);
  75.     if (startupResult != 0) {
  76.         printf("WSAStartup failed: %d\n", startupResult);
  77.         return 1;
  78.     }
  79.  
  80.     //Create server socket
  81.     struct addrinfo *result = NULL;
  82.     struct addrinfo *ptr = NULL;
  83.     struct addrinfo hints;
  84.  
  85.     ZeroMemory(&hints, sizeof(hints));
  86.     hints.ai_family = AF_INET;
  87.     hints.ai_socktype = SOCK_STREAM;
  88.     hints.ai_protocol = IPPROTO_TCP;
  89.     hints.ai_flags = AI_PASSIVE;
  90.  
  91.     //--Resolve address & port
  92.     int gaiResult = 0;
  93.     gaiResult = getaddrinfo(NULL, port, &hints, &result);
  94.     if (gaiResult != 0) {
  95.         printf("getaddrinfo failed: %d\n", gaiResult);
  96.         WSACleanup();
  97.         return 1;
  98.     }
  99.        
  100.     //--Create socket
  101.     listenSocket = INVALID_SOCKET;
  102.  
  103.     for (int i = 0; i < 5; i++)
  104.     {
  105.         listenSocket = socket(result->ai_family,
  106.             result->ai_socktype, result->ai_protocol);
  107.         if (listenSocket != INVALID_SOCKET) break;
  108.         printf("Failed to create socket [Attempt %d]\n", i);
  109.         Sleep(1000);
  110.     }
  111.  
  112.     if (listenSocket == INVALID_SOCKET) {
  113.         printf("Failed to create socket: %d\n", WSAGetLastError());
  114.         freeaddrinfo(result);
  115.         WSACleanup();
  116.         return 1;
  117.     }
  118.  
  119.     //--Bind socket
  120.     int bindResult = 0;
  121.     bindResult = bind(listenSocket, result->ai_addr,
  122.         (int)result->ai_addrlen); //bind to localhost:port
  123.     if (bindResult == SOCKET_ERROR) {
  124.         printf("Fail to bind socket: %d\n", WSAGetLastError());
  125.         freeaddrinfo(result);
  126.         WSACleanup();
  127.         return 1;
  128.     }
  129.    
  130.     freeaddrinfo(result);
  131.  
  132.     //Start listening
  133.     if (listen(listenSocket, MAX_CONNECTIONS) == SOCKET_ERROR) {
  134.         printf("Failed to listen: %d\n", WSAGetLastError());
  135.         closesocket(listenSocket);
  136.         WSACleanup();
  137.         return 1;
  138.     }
  139.  
  140.     /*Non-blocking
  141.     unsigned long nonblocking = 1;
  142.     ioctlsocket(listenSocket, FIONBIO, &nonblocking);*/
  143.  
  144.     //Startup lua
  145.     printf("Creating lua state...\n");
  146.     luastate = lua_open();
  147.     luaL_openlibs(luastate);
  148.     lua_register(luastate, "print", l_print);
  149.  
  150.     //Server loop
  151.     printf("Entering server loop...\n");
  152.     char buffer[BUFFER_SIZE] = {0};
  153.  
  154.     while (!GetAsyncKeyState(VK_END))
  155.     {
  156.         memset(buffer, 0, BUFFER_SIZE);
  157.         SOCKET cs = INVALID_SOCKET;
  158.  
  159.         cs = accept(listenSocket, NULL, NULL);
  160.         if (cs == INVALID_SOCKET) continue;
  161.  
  162.         int sz = recv(cs, buffer, BUFFER_SIZE, 0);
  163.         if (sz > 0)
  164.         {
  165.             if (lstrcmpn(buffer, "GET", 3) == 0)
  166.             {
  167.                 parsesendGET(&cs, buffer);
  168.             }
  169.         }
  170.  
  171.         closesocket(cs);
  172.     }
  173.  
  174.     lua_close(luastate);
  175.     closesocket(listenSocket);
  176.     WSACleanup();
  177.  
  178.     return 0;
  179. }
  180.  
  181. void parsesendGET(SOCKET *cs, char *request)
  182. {
  183.     char *newreq = (char*)halloc(lstrlenA(request));
  184.     char lastReqChar = *request; int nridx = 0;
  185.     while (*request != NULL)
  186.     {
  187.         if (*request != '\r' && !(*request == '\n' && lastReqChar == '\n'))
  188.         {
  189.             newreq[nridx++] = *request;
  190.             lastReqChar = *request;
  191.         }
  192.         *request++;
  193.     }
  194.     newreq[lstrlenA(newreq)-1] = '\0';
  195.    
  196.     char *pnewreq = newreq;
  197.     while (*pnewreq != NULL)
  198.     {
  199.         if (*pnewreq == '\n') *pnewreq = '\0';
  200.         pnewreq++;
  201.     }
  202.  
  203.     char *GETline = newreq;
  204.     char *GETfile = GETline+4;
  205.     while (*GETline != NULL)
  206.     {
  207.         if (*GETline == ' ') *GETline = '\0';
  208.         *GETline++;
  209.     }
  210.    
  211.     char returnFile[MAX_PATH] = {0};
  212.     if (lstrcmpA(GETfile, "/") == 0)
  213.         lstrcpyA(returnFile, HTTP_DEFAULT_FILE);
  214.     else
  215.         lstrcpyA(returnFile, GETfile);
  216.     GETfile = &returnFile[0];
  217.  
  218.     char *GEText = NULL;
  219.     while (*GETfile != NULL)
  220.     {
  221.         if (*GETfile == '.') GEText = GETfile+1;
  222.         *GETfile++;
  223.     }
  224.  
  225.     char returnExt[16] = {0};
  226.     lstrcpyA(returnExt, "ext_");
  227.     lstrcatA(returnExt, GEText);
  228.     hfree(newreq);
  229.  
  230.     char mimeType[MAX_PATH] = {0};
  231.     if (GEText == NULL) lstrcpyA(mimeType, "text/plain");
  232.     else GetPrivateProfileStringA("TRANSLATIONS", returnExt, "text/plain",
  233.         mimeType, MAX_PATH, configFile);
  234.  
  235.     char filePath[MAX_PATH] = {0};
  236.     GetCurrentDirectoryA(MAX_PATH, filePath);
  237.     int currdirsize = lstrlenA(filePath);
  238.     lstrcatA(filePath, returnFile);
  239.    
  240.     //Read file
  241.     printf("File requested: %s\n", &filePath[0]+currdirsize);
  242.     char *fc = NULL; DWORD fsize = 0;
  243.  
  244.     HANDLE file = INVALID_HANDLE_VALUE;
  245.     file = CreateFileA(filePath, GENERIC_READ, FILE_SHARE_READ,
  246.         NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  247.     if (file == INVALID_HANDLE_VALUE)
  248.     {
  249.         printf("Error opening file! %d\n", GetLastError());
  250.         fc = (char*)halloc(KB * 5);
  251.         GetPrivateProfileSectionA("ERROR_404", fc, KB * 5, configFile);
  252.         if (lstrlenA(fc) > 0) ProfileSection2str(fc);
  253.         else lstrcpyA(fc, HTTP_404_CONTENT);
  254.         lstrcpyA(mimeType, "text/html");
  255.     }
  256.     else
  257.     {
  258.         fsize = GetFileSize(file, NULL);
  259.         printf("File size: %d\n", fsize);
  260.         fc = (char*)halloc(fsize+8);
  261.         DWORD bytesRead = 0;
  262.         if (ReadFile(file, fc, fsize, &bytesRead, NULL) == FALSE)
  263.         {
  264.             printf("Error reading file! %d\n", GetLastError());
  265.             CloseHandle(file);
  266.         }
  267.         CloseHandle(file);
  268.     }
  269.  
  270.     //Build HTTP response
  271.     lua_print_buffer = (char*)halloc(LUA_PRINTBUFFER_SIZE);
  272.     *lua_print_buffer = '\n';
  273.     char *data = (char*)halloc(512+fsize+LUA_PRINTBUFFER_SIZE);
  274.  
  275.     char httpVer[64] = {0};
  276.     wsprintfA(httpVer, HTTP_VER, (fsize==0)?"404 Not Found":"200 OK");
  277.     lstrcatA(data, HTTP_VER);
  278.     lstrcatA(data, HTTP_SERVER);
  279.     lstrcatA(data, HTTP_CACHECONTROL);
  280.     lstrcatA(data, HTTP_KEEPALIVE);
  281.     lstrcatA(data, HTTP_CONNECTION);
  282.     char httpContenttype[64] = {0};
  283.     wsprintfA(httpContenttype, HTTP_CONTENTTYPE, mimeType);
  284.     lstrcatA(data, httpContenttype);
  285.  
  286.     if (fc != NULL)
  287.     {
  288.         char *lend = ParseLuaTags(fc);
  289.         lstrcatA(data, fc);
  290.         if (lend != NULL)
  291.         {
  292.             lstrcatA(data, lend);
  293.             if (lstrlenA(lua_print_buffer) > 0)
  294.                 lstrcatA(data, lua_print_buffer);
  295.             hfree(lua_print_buffer);
  296.         }
  297.         hfree(fc);
  298.     }
  299.  
  300.     send(*cs, data, lstrlenA(data), 0);
  301.  
  302.     hfree(data);
  303. }
  304.  
  305. char *ParseLuaTags(char *html)
  306. {
  307.     char *ptr = html;
  308.     char *luastart = NULL;
  309.     char *luaend = NULL;
  310.     int lualen = -1;
  311.  
  312.     while (*ptr != NULL)
  313.     {
  314.         if (luastart == NULL)
  315.         {
  316.             if (*ptr == '<' && *++ptr == 'l' && *++ptr == 'u' &&
  317.                 *++ptr == 'a' && *++ptr == '>')
  318.             {
  319.                 *(ptr - 4) = '\0';
  320.                 luastart = ++ptr;
  321.                 if (*luastart == '\r') *luastart++;
  322.                 if (*luastart == '\n') *luastart++;
  323.             }
  324.         } else {
  325.             if (*ptr == '<' && *++ptr == '/' && *++ptr == 'l' &&
  326.                 *++ptr == 'u' && *++ptr == 'a' && *++ptr == '>')
  327.             {
  328.                 luaend = ptr - 7;
  329.             }
  330.         }
  331.         *ptr++;
  332.     }
  333.  
  334.     if (luastart != NULL && luaend != NULL)
  335.     {
  336.         lualen = luaend - luastart;
  337.         char *luastr = (char*)halloc(lualen + 1);
  338.         lstrcpynA(luastr, luastart, lualen);
  339.         //printf("Lua: %X %X %d\n", luastart, luaend, lualen);
  340.         luaL_dostring(luastate, luastr);
  341.         hfree(luastr);
  342.     }
  343.     return luaend+8;
  344. }
  345.  
  346. LUA_FUNCTION(l_print)
  347. {
  348.     if (!lua_isstring(L, 1)) return 0;
  349.     const char *str = lua_tostring(L, 1);
  350.     if (lstrlenA(lua_print_buffer) + lstrlenA(str) < LUA_PRINTBUFFER_SIZE)
  351.         lstrcatA(lua_print_buffer, str);
  352.     return 0;
  353. }
  354.  
  355. void ProfileSection2str(char *sec)
  356. {
  357.     char *ptr = sec;
  358.     while (true)
  359.     {
  360.         if (*ptr == NULL)
  361.         {
  362.             if (*(ptr+1) == NULL) break;
  363.             *ptr = '\n';
  364.         }
  365.         *ptr++;
  366.     }
  367. }
  368.  
  369. int lstrcmpn(char *str1, char *str2, int size)
  370. {
  371.     for (int i = 0; i < size; i++)
  372.     {
  373.         if (str1[i] != str2[i]) return 1;
  374.     }
  375.     return 0;
  376. }
  377.  
  378. int lstrcnt(char *str1, char chr)
  379. {
  380.     char *ptr = str1;
  381.     int charCount = 0;
  382.     while (*ptr != NULL)
  383.     {
  384.         if (chr == *ptr) charCount++;
  385.         *ptr++;
  386.     }
  387.     return charCount;
  388. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement