home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / DropFTP / tcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-01  |  8.2 KB  |  344 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     tcp.c
  4.  
  5.     This module handle all the high-level calls to MacTCP.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "MacTCPCommonTypes.h"
  16. #include "TCPPB.h"
  17.  
  18. #include "glob.h"
  19. #include "tcp.h"
  20. #include "tcplow.h"
  21. #include "util.h"
  22.  
  23.  
  24. #ifndef MAX_WDS
  25. #define MAX_WDS        6
  26. #endif
  27.  
  28.  
  29. /* InitNetwork opens the network driver. */
  30.  
  31. OSErr InitNetwork (void)
  32. {
  33.     return OpenTCPDriver();
  34. }
  35.  
  36.  
  37. /* CreateStream() creates an unconnected network stream to be
  38.    used later by OpenConnection.  The length of the receive
  39.    buffer must be specified in the call. */
  40.    
  41. OSErr CreateStream (unsigned long *stream, unsigned long recvLen)
  42. {
  43.     Ptr recvPtr;
  44.     OSErr err;
  45.     
  46.     recvPtr = MyNewPtr(recvLen);
  47.     if ((err = MyMemErr())==noErr)
  48.         err = LowTCPCreateStream(stream,recvPtr,recvLen,(TCPNotifyProc)nil);
  49.     return err;
  50. }
  51.     
  52.  
  53. /* ReleaseStream() frees the allocated buffer space for a given connection
  54.    stream.  This call should be made after CloseConnection. */
  55.    
  56. OSErr ReleaseStream (unsigned long stream)
  57. {
  58.     OSErr err;
  59.     Ptr recvPtr;
  60.     unsigned long recvLen;
  61.     
  62.     if ((err = LowTCPRelease(stream,&recvPtr,&recvLen)) == noErr)
  63.         MyDisposPtr(recvPtr);
  64.     return err;
  65. }
  66.  
  67.  
  68. /* OpenConnection() initiates a connection to a remote machine,
  69.    given that machine's network number and connection port.  A timeout
  70.    value for the call must be given, and the stream identifier is returned. */
  71.  
  72. OSErr OpenConnection (unsigned long stream, long remoteHost, short remotePort,
  73.     Byte timeout)
  74. {
  75.     ip_addr localHost;
  76.     tcp_port localPort = 0;
  77.     
  78.     return LowTCPOpenConnection(stream,timeout,remoteHost,remotePort,&localHost,
  79.                                 &localPort);
  80. }
  81.  
  82.  
  83. /* WaitForConnection() listens for a connection on a particular port from a
  84.     particular host.  It returns when a connection has been established. */
  85.  
  86. OSErr WaitForConnection (unsigned long stream, Byte timeout, short localPort,
  87.                         long *remoteHost, short *remotePort)
  88. {
  89.     ip_addr localHost;
  90.     
  91.     return LowTCPWaitForConnection(stream,timeout,(ip_addr *)remoteHost,
  92.                 (tcp_port *)remotePort,&localHost,(tcp_port *)&localPort,false,nil);
  93. }
  94.  
  95.  
  96. /*    AsyncWaitForConnection() listens for a connection on a particular port from a
  97.     particular host.  It is executed asynchronously and returns immediately */
  98.  
  99. OSErr AsyncWaitForConnection (unsigned long stream, Byte timeout,
  100.     short localPort, long remoteHost, short remotePort, TCPiopb **returnBlock)
  101. {
  102.     ip_addr localHost;
  103.     
  104.     return LowTCPWaitForConnection(stream,timeout,(ip_addr *)&remoteHost,
  105.                 (tcp_port *)&remotePort,&localHost,(tcp_port *)&localPort,true,returnBlock);
  106. }
  107.  
  108.  
  109. /*    AsyncGetConnectionData() should be called when a call to AsyncWaitForConnection
  110.     completes (when returnBlock->ioResult <= 0).  This call retrieves the information
  111.     about this new connection and disposes the parameter block. */
  112.     
  113. OSErr AsyncGetConnectionData (TCPiopb *returnBlock, long *remoteHost,
  114.     short *remotePort)
  115. {
  116.     ip_addr localHost;
  117.     tcp_port localPort;
  118.     
  119.     return LowFinishTCPWaitForConn(returnBlock,(ip_addr *)remoteHost,
  120.                         (tcp_port *)remotePort,&localHost,&localPort);
  121. }
  122.  
  123.  
  124. /*     IsAUX is a helper function used by CloseConnection to figure out whether 
  125.     we are running under A/UX. */
  126.     
  127. static Boolean IsAUX (void)
  128. {
  129.     return ((*(short*)0xB22) & (1<<9)) != 0;
  130. }
  131.  
  132.  
  133. /* CloseConnection() terminates a connection to a remote host, given the
  134.    stream identifier of the connection. It waits for the remote host to also
  135.    close its end of the connection. */
  136.    
  137. OSErr CloseConnection (unsigned long stream, Boolean waitForOtherSideToCloseFirst)
  138. {
  139.     unsigned short length;
  140.     CStr255 data;
  141.     OSErr err;
  142.     
  143.     if (IsAUX()) {
  144.         err = LowTCPClose(stream, 10);
  145.         err = LowTCPClose(stream, 10);
  146.         if (err != noErr && err != connectionDoesntExist &&
  147.             err != connectionClosing && err != connectionTerminated) goto exit;
  148.         return noErr;
  149.     }
  150.     
  151.     if (!waitForOtherSideToCloseFirst) {
  152.         err = LowTCPClose(stream, 10);
  153.         if (err != noErr && err != connectionDoesntExist &&
  154.             err != connectionClosing && err != connectionTerminated) goto exit;
  155.     }
  156.  
  157.     while (true) {
  158.         length = 256;
  159.         err = RecvData(stream, data, &length, true);
  160.         if (err != noErr) break;
  161.     }
  162.     
  163.     if (waitForOtherSideToCloseFirst) {
  164.         err = LowTCPClose(stream, 10);
  165.         if (err != noErr) goto exit;
  166.     }
  167.     
  168.     return noErr;
  169.  
  170. exit:
  171.  
  172.     AbortConnection(stream);
  173.     return err;
  174. }
  175.  
  176.  
  177. /* AbortConnection() aborts a connection to a remote host, given the
  178.    stream identifier of the connection */
  179.    
  180. OSErr AbortConnection (unsigned long stream)
  181. {
  182.     return LowTCPAbort(stream);
  183. }
  184.  
  185.  
  186. /* SendData() sends data along a connection stream to a remote host. */
  187.  
  188. OSErr SendData (unsigned long stream, Ptr data, unsigned short length)
  189. {    
  190.     struct wdsEntry myWDS[2];    /* global write data structure */
  191.  
  192.     myWDS[0].length = length;
  193.     myWDS[0].ptr = data;
  194.     myWDS[1].length = 0;
  195.     myWDS[1].ptr = nil;
  196.     return LowTCPSendData(stream,120,false,false,(Ptr) myWDS,false,nil);
  197. }
  198.  
  199. /* SendMultiData() is similar to SendData, but takes an array of strings to send
  200.    to the remote host. 
  201.  
  202.     A/UX versions previous to and including 3.0b15 have a fixed limit of
  203.     6 WDS segments per TCPSend.
  204.     So we enforce that limit since folks using SendMultiData may want
  205.     to send more than 6 chucks of data.
  206. */
  207.  
  208. OSErr SendMultiData (unsigned long stream, CStr255 data[], short numData)
  209. {
  210.     struct wdsEntry theWDS[MAX_WDS+1];
  211.     short i = 0, j, numToSend;
  212.     OSErr err = noErr;
  213.  
  214.     while (numData > 0 && err == noErr) {
  215.         numToSend = (numData > MAX_WDS) ? MAX_WDS : numData;
  216.         for (j=0; j < numToSend; i++,j++) {
  217.             theWDS[j].ptr = (Ptr)data[i];
  218.             theWDS[j].length = strlen((Ptr)data[i]);
  219.         }
  220.         theWDS[numToSend].ptr = nil;
  221.         theWDS[numToSend].length = 0;
  222.         err = LowTCPSendData(stream,120,false,false,(Ptr)theWDS,false,nil);
  223.         numData -= numToSend;
  224.     }
  225.  
  226.     return err;
  227. }
  228.  
  229.  
  230. /* RecvData() waits for data to be received on a connection stream.  When data
  231.    arrives, it is copied into the data buffer and the call terminates. */
  232.  
  233. OSErr RecvData (unsigned long stream, Ptr data, unsigned short *length,
  234.     Boolean retry)
  235. {
  236.     Boolean    urgent,mark;
  237.     OSErr    err;
  238.     unsigned short recvLength;
  239.  
  240.     do {
  241.         recvLength = *length-1;
  242.         err = LowTCPRecvData(stream,40,&urgent,&mark,data,&recvLength,false,nil);
  243.     }
  244.     while (retry && err==commandTimeout);
  245.     *length = recvLength;
  246.     if (err == noErr) *(data+*length) = 0;
  247.     return err;
  248. }
  249.  
  250.  
  251. /*    GetConnectionState gets the connection state of a stream. */
  252.  
  253. OSErr GetConnectionState (unsigned long stream, byte *state)
  254. {
  255.     TCPStatusPB theStatus;
  256.     OSErr err;
  257.     
  258.     err = LowTCPStatus(stream,&theStatus);
  259.     if (err == connectionDoesntExist) {
  260.         *state = 0;
  261.         return noErr;
  262.     }
  263.     *state = theStatus.connectionState;
  264.     return err;
  265. }
  266.  
  267.  
  268. /*    IPNameToAddr invokes the domain name system to translate a domain name
  269.     into an IP address. */
  270.     
  271. OSErr IPNameToAddr (char *name, unsigned long *addr)
  272. {
  273.     OSErr err;
  274.     short i;
  275.     static struct {
  276.         CStr255 name;
  277.         unsigned long addr;
  278.     } cache[10];
  279.     static short numCache=0;
  280.     
  281.     for (i=0; i<numCache; i++) {
  282.         if (strcmp(name, cache[i].name) == 0) {
  283.             *addr = cache[i].addr;
  284.             return noErr;
  285.         }
  286.     }
  287.     if ((err = LowIPNameToAddr(name, addr)) != noErr) return err;
  288.     if (numCache < 10) {
  289.         strcpy(cache[numCache].name, name);
  290.         cache[numCache].addr = *addr;
  291.         numCache++;
  292.     }
  293.     return noErr;
  294. }
  295.  
  296.  
  297. /*    IPAddrToName invokes the domain name system to translate an IP address
  298.     into a domain name. */
  299.     
  300. OSErr IPAddrToName (unsigned long addr, char *name)
  301. {
  302.     return LowIPAddrToName(addr, name);
  303. }
  304.  
  305.  
  306. /*    GetMyIPAddr returns the IP address of this Mac. */
  307.  
  308. OSErr GetMyIPAddr (unsigned long *addr)
  309. {
  310.     return LowGetMyIPAddr(addr);
  311. }
  312.  
  313.  
  314. /*    GetMyIPAddrStr returns the IP address of this Mac as a dotted decimal
  315.     string. */
  316.     
  317. OSErr GetMyIPAddrStr (char *addrStr)
  318. {
  319.     return LowGetMyIPAddrStr(addrStr);
  320. }
  321.  
  322.  
  323. /*    GetMyIPName returns the domain name of this Mac. */
  324.  
  325. OSErr GetMyIPName (char *name)
  326. {
  327.     unsigned long addr;
  328.     short len;
  329.     static OSErr err;
  330.     static Boolean gotIt=false;
  331.     static CStr255 theName;
  332.     
  333.     if (!gotIt) {
  334.         if ((err = LowGetMyIPAddr(&addr)) != noErr) return err;
  335.         err = LowIPAddrToName(addr,theName);
  336.         gotIt = true;
  337.         len = strlen(theName);
  338.         if (theName[len-1] == '.') theName[len-1] = 0;
  339.     }
  340.     if (err != noErr) return err;
  341.     strcpy(name,theName);
  342.     return noErr;
  343. }
  344.