1 /**\r
2 * @file rm_transport.c\r
3 *\r
4 * @brief \r
5 * This is the Resource Manager transport source.\r
6 *\r
7 * \par\r
8 * ============================================================================\r
9 * @n (C) Copyright 2012-2015, Texas Instruments, Inc.\r
10 * \r
11 * Redistribution and use in source and binary forms, with or without \r
12 * modification, are permitted provided that the following conditions \r
13 * are met:\r
14 *\r
15 * Redistributions of source code must retain the above copyright \r
16 * notice, this list of conditions and the following disclaimer.\r
17 *\r
18 * Redistributions in binary form must reproduce the above copyright\r
19 * notice, this list of conditions and the following disclaimer in the \r
20 * documentation and/or other materials provided with the \r
21 * distribution.\r
22 *\r
23 * Neither the name of Texas Instruments Incorporated nor the names of\r
24 * its contributors may be used to endorse or promote products derived\r
25 * from this software without specific prior written permission.\r
26 *\r
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
38 *\r
39 * \par\r
40 */\r
41 \r
42 /* RM external includes */\r
43 #include <ti/drv/rm/rm.h>\r
44 #include <ti/drv/rm/rm_transport.h>\r
45 \r
46 /* RM internal includes */\r
47 #include <ti/drv/rm/include/rm_loc.h>\r
48 #include <ti/drv/rm/include/rm_transportloc.h>\r
49 \r
50 /* RM OSAL layer */\r
51 #include <rm_osal.h>\r
52 \r
53 /**********************************************************************\r
54 ************************ Local Functions *****************************\r
55 **********************************************************************/\r
56 \r
57 /* FUNCTION PURPOSE: Adds a transport\r
58 ***********************************************************************\r
59 * DESCRIPTION: Returns a pointer to a transport structure that\r
60 * was created, initialized, and added to the \r
61 * instance transport list.\r
62 */\r
63 static Rm_Transport *transportAdd(const Rm_TransportCfg *transportCfg)\r
64 {\r
65 Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
66 Rm_Transport *transports = rmInst->transports;\r
67 Rm_Transport *newTransport = NULL;\r
68 \r
69 newTransport = Rm_osalMalloc (sizeof(Rm_Transport));\r
70 memset((void *)newTransport, 0, sizeof(Rm_Transport));\r
71 \r
72 if (newTransport) {\r
73 newTransport->rmHandle = transportCfg->rmHandle;\r
74 newTransport->appTransportHandle = transportCfg->appTransportHandle;\r
75 newTransport->remoteInstType = transportCfg->remoteInstType;\r
76 newTransport->callouts.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
77 newTransport->callouts.rmSendPkt = transportCfg->transportCallouts.rmSendPkt;\r
78 newTransport->nextTransport = NULL;\r
79 \r
80 if (transports) {\r
81 while (transports->nextTransport) {\r
82 transports = transports->nextTransport;\r
83 }\r
84 transports->nextTransport = newTransport;\r
85 } else {\r
86 rmInst->transports = newTransport;\r
87 }\r
88 }\r
89 return(newTransport);\r
90 }\r
91 \r
92 /* FUNCTION PURPOSE: Tests if a transport is registered to an instance\r
93 ***********************************************************************\r
94 * DESCRIPTION: Returns TRUE if the supplied transport is found in\r
95 * the instance transport list. Otherwise, returns FALSE\r
96 */\r
97 static int transportIsRegistered(Rm_Handle rmHandle, Rm_Transport *transport)\r
98 {\r
99 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
100 Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
101 \r
102 while (transportList) {\r
103 if (transportList == transport) {\r
104 return(RM_TRUE);\r
105 }\r
106 transportList = transportList->nextTransport;\r
107 }\r
108 return(RM_FALSE);\r
109 }\r
110 \r
111 /* FUNCTION PURPOSE: Deletes a transport\r
112 ***********************************************************************\r
113 * DESCRIPTION: Removes a transport from an instance transport list\r
114 * and then frees the memory associated with the transport\r
115 * data structure\r
116 */\r
117 static void transportDelete(Rm_Transport *transport)\r
118 {\r
119 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
120 Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
121 Rm_Transport *prevTransport = NULL;\r
122 \r
123 /* Get previous transport in list */\r
124 while (transportList) {\r
125 if (transportList == transport) {\r
126 break;\r
127 }\r
128 prevTransport = transportList;\r
129 transportList = transportList->nextTransport;\r
130 }\r
131 \r
132 if (prevTransport == NULL) {\r
133 rmInst->transports = transport->nextTransport;\r
134 } else {\r
135 prevTransport->nextTransport = transport->nextTransport;\r
136 }\r
137 Rm_osalFree((void *)transport, sizeof(Rm_Transport));\r
138 }\r
139 \r
140 /* FUNCTION PURPOSE: Returns RM packet source instance\r
141 ***********************************************************************\r
142 * DESCRIPTION: Can return the RM instance name for one of two things:\r
143 * - RM instance from which provided RM packet originated\r
144 * - RM instance from which the service request contained\r
145 * in the provided RM packet originated\r
146 */\r
147 static int32_t getPktSrcNames(const Rm_Packet *pkt, char *pktSrc,\r
148 char *serviceSrc, int32_t bufLen)\r
149 {\r
150 int32_t retVal = RM_OK;\r
151 \r
152 if (bufLen != RM_NAME_MAX_CHARS) {\r
153 retVal = RM_ERROR_SRC_NAME_BUF_INVALID_SIZE;\r
154 } else {\r
155 switch (pkt->pktType) {\r
156 case Rm_pktType_RESOURCE_REQUEST:\r
157 {\r
158 Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
159 \r
160 if (pktSrc){\r
161 rm_strncpy(pktSrc, resourceReqPkt->pktSrcInstName,\r
162 RM_NAME_MAX_CHARS);\r
163 }\r
164 \r
165 if (serviceSrc) {\r
166 rm_strncpy(serviceSrc, resourceReqPkt->serviceSrcInstName,\r
167 RM_NAME_MAX_CHARS);\r
168 }\r
169 break;\r
170 }\r
171 case Rm_pktType_NAMESERVER_REQUEST:\r
172 {\r
173 Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
174 \r
175 if (pktSrc){\r
176 rm_strncpy(pktSrc, nsRequestPkt->pktSrcInstName,\r
177 RM_NAME_MAX_CHARS);\r
178 }\r
179 \r
180 if (serviceSrc) {\r
181 rm_strncpy(serviceSrc, nsRequestPkt->serviceSrcInstName,\r
182 RM_NAME_MAX_CHARS);\r
183 }\r
184 break;\r
185 }\r
186 case Rm_pktType_RESOURCE_RESPONSE:\r
187 case Rm_pktType_NAMESERVER_RESPONSE:\r
188 default:\r
189 retVal = RM_ERROR_PKT_AND_SERVICE_SRC_NOT_AVAIL;\r
190 break;\r
191 }\r
192 }\r
193 \r
194 return(retVal);\r
195 }\r
196 \r
197 /**********************************************************************\r
198 ********************** Internal Functions ****************************\r
199 **********************************************************************/\r
200 \r
201 /* FUNCTION PURPOSE: Finds a transport based on remote inst type\r
202 ***********************************************************************\r
203 * DESCRIPTION: Returns a pointer to the transport within an instance's\r
204 * transport list that matches the provided remote\r
205 * instance type. NULL is returned if no transports in \r
206 * the list match the remote instance type.\r
207 */\r
208 Rm_Transport *rmTransportFindRemoteInstType(Rm_Transport *transports,\r
209 Rm_InstType remoteInstType)\r
210 {\r
211 while (transports) {\r
212 if (transports->remoteInstType == remoteInstType) {\r
213 break;\r
214 }\r
215 transports = transports->nextTransport;\r
216 }\r
217 return(transports);\r
218 }\r
219 \r
220 /**********************************************************************\r
221 ********************* Application visible APIs ***********************\r
222 **********************************************************************/\r
223 \r
224 /* FUNCTION PURPOSE: Registers an app transport with a RM instance\r
225 ***********************************************************************\r
226 * DESCRIPTION: Returns a transport handle to the application that\r
227 * has been registered with an RM instance. The handle\r
228 * is used by the application to route packets to the\r
229 * proper RM instance's based on the application\r
230 * transport receive code. The handle is also used\r
231 * internally by RM to route request and response \r
232 * packets to the correct application transports. NULL\r
233 * is returned for the transport handle if any errors\r
234 * are encountered.\r
235 */\r
236 Rm_TransportHandle Rm_transportRegister(const Rm_TransportCfg *transportCfg,\r
237 int32_t *result)\r
238 {\r
239 Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
240 Rm_Transport *transport = NULL;\r
241 void *key;\r
242 void *mtKey;\r
243 \r
244 *result = RM_OK;\r
245 \r
246 RM_SS_INST_INV_ENTER_CS(rmInst, key);\r
247 if (rmInst->mtSemObj) {\r
248 mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);\r
249 }\r
250 \r
251 /* Shared servers and clients cannot connect to anyone */\r
252 if ((rmInst->instType == Rm_instType_SHARED_SERVER) ||\r
253 (rmInst->instType == Rm_instType_SHARED_CLIENT)){\r
254 *result = RM_ERROR_SHARED_INSTANCE_CANNOT_REG_TRANS;\r
255 goto errorExit;\r
256 }\r
257 \r
258 /* No one can connect to a shared server\r
259 * RM Servers cannot connect to other Servers. \r
260 * RM Client Delegates cannot connect to other Client Delegates.\r
261 * RM Clients cannot connect to other Clients */\r
262 if ((transportCfg->remoteInstType == Rm_instType_SHARED_SERVER) ||\r
263 ((rmInst->instType == Rm_instType_SERVER) &&\r
264 (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
265 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
266 (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
267 ((rmInst->instType == Rm_instType_CLIENT) &&\r
268 (transportCfg->remoteInstType == Rm_instType_CLIENT))) {\r
269 *result = RM_ERROR_INVALID_REMOTE_INST_TYPE;\r
270 goto errorExit;\r
271 }\r
272 \r
273 /* Verify Clients are not registering with more than one Client Delegate or\r
274 * Server. And that Client Delegate is not registering with more than one\r
275 * Server. */\r
276 if (rmInst->registeredWithDelegateOrServer &&\r
277 (((rmInst->instType == Rm_instType_CLIENT) &&\r
278 (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
279 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
280 (transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
281 *result = RM_ERROR_ALREADY_REGD_SERVER_OR_CD;\r
282 goto errorExit;\r
283 }\r
284 \r
285 if (!transportCfg->transportCallouts.rmAllocPkt) {\r
286 *result = RM_ERROR_TRANSPORT_ALLOC_PKT_NOT_REGD;\r
287 goto errorExit;\r
288 }\r
289 if (!transportCfg->transportCallouts.rmSendPkt) {\r
290 *result = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
291 goto errorExit;\r
292 }\r
293 \r
294 transport = transportAdd(transportCfg);\r
295 if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
296 (transport->remoteInstType == Rm_instType_SERVER)) {\r
297 rmInst->registeredWithDelegateOrServer = RM_TRUE;\r
298 }\r
299 \r
300 errorExit:\r
301 if (rmInst->mtSemObj) {\r
302 Rm_osalMtCsExit(rmInst->mtSemObj, mtKey);\r
303 }\r
304 RM_SS_INST_WB_EXIT_CS(rmInst, key);\r
305 return ((Rm_TransportHandle) transport);\r
306 }\r
307 \r
308 /* FUNCTION PURPOSE: Reconfigures an instance's transport handle\r
309 ***********************************************************************\r
310 * DESCRIPTION: Reconfigures a transport handle based on the provided\r
311 * configuration parameters if it exists within the \r
312 * instance.\r
313 */\r
314 int32_t Rm_transportReconfig(Rm_TransportHandle transportHandle,\r
315 const Rm_TransportReCfg *reCfg)\r
316 {\r
317 Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
318 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
319 void *key;\r
320 void *mtKey;\r
321 int32_t retVal = RM_OK;\r
322 \r
323 RM_SS_INST_INV_ENTER_CS(rmInst, key);\r
324 if (rmInst->mtSemObj) {\r
325 mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);\r
326 }\r
327 \r
328 if (transportIsRegistered(transport->rmHandle, transport)) {\r
329 /* Reconfigure existing transport's appTransportHandle. Used in cases\r
330 * where instances running on same core connected by function call. */\r
331 transport->appTransportHandle = reCfg->appTransportHandle;\r
332 \r
333 if (reCfg->transportCallouts.rmAllocPkt) {\r
334 transport->callouts.rmAllocPkt = reCfg->transportCallouts.rmAllocPkt;\r
335 }\r
336 if (reCfg->transportCallouts.rmSendPkt) {\r
337 transport->callouts.rmSendPkt = reCfg->transportCallouts.rmSendPkt;\r
338 }\r
339 } else {\r
340 retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
341 }\r
342 \r
343 if (rmInst->mtSemObj) {\r
344 Rm_osalMtCsExit(rmInst->mtSemObj, mtKey);\r
345 }\r
346 RM_SS_INST_WB_EXIT_CS(rmInst, key);\r
347 return(retVal);\r
348 }\r
349 \r
350 /* FUNCTION PURPOSE: Unregisters an app transport from a RM instance\r
351 ***********************************************************************\r
352 * DESCRIPTION: Deletes a registered transport from the transport\r
353 * list and cleans up the memory associated with the\r
354 * transport data structure.\r
355 */\r
356 int32_t Rm_transportUnregister(Rm_TransportHandle transportHandle)\r
357 {\r
358 Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
359 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
360 int32_t retVal = RM_OK;\r
361 \r
362 if (transportIsRegistered(transport->rmHandle, transport)) {\r
363 if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
364 (transport->remoteInstType == Rm_instType_SERVER)) {\r
365 rmInst->registeredWithDelegateOrServer = RM_FALSE;\r
366 }\r
367 transportDelete(transport);\r
368 } else {\r
369 retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
370 }\r
371 return(retVal);\r
372 }\r
373 \r
374 /* FUNCTION PURPOSE: Returns a RM packet's service source instance name\r
375 ***********************************************************************\r
376 * DESCRIPTION: Returns the RM instance name from which the service\r
377 * encapsulated in the RM packet originated.\r
378 */\r
379 int32_t Rm_receiveGetPktServiceSrcName(const Rm_Packet *pkt,\r
380 char *serviceInstName,\r
381 int32_t charBufLen)\r
382 {\r
383 return(getPktSrcNames(pkt, NULL, serviceInstName, charBufLen));\r
384 }\r
385 \r
386 /* FUNCTION PURPOSE: Returns a RM packet's source instance name\r
387 ***********************************************************************\r
388 * DESCRIPTION: Returns the RM instance name from which the RM packet\r
389 * originated.\r
390 */\r
391 int32_t Rm_receiveGetPktSrcName(const Rm_Packet *pkt, char *pktInstName,\r
392 int32_t charBufLen)\r
393 {\r
394 return(getPktSrcNames(pkt, pktInstName, NULL, charBufLen));\r
395 }\r
396 \r
397 /* FUNCTION PURPOSE: Receives RM packets\r
398 ***********************************************************************\r
399 * DESCRIPTION: The application provides RM packets received on the\r
400 * application transports to RM via this API. Function\r
401 * can be called from polling or ISR contexts. Assume \r
402 * invoking application will free packet after this\r
403 * function returns.\r
404 */\r
405 int32_t Rm_receivePacket(Rm_TransportHandle transportHandle,\r
406 const Rm_Packet *pkt)\r
408 Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
409 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
410 Rm_Transaction *transaction;\r
411 int32_t retVal = RM_OK;\r
412 \r
413 if (!transportIsRegistered(transport->rmHandle, transport)) {\r
414 retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
415 goto errorExit;\r
416 }\r
417 \r
418 switch (pkt->pktType) {\r
419 case Rm_pktType_RESOURCE_REQUEST:\r
420 {\r
421 Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
422 \r
423 transaction = rmTransactionQueueAdd(rmInst);\r
424 transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
425 transaction->u.respTrans = transport;\r
426 if (resourceReqPkt->resourceReqType ==\r
427 Rm_resReqPktType_ALLOCATE_INIT) {\r
428 transaction->type = Rm_service_RESOURCE_ALLOCATE_INIT;\r
429 } else if (resourceReqPkt->resourceReqType ==\r
430 Rm_resReqPktType_ALLOCATE_USE) {\r
431 transaction->type = Rm_service_RESOURCE_ALLOCATE_USE;\r
432 } else if (resourceReqPkt->resourceReqType ==\r
433 Rm_resReqPktType_GET_STATUS) {\r
434 transaction->type = Rm_service_RESOURCE_STATUS;\r
435 } else if (resourceReqPkt->resourceReqType ==\r
436 Rm_resReqPktType_FREE) {\r
437 transaction->type = Rm_service_RESOURCE_FREE;\r
438 } else if (resourceReqPkt->resourceReqType ==\r
439 Rm_resReqPktType_GET_NAMED) {\r
440 transaction->type = Rm_service_RESOURCE_GET_BY_NAME;\r
441 } else {\r
442 retVal = RM_ERROR_RECEIVED_INVALID_PACKET_TYPE;\r
443 goto errorExit;\r
444 }\r
445 rm_strncpy(transaction->serviceSrcInstName,\r
446 resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
447 transaction->state = RM_SERVICE_PROCESSING;\r
448 memcpy((void *)&(transaction->resourceInfo),\r
449 (void *)&(resourceReqPkt->resourceInfo),\r
450 sizeof(Rm_ResourceInfo));\r
451 break;\r
452 }\r
453 case Rm_pktType_RESOURCE_RESPONSE:\r
454 {\r
455 Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
456 \r
457 if ((transaction = rmTransactionQueueFind(rmInst,\r
458 resourceRespPkt->responseId))) {\r
459 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
460 (resourceRespPkt->requestState != RM_SERVICE_APPROVED)) {\r
461 /* Lock the RM instance since service validated against\r
462 * static policy failed against Server's global policy */\r
463 rmInst->isLocked = RM_TRUE;\r
464 }\r
465 transaction->state = resourceRespPkt->requestState;\r
466 \r
467 if ((transaction->state == RM_SERVICE_APPROVED) &&\r
468 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
469 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
470 (transaction->type == Rm_service_RESOURCE_STATUS) ||\r
471 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {\r
472 memcpy((void *)&(transaction->resourceInfo),\r
473 (void *)&(resourceRespPkt->resourceInfo),\r
474 sizeof(Rm_ResourceInfo));\r
475 } else {\r
476 /* Always copy owner count and instance allocation count */\r
477 transaction->resourceInfo.ownerCount = resourceRespPkt->resourceInfo.ownerCount;\r
478 transaction->resourceInfo.instAllocCount = resourceRespPkt->resourceInfo.instAllocCount;\r
479 }\r
480 } else {\r
481 retVal = RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ;\r
482 goto errorExit;\r
483 }\r
484 break;\r
485 }\r
486 case Rm_pktType_NAMESERVER_REQUEST:\r
487 {\r
488 Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
489 \r
490 transaction = rmTransactionQueueAdd(rmInst);\r
491 transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
492 transaction->u.respTrans = transport;\r
493 \r
494 if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE) {\r
495 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
496 } else if (nsRequestPkt->nsRequestType ==\r
497 Rm_nsReqPktType_UNMAP_RESOURCE) {\r
498 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
499 }\r
500 \r
501 rm_strncpy(transaction->serviceSrcInstName,\r
502 nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
503 transaction->state = RM_SERVICE_PROCESSING;\r
504 memcpy((void *)&(transaction->resourceInfo),\r
505 (void *)&(nsRequestPkt->resourceInfo),\r
506 sizeof(Rm_ResourceInfo));\r
507 break;\r
508 }\r
509 case Rm_pktType_NAMESERVER_RESPONSE:\r
510 {\r
511 Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
512 \r
513 if ((transaction = rmTransactionQueueFind(rmInst,\r
514 nsResponsePkt->responseId))) {\r
515 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
516 (nsResponsePkt->requestState != RM_SERVICE_APPROVED)) {\r
517 /* Lock the RM instance since service validated against\r
518 * static policy failed against Server's global policy */\r
519 rmInst->isLocked = RM_TRUE;\r
520 }\r
521 transaction->state = nsResponsePkt->requestState;\r
522 } else {\r
523 retVal = RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ;\r
524 goto errorExit;\r
525 }\r
526 break;\r
527 }\r
528 default:\r
529 retVal = RM_ERROR_RECEIVED_INVALID_PACKET_TYPE;\r
530 goto errorExit;\r
531 }\r
532 \r
533 /* Process received transaction */\r
534 rmProcessRouter(rmInst, transaction);\r
535 errorExit:\r
536 return(retVal);\r
537 }\r
538 \r