airevent

WebSocket для Lua

Mar 11th, 2013
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.12 KB | None | 0 0
  1. //
  2.  
  3. #include "ws.h"
  4.  
  5.  
  6.  
  7. int luaopen_ws( lua_State *L ) {
  8.     luaL_newlib(L, __index);
  9.  
  10.     luaL_newlib(L, _server_index);
  11.     lua_setfield(L, -2, "server");
  12.  
  13.     luaL_newlib(L, _client_index);
  14.     lua_setfield(L, -2, "client");
  15.  
  16.     return 1;
  17. }
  18.  
  19.  
  20.  
  21. static int lua_ws_xor( lua_State *L ) {
  22.     size_t data_len, key_len;
  23.     const char *data = luaL_checklstring(L, 1, &data_len);
  24.     const char *key  = luaL_checklstring(L, 2, &key_len);
  25.     char result[data_len];
  26.  
  27.     for ( size_t d=0, k=0; d<data_len; ) {
  28.         result[d] = data[d] ^ key[k];
  29.         k++; d++;
  30.         if ( k >= key_len ) k = 0;
  31.     }
  32.  
  33.     lua_pushlstring(L, result, data_len);
  34.     return 1;
  35. }
  36.  
  37.  
  38.  
  39. static int lua_ws_client_newmask( lua_State *L ) {
  40.     char mask[WS_MASKLEN];
  41.     struct timeval tv;
  42.  
  43.     for ( short i=0; i<WS_MASKLEN; i++ ) {
  44.         gettimeofday(&tv, NULL);
  45.         srand((unsigned int)tv.tv_usec);
  46.         mask[i] = (char)rand();
  47.     }
  48.  
  49.     lua_pushlstring(L, mask, WS_MASKLEN);
  50.     return 1;
  51. }
  52.  
  53.  
  54.  
  55. // пакет закрытия от клиента к серверу
  56. static int lua_ws_client_close( lua_State *L ) {
  57.     uchar str[] = { 0x88, 0x80, 0x11, 0x11, 0x11, 0x11 };
  58.     lua_pushlstring(L, (char *)str, 6);
  59.     return 1;
  60. }
  61.  
  62.  
  63.  
  64. // пакет закрытия от сервера к клиенту
  65. static int lua_ws_server_close( lua_State *L ) {
  66.     uchar str[] = { 0x88, 0x00 };
  67.     lua_pushlstring(L, (char *)str, 2);
  68.     return 1;
  69. }
  70.  
  71.  
  72.  
  73. // пакет от клиента к серверу
  74. static int lua_ws_client_pack( lua_State *L ) {
  75.     ulong len = luaL_checknumber(L, 1);
  76.     ushort len2;
  77.     uchar head[10];
  78.     uchar head_len = 2;
  79.  
  80.     if ( len > 65535 ) { // long
  81.         head_len += 8;
  82.         head[1] = 127;
  83.         len = (ulong)ntohll(len);
  84.         memcpy(&head[2], &len, 8);
  85.     } else if ( len > 125 ) { // medium
  86.         head_len += 2;
  87.         head[1] = 126;
  88.         len2 = (ushort)ntohs((ushort)len);
  89.         memcpy(&head[2], &len2, 2);
  90.     } else { // short
  91.         head[1] = (uchar)len;
  92.     }
  93.  
  94.     head[0] = 0x81;
  95.     head[1] |= 0x80;
  96.  
  97.     lua_pushlstring(L, (char *)head, head_len);
  98.     return 1;
  99. }
  100.  
  101.  
  102.  
  103. // пакет от сервера к клиенту
  104. static int lua_ws_server_pack( lua_State *L ) {
  105.     ulong len = luaL_checknumber(L, 1);
  106.     ushort len2;
  107.     uchar head[10];
  108.     uchar head_len = 2;
  109.  
  110.     if ( len > 65535 ) { // long
  111.         head_len += 8;
  112.         head[1] = 127;
  113.         len = (ulong)ntohll(len);
  114.         memcpy(&head[2], &len, 8);
  115.     } else if ( len > 125 ) { // medium
  116.         head_len += 2;
  117.         head[1] = 126;
  118.         len2 = (ushort)ntohs((ushort)len);
  119.         memcpy(&head[2], &len2, 2);
  120.     } else { // short
  121.         head[1] = (uchar)len;
  122.     }
  123.  
  124.     head[0] = 0x81;
  125.  
  126.     lua_pushlstring(L, (char *)head, head_len);
  127.     return 1;
  128. }
  129.  
  130.  
  131.  
  132. /* errors:
  133.     0 - no error
  134.     1 - not enough data
  135.     2 - connection closed
  136.     3 - unknown opcode or not implemented
  137. */
  138. static int lua_ws_server_unpack( lua_State *L ) {
  139.     size_t str_len;
  140.     const char *str = luaL_checklstring(L, 1, &str_len);
  141.     uchar FIN, OPCODE, MASK, PLEN;
  142.     ulong data_len; // real length of body
  143.     ulong head_len; // real length of header
  144.     char mask[WS_MASKLEN];
  145.  
  146.     head_len = 2; // min header len
  147.     if ( str_len < head_len ) ws_err(1);
  148.  
  149.     FIN = ((str[0] & 0x80) > 0);
  150.     OPCODE = (str[0] & 0x0F);
  151.     MASK = ((str[1] & 0x80) > 0);
  152.     PLEN = (str[1] & 0x7F);
  153.  
  154.     if ( OPCODE == 8 ) ws_err(2);
  155.     if ( OPCODE != 1 ) ws_err(3);
  156.     if ( FIN != 1 )    ws_err(3);
  157.     if ( MASK != 1 )   ws_err(3);
  158.  
  159.     if ( PLEN == 127 ) {
  160.         head_len += 8; // long (+8b)
  161.         if ( str_len < head_len ) ws_err(1);
  162.         data_len = (ulong)ntohll(*((ulong *)&str[2]));
  163.     } else if ( PLEN == 126 ) {
  164.         head_len += 2; // medium (+2b)
  165.         if ( str_len < head_len ) ws_err(1);
  166.         data_len = (ulong)ntohs(*((ushort *)&str[2]));
  167.     } else { // short
  168.         data_len = (ulong)PLEN;
  169.     }
  170.  
  171.     head_len += WS_MASKLEN; // + mask
  172.     if ( str_len < head_len ) ws_err(1);
  173.  
  174.     for ( size_t i=0; i<WS_MASKLEN; i++ ) {
  175.         mask[i] = str[head_len-WS_MASKLEN+i];
  176.     }
  177.  
  178.     if ( str_len < head_len+data_len ) ws_err(1);
  179.  
  180.     lua_pushnumber(L, 0); // success
  181.     lua_pushlstring(L, str+head_len, data_len); // masked data
  182.     lua_pushnumber(L, head_len+data_len); // packet full len
  183.     lua_pushlstring(L, mask, WS_MASKLEN); // mask
  184.     return 4;
  185. }
  186.  
  187.  
  188.  
  189. static int lua_ws_client_unpack( lua_State *L ) {
  190.     size_t str_len;
  191.     const char *str = luaL_checklstring(L, 1, &str_len);
  192.     uchar FIN, OPCODE, MASK, PLEN;
  193.     ulong data_len; // real length of body
  194.     ulong head_len; // real length of header
  195.  
  196.     head_len = 2; // min header len
  197.     if ( str_len < head_len ) ws_err(1);
  198.  
  199.     FIN = ((str[0] & 0x80) > 0);
  200.     OPCODE = (str[0] & 0x0F);
  201.     MASK = ((str[1] & 0x80) > 0);
  202.     PLEN = (str[1] & 0x7F);
  203.  
  204.     if ( OPCODE == 8 ) ws_err(2);
  205.     if ( OPCODE != 1 ) ws_err(3);
  206.     if ( FIN != 1 )    ws_err(3);
  207.     if ( MASK != 0 )   ws_err(3);
  208.  
  209.     if ( PLEN == 127 ) {
  210.         head_len += 8; // long (+8b)
  211.         if ( str_len < head_len ) ws_err(1);
  212.         data_len = (ulong)ntohll(*((ulong *)&str[2]));
  213.     } else if ( PLEN == 126 ) {
  214.         head_len += 2; // medium (+2b)
  215.         if ( str_len < head_len ) ws_err(1);
  216.         data_len = (ulong)ntohs(*((ushort *)&str[2]));
  217.     } else { // short
  218.         data_len = (ulong)PLEN;
  219.     }
  220.  
  221.     if ( str_len < head_len+data_len ) ws_err(1);
  222.  
  223.     lua_pushnumber(L, 0); // success
  224.     lua_pushlstring(L, str+head_len, data_len); // data
  225.     lua_pushnumber(L, head_len+data_len); // packet full len
  226.     return 3;
  227. }
Advertisement
Add Comment
Please, Sign In to add comment