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.

3825 lines
116 KiB

  1. /*
  2. * File: ctrlh323.cpp
  3. *
  4. * Implementation of IControlChannel using H.323 call control protocol
  5. * via apis of CALLCONT.DLL
  6. *
  7. *
  8. * Revision History:
  9. *
  10. * 09/06/96 mikev created
  11. *
  12. */
  13. #include "precomp.h"
  14. #include "ctrlh323.h"
  15. #include "version.h"
  16. #include "strutil.h"
  17. #ifdef DEBUG
  18. VOID DumpChannelParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2);
  19. VOID DumpNonstdParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2);
  20. #else
  21. #define DumpNonstdParameters(a, b)
  22. #define DumpChannelParameters(a, b)
  23. #endif
  24. extern HRESULT AllocTranslatedAliasList(PCC_ALIASNAMES *ppDest, P_H323ALIASLIST pSource);
  25. extern VOID FreeTranslatedAliasList(PCC_ALIASNAMES pDoomed);
  26. static char DefaultProductID[] = H323_PRODUCTNAME_STR;
  27. static char DefaultProductVersion[] = H323_PRODUCTRELEASE_STR;
  28. HRESULT CCConferenceCallback (BYTE bIndication,
  29. HRESULT hStatus,
  30. CC_HCONFERENCE hConference,
  31. DWORD_PTR dwConferenceToken,
  32. PCC_CONFERENCE_CALLBACK_PARAMS pConferenceCallbackParams);
  33. VOID CCListenCallback (HRESULT hStatus,PCC_LISTEN_CALLBACK_PARAMS pListenCallbackParams);
  34. VOID CH323Ctrl::DoAdvise(DWORD dwEvent, LPVOID lpvData)
  35. {
  36. FX_ENTRY ("CH323Ctrl::DoAdvise");
  37. if(IsReleasing()) // don't call out while releasing because it could call
  38. // back in!
  39. {
  40. ERRORMESSAGE(("%s:in releasing state\r\n",_fx_));
  41. return;
  42. }
  43. AddRef(); // protect ourselves from reentrant calls to Release().
  44. if(m_pConfAdvise)
  45. {
  46. hrLast = m_pConfAdvise->OnControlEvent(dwEvent, lpvData, this);
  47. }
  48. else
  49. {
  50. ERRORMESSAGE(("%s:Invalid m_pConfAdvise\r\n",_fx_));
  51. }
  52. Release();
  53. }
  54. VOID CH323Ctrl::GoNextPhase(CtlChanStateType phase)
  55. {
  56. FX_ENTRY ("CH323Ctrl::GoNextPhase");
  57. BOOL fNotifyReady = FALSE;
  58. #define InvError() ERRORMESSAGE(("%s:Invalid transition from %d to %d\r\n",_fx_,m_Phase,phase))
  59. switch(phase)
  60. {
  61. case CCS_Idle:
  62. if(m_Phase != CCS_Idle && m_Phase != CCS_Disconnecting && m_Phase != CCS_Listening)
  63. {
  64. InvError();
  65. }
  66. else
  67. {
  68. m_ChanFlags &= ~(CTRLF_OPEN);
  69. }
  70. break;
  71. case CCS_Connecting:
  72. if((m_Phase != CCS_Idle) && (m_Phase != CCS_Ringing))
  73. {
  74. InvError();
  75. }
  76. break;
  77. case CCS_Accepting:
  78. if(m_Phase != CCS_Listening)
  79. {
  80. InvError();
  81. }
  82. break;
  83. case CCS_Ringing:
  84. // transition from CCS_Idle state is actually only valid if
  85. // there is an incoming call
  86. if(m_Phase != CCS_Connecting && m_Phase != CCS_Filtering && m_Phase != CCS_Listening)
  87. {
  88. InvError();
  89. }
  90. break;
  91. case CCS_Opening:
  92. if(m_Phase != CCS_Connecting && m_Phase != CCS_Accepting
  93. && m_Phase != CCS_Ringing)
  94. {
  95. InvError();
  96. }
  97. break;
  98. case CCS_Closing:
  99. if(m_Phase != CCS_Opening && m_Phase != CCS_Ready && m_Phase != CCS_InUse)
  100. {
  101. InvError();
  102. }
  103. break;
  104. case CCS_Ready:
  105. // can be reentered. if notification is already pending, (state is
  106. // already CCS_InUse) stay there, else do the transition
  107. if(m_Phase != CCS_InUse)
  108. {
  109. if(m_Phase != CCS_Opening)
  110. {
  111. InvError();
  112. }
  113. else
  114. {
  115. //signal "all channels ready" to IConfAdvise
  116. fNotifyReady = TRUE;
  117. }
  118. }
  119. phase = CCS_InUse;
  120. break;
  121. case CCS_InUse:
  122. // previous state must be CCS_InUse or CCS_Ready
  123. if(m_Phase != CCS_InUse && m_Phase != CCS_Ready)
  124. {
  125. InvError();
  126. }
  127. break;
  128. case CCS_Listening:
  129. if(m_Phase != CCS_Idle)
  130. {
  131. InvError();
  132. }
  133. break;
  134. case CCS_Disconnecting:
  135. //if(m_Phase != CCS_Closing)
  136. //{
  137. // InvError();
  138. //}
  139. break;
  140. }
  141. m_Phase = phase;
  142. if (fNotifyReady)
  143. {
  144. DoAdvise(CCEV_ALL_CHANNELS_READY, NULL);
  145. }
  146. }
  147. HRESULT CCConferenceCallback (BYTE bIndication,
  148. HRESULT hConfStatus, CC_HCONFERENCE hConference, DWORD_PTR dwConferenceToken,
  149. PCC_CONFERENCE_CALLBACK_PARAMS pConferenceCallbackParams)
  150. {
  151. HRESULT hr = CC_NOT_IMPLEMENTED;
  152. FX_ENTRY ("CCConferenceCallback ");
  153. CH323Ctrl *pConnection = (CH323Ctrl *)dwConferenceToken;
  154. if(IsBadWritePtr(pConnection, sizeof(CH323Ctrl)))
  155. {
  156. ERRORMESSAGE(("%s:invalid conf token: 0x%08lx\r\n",_fx_, dwConferenceToken));
  157. return CC_NOT_IMPLEMENTED; // must be either CC_NOT_IMPLEMENTED or CC_OK.
  158. }
  159. if(pConnection && pConnection->GetConfHandle() == hConference)
  160. {
  161. if(pConnection->IsReleasing())
  162. {
  163. // we are in the cleanup path. The object is being deleted without
  164. // waiting for asynchronous stuff to complete, and we called that one
  165. // final API (most likely Hangup()) that resulted in a callback. Don't call
  166. // back into the object.
  167. DEBUGMSG(ZONE_CONN,("%s:callback while releasing:0x%08lx, hconf:0x%08lx\r\n",_fx_,
  168. pConnection, hConference));
  169. return hr;
  170. }
  171. pConnection->AddRef(); // protect against Release()ing while not in
  172. // a quiescent state. We do not want to be
  173. // released while inside ourself
  174. hr = pConnection->ConfCallback(bIndication, hConfStatus, pConferenceCallbackParams);
  175. pConnection->Release();
  176. }
  177. #ifdef DEBUG
  178. else
  179. {
  180. if(pConnection)
  181. DEBUGMSG(ZONE_CONN,("%s:hConference mismatch, hConference:0x%08lx, object hconf:0x%08lx, pObject:0x%08lx\r\n",_fx_,
  182. hConference, pConnection->GetConfHandle(), pConnection));
  183. else
  184. DEBUGMSG(ZONE_CONN,("%s:null dwConferenceToken\r\n",_fx_));
  185. }
  186. #endif //DEBUG
  187. return hr;
  188. }
  189. VOID CCListenCallback (HRESULT hStatus,PCC_LISTEN_CALLBACK_PARAMS pListenCallbackParams)
  190. {
  191. FX_ENTRY ("CCListenCallback");
  192. CH323Ctrl *pConnection;
  193. if(!pListenCallbackParams)
  194. {
  195. return;
  196. }
  197. pConnection = (CH323Ctrl *)pListenCallbackParams->dwListenToken;
  198. if(IsBadWritePtr(pConnection, sizeof(CH323Ctrl)))
  199. {
  200. ERRORMESSAGE(("%s:invalid listen token: 0x%08lx\r\n",_fx_, pListenCallbackParams->dwListenToken));
  201. return;
  202. }
  203. // BUGBUG there's no hListen passed in - we can't validate it
  204. // if(pConnection && (pConnection->GetListenHandle() == pListenCallbackParams->h??????))
  205. if(pConnection)
  206. {
  207. pConnection->AddRef(); // protect against Release()ing while not in
  208. // a quiescent state. We do not want to be
  209. // released while inside ourself
  210. pConnection->ListenCallback(hStatus,pListenCallbackParams);
  211. pConnection->Release();
  212. }
  213. else
  214. {
  215. ERRORMESSAGE(("%s:null listen token\r\n",_fx_));
  216. }
  217. }
  218. VOID CH323Ctrl::ListenCallback (HRESULT hStatus,PCC_LISTEN_CALLBACK_PARAMS pListenCallbackParams)
  219. {
  220. FX_ENTRY ("CH323Ctrl::ListenCallback");
  221. HRESULT hr;
  222. if(hStatus != CC_OK)
  223. {
  224. m_hCallCompleteCode = CCCI_LOCAL_ERROR;
  225. CH323Ctrl * pAcceptingConnection = NULL;
  226. BOOL bDisconnect = FALSE;
  227. ERRORMESSAGE(("%s:error 0x%08lx\r\n",_fx_,hStatus));
  228. // aaaaghhh!!! an unsolicited error!!!!!
  229. // MikeV 10/12/96 - observed behavior is that this will occur if the caller disconnects
  230. // before the call is accepted (or during acceptance - if a BP is set before the call
  231. // to AcceptRejectConnection(), the caller times out. But even after that, tracing
  232. // over AcceptRejectConnection() shown no error is returned. This is bad, because
  233. // it is hard to tell if this error needs cleaning up after. The error code in
  234. // that case is 0xa085a001, which is CC_PEER_REJECT
  235. // We also don't know if another object has been created to accept the connection
  236. // or if this is being called in the context of the object that was created and
  237. // its handle passed to AcceptRejectConnection(). The typical behavior is that it
  238. // is called in the context of the listening object.
  239. // once the accepting object is located, need to check state to see if
  240. // connection is in the process of being accepted. Find accepting object
  241. // by matching pListenCallbackParams->ConferenceID;
  242. // see if this is the correct context
  243. if(memcmp(&pListenCallbackParams->ConferenceID, &m_ConferenceID, sizeof(m_ConferenceID))==0)
  244. {
  245. // check the current state. If in the process of accepting
  246. // (either Idle, or filtering), change state to CCS_Closing to make
  247. // cleanup occur. If already accepted (accepting or ringing), initiate
  248. // InternalDisconnect(). This should never happen in any other state.
  249. // EnterCriticalSection() // LOOKLOOK - NYI
  250. switch(m_Phase)
  251. {
  252. case CCS_Idle:
  253. case CCS_Filtering:
  254. break;
  255. default:
  256. case CCS_Ringing:
  257. case CCS_Accepting:
  258. bDisconnect = TRUE;
  259. switch(hStatus)
  260. {
  261. case CC_PEER_REJECT:
  262. m_hCallCompleteCode = CCCI_REJECTED;
  263. ERRORMESSAGE(("%s:Received CC_PEER_REJECT in state %d\r\n",_fx_,m_Phase));
  264. break;
  265. default:
  266. case CC_INTERNAL_ERROR:
  267. m_hCallCompleteCode = CCCI_LOCAL_ERROR;
  268. break;
  269. }
  270. break;
  271. }
  272. // ExitCriticalSection()
  273. if(bDisconnect)
  274. InternalDisconnect();
  275. }
  276. else
  277. {
  278. hr = m_pConfAdvise->FindAcceptingObject((LPIControlChannel *)&pAcceptingConnection,
  279. &pListenCallbackParams->ConferenceID);
  280. if(HR_SUCCEEDED(hr) && pAcceptingConnection)
  281. {
  282. // call this function in the correct context
  283. pAcceptingConnection->AddRef();
  284. pAcceptingConnection->ListenCallback (hStatus, pListenCallbackParams);
  285. pAcceptingConnection->Release();
  286. }
  287. else
  288. {
  289. ERRORMESSAGE(("%s:conference ID 0x%08lx 0x%08lx 0x%08lx 0x%08lx\r\n"
  290. ,_fx_,pListenCallbackParams->ConferenceID.buffer[0],
  291. pListenCallbackParams->ConferenceID.buffer[4],
  292. pListenCallbackParams->ConferenceID.buffer[8],
  293. pListenCallbackParams->ConferenceID.buffer[12]));
  294. ERRORMESSAGE(("%s:Received 0x%08lx in state %d, accepting object not found\r\n"
  295. ,_fx_,hStatus, m_Phase));
  296. }
  297. }
  298. return;
  299. }
  300. // non error case falls out
  301. switch(pListenCallbackParams->wGoal)
  302. {
  303. default:
  304. case CC_GOAL_UNKNOWN:
  305. break;
  306. case CC_GOAL_CREATE:
  307. case CC_GOAL_JOIN:
  308. case CC_GOAL_INVITE:
  309. m_ConferenceID = pListenCallbackParams->ConferenceID;
  310. m_hCall = pListenCallbackParams->hCall;
  311. if(pListenCallbackParams->pCallerAliasNames || pListenCallbackParams->pszDisplay)
  312. {
  313. NewRemoteUserInfo(pListenCallbackParams->pCallerAliasNames,
  314. pListenCallbackParams->pszDisplay);
  315. }
  316. else
  317. {
  318. ERRORMESSAGE(("%s:null pListenCallbackParams->pCallerAliasNames\r\n",_fx_));
  319. }
  320. if(!OnCallAccept(pListenCallbackParams))
  321. {
  322. ERRORMESSAGE(("ListenCallback:OnCallAccept failed\r\n"));
  323. }
  324. break;
  325. }
  326. }
  327. //
  328. // Main conference indication dispatcher
  329. //
  330. #ifdef DEBUG
  331. TCHAR *i_strs[ ] =
  332. {
  333. "ERROR! - INDICATION ZERO",
  334. "CC_RINGING_INDICATION",
  335. "CC_CONNECT_INDICATION",
  336. "CC_TX_CHANNEL_OPEN_INDICATION",
  337. "CC_RX_CHANNEL_REQUEST_INDICATION",
  338. "CC_RX_CHANNEL_CLOSE_INDICATION",
  339. "CC_MUTE_INDICATION",
  340. "CC_UNMUTE_INDICATION",
  341. "CC_PEER_ADD_INDICATION",
  342. "CC_PEER_DROP_INDICATION",
  343. "CC_PEER_CHANGE_CAP_INDICATION",
  344. "CC_CONFERENCE_TERMINATION_INDICATION",
  345. "CC_HANGUP_INDICATION",
  346. "CC_RX_NONSTANDARD_MESSAGE_INDICATION",
  347. "CC_MULTIPOINT_INDICATION",
  348. "CC_PEER_UPDATE_INDICATION",
  349. "CC_H245_MISCELLANEOUS_COMMAND_INDICATION",
  350. "CC_H245_MISCELLANEOUS_INDICATION_INDICATION",
  351. "CC_H245_CONFERENCE_REQUEST_INDICATION",
  352. "CC_H245_CONFERENCE_RESPONSE_INDICATION",
  353. "CC_H245_CONFERENCE_COMMAND_INDICATION",
  354. "CC_H245_CONFERENCE_INDICATION_INDICATION",
  355. "CC_FLOW_CONTROL_INDICATION",
  356. "CC_TX_CHANNEL_CLOSE_REQUEST_INDICATION",
  357. "CC_REQUEST_MODE_INDICATION",
  358. "CC_REQUEST_MODE_RESPONSE_INDICATION",
  359. "CC_VENDOR_ID_INDICATION",
  360. "CC_MAXIMUM_AUDIO_VIDEO_SKEW_INDICATION",
  361. "CC_T120_CHANNEL_REQUEST_INDICATION",
  362. "CC_T120_CHANNEL_OPEN_INDICATION",
  363. "CC_BANDWIDTH_CHANGED_INDICATION",
  364. "CC_ACCEPT_CHANNEL_INDICATION",
  365. "CC_TERMINAL_ID_REQUEST_INDICATION",
  366. "CC_PING_RESPONSE_INDICATION",
  367. "CC_TERMINAL_NUMBER_INDICATION"
  368. };
  369. #endif //DEBUG
  370. HRESULT CH323Ctrl::ConfCallback (BYTE bIndication,
  371. HRESULT hStatus, PCC_CONFERENCE_CALLBACK_PARAMS pConferenceCallbackParams)
  372. {
  373. FX_ENTRY ("CH323Ctrl::ConfCallback");
  374. HRESULT hr = CC_NOT_IMPLEMENTED;
  375. DEBUGMSG(ZONE_CONN,("%s: %s\r\n", _fx_, i_strs[bIndication]));
  376. SHOW_OBJ_ETIME(i_strs[bIndication]);
  377. switch (bIndication)
  378. {
  379. case CC_RINGING_INDICATION:
  380. // (PCC_RINGING_CALLBACK_PARAMS) pConferenceCallbackParams;
  381. // user info may be available now and it may not be
  382. OnCallRinging(hStatus, (PCC_RINGING_CALLBACK_PARAMS) pConferenceCallbackParams);
  383. break;
  384. case CC_CONNECT_INDICATION:
  385. OnCallConnect(hStatus, (PCC_CONNECT_CALLBACK_PARAMS) pConferenceCallbackParams);
  386. hr = CC_OK;
  387. break;
  388. case CC_PEER_ADD_INDICATION:
  389. case CC_PEER_UPDATE_INDICATION:
  390. case CC_PEER_DROP_INDICATION:
  391. case CC_TERMINAL_NUMBER_INDICATION:
  392. break;
  393. case CC_HANGUP_INDICATION:
  394. OnHangup(hStatus);
  395. hr = CC_OK;
  396. break;
  397. case CC_CONFERENCE_TERMINATION_INDICATION:
  398. // September 1996 comments:
  399. // I don't know if there will also be a CC_HANGUP_INDICATION after this.
  400. // We're going to call Hangup() via Disconnect()
  401. // December 1996: Hangup() (excuse me, CC_Hangup()) no longer gives back a
  402. // CC_HANGUP_INDICATION in this state. It returns an error. The new behavior
  403. // seems to indicate that the call control channel is already dead at this point
  404. // so, set our flags as such!!!
  405. m_ChanFlags &= ~(CTRLF_OPEN);
  406. //set state to indicate disconnecting.
  407. GoNextPhase(CCS_Disconnecting);
  408. DoAdvise(CCEV_REMOTE_DISCONNECTING ,NULL);
  409. GoNextPhase(CCS_Idle); // no need to ck retval - we're disconnected
  410. // notify the UI or application code or whatever..
  411. DoAdvise(CCEV_DISCONNECTED ,NULL);
  412. hr = CC_OK;
  413. break;
  414. case CC_PEER_CHANGE_CAP_INDICATION:
  415. break;
  416. //
  417. // Channel stuff
  418. //
  419. case CC_TX_CHANNEL_OPEN_INDICATION:
  420. OnChannelOpen(hStatus,(PCC_TX_CHANNEL_OPEN_CALLBACK_PARAMS)pConferenceCallbackParams);
  421. hr = CC_OK;
  422. break;
  423. case CC_RX_CHANNEL_REQUEST_INDICATION:
  424. OnChannelRequest(hStatus, (PCC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS)pConferenceCallbackParams);
  425. hr = CC_OK;
  426. break;
  427. // the following 4 channel-centric indications have the same basic parameter
  428. // structure. When we get the final Intel drop, we can clean it up. 1 - collapse
  429. // the parameters into a common "channel indication" structure. 2 - make sure
  430. // that a user pointer is stored in that structure for easy finding of channel
  431. // context. 3 - collapse separate channel event handling functions into one.
  432. case CC_MUTE_INDICATION:
  433. OnMute(hStatus, (PCC_MUTE_CALLBACK_PARAMS)pConferenceCallbackParams);
  434. hr = CC_OK;
  435. break;
  436. case CC_UNMUTE_INDICATION:
  437. OnUnMute(hStatus, (PCC_UNMUTE_CALLBACK_PARAMS)pConferenceCallbackParams);
  438. hr = CC_OK;
  439. break;
  440. case CC_RX_CHANNEL_CLOSE_INDICATION:
  441. OnRxChannelClose(hStatus,(PCC_RX_CHANNEL_CLOSE_CALLBACK_PARAMS)pConferenceCallbackParams);
  442. hr = CC_OK;
  443. break;
  444. case CC_TX_CHANNEL_CLOSE_REQUEST_INDICATION:
  445. OnTxChannelClose(hStatus,(PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS)pConferenceCallbackParams);
  446. hr = CC_OK;
  447. // CC_TX_CHANNEL_CLOSE_REQUEST_INDICATION callback parameters (pConferenceCallbackParams)
  448. //typedef struct {
  449. // CC_HCHANNEL hChannel;
  450. //} CC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS, *PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS;
  451. break;
  452. case CC_FLOW_CONTROL_INDICATION:
  453. // CC_FLOW_CONTROL_INDICATION callback parameters (pConferenceCallbackParams)
  454. // typedef struct {
  455. // CC_HCHANNEL hChannel;
  456. // DWORD dwRate;
  457. // } CC_FLOW_CONTROL_CALLBACK_PARAMS, *PCC_FLOW_CONTROL_CALLBACK_PARAMS;
  458. break;
  459. case CC_BANDWIDTH_CHANGED_INDICATION:
  460. case CC_REQUEST_MODE_INDICATION:
  461. case CC_REQUEST_MODE_RESPONSE_INDICATION:
  462. break;
  463. case CC_ACCEPT_CHANNEL_INDICATION:
  464. hr = CC_OK;
  465. OnChannelAcceptComplete(hStatus, (PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS)pConferenceCallbackParams);
  466. break;
  467. //
  468. // Misc commands and indications. Some are related to channels
  469. //
  470. case CC_RX_NONSTANDARD_MESSAGE_INDICATION:
  471. break;
  472. case CC_H245_MISCELLANEOUS_COMMAND_INDICATION:
  473. OnMiscCommand(hStatus,
  474. (PCC_H245_MISCELLANEOUS_COMMAND_CALLBACK_PARAMS)pConferenceCallbackParams);
  475. break;
  476. case CC_H245_MISCELLANEOUS_INDICATION_INDICATION: // from the Department of Redundancy Department
  477. OnMiscIndication(hStatus,
  478. (PCC_H245_MISCELLANEOUS_INDICATION_CALLBACK_PARAMS)pConferenceCallbackParams);
  479. break;
  480. case CC_T120_CHANNEL_REQUEST_INDICATION:
  481. OnT120ChannelRequest(hStatus,(PCC_T120_CHANNEL_REQUEST_CALLBACK_PARAMS)pConferenceCallbackParams);
  482. break;
  483. case CC_T120_CHANNEL_OPEN_INDICATION:
  484. OnT120ChannelOpen(hStatus,(PCC_T120_CHANNEL_OPEN_CALLBACK_PARAMS)pConferenceCallbackParams);
  485. default:
  486. break;
  487. }
  488. return hr;
  489. }
  490. VOID CH323Ctrl::OnT120ChannelRequest(
  491. HRESULT hStatus,
  492. PCC_T120_CHANNEL_REQUEST_CALLBACK_PARAMS pT120RequestParams)
  493. {
  494. FX_ENTRY ("CH323Ctrl::OnT120ChannelRequest");
  495. PSOCKADDR_IN pAddr;
  496. SOCKADDR_IN sinD;
  497. CC_ADDR ChannelAddr;
  498. PCC_ADDR pChannelAddr;
  499. GUID mediaID;
  500. DWORD dwRejectReason = H245_REJ;
  501. BOOL bFound = FALSE;
  502. POSITION pos = m_ChannelList.GetHeadPosition();
  503. ICtrlCommChan *pChannel = NULL;
  504. // look for a matching channel instance.
  505. while (pos)
  506. {
  507. pChannel = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  508. ASSERT(pChannel);
  509. hrLast = pChannel->GetMediaType(&mediaID);
  510. if(!HR_SUCCEEDED(hrLast))
  511. goto ERROR_EXIT;
  512. if(mediaID == MEDIA_TYPE_H323_T120)
  513. {
  514. bFound = TRUE;
  515. break;
  516. }
  517. }
  518. if(!HR_SUCCEEDED(hrLast) || !bFound)
  519. {
  520. // Non-default channels Not Yet Implemented!!!!
  521. // When it is, ask the parent conference object to create another channel of the
  522. // specified media type.
  523. if(hrLast == CCO_E_NODEFAULT_CHANNEL)
  524. dwRejectReason = H245_REJ_TYPE_NOTAVAIL;
  525. goto REJECT_CHANNEL;
  526. }
  527. // if we are the H.245 master and have requested a T.120 channel already,
  528. // reject this request.
  529. if(m_ConferenceAttributes.bMaster && pChannel->GetHChannel())
  530. {
  531. goto REJECT_CHANNEL;
  532. }
  533. if(!pChannel->IsChannelEnabled()) // allow this channel ?
  534. {
  535. goto REJECT_CHANNEL;
  536. }
  537. pChannel->SetHChannel(pT120RequestParams->hChannel);
  538. if(pT120RequestParams->pAddr)
  539. {
  540. // the other end is listening on the specified address
  541. sinD.sin_family = AF_INET;
  542. sinD.sin_addr.S_un.S_addr = htonl(pT120RequestParams->pAddr->Addr.IP_Binary.dwAddr);
  543. sinD.sin_port = htons(pT120RequestParams->pAddr->Addr.IP_Binary.wPort);
  544. DEBUGMSG(ZONE_CONN,("%s, requestor listening on port 0x%04x, address 0x%08lX\r\n",_fx_,
  545. pT120RequestParams->pAddr->Addr.IP_Binary.wPort,
  546. pT120RequestParams->pAddr->Addr.IP_Binary.dwAddr));
  547. hrLast = pChannel->AcceptRemoteAddress(&sinD);
  548. pChannelAddr = NULL;
  549. }
  550. else
  551. {
  552. // the channel selects its local address(es)/port(s)
  553. if(!pChannel->SelectPorts((LPIControlChannel)this))
  554. {
  555. ERRORMESSAGE(("%s, SelectPorts failed\r\n",_fx_));
  556. hrLast = CCO_E_BAD_ADDRESS;
  557. goto REJECT_CHANNEL;
  558. }
  559. // get the address and ports of our end of the channel
  560. pAddr = pChannel->GetLocalAddress();
  561. // fixup channel addr pair structure.
  562. ChannelAddr.nAddrType = CC_IP_BINARY;
  563. ChannelAddr.bMulticast = FALSE;
  564. ChannelAddr.Addr.IP_Binary.wPort = ntohs(pAddr->sin_port);
  565. ChannelAddr.Addr.IP_Binary.dwAddr = ntohl(pAddr->sin_addr.S_un.S_addr);
  566. pChannelAddr = &ChannelAddr;
  567. DEBUGMSG(ZONE_CONN,("%s: accepting on port 0x%04x, address 0x%08lX\r\n",_fx_,
  568. ChannelAddr.Addr.IP_Binary.wPort,ChannelAddr.Addr.IP_Binary.dwAddr));
  569. }
  570. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelRequest accepting");
  571. hrLast = CC_AcceptT120Channel(
  572. pChannel->GetHChannel(),
  573. FALSE, // BOOL bAssociateConference,
  574. NULL, // PCC_OCTETSTRING pExternalReference,
  575. pChannelAddr);
  576. if(hrLast != CC_OK)
  577. {
  578. ERRORMESSAGE(("%s, CC_AcceptT120Channel returned 0x%08lX\r\n",_fx_, hrLast));
  579. goto ERROR_EXIT;
  580. }
  581. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelRequest accepted");
  582. // LOOKLOOK !!! the 2 following lines would not be there because we should
  583. // Wait for CC_ACCEPT_CHANNEL_INDICATION. But the CC_ACCEPT_CHANNEL_INDICATION
  584. // is missing if a send audio and send video channel is open at the time this
  585. // channel is accepted. A bug in CALLCONT.DLL that needs investigating.
  586. hrLast = pChannel->OnChannelOpen(CHANNEL_OPEN);
  587. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelRequest, open done");
  588. // ******
  589. // LOOKLOOK if OnChannelOpen returns an error, need to close the channel
  590. // but pChannel->Close() is not yet implemented for bidirectional channels
  591. // ******
  592. m_pConfAdvise->OnControlEvent(CCEV_CHANNEL_READY_BIDI, pChannel, this);
  593. //
  594. // Check for readiness to notify that all required channels are open
  595. //
  596. CheckChannelsReady( ); //
  597. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelRequest done");
  598. return;
  599. REJECT_CHANNEL:
  600. {
  601. // need private HRESULT! don't overwrite the reason we're rejecting the channel!!
  602. HRESULT hr;
  603. ERRORMESSAGE(("%s, rejecting channel\r\n",_fx_));
  604. hr = CC_RejectChannel(pT120RequestParams->hChannel, dwRejectReason);
  605. if(hr != CC_OK)
  606. {
  607. ERRORMESSAGE(("%s, CC_RejectChannel returned 0x%08lX\r\n",_fx_, hr));
  608. }
  609. }
  610. ERROR_EXIT:
  611. return;
  612. }
  613. VOID CH323Ctrl::OnT120ChannelOpen(
  614. HRESULT hStatus,
  615. PCC_T120_CHANNEL_OPEN_CALLBACK_PARAMS pT120OpenParams)
  616. {
  617. FX_ENTRY ("CH323Ctrl::OnT120ChannelOpen");
  618. SOCKADDR_IN sinD;
  619. GUID mediaID;
  620. ICtrlCommChan *pChannel = (ICtrlCommChan *)pT120OpenParams->dwUserToken;
  621. // validate channel token - is this what we think it is?
  622. if(IsBadWritePtr(pChannel, sizeof(ICtrlCommChan)))
  623. {
  624. ERRORMESSAGE(("%s:invalid channel token: 0x%08lx\r\n",_fx_, pT120OpenParams->dwUserToken));
  625. return;
  626. }
  627. #ifdef DEBUG
  628. POSITION pos = m_ChannelList.GetHeadPosition();
  629. ICtrlCommChan *pChan;
  630. BOOL bValid = FALSE;
  631. // look for a matching channel instance.
  632. while (pos)
  633. {
  634. pChan = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  635. ASSERT(pChan);
  636. if(pChan == pChannel)
  637. {
  638. bValid = TRUE;
  639. break;
  640. }
  641. }
  642. if(!bValid)
  643. {
  644. ERRORMESSAGE(("%s:unrecognized token 0x%08lX\r\n",_fx_,
  645. pT120OpenParams->dwUserToken));
  646. return;
  647. }
  648. #endif //DEBUG
  649. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelOpen");
  650. if(hStatus != CC_OK)
  651. {
  652. DEBUGMSG(ZONE_CONN,("%s: hStatus:0x%08lX\r\n",_fx_,hStatus));
  653. // LOOKLOOK need to interpret hStatus
  654. // let the channel know what happened.
  655. // if the request was rejected due to a collision of T.120 O.L.C. requests,
  656. // (other end is the master and other end also requested a T.120 channel)
  657. // then proceed with the call.
  658. if(m_ConferenceAttributes.bMaster)
  659. {
  660. // the slave would only reject in a real error condition
  661. pChannel->OnChannelOpen(CHANNEL_REJECTED);
  662. // the channel knows what happened, so let it do the worrying.
  663. return;
  664. }
  665. else // just a typical collision
  666. {
  667. return;
  668. }
  669. }
  670. // if the other end specified its listen address, use it
  671. if(pT120OpenParams->pAddr)
  672. {
  673. if(pT120OpenParams->pAddr->nAddrType != CC_IP_BINARY)
  674. {
  675. ERRORMESSAGE(("%s: invalid address type %d\r\n",_fx_,
  676. pT120OpenParams->pAddr->nAddrType));
  677. goto ERROR_EXIT;
  678. }
  679. // we now have the remote port info ( in host byte order)
  680. sinD.sin_family = AF_INET;
  681. sinD.sin_addr.S_un.S_addr = htonl(pT120OpenParams->pAddr->Addr.IP_Binary.dwAddr);
  682. sinD.sin_port = htons(pT120OpenParams->pAddr->Addr.IP_Binary.wPort);
  683. DEBUGMSG(ZONE_CONN,("%s, opened on port 0x%04x, address 0x%08lX\r\n",_fx_,
  684. pT120OpenParams->pAddr->Addr.IP_Binary.wPort,pT120OpenParams->pAddr->Addr.IP_Binary.dwAddr));
  685. hrLast = pChannel->AcceptRemoteAddress(&sinD);
  686. if(!HR_SUCCEEDED(hrLast))
  687. {
  688. ERRORMESSAGE(("%s:AcceptRemoteAddress failed\r\n",_fx_));
  689. goto ERROR_EXIT;
  690. }
  691. }
  692. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelOpen opening");
  693. hrLast = pChannel->OnChannelOpen(CHANNEL_OPEN);
  694. if(!HR_SUCCEEDED(hrLast))
  695. {
  696. ERRORMESSAGE(("%s:channel's OnChannelOpen() returned 0x%08lX\r\n", _fx_, hrLast));
  697. CloseChannel(pChannel);
  698. goto ERROR_EXIT;
  699. }
  700. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelOpen open done");
  701. m_pConfAdvise->OnControlEvent(CCEV_CHANNEL_READY_BIDI, pChannel, this);
  702. //
  703. // Check for readiness to notify that all required channels are open
  704. //
  705. CheckChannelsReady( );
  706. SHOW_OBJ_ETIME("CH323Ctrl::OnT120ChannelOpen done");
  707. return;
  708. ERROR_EXIT:
  709. // need to cleanup, disconnect, etc.
  710. m_hCallCompleteCode = CCCI_CHANNEL_OPEN_ERROR;
  711. // let the parent Conference object know about the imminent disconnect
  712. DoAdvise(CCEV_CALL_INCOMPLETE, &m_hCallCompleteCode);
  713. hrLast = CCO_E_MANDATORY_CHAN_OPEN_FAILED;
  714. InternalDisconnect();
  715. return;
  716. }
  717. //
  718. // This once did something. Currently, it's called whenever a channel is opened. The
  719. // call to GoNextPhase(CCS_Ready) changes state and posts a notification upward, but
  720. // that notification is currently ignored. (it's useless)
  721. // Reminder to mikev: A new notification is needed to indicate that capabilities
  722. // have been exchanged and it is OK to open channels.
  723. //
  724. VOID CH323Ctrl::CheckChannelsReady()
  725. {
  726. GoNextPhase(CCS_Ready);
  727. }
  728. // handles local hangup indication
  729. VOID CH323Ctrl::OnHangup(HRESULT hStatus)
  730. {
  731. FX_ENTRY ("CH323Ctrl::OnHangup");
  732. DEBUGMSG(ZONE_CONN,("%s:CC_HANGUP_INDICATION in phase %d\r\n", _fx_, m_Phase));
  733. switch(m_Phase)
  734. {
  735. case CCS_Disconnecting:
  736. GoNextPhase(CCS_Idle);
  737. Cleanup();
  738. DoAdvise(CCEV_DISCONNECTED ,NULL);
  739. break;
  740. default: // do nothing
  741. ERRORMESSAGE(("%s:Unexpected CC_HANGUP_INDICATION\r\n",_fx_));
  742. break;
  743. }
  744. }
  745. HRESULT CH323Ctrl::CloseChannel(ICtrlCommChan* pChannel)
  746. {
  747. FX_ENTRY ("CH323Ctrl::CloseChannel");
  748. if(!pChannel->IsChannelOpen())
  749. {
  750. ERRORMESSAGE(("%s: channel is not open\r\n",_fx_));
  751. hrLast = CCO_E_INVALID_PARAM;
  752. goto EXIT;
  753. }
  754. hrLast = CC_CloseChannel(pChannel->GetHChannel());
  755. if(!HR_SUCCEEDED(hrLast))
  756. {
  757. ERRORMESSAGE(("%s: CC_CloseChannel returned 0x%08lX\r\n",_fx_, hrLast));
  758. goto EXIT;
  759. }
  760. // make the channel handle its own media stream specific shutdown and cleanup chores
  761. hrLast = pChannel->OnChannelClose(CHANNEL_CLOSED);
  762. EXIT:
  763. return hrLast;
  764. }
  765. HRESULT CH323Ctrl::AddChannel(ICtrlCommChan * pCommChannel, LPIH323PubCap pCapabilityResolver)
  766. {
  767. ICtrlCommChan *pChan = NULL;
  768. // get the ICtrlCommChannel interface of each channel
  769. hrLast = pCommChannel->QueryInterface(IID_ICtrlCommChannel,(void **)&pChan);
  770. if(!HR_SUCCEEDED(hrLast))
  771. goto ADD_ERROR;
  772. // make the channel aware of its new scope
  773. hrLast = pChan->BeginControlSession(this, pCapabilityResolver);
  774. if(!HR_SUCCEEDED(hrLast))
  775. goto ADD_ERROR;
  776. // add it to the list
  777. m_ChannelList.AddTail(pChan);
  778. return hrSuccess;
  779. ADD_ERROR:
  780. if(pChan)
  781. pChan->Release();
  782. return CHAN_E_INVALID_PARAM;
  783. }
  784. HRESULT CH323Ctrl::OpenChannel(ICtrlCommChan* pChan, IH323PubCap *pCapResolver,
  785. MEDIA_FORMAT_ID dwIDLocalSend, MEDIA_FORMAT_ID dwIDRemoteRecv)
  786. {
  787. FX_ENTRY ("CH323Ctrl::OpenChannel");
  788. CC_TERMCAP H245ChannelCap;
  789. PSOCKADDR_IN pAddr;
  790. CC_ADDR ChannelAddr;
  791. LPVOID pChannelParams;
  792. PCC_TERMCAP pSaveChannelCapability = NULL;
  793. UINT uLocalParamSize;
  794. BYTE SessionID;
  795. BYTE payload_type;
  796. DWORD_PTR dwhChannel;
  797. GUID mediaID;
  798. ASSERT((pChan->IsChannelOpen()== FALSE) && (pChan->IsOpenPending()== FALSE));
  799. hrLast = pChan->GetMediaType(&mediaID);
  800. if(!HR_SUCCEEDED(hrLast))
  801. goto CHANNEL_ERROR;
  802. if (mediaID == MEDIA_TYPE_H323_T120)
  803. {
  804. if(pChan->GetHChannel()) // already accepted a T.120 channel?
  805. {
  806. ERRORMESSAGE(("%s, already have a pending channel\r\n",_fx_));
  807. goto CHANNEL_ERROR; // this is not an error, excuse the label
  808. }
  809. // test the no common capability case. notify the conference object of the
  810. // inability to open the channel, and return success
  811. if(dwIDLocalSend == INVALID_MEDIA_FORMAT)
  812. {
  813. pChan->OnChannelOpen(CHANNEL_NO_CAPABILITY);
  814. return hrSuccess;
  815. }
  816. // There is no "standard" rule regarding which end specifies the "listen"
  817. // address of a T.120 channel. However: we want NetMeeting-NetMeeting calls
  818. // to behave consistently (the "caller" always "places the T.120 call").
  819. // Therefore, specify the address if this end is not the originator. That will
  820. // force the other end to specify it's address.
  821. if(IsOriginating(m_ChanFlags))
  822. {
  823. pAddr = NULL; // the other end "listens" and we "connect"
  824. }
  825. else // listen on local address
  826. {
  827. // select ports if they are not already selected
  828. if(!pChan->SelectPorts((LPIControlChannel)this))
  829. {
  830. ERRORMESSAGE(("%s, SelectPorts failed\r\n",_fx_));
  831. hrLast = CCO_E_BAD_ADDRESS;
  832. goto CHANNEL_ERROR;
  833. }
  834. // get the address and port
  835. pAddr = pChan->GetLocalAddress();
  836. // fixup channel addr structure.
  837. ChannelAddr.nAddrType = CC_IP_BINARY;
  838. ChannelAddr.bMulticast = FALSE;
  839. ChannelAddr.Addr.IP_Binary.wPort = ntohs(pAddr->sin_port);
  840. ChannelAddr.Addr.IP_Binary.dwAddr = ntohl(pAddr->sin_addr.S_un.S_addr);
  841. }
  842. hrLast = CC_OpenT120Channel(
  843. // CC_HCONFERENCE hConference,
  844. m_hConference,
  845. // PCC_HCHANNEL phChannel,
  846. &dwhChannel,
  847. // BOOL bAssociateConference,
  848. FALSE,
  849. // PCC_OCTETSTRING pExternalReference,
  850. NULL,
  851. // PCC_ADDR pAddr,
  852. IsOriginating(m_ChanFlags) ? NULL : &ChannelAddr,
  853. // DWORD dwChannelBitRate,
  854. 0,
  855. // DWORD dwUserToken);
  856. (DWORD_PTR)pChan);
  857. // and fall out to test hrLast, etc.
  858. }
  859. else // is an audio or video channel
  860. {
  861. // test the no common capability case. If the channel is mandatory,
  862. // return an error, else notify the conference object of the
  863. // inability to open the channel, and return success
  864. if((dwIDLocalSend == INVALID_MEDIA_FORMAT) ||(dwIDRemoteRecv == INVALID_MEDIA_FORMAT))
  865. {
  866. pChan->OnChannelOpen(CHANNEL_NO_CAPABILITY);
  867. return hrSuccess;
  868. }
  869. //
  870. // test if we need to try to open this !!!
  871. //
  872. if(!pChan->IsChannelEnabled())
  873. {
  874. return hrSuccess;
  875. }
  876. SHOW_OBJ_ETIME("CH323Ctrl::OpenChannel");
  877. // Get the remote channel parameters for
  878. // the send channel - these parameters are used to request a channel
  879. uLocalParamSize = pCapResolver->GetLocalSendParamSize((MEDIA_FORMAT_ID)dwIDLocalSend);
  880. pChannelParams=MemAlloc (uLocalParamSize);
  881. if (pChannelParams == NULL) {
  882. //Doom
  883. hrLast = CCO_E_SYSTEM_ERROR;
  884. goto CHANNEL_ERROR;
  885. }
  886. hrLast = pCapResolver->GetEncodeParams(
  887. (LPVOID)&H245ChannelCap, sizeof(H245ChannelCap),
  888. (LPVOID)pChannelParams, uLocalParamSize,
  889. (AUDIO_FORMAT_ID)dwIDRemoteRecv,
  890. (AUDIO_FORMAT_ID)dwIDLocalSend);
  891. if(!HR_SUCCEEDED(hrLast))
  892. {
  893. ERRORMESSAGE(("%s: GetEncodeParams returned 0x%08lX\r\n",_fx_, hrLast));
  894. goto CHANNEL_ERROR;
  895. }
  896. // set session ID and payload type. Note that payload type is relevant only for
  897. // dynamic payloads. Otherwise, it must be zero.
  898. if (H245ChannelCap.DataType == H245_DATA_AUDIO)
  899. {
  900. payload_type = ((PAUDIO_CHANNEL_PARAMETERS)pChannelParams)->RTP_Payload;
  901. // Session ID is 1 for Audio, 2 for Video . H245 7.3.1 (H2250 Logical Channel Param)
  902. SessionID=1;
  903. }
  904. else if (H245ChannelCap.DataType == H245_DATA_VIDEO)
  905. {
  906. payload_type = ((PVIDEO_CHANNEL_PARAMETERS)pChannelParams)->RTP_Payload;
  907. SessionID=2;
  908. }
  909. // payload_type must be zero for fixed payload types. Weird.
  910. if(!IsDynamicPayload(payload_type))
  911. payload_type = 0;
  912. // create a marshalled version of channel parameters and store it in the channel
  913. // for later reference
  914. if(H245ChannelCap.ClientType == H245_CLIENT_AUD_NONSTD)
  915. {
  916. // Make a flat copy of the nonstandard capability to store as the channel
  917. // parameter
  918. UINT uSize = H245ChannelCap.Cap.H245Aud_NONSTD.data.length;
  919. pSaveChannelCapability = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP) + uSize);
  920. if(!pSaveChannelCapability)
  921. {
  922. hrLast = CCO_E_SYSTEM_ERROR;
  923. goto CHANNEL_ERROR;
  924. }
  925. // copy fixed part
  926. memcpy(pSaveChannelCapability, &H245ChannelCap, sizeof(CC_TERMCAP));
  927. // variable part follows the fixed part
  928. pSaveChannelCapability->Cap.H245Aud_NONSTD.data.value
  929. = (unsigned char *)(((BYTE *)pSaveChannelCapability) + sizeof(CC_TERMCAP));
  930. // copy variable part
  931. memcpy(pSaveChannelCapability->Cap.H245Aud_NONSTD.data.value,
  932. H245ChannelCap.Cap.H245Aud_NONSTD.data.value,
  933. H245ChannelCap.Cap.H245Aud_NONSTD.data.length);
  934. // and length
  935. pSaveChannelCapability->Cap.H245Aud_NONSTD.data.length
  936. = H245ChannelCap.Cap.H245Aud_NONSTD.data.length;
  937. // make the channel remember the channel parameters.
  938. // a zero size as the second arg means that a preallocated chunk is being passed
  939. hrLast = pChan->ConfigureCapability(pSaveChannelCapability, 0,
  940. pChannelParams, uLocalParamSize);
  941. if(!HR_SUCCEEDED(hrLast))
  942. {
  943. ERRORMESSAGE(("%s:ConfigureCapability returned 0x%08lx\r\n",_fx_, hrLast));
  944. hrLast = CCO_E_SYSTEM_ERROR;
  945. goto CHANNEL_ERROR;
  946. }
  947. pSaveChannelCapability=NULL; // the channel owns this memory now
  948. }
  949. else if(H245ChannelCap.ClientType == H245_CLIENT_VID_NONSTD)
  950. {
  951. // Make a flat copy of the nonstandard capability to store as the channel
  952. // parameter
  953. UINT uSize = H245ChannelCap.Cap.H245Vid_NONSTD.data.length;
  954. pSaveChannelCapability = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP) + uSize);
  955. if(!pSaveChannelCapability)
  956. {
  957. hrLast = CCO_E_SYSTEM_ERROR;
  958. goto CHANNEL_ERROR;
  959. }
  960. // copy fixed part
  961. memcpy(pSaveChannelCapability, &H245ChannelCap, sizeof(CC_TERMCAP));
  962. // variable part follows the fixed part
  963. pSaveChannelCapability->Cap.H245Vid_NONSTD.data.value
  964. = (unsigned char *)(((BYTE *)pSaveChannelCapability) + sizeof(CC_TERMCAP));
  965. // copy variable part
  966. memcpy(pSaveChannelCapability->Cap.H245Vid_NONSTD.data.value,
  967. H245ChannelCap.Cap.H245Vid_NONSTD.data.value,
  968. H245ChannelCap.Cap.H245Vid_NONSTD.data.length);
  969. // and length
  970. pSaveChannelCapability->Cap.H245Vid_NONSTD.data.length
  971. = H245ChannelCap.Cap.H245Vid_NONSTD.data.length;
  972. // make the channel remember the channel parameters.
  973. // a zero size as the second arg means that a preallocated chunk is being passed
  974. hrLast = pChan->ConfigureCapability(pSaveChannelCapability, 0,
  975. pChannelParams, uLocalParamSize);
  976. if(!HR_SUCCEEDED(hrLast))
  977. {
  978. ERRORMESSAGE(("%s:ConfigureCapability returned 0x%08lx\r\n",_fx_, hrLast));
  979. hrLast = CCO_E_SYSTEM_ERROR;
  980. goto CHANNEL_ERROR;
  981. }
  982. pSaveChannelCapability=NULL; // the channel owns this memory now
  983. }
  984. else
  985. {
  986. // only need to remember the already-flat H.245 cap structure.
  987. hrLast = pChan->ConfigureCapability(&H245ChannelCap, sizeof(CC_TERMCAP),
  988. pChannelParams, uLocalParamSize);
  989. if(!HR_SUCCEEDED(hrLast))
  990. {
  991. ERRORMESSAGE(("%s:ConfigureCapability returned 0x%08lx\r\n",_fx_, hrLast));
  992. hrLast = CCO_E_SYSTEM_ERROR;
  993. goto CHANNEL_ERROR;
  994. }
  995. }
  996. // remember both versions of the resolved send format for the channel
  997. // we're about to open
  998. pChan->SetNegotiatedLocalFormat(dwIDLocalSend);
  999. pChan->SetNegotiatedRemoteFormat(dwIDRemoteRecv);
  1000. SHOW_OBJ_ETIME("CH323Ctrl::OpenChannel done configuring");
  1001. // select ports if they are not already selected
  1002. if(!pChan->SelectPorts((LPIControlChannel)this))
  1003. {
  1004. ERRORMESSAGE(("%s, SelectPorts failed\r\n",_fx_));
  1005. hrLast = CCO_E_BAD_ADDRESS;
  1006. goto CHANNEL_ERROR;
  1007. }
  1008. // get the address and port of our RTCP channel
  1009. pAddr = pChan->GetLocalAddress();
  1010. // fixup channel addr structure. There are two ports, but in RTP, it is implicit
  1011. // that the RTCP control port is the next highest port number.
  1012. // The open logical channel request needs the reverse RTCP port to be specified.
  1013. ChannelAddr.nAddrType = CC_IP_BINARY;
  1014. ChannelAddr.bMulticast = FALSE;
  1015. ChannelAddr.Addr.IP_Binary.wPort = pChan->GetLocalRTCPPort();
  1016. ChannelAddr.Addr.IP_Binary.dwAddr = ntohl(pAddr->sin_addr.S_un.S_addr);
  1017. DEBUGMSG(ZONE_CONN,("%s: opening using RTCP port 0x%04x, address 0x%08lX\r\n",_fx_,
  1018. ChannelAddr.Addr.IP_Binary.wPort,ChannelAddr.Addr.IP_Binary.dwAddr));
  1019. DEBUGMSG(ZONE_CONN,("%s: requesting capability ID:0x%08lX\r\n",
  1020. _fx_, H245ChannelCap.CapId));
  1021. // open a channel
  1022. SHOW_OBJ_ETIME("CH323Ctrl::OpenChannel, opening");
  1023. hrLast = CC_OpenChannel(m_hConference, &dwhChannel,
  1024. SessionID,
  1025. 0, // BYTE bAssociatedSessionID,
  1026. TRUE, //BOOL bSilenceSuppression, WE ALWAYS DO SILENCE SUPPRESSION
  1027. &H245ChannelCap,
  1028. &ChannelAddr, // the local address on which we're listening for RTCP
  1029. payload_type, // PAYLOAD TYPE
  1030. 0, // DWORD dwChannelBitRate,
  1031. (DWORD_PTR)pChan); // use the channel pointer as the user token
  1032. } // end else is an audio or video channel
  1033. if(hrLast != CC_OK)
  1034. {
  1035. ERRORMESSAGE(("%s: OpenChannel returned 0x%08lX\r\n",_fx_, hrLast));
  1036. goto CHANNEL_ERROR;
  1037. }
  1038. else
  1039. {
  1040. pChan->SetHChannel(dwhChannel);
  1041. pChan->OnChannelOpening();
  1042. }
  1043. SHOW_OBJ_ETIME("CH323Ctrl::OpenChannel done");
  1044. return hrLast;
  1045. CHANNEL_ERROR:
  1046. if(pSaveChannelCapability)
  1047. MemFree(pSaveChannelCapability);
  1048. return hrLast;
  1049. }
  1050. VOID CH323Ctrl::CleanupConferenceAttributes()
  1051. {
  1052. WORD w;
  1053. if(m_ConferenceAttributes.pParticipantList->ParticipantInfoArray)
  1054. {
  1055. for(w=0;w<m_ConferenceAttributes.pParticipantList->wLength;w++)
  1056. {
  1057. if(m_ConferenceAttributes.pParticipantList->
  1058. ParticipantInfoArray[w].TerminalID.pOctetString)
  1059. {
  1060. MemFree(m_ConferenceAttributes.pParticipantList->
  1061. ParticipantInfoArray[w].TerminalID.pOctetString);
  1062. }
  1063. }
  1064. MemFree(m_ConferenceAttributes.pParticipantList->ParticipantInfoArray);
  1065. }
  1066. m_ConferenceAttributes.pParticipantList->ParticipantInfoArray = NULL;
  1067. m_ConferenceAttributes.pParticipantList->wLength = 0;
  1068. }
  1069. HRESULT CH323Ctrl::AllocConferenceAttributes()
  1070. {
  1071. WORD w;
  1072. #define MAX_PART_LEN 128
  1073. if(m_ConferenceAttributes.pParticipantList->wLength)
  1074. {
  1075. m_ConferenceAttributes.pParticipantList->ParticipantInfoArray =
  1076. (PCC_PARTICIPANTINFO) MemAlloc (sizeof(CC_PARTICIPANTINFO)
  1077. * m_ConferenceAttributes.pParticipantList->wLength);
  1078. if(!m_ConferenceAttributes.pParticipantList->ParticipantInfoArray)
  1079. return CCO_E_OUT_OF_MEMORY;
  1080. for(w=0;w<m_ConferenceAttributes.pParticipantList->wLength;w++)
  1081. {
  1082. m_ConferenceAttributes.pParticipantList->
  1083. ParticipantInfoArray[w].TerminalID.pOctetString
  1084. = (BYTE *)MemAlloc(MAX_PART_LEN);
  1085. if(m_ConferenceAttributes.pParticipantList->
  1086. ParticipantInfoArray[w].TerminalID.pOctetString)
  1087. {
  1088. m_ConferenceAttributes.pParticipantList->
  1089. ParticipantInfoArray[w].TerminalID.wOctetStringLength
  1090. = MAX_PART_LEN;
  1091. }
  1092. else
  1093. {
  1094. m_ConferenceAttributes.pParticipantList->
  1095. ParticipantInfoArray[w].TerminalID.wOctetStringLength =0;
  1096. return CCO_E_OUT_OF_MEMORY;
  1097. }
  1098. }
  1099. }
  1100. return hrSuccess;
  1101. }
  1102. VOID CH323Ctrl::OnCallConnect(HRESULT hStatus, PCC_CONNECT_CALLBACK_PARAMS pConfParams)
  1103. {
  1104. FX_ENTRY ("CH323Ctrl::OnCallConnect");
  1105. PCC_TERMCAPLIST pTermCapList;
  1106. PCC_TERMCAPDESCRIPTORS pTermCapDescriptors;
  1107. CC_TERMCAP H245ChannelCap;
  1108. PCC_TERMCAP pChannelCap = NULL;
  1109. CapsCtl *pCapabilityResolver = NULL;
  1110. GUID mediaID;
  1111. POSITION pos = NULL;
  1112. ICtrlCommChan *pChan = NULL;
  1113. if(hStatus != CC_OK)
  1114. {
  1115. ERRORMESSAGE(("%s hStatus=0x%08lx in phase %d\r\n",_fx_,hStatus,m_Phase));
  1116. // test for gatekeeper admission reject
  1117. // FACILITY_GKIADMISSION
  1118. if(CUSTOM_FACILITY(hStatus) == FACILITY_GKIADMISSION)
  1119. {
  1120. // pass this code intact - do not remap
  1121. m_hCallCompleteCode = hStatus;
  1122. }
  1123. else
  1124. {
  1125. switch (hStatus)
  1126. {
  1127. default:
  1128. // reason is unknown
  1129. m_hCallCompleteCode = CCCI_UNKNOWN;
  1130. break;
  1131. case CC_PEER_REJECT:
  1132. if(m_Phase == CCS_Connecting)
  1133. {
  1134. switch(pConfParams->bRejectReason)
  1135. {
  1136. case CC_REJECT_ADAPTIVE_BUSY:
  1137. case CC_REJECT_IN_CONF:
  1138. case CC_REJECT_USER_BUSY:
  1139. m_hCallCompleteCode = CCCI_BUSY;
  1140. break;
  1141. case CC_REJECT_SECURITY_DENIED:
  1142. m_hCallCompleteCode = CCCI_SECURITY_DENIED;
  1143. break;
  1144. case CC_REJECT_NO_ANSWER:
  1145. case CC_REJECT_TIMER_EXPIRED:
  1146. m_hCallCompleteCode = CCCI_NO_ANSWER_TIMEOUT;
  1147. break;
  1148. case CC_REJECT_GATEKEEPER_RESOURCES:
  1149. m_hCallCompleteCode = CCCI_GK_NO_RESOURCES;
  1150. break;
  1151. default:
  1152. //#define CC_REJECT_NO_BANDWIDTH 1
  1153. //#define CC_REJECT_GATEKEEPER_RESOURCES 2
  1154. //#define CC_REJECT_UNREACHABLE_DESTINATION 3
  1155. //#define CC_REJECT_DESTINATION_REJECTION 4
  1156. //#define CC_REJECT_INVALID_REVISION 5
  1157. //#define CC_REJECT_NO_PERMISSION 6
  1158. //#define CC_REJECT_UNREACHABLE_GATEKEEPER 7
  1159. //#define CC_REJECT_GATEWAY_RESOURCES 8
  1160. //#define CC_REJECT_BAD_FORMAT_ADDRESS 9
  1161. //#define CC_REJECT_ROUTE_TO_GATEKEEPER 12
  1162. // would be nice to handle this -->> //#define CC_REJECT_CALL_FORWARDED 13
  1163. //#define CC_REJECT_ROUTE_TO_MC 14
  1164. //#define CC_REJECT_UNDEFINED_REASON 15
  1165. //#define CC_REJECT_INTERNAL_ERROR 16 // Internal error occured in peer CS stack.
  1166. //#define CC_REJECT_NORMAL_CALL_CLEARING 17 // Normal call hangup
  1167. //#define CC_REJECT_NOT_IMPLEMENTED 20 // Service has not been implemented
  1168. //#define CC_REJECT_MANDATORY_IE_MISSING 21 // Pdu missing mandatory ie
  1169. //#define CC_REJECT_INVALID_IE_CONTENTS 22 // Pdu ie was incorrect
  1170. //#define CC_REJECT_CALL_DEFLECTION 24 // You deflected the call, so lets quit.
  1171. //#define CC_REJECT_GATEKEEPER_TERMINATED 25 // Gatekeeper terminated call
  1172. m_hCallCompleteCode = CCCI_REJECTED;
  1173. break;
  1174. }
  1175. }
  1176. else
  1177. {
  1178. ERRORMESSAGE(("%s:Received CC_PEER_REJECT in state %d\r\n",_fx_,m_Phase));
  1179. }
  1180. break;
  1181. case CC_INTERNAL_ERROR:
  1182. m_hCallCompleteCode = CCCI_LOCAL_ERROR;
  1183. break;
  1184. }
  1185. }
  1186. // let the parent Conference object know (unless this is the answering end)
  1187. if(m_Phase == CCS_Connecting)
  1188. {
  1189. DoAdvise(CCEV_CALL_INCOMPLETE, &m_hCallCompleteCode);
  1190. }
  1191. InternalDisconnect();
  1192. return;
  1193. }
  1194. else if(!pConfParams)
  1195. {
  1196. ERRORMESSAGE(("OnCallConnect: null pConfParams\r\n"));
  1197. m_hCallCompleteCode = CCCI_LOCAL_ERROR;
  1198. DoAdvise(CCEV_CALL_INCOMPLETE, &m_hCallCompleteCode);
  1199. InternalDisconnect();
  1200. return;
  1201. }
  1202. SetRemoteVendorID(pConfParams->pVendorInfo);
  1203. GoNextPhase(CCS_Opening);
  1204. m_ChanFlags |= (CTRLF_OPEN);
  1205. DEBUGMSG(ZONE_CONN,("%s:CONNECTION_CONNECTED\r\n", _fx_));
  1206. if((!pConfParams->pLocalAddr) || (pConfParams->pLocalAddr->nAddrType != CC_IP_BINARY))
  1207. {
  1208. if(pConfParams->pLocalAddr)
  1209. {
  1210. ERRORMESSAGE(("%s: invalid address type %d\r\n",_fx_,pConfParams->pLocalAddr->nAddrType));
  1211. }
  1212. else
  1213. {
  1214. ERRORMESSAGE(("%s: null local address\r\n",_fx_));
  1215. }
  1216. ERRORMESSAGE(("%s:where's the local address????\r\n",_fx_));
  1217. PHOSTENT phe;
  1218. PSOCKADDR_IN psin;
  1219. char szTemp[200];
  1220. LPCSTR lpHostName;
  1221. gethostname(szTemp,sizeof(szTemp));
  1222. lpHostName = szTemp;
  1223. psin = &local_sin;
  1224. phe = gethostbyname(lpHostName);
  1225. if (phe != NULL)
  1226. {
  1227. memcpy((char FAR *)&(psin->sin_addr), phe->h_addr,phe->h_length);
  1228. psin->sin_family = AF_INET;
  1229. }
  1230. }
  1231. else
  1232. {
  1233. // remember our local address
  1234. local_sin.sin_family = AF_INET;
  1235. // in host byte order
  1236. local_sin.sin_addr.S_un.S_addr = htonl(pConfParams->pLocalAddr->Addr.IP_Binary.dwAddr);
  1237. // in host byte order
  1238. local_sin.sin_port = htons(pConfParams->pLocalAddr->Addr.IP_Binary.wPort);
  1239. }
  1240. DEBUGMSG(ZONE_CONN,("%s local port 0x%04x, address 0x%08lX\r\n",_fx_,
  1241. local_sin.sin_port,local_sin.sin_addr.S_un.S_addr));
  1242. // get remote address
  1243. if((!pConfParams->pPeerAddr) || (pConfParams->pPeerAddr->nAddrType != CC_IP_BINARY))
  1244. {
  1245. if(pConfParams->pPeerAddr)
  1246. {
  1247. ERRORMESSAGE(("%s: invalid address type %d\r\n",_fx_,pConfParams->pPeerAddr->nAddrType));
  1248. }
  1249. else
  1250. {
  1251. ERRORMESSAGE(("%s: null local address\r\n",_fx_));
  1252. }
  1253. }
  1254. else
  1255. {
  1256. // remember the remote peer address
  1257. remote_sin.sin_family = AF_INET;
  1258. // in host byte order
  1259. remote_sin.sin_addr.S_un.S_addr = htonl(pConfParams->pPeerAddr->Addr.IP_Binary.dwAddr);
  1260. // in host byte order
  1261. remote_sin.sin_port = htons(pConfParams->pPeerAddr->Addr.IP_Binary.wPort);
  1262. }
  1263. //
  1264. // The only available remote user information in this state is the Q.931 display name.
  1265. // If we are the callee, we got the caller alias name (wire format was unicode) in
  1266. // the listen callback parameters. If we are the caller, we really need the callee
  1267. // alias name(s), which are not propagated. Fallback to the Q.931 display name (ASCII)
  1268. //
  1269. NewRemoteUserInfo(NULL, pConfParams->pszPeerDisplay);
  1270. // release any stale memory, reset ConferenceAttributes struture
  1271. CleanupConferenceAttributes();
  1272. // get the number of conference participants etc.
  1273. SHOW_OBJ_ETIME("CH323Ctrl::OnCallConnect getting attribs 1");
  1274. hrLast = CC_GetConferenceAttributes(m_hConference, &m_ConferenceAttributes);
  1275. if(!HR_SUCCEEDED(hrLast))
  1276. {// fatal error
  1277. ERRORMESSAGE(("%s,CC_GetConferenceAttributes returned 0x%08lX\r\n", _fx_, hrLast));
  1278. goto CONNECT_ERROR;
  1279. }
  1280. hrLast = AllocConferenceAttributes();
  1281. if(!HR_SUCCEEDED(hrLast))
  1282. {// fatal error
  1283. ERRORMESSAGE(("%s,AllocConferenceAttributes returned 0x%08lX\r\n", _fx_, hrLast));
  1284. goto CONNECT_ERROR;
  1285. }
  1286. // now get the real attributes
  1287. SHOW_OBJ_ETIME("CH323Ctrl::OnCallConnect getting attribs 2");
  1288. hrLast = CC_GetConferenceAttributes(m_hConference, &m_ConferenceAttributes);
  1289. if(!HR_SUCCEEDED(hrLast))
  1290. {// fatal error
  1291. ERRORMESSAGE(("%s,CC_GetConferenceAttributes returned 0x%08lX\r\n", _fx_, hrLast));
  1292. goto CONNECT_ERROR;
  1293. }
  1294. SHOW_OBJ_ETIME("CH323Ctrl::OnCallConnect got attribs");
  1295. m_ConferenceID =m_ConferenceAttributes.ConferenceID;
  1296. m_bMultipointController = m_ConferenceAttributes.bMultipointController;
  1297. hrLast = m_pConfAdvise->GetCapResolver((LPVOID *)&pCapabilityResolver, OID_CAP_ACM_TO_H323);
  1298. if(!HR_SUCCEEDED(hrLast) || (pCapabilityResolver == NULL))
  1299. {// fatal error
  1300. ERRORMESSAGE(("%s,null resolver\r\n", _fx_));
  1301. goto CONNECT_ERROR;
  1302. }
  1303. // get the remote capabilities
  1304. // cache the remote capabilities now
  1305. pTermCapList = pConfParams->pTermCapList;
  1306. pTermCapDescriptors = pConfParams->pTermCapDescriptors;
  1307. hrLast = pCapabilityResolver->AddRemoteDecodeCaps(pTermCapList, pTermCapDescriptors, &m_RemoteVendorInfo);
  1308. if(!HR_SUCCEEDED(hrLast))
  1309. {// fatal error
  1310. ERRORMESSAGE(("%s,AddRemoteDecodeCaps returned 0x%08lX\r\n", _fx_, hrLast));
  1311. goto CONNECT_ERROR;
  1312. }
  1313. SHOW_OBJ_ETIME("CH323Ctrl::OnCallConnect saved caps");
  1314. DoAdvise(CCEV_CAPABILITIES_READY, NULL); // put connobj in a state to allow other
  1315. // channels to be added & opened
  1316. //
  1317. // notify UI here. It wants remote user info.
  1318. //
  1319. ConnectNotify(CCEV_CONNECTED);
  1320. SHOW_OBJ_ETIME("CH323Ctrl::OnCallConnect notified");
  1321. return;
  1322. CONNECT_ERROR:
  1323. // release all channels
  1324. ReleaseAllChannels();
  1325. InternalDisconnect();
  1326. }
  1327. // LOOKLOOK methinks ConnectNotify might need to propagate the conference ID.
  1328. // This will be a moot point if we have a real property interface. Watch
  1329. // for this in the meantime
  1330. VOID CH323Ctrl::ConnectNotify(DWORD dwEvent)
  1331. {
  1332. FX_ENTRY ("CH323Ctrl::ConnectNotify");
  1333. CTRL_USER_INFO UserInfo;
  1334. LPWSTR lpwstr = NULL;
  1335. WCHAR wc =0;
  1336. // init to zero in case of error
  1337. UserInfo.dwCallerIDSize = 0;
  1338. UserInfo.lpvCallerIDData = NULL;
  1339. UserInfo.lpvRemoteProtocolInfo = NULL;
  1340. UserInfo.lpvLocalProtocolInfo = NULL;
  1341. // alias address strings, e.g. caller ID, are in UNICODE
  1342. if( m_pRemoteAliasItem &&
  1343. m_pRemoteAliasItem->pData &&
  1344. *((LPWSTR*)(m_pRemoteAliasItem->pData)))
  1345. {
  1346. lpwstr =(LPWSTR)m_pRemoteAliasItem->pData;
  1347. }
  1348. else
  1349. {
  1350. lpwstr = pwszPeerDisplayName;
  1351. }
  1352. if(lpwstr)
  1353. {
  1354. if(pwszPeerAliasName)
  1355. {
  1356. MemFree(pwszPeerAliasName);
  1357. }
  1358. ULONG ulSize = (lstrlenW(lpwstr) + 1) * sizeof(WCHAR);
  1359. pwszPeerAliasName = (LPWSTR)MemAlloc(ulSize);
  1360. LStrCpyW(pwszPeerAliasName, lpwstr);
  1361. // point to user name stuff
  1362. UserInfo.dwCallerIDSize = ulSize;
  1363. UserInfo.lpvCallerIDData = (LPVOID)pwszPeerAliasName;
  1364. }
  1365. else
  1366. {
  1367. // point to the single NULL character on the stack
  1368. UserInfo.dwCallerIDSize = 1;
  1369. UserInfo.lpvCallerIDData = &wc;
  1370. }
  1371. DoAdvise(dwEvent, &UserInfo);
  1372. }
  1373. VOID CH323Ctrl::NewRemoteUserInfo(PCC_ALIASNAMES pRemoteAliasNames,
  1374. LPWSTR pwszRemotePeerDisplayName)
  1375. {
  1376. FX_ENTRY ("CH323Ctrl::NewRemoteUserInfo");
  1377. ULONG ulSize;
  1378. PCC_ALIASITEM pItem;
  1379. WORD wC;
  1380. // make a copy of the user display name (what else???) We need to hold this
  1381. // at least until the parent object is notified and has a chance to copy the
  1382. // information
  1383. // Future implementation will store each item as a distinct property.
  1384. // These will be accessable via the IProperty interface
  1385. // find the display name if it exists
  1386. if(pRemoteAliasNames)
  1387. {
  1388. wC = pRemoteAliasNames->wCount;
  1389. pItem = pRemoteAliasNames->pItems;
  1390. while (wC--)
  1391. {
  1392. if(!pItem)
  1393. {
  1394. continue;
  1395. }
  1396. if(pItem->wType == CC_ALIAS_H323_ID)
  1397. {
  1398. if(!pItem->wDataLength || !pItem->pData)
  1399. {
  1400. continue;
  1401. }
  1402. if(m_pRemoteAliasItem)
  1403. {
  1404. DEBUGMSG(ZONE_CONN,("%s: Releasing previous user info\r\n",_fx_));
  1405. MemFree(m_pRemoteAliasItem);
  1406. }
  1407. // The H323 ID is UNICODE, and needs to be converted to ANSI
  1408. // for propagation to UI/client app. The conversion is done
  1409. // in ConnectNotify()
  1410. // need enough mem for the struct, the name, + null terminator
  1411. ulSize = ((pItem->wDataLength +1)*sizeof(WCHAR)) + sizeof(CC_ALIASITEM);
  1412. m_pRemoteAliasItem = (PCC_ALIASITEM)MemAlloc(ulSize);
  1413. memcpy(m_pRemoteAliasItem, pItem, sizeof(CC_ALIASITEM));
  1414. m_pRemoteAliasItem->pData = (WCHAR*)(((char *)m_pRemoteAliasItem)+sizeof(CC_ALIASITEM));
  1415. memcpy(m_pRemoteAliasItem->pData, pItem->pData, pItem->wDataLength*sizeof(WCHAR));
  1416. // need to null terminate it
  1417. *(WCHAR *)(((BYTE *)m_pRemoteAliasItem->pData) + pItem->wDataLength*sizeof(WCHAR))
  1418. = (WCHAR)0;
  1419. }
  1420. pItem++;
  1421. }
  1422. }
  1423. if(pwszRemotePeerDisplayName)
  1424. {
  1425. if(pwszPeerDisplayName)
  1426. {
  1427. DEBUGMSG(ZONE_CONN,("%s: Releasing previous pwszPeerDisplayName\r\n",_fx_));
  1428. MemFree(pwszPeerDisplayName);
  1429. }
  1430. // this WAS the Q.931 display name which WAS always ascii
  1431. // ulSize = lstrlen(szRemotePeerDisplayName) + 1;
  1432. // Now it's unicode
  1433. ulSize = (lstrlenW(pwszRemotePeerDisplayName) + 1)* sizeof(WCHAR);
  1434. pwszPeerDisplayName = (LPWSTR)MemAlloc(ulSize);
  1435. memcpy(pwszPeerDisplayName, pwszRemotePeerDisplayName, ulSize);
  1436. }
  1437. }
  1438. VOID CH323Ctrl::OnCallRinging(HRESULT hStatus, PCC_RINGING_CALLBACK_PARAMS pRingingParams)
  1439. {
  1440. if(pRingingParams->pNonStandardData)
  1441. {
  1442. // nyi
  1443. }
  1444. DoAdvise(CCEV_RINGING, NULL);
  1445. }
  1446. HRESULT CH323Ctrl::FindDefaultRXChannel(PCC_TERMCAP pChannelCapability, ICtrlCommChan **lplpChannel)
  1447. {
  1448. FX_ENTRY ("CH323Ctrl::FindDefaultRXChannel");
  1449. HRESULT hr = hrSuccess;
  1450. GUID mediaID;
  1451. POSITION pos = m_ChannelList.GetHeadPosition();
  1452. ICtrlCommChan *pChannel;
  1453. if(!pChannelCapability | !lplpChannel)
  1454. {
  1455. ERRORMESSAGE(("%s: null param:pcap:0x%08lX, pchan:0x%08lX\r\n",_fx_,
  1456. pChannelCapability, lplpChannel));
  1457. hr = CCO_E_INVALID_PARAM;
  1458. goto EXIT;
  1459. }
  1460. // look for a matching channel instance.
  1461. while (pos)
  1462. {
  1463. pChannel = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  1464. ASSERT(pChannel);
  1465. if(pChannel->IsSendChannel() == FALSE)
  1466. {
  1467. hr = pChannel->GetMediaType(&mediaID);
  1468. if(!HR_SUCCEEDED(hr))
  1469. goto EXIT;
  1470. if(((mediaID == MEDIA_TYPE_H323AUDIO) && (pChannelCapability->DataType ==H245_DATA_AUDIO))
  1471. || ((mediaID == MEDIA_TYPE_H323VIDEO) && (pChannelCapability->DataType ==H245_DATA_VIDEO)))
  1472. {
  1473. *lplpChannel = pChannel;
  1474. return hrSuccess;
  1475. }
  1476. }
  1477. }
  1478. // fallout if not found
  1479. hr = CCO_E_NODEFAULT_CHANNEL;
  1480. EXIT:
  1481. return hr;
  1482. }
  1483. #ifdef DEBUG
  1484. VOID DumpWFX(LPWAVEFORMATEX lpwfxLocal, LPWAVEFORMATEX lpwfxRemote)
  1485. {
  1486. FX_ENTRY("DumpWFX");
  1487. ERRORMESSAGE((" -------- %s Begin --------\r\n",_fx_));
  1488. if(lpwfxLocal)
  1489. {
  1490. ERRORMESSAGE((" -------- Local --------\r\n"));
  1491. ERRORMESSAGE(("wFormatTag:\t0x%04X, nChannels:\t0x%04X\r\n",
  1492. lpwfxLocal->wFormatTag, lpwfxLocal->nChannels));
  1493. ERRORMESSAGE(("nSamplesPerSec:\t0x%08lX, nAvgBytesPerSec:\t0x%08lX\r\n",
  1494. lpwfxLocal->nSamplesPerSec, lpwfxLocal->nAvgBytesPerSec));
  1495. ERRORMESSAGE(("nBlockAlign:\t0x%04X, wBitsPerSample:\t0x%04X, cbSize:\t0x%04X\r\n",
  1496. lpwfxLocal->nBlockAlign, lpwfxLocal->wBitsPerSample, lpwfxLocal->cbSize));
  1497. }
  1498. if(lpwfxRemote)
  1499. {
  1500. ERRORMESSAGE((" -------- Remote --------\r\n"));
  1501. ERRORMESSAGE(("wFormatTag:\t0x%04X, nChannels:\t0x%04X\r\n",
  1502. lpwfxRemote->wFormatTag, lpwfxRemote->nChannels));
  1503. ERRORMESSAGE(("nSamplesPerSec:\t0x%08lX, nAvgBytesPerSec:\t0x%08lX\r\n",
  1504. lpwfxRemote->nSamplesPerSec, lpwfxRemote->nAvgBytesPerSec));
  1505. ERRORMESSAGE(("nBlockAlign:\t0x%04X, wBitsPerSample:\t0x%04X, cbSize:\t0x%04X\r\n",
  1506. lpwfxRemote->nBlockAlign, lpwfxRemote->wBitsPerSample, lpwfxRemote->cbSize));
  1507. }
  1508. ERRORMESSAGE((" -------- %s End --------\r\n",_fx_));
  1509. }
  1510. VOID DumpChannelParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2)
  1511. {
  1512. FX_ENTRY("DumpChannelParameters");
  1513. ERRORMESSAGE((" -------- %s Begin --------\r\n",_fx_));
  1514. if(pChanCap1)
  1515. {
  1516. ERRORMESSAGE((" -------- Local Cap --------\r\n"));
  1517. ERRORMESSAGE(("DataType:%d(d), ClientType:%d(d)\r\n",pChanCap1->DataType,pChanCap1->ClientType));
  1518. ERRORMESSAGE(("Direction:%d(d), CapId:%d(d)\r\n",pChanCap1->Dir,pChanCap1->CapId));
  1519. }
  1520. if(pChanCap2)
  1521. {
  1522. ERRORMESSAGE((" -------- Remote Cap --------\r\n"));
  1523. ERRORMESSAGE(("DataType:%d(d), ClientType:%d(d)\r\n",pChanCap2->DataType,pChanCap2->ClientType));
  1524. ERRORMESSAGE(("Direction:%d(d), CapId:%d(d)\r\n",pChanCap2->Dir,pChanCap2->CapId));
  1525. }
  1526. ERRORMESSAGE((" -------- %s End --------\r\n",_fx_));
  1527. }
  1528. VOID DumpNonstdParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2)
  1529. {
  1530. FX_ENTRY("DumpNonstdParameters");
  1531. ERRORMESSAGE((" -------- %s Begin --------\r\n",_fx_));
  1532. DumpChannelParameters(pChanCap1, pChanCap2);
  1533. if(pChanCap1)
  1534. {
  1535. ERRORMESSAGE((" -------- Local Cap --------\r\n"));
  1536. if(pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  1537. {
  1538. ERRORMESSAGE(("t35CountryCode:%d(d), t35Extension:%d(d)\r\n",
  1539. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode,
  1540. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension));
  1541. ERRORMESSAGE(("MfrCode:%d(d), data length:%d(d)\r\n",
  1542. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode,
  1543. pChanCap1->Cap.H245Aud_NONSTD.data.length));
  1544. }
  1545. else
  1546. {
  1547. ERRORMESSAGE(("unrecognized nonStandardIdentifier.choice: %d(d)\r\n",
  1548. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice));
  1549. }
  1550. }
  1551. if(pChanCap2)
  1552. {
  1553. ERRORMESSAGE((" -------- Remote Cap --------\r\n"));
  1554. if(pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  1555. {
  1556. ERRORMESSAGE(("t35CountryCode:%d(d), t35Extension:%d(d)\r\n",
  1557. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode,
  1558. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension));
  1559. ERRORMESSAGE(("MfrCode:%d(d), data length:%d(d)\r\n",
  1560. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode,
  1561. pChanCap2->Cap.H245Aud_NONSTD.data.length));
  1562. }
  1563. else
  1564. {
  1565. ERRORMESSAGE(("nonStandardIdentifier.choice: %d(d)\r\n",
  1566. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice));
  1567. }
  1568. }
  1569. ERRORMESSAGE((" -------- %s End --------\r\n",_fx_));
  1570. }
  1571. #else
  1572. #define DumpWFX(x,y)
  1573. #define DumpChannelParameters(x,y)
  1574. #define DumpNonstdParameters(x,y)
  1575. #endif
  1576. // make sure requested channel parameters are valid (data type, ID and capability
  1577. // structure are consistent). Also obtains the local channel parameters needed
  1578. // to deal with the resulting stream
  1579. //
  1580. BOOL CH323Ctrl::ValidateChannelParameters(PCC_TERMCAP pChanCapLocal, PCC_TERMCAP pChanCapRemote)
  1581. {
  1582. FX_ENTRY ("CH323Ctrl::ValidateChannelParameters");
  1583. if((pChanCapLocal->DataType != pChanCapRemote->DataType)
  1584. || (pChanCapLocal->ClientType != pChanCapRemote->ClientType))
  1585. {
  1586. DEBUGMSG(ZONE_CONN,("%s:unmatched type\r\n",_fx_));
  1587. DumpChannelParameters(pChanCapLocal, pChanCapRemote);
  1588. return FALSE;
  1589. }
  1590. if(pChanCapLocal->ClientType == H245_CLIENT_AUD_NONSTD)
  1591. {
  1592. PNSC_AUDIO_CAPABILITY pNSCapLocal, pNSCapRemote;
  1593. if((pChanCapLocal->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice
  1594. != pChanCapRemote->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice )
  1595. ||(pChanCapLocal->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode
  1596. != pChanCapRemote->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode)
  1597. ||(pChanCapLocal->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension
  1598. != pChanCapRemote->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension)
  1599. ||(pChanCapLocal->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode
  1600. != pChanCapRemote->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode)
  1601. ||(pChanCapLocal->Cap.H245Aud_NONSTD.data.length
  1602. != pChanCapRemote->Cap.H245Aud_NONSTD.data.length))
  1603. {
  1604. DEBUGMSG(ZONE_CONN,("%s:unmatched NonStd capability\r\n",_fx_));
  1605. DumpNonstdParameters(pChanCapLocal, pChanCapRemote);
  1606. return FALSE;
  1607. }
  1608. //
  1609. pNSCapLocal = (PNSC_AUDIO_CAPABILITY)pChanCapLocal->Cap.H245Aud_NONSTD.data.value;
  1610. pNSCapRemote = (PNSC_AUDIO_CAPABILITY)pChanCapRemote->Cap.H245Aud_NONSTD.data.value;
  1611. // we only know about NSC_ACM_WAVEFORMATEX at this time
  1612. if(pNSCapRemote->cap_type != NSC_ACM_WAVEFORMATEX)
  1613. {
  1614. DEBUGMSG(ZONE_CONN,("%s:unrecognized NonStd capability type %d\r\n",_fx_, pNSCapRemote->cap_type));
  1615. return FALSE;
  1616. }
  1617. if((pNSCapLocal->cap_data.wfx.cbSize != pNSCapRemote->cap_data.wfx.cbSize)
  1618. || (memcmp(&pNSCapLocal->cap_data.wfx, &pNSCapRemote->cap_data.wfx, sizeof(WAVEFORMATEX)) != 0))
  1619. {
  1620. DumpWFX(&pNSCapLocal->cap_data.wfx, &pNSCapRemote->cap_data.wfx);
  1621. return FALSE;
  1622. }
  1623. }
  1624. else
  1625. {
  1626. }
  1627. // if it falls out, it's valid
  1628. return TRUE;
  1629. }
  1630. BOOL CH323Ctrl::ConfigureRecvChannelCapability(
  1631. ICtrlCommChan *pChannel,
  1632. PCC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS pChannelParams)
  1633. {
  1634. FX_ENTRY ("CH323Ctrl::ConfigureRecvChannelCapability");
  1635. //IH323PubCap *pCapObject = NULL;
  1636. CapsCtl *pCapObject = NULL;
  1637. // CCapability *pCapObject = NULL;
  1638. DWORD dwFormatID =INVALID_AUDIO_FORMAT;
  1639. PCC_TERMCAP pChannelCapability = pChannelParams->pChannelCapability, pSaveChannelCapability = NULL;
  1640. UINT uSize, uLocalParamSize;
  1641. LPVOID lpvData;
  1642. LPVOID pLocalParams;
  1643. DEBUGMSG(ZONE_CONN,("%s: requested capability ID:0x%08lX, dir %d, type %d\r\n",
  1644. _fx_, pChannelCapability->CapId, pChannelCapability->Dir,
  1645. pChannelCapability->DataType));
  1646. // at one time, we thought the capability ID would be valid
  1647. // and we would be receiving the format specified in pChannelCapability->CapId
  1648. // but it IS NOT VALID. The only viable info is in the channel parameters.
  1649. // The code would be --->>> dwFormatID = pChannelCapability->CapId;
  1650. // the ID *should* be all that is necessary to configure ourselves.
  1651. // However.....
  1652. // validate media (data) type - why? shouldn't this be prevalidated?
  1653. // shouldn't this be eventually used to select a channel object from
  1654. // among multiple channel objects?
  1655. if((pChannelCapability->DataType != H245_DATA_AUDIO) && (pChannelCapability->DataType != H245_DATA_VIDEO))
  1656. {
  1657. hrLast = CCO_E_UNSUPPORTED_MEDIA_TYPE;
  1658. DumpChannelParameters(NULL, pChannelCapability);
  1659. goto BAD_CAPABILITY_EXIT;
  1660. }
  1661. // Look at the local capability referenced by pChannelCapability->CapId
  1662. // and Validate the format details
  1663. hrLast = m_pConfAdvise->GetCapResolver((LPVOID *)&pCapObject, OID_CAP_ACM_TO_H323);
  1664. if(!HR_SUCCEEDED(hrLast) || (pCapObject == NULL))
  1665. {
  1666. ERRORMESSAGE(("%s: null resolver\r\n",_fx_));
  1667. goto BAD_CAPABILITY_EXIT;
  1668. }
  1669. // Find the local *receive* capability that matches the remote *send* channel
  1670. // parameters and get the local parameters.
  1671. uLocalParamSize = pCapObject->GetLocalRecvParamSize(pChannelCapability);
  1672. pLocalParams=MemAlloc (uLocalParamSize);
  1673. if (pLocalParams == NULL)
  1674. {
  1675. hrLast = CCO_E_SYSTEM_ERROR;
  1676. goto BAD_CAPABILITY_EXIT;
  1677. }
  1678. hrLast = ((CapsCtl *)pCapObject)->GetDecodeParams( pChannelParams,
  1679. (MEDIA_FORMAT_ID *)&dwFormatID, pLocalParams, uLocalParamSize);
  1680. if(!HR_SUCCEEDED(hrLast) || (dwFormatID == INVALID_AUDIO_FORMAT))
  1681. {
  1682. ERRORMESSAGE(("%s:GetDecodeParams returned 0x%08lx\r\n",_fx_, hrLast));
  1683. goto BAD_CAPABILITY_EXIT;
  1684. }
  1685. // create a marshalled version of channel parameters and store it in the channel for later
  1686. // reference
  1687. if(pChannelCapability->ClientType == H245_CLIENT_AUD_NONSTD)
  1688. {
  1689. // The nonstandard capability already passed all the recognition tests so
  1690. // don't need to test again.
  1691. // Make a flat copy of the nonstandard capability
  1692. uSize = pChannelCapability->Cap.H245Aud_NONSTD.data.length;
  1693. // lpData = pChannelCapability->Cap.H245Aud_NONSTD.data.value;
  1694. pSaveChannelCapability = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP) + uSize);
  1695. if(!pSaveChannelCapability)
  1696. {
  1697. hrLast = CCO_E_SYSTEM_ERROR;
  1698. goto BAD_CAPABILITY_EXIT;
  1699. }
  1700. // copy fixed part
  1701. memcpy(pSaveChannelCapability, pChannelCapability, sizeof(CC_TERMCAP));
  1702. // variable part follows the fixed part
  1703. pSaveChannelCapability->Cap.H245Aud_NONSTD.data.value
  1704. = (unsigned char *)(((BYTE *)pSaveChannelCapability) + sizeof(CC_TERMCAP));
  1705. // copy variable part
  1706. memcpy(pSaveChannelCapability->Cap.H245Aud_NONSTD.data.value,
  1707. pChannelCapability->Cap.H245Aud_NONSTD.data.value,
  1708. pChannelCapability->Cap.H245Aud_NONSTD.data.length);
  1709. // and length
  1710. pSaveChannelCapability->Cap.H245Aud_NONSTD.data.length
  1711. = pChannelCapability->Cap.H245Aud_NONSTD.data.length;
  1712. // make the channel remember the channel parameters.
  1713. // a zero size as the second arg means that a preallocated chunk is being passed
  1714. hrLast = pChannel->ConfigureCapability(pSaveChannelCapability, 0,
  1715. pLocalParams, uLocalParamSize);
  1716. if(!HR_SUCCEEDED(hrLast))
  1717. {
  1718. ERRORMESSAGE(("%s:ConfigureCapability (recv) returned 0x%08lx\r\n",_fx_, hrLast));
  1719. goto BAD_CAPABILITY_EXIT;
  1720. }
  1721. pSaveChannelCapability=NULL; // the channel owns this memory now
  1722. }
  1723. else if(pChannelCapability->ClientType == H245_CLIENT_VID_NONSTD)
  1724. {
  1725. // The nonstandard capability already passed all the recognition tests so
  1726. // don't need to test again.
  1727. // Make a flat copy of the nonstandard capability
  1728. uSize = pChannelCapability->Cap.H245Vid_NONSTD.data.length;
  1729. // lpData = pChannelCapability->Cap.H245Vid_NONSTD.data.value;
  1730. pSaveChannelCapability = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP) + uSize);
  1731. if(!pSaveChannelCapability)
  1732. {
  1733. hrLast = CCO_E_SYSTEM_ERROR;
  1734. goto BAD_CAPABILITY_EXIT;
  1735. }
  1736. // copy fixed part
  1737. memcpy(pSaveChannelCapability, pChannelCapability, sizeof(CC_TERMCAP));
  1738. // variable part follows the fixed part
  1739. pSaveChannelCapability->Cap.H245Vid_NONSTD.data.value
  1740. = (unsigned char *)(((BYTE *)pSaveChannelCapability) + sizeof(CC_TERMCAP));
  1741. // copy variable part
  1742. memcpy(pSaveChannelCapability->Cap.H245Vid_NONSTD.data.value,
  1743. pChannelCapability->Cap.H245Vid_NONSTD.data.value,
  1744. pChannelCapability->Cap.H245Vid_NONSTD.data.length);
  1745. // and length
  1746. pSaveChannelCapability->Cap.H245Vid_NONSTD.data.length
  1747. = pChannelCapability->Cap.H245Vid_NONSTD.data.length;
  1748. // make the channel remember the channel parameters.
  1749. // a zero size as the second arg means that a preallocated chunk is being passed
  1750. hrLast = pChannel->ConfigureCapability(pSaveChannelCapability, 0,
  1751. pLocalParams, uLocalParamSize);
  1752. if(!HR_SUCCEEDED(hrLast))
  1753. {
  1754. ERRORMESSAGE(("%s:ConfigureCapability (recv) returned 0x%08lx\r\n",_fx_, hrLast));
  1755. goto BAD_CAPABILITY_EXIT;
  1756. }
  1757. pSaveChannelCapability=NULL; // the channel owns this memory now
  1758. }
  1759. else
  1760. {
  1761. // only need to remember the already-flat H.245 cap structure.
  1762. hrLast = pChannel->ConfigureCapability(pChannelCapability, sizeof(CC_TERMCAP),
  1763. pLocalParams, uLocalParamSize);
  1764. if(!HR_SUCCEEDED(hrLast))
  1765. {
  1766. ERRORMESSAGE(("%s:ConfigureCapability(recv) returned 0x%08lx\r\n",_fx_, hrLast));
  1767. goto BAD_CAPABILITY_EXIT;
  1768. }
  1769. }
  1770. // Remember the receive format ID
  1771. pChannel->SetNegotiatedLocalFormat(dwFormatID);
  1772. // very special case check for video Temporal/Spatial tradeoff capability.
  1773. // Set the property of the channel accordingly
  1774. if(pChannelCapability->DataType == H245_DATA_VIDEO )
  1775. {
  1776. BOOL bTSCap;
  1777. bTSCap = ((PVIDEO_CHANNEL_PARAMETERS)pLocalParams)->TS_Tradeoff;
  1778. pChannel->CtrlChanSetProperty(PROP_REMOTE_TS_CAPABLE,&bTSCap, sizeof(bTSCap));
  1779. // don't bother checking or panicking over this SetProperty error
  1780. }
  1781. return TRUE;
  1782. ///////////////////
  1783. BAD_CAPABILITY_EXIT:
  1784. ERRORMESSAGE(("%s:received bad capability\r\n",_fx_));
  1785. hrLast = CCO_E_INVALID_CAPABILITY;
  1786. if(pSaveChannelCapability)
  1787. MemFree(pSaveChannelCapability);
  1788. return FALSE;
  1789. }
  1790. //
  1791. // we're being requested to open a channel for receive
  1792. //
  1793. VOID CH323Ctrl::OnChannelRequest(HRESULT hStatus,
  1794. PCC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS pChannelReqParams)
  1795. {
  1796. FX_ENTRY("CH323Ctrl::OnChannelRequest");
  1797. CC_ADDR CChannelAddr, DChannelAddr;
  1798. PCC_ADDR pCChannelAddr = pChannelReqParams->pPeerRTCPAddr;;
  1799. PCC_TERMCAP pChannelCapability;
  1800. PSOCKADDR_IN pAddr;
  1801. SOCKADDR_IN sinC;
  1802. pChannelCapability = pChannelReqParams->pChannelCapability;
  1803. DWORD dwRejectReason = H245_REJ;
  1804. ICtrlCommChan *pChannel;
  1805. if(!pChannelCapability)
  1806. {
  1807. ERRORMESSAGE(("OnChannelRequest: null capability\r\n"));
  1808. goto REJECT_CHANNEL;
  1809. }
  1810. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelRequest");
  1811. //
  1812. // Try to find a default channel to handle this open request.
  1813. hrLast = FindDefaultRXChannel(pChannelCapability, &pChannel);
  1814. if(!HR_SUCCEEDED(hrLast) || !pChannel)
  1815. {
  1816. // Non-default channels Not Yet Implemented!!!!
  1817. // Ask the parent conference object to create another channel of the
  1818. // specified media type. The H.245 media type should map to one of the
  1819. // media type GUIDs that the parent conference object understands.
  1820. // GUID typeGuid;
  1821. // if(!MapGuidType(pChannelCapability, &typeGUID))
  1822. // goto REJECT_CHANNEL;
  1823. // hrLast = m_pConfAdvise->GetChannel(&typeGuid, &pChannel);
  1824. // if(!HR_SUCCEEDED(hrLast))
  1825. // goto REJECT_CHANNEL;
  1826. if(hrLast == CCO_E_NODEFAULT_CHANNEL)
  1827. dwRejectReason = H245_REJ_TYPE_NOTAVAIL;
  1828. goto REJECT_CHANNEL;
  1829. }
  1830. if(pChannel->GetHChannel())
  1831. {
  1832. ERRORMESSAGE(("%s: existing channel or leak:0x%08lX\r\n",_fx_,
  1833. pChannel->GetHChannel()));
  1834. goto REJECT_CHANNEL;
  1835. }
  1836. //
  1837. // test if we want to allow this !!!
  1838. //
  1839. if(!pChannel->IsChannelEnabled())
  1840. {
  1841. goto REJECT_CHANNEL;
  1842. }
  1843. pChannel->SetHChannel(pChannelReqParams->hChannel);
  1844. // configure based on the requested capability. (store capability ID, validate requested
  1845. // capabilities
  1846. if(!ConfigureRecvChannelCapability(pChannel, pChannelReqParams))
  1847. {
  1848. goto REJECT_CHANNEL;
  1849. }
  1850. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelRequest done configuring");
  1851. // select our receive ports for this RTP session
  1852. if(!pChannel->SelectPorts((LPIControlChannel)this))
  1853. {
  1854. ERRORMESSAGE(("%s, SelectPorts failed\r\n",_fx_));
  1855. hrLast = CCO_E_BAD_ADDRESS;
  1856. goto REJECT_CHANNEL;
  1857. }
  1858. if(pCChannelAddr)
  1859. {
  1860. if(pCChannelAddr->nAddrType != CC_IP_BINARY)
  1861. {
  1862. ERRORMESSAGE(("%s:invalid address type %d\r\n",_fx_, pCChannelAddr->nAddrType));
  1863. hrLast = CCO_E_BAD_ADDRESS;
  1864. goto REJECT_CHANNEL;
  1865. }
  1866. // pass the remote RTCP address to the channel instance
  1867. sinC.sin_family = AF_INET;
  1868. sinC.sin_addr.S_un.S_addr = htonl(pCChannelAddr->Addr.IP_Binary.dwAddr);
  1869. sinC.sin_port = htons(pCChannelAddr->Addr.IP_Binary.wPort);
  1870. DEBUGMSG(ZONE_CONN,("%s, request reverse port 0x%04x, address 0x%08lX\r\n",_fx_,
  1871. pCChannelAddr->Addr.IP_Binary.wPort,pCChannelAddr->Addr.IP_Binary.dwAddr));
  1872. hrLast = pChannel->AcceptRemoteRTCPAddress(&sinC);
  1873. if(hrLast != CC_OK)
  1874. {
  1875. ERRORMESSAGE(("%s, AcceptRemoteRTCPAddress returned 0x%08lX\r\n",_fx_, hrLast));
  1876. goto ERROR_EXIT;
  1877. }
  1878. }
  1879. // get the address and ports of our end of the channel
  1880. pAddr = pChannel->GetLocalAddress();
  1881. // fixup channel addr pair structure.
  1882. DChannelAddr.nAddrType = CC_IP_BINARY;
  1883. DChannelAddr.bMulticast = FALSE;
  1884. DChannelAddr.Addr.IP_Binary.wPort = pChannel->GetLocalRTPPort();
  1885. DChannelAddr.Addr.IP_Binary.dwAddr = ntohl(pAddr->sin_addr.S_un.S_addr);
  1886. CChannelAddr.nAddrType = CC_IP_BINARY;
  1887. CChannelAddr.bMulticast = FALSE;
  1888. CChannelAddr.Addr.IP_Binary.wPort = pChannel->GetLocalRTCPPort();
  1889. CChannelAddr.Addr.IP_Binary.dwAddr = ntohl(pAddr->sin_addr.S_un.S_addr);
  1890. DEBUGMSG(ZONE_CONN,("%s: accepting on port 0x%04x, address 0x%08lX\r\n",_fx_,
  1891. DChannelAddr.Addr.IP_Binary.wPort,DChannelAddr.Addr.IP_Binary.dwAddr));
  1892. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelRequest accepting");
  1893. hrLast = CC_AcceptChannel(pChannelReqParams->hChannel,&DChannelAddr, &CChannelAddr,
  1894. 0 /* this param is the bitrate that will be used by THIS channel !! */);
  1895. if(hrLast != CC_OK)
  1896. {
  1897. ERRORMESSAGE(("%s, CC_AcceptChannel returned 0x%08lX\r\n",_fx_, hrLast));
  1898. goto ERROR_EXIT;
  1899. }
  1900. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelRequest accepted");
  1901. return;
  1902. REJECT_CHANNEL:
  1903. {
  1904. // need private HRESULT! don't overwrite the reason we're rejecting the channel!!
  1905. HRESULT hr;
  1906. ERRORMESSAGE(("%s, rejecting channel, Dir:%d, DataType:%d, ClientType:%d, CapId:%d\r\n",
  1907. _fx_, pChannelCapability->Dir, pChannelCapability->DataType,
  1908. pChannelCapability->ClientType, pChannelCapability->CapId));
  1909. hr = CC_RejectChannel(pChannelReqParams->hChannel, dwRejectReason);
  1910. if(hr != CC_OK)
  1911. {
  1912. ERRORMESSAGE(("%s, CC_RejectChannel returned 0x%08lX\r\n",_fx_, hr));
  1913. }
  1914. }
  1915. ERROR_EXIT:
  1916. return;
  1917. }
  1918. VOID CH323Ctrl::OnChannelAcceptComplete(HRESULT hStatus,
  1919. PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS pChannelParams)
  1920. {
  1921. FX_ENTRY("CH323Ctrl::OnChannelAcceptComplete");
  1922. ICtrlCommChan *pChannel;
  1923. if(hStatus != CC_OK)
  1924. {
  1925. return;
  1926. }
  1927. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelAcceptComplete");
  1928. pChannel = FindChannel(pChannelParams->hChannel);
  1929. if(!pChannel)
  1930. {
  1931. ERRORMESSAGE(("OnChannelAcceptComplete: hChannel 0x%08lx not found\r\n", pChannelParams->hChannel));
  1932. return;
  1933. }
  1934. hrLast = pChannel->OnChannelOpen(CHANNEL_OPEN); // the receive side is open
  1935. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelAcceptComplete, open done");
  1936. if(HR_SUCCEEDED(hrLast))
  1937. {
  1938. m_pConfAdvise->OnControlEvent(CCEV_CHANNEL_READY_RX, pChannel, this);
  1939. }
  1940. //
  1941. // Check for readiness to notify that all required channels are open
  1942. //
  1943. CheckChannelsReady( );
  1944. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelAcceptComplete done");
  1945. }
  1946. VOID CH323Ctrl::OnChannelOpen(HRESULT hStatus,
  1947. PCC_TX_CHANNEL_OPEN_CALLBACK_PARAMS pChannelParams )
  1948. {
  1949. FX_ENTRY("CH323Ctrl::OnChannelOpen");
  1950. PCC_ADDR pChannelRTPAddr;
  1951. PCC_ADDR pChannelRTCPAddr;
  1952. SOCKADDR_IN sinC, sinD;
  1953. ICtrlCommChan *pChannel = (ICtrlCommChan *)pChannelParams->dwUserToken;
  1954. // validate channel token - is this what we think it is?
  1955. if(IsBadWritePtr(pChannel, sizeof(ICtrlCommChan)))
  1956. {
  1957. ERRORMESSAGE(("%s:invalid channel token: 0x%08lx\r\n",_fx_, pChannelParams->dwUserToken));
  1958. return;
  1959. }
  1960. if(pChannel->IsSendChannel() == FALSE)
  1961. {
  1962. ERRORMESSAGE(("%s:not a send channel:token 0x%08lX\r\n",_fx_,
  1963. pChannelParams->dwUserToken));
  1964. return;
  1965. }
  1966. #ifdef DEBUG
  1967. POSITION pos = m_ChannelList.GetHeadPosition();
  1968. ICtrlCommChan *pChan;
  1969. BOOL bValid = FALSE;
  1970. // look for a matching channel instance.
  1971. while (pos)
  1972. {
  1973. pChan = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  1974. ASSERT(pChan);
  1975. if(pChan == pChannel)
  1976. {
  1977. bValid = TRUE;
  1978. break;
  1979. }
  1980. }
  1981. if(!bValid)
  1982. {
  1983. ERRORMESSAGE(("%s:unrecognized token 0x%08lX\r\n",_fx_,
  1984. pChannelParams->dwUserToken));
  1985. return;
  1986. }
  1987. #endif //DEBUG
  1988. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen");
  1989. if((hStatus != CC_OK) || (!(pChannelRTPAddr = pChannelParams->pPeerRTPAddr))
  1990. || (!(pChannelRTCPAddr = pChannelParams->pPeerRTCPAddr)))
  1991. {
  1992. ERRORMESSAGE(("%s: hStatus:0x%08lX, address:0x%08lX\r\n",_fx_,
  1993. hStatus, pChannelRTPAddr));
  1994. // LOOKLOOK need to interpret hStatus
  1995. // let the channel know what happened.
  1996. pChannel->OnChannelOpen(CHANNEL_REJECTED);
  1997. // the channel knows what happened, so let it do the worrying.
  1998. return;
  1999. }
  2000. // what's the need for the different address types ????
  2001. if((pChannelRTPAddr->nAddrType != CC_IP_BINARY)
  2002. || (pChannelRTCPAddr->nAddrType != CC_IP_BINARY))
  2003. {
  2004. ERRORMESSAGE(("%s: invalid address types %d, %d\r\n",_fx_,
  2005. pChannelRTPAddr->nAddrType, pChannelRTCPAddr->nAddrType));
  2006. goto ERROR_EXIT;
  2007. }
  2008. // we now have the remote port info ( in host byte order)
  2009. sinD.sin_family = AF_INET;
  2010. sinD.sin_addr.S_un.S_addr = htonl(pChannelRTPAddr->Addr.IP_Binary.dwAddr);
  2011. sinD.sin_port = htons(pChannelRTPAddr->Addr.IP_Binary.wPort);
  2012. sinC.sin_family = AF_INET;
  2013. sinC.sin_addr.S_un.S_addr = htonl(pChannelRTCPAddr->Addr.IP_Binary.dwAddr);
  2014. // There are two ports, but in RTP, it is implicit
  2015. // that the RTCP control port is the next highest port number
  2016. // sinC.sin_port = htons(ntohs(pChannelAddr->Addr.IP_Binary.wPort) +1);
  2017. sinC.sin_port = htons(pChannelRTCPAddr->Addr.IP_Binary.wPort);
  2018. DEBUGMSG(ZONE_CONN,("%s, opened on port 0x%04x, address 0x%08lX\r\n",_fx_,
  2019. pChannelRTPAddr->Addr.IP_Binary.wPort,pChannelRTPAddr->Addr.IP_Binary.dwAddr));
  2020. hrLast = pChannel->AcceptRemoteAddress(&sinD);
  2021. if(!HR_SUCCEEDED(hrLast))
  2022. {
  2023. ERRORMESSAGE(("OnChannelOpen: AcceptRemoteAddress failed\r\n"));
  2024. goto ERROR_EXIT;
  2025. }
  2026. hrLast = pChannel->AcceptRemoteRTCPAddress(&sinC);
  2027. if(!HR_SUCCEEDED(hrLast))
  2028. {
  2029. ERRORMESSAGE(("OnChannelOpen: AcceptRemoteRTCPAddress failed\r\n"));
  2030. goto ERROR_EXIT;
  2031. }
  2032. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen opening");
  2033. hrLast = pChannel->OnChannelOpen(CHANNEL_OPEN); // the send side is open
  2034. if(!HR_SUCCEEDED(hrLast))
  2035. {
  2036. ERRORMESSAGE(("OnChannelOpen:channel's OnChannelOpen() returned 0x%08lX\r\n", hrLast));
  2037. CloseChannel(pChannel);
  2038. goto ERROR_EXIT;
  2039. }
  2040. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen open done");
  2041. m_pConfAdvise->OnControlEvent(CCEV_CHANNEL_READY_TX, pChannel, this);
  2042. //
  2043. // Check for readiness to notify that all required channels are open
  2044. //
  2045. CheckChannelsReady( );
  2046. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen done");
  2047. return;
  2048. ERROR_EXIT:
  2049. // need to cleanup, disconnect, etc.
  2050. m_hCallCompleteCode = CCCI_CHANNEL_OPEN_ERROR;
  2051. // let the parent Conference object know about the imminent disconnect
  2052. DoAdvise(CCEV_CALL_INCOMPLETE, &m_hCallCompleteCode);
  2053. hrLast = CCO_E_MANDATORY_CHAN_OPEN_FAILED;
  2054. InternalDisconnect();
  2055. return;
  2056. }
  2057. VOID CH323Ctrl::OnRxChannelClose(HRESULT hStatus,
  2058. PCC_RX_CHANNEL_CLOSE_CALLBACK_PARAMS pChannelParams )
  2059. {
  2060. FX_ENTRY("CH323Ctrl::OnRxChannelClose");
  2061. PCC_ADDR pChannelRTPAddr;
  2062. PCC_ADDR pChannelRTCPAddr;
  2063. SOCKADDR_IN sinC, sinD;
  2064. ICtrlCommChan *pChannel;
  2065. if(hStatus != CC_OK)
  2066. {
  2067. ERRORMESSAGE(("%s: hStatus:0x%08lX\r\n",_fx_,hStatus));
  2068. // LOOKLOOK need to interpret hStatus
  2069. }
  2070. if(!(pChannel = FindChannel(pChannelParams->hChannel)))
  2071. {
  2072. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2073. return;
  2074. }
  2075. // validate channel - is this really a receive channel?
  2076. if(pChannel->IsSendChannel() == TRUE)
  2077. {
  2078. ERRORMESSAGE(("%s:not a receive channel:hChannel 0x%08lX\r\n",_fx_,
  2079. pChannelParams->hChannel));
  2080. return;
  2081. }
  2082. pChannel->OnChannelClose(CHANNEL_CLOSED);
  2083. return;
  2084. }
  2085. VOID CH323Ctrl::OnTxChannelClose(HRESULT hStatus,
  2086. PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS pChannelParams )
  2087. {
  2088. FX_ENTRY("CH323Ctrl::OnTxChannelClose");
  2089. PCC_ADDR pChannelRTPAddr;
  2090. PCC_ADDR pChannelRTCPAddr;
  2091. SOCKADDR_IN sinC, sinD;
  2092. ICtrlCommChan *pChannel;
  2093. if(hStatus != CC_OK)
  2094. {
  2095. ERRORMESSAGE(("%s: hStatus:0x%08lX\r\n",_fx_,hStatus));
  2096. // LOOKLOOK need to interpret hStatus
  2097. }
  2098. if(!(pChannel = FindChannel(pChannelParams->hChannel)))
  2099. {
  2100. CC_CloseChannelResponse(pChannelParams->hChannel, FALSE);
  2101. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2102. return;
  2103. }
  2104. // validate channel - is this really a send channel?
  2105. if(pChannel->IsSendChannel() == FALSE)
  2106. {
  2107. ERRORMESSAGE(("%s:not a send channel:hChannel 0x%08lX\r\n",_fx_,
  2108. pChannelParams->hChannel));
  2109. CC_CloseChannelResponse(pChannelParams->hChannel, FALSE);
  2110. return;
  2111. }
  2112. CC_CloseChannelResponse(pChannelParams->hChannel, TRUE);
  2113. pChannel->OnChannelClose(CHANNEL_CLOSED);
  2114. return;
  2115. }
  2116. BOOL CH323Ctrl::OnCallAccept(PCC_LISTEN_CALLBACK_PARAMS pListenCallbackParams)
  2117. {
  2118. FX_ENTRY ("CH323Ctrl::OnCallAccept");
  2119. BOOL bRet = FALSE;
  2120. CH323Ctrl *pNewConnection = NULL;
  2121. if(m_Phase != CCS_Listening)
  2122. {
  2123. ERRORMESSAGE(("OnCallAccept: unexpected call, m_Phase = 0x%08lX\r\n", m_Phase));
  2124. goto EXIT;
  2125. }
  2126. if((!pListenCallbackParams->pCalleeAddr)
  2127. || (pListenCallbackParams->pCalleeAddr->nAddrType != CC_IP_BINARY))
  2128. {
  2129. if(pListenCallbackParams->pCalleeAddr)
  2130. {
  2131. ERRORMESSAGE(("%s: invalid address type %d\r\n",_fx_,pListenCallbackParams->pCalleeAddr->nAddrType));
  2132. }
  2133. else
  2134. {
  2135. ERRORMESSAGE(("%s: null local address\r\n",_fx_));
  2136. }
  2137. ERRORMESSAGE(("OnCallAccept:where's the local address????\r\n"));
  2138. PHOSTENT phe;
  2139. PSOCKADDR_IN psin;
  2140. char szTemp[200];
  2141. LPCSTR lpHostName;
  2142. gethostname(szTemp,sizeof(szTemp));
  2143. lpHostName = szTemp;
  2144. psin = &local_sin;
  2145. phe = gethostbyname(lpHostName);
  2146. if (phe != NULL)
  2147. {
  2148. memcpy((char FAR *)&(psin->sin_addr), phe->h_addr,phe->h_length);
  2149. psin->sin_family = AF_INET;
  2150. }
  2151. }
  2152. else
  2153. {
  2154. // remember our local address
  2155. local_sin.sin_family = AF_INET;
  2156. // in host byte order
  2157. local_sin.sin_addr.S_un.S_addr = htonl(pListenCallbackParams->pCalleeAddr->Addr.IP_Binary.dwAddr);
  2158. // in host byte order
  2159. local_sin.sin_port = htons(pListenCallbackParams->pCalleeAddr->Addr.IP_Binary.wPort);
  2160. }
  2161. hrLast = m_pConfAdvise->GetAcceptingObject((LPIControlChannel *)&pNewConnection,
  2162. &m_PID);
  2163. if(HR_SUCCEEDED(hrLast) && pNewConnection)
  2164. {
  2165. // NOTE: The UI does not yet know this new object exists, and we may
  2166. // need to silently delete it if there is a disconnect or error
  2167. // Its ref count is 1 at this point. The decision to delete could be
  2168. // made inside pNewConnection->AcceptConnection(), (because sometimes
  2169. // socket reads complete synchronously depending on timing) SO, we need to
  2170. // protect the "unwind path" via AddRef() and Release() around the call
  2171. //
  2172. pNewConnection->AddRef(); //
  2173. hrLast = pNewConnection->AcceptConnection(this, pListenCallbackParams);
  2174. pNewConnection->Release();
  2175. if(HR_SUCCEEDED(hrLast))
  2176. {
  2177. // The Intel Call control DLL already did a socket accept, the
  2178. // Accept() methods simply initialize the handles and states of
  2179. // pNewConnection and get user information (caller ID)
  2180. // BUGBUG - the caller ID may change in Intel's code - it might
  2181. // come via a conference event
  2182. DEBUGMSG(ZONE_CONN,("OnCallAccept:accepted on connection 0x%08lX\r\n",pNewConnection));
  2183. bRet = TRUE;
  2184. }
  2185. else
  2186. {
  2187. ERRORMESSAGE(("OnCallAccept:Accept failed\r\n"));
  2188. // LOOK - Q: where does the accepting object get cleaned up?
  2189. // A: pNewConnection->AcceptConnection((LPIControlChannel)this)
  2190. // must call pNewConnection->DoAdvise(CCEV_ACCEPT_INCOMPLETE, NULL)
  2191. // if the error occurred before the conference object got involved,
  2192. // and must call InternalDisconnect() if the error occurred after
  2193. // the conference object got involved,
  2194. }
  2195. }
  2196. else
  2197. {
  2198. ERRORMESSAGE(("OnCallAccept:GetAcceptingObject failed, hr=0x%08lx\r\n",hrLast));
  2199. }
  2200. EXIT:
  2201. return bRet;
  2202. }
  2203. HRESULT CH323Ctrl::NewConference()
  2204. {
  2205. FX_ENTRY ("CH323Ctrl::NewConference");
  2206. CapsCtl *pCapObject = NULL;
  2207. PCC_TERMCAPLIST pTermCaps = NULL;
  2208. CC_OCTETSTRING TerminalID;
  2209. PCC_TERMCAPDESCRIPTORS pCapsList = NULL;
  2210. LPWSTR lpwUserDisplayName;
  2211. hrLast = m_pConfAdvise->GetCapResolver((LPVOID *)&pCapObject, OID_CAP_ACM_TO_H323);
  2212. if(!HR_SUCCEEDED(hrLast) || (pCapObject == NULL))
  2213. {
  2214. ERRORMESSAGE(("%s: null resolver\r\n",_fx_));
  2215. goto EXIT;
  2216. }
  2217. if(m_hConference)
  2218. {
  2219. ERRORMESSAGE(("%s:leak or uninitialized m_hConference:0x%08lx\r\n",_fx_,
  2220. m_hConference));
  2221. }
  2222. hrLast = pCapObject->CreateCapList(&pTermCaps, &pCapsList);
  2223. if(!HR_SUCCEEDED(hrLast))
  2224. {
  2225. goto EXIT;
  2226. }
  2227. lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2228. if(lpwUserDisplayName)
  2229. {
  2230. TerminalID.pOctetString = (BYTE *)lpwUserDisplayName;
  2231. TerminalID.wOctetStringLength = (WORD)lstrlenW(lpwUserDisplayName)*sizeof(WCHAR);
  2232. }
  2233. // create a conference
  2234. hrLast = CC_CreateConference(&m_hConference, NULL,
  2235. 0, // DWORD dwConferenceConfiguration,
  2236. pTermCaps, // PCC_TERMCAPLIST
  2237. pCapsList, // ptr to term cap descriptors (PCC_TERMCAPDESCRIPTORS)
  2238. &m_VendorInfo, // PVENDORINFO
  2239. (lpwUserDisplayName)? &TerminalID: NULL, // PCC_OCTETSTRING pTerminalID,
  2240. (DWORD_PTR)this,
  2241. NULL, // CC_TERMCAP_CONSTRUCTOR TermCapConstructor,
  2242. NULL, // CC_SESSIONTABLE_CONSTRUCTOR SessionTableConstructor,
  2243. CCConferenceCallback);
  2244. if(hrLast != CC_OK)
  2245. {
  2246. ERRORMESSAGE(("%s: CreateConference returned 0x%08lX\r\n", _fx_, hrLast));
  2247. }
  2248. EXIT:
  2249. pCapObject->DeleteCapList(pTermCaps, pCapsList);
  2250. return hrLast;
  2251. }
  2252. HRESULT CH323Ctrl::AcceptConnection(LPIControlChannel pIListenCtrlChan,
  2253. LPVOID lpvListenCallbackParams)
  2254. {
  2255. FX_ENTRY ("CH323Ctrl::AcceptConnection");
  2256. BOOL bRet = FALSE;
  2257. CREQ_RESPONSETYPE Response;
  2258. DWORD dwCode = CCR_LOCAL_SYSTEM_ERROR; // error variable only used in error case
  2259. ULONG ulNameSize, ulSize;
  2260. PSOCKADDR_IN psin;
  2261. LPWSTR lpwUserDisplayName;
  2262. CH323Ctrl *pListenConnection = (CH323Ctrl *)pIListenCtrlChan;
  2263. P_APP_CALL_SETUP_DATA pAppData = NULL;
  2264. APP_CALL_SETUP_DATA AppData;
  2265. PCC_NONSTANDARDDATA pNSData = ((PCC_LISTEN_CALLBACK_PARAMS)
  2266. lpvListenCallbackParams)->pNonStandardData;
  2267. if(pNSData
  2268. && pNSData->bCountryCode == USA_H221_COUNTRY_CODE
  2269. // why be this picky -> && pNSData->bExtension == USA_H221_COUNTRY_EXTENSION;
  2270. && pNSData->wManufacturerCode == MICROSOFT_H_221_MFG_CODE
  2271. && pNSData->sData.pOctetString
  2272. && pNSData->sData.wOctetStringLength >= sizeof(MSFT_NONSTANDARD_DATA))
  2273. {
  2274. if(((PMSFT_NONSTANDARD_DATA)pNSData->sData.pOctetString)->
  2275. data_type == NSTD_APPLICATION_DATA)
  2276. {
  2277. AppData.lpData = &((PMSFT_NONSTANDARD_DATA)pNSData->sData.pOctetString)->
  2278. nonstd_data.AppData.data;
  2279. AppData.dwDataSize = (DWORD)
  2280. ((PMSFT_NONSTANDARD_DATA)pNSData->sData.pOctetString)->dw_nonstd_data_size;
  2281. pAppData = &AppData;
  2282. }
  2283. }
  2284. SetRemoteVendorID(((PCC_LISTEN_CALLBACK_PARAMS)lpvListenCallbackParams)->pVendorInfo);
  2285. // this object is assuming everything from the listening object, including
  2286. // the "Listening" state
  2287. // enter critical section and make sure another thread is not handling a caller disconnect
  2288. // or timeout
  2289. // EnterCriticalSection()
  2290. if(m_Phase == CCS_Idle)
  2291. {
  2292. GoNextPhase(CCS_Listening);
  2293. // once in this state, a disconnect on another thread will change the state
  2294. // to something besides CCS_Listening
  2295. pListenConnection->GetLocalAddress(&psin);
  2296. SetLocalAddress(psin);
  2297. // steal the conference ID from the listen object
  2298. // m_ConferenceID = pListenConnection->GetConfID();
  2299. memcpy(&m_ConferenceID, pListenConnection->GetConfIDptr(),sizeof(m_ConferenceID));
  2300. ZeroMemory(pListenConnection->GetConfIDptr(),sizeof(m_ConferenceID));
  2301. m_hCall = pListenConnection->GetHCall();
  2302. // steal the user info from the listen object
  2303. m_pRemoteAliasItem = pListenConnection->m_pRemoteAliasItem;
  2304. pListenConnection->m_pRemoteAliasItem = NULL; // make the listen object forget this
  2305. // steal the peer display name
  2306. pwszPeerDisplayName = pListenConnection->pwszPeerDisplayName;
  2307. pListenConnection->pwszPeerDisplayName = NULL;
  2308. lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2309. }
  2310. // else already timing out
  2311. // LeaveCriticalSection()
  2312. if (m_Phase != CCS_Listening) // cleanup before it gets accepted
  2313. {
  2314. goto ACCEPT_ERROR;
  2315. }
  2316. // let the conference object know that caller ID info is available
  2317. ConnectNotify(CCEV_CALLER_ID);
  2318. // Now going to do stuff that might put cleanup responsibility on the
  2319. // conference object or UI. (i.e. the call could be accepted)
  2320. // EnterCriticalSection()
  2321. if(m_Phase == CCS_Listening)
  2322. {
  2323. // state is still OK
  2324. GoNextPhase(CCS_Filtering);
  2325. // once in this state, a disconnect on another thread will change the state
  2326. // to something besides CCS_Filtering
  2327. }
  2328. // else already timing out
  2329. // LeaveCriticalSection()
  2330. if (m_Phase != CCS_Filtering) // one last chance to cleanup before it gets accepted
  2331. {
  2332. goto ERROR_REJECT;
  2333. }
  2334. // can't (should not) do this inside a critical section
  2335. // create a conference to accept the call
  2336. hrLast = NewConference();
  2337. if(!HR_SUCCEEDED(hrLast))
  2338. {
  2339. ERRORMESSAGE(("%s, NewConference returned 0x%08lX\r\n", _fx_, hrLast));
  2340. goto ERROR_REJECT;
  2341. }
  2342. m_pConfAdvise->AddRef();
  2343. Response = m_pConfAdvise->FilterConnectionRequest(this, pAppData);
  2344. m_pConfAdvise->Release();
  2345. // Now it may be in the hands of the Conference object, and the accepted connection will
  2346. // need to go through the "disconnecting" state if cleanup is needed.
  2347. // Because connection code is reentrant, the connection could also have
  2348. // been torn down (via connection methods) while inside
  2349. // m_pConfAdvise->FilterConnectionRequest();
  2350. // In each case below, check validity of the connection state - it might have changed
  2351. // because a connection method was called or because the caller timed out
  2352. switch(Response)
  2353. {
  2354. default:
  2355. case CRR_ACCEPT:
  2356. if(m_Phase != CCS_Filtering)
  2357. {
  2358. ERRORMESSAGE(("%s, accepting state no longer valid 0x%08lX\r\n", _fx_, hrLast));
  2359. goto CANCEL_ACCEPT;
  2360. }
  2361. // accept this request
  2362. hrLast = CC_AcceptCall(m_hConference,
  2363. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2364. lpwUserDisplayName,
  2365. m_hCall,
  2366. 0, // DWORD dwBandwidth,
  2367. (DWORD_PTR)this);
  2368. if(hrLast != CC_OK)
  2369. {
  2370. m_ChanFlags &= ~CTRLF_OPEN;
  2371. goto CANCEL_ACCEPT;
  2372. }
  2373. GoNextPhase(CCS_Accepting);
  2374. bRet = TRUE;
  2375. break;
  2376. case CRR_ASYNC:
  2377. if(m_Phase == CCS_Accepting)
  2378. {
  2379. // then call has already been accepted inside FilterConnectionRequest callback
  2380. bRet = TRUE;
  2381. }
  2382. else
  2383. {
  2384. if(m_Phase != CCS_Filtering)
  2385. {
  2386. ERRORMESSAGE(("%s, accepting state no longer valid 0x%08lX\r\n", _fx_, hrLast));
  2387. goto CANCEL_ACCEPT;
  2388. }
  2389. GoNextPhase(CCS_Ringing);
  2390. bRet = TRUE;
  2391. }
  2392. break;
  2393. case CRR_BUSY:
  2394. hrLast = CC_RejectCall(CC_REJECT_USER_BUSY,
  2395. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2396. m_hCall);
  2397. // always clean up this object that's not accepting the call
  2398. GoNextPhase(CCS_Idle);
  2399. goto ACCEPT_ERROR;
  2400. break;
  2401. case CRR_REJECT:
  2402. hrLast = CC_RejectCall(CC_REJECT_DESTINATION_REJECTION,
  2403. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2404. m_hCall);
  2405. // always clean up this object that's not accepting the call
  2406. GoNextPhase(CCS_Idle);
  2407. goto ACCEPT_ERROR;
  2408. break;
  2409. case CRR_SECURITY_DENIED:
  2410. hrLast = CC_RejectCall(CC_REJECT_SECURITY_DENIED,
  2411. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2412. m_hCall);
  2413. // always clean up this object that's not accepting the call
  2414. GoNextPhase(CCS_Idle);
  2415. goto ACCEPT_ERROR;
  2416. break;
  2417. }
  2418. return hrLast;
  2419. ERROR_REJECT:
  2420. hrLast = CC_RejectCall(CC_REJECT_UNDEFINED_REASON,
  2421. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2422. m_hCall); // always clean up this object that's not accepting the call
  2423. GoNextPhase(CCS_Idle);
  2424. ACCEPT_ERROR:
  2425. DoAdvise(CCEV_ACCEPT_INCOMPLETE, &dwCode);
  2426. return hrLast;
  2427. CANCEL_ACCEPT:
  2428. // InternalDisconnect() can be called from any state, and will do fine if
  2429. // it is already in a disconnecting state.
  2430. InternalDisconnect();
  2431. return hrLast;
  2432. }
  2433. VOID CH323Ctrl::Cleanup()
  2434. {
  2435. POSITION pos = m_ChannelList.GetHeadPosition();
  2436. ICtrlCommChan *pChan = NULL;
  2437. CleanupConferenceAttributes();
  2438. if(m_hConference)
  2439. {
  2440. hrLast = CC_DestroyConference(m_hConference, FALSE);
  2441. // LOOKLOOK - need to check return code!!!
  2442. m_hConference = 0;
  2443. }
  2444. // reset each channel (cleanup underlying socket references)
  2445. while (pos)
  2446. {
  2447. pChan = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  2448. ASSERT(pChan);
  2449. // cleanup RTP sockets
  2450. pChan->Reset();
  2451. }
  2452. // clear "socket(s) are open flags
  2453. m_ChanFlags &= ~CTRLF_OPEN;
  2454. }
  2455. HRESULT CH323Ctrl::GetLocalPort(PORT * lpPort)
  2456. {
  2457. *lpPort = ntohs(local_sin.sin_port);
  2458. return hrSuccess;
  2459. }
  2460. HRESULT CH323Ctrl::GetRemotePort(PORT * lpPort)
  2461. {
  2462. *lpPort = ntohs(remote_sin.sin_port);
  2463. return hrSuccess;
  2464. }
  2465. HRESULT CH323Ctrl::GetLocalAddress(PSOCKADDR_IN *lplpAddr)
  2466. {
  2467. *lplpAddr = &local_sin;
  2468. return hrSuccess;
  2469. }
  2470. HRESULT CH323Ctrl::GetRemoteAddress(PSOCKADDR_IN *lplpAddr)
  2471. {
  2472. *lplpAddr = &remote_sin;
  2473. return hrSuccess;
  2474. }
  2475. HRESULT CH323Ctrl::ListenOn(PORT Port)
  2476. {
  2477. FX_ENTRY ("CH323Ctrl::ListenOn");
  2478. PCC_ALIASNAMES pAliasNames = m_pConfAdvise->GetUserAliases();
  2479. // temporary hack to override UI's ignorance of multiple protocol types
  2480. if(Port != H323_PORT)
  2481. {
  2482. ERRORMESSAGE(("%s, overriding port %d(d) with H323 port %d\r\n",_fx_,
  2483. Port, H323_PORT));
  2484. Port = H323_PORT;
  2485. }
  2486. // do we need to remember this?
  2487. local_sin.sin_addr.S_un.S_addr = INADDR_ANY;
  2488. local_sin.sin_family = AF_INET;
  2489. local_sin.sin_port = htons((u_short)Port); // set port
  2490. CC_ADDR ListenAddr;
  2491. ListenAddr.nAddrType = CC_IP_BINARY;
  2492. ListenAddr.bMulticast = FALSE;
  2493. // in host byte order
  2494. ListenAddr.Addr.IP_Binary.wPort = (u_short)Port;
  2495. ListenAddr.Addr.IP_Binary.dwAddr = ntohl(INADDR_ANY);
  2496. hrLast = CC_CallListen(&m_hListen, &ListenAddr,
  2497. pAliasNames, (DWORD_PTR)this, CCListenCallback);
  2498. if(hrLast != CC_OK)
  2499. {
  2500. ERRORMESSAGE(("CH323Ctrl::ListenOn:CallListen returned 0x%08lX\r\n", hrLast));
  2501. goto EXIT;
  2502. }
  2503. GoNextPhase(CCS_Listening);
  2504. m_ChanFlags = CTRLF_RESET;
  2505. hrLast = hrSuccess;
  2506. EXIT:
  2507. return hrLast;
  2508. }
  2509. HRESULT CH323Ctrl::StopListen(VOID)
  2510. {
  2511. if(m_Phase == CCS_Listening)
  2512. {
  2513. hrLast = CC_CancelListen(m_hListen);
  2514. }
  2515. else
  2516. {
  2517. hrLast = CCO_E_NOT_LISTENING;
  2518. }
  2519. //EXIT:
  2520. return hrLast;
  2521. }
  2522. HRESULT CH323Ctrl::AsyncAcceptRejectCall(CREQ_RESPONSETYPE Response)
  2523. {
  2524. FX_ENTRY ("CH323Ctrl::AsyncAcceptRejectCall");
  2525. HRESULT hr = CCO_E_CONNECT_FAILED;
  2526. LPWSTR lpwUserDisplayName;
  2527. if(Response == CRR_ACCEPT)
  2528. {
  2529. DEBUGMSG(ZONE_CONN,("%s:accepting\r\n",_fx_));
  2530. lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2531. // check call setup phase - send ready if user's acceptance is what
  2532. // was holding us up
  2533. if((m_Phase == CCS_Ringing) || (m_Phase == CCS_Filtering))
  2534. {
  2535. // accept this request
  2536. hrLast = CC_AcceptCall(m_hConference,
  2537. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2538. lpwUserDisplayName,
  2539. m_hCall,
  2540. 0, // DWORD dwBandwidth,
  2541. (DWORD_PTR)this);
  2542. if(hrLast != CC_OK)
  2543. {
  2544. ERRORMESSAGE(("%s, CC_AcceptCall() returned 0x%08lX\r\n",_fx_, hrLast));
  2545. goto EXIT;
  2546. }
  2547. GoNextPhase(CCS_Accepting);
  2548. hr = hrSuccess;
  2549. }
  2550. }
  2551. else
  2552. {
  2553. // reject only if in accepting state(s)
  2554. // deletion is possible while in advise callback, so protect w/ AddRef()
  2555. AddRef();
  2556. DEBUGMSG(ZONE_CONN,("%s:rejecting\r\n",_fx_));
  2557. if((m_Phase == CCS_Ringing) || (m_Phase == CCS_Filtering))
  2558. {
  2559. hrLast = CC_RejectCall((Response == CRR_BUSY) ?
  2560. CC_REJECT_USER_BUSY : CC_REJECT_DESTINATION_REJECTION,
  2561. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2562. m_hCall);
  2563. if(hrLast != CC_OK)
  2564. {
  2565. ERRORMESSAGE(("%s, CC_RejectCall() returned 0x%08lX\r\n",_fx_, hrLast));
  2566. }
  2567. GoNextPhase(CCS_Idle);
  2568. // notify the UI or application code or whatever..
  2569. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2570. }
  2571. else
  2572. {
  2573. hr = CCO_E_INVALID_PARAM; // LOOKLOOK - need INVALID_STATE error code
  2574. }
  2575. Release();
  2576. }
  2577. EXIT:
  2578. return (hr);
  2579. }
  2580. ULONG CH323Ctrl ::AddRef()
  2581. {
  2582. FX_ENTRY ("CH323Ctrl::AddRef");
  2583. uRef++;
  2584. DEBUGMSG(ZONE_REFCOUNT,("%s:(0x%08lX)->AddRef() uRef = 0x%08lX\r\n",_fx_, this, uRef ));
  2585. return uRef;
  2586. }
  2587. ULONG CH323Ctrl ::Release()
  2588. {
  2589. FX_ENTRY("CH323Ctrl ::Release");
  2590. uRef--;
  2591. if(uRef == 0)
  2592. {
  2593. DEBUGMSG(ZONE_CONN,("%s:(0x%08lX)->Releasing in phase:%d\r\n",_fx_, this, m_Phase ));
  2594. if(m_Phase != CCS_Idle)
  2595. {
  2596. ERRORMESSAGE(("CMSIACtrl::uRef zero in non idle (%d) state!\r\n",m_Phase));
  2597. InternalDisconnect();
  2598. }
  2599. delete this;
  2600. return 0;
  2601. }
  2602. DEBUGMSG(ZONE_REFCOUNT,("%s:(0x%08lX)->Release() uRef = 0x%08lX\r\n",_fx_, this, uRef ));
  2603. return uRef;
  2604. }
  2605. // implement IControlChannel::Disconnect(). Map reason codes to the protocol.
  2606. VOID CH323Ctrl::Disconnect(DWORD dwReason)
  2607. {
  2608. // no way to propagate reason through H.323 stack?????
  2609. InternalDisconnect();
  2610. }
  2611. VOID CH323Ctrl::InternalDisconnect()
  2612. {
  2613. FX_ENTRY ("CH323Ctrl::Disconnect");
  2614. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect");
  2615. m_ChanFlags &= ~CTRLF_ORIGINATING; // reset "originating" flag.
  2616. DEBUGMSG(ZONE_CONN,("%s, called in state %d, uRef = 0x%08lX\r\n",_fx_, m_Phase, uRef));
  2617. switch(m_Phase)
  2618. {
  2619. case CCS_Connecting:
  2620. case CCS_Accepting:
  2621. // if we believe the control channel is still connected, disconnect
  2622. if(IsCtlChanOpen(m_ChanFlags))
  2623. {
  2624. //set state to indicate disconnecting.
  2625. GoNextPhase(CCS_Disconnecting);
  2626. DEBUGMSG(ZONE_CONN,("%s, Expecting a CC_HANGUP_INDICATION\r\n",_fx_));
  2627. hrLast = CC_Hangup(m_hConference, FALSE, (DWORD_PTR)this);
  2628. if(hrLast != CC_OK)
  2629. {
  2630. ERRORMESSAGE(("%s:Hangup() returned 0x%08lX\r\n",_fx_, hrLast));
  2631. }
  2632. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect hangup done");
  2633. }
  2634. else
  2635. {
  2636. CC_CancelCall(m_hCall);
  2637. GoNextPhase(CCS_Idle); // no need to ck retval - we're disconnected
  2638. // notify the UI or application code or whatever..
  2639. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2640. }
  2641. break;
  2642. case CCS_Ringing:
  2643. // The call has not yet been accepted!!! Reject it!
  2644. hrLast = CC_RejectCall(CC_REJECT_UNDEFINED_REASON,
  2645. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2646. m_hCall);
  2647. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect reject done");
  2648. GoNextPhase(CCS_Idle);
  2649. // notify the UI or application code or whatever..
  2650. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2651. break;
  2652. case CCS_Idle:
  2653. case CCS_Disconnecting:
  2654. ERRORMESSAGE(("%s:called in unconnected state %d\r\n",_fx_, m_Phase));
  2655. break;
  2656. default:
  2657. //CCS_Ringing
  2658. //CCS_Opening
  2659. //CCS_Closing
  2660. //CCS_Ready
  2661. //CCS_InUse
  2662. //CCS_Listening
  2663. // if we believe the control channel is still connected, disconnect
  2664. if(IsCtlChanOpen(m_ChanFlags))
  2665. {
  2666. //set state to indicate disconnecting.
  2667. GoNextPhase(CCS_Disconnecting);
  2668. hrLast = CC_Hangup(m_hConference, FALSE, (DWORD_PTR)this);
  2669. if(hrLast != CC_OK)
  2670. {
  2671. ERRORMESSAGE(("%s:Hangup() returned 0x%08lX\r\n",_fx_, hrLast));
  2672. DoAdvise(CCEV_DISCONNECTED ,NULL);
  2673. }
  2674. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect hangup done");
  2675. }
  2676. else
  2677. {
  2678. GoNextPhase(CCS_Idle); // no need to ck retval - we're disconnected
  2679. // notify the UI or application code or whatever..
  2680. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2681. }
  2682. break;
  2683. }
  2684. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect done");
  2685. }
  2686. // start the asynchronous stuff that will instantiate a control channel
  2687. HRESULT CH323Ctrl::PlaceCall (BOOL bUseGKResolution, PSOCKADDR_IN pCallAddr,
  2688. P_H323ALIASLIST pDestinationAliases, P_H323ALIASLIST pExtraAliases,
  2689. LPCWSTR pCalledPartyNumber, P_APP_CALL_SETUP_DATA pAppData)
  2690. {
  2691. FX_ENTRY ("CH323Ctrl::PlaceCall");
  2692. CC_ALIASNAMES pstn_alias;
  2693. PCC_ALIASITEM pPSTNAlias = NULL;
  2694. PCC_ALIASNAMES pRemoteAliasNames = NULL;
  2695. PCC_ALIASNAMES pTranslatedAliasNames = NULL;
  2696. PCC_ALIASNAMES pLocalAliasNames = NULL;
  2697. PCC_ADDR pDestinationAddr = NULL;
  2698. PCC_ADDR pConnectAddr = NULL;
  2699. LPWSTR lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2700. PCC_NONSTANDARDDATA pNSData = NULL;
  2701. PMSFT_NONSTANDARD_DATA lpNonstdContent = NULL;
  2702. int iLen;
  2703. LPWSTR lpwszDest;
  2704. HRESULT hResult = hrSuccess;
  2705. // validate current state, don't allow bad actions
  2706. if(m_Phase != CCS_Idle)
  2707. {
  2708. hResult = CCO_E_NOT_IDLE;
  2709. goto EXIT;
  2710. }
  2711. OBJ_CPT_RESET; // reset elapsed timer
  2712. m_ChanFlags |= CTRLF_INIT_ORIGINATING;
  2713. if(!pCallAddr)
  2714. {
  2715. hResult = CCO_E_BAD_ADDRESS;
  2716. goto EXIT;
  2717. }
  2718. else
  2719. {
  2720. // keep a copy of the address
  2721. SetRemoteAddress(pCallAddr);
  2722. }
  2723. // temporary hack to override UI's ignorance of multiple protocol types
  2724. if(remote_sin.sin_port != htons(H323_PORT))
  2725. {
  2726. ERRORMESSAGE(("%s, overriding port %d(d) with H323 port %d\r\n",_fx_,
  2727. ntohs(remote_sin.sin_port), H323_PORT));
  2728. remote_sin.sin_port = htons(H323_PORT);
  2729. }
  2730. // check for connecting to self (not supported)
  2731. if(local_sin.sin_addr.s_addr == remote_sin.sin_addr.s_addr)
  2732. {
  2733. hResult = CCO_E_BAD_ADDRESS;
  2734. goto EXIT;
  2735. }
  2736. if(m_pRemoteAliasItem)
  2737. {
  2738. MemFree(m_pRemoteAliasItem);
  2739. m_pRemoteAliasItem = NULL;
  2740. }
  2741. // Is this a PSTN or H.320 gateway call?
  2742. if(pCalledPartyNumber)
  2743. {
  2744. // Then, due to the bogus way that CC_PlaceCall() is overloaded, the remote alias names
  2745. // must be overridden with the E.164 phone number. The hack is buried in
  2746. // Q931ConnectCallback() in CALLCONT.DLL (thank you Intel). That hack propagates
  2747. // the phone number to the "CalledPartyNumber" of the SETUP message only if there is
  2748. // exactly one alias, and that one alias is of type E.164.
  2749. // get # of characters
  2750. iLen = lstrlenW(pCalledPartyNumber);
  2751. // need buffer of size CC_ALIASITEM plus the size (in bytes) of the string
  2752. pPSTNAlias = (PCC_ALIASITEM)MemAlloc(sizeof(CC_ALIASITEM)
  2753. + sizeof(WCHAR)* (iLen+1));
  2754. if(!pPSTNAlias)
  2755. {
  2756. ERRORMESSAGE(("%s:failed alloc of pPSTNAlias:0x%08lx\r\n",_fx_));
  2757. hResult = CCO_E_OUT_OF_MEMORY;
  2758. goto EXIT;
  2759. }
  2760. WORD wIndex, wLength =1; // init wLength to count the null terminator
  2761. WCHAR E164Chars[] = {CC_ALIAS_H323_PHONE_CHARS};
  2762. LPCWSTR lpSrc = pCalledPartyNumber;
  2763. pPSTNAlias->wType = CC_ALIAS_H323_PHONE;
  2764. // set offsets - the E.164 address (a phone number) is the only thing
  2765. // in the alias name buffer
  2766. lpwszDest = (LPWSTR)(((char *)pPSTNAlias)+ sizeof(CC_ALIASITEM));
  2767. pPSTNAlias->pData = lpwszDest;
  2768. while(iLen--)
  2769. {
  2770. wIndex = (sizeof(E164Chars)/sizeof (WCHAR)) -1; //scan E164Chars[]
  2771. do
  2772. {
  2773. if(*lpSrc == E164Chars[wIndex])
  2774. {
  2775. *lpwszDest++ = *lpSrc;
  2776. wLength++;
  2777. break;
  2778. }
  2779. }while(wIndex--);
  2780. lpSrc++;
  2781. }
  2782. // terminate it
  2783. *lpwszDest = 0;
  2784. // wDataLength is the # of UNICODE characters
  2785. pPSTNAlias->wDataLength = wLength;
  2786. pstn_alias.wCount = 1;
  2787. pstn_alias.pItems = pPSTNAlias;
  2788. pRemoteAliasNames = &pstn_alias;
  2789. }
  2790. else if (pDestinationAliases && bUseGKResolution)// use the supplied callee alias names
  2791. {
  2792. hrLast = AllocTranslatedAliasList(&pTranslatedAliasNames, pDestinationAliases);
  2793. if(!HR_SUCCEEDED(hrLast))
  2794. {
  2795. ERRORMESSAGE(("%s, AllocTranslatedAliasList returned 0x%08lX\r\n", _fx_, hrLast));
  2796. hResult = CCO_E_SYSTEM_ERROR;
  2797. goto EXIT;
  2798. }
  2799. pRemoteAliasNames = pTranslatedAliasNames;
  2800. }
  2801. // else pRemoteAliasNames is initialized to NULL
  2802. pLocalAliasNames = m_pConfAdvise->GetUserAliases();
  2803. // start!!!
  2804. CC_ADDR ConfAddr;
  2805. // fixup the intel version of the address
  2806. // also note that it's all in host byte order
  2807. ConfAddr.bMulticast = FALSE;
  2808. ConfAddr.nAddrType = CC_IP_BINARY;
  2809. //hrLast = GetRemotePort(&ConfAddr.Addr.IP_Binary.wPort);
  2810. ConfAddr.Addr.IP_Binary.wPort = htons(remote_sin.sin_port);
  2811. ConfAddr.Addr.IP_Binary.dwAddr = ntohl(remote_sin.sin_addr.S_un.S_addr);
  2812. #ifdef DEBUG
  2813. if(m_hConference)
  2814. ERRORMESSAGE(("%s:leak or uninitialized m_hConference:0x%08lx\r\n",_fx_,
  2815. m_hConference));
  2816. #endif // DEBUG
  2817. // create a conference to place the call
  2818. SHOW_OBJ_ETIME("PlaceCall ready to create conference");
  2819. hrLast = NewConference();
  2820. if(!HR_SUCCEEDED(hrLast))
  2821. {
  2822. ERRORMESSAGE(("%s, NewConference returned 0x%08lX\r\n", _fx_, hrLast));
  2823. hResult = CCO_E_SYSTEM_ERROR;
  2824. goto EXIT;
  2825. }
  2826. // Set connect timeout value
  2827. // LOOKLOOK - this is a hardcoded value - !!! Where should this actualy come from?
  2828. // 30 secs == 30000mS
  2829. SHOW_OBJ_ETIME("PlaceCall setting timeout");
  2830. hrLast = CC_SetCallControlTimeout(CC_Q931_ALERTING_TIMEOUT, 30000);
  2831. if(pAppData)
  2832. {
  2833. // typical case - app data should be really small
  2834. if(pAppData->dwDataSize <= APPLICATION_DATA_DEFAULT_SIZE)
  2835. {
  2836. m_NonstdContent.data_type = NSTD_APPLICATION_DATA;
  2837. m_NonstdContent.dw_nonstd_data_size = pAppData->dwDataSize;
  2838. memcpy(&m_NonstdContent.nonstd_data.AppData.data,
  2839. pAppData->lpData, pAppData->dwDataSize);
  2840. m_NonstandardData.sData.pOctetString = (LPBYTE) &m_NonstdContent;
  2841. m_NonstandardData.sData.wOctetStringLength = sizeof(m_NonstdContent);
  2842. }
  2843. else // need some heap
  2844. {
  2845. UINT uTotalSize = sizeof(MSFT_NONSTANDARD_DATA)+ pAppData->dwDataSize;
  2846. lpNonstdContent = (PMSFT_NONSTANDARD_DATA)MemAlloc(uTotalSize);
  2847. if(lpNonstdContent)
  2848. {
  2849. lpNonstdContent->data_type = NSTD_APPLICATION_DATA;
  2850. lpNonstdContent->dw_nonstd_data_size = pAppData->dwDataSize;
  2851. memcpy(&lpNonstdContent->nonstd_data.AppData.data, pAppData->lpData,pAppData->dwDataSize);
  2852. m_NonstandardData.sData.pOctetString = (LPBYTE) lpNonstdContent;
  2853. m_NonstandardData.sData.wOctetStringLength = LOWORD(uTotalSize);
  2854. }
  2855. else
  2856. {
  2857. ERRORMESSAGE(("%s, alloc failed\r\n", _fx_));
  2858. hResult = CCO_E_SYSTEM_ERROR;
  2859. goto EXIT;
  2860. }
  2861. }
  2862. pNSData = &m_NonstandardData;
  2863. }
  2864. m_NonstandardData.bCountryCode = USA_H221_COUNTRY_CODE;
  2865. m_NonstandardData.bExtension = USA_H221_COUNTRY_EXTENSION;
  2866. m_NonstandardData.wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  2867. SHOW_OBJ_ETIME("CH323Ctrl::PlaceCall ready to place call");
  2868. // set destination address pointers
  2869. if(bUseGKResolution)
  2870. {
  2871. // the address passed in pCallAddr is the GK's address
  2872. pConnectAddr = &ConfAddr;
  2873. }
  2874. else
  2875. {
  2876. pDestinationAddr = &ConfAddr;
  2877. }
  2878. hrLast = CC_PlaceCall(
  2879. m_hConference,
  2880. &m_hCall,
  2881. pLocalAliasNames, // PCC_ALIASNAMES pLocalAliasNames,
  2882. pRemoteAliasNames,
  2883. NULL, // PCC_ALIASNAMES pExtraCalleeAliasNames,
  2884. NULL, // PCC_ALIASITEM pCalleeExtension,
  2885. pNSData, // PCC_NONSTANDARDDATA pNonStandardData,
  2886. lpwUserDisplayName, // PWSTR pszDisplay,
  2887. pDestinationAddr, // Destination call signalling address
  2888. pConnectAddr, // address to send the SETUP message to, if different than
  2889. // the destination address. (used for gatekeeper calls?)
  2890. 0, // DWORD dwBandwidth,
  2891. (DWORD_PTR) this);
  2892. SHOW_OBJ_ETIME("CH323Ctrl::PlaceCall placed call");
  2893. // clear these out so that cleanup does not try to free later
  2894. if(lpNonstdContent)
  2895. MemFree(lpNonstdContent);
  2896. m_NonstandardData.sData.pOctetString = NULL;
  2897. m_NonstandardData.sData.wOctetStringLength = 0;
  2898. // check return from CC_PlaceCall
  2899. if(hrLast != CC_OK)
  2900. {
  2901. ERRORMESSAGE(("CH323Ctrl::PlaceCall, PlaceCall returned 0x%08lX\r\n", hrLast));
  2902. hResult = CCO_E_CONNECT_FAILED;
  2903. goto EXIT;
  2904. }
  2905. // wait for an indication
  2906. GoNextPhase(CCS_Connecting);
  2907. EXIT:
  2908. if(pTranslatedAliasNames)
  2909. {
  2910. FreeTranslatedAliasList(pTranslatedAliasNames);
  2911. }
  2912. if(pPSTNAlias)
  2913. {
  2914. MemFree(pPSTNAlias);
  2915. }
  2916. return hResult;
  2917. }
  2918. //
  2919. // Given HCHANNEL, find the channel object.
  2920. //
  2921. ICtrlCommChan *CH323Ctrl::FindChannel(CC_HCHANNEL hChannel)
  2922. {
  2923. FX_ENTRY ("CH323Ctrl::FindChannel");
  2924. // find the channel
  2925. POSITION pos = m_ChannelList.GetHeadPosition();
  2926. ICtrlCommChan *pChannel;
  2927. while (pos)
  2928. {
  2929. pChannel = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  2930. ASSERT(pChannel);
  2931. if(pChannel->GetHChannel() == hChannel)
  2932. return pChannel;
  2933. }
  2934. #ifdef DEBUG
  2935. // fallout to error case
  2936. ERRORMESSAGE(("%s, did not find hChannel 0x%08lX\r\n",_fx_,hChannel));
  2937. #endif // DEBUG
  2938. return NULL;
  2939. }
  2940. VOID CH323Ctrl::OnMute(HRESULT hStatus,
  2941. PCC_MUTE_CALLBACK_PARAMS pParams)
  2942. {
  2943. FX_ENTRY ("CH323Ctrl::OnMute");
  2944. ICtrlCommChan *pChannel;
  2945. HRESULT hr;
  2946. if(!(pChannel = FindChannel(pParams->hChannel)))
  2947. {
  2948. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2949. return;
  2950. }
  2951. hr = pChannel->PauseNet(TRUE, TRUE);
  2952. if(!HR_SUCCEEDED(hr))
  2953. {
  2954. ERRORMESSAGE(("%s, Pausenet returned 0x%08lx\r\n", _fx_, hr));
  2955. }
  2956. }
  2957. VOID CH323Ctrl::OnUnMute(HRESULT hStatus,
  2958. PCC_UNMUTE_CALLBACK_PARAMS pParams)
  2959. {
  2960. FX_ENTRY ("CH323Ctrl::OnUnMute");
  2961. ICtrlCommChan *pChannel;
  2962. HRESULT hr;
  2963. if(!(pChannel = FindChannel(pParams->hChannel)))
  2964. {
  2965. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2966. return;
  2967. }
  2968. hr = pChannel->PauseNet(FALSE, TRUE);
  2969. if(!HR_SUCCEEDED(hr))
  2970. {
  2971. ERRORMESSAGE(("%s, Pausenet returned 0x%08lx\r\n", _fx_, hr));
  2972. }
  2973. }
  2974. VOID CH323Ctrl::OnMiscCommand(HRESULT hStatus,
  2975. PCC_H245_MISCELLANEOUS_COMMAND_CALLBACK_PARAMS pParams)
  2976. {
  2977. FX_ENTRY ("CH323Ctrl::OnMiscCommand");
  2978. ICtrlCommChan *pChannel;
  2979. // not every command references an individual channel. The 4 exceptions are:
  2980. // case equaliseDelay_chosen:
  2981. // case zeroDelay_chosen:
  2982. // case multipointModeCommand_chosen:
  2983. // case cnclMltpntMdCmmnd_chosen:
  2984. //
  2985. // if we were betting on receiving few of the exceptional cases, we would always
  2986. // try to find the channel.
  2987. //if(!(pChannel = FindChannel(pParams->hChannel)))
  2988. //{
  2989. // ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2990. // but don't error because of the exceptions
  2991. //}
  2992. switch(pParams->pMiscellaneousCommand->type.choice)
  2993. {
  2994. // the name and spelling of these constants was invented by the OSS compiler
  2995. //
  2996. case videoFreezePicture_chosen:
  2997. if(!(pChannel = FindChannel(pParams->hChannel)))
  2998. {
  2999. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3000. break;
  3001. }
  3002. break;
  3003. case videoFastUpdatePicture_chosen: // the receiver wants an I-Frame
  3004. {
  3005. HRESULT hr;
  3006. IVideoChannel *pIVC=NULL;
  3007. if(!(pChannel = FindChannel(pParams->hChannel)))
  3008. {
  3009. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3010. break;
  3011. }
  3012. hr = pChannel->QueryInterface(IID_IVideoChannel, (void **)&pIVC);
  3013. if(HR_SUCCEEDED(hr))
  3014. {
  3015. pIVC->SendKeyFrame();
  3016. pIVC->Release();
  3017. }
  3018. // else it must not be a video channel
  3019. }
  3020. break;
  3021. case MCd_tp_vdTmprlSptlTrdOff_chosen:
  3022. {
  3023. DWORD dwTradeoff;
  3024. HRESULT hr;
  3025. if(!(pChannel = FindChannel(pParams->hChannel)))
  3026. {
  3027. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3028. break;
  3029. }
  3030. // set TS value of the channel, also propagate to Datapump
  3031. dwTradeoff = MAKELONG(
  3032. pParams->pMiscellaneousCommand->type.u.MCd_tp_vdTmprlSptlTrdOff, 0);
  3033. // set channel property
  3034. // NOTE: when PROP_TS_TRADEOFF is set, the channel does all the
  3035. // local tweaking to make it happen. The channel will also signal the
  3036. // new value to the remote as if the local end initiated it.
  3037. hr = pChannel->CtrlChanSetProperty(PROP_TS_TRADEOFF, &dwTradeoff, sizeof(dwTradeoff));
  3038. }
  3039. break;
  3040. default:
  3041. // the following are not currently handled
  3042. // case equaliseDelay_chosen:
  3043. // case zeroDelay_chosen:
  3044. // case videoSendSyncEveryGOB_chosen:
  3045. // case vdSndSyncEvryGOBCncl_chosen:
  3046. // case videoFastUpdateGOB_chosen: // suposedly required by H.323
  3047. // case videoFastUpdateMB_chosen: // suposedly required by H.323
  3048. // and the remaining 2 are handled by the call control layer
  3049. // so we will never see these
  3050. // case multipointModeCommand_chosen:
  3051. // case cnclMltpntMdCmmnd_chosen:
  3052. break;
  3053. }
  3054. }
  3055. VOID CH323Ctrl::OnMiscIndication(HRESULT hStatus,
  3056. PCC_H245_MISCELLANEOUS_INDICATION_CALLBACK_PARAMS pParams)
  3057. {
  3058. FX_ENTRY ("CH323Ctrl::OnMiscIndication");
  3059. ICtrlCommChan *pChannel;
  3060. HRESULT hr;
  3061. unsigned short choice = pParams->pMiscellaneousIndication->type.choice;
  3062. if(!(pChannel = FindChannel(pParams->hChannel)))
  3063. {
  3064. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3065. // check the exceptional cases for which this is OK
  3066. if((choice == multipointConference_chosen)
  3067. || (choice == cnclMltpntCnfrnc_chosen)
  3068. || (choice == multipointZeroComm_chosen)
  3069. || (choice == cancelMultipointZeroComm_chosen)
  3070. || (choice == mltpntScndryStts_chosen)
  3071. || (choice == cnclMltpntScndryStts_chosen))
  3072. {
  3073. return; // as long as the above choices are not supported......
  3074. }
  3075. }
  3076. switch(choice)
  3077. {
  3078. case logicalChannelActive_chosen:
  3079. hr = pChannel->PauseNet(FALSE, TRUE);
  3080. break;
  3081. case logicalChannelInactive_chosen:
  3082. hr = pChannel->PauseNet(TRUE, TRUE);
  3083. break;
  3084. case MIn_tp_vdTmprlSptlTrdOff_chosen:
  3085. {
  3086. HRESULT hr;
  3087. DWORD dwTradeoff = MAKELONG(0,
  3088. pParams->pMiscellaneousIndication->type.u.MIn_tp_vdTmprlSptlTrdOff);
  3089. if(!(pChannel = FindChannel(pParams->hChannel)))
  3090. {
  3091. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3092. break;
  3093. }
  3094. // Set the indicated TS value of the channel.
  3095. // This should never occur for send channels.
  3096. //
  3097. hr = pChannel->CtrlChanSetProperty(PROP_TS_TRADEOFF_IND, &dwTradeoff, sizeof(dwTradeoff));
  3098. }
  3099. break;
  3100. // the following are not currently handled
  3101. // case multipointConference_chosen:
  3102. // case cnclMltpntCnfrnc_chosen:
  3103. // case multipointZeroComm_chosen:
  3104. // case cancelMultipointZeroComm_chosen:
  3105. // case mltpntScndryStts_chosen:
  3106. // case cnclMltpntScndryStts_chosen:
  3107. // case vdIndctRdyTActvt_chosen:
  3108. // case videoNotDecodedMBs_chosen:
  3109. }
  3110. }
  3111. HRESULT CH323Ctrl::MiscChannelCommand(
  3112. ICtrlCommChan *pChannel,
  3113. VOID * pCmd)
  3114. {
  3115. #ifdef BETA_2_ASN_PRESENT
  3116. if(m_fAvoidCrashingPDUs)
  3117. return hrSuccess;
  3118. #endif // BETA_2_ASN_PRESENT
  3119. return CC_H245MiscellaneousCommand(m_hCall, pChannel->GetHChannel(),
  3120. (MiscellaneousCommand *)pCmd);
  3121. }
  3122. HRESULT CH323Ctrl::MiscChannelIndication(
  3123. ICtrlCommChan *pChannel,
  3124. VOID * pInd)
  3125. {
  3126. MiscellaneousIndication *pMI = (MiscellaneousIndication *)pInd;
  3127. #ifdef BETA_2_ASN_PRESENT
  3128. if(m_fAvoidCrashingPDUs)
  3129. return hrSuccess;
  3130. #endif
  3131. // Intel decided that they had to wrap two Misc commands with two separate,
  3132. // additional APIs. And it won't allow those to be issued any other way.
  3133. // (it returns an error). Until we fix that, need to catch and reroute those
  3134. // two special ones
  3135. if(pMI->type.choice == logicalChannelActive_chosen)
  3136. {
  3137. return CC_UnMute(pChannel->GetHChannel());
  3138. }
  3139. else if (pMI->type.choice == logicalChannelInactive_chosen )
  3140. {
  3141. return CC_Mute(pChannel->GetHChannel());
  3142. }
  3143. else
  3144. return CC_H245MiscellaneousIndication(m_hCall,pChannel->GetHChannel(),pMI);
  3145. }
  3146. VOID CH323Ctrl::SetRemoteVendorID(PCC_VENDORINFO pVendorInfo)
  3147. {
  3148. if(!pVendorInfo)
  3149. return;
  3150. m_RemoteVendorInfo.bCountryCode = pVendorInfo->bCountryCode;
  3151. m_RemoteVendorInfo.bExtension = pVendorInfo->bExtension;
  3152. m_RemoteVendorInfo.wManufacturerCode = pVendorInfo->wManufacturerCode;
  3153. if(pVendorInfo->pProductNumber
  3154. && pVendorInfo->pProductNumber->wOctetStringLength
  3155. && pVendorInfo->pProductNumber->pOctetString)
  3156. {
  3157. if(m_RemoteVendorInfo.pProductNumber)
  3158. {
  3159. MemFree(m_RemoteVendorInfo.pProductNumber);
  3160. }
  3161. m_RemoteVendorInfo.pProductNumber = (PCC_OCTETSTRING)
  3162. MemAlloc(sizeof(CC_OCTETSTRING)
  3163. + pVendorInfo->pProductNumber->wOctetStringLength);
  3164. if(m_RemoteVendorInfo.pProductNumber)
  3165. {
  3166. m_RemoteVendorInfo.pProductNumber->wOctetStringLength
  3167. = pVendorInfo->pProductNumber->wOctetStringLength;
  3168. m_RemoteVendorInfo.pProductNumber->pOctetString =
  3169. ((BYTE *)m_RemoteVendorInfo.pProductNumber + sizeof(CC_OCTETSTRING));
  3170. memcpy(m_RemoteVendorInfo.pProductNumber->pOctetString,
  3171. pVendorInfo->pProductNumber->pOctetString,
  3172. pVendorInfo->pProductNumber->wOctetStringLength);
  3173. }
  3174. }
  3175. if(pVendorInfo->pVersionNumber)
  3176. {
  3177. if(m_RemoteVendorInfo.pVersionNumber)
  3178. {
  3179. MemFree(m_RemoteVendorInfo.pVersionNumber);
  3180. }
  3181. m_RemoteVendorInfo.pVersionNumber = (PCC_OCTETSTRING)
  3182. MemAlloc(sizeof(CC_OCTETSTRING)
  3183. + pVendorInfo->pVersionNumber->wOctetStringLength);
  3184. if(m_RemoteVendorInfo.pVersionNumber)
  3185. {
  3186. m_RemoteVendorInfo.pVersionNumber->wOctetStringLength
  3187. = pVendorInfo->pVersionNumber->wOctetStringLength;
  3188. m_RemoteVendorInfo.pVersionNumber->pOctetString =
  3189. ((BYTE *)m_RemoteVendorInfo.pVersionNumber + sizeof(CC_OCTETSTRING));
  3190. memcpy(m_RemoteVendorInfo.pVersionNumber->pOctetString,
  3191. pVendorInfo->pVersionNumber->pOctetString,
  3192. pVendorInfo->pVersionNumber->wOctetStringLength);
  3193. }
  3194. }
  3195. #ifdef BETA_2_ASN_PRESENT
  3196. char IntelCrashingID[] = "Intel Internet Video Phone";
  3197. char IntelCrashingVer[] = "1.0";
  3198. m_fAvoidCrashingPDUs = FALSE; // innocent until proven guilty
  3199. if(m_RemoteVendorInfo.bCountryCode == USA_H221_COUNTRY_CODE)
  3200. {
  3201. // then it's possible that it is Intel or Microsoft
  3202. if(m_RemoteVendorInfo.wManufacturerCode == MICROSOFT_H_221_MFG_CODE)
  3203. {
  3204. if((!pVendorInfo->pProductNumber) && (!pVendorInfo->pVersionNumber))
  3205. {
  3206. // safe to assume this is Beta2 or Beta3
  3207. m_fAvoidCrashingPDUs = TRUE;
  3208. }
  3209. else if((pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->wOctetStringLength == 0)
  3210. && (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->wOctetStringLength == 0))
  3211. {
  3212. // safe to assume this is Beta2 or Beta3
  3213. m_fAvoidCrashingPDUs = TRUE;
  3214. }
  3215. }
  3216. else if(m_RemoteVendorInfo.wManufacturerCode == INTEL_H_221_MFG_CODE)
  3217. {
  3218. if(pVendorInfo->pProductNumber
  3219. && pVendorInfo->pVersionNumber
  3220. && pVendorInfo->pProductNumber->wOctetStringLength
  3221. && pVendorInfo->pProductNumber->pOctetString
  3222. && pVendorInfo->pVersionNumber->wOctetStringLength
  3223. && pVendorInfo->pVersionNumber->pOctetString)
  3224. {
  3225. // compare strings, don't care about null terminator
  3226. if((0 == memcmp(pVendorInfo->pProductNumber->pOctetString,
  3227. IntelCrashingID, min(sizeof(IntelCrashingID)-1,pVendorInfo->pProductNumber->wOctetStringLength)))
  3228. && (0 == memcmp(pVendorInfo->pVersionNumber->pOctetString,
  3229. IntelCrashingVer,
  3230. min(sizeof(IntelCrashingVer)-1, pVendorInfo->pVersionNumber->wOctetStringLength)) ))
  3231. {
  3232. m_fAvoidCrashingPDUs = TRUE;
  3233. }
  3234. }
  3235. }
  3236. }
  3237. #endif //BETA_2_ASN_PRESENT
  3238. }
  3239. HRESULT CH323Ctrl::Init(IConfAdvise *pConfAdvise)
  3240. {
  3241. hrLast = hrSuccess;
  3242. if(!(m_pConfAdvise = pConfAdvise))
  3243. {
  3244. hrLast = CCO_E_INVALID_PARAM;
  3245. goto EXIT;
  3246. }
  3247. EXIT:
  3248. return hrLast;
  3249. }
  3250. HRESULT CH323Ctrl::DeInit(IConfAdvise *pConfAdvise)
  3251. {
  3252. hrLast = hrSuccess;
  3253. if(m_pConfAdvise != pConfAdvise)
  3254. {
  3255. hrLast = CCO_E_INVALID_PARAM;
  3256. goto EXIT;
  3257. }
  3258. m_pConfAdvise = NULL;
  3259. EXIT:
  3260. return hrLast;
  3261. }
  3262. BOOL CH323Ctrl::IsAcceptingConference(LPVOID lpvConfID)
  3263. {
  3264. if(memcmp(lpvConfID, &m_ConferenceID, sizeof(m_ConferenceID))==0)
  3265. {
  3266. return TRUE;
  3267. }
  3268. return FALSE;
  3269. }
  3270. HRESULT CH323Ctrl::GetProtocolID(LPGUID lpPID)
  3271. {
  3272. if(!lpPID)
  3273. return CCO_E_INVALID_PARAM;
  3274. *lpPID = m_PID;
  3275. hrLast = hrSuccess;
  3276. return hrLast;
  3277. }
  3278. IH323Endpoint * CH323Ctrl::GetIConnIF()
  3279. {
  3280. if(!m_pConfAdvise)
  3281. return NULL;
  3282. return m_pConfAdvise->GetIConnIF();
  3283. }
  3284. STDMETHODIMP CH323Ctrl::GetVersionInfo(
  3285. PCC_VENDORINFO *ppLocalVendorInfo,
  3286. PCC_VENDORINFO *ppRemoteVendorInfo)
  3287. {
  3288. FX_ENTRY ("CH323Ctrl::GetVersionInfo");
  3289. if(!ppLocalVendorInfo || !ppRemoteVendorInfo)
  3290. {
  3291. return CCO_E_INVALID_PARAM;
  3292. }
  3293. *ppLocalVendorInfo = &m_VendorInfo;
  3294. *ppRemoteVendorInfo = &m_RemoteVendorInfo;
  3295. return hrSuccess;
  3296. }
  3297. CH323Ctrl::CH323Ctrl()
  3298. :m_hListen(0),
  3299. m_hConference(0),
  3300. m_hCall(0),
  3301. m_pRemoteAliases(NULL),
  3302. m_pRemoteAliasItem(NULL),
  3303. pwszPeerDisplayName(NULL),
  3304. pwszPeerAliasName(NULL),
  3305. m_bMultipointController(FALSE),
  3306. m_fLocalT120Cap(TRUE),
  3307. m_fRemoteT120Cap(FALSE),
  3308. hrLast(hrSuccess),
  3309. m_ChanFlags(0),
  3310. m_hCallCompleteCode(0),
  3311. m_pConfAdvise(NULL),
  3312. m_Phase( CCS_Idle ),
  3313. #ifdef BETA_2_ASN_PRESENT
  3314. m_fAvoidCrashingPDUs(FALSE),
  3315. #endif
  3316. uRef(1)
  3317. {
  3318. m_PID = PID_H323;
  3319. ZeroMemory(&m_ConferenceID,sizeof(m_ConferenceID));
  3320. ZeroMemory(&local_sin, sizeof(local_sin));
  3321. ZeroMemory(&remote_sin, sizeof(remote_sin));
  3322. ZeroMemory(&m_RemoteVendorInfo, sizeof(m_RemoteVendorInfo));
  3323. local_sin_len = sizeof(local_sin);
  3324. remote_sin_len = sizeof(remote_sin);
  3325. m_VendorInfo.bCountryCode = USA_H221_COUNTRY_CODE;
  3326. m_VendorInfo.bExtension = USA_H221_COUNTRY_EXTENSION;
  3327. m_VendorInfo.wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  3328. m_VendorInfo.pProductNumber = (PCC_OCTETSTRING)MemAlloc(sizeof(CC_OCTETSTRING)
  3329. + sizeof(DefaultProductID));
  3330. if(m_VendorInfo.pProductNumber)
  3331. {
  3332. m_VendorInfo.pProductNumber->wOctetStringLength = sizeof(DefaultProductID);
  3333. m_VendorInfo.pProductNumber->pOctetString =
  3334. ((BYTE *)m_VendorInfo.pProductNumber + sizeof(CC_OCTETSTRING));
  3335. memcpy(m_VendorInfo.pProductNumber->pOctetString,
  3336. DefaultProductID, sizeof(DefaultProductID));
  3337. }
  3338. m_VendorInfo.pVersionNumber = (PCC_OCTETSTRING)MemAlloc(sizeof(CC_OCTETSTRING)
  3339. + sizeof(DefaultProductVersion));
  3340. if(m_VendorInfo.pVersionNumber)
  3341. {
  3342. m_VendorInfo.pVersionNumber->wOctetStringLength = sizeof(DefaultProductVersion);
  3343. m_VendorInfo.pVersionNumber->pOctetString =
  3344. ((BYTE *)m_VendorInfo.pVersionNumber + sizeof(CC_OCTETSTRING));
  3345. memcpy(m_VendorInfo.pVersionNumber->pOctetString,
  3346. DefaultProductVersion, sizeof(DefaultProductVersion));
  3347. }
  3348. m_NonstandardData.bCountryCode = USA_H221_COUNTRY_CODE;
  3349. m_NonstandardData.bExtension = USA_H221_COUNTRY_EXTENSION;
  3350. m_NonstandardData.wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  3351. m_NonstandardData.sData.pOctetString = NULL;
  3352. m_NonstandardData.sData.wOctetStringLength = 0;
  3353. m_ParticipantList.wLength = 0;
  3354. m_ParticipantList.ParticipantInfoArray = NULL;
  3355. m_ConferenceAttributes.pParticipantList = &m_ParticipantList;
  3356. }
  3357. VOID CH323Ctrl ::ReleaseAllChannels()
  3358. {
  3359. ICtrlCommChan *pChan = NULL;
  3360. if (!m_ChannelList.IsEmpty())
  3361. {
  3362. while (!m_ChannelList.IsEmpty())
  3363. {
  3364. pChan = (ICtrlCommChan *) m_ChannelList.RemoveHead();
  3365. if(pChan)
  3366. {
  3367. pChan->EndControlSession();
  3368. pChan->Release();
  3369. pChan = NULL;
  3370. }
  3371. }
  3372. }
  3373. }
  3374. CH323Ctrl ::~CH323Ctrl()
  3375. {
  3376. Cleanup();
  3377. ReleaseAllChannels();
  3378. if(m_pRemoteAliases)
  3379. FreeTranslatedAliasList(m_pRemoteAliases);
  3380. if(pwszPeerDisplayName)
  3381. MemFree(pwszPeerDisplayName);
  3382. if(pwszPeerAliasName)
  3383. MemFree(pwszPeerAliasName);
  3384. if(m_pRemoteAliasItem)
  3385. MemFree(m_pRemoteAliasItem);
  3386. if(m_NonstandardData.sData.pOctetString)
  3387. MemFree(m_NonstandardData.sData.pOctetString);
  3388. if(m_VendorInfo.pProductNumber)
  3389. MemFree(m_VendorInfo.pProductNumber);
  3390. if(m_VendorInfo.pVersionNumber)
  3391. MemFree(m_VendorInfo.pVersionNumber);
  3392. if(m_RemoteVendorInfo.pProductNumber)
  3393. MemFree(m_RemoteVendorInfo.pProductNumber);
  3394. if(m_RemoteVendorInfo.pVersionNumber)
  3395. MemFree(m_RemoteVendorInfo.pVersionNumber);
  3396. }
  3397.