Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include <sys/socket.h>
  2. // #include <menuet/net.h>
  3.  
  4. #include "tp.h"
  5.  
  6. extern tp_obj tp_dict(TP);
  7. extern tp_obj tp_method(TP,tp_obj self,tp_obj v(TP));
  8. extern tp_obj tp_fnc(TP,tp_obj v(TP));
  9. extern tp_obj tp_get(TP,tp_obj self, tp_obj k);
  10. tp_obj tp_has(TP,tp_obj self, tp_obj k);
  11. // #define _cdecl __attribute__((cdecl))
  12. extern int (* _cdecl con_printf)(const char* format,...);
  13.  
  14. #define PRECISION 0.000001
  15.  
  16. #define GET_SOCKET_DESCRIPTOR(_obj, _sock) do{                  \
  17.     if (fabs(tp_has(tp, _obj, tp_string("socket")).number.val) < PRECISION)\
  18.         tp_raise(tp_None, "Socket not open", tp_None);          \
  19.     _sock = (__u32)(tp_get(tp, _obj, tp_string("socket")).number.val + PRECISION);\
  20. } while(0)
  21.  
  22. /* Socket close method.
  23.  *
  24.  * Example:
  25.  * s.close() # s must be a socket object created by socket.
  26.  *
  27.  * Raises exception if socket was not opened. Otherwise returns True.
  28.  */
  29. static tp_obj kolibri_close_socket(TP)
  30. {
  31.     // tp_obj self = TP_TYPE(TP_DICT);
  32.     // __u32  socktype;
  33.     // __u32  s;
  34.  
  35.     // GET_SOCKET_DESCRIPTOR(self, s);
  36.  
  37.     // socktype = (__u32)tp_get(tp, self, tp_string("type")).number.val;
  38.     // GET_SOCKET_DESCRIPTOR(self, s);
  39.     // if (socktype == SOCK_STREAM)
  40.     //     __menuet__close_TCP_socket(s);
  41.     // else if (socktype == SOCK_DGRAM)
  42.     //     __menuet__close_UDP_socket(s);
  43.     return tp_True;
  44. }
  45.  
  46. /* Socket send method.
  47.  *
  48.  * Example:
  49.  * data="<html><head><title>Preved!!!</title></head><body>Example.</body></html>"
  50.  * s.send(data)
  51.  * or:
  52.  * s.send(data, 20) # Send just 20 bytes
  53.  */
  54. static tp_obj kolibri_send(TP)
  55. {
  56.     // tp_obj self = TP_TYPE(TP_DICT);
  57.     // tp_obj data_obj = TP_TYPE(TP_STRING);
  58.     // __u32  datalen = TP_DEFAULT(tp_False).number.val;
  59.     // __u32  socktype = (__u32)tp_get(tp, self, tp_string("type")).number.val;
  60.     // __u32  s;
  61.     // int result;
  62.  
  63.     // GET_SOCKET_DESCRIPTOR(self, s);
  64.  
  65.     // if (datalen < 0 || datalen > data_obj.string.len)
  66.     //     datalen = data_obj.string.len;
  67.     // if (socktype == SOCK_STREAM)
  68.     //     result = __menuet__write_TCP_socket(s, datalen, (void *)data_obj.string.val);
  69.     // else if (socktype == SOCK_DGRAM)
  70.     //     result = __menuet__write_UDP_socket(s, datalen, (void *)data_obj.string.val);
  71.     // return tp_number(!(result != 0));
  72.     return tp_number(0);
  73. }
  74.  
  75. #define __u32 unsigned int
  76. #define __u8 unsigned char
  77.  
  78. /* Socket recv method.
  79.  *
  80.  * data="<html><head><title>Preved!!!</title></head><body>Example.</body></html>"
  81.  * s.recv(data)
  82.  * or:
  83.  * s.recv(data, 20) # Send just 20 bytes
  84.  */
  85. static tp_obj kolibri_recv(TP)
  86. {
  87.     tp_obj self = TP_TYPE(TP_DICT);
  88.     __u32  datalen = TP_DEFAULT(tp_False).number.val;
  89.     __u32  s;
  90.     __u8 c;
  91.     __u8 *buf, *p;
  92.     __u32 buf_size;
  93.     __u32 bytes_read = 0;
  94.     int i;
  95.  
  96.     // GET_SOCKET_DESCRIPTOR(self, s);
  97.  
  98.     // if (datalen)
  99.     //     buf_size = datalen;
  100.     // else
  101.     //     buf_size = 2048;
  102.     // if (!(buf = malloc(datalen)))
  103.     //     tp_raise(tp_None, "Cannot allocate buffer for received data", tp_None);
  104.     // p = buf;
  105.     // while (__menuet__read_socket(s, &c) && bytes_read < buf_size)
  106.     // {
  107.     //     *p++ = c;
  108.     //     bytes_read++;
  109.     //     if (bytes_read >= buf_size && !datalen)
  110.     //     {
  111.     //         buf_size += 1024;
  112.     //         buf = realloc(buf, buf_size);
  113.     //     }
  114.     // }
  115.     return tp_string_n(buf, bytes_read);
  116. }
  117.  
  118. static void inet_pton(TP, const char *buf, int len, __u32 *addr)
  119. {
  120.     char *p = (char *)buf;
  121.     int i = 0;
  122.     __u32 val = 0;
  123.     *addr = 0;
  124.     while (*p && p < buf + len && i < 4)
  125.     {
  126.         if (*p == '.' || !*p)
  127.         {
  128.             if (val > 255)
  129.                 tp_raise(tp_None, "ValueError: number > 255 in IP address", tp_None);
  130.             *addr += (val << ((i++) << 3));
  131.             val = 0;
  132.         }
  133.         else
  134.         {
  135.             if (*p < '0' || *p > '9')
  136.                 tp_raise(tp_None, "ValueError: bad char in IP address, digit expected", tp_None);
  137.             val = val * 10 + *p - '0';
  138.         }
  139.         p++;
  140.     }
  141.     if (!*p)
  142.     {
  143.         if (i == 3)
  144.             *addr += (val << ((i++) << 3));
  145.         else
  146.             tp_raise(tp_None, "ValueError: bad IP address", tp_None);
  147.     }
  148.  
  149. }
  150.  
  151. /* Converter from string presentation to binary address. */
  152. static tp_obj kolibri_inet_pton(TP)
  153. {
  154.     tp_obj obj;
  155.     __u32 addr;
  156.     obj = TP_TYPE(TP_STRING);
  157.     // inet_pton(tp, (char *)obj.string.val, (int)obj.string.len, &addr);
  158.     return tp_number(addr);
  159. }
  160.  
  161. /* Socket bind method.
  162.  *
  163.  * In KolibriOS it just sets local address and port.
  164.  *
  165.  * Example:
  166.  * s.bind('10.10.1.2', 6000) #Connects to 10.10.1.2:6000
  167.  */
  168. tp_obj kolibri_bind(TP)
  169. {
  170.     // tp_obj self = TP_TYPE(TP_DICT);
  171.     // tp_obj local_addr_obj = TP_OBJ();
  172.     // __u32  local_port = (__u32)TP_TYPE(TP_NUMBER).number.val;
  173.     // __u32  local_addr;
  174.  
  175.     // if (local_addr_obj.type == TP_NUMBER)
  176.     //     local_addr = local_addr_obj.number.val;
  177.     // else if (local_addr_obj.type == TP_STRING)
  178.     //     inet_pton(tp, (const char *)local_addr_obj.string.val, local_addr_obj.string.len, &local_addr);
  179.  
  180.     // tp_set(tp, self, tp_string("local_addr"), tp_number(local_addr));
  181.     // tp_set(tp, self, tp_string("local_port"), tp_number(local_port));
  182.     return tp_None;
  183. }
  184.  
  185. /* Socket connect method.
  186.  *
  187.  * Example:
  188.  * s.connect('10.10.1.1', 7000) #Connects to 10.10.1.1:7000
  189.  */
  190. tp_obj kolibri_connect(TP)
  191. {
  192.     // tp_obj self = TP_TYPE(TP_DICT);
  193.     // tp_obj  remote_addr_obj = TP_OBJ();
  194.     // __u32  remote_addr;
  195.     // __u32  remote_port = (__u32)TP_TYPE(TP_NUMBER).number.val;
  196.     // __u32  local_port  = tp_get(tp, self, tp_string("local_port")).number.val;
  197.     // __u32  socktype = (__u32)tp_get(tp, self, tp_string("type")).number.val;
  198.     // int  s = -1; /* Socket descriptor */
  199.  
  200.  
  201.     // if (remote_addr_obj.type == TP_NUMBER)
  202.     //     remote_addr = remote_addr_obj.number.val;
  203.     // else if (remote_addr_obj.type == TP_STRING)
  204.     //     inet_pton(tp, (const char *)remote_addr_obj.string.val, remote_addr_obj.string.len, &remote_addr);
  205.  
  206.     // if (socktype == SOCK_STREAM)
  207.     //     s = __menuet__open_TCP_socket(local_port, remote_port, remote_addr, 1);
  208.     // else if (socktype == SOCK_DGRAM)
  209.     //     s = __menuet__open_UDP_socket(local_port, remote_port, remote_addr);
  210.     // if (s >= 0)
  211.     // {
  212.     //     tp_set(tp, self, tp_string("socket"), tp_number(s));
  213.     //     return tp_True;
  214.     // }
  215.     // else
  216.         return tp_False;
  217. }
  218.  
  219. /* Socket listen method.
  220.  *
  221.  * Example:
  222.  * s.listen('10.10.1.1', 5000)
  223.  */
  224. tp_obj kolibri_listen(TP)
  225. {
  226.     // tp_obj self = TP_TYPE(TP_DICT);
  227.     // tp_obj remote_addr_obj = TP_OBJ();
  228.     // __u32  remote_addr;
  229.     // __u32  remote_port = (__u32)TP_TYPE(TP_NUMBER).number.val;
  230.     // __u32  local_port  = tp_get(tp, self, tp_string("local_port")).number.val;
  231.     // __u32  socktype = (__u32)tp_get(tp, self, tp_string("type")).number.val;
  232.     // int  s = -1; /* Socket descriptor */
  233.  
  234.     // if (socktype != SOCK_STREAM)
  235.     //     tp_raise(tp_None, "IOError: attempt to listen on non-TCP socket", tp_None);
  236.  
  237.     // if (remote_addr_obj.type == TP_NUMBER)
  238.     //     remote_addr = remote_addr_obj.number.val;
  239.     // else if (remote_addr_obj.type == TP_STRING)
  240.     //     inet_pton(tp, (const char *)remote_addr_obj.string.val, remote_addr_obj.string.len, &remote_addr);
  241.  
  242.     // if ((s = __menuet__open_TCP_socket(local_port, remote_port, remote_addr, 0)) >= 0)
  243.     // {
  244.     //     tp_set(tp, self, tp_string("socket"), tp_number(s));
  245.     //     return tp_True;
  246.     // }
  247.     // else
  248.         return tp_False;
  249. }
  250.  
  251.  
  252. /* Exported function.
  253.  *
  254.  * Example:
  255.  *
  256.  * s = socket(socket.AF_INET, socket.SOCK_DGRAM)
  257.  *
  258.  * Returns socket object.
  259.  */
  260. tp_obj kolibri_socket(TP)
  261. {
  262.     tp_obj s;
  263.     tp_obj sockfamily = TP_TYPE(TP_NUMBER);
  264.     tp_obj socktype = TP_TYPE(TP_NUMBER);
  265.  
  266.     // if (fabs(sockfamily.number.val - AF_INET) > PRECISION ||
  267.     //     (fabs(socktype.number.val - SOCK_STREAM) > PRECISION &&
  268.     //      fabs(socktype.number.val - SOCK_DGRAM) > PRECISION))
  269.     //     return tp_None;
  270.     s = tp_dict(tp);
  271.     // tp_set(tp, s, tp_string("family"), sockfamily);
  272.     // tp_set(tp, s, tp_string("type"), socktype);
  273.     // tp_set(tp, s, tp_string("bind"), tp_method(tp, s, kolibri_bind));
  274.     // tp_set(tp, s, tp_string("connect"), tp_method(tp, s, kolibri_connect));
  275.     // tp_set(tp, s, tp_string("send"), tp_method(tp, s, kolibri_send));
  276.     // tp_set(tp, s, tp_string("recv"), tp_method(tp, s, kolibri_recv));
  277.     // tp_set(tp, s, tp_string("close"), tp_method(tp, s, kolibri_close_socket));
  278.     // if (fabs(socktype.number.val - SOCK_STREAM) < PRECISION)
  279.     //     tp_set(tp, s, tp_string("listen"), tp_method(tp, s, kolibri_listen));
  280.     return s;
  281. }
  282.  
  283. tp_obj kolibri_socket_module(TP)
  284. {
  285.     tp_obj socket_mod = tp_dict(tp);
  286.  
  287.     // tp_set(tp, socket_mod, tp_string("AF_INET"), tp_number(AF_INET));
  288.     // tp_set(tp, socket_mod, tp_string("SOCK_STREAM"), tp_number(SOCK_STREAM));
  289.     // tp_set(tp, socket_mod, tp_string("SOCK_DGRAM"), tp_number(SOCK_DGRAM));
  290.     tp_set(tp, socket_mod, tp_string("AF_INET"), tp_number(0));
  291.     tp_set(tp, socket_mod, tp_string("SOCK_STREAM"), tp_number(0));
  292.     tp_set(tp, socket_mod, tp_string("SOCK_DGRAM"), tp_number(0));
  293.     tp_set(tp, socket_mod, tp_string("inet_pton"), tp_fnc(tp, kolibri_inet_pton));
  294.     tp_set(tp, socket_mod, tp_string("socket"), tp_fnc(tp, kolibri_socket));
  295.     return socket_mod;
  296. }
  297.