home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / clintsrc.sit / DAtcp.c < prev    next >
Text File  |  1990-02-13  |  14KB  |  598 lines

  1. /*========================================================================
  2. ===  DAtcp.c
  3. ===
  4. ===  Greg Anderson
  5. ===  29 Kerr Hall
  6. ===  Social Sciences Computing
  7. ===  University of California at Santa Cruz
  8. ===  Santa Cruz CA  95062
  9. ===
  10. ===  (408) 459-2658
  11. ===  sirkm@ssyx.ucsc.edu
  12. ===
  13. ===  TCP/IP portion of client DA.
  14. ===
  15. ========================================================================*/
  16. #include    <MacTCPCommontypes.h>
  17. #include    <TCPPB.h>
  18. #include    <AddressXlation.h>
  19.  
  20. #include    <types.h>
  21. #include    <osutils.h>
  22. #include    <memory.h>
  23. #include    <devices.h>
  24. #include    <events.h>
  25. #include    <quickdraw.h>
  26. #include    <fonts.h>
  27. #include    <windows.h>
  28. #include    <files.h>
  29. #include    <errors.h>
  30. #include    <toolutils.h>
  31. #include    <packages.h>
  32.  
  33. #include    <Limits.h>
  34. #include    <Controls.h>
  35. #include    <TextEdit.h>
  36. #include    <Dialogs.h>
  37. #include    <Desk.h>
  38. #include    <Scrap.h>
  39. #include    <Traps.h>
  40. #include    <Lists.h>
  41. #include    <Resources.h>
  42.  
  43.  
  44. #include    "unixDA.h"
  45. #include    "DA.h"
  46.  
  47.  
  48. void        itoa(int var,char **str);
  49. void        myAddrToStr(long a, char *str);
  50.  
  51. /*----------------------------------------------------------------------
  52. |  Translate a TCP error code into an index into the str# resource
  53. ----------------------------------------------------------------------*/
  54. short getTCPErrorStr(OSErr err)
  55. {
  56.     if( err == connectionClosing )        return(eClosing);
  57.     if( err == connectionExists )        return(eConExists);
  58.     if( err == connectionDoesntExist )    return(eConNoExist);
  59.     if( err == connectionTerminated )    return(eConTerm);
  60.     if( err == invalidStreamPtr )        return(eBadStream);
  61.     if( err == streamAlreadyOpen )        return(eStreamOpen);
  62.     if( err == openFailed )                return(eBadOpen);
  63.     if( err == commandTimeout )            return(eTimeOut);
  64.     if( err == duplicateSocket )        return(eSocUsed);
  65.     if( err == ipDestDeadErr)            return(eDestDead);
  66.  
  67.     return(eUnknownErr);
  68. }
  69.  
  70. #define add_dot(str)    *str++ = '.'; *str = 0;
  71. #define add_cr(str)        *str++ = '\n'; *str = 0;
  72.  
  73. /*----------------------------------------------------------------------
  74. |  Integer to ascii--takes a var pointer, which is advanced as the
  75. |  integer is converted to a string.
  76. ----------------------------------------------------------------------*/
  77. void myItoa(int var,char **text)
  78. {
  79.     char    *str    = *text;
  80.     int        i,
  81.             m        = 1;
  82.     
  83.     if(var < 0)
  84.     {
  85.         var = -var;
  86.         *(str++) = '-';
  87.         ++(*text);
  88.     }
  89.     *str = 0;
  90.     
  91.     do
  92.     {
  93.         for(i=m;i>0;--i)
  94.             str[i] = str[i-1];
  95.         str[0] = '0' + (var % 10);
  96.         ++m;
  97.         ++(*text);
  98.         var /= 10;
  99.     } while(var);
  100. }
  101.  
  102. /*----------------------------------------------------------------------
  103. |  Convert an ascii number to an integer.
  104. ----------------------------------------------------------------------*/
  105. int myAtoI(char **str)
  106. {
  107.     char c;
  108.     int        result = 0;
  109.     
  110.     while( ((c = **str) >= '0') && (c <= '9') )
  111.     {
  112.         result = result * 10 + c - '0';
  113.         ++(*str);
  114.     }
  115.     ++(*str);
  116.     return( result );
  117. }
  118.  
  119. /*----------------------------------------------------------------------
  120. |  Convert an internet address to ascii.
  121. ----------------------------------------------------------------------*/
  122. void myAddrToStr(long inet_addr,char *str)
  123. {
  124.     int        a1 = (inet_addr >> 24) & 0xFF,
  125.             a2 = (inet_addr >> 16) & 0xFF,
  126.             a3 = (inet_addr >>  8) & 0xFF,
  127.             a4 = (inet_addr      ) & 0xFF;
  128.     
  129.     myItoa(a1,&str);
  130.     add_dot(str);
  131.     myItoa(a2,&str);
  132.     add_dot(str);
  133.     myItoa(a3,&str);
  134.     add_dot(str);
  135.     myItoa(a4,&str);
  136. }
  137.  
  138. /*----------------------------------------------------------------------
  139. |  Convert an ascii dot-notation internet address to a long address.
  140. ----------------------------------------------------------------------*/
  141. void myStrToAddr(char *lookupName,long *inet_addr)
  142. {
  143.     char    *str = lookupName;
  144.     int        a1,
  145.             a2,
  146.             a3,
  147.             a4;
  148.     
  149.     a1 = myAtoI(&str);
  150.     a2 = myAtoI(&str);
  151.     a3 = myAtoI(&str);
  152.     a4 = myAtoI(&str);
  153.     
  154.     *inet_addr = (a1 << 24) + (a2 << 16) + (a3 << 8) + a4;
  155. }
  156.  
  157. void showBounds( DCtlPtr dCtl )
  158. {
  159.     Handle    knownHosts;
  160.     Rect    tempRect;
  161.     char    msg[80],
  162.             *str = msg;
  163.     
  164.     knownHosts = GetResource('STR#',DA_global->rsrcID+1 );
  165.     HLock(knownHosts);
  166.     addTEstring( dCtl, *knownHosts+2 );
  167.     HUnlock(knownHosts);
  168.     
  169. /*    
  170.     extern void getScreenRect( Rect *r );
  171.     
  172.     getScreenRect(&tempRect);
  173.     
  174.     myItoa(tempRect.left,&str);
  175.     add_dot(str);
  176.     myItoa(tempRect.top,&str);
  177.     add_dot(str);
  178.     myItoa(tempRect.right,&str);
  179.     add_dot(str);
  180.     myItoa(tempRect.bottom,&str);
  181.     
  182.     addTEstring( dCtl, msg);
  183. */
  184. }
  185.  
  186. void PutLongAtOffset(char *base,int offset,long data)
  187. {
  188.     long    *L_base;
  189.     
  190.     base += offset;
  191.     L_base = (long *)base;
  192.     *L_base = data;
  193. }
  194.  
  195. void PutWordAtOffset(char *base,int offset,short data)
  196. {
  197.     short    *W_base;
  198.     
  199.     base += offset;
  200.     W_base = (short *)base;
  201.     *W_base = data;
  202. }
  203.  
  204. void PutByteAtOffset(char *base,int offset,char data)
  205. {
  206.     base[offset] = data;
  207. }
  208.  
  209. long GetLongAtOffset(char *base,int offset)
  210. {
  211.     long    *L_base;
  212.     
  213.     base += offset;
  214.     L_base = (long *)base;
  215.     return( *L_base );
  216. }
  217.  
  218. int GetWordAtOffset(char *base,int offset)
  219. {
  220.     short        *W_base;
  221.     
  222.     base += offset;
  223.     W_base = (short *)base;
  224.     return( *W_base );
  225. }
  226.  
  227. char GetByteAtOffset(char *base,int offset)
  228. {
  229.     return( base[offset] );
  230. }
  231.  
  232. /*----------------------------------------------------------------------
  233. |  Zero the PBcontrol structure parameter space.
  234. ----------------------------------------------------------------------*/
  235. ZeroIOParams(char *base)
  236. {
  237.     int i;
  238.     
  239.     for(i=32; i<TCPCTLSIZE; ++i)
  240.         PutByteAtOffset(base,i,0);
  241. }
  242.  
  243. /*----------------------------------------------------------------------
  244. |  Make a TCP stream
  245. ----------------------------------------------------------------------*/
  246. OSErr MakeTCPStream( DCtlPtr dCtl )
  247. {
  248.     OSErr            err        = noErr;
  249.     int i;
  250.     
  251.     /*
  252.      *  Get some memory for the TCP control
  253.      */
  254.     DA_tcp = (CntrlParam *)NewPtr(TCPCTLSIZE);
  255.     if( !DA_tcp )
  256.     {
  257.         alertUser( dCtl, eNoMemory );
  258.         return(-1);
  259.     }
  260.     /*
  261.      *  Zero the memory we were just given
  262.      */
  263.     for(i=0; i<TCPCTLSIZE; ++i)
  264.         PutByteAtOffset(DA_tcpB,i,0);
  265.     /*
  266.      *  Open TCP driver
  267.      */
  268.     text(etcpDRVR, DA_global);
  269.     if( (err = OpenDriver(DA_global->strBuf,&(DA_tcp->ioCRefNum) )) != noErr)
  270.     {
  271.         alertUser2( dCtl, eNoDRVR, getTCPErrorStr(err) );
  272.         return(err);
  273.     }
  274.     /*
  275.      *  Create a stream
  276.      */
  277.     DA_tcp->csCode        = TCPCreate;
  278.     PutLongAtOffset( DA_tcpB, 32, (long)( &(DA_global->tcpBuf)) );
  279.     PutLongAtOffset( DA_tcpB, 36, TCPBUFSIZE );
  280.     PutLongAtOffset( DA_tcpB, 40, 0L );
  281.     PutLongAtOffset( DA_tcpB, 44, (long)dCtl );
  282.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  283.     if( err != noErr )
  284.         alertUser2( dCtl, eBadCreate, getTCPErrorStr(err) );
  285.         
  286.     return(err);
  287. }
  288.  
  289. /*----------------------------------------------------------------------
  290. |  Kill a TCP stream, releasing its memory.
  291. ----------------------------------------------------------------------*/
  292. OSErr KillTCPStream( DCtlPtr dCtl )
  293. {
  294.     OSErr        err        = noErr;
  295.  
  296.     ZeroIOParams(DA_tcpB);
  297.     DA_tcp->csCode        = TCPRelease;
  298.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  299.     if( err != noErr )
  300.         alertUser2( dCtl, eBadKill, getTCPErrorStr(err) );
  301.     DisposPtr( (Ptr)DA_tcp);
  302.     DA_tcp = nil;
  303.  
  304.     DA_global->windButton    = eReconnectButton;
  305.     drawWInfo( dCtl );
  306.     
  307.     return(err);
  308. }
  309.  
  310. /*----------------------------------------------------------------------
  311. |  Open a TCP connection
  312. ----------------------------------------------------------------------*/
  313. OSErr ActiveOpen( DCtlPtr dCtl, long inet_addr, long port )
  314. {
  315.     OSErr        err        = noErr;
  316.  
  317.     DA_global->ignoreUntil = 0;
  318.     ZeroIOParams(DA_tcpB);
  319.     DA_tcp->csCode        = TCPActiveOpen;
  320.     /*
  321.      *  Time out value, in seconds:
  322.      */
  323.     PutByteAtOffset( DA_tcpB,32,1);
  324.     PutByteAtOffset( DA_tcpB,33,1);
  325.     PutByteAtOffset( DA_tcpB,34,0xC0);
  326.     PutLongAtOffset( DA_tcpB,36,inet_addr);
  327.     PutWordAtOffset( DA_tcpB,40,port);
  328.     PutWordAtOffset( DA_tcpB,46,0);
  329.     PutByteAtOffset( DA_tcpB,50,0);
  330.     PutByteAtOffset( DA_tcpB,51,0);
  331.     PutByteAtOffset( DA_tcpB,52,0);
  332.     PutByteAtOffset( DA_tcpB,53,0);
  333.     PutLongAtOffset( DA_tcpB,94,(long) dCtl);
  334.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  335.     if( err != noErr )
  336.         alertUser2( dCtl, eBadActiveOpen, getTCPErrorStr(err) );
  337.  
  338.     return(err);
  339. }
  340.  
  341. /*----------------------------------------------------------------------
  342. |  Close a TCP session
  343. ----------------------------------------------------------------------*/
  344. OSErr CloseTCP( DCtlPtr dCtl )
  345. {
  346.     OSErr        err        = noErr;
  347.  
  348.     DA_global->windButton    = eReconnectButton;
  349.     drawWInfo( dCtl );
  350.     
  351.     ZeroIOParams(DA_tcpB);
  352.     DA_tcp->csCode        = TCPClose;
  353.     /*
  354.      *  Time out, in seconds:
  355.      */
  356.     PutByteAtOffset( DA_tcpB,32, 2 );
  357.     PutByteAtOffset( DA_tcpB,33, 0 );
  358.     PutByteAtOffset( DA_tcpB,34, 0 );
  359.     /* PutLongAtOffset( DA_tcpB,35, (long) dCtl); */
  360.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  361.     if( err != noErr )
  362.         alertUser2( dCtl, eBadKill, getTCPErrorStr(err) );
  363.  
  364.     return(err);
  365. }
  366.  
  367. /*----------------------------------------------------------------------
  368. |  Return the status of a TCP connection & the number of unread bytes
  369. ----------------------------------------------------------------------*/
  370. OSErr StatusTCP( DCtlPtr dCtl, char *connection_state, short *unread_data )
  371. {
  372.     OSErr        err        = noErr;
  373.  
  374.     *connection_state = 0;
  375.     *unread_data = 0;
  376.     
  377.     if( DA_tcp == nil ) return( noErr );
  378.     
  379.     ZeroIOParams(DA_tcpB);
  380.     DA_tcp->csCode        = TCPStatus;
  381.     PutLongAtOffset( DA_tcpB,98, (long) dCtl);
  382.  
  383.     *unread_data = 0;
  384.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  385.     if( err != noErr )
  386.         return(err);
  387.  
  388.     *connection_state    = GetByteAtOffset(DA_tcpB,52);
  389.     *unread_data        = GetWordAtOffset(DA_tcpB,60);
  390.     
  391.     return(err);
  392. }
  393.  
  394. /*----------------------------------------------------------------------
  395. |  Return the state of a TCP connection
  396. ----------------------------------------------------------------------*/
  397. char connectionState( DCtlPtr dCtl )
  398. {
  399.     char    connection_state;
  400.     short    dummy;
  401.  
  402.     StatusTCP( dCtl, &connection_state, &dummy );
  403.     return(connection_state);
  404. }
  405.  
  406. /*----------------------------------------------------------------------
  407. |  Send data on a TCP stream
  408. ----------------------------------------------------------------------*/
  409. OSErr SendTCP( DCtlPtr dCtl, char *data)
  410. {
  411.     OSErr        err        = noErr;
  412.     char        WDS[32];
  413.     
  414.     if( !*data ) return(err);
  415.     
  416.     /*
  417.      *  Build a WDS
  418.      */
  419.     PutWordAtOffset(WDS, 0, strlen(data) );
  420.     PutLongAtOffset(WDS, 2, (long)(data) );
  421.     PutWordAtOffset(WDS, 6, 0 );
  422.     
  423.     ZeroIOParams(DA_tcpB);
  424.     DA_tcp->csCode        = TCPSend;
  425.     PutByteAtOffset( DA_tcpB,32, 30 );
  426.     PutByteAtOffset( DA_tcpB,33,  0 );
  427.     PutByteAtOffset( DA_tcpB,34,  0 );
  428.     PutByteAtOffset( DA_tcpB,35,  0 );
  429.     PutByteAtOffset( DA_tcpB,36,  0 );
  430.     PutLongAtOffset( DA_tcpB,38, (long) WDS );
  431.     PutLongAtOffset( DA_tcpB,48, (long) dCtl);
  432.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  433.     if( err != noErr )
  434.         alertUser2( dCtl, eBadSend, getTCPErrorStr(err) );
  435.  
  436.     return(err);
  437. }
  438.  
  439. /*----------------------------------------------------------------------
  440. |  Get data from a TCP connection
  441. ----------------------------------------------------------------------*/
  442. OSErr GetTCP( DCtlPtr dCtl, char *buf, int max )
  443. {
  444.     OSErr        err        = noErr;
  445.  
  446.     ZeroIOParams(DA_tcpB);
  447.     DA_tcp->csCode        = TCPRcv;
  448.     /*
  449.      *  Time out, in seconds:
  450.      */
  451.     PutByteAtOffset( DA_tcpB,32, 1 );
  452.     PutLongAtOffset( DA_tcpB,36, (long) buf );
  453.     PutWordAtOffset( DA_tcpB,40, max );
  454.     PutLongAtOffset( DA_tcpB,50, (long) dCtl);
  455.     err = PBControl( (ParmBlkPtr)DA_tcp, false );
  456.     if( (err != noErr) && (err != commandTimeout) )
  457.     {
  458.         alertUser2( dCtl, eBadGet, getTCPErrorStr(err) );
  459.         return(err);
  460.     }
  461.  
  462.     buf[ GetWordAtOffset(DA_tcpB,40) ] = 0;
  463.     return(err);
  464. }
  465.  
  466. /*----------------------------------------------------------------------
  467. |  Keep getting info until the other side closes the connection
  468. ----------------------------------------------------------------------*/
  469. OSErr GetUntilClosed( DCtlPtr dCtl, char *buf, int max )
  470. {
  471.     OSErr        err        = noErr;
  472.     short        avail;
  473.     char        state;
  474.     int            i;
  475.     
  476.     *buf = 0;
  477.     while( err == noErr )
  478.     {
  479.         err = StatusTCP( dCtl, &state, &avail );
  480.         if( state != 8 ) return( err );
  481.         if( avail )
  482.         {
  483.             i = strlen(buf);
  484.             err = GetTCP( dCtl, buf + i, max - i );
  485.         }
  486.     }
  487.     return( err );
  488. }
  489.  
  490. /*----------------------------------------------------------------------
  491. |  Get all outstanding TCP data & put it into the DA's window.
  492. ----------------------------------------------------------------------*/
  493. OSErr GetTCPtoWindow( DCtlPtr dCtl )
  494. {
  495.     #define    RCVBUFSIZE    2000
  496.     
  497.     OSErr        err        = noErr;
  498.     short        avail,
  499.                 more,
  500.                 rep = 0;
  501.     char        state,
  502.                 buf[RCVBUFSIZE+4],
  503.                 *bp;
  504.  
  505.     do
  506.     {
  507.         ++rep;
  508.         /*
  509.          *  Are there any characters available?
  510.          */
  511.         err = StatusTCP( dCtl, &state, &avail );
  512.         if( !avail ) return(err);
  513.         if( (more = (avail > RCVBUFSIZE)) )
  514.             avail = RCVBUFSIZE;
  515.         /*
  516.          *  Read them.
  517.          */
  518.         if( (err = GetTCP( dCtl, buf, avail )) != noErr )
  519.             return(err);
  520.         /*
  521.          *  Check if there's anything we want to skip.
  522.          */
  523.         bp = buf;
  524.         if( DA_global->ignoreUntil )
  525.         {
  526.             while( *bp != DA_global->ignoreUntil )
  527.             {
  528.                 if( !*bp ) return(noErr);
  529.                 ++bp;
  530.             }
  531.             DA_global->ignoreUntil = 0;
  532.             ++bp;
  533.             if( !*bp ) return(noErr);
  534.         }
  535.         addTEstring( dCtl, bp);
  536.     } while( more && (rep < 10) );
  537.     
  538.     return(err);
  539. }
  540.  
  541. /*----------------------------------------------------------------------
  542. |  Check the status of a TCP connection & handle periodic stuff
  543. ----------------------------------------------------------------------*/
  544. void checkTCP( DCtlPtr dCtl )
  545. {
  546.     OSErr        err        = noErr;
  547.     char        state;
  548.     short        avail;
  549.     
  550.     if( (err = StatusTCP( dCtl, &state, &avail )) == noErr )
  551.     {
  552.         changeMsg( dCtl, eStatClosed + (state >> 1) );
  553.  
  554.         /*
  555.          *  If the connection has closed, kill the stream.
  556.          */
  557.         if( !state || (state == 12) )
  558.         {
  559.             KillTCPStream( dCtl );
  560.         }
  561.         /*
  562.          *  If there is an established connection, read any bytes that
  563.          *  might be available.
  564.          */
  565.         if( (state >= 8) && (avail != 0) )
  566.             GetTCPtoWindow( dCtl );
  567.         /*
  568.          *  If there is no data waiting & the server has issued a close,
  569.          *  shut down our part of the connection too.
  570.          */
  571.         else if( state == 14 )
  572.         {
  573.             CloseTCP( dCtl );
  574.         }
  575.     }
  576.     else
  577.     {
  578.         changeMsg( dCtl, eStatClosed );
  579.     }
  580. }
  581.  
  582. /*----------------------------------------------------------------------
  583. |  Open a connection to the SuperServer & send the specified command
  584. ----------------------------------------------------------------------*/
  585. void connectToServer( DCtlPtr dCtl, long inet_addr, char *command )
  586. {
  587.     /* showBounds( dCtl ); */
  588.  
  589.     if( MakeTCPStream( dCtl ) == noErr)
  590.     {
  591.         if( ActiveOpen( dCtl, inet_addr, 3502 ) == noErr )
  592.         {
  593.             DA_global->ignoreUntil = '\r';
  594.             SendTCP( dCtl, command );
  595.         }
  596.     }
  597. }
  598.