blob: a54a2cb7e99dcb47915be86acecce7aaf1b6c0ad [file] [log] [blame]
Guido van Rossum6574b3e1991-06-25 21:36:08 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Socket module */
26
27/*
28This module provides an interface to Berkeley socket IPC.
29
30Limitations:
31
32- only AF_INET and AF_UNIX address families
33- no asynchronous I/O
34- no flags on send/receive operations
35- no socket options
36- no protocol parameter on socket() system call
37- although socket objects have read() and write() methods, they can't be
38 used everywhere where file objects can be used (e.g., sys.stdout won't
39 work and there is no readline() method)
40
41Interface:
42
43- socket.socket(family, type) returns a new socket object
44- family and type constants from <socket.h> are accessed as socket.AF_INET etc.
45- socket methods are:
46 - s.bind(sockaddr) --> None
47 - s.connect(sockaddr) --> None
48 - s.accept() --> newsocket, sockaddr
49 - s.listen(n) --> None
50 - s.read(nbytes) --> string
51 - s.write(string) --> nbytes
52 - s.recvfrom(nbytes) --> string, sockaddr
53 - s.sendto(string, sockaddr) --> nbytes
54 - s.shutdown(how) --> None
55 - s.close() --> None
56- errors are reported as the exception socket.error
57- an Internet socket address is a pair (hostname, port)
58 where hostname can be anything recognized by gethostbyname()
59 (including the dd.dd.dd.dd notation) and port is in host byte order
60- where a hostname is returned, the dd.dd.dd.dd notation is used
61- a UNIX domain socket is a string specifying the pathname
62
63Bugs:
64
65- On the vax, the port numbers seem to be mixed up (when receiving only???)
66*/
67
68#include "allobjects.h"
69#include "modsupport.h"
70
71#include <sys/types.h>
72#include <sys/socket.h>
73#include <netinet/in.h>
74#include <sys/un.h>
75#include <netdb.h>
76
77static object *SocketError; /* Exception socket.error */
78
79static object *
80socket_error()
81{
82 return err_errno(SocketError);
83}
84
85typedef struct {
86 OB_HEAD
87 int sock_fd;
88 int sock_family;
89 int sock_type;
90 int sock_proto;
91} sockobject;
92
93extern typeobject Socktype; /* Forward */
94
95static sockobject *
96newsockobject(fd, family, type, proto)
97 int fd, family, type, proto;
98{
99 sockobject *s;
100 s = NEWOBJ(sockobject, &Socktype);
101 if (s != NULL) {
102 s->sock_fd = fd;
103 s->sock_family = family;
104 s->sock_type = type;
105 s->sock_proto = proto;
106 }
107 return s;
108}
109
110static int setinetaddr PROTO((char *, struct sockaddr_in *));
111static int
112setinetaddr(name, addr_ret)
113 char *name;
114 struct sockaddr_in *addr_ret;
115{
116 struct hostent *hp;
117
118 if (strcmp(name, "<any>") == 0) {
119 addr_ret->sin_addr.s_addr = INADDR_ANY;
120 return 4;
121 }
122 if (strcmp(name, "<broadcast>") == 0) {
123 addr_ret->sin_addr.s_addr = INADDR_BROADCAST;
124 return 4;
125 }
126 hp = gethostbyname(name);
127 if (hp == NULL) {
128 err_setstr(SocketError, "host not found");
129 return -1;
130 }
131 memcpy((char *) &addr_ret->sin_addr, hp->h_addr, hp->h_length);
132 return hp->h_length;
133}
134
135static object *
136makepair(a, b)
137 object *a, *b;
138{
139 object *pair = NULL;
140 if (a == NULL || b == NULL || (pair = newtupleobject(2)) == NULL) {
141 XDECREF(a);
142 XDECREF(b);
143 return NULL;
144 }
145 settupleitem(pair, 0, a);
146 settupleitem(pair, 1, b);
147 return pair;
148}
149
150/*ARGSUSED*/
151static object *
152makesockaddr(addr, addrlen)
153 struct sockaddr *addr;
154 int addrlen;
155{
156 if (addr->sa_family == AF_INET) {
157 struct sockaddr_in *a = (struct sockaddr_in *) addr;
158 long x = ntohl(a->sin_addr.s_addr);
159 char buf[100];
160 sprintf(buf, "%d.%d.%d.%d",
161 (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
162 (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
163 return makepair(newstringobject(buf),
164 newintobject((long) ntohs(a->sin_port)));
165 }
166 if (addr->sa_family == AF_UNIX) {
167 struct sockaddr_un *a = (struct sockaddr_un *) addr;
168 return newstringobject(a->sun_path);
169 }
170 err_setstr(SocketError, "returning unknown socket address type");
171 return NULL;
172}
173
174static int getsockaddrarg PROTO((sockobject *, object *,
175 struct sockaddr **, int *));
176static int
177getsockaddrarg(s, args, addr_ret, len_ret)
178 sockobject *s;
179 object *args;
180 struct sockaddr **addr_ret;
181 int *len_ret;
182{
183 if (s->sock_family == AF_UNIX) {
184 static struct sockaddr_un addr;
185 object *path;
186 int len;
187 if (!getstrarg(args, &path) ||
188 (len = getstringsize(path)) > sizeof addr.sun_path)
189 return 0;
190 addr.sun_family = AF_UNIX;
191 memcpy(addr.sun_path, getstringvalue(path), len);
192 *addr_ret = (struct sockaddr *) &addr;
193 *len_ret = len + sizeof addr.sun_family;
194 return 1;
195 }
196
197 if (s->sock_family == AF_INET) {
198 static struct sockaddr_in addr;
199 object *host;
200 int port;
201 if (!getstrintarg(args, &host, &port))
202 return 0;
203 if (setinetaddr(getstringvalue(host), &addr) < 0)
204 return 0;
205 addr.sin_family = AF_INET;
206 addr.sin_port = htons(port);
207 *addr_ret = (struct sockaddr *) &addr;
208 *len_ret = sizeof addr;
209 return 1;
210 }
211
212 err_setstr(SocketError, "getsockaddrarg: bad family");
213 return 0;
214}
215
216static object *
217sock_accept(s, args)
218 sockobject *s;
219 object *args;
220{
221 char addrbuf[256];
222 int addrlen, newfd;
223 object *res;
224 if (!getnoarg(args))
225 return NULL;
226 addrlen = sizeof addrbuf;
227 newfd = accept(s->sock_fd, (struct sockaddr *) addrbuf, &addrlen);
228 if (newfd < 0)
229 return socket_error();
230 res = makepair((object *) newsockobject(newfd, AF_UNSPEC, 0, 0),
231 makesockaddr((struct sockaddr *) addrbuf, addrlen));
232 if (res == NULL)
233 close(newfd);
234 return res;
235}
236
237static object *
238sock_bind(s, args)
239 sockobject *s;
240 object *args;
241{
242 struct sockaddr *addr;
243 int addrlen;
244 if (!getsockaddrarg(s, args, &addr, &addrlen))
245 return NULL;
246 if (bind(s->sock_fd, addr, addrlen) < 0)
247 return socket_error();
248 INCREF(None);
249 return None;
250}
251
252static object *
253sock_close(s, args)
254 sockobject *s;
255 object *args;
256{
257 if (!getnoarg(args))
258 return NULL;
259 (void) close(s->sock_fd);
260 s->sock_fd = -1;
261 INCREF(None);
262 return None;
263}
264
265static object *
266sock_connect(s, args)
267 sockobject *s;
268 object *args;
269{
270 struct sockaddr *addr;
271 int addrlen;
272 if (!getsockaddrarg(s, args, &addr, &addrlen))
273 return NULL;
274 if (connect(s->sock_fd, addr, addrlen) < 0)
275 return socket_error();
276 INCREF(None);
277 return None;
278}
279
280static object *
281sock_listen(s, args)
282 sockobject *s;
283 object *args;
284{
285 int backlog;
286 if (!getintarg(args, &backlog))
287 return NULL;
288 if (listen(s->sock_fd, backlog) < 0)
289 return socket_error();
290 INCREF(None);
291 return None;
292}
293
294static object *
295sock_read(s, args)
296 sockobject *s;
297 object *args;
298{
299 int len, n;
300 object *buf;
301 if (!getintarg(args, &len))
302 return NULL;
303 buf = newsizedstringobject((char *) 0, len);
304 if (buf == NULL)
305 return NULL;
306 n = read(s->sock_fd, getstringvalue(buf), len);
307 if (n < 0)
308 return socket_error();
309 if (resizestring(&buf, n) < 0)
310 return NULL;
311 return buf;
312}
313
314static object *
315sock_recvfrom(s, args)
316 sockobject *s;
317 object *args;
318{
319 char addrbuf[256];
320 object *buf;
321 int addrlen, len, n;
322 if (!getintarg(args, &len))
323 return NULL;
324 buf = newsizedstringobject((char *) 0, len);
325 addrlen = sizeof addrbuf;
326 n = recvfrom(s->sock_fd, getstringvalue(buf), len, 0,
327 addrbuf, &addrlen);
328 if (n < 0)
329 return socket_error();
330 if (resizestring(&buf, n) < 0)
331 return NULL;
332 return makepair(buf, makesockaddr(addrbuf, addrlen));
333}
334
335static object *
336sock_sendto(s, args)
337 sockobject *s;
338 object *args;
339{
340 object *buf;
341 struct sockaddr *addr;
342 int addrlen, len, n;
343 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
344 err_badarg();
345 return NULL;
346 }
347 if (!getstrarg(gettupleitem(args, 0), &buf) ||
348 !getsockaddrarg(s, gettupleitem(args, 1), &addr, &addrlen))
349 return NULL;
350 len = getstringsize(buf);
351 n = sendto(s->sock_fd, getstringvalue(buf), len, 0,
352 addr, addrlen);
353 if (n < 0)
354 return socket_error();
355 return newintobject((long) n);
356}
357
358static object *
359sock_shutdown(s, args)
360 sockobject *s;
361 object *args;
362{
363 int how;
364 if (!getintarg(args, &how))
365 return NULL;
366 if (shutdown(s->sock_fd, how) < 0)
367 return socket_error();
368 INCREF(None);
369 return None;
370}
371
372static object *
373sock_write(s, args)
374 sockobject *s;
375 object *args;
376{
377 object *buf;
378 int len, n;
379 if (!getstrarg(args, &buf))
380 return NULL;
381 len = getstringsize(buf);
382 n = write(s->sock_fd, getstringvalue(buf), len);
383 if (n < 0)
384 return socket_error();
385 return newintobject((long) n);
386}
387
388static struct methodlist sock_methods[] = {
389 {"accept", sock_accept},
390 {"bind", sock_bind},
391 {"close", sock_close},
392 {"connect", sock_connect},
393 {"listen", sock_listen},
394 {"read", sock_read},
395 {"recvfrom", sock_recvfrom},
396 {"sendto", sock_sendto},
397 {"shutdown", sock_shutdown},
398 {"write", sock_write},
399 {NULL, NULL} /* sentinel */
400};
401
402static void
403sock_dealloc(s)
404 sockobject *s;
405{
406 (void) close(s->sock_fd);
407 DEL(s);
408}
409
410static object *
411sock_getattr(s, name)
412 sockobject *s;
413 char *name;
414{
415 return findmethod(sock_methods, (object *) s, name);
416}
417
418static typeobject Socktype = {
419 OB_HEAD_INIT(&Typetype)
420 0,
421 "socket",
422 sizeof(sockobject),
423 0,
424 sock_dealloc, /*tp_dealloc*/
425 0, /*tp_print*/
426 sock_getattr, /*tp_getattr*/
427 0, /*tp_setattr*/
428 0, /*tp_compare*/
429 0, /*tp_repr*/
430 0, /*tp_as_number*/
431 0, /*tp_as_sequence*/
432 0, /*tp_as_mapping*/
433};
434
435/*ARGSUSED*/
436static object *
437socket_socket(self, args)
438 object *self;
439 object *args;
440{
441 sockobject *s;
442 int family, type, proto, fd;
443 if (!getintintarg(args, &family, &type))
444 return NULL;
445 proto = 0;
446 fd = socket(family, type, proto);
447 if (fd < 0)
448 return socket_error();
449 s = newsockobject(fd, family, type, proto);
450 if (s == NULL)
451 close(fd);
452 return (object *) s;
453}
454
455static struct methodlist socket_methods[] = {
456 {"socket", socket_socket},
457 {NULL, NULL} /* Sentinel */
458};
459
460static void
461insint(d, name, value)
462 object *d;
463 char *name;
464 int value;
465{
466 object *v = newintobject((long) value);
467 if (v == NULL) {
468 /* Don't bother reporting this error */
469 err_clear();
470 }
471 else {
472 dictinsert(d, name, v);
473 DECREF(v);
474 }
475}
476
477void
478initsocket()
479{
480 object *m, *d;
481
482 m = initmodule("socket", socket_methods);
483 d = getmoduledict(m);
484 SocketError = newstringobject("socket.error");
485 if (SocketError == NULL || dictinsert(d, "error", SocketError) != 0)
486 fatal("can't define socket.error");
487 insint(d, "AF_INET", AF_INET);
488 insint(d, "AF_UNIX", AF_UNIX);
489 insint(d, "SOCK_STREAM", SOCK_STREAM);
490 insint(d, "SOCK_DGRAM", SOCK_DGRAM);
491 insint(d, "SOCK_RAW", SOCK_RAW);
492 insint(d, "SOCK_SEQPACKET", SOCK_SEQPACKET);
493 insint(d, "SOCK_RDM", SOCK_RDM);
494}