wdbSvcLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:9k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* wdbSvcLib.c - maintain the set of services provided by the WDB agent */
  2. /* Copyright 1984-1994 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01g,11jan99,dbt  added a hook to call after the WDB request is handled (fixed
  7.                  SPR #24323).
  8. 01f,12feb98,dbt  added a routine to unload all dynamically loaded services.
  9.                  Fixed a problem in wdbSvcDispatch when the service is
  10.                  unavailabe and the target has rebooted
  11. 01e,31aug95,ms   better handling of sequence number overflows (SPR #4498)
  12. 01d,20jun95,ms  handled sequence number overflow
  13. 01c,03jun95,ms  call wdbRpcNotifyConnect() on connection.
  14. 01b,07feb95,ms added XPORT handle to dispacth routine.
  15. 01a,21sep94,ms  written.
  16. */
  17. /*
  18. DESCPRIPTION
  19. This library is used to hold the current set of services supported
  20. by the WDB agent. It provides scalability and extensibility.
  21. */
  22. #include "wdb/wdb.h"
  23. #include "wdb/wdbLib.h"
  24. #include "wdb/wdbLibP.h"
  25. #include "wdb/wdbSvcLib.h"
  26. #include "wdb/wdbEvtLib.h"
  27. #include "string.h"
  28. /* definitions */
  29. #define MAX_RPC_PARAM_SIZE 200
  30. #define NOT_CONNECTED -1
  31. #define SEQ_NUM_DELTA 100
  32. /* local variables */
  33. static WDB_SVC * pWdbSvcArray;
  34. static u_int wdbSvcArraySize;
  35. static u_int wdbNumSvcs;
  36. static FUNCPTR wdbSvcHookRtn = NULL;
  37. static u_int wdbSvcHookRtnArg;
  38. static u_int wdbSeqNum = NOT_CONNECTED;
  39. /******************************************************************************
  40. *
  41. * wdbSvcLibInit - initialize the library.
  42. */ 
  43. void wdbSvcLibInit
  44.     (
  45.     WDB_SVC * pArray,
  46.     u_int size
  47.     )
  48.     {
  49.     pWdbSvcArray = pArray;
  50.     wdbSvcArraySize = size;
  51.     wdbSvcHookRtn = NULL;
  52.     wdbSeqNum = NOT_CONNECTED;
  53.     }
  54. /******************************************************************************
  55. *
  56. * wdbSvcHookAdd - add a hook to be called when the service is handled
  57. *
  58. * This routine adds a hook to be called when the RPC service is handled
  59. * (when the answer is sent). This can be used to free memory that was 
  60. * allocated to send the answer.
  61. *
  62. * RETURNS: N/A
  63. *
  64. * NOMANUAL
  65. */ 
  66. void wdbSvcHookAdd
  67.     (
  68.     FUNCPTR hookRtn, /* routine to be called when a service is handled */
  69.     u_int arg  /* argument of the routine */
  70.     )
  71.     {
  72.     wdbSvcHookRtn = hookRtn;
  73.     wdbSvcHookRtnArg = arg;
  74.     }
  75. /******************************************************************************
  76. *
  77. * wdbSvcGetSvc - get information about an RPC procedure number.
  78. *
  79. * RETURNS: Pointer to a WDB_SERVICE structure which contains
  80. *      1) The address of the associated service function.
  81. *      2) The address of the associated XDR input filter
  82. *      3) The address of the associated XDR output filter.
  83. * Or NULL if the procedure number is not supported.
  84. */
  85. static WDB_SVC * wdbSvcGetSvc
  86.     (
  87.     u_int procNum
  88.     )
  89.     {
  90.     uint_t i;
  91.     for (i = 0; i < wdbSvcArraySize; i++)
  92. if (pWdbSvcArray[i].serviceNum >= procNum)
  93.     break;
  94.     return (pWdbSvcArray[i].serviceNum == procNum ? &pWdbSvcArray[i] : NULL);
  95.     }
  96. /******************************************************************************
  97. *
  98. * wdbSvcAdd - Add an RPC service.
  99. *
  100. * RETURNS: OK or ERROR if the service table is full.
  101. */
  102. STATUS wdbSvcAdd
  103.     (
  104.     uint_t procNum, /* procedure number */
  105.     UINT32 (*serviceRtn)(), /* function to call */
  106.     BOOL (*inProc)(), /* XDR filter for parameters */
  107.     BOOL (*outProc)() /* XDR filter for return value */
  108.     )
  109.     {
  110.     int i;
  111.     /* any more room left in service table ? */
  112.     if (wdbNumSvcs >= wdbSvcArraySize)
  113.         return (ERROR);
  114.     /* We add the service to the array in sorted order */
  115.     for (i = wdbNumSvcs; i > 0; i--)
  116. {
  117. if (pWdbSvcArray[i-1].serviceNum < procNum)
  118.     break;
  119. pWdbSvcArray[i].serviceNum = pWdbSvcArray[i-1].serviceNum;
  120. pWdbSvcArray[i].serviceRtn = pWdbSvcArray[i-1].serviceRtn;
  121. pWdbSvcArray[i].inProc     = pWdbSvcArray[i-1].inProc;
  122. pWdbSvcArray[i].outProc    = pWdbSvcArray[i-1].outProc;
  123. pWdbSvcArray[i].dynamic    = pWdbSvcArray[i-1].dynamic;
  124. }
  125.     pWdbSvcArray[i].serviceNum = procNum;
  126.     pWdbSvcArray[i].serviceRtn = serviceRtn;
  127.     pWdbSvcArray[i].inProc     = inProc;
  128.     pWdbSvcArray[i].outProc    = outProc;
  129.     /* 
  130.      * We consider that all service added after the target server is connected
  131.      * are dynamic services (loaded by the target server dynamically). Those
  132.      * services must be removed when we disconnect from target server.
  133.      */
  134.     if (wdbTargetIsConnected ())
  135. pWdbSvcArray[i].dynamic = TRUE;
  136.     else
  137. pWdbSvcArray[i].dynamic = FALSE;
  138.     wdbNumSvcs ++;
  139.     return (OK);
  140.     }
  141. /******************************************************************************
  142. *
  143. * wdbSvcDispatch - invoke the service associated with an RPC procedure number.
  144. */
  145. void wdbSvcDispatch
  146.     (
  147.     WDB_XPORT * pXport, /* RPC transport handle */
  148.     uint_t procNum /* RPC procedure number */
  149.     )
  150.     {
  151.     WDB_SVC * pWdbService; /* node for procedure lookup */
  152.     UINT32 (*rout)(); /* service proc address */
  153.     BOOL (*inProc)();          /* XDR input filter */
  154.     BOOL (*outProc)();         /* XDR output filter */
  155.     UINT32 args [MAX_RPC_PARAM_SIZE/4]; /* procedure args */
  156.     UINT32 reply [MAX_RPC_PARAM_SIZE/4]; /* procedure reply */
  157.     WDB_PARAM_WRAPPER paramWrapper;
  158.     WDB_REPLY_WRAPPER replyWrapper;
  159.     /* get the routine and XDR filters associated with the service number */
  160.     pWdbService = wdbSvcGetSvc (procNum);
  161.     if (pWdbService == NULL)
  162.         {
  163. /* if we are not connected, reply SYSTEM_ERR */
  164. if (wdbSeqNum == NOT_CONNECTED)
  165.     wdbRpcReplyErr (pXport, SYSTEM_ERR);
  166. else
  167.     wdbRpcReplyErr (pXport, PROC_UNAVAIL);
  168.         return;
  169.         }
  170.     rout = pWdbService->serviceRtn;
  171.     inProc = pWdbService->inProc;
  172.     outProc = pWdbService->outProc;
  173.     /* initialize the parameter and reply wrapper data */
  174.     paramWrapper.pParams = args;
  175.     paramWrapper.xdr     = inProc;
  176.     replyWrapper.pReply  = reply;
  177.     replyWrapper.xdr     = outProc;
  178.     /* use the input wrapper to decode the sequence number and parameters */
  179.     bzero ((caddr_t)args, MAX_RPC_PARAM_SIZE);
  180.     if (!wdbRpcGetArgs (pXport, xdr_WDB_PARAM_WRAPPER, (char *)&paramWrapper))
  181. {
  182. wdbRpcReplyErr (pXport, GARBAGE_ARGS);
  183. return;
  184. }
  185.     /* if this is a connection request, mark the agent as connected */
  186.     if (procNum == WDB_TARGET_CONNECT)
  187.         {
  188.         wdbSeqNum = paramWrapper.seqNum;
  189. wdbRpcNotifyConnect (pXport);
  190.         }
  191.     /* if we are not connected, reply SYSTEM_ERR */
  192.     if (wdbSeqNum == NOT_CONNECTED)
  193.         {
  194.         wdbRpcReplyErr (pXport, SYSTEM_ERR);
  195.         return;
  196.         }
  197.     /* if we are connected to another host, reply PROG_UNAVAIL */
  198.     if ((paramWrapper.seqNum ^ wdbSeqNum) & WDB_HOST_ID_MASK)
  199.         {
  200.         wdbRpcReplyErr (pXport, PROG_UNAVAIL);
  201.         return;
  202.         }
  203.     /* check if this is a duplicate of an old request */
  204.     if (procNum != WDB_TARGET_CONNECT)
  205.         {
  206.         /*
  207.          * If the last reply got lost, the host will resend
  208.          * the request. In this case, we need to resend the reply without
  209.          * reexecuting the routine.
  210.          */
  211.         if (paramWrapper.seqNum == wdbSeqNum)
  212.             {
  213.     wdbRpcResendReply (pXport);
  214.             return;
  215.             }
  216.         /*
  217.          * Packets can arrive out of order with UDP. If an old request
  218.          * arrives after a more recent request, it means that the host
  219.          * has already forgotten about the old request. We should just
  220.          * ignore the old request.
  221.  */
  222. /* ignore a smaller sequence number unless it is a wrap-around */
  223.         if (paramWrapper.seqNum < wdbSeqNum)
  224.             {
  225.     if (((wdbSeqNum & ~WDB_HOST_ID_MASK) < 0xffff - 100) ||
  226. ((paramWrapper.seqNum & ~WDB_HOST_ID_MASK) > 100))
  227. return;
  228.             }
  229. /* ignore a larger sequence number if it jumps by too much */
  230. if (paramWrapper.seqNum > wdbSeqNum + SEQ_NUM_DELTA)
  231.     {
  232.     return;
  233.     }
  234.         }
  235.     /* save away the sequence number */
  236.     wdbSeqNum = paramWrapper.seqNum;
  237.     /* invoke the service */
  238.     replyWrapper.errCode = (*rout) (args, &reply);
  239.     /*
  240.      * The first word of the reply is always the errCode field.
  241.      * One bit is reserved to let the host know that events are pending.
  242.      */
  243.     if (!wdbEventListIsEmpty())
  244. replyWrapper.errCode |= WDB_EVENT_NOTIFY;
  245.     /* send the reply */
  246.     wdbRpcReply (pXport, xdr_WDB_REPLY_WRAPPER, (char *)&replyWrapper);
  247.     /* if this was a WDB_TARGET_DISCONNECT reset the sequence number */
  248.     if (procNum == WDB_TARGET_DISCONNECT)
  249.         {
  250.         wdbSeqNum       = NOT_CONNECTED;
  251.         }
  252.     /* call the hook routine if it was initialized */
  253.     if (wdbSvcHookRtn != NULL)
  254.      {
  255. wdbSvcHookRtn (wdbSvcHookRtnArg);
  256. wdbSvcHookRtn = NULL; /* reset the hook */
  257. }
  258.     }
  259. /******************************************************************************
  260. *
  261. * wdbSvcDsaSvcRemove - Removed all dynamically loaded services.
  262. *
  263. * RETURNS: NA 
  264. */
  265. void wdbSvcDsaSvcRemove (void)
  266.     {
  267.     int i;
  268.     int count = 0; /* number of services removed */
  269.     for (i = 0; i < wdbNumSvcs; i++)
  270. if (pWdbSvcArray[i].dynamic)
  271.     {
  272.     pWdbSvcArray[i].serviceNum = 0; /* unvalid entry */
  273.     count ++;
  274.     }
  275. else
  276.     /* fill table with valid entry */
  277.     pWdbSvcArray[i - count] = pWdbSvcArray[i];
  278. }
  279.     wdbNumSvcs = wdbNumSvcs - count;
  280.     }