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

VxWorks

开发平台:

C/C++

  1. /* wdbUdpLib.c - WDB communication interface UDP datagrams */
  2. /* Copyright 1994-2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01h,14sep01,jhw  Fixed warnings from compiling with gnu -pedantic flag
  7. 01g,22jul98,dbt  in udpSendTo(), test wdbComMode rather thant wdbMode (with
  8.                  wdbIsNowTasking) to choose if we must use semTake and
  9.                  semGive.
  10. 01f,07apr97,gnn  turned version number into a #define
  11. 01e,07apr97,gnn  really added version number, was not really there.
  12. 01d,22nov96,vin  made modifications required for BSD44 cluster code.
  13.  added udpIpHdrBuf.
  14. 01c,29feb96,ms   added IP version number to IP header (SPR #5867).
  15. 01b,03jun95,ms  use new commIf structure (sendto/rvcfrom replaces read/write).
  16. 01a,06oct94,ms   written.
  17. */
  18. /*
  19. DESCRIPTION
  20. The WDB agent communicates with the host using sendto/rcvfrom function
  21. pointers contained in a WDB_COMM_IF structure.
  22. This library implements these methods using a lightweight UDP/IP stack
  23. as the transport.
  24. It supports two modes of operation; interrupt and polled, and the
  25. mode can be dynamically toggled.
  26. During agent initialization (in the file target/src/config/usrWdb.c), this
  27. libraries udpCommIfInit() routine is called to initializes a WDB_COMM_IF
  28. structure. A pointer to this structure is then passed to the agent's
  29. wdbInstallCommIf().
  30. Note: This particular library is not required by the WDB target agent.
  31. Other communication libraries can be used instead simply by initializing
  32. a WDB_COMM_IF structure and installing it in the agent.
  33. */
  34. #include "wdb/wdb.h"
  35. #include "wdb/wdbCommIfLib.h"
  36. #include "wdb/wdbLibP.h"
  37. #include "wdb/wdbRtIfLib.h"
  38. #include "wdb/wdbUdpLib.h"
  39. #include "wdb/wdbMbufLib.h"
  40. #include "string.h"
  41. #include "netinet/in_systm.h"
  42. #include "netinet/in.h"
  43. #include "netinet/ip.h"
  44. #include "netinet/udp.h"
  45. #define IP_HDR_SIZE 20
  46. #define UDP_HDR_SIZE 8
  47. #define UDP_IP_HDR_SIZE IP_HDR_SIZE + UDP_HDR_SIZE
  48. #ifndef MIN
  49. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  50. #endif
  51. /* State Information */
  52. static u_int    commMode; /* POLL or INT */
  53. static int agentIp; /* in network byte order */
  54. /* This is a volatile pointer. Not a pointer to volatile data. */
  55. static struct mbuf * volatile pInputMbufs;
  56. static WDB_DRV_IF * pWdbDrvIf;
  57. static void (*udpHookRtn) (u_int arg);
  58. static u_int udpHookArg;
  59. static void * readSyncSem;
  60. static void * writeSyncSem;
  61. static char  udpIpHdrBuf [128];  /* 128 byte buffer for header */
  62. /* foward declarations */
  63. static int  udpRcvfrom (WDB_COMM_ID commId, caddr_t addr, u_int len,
  64.  struct sockaddr_in *pAddr, struct timeval *tv);
  65. static int  udpSendto (WDB_COMM_ID commId, caddr_t addr, u_int len,
  66.  struct sockaddr_in *pAddr);
  67. static int  udpModeSet (WDB_COMM_ID commId, u_int newMode);
  68. static int  udpCancel (WDB_COMM_ID commId);
  69. static int  udpHookAdd (WDB_COMM_ID commId, void (*rout)(), u_int arg);
  70. extern int wdbCksum (char * pData, int nBytes);
  71. /******************************************************************************
  72. *
  73. * udpCommIfInit - Initialize the WDB communication function pointers.
  74. *
  75. * The configlette for the selected WDB_COMM_TYPE calls this function
  76. * from its wdbCommDevInit routine. This function can only be called once.
  77. *
  78. */
  79. STATUS udpCommIfInit
  80.     (
  81.     WDB_COMM_IF * pWdbCommIf, /* function pointers to install */
  82.     WDB_DRV_IF *  pDrvIf
  83.     )
  84.     {
  85.     pWdbCommIf->rcvfrom = udpRcvfrom;
  86.     pWdbCommIf->sendto = udpSendto;
  87.     pWdbCommIf->modeSet = udpModeSet;
  88.     pWdbCommIf->cancel  = udpCancel;
  89.     pWdbCommIf->hookAdd = udpHookAdd;
  90.     pWdbCommIf->notifyHost = NULL;
  91.     pWdbDrvIf = pDrvIf;
  92.     commMode = WDB_COMM_MODE_INT; /* default communication mode */
  93.     if (pWdbRtIf->semCreate != NULL)
  94. {
  95. readSyncSem = pWdbRtIf->semCreate();
  96. writeSyncSem = pWdbRtIf->semCreate();
  97. }
  98.     return (OK);
  99.     }
  100. /******************************************************************************
  101. *
  102. * udpModeSet - Set the communication mode to POLL or INT.
  103. *
  104. * RETURNS: OK on success, or ERROR if the new mode is not supported.
  105. */
  106. static int udpModeSet
  107.     (
  108.     WDB_COMM_ID commId,
  109.     u_int newMode
  110.     )
  111.     {
  112.     if (pWdbDrvIf->modeSetRtn == NULL)
  113. return (ERROR);
  114.     if ((*pWdbDrvIf->modeSetRtn)(pWdbDrvIf->devId, newMode) == ERROR)
  115. return (ERROR);
  116.     commMode = newMode;
  117.     return (OK);
  118.     }
  119. /******************************************************************************
  120. *
  121. * udpRcv - receive a UDP/IP datagram from the driver.
  122. */
  123. void udpRcv
  124.     (
  125.     struct mbuf * pMbuf /* mbuf chain received */
  126.     )
  127.     {
  128.     /* store away the data for the next agent read */
  129.     if (pInputMbufs != NULL) /* only allow one queued request */
  130. {
  131. wdbMbufChainFree (pInputMbufs);
  132. return;
  133. }
  134.     pInputMbufs        = pMbuf;
  135.     /* interrupt on first packet mode? Then call the input hook */
  136.     if ((commMode == WDB_COMM_MODE_INT) && (udpHookRtn != NULL))
  137. {
  138. (*udpHookRtn) (udpHookArg);
  139. return;
  140. }
  141.     /* normal tasking mode? Then unblock the task */
  142.     if (commMode == WDB_COMM_MODE_INT)
  143. {
  144. pWdbRtIf->semGive (readSyncSem);
  145. }
  146.     }
  147. /******************************************************************************
  148. *
  149. * udpRcvfrom - read a UDP/IP datagram (after removing the UDP/IP headers).
  150. *
  151. * This routine assumes that the mbuf chain received from the driver
  152. * has a UDP/IP header in the first mbuf.
  153. *
  154. * In polled mode operation, there is no timeout. This needs to be fixed 
  155. * because it could cause an infinite loop waiting for data.
  156. *
  157. */
  158. static int udpRcvfrom
  159.     (
  160.     WDB_COMM_ID commId,
  161.     caddr_t addr,
  162.     u_int len,
  163.     struct sockaddr_in *pAddr,
  164.     struct timeval *tv
  165.     )
  166.     {
  167.     struct udphdr * pUdpHdr;
  168.     struct ip * pIpHdr;
  169.     u_int nBytes;
  170.    
  171.     /* WDB_COMM_MODE_INT means "task mode". Use semaphore to wait for data */
  172.     if (commMode == WDB_COMM_MODE_INT)
  173. pWdbRtIf->semTake (readSyncSem, tv);
  174.     /* 
  175.      * Otherwise poll the driver until data arrives or a timeout occurs.
  176.      * Note that presently the timeout is not implemented
  177.      */
  178.     else
  179. {
  180. while (pInputMbufs == NULL)
  181.     (*pWdbDrvIf->pollRtn) (pWdbDrvIf->devId);
  182. }
  183.     /* Any data available ? */
  184.     if (pInputMbufs == NULL)
  185. {
  186. return (0);
  187. }
  188.     /* If so, break the packet up into components */
  189.     pIpHdr  = mtod (pInputMbufs, struct ip *);
  190.     pUdpHdr = (struct udphdr *)((int)pIpHdr + IP_HDR_SIZE);
  191.     /* If this packet is not for the agent, ignore it */
  192.     if ((pIpHdr->ip_p      != IPPROTO_UDP) ||
  193. (pUdpHdr->uh_dport != htons(WDBPORT)) ||
  194. (pInputMbufs->m_len < UDP_IP_HDR_SIZE))
  195. {
  196. nBytes = 0;
  197.         goto done;
  198. }
  199.     /* Save away reply address info */
  200.     agentIp = pIpHdr->ip_dst.s_addr;
  201.     pAddr->sin_port = pUdpHdr->uh_sport;
  202.     pAddr->sin_addr = pIpHdr->ip_src;
  203.     /* copy the RPC data into the uses buffer */
  204.     pInputMbufs->m_len -= UDP_IP_HDR_SIZE;
  205.     pInputMbufs->m_data += UDP_IP_HDR_SIZE;
  206.     wdbMbufDataGet (pInputMbufs, addr, len, &nBytes);
  207. done:
  208.     /* free the mbuf chain */
  209.     wdbMbufChainFree (pInputMbufs);
  210.     pInputMbufs = NULL;
  211.     return (nBytes);
  212.     }
  213. /******************************************************************************
  214. *
  215. * udpCancel - cancel a udpRcvfrom
  216. */
  217. static int udpCancel
  218.     (
  219.     WDB_COMM_ID commId
  220.     )
  221.     {
  222.     pWdbRtIf->semGive (readSyncSem);
  223.     return (OK);
  224.     }
  225. /******************************************************************************
  226. *
  227. * udpSendto - send a reply packet (after adding a UDP/IP header).
  228. */
  229. static int udpSendto
  230.     (
  231.     WDB_COMM_ID commId,
  232.     caddr_t addr,
  233.     u_int len,
  234.     struct sockaddr_in *pAddr
  235.     )
  236.     {
  237.     static u_short ip_id;
  238.     struct udphdr *     pUdpHdr;
  239.     struct ip *         pIpHdr;
  240.     STATUS status;
  241.     struct mbuf * pDataMbuf;
  242.     struct mbuf * pHeaderMbuf;
  243.     /* allocate a couple of mbufs */
  244.     pDataMbuf = wdbMbufAlloc();
  245.     if (pDataMbuf == NULL)
  246. return (0);
  247.     pHeaderMbuf = wdbMbufAlloc ();
  248.     if (pHeaderMbuf == NULL)
  249. {
  250. wdbMbufFree (pDataMbuf);
  251. return (0);
  252. }
  253.     /* put the reply data in an mbuf cluster */
  254.     wdbMbufClusterInit (pDataMbuf, addr, len, NULL, 0);
  255.     if (commMode == WDB_COMM_MODE_INT)
  256. {
  257. pDataMbuf->m_extFreeRtn = pWdbRtIf->semGive;
  258. pDataMbuf->m_extArg1 = (int)writeSyncSem;
  259. }
  260.     /* put the header data in the other mbuf */
  261.     wdbMbufClusterInit (pHeaderMbuf, udpIpHdrBuf, len, NULL, 0); 
  262.     pHeaderMbuf->m_data += 40;
  263.     pHeaderMbuf->m_len = UDP_IP_HDR_SIZE;
  264.     pHeaderMbuf->m_type = MT_DATA;
  265.     pHeaderMbuf->m_next  = pDataMbuf;
  266.     pIpHdr = mtod (pHeaderMbuf, struct ip *);
  267.     pUdpHdr = (struct udphdr *)((int)pIpHdr + IP_HDR_SIZE);
  268.     pIpHdr->ip_v        = IPVERSION;
  269.     pIpHdr->ip_hl = 0x45;
  270.     pIpHdr->ip_tos = 0;
  271.     pIpHdr->ip_off = 0;
  272.     pIpHdr->ip_ttl = 0x20;
  273.     pIpHdr->ip_p = IPPROTO_UDP;
  274.     pIpHdr->ip_src.s_addr = agentIp;
  275.     pIpHdr->ip_dst.s_addr = pAddr->sin_addr.s_addr;
  276.     pIpHdr->ip_len = htons (UDP_IP_HDR_SIZE + len);
  277.     pIpHdr->ip_id = ip_id++;
  278.     pIpHdr->ip_sum = 0;
  279.     pIpHdr->ip_sum = ~wdbCksum ((char *)pIpHdr, IP_HDR_SIZE);
  280.     pUdpHdr->uh_sport = htons(WDBPORT);
  281.     pUdpHdr->uh_dport = pAddr->sin_port;
  282.     pUdpHdr->uh_sum = 0;
  283.     pUdpHdr->uh_ulen  = htons (UDP_HDR_SIZE + len);
  284.     /* tell the driver to output the data */
  285.     if (pWdbDrvIf == NULL)
  286. return (ERROR);
  287.     status = (*pWdbDrvIf->pktTxRtn) (pWdbDrvIf->devId, pHeaderMbuf);
  288.     if (status == ERROR)
  289. return (ERROR);
  290.     /* wait for the driver to finish transmition before returning */
  291.     if (commMode == WDB_COMM_MODE_INT)
  292. pWdbRtIf->semTake (writeSyncSem, NULL);
  293.     return (UDP_IP_HDR_SIZE + len);
  294.     }
  295. /******************************************************************************
  296. *
  297. * udpHookAdd -
  298. */
  299. static int udpHookAdd
  300.     (
  301.     WDB_COMM_ID commId,
  302.     void (*rout)(),
  303.     u_int arg
  304.     )
  305.     {
  306.     udpHookRtn = rout;
  307.     udpHookArg = arg;
  308.     return (OK);
  309.     }