home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / MacMud / Sockets / socket.util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-17  |  6.8 KB  |  363 lines  |  [TEXT/MPS ]

  1. /*
  2.  *    A more or less BSD compatable socket library for MacTCP
  3.  *    
  4.  *    Summer 1989, Tom Milligan, University of Toronto Computing Services
  5.  */
  6.      
  7. #include <Events.h>
  8. #include <types.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11. #include <OSUtils.h> /* for SysBeep */
  12.  
  13. /* unixincludes */
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16. #include <sys/errno.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <sys/file.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/uio.h>
  22. #include <net/if.h>
  23.  
  24. #include "tcpglue.h"
  25. #include "socket.internal.h"
  26.  
  27. /*
  28.  * sock_init() - initialize everything.
  29.  */
  30. sock_init()
  31. {
  32.     OSErr io;
  33.     int i;
  34.     
  35.     if (sockets != NULL)
  36.         return;
  37.     
  38. #if SOCK_UTIL_DEBUG >= 2
  39.     dprintf("sock_init: first time through\n");
  40.     dprintf("sock_init: allocating %d bytes for %d socket records\n",
  41.             NUM_SOCKETS * sizeof(SocketRecord),NUM_SOCKETS);
  42. #endif
  43.  
  44.     /* allocate storage for socket records */
  45.     sockets = (SocketPtr)NewPtr(NUM_SOCKETS * sizeof(SocketRecord));
  46.     if (sockets == NULL)
  47.         return(sock_err(ENOMEM));
  48.     bzero(sockets, NUM_SOCKETS * sizeof(SocketRecord));
  49.     
  50.     /* initialize them */
  51.     for (i=0; i<NUM_SOCKETS; i++)
  52.     {
  53.         sock_clear_fd(i);
  54.     }
  55.     
  56.     /* load the MacTCP name server resolver */
  57. #if SOCK_UTIL_DEBUG >= 2
  58.     dprintf("sock_init: loading name server resolver\n");
  59. #endif
  60.  
  61.     io = OpenResolver(NULL);
  62.     
  63. #if SOCK_UTIL_DEBUG >= 1
  64.     if (io != noErr)
  65.         dprintf("sock_init: failed to load name server resolver code %d\n",io);
  66. #endif
  67. }
  68.  
  69. /*
  70.  * sock_close_all() - Close all sockets (aborting their connections) and
  71.  *                    release dynamic storage.
  72.  */
  73. sock_close_all()
  74. {
  75.     int s;
  76.     SocketPtr sp;
  77.  
  78.     for (s = 0 ; s < NUM_SOCKETS ; ++s) 
  79.     {
  80.         sp = &sockets[s];
  81.         if (sp->status == SOCK_STATUS_USED) 
  82.         {
  83.             switch(sp->protocol) 
  84.             {
  85.                 case IPPROTO_UDP:
  86.                     (void) xUDPRelease(&sp->pb);
  87.                     break;
  88.                     
  89.                 case IPPROTO_TCP:
  90.                     (void) xTCPRelease(&sp->pb.tcp);
  91.                     break;
  92.             }
  93.             sock_clear_fd(s);
  94.         }
  95.     }
  96.     DisposPtr((Ptr)sockets);
  97.     
  98.     /* release name server resources */
  99.     (void) CloseResolver();
  100. }
  101.  
  102. /*
  103.  *    sock_free_fd()
  104.  *
  105.  *    Get the next free file descriptor >= f.  Return -1 if none available.
  106.  */
  107. sock_free_fd(f)
  108.     int f;
  109. {
  110.     int s;
  111.  
  112.     for (s = f; s < NUM_SOCKETS; s++)
  113.           if (! is_used(&sockets[s]))
  114.             return(s);
  115.     return(-1);
  116. }
  117.  
  118. /*
  119.  *    sock_dup_fd() - duplicate a socket table entry.
  120.  */
  121. sock_dup_fd(s,s1)
  122. {
  123.     BlockMove((Ptr)&sockets[s], (Ptr)&sockets[s1], sizeof(SocketRecord));    
  124.     sock_init_fd(s1);
  125. }
  126.  
  127. /*
  128.  *    sock_clear_fd() - Clear out a socket table entry freeing any 
  129.  *                    storage attached to it.
  130.  *  
  131.  *                    Then re-initialize it for reuse.
  132.  */
  133. sock_clear_fd(s)
  134.     int s;
  135. {
  136.     SocketPtr sp = &sockets[s];
  137.     int i;
  138.     
  139.     for (i=0; i<TCP_MAX_WRITES; i++)
  140.     {
  141.         if (sp->wpb[i].wds[0].ptr != NULL)
  142.             DisposPtr(sp->wpb[i].wds[0].ptr);
  143.     }
  144.     bzero(sp, sizeof(SocketRecord));
  145.     sp->sa.sin_family = AF_UNSPEC;
  146.     sp->status &= ~SOCK_STATUS_USED;
  147.  
  148.     sock_init_fd(s);
  149. }
  150.  
  151. sock_init_fd(s)
  152.     int s;
  153. {
  154.     SocketPtr sp = &sockets[s];
  155.     int i;
  156.  
  157.     sp->fd = s;
  158.     sp->apb.sp = sp;
  159.     for (i=0; i<TCP_MAX_WRITES; i++)
  160.         sp->wpb[i].sp = sp;
  161. }
  162.  
  163.  
  164. /*
  165.  * sock_alloc_wds_buf() - allocate a new buffer if the old one is too
  166.  *                        small or if there isn't one yet
  167.  */
  168. static Ptr 
  169. sock_alloc_wds_buf(sp,len)
  170.     SocketPtr sp;
  171.     unsigned short len;
  172. {
  173.     if (sp->wpb[sp->nextwpb].wds[0].ptr != NULL)
  174.     {
  175.         if (GetPtrSize(sp->wpb[sp->nextwpb].wds[0].ptr) < len)
  176.         {
  177.             DisposPtr(sp->wpb[sp->nextwpb].wds[0].ptr);
  178.             sp->wpb[sp->nextwpb].wds[0].ptr = NULL;
  179.         }
  180.     }
  181.     if (sp->wpb[sp->nextwpb].wds[0].ptr == NULL)
  182.     {
  183.         len = max(len,536);
  184.         sp->wpb[sp->nextwpb].wds[0].ptr = NewPtr(len);
  185.         if (sp->wpb[sp->nextwpb].wds[0].ptr == nil)
  186.             return(NULL);
  187.     }
  188.     return(sp->wpb[sp->nextwpb].wds[0].ptr);
  189. }
  190.  
  191. /*
  192.  *  sock_buf_to_wds() - build a one-entry macTCP wds
  193.  */
  194. sock_buf_to_wds(sp, buffer, len)
  195.     SocketPtr sp;
  196.     char *buffer;
  197.     int len;
  198. {
  199.     if (!goodptr(buffer))
  200.         return(sock_err(EFAULT));
  201.     
  202.     switch(sp->protocol) 
  203.     {
  204.         case IPPROTO_UDP:
  205.             if (len <= 0 || len > UDP_MAX_MSG)
  206.                 return(sock_err(EINVAL));
  207.             break;
  208.  
  209.         case IPPROTO_TCP:
  210.             if (len <= 0 || len > TCP_MAX_MSG)
  211.                 return(sock_err(EINVAL));
  212.             break;
  213.     }
  214.  
  215.     if (sock_alloc_wds_buf(sp,len) == NULL)
  216.         return(sock_err(ENOMEM));
  217.  
  218.     BlockMove(buffer,sp->wpb[sp->nextwpb].wds[0].ptr,len);
  219.     sp->wpb[sp->nextwpb].wds[0].length = len;
  220.     sp->wpb[sp->nextwpb].wds[1].length = 0;
  221.     return(len);
  222. }
  223.  
  224. /*
  225.  *  sock_iov_to_wds() - mash an iov into a one-entry macTCP wds
  226.  */
  227. sock_iov_to_wds(sp,iov, count)
  228.     SocketPtr sp;
  229.     struct iovec *iov;
  230.     int count;
  231. {
  232.     int i;
  233.     struct iovec *v;
  234.     unsigned long len;
  235.     Ptr p;
  236.  
  237.     len = 0;
  238.     for (v=iov, i=0; i<count; i++, v++) 
  239.     {
  240.         if (!goodptr(v->iov_base))
  241.             return(sock_err(EFAULT));
  242.  
  243.         switch(sp->protocol) 
  244.         {
  245.             case IPPROTO_UDP:
  246.                 if (v->iov_len < 0 || v->iov_len > UDP_MAX_MSG)    
  247.                     return(sock_err(EINVAL));
  248.                 len += v->iov_len;
  249.                 if (len > UDP_MAX_MSG)    
  250.                     return(sock_err(EINVAL));
  251.                 break;
  252.     
  253.             case IPPROTO_TCP:
  254.                 if (v->iov_len < 0 || v->iov_len > TCP_MAX_MSG)    
  255.                     return(sock_err(EINVAL));
  256.                 len += v->iov_len;
  257.                 if (len > TCP_MAX_MSG)    
  258.                     return(sock_err(EINVAL));
  259.                 break;
  260.         }
  261.     }
  262.  
  263.     if (sock_alloc_wds_buf(sp,len) == NULL)
  264.         return(sock_err(ENOMEM));
  265.  
  266.     p = sp->wpb[sp->nextwpb].wds[0].ptr;
  267.     for (v=iov, i=0; i<count; i++, v++) 
  268.     {
  269.         BlockMove(v->iov_base,p,v->iov_len);
  270.         p += v->iov_len;
  271.     }
  272.     sp->wpb[sp->nextwpb].wds[0].length = len;
  273.     sp->wpb[sp->nextwpb].wds[1].length = 0;
  274.     return(len);
  275. }
  276.  
  277. /*
  278.  *    sock_err() - Socket error. Set errno and show debugging info.
  279.  */
  280. sock_err(err_code)
  281.     int err_code;
  282. {
  283.     errno = err_code;
  284. #if    SOCK_UTIL_DEBUG >= 1
  285.     dprintf("SOCK  error %d\n", errno);
  286. #endif
  287.     return(-1);
  288. }
  289.  
  290. /*
  291.  *  valid_file_ptr
  292.  *
  293.  * Make sure the file pointer "sp" points to one of the entrys in the
  294.  * socket table and that that entry is in use. 
  295.  * Return the file descriptor if valid, or -1 if invalid.
  296.  *
  297.  * dont print anything. this can be called from interrupt level.
  298.  */
  299. valid_file_ptr(sp)
  300.     SocketPtr sp;
  301. {
  302.     int s;
  303.  
  304.     for(s = 0; s < NUM_SOCKETS; s++) 
  305.     {
  306.         if (&sockets[s] == sp)  
  307.         {
  308.             if (is_used(sp))
  309.                 return(s);
  310.             else
  311.                 return(-1);
  312.         }
  313.     }
  314. }
  315.  
  316.  
  317. /*
  318.  *  sock_copy_addr
  319.  */
  320. sock_copy_addr(from,to,tolen)
  321.     struct sockaddr_in *from;
  322.     struct sockaddr_in *to;
  323.     int *tolen;
  324. {
  325.     *tolen = min(*tolen, sizeof(struct sockaddr_in));
  326.     BlockMove((Ptr)from, (Ptr)to, *tolen);
  327. }
  328.  
  329.  
  330. #if SOCK_UTIL_DEBUG > 1
  331. /*
  332.  * print the socket records.
  333.  */
  334. sock_dump()
  335. {
  336.     int s;
  337.     char title[20];
  338.  
  339.     for (s=0; s<NUM_SOCKETS; s++) 
  340.     {
  341.         if (! is_used(&sockets[s]))
  342.             continue;
  343.         sprintf(title,"%2d",s);
  344.         sock_print(title,&sockets[s]);
  345.     }
  346. }
  347.  
  348. sock_print(title,sp)
  349.     char *title;
  350.     SocketPtr sp;
  351. {
  352.     dprintf("%s: %08x %s %08x addr %08x/%d %08x/%d state %d/%d err %d\n",
  353.             title, sp, 
  354.             (sp->protocol == IPPROTO_UDP ? "udp" : "tcp"),
  355.             (sp->protocol == IPPROTO_UDP ? sp->pb.udp.udpStream : sp->pb.tcp.tcpStream),
  356.             sp->sa.sin_addr.s_addr,sp->sa.sin_port,
  357.             sp->peer.sin_addr.s_addr,sp->peer.sin_port,
  358.             sp->sstate,xTCPState(&sp->pb),
  359.             sp->asyncerr);
  360. }
  361. #endif 
  362.  
  363.