Subversion Repositories Kolibri OS

Rev

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

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