home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks '96 / Internet Chooser / reggie / light / bsdsocks.cpp next >
Encoding:
C/C++ Source or Header  |  1996-06-21  |  10.8 KB  |  364 lines  |  [TEXT/MMCC]

  1. /* File "bsdsocks.cpp", Light Sockets - Copyright (C) Matt Slot, 1996         */
  2. /* BSD/UNIX sockets implementation for "Light Sockets" abstraction library.   */
  3.  
  4. #include <errno.h>
  5. #include <netdb.h>
  6. #include <netinet/in.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/time.h>
  11. #include <sys/types.h>
  12. #include <sys/socket.h>
  13. #include <time.h>
  14. #include <unistd.h>
  15.  
  16.  
  17. #include "stddebug.h"
  18. #include "stdtypes.h"
  19.  
  20. #include "bsdsocks.h"
  21.  
  22. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  23. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  24. /* Global/Static Data */
  25.  
  26.  
  27. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  28. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  29.  
  30. BSDSocketStack::BSDSocketStack(SocketRef socket) : NetworkStack(socket) {
  31.     theSocket = 0;
  32.     }
  33.  
  34. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  35. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  36.  
  37. BSDSocketStack::~BSDSocketStack() {
  38.     DoDispose();
  39.     }
  40.  
  41. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  42. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  43. #pragma mark -
  44.  
  45. SocketResult BSDSocketStack::DoLoad() {
  46.     SocketResult error = eSocketNoError;
  47.     
  48.     /* Implement socket callback chain */
  49.     qThrowIfError(NetworkStack::DoLoad(), 0);
  50.  
  51.     
  52. /* CATCH */
  53.     qCatch();
  54.     return(error);
  55.     }
  56.  
  57. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  58. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  59.  
  60. SocketResult BSDSocketStack::DoUnload() {
  61.     SocketResult error = eSocketNoError;
  62.     
  63.     /* Implement socket callback chain */
  64.     qThrowIfError(NetworkStack::DoUnload(), 0);
  65.     
  66. /* CATCH */
  67.     qCatch();
  68.     return(error);
  69.     }
  70.  
  71. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  72. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  73. #pragma mark -
  74.  
  75. SocketResult BSDSocketStack::DoCreate() {
  76.     SocketResult error = eSocketNoError;
  77.     
  78.     /* Implement socket callback chain */
  79.     qThrowIfError(NetworkStack::DoCreate(), 0);
  80.  
  81.     if (qIsSocketTypeUDP(socket->GetSocketType())) {
  82.         theSocket = ::socket(AF_INET, SOCK_DGRAM, 17);
  83.         qThrowIfTrue(theSocket < 0, errno, "Error creating socket");
  84.         }
  85.       else if (qIsSocketTypeRawIP(socket->GetSocketType())) {
  86.         qThrowErr(eSocketErrNoSupport, kSocketErrNoSupportStr);
  87.         }
  88.       else if (qIsSocketTypeTCP(socket->GetSocketType())) {
  89.         qThrowErr(eSocketErrNoSupport, kSocketErrNoSupportStr);
  90.         }
  91. //      else qThrowErr(eSocketErrBadParam, kSocketErrBadParamStr);
  92.  
  93.  
  94. /* CATCH */
  95.     qCatch();
  96.     
  97.     if (error) {
  98.         theSocket = 0;
  99.         DoDispose();
  100.         }
  101.         
  102.     return(error);
  103.     }
  104.  
  105. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  106. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  107.  
  108. SocketResult BSDSocketStack::DoTickle() {
  109.     SocketResult error = eSocketNoError;
  110.     fd_set read_fdset;
  111.     struct timeval timeout;
  112.     
  113.     /* Parameter validation */
  114.     qThrowIfNull(theSocket, eSocketErrBadParam, kSocketErrBadParamStr);
  115.  
  116.     /* Implement socket callback chain */
  117.     qThrowIfError(NetworkStack::DoTickle(), 0);
  118.  
  119.     /* Check for any incoming connection requests */
  120.     FD_ZERO(&read_fdset);
  121.     FD_SET(theSocket, &read_fdset);
  122.     timeout.tv_sec = 0; timeout.tv_usec = 0;
  123.     while(select(getdtablesize(), &read_fdset, 0, 0, &timeout) > 0) {
  124.  
  125.         if (FD_ISSET(theSocket, &read_fdset)) {
  126.             SocketAddress remoteAddr;
  127.             Int addrLen = sizeof(remoteAddr.buffer.tcpip);
  128.             Char8 buff[PING_BUFFER_SIZE];
  129.             SInt32 buffLen = sizeof(buff);
  130.             
  131.             buffLen = recvfrom(theSocket, buff, buffLen, 0, 
  132.                     &remoteAddr.buffer.tcpip, &addrLen);
  133.             if (buffLen < 0) qTraceIfError(buffLen, "Error reading packet")
  134.             
  135.             remoteAddr.type = eSocketTypeUDP;
  136.             remoteAddr.length = sizeof(remoteAddr.buffer.tcpip);
  137.             qTraceIfError(DatagramRead(buff, buffLen, &remoteAddr), 0);
  138.             }
  139.     
  140.         /* Try again */
  141.         FD_ZERO(&read_fdset);
  142.         FD_SET(theSocket, &read_fdset);
  143.         timeout.tv_sec = 0; timeout.tv_usec = 0;
  144.         }
  145.  
  146. /* CATCH */
  147.     qCatch();
  148.     return(error);
  149.     }
  150.  
  151. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  152. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  153.  
  154. SocketResult BSDSocketStack::DoDispose() {
  155.     SocketResult error = eSocketNoError;
  156.  
  157.     if (theSocket) {
  158.         if (qIsSocketTypeUDP(socket->GetSocketType())) {
  159.             close(theSocket);
  160.             theSocket = 0;
  161.             }
  162.           else if (qIsSocketTypeRawIP(socket->GetSocketType())) {
  163.             qThrowErr(eSocketErrNoSupport, kSocketErrNoSupportStr);
  164.             }
  165.           else if (qIsSocketTypeTCP(socket->GetSocketType())) {
  166.             qThrowErr(eSocketErrNoSupport, kSocketErrNoSupportStr);
  167.             }
  168.           else qThrowErr(eSocketErrBadParam, kSocketErrBadParamStr);
  169.         }
  170.  
  171.     /* Implement socket callback chain */
  172.     qTraceIfError(NetworkStack::DoDispose(), 0);
  173.  
  174. /* CATCH */
  175.     qCatch();
  176.     return(error);
  177.     }
  178.  
  179. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  180. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  181. #pragma mark -
  182.  
  183. SocketResult BSDSocketStack::DoBind(SocketAddressPtr reqAddress,
  184.         SocketAddressPtr retAddress) {
  185.     SocketResult error = eSocketNoError;
  186.     SocketAddress localAddr;
  187.     UInt16 savePort = 0;
  188.     
  189.     /* Parameter validation */
  190.     qThrowIfNull(theSocket, eSocketErrBadParam, kSocketErrBadParamStr);
  191.  
  192.     /* Implement socket callback chain */
  193.     qThrowIfError(NetworkStack::DoBind(reqAddress, retAddress), 0);
  194.  
  195.     if (reqAddress) {
  196.         qThrowIfTrue(bind(theSocket, &reqAddress->buffer.tcpip,
  197.             sizeof(reqAddress->buffer.tcpip))< 0, errno,"Error binding socket");
  198.         }
  199.       else {
  200.         localAddr.buffer.tcpip.type = AF_INET;
  201.         localAddr.buffer.tcpip.port = 0;
  202.         localAddr.buffer.tcpip.host = 0;
  203.         memset(localAddr.buffer.tcpip.data, 0,
  204.                 sizeof(localAddr.buffer.tcpip.data));
  205.  
  206.         qThrowIfTrue(bind(theSocket, &localAddr.buffer.tcpip,
  207.                 sizeof(localAddr.buffer.tcpip))<0,errno,"Error binding socket");
  208.         }
  209.     
  210.  
  211. /* CATCH */
  212.     qCatch();
  213.     return(error);
  214.     }
  215.  
  216. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  217. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  218.  
  219. SocketResult BSDSocketStack::DoUnbind(void) {
  220.     SocketResult error = eSocketNoError;
  221.  
  222.     /* Parameter validation */
  223.     qThrowIfNull(theSocket, eSocketErrBadParam, kSocketErrBadParamStr);
  224.  
  225.     /* Implement socket callback chain */
  226.     qThrowIfError(NetworkStack::DoUnbind(), 0);
  227.  
  228.  
  229. /* CATCH */
  230.     qCatch();
  231.     return(error);
  232.     }
  233.  
  234. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  235. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  236.  
  237. SocketResult BSDSocketStack::DoAddressResolve(Char8 *textAddress,
  238.         SocketAddressPtr socketAddress) {
  239.     SocketResult error = eSocketNoError;
  240.     struct hostent *hostInfo;
  241.     UInt32 host=0;
  242.     
  243.     /* Parameter validation */
  244.     qAssertIfNull(socketAddress, eSocketErrBadParam, kSocketErrBadParamStr);
  245.     qAssertIfNull(textAddress, eSocketErrBadParam, kSocketErrBadParamStr);
  246.     
  247.     if (hostInfo = gethostbyname(textAddress))
  248.         host = ** (UInt32 **) hostInfo->h_addr_list;
  249.       else if ((*textAddress >= '0') && (*textAddress <= '9')) {
  250.         UInt8 ipBytes[4];
  251.         UInt32 i;
  252.         Char8 *token, *dummy;
  253.         Char8 dottedBuff[ARBITRARY_BUFFER_SIZE];
  254.         
  255.         strcpy(dottedBuff, textAddress);
  256.         for(i=0, token = strtok(dottedBuff, "."); (i<4) && token;
  257.                 i++, token = strtok((Char8 *) NULL, "."))
  258.             ipBytes[i] = strtol(token, &dummy, 10);
  259.         
  260.         if (i==4)
  261.             memcpy(&host, ipBytes, sizeof(host));
  262.           else
  263.             qThrowErr(eSocketErrUnknown, kSocketErrUnknownStr);
  264.         }
  265.         
  266.     socketAddress->type = eSocketTypeUDP; /* For a guess */
  267.     socketAddress->length = sizeof(socketAddress->buffer.tcpip);
  268.     socketAddress->buffer.tcpip.type = AF_INET;
  269.     socketAddress->buffer.tcpip.port = 0;
  270.     socketAddress->buffer.tcpip.host = host;
  271.     memset(socketAddress->buffer.tcpip.data, 0, 
  272.             sizeof(socketAddress->buffer.tcpip.data));
  273.     
  274. /* CATCH */
  275.     qCatch();
  276.     return(error);
  277.     }
  278.  
  279. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  280. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  281.  
  282. SocketResult BSDSocketStack::DoAddressLookup(SocketAddressPtr socketAddress,
  283.         Char8 *textAddress) {
  284.     SocketResult error = eSocketNoError;
  285.     struct hostent *host_info;
  286.         
  287.     /* Parameter validation */
  288.     qAssertIfNull(socketAddress, eSocketErrBadParam, kSocketErrBadParamStr);
  289.     qAssertIfNull(textAddress, eSocketErrBadParam, kSocketErrBadParamStr);
  290.     
  291.     if (host_info = gethostbyaddr((Char8 *) &socketAddress->buffer.tcpip.host, 
  292.             sizeof(socketAddress->buffer.tcpip.host), AF_INET))
  293.         strcpy(textAddress, host_info->h_name);
  294.       else {
  295.         UInt8 ipBytes[4];
  296.  
  297.         memcpy(ipBytes, &socketAddress->buffer.tcpip.host, sizeof(ipBytes));
  298.         sprintf(textAddress, "%u.%u.%u.%u",
  299.                 (UInt) ipBytes[0], (UInt) ipBytes[1],
  300.                 (UInt) ipBytes[2], (UInt) ipBytes[3]);
  301.         }
  302.     
  303. /* CATCH */
  304.     qCatch();
  305.  
  306.     if (error && textAddress) *textAddress = 0;
  307.     return(error);
  308.     }
  309.  
  310. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  311. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  312. #pragma mark -
  313.  
  314. SocketResult BSDSocketStack::DoDatagramWrite(Byte8 *dataPtr, UInt32 dataLen,
  315.         SocketAddressPtr address) {
  316.     SocketResult error = eSocketNoError;
  317.     SInt32 result;
  318.  
  319.     /* Parameter validation */
  320.     qThrowIfNull(theSocket, eSocketErrBadParam, kSocketErrBadParamStr);
  321.  
  322.     result = sendto(theSocket, dataPtr, dataLen, 0, &address->buffer.tcpip,
  323.             sizeof(address->buffer.tcpip));
  324.     qThrowIfTrue(result < 0, errno, "Error writing packet");
  325.  
  326.     /* Implement socket callback chain */
  327.     qThrowIfError(NetworkStack::DoDatagramWrite(dataPtr, dataLen, address), 0);
  328.  
  329.  
  330. /* CATCH */
  331.     qCatch();
  332.     return(error);
  333.     }
  334.  
  335. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  336. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  337. #pragma mark -
  338.  
  339. SocketResult BSDSocketStack::DoStreamServer(UInt32 sessions) {
  340.     return(eSocketErrNoSupport); /* Function not supported yet */
  341.     }
  342.  
  343. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  344. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  345.  
  346. SocketResult BSDSocketStack::DoStreamClient(SocketAddressPtr address) {
  347.     return(eSocketErrNoSupport); /* Function not supported yet */
  348.     }
  349.  
  350. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  351. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  352.  
  353. SocketResult BSDSocketStack::DoStreamWrite(Byte8 *dataPtr, UInt32 dataLen) {
  354.     return(eSocketErrNoSupport); /* Function not supported yet */
  355.     }
  356.  
  357. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  358. /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  359.  
  360. SocketResult BSDSocketStack::DoStreamClose(Bool8 orderly) {
  361.     return(eSocketErrNoSupport); /* Function not supported yet */
  362.     }
  363.  
  364.