Source code of Windows XP (NT5)
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.

4555 lines
110 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. callback.c
  5. Abstract:
  6. Callback routines for Intel Call Control Module.
  7. Environment:
  8. User Mode - Win32
  9. --*/
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // //
  12. // Include files //
  13. // //
  14. ///////////////////////////////////////////////////////////////////////////////
  15. #include "globals.h"
  16. #include <limits.h>
  17. #include "registry.h"
  18. #include "termcaps.h"
  19. #include "provider.h"
  20. #include "callback.h"
  21. #include "line.h"
  22. #include "apierror.h"
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // //
  25. // Global variables //
  26. // //
  27. ///////////////////////////////////////////////////////////////////////////////
  28. HANDLE g_hCallbackThread = NULL;
  29. DWORD g_dwCallbackThreadID = UNINITIALIZED;
  30. HANDLE g_WaitableObjects[NUM_WAITABLE_OBJECTS];
  31. ///////////////////////////////////////////////////////////////////////////////
  32. // //
  33. // Private procedures //
  34. // //
  35. ///////////////////////////////////////////////////////////////////////////////
  36. VOID
  37. H323ComputeVideoChannelBitRates(
  38. IN const DWORD dwReferenceMaxBitRate,
  39. IN const DWORD dwAudioBitRate,
  40. OUT DWORD * pdwFinalBitRate,
  41. OUT DWORD * pdwStartUpBitRate
  42. )
  43. /*++
  44. Routine Description:
  45. caculate the bit rate for opening the local channel and the initial bit
  46. rate for the MSP.
  47. Arguments:
  48. dwReferenceMaxBitRate - The max bit rate we got from capability exchange.
  49. (in 100 bps unit)
  50. dwAudioBitRate - The bit rate of the audio stream.
  51. (in 100 bps unit)
  52. pdwFinalBitRate - the bit rate we are going to use to open the channel.
  53. (in 100 bps unit)
  54. pdwStartUpBitRate - the bit rate the MSP should use to start the stream. It
  55. will adapt to the max bit rate if everything is fine.
  56. (in 1 bps unit)
  57. Return Values:
  58. Returns true if successful.
  59. --*/
  60. {
  61. DWORD dwMaxBitRate = dwReferenceMaxBitRate;
  62. if (dwMaxBitRate < H323_UNADJ_VIDEORATE_THRESHOLD) {
  63. // if the max bit rate is too small, just use it.
  64. *pdwStartUpBitRate = dwMaxBitRate * 100;
  65. } else if (dwMaxBitRate < H323_TRUE_VIDEORATE_THRESHOLD) {
  66. // if the max bit rate is still smaller than our threshold,
  67. // the other side must mean .
  68. *pdwStartUpBitRate = dwMaxBitRate * 80;
  69. if (*pdwStartUpBitRate < H323_UNADJ_VIDEORATE_THRESHOLD * 100) {
  70. *pdwStartUpBitRate = H323_UNADJ_VIDEORATE_THRESHOLD * 100;
  71. }
  72. } else if (dwMaxBitRate < MAXIMUM_BITRATE_28800) {
  73. // We assume the MaxBitRate is the total bandwidth of
  74. // the pipe. We need to substract the bandwidth needed
  75. // by audio from this number.
  76. dwMaxBitRate -= dwAudioBitRate;
  77. // We don't want to use 100% of the bandwidth for RTP packets
  78. // So the video bandwidth is further adjusted.
  79. dwMaxBitRate = dwMaxBitRate * (100 - H323_BANDWIDTH_CUSHION_PERCENT) / 100;
  80. *pdwStartUpBitRate = dwMaxBitRate * 100;
  81. } else if (dwMaxBitRate < MAXIMUM_BITRATE_63000) {
  82. // We assume the MaxBitRate is the total bandwidth of
  83. // the pipe. We need to substract the bandwidth needed
  84. // by audio from this number.
  85. dwMaxBitRate -= dwAudioBitRate;
  86. // We don't want to use 100% of the bandwidth for RTP packets
  87. // So the video bandwidth is further adjusted.
  88. dwMaxBitRate = dwMaxBitRate * (100 - H323_BANDWIDTH_CUSHION_PERCENT) / 100;
  89. *pdwStartUpBitRate = dwMaxBitRate * 80;
  90. if (*pdwStartUpBitRate < H323_UNADJ_VIDEORATE_THRESHOLD * 100) {
  91. *pdwStartUpBitRate = H323_UNADJ_VIDEORATE_THRESHOLD * 100;
  92. }
  93. } else {
  94. *pdwStartUpBitRate = dwMaxBitRate * 80;
  95. }
  96. *pdwFinalBitRate = dwMaxBitRate;
  97. }
  98. BOOL
  99. H323SendNewCallIndication(
  100. PH323_CALL pCall
  101. )
  102. /*++
  103. Routine Description:
  104. Sends NEW_CALL_INDICATION from TSP to MSP.
  105. Arguments:
  106. pCall - Specifies a pointer to the associated call object.
  107. Return Values:
  108. Returns true if successful.
  109. --*/
  110. {
  111. H323TSP_MESSAGE Message;
  112. // set the appropriate message type
  113. Message.Type = H323TSP_NEW_CALL_INDICATION;
  114. // send msp message
  115. (*g_pfnLineEventProc)(
  116. pCall->pLine->htLine,
  117. pCall->htCall,
  118. LINE_SENDMSPDATA,
  119. MSP_HANDLE_UNKNOWN,
  120. (DWORD_PTR)&Message,
  121. sizeof(Message)
  122. );
  123. // success
  124. return TRUE;
  125. }
  126. BOOL
  127. H323SendVideoFastUpdatePictureCommand(
  128. PH323_CALL pCall,
  129. PH323_CHANNEL pChannel
  130. )
  131. /*++
  132. Routine Description:
  133. Sends VIDEO_FAST_UPDATE_PICTURE_COMMAND from TSP to MSP.
  134. Arguments:
  135. pCall - Specifies a pointer to the call object.
  136. pChannel - Specifies a pointer to the channel object to open.
  137. Return Values:
  138. Returns TRUE if successful.
  139. --*/
  140. {
  141. H323TSP_MESSAGE Message;
  142. H323DBG((
  143. DEBUG_LEVEL_TRACE,
  144. "TSP->MSP I-Frame request. hmChannel=0x%08lx.\n",
  145. pChannel->hmChannel
  146. ));
  147. // set the appropriate message type
  148. Message.Type = H323TSP_VIDEO_FAST_UPDATE_PICTURE_COMMAND;
  149. // initialize tsp channel handle
  150. Message.VideoFastUpdatePictureCommand.hChannel =
  151. pChannel->hmChannel;
  152. // send msp message
  153. (*g_pfnLineEventProc)(
  154. pCall->pLine->htLine,
  155. pCall->htCall,
  156. LINE_SENDMSPDATA,
  157. MSP_HANDLE_UNKNOWN,
  158. (DWORD_PTR)&Message,
  159. sizeof(Message)
  160. );
  161. // success
  162. return TRUE;
  163. }
  164. BOOL
  165. H323SendFlowControlCommand(
  166. PH323_CALL pCall,
  167. PH323_CHANNEL pChannel,
  168. DWORD dwBitRate
  169. )
  170. /*++
  171. Routine Description:
  172. Sends FLOW_CONTROL_COMMAND from TSP to MSP.
  173. Arguments:
  174. pCall - Specifies a pointer to the call object.
  175. pChannel - Specifies a pointer to the channel object to open.
  176. dwBitRate - Specifies new media stream bit rate (in bps) for MSP
  177. Return Values:
  178. Returns true if successful.
  179. --*/
  180. {
  181. H323TSP_MESSAGE Message;
  182. H323DBG((
  183. DEBUG_LEVEL_TRACE,
  184. "TSP->MSP Flow Control request. hmChannel=0x%08lx. Req. rate=%08d.\n",
  185. pChannel->hmChannel,
  186. dwBitRate
  187. ));
  188. // set the appropriate message type
  189. Message.Type = H323TSP_FLOW_CONTROL_COMMAND;
  190. // initialize tsp channel handle
  191. Message.FlowControlCommand.hChannel = pChannel->hmChannel;
  192. // transfer stream settings
  193. Message.FlowControlCommand.dwBitRate = dwBitRate;
  194. // send msp message
  195. (*g_pfnLineEventProc)(
  196. pCall->pLine->htLine,
  197. pCall->htCall,
  198. LINE_SENDMSPDATA,
  199. MSP_HANDLE_UNKNOWN,
  200. (DWORD_PTR)&Message,
  201. sizeof(Message)
  202. );
  203. // success
  204. return TRUE;
  205. }
  206. BOOL
  207. H323UpdateMediaModes(
  208. PH323_CALL pCall
  209. )
  210. /*++
  211. Routine Description:
  212. Updates media modes based on new channel table.
  213. Arguments:
  214. pCall - Pointer to call object to update.
  215. Return Values:
  216. Returns true if successful.
  217. --*/
  218. {
  219. DWORD i;
  220. DWORD dwIncomingModesOld;
  221. DWORD dwOutgoingModesOld;
  222. PH323_CHANNEL_TABLE pChannelTable = pCall->pChannelTable;
  223. // save old media modes
  224. dwIncomingModesOld = pCall->dwIncomingModes;
  225. dwOutgoingModesOld = pCall->dwOutgoingModes;
  226. // clear modia modes
  227. pCall->dwIncomingModes = 0;
  228. pCall->dwOutgoingModes = 0;
  229. // loop through each object in table
  230. for (i = 0; i < pChannelTable->dwNumSlots; i++) {
  231. // see if there are any open channels in table
  232. if (H323IsChannelOpen(pChannelTable->pChannels[i])) {
  233. // see if open channel is incoming
  234. if (H323IsChannelInbound(pChannelTable->pChannels[i])) {
  235. // add media mode to list of media modes
  236. pCall->dwIncomingModes |=
  237. H323IsVideoPayloadType(pChannelTable->pChannels[i]->Settings.dwPayloadType)
  238. ? LINEMEDIAMODE_VIDEO
  239. : H323IsInteractiveVoiceRequested(pCall)
  240. ? LINEMEDIAMODE_INTERACTIVEVOICE
  241. : LINEMEDIAMODE_AUTOMATEDVOICE
  242. ;
  243. } else {
  244. // add media mode to list of media modes
  245. pCall->dwOutgoingModes |=
  246. H323IsVideoPayloadType(pChannelTable->pChannels[i]->Settings.dwPayloadType)
  247. ? LINEMEDIAMODE_VIDEO
  248. : H323IsInteractiveVoiceRequested(pCall)
  249. ? LINEMEDIAMODE_INTERACTIVEVOICE
  250. : LINEMEDIAMODE_AUTOMATEDVOICE
  251. ;
  252. }
  253. }
  254. }
  255. // see if media modes were modified
  256. if ((dwIncomingModesOld | dwOutgoingModesOld) !=
  257. (pCall->dwIncomingModes | pCall->dwOutgoingModes)) {
  258. // announce media change
  259. (*g_pfnLineEventProc)(
  260. pCall->pLine->htLine,
  261. pCall->htCall,
  262. LINE_CALLINFO,
  263. LINECALLINFOSTATE_MEDIAMODE,
  264. 0,
  265. 0
  266. );
  267. }
  268. H323DBG((
  269. DEBUG_LEVEL_VERBOSE,
  270. "call 0x%08lx incoming modes 0x%08x (old=0x%08lx).\n",
  271. pCall,
  272. pCall->dwIncomingModes,
  273. dwIncomingModesOld
  274. ));
  275. H323DBG((
  276. DEBUG_LEVEL_VERBOSE,
  277. "call 0x%08lx outgoing modes 0x%08x (old=0x%08lx).\n",
  278. pCall,
  279. pCall->dwOutgoingModes,
  280. dwOutgoingModesOld
  281. ));
  282. // success
  283. return TRUE;
  284. }
  285. BOOL
  286. H323SendAcceptChannelRequest(
  287. PH323_CALL pCall,
  288. PH323_CHANNEL pChannel
  289. )
  290. /*++
  291. Routine Description:
  292. Sends ACCEPT_CHANNEL_REQUEST from TSP to MSP.
  293. Arguments:
  294. pCall - Specifies a pointer to the call object.
  295. pChannel - Specifies a pointer to the channel object to open.
  296. Return Values:
  297. Returns true if successful.
  298. --*/
  299. {
  300. H323TSP_MESSAGE Message;
  301. H323DBG((
  302. DEBUG_LEVEL_TRACE,
  303. "Accept channel request to MSP. htChannel=0x%08lx.\n",
  304. pChannel->hccChannel
  305. ));
  306. // set the appropriate message type
  307. Message.Type = H323TSP_ACCEPT_CHANNEL_REQUEST;
  308. // initialize tsp channel handle
  309. Message.AcceptChannelRequest.htChannel = (HANDLE)(DWORD)pChannel->hccChannel;
  310. // transfer stream settings
  311. Message.AcceptChannelRequest.Settings = pChannel->Settings;
  312. // send msp message
  313. (*g_pfnLineEventProc)(
  314. pCall->pLine->htLine,
  315. pCall->htCall,
  316. LINE_SENDMSPDATA,
  317. MSP_HANDLE_UNKNOWN,
  318. (DWORD_PTR)&Message,
  319. sizeof(Message)
  320. );
  321. // success
  322. return TRUE;
  323. }
  324. BOOL
  325. H323SendOpenChannelResponse(
  326. PH323_CALL pCall,
  327. PH323_CHANNEL pChannel
  328. )
  329. /*++
  330. Routine Description:
  331. Sends OPEN_CHANNEL_RESPONSE from TSP to MSP.
  332. Arguments:
  333. pCall - Specifies a pointer to the call object.
  334. pChannel - Specifies a pointer to the channel object to open.
  335. Return Values:
  336. Returns true if successful.
  337. --*/
  338. {
  339. H323TSP_MESSAGE Message;
  340. H323DBG((
  341. DEBUG_LEVEL_TRACE,
  342. "Open channel response to MSP. hmChannel=0x%08lx.\n",
  343. pChannel->hmChannel
  344. ));
  345. // set the appropriate message type
  346. Message.Type = H323TSP_OPEN_CHANNEL_RESPONSE;
  347. // initialize channel handles
  348. Message.OpenChannelResponse.hmChannel = pChannel->hmChannel;
  349. Message.OpenChannelResponse.htChannel = (HANDLE)(DWORD)pChannel->hccChannel;
  350. // transfer stream settings
  351. Message.OpenChannelResponse.Settings = pChannel->Settings;
  352. // send msp message
  353. (*g_pfnLineEventProc)(
  354. pCall->pLine->htLine,
  355. pCall->htCall,
  356. LINE_SENDMSPDATA,
  357. MSP_HANDLE_UNKNOWN,
  358. (DWORD_PTR)&Message,
  359. sizeof(Message)
  360. );
  361. // success
  362. return TRUE;
  363. }
  364. BOOL
  365. H323SendCloseChannelCommand(
  366. PH323_CALL pCall,
  367. HANDLE hmChannel,
  368. DWORD dwReason
  369. )
  370. /*++
  371. Routine Description:
  372. Sends CLOSE_CHANNEL_COMMAND from TSP to MSP.
  373. Arguments:
  374. pCall - Specifies a pointer to the call object.
  375. hmChannel - Specifies a handle to the channel to close.
  376. dwReason - Specifies reason for closing channel.
  377. Return Values:
  378. Returns true if successful.
  379. --*/
  380. {
  381. H323TSP_MESSAGE Message;
  382. H323DBG((
  383. DEBUG_LEVEL_TRACE,
  384. "Close channel command to MSP. hmChannel=0x%08lx.\n",
  385. hmChannel
  386. ));
  387. // set the appropriate message type
  388. Message.Type = H323TSP_CLOSE_CHANNEL_COMMAND;
  389. // transfer reason
  390. Message.CloseChannelCommand.dwReason = dwReason;
  391. // initialize channel handles
  392. Message.CloseChannelCommand.hChannel = hmChannel;
  393. // send msp message
  394. (*g_pfnLineEventProc)(
  395. pCall->pLine->htLine,
  396. pCall->htCall,
  397. LINE_SENDMSPDATA,
  398. MSP_HANDLE_UNKNOWN,
  399. (DWORD_PTR)&Message,
  400. sizeof(Message)
  401. );
  402. // success
  403. return TRUE;
  404. }
  405. BOOL
  406. H323ProcessOpenChannelRequest(
  407. PH323_CALL pCall,
  408. PH323MSG_OPEN_CHANNEL_REQUEST pRequest
  409. )
  410. /*++
  411. Routine Description:
  412. Process command from MSP.
  413. Arguments:
  414. pCall - Specifies a pointer to the call object to process.
  415. pRequest - Specifies a pointer to the command block.
  416. Return Values:
  417. Returns true if successful.
  418. --*/
  419. {
  420. BOOL fOpened = FALSE;
  421. PH323_CHANNEL pChannel = NULL;
  422. PH323_CHANNEL pAssociatedChannel = NULL;
  423. BYTE bSessionID;
  424. H323DBG((
  425. DEBUG_LEVEL_TRACE,
  426. "open channel reqest from MSP. hmChannel=0x%08lx.\n",
  427. pRequest->hmChannel
  428. ));
  429. // determine session id from media type
  430. bSessionID = (pRequest->Settings.MediaType == MEDIA_AUDIO)
  431. ? H245_SESSIONID_AUDIO
  432. : H245_SESSIONID_VIDEO
  433. ;
  434. // look for existing session
  435. H323LookupChannelBySessionID(
  436. &pAssociatedChannel,
  437. pCall->pChannelTable,
  438. bSessionID
  439. );
  440. // allocate new channel object
  441. if (!H323AllocChannelFromTable(
  442. &pChannel,
  443. &pCall->pChannelTable,
  444. pCall)) {
  445. H323DBG((
  446. DEBUG_LEVEL_WARNING,
  447. "could not allocate channel hmChannel=0x%08lx.\n",
  448. pRequest->hmChannel
  449. ));
  450. // close the requested channel
  451. H323SendCloseChannelCommand(
  452. pCall,
  453. pRequest->hmChannel,
  454. ERROR_NOT_ENOUGH_MEMORY
  455. );
  456. // failure
  457. return FALSE;
  458. }
  459. // save msp channel handle
  460. pChannel->hmChannel = pRequest->hmChannel;
  461. // initialize common information
  462. pChannel->bSessionID = bSessionID;
  463. pChannel->pCall = pCall;
  464. // examine existing session
  465. if (pAssociatedChannel != NULL) {
  466. H323DBG((
  467. DEBUG_LEVEL_VERBOSE,
  468. "overriding default local RTCP port for session %d\n",
  469. pChannel->bSessionID
  470. ));
  471. // override default RTCP port with existing one
  472. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort =
  473. pAssociatedChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort;
  474. }
  475. // see if outgoing audio requested
  476. if (bSessionID == H245_SESSIONID_AUDIO) {
  477. // transfer capabilities from call object
  478. pChannel->ccTermCaps = pCall->ccRemoteAudioCaps;
  479. // check terminal capabilities for g723
  480. if (pChannel->ccTermCaps.ClientType == H245_CLIENT_AUD_G723) {
  481. // complete stream description structure
  482. pChannel->Settings.MediaType = MEDIA_AUDIO;
  483. pChannel->Settings.dwPayloadType = G723_RTP_PAYLOAD_TYPE;
  484. pChannel->Settings.dwDynamicType = G723_RTP_PAYLOAD_TYPE;
  485. pChannel->Settings.Audio.dwMillisecondsPerPacket =
  486. G723_MILLISECONDS_PER_PACKET(
  487. pChannel->ccTermCaps.Cap.H245Aud_G723.maxAl_sduAudioFrames
  488. );
  489. pChannel->Settings.Audio.G723Settings.bG723LowSpeed =
  490. H323IsSlowLink(pCall->dwLinkSpeed);
  491. H323DBG((
  492. DEBUG_LEVEL_VERBOSE,
  493. "outgoing G723 stream (%d milliseconds).\n",
  494. pChannel->Settings.Audio.dwMillisecondsPerPacket
  495. ));
  496. // open outgoing channel
  497. fOpened = H323OpenChannel(pChannel);
  498. } else if (pChannel->ccTermCaps.ClientType == H245_CLIENT_AUD_G711_ULAW64) {
  499. // complete stream description structure
  500. pChannel->Settings.MediaType = MEDIA_AUDIO;
  501. pChannel->Settings.dwPayloadType = G711U_RTP_PAYLOAD_TYPE;
  502. pChannel->Settings.dwDynamicType = G711U_RTP_PAYLOAD_TYPE;
  503. pChannel->Settings.Audio.dwMillisecondsPerPacket =
  504. G711_MILLISECONDS_PER_PACKET(
  505. pChannel->ccTermCaps.Cap.H245Aud_G711_ULAW64
  506. );
  507. H323DBG((
  508. DEBUG_LEVEL_VERBOSE,
  509. "outgoing G711U stream (%d milliseconds).\n",
  510. pChannel->Settings.Audio.dwMillisecondsPerPacket
  511. ));
  512. // open outgoing channel
  513. fOpened = H323OpenChannel(pChannel);
  514. } else if (pChannel->ccTermCaps.ClientType == H245_CLIENT_AUD_G711_ALAW64) {
  515. // complete stream description structure
  516. pChannel->Settings.MediaType = MEDIA_AUDIO;
  517. pChannel->Settings.dwPayloadType = G711A_RTP_PAYLOAD_TYPE;
  518. pChannel->Settings.dwDynamicType = G711A_RTP_PAYLOAD_TYPE;
  519. pChannel->Settings.Audio.dwMillisecondsPerPacket =
  520. G711_MILLISECONDS_PER_PACKET(
  521. pChannel->ccTermCaps.Cap.H245Aud_G711_ALAW64
  522. );
  523. H323DBG((
  524. DEBUG_LEVEL_VERBOSE,
  525. "outgoing G711A stream (%d milliseconds).\n",
  526. pChannel->Settings.Audio.dwMillisecondsPerPacket
  527. ));
  528. // open outgoing channel
  529. fOpened = H323OpenChannel(pChannel);
  530. }
  531. } else if (bSessionID == H245_SESSIONID_VIDEO) {
  532. // transfer capabilities from call object
  533. pChannel->ccTermCaps = pCall->ccRemoteVideoCaps;
  534. // check terminal capabilities for h263
  535. if (pChannel->ccTermCaps.ClientType == H245_CLIENT_VID_H263) {
  536. DWORD dwFinalMaxBitRate;
  537. DWORD dwStartUpBitRate;
  538. DWORD dwAudioBitRate;
  539. // complete stream description structure
  540. pChannel->Settings.MediaType = MEDIA_VIDEO;
  541. pChannel->Settings.dwPayloadType = H263_RTP_PAYLOAD_TYPE;
  542. pChannel->Settings.dwDynamicType = H263_RTP_PAYLOAD_TYPE;
  543. pChannel->Settings.Video.bCIF = FALSE;
  544. if (pCall->ccRemoteAudioCaps.ClientType == H245_CLIENT_AUD_G723)
  545. {
  546. DWORD dwFramesPerPacket =
  547. pCall->ccRemoteAudioCaps.Cap.H245Aud_G723.maxAl_sduAudioFrames;
  548. dwAudioBitRate =
  549. (TOTAL_HEADER_SIZE + dwFramesPerPacket * G723_BYTES_PER_FRAME)
  550. * CHAR_BIT * 1000 / (dwFramesPerPacket * G723_MILLISECONDS_PER_FRAME);
  551. }
  552. else
  553. {
  554. // Since for other types of audio encoding the
  555. // call to H323ComputeVideoChannelBitRates will have
  556. // no effect, we set the audio bit rate to a dummy
  557. // value.
  558. dwAudioBitRate = H323_MINIMUM_AUDIO_BANDWIDTH;
  559. }
  560. // ajust three percent to make QOS happy.
  561. dwAudioBitRate = dwAudioBitRate * 103 / 100;
  562. H323ComputeVideoChannelBitRates(
  563. pChannel->ccTermCaps.Cap.H245Vid_H263.maxBitRate,
  564. dwAudioBitRate / 100 + 1,
  565. &dwFinalMaxBitRate,
  566. &dwStartUpBitRate
  567. );
  568. pChannel->ccTermCaps.Cap.H245Vid_H263.maxBitRate = dwFinalMaxBitRate;
  569. pChannel->Settings.Video.dwMaxBitRate = dwFinalMaxBitRate * 100;
  570. pChannel->Settings.Video.dwStartUpBitRate = dwStartUpBitRate;
  571. H323DBG((
  572. DEBUG_LEVEL_VERBOSE,
  573. "outgoing H263 stream (%d bps).\n",
  574. pChannel->Settings.Video.dwMaxBitRate
  575. ));
  576. // open outgoing channel
  577. fOpened = H323OpenChannel(pChannel);
  578. } else if (pChannel->ccTermCaps.ClientType == H245_CLIENT_VID_H261) {
  579. DWORD dwFinalMaxBitRate;
  580. DWORD dwStartUpBitRate;
  581. DWORD dwAudioBitRate;
  582. // complete stream description structure
  583. pChannel->Settings.MediaType = MEDIA_VIDEO;
  584. pChannel->Settings.dwPayloadType = H261_RTP_PAYLOAD_TYPE;
  585. pChannel->Settings.dwDynamicType = H261_RTP_PAYLOAD_TYPE;
  586. pChannel->Settings.Video.bCIF = FALSE;
  587. if (pCall->ccRemoteAudioCaps.ClientType == H245_CLIENT_AUD_G723)
  588. {
  589. DWORD dwFramesPerPacket =
  590. pCall->ccRemoteAudioCaps.Cap.H245Aud_G723.maxAl_sduAudioFrames;
  591. dwAudioBitRate =
  592. (TOTAL_HEADER_SIZE + dwFramesPerPacket * G723_BYTES_PER_FRAME)
  593. * CHAR_BIT * 1000 / (dwFramesPerPacket * G723_MILLISECONDS_PER_FRAME);
  594. }
  595. else
  596. {
  597. // Since for other types of audio encoding the
  598. // call to H323ComputeVideoChannelBitRates will have
  599. // no effect, we set the audio bit rate to a dummy
  600. // value.
  601. dwAudioBitRate = H323_MINIMUM_AUDIO_BANDWIDTH;
  602. }
  603. // ajust three percent to make QOS happy.
  604. dwAudioBitRate = dwAudioBitRate * 103 / 100;
  605. H323ComputeVideoChannelBitRates(
  606. (DWORD)pChannel->ccTermCaps.Cap.H245Vid_H261.maxBitRate,
  607. dwAudioBitRate / 100 + 1,
  608. &dwFinalMaxBitRate,
  609. &dwStartUpBitRate
  610. );
  611. pChannel->ccTermCaps.Cap.H245Vid_H261.maxBitRate = (WORD)dwFinalMaxBitRate;
  612. pChannel->Settings.Video.dwMaxBitRate = dwFinalMaxBitRate * 100;
  613. pChannel->Settings.Video.dwStartUpBitRate = dwStartUpBitRate;
  614. H323DBG((
  615. DEBUG_LEVEL_VERBOSE,
  616. "outgoing H261 stream (%d bps).\n",
  617. pChannel->Settings.Video.dwMaxBitRate
  618. ));
  619. // open outgoing channel
  620. fOpened = H323OpenChannel(pChannel);
  621. }
  622. }
  623. // validate
  624. if (!fOpened) {
  625. H323DBG((
  626. DEBUG_LEVEL_WARNING,
  627. "could not open channel hmChannel=0x%08lx.\n",
  628. pRequest->hmChannel
  629. ));
  630. // close the requested channel
  631. H323SendCloseChannelCommand(
  632. pCall,
  633. pRequest->hmChannel,
  634. ERROR_GEN_FAILURE
  635. );
  636. // failure
  637. return FALSE;
  638. }
  639. // success
  640. return TRUE;
  641. }
  642. BOOL
  643. H323ProcessAcceptChannelResponse(
  644. PH323_CALL pCall,
  645. PH323MSG_ACCEPT_CHANNEL_RESPONSE pResponse
  646. )
  647. /*++
  648. Routine Description:
  649. Process command from MSP.
  650. Arguments:
  651. pCall - Specifies a pointer to the call object to process.
  652. pResponse - Specifies a pointer to the command block.
  653. Return Values:
  654. Returns true if successful.
  655. --*/
  656. {
  657. PH323_CHANNEL pChannel = NULL;
  658. H323DBG((
  659. DEBUG_LEVEL_TRACE,
  660. "accept channel response from MSP. hmChannel=0x%08lx. htChannel=0x%08lx.\n",
  661. pResponse->hmChannel,
  662. pResponse->htChannel
  663. ));
  664. // retrieve channel given handle
  665. if (!H323LookupChannelByHandle(
  666. &pChannel,
  667. pCall->pChannelTable,
  668. (CC_HCHANNEL)PtrToUlong(pResponse->htChannel))) {
  669. H323DBG((
  670. DEBUG_LEVEL_ERROR,
  671. "could not accept unknown htChannel 0x%08lx",
  672. pResponse->htChannel
  673. ));
  674. // done
  675. return TRUE;
  676. }
  677. // accept channel
  678. CC_AcceptChannel(
  679. pChannel->hccChannel, // hChannel
  680. &pChannel->ccLocalRTPAddr, // pRTPAddr
  681. &pChannel->ccLocalRTCPAddr, // pRTCPAddr
  682. 0 // dwChannelBitRate
  683. );
  684. H323DBG((
  685. DEBUG_LEVEL_VERBOSE,
  686. "call 0x%08lx accepted htChannel 0x%08lx.\n",
  687. pCall,
  688. pChannel->hccChannel
  689. ));
  690. // change state to opened
  691. pChannel->nState = H323_CHANNELSTATE_OPENED;
  692. // update media modes
  693. H323UpdateMediaModes(pCall);
  694. // success
  695. return TRUE;
  696. }
  697. BOOL
  698. H323ProcessVideoFastUpdatePictureCommand(
  699. PH323_CALL pCall,
  700. PH323MSG_VIDEO_FAST_UPDATE_PICTURE_COMMAND pCommand
  701. )
  702. /*++
  703. Routine Description:
  704. Process I-frame request command from MSP.
  705. Arguments:
  706. pCall - Specifies a pointer to the call object to process.
  707. pCommand - Specifies a pointer to the command block.
  708. Return Values:
  709. Returns TRUE if successful.
  710. --*/
  711. {
  712. PH323_CHANNEL pChannel = NULL;
  713. MiscellaneousCommand h245miscellaneousCommand;
  714. H323DBG((
  715. DEBUG_LEVEL_TRACE,
  716. "MSP->TSP I-frame request. hChannel=0x%08lx.\n",
  717. pCommand->hChannel
  718. ));
  719. h245miscellaneousCommand.type.choice = videoFastUpdatePicture_chosen;
  720. // retrieve channel given handle
  721. if (!H323LookupChannelByHandle(
  722. &pChannel,
  723. pCall->pChannelTable,
  724. (CC_HCHANNEL)PtrToUlong(pCommand->hChannel))) {
  725. H323DBG((
  726. DEBUG_LEVEL_ERROR,
  727. "Could not process MSP->TSP I-frame request. Unknown hChannel 0x%08lx.\n",
  728. pCommand->hChannel
  729. ));
  730. // done
  731. return TRUE;
  732. }
  733. // send H245 Miscellaneous Command to the remote entity
  734. CC_H245MiscellaneousCommand(
  735. pCall->hccCall, // hCall
  736. pChannel->hccChannel, // hChannel
  737. &h245miscellaneousCommand // Command
  738. );
  739. H323DBG((
  740. DEBUG_LEVEL_VERBOSE,
  741. "MSP->TSP I-frame request processed. call 0x%08lx -- hccChannel 0x%08lx. \n",
  742. pCall,
  743. pChannel->hccChannel
  744. ));
  745. // success
  746. return TRUE;
  747. }
  748. BOOL
  749. H323ProcessFlowControlCommand(
  750. PH323_CALL pCall,
  751. PH323MSG_FLOW_CONTROL_COMMAND pCommand
  752. )
  753. /*++
  754. Routine Description:
  755. Process flow control command from MSP.
  756. Arguments:
  757. pCall - Specifies a pointer to the call object to process.
  758. pCommand - Specifies a pointer to the command block.
  759. Return Values:
  760. Returns true if successful.
  761. --*/
  762. {
  763. PH323_CHANNEL pChannel = NULL;
  764. H323DBG((
  765. DEBUG_LEVEL_TRACE,
  766. "MSP->TSP Flow control cmd. hChannel=0x%08lx. Req. rate=%08d.\n",
  767. pCommand->hChannel,
  768. pCommand->dwBitRate
  769. ));
  770. // retrieve channel given handle
  771. if (!H323LookupChannelByHandle(
  772. &pChannel,
  773. pCall->pChannelTable,
  774. (CC_HCHANNEL)PtrToUlong(pCommand->hChannel))) {
  775. H323DBG((
  776. DEBUG_LEVEL_ERROR,
  777. "Could not process MSP->TSP flow control cmd. Unknown hChannel 0x%08lx",
  778. pCommand->hChannel
  779. ));
  780. // done
  781. return TRUE;
  782. }
  783. // send flow control command to the remote entity
  784. CC_FlowControl(
  785. pChannel->hccChannel, // hChannel
  786. pCommand->dwBitRate // requested bit rate, bps
  787. );
  788. H323DBG((
  789. DEBUG_LEVEL_VERBOSE,
  790. "call 0x%08lx -- hccChannel 0x%08lx, MSP->TSP flow control cmd processed.\n",
  791. pCall,
  792. pChannel->hccChannel
  793. ));
  794. // success
  795. return TRUE;
  796. }
  797. BOOL
  798. H323ProcessQoSEventIndication(
  799. PH323_CALL pCall,
  800. PH323MSG_QOS_EVENT pCommand
  801. )
  802. /*++
  803. Routine Description:
  804. Process QoS event indication from MSP.
  805. Arguments:
  806. pCall - Specifies a pointer to the call object to process.
  807. pCommand - Specifies a pointer to the command block.
  808. Return Values:
  809. Returns true if successful.
  810. --*/
  811. {
  812. PH323_CHANNEL pChannel = NULL;
  813. H323DBG((
  814. DEBUG_LEVEL_TRACE,
  815. "MSP->TSP QoS event. htChannel=0x%08lx. dwEvent=%08d.\n",
  816. pCommand->htChannel,
  817. pCommand->dwEvent
  818. ));
  819. // retrieve channel given handle
  820. if (!H323LookupChannelByHandle(
  821. &pChannel,
  822. pCall->pChannelTable,
  823. (CC_HCHANNEL)PtrToUlong(pCommand->htChannel))) {
  824. H323DBG((
  825. DEBUG_LEVEL_ERROR,
  826. "Could not process MSP->TSP QoS event. Unknown htChannel 0x%08lx",
  827. pCommand->htChannel
  828. ));
  829. // done
  830. return TRUE;
  831. }
  832. // report qos event
  833. (*g_pfnLineEventProc)(
  834. pCall->pLine->htLine,
  835. pCall->htCall,
  836. LINE_QOSINFO,
  837. pCommand->dwEvent,
  838. (pChannel->Settings.MediaType == MEDIA_AUDIO)
  839. ? LINEMEDIAMODE_INTERACTIVEVOICE
  840. : LINEMEDIAMODE_VIDEO,
  841. 0
  842. );
  843. // success
  844. return TRUE;
  845. }
  846. BOOL
  847. H323ProcessCloseChannelCommand(
  848. PH323_CALL pCall,
  849. PH323MSG_CLOSE_CHANNEL_COMMAND pCommand
  850. )
  851. /*++
  852. Routine Description:
  853. Process command from MSP.
  854. Arguments:
  855. pCall - Specifies a pointer to the call object to process.
  856. pCommand - Specifies a pointer to the command block.
  857. Return Values:
  858. Returns true if successful.
  859. --*/
  860. {
  861. PH323_CHANNEL pChannel = NULL;
  862. H323DBG((
  863. DEBUG_LEVEL_TRACE,
  864. "close channel command from MSP. htChannel=0x%08lx.\n",
  865. pCommand->hChannel
  866. ));
  867. // retrieve channel given handle
  868. if (!H323LookupChannelByHandle(
  869. &pChannel,
  870. pCall->pChannelTable,
  871. (CC_HCHANNEL)PtrToUlong(pCommand->hChannel))) {
  872. H323DBG((
  873. DEBUG_LEVEL_ERROR,
  874. "could not close unknown htChannel 0x%08lx",
  875. pCommand->hChannel
  876. ));
  877. // done
  878. return TRUE;
  879. }
  880. H323DBG((
  881. DEBUG_LEVEL_WARNING,
  882. "closing htChannel 0x%08lx.\n",
  883. pCommand->hChannel
  884. ));
  885. // close channel
  886. H323CloseChannel(pChannel);
  887. // release channel resources
  888. H323FreeChannelFromTable(pChannel,pCall->pChannelTable);
  889. // success
  890. return TRUE;
  891. }
  892. VOID
  893. H323ProcessPlaceCallMessage(
  894. HDRVCALL hdCall
  895. )
  896. /*++
  897. Routine Description:
  898. Processes async place call messages.
  899. Arguments:
  900. hdCall - Handle to call to be placed.
  901. Return Values:
  902. None.
  903. --*/
  904. {
  905. PH323_CALL pCall = NULL;
  906. H323DBG((
  907. DEBUG_LEVEL_TRACE,
  908. "place call message received (hdCall=0x%08lx).\n",
  909. PtrToUlong(hdCall)
  910. ));
  911. // retrieve call pointer from handle
  912. if (H323GetCallAndLock(&pCall, hdCall)) {
  913. // place outgoing call
  914. if (!H323PlaceCall(pCall)) {
  915. // drop call using disconnect mode
  916. H323DropCall(pCall, LINEDISCONNECTMODE_TEMPFAILURE);
  917. }
  918. // unlock line device
  919. H323UnlockLine(pCall->pLine);
  920. } else {
  921. H323DBG((
  922. DEBUG_LEVEL_ERROR,
  923. "invalid handle in place call message.\n"
  924. ));
  925. }
  926. }
  927. VOID
  928. H323ProcessAcceptCallMessage(
  929. HDRVCALL hdCall
  930. )
  931. /*++
  932. Routine Description:
  933. Processes async accept call messages.
  934. Arguments:
  935. hdCall - Handle to call to be placed.
  936. Return Values:
  937. None.
  938. --*/
  939. {
  940. PH323_CALL pCall = NULL;
  941. H323DBG((
  942. DEBUG_LEVEL_TRACE,
  943. "accept call message received (hdCall=0x%08lx).\n",
  944. PtrToUlong(hdCall)
  945. ));
  946. // retrieve call pointer from handle
  947. if (H323GetCallAndLock(&pCall, hdCall)) {
  948. // place outgoing call
  949. if (!H323AcceptCall(pCall)) {
  950. // drop call using disconnect mode
  951. H323DropCall(pCall, LINEDISCONNECTMODE_TEMPFAILURE);
  952. }
  953. // unlock line device
  954. H323UnlockLine(pCall->pLine);
  955. } else {
  956. H323DBG((
  957. DEBUG_LEVEL_ERROR,
  958. "invalid handle in accept call message.\n"
  959. ));
  960. }
  961. }
  962. VOID
  963. H323ProcessDropCallMessage(
  964. HDRVCALL hdCall,
  965. DWORD dwDisconnectMode
  966. )
  967. /*++
  968. Routine Description:
  969. Processes async drop call messages.
  970. Arguments:
  971. hdCall - Handle to call to be hung up.
  972. dwDisconnectMode - Status to be placed in disconnected message.
  973. Return Values:
  974. None.
  975. --*/
  976. {
  977. PH323_CALL pCall = NULL;
  978. H323DBG((
  979. DEBUG_LEVEL_TRACE,
  980. "drop call message received (hdCall=0x%08lx).\n",
  981. PtrToUlong(hdCall)
  982. ));
  983. // retrieve call pointer from handle
  984. if (H323GetCallAndLock(&pCall, hdCall)) {
  985. // drop call using disconnect code
  986. H323DropCall(pCall, dwDisconnectMode);
  987. // unlock line device
  988. H323UnlockLine(pCall->pLine);
  989. } else {
  990. H323DBG((
  991. DEBUG_LEVEL_ERROR,
  992. "invalid handle in place call message.\n"
  993. ));
  994. }
  995. }
  996. VOID
  997. H323ProcessCloseCallMessage(
  998. HDRVCALL hdCall
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Processes async close call messages.
  1003. Arguments:
  1004. hdCall - Handle to call to be closed.
  1005. Return Values:
  1006. None.
  1007. --*/
  1008. {
  1009. PH323_CALL pCall = NULL;
  1010. H323DBG((
  1011. DEBUG_LEVEL_TRACE,
  1012. "close call message received (hdCall=0x%08lx).\n",
  1013. PtrToUlong(hdCall)
  1014. ));
  1015. // retrieve call pointer from handle
  1016. if (H323GetCallAndLock(&pCall, hdCall)) {
  1017. // close call
  1018. H323CloseCall(pCall);
  1019. // unlock line device
  1020. H323UnlockLine(pCall->pLine);
  1021. } else {
  1022. H323DBG((
  1023. DEBUG_LEVEL_ERROR,
  1024. "invalid handle in place call message.\n"
  1025. ));
  1026. }
  1027. }
  1028. VOID
  1029. H323ProcessCallListenMessage(
  1030. HDRVLINE hdLine
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. Processes async call listen messages.
  1035. Arguments:
  1036. hdLine - Line to be placed into listening state.
  1037. Return Values:
  1038. None.
  1039. --*/
  1040. {
  1041. PH323_LINE pLine = NULL;
  1042. H323DBG((
  1043. DEBUG_LEVEL_TRACE,
  1044. "call listen message received (hdLine=0x%08lx).\n",
  1045. PtrToUlong(hdLine)
  1046. ));
  1047. // retrieve line pointer from handle
  1048. if (H323GetLineAndLock(&pLine, hdLine)) {
  1049. // start listening for calls
  1050. if (!H323CallListen(pLine)) {
  1051. // change state to opened
  1052. pLine->nState = H323_LINESTATE_OPENED;
  1053. }
  1054. // unlock line device
  1055. H323UnlockLine(pLine);
  1056. } else {
  1057. H323DBG((
  1058. DEBUG_LEVEL_ERROR,
  1059. "invalid handle in call listen message.\n"
  1060. ));
  1061. }
  1062. }
  1063. DWORD
  1064. WINAPI
  1065. H323CallbackThread(
  1066. LPVOID pParam
  1067. )
  1068. /*++
  1069. Routine Description:
  1070. Worker thread to handle async operations.
  1071. Arguments:
  1072. pParam - Pointer to opaque thread parameter (unused).
  1073. Return Values:
  1074. Win32 error codes.
  1075. --*/
  1076. {
  1077. MSG msg;
  1078. DWORD dwStatus;
  1079. // associate event with key
  1080. H323ListenForRegistryChanges(
  1081. g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE]
  1082. );
  1083. // loop...
  1084. for (;;) {
  1085. // wait for message or termination
  1086. dwStatus = MsgWaitForMultipleObjectsEx(
  1087. NUM_WAITABLE_OBJECTS,
  1088. g_WaitableObjects,
  1089. INFINITE,
  1090. QS_ALLINPUT,
  1091. MWMO_ALERTABLE
  1092. );
  1093. // see if new message has arrived
  1094. if (dwStatus == WAIT_OBJECT_INCOMING_MESSAGE) {
  1095. // retrieve next item in thread message queue
  1096. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  1097. // handle service provider messages
  1098. if (H323IsPlaceCallMessage(&msg)) {
  1099. // process place call message
  1100. H323ProcessPlaceCallMessage((HDRVCALL)msg.wParam);
  1101. } else if (H323IsAcceptCallMessage(&msg)) {
  1102. // process accept call message
  1103. H323ProcessAcceptCallMessage((HDRVCALL)msg.wParam);
  1104. } else if (H323IsDropCallMessage(&msg)) {
  1105. // process drop call message
  1106. H323ProcessDropCallMessage((HDRVCALL)msg.wParam,(DWORD)msg.lParam);
  1107. } else if (H323IsCloseCallMessage(&msg)) {
  1108. // process close call message
  1109. H323ProcessCloseCallMessage((HDRVCALL)msg.wParam);
  1110. } else if (H323IsCallListenMessage(&msg)) {
  1111. // process call listen message
  1112. H323ProcessCallListenMessage((HDRVLINE)msg.wParam);
  1113. } else {
  1114. // translate message
  1115. TranslateMessage(&msg);
  1116. // dispatch message
  1117. DispatchMessage(&msg);
  1118. }
  1119. }
  1120. } else if (dwStatus == WAIT_OBJECT_REGISTRY_CHANGE) {
  1121. // lock provider
  1122. H323LockProvider();
  1123. // refresh registry settings
  1124. H323GetConfigFromRegistry();
  1125. // associate event with registry key
  1126. H323ListenForRegistryChanges(g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE]);
  1127. // unlock provider
  1128. H323UnlockProvider();
  1129. } else if (dwStatus == WAIT_IO_COMPLETION) {
  1130. H323DBG((
  1131. DEBUG_LEVEL_VERBOSE,
  1132. "callback thread %x io completion.\n",
  1133. g_dwCallbackThreadID
  1134. ));
  1135. } else if (dwStatus == WAIT_OBJECT_TERMINATE_EVENT) {
  1136. H323DBG((
  1137. DEBUG_LEVEL_TRACE,
  1138. "callback thread %x terminating on command.\n",
  1139. g_dwCallbackThreadID
  1140. ));
  1141. break; // bail...
  1142. } else {
  1143. H323DBG((
  1144. DEBUG_LEVEL_TRACE,
  1145. "callback thread %x terminating (dwStatus=0x%08lx).\n",
  1146. g_dwCallbackThreadID,
  1147. dwStatus
  1148. ));
  1149. break; // bail...
  1150. }
  1151. }
  1152. // stop listening for registry changes
  1153. H323StopListeningForRegistryChanges();
  1154. H323DBG((
  1155. DEBUG_LEVEL_VERBOSE,
  1156. "callback thread %x exiting.\n",
  1157. g_dwCallbackThreadID
  1158. ));
  1159. // success
  1160. return NOERROR;
  1161. }
  1162. DWORD
  1163. H323RejectReasonToDisconnectMode(
  1164. BYTE bRejectReason
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. Converts connect reject reason to tapi disconnect mode.
  1169. Arguments:
  1170. bRejectReason - Specifies reason peer rejected call.
  1171. Return Values:
  1172. Returns disconnect mode corresponding to reject reason.
  1173. --*/
  1174. {
  1175. H323DBG((
  1176. DEBUG_LEVEL_VERBOSE,
  1177. "Reject Reason: %s.\n",
  1178. CCRejectReasonToString((DWORD)bRejectReason)
  1179. ));
  1180. // determine reject reason
  1181. switch (bRejectReason) {
  1182. case CC_REJECT_NORMAL_CALL_CLEARING:
  1183. // call was terminated normally
  1184. return LINEDISCONNECTMODE_NORMAL;
  1185. case CC_REJECT_UNREACHABLE_DESTINATION:
  1186. // remote user could not be reached
  1187. return LINEDISCONNECTMODE_UNREACHABLE;
  1188. case CC_REJECT_DESTINATION_REJECTION:
  1189. // remote user has rejected the call
  1190. return LINEDISCONNECTMODE_REJECT;
  1191. case CC_REJECT_USER_BUSY:
  1192. // remote user's station is busy
  1193. return LINEDISCONNECTMODE_BUSY;
  1194. case CC_REJECT_NO_ANSWER:
  1195. // remote user's station does not answer
  1196. return LINEDISCONNECTMODE_NOANSWER;
  1197. case CC_REJECT_BAD_FORMAT_ADDRESS:
  1198. // destination address in invalid
  1199. return LINEDISCONNECTMODE_BADADDRESS;
  1200. default:
  1201. // reason for the disconnect is unavailable
  1202. return LINEDISCONNECTMODE_UNAVAIL;
  1203. }
  1204. }
  1205. BOOL
  1206. H323GetTermCapById(
  1207. H245_CAPID_T CapId,
  1208. PCC_TERMCAPLIST pTermCapList,
  1209. PCC_TERMCAP * ppTermCap
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. Retrieve pointer to termcap from list via id.
  1214. Arguments:
  1215. CapId - Id of termcap of interest.
  1216. pTermCapList - Pointer to termcap list.
  1217. ppTermCap - Pointer to place to copy termcap pointer.
  1218. Return Values:
  1219. Returns TRUE if successful.
  1220. --*/
  1221. {
  1222. WORD wIndex;
  1223. PCC_TERMCAP pTermCap;
  1224. // walk caps
  1225. for (wIndex = 0; wIndex < pTermCapList->wLength; wIndex++) {
  1226. // compare id with the next item in the list
  1227. if (pTermCapList->pTermCapArray[wIndex]->CapId == CapId) {
  1228. // return pointer
  1229. *ppTermCap = pTermCapList->pTermCapArray[wIndex];
  1230. // success
  1231. return TRUE;
  1232. }
  1233. }
  1234. // failure
  1235. return FALSE;
  1236. }
  1237. BOOL
  1238. H323GetTermCapByType(
  1239. H245_DATA_T DataType,
  1240. H245_CLIENT_T ClientType,
  1241. PCC_TERMCAPLIST pTermCapList,
  1242. PCC_TERMCAP * ppTermCap
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. Retrieve pointer to termcap from list via id.
  1247. Arguments:
  1248. DataType - Type of capability.
  1249. ClientType - Type of media-specific cabability.
  1250. pTermCapList - Pointer to termcap list.
  1251. ppTermCap - Pointer to place to copy termcap pointer.
  1252. Return Values:
  1253. Returns TRUE if successful.
  1254. --*/
  1255. {
  1256. WORD wIndex;
  1257. PCC_TERMCAP pTermCap;
  1258. // walk caps
  1259. for (wIndex = 0; wIndex < pTermCapList->wLength; wIndex++) {
  1260. // compare id with the next item in the list
  1261. if ((pTermCapList->pTermCapArray[wIndex]->DataType == DataType) &&
  1262. (pTermCapList->pTermCapArray[wIndex]->ClientType == ClientType)) {
  1263. // return pointer
  1264. *ppTermCap = pTermCapList->pTermCapArray[wIndex];
  1265. // success
  1266. return TRUE;
  1267. }
  1268. }
  1269. // failure
  1270. return FALSE;
  1271. }
  1272. BOOL
  1273. H323SavePreferredTermCap(
  1274. PH323_CALL pCall,
  1275. PCC_TERMCAP pLocalCap,
  1276. PCC_TERMCAP pRemoteCap
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. Save remote cap adjusted for outgoing settings.
  1281. Arguments:
  1282. pCall - Pointer to call object.
  1283. pLocalCap - Pointer to local capability.
  1284. pRemoteCap - Pointer to termcap to save.
  1285. Return Values:
  1286. Returns TRUE if both audio and video termcaps resolved.
  1287. --*/
  1288. {
  1289. PCC_TERMCAP pPreferredCap;
  1290. WORD wMillisecondsPerPacket;
  1291. // retrieve pointer to stored termcap preferences
  1292. pPreferredCap = H323IsValidAudioClientType(pRemoteCap->ClientType)
  1293. ? &pCall->ccRemoteAudioCaps
  1294. : &pCall->ccRemoteVideoCaps
  1295. ;
  1296. // make sure we have not already saved preferred type
  1297. if (H323IsValidClientType(pPreferredCap->ClientType)) {
  1298. H323DBG((
  1299. DEBUG_LEVEL_VERBOSE,
  1300. "call 0x%08lx ignoring remote cap %d\n",
  1301. pCall,
  1302. pRemoteCap->CapId
  1303. ));
  1304. // failure
  1305. return FALSE;
  1306. }
  1307. H323DBG((
  1308. DEBUG_LEVEL_VERBOSE,
  1309. "call 0x%08lx saving remote cap %d\n",
  1310. pCall,
  1311. pRemoteCap->CapId
  1312. ));
  1313. // modify preferred caps
  1314. *pPreferredCap = *pLocalCap;
  1315. // reverse capability direction
  1316. pPreferredCap->Dir = H245_CAPDIR_LCLTX;
  1317. // determine client type
  1318. switch (pPreferredCap->ClientType) {
  1319. case H245_CLIENT_AUD_G723:
  1320. // determine packet size
  1321. wMillisecondsPerPacket =
  1322. H323IsSlowLink(pCall->dwLinkSpeed)
  1323. ? G723_SLOWLNK_MILLISECONDS_PER_PACKET
  1324. : G723_DEFAULT_MILLISECONDS_PER_PACKET
  1325. ;
  1326. // adjust default parameters for link speed
  1327. pPreferredCap->Cap.H245Aud_G723.maxAl_sduAudioFrames =
  1328. G723_FRAMES_PER_PACKET(wMillisecondsPerPacket)
  1329. ;
  1330. // see if remote maximum less than default
  1331. if (pRemoteCap->Cap.H245Aud_G723.maxAl_sduAudioFrames <
  1332. pPreferredCap->Cap.H245Aud_G723.maxAl_sduAudioFrames) {
  1333. // use remote maximum instead of default
  1334. pPreferredCap->Cap.H245Aud_G723.maxAl_sduAudioFrames =
  1335. pRemoteCap->Cap.H245Aud_G723.maxAl_sduAudioFrames
  1336. ;
  1337. }
  1338. break;
  1339. case H245_CLIENT_AUD_G711_ULAW64:
  1340. // store default parameters
  1341. pPreferredCap->Cap.H245Aud_G711_ULAW64 =
  1342. G711_FRAMES_PER_PACKET(
  1343. G711_DEFAULT_MILLISECONDS_PER_PACKET
  1344. );
  1345. // see if remote maximum less than default
  1346. if (pRemoteCap->Cap.H245Aud_G711_ULAW64 <
  1347. pPreferredCap->Cap.H245Aud_G711_ULAW64) {
  1348. // use remote maximum instead of default
  1349. pPreferredCap->Cap.H245Aud_G711_ULAW64 =
  1350. pRemoteCap->Cap.H245Aud_G711_ULAW64
  1351. ;
  1352. }
  1353. break;
  1354. case H245_CLIENT_AUD_G711_ALAW64:
  1355. // store default parameters
  1356. pPreferredCap->Cap.H245Aud_G711_ALAW64 =
  1357. G711_FRAMES_PER_PACKET(
  1358. G711_DEFAULT_MILLISECONDS_PER_PACKET
  1359. );
  1360. // see if remote maximum less than default
  1361. if (pRemoteCap->Cap.H245Aud_G711_ALAW64 <
  1362. pPreferredCap->Cap.H245Aud_G711_ALAW64) {
  1363. // use remote maximum instead of default
  1364. pPreferredCap->Cap.H245Aud_G711_ALAW64 =
  1365. pRemoteCap->Cap.H245Aud_G711_ALAW64
  1366. ;
  1367. }
  1368. break;
  1369. case H245_CLIENT_VID_H263:
  1370. // see if remote maximum less than local
  1371. if (pRemoteCap->Cap.H245Vid_H263.maxBitRate <
  1372. pPreferredCap->Cap.H245Vid_H263.maxBitRate) {
  1373. // use remote maximum instead of local
  1374. pPreferredCap->Cap.H245Vid_H263.maxBitRate =
  1375. pRemoteCap->Cap.H245Vid_H263.maxBitRate
  1376. ;
  1377. }
  1378. break;
  1379. case H245_CLIENT_VID_H261:
  1380. // see if remote maximum less than local
  1381. if (pRemoteCap->Cap.H245Vid_H261.maxBitRate <
  1382. pPreferredCap->Cap.H245Vid_H261.maxBitRate) {
  1383. // use remote maximum instead of local
  1384. pPreferredCap->Cap.H245Vid_H261.maxBitRate =
  1385. pRemoteCap->Cap.H245Vid_H261.maxBitRate
  1386. ;
  1387. }
  1388. break;
  1389. }
  1390. // return success if we have resolved both audio and video caps
  1391. return (H323IsValidClientType(pCall->ccRemoteAudioCaps.ClientType) &&
  1392. H323IsValidClientType(pCall->ccRemoteVideoCaps.ClientType));
  1393. }
  1394. VOID
  1395. H323GetPreferedTransmitTypes(
  1396. PCC_TERMCAPDESCRIPTORS pTermCapDescriptors,
  1397. H245_CLIENT_T *pPreferredAudioType,
  1398. H245_CLIENT_T *pPreferredVideoType
  1399. )
  1400. /*++
  1401. Routine Description:
  1402. Find the preferred audio and video format in the local terminal capability
  1403. descriptors array if they exist.
  1404. Arguments:
  1405. pTermCapDescriptors - pointer to the local terminal capability descriptor.
  1406. pPreferredAudioType - return the preferred audio type.
  1407. pPreferredVideoType - return the preferred video type.
  1408. Return Values:
  1409. NONE
  1410. --*/
  1411. {
  1412. WORD wDescIndex;
  1413. WORD wSimCapIndex;
  1414. WORD wAltCapIndex;
  1415. // process descriptors
  1416. for (wDescIndex = 0; wDescIndex < pTermCapDescriptors->wLength; wDescIndex++)
  1417. {
  1418. H245_TOTCAPDESC_T * pTotCapDesc;
  1419. // retrieve pointer to capability structure
  1420. pTotCapDesc = pTermCapDescriptors->pTermCapDescriptorArray[wDescIndex];
  1421. // process simultaneous caps
  1422. for (wSimCapIndex = 0; wSimCapIndex < pTotCapDesc->CapDesc.Length; wSimCapIndex++)
  1423. {
  1424. H245_SIMCAP_T * pSimCap;
  1425. // retrieve pointer to simulateous cap
  1426. pSimCap = &pTotCapDesc->CapDesc.SimCapArray[wSimCapIndex];
  1427. if (pSimCap->Length > 0)
  1428. {
  1429. // the first one in the altcaps array is the preferred one.
  1430. switch (pSimCap->AltCaps[0])
  1431. {
  1432. case H245_TERMCAPID_G723:
  1433. *pPreferredAudioType = H245_CLIENT_AUD_G723;
  1434. break;
  1435. case H245_TERMCAPID_H263:
  1436. *pPreferredVideoType = H245_CLIENT_VID_H263;
  1437. break;
  1438. case H245_TERMCAPID_G711_ULAW64:
  1439. *pPreferredAudioType = H245_CLIENT_AUD_G711_ULAW64;
  1440. break;
  1441. case H245_TERMCAPID_G711_ALAW64:
  1442. *pPreferredAudioType = H245_CLIENT_AUD_G711_ALAW64;
  1443. break;
  1444. case H245_TERMCAPID_H261:
  1445. *pPreferredVideoType = H245_CLIENT_VID_H261;
  1446. break;
  1447. }
  1448. }
  1449. }
  1450. }
  1451. }
  1452. BOOL
  1453. H323ProcessRemoteTermCaps(
  1454. PH323_CALL pCall,
  1455. PCC_TERMCAPLIST pRemoteTermCapList,
  1456. PCC_TERMCAPDESCRIPTORS pRemoteTermCapDescriptors
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. Process remote capabilities and establish outgoing termcaps.
  1461. Arguments:
  1462. pCall - Pointer to call object.
  1463. pRemoteTermCapList - Pointer to termcap list.
  1464. pRemoteTermCapDescriptors - Pointer to descriptor list.
  1465. Return Values:
  1466. Returns TRUE if successful.
  1467. --*/
  1468. {
  1469. WORD wDescIndex;
  1470. WORD wSimCapIndex;
  1471. WORD wAltCapIndex;
  1472. PCC_TERMCAP pLocalCap = NULL;
  1473. PCC_TERMCAP pRemoteCap = NULL;
  1474. CC_TERMCAPLIST LocalTermCapList;
  1475. CC_TERMCAPDESCRIPTORS LocalTermCapDescriptors;
  1476. CC_TERMCAP SavedAudioCap;
  1477. CC_TERMCAP SavedVideoCap;
  1478. H245_CLIENT_T PreferredAudioType = H245_CLIENT_DONTCARE;
  1479. H245_CLIENT_T PreferredVideoType = H245_CLIENT_DONTCARE;
  1480. // initialize cached termcaps
  1481. memset(&SavedAudioCap,0,sizeof(CC_TERMCAP));
  1482. memset(&SavedVideoCap,0,sizeof(CC_TERMCAP));
  1483. // retrieve local caps
  1484. H323GetTermCapList(pCall,&LocalTermCapList,&LocalTermCapDescriptors);
  1485. H323GetPreferedTransmitTypes(
  1486. &LocalTermCapDescriptors,
  1487. &PreferredAudioType,
  1488. &PreferredVideoType
  1489. );
  1490. // look for our preferred audio format.
  1491. if (PreferredAudioType != H245_CLIENT_DONTCARE)
  1492. {
  1493. // look for match
  1494. if (H323GetTermCapByType(H245_DATA_AUDIO, PreferredAudioType,
  1495. pRemoteTermCapList, &pRemoteCap )
  1496. && H323GetTermCapByType(H245_DATA_AUDIO, PreferredAudioType,
  1497. &LocalTermCapList, &pLocalCap ))
  1498. {
  1499. // adjust termcaps and save
  1500. if (H323SavePreferredTermCap(
  1501. pCall,
  1502. pLocalCap,
  1503. pRemoteCap
  1504. ))
  1505. {
  1506. //
  1507. // The function above will only return
  1508. // true when both audio and video caps
  1509. // have been successfully resolved.
  1510. //
  1511. return TRUE;
  1512. }
  1513. }
  1514. }
  1515. // look for our preferred video format.
  1516. if (PreferredVideoType != H245_CLIENT_DONTCARE)
  1517. {
  1518. // look for match
  1519. if (H323GetTermCapByType(H245_DATA_VIDEO, PreferredVideoType,
  1520. pRemoteTermCapList, &pRemoteCap )
  1521. && H323GetTermCapByType(H245_DATA_VIDEO, PreferredVideoType,
  1522. &LocalTermCapList, &pLocalCap ))
  1523. {
  1524. // adjust termcaps and save
  1525. if (H323SavePreferredTermCap(
  1526. pCall,
  1527. pLocalCap,
  1528. pRemoteCap
  1529. ))
  1530. {
  1531. //
  1532. // The function above will only return
  1533. // true when both audio and video caps
  1534. // have been successfully resolved.
  1535. //
  1536. return TRUE;
  1537. }
  1538. }
  1539. }
  1540. // process descriptors
  1541. for (wDescIndex = 0;
  1542. wDescIndex < pRemoteTermCapDescriptors->wLength;
  1543. wDescIndex++) {
  1544. H245_TOTCAPDESC_T * pTotCapDesc;
  1545. // retrieve pointer to capability structure
  1546. pTotCapDesc = pRemoteTermCapDescriptors->pTermCapDescriptorArray[wDescIndex];
  1547. H323DBG((
  1548. DEBUG_LEVEL_VERBOSE,
  1549. "call 0x%08lx processing CapDescId %d\n",
  1550. pCall,
  1551. pTotCapDesc->CapDescId
  1552. ));
  1553. // process simultaneous caps
  1554. for (wSimCapIndex = 0;
  1555. wSimCapIndex < pTotCapDesc->CapDesc.Length;
  1556. wSimCapIndex++) {
  1557. H245_SIMCAP_T * pSimCap;
  1558. // retrieve pointer to simulateous cap
  1559. pSimCap = &pTotCapDesc->CapDesc.SimCapArray[wSimCapIndex];
  1560. H323DBG((
  1561. DEBUG_LEVEL_VERBOSE,
  1562. "call 0x%08lx processing SimCap %d\n",
  1563. pCall,
  1564. wSimCapIndex + 1
  1565. ));
  1566. // process alternative caps
  1567. for (wAltCapIndex = 0;
  1568. wAltCapIndex < pSimCap->Length;
  1569. wAltCapIndex++) {
  1570. H245_CAPID_T CapId;
  1571. // re-initialize
  1572. pRemoteCap = NULL;
  1573. // retrieve alternative capid
  1574. CapId = pSimCap->AltCaps[wAltCapIndex];
  1575. H323DBG((
  1576. DEBUG_LEVEL_VERBOSE,
  1577. "call 0x%08lx processing AltCapId %d\n",
  1578. pCall,
  1579. CapId
  1580. ));
  1581. // lookup termcap from id
  1582. if (H323GetTermCapById(
  1583. CapId,
  1584. pRemoteTermCapList,
  1585. &pRemoteCap
  1586. )) {
  1587. H323DBG((
  1588. DEBUG_LEVEL_VERBOSE,
  1589. "call 0x%08lx examining remote cap %d:\n\t%s\n\t%s\n\t%s\n",
  1590. pCall,
  1591. pRemoteCap->CapId,
  1592. H323DirToString(pRemoteCap->Dir),
  1593. H323DataTypeToString(pRemoteCap->DataType),
  1594. H323ClientTypeToString(pRemoteCap->ClientType)
  1595. ));
  1596. // validate remote termcap and check priority
  1597. if (H323IsReceiveCapability(pRemoteCap->Dir)) {
  1598. // re-initialize
  1599. pLocalCap = NULL;
  1600. // look for match
  1601. if (H323GetTermCapByType(
  1602. pRemoteCap->DataType,
  1603. pRemoteCap->ClientType,
  1604. &LocalTermCapList,
  1605. &pLocalCap
  1606. )) {
  1607. // adjust termcaps and save
  1608. if (H323SavePreferredTermCap(
  1609. pCall,
  1610. pLocalCap,
  1611. pRemoteCap
  1612. )) {
  1613. //
  1614. // The function above will only return
  1615. // true when both audio and video caps
  1616. // have been successfully resolved.
  1617. //
  1618. return TRUE;
  1619. }
  1620. }
  1621. }
  1622. }
  1623. }
  1624. }
  1625. // see if we discovered any audio-only caps we would like to save
  1626. if (H323IsValidClientType(pCall->ccRemoteAudioCaps.ClientType) &&
  1627. !H323IsValidClientType(SavedAudioCap.ClientType)) {
  1628. // save discovered audio-only cap
  1629. SavedAudioCap = pCall->ccRemoteAudioCaps;
  1630. // reset video-only cap (prefer audio-only)
  1631. memset(&SavedVideoCap,0,sizeof(CC_TERMCAP));
  1632. }
  1633. // see if we discovered any video-only caps we would like to save
  1634. if (H323IsValidClientType(pCall->ccRemoteVideoCaps.ClientType) &&
  1635. !H323IsValidClientType(SavedAudioCap.ClientType)) {
  1636. // save video-only cap (only if no saved audio-only cap)
  1637. SavedVideoCap = pCall->ccRemoteVideoCaps;
  1638. }
  1639. // reset capability stored in call for next iteration
  1640. memset(&pCall->ccRemoteAudioCaps,0,sizeof(CC_TERMCAP));
  1641. memset(&pCall->ccRemoteVideoCaps,0,sizeof(CC_TERMCAP));
  1642. }
  1643. // see if we saved any audio-only capabilities
  1644. if (H323IsValidClientType(SavedAudioCap.ClientType)) {
  1645. // restore saved audio-only capabilities
  1646. pCall->ccRemoteAudioCaps = SavedAudioCap;
  1647. // success
  1648. return TRUE;
  1649. }
  1650. // see if we saved any video-only capabilities
  1651. if (H323IsValidClientType(SavedVideoCap.ClientType)) {
  1652. // restore saved video-only capabilities
  1653. pCall->ccRemoteVideoCaps = SavedVideoCap;
  1654. // success
  1655. return TRUE;
  1656. }
  1657. // failure
  1658. return FALSE;
  1659. }
  1660. HRESULT
  1661. H323ConnectCallback(
  1662. PH323_CALL pCall,
  1663. HRESULT hrConf,
  1664. PCC_CONNECT_CALLBACK_PARAMS pCallbackParams
  1665. )
  1666. /*++
  1667. Routine Description:
  1668. Callback for connect indications.
  1669. Arguments:
  1670. pCall - Pointer to call object.
  1671. hrConf - Current status of H.323 conference.
  1672. pCallbackParams - Parameters returned by call control module.
  1673. Return Values:
  1674. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  1675. --*/
  1676. {
  1677. DWORD dwDisconnectMode;
  1678. PH323_CHANNEL pChannel = NULL;
  1679. BOOL bRemoteVideoSupported;
  1680. DWORD dwRemoteVideoBitRate;
  1681. WORD wRemoteMaxAl_sduAudioFrames;
  1682. // validate status
  1683. if (hrConf != CC_OK) {
  1684. H323DBG((
  1685. DEBUG_LEVEL_ERROR,
  1686. "error %s (0x%08lx) connecting call 0x%08lx.\n",
  1687. H323StatusToString(hrConf), hrConf,
  1688. pCall
  1689. ));
  1690. // see if we timed out
  1691. if (hrConf == MAKE_WINSOCK_ERROR(WSAETIMEDOUT)) {
  1692. // if so, report it as an unreachable destination
  1693. dwDisconnectMode = LINEDISCONNECTMODE_UNREACHABLE;
  1694. } else if (hrConf == CC_PEER_REJECT) {
  1695. // translate reject code into failure
  1696. dwDisconnectMode = H323RejectReasonToDisconnectMode(
  1697. pCallbackParams->bRejectReason
  1698. );
  1699. } else {
  1700. // default to temp failure
  1701. dwDisconnectMode = LINEDISCONNECTMODE_TEMPFAILURE;
  1702. }
  1703. // drop call using disconnect mode
  1704. H323DropCall(pCall, dwDisconnectMode);
  1705. // release line device
  1706. H323UnlockLine(pCall->pLine);
  1707. // processed
  1708. return CC_OK;
  1709. }
  1710. // send msp new call indication
  1711. H323SendNewCallIndication(pCall);
  1712. // process remote terminal capabilities
  1713. if ((pCallbackParams->pTermCapList != NULL) &&
  1714. (pCallbackParams->pTermCapDescriptors != NULL)) {
  1715. // process capabilirties
  1716. H323ProcessRemoteTermCaps(
  1717. pCall,
  1718. pCallbackParams->pTermCapList,
  1719. pCallbackParams->pTermCapDescriptors
  1720. );
  1721. }
  1722. // By this time remote capabilities have been discovered.
  1723. // Thus, we can classify the call as a 'FastLink' call, if
  1724. // both local and remote links are LAN connections; or as a
  1725. // 'SlowLink' call otherwise.
  1726. // Using this classification we then determine the length of
  1727. // the interval of audio signal to be packed into one IP
  1728. // packet.
  1729. bRemoteVideoSupported = FALSE;
  1730. // Determine remote side video bit rate, in case it
  1731. // supports video in one of the recognizable formats
  1732. switch (pCall->ccRemoteVideoCaps.ClientType)
  1733. {
  1734. case H245_CLIENT_VID_H263:
  1735. dwRemoteVideoBitRate =
  1736. pCall->ccRemoteVideoCaps.Cap.H245Vid_H263.maxBitRate;
  1737. bRemoteVideoSupported = TRUE;
  1738. break;
  1739. case H245_CLIENT_VID_H261:
  1740. dwRemoteVideoBitRate =
  1741. pCall->ccRemoteVideoCaps.Cap.H245Vid_H261.maxBitRate;
  1742. bRemoteVideoSupported = TRUE;
  1743. break;
  1744. default:
  1745. // Remote side either does not support video, or
  1746. // supports unrecognizable video format
  1747. bRemoteVideoSupported = FALSE;
  1748. break;
  1749. }
  1750. // If the remote end supports video in one of the recognizable
  1751. // formats, then we can guess, based on the remote video bit rate
  1752. // capability, whether it sits on a slow link or not.
  1753. if ( bRemoteVideoSupported
  1754. && H323IsSlowLink(dwRemoteVideoBitRate * 100)){
  1755. // Remote end has slow link. Adjust the number of
  1756. // milliseconds of audio signal per packet.
  1757. // Note that if the local end has slow link, the
  1758. // adjustment has already been made, but there is
  1759. // no harm in resetting the number.
  1760. if (pCall->ccRemoteAudioCaps.ClientType == H245_CLIENT_AUD_G723){
  1761. // recalculate new setting
  1762. wRemoteMaxAl_sduAudioFrames =
  1763. G723_FRAMES_PER_PACKET(G723_SLOWLNK_MILLISECONDS_PER_PACKET);
  1764. // see if new setting less than current
  1765. if (wRemoteMaxAl_sduAudioFrames <
  1766. pCall->ccRemoteAudioCaps.Cap.H245Aud_G723.maxAl_sduAudioFrames){
  1767. // use new setting instead of current
  1768. pCall->ccRemoteAudioCaps.Cap.H245Aud_G723.maxAl_sduAudioFrames =
  1769. wRemoteMaxAl_sduAudioFrames;
  1770. }
  1771. }
  1772. }
  1773. // see if user user information specified
  1774. if ((pCallbackParams->pNonStandardData != NULL) &&
  1775. H323IsValidU2U(pCallbackParams->pNonStandardData)) {
  1776. // add user user info
  1777. if (H323AddU2U(
  1778. &pCall->IncomingU2U,
  1779. pCallbackParams->pNonStandardData->sData.wOctetStringLength,
  1780. pCallbackParams->pNonStandardData->sData.pOctetString
  1781. )) {
  1782. H323DBG((
  1783. DEBUG_LEVEL_VERBOSE,
  1784. "user user info available in CONNECT PDU.\n"
  1785. ));
  1786. // signal incoming
  1787. (*g_pfnLineEventProc)(
  1788. pCall->pLine->htLine,
  1789. pCall->htCall,
  1790. LINE_CALLINFO,
  1791. LINECALLINFOSTATE_USERUSERINFO,
  1792. 0,
  1793. 0
  1794. );
  1795. } else {
  1796. H323DBG((
  1797. DEBUG_LEVEL_WARNING,
  1798. "could not save incoming user user info.\n"
  1799. ));
  1800. }
  1801. }
  1802. H323DBG((
  1803. DEBUG_LEVEL_TRACE,
  1804. "call 0x%08lx connected to %S.\n",
  1805. pCall,
  1806. pCallbackParams->pszPeerDisplay
  1807. ));
  1808. // no outgoing channels so connect
  1809. H323ChangeCallState(pCall, LINECALLSTATE_CONNECTED, 0);
  1810. // release line device
  1811. H323UnlockLine(pCall->pLine);
  1812. // processed
  1813. return CC_OK;
  1814. }
  1815. HRESULT
  1816. H323RingingCallback(
  1817. PH323_CALL pCall
  1818. )
  1819. /*++
  1820. Routine Description:
  1821. Callback for ringing indications.
  1822. Arguments:
  1823. pCall - Pointer to call object.
  1824. Return Values:
  1825. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  1826. --*/
  1827. {
  1828. H323DBG((
  1829. DEBUG_LEVEL_VERBOSE,
  1830. "call 0x%08x ringing.\n",
  1831. pCall
  1832. ));
  1833. // change state to ringback
  1834. H323ChangeCallState(pCall, LINECALLSTATE_RINGBACK, 0);
  1835. // release line device
  1836. H323UnlockLine(pCall->pLine);
  1837. // processed
  1838. return CC_OK;
  1839. }
  1840. HRESULT
  1841. H323TerminationCallback(
  1842. PH323_CALL pCall,
  1843. HRESULT hrConf,
  1844. PCC_CONFERENCE_TERMINATION_CALLBACK_PARAMS pCallbackParams
  1845. )
  1846. /*++
  1847. Routine Description:
  1848. Callback for termination indications.
  1849. Arguments:
  1850. pCall - Pointer to call object.
  1851. hrConf - Current status of H.323 conference.
  1852. pCallbackParams - Parameters returned by call control module.
  1853. Return Values:
  1854. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  1855. --*/
  1856. {
  1857. DWORD dwDisconnectMode;
  1858. // validate status
  1859. if (hrConf == CC_OK) {
  1860. H323DBG((
  1861. DEBUG_LEVEL_ERROR,
  1862. "call 0x%08lx is being terminated.\n",
  1863. pCall
  1864. ));
  1865. // set disconnect mode to normal
  1866. dwDisconnectMode = LINEDISCONNECTMODE_NORMAL;
  1867. } else {
  1868. H323DBG((
  1869. DEBUG_LEVEL_ERROR,
  1870. "call 0x%08lx could not be terminated.\n",
  1871. pCall
  1872. ));
  1873. // unable to determine disconnect mode
  1874. dwDisconnectMode = LINEDISCONNECTMODE_UNKNOWN;
  1875. }
  1876. // change call state to disconnected before dropping call
  1877. H323ChangeCallState(pCall, LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
  1878. // drop call using disconnect mode
  1879. H323DropCall(pCall, dwDisconnectMode);
  1880. // release line device
  1881. H323UnlockLine(pCall->pLine);
  1882. // processed
  1883. return CC_OK;
  1884. }
  1885. HRESULT
  1886. H323RxChannelRequestCallback(
  1887. PH323_CALL pCall,
  1888. HRESULT hrConf,
  1889. PCC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS pCallbackParams
  1890. )
  1891. /*++
  1892. Routine Description:
  1893. Callback for channel request indications.
  1894. Arguments:
  1895. pCall - Pointer to call object.
  1896. hrConf - Current status of H.323 conference.
  1897. pCallbackParams - Parameters returned by call control module.
  1898. Return Values:
  1899. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  1900. --*/
  1901. {
  1902. HRESULT hr;
  1903. DWORD dwIndex;
  1904. DWORD dwRejectReason;
  1905. CC_TERMCAPLIST TermCapList;
  1906. CC_TERMCAPDESCRIPTORS TermCapDescriptors;
  1907. PCC_TERMCAP pRemoteCap;
  1908. PCC_TERMCAP pLocalCap = NULL;
  1909. PH323_CHANNEL pChannel = NULL;
  1910. PH323_CHANNEL pAssociatedChannel = NULL;
  1911. #if DBG
  1912. DWORD dwIPAddr;
  1913. #endif
  1914. // retrieve pointer to capabilities structure
  1915. pRemoteCap = pCallbackParams->pChannelCapability;
  1916. H323DBG((
  1917. DEBUG_LEVEL_VERBOSE,
  1918. "call 0x%08lx incoming channel:\n\t%s\n\t%s\n\t%s\n",
  1919. pCall,
  1920. H323DirToString(pRemoteCap->Dir),
  1921. H323DataTypeToString(pRemoteCap->DataType),
  1922. H323ClientTypeToString(pRemoteCap->ClientType)
  1923. ));
  1924. // validate data and client type
  1925. if (!H323IsValidDataType(pRemoteCap->DataType)) {
  1926. H323DBG((
  1927. DEBUG_LEVEL_ERROR,
  1928. "channel rejected invalid type(s).\n"
  1929. ));
  1930. // initialize reject reason
  1931. dwRejectReason = H245_REJ_TYPE_UNKNOWN;
  1932. // bail...
  1933. goto reject;
  1934. }
  1935. // see whether incoming channel is available
  1936. if (H323IsVideoDataType(pRemoteCap->DataType) &&
  1937. !H323IsVideoRequested(pCall)) {
  1938. H323DBG((
  1939. DEBUG_LEVEL_ERROR,
  1940. "channel rejected video not enabled.\n"
  1941. ));
  1942. // initialize reject reason
  1943. dwRejectReason = H245_REJ_TYPE_NOTAVAIL;
  1944. // bail...
  1945. goto reject;
  1946. } else if (H323IsAudioDataType(pRemoteCap->DataType) &&
  1947. !H323IsAudioRequested(pCall)) {
  1948. H323DBG((
  1949. DEBUG_LEVEL_ERROR,
  1950. "channel rejected audio not enabled.\n"
  1951. ));
  1952. // initialize reject reason
  1953. dwRejectReason = H245_REJ_TYPE_NOTAVAIL;
  1954. // bail...
  1955. goto reject;
  1956. }
  1957. // retrieve local caps
  1958. H323GetTermCapList(pCall,&TermCapList,&TermCapDescriptors);
  1959. // search term cap list for incoming cap
  1960. for (dwIndex = 0; dwIndex < TermCapList.wLength; dwIndex++) {
  1961. // see if local cap matchs incoming channel cap
  1962. if (TermCapList.pTermCapArray[dwIndex]->ClientType ==
  1963. pRemoteCap->ClientType) {
  1964. // save pointer to termcap for later use
  1965. pLocalCap = TermCapList.pTermCapArray[dwIndex];
  1966. // done
  1967. break;
  1968. }
  1969. }
  1970. // validate termcap
  1971. if (pLocalCap == NULL) {
  1972. H323DBG((
  1973. DEBUG_LEVEL_ERROR,
  1974. "channel rejected unsupported termcap.\n"
  1975. ));
  1976. // initialize reject reason
  1977. dwRejectReason = H245_REJ_TYPE_NOTSUPPORT;
  1978. // bail...
  1979. goto reject;
  1980. }
  1981. // determine client type
  1982. switch (pRemoteCap->ClientType) {
  1983. case H245_CLIENT_VID_H263:
  1984. // see if incoming bitrate too large
  1985. if (pLocalCap->Cap.H245Vid_H263.maxBitRate <
  1986. pRemoteCap->Cap.H245Vid_H263.maxBitRate) {
  1987. H323DBG((
  1988. DEBUG_LEVEL_ERROR,
  1989. "incoming H263 bitrate too large (%d bps).\n",
  1990. pRemoteCap->Cap.H245Vid_H263.maxBitRate * 100
  1991. ));
  1992. // initialize reject reason
  1993. dwRejectReason = H245_REJ_BANDWIDTH;
  1994. // bail...
  1995. goto reject;
  1996. }
  1997. break;
  1998. case H245_CLIENT_VID_H261:
  1999. // see if incoming bitrate too large
  2000. if (pLocalCap->Cap.H245Vid_H261.maxBitRate <
  2001. pRemoteCap->Cap.H245Vid_H261.maxBitRate) {
  2002. H323DBG((
  2003. DEBUG_LEVEL_ERROR,
  2004. "incoming H261 bitrate too large (%d bps).\n",
  2005. pRemoteCap->Cap.H245Vid_H261.maxBitRate * 100
  2006. ));
  2007. // initialize reject reason
  2008. dwRejectReason = H245_REJ_BANDWIDTH;
  2009. // bail...
  2010. goto reject;
  2011. }
  2012. break;
  2013. }
  2014. // look for existing session
  2015. H323LookupChannelBySessionID(
  2016. &pAssociatedChannel,
  2017. pCall->pChannelTable,
  2018. pCallbackParams->bSessionID
  2019. );
  2020. // allocate channel object
  2021. if (!H323AllocChannelFromTable(
  2022. &pChannel,
  2023. &pCall->pChannelTable,
  2024. pCall)) {
  2025. H323DBG((
  2026. DEBUG_LEVEL_ERROR,
  2027. "channel rejected could not allocate.\n"
  2028. ));
  2029. // initialize reject reason
  2030. dwRejectReason = H245_REJ_TYPE_UNKNOWN;
  2031. // bail...
  2032. goto reject;
  2033. }
  2034. // transfer peer rtcp address from callback parameters
  2035. // fail if the peer address was invalid
  2036. if (NULL == pCallbackParams->pPeerRTCPAddr)
  2037. {
  2038. H323DBG((
  2039. DEBUG_LEVEL_ERROR,
  2040. "channel rejected: empty peer RTCP address.\n"
  2041. ));
  2042. // initialize reject reason
  2043. dwRejectReason = H245_REJ_TYPE_UNKNOWN;
  2044. // bail...
  2045. goto reject;
  2046. }
  2047. pChannel->ccRemoteRTCPAddr = *pCallbackParams->pPeerRTCPAddr;
  2048. // transfer channel information from callback parameters
  2049. pChannel->hccChannel = pCallbackParams->hChannel;
  2050. pChannel->bSessionID = pCallbackParams->bSessionID;
  2051. // transfer termcap to channel
  2052. pChannel->ccTermCaps = *pRemoteCap;
  2053. // initialize direction
  2054. pChannel->fInbound = TRUE;
  2055. // determine payload type from channel capability data type
  2056. pChannel->Settings.MediaType = H323IsVideoDataType(pRemoteCap->DataType)
  2057. ? MEDIA_VIDEO
  2058. : MEDIA_AUDIO
  2059. ;
  2060. // examine existing session
  2061. if (pAssociatedChannel != NULL) {
  2062. H323DBG((
  2063. DEBUG_LEVEL_VERBOSE,
  2064. "overriding default local RTCP port for session %d\n",
  2065. pChannel->bSessionID
  2066. ));
  2067. // override default RTCP port with existing one
  2068. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort =
  2069. pAssociatedChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort;
  2070. }
  2071. // complete media stream address information
  2072. pChannel->Settings.dwIPLocal = pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr;
  2073. pChannel->Settings.wRTPPortLocal = pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort;
  2074. pChannel->Settings.wRTCPPortLocal = pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort;
  2075. pChannel->Settings.dwIPRemote = pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.dwAddr;
  2076. pChannel->Settings.wRTPPortRemote = 0;
  2077. pChannel->Settings.wRTCPPortRemote = pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.wPort;
  2078. #if DBG
  2079. // convert local address to network order
  2080. dwIPAddr = htonl(pChannel->Settings.dwIPLocal);
  2081. H323DBG((
  2082. DEBUG_LEVEL_VERBOSE,
  2083. "incoming RTP stream %s:%d\n",
  2084. H323AddrToString(dwIPAddr),
  2085. pChannel->Settings.wRTPPortLocal
  2086. ));
  2087. H323DBG((
  2088. DEBUG_LEVEL_VERBOSE,
  2089. "incoming RTCP stream %s:%d\n",
  2090. H323AddrToString(dwIPAddr),
  2091. pChannel->Settings.wRTCPPortLocal
  2092. ));
  2093. // convert remote address to network order
  2094. dwIPAddr = htonl(pChannel->Settings.dwIPRemote);
  2095. H323DBG((
  2096. DEBUG_LEVEL_VERBOSE,
  2097. "outgoing RTCP stream %s:%d\n",
  2098. H323AddrToString(dwIPAddr),
  2099. pChannel->Settings.wRTCPPortRemote
  2100. ));
  2101. #endif
  2102. // check incoming stream type
  2103. switch (pRemoteCap->ClientType) {
  2104. case H245_CLIENT_AUD_G723:
  2105. // initialize rtp payload type
  2106. pChannel->Settings.dwPayloadType = G723_RTP_PAYLOAD_TYPE;
  2107. pChannel->Settings.dwDynamicType =
  2108. (pCallbackParams->bRTPPayloadType != 0)
  2109. ? (DWORD)(BYTE)(pCallbackParams->bRTPPayloadType)
  2110. : G723_RTP_PAYLOAD_TYPE
  2111. ;
  2112. pChannel->Settings.Audio.dwMillisecondsPerPacket =
  2113. G723_MILLISECONDS_PER_PACKET(
  2114. pRemoteCap->Cap.H245Aud_G723.maxAl_sduAudioFrames
  2115. );
  2116. pChannel->Settings.Audio.G723Settings.bG723LowSpeed =
  2117. H323IsSlowLink(pCall->dwLinkSpeed);
  2118. H323DBG((
  2119. DEBUG_LEVEL_VERBOSE,
  2120. "incoming G723 stream (%d milliseconds).\n",
  2121. pChannel->Settings.Audio.dwMillisecondsPerPacket
  2122. ));
  2123. break;
  2124. case H245_CLIENT_AUD_G711_ULAW64:
  2125. // complete audio information
  2126. pChannel->Settings.dwPayloadType = G711U_RTP_PAYLOAD_TYPE;
  2127. pChannel->Settings.dwDynamicType =
  2128. (pCallbackParams->bRTPPayloadType != 0)
  2129. ? (DWORD)(BYTE)(pCallbackParams->bRTPPayloadType)
  2130. : G711U_RTP_PAYLOAD_TYPE
  2131. ;
  2132. pChannel->Settings.Audio.dwMillisecondsPerPacket =
  2133. G711_MILLISECONDS_PER_PACKET(
  2134. pRemoteCap->Cap.H245Aud_G711_ULAW64
  2135. );
  2136. H323DBG((
  2137. DEBUG_LEVEL_VERBOSE,
  2138. "incoming G711U stream (%d milliseconds).\n",
  2139. pChannel->Settings.Audio.dwMillisecondsPerPacket
  2140. ));
  2141. break;
  2142. case H245_CLIENT_AUD_G711_ALAW64:
  2143. // complete audio information
  2144. pChannel->Settings.dwPayloadType = G711A_RTP_PAYLOAD_TYPE;
  2145. pChannel->Settings.dwDynamicType =
  2146. (pCallbackParams->bRTPPayloadType != 0)
  2147. ? (DWORD)(BYTE)(pCallbackParams->bRTPPayloadType)
  2148. : G711A_RTP_PAYLOAD_TYPE
  2149. ;
  2150. pChannel->Settings.Audio.dwMillisecondsPerPacket =
  2151. G711_MILLISECONDS_PER_PACKET(
  2152. pRemoteCap->Cap.H245Aud_G711_ALAW64
  2153. );
  2154. H323DBG((
  2155. DEBUG_LEVEL_VERBOSE,
  2156. "incoming G711A stream (%d milliseconds).\n",
  2157. pChannel->Settings.Audio.dwMillisecondsPerPacket
  2158. ));
  2159. break;
  2160. case H245_CLIENT_VID_H263:
  2161. // complete video information
  2162. pChannel->Settings.dwPayloadType = H263_RTP_PAYLOAD_TYPE;
  2163. pChannel->Settings.dwDynamicType =
  2164. (pCallbackParams->bRTPPayloadType != 0)
  2165. ? (DWORD)(BYTE)(pCallbackParams->bRTPPayloadType)
  2166. : H263_RTP_PAYLOAD_TYPE
  2167. ;
  2168. pChannel->Settings.Video.bCIF = FALSE;
  2169. pChannel->Settings.Video.dwMaxBitRate =
  2170. pRemoteCap->Cap.H245Vid_H263.maxBitRate * 100
  2171. ;
  2172. H323DBG((
  2173. DEBUG_LEVEL_VERBOSE,
  2174. "incoming H263 stream (%d bps).\n",
  2175. pChannel->Settings.Video.dwMaxBitRate
  2176. ));
  2177. break;
  2178. case H245_CLIENT_VID_H261:
  2179. // complete video information
  2180. pChannel->Settings.dwPayloadType = H261_RTP_PAYLOAD_TYPE;
  2181. pChannel->Settings.dwDynamicType =
  2182. (pCallbackParams->bRTPPayloadType != 0)
  2183. ? (DWORD)(BYTE)(pCallbackParams->bRTPPayloadType)
  2184. : H261_RTP_PAYLOAD_TYPE
  2185. ;
  2186. pChannel->Settings.Video.bCIF = FALSE;
  2187. pChannel->Settings.Video.dwMaxBitRate =
  2188. pRemoteCap->Cap.H245Vid_H261.maxBitRate * 100
  2189. ;
  2190. H323DBG((
  2191. DEBUG_LEVEL_VERBOSE,
  2192. "incoming H261 stream (%d bps).\n",
  2193. pChannel->Settings.Video.dwMaxBitRate
  2194. ));
  2195. break;
  2196. }
  2197. // save back pointer
  2198. pChannel->pCall = pCall;
  2199. // let msp accept incoming channel
  2200. H323SendAcceptChannelRequest(pCall, pChannel);
  2201. // release line device
  2202. H323UnlockLine(pCall->pLine);
  2203. // processed
  2204. return CC_OK;
  2205. reject:
  2206. // reject channel
  2207. CC_RejectChannel(
  2208. pCallbackParams->hChannel,
  2209. dwRejectReason
  2210. );
  2211. H323DBG((
  2212. DEBUG_LEVEL_VERBOSE,
  2213. "call 0x%08lx incoming channel rejected.\n",
  2214. pCall
  2215. ));
  2216. // release line device
  2217. H323UnlockLine(pCall->pLine);
  2218. // processed
  2219. return CC_OK;
  2220. }
  2221. HRESULT
  2222. H323RxChannelCloseCallback(
  2223. PH323_CALL pCall,
  2224. HRESULT hrConf,
  2225. PCC_RX_CHANNEL_CLOSE_CALLBACK_PARAMS pCallbackParams
  2226. )
  2227. /*++
  2228. Routine Description:
  2229. Callback for channel close indications.
  2230. Arguments:
  2231. pCall - Pointer to call object.
  2232. hrConf - Current status of H.323 conference.
  2233. pCallbackParams - Parameters returned by call control module.
  2234. Return Values:
  2235. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2236. --*/
  2237. {
  2238. PH323_CHANNEL pChannel = NULL;
  2239. // attempt to retrieve channel
  2240. if (!H323LookupChannelByHandle(
  2241. &pChannel,
  2242. pCall->pChannelTable,
  2243. pCallbackParams->hChannel
  2244. )) {
  2245. H323DBG((
  2246. DEBUG_LEVEL_ERROR,
  2247. "could not close unknown rx channel 0x%08lx.\n",
  2248. pCallbackParams->hChannel
  2249. ));
  2250. // release line device
  2251. H323UnlockLine(pCall->pLine);
  2252. // could not find channel
  2253. return CC_NOT_IMPLEMENTED;
  2254. }
  2255. // notify msp of channel closure
  2256. H323SendCloseChannelCommand(pCall, pChannel->hmChannel,ERROR_SUCCESS);
  2257. // release memory for logical channel
  2258. H323FreeChannelFromTable(pChannel, pCall->pChannelTable);
  2259. // update media modes
  2260. H323UpdateMediaModes(pCall);
  2261. // release line device
  2262. H323UnlockLine(pCall->pLine);
  2263. // success
  2264. return CC_OK;
  2265. }
  2266. HRESULT
  2267. H323TxChannelOpenCallback(
  2268. PH323_CALL pCall,
  2269. HRESULT hrConf,
  2270. PCC_TX_CHANNEL_OPEN_CALLBACK_PARAMS pCallbackParams
  2271. )
  2272. /*++
  2273. Routine Description:
  2274. Callback for channel open indications.
  2275. Arguments:
  2276. pCall - Pointer to call object.
  2277. hrConf - Current status of H.323 conference.
  2278. pCallbackParams - Parameters returned by call control module.
  2279. Return Values:
  2280. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2281. --*/
  2282. {
  2283. PH323_CHANNEL pChannel = NULL;
  2284. // attempt to retrieve channel
  2285. if (!H323LookupChannelByHandle(
  2286. &pChannel,
  2287. pCall->pChannelTable,
  2288. pCallbackParams->hChannel
  2289. )) {
  2290. H323DBG((
  2291. DEBUG_LEVEL_ERROR,
  2292. "could not open unknown tx channel 0x%08lx.\n",
  2293. pCallbackParams->hChannel
  2294. ));
  2295. // release line device
  2296. H323UnlockLine(pCall->pLine);
  2297. // could not find channel
  2298. return CC_NOT_IMPLEMENTED;
  2299. }
  2300. // validate status
  2301. if (hrConf != CC_OK) {
  2302. // see if peer rejected
  2303. if (hrConf == CC_PEER_REJECT) {
  2304. H323DBG((
  2305. DEBUG_LEVEL_VERBOSE,
  2306. "channel 0x%08lx rejected 0x%08lx.\n",
  2307. pChannel,
  2308. pCallbackParams->dwRejectReason
  2309. ));
  2310. } else {
  2311. H323DBG((
  2312. DEBUG_LEVEL_VERBOSE,
  2313. "channel 0x%08lx unable to be opened.\n",
  2314. pChannel
  2315. ));
  2316. }
  2317. // close channel (with error)
  2318. H323SendCloseChannelCommand(pCall, pChannel->hmChannel,(DWORD)-1);
  2319. // release channel object
  2320. H323FreeChannelFromTable(pChannel,pCall->pChannelTable);
  2321. } else {
  2322. // transfer peer rtcp address from callback parameters
  2323. pChannel->ccRemoteRTPAddr = *pCallbackParams->pPeerRTPAddr;
  2324. // transfer peer rtcp address from callback parameters
  2325. pChannel->ccRemoteRTCPAddr = *pCallbackParams->pPeerRTCPAddr;
  2326. H323DBG((
  2327. DEBUG_LEVEL_VERBOSE,
  2328. "channel 0x%08lx accepted by peer.\n",
  2329. pChannel
  2330. ));
  2331. // complete media stream address information
  2332. pChannel->Settings.dwIPLocal = pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr;
  2333. pChannel->Settings.wRTPPortLocal = 0;
  2334. pChannel->Settings.wRTCPPortLocal = pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort;
  2335. pChannel->Settings.dwIPRemote = pChannel->ccRemoteRTPAddr.Addr.IP_Binary.dwAddr;
  2336. pChannel->Settings.wRTPPortRemote = pChannel->ccRemoteRTPAddr.Addr.IP_Binary.wPort;
  2337. pChannel->Settings.wRTCPPortRemote = pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.wPort;
  2338. #if DBG
  2339. {
  2340. DWORD dwIPAddr;
  2341. // convert local address to network order
  2342. dwIPAddr = htonl(pChannel->Settings.dwIPLocal);
  2343. H323DBG((
  2344. DEBUG_LEVEL_VERBOSE,
  2345. "incoming RTCP stream %s:%d\n",
  2346. H323AddrToString(dwIPAddr),
  2347. pChannel->Settings.wRTCPPortLocal
  2348. ));
  2349. // convert remote address to network order
  2350. dwIPAddr = htonl(pChannel->Settings.dwIPRemote);
  2351. H323DBG((
  2352. DEBUG_LEVEL_VERBOSE,
  2353. "outgoing RTP stream %s:%d\n",
  2354. H323AddrToString(dwIPAddr),
  2355. pChannel->Settings.wRTPPortRemote
  2356. ));
  2357. H323DBG((
  2358. DEBUG_LEVEL_VERBOSE,
  2359. "outgoing RTCP stream %s:%d\n",
  2360. H323AddrToString(dwIPAddr),
  2361. pChannel->Settings.wRTCPPortRemote
  2362. ));
  2363. }
  2364. #endif
  2365. // change state to opened
  2366. pChannel->nState = H323_CHANNELSTATE_OPENED;
  2367. // notify msp channel is opened
  2368. H323SendOpenChannelResponse(pCall, pChannel);
  2369. }
  2370. // update media modes
  2371. H323UpdateMediaModes(pCall);
  2372. // release line device
  2373. H323UnlockLine(pCall->pLine);
  2374. // processed
  2375. return CC_OK;
  2376. }
  2377. HRESULT
  2378. H323TxChannelCloseCallback(
  2379. PH323_CALL pCall,
  2380. HRESULT hrConf,
  2381. PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS pCallbackParams
  2382. )
  2383. /*++
  2384. Routine Description:
  2385. Callback for channel close indications.
  2386. Arguments:
  2387. pCall - Pointer to call object.
  2388. hrConf - Current status of H.323 conference.
  2389. pCallbackParams - Parameters returned by call control module.
  2390. Return Values:
  2391. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2392. --*/
  2393. {
  2394. PH323_CHANNEL pChannel = NULL;
  2395. // attempt to retrieve channel
  2396. if (!H323LookupChannelByHandle(
  2397. &pChannel,
  2398. pCall->pChannelTable,
  2399. pCallbackParams->hChannel
  2400. )) {
  2401. H323DBG((
  2402. DEBUG_LEVEL_ERROR,
  2403. "could not close unknown tx channel 0x%08lx.\n",
  2404. pCallbackParams->hChannel
  2405. ));
  2406. // release line device
  2407. H323UnlockLine(pCall->pLine);
  2408. // could not find channel
  2409. return CC_NOT_IMPLEMENTED;
  2410. }
  2411. // notify msp channel is closed
  2412. H323SendCloseChannelCommand(pCall, pChannel->hmChannel,ERROR_SUCCESS);
  2413. // release memory for logical channel
  2414. H323FreeChannelFromTable(pChannel, pCall->pChannelTable);
  2415. // update media modes
  2416. H323UpdateMediaModes(pCall);
  2417. // release line device
  2418. H323UnlockLine(pCall->pLine);
  2419. // success
  2420. return CC_OK;
  2421. }
  2422. HRESULT
  2423. H323FlowControlCallback(
  2424. PH323_CALL pCall,
  2425. HRESULT hrConf,
  2426. PCC_FLOW_CONTROL_CALLBACK_PARAMS pCallbackParams
  2427. )
  2428. /*++
  2429. Routine Description:
  2430. Callback for flow control commands.
  2431. Arguments:
  2432. pCall - Pointer to call object.
  2433. hrConf - Current status of H.323 conference.
  2434. pCallbackParams - Parameters returned by call control module.
  2435. Return Values:
  2436. Returns CC_OK.
  2437. --*/
  2438. {
  2439. PH323_CHANNEL pChannel = NULL;
  2440. // attempt to retrieve channel
  2441. if (!H323LookupChannelByHandle(
  2442. &pChannel,
  2443. pCall->pChannelTable,
  2444. pCallbackParams->hChannel
  2445. )) {
  2446. H323DBG((
  2447. DEBUG_LEVEL_ERROR,
  2448. "could not process flow control command for channel 0x%08lx.\n",
  2449. pCallbackParams->hChannel
  2450. ));
  2451. // release line device
  2452. H323UnlockLine(pCall->pLine);
  2453. // could not find channel
  2454. return CC_OK;
  2455. }
  2456. // notify msp that media stream bit rate is to be changed
  2457. H323SendFlowControlCommand(
  2458. pCall,
  2459. pChannel,
  2460. pCallbackParams->dwRate
  2461. );
  2462. // release line device
  2463. H323UnlockLine(pCall->pLine);
  2464. // success
  2465. return CC_OK;
  2466. }
  2467. HRESULT
  2468. H323VideoFastUpdatePictureCallback(
  2469. PH323_CALL pCall,
  2470. HRESULT hrConf,
  2471. PCC_H245_MISCELLANEOUS_COMMAND_CALLBACK_PARAMS pCallbackParams
  2472. )
  2473. /*++
  2474. Routine Description:
  2475. Callback for Video Fast Update Picture command (a.k.a. I-frame request command)
  2476. Arguments:
  2477. pCall - Pointer to call object.
  2478. hrConf - Current status of H.323 conference.
  2479. pCallbackParams - Parameters returned by call control module.
  2480. Return Values:
  2481. Returns CC_OK.
  2482. --*/
  2483. {
  2484. PH323_CHANNEL pChannel = NULL;
  2485. // attempt to retrieve channel
  2486. if (!H323LookupChannelByHandle(
  2487. &pChannel,
  2488. pCall->pChannelTable,
  2489. pCallbackParams->hChannel
  2490. )) {
  2491. H323DBG((
  2492. DEBUG_LEVEL_ERROR,
  2493. "could not process I-frame request cmd for channel 0x%08lx.\n",
  2494. pCallbackParams->hChannel
  2495. ));
  2496. // release line device
  2497. H323UnlockLine(pCall->pLine);
  2498. // could not find channel
  2499. return CC_OK;
  2500. }
  2501. // notify msp that media stream bit rate is to be changed
  2502. H323SendVideoFastUpdatePictureCommand(
  2503. pCall,
  2504. pChannel
  2505. );
  2506. // release line device
  2507. H323UnlockLine(pCall->pLine);
  2508. // success
  2509. return CC_OK;
  2510. }
  2511. HRESULT
  2512. H245MiscellaneousCommandCallback(
  2513. PH323_CALL pCall,
  2514. HRESULT hrConf,
  2515. PCC_H245_MISCELLANEOUS_COMMAND_CALLBACK_PARAMS pCallbackParams
  2516. )
  2517. /*++
  2518. Routine Description:
  2519. Callback for miscellaneous H.245 commands.
  2520. Arguments:
  2521. pCall - Pointer to call object.
  2522. hrConf - Current status of H.323 conference.
  2523. pCallbackParams - Parameters returned by call control module.
  2524. Return Values:
  2525. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2526. --*/
  2527. {
  2528. // retrieve command structure from incoming callback parameters
  2529. MiscellaneousCommand * pCommand = pCallbackParams->pMiscellaneousCommand;
  2530. switch (pCommand->type.choice) {
  2531. case videoFastUpdatePicture_chosen:
  2532. // process I-frame request from remote entity
  2533. return H323VideoFastUpdatePictureCallback(
  2534. pCall,
  2535. hrConf,
  2536. (PVOID)pCallbackParams
  2537. );
  2538. default:
  2539. // intentionally left blank
  2540. break;
  2541. }
  2542. H323DBG((
  2543. DEBUG_LEVEL_VERBOSE,
  2544. "misc command %s ignored.\n",
  2545. H323MiscCommandToString((DWORD)(USHORT)pCommand->type.choice)
  2546. ));
  2547. // release line device
  2548. H323UnlockLine(pCall->pLine);
  2549. // success
  2550. return CC_NOT_IMPLEMENTED;
  2551. }
  2552. HRESULT
  2553. H245RxNonStandardMessageCallback(
  2554. PH323_CALL pCall,
  2555. HRESULT hrConf,
  2556. PCC_RX_NONSTANDARD_MESSAGE_CALLBACK_PARAMS pCallbackParams
  2557. )
  2558. /*++
  2559. Routine Description:
  2560. Callback for miscellaneous H.245 commands.
  2561. Arguments:
  2562. pCall - Pointer to call object.
  2563. hrConf - Current status of H.323 conference.
  2564. pCallbackParams - Parameters returned by call control module.
  2565. Return Values:
  2566. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2567. --*/
  2568. {
  2569. // validate status
  2570. if (hrConf == CC_OK) {
  2571. // validate incoming parameters
  2572. if ((pCallbackParams->bH245MessageType == CC_H245_MESSAGE_COMMAND) &&
  2573. H323IsValidU2U(&pCallbackParams->NonStandardData)) {
  2574. // add user user info
  2575. if (H323AddU2U(
  2576. &pCall->IncomingU2U,
  2577. pCallbackParams->NonStandardData.sData.wOctetStringLength,
  2578. pCallbackParams->NonStandardData.sData.pOctetString
  2579. )) {
  2580. H323DBG((
  2581. DEBUG_LEVEL_VERBOSE,
  2582. "user user info available in NONSTANDARD MESSAGE.\n"
  2583. ));
  2584. // signal incoming
  2585. (*g_pfnLineEventProc)(
  2586. pCall->pLine->htLine,
  2587. pCall->htCall,
  2588. LINE_CALLINFO,
  2589. LINECALLINFOSTATE_USERUSERINFO,
  2590. 0,
  2591. 0
  2592. );
  2593. }
  2594. }
  2595. } else {
  2596. H323DBG((
  2597. DEBUG_LEVEL_WARNING,
  2598. "error 0x%08lx receiving non-standard message.\n",
  2599. hrConf
  2600. ));
  2601. }
  2602. // release line device
  2603. H323UnlockLine(pCall->pLine);
  2604. // success
  2605. return CC_OK;
  2606. }
  2607. HRESULT
  2608. H245UserInputCallback(
  2609. PH323_CALL pCall,
  2610. HRESULT hrConf,
  2611. PCC_USER_INPUT_CALLBACK_PARAMS pCallbackParams
  2612. )
  2613. /*++
  2614. Routine Description:
  2615. Callback for miscellaneous H.245 commands.
  2616. Arguments:
  2617. pCall - Pointer to call object.
  2618. hrConf - Current status of H.323 conference.
  2619. pCallbackParams - Parameters returned by call control module.
  2620. Return Values:
  2621. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2622. --*/
  2623. {
  2624. // validate status
  2625. if (hrConf == CC_OK) {
  2626. // check monitoring mode
  2627. if (pCall->fMonitoringDigits == TRUE) {
  2628. WCHAR * pwch;
  2629. H323DBG((
  2630. DEBUG_LEVEL_VERBOSE,
  2631. "incoming user input %S.\n",
  2632. pCallbackParams->pUserInput
  2633. ));
  2634. // initialize string pointer
  2635. pwch = pCallbackParams->pUserInput;
  2636. // process each digit
  2637. while (*pwch != L'\0') {
  2638. // signal incoming
  2639. (*g_pfnLineEventProc)(
  2640. pCall->pLine->htLine,
  2641. pCall->htCall,
  2642. LINE_MONITORDIGITS,
  2643. (DWORD_PTR)*pwch,
  2644. LINEDIGITMODE_DTMF,
  2645. GetTickCount()
  2646. );
  2647. // next
  2648. ++pwch;
  2649. }
  2650. } else {
  2651. H323DBG((
  2652. DEBUG_LEVEL_VERBOSE,
  2653. "ignoring incoming user input message.\n"
  2654. ));
  2655. }
  2656. } else {
  2657. H323DBG((
  2658. DEBUG_LEVEL_WARNING,
  2659. "error 0x%08lx receiving user input message.\n",
  2660. hrConf
  2661. ));
  2662. }
  2663. // release line device
  2664. H323UnlockLine(pCall->pLine);
  2665. // success
  2666. return CC_OK;
  2667. }
  2668. HRESULT
  2669. H245T120ChannelRequestCallback(
  2670. PH323_CALL pCall,
  2671. HRESULT hrConf,
  2672. PCC_T120_CHANNEL_REQUEST_CALLBACK_PARAMS pT120RequestParams
  2673. )
  2674. /*++
  2675. Routine Description:
  2676. Callback for a T120 open channel request.
  2677. Arguments:
  2678. pCall - Pointer to call object.
  2679. hrConf - Current status of H.323 conference.
  2680. pCallbackParams - Parameters returned by call control module.
  2681. Return Values:
  2682. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2683. --*/
  2684. {
  2685. HRESULT hr;
  2686. // validate status
  2687. if (hrConf == CC_OK) {
  2688. CC_ADDR ChannelAddr;
  2689. ChannelAddr.nAddrType = CC_IP_BINARY;
  2690. ChannelAddr.bMulticast = FALSE;
  2691. ChannelAddr.Addr.IP_Binary.wPort = g_wPortT120;
  2692. if (g_dwIPT120 != INADDR_ANY)
  2693. {
  2694. ChannelAddr.Addr.IP_Binary.dwAddr = g_dwIPT120;
  2695. }
  2696. else
  2697. {
  2698. ChannelAddr.Addr.IP_Binary.dwAddr =
  2699. H323IsCallInbound(pCall)
  2700. ? pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr
  2701. : pCall->ccCallerAddr.Addr.IP_Binary.dwAddr
  2702. ;
  2703. }
  2704. hr = CC_AcceptT120Channel(
  2705. pT120RequestParams->hChannel,
  2706. FALSE, // BOOL bAssociateConference,
  2707. NULL, // PCC_OCTETSTRING pExternalReference,
  2708. &ChannelAddr
  2709. );
  2710. if (hr != CC_OK)
  2711. {
  2712. H323DBG((
  2713. DEBUG_LEVEL_WARNING,
  2714. "error 0x%08lx accepting T120 channel.\n",
  2715. hr
  2716. ));
  2717. }
  2718. } else {
  2719. H323DBG((
  2720. DEBUG_LEVEL_WARNING,
  2721. "error 0x%08lx receiving user input message.\n",
  2722. hrConf
  2723. ));
  2724. }
  2725. // release line device
  2726. H323UnlockLine(pCall->pLine);
  2727. // success
  2728. return CC_OK;
  2729. }
  2730. ///////////////////////////////////////////////////////////////////////////////
  2731. // //
  2732. // Public procedures //
  2733. // //
  2734. ///////////////////////////////////////////////////////////////////////////////
  2735. HRESULT
  2736. H323ConferenceCallback(
  2737. BYTE bIndication,
  2738. HRESULT hrConf,
  2739. CC_HCONFERENCE hConference,
  2740. DWORD dwConferenceToken,
  2741. PCC_CONFERENCE_CALLBACK_PARAMS pCallbackParams
  2742. )
  2743. /*++
  2744. Routine Description:
  2745. Conference callback for Intel Call Control module.
  2746. Arguments:
  2747. bIndication - indicates the reason for the callback.
  2748. hrConf - indicates the asynchronous status of the call.
  2749. hConference - conference handle associated with the callback.
  2750. dwConferenceToken - conference token specified in the CC_CreateConference().
  2751. pCallbackParams - pointer to a structure containing callback
  2752. parameters specific for the callback indication.
  2753. Return Values:
  2754. Returns either CC_OK or CC_NOT_IMPLEMENTED.
  2755. --*/
  2756. {
  2757. HRESULT hr;
  2758. HDRVCALL hdCall;
  2759. PH323_CALL pCall = NULL;
  2760. H323DBG((
  2761. DEBUG_LEVEL_TRACE,
  2762. "%s %s (0x%08lx).\n",
  2763. H323IndicationToString(bIndication),
  2764. H323StatusToString((DWORD)hrConf),
  2765. hrConf
  2766. ));
  2767. // retrieve call handle from token
  2768. hdCall = (HDRVCALL)dwConferenceToken;
  2769. // handle hangup indications separately
  2770. if (bIndication == CC_HANGUP_INDICATION) {
  2771. H323DBG((
  2772. DEBUG_LEVEL_VERBOSE,
  2773. "hangup confirmed (hdCall=0x%08lx).\n",
  2774. hdCall
  2775. ));
  2776. // success
  2777. return CC_OK;
  2778. } else if (bIndication == CC_ACCEPT_CHANNEL_INDICATION) {
  2779. H323DBG((
  2780. DEBUG_LEVEL_VERBOSE,
  2781. "ignoring accept channel indication (hdCall=0x%08lx).\n",
  2782. hdCall
  2783. ));
  2784. // success
  2785. return CC_OK;
  2786. }
  2787. // retrieve call pointer from handle
  2788. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2789. H323DBG((
  2790. DEBUG_LEVEL_ERROR,
  2791. "invalid call handle in callback.\n"
  2792. ));
  2793. // need to return error
  2794. return CC_NOT_IMPLEMENTED;
  2795. }
  2796. // validate conference handle
  2797. if (pCall->hccConf != hConference) {
  2798. H323DBG((
  2799. DEBUG_LEVEL_ERROR,
  2800. "conference handle mismatch.\n"
  2801. ));
  2802. // unlock line device
  2803. H323UnlockLine(pCall->pLine);
  2804. // need to return error
  2805. return CC_NOT_IMPLEMENTED;
  2806. }
  2807. // determine message
  2808. switch (bIndication) {
  2809. case CC_CONNECT_INDICATION:
  2810. // process connect indication
  2811. return H323ConnectCallback(
  2812. pCall,
  2813. hrConf,
  2814. (PVOID)pCallbackParams
  2815. );
  2816. case CC_RINGING_INDICATION:
  2817. // process ringing indication
  2818. return H323RingingCallback(
  2819. pCall
  2820. );
  2821. case CC_CONFERENCE_TERMINATION_INDICATION:
  2822. // process termination indication
  2823. return H323TerminationCallback(
  2824. pCall,
  2825. hrConf,
  2826. (PVOID)pCallbackParams
  2827. );
  2828. case CC_RX_CHANNEL_REQUEST_INDICATION:
  2829. // process termination indication
  2830. return H323RxChannelRequestCallback(
  2831. pCall,
  2832. hrConf,
  2833. (PVOID)pCallbackParams
  2834. );
  2835. case CC_RX_CHANNEL_CLOSE_INDICATION:
  2836. // process channel close
  2837. return H323RxChannelCloseCallback(
  2838. pCall,
  2839. hrConf,
  2840. (PVOID)pCallbackParams
  2841. );
  2842. case CC_TX_CHANNEL_OPEN_INDICATION:
  2843. // process channel open
  2844. return H323TxChannelOpenCallback(
  2845. pCall,
  2846. hrConf,
  2847. (PVOID)pCallbackParams
  2848. );
  2849. case CC_TX_CHANNEL_CLOSE_REQUEST_INDICATION:
  2850. // process channel close
  2851. return H323TxChannelCloseCallback(
  2852. pCall,
  2853. hrConf,
  2854. (PVOID)pCallbackParams
  2855. );
  2856. case CC_FLOW_CONTROL_INDICATION:
  2857. // process flow control command
  2858. return H323FlowControlCallback(
  2859. pCall,
  2860. hrConf,
  2861. (PVOID)pCallbackParams
  2862. );
  2863. case CC_H245_MISCELLANEOUS_COMMAND_INDICATION:
  2864. // process miscellaneous commands
  2865. return H245MiscellaneousCommandCallback(
  2866. pCall,
  2867. hrConf,
  2868. (PVOID)pCallbackParams
  2869. );
  2870. case CC_RX_NONSTANDARD_MESSAGE_INDICATION:
  2871. // process nonstandard commands
  2872. return H245RxNonStandardMessageCallback(
  2873. pCall,
  2874. hrConf,
  2875. (PVOID)pCallbackParams
  2876. );
  2877. case CC_USER_INPUT_INDICATION:
  2878. // process nonstandard commands
  2879. return H245UserInputCallback(
  2880. pCall,
  2881. hrConf,
  2882. (PVOID)pCallbackParams
  2883. );
  2884. case CC_T120_CHANNEL_REQUEST_INDICATION:
  2885. // process T120 channel request
  2886. return H245T120ChannelRequestCallback(
  2887. pCall,
  2888. hrConf,
  2889. (PVOID)pCallbackParams
  2890. );
  2891. }
  2892. H323DBG((
  2893. DEBUG_LEVEL_WARNING,
  2894. "conference callback indication not supported.\n"
  2895. ));
  2896. // unlock line device
  2897. H323UnlockLine(pCall->pLine);
  2898. // not yet supported
  2899. return CC_NOT_IMPLEMENTED;
  2900. }
  2901. VOID
  2902. H323ListenCallback(
  2903. HRESULT hrListen,
  2904. PCC_LISTEN_CALLBACK_PARAMS pCallbackParams
  2905. )
  2906. /*++
  2907. Routine Description:
  2908. Conference callback for Intel Call Control module.
  2909. Arguments:
  2910. hrListen - indicates the asynchronous status of the call.
  2911. pCallbackParams - pointer to a structure containing callback
  2912. parameters specific for the callback indication.
  2913. Return Values:
  2914. None.
  2915. --*/
  2916. {
  2917. HRESULT hr;
  2918. HDRVLINE hdLine;
  2919. PH323_LINE pLine = NULL;
  2920. PH323_CALL pCall = NULL;
  2921. H323DBG((
  2922. DEBUG_LEVEL_TRACE,
  2923. "INCOMING CALL %s (0x%08lx).\n",
  2924. H323StatusToString(hrListen),
  2925. hrListen
  2926. ));
  2927. // retrieve line handle from token
  2928. hdLine = (HDRVLINE)pCallbackParams->dwListenToken;
  2929. // retrieve line pointer from handle
  2930. if (!H323GetLineAndLock(&pLine, hdLine)) {
  2931. H323DBG((
  2932. DEBUG_LEVEL_ERROR,
  2933. "invalid line handle in listen callback.\n"
  2934. ));
  2935. // failure
  2936. return ;
  2937. }
  2938. // validate status
  2939. if (hrListen != CC_OK) {
  2940. // check for active call
  2941. if (H323GetCallByHCall(
  2942. &pCall,
  2943. pLine,
  2944. pCallbackParams->hCall)) {
  2945. // drop offering call
  2946. H323DropCall(pCall,LINEDISCONNECTMODE_CANCELLED);
  2947. }
  2948. // release line device
  2949. H323UnlockLine(pLine);
  2950. // done
  2951. return;
  2952. }
  2953. H323DBG((
  2954. DEBUG_LEVEL_TRACE,
  2955. "line %d receiving call request from %S.\n",
  2956. pLine->dwDeviceID,
  2957. pCallbackParams->pszDisplay
  2958. ));
  2959. // allocate outgoing call from line call table
  2960. if (!H323AllocCallFromTable(&pCall,&pLine->pCallTable,pLine)) {
  2961. H323DBG((
  2962. DEBUG_LEVEL_ERROR,
  2963. "could not allocate call object.\n"
  2964. ));
  2965. // release line device
  2966. H323UnlockLine(pLine);
  2967. // failure
  2968. return;
  2969. }
  2970. // save back pointer
  2971. pCall->pLine = pLine;
  2972. // clear incoming modes
  2973. pCall->dwIncomingModes = 0;
  2974. // outgoing modes will be finalized during H.245 phase
  2975. pCall->dwOutgoingModes = pLine->dwMediaModes | LINEMEDIAMODE_UNKNOWN;
  2976. // save media modes specified
  2977. pCall->dwRequestedModes = pLine->dwMediaModes;
  2978. // specify incoming call direction
  2979. pCall->dwOrigin = LINECALLORIGIN_INBOUND;
  2980. // save incoming call handle
  2981. pCall->hccCall = pCallbackParams->hCall;
  2982. // save caller transport address
  2983. pCall->ccCallerAddr = *pCallbackParams->pCallerAddr;
  2984. // save callee transport address
  2985. pCall->ccCalleeAddr = *pCallbackParams->pCalleeAddr;
  2986. #if DBG
  2987. {
  2988. DWORD dwIPAddr;
  2989. // retrieve ip address in network byte order
  2990. dwIPAddr = htonl(pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr);
  2991. H323DBG((
  2992. DEBUG_LEVEL_VERBOSE,
  2993. "callee address resolved to %s.\n",
  2994. H323AddrToString(dwIPAddr)
  2995. ));
  2996. // retrieve ip address in network byte order
  2997. dwIPAddr = htonl(pCall->ccCallerAddr.Addr.IP_Binary.dwAddr);
  2998. H323DBG((
  2999. DEBUG_LEVEL_VERBOSE,
  3000. "caller address resolved to %s.\n",
  3001. H323AddrToString(dwIPAddr)
  3002. ));
  3003. }
  3004. #endif
  3005. // determine link speed for local interface
  3006. pCall->dwLinkSpeed = H323DetermineLinkSpeed(
  3007. pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr
  3008. );
  3009. // bind incoming call
  3010. if (!H323BindCall(pCall,NULL)) {
  3011. H323DBG((
  3012. DEBUG_LEVEL_ERROR,
  3013. "could not bind call object.\n"
  3014. ));
  3015. // failure
  3016. goto cleanup;
  3017. }
  3018. // see if caller alias was specified
  3019. if ((pCallbackParams->pCallerAliasNames != NULL) &&
  3020. (pCallbackParams->pCallerAliasNames->wCount > 0)) {
  3021. PCC_ALIASITEM pCallerAlias;
  3022. // retrieve pointer to caller alias
  3023. pCallerAlias = pCallbackParams->pCallerAliasNames->pItems;
  3024. // validate alias type
  3025. if ((pCallerAlias->wDataLength > 0) &&
  3026. ((pCallerAlias->wType == CC_ALIAS_H323_ID) ||
  3027. (pCallerAlias->wType == CC_ALIAS_H323_PHONE))) {
  3028. // initialize alias
  3029. pCall->ccCallerAlias.wType = pCallerAlias->wType;
  3030. pCall->ccCallerAlias.wDataLength = pCallerAlias->wDataLength;
  3031. pCall->ccCallerAlias.wPrefixLength = 0;
  3032. pCall->ccCallerAlias.pPrefix = NULL;
  3033. // allocate memory for caller string
  3034. pCall->ccCallerAlias.pData = H323HeapAlloc(
  3035. (pCallerAlias->wDataLength + 1) * sizeof(WCHAR)
  3036. );
  3037. // validate pointer
  3038. if (pCall->ccCallerAlias.pData == NULL) {
  3039. H323DBG((
  3040. DEBUG_LEVEL_ERROR,
  3041. "could not allocate caller name.\n"
  3042. ));
  3043. // failure
  3044. goto cleanup;
  3045. }
  3046. // transfer string information
  3047. memcpy(pCall->ccCallerAlias.pData,
  3048. pCallerAlias->pData,
  3049. pCallerAlias->wDataLength * sizeof(WCHAR)
  3050. );
  3051. // terminate incoming string
  3052. pCall->ccCallerAlias.pData[pCallerAlias->wDataLength] = L'\0';
  3053. H323DBG((
  3054. DEBUG_LEVEL_VERBOSE,
  3055. "incoming caller alias is %S.\n",
  3056. pCall->ccCallerAlias.pData
  3057. ));
  3058. }
  3059. }
  3060. // see if callee alias was specified
  3061. if ((pCallbackParams->pCalleeAliasNames != NULL) &&
  3062. (pCallbackParams->pCalleeAliasNames->wCount > 0)) {
  3063. PCC_ALIASITEM pCalleeAlias;
  3064. // retrieve pointer to callee alias
  3065. pCalleeAlias = pCallbackParams->pCalleeAliasNames->pItems;
  3066. // validate alias type
  3067. if ((pCalleeAlias->wDataLength > 0) &&
  3068. ((pCalleeAlias->wType == CC_ALIAS_H323_ID) ||
  3069. (pCalleeAlias->wType == CC_ALIAS_H323_PHONE))) {
  3070. // initialize alias
  3071. pCall->ccCalleeAlias.wType = pCalleeAlias->wType;
  3072. pCall->ccCalleeAlias.wDataLength = pCalleeAlias->wDataLength;
  3073. pCall->ccCalleeAlias.wPrefixLength = 0;
  3074. pCall->ccCalleeAlias.pPrefix = NULL;
  3075. // allocate memory for caller string
  3076. pCall->ccCalleeAlias.pData = H323HeapAlloc(
  3077. (pCalleeAlias->wDataLength + 1) * sizeof(WCHAR)
  3078. );
  3079. // validate pointer
  3080. if (pCall->ccCalleeAlias.pData == NULL) {
  3081. H323DBG((
  3082. DEBUG_LEVEL_ERROR,
  3083. "could not allocate callee name.\n"
  3084. ));
  3085. // failure
  3086. goto cleanup;
  3087. }
  3088. // transfer string information
  3089. memcpy(pCall->ccCalleeAlias.pData,
  3090. pCalleeAlias->pData,
  3091. pCalleeAlias->wDataLength * sizeof(WCHAR)
  3092. );
  3093. // terminate incoming string
  3094. pCall->ccCalleeAlias.pData[pCalleeAlias->wDataLength] = L'\0';
  3095. H323DBG((
  3096. DEBUG_LEVEL_VERBOSE,
  3097. "incoming callee alias is %S.\n",
  3098. pCall->ccCalleeAlias.pData
  3099. ));
  3100. }
  3101. }
  3102. // validate user user info specified
  3103. if ((pCallbackParams->pNonStandardData != NULL) &&
  3104. H323IsValidU2U(pCallbackParams->pNonStandardData)) {
  3105. // add user user info
  3106. if (!H323AddU2U(
  3107. &pCall->IncomingU2U,
  3108. pCallbackParams->pNonStandardData->sData.wOctetStringLength,
  3109. pCallbackParams->pNonStandardData->sData.pOctetString
  3110. )) {
  3111. H323DBG((
  3112. DEBUG_LEVEL_ERROR,
  3113. "could not save incoming user user info.\n"
  3114. ));
  3115. // failure
  3116. goto cleanup;
  3117. }
  3118. }
  3119. // signal incoming call
  3120. (*g_pfnLineEventProc)(
  3121. pLine->htLine,
  3122. (HTAPICALL)NULL,
  3123. LINE_NEWCALL,
  3124. (DWORD_PTR)pCall->hdCall,
  3125. (DWORD_PTR)&pCall->htCall,
  3126. 0
  3127. );
  3128. // see if user user info specified
  3129. if (!IsListEmpty(&pCall->IncomingU2U)) {
  3130. H323DBG((
  3131. DEBUG_LEVEL_VERBOSE,
  3132. "user user info available in SETUP PDU.\n"
  3133. ));
  3134. // signal incoming
  3135. (*g_pfnLineEventProc)(
  3136. pLine->htLine,
  3137. pCall->htCall,
  3138. LINE_CALLINFO,
  3139. LINECALLINFOSTATE_USERUSERINFO,
  3140. 0,
  3141. 0
  3142. );
  3143. }
  3144. // change state to offering
  3145. H323ChangeCallState(pCall, LINECALLSTATE_OFFERING, 0);
  3146. // release line device
  3147. H323UnlockLine(pLine);
  3148. // success
  3149. return;
  3150. cleanup:
  3151. // unbind call
  3152. H323UnbindCall(pCall);
  3153. // release outgoing call from line call table
  3154. H323FreeCallFromTable(pCall,pLine->pCallTable);
  3155. // release line device
  3156. H323UnlockLine(pLine);
  3157. // failure
  3158. return;
  3159. }
  3160. BOOL
  3161. H323StartCallbackThread(
  3162. )
  3163. /*++
  3164. Routine Description:
  3165. Creates thread which handles async processing.
  3166. Arguments:
  3167. None.
  3168. Return Values:
  3169. Returns true if successful.
  3170. --*/
  3171. {
  3172. // transfer registry key change event to waitable object array
  3173. g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE] = CreateEvent(
  3174. NULL, // lpEventAttributes
  3175. FALSE, // bManualReset
  3176. FALSE, // bInitialState
  3177. NULL // lpName
  3178. );
  3179. // transfer termination event to waitable object array
  3180. g_WaitableObjects[WAIT_OBJECT_TERMINATE_EVENT] = CreateEvent(
  3181. NULL, // lpEventAttributes
  3182. TRUE, // bManualReset
  3183. FALSE, // bInitialState
  3184. NULL // lpName
  3185. );
  3186. // validate waitable object handles
  3187. if ((g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE] == NULL) ||
  3188. (g_WaitableObjects[WAIT_OBJECT_TERMINATE_EVENT] == NULL)) {
  3189. H323DBG((
  3190. DEBUG_LEVEL_ERROR,
  3191. "could not allocate waitable objects.\n"
  3192. ));
  3193. // cleanup resources
  3194. H323StopCallbackThread();
  3195. // failure
  3196. return FALSE;
  3197. }
  3198. // attempt to start thread
  3199. g_hCallbackThread = CreateThread(
  3200. NULL, // lpThreadAttributes
  3201. 0, // dwStackSize
  3202. H323CallbackThread,
  3203. NULL, // lpParameter
  3204. 0, // dwCreationFlags
  3205. &g_dwCallbackThreadID
  3206. );
  3207. // validate thread handle
  3208. if (g_hCallbackThread == NULL) {
  3209. H323DBG((
  3210. DEBUG_LEVEL_ERROR,
  3211. "error 0x%08lx creating callback thread.\n",
  3212. GetLastError()
  3213. ));
  3214. // cleanup resources
  3215. H323StopCallbackThread();
  3216. // failure
  3217. return FALSE;
  3218. }
  3219. H323DBG((
  3220. DEBUG_LEVEL_VERBOSE,
  3221. "callback thread %x started.\n",
  3222. g_dwCallbackThreadID
  3223. ));
  3224. // success
  3225. return TRUE;
  3226. }
  3227. BOOL
  3228. H323StopCallbackThread(
  3229. )
  3230. /*++
  3231. Routine Description:
  3232. Destroys thread which handles async processing.
  3233. Arguments:
  3234. None.
  3235. Return Values:
  3236. Returns true if successful.
  3237. --*/
  3238. {
  3239. HRESULT hr;
  3240. DWORD dwStatus;
  3241. // validate thread handle
  3242. if (g_hCallbackThread != NULL) {
  3243. // signal termination event
  3244. SetEvent(g_WaitableObjects[WAIT_OBJECT_TERMINATE_EVENT]);
  3245. H323DBG((
  3246. DEBUG_LEVEL_VERBOSE,
  3247. "callback thread %x stopping.\n",
  3248. g_dwCallbackThreadID
  3249. ));
  3250. // unlock temporarily
  3251. H323UnlockProvider();
  3252. // wait for callback thread to terminate
  3253. dwStatus = WaitForSingleObject(g_hCallbackThread, INFINITE);
  3254. // relock provider
  3255. H323LockProvider();
  3256. H323DBG((
  3257. DEBUG_LEVEL_VERBOSE,
  3258. "callback thread %x stopped (dwStatus=0x%08lx).\n",
  3259. g_dwCallbackThreadID,
  3260. dwStatus
  3261. ));
  3262. // close thread handle
  3263. CloseHandle(g_hCallbackThread);
  3264. // re-initialize callback thread id
  3265. g_dwCallbackThreadID = UNINITIALIZED;
  3266. g_hCallbackThread = NULL;
  3267. }
  3268. // validate waitable object handle
  3269. if (g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE] != NULL) {
  3270. // release waitable object handle
  3271. CloseHandle(g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE]);
  3272. // re-initialize waitable object handle
  3273. g_WaitableObjects[WAIT_OBJECT_REGISTRY_CHANGE] = NULL;
  3274. }
  3275. // validate waitable object handle
  3276. if (g_WaitableObjects[WAIT_OBJECT_TERMINATE_EVENT] != NULL) {
  3277. // release waitable object handle
  3278. CloseHandle(g_WaitableObjects[WAIT_OBJECT_TERMINATE_EVENT]);
  3279. // re-initialize waitable object handle
  3280. g_WaitableObjects[WAIT_OBJECT_TERMINATE_EVENT] = NULL;
  3281. }
  3282. // success
  3283. return TRUE;
  3284. }