Oops -- Lib/Test should be Lib/test, of course!
[python/dscho.git] / Mac / Unsupported / mactcp / mactcpmodule.c
blobfc07f1e73e5f5927a105b0bc3b8b376893b00e8b
1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 #include "allobjects.h"
26 #include "modsupport.h" /* For getargs() etc. */
28 #include "macglue.h"
29 #include "tcpglue.h"
31 #include <Desk.h>
33 /* State of a tcp stream, in the connectionState field */
34 #define STATE_CLOSED 0
35 #define STATE_LISTEN 2
36 #define STATE_ESTAB 8
37 #define STATE_CWAIT 18
39 /* Python code has an additional reason for asr call: open done */
40 #define MY_OPEN_DONE 32766
42 static object *ErrorObject;
44 TCPIOCompletionUPP upp_tcp_done;
45 TCPNotifyUPP upp_tcp_asr;
46 #if 0
47 UDPIOCompletionUPP upp_udp_done;
48 #endif
49 UDPNotifyUPP upp_udp_asr;
51 /* ----------------------------------------------------- */
52 /* Declarations for objects of type MacTCP connection status */
54 typedef struct {
55 OB_HEAD
56 TCPStatusPB status;
57 } tcpcsobject;
59 staticforward typeobject Tcpcstype;
61 #define is_tcpcsobject(v) ((v)->ob_type == &Tcpcstype)
63 /* ---------------------------------------------------------------- */
64 /* Declarations for objects of type MacTCP global status */
66 #ifdef TCP_GS
67 typedef struct {
68 OB_HEAD
69 TCPParam *ptr;
70 } tcpgsobject;
72 staticforward typeobject Tcpgstype;
74 #define is_tcpgsobject(v) ((v)->ob_type == &Tcpgstype)
75 #endif /* TCP_GS */
77 /* ---------------------------------------------------------------- */
78 /* Declarations for objects of type MacTCP TCP stream */
80 typedef struct {
81 OB_HEAD
82 TCPiopb iop;
83 long localhost; /* Our IP address */
84 short localport; /* Our port number */
85 object *asr; /* Optional async notification routine */
86 int asr_ec; /* error code parameter to asr */
87 int asr_reason; /* detail for some errors */
88 int async_busy; /* True when completion routine pending */
89 int async_err; /* the error for the async call */
90 } tcpsobject;
92 staticforward typeobject Tcpstype;
94 #define is_tcpsobject(v) ((v)->ob_type == &Tcpstype)
96 /* ---------------------------------------------------------------- */
97 /* Declarations for objects of type MacTCP UDP stream */
99 typedef struct {
100 OB_HEAD
101 UDPiopb iop;
102 object *asr;
103 int asr_ec; /* error code parameter to asr */
104 ip_port port;
105 } udpsobject;
107 staticforward typeobject Udpstype;
109 #define is_udpsobject(v) ((v)->ob_type == &Udpstype)
111 /* ---------------------------------------------------------------- */
113 static tcpcsobject *
114 newtcpcsobject(ptr)
115 TCPStatusPB *ptr;
117 tcpcsobject *self;
119 self = NEWOBJ(tcpcsobject, &Tcpcstype);
120 if (self == NULL)
121 return NULL;
122 self->status = *ptr;
123 return self;
126 static void
127 tcpcs_dealloc(self)
128 tcpcsobject *self;
130 DEL(self);
132 /* Code to access structure members by accessing attributes */
134 #include "structmember.h"
136 #define OFF(x) offsetof(TCPStatusPB, x)
138 static struct memberlist tcpcs_memberlist[] = {
139 {"remoteHost", T_ULONG, OFF(remoteHost), RO},
140 {"remotePort", T_USHORT, OFF(remotePort), RO},
141 {"localHost", T_UINT, OFF(localHost), RO},
142 {"localPort", T_USHORT, OFF(localPort), RO},
143 {"tosFlags", T_BYTE, OFF(tosFlags), RO},
144 #if 0 /* Bug in header file: cannot access precedence */
145 {"precedence" T_BYTE, OFF(precedence), RO},
146 #endif
147 {"connectionState", T_BYTE, OFF(connectionState), RO},
148 {"sendWindow", T_USHORT, OFF(sendWindow), RO},
149 {"rcvWindow", T_USHORT, OFF(rcvWindow), RO},
150 {"amtUnackedData", T_USHORT, OFF(amtUnackedData), RO},
151 {"amtUnreadData", T_USHORT, OFF(amtUnreadData), RO},
152 {"sendUnacked", T_UINT, OFF(sendUnacked), RO},
153 {"sendNext", T_UINT, OFF(sendNext), RO},
154 {"congestionWindow", T_UINT, OFF(congestionWindow), RO},
155 {"rcvNext", T_UINT, OFF(rcvNext), RO},
156 {"srtt", T_UINT, OFF(srtt), RO},
157 {"lastRTT", T_UINT, OFF(lastRTT), RO},
158 {"sendMaxSegSize", T_UINT, OFF(sendMaxSegSize), RO},
159 {NULL} /* Sentinel */
162 static object *
163 tcpcs_getattr(self, name)
164 tcpcsobject *self;
165 char *name;
167 return getmember((char *)&self->status, tcpcs_memberlist, name);
171 static typeobject Tcpcstype = {
172 OB_HEAD_INIT(&Typetype)
173 0, /*ob_size*/
174 "MacTCP connection status", /*tp_name*/
175 sizeof(tcpcsobject), /*tp_basicsize*/
176 0, /*tp_itemsize*/
177 /* methods */
178 (destructor)tcpcs_dealloc, /*tp_dealloc*/
179 (printfunc)0, /*tp_print*/
180 (getattrfunc)tcpcs_getattr, /*tp_getattr*/
181 (setattrfunc)0, /*tp_setattr*/
182 (cmpfunc)0, /*tp_compare*/
183 (reprfunc)0, /*tp_repr*/
184 0, /*tp_as_number*/
185 0, /*tp_as_sequence*/
186 0, /*tp_as_mapping*/
187 (hashfunc)0, /*tp_hash*/
190 /* End of code for MacTCP connection status objects */
191 /* -------------------------------------------------------- */
193 #ifdef TCP_GS
194 static tcpgsobject *
195 newtcpgsobject(ptr)
196 TCPParam *ptr;
198 tcpgsobject *self;
200 self = NEWOBJ(tcpgsobject, &Tcpgstype);
201 if (self == NULL)
202 return NULL;
203 self->ptr = ptr;
204 return self;
207 static void
208 tcpgs_dealloc(self)
209 tcpgsobject *self;
211 DEL(self);
213 /* Code to access structure members by accessing attributes */
214 #undef OFF
215 #define OFF(x) offsetof(TCPParam, x)
217 static struct memberlist tcpgs_memberlist[] = {
218 {"RtoA", T_UINT, OFF(tcpRtoA), RO},
219 {"RtoMin", T_UINT, OFF(tcpRtoMin), RO},
220 {"RtoMax", T_UINT, OFF(tcpRtoMax), RO},
221 {"MaxSegSize", T_UINT, OFF(tcpMaxSegSize), RO},
222 {"MaxConn", T_UINT, OFF(tcpMaxConn), RO},
223 {"MaxWindow", T_UINT, OFF(tcpMaxWindow), RO},
224 {NULL} /* Sentinel */
227 static object *
228 tcpgs_getattr(self, name)
229 tcpgsobject *self;
230 char *name;
232 object *rv;
234 return getmember((char *)self->ptr, tcpgs_memberlist, name);
237 static typeobject Tcpgstype = {
238 OB_HEAD_INIT(&Typetype)
239 0, /*ob_size*/
240 "MacTCP global status", /*tp_name*/
241 sizeof(tcpgsobject), /*tp_basicsize*/
242 0, /*tp_itemsize*/
243 /* methods */
244 (destructor)tcpgs_dealloc, /*tp_dealloc*/
245 (printfunc)0, /*tp_print*/
246 (getattrfunc)tcpgs_getattr, /*tp_getattr*/
247 (setattrfunc)0, /*tp_setattr*/
248 (cmpfunc)0, /*tp_compare*/
249 (reprfunc)0, /*tp_repr*/
250 0, /*tp_as_number*/
251 0, /*tp_as_sequence*/
252 0, /*tp_as_mapping*/
253 (hashfunc)0, /*tp_hash*/
255 #endif /* TCP_GS */
257 /* End of code for MacTCP global status objects */
258 /* -------------------------------------------------------- */
260 static int
261 tcps_checkstate(self, state, state2)
262 tcpsobject *self;
263 int state, state2;
265 OSErr err;
266 TCPStatusPB *pb;
267 char buf[80];
269 if ( self->async_busy ) {
270 err_setstr(ErrorObject, "Operation not allowed, PassiveOpen in progress");
271 return -1;
273 if ( state < 0 && state2 < 0 )
274 return 0;
275 err = xTCPStatus(&self->iop, &pb);
276 if ( err ) {
277 PyErr_Mac(ErrorObject, err);
278 return -1;
280 if ( state == pb->connectionState ||
281 state2 == pb->connectionState )
282 return 0;
283 sprintf(buf, "Operation not allowed, connection state=%d", pb->connectionState);
284 err_setstr(ErrorObject, buf);
285 return -1;
288 static int
289 tcps_asr_safe(arg)
290 void *arg;
292 tcpsobject *self = (tcpsobject *)arg;
293 object *args, *rv;
295 if ( self->asr == None )
296 return 0;
297 args = mkvalue("(ii)", self->asr_ec, self->asr_reason);
298 rv = call_object(self->asr, args);
299 DECREF(args);
300 if ( rv ) {
301 DECREF(rv);
302 return 0;
304 return -1;
307 static pascal void
308 tcps_asr(str, ec, self, reason, icmp)
309 StreamPtr str;
310 unsigned short ec;
311 tcpsobject *self;
312 unsigned short reason;
313 struct ICMPReport icmp;
315 if ( self->asr == None )
316 return;
317 self->asr_ec = ec;
318 self->asr_reason = reason;
319 Py_AddPendingCall(tcps_asr_safe, (void *)self);
322 static void
323 tcps_done(pb)
324 TCPiopb *pb;
326 tcpsobject *self = (tcpsobject *)pb->csParam.open.userDataPtr;
328 if ( pb != &self->iop || !self->async_busy ) {
329 /* Oops... problems */
330 printf("tcps_done: unexpected call\n");
331 return;
333 self->async_busy = 0;
334 self->async_err = pb->ioResult;
335 /* Extension of mactcp semantics: also call asr on open complete */
336 if ( self->asr == None )
337 return;
338 self->asr_ec = MY_OPEN_DONE;
339 self->asr_reason = 0;
340 Py_AddPendingCall(tcps_asr_safe, (void *)self);
343 static object *
344 tcps_isdone(self, args)
345 tcpsobject *self;
346 object *args;
348 if (!newgetargs(args, ""))
349 return NULL;
350 return newintobject(!self->async_busy);
353 static object *
354 tcps_wait(self, args)
355 tcpsobject *self;
356 object *args;
358 if (!newgetargs(args, ""))
359 return NULL;
360 while ( self->async_busy ) {
361 if ( PyMac_Idle() ) {
362 INCREF(None);
363 return None;
366 if ( self->async_err ) {
367 PyErr_Mac(ErrorObject, self->async_err);
368 self->async_err = 0;
369 return NULL;
371 INCREF(None);
372 return None;
376 static object *
377 tcps_PassiveOpen(self, args)
378 tcpsobject *self;
379 object *args;
381 short port;
382 OSErr err;
384 if (!newgetargs(args, "h", &port))
385 return NULL;
386 if ( tcps_checkstate(self, -1, -1) < 0 )
387 return NULL;
388 self->async_busy = 1;
389 self->async_err = 0;
390 err = xTCPPassiveOpen(&self->iop, port, upp_tcp_done,
391 (void *)self);
392 if ( err ) {
393 self->async_busy = 0;
394 PyErr_Mac(ErrorObject, err);
395 return NULL;
397 self->localhost = self->iop.csParam.open.localHost;
398 self->localport = self->iop.csParam.open.localPort;
399 INCREF(None);
400 return None;
403 static object *
404 tcps_ActiveOpen(self, args)
405 tcpsobject *self;
406 object *args;
408 short lport, rport;
409 long rhost;
410 OSErr err;
412 if (!newgetargs(args, "hlh", &lport, &rhost, &rport))
413 return NULL;
414 if ( tcps_checkstate(self, -1, -1) < 0 )
415 return NULL;
416 err = xTCPActiveOpen(&self->iop, lport, rhost, rport, (TCPIOCompletionUPP)0);
417 if ( err ) {
418 PyErr_Mac(ErrorObject, err);
419 return NULL;
421 self->localhost = self->iop.csParam.open.localHost;
422 self->localport = self->iop.csParam.open.localPort;
423 INCREF(None);
424 return None;
427 static object *
428 tcps_Send(self, args)
429 tcpsobject *self;
430 object *args;
432 char *buf;
433 int bufsize;
434 int push = 0, urgent = 0;
435 OSErr err;
436 miniwds wds;
438 if (!newgetargs(args, "s#|ii", &buf, &bufsize, &push, &urgent))
439 return NULL;
440 if ( tcps_checkstate(self, STATE_ESTAB, STATE_CWAIT) < 0 )
441 return NULL;
442 wds.length = bufsize;
443 wds.ptr = buf;
444 wds.terminus = 0;
445 err = xTCPSend(&self->iop, (wdsEntry *)&wds, (Boolean)push, (Boolean)urgent,
446 (TCPIOCompletionUPP)0);
447 if ( err ) {
448 PyErr_Mac(ErrorObject, err);
449 return NULL;
451 INCREF(None);
452 return None;
455 static object *
456 tcps_Rcv(self, args)
457 tcpsobject *self;
458 object *args;
460 int timeout;
461 rdsEntry rds[2];
462 OSErr err;
463 object *rv;
464 int urgent, mark;
466 if (!newgetargs(args, "i", &timeout))
467 return NULL;
468 if ( tcps_checkstate(self, -1, -1) < 0 )
469 return NULL;
470 memset((char *)&rds, 0, sizeof(rds));
471 err = xTCPNoCopyRcv(&self->iop, rds, 1, timeout, (TCPIOCompletionUPP)0);
472 if ( err ) {
473 PyErr_Mac(ErrorObject, err);
474 return NULL;
476 urgent = self->iop.csParam.receive.urgentFlag;
477 mark = self->iop.csParam.receive.markFlag;
478 rv = newsizedstringobject((char *)rds[0].ptr, rds[0].length);
479 err = xTCPBufReturn(&self->iop, rds, (TCPIOCompletionUPP)0);
480 if ( err ) {
481 /* Should not happen */printf("mactcp module: BufReturn failed?\n");
482 PyErr_Mac(ErrorObject, err);
483 DECREF(rv);
484 return NULL;
486 return mkvalue("(Oii)", rv, urgent, mark);
489 static object *
490 tcps_Close(self, args)
491 tcpsobject *self;
492 object *args;
494 OSErr err;
496 if (!newgetargs(args, ""))
497 return NULL;
498 err = xTCPClose(&self->iop, (TCPIOCompletionUPP)0);
499 if ( err ) {
500 PyErr_Mac(ErrorObject, err);
501 return NULL;
503 INCREF(None);
504 return None;
507 static object *
508 tcps_Abort(self, args)
509 tcpsobject *self;
510 object *args;
512 OSErr err;
514 if (!newgetargs(args, ""))
515 return NULL;
516 err = xTCPAbort(&self->iop);
517 if ( err ) {
518 PyErr_Mac(ErrorObject, err);
519 return NULL;
521 INCREF(None);
522 return None;
525 static object *
526 tcps_Status(self, args)
527 tcpsobject *self;
528 object *args;
530 OSErr err;
531 TCPStatusPB *pb;
533 if (!newgetargs(args, ""))
534 return NULL;
535 if ( tcps_checkstate(self, -1, -1) < 0 )
536 return NULL;
537 err = xTCPStatus(&self->iop, &pb);
538 if ( err ) {
539 PyErr_Mac(ErrorObject, err);
540 return NULL;
542 return (object *)newtcpcsobject(pb);
545 static object *
546 tcps_GetSockName(self, args)
547 tcpsobject *self;
548 object *args;
550 /* This routine is needed so we can get at the local port even when
551 ** a PassiveOpen is in progress (when we can't do a Status call).
552 ** This is needed for socket listen(); getsockname(); accept() emulation
553 ** as used by ftp and the like.
555 if (!newgetargs(args, ""))
556 return NULL;
557 return mkvalue("(lh)", self->localhost, self->localport);
560 static struct methodlist tcps_methods[] = {
561 {"isdone", (method)tcps_isdone, 1},
562 {"wait", (method)tcps_wait, 1},
563 {"PassiveOpen", (method)tcps_PassiveOpen, 1},
564 {"ActiveOpen", (method)tcps_ActiveOpen, 1},
565 {"Send", (method)tcps_Send, 1},
566 {"Rcv", (method)tcps_Rcv, 1},
567 {"Close", (method)tcps_Close, 1},
568 {"Abort", (method)tcps_Abort, 1},
569 {"Status", (method)tcps_Status, 1},
570 {"GetSockName", (method)tcps_GetSockName, 1},
571 {NULL, NULL} /* sentinel */
574 /* ---------- */
576 static object *
577 tcps_getattr(self, name)
578 tcpsobject *self;
579 char *name;
581 if ( strcmp(name, "asr") == 0 ) {
582 INCREF(self->asr);
583 return self->asr;
585 return findmethod(tcps_methods, (object *)self, name);
588 static int
589 tcps_setattr(self, name, value)
590 tcpsobject *self;
591 char *name;
592 object *value;
594 if ( strcmp(name, "asr") != 0 || value == NULL )
595 return -1;
596 self->asr = value; /* XXXX Assuming I don't have to incref */
597 return 0;
600 static tcpsobject *
601 newtcpsobject(bufsize)
602 int bufsize;
604 tcpsobject *self;
605 OSErr err;
607 self = NEWOBJ(tcpsobject, &Tcpstype);
608 if (self == NULL)
609 return NULL;
610 memset((char *)&self->iop, 0, sizeof(self->iop));
611 err= xTCPCreate(bufsize, upp_tcp_asr, (void *)self, &self->iop);
612 if ( err ) {
613 DEL(self);
614 PyErr_Mac(ErrorObject, err);
615 return NULL;
617 INCREF(None);
618 self->localhost = 0;
619 self->localport = 0;
620 self->asr = None;
621 self->async_busy = 0;
622 self->async_err = 0;
623 return self;
626 static void
627 tcps_dealloc(self)
628 tcpsobject *self;
630 if ( self->async_busy ) {
631 printf("mactcp module: error: dealloc with async busy\n");
632 return;
634 xTCPRelease(&self->iop);
635 DEL(self);
638 static typeobject Tcpstype = {
639 OB_HEAD_INIT(&Typetype)
640 0, /*ob_size*/
641 "MacTCP TCP stream", /*tp_name*/
642 sizeof(tcpsobject), /*tp_basicsize*/
643 0, /*tp_itemsize*/
644 /* methods */
645 (destructor)tcps_dealloc, /*tp_dealloc*/
646 (printfunc)0, /*tp_print*/
647 (getattrfunc)tcps_getattr, /*tp_getattr*/
648 (setattrfunc)tcps_setattr, /*tp_setattr*/
649 (cmpfunc)0, /*tp_compare*/
650 (reprfunc)0, /*tp_repr*/
651 0, /*tp_as_number*/
652 0, /*tp_as_sequence*/
653 0, /*tp_as_mapping*/
654 (hashfunc)0, /*tp_hash*/
657 /* End of code for MacTCP TCP stream objects */
658 /* -------------------------------------------------------- */
660 static int
661 udps_asr_safe(arg)
662 void *arg;
664 udpsobject *self = (udpsobject *)arg;
665 object *args, *rv;
667 if ( self->asr == None )
668 return 0;
669 args = mkvalue("(i)", self->asr_ec);
670 rv = call_object(self->asr, args);
671 DECREF(args);
672 if ( rv ) {
673 DECREF(rv);
674 return 0;
676 return -1;
679 static pascal void
680 udps_asr(str, ec, self, icmp)
681 StreamPtr str;
682 unsigned short ec;
683 udpsobject *self;
684 struct ICMPReport icmp;
686 if ( self->asr == None )
687 return;
688 self->asr_ec = ec;
689 Py_AddPendingCall(udps_asr_safe, (void *)self);
693 static object *
694 udps_Read(self, args)
695 udpsobject *self;
696 object *args;
698 OSErr err;
699 object *rv;
700 int timeout;
702 if (!newgetargs(args, "i", &timeout))
703 return NULL;
704 err = xUDPRead(&self->iop, timeout, (UDPIOCompletionUPP)0);
705 if ( err ) {
706 PyErr_Mac(ErrorObject, err);
707 return NULL;
709 rv = newsizedstringobject((char *)self->iop.csParam.receive.rcvBuff,
710 self->iop.csParam.receive.rcvBuffLen);
711 err = xUDPBfrReturn(&self->iop, self->iop.csParam.receive.rcvBuff);
712 if ( err ) {
713 PyErr_Mac(ErrorObject, err);
714 DECREF(rv);
715 return NULL;
717 return rv;
720 static object *
721 udps_Write(self, args)
722 udpsobject *self;
723 object *args;
725 unsigned long host;
726 unsigned short port;
727 char *buf;
728 int bufsize;
729 OSErr err;
730 miniwds wds;
732 if (!newgetargs(args, "lhs#", &host, &port, &buf, &bufsize))
733 return NULL;
734 wds.length = bufsize;
735 wds.ptr = buf;
736 wds.terminus = 0;
737 err = xUDPWrite(&self->iop, host, port, &wds, (UDPIOCompletionUPP)0);
738 if ( err ) {
739 PyErr_Mac(ErrorObject, err);
740 return NULL;
742 INCREF(None);
743 return None;
745 static struct methodlist udps_methods[] = {
746 {"Read", (method)udps_Read, 1},
747 {"Write", (method)udps_Write, 1},
749 {NULL, NULL} /* sentinel */
752 /* ---------- */
754 static object *
755 udps_getattr(self, name)
756 udpsobject *self;
757 char *name;
759 if ( strcmp(name, "asr") == 0 ) {
760 INCREF(self->asr);
761 return self->asr;
763 if ( strcmp(name, "port") == 0 )
764 return newintobject((int)self->port);
765 return findmethod(udps_methods, (object *)self, name);
768 static int
769 udps_setattr(self, name, value)
770 udpsobject *self;
771 char *name;
772 object *value;
774 if ( strcmp(name, "asr") != 0 || value == NULL )
775 return -1;
776 self->asr = value; /* XXXX Assuming I don't have to incref */
777 return 0;
780 static udpsobject *
781 newudpsobject(bufsize, port)
782 int bufsize;
783 int port;
785 udpsobject *self;
786 OSErr err;
788 self = NEWOBJ(udpsobject, &Udpstype);
789 if (self == NULL)
790 return NULL;
791 memset((char *)&self->iop, 0, sizeof(self->iop));
792 self->port = port;
793 err= xUDPCreate(&self->iop, bufsize, &self->port, upp_udp_asr,
794 (void *)self);
795 if ( err ) {
796 DEL(self);
797 PyErr_Mac(ErrorObject, err);
798 return NULL;
800 INCREF(None);
801 self->asr = None;
802 return self;
805 static void
806 udps_dealloc(self)
807 udpsobject *self;
809 xUDPRelease(&self->iop);
810 DEL(self);
813 static typeobject Udpstype = {
814 OB_HEAD_INIT(&Typetype)
815 0, /*ob_size*/
816 "MacTCP UDP stream", /*tp_name*/
817 sizeof(udpsobject), /*tp_basicsize*/
818 0, /*tp_itemsize*/
819 /* methods */
820 (destructor)udps_dealloc, /*tp_dealloc*/
821 (printfunc)0, /*tp_print*/
822 (getattrfunc)udps_getattr, /*tp_getattr*/
823 (setattrfunc)udps_setattr, /*tp_setattr*/
824 (cmpfunc)0, /*tp_compare*/
825 (reprfunc)0, /*tp_repr*/
826 0, /*tp_as_number*/
827 0, /*tp_as_sequence*/
828 0, /*tp_as_mapping*/
829 (hashfunc)0, /*tp_hash*/
832 /* End of code for MacTCP UDP stream objects */
833 /* -------------------------------------------------------- */
835 static object *
836 mactcp_TCPCreate(self, args)
837 object *self; /* Not used */
838 object *args;
840 OSErr err;
841 object *rv;
842 int bufsize;
844 if (!newgetargs(args, "i", &bufsize))
845 return NULL;
846 if ( (err = xOpenDriver()) != noErr ) {
847 PyErr_Mac(ErrorObject, err);
848 return NULL;
850 rv = (object *)newtcpsobject(bufsize);
851 return rv;
854 static object *
855 mactcp_UDPCreate(self, args)
856 object *self; /* Not used */
857 object *args;
859 OSErr err;
860 object *rv;
861 int bufsize, port;
863 if (!newgetargs(args, "ii", &bufsize, &port))
864 return NULL;
865 if ( (err = xOpenDriver()) != noErr ) {
866 PyErr_Mac(ErrorObject, err);
867 return NULL;
869 rv = (object *)newudpsobject(bufsize, port);
870 return rv;
873 static object *
874 mactcp_MTU(self, args)
875 object *self; /* Not used */
876 object *args;
878 OSErr err;
879 unsigned short mtu;
881 if (!newgetargs(args, ""))
882 return NULL;
883 if ( (err = xOpenDriver()) != noErr ) {
884 PyErr_Mac(ErrorObject, err);
885 return NULL;
887 mtu = xMaxMTU();
888 return newintobject((int)mtu);
891 static object *
892 mactcp_IPAddr(self, args)
893 object *self; /* Not used */
894 object *args;
896 OSErr err;
897 unsigned long rv;
899 if (!newgetargs(args, ""))
900 return NULL;
901 if ( (err = xOpenDriver()) != noErr ) {
902 PyErr_Mac(ErrorObject, err);
903 return NULL;
905 rv = xIPAddr();
906 return newintobject((int)rv);
909 static object *
910 mactcp_NetMask(self, args)
911 object *self; /* Not used */
912 object *args;
914 OSErr err;
915 unsigned long rv;
917 if (!newgetargs(args, ""))
918 return NULL;
919 if ( (err = xOpenDriver()) != noErr ) {
920 PyErr_Mac(ErrorObject, err);
921 return NULL;
923 rv = xNetMask();
924 return newintobject((int)rv);
927 #ifdef TCP_GS
928 static object *
929 mactcp_GlobalInfo(self, args)
930 object *self; /* Not used */
931 object *args;
933 OSErr err;
935 if (!newgetargs(args, ""))
936 return NULL;
937 if ( (err = xOpenDriver()) != noErr ) {
938 PyErr_Mac(ErrorObject, err);
939 return NULL;
941 /* XXXX Allocate, fill */
942 INCREF(None);
943 return None;
945 #endif /* TCP_GS */
947 /* List of methods defined in the module */
949 static struct methodlist mactcp_methods[] = {
950 {"TCPCreate", mactcp_TCPCreate, 1},
951 {"UDPCreate", mactcp_UDPCreate, 1},
952 {"MTU", mactcp_MTU, 1},
953 {"IPAddr", mactcp_IPAddr, 1},
954 {"NetMask", mactcp_NetMask, 1},
955 #ifdef TCP_GS
956 {"GlobalInfo", mactcp_GlobalInfo, 1},
957 #endif
959 {NULL, NULL} /* sentinel */
963 /* Initialization function for the module (*must* be called initmactcp) */
965 void
966 initmactcp()
968 object *m, *d;
970 /* Create the module and add the functions */
971 m = initmodule("mactcp", mactcp_methods);
973 /* Add some symbolic constants to the module */
974 d = getmoduledict(m);
975 ErrorObject = newstringobject("mactcp.error");
976 dictinsert(d, "error", ErrorObject);
978 upp_tcp_done = NewTCPIOCompletionProc(tcps_done);
979 upp_tcp_asr = NewTCPNotifyProc(tcps_asr);
980 #if 0
981 upp_udp_done = NewUDPIOCompletionProc(udps_done);
982 #endif
983 upp_udp_asr = NewUDPNotifyProc(udps_asr);
985 /* XXXX Add constants here */
987 /* Check for errors */
988 if (err_occurred())
989 fatal("can't initialize module mactcp");