From edf585579c637fc70ff80fc33d9bc4251313ce99 Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Wed, 14 Dec 1994 13:36:34 +0000 Subject: [PATCH] Interface to MacTCP and the MacTCP Domain Name Resolver --- Mac/Unsupported/mactcp/dnrglue.c | 301 +++++++++ Mac/Unsupported/mactcp/macdnrmodule.c | 456 +++++++++++++ Mac/Unsupported/mactcp/mactcpmodule.c | 908 ++++++++++++++++++++++++++ Mac/Unsupported/mactcp/tcpglue.c | 490 ++++++++++++++ Mac/Unsupported/mactcp/tcpglue.h | 49 ++ 5 files changed, 2204 insertions(+) create mode 100644 Mac/Unsupported/mactcp/dnrglue.c create mode 100644 Mac/Unsupported/mactcp/macdnrmodule.c create mode 100644 Mac/Unsupported/mactcp/mactcpmodule.c create mode 100644 Mac/Unsupported/mactcp/tcpglue.c create mode 100644 Mac/Unsupported/mactcp/tcpglue.h diff --git a/Mac/Unsupported/mactcp/dnrglue.c b/Mac/Unsupported/mactcp/dnrglue.c new file mode 100644 index 00000000000..5474b73ceda --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 00000000000..75dd89a2ece --- /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 +#include + +#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 00000000000..0ba05ec5670 --- /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 + +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 00000000000..1c8ecb0f9b4 --- /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 +# include +# include + +#include "tcpglue.h" +#include + +#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 00000000000..4db91f004d7 --- /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 +#include +#include +#include +#include + +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); +