]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Interface to MacTCP and the MacTCP Domain Name Resolver
authorJack Jansen <jack.jansen@cwi.nl>
Wed, 14 Dec 1994 13:36:34 +0000 (13:36 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Wed, 14 Dec 1994 13:36:34 +0000 (13:36 +0000)
Mac/Unsupported/mactcp/dnrglue.c [new file with mode: 0644]
Mac/Unsupported/mactcp/macdnrmodule.c [new file with mode: 0644]
Mac/Unsupported/mactcp/mactcpmodule.c [new file with mode: 0644]
Mac/Unsupported/mactcp/tcpglue.c [new file with mode: 0644]
Mac/Unsupported/mactcp/tcpglue.h [new file with mode: 0644]

diff --git a/Mac/Unsupported/mactcp/dnrglue.c b/Mac/Unsupported/mactcp/dnrglue.c
new file mode 100644 (file)
index 0000000..5474b73
--- /dev/null
@@ -0,0 +1,301 @@
+/*     DNR.c - DNR library for MPW
+
+       (c) Copyright 1988 by Apple Computer.  All rights reserved
+       
+       Modifications by Jim Matthews, Dartmouth College, 5/91
+       Again modified for use with python by Jack Jansen, CWI, October 1994.
+       
+*/
+
+#include <Traps.h>
+#include <OSUtils.h>
+#include <Errors.h>
+#include <Files.h>
+#include <Resources.h>
+#include <Memory.h>
+#include <Traps.h>
+#include <GestaltEqu.h>
+#include <Folders.h>
+#include <ToolUtils.h>
+#include <MacTCPCommonTypes.h>
+#include "AddressXlation.h"
+
+TrapType GetTrapType(unsigned long theTrap);
+Boolean TrapAvailable(unsigned long trap);
+void GetSystemFolder(short *vRefNumP, long *dirIDP);
+void GetCPanelFolder(short *vRefNumP, long *dirIDP);
+short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID);
+short OpenOurRF(void);
+
+#define OPENRESOLVER   1L
+#define CLOSERESOLVER  2L
+#define STRTOADDR              3L
+#define        ADDRTOSTR               4L
+#define        ENUMCACHE               5L
+#define ADDRTONAME             6L
+#define        HINFO                   7L
+#define MXINFO                 8L
+
+Handle codeHndl = nil;
+
+OSErrProcPtr dnr = nil;
+
+TrapType GetTrapType(theTrap)
+unsigned long theTrap;
+{
+       if (BitAnd(theTrap, 0x0800) > 0)
+               return(ToolTrap);
+       else
+               return(OSTrap);
+       }
+       
+Boolean TrapAvailable(trap)
+unsigned long trap;
+{
+TrapType trapType = ToolTrap;
+unsigned long numToolBoxTraps;
+
+       if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
+               numToolBoxTraps = 0x200;
+       else
+               numToolBoxTraps = 0x400;
+
+       trapType = GetTrapType(trap);
+       if (trapType == ToolTrap) {
+               trap = BitAnd(trap, 0x07FF);
+               if (trap >= numToolBoxTraps)
+                       trap = _Unimplemented;
+               }
+       return(NGetTrapAddress(trap, trapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
+
+}
+
+void GetSystemFolder(short *vRefNumP, long *dirIDP)
+{
+       SysEnvRec info;
+       long wdProcID;
+       
+       SysEnvirons(1, &info);
+       if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
+               *vRefNumP = 0;
+               *dirIDP = 0;
+               }
+       }
+
+void GetCPanelFolder(short *vRefNumP, long *dirIDP)
+{
+       Boolean hasFolderMgr = false;
+       long feature;
+       
+       if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+       if (!hasFolderMgr) {
+               GetSystemFolder(vRefNumP, dirIDP);
+               return;
+               }
+       else {
+               if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
+                       *vRefNumP = 0;
+                       *dirIDP = 0;
+                       }
+               }
+       }
+       
+/* SearchFolderForDNRP is called to search a folder for files that might 
+       contain the 'dnrp' resource */
+short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID)
+{
+       HParamBlockRec fi;
+       Str255 filename;
+       short refnum;
+       
+       fi.fileParam.ioCompletion = nil;
+       fi.fileParam.ioNamePtr = filename;
+       fi.fileParam.ioVRefNum = vRefNum;
+       fi.fileParam.ioDirID = dirID;
+       fi.fileParam.ioFDirIndex = 1;
+       
+       while (PBHGetFInfo(&fi, false) == noErr) {
+               /* scan system folder for driver resource files of specific type & creator */
+               if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
+                       fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
+                       /* found the MacTCP driver file? */
+                       refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
+                       if (GetIndResource('dnrp', 1) == NULL)
+                               CloseResFile(refnum);
+                       else
+                               return refnum;
+                       }
+               /* check next file in system folder */
+               fi.fileParam.ioFDirIndex++;
+               fi.fileParam.ioDirID = dirID;   /* PBHGetFInfo() clobbers ioDirID */
+               }
+       return(-1);
+       }       
+
+/* OpenOurRF is called to open the MacTCP driver resources */
+
+short OpenOurRF()
+{
+       short refnum;
+       short vRefNum;
+       long dirID;
+       
+       /* first search Control Panels for MacTCP 1.1 */
+       GetCPanelFolder(&vRefNum, &dirID);
+       refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
+       if (refnum != -1) return(refnum);
+               
+       /* next search System Folder for MacTCP 1.0.x */
+       GetSystemFolder(&vRefNum, &dirID);
+       refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
+       if (refnum != -1) return(refnum);
+               
+       /* finally, search Control Panels for MacTCP 1.0.x */
+       GetCPanelFolder(&vRefNum, &dirID);
+       refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
+       if (refnum != -1) return(refnum);
+               
+       return -1;
+       }       
+
+
+OSErr OpenResolver(fileName)
+char *fileName;
+{
+       short refnum;
+       OSErr rc;
+       
+       if (dnr != nil)
+               /* resolver already loaded in */
+               return(noErr);
+               
+       /* open the MacTCP driver to get DNR resources. Search for it based on
+          creator & type rather than simply file name */       
+       refnum = OpenOurRF();
+
+       /* ignore failures since the resource may have been installed in the 
+          System file if running on a Mac 512Ke */
+          
+       /* load in the DNR resource package */
+       codeHndl = GetIndResource('dnrp', 1);
+       if (codeHndl == nil) {
+               /* can't open DNR */
+               return(ResError());
+               }
+       
+       DetachResource(codeHndl);
+       if (refnum != -1) {
+               CloseWD(refnum);
+               CloseResFile(refnum);
+               }
+               
+       /* lock the DNR resource since it cannot be reloated while opened */
+       HLock(codeHndl);
+       dnr = (OSErrProcPtr) *codeHndl;
+       
+       /* call open resolver */
+       rc = (*dnr)(OPENRESOLVER, fileName);
+       if (rc != noErr) {
+               /* problem with open resolver, flush it */
+               HUnlock(codeHndl);
+               DisposHandle(codeHndl);
+               dnr = nil;
+               }
+       return(rc);
+       }
+
+
+OSErr CloseResolver()
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       /* call close resolver */
+       (void) (*dnr)(CLOSERESOLVER);
+
+       /* release the DNR resource package */
+       HUnlock(codeHndl);
+       DisposHandle(codeHndl);
+       dnr = nil;
+       return(noErr);
+       }
+
+OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
+char *hostName;
+struct hostInfo *rtnStruct;
+ResultProcPtr resultproc;
+char *userDataPtr;
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       return((*dnr)(STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr));
+       }
+       
+OSErr AddrToStr(addr, addrStr)
+unsigned long addr;
+char *addrStr;                                                                 
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       (*dnr)(ADDRTOSTR, addr, addrStr);
+       return(noErr);
+       }
+       
+OSErr EnumCache(resultproc, userDataPtr)
+EnumResultProcPtr resultproc;
+char *userDataPtr;
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       return((*dnr)(ENUMCACHE, resultproc, userDataPtr));
+       }
+       
+       
+OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
+unsigned long addr;
+struct hostInfo *rtnStruct;
+ResultProcPtr resultproc;
+char *userDataPtr;                                                                     
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       return((*dnr)(ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
+       }
+
+
+extern OSErr HInfo(hostName, returnRecPtr, resultProc, userDataPtr)
+char *hostName;
+struct returnRec *returnRecPtr;
+ResultProc2Ptr resultProc;
+char *userDataPtr;
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       return((*dnr)(HINFO, hostName, returnRecPtr, resultProc, userDataPtr));
+
+       }
+       
+extern OSErr MXInfo(hostName, returnRecPtr, resultProc, userDataPtr)
+char *hostName;
+struct returnRec *returnRecPtr;
+ResultProc2Ptr resultProc;
+char *userDataPtr;
+{
+       if (dnr == nil)
+               /* resolver not loaded error */
+               return(notOpenErr);
+               
+       return((*dnr)(MXINFO, hostName, returnRecPtr, resultProc, userDataPtr));
+
+       }
\ No newline at end of file
diff --git a/Mac/Unsupported/mactcp/macdnrmodule.c b/Mac/Unsupported/mactcp/macdnrmodule.c
new file mode 100644 (file)
index 0000000..75dd89a
--- /dev/null
@@ -0,0 +1,456 @@
+/***********************************************************
+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 <AddressXlation.h>
+#include <Desk.h>
+
+#ifndef __MWERKS__
+#define ResultUPP ResultProcPtr
+#define NewResultProc(x) (x)
+#endif
+
+static object *ErrorObject;
+
+/* ----------------------------------------------------- */
+/* Declarations for objects of type MacTCP DNR Result */
+
+/* Types of records we have */
+#define DNR_ADDR 0
+#define DNR_HINFO 1
+#define DNR_MX 2
+
+typedef struct {
+       OB_HEAD
+       int type;               /* DNR_XXX */
+       int waiting;    /* True while completion proc not called */
+       struct returnRec hinfo;
+} dnrrobject;
+
+staticforward typeobject Dnrrtype;
+
+#define is_dnrrobject(v)               ((v)->ob_type == &Dnrrtype)
+
+/* ---------------------------------------------------------------- */
+
+static pascal void
+dnrr_done(rrp, udp)
+       struct hostInfo *rrp;   /* Unused */
+       dnrrobject *udp;
+{
+       if ( !udp->waiting ) {
+               printf("macdnr: dnrr_done: spurious completion call!\n");
+               return;
+       }
+       udp->waiting = 0;
+       DECREF(udp);
+}
+
+static int dnrwait(self)
+       dnrrobject *self;
+{
+       while ( self->waiting ) {
+               if ( !PyMac_Idle() )
+                       return 0;
+       }
+       return 1;
+}
+
+static object *
+dnrr_wait(self, args)
+       dnrrobject *self;
+       object *args;
+{
+       if (!newgetargs(args, ""))
+               return NULL;
+       if ( !dnrwait(self) ) {
+               INCREF(None);
+               return None;
+       }
+       if ( self->hinfo.rtnCode ) {
+               PyErr_Mac(ErrorObject, self->hinfo.rtnCode);
+               return NULL;
+       }
+       INCREF(None);
+       return None;
+}
+
+static object *
+dnrr_isdone(self, args)
+       dnrrobject *self;
+       object *args;
+{
+       if (!newgetargs(args, ""))
+               return NULL;
+       return newintobject(!self->waiting);
+}
+
+static struct methodlist dnrr_methods[] = {
+       {"wait",        (method)dnrr_wait,      1},
+       {"isdone",      (method)dnrr_isdone,    1},
+       {NULL,          NULL}           /* sentinel */
+};
+
+/* ---------- */
+
+static dnrrobject *
+newdnrrobject(tp)
+       int tp;
+{
+       dnrrobject *self;
+       
+       self = NEWOBJ(dnrrobject, &Dnrrtype);
+       if (self == NULL)
+               return NULL;
+       self->type = tp;
+       self->waiting = 0;
+       memset(&self->hinfo, 0, sizeof(self->hinfo));
+       return self;
+}
+
+static void
+dnrr_dealloc(self)
+       dnrrobject *self;
+{
+       self->waiting = 0;  /* Not really needed, since we incref for completion */
+       DEL(self);
+}
+
+/* Code to access structure members by accessing attributes */
+
+#include "structmember.h"
+
+#define OFF(x) offsetof(struct returnRec, x)
+
+static struct memberlist dnrr_memberlist_addr[] = {
+       { "rtnCode", T_INT, OFF(rtnCode), RO},
+       { "cname", T_STRING_INPLACE, OFF(cname), RO},
+       { "ip0", T_UINT, OFF(rdata.addr[0]), RO},
+       { "ip1", T_UINT, OFF(rdata.addr[1]), RO},
+       { "ip2", T_UINT, OFF(rdata.addr[2]), RO},
+       { "ip3", T_UINT, OFF(rdata.addr[3]), RO},
+       {NULL}  /* Sentinel */
+};
+
+static struct memberlist dnrr_memberlist_hinfo[] = {
+       { "rtnCode", T_INT, OFF(rtnCode), RO},
+       { "cname", T_STRING_INPLACE, OFF(cname), RO},
+       { "cpuType", T_STRING_INPLACE, OFF(rdata.hinfo.cpuType), RO},
+       { "osType", T_STRING_INPLACE, OFF(rdata.hinfo.osType), RO},
+       {NULL}  /* Sentinel */
+};
+
+static struct memberlist dnrr_memberlist_mx[] = {
+       { "rtnCode", T_INT, OFF(rtnCode), RO},
+       { "cname", T_STRING_INPLACE, OFF(cname), RO},
+       { "preference", T_USHORT, OFF(rdata.mx.preference), RO},
+       { "exchange", T_STRING_INPLACE, OFF(rdata.mx.exchange), RO},
+       {NULL}  /* Sentinel */
+};
+
+static struct memberlist *dnrr_mlists[3] = {
+       dnrr_memberlist_addr,
+       dnrr_memberlist_hinfo,
+       dnrr_memberlist_mx
+};
+
+static object *
+dnrr_getattr(self, name)
+       dnrrobject *self;
+       char *name;
+{
+       object *rv;
+       int tp;
+       
+       rv = findmethod(dnrr_methods, (object *)self, name);
+       if ( rv ) return rv;
+       err_clear();
+       if ( self->waiting )
+               if ( !dnrwait(self) )
+                       return NULL;
+       tp = self->type;
+       return getmember((char *)&self->hinfo, dnrr_mlists[tp], name);
+}
+
+
+static typeobject Dnrrtype = {
+       OB_HEAD_INIT(&Typetype)
+       0,                              /*ob_size*/
+       "MacTCP DNR Result",                    /*tp_name*/
+       sizeof(dnrrobject),             /*tp_basicsize*/
+       0,                              /*tp_itemsize*/
+       /* methods */
+       (destructor)dnrr_dealloc,       /*tp_dealloc*/
+       (printfunc)0,           /*tp_print*/
+       (getattrfunc)dnrr_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 DNR Result objects */
+/* -------------------------------------------------------- */
+
+int dnr_is_open;
+
+static int
+opendnr(fn)
+       char *fn;
+{
+       OSErr err;
+       
+       if ( dnr_is_open ) return 1;
+       if ( (err=OpenResolver(fn)) ) {
+               PyErr_Mac(ErrorObject, err);
+               return 0;
+       }
+       dnr_is_open = 1;
+       return 1;
+}
+       
+static object *
+dnr_Open(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       char *fn = NULL;
+
+       if (!newgetargs(args, "|s", &fn))
+               return NULL;
+       if ( dnr_is_open ) {
+               err_setstr(ErrorObject, "DNR already open");
+               return NULL;
+       }
+       if ( !opendnr(fn) )
+               return NULL;
+       INCREF(None);
+       return None;
+}
+
+static object *
+dnr_Close(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       OSErr err;
+
+       if (!newgetargs(args, ""))
+               return NULL;
+       dnr_is_open = 0;
+       if ( (err=CloseResolver()) ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       INCREF(None);
+       return None;
+}
+
+static object *
+dnr_StrToAddr(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       OSErr err;
+       char *hostname;
+       dnrrobject *rv;
+       ResultUPP cb_upp = NewResultProc(dnrr_done);
+
+       if (!newgetargs(args, "s", &hostname))
+               return NULL;
+       if ( !opendnr(NULL) )
+               return NULL;
+       if ( (rv=newdnrrobject(DNR_ADDR)) == NULL )
+               return NULL;
+       err = StrToAddr(hostname, (struct hostInfo *)&rv->hinfo, cb_upp, (char *)rv);
+       if ( err == cacheFault ) {
+               rv->waiting++;
+               INCREF(rv);
+       } else {
+               DECREF(rv);
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (object *)rv;
+}
+
+static object *
+dnr_AddrToName(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       OSErr err;
+       unsigned long ipaddr;
+       dnrrobject *rv;
+       ResultUPP cb_upp = NewResultProc(dnrr_done);
+
+       if (!newgetargs(args, "l", &ipaddr))
+               return NULL;
+       if ( !opendnr(NULL) )
+               return NULL;
+       if ( (rv=newdnrrobject(DNR_ADDR)) == NULL )
+               return NULL;
+       err = AddrToName(ipaddr, (struct hostInfo *)&rv->hinfo, cb_upp, (char *)rv);
+       if ( err == cacheFault ) {
+               rv->waiting++;
+               INCREF(rv);
+       } else {
+               DECREF(rv);
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (object *)rv;
+}
+
+static object *
+dnr_AddrToStr(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       OSErr err;
+       unsigned long ipaddr;
+       char ipname[16];
+       object *rv;
+
+       if (!newgetargs(args, "l", &ipaddr))
+               return NULL;
+       if ( !opendnr(NULL) )
+               return NULL;
+       if ( (err=AddrToStr(ipaddr, ipname)) ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return newstringobject(ipname);
+}
+
+static object *
+dnr_HInfo(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       OSErr err;
+       char *hostname;
+       dnrrobject *rv;
+
+       if (!newgetargs(args, "s", &hostname))
+               return NULL;
+       if ( !opendnr(NULL) )
+               return NULL;
+       if ( (rv=newdnrrobject(DNR_HINFO)) == NULL )
+               return NULL;
+       err = HInfo(hostname, &rv->hinfo, (ResultProc2Ptr)dnrr_done, (char *)rv);
+       if ( err == cacheFault ) {
+               rv->waiting++;
+               INCREF(rv);
+       } else {
+               DECREF(rv);
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (object *)rv;
+
+       if (!newgetargs(args, ""))
+               return NULL;
+       INCREF(None);
+       return None;
+}
+
+static object *
+dnr_MXInfo(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+       OSErr err;
+       char *hostname;
+       dnrrobject *rv;
+
+       if (!newgetargs(args, "s", &hostname))
+               return NULL;
+       if ( !opendnr(NULL) )
+               return NULL;
+       if ( (rv=newdnrrobject(DNR_MX)) == NULL )
+               return NULL;
+       err = MXInfo(hostname, &rv->hinfo, (ResultProc2Ptr)dnrr_done, (char *)rv);
+       if ( err == cacheFault ) {
+               rv->waiting++;
+               INCREF(rv);
+       } else {
+               DECREF(rv);
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (object *)rv;
+
+       if (!newgetargs(args, ""))
+               return NULL;
+       INCREF(None);
+       return None;
+}
+
+/* List of methods defined in the module */
+
+static struct methodlist dnr_methods[] = {
+       {"Open",        dnr_Open,       1},
+       {"Close",       dnr_Close,      1},
+       {"StrToAddr",   dnr_StrToAddr,  1},
+       {"AddrToStr",   dnr_AddrToStr,  1},
+       {"AddrToName",  dnr_AddrToName, 1},
+       {"HInfo",       dnr_HInfo,      1},
+       {"MXInfo",      dnr_MXInfo,     1},
+       {NULL,          NULL}           /* sentinel */
+};
+
+
+/* Initialization function for the module (*must* be called initmacdnr) */
+
+void
+initmacdnr()
+{
+       object *m, *d, *o;
+
+       /* Create the module and add the functions */
+       m = initmodule("macdnr", dnr_methods);
+
+       /* Add some symbolic constants to the module */
+       d = getmoduledict(m);
+       ErrorObject = newstringobject("macdnr.error");
+       dictinsert(d, "error", ErrorObject);
+#if 0
+/* Not needed, after all */
+#define CONST(name, value) o = newintobject(value); dictinsert(d, name, o);
+       CONST("ADDR", DNR_ADDR);
+       CONST("HINFO", DNR_HINFO);
+       CONST("MX", DNR_MX);
+#endif
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module macdnr");
+}
diff --git a/Mac/Unsupported/mactcp/mactcpmodule.c b/Mac/Unsupported/mactcp/mactcpmodule.c
new file mode 100644 (file)
index 0000000..0ba05ec
--- /dev/null
@@ -0,0 +1,908 @@
+/***********************************************************
+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>
+
+static object *ErrorObject;
+
+/* ----------------------------------------------------- */
+/* 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;
+       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;
+{
+       object *rv;
+       
+       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_asr_safe(arg)
+       void *arg;
+{
+       tcpsobject *self = (tcpsobject *)arg;
+       object *args, *rv;
+       
+       if ( self->asr == None )
+               return;
+       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_opendone(pb)
+       TCPiopb *pb;
+{
+       tcpsobject *self = (tcpsobject *)pb->csParam.open.userDataPtr;
+       
+       if ( pb != &self->iop || !self->async_busy ) {
+               /* Oops... problems */
+               printf("tcps_opendone: 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 = lastEvent-1;
+       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;
+       self->async_busy = 1;
+       self->async_err = 0;
+       err = xTCPPassiveOpen(&self->iop, port, (TCPIOCompletionProc)tcps_opendone,
+                                                (void *)self);
+       if ( err ) {
+               self->async_busy = 0;
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       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;
+       err = xTCPActiveOpen(&self->iop, lport, rhost, rport, (TCPIOCompletionProc)0);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }       
+       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;
+       wds.length = bufsize;
+       wds.ptr = buf;
+       wds.terminus = 0;
+       err = xTCPSend(&self->iop, (wdsEntry *)&wds, (Boolean)push, (Boolean)urgent,
+                                       (TCPIOCompletionProc)0);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       INCREF(None);
+       return None;
+}
+
+static object *
+tcps_Rcv(self, args)
+       tcpsobject *self;
+       object *args;
+{
+       int length;
+       int timeout;
+       rdsEntry rds[2];
+       OSErr err;
+       object *rv;
+       int urgent, mark;
+       
+       if (!newgetargs(args, "i", &timeout))
+               return NULL;
+       memset((char *)&rds, 0, sizeof(rds));
+       err = xTCPNoCopyRcv(&self->iop, rds, 1, timeout, (TCPIOCompletionProc)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, (TCPIOCompletionProc)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, (TCPIOCompletionProc)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;
+       err = xTCPStatus(&self->iop, &pb);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (object *)newtcpcsobject(pb);
+}
+
+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},
+       {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, (TCPNotifyProc)tcps_asr, (void *)self, &self->iop);
+       if ( err ) {
+               DEL(self);
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       INCREF(None);
+       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;
+       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, (UDPIOCompletionProc)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, (UDPIOCompletionProc)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, (UDPNotifyProc)udps_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);
+
+       /* XXXX Add constants here */
+       
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module mactcp");
+}
diff --git a/Mac/Unsupported/mactcp/tcpglue.c b/Mac/Unsupported/mactcp/tcpglue.c
new file mode 100644 (file)
index 0000000..1c8ecb0
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Glue routines for mactcp module.
+ * Jack Jansen, CWI, 1994.
+ *
+ * Adapted from mactcp socket library, which was in turn
+ * adapted from ncsa telnet code.
+ *
+ * Original authors: Tom Milligan, Charlie Reiman
+ */
+# include <Memory.h>
+# include <Files.h>
+# include <Errors.h>
+
+#include "tcpglue.h"
+#include <Devices.h>
+
+#ifndef __MWERKS__
+#define TCPIOCompletionUPP TCPIOCompletionProc
+#define NewTCPIOCompletionProc(x) (x)
+#endif /* __MWERKS__ */
+
+static short driver = 0;
+
+#ifndef __powerc
+/*
+ * Hack fix for MacTCP 1.0.X bug
+ *
+ * This hack doesn't work on the PPC. But then, people with new machines
+ * shouldn't run ancient buggy software. -- Jack.
+ */
+pascal char *ReturnA5(void) = {0x2E8D};
+#endif /* !__powerc */
+
+OSErr xOpenDriver() 
+{ 
+       if (driver == 0) 
+       { 
+               ParamBlockRec pb; 
+               OSErr io; 
+               
+               pb.ioParam.ioCompletion = 0L; 
+               pb.ioParam.ioNamePtr = "\p.IPP"; 
+               pb.ioParam.ioPermssn = fsCurPerm; 
+               io = PBOpen(&pb,false); 
+               if (io != noErr) 
+                       return(io); 
+               driver = pb.ioParam.ioRefNum; 
+       }
+       return noErr;
+}
+
+/*
+ * create a TCP stream
+ */
+OSErr xTCPCreate(buflen,notify,udp, pb) 
+       int buflen;
+       TCPNotifyProc notify;
+       void *udp;
+       TCPiopb *pb;
+{      
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPCreate;
+       pb->csParam.create.rcvBuff = (char *)NewPtr(buflen);
+       pb->csParam.create.rcvBuffLen = buflen;
+       pb->csParam.create.notifyProc = notify;
+       pb->csParam.create.userDataPtr = udp;
+       return (xPBControlSync(pb));
+}
+
+
+/*
+ * start listening for a TCP connection
+ */
+OSErr xTCPPassiveOpen(TCPiopb *pb, short port, TCPIOCompletionProc completion,
+       void *udp)
+{
+       if (driver == 0)
+               return(invalidStreamPtr);
+
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPPassiveOpen;
+       pb->csParam.open.validityFlags = timeoutValue | timeoutAction;
+       pb->csParam.open.ulpTimeoutValue = 255 /* seconds */;
+       pb->csParam.open.ulpTimeoutAction = 0 /* 1:abort 0:report */;
+       pb->csParam.open.commandTimeoutValue = 0 /* infinity */;
+       pb->csParam.open.remoteHost = 0;
+       pb->csParam.open.remotePort = 0;
+       pb->csParam.open.localHost = 0;
+       pb->csParam.open.localPort = port;
+       pb->csParam.open.dontFrag = 0;
+       pb->csParam.open.timeToLive = 0;
+       pb->csParam.open.security = 0;
+       pb->csParam.open.optionCnt = 0;
+       pb->csParam.open.userDataPtr = udp;
+       return (xPBControl(pb,completion));
+}
+
+/*
+ * connect to a remote TCP
+ */
+OSErr xTCPActiveOpen(TCPiopb *pb, short port, long rhost, short rport, 
+       TCPIOCompletionProc completion)
+{
+       if (driver == 0)
+               return(invalidStreamPtr);
+
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPActiveOpen;
+       pb->csParam.open.validityFlags = timeoutValue | timeoutAction;
+       pb->csParam.open.ulpTimeoutValue = 60 /* seconds */;
+       pb->csParam.open.ulpTimeoutAction = 1 /* 1:abort 0:report */;
+       pb->csParam.open.commandTimeoutValue = 0;
+       pb->csParam.open.remoteHost = rhost;
+       pb->csParam.open.remotePort = rport;
+       pb->csParam.open.localHost = 0;
+       pb->csParam.open.localPort = port;
+       pb->csParam.open.dontFrag = 0;
+       pb->csParam.open.timeToLive = 0;
+       pb->csParam.open.security = 0;
+       pb->csParam.open.optionCnt = 0;
+       return (xPBControl(pb,completion));
+}
+
+OSErr xTCPNoCopyRcv(pb,rds,rdslen,timeout,completion) 
+       TCPiopb *pb;
+       rdsEntry *rds; 
+       int rdslen;
+       int     timeout;
+       TCPIOCompletionProc completion;
+{
+       
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPNoCopyRcv;
+       pb->csParam.receive.commandTimeoutValue = timeout; /* seconds, 0 = blocking */
+       pb->csParam.receive.rdsPtr = (Ptr)rds;
+       pb->csParam.receive.rdsLength = rdslen;
+       return (xPBControl(pb,completion));
+}
+
+OSErr xTCPBufReturn(TCPiopb *pb,rdsEntry *rds,TCPIOCompletionProc completion)
+       {
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPRcvBfrReturn;
+       pb->csParam.receive.rdsPtr = (Ptr)rds;
+       
+       return (xPBControl(pb,completion));
+       }
+       
+/*
+ * send data
+ */
+OSErr xTCPSend(TCPiopb *pb, wdsEntry *wds, Boolean push, Boolean urgent, TCPIOCompletionProc completion)
+{
+       if (driver == 0)
+               return invalidStreamPtr;
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPSend;
+       pb->csParam.send.validityFlags = timeoutValue | timeoutAction;
+       pb->csParam.send.ulpTimeoutValue = 60 /* seconds */;
+       pb->csParam.send.ulpTimeoutAction = 0 /* 0:abort 1:report */;
+       pb->csParam.send.pushFlag = push;
+       pb->csParam.send.urgentFlag = urgent;
+       pb->csParam.send.wdsPtr = (Ptr)wds;
+       return (xPBControl(pb,completion));
+}
+
+
+/*
+ * close a connection
+ */
+OSErr xTCPClose(TCPiopb *pb,TCPIOCompletionProc completion) 
+{
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPClose;
+       pb->csParam.close.validityFlags = timeoutValue | timeoutAction;
+       pb->csParam.close.ulpTimeoutValue = 60 /* seconds */;
+       pb->csParam.close.ulpTimeoutAction = 1 /* 1:abort 0:report */;
+       return (xPBControl(pb,completion));
+}
+
+/*
+ * abort a connection
+ */
+OSErr xTCPAbort(TCPiopb *pb) 
+{
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPAbort;
+       return (xPBControlSync(pb));
+}
+
+/*
+ * close down a TCP stream (aborting a connection, if necessary)
+ */
+OSErr xTCPRelease(pb) 
+       TCPiopb *pb;
+{
+       OSErr io;
+       
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPRelease;
+       io = xPBControlSync(pb);
+       if (io == noErr)
+               DisposPtr(pb->csParam.create.rcvBuff); /* there is no release pb */
+       return(io);
+}
+
+#if 0
+
+int
+xTCPBytesUnread(sp) 
+       SocketPtr sp;
+{
+       TCPiopb *pb;
+       OSErr io;
+       
+       if (!(pb = sock_fetch_pb(sp)))
+               return -1;              /* panic */
+       
+       if (driver == 0)
+               return(-1);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPStatus;
+       io = xPBControlSync(pb);
+       if (io != noErr)
+               return(-1);
+       return(pb->csParam.status.amtUnreadData);
+}
+
+int
+xTCPBytesWriteable(sp)
+       SocketPtr sp;
+       {
+       TCPiopb *pb;
+       OSErr   io;
+       long    amount;
+       
+       if (!(pb = sock_fetch_pb(sp)))
+               return -1;              /* panic */
+       
+       if (driver == 0)
+               return(-1);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPStatus;
+       io = xPBControlSync(pb);
+       if (io != noErr)
+               return(-1);
+       amount = pb->csParam.status.sendWindow-pb->csParam.status.amtUnackedData;
+       if (amount < 0)
+               amount = 0;
+       return amount;
+       }
+       
+int xTCPWriteBytesLeft(SocketPtr sp)
+       {
+       TCPiopb *pb;
+       OSErr   io;
+       
+       if (!(pb = sock_fetch_pb(sp)))
+               return -1;              /* panic */
+       
+       if (driver == 0)
+               return(-1);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPStatus;
+       io = xPBControlSync(pb);
+       if (io != noErr)
+               return(-1);
+       return (pb->csParam.status.amtUnackedData);
+       }
+#endif
+
+OSErr xTCPStatus(TCPiopb *pb, TCPStatusPB **spb)
+       {
+       OSErr io;
+       
+       if (driver == 0)
+               return(-1);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPStatus;
+       io = xPBControlSync(pb);
+       if (io == noErr)
+               *spb = &pb->csParam.status;
+       return(io);
+       }
+
+
+/*
+ * create a UDP stream, hook it to a socket.
+ */
+OSErr xUDPCreate(UDPiopb *pb,int buflen,ip_port *port, UDPNotifyProc asr, void *udp)
+       {       
+       OSErr   io;
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = UDPCreate;
+       pb->csParam.create.rcvBuff = (char *)NewPtr(buflen);
+       pb->csParam.create.rcvBuffLen = buflen;
+       pb->csParam.create.notifyProc = asr;
+       pb->csParam.create.userDataPtr = udp;
+       pb->csParam.create.localPort = *port;
+       if ( (io = xPBControlSync( (TCPiopb *)pb ) ) != noErr)
+               return io;
+               
+       *port = pb->csParam.create.localPort;
+       return noErr;
+       }
+
+/*
+ * ask for incoming data
+ */
+OSErr xUDPRead(UDPiopb *pb, int timeout, UDPIOCompletionProc completion) 
+       {
+       
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = UDPRead;
+       pb->csParam.receive.timeOut = timeout;
+       pb->csParam.receive.secondTimeStamp = 0/* must be zero */;
+       return (xPBControl ( (TCPiopb *)pb, (TCPIOCompletionProc)completion ));
+       }
+
+OSErr xUDPBfrReturn(UDPiopb *pb, char *buff) 
+       {
+       
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = UDPBfrReturn;
+       pb->csParam.receive.rcvBuff = buff;
+       return ( xPBControl( (TCPiopb *)pb,(TCPIOCompletionProc)-1 ) );
+       }
+
+/*
+ * send data
+ */
+OSErr xUDPWrite(UDPiopb        *pb,ip_addr host,ip_port port,miniwds *wds,
+               UDPIOCompletionProc completion) 
+       {
+               
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = UDPWrite;
+       pb->csParam.send.remoteHost = host;
+       pb->csParam.send.remotePort = port;
+       pb->csParam.send.wdsPtr = (Ptr)wds;
+       pb->csParam.send.checkSum = true;
+       pb->csParam.send.sendLength = 0/* must be zero */;
+       return (xPBControl( (TCPiopb *)pb, (TCPIOCompletionProc)completion));
+       }
+
+/*
+ * close down a UDP stream (aborting a read, if necessary)
+ */
+OSErr xUDPRelease(UDPiopb *pb) {
+       OSErr io;
+
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = UDPRelease;
+       io = xPBControlSync( (TCPiopb *)pb );
+       if (io == noErr) {
+               DisposPtr(pb->csParam.create.rcvBuff);
+               }
+       return(io);
+       }
+
+ip_addr xIPAddr(void) 
+{
+       struct GetAddrParamBlock pbr;
+       OSErr io;
+       
+       pbr.ioCRefNum = driver;
+       pbr.csCode = ipctlGetAddr;
+       io = xPBControlSync( (TCPiopb *)&pbr );
+       if (io != noErr)
+               return(0);
+       return(pbr.ourAddress);
+}
+
+long xNetMask() 
+{
+       struct GetAddrParamBlock pbr;
+       OSErr io;
+       
+       pbr.ioCRefNum = driver;
+       pbr.csCode = ipctlGetAddr;
+       io = xPBControlSync( (TCPiopb *)&pbr);
+       if (io != noErr)
+               return(0);
+       return(pbr.ourNetMask);
+}
+
+unsigned short xMaxMTU()
+{
+       struct UDPiopb pbr;
+       OSErr io;
+       
+       pbr.ioCRefNum = driver;
+       pbr.csCode = UDPMaxMTUSize;
+       pbr.csParam.mtu.remoteHost = xIPAddr();
+       io = xPBControlSync( (TCPiopb *)&pbr );
+       if (io != noErr)
+               return(0);
+       return(pbr.csParam.mtu.mtuSize);
+}
+
+OSErr xPBControlSync(TCPiopb *pb) 
+{ 
+       (pb)->ioCompletion = 0L; 
+       return PBControl((ParmBlkPtr)(pb),false); 
+}
+
+#pragma segment SOCK_RESIDENT
+
+OSErr xTCPRcv(pb,buf,buflen,timeout,completion) 
+       TCPiopb *pb;
+       Ptr buf; 
+       int buflen;
+       int     timeout;
+       TCPIOCompletionProc completion;
+{
+       
+       if (driver == 0)
+               return(invalidStreamPtr);
+       
+       pb->ioCRefNum = driver;
+       pb->csCode = TCPRcv;
+       pb->csParam.receive.commandTimeoutValue = timeout; /* seconds, 0 = blocking */
+       pb->csParam.receive.rcvBuff = buf;
+       pb->csParam.receive.rcvBuffLen = buflen;
+       return (xPBControl(pb,completion));
+}
+
+OSErr xPBControl(TCPiopb *pb,TCPIOCompletionProc completion) 
+{ 
+#ifndef __MWERKS__
+       pb->ioNamePtr = ReturnA5();
+#endif
+       
+       if (completion == 0L) 
+       { 
+               (pb)->ioCompletion = 0L; 
+               return(PBControl((ParmBlkPtr)(pb),false));              /* sync */
+       } 
+       else if (completion == (TCPIOCompletionProc)-1L) 
+       { 
+               (pb)->ioCompletion = 0L; 
+               return(PBControl((ParmBlkPtr)(pb),true));               /* async */
+       } 
+       else 
+       {  
+#if 0
+               /* If I understand the PowerPC calling correctly this is the right
+               ** code, but the MetroWerks headers seem to disagree. We'll see... -- Jack
+               */
+               TCPIOCompletionUPP comp_upp = NewTCPIOCompletionProc(completion);
+               (pb)->ioCompletion = comp_upp; 
+#else
+               (pb)->ioCompletion = completion;
+#endif
+               return(PBControl((ParmBlkPtr)(pb),true));               /* async */
+       } 
+}
+
diff --git a/Mac/Unsupported/mactcp/tcpglue.h b/Mac/Unsupported/mactcp/tcpglue.h
new file mode 100644 (file)
index 0000000..4db91f0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Prototypes for mactcpglue routines and includes/structures needed
+ * by those.
+ *
+ * Jack Jansen, CWI, 1994.
+ *
+ * Adapted from mac socket library, which has in turn adapted from ncsa telnet.
+ * Original authors: Tom Milligan, Charlie Reiman
+ */
+  
+#include <MacTCPCommonTypes.h>
+#include <GetMyIPAddr.h>
+#include <TCPPB.h>
+#include <UDPPB.h>
+#include <AddressXlation.h>
+
+typedef        struct  miniwds
+       {
+       unsigned short length;
+       char * ptr;
+       unsigned short terminus;        /* must be zero'd for use */
+       } miniwds;
+
+
+OSErr xOpenDriver(void);
+OSErr xPBControl(TCPiopb *pb, TCPIOCompletionProc completion);
+OSErr xPBControlSync(TCPiopb *pb);
+OSErr xTCPCreate(int buflen, TCPNotifyProc notify, void *udp, TCPiopb *pb);
+OSErr xTCPPassiveOpen(TCPiopb *pb, short port, TCPIOCompletionProc completion, void *udp);
+OSErr xTCPActiveOpen(TCPiopb *pb, short port, long rhost, short rport, TCPIOCompletionProc completion);
+OSErr xTCPRcv(TCPiopb *pb, char *buf, int buflen, int timeout, TCPIOCompletionProc completion);
+OSErr xTCPNoCopyRcv(TCPiopb *,rdsEntry *,int,int,TCPIOCompletionProc);
+OSErr xTCPBufReturn(TCPiopb *pb,rdsEntry *rds,TCPIOCompletionProc completion);
+OSErr xTCPSend(TCPiopb *pb, wdsEntry *wds, Boolean push, Boolean urgent, TCPIOCompletionProc completion);
+OSErr xTCPClose(TCPiopb *pb,TCPIOCompletionProc completion);
+OSErr xTCPAbort(TCPiopb *pb);
+OSErr xTCPRelease(TCPiopb *pb);
+
+OSErr xUDPCreate(UDPiopb *pb,int buflen,ip_port *port, UDPNotifyProc asr, void *udp);
+OSErr xUDPRead(UDPiopb *pb,int timeout, UDPIOCompletionProc completion);
+OSErr xUDPBfrReturn(UDPiopb *pb, char *buff);
+OSErr xUDPWrite(UDPiopb *pb,ip_addr host,ip_port port,miniwds *wds,
+               UDPIOCompletionProc completion);
+OSErr xUDPRelease(UDPiopb *pb);
+
+ip_addr xIPAddr(void);
+long xNetMask(void);
+unsigned short xMaxMTU(void);
+