home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / util / comm / news102.sit / NewsWatcher / source / tcproutines.c < prev    next >
Text File  |  1991-04-03  |  13KB  |  528 lines

  1. /*----------------------------------------------------------
  2. #
  3. #    NewsWatcher    - Macintosh NNTP Client Application
  4. #
  5. #    Written by Steven Falkenburg
  6. #    ⌐1990 Apple Computer, Inc.
  7. #
  8. #-----------------------------------------------------------
  9. #
  10. #    tcproutines.c
  11. #
  12. #    This code segment contains the low-level interfaces to
  13. #    the MacTCP device driver calls.
  14. #
  15. #-----------------------------------------------------------*/
  16.  
  17. #include "compat.h"
  18.  
  19. #ifdef    PROTOS
  20. #include <SysEqu.h>
  21. #include <Types.h>
  22. #include <Events.h>
  23. #include <OSUtils.h>
  24. #include <Devices.h>
  25. #include <CursorCtl.h>
  26. #include <Memory.h>
  27. #include <Dialogs.h>
  28. #include <Lists.h>
  29. #endif
  30.  
  31. #include "MacTCPCommonTypes.h"
  32. #include "TCPPB.h"
  33. #include "GetMyIPAddr.h"
  34. #include "nntp.h"
  35. #include "miscstuff.h"
  36. #include "TCPRoutines.h"
  37.  
  38. OSErr NewBlock(TCPiopb **pBlock);
  39.  
  40. long cSleepTime = 20;
  41.  
  42. /* global variables */
  43.  
  44. extern Boolean gCancel;
  45. short         refNum;
  46.  
  47.  
  48. /* Opens the MacTCP driver.
  49.    This routine must be called prior to any of the below functions. */
  50.  
  51. OSErr OpenTCPDriver()
  52. {
  53.     OSErr    err;
  54.     
  55.     err = OpenDriver("\p.IPP",&refNum);
  56.     return(err);
  57. }
  58.  
  59.  
  60. OSErr NewBlock(TCPiopb **pBlock)
  61. {
  62.     *pBlock = (TCPiopb *)MyNewPtr(sizeof(TCPiopb));
  63.     if (MyMemErr() != noErr)
  64.         return MyMemErr();
  65.     (*pBlock)->ioCompletion = 0L;
  66.     (*pBlock)->ioCRefNum = refNum;
  67.     return noErr;
  68. }
  69.  
  70.  
  71. /* kills any pending calls to the TCP driver */
  72.  
  73. OSErr LowKillTCP(TCPiopb *pBlock)
  74. {
  75.     return(PBKillIO((ParmBlkPtr)pBlock,false));
  76. }
  77.  
  78.  
  79. /* Creates a new TCP stream in preparation for initiating a connection.
  80.    A buffer must be provided for storing incoming data waiting to be processed */
  81.  
  82. OSErr LowTCPCreateStream(StreamPtr *streamPtr,Ptr connectionBuffer,
  83.             unsigned long connBufferLen,TCPNotifyProc notifPtr)
  84. {
  85.     OSErr err;
  86.     TCPiopb *pBlock;
  87.     
  88.     if ((err = NewBlock(&pBlock)) != noErr)
  89.         return err;
  90.         
  91.     pBlock->csCode = TCPCreate;
  92.     pBlock->ioResult = 1;
  93.     pBlock->csParam.create.rcvBuff = connectionBuffer;
  94.     pBlock->csParam.create.rcvBuffLen = connBufferLen;
  95.     pBlock->csParam.create.notifyProc = notifPtr;
  96.     PBControl((ParmBlkPtr)pBlock,true);
  97.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  98.         ;
  99.     if (gCancel)
  100.         return -1;
  101.         
  102.     *streamPtr = pBlock->tcpStream;
  103.     err = pBlock->ioResult;
  104.     MyDisposPtr((Ptr)pBlock);
  105.     return err;
  106. }
  107.  
  108.  
  109. /* If TCPWaitForConnection is called asynchronously, this command retrieves the 
  110.    result of the call.  It should be called when the above command completes. */
  111.  
  112. OSErr LowFinishTCPWaitForConn(TCPiopb *pBlock,ip_addr *remoteHost,tcp_port *remotePort,
  113.                             ip_addr *localHost,tcp_port *localPort)
  114. {    
  115.     OSErr err;
  116.     
  117.     *remoteHost = pBlock->csParam.open.remoteHost;
  118.     *remotePort = pBlock->csParam.open.remotePort;
  119.     *localHost = pBlock->csParam.open.localHost;
  120.     *localPort = pBlock->csParam.open.localPort;
  121.     err = pBlock->ioResult;
  122.     MyDisposPtr((Ptr)pBlock);
  123.     return err;
  124. }
  125.  
  126.  
  127. /* Waits for a connection to be opened on a specified port from a specified address.
  128.    It completes when a connection is made, or a timeout value is reached.  This call
  129.    may be made asynchronously. */
  130.  
  131. OSErr LowTCPWaitForConnection(StreamPtr streamPtr,byte timeout,ip_addr *remoteHost,
  132.             tcp_port *remotePort,ip_addr *localHost,tcp_port *localPort,
  133.             Boolean async,TCPiopb **returnBlock)
  134. {
  135.     OSErr err;
  136.     TCPiopb *pBlock;
  137.     
  138.     if ((err = NewBlock(&pBlock)) != noErr)
  139.         return err;
  140.     
  141.     pBlock->csCode = TCPPassiveOpen;
  142.     pBlock->ioResult = 1;
  143.     pBlock->ioCompletion = nil;
  144.     pBlock->tcpStream = streamPtr;
  145.     pBlock->csParam.open.ulpTimeoutValue = timeout;
  146.     pBlock->csParam.open.ulpTimeoutAction = 1;
  147.     pBlock->csParam.open.validityFlags = 0xC0;
  148.     pBlock->csParam.open.commandTimeoutValue = timeout;
  149.     pBlock->csParam.open.remoteHost = *remoteHost;
  150.     pBlock->csParam.open.remotePort = *remotePort;
  151.     pBlock->csParam.open.localPort = *localPort;
  152.     pBlock->csParam.open.tosFlags = 0;
  153.     pBlock->csParam.open.precedence = 0;
  154.     pBlock->csParam.open.dontFrag = 0;
  155.     pBlock->csParam.open.timeToLive = 0;
  156.     pBlock->csParam.open.security = 0;
  157.     pBlock->csParam.open.optionCnt = 0;
  158.     PBControl((ParmBlkPtr)pBlock,true);
  159.     if (!async) {
  160.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  161.             ;
  162.         if (gCancel)
  163.             return -1;
  164.         return(LowFinishTCPWaitForConn(pBlock,remoteHost,remotePort,localHost,localPort));
  165.     }
  166.     
  167.     *returnBlock = pBlock;
  168.     return noErr;
  169. }
  170.  
  171.  
  172. /* Attempts to initiate a connection with a host specified by host and port. */
  173.  
  174. OSErr LowTCPOpenConnection(StreamPtr streamPtr,byte timeout,ip_addr remoteHost,
  175.             tcp_port remotePort,ip_addr *localHost,tcp_port *localPort)
  176. {
  177.     OSErr err;
  178.     TCPiopb *pBlock;
  179.     
  180.     if ((err = NewBlock(&pBlock)) != noErr)
  181.         return err;
  182.     
  183.     pBlock->csCode = TCPActiveOpen;
  184.     pBlock->ioResult = 1;
  185.     pBlock->tcpStream = streamPtr;
  186.     pBlock->csParam.open.ulpTimeoutValue = timeout;
  187.     pBlock->csParam.open.ulpTimeoutAction = 1;
  188.     pBlock->csParam.open.validityFlags = 0xC0;
  189.     pBlock->csParam.open.commandTimeoutValue = timeout;
  190.     pBlock->csParam.open.remoteHost = remoteHost;
  191.     pBlock->csParam.open.remotePort = remotePort;
  192.     pBlock->csParam.open.localPort = *localPort;
  193.     pBlock->csParam.open.tosFlags = 0;
  194.     pBlock->csParam.open.precedence = 0;
  195.     pBlock->csParam.open.dontFrag = 0;
  196.     pBlock->csParam.open.timeToLive = 0;
  197.     pBlock->csParam.open.security = 0;
  198.     pBlock->csParam.open.optionCnt = 0;
  199.     PBControl((ParmBlkPtr)pBlock,true);
  200.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  201.         ;
  202.     if (gCancel)
  203.         return -1;
  204.     *localHost = pBlock->csParam.open.localHost;
  205.     *localPort = pBlock->csParam.open.localPort;
  206.     err = pBlock->ioResult;
  207.     MyDisposPtr((Ptr)pBlock);
  208.     return err;
  209. }
  210.  
  211.  
  212. /* This routine should be called when a TCPSendData call completes.  It returns the
  213.    error code generated upon completion of the CallTCPSend. */
  214.  
  215. OSErr LowFinishTCPSend(TCPiopb *pBlock)
  216. {
  217.     OSErr err;
  218.     
  219.     err = pBlock->ioResult;
  220.     MyDisposPtr((Ptr)pBlock);
  221.     return err;
  222. }
  223.  
  224.  
  225. /* Sends data through an open connection stream.  Note that the connection must be
  226.    open before any data is sent. This call may be made asynchronously. */
  227.  
  228. OSErr LowTCPSendData(StreamPtr streamPtr,byte timeout,Boolean push,Boolean urgent,
  229.                     Ptr wdsPtr,Boolean async,TCPiopb **returnBlock)
  230. {    
  231.     OSErr err;
  232.     TCPiopb *pBlock;
  233.     
  234.     if ((err = NewBlock(&pBlock)) != noErr)
  235.         return err;
  236.     
  237.     pBlock->csCode = TCPSend;
  238.     pBlock->ioResult = 1;
  239.     pBlock->tcpStream = streamPtr;
  240.     pBlock->ioCompletion = nil;
  241.     pBlock->csParam.send.ulpTimeoutValue = timeout;
  242.     pBlock->csParam.send.ulpTimeoutAction = 1;
  243.     pBlock->csParam.send.validityFlags = 0xC0;
  244.     pBlock->csParam.send.pushFlag = push;
  245.     pBlock->csParam.send.urgentFlag = urgent;
  246.     pBlock->csParam.send.wdsPtr = wdsPtr;
  247.     PBControl((ParmBlkPtr)pBlock,true);
  248.     if (!async) {
  249.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  250.             ;
  251.         if (gCancel)
  252.             return -1;
  253.         return LowFinishTCPSend(pBlock);
  254.         return err;
  255.     }
  256.     
  257.     *returnBlock = pBlock;
  258.     return noErr;
  259. }
  260.  
  261.  
  262. OSErr LowFinishTCPNoCopyRcv(TCPiopb *pBlock,Boolean *urgent,Boolean *mark)
  263. {
  264.     OSErr err;
  265.     
  266.     *urgent = pBlock->csParam.receive.urgentFlag;
  267.     *mark = pBlock->csParam.receive.markFlag;
  268.     
  269.     err = pBlock->ioResult;
  270.     MyDisposPtr((Ptr)pBlock);
  271.     return err;
  272. }
  273.  
  274.  
  275. OSErr LowTCPNoCopyRcv(StreamPtr streamPtr,byte timeout,Boolean *urgent,Boolean *mark,
  276.                 Ptr rdsPtr,short numEntry,Boolean async,TCPiopb **returnBlock)
  277. {
  278.     OSErr    err = noErr;
  279.     TCPiopb *pBlock;
  280.     
  281.     if ((err = NewBlock(&pBlock)) != noErr)
  282.         return err;
  283.     
  284.     pBlock->csCode = TCPNoCopyRcv;
  285.     pBlock->ioResult = 1;
  286.     pBlock->tcpStream = streamPtr;
  287.     pBlock->ioCompletion = nil;
  288.     pBlock->csParam.receive.commandTimeoutValue = timeout;
  289.     pBlock->csParam.receive.rdsPtr = rdsPtr;
  290.     pBlock->csParam.receive.rdsLength = numEntry;
  291.     PBControl((ParmBlkPtr)pBlock,true);
  292.     if (!async) {
  293.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  294.             ;
  295.         if (gCancel)
  296.             return -1;
  297.         return LowFinishTCPNoCopyRcv(pBlock,urgent,mark);
  298.     }
  299.     
  300.     *returnBlock = pBlock;
  301.     return noErr;
  302. }
  303.  
  304.  
  305. OSErr LowTCPBfrReturn(StreamPtr streamPtr,Ptr rdsPtr)
  306. {
  307.     OSErr err;
  308.     TCPiopb *pBlock;
  309.     
  310.     if ((err = NewBlock(&pBlock)) != noErr)
  311.         return err;
  312.     
  313.     pBlock->csCode = TCPRcvBfrReturn;
  314.     pBlock->ioResult = 1;
  315.     pBlock->tcpStream = streamPtr;
  316.     pBlock->csParam.receive.rdsPtr = rdsPtr;
  317.     PBControl((ParmBlkPtr)pBlock,true);
  318.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  319.         ;
  320.     if (gCancel)
  321.         return -1;
  322.     err = pBlock->ioResult;
  323.     MyDisposPtr((Ptr)pBlock);
  324.     return err;
  325. }
  326.  
  327.  
  328. /* If the above is called asynchronously, this routine returns the data that was
  329.    received from the remote host. */
  330.    
  331. OSErr LowFinishTCPRecv(TCPiopb *pBlock,Boolean *urgent,Boolean *mark,
  332.                     unsigned short *rcvLen)
  333. {
  334.     OSErr err;
  335.     
  336.     *rcvLen = pBlock->csParam.receive.rcvBuffLen;
  337.     *urgent = pBlock->csParam.receive.urgentFlag;
  338.     *mark = pBlock->csParam.receive.markFlag;
  339.     err = pBlock->ioResult;
  340.     MyDisposPtr((Ptr)pBlock);
  341.     return err;
  342. }
  343.  
  344.  
  345. /* Attempts to pull data out of the incoming stream for a connection. If data is
  346.    not present, the routine waits a specified amout of time before returning with
  347.    a timeout error.  This call may be made asynchronously. */
  348.    
  349. OSErr LowTCPRecvData(StreamPtr streamPtr,byte timeout,Boolean *urgent,Boolean *mark,
  350.                 Ptr rcvBuff,unsigned short *rcvLen,Boolean async,TCPiopb **returnBlock)
  351. {
  352.     OSErr err;
  353.     TCPiopb *pBlock;
  354.     
  355.     if ((err = NewBlock(&pBlock)) != noErr)
  356.         return err;
  357.     
  358.     pBlock->csCode = TCPRcv;
  359.     pBlock->ioResult = 1;
  360.     pBlock->ioCompletion = nil;
  361.     pBlock->tcpStream = streamPtr;
  362.     pBlock->csParam.receive.commandTimeoutValue = timeout;
  363.     pBlock->csParam.receive.rcvBuff = rcvBuff;
  364.     pBlock->csParam.receive.rcvBuffLen = *rcvLen;
  365.     PBControl((ParmBlkPtr)pBlock,true);
  366.     if (!async) {
  367.         while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  368.             ;
  369.         if (gCancel)
  370.             return -1;
  371.         return(LowFinishTCPRecv(pBlock,urgent,mark,rcvLen));
  372.     }
  373.     
  374.     *returnBlock = pBlock;
  375.     return noErr;
  376. }
  377.     
  378.  
  379. /* Gracefully closes a connection with a remote host.  This is not always possible,
  380.    and the programmer might have to resort to CallTCPAbort, described next. */
  381.  
  382. OSErr LowTCPClose(StreamPtr streamPtr,byte timeout)
  383. {
  384.     OSErr err;
  385.     TCPiopb *pBlock;
  386.     
  387.     if ((err = NewBlock(&pBlock)) != noErr)
  388.         return err;
  389.     
  390.     pBlock->csCode = TCPClose;
  391.     pBlock->ioResult = 1;
  392.     pBlock->tcpStream = streamPtr;
  393.     pBlock->csParam.close.ulpTimeoutValue = timeout;
  394.     pBlock->csParam.close.validityFlags = 0xC0;
  395.     pBlock->csParam.close.ulpTimeoutAction = 1;
  396.     PBControl((ParmBlkPtr)pBlock,true);
  397.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  398.         ;
  399.     if (gCancel)
  400.         return -1;
  401.     err = pBlock->ioResult;
  402.     MyDisposPtr((Ptr)pBlock);
  403.     return err;
  404. }
  405.  
  406.  
  407. /* Should be called if a CallTCPClose fails to close a connection properly.
  408.    This call should not normally be used to terminate connections. */
  409.    
  410. OSErr LowTCPAbort(StreamPtr streamPtr)
  411. {
  412.     OSErr err;
  413.     TCPiopb *pBlock;
  414.     
  415.     if ((err = NewBlock(&pBlock)) != noErr)
  416.         return err;
  417.     
  418.     pBlock->csCode = TCPAbort;
  419.     pBlock->ioResult = 1;
  420.     pBlock->tcpStream = streamPtr;
  421.     PBControl((ParmBlkPtr)pBlock,true);
  422.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  423.         ;
  424.     if (gCancel)
  425.         return -1;
  426.     err = pBlock->ioResult;
  427.     MyDisposPtr((Ptr)pBlock);
  428.     return err;
  429. }
  430.  
  431. OSErr LowTCPStatus(StreamPtr streamPtr,TCPStatusPB *theStatus)
  432. {
  433.     OSErr err;
  434.     TCPiopb *pBlock;
  435.     
  436.     if ((err = NewBlock(&pBlock)) != noErr)
  437.         return err;
  438.     
  439.     pBlock->csCode = TCPStatus;
  440.     pBlock->ioResult = 1;
  441.     pBlock->tcpStream = streamPtr;
  442.     PBControl((ParmBlkPtr)pBlock,true);
  443.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  444.         ;
  445.     if (gCancel)
  446.         return -1;
  447.     theStatus = &(pBlock->csParam.status);
  448.     err = pBlock->ioResult;
  449.     MyDisposPtr((Ptr)pBlock);
  450.     return err;
  451. }
  452.  
  453.  
  454. /* Deallocates internal buffers used to hold connection data. This should be
  455.    called after a connection has been closed. */
  456.  
  457. OSErr LowTCPRelease(StreamPtr streamPtr,Ptr *recvPtr,unsigned long *recvLen)
  458. {
  459.     OSErr err;
  460.     TCPiopb *pBlock;
  461.     
  462.     if ((err = NewBlock(&pBlock)) != noErr)
  463.         return err;
  464.     
  465.     pBlock->csCode = TCPRelease;
  466.     pBlock->ioResult = 1;
  467.     pBlock->tcpStream = streamPtr;
  468.     PBControl((ParmBlkPtr)pBlock,true);
  469.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  470.         ;
  471.     if (gCancel)
  472.         return -1;
  473.     *recvPtr = pBlock->csParam.create.rcvBuff;
  474.     *recvLen = pBlock->csParam.create.rcvBuffLen;
  475.     err = pBlock->ioResult;
  476.     MyDisposPtr((Ptr)pBlock);
  477.     return err;
  478. }
  479.  
  480. OSErr LowTCPGlobalInfo(Ptr *tcpParam,Ptr *tcpStat)
  481. {
  482.     OSErr err;
  483.     TCPiopb *pBlock;
  484.     
  485.     if ((err = NewBlock(&pBlock)) != noErr)
  486.         return err;
  487.     
  488.     pBlock->csCode = TCPGlobalInfo;
  489.     pBlock->ioResult = 1;
  490.     PBControl((ParmBlkPtr)pBlock,true);
  491.     while (pBlock->ioResult > 0 && GiveTime(cSleepTime))
  492.         ;
  493.     if (gCancel)
  494.         return -1;
  495.     *tcpParam = (Ptr) pBlock->csParam.globalInfo.tcpParamPtr;
  496.     *tcpStat = (Ptr) pBlock->csParam.globalInfo.tcpStatsPtr;
  497.     err = pBlock->ioResult;
  498.     MyDisposPtr((Ptr)pBlock);
  499.     return err;
  500. }
  501.  
  502.  
  503. /* Returns the IP address of the local computer. */
  504.  
  505. OSErr GetMyIP(ip_addr *ipnum)
  506. {
  507.     struct    IPParamBlock    *IPBlock;
  508.     OSErr    err;
  509.     
  510.     IPBlock = (struct IPParamBlock *)MyNewPtr(sizeof(struct IPParamBlock));
  511.     if (MyMemErr() != noErr)
  512.         return MyMemErr();
  513.     
  514.     IPBlock->ioResult = 1;
  515.     IPBlock->csCode = ipctlGetAddr;
  516.     IPBlock->ioCompletion = nil;
  517.     IPBlock->ioCRefNum = refNum;
  518.     PBControl((ParmBlkPtr)IPBlock,true);
  519.     while (IPBlock->ioResult > 0 && GiveTime(cSleepTime))
  520.         ;
  521.     if (gCancel)
  522.         return -1;
  523.     *ipnum = IPBlock->ourAddress;
  524.     err = IPBlock->ioResult;
  525.     MyDisposPtr((Ptr)IPBlock);
  526.     return err;
  527. }
  528.