home *** CD-ROM | disk | FTP | other *** search
/ Mac Expert 1995 Winter / Mac Expert - Winter 95.iso / Les fichiers / Communications / Internet / TurboTCP 2.1 ƒ / TurboTCP core / CTCPDriver.cp < prev    next >
Encoding:
Text File  |  1995-01-19  |  10.0 KB  |  424 lines  |  [TEXT/MMCC]

  1. //
  2. // CTCPDriver.cp
  3. //
  4. //    TurboTCP library
  5. //    TCP driver interface class
  6. //
  7. //    Copyright © 1993-95, FrostByte Design / Eric Scouten
  8. //
  9.  
  10. #include "CTCPDriver.h"
  11.  
  12. #include "CTCPAsyncCall.h"
  13. #include "CTCPStream.h"
  14. #include "CTCPResolverCall.h"
  15.  
  16. #if TurboTCP_UH2
  17.     #include <MacTCP.h>
  18. #else
  19.     #include <GetMyIPAddr.h>
  20. #endif
  21.  
  22. #if TurboTCP_TCL
  23.     #include "CApplication.h"
  24.     #include "CBartender.h"
  25.     #include "CDLOGDirector.h"
  26.     #include "Global.h"
  27.     extern CApplication* gApplication;
  28.     extern CBartender*    gBartender;
  29. #endif
  30.  
  31.  
  32. //***********************************************************
  33. //
  34. // All routines are private interfaces for the use of TurboTCP classes ONLY!
  35. // They are subject to change in future versions. Be forewarned!
  36. //
  37. //***********************************************************
  38.  
  39.  
  40. //***********************************************************
  41. //
  42. // class variable for CTCP driver
  43. //
  44.  
  45. CTCPDriver*            CTCPDriver::gTCPDriver = nil;
  46.  
  47.  
  48. //***********************************************************
  49.  
  50. CTCPDriver::CTCPDriver()
  51.  
  52. {
  53.  
  54.     // clear variables
  55.     
  56.     hasMacTCP = false;
  57.     hasResolver = false;
  58.     activeResolverCount = myTCPRefNum = 0;
  59.     myIPAddress = 0L;
  60.     gTCPDriver = this;
  61.     activeStreamList.qHead = activeStreamList.qTail = nil;
  62.     activeResolverList.qHead = activeResolverList.qTail = nil;
  63.     asyncQueue.qHead = asyncQueue.qTail = nil;
  64.  
  65.     
  66.     // if on PowerPC, get completion procedure (which is 68K code)
  67.  
  68.     #if TurboTCP_PPC
  69.         CTCPAsyncCall::GetCompletionProc();
  70.     #endif
  71.  
  72. }
  73.  
  74.  
  75. //***********************************************************
  76.  
  77. void CTCPDriver::Dispose()
  78.  
  79.     // Dispose of this object and any lingering TCP async call objects or TCP stream objects.
  80.     // It is CRITICAL that any lingering TCP streams be closed, released, and disposed;
  81.     // otherwise MacTCP is *guaranteed* to crash the machine when the next app launches.
  82.     // If the resolver is open, wait until all resolver queries have been cancelled.
  83.  
  84.     // If at least one second elapses between the start of this routine and the end, flash a
  85.     // dialog box to indicate the reason for the delay.
  86.  
  87.     // The ‘Dispose’ method is retained in C++ because the driver object may need to
  88.     // delay its destruction.
  89.  
  90. {
  91.     unsigned long startTickCount;
  92.     
  93.     #if TurboTCP_TCL
  94.         CDLOGDirector* theDialog = nil;
  95.     #else
  96.         DialogPtr theDialog = nil;
  97.     #endif
  98.  
  99.     
  100.     // cancel outstanding DNR calls & close resolver
  101.     
  102.     if (hasResolver)
  103.         CTCPResolverCall::CloseResolver();
  104.  
  105.  
  106.     // kill any lingering streams
  107.  
  108.     while (activeStreamList.qHead) {
  109.         CTCPStream* theStream = (CTCPStream*) ((TurboTCPQElem*) activeStreamList.qHead)->qSelfLink;
  110.         theStream->PostponeDispose();
  111.     }
  112.  
  113.  
  114.     // wait for TCP to be done with everything
  115.     
  116.     ::GetDateTime(&startTickCount);
  117.     #if TurboTCP_TCL
  118.         gBartender->DisableMenuBar();                    // disable all menus
  119.     #endif
  120.     
  121.     while (activeStreamList.qHead) {
  122.  
  123.         unsigned long theTime;
  124.  
  125.         // do a private event loop & toss up a dialog if it takes more than 2 seconds
  126.         
  127.         ::GetDateTime(&theTime);
  128.         if ((theDialog == nil) && (theTime - startTickCount >= 2)) {
  129.             #if TurboTCP_TCL
  130.                 theDialog = new CDLOGDirector(DLOG_TCPDelayedQuit, gApplication);
  131.                 theDialog->BeginDialog();
  132.             #else    
  133.                 theDialog = (DialogPtr) ::GetNewDialog(DLOG_TCPDelayedQuit, nil, (WindowRef) -1);
  134.                 ::DrawDialog(theDialog);
  135.             #endif
  136.         }
  137.  
  138.                 
  139.         // wait for TCP completions & terminations
  140.         
  141.         #if TurboTCP_TCL
  142.             gApplication->Process1Event();
  143.         #else
  144.             ::SystemTask();            //? should we use WaitNextEvent instead?
  145.         #endif
  146.  
  147.     }
  148.     
  149.     
  150.     // get rid of dialog box (if there was one)
  151.  
  152.     #if TurboTCP_TCL
  153.         TCLForgetObject(theDialog);
  154.     #else
  155.         if (theDialog)
  156.             ::DisposeDialog(theDialog);
  157.     #endif
  158.  
  159.     
  160.     // dispose all the objects
  161.     
  162.     delete this;
  163.  
  164. }
  165.  
  166.  
  167. // -- event handling --
  168.  
  169. //***********************************************************
  170.  
  171. Boolean CTCPDriver::ProcessOneNetEvent()
  172.  
  173.     // Respond to all delayed TCP notifications, completions, disposals. This routine should be
  174.     // hooked into the application’s event loop or some very frequently called routine.
  175.     // Returns true if there are more asynchronous events in the queue.
  176.  
  177. {
  178.     void*            theAsyncObject;
  179.     TurboTCPQElem*    theAsyncEntry;
  180.     CTCPAsyncCall*    theAsyncCall;
  181.     CTCPResolverCall*    theResolverCall;
  182.     CTCPStream*        theStream;
  183.     
  184.     
  185.     // if no events, quit now
  186.  
  187.     if (asyncQueue.qHead == nil)
  188.         return false;
  189.  
  190.  
  191.     // figure out what object caused the notification
  192.  
  193.     theAsyncEntry = (TurboTCPQElem*) asyncQueue.qHead;
  194.     theAsyncObject = theAsyncEntry->qSelfLink;
  195.  
  196.  
  197.     // remove it from the queue (just in case the event processing fails)
  198.     
  199.     ::Dequeue((QElemPtr) theAsyncEntry, &asyncQueue);
  200.     
  201.     
  202.     // process the event
  203.  
  204.     switch (theAsyncEntry->qType) {
  205.         case asyncCall:
  206.             theAsyncCall = (CTCPAsyncCall*) theAsyncObject;
  207.             if (theAsyncCall)
  208.                 theAsyncCall ->ProcessCompletion();
  209.             break;
  210.         case resolverCall:
  211.             theResolverCall = (CTCPResolverCall*) theAsyncObject;
  212.             if (theResolverCall)
  213.                 theResolverCall->ProcessNotify();
  214.             break;
  215.         case notifyStream:
  216.             theStream = (CTCPStream*) theAsyncObject;
  217.             if (theStream)
  218.                 theStream->ProcessNotify();
  219.             break;
  220.         case disposeStream:
  221.             theStream = (CTCPStream*) theAsyncObject;
  222.             if (theStream)
  223.                 theStream->Dispose();
  224.             break;
  225.  
  226.     }    // switch
  227.  
  228.     
  229.     // tell caller whether there’s another call
  230.     
  231.     return asyncQueue.qHead != nil;
  232.  
  233. }
  234.  
  235.  
  236. // -- TCP verification routines --
  237.  
  238. //***********************************************************
  239.  
  240. ip_addr CTCPDriver::GetIPAddr()                    // static method
  241.  
  242.     // Returns the current local IP address, if available. Fails with “noTCPError” error if
  243.     // MacTCP is not installed.
  244.  
  245. {
  246.     if (!(gTCPDriver->hasMacTCP))
  247.         ThrowOSErr_(noTCPError);
  248.     return gTCPDriver->myIPAddress;
  249. }
  250.  
  251.  
  252. //***********************************************************
  253.  
  254. Boolean CTCPDriver::CheckTCPDriver()
  255.  
  256.     // Check to see if the MacTCP driver is present. Should be done before opening each new
  257.     // connection (built into CTCPStream). If TCP driver is present, updates the current IP
  258.     // address.
  259.     
  260.     // Return true if MacTCP driver is present.
  261.  
  262. {
  263.     ParamBlockRec        theParamBlock;
  264.     unsigned char    theName[6] = "\p.IPP";        // MacTCP driver name
  265.  
  266.  
  267.     // if TCP not already confirmed, look for it
  268.     
  269.     if (!hasMacTCP) {
  270.         theParamBlock.ioParam.ioNamePtr = (StringPtr) &theName;
  271.         theParamBlock.ioParam.ioPermssn = fsCurPerm;
  272.         if ((short) ::PBOpenSync(&theParamBlock) == 0) {
  273.             myTCPRefNum = theParamBlock.ioParam.ioRefNum;
  274.             hasMacTCP = true;
  275.         }
  276.     }
  277.  
  278.  
  279.     // If TCP driver available, get the IP address. This is done *each* time a new stream
  280.     // is created because the address might have changed. (This could happen on a machine
  281.     // connected by modem & SLIP, if the user hangs up the modem and re-dials the
  282.     // SLIP server without quitting the program.)
  283.     
  284.     FetchIPAddr();
  285.     return hasMacTCP;
  286.  
  287. }
  288.  
  289.  
  290. //***********************************************************
  291.  
  292. Boolean CTCPDriver::CheckResolver()
  293.  
  294.     // Check to see if the MacTCP DNR code segment is available. If it isn’t, use the
  295.     // OpenResolver call to make it available.
  296.  
  297.     // Returns true if TCP resolver is present.
  298.  
  299. {
  300.  
  301.     Try_ {
  302.         CTCPResolverCall::OpenResolver();
  303.         hasResolver = true;
  304.     }
  305.     Catch_(err) {
  306.         hasResolver = false;
  307.         DontThrowSame_;
  308.     }
  309.     EndCatch_;
  310.     return hasResolver;
  311.  
  312. }
  313.  
  314.  
  315. //***********************************************************
  316.  
  317. short CTCPDriver::GetTCPRefNum()
  318.  
  319.     // Returns the Device Manager reference number for MacTCP, if available.
  320.     // Fails with “noTCPError” error if not available.
  321.  
  322. {
  323.     if (!(gTCPDriver->hasMacTCP))
  324.         ThrowOSErr_(noTCPError);
  325.     return gTCPDriver->myTCPRefNum;
  326. }
  327.  
  328.  
  329. //***********************************************************
  330.  
  331. void CTCPDriver::FetchIPAddr()
  332.  
  333.     // Retrieve the local host’s IP address. Does nothing if MacTCP is not available.
  334.     // Stores the new address in the local field myIPAddress, which can be retrieved
  335.     // with the GetIPAddr() method.
  336.  
  337. {
  338.     struct GetAddrParamBlock theIPParamBlock;
  339.  
  340.     myIPAddress = 0L;
  341.  
  342.     if (hasMacTCP) {
  343.         theIPParamBlock.csCode = ipctlGetAddr;
  344.         theIPParamBlock.ioCRefNum = myTCPRefNum;
  345.         ::PBControlSync((ParmBlkPtr) &theIPParamBlock);
  346.         if (theIPParamBlock.ioResult == noErr)
  347.             myIPAddress = theIPParamBlock.ourAddress;
  348.     }
  349. }
  350.  
  351.  
  352. // -- tracking active streams/resolvers --
  353.  
  354. //***********************************************************
  355.  
  356. void CTCPDriver::RegisterActiveStream
  357.     (CTCPStream* theStream)                    // the new stream
  358.  
  359.     // Add a stream object to the list of active TCP streams. The driver object uses this
  360.     // information to ensure that all streams are closed and terminated before the
  361.     // application quits.
  362.  
  363. {
  364.     ::Enqueue((QElemPtr) &theStream->qActiveStreamEntry, &activeStreamList);
  365. //    activeStreamList->Append(theStream);
  366. }
  367.  
  368.  
  369. //***********************************************************
  370.  
  371. void CTCPDriver::RegisterActiveResolver
  372.     (CTCPResolverCall* theResolver)                // the new resolver call
  373.  
  374.     // Add a DNR resolver call to the list of active calls. The driver object uses this
  375.     // information to ensure that all resolver calls are closed and terminated before the
  376.     // application quits.
  377.  
  378. {
  379.     if (CheckResolverLimit())                        // disallow 9th DNR call
  380.         ThrowOSErr_(resolverBusy);
  381.     ::Enqueue((QElemPtr) &theResolver->activeResListEntry, &activeResolverList);
  382.     activeResolverCount++;
  383. }
  384.  
  385.  
  386. //***********************************************************
  387.  
  388. void CTCPDriver::RemoveActiveStream
  389.     (CTCPStream* theStream)                    // the stream to remove
  390.  
  391.     // Remove a TCP stream from the list of active TCP streams. This message
  392.     // indicates that MacTCP is no longer dependent on the memory structure for
  393.     // the stream.
  394.  
  395. {
  396.     ::Dequeue((QElemPtr) &theStream->qActiveStreamEntry, &activeStreamList);
  397. }
  398.  
  399.  
  400. //***********************************************************
  401.  
  402. void CTCPDriver::RemoveActiveResolver
  403.     (CTCPResolverCall* theResolver)                    // the call to remove
  404.  
  405.     // Remove a DNR resolver call from the list of active calls. This message indicates that
  406.     // the MacTCP DNR is no longer dependent on the memory structure for the call.
  407.  
  408. {
  409.     ::Dequeue((QElemPtr) &theResolver->activeResListEntry, &activeResolverList);
  410.     activeResolverCount--;
  411. }
  412.  
  413.  
  414. //***********************************************************
  415.  
  416. Boolean CTCPDriver::CheckResolverLimit()
  417.  
  418.     // Ensure that the DNR’s limit of 8 calls is not violated.
  419.     // Returns true if too many calls have been issued.
  420.  
  421. {
  422.     return activeResolverCount >= maxResolverCalls;
  423. }
  424.