Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

532 lines
16 KiB

  1. /***********************************************************************
  2. * *
  3. * Filename: fsmapi.c *
  4. * Module: H245 Finite State Machine Subsystem *
  5. * *
  6. ***********************************************************************
  7. * INTEL Corporation Proprietary Information *
  8. * *
  9. * This listing is supplied under the terms of a license agreement *
  10. * with INTEL Corporation and may not be copied nor disclosed except *
  11. * in accordance with the terms of that agreement. *
  12. * *
  13. * Copyright (c) 1996 Intel Corporation. All rights reserved. *
  14. ***********************************************************************
  15. * *
  16. * $Workfile: FSMAPI.C $
  17. * $Revision: 1.12 $
  18. * $Modtime: 09 Dec 1996 13:34:24 $
  19. * $Log L:\mphone\h245\h245env\comm\h245_3\h245_fsm\vcs\src\fsmapi.c_v $
  20. * *
  21. ***********************************************************************/
  22. #include "precomp.h"
  23. #include "h245api.h"
  24. #include "h245com.h"
  25. #include "h245fsm.h"
  26. #include "h245deb.x"
  27. extern char *EntityName[];
  28. /*
  29. * This table maps FSM stateless events into H.245 API events
  30. */
  31. static WORD StatelessTable[NUM_EVENTS - NUM_STATE_EVENTS] =
  32. {
  33. H245_IND_NONSTANDARD_REQUEST, // NonStandardRequestPDU
  34. H245_IND_NONSTANDARD_RESPONSE, // NonStandardResponsePDU
  35. H245_IND_NONSTANDARD_COMMAND, // NonStandardCommandPDU
  36. H245_IND_NONSTANDARD, // NonStandardIndicationPDU
  37. H245_IND_MISC_COMMAND, // MiscellaneousCommandPDU
  38. H245_IND_MISC, // MiscellaneousIndicationPDU
  39. H245_IND_COMM_MODE_REQUEST, // CommunicationModeRequestPDU
  40. H245_IND_COMM_MODE_RESPONSE, // CommunicationModeResponsePDU
  41. H245_IND_COMM_MODE_COMMAND, // CommunicationModeCommandPDU
  42. H245_IND_CONFERENCE_REQUEST, // ConferenceRequestPDU
  43. H245_IND_CONFERENCE_RESPONSE, // ConferenceResponsePDU
  44. H245_IND_CONFERENCE_COMMAND, // ConferenceCommandPDU
  45. H245_IND_CONFERENCE, // ConferenceIndicationPDU
  46. H245_IND_SEND_TERMCAP, // SendTerminalCapabilitySetPDU
  47. H245_IND_ENCRYPTION, // EncryptionCommandPDU
  48. H245_IND_FLOW_CONTROL, // FlowControlCommandPDU
  49. H245_IND_ENDSESSION, // EndSessionCommandPDU
  50. H245_IND_FUNCTION_NOT_UNDERSTOOD, // FunctionNotUnderstoodIndicationPDU
  51. H245_IND_JITTER, // JitterIndicationPDU
  52. H245_IND_H223_SKEW, // H223SkewIndicationPDU
  53. H245_IND_NEW_ATM_VC, // NewATMVCIndicationPDU
  54. H245_IND_USERINPUT, // UserInputIndicationPDU
  55. H245_IND_H2250_MAX_SKEW, // H2250MaximumSkewIndicationPDU
  56. H245_IND_MC_LOCATION, // MCLocationIndicationPDU
  57. H245_IND_VENDOR_ID, // VendorIdentificationIndicationPDU
  58. H245_IND_FUNCTION_NOT_SUPPORTED, // FunctionNotSupportedIndicationPDU
  59. };
  60. /*
  61. * Configurable counter values
  62. */
  63. unsigned int uN100 = 10; // Master Slave Determination
  64. /*
  65. * Configurable timer values
  66. */
  67. unsigned int uT101 = 30000; // Capability Exchange
  68. unsigned int uT102 = 30000; // Maintenance Loop
  69. unsigned int uT103 = 30000; // Logical Channel Signalling
  70. unsigned int uT104 = 30000; // H.223 Multiplex Table
  71. unsigned int uT105 = 30000; // Round Trip Delay
  72. unsigned int uT106 = 30000; // Master Slave Determination
  73. unsigned int uT107 = 30000; // Request Multiplex Entry
  74. unsigned int uT108 = 30000; // Send Logical Channel
  75. unsigned int uT109 = 30000; // Mode Request
  76. /*
  77. * NAME
  78. * ObjectCreate - create an State Entity object
  79. *
  80. *
  81. * PARAMETERS
  82. * INPUT pInst Pointer to FSM instance data
  83. * INPUT Entity State Entity represented by object, e.g. LCSE_OUT
  84. * INPUT Key Lookup key for distinguish multiple instances of SE
  85. * INPUT dwTransId Transaction identifier to be sent up to client
  86. *
  87. * RETURN VALUE
  88. * pObject Function succeeded
  89. * NULL Memory allocation failed
  90. */
  91. Object_t *
  92. ObjectCreate(struct InstanceStruct *pInstance, Entity_t Entity, Key_t Key, DWORD_PTR dwTransId)
  93. {
  94. register Object_t * pObject;
  95. #if defined(_DEBUG)
  96. H245TRACE(pInstance->dwInst, 4, "ObjectCreate: Entity=%s(%d) Key=%d dwTransID=0x%p",
  97. EntityName[Entity], Entity, Key, dwTransId);
  98. #else
  99. H245TRACE(pInstance->dwInst, 4, "ObjectCreate: Entity=%d Key=%d dwTransID=0x%p",
  100. Entity, Key, dwTransId);
  101. #endif
  102. pObject = (Object_t *)MemAlloc(sizeof(*pObject));
  103. if (pObject == NULL)
  104. {
  105. H245TRACE(pInstance->dwInst, 1, "ObjectCreate: FSM Object memory allocation failed");
  106. return NULL;
  107. }
  108. memset(pObject, 0, sizeof(*pObject));
  109. /* copy primitive variables to my object */
  110. pObject->pInstance = pInstance;
  111. pObject->dwInst = pInstance->dwInst;
  112. pObject->dwTransId = dwTransId;
  113. pObject->Key = Key;
  114. pObject->Entity = Entity;
  115. pObject->pNext = pInstance->StateMachine.Object_tbl[Entity];
  116. pInstance->StateMachine.Object_tbl[Entity] = pObject;
  117. return pObject;
  118. } // ObjectCreate()
  119. /*
  120. * NAME
  121. * ObjectDestroy - deallocate an object created by ObjectCreate()
  122. *
  123. *
  124. * PARAMETERS
  125. * INPUT pInst pointer to FSM instance data
  126. * INPUT id index into the object table
  127. *
  128. * RETURN VALUE
  129. * FALSE object deallocated
  130. * TRUE object not found
  131. */
  132. int
  133. ObjectDestroy(Object_t *pObject)
  134. {
  135. struct InstanceStruct * pInstance;
  136. Object_t * pSearch;
  137. Object_t * pPrev;
  138. ASSERT(pObject != NULL);
  139. ASSERT(pObject->uNestLevel == 0);
  140. ASSERT(pObject->pInstance != NULL);
  141. pInstance = pObject->pInstance;
  142. #if defined(_DEBUG)
  143. H245TRACE(pInstance->dwInst, 4, "ObjectDestroy: Entity=%s(%d) Key=%d State=%d",
  144. EntityName[pObject->Entity], pObject->Entity, pObject->Key, pObject->State);
  145. #else
  146. H245TRACE(pInstance->dwInst, 4, "ObjectDestroy: Entity=%d Key=%d State=%d",
  147. pObject->Entity, pObject->Key, pObject->State);
  148. #endif
  149. if (pObject->dwTimerId)
  150. {
  151. H245TRACE(pObject->dwInst, 4, "ObjectDestroy: stoping timer");
  152. FsmStopTimer(pObject);
  153. }
  154. if (pInstance->StateMachine.Object_tbl[pObject->Entity] == NULL)
  155. {
  156. H245TRACE(pInstance->dwInst, 1, "ObjectDestroy: no State Entity of specified type found");
  157. return TRUE;
  158. }
  159. if (pInstance->StateMachine.Object_tbl[pObject->Entity] == pObject)
  160. {
  161. pInstance->StateMachine.Object_tbl[pObject->Entity] = pObject->pNext;
  162. MemFree(pObject);
  163. return FALSE;
  164. }
  165. pPrev = pInstance->StateMachine.Object_tbl[pObject->Entity];
  166. pSearch = pPrev->pNext;
  167. while (pSearch != NULL)
  168. {
  169. if (pSearch == pObject)
  170. {
  171. pPrev->pNext = pSearch->pNext;
  172. MemFree(pObject);
  173. return FALSE;
  174. }
  175. pPrev = pSearch;
  176. pSearch = pSearch->pNext;
  177. }
  178. H245TRACE(pInstance->dwInst, 1, "ObjectDestroy: State Entity not found");
  179. return TRUE;
  180. } // ObjectDestroy()
  181. /*
  182. * NAME
  183. * ObjectFind - given parsed information of a PDU, it searches the object table for
  184. * an object with a matching id, type and category
  185. *
  186. *
  187. * PARAMETERS
  188. * INPUT pInst
  189. * INPUT Category category of a given PDU
  190. * INPUT Type type of the PDU
  191. * INPUT pdu_id unique id shared by PDU and object (usually channel number or sequence number)
  192. *
  193. * RETURN VALUE
  194. * pObject object found
  195. * NULL object not found
  196. */
  197. Object_t *
  198. ObjectFind(struct InstanceStruct *pInstance, Entity_t Entity, Key_t Key)
  199. {
  200. register Object_t * pObject;
  201. ASSERT(Entity < STATELESS);
  202. pObject = pInstance->StateMachine.Object_tbl[Entity];
  203. while (pObject != NULL)
  204. {
  205. if (pObject->Key == Key)
  206. {
  207. #if defined(_DEBUG)
  208. H245TRACE(pInstance->dwInst, 4, "ObjectFind(%s, %d) object found",
  209. EntityName[Entity], Key);
  210. #else
  211. H245TRACE(pInstance->dwInst, 4, "ObjectFind(%d, %d) object found",
  212. Entity, Key);
  213. #endif
  214. return pObject;
  215. }
  216. pObject = pObject->pNext;
  217. }
  218. #if defined(_DEBUG)
  219. H245TRACE(pInstance->dwInst, 4, "ObjectFind(%s, %d) object not found",
  220. EntityName[Entity], Key);
  221. #else
  222. H245TRACE(pInstance->dwInst, 4, "ObjectFind(%d, %d) object not found",
  223. Entity, Key);
  224. #endif
  225. return NULL;
  226. } // ObjectFind()
  227. /*
  228. * NAME
  229. * SendFunctionNotUnderstood - builds and sends Function Not Supported PDU
  230. *
  231. *
  232. * PARAMETERS
  233. * INPUT dwInst Current H.245 instance
  234. * INPUT pPdu Not supported PDU
  235. *
  236. * RETURN VALUE
  237. * H245_ERROR_OK
  238. */
  239. HRESULT
  240. SendFunctionNotUnderstood(struct InstanceStruct *pInstance, PDU_t *pPdu)
  241. {
  242. PDU_t * pOut;
  243. HRESULT lError;
  244. pOut = MemAlloc(sizeof(*pOut));
  245. if (pOut == NULL)
  246. {
  247. return H245_ERROR_NOMEM;
  248. }
  249. switch (pPdu->choice)
  250. {
  251. case MltmdSystmCntrlMssg_rqst_chosen:
  252. pOut->u.indication.u.functionNotUnderstood.choice = FnctnNtUndrstd_request_chosen;
  253. pOut->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_request =
  254. pPdu->u.MltmdSystmCntrlMssg_rqst;
  255. break;
  256. case MSCMg_rspns_chosen:
  257. pOut->u.indication.u.functionNotUnderstood.choice = FnctnNtUndrstd_response_chosen;
  258. pOut->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_response =
  259. pPdu->u.MSCMg_rspns;
  260. break;
  261. case MSCMg_cmmnd_chosen:
  262. pOut->u.indication.u.functionNotUnderstood.choice = FnctnNtUndrstd_command_chosen;
  263. pOut->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_command =
  264. pPdu->u.MSCMg_cmmnd;
  265. break;
  266. default:
  267. // Can't reply to unsupported indication...
  268. MemFree(pOut);
  269. return H245_ERROR_OK;
  270. } // switch (Type)
  271. pOut->choice = indication_chosen;
  272. pOut->u.indication.choice = functionNotUnderstood_chosen;
  273. lError = sendPDU(pInstance, pOut);
  274. MemFree(pOut);
  275. return lError;
  276. } // SendFunctionNotUnderstood()
  277. /*
  278. * NAME
  279. * FsmOutgoing - process outbound PDU
  280. *
  281. *
  282. * PARAMETERS
  283. * INPUT pInst Pointer to FSM instance structure
  284. * INPUT pPdu Pointer to PDU to send
  285. * INPUT dwTransId Transaction identifier to use for response
  286. *
  287. * RETURN VALUE
  288. * Error codes defined in h245com.h
  289. */
  290. HRESULT
  291. FsmOutgoing(struct InstanceStruct *pInstance, PDU_t *pPdu, DWORD_PTR dwTransId)
  292. {
  293. HRESULT lError;
  294. Entity_t Entity;
  295. Event_t Event;
  296. Key_t Key;
  297. int bCreate;
  298. Object_t * pObject;
  299. ASSERT(pInstance != NULL);
  300. ASSERT(pPdu != NULL);
  301. H245TRACE(pInstance->dwInst, 4, "FsmOutgoing");
  302. #if defined(_DEBUG)
  303. if (check_pdu(pInstance, pPdu))
  304. return H245_ERROR_ASN1;
  305. #endif // (DEBUG)
  306. lError = PduParseOutgoing(pInstance, pPdu, &Entity, &Event, &Key, &bCreate);
  307. if (lError != H245_ERROR_OK)
  308. {
  309. H245TRACE(pInstance->dwInst, 1,
  310. "FsmOutgoing: PDU not recognized; Error=%d", lError);
  311. return lError;
  312. }
  313. ASSERT(Entity < NUM_ENTITYS);
  314. if (Entity == STATELESS)
  315. {
  316. H245TRACE(pInstance->dwInst, 4, "FsmOutgoing: Sending stateless PDU");
  317. return sendPDU(pInstance, pPdu);
  318. }
  319. ASSERT(Event < NUM_STATE_EVENTS);
  320. pObject = ObjectFind(pInstance, Entity, Key);
  321. if (pObject == NULL)
  322. {
  323. if (bCreate == FALSE)
  324. {
  325. #if defined(_DEBUG)
  326. H245TRACE(pInstance->dwInst, 1,
  327. "FsmOutgoing: State Entity %s(%d) not found; Key=%d",
  328. EntityName[Entity], Entity, Key);
  329. #else
  330. H245TRACE(pInstance->dwInst, 1,
  331. "FsmOutgoing: State Entity %d not found; Key=%d",
  332. Entity, Key);
  333. #endif
  334. return H245_ERROR_PARAM;
  335. }
  336. pObject = ObjectCreate(pInstance, Entity, Key, dwTransId);
  337. if (pObject == NULL)
  338. {
  339. H245TRACE(pInstance->dwInst, 1, "FsmOutgoing: State Entity memory allocation failed");
  340. return H245_ERROR_NOMEM;
  341. }
  342. }
  343. else
  344. {
  345. pObject->dwTransId = dwTransId;
  346. }
  347. return StateMachine(pObject, pPdu, Event);
  348. } // FsmOutgoing()
  349. /*
  350. * NAME
  351. * FsmIncoming - process inbound PDU
  352. *
  353. *
  354. * PARAMETERS
  355. * INPUT dwInst current H.245 instance
  356. * INPUT pPdu pointer to a PDU structure
  357. *
  358. * RETURN VALUE
  359. * error codes defined in h245com.h (not checked)
  360. */
  361. HRESULT
  362. FsmIncoming(struct InstanceStruct *pInstance, PDU_t *pPdu)
  363. {
  364. HRESULT lError;
  365. Entity_t Entity;
  366. Event_t Event;
  367. Key_t Key;
  368. int bCreate;
  369. Object_t * pObject;
  370. Object_t * pObject1;
  371. ASSERT(pInstance != NULL);
  372. ASSERT(pPdu != NULL);
  373. H245TRACE(pInstance->dwInst, 4, "FsmIncoming");
  374. lError = PduParseIncoming(pInstance, pPdu, &Entity, &Event, &Key, &bCreate);
  375. if (lError != H245_ERROR_OK)
  376. {
  377. H245TRACE(pInstance->dwInst, 1,
  378. "FsmIncoming: Received PDU not recognized", lError);
  379. SendFunctionNotUnderstood(pInstance, pPdu);
  380. return lError;
  381. }
  382. ASSERT(Entity < NUM_ENTITYS);
  383. if (Entity == STATELESS)
  384. {
  385. H245TRACE(pInstance->dwInst, 4, "FsmIncoming: Received stateless PDU");
  386. return H245FsmIndication(pPdu, (DWORD)StatelessTable[Event - NUM_STATE_EVENTS], pInstance, 0, H245_ERROR_OK);
  387. }
  388. ASSERT(Event < NUM_STATE_EVENTS);
  389. if (Event == MaintenanceLoopOffCommandPDU)
  390. {
  391. // Special case MaintenanceLoopOff applies to ALL loops
  392. ASSERT(Entity == MLSE_IN);
  393. pObject = pInstance->StateMachine.Object_tbl[Entity];
  394. if (pObject == NULL)
  395. {
  396. return H245_ERROR_OK;
  397. }
  398. lError = StateMachine(pObject, pPdu, Event);
  399. pObject = pInstance->StateMachine.Object_tbl[Entity];
  400. while (pObject)
  401. {
  402. if (pObject->uNestLevel == 0)
  403. {
  404. pObject1 = pObject;
  405. pObject = pObject->pNext;
  406. ObjectDestroy(pObject1);
  407. }
  408. else
  409. {
  410. pObject->State = 0;
  411. pObject = pObject->pNext;
  412. }
  413. }
  414. return lError;
  415. } // if
  416. pObject = ObjectFind(pInstance, Entity, Key);
  417. if (pObject == NULL)
  418. {
  419. if (bCreate == FALSE)
  420. {
  421. #if defined(_DEBUG)
  422. H245TRACE(pInstance->dwInst, 1,
  423. "FsmIncoming: State Entity %s(%d) not found; Key=%d",
  424. EntityName[Entity], Entity, Key);
  425. #else
  426. H245TRACE(pInstance->dwInst, 1,
  427. "FsmIncoming: State Entity %d not found; Key=%d",
  428. Entity, Key);
  429. #endif
  430. return H245_ERROR_PARAM;
  431. }
  432. pObject = ObjectCreate(pInstance, Entity, Key, 0);
  433. if (pObject == NULL)
  434. {
  435. H245TRACE(pInstance->dwInst, 1, "FsmIncoming: State Entity memory allocation failed");
  436. return H245_ERROR_NOMEM;
  437. }
  438. }
  439. return StateMachine(pObject, pPdu, Event);
  440. } // FsmIncoming()
  441. // CAVEAT: Need to save dwInst since StateMachine() might deallocate pObject!
  442. HRESULT
  443. FsmTimerEvent(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId, Object_t *pObject, Event_t Event)
  444. {
  445. ASSERT(pInstance != NULL);
  446. ASSERT(pObject != NULL);
  447. ASSERT(pObject->pInstance == pInstance);
  448. ASSERT(pObject->dwTimerId == dwTimerId);
  449. H245TRACE(pInstance->dwInst, 4, "FsmTimerEvent");
  450. pObject->dwTimerId = 0;
  451. return StateMachine(pObject, NULL, Event);
  452. } // FsmTimerEvent()
  453.