home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / udpsock.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  4KB  |  189 lines

  1. #include "global.h"
  2. #include "udp.h"
  3. #include "socket.h"
  4. #include "usock.h"
  5.  
  6. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  7. static void autobind __ARGS((struct usock *up));
  8. static int checkipaddr __ARGS((char *name,int namelen));
  9.  
  10. int
  11. so_udp(up,protocol)
  12. struct usock *up;
  13. int protocol;
  14. {
  15.     return 0;
  16. }
  17. int
  18. so_udp_bind(up)
  19. struct usock *up;
  20. {
  21.     int s;
  22.     struct sockaddr_in *sp;
  23.     struct socket lsock;
  24.  
  25.     s = up - Usock + SOCKBASE;
  26.     sp = (struct sockaddr_in *)up->name;
  27.     lsock.address = sp->sin_addr.s_addr;
  28.     lsock.port = sp->sin_port;
  29.     up->cb.udp = open_udp(&lsock,s_urcall);
  30.     up->cb.udp->user = s;
  31.     return 0;
  32. }
  33. int
  34. so_udp_conn(up)
  35. struct usock *up;
  36. {
  37.     if(up->name == NULLCHAR){
  38.         autobind(up);
  39.     }
  40.     return 0;
  41. }
  42. int
  43. so_udp_recv(up,bpp,from,fromlen)
  44. struct usock *up;
  45. struct mbuf **bpp;
  46. char *from;
  47. int *fromlen;
  48. {
  49.     int cnt;
  50.     struct udp_cb *udp;
  51.     struct sockaddr_in *remote;
  52.     struct socket fsocket;
  53.  
  54.     while((udp = up->cb.udp) != NULLUDP
  55.     && (cnt = recv_udp(udp,&fsocket,bpp)) == -1){
  56.         if(up->noblock){
  57.             errno = EWOULDBLOCK;
  58.             return -1;
  59.         } else if((errno = pwait(up)) != 0){
  60.             return -1;
  61.         }
  62.     }
  63.     if(udp == NULLUDP){
  64.         /* Connection went away */
  65.         errno = ENOTCONN;
  66.         return -1;
  67.     }
  68.     if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  69.         remote = (struct sockaddr_in *)from;
  70.         remote->sin_family = AF_INET;
  71.         remote->sin_addr.s_addr = fsocket.address;
  72.         remote->sin_port = fsocket.port;
  73.         *fromlen = SOCKSIZE;
  74.     }
  75.     return cnt;
  76. }
  77. int
  78. so_udp_send(up,bp,to)
  79. struct usock *up;
  80. struct mbuf *bp;
  81. char *to;
  82. {
  83.     struct sockaddr_in *local,*remote;
  84.     struct socket lsock,fsock;
  85.  
  86.     if(up->name == NULLCHAR)
  87.         autobind(up);
  88.     local = (struct sockaddr_in *)up->name;
  89.     lsock.address = local->sin_addr.s_addr;
  90.     lsock.port = local->sin_port;
  91.     if(to != NULLCHAR) {
  92.         remote = (struct sockaddr_in *)to;
  93.     } else if(up->peername != NULLCHAR){
  94.         remote = (struct sockaddr_in *)up->peername;
  95.     } else {
  96.         free_p(bp);
  97.         errno = ENOTCONN;
  98.         return -1;
  99.     }    
  100.     if(checkipaddr(to,up->namelen) == -1){
  101.         errno = EAFNOSUPPORT;
  102.         return -1;
  103.     }
  104.     fsock.address = remote->sin_addr.s_addr;
  105.     fsock.port = remote->sin_port;
  106.     send_udp(&lsock,&fsock,up->tos,0,bp,0,0,0);
  107.     return 0;
  108. }
  109. int
  110. so_udp_qlen(up,rtx)
  111. struct usock *up;
  112. int rtx;
  113. {
  114.     int len;
  115.  
  116.     switch(rtx){
  117.     case 0:
  118.         len = up->cb.udp->rcvcnt;
  119.         break;
  120.     case 1:
  121.         len = 0;
  122.         break;
  123.     }
  124.     return len;
  125. }
  126. int
  127. so_udp_close(up)
  128. struct usock *up;
  129. {
  130.     if(up->cb.udp != NULLUDP){
  131.         del_udp(up->cb.udp);
  132.     }
  133.     return 0;
  134. }
  135. int
  136. so_udp_shut(up,how)
  137. struct usock *up;
  138. int how;
  139. {
  140.     int s;
  141.  
  142.     s = up - Usock + SOCKBASE;
  143.     close_s(s);
  144.     return 0;
  145. }
  146. static void
  147. s_urcall(iface,udp,cnt)
  148. struct iface *iface;
  149. struct udp_cb *udp;
  150. int cnt;
  151. {
  152.     psignal(itop(udp->user),1);
  153.     pwait(NULL);
  154. }
  155.  
  156. /* Issue an automatic bind of a local address */
  157. static void
  158. autobind(up)
  159. struct usock *up;
  160. {
  161.     struct sockaddr_in local;
  162.     int s;
  163.  
  164.     s = up - Usock + SOCKBASE;
  165.     local.sin_family = AF_INET;
  166.     local.sin_addr.s_addr = INADDR_ANY;
  167.     local.sin_port = Lport++;
  168.     bind(s,(char *)&local,sizeof(struct sockaddr_in));
  169. }
  170. static int
  171. checkipaddr(name,namelen)
  172. char *name;
  173. int namelen;
  174. {
  175.     struct sockaddr_in *sock;
  176.  
  177.     sock = (struct sockaddr_in *)name;
  178.     if(sock->sin_family != AF_INET || namelen != sizeof(struct sockaddr_in))
  179.         return -1;
  180.     return 0;
  181. }
  182. int
  183. so_udp_stat(up)
  184. struct usock *up;
  185. {
  186.     st_udp(up->cb.udp,0);
  187.     return 0;
  188. }
  189.