| /*********************************************************** |
| Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, |
| Amsterdam, The Netherlands. |
| |
| All Rights Reserved |
| |
| Permission to use, copy, modify, and distribute this software and its |
| documentation for any purpose and without fee is hereby granted, |
| provided that the above copyright notice appear in all copies and that |
| both that copyright notice and this permission notice appear in |
| supporting documentation, and that the names of Stichting Mathematisch |
| Centrum or CWI not be used in advertising or publicity pertaining to |
| distribution of the software without specific, written prior permission. |
| |
| STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE |
| FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
| OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| ******************************************************************/ |
| |
| #include "allobjects.h" |
| #include "modsupport.h" /* For getargs() etc. */ |
| |
| #include "macglue.h" |
| #include "tcpglue.h" |
| |
| #include <Desk.h> |
| |
| /* State of a tcp stream, in the connectionState field */ |
| #define STATE_CLOSED 0 |
| #define STATE_LISTEN 2 |
| #define STATE_ESTAB 8 |
| #define STATE_CWAIT 18 |
| |
| /* Python code has an additional reason for asr call: open done */ |
| #define MY_OPEN_DONE 32766 |
| |
| static object *ErrorObject; |
| |
| TCPIOCompletionUPP upp_tcp_done; |
| TCPNotifyUPP upp_tcp_asr; |
| #if 0 |
| UDPIOCompletionUPP upp_udp_done; |
| #endif |
| UDPNotifyUPP upp_udp_asr; |
| |
| /* ----------------------------------------------------- */ |
| /* Declarations for objects of type MacTCP connection status */ |
| |
| typedef struct { |
| OB_HEAD |
| TCPStatusPB status; |
| } tcpcsobject; |
| |
| staticforward typeobject Tcpcstype; |
| |
| #define is_tcpcsobject(v) ((v)->ob_type == &Tcpcstype) |
| |
| /* ---------------------------------------------------------------- */ |
| /* Declarations for objects of type MacTCP global status */ |
| |
| #ifdef TCP_GS |
| typedef struct { |
| OB_HEAD |
| TCPParam *ptr; |
| } tcpgsobject; |
| |
| staticforward typeobject Tcpgstype; |
| |
| #define is_tcpgsobject(v) ((v)->ob_type == &Tcpgstype) |
| #endif /* TCP_GS */ |
| |
| /* ---------------------------------------------------------------- */ |
| /* Declarations for objects of type MacTCP TCP stream */ |
| |
| typedef struct { |
| OB_HEAD |
| TCPiopb iop; |
| long localhost; /* Our IP address */ |
| short localport; /* Our port number */ |
| object *asr; /* Optional async notification routine */ |
| int asr_ec; /* error code parameter to asr */ |
| int asr_reason; /* detail for some errors */ |
| int async_busy; /* True when completion routine pending */ |
| int async_err; /* the error for the async call */ |
| } tcpsobject; |
| |
| staticforward typeobject Tcpstype; |
| |
| #define is_tcpsobject(v) ((v)->ob_type == &Tcpstype) |
| |
| /* ---------------------------------------------------------------- */ |
| /* Declarations for objects of type MacTCP UDP stream */ |
| |
| typedef struct { |
| OB_HEAD |
| UDPiopb iop; |
| object *asr; |
| int asr_ec; /* error code parameter to asr */ |
| ip_port port; |
| } udpsobject; |
| |
| staticforward typeobject Udpstype; |
| |
| #define is_udpsobject(v) ((v)->ob_type == &Udpstype) |
| |
| /* ---------------------------------------------------------------- */ |
| |
| static tcpcsobject * |
| newtcpcsobject(ptr) |
| TCPStatusPB *ptr; |
| { |
| tcpcsobject *self; |
| |
| self = NEWOBJ(tcpcsobject, &Tcpcstype); |
| if (self == NULL) |
| return NULL; |
| self->status = *ptr; |
| return self; |
| } |
| |
| static void |
| tcpcs_dealloc(self) |
| tcpcsobject *self; |
| { |
| DEL(self); |
| } |
| /* Code to access structure members by accessing attributes */ |
| |
| #include "structmember.h" |
| |
| #define OFF(x) offsetof(TCPStatusPB, x) |
| |
| static struct memberlist tcpcs_memberlist[] = { |
| {"remoteHost", T_ULONG, OFF(remoteHost), RO}, |
| {"remotePort", T_USHORT, OFF(remotePort), RO}, |
| {"localHost", T_UINT, OFF(localHost), RO}, |
| {"localPort", T_USHORT, OFF(localPort), RO}, |
| {"tosFlags", T_BYTE, OFF(tosFlags), RO}, |
| #if 0 /* Bug in header file: cannot access precedence */ |
| {"precedence" T_BYTE, OFF(precedence), RO}, |
| #endif |
| {"connectionState", T_BYTE, OFF(connectionState), RO}, |
| {"sendWindow", T_USHORT, OFF(sendWindow), RO}, |
| {"rcvWindow", T_USHORT, OFF(rcvWindow), RO}, |
| {"amtUnackedData", T_USHORT, OFF(amtUnackedData), RO}, |
| {"amtUnreadData", T_USHORT, OFF(amtUnreadData), RO}, |
| {"sendUnacked", T_UINT, OFF(sendUnacked), RO}, |
| {"sendNext", T_UINT, OFF(sendNext), RO}, |
| {"congestionWindow", T_UINT, OFF(congestionWindow), RO}, |
| {"rcvNext", T_UINT, OFF(rcvNext), RO}, |
| {"srtt", T_UINT, OFF(srtt), RO}, |
| {"lastRTT", T_UINT, OFF(lastRTT), RO}, |
| {"sendMaxSegSize", T_UINT, OFF(sendMaxSegSize), RO}, |
| {NULL} /* Sentinel */ |
| }; |
| |
| static object * |
| tcpcs_getattr(self, name) |
| tcpcsobject *self; |
| char *name; |
| { |
| return getmember((char *)&self->status, tcpcs_memberlist, name); |
| } |
| |
| |
| static typeobject Tcpcstype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "MacTCP connection status", /*tp_name*/ |
| sizeof(tcpcsobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)tcpcs_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)tcpcs_getattr, /*tp_getattr*/ |
| (setattrfunc)0, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)0, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| }; |
| |
| /* End of code for MacTCP connection status objects */ |
| /* -------------------------------------------------------- */ |
| |
| #ifdef TCP_GS |
| static tcpgsobject * |
| newtcpgsobject(ptr) |
| TCPParam *ptr; |
| { |
| tcpgsobject *self; |
| |
| self = NEWOBJ(tcpgsobject, &Tcpgstype); |
| if (self == NULL) |
| return NULL; |
| self->ptr = ptr; |
| return self; |
| } |
| |
| static void |
| tcpgs_dealloc(self) |
| tcpgsobject *self; |
| { |
| DEL(self); |
| } |
| /* Code to access structure members by accessing attributes */ |
| #undef OFF |
| #define OFF(x) offsetof(TCPParam, x) |
| |
| static struct memberlist tcpgs_memberlist[] = { |
| {"RtoA", T_UINT, OFF(tcpRtoA), RO}, |
| {"RtoMin", T_UINT, OFF(tcpRtoMin), RO}, |
| {"RtoMax", T_UINT, OFF(tcpRtoMax), RO}, |
| {"MaxSegSize", T_UINT, OFF(tcpMaxSegSize), RO}, |
| {"MaxConn", T_UINT, OFF(tcpMaxConn), RO}, |
| {"MaxWindow", T_UINT, OFF(tcpMaxWindow), RO}, |
| {NULL} /* Sentinel */ |
| }; |
| |
| static object * |
| tcpgs_getattr(self, name) |
| tcpgsobject *self; |
| char *name; |
| { |
| object *rv; |
| |
| return getmember((char *)self->ptr, tcpgs_memberlist, name); |
| } |
| |
| static typeobject Tcpgstype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "MacTCP global status", /*tp_name*/ |
| sizeof(tcpgsobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)tcpgs_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)tcpgs_getattr, /*tp_getattr*/ |
| (setattrfunc)0, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)0, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| }; |
| #endif /* TCP_GS */ |
| |
| /* End of code for MacTCP global status objects */ |
| /* -------------------------------------------------------- */ |
| |
| static int |
| tcps_checkstate(self, state, state2) |
| tcpsobject *self; |
| int state, state2; |
| { |
| OSErr err; |
| TCPStatusPB *pb; |
| char buf[80]; |
| |
| if ( self->async_busy ) { |
| err_setstr(ErrorObject, "Operation not allowed, PassiveOpen in progress"); |
| return -1; |
| } |
| if ( state < 0 && state2 < 0 ) |
| return 0; |
| err = xTCPStatus(&self->iop, &pb); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return -1; |
| } |
| if ( state == pb->connectionState || |
| state2 == pb->connectionState ) |
| return 0; |
| sprintf(buf, "Operation not allowed, connection state=%d", pb->connectionState); |
| err_setstr(ErrorObject, buf); |
| return -1; |
| } |
| |
| static int |
| tcps_asr_safe(arg) |
| void *arg; |
| { |
| tcpsobject *self = (tcpsobject *)arg; |
| object *args, *rv; |
| |
| if ( self->asr == None ) |
| return 0; |
| args = mkvalue("(ii)", self->asr_ec, self->asr_reason); |
| rv = call_object(self->asr, args); |
| DECREF(args); |
| if ( rv ) { |
| DECREF(rv); |
| return 0; |
| } |
| return -1; |
| } |
| |
| static pascal void |
| tcps_asr(str, ec, self, reason, icmp) |
| StreamPtr str; |
| unsigned short ec; |
| tcpsobject *self; |
| unsigned short reason; |
| struct ICMPReport icmp; |
| { |
| if ( self->asr == None ) |
| return; |
| self->asr_ec = ec; |
| self->asr_reason = reason; |
| Py_AddPendingCall(tcps_asr_safe, (void *)self); |
| } |
| |
| static void |
| tcps_done(pb) |
| TCPiopb *pb; |
| { |
| tcpsobject *self = (tcpsobject *)pb->csParam.open.userDataPtr; |
| |
| if ( pb != &self->iop || !self->async_busy ) { |
| /* Oops... problems */ |
| printf("tcps_done: unexpected call\n"); |
| return; |
| } |
| self->async_busy = 0; |
| self->async_err = pb->ioResult; |
| /* Extension of mactcp semantics: also call asr on open complete */ |
| if ( self->asr == None ) |
| return; |
| self->asr_ec = MY_OPEN_DONE; |
| self->asr_reason = 0; |
| Py_AddPendingCall(tcps_asr_safe, (void *)self); |
| } |
| |
| static object * |
| tcps_isdone(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| if (!newgetargs(args, "")) |
| return NULL; |
| return newintobject(!self->async_busy); |
| } |
| |
| static object * |
| tcps_wait(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| if (!newgetargs(args, "")) |
| return NULL; |
| while ( self->async_busy ) { |
| if ( PyMac_Idle() ) { |
| INCREF(None); |
| return None; |
| } |
| } |
| if ( self->async_err ) { |
| PyErr_Mac(ErrorObject, self->async_err); |
| self->async_err = 0; |
| return NULL; |
| } |
| INCREF(None); |
| return None; |
| } |
| |
| |
| static object * |
| tcps_PassiveOpen(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| short port; |
| OSErr err; |
| |
| if (!newgetargs(args, "h", &port)) |
| return NULL; |
| if ( tcps_checkstate(self, -1, -1) < 0 ) |
| return NULL; |
| self->async_busy = 1; |
| self->async_err = 0; |
| err = xTCPPassiveOpen(&self->iop, port, upp_tcp_done, |
| (void *)self); |
| if ( err ) { |
| self->async_busy = 0; |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| self->localhost = self->iop.csParam.open.localHost; |
| self->localport = self->iop.csParam.open.localPort; |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| tcps_ActiveOpen(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| short lport, rport; |
| long rhost; |
| OSErr err; |
| |
| if (!newgetargs(args, "hlh", &lport, &rhost, &rport)) |
| return NULL; |
| if ( tcps_checkstate(self, -1, -1) < 0 ) |
| return NULL; |
| err = xTCPActiveOpen(&self->iop, lport, rhost, rport, (TCPIOCompletionUPP)0); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| self->localhost = self->iop.csParam.open.localHost; |
| self->localport = self->iop.csParam.open.localPort; |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| tcps_Send(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| char *buf; |
| int bufsize; |
| int push = 0, urgent = 0; |
| OSErr err; |
| miniwds wds; |
| |
| if (!newgetargs(args, "s#|ii", &buf, &bufsize, &push, &urgent)) |
| return NULL; |
| if ( tcps_checkstate(self, STATE_ESTAB, STATE_CWAIT) < 0 ) |
| return NULL; |
| wds.length = bufsize; |
| wds.ptr = buf; |
| wds.terminus = 0; |
| err = xTCPSend(&self->iop, (wdsEntry *)&wds, (Boolean)push, (Boolean)urgent, |
| (TCPIOCompletionUPP)0); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| tcps_Rcv(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| int timeout; |
| rdsEntry rds[2]; |
| OSErr err; |
| object *rv; |
| int urgent, mark; |
| |
| if (!newgetargs(args, "i", &timeout)) |
| return NULL; |
| if ( tcps_checkstate(self, -1, -1) < 0 ) |
| return NULL; |
| memset((char *)&rds, 0, sizeof(rds)); |
| err = xTCPNoCopyRcv(&self->iop, rds, 1, timeout, (TCPIOCompletionUPP)0); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| urgent = self->iop.csParam.receive.urgentFlag; |
| mark = self->iop.csParam.receive.markFlag; |
| rv = newsizedstringobject((char *)rds[0].ptr, rds[0].length); |
| err = xTCPBufReturn(&self->iop, rds, (TCPIOCompletionUPP)0); |
| if ( err ) { |
| /* Should not happen */printf("mactcp module: BufReturn failed?\n"); |
| PyErr_Mac(ErrorObject, err); |
| DECREF(rv); |
| return NULL; |
| } |
| return mkvalue("(Oii)", rv, urgent, mark); |
| } |
| |
| static object * |
| tcps_Close(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| OSErr err; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| err = xTCPClose(&self->iop, (TCPIOCompletionUPP)0); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| tcps_Abort(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| OSErr err; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| err = xTCPAbort(&self->iop); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| tcps_Status(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| OSErr err; |
| TCPStatusPB *pb; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| if ( tcps_checkstate(self, -1, -1) < 0 ) |
| return NULL; |
| err = xTCPStatus(&self->iop, &pb); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| return (object *)newtcpcsobject(pb); |
| } |
| |
| static object * |
| tcps_GetSockName(self, args) |
| tcpsobject *self; |
| object *args; |
| { |
| /* This routine is needed so we can get at the local port even when |
| ** a PassiveOpen is in progress (when we can't do a Status call). |
| ** This is needed for socket listen(); getsockname(); accept() emulation |
| ** as used by ftp and the like. |
| */ |
| if (!newgetargs(args, "")) |
| return NULL; |
| return mkvalue("(lh)", self->localhost, self->localport); |
| } |
| |
| static struct methodlist tcps_methods[] = { |
| {"isdone", (method)tcps_isdone, 1}, |
| {"wait", (method)tcps_wait, 1}, |
| {"PassiveOpen", (method)tcps_PassiveOpen, 1}, |
| {"ActiveOpen", (method)tcps_ActiveOpen, 1}, |
| {"Send", (method)tcps_Send, 1}, |
| {"Rcv", (method)tcps_Rcv, 1}, |
| {"Close", (method)tcps_Close, 1}, |
| {"Abort", (method)tcps_Abort, 1}, |
| {"Status", (method)tcps_Status, 1}, |
| {"GetSockName", (method)tcps_GetSockName, 1}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| /* ---------- */ |
| |
| static object * |
| tcps_getattr(self, name) |
| tcpsobject *self; |
| char *name; |
| { |
| if ( strcmp(name, "asr") == 0 ) { |
| INCREF(self->asr); |
| return self->asr; |
| } |
| return findmethod(tcps_methods, (object *)self, name); |
| } |
| |
| static int |
| tcps_setattr(self, name, value) |
| tcpsobject *self; |
| char *name; |
| object *value; |
| { |
| if ( strcmp(name, "asr") != 0 || value == NULL ) |
| return -1; |
| self->asr = value; /* XXXX Assuming I don't have to incref */ |
| return 0; |
| } |
| |
| static tcpsobject * |
| newtcpsobject(bufsize) |
| int bufsize; |
| { |
| tcpsobject *self; |
| OSErr err; |
| |
| self = NEWOBJ(tcpsobject, &Tcpstype); |
| if (self == NULL) |
| return NULL; |
| memset((char *)&self->iop, 0, sizeof(self->iop)); |
| err= xTCPCreate(bufsize, upp_tcp_asr, (void *)self, &self->iop); |
| if ( err ) { |
| DEL(self); |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| INCREF(None); |
| self->localhost = 0; |
| self->localport = 0; |
| self->asr = None; |
| self->async_busy = 0; |
| self->async_err = 0; |
| return self; |
| } |
| |
| static void |
| tcps_dealloc(self) |
| tcpsobject *self; |
| { |
| if ( self->async_busy ) { |
| printf("mactcp module: error: dealloc with async busy\n"); |
| return; |
| } |
| xTCPRelease(&self->iop); |
| DEL(self); |
| } |
| |
| static typeobject Tcpstype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "MacTCP TCP stream", /*tp_name*/ |
| sizeof(tcpsobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)tcps_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)tcps_getattr, /*tp_getattr*/ |
| (setattrfunc)tcps_setattr, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)0, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| }; |
| |
| /* End of code for MacTCP TCP stream objects */ |
| /* -------------------------------------------------------- */ |
| |
| static int |
| udps_asr_safe(arg) |
| void *arg; |
| { |
| udpsobject *self = (udpsobject *)arg; |
| object *args, *rv; |
| |
| if ( self->asr == None ) |
| return 0; |
| args = mkvalue("(i)", self->asr_ec); |
| rv = call_object(self->asr, args); |
| DECREF(args); |
| if ( rv ) { |
| DECREF(rv); |
| return 0; |
| } |
| return -1; |
| } |
| |
| static pascal void |
| udps_asr(str, ec, self, icmp) |
| StreamPtr str; |
| unsigned short ec; |
| udpsobject *self; |
| struct ICMPReport icmp; |
| { |
| if ( self->asr == None ) |
| return; |
| self->asr_ec = ec; |
| Py_AddPendingCall(udps_asr_safe, (void *)self); |
| } |
| |
| |
| static object * |
| udps_Read(self, args) |
| udpsobject *self; |
| object *args; |
| { |
| OSErr err; |
| object *rv; |
| int timeout; |
| |
| if (!newgetargs(args, "i", &timeout)) |
| return NULL; |
| err = xUDPRead(&self->iop, timeout, (UDPIOCompletionUPP)0); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| rv = newsizedstringobject((char *)self->iop.csParam.receive.rcvBuff, |
| self->iop.csParam.receive.rcvBuffLen); |
| err = xUDPBfrReturn(&self->iop, self->iop.csParam.receive.rcvBuff); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| DECREF(rv); |
| return NULL; |
| } |
| return rv; |
| } |
| |
| static object * |
| udps_Write(self, args) |
| udpsobject *self; |
| object *args; |
| { |
| unsigned long host; |
| unsigned short port; |
| char *buf; |
| int bufsize; |
| OSErr err; |
| miniwds wds; |
| |
| if (!newgetargs(args, "lhs#", &host, &port, &buf, &bufsize)) |
| return NULL; |
| wds.length = bufsize; |
| wds.ptr = buf; |
| wds.terminus = 0; |
| err = xUDPWrite(&self->iop, host, port, &wds, (UDPIOCompletionUPP)0); |
| if ( err ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| INCREF(None); |
| return None; |
| } |
| static struct methodlist udps_methods[] = { |
| {"Read", (method)udps_Read, 1}, |
| {"Write", (method)udps_Write, 1}, |
| |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| /* ---------- */ |
| |
| static object * |
| udps_getattr(self, name) |
| udpsobject *self; |
| char *name; |
| { |
| if ( strcmp(name, "asr") == 0 ) { |
| INCREF(self->asr); |
| return self->asr; |
| } |
| if ( strcmp(name, "port") == 0 ) |
| return newintobject((int)self->port); |
| return findmethod(udps_methods, (object *)self, name); |
| } |
| |
| static int |
| udps_setattr(self, name, value) |
| udpsobject *self; |
| char *name; |
| object *value; |
| { |
| if ( strcmp(name, "asr") != 0 || value == NULL ) |
| return -1; |
| self->asr = value; /* XXXX Assuming I don't have to incref */ |
| return 0; |
| } |
| |
| static udpsobject * |
| newudpsobject(bufsize, port) |
| int bufsize; |
| int port; |
| { |
| udpsobject *self; |
| OSErr err; |
| |
| self = NEWOBJ(udpsobject, &Udpstype); |
| if (self == NULL) |
| return NULL; |
| memset((char *)&self->iop, 0, sizeof(self->iop)); |
| self->port = port; |
| err= xUDPCreate(&self->iop, bufsize, &self->port, upp_udp_asr, |
| (void *)self); |
| if ( err ) { |
| DEL(self); |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| INCREF(None); |
| self->asr = None; |
| return self; |
| } |
| |
| static void |
| udps_dealloc(self) |
| udpsobject *self; |
| { |
| xUDPRelease(&self->iop); |
| DEL(self); |
| } |
| |
| static typeobject Udpstype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "MacTCP UDP stream", /*tp_name*/ |
| sizeof(udpsobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)udps_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)udps_getattr, /*tp_getattr*/ |
| (setattrfunc)udps_setattr, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)0, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| }; |
| |
| /* End of code for MacTCP UDP stream objects */ |
| /* -------------------------------------------------------- */ |
| |
| static object * |
| mactcp_TCPCreate(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| OSErr err; |
| object *rv; |
| int bufsize; |
| |
| if (!newgetargs(args, "i", &bufsize)) |
| return NULL; |
| if ( (err = xOpenDriver()) != noErr ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| rv = (object *)newtcpsobject(bufsize); |
| return rv; |
| } |
| |
| static object * |
| mactcp_UDPCreate(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| OSErr err; |
| object *rv; |
| int bufsize, port; |
| |
| if (!newgetargs(args, "ii", &bufsize, &port)) |
| return NULL; |
| if ( (err = xOpenDriver()) != noErr ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| rv = (object *)newudpsobject(bufsize, port); |
| return rv; |
| } |
| |
| static object * |
| mactcp_MTU(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| OSErr err; |
| unsigned short mtu; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| if ( (err = xOpenDriver()) != noErr ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| mtu = xMaxMTU(); |
| return newintobject((int)mtu); |
| } |
| |
| static object * |
| mactcp_IPAddr(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| OSErr err; |
| unsigned long rv; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| if ( (err = xOpenDriver()) != noErr ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| rv = xIPAddr(); |
| return newintobject((int)rv); |
| } |
| |
| static object * |
| mactcp_NetMask(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| OSErr err; |
| unsigned long rv; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| if ( (err = xOpenDriver()) != noErr ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| rv = xNetMask(); |
| return newintobject((int)rv); |
| } |
| |
| #ifdef TCP_GS |
| static object * |
| mactcp_GlobalInfo(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| OSErr err; |
| |
| if (!newgetargs(args, "")) |
| return NULL; |
| if ( (err = xOpenDriver()) != noErr ) { |
| PyErr_Mac(ErrorObject, err); |
| return NULL; |
| } |
| /* XXXX Allocate, fill */ |
| INCREF(None); |
| return None; |
| } |
| #endif /* TCP_GS */ |
| |
| /* List of methods defined in the module */ |
| |
| static struct methodlist mactcp_methods[] = { |
| {"TCPCreate", mactcp_TCPCreate, 1}, |
| {"UDPCreate", mactcp_UDPCreate, 1}, |
| {"MTU", mactcp_MTU, 1}, |
| {"IPAddr", mactcp_IPAddr, 1}, |
| {"NetMask", mactcp_NetMask, 1}, |
| #ifdef TCP_GS |
| {"GlobalInfo", mactcp_GlobalInfo, 1}, |
| #endif |
| |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| |
| /* Initialization function for the module (*must* be called initmactcp) */ |
| |
| void |
| initmactcp() |
| { |
| object *m, *d; |
| |
| /* Create the module and add the functions */ |
| m = initmodule("mactcp", mactcp_methods); |
| |
| /* Add some symbolic constants to the module */ |
| d = getmoduledict(m); |
| ErrorObject = newstringobject("mactcp.error"); |
| dictinsert(d, "error", ErrorObject); |
| |
| upp_tcp_done = NewTCPIOCompletionProc(tcps_done); |
| upp_tcp_asr = NewTCPNotifyProc(tcps_asr); |
| #if 0 |
| upp_udp_done = NewUDPIOCompletionProc(udps_done); |
| #endif |
| upp_udp_asr = NewUDPNotifyProc(udps_asr); |
| |
| /* XXXX Add constants here */ |
| |
| /* Check for errors */ |
| if (err_occurred()) |
| fatal("can't initialize module mactcp"); |
| } |