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=" |
||
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=" |
||
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 | }>>><>><>>>>> |