wdbUdpSockLib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:7k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* wdbUdpSockLib.c - WDB communication interface for UDP sockets */
  2. /* Copyright 1984-1994 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01d,17mar98,jmb merge from HPSIM, jmb patch 20mar97, rtalloc fails if port
  7.                 number is not zero in socket address.
  8. 01c,27sep95,ms  put netif MTU in global variable (SPR #4645).
  9. 01b,03jun95,ms use new commIf structure (sendto/rvcfrom replaces read/write).
  10. 01a,22dec94,ms  written.
  11. */
  12. /*
  13. DESCRIPTION
  14. The WDB agent communicates with the host using sendto/rcvfrom function
  15. pointers contained in a WDB_COMM_IF structure.
  16. This library iniitalizes these functions to be callouts to the standard
  17. UDP socket routines.
  18. It supports only "interrupt" mode (meaning that packets arrive for
  19. the agent asynchronously to this library). "Polled" mode is not supported,
  20. because the external mode agent requires that polling routines not
  21. make any calls to the kernel (so simply doing non-blocking I/O is not
  22. enough). As a result, this communication library can only support
  23. a task mode agent.
  24. During agent initialization (in the file target/src/config/usrWdb.c), this
  25. libraries wdbUdpSockIfInit() routine is called to initializes a WDB_COMM_IF
  26. structure. A pointer to this structure is then passed to the agent's
  27. wdbInstallCommIf().
  28. Note: This particular library is not required by the WDB target agent.
  29. Other communication libraries can be used instead simply by initializing
  30. a WDB_COMM_IF structure and installing it in the agent.
  31. */
  32. #include "vxWorks.h"
  33. #include "stdio.h"
  34. #include "net/protosw.h"
  35. #include "sys/socket.h"
  36. #include "net/socketvar.h"
  37. #include "net/route.h"
  38. #include "net/if.h"
  39. #include "netinet/in_systm.h"
  40. #include "netinet/in.h"
  41. #include "netinet/ip.h"
  42. #include "netinet/udp.h"
  43. #include "arpa/inet.h"
  44. #include "sockLib.h"
  45. #include "string.h"
  46. #include "selectLib.h"
  47. #include "ioLib.h"
  48. #include "pipeDrv.h"
  49. #include "netLib.h"
  50. #include "intLib.h"
  51. #include "iv.h"
  52. #include "wdb/wdb.h"
  53. #include "wdb/wdbSvcLib.h"
  54. #include "wdb/wdbCommIfLib.h"
  55. #include "wdb/wdbLibP.h"
  56. /* external functions */
  57. extern void rtalloc();
  58. extern void rtfree();
  59. /* static variables */
  60. static int wdbUdpSock; /* for the agent to read from */
  61. static int wdbUdpCancelSock; /* to "cancel read" to wdbUdpSock */
  62. /* foward declarations */
  63. static int  wdbUdpSockRcvfrom (WDB_COMM_ID commId, caddr_t addr, uint_t len,
  64.  struct sockaddr_in *pAddr, struct timeval *tv);
  65. static int  wdbUdpSockSendto (WDB_COMM_ID commId, caddr_t addr, uint_t len,
  66.  struct sockaddr_in *pAddr);
  67. static int  wdbUdpSockModeSet (WDB_COMM_ID commId, uint_t newMode);
  68. static int  wdbUdpSockCancel (WDB_COMM_ID commId);
  69. /******************************************************************************
  70. *
  71. * wdbUdpSockIfInit - Initialize the WDB communication function pointers.
  72. */
  73. STATUS wdbUdpSockIfInit
  74.     (
  75.     WDB_COMM_IF * pWdbCommIf
  76.     )
  77.     {
  78.     struct sockaddr_in srvAddr;
  79.     pWdbCommIf->rcvfrom = wdbUdpSockRcvfrom;
  80.     pWdbCommIf->sendto = wdbUdpSockSendto;
  81.     pWdbCommIf->modeSet = wdbUdpSockModeSet;
  82.     pWdbCommIf->cancel  = wdbUdpSockCancel;
  83.     pWdbCommIf->hookAdd = NULL;
  84.     pWdbCommIf->notifyHost = NULL;
  85.     /* Create the wdbUdpSocket */
  86.     if ((wdbUdpSock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
  87.         {
  88.         printErr ("Socket failedn");
  89.         return (ERROR);
  90.         }
  91.     /* Bind to WDB agents port number */
  92.     bzero ((char *)&srvAddr, sizeof(srvAddr));
  93.     srvAddr.sin_family      = AF_INET;
  94.     srvAddr.sin_port        = htons(WDBPORT);
  95.     srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  96.     if (bind (wdbUdpSock, (struct sockaddr *)&srvAddr, sizeof(srvAddr)) < 0 )
  97.         {
  98.         printErr ("Bind failedn");
  99.         return (ERROR);
  100.         }
  101.     /* Create the wdbUdpCancelSocket */
  102.     if ((wdbUdpCancelSock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
  103.         {
  104.         printErr ("Socket failedn");
  105.         return (ERROR);
  106. }
  107.     /* connect it (for writes) to the wdbUdpSocket */
  108.     bzero ((char *)&srvAddr, sizeof(srvAddr));
  109.     srvAddr.sin_family      = AF_INET;
  110.     srvAddr.sin_port        = htons(WDBPORT);
  111.     srvAddr.sin_addr.s_addr = inet_addr ("127.0.0.1");
  112.     if (connect (wdbUdpCancelSock, (struct sockaddr *)&srvAddr, sizeof(srvAddr))
  113. == ERROR)
  114. {
  115.         printErr ("Connect failedn");
  116. return (ERROR);
  117. }
  118.     return (OK);
  119.     }
  120. /******************************************************************************
  121. *
  122. * wdbUdpSockModeSet - Set the communication mode (only INT is supported).
  123. */
  124. static int wdbUdpSockModeSet
  125.     (
  126.     WDB_COMM_ID commId,
  127.     uint_t newMode
  128.     )
  129.     {
  130.     if (newMode != WDB_COMM_MODE_INT)
  131. return (ERROR);
  132.     return (OK);
  133.     }
  134. /******************************************************************************
  135. *
  136. * wdbUdpSockRcvfrom - read data from the UDP socket with a timeout.
  137. */
  138. static int wdbUdpSockRcvfrom
  139.     (
  140.     WDB_COMM_ID commId,
  141.     caddr_t addr,
  142.     uint_t len,
  143.     struct sockaddr_in *pSockAddr,
  144.     struct timeval *tv
  145.     )
  146.     {
  147.     uint_t nBytes;
  148.     int  addrLen = sizeof (struct sockaddr_in);
  149.     struct fd_set readFds;
  150.     static struct route theRoute;
  151.     struct sockaddr_in  sockAddr;
  152.     /* wait for data with a timeout */
  153.     FD_ZERO (&readFds);
  154.     FD_SET  (wdbUdpSock, &readFds);
  155.     if (select (wdbUdpSock + 1, &readFds, NULL, NULL, tv) < 0)
  156.         {
  157.         printErr ("wdbUdpSockLib: select failed!n");
  158.         return (0);
  159.         }
  160.     if (!FD_ISSET (wdbUdpSock, &readFds))
  161.         {
  162.         return (0);             /* select timed out */
  163.         }
  164.     /* read the data */
  165.     nBytes   = recvfrom (wdbUdpSock, addr, len, 0,
  166. (struct sockaddr  *)pSockAddr, &addrLen);
  167.     if (nBytes < 4)
  168. return (0);
  169.     /* 
  170.      * The following is a fix for SPR #4645 (the agent does
  171.      * not report the correct MTU to the host). We lower
  172.      * the value of the global variable wdbCommMtu if a packet
  173.      * arrives via an interface with a smaller MTU.
  174.      *
  175.      * XXX This fix has some problems:
  176.      *   1) it uses rtalloc, which is not an approved interface.
  177.      *      Note: rtalloc doesn't seem to like having the port number
  178.      *            in the socket address.
  179.      *   2) it assumes all agent packets arrive via the same netif.
  180.      *   3) it doesn't take into account intermediate MTUs in a WAN.
  181.      * The right fix for (3) would be to use an MTU-discovey
  182.      * algorithm (e.g. send larger and larger IP datagrams with the
  183.      * "don't fragment" flag until an ICMP error is returned).
  184.      */
  185.     if (theRoute.ro_rt == NULL)
  186. {
  187. sockAddr = *pSockAddr;
  188. sockAddr.sin_port = 0;
  189. theRoute.ro_dst = * (struct sockaddr *) &sockAddr;
  190. rtalloc (&theRoute);
  191. if (theRoute.ro_rt != NULL)
  192.     {
  193.     if (wdbCommMtu > theRoute.ro_rt->rt_ifp->if_mtu)
  194. wdbCommMtu = theRoute.ro_rt->rt_ifp->if_mtu;
  195.     rtfree (theRoute.ro_rt);
  196.     }
  197. }
  198.     return (nBytes);
  199.     }
  200. /******************************************************************************
  201. *
  202. * wdbUdpSockCancel - cancel a wdbUdpSockRcvfrom
  203. */
  204. static int wdbUdpSockCancel
  205.     (
  206.     WDB_COMM_ID commId
  207.     )
  208.     {
  209.     char  dummy;
  210.     netJobAdd (write, wdbUdpCancelSock, (int)&dummy, 1, 0, 0);
  211.     return (OK);
  212.     }
  213. /******************************************************************************
  214. *
  215. * wdbUdpSockSendto - write data to a UDP socket.
  216. */
  217. static int wdbUdpSockSendto
  218.     (
  219.     WDB_COMM_ID commId,
  220.     caddr_t addr,
  221.     uint_t len,
  222.     struct sockaddr_in * pRemoteAddr
  223.     )
  224.     {
  225.     uint_t nBytes;
  226.     nBytes = sendto (wdbUdpSock, addr, len, 0, (struct sockaddr *)pRemoteAddr,
  227. sizeof (*pRemoteAddr));
  228.     return (nBytes);
  229.     }