summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Mac/Unsupported/mactcp/dnrglue.c301
-rw-r--r--Mac/Unsupported/mactcp/macdnrmodule.c456
-rw-r--r--Mac/Unsupported/mactcp/mactcpmodule.c908
-rw-r--r--Mac/Unsupported/mactcp/tcpglue.c490
-rw-r--r--Mac/Unsupported/mactcp/tcpglue.h49
5 files changed, 2204 insertions, 0 deletions
diff --git a/Mac/Unsupported/mactcp/dnrglue.c b/Mac/Unsupported/mactcp/dnrglue.c
new file mode 100644
index 0000000..5474b73
--- /dev/null
+++ b/Mac/Unsupported/mactcp/dnrglue.c
@@ -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
index 0000000..75dd89a
--- /dev/null
+++ b/Mac/Unsupported/mactcp/macdnrmodule.c
@@ -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
index 0000000..0ba05ec
--- /dev/null
+++ b/Mac/Unsupported/mactcp/mactcpmodule.c
@@ -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
index 0000000..1c8ecb0
--- /dev/null
+++ b/Mac/Unsupported/mactcp/tcpglue.c
@@ -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
index 0000000..4db91f0
--- /dev/null
+++ b/Mac/Unsupported/mactcp/tcpglue.h
@@ -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);
+