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

3835 lines
119 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. if(NULL != pChannelCapability)
  1907. {
  1908. ERRORMESSAGE(("%s, rejecting channel, Dir:%d, DataType:%d, ClientType:%d, CapId:%d\r\n",
  1909. _fx_, pChannelCapability->Dir, pChannelCapability->DataType,
  1910. pChannelCapability->ClientType, pChannelCapability->CapId));
  1911. }
  1912. hr = CC_RejectChannel(pChannelReqParams->hChannel, dwRejectReason);
  1913. if(hr != CC_OK)
  1914. {
  1915. ERRORMESSAGE(("%s, CC_RejectChannel returned 0x%08lX\r\n",_fx_, hr));
  1916. }
  1917. }
  1918. ERROR_EXIT:
  1919. return;
  1920. }
  1921. VOID CH323Ctrl::OnChannelAcceptComplete(HRESULT hStatus,
  1922. PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS pChannelParams)
  1923. {
  1924. FX_ENTRY("CH323Ctrl::OnChannelAcceptComplete");
  1925. ICtrlCommChan *pChannel;
  1926. if(hStatus != CC_OK)
  1927. {
  1928. return;
  1929. }
  1930. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelAcceptComplete");
  1931. pChannel = FindChannel(pChannelParams->hChannel);
  1932. if(!pChannel)
  1933. {
  1934. ERRORMESSAGE(("OnChannelAcceptComplete: hChannel 0x%08lx not found\r\n", pChannelParams->hChannel));
  1935. return;
  1936. }
  1937. hrLast = pChannel->OnChannelOpen(CHANNEL_OPEN); // the receive side is open
  1938. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelAcceptComplete, open done");
  1939. if(HR_SUCCEEDED(hrLast))
  1940. {
  1941. m_pConfAdvise->OnControlEvent(CCEV_CHANNEL_READY_RX, pChannel, this);
  1942. }
  1943. //
  1944. // Check for readiness to notify that all required channels are open
  1945. //
  1946. CheckChannelsReady( );
  1947. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelAcceptComplete done");
  1948. }
  1949. VOID CH323Ctrl::OnChannelOpen(HRESULT hStatus,
  1950. PCC_TX_CHANNEL_OPEN_CALLBACK_PARAMS pChannelParams )
  1951. {
  1952. FX_ENTRY("CH323Ctrl::OnChannelOpen");
  1953. PCC_ADDR pChannelRTPAddr;
  1954. PCC_ADDR pChannelRTCPAddr;
  1955. SOCKADDR_IN sinC, sinD;
  1956. ICtrlCommChan *pChannel = (ICtrlCommChan *)pChannelParams->dwUserToken;
  1957. // validate channel token - is this what we think it is?
  1958. if(IsBadWritePtr(pChannel, sizeof(ICtrlCommChan)))
  1959. {
  1960. ERRORMESSAGE(("%s:invalid channel token: 0x%08lx\r\n",_fx_, pChannelParams->dwUserToken));
  1961. return;
  1962. }
  1963. if(pChannel->IsSendChannel() == FALSE)
  1964. {
  1965. ERRORMESSAGE(("%s:not a send channel:token 0x%08lX\r\n",_fx_,
  1966. pChannelParams->dwUserToken));
  1967. return;
  1968. }
  1969. #ifdef DEBUG
  1970. POSITION pos = m_ChannelList.GetHeadPosition();
  1971. ICtrlCommChan *pChan;
  1972. BOOL bValid = FALSE;
  1973. // look for a matching channel instance.
  1974. while (pos)
  1975. {
  1976. pChan = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  1977. ASSERT(pChan);
  1978. if(pChan == pChannel)
  1979. {
  1980. bValid = TRUE;
  1981. break;
  1982. }
  1983. }
  1984. if(!bValid)
  1985. {
  1986. ERRORMESSAGE(("%s:unrecognized token 0x%08lX\r\n",_fx_,
  1987. pChannelParams->dwUserToken));
  1988. return;
  1989. }
  1990. #endif //DEBUG
  1991. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen");
  1992. if((hStatus != CC_OK) || (!(pChannelRTPAddr = pChannelParams->pPeerRTPAddr))
  1993. || (!(pChannelRTCPAddr = pChannelParams->pPeerRTCPAddr)))
  1994. {
  1995. ERRORMESSAGE(("%s: hStatus:0x%08lX, address:0x%08lX\r\n",_fx_,
  1996. hStatus, pChannelRTPAddr));
  1997. // LOOKLOOK need to interpret hStatus
  1998. // let the channel know what happened.
  1999. pChannel->OnChannelOpen(CHANNEL_REJECTED);
  2000. // the channel knows what happened, so let it do the worrying.
  2001. return;
  2002. }
  2003. // what's the need for the different address types ????
  2004. if((pChannelRTPAddr->nAddrType != CC_IP_BINARY)
  2005. || (pChannelRTCPAddr->nAddrType != CC_IP_BINARY))
  2006. {
  2007. ERRORMESSAGE(("%s: invalid address types %d, %d\r\n",_fx_,
  2008. pChannelRTPAddr->nAddrType, pChannelRTCPAddr->nAddrType));
  2009. goto ERROR_EXIT;
  2010. }
  2011. // we now have the remote port info ( in host byte order)
  2012. sinD.sin_family = AF_INET;
  2013. sinD.sin_addr.S_un.S_addr = htonl(pChannelRTPAddr->Addr.IP_Binary.dwAddr);
  2014. sinD.sin_port = htons(pChannelRTPAddr->Addr.IP_Binary.wPort);
  2015. sinC.sin_family = AF_INET;
  2016. sinC.sin_addr.S_un.S_addr = htonl(pChannelRTCPAddr->Addr.IP_Binary.dwAddr);
  2017. // There are two ports, but in RTP, it is implicit
  2018. // that the RTCP control port is the next highest port number
  2019. // sinC.sin_port = htons(ntohs(pChannelAddr->Addr.IP_Binary.wPort) +1);
  2020. sinC.sin_port = htons(pChannelRTCPAddr->Addr.IP_Binary.wPort);
  2021. DEBUGMSG(ZONE_CONN,("%s, opened on port 0x%04x, address 0x%08lX\r\n",_fx_,
  2022. pChannelRTPAddr->Addr.IP_Binary.wPort,pChannelRTPAddr->Addr.IP_Binary.dwAddr));
  2023. hrLast = pChannel->AcceptRemoteAddress(&sinD);
  2024. if(!HR_SUCCEEDED(hrLast))
  2025. {
  2026. ERRORMESSAGE(("OnChannelOpen: AcceptRemoteAddress failed\r\n"));
  2027. goto ERROR_EXIT;
  2028. }
  2029. hrLast = pChannel->AcceptRemoteRTCPAddress(&sinC);
  2030. if(!HR_SUCCEEDED(hrLast))
  2031. {
  2032. ERRORMESSAGE(("OnChannelOpen: AcceptRemoteRTCPAddress failed\r\n"));
  2033. goto ERROR_EXIT;
  2034. }
  2035. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen opening");
  2036. hrLast = pChannel->OnChannelOpen(CHANNEL_OPEN); // the send side is open
  2037. if(!HR_SUCCEEDED(hrLast))
  2038. {
  2039. ERRORMESSAGE(("OnChannelOpen:channel's OnChannelOpen() returned 0x%08lX\r\n", hrLast));
  2040. CloseChannel(pChannel);
  2041. goto ERROR_EXIT;
  2042. }
  2043. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen open done");
  2044. m_pConfAdvise->OnControlEvent(CCEV_CHANNEL_READY_TX, pChannel, this);
  2045. //
  2046. // Check for readiness to notify that all required channels are open
  2047. //
  2048. CheckChannelsReady( );
  2049. SHOW_OBJ_ETIME("CH323Ctrl::OnChannelOpen done");
  2050. return;
  2051. ERROR_EXIT:
  2052. // need to cleanup, disconnect, etc.
  2053. m_hCallCompleteCode = CCCI_CHANNEL_OPEN_ERROR;
  2054. // let the parent Conference object know about the imminent disconnect
  2055. DoAdvise(CCEV_CALL_INCOMPLETE, &m_hCallCompleteCode);
  2056. hrLast = CCO_E_MANDATORY_CHAN_OPEN_FAILED;
  2057. InternalDisconnect();
  2058. return;
  2059. }
  2060. VOID CH323Ctrl::OnRxChannelClose(HRESULT hStatus,
  2061. PCC_RX_CHANNEL_CLOSE_CALLBACK_PARAMS pChannelParams )
  2062. {
  2063. FX_ENTRY("CH323Ctrl::OnRxChannelClose");
  2064. PCC_ADDR pChannelRTPAddr;
  2065. PCC_ADDR pChannelRTCPAddr;
  2066. SOCKADDR_IN sinC, sinD;
  2067. ICtrlCommChan *pChannel;
  2068. if(hStatus != CC_OK)
  2069. {
  2070. ERRORMESSAGE(("%s: hStatus:0x%08lX\r\n",_fx_,hStatus));
  2071. // LOOKLOOK need to interpret hStatus
  2072. }
  2073. if(!(pChannel = FindChannel(pChannelParams->hChannel)))
  2074. {
  2075. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2076. return;
  2077. }
  2078. // validate channel - is this really a receive channel?
  2079. if(pChannel->IsSendChannel() == TRUE)
  2080. {
  2081. ERRORMESSAGE(("%s:not a receive channel:hChannel 0x%08lX\r\n",_fx_,
  2082. pChannelParams->hChannel));
  2083. return;
  2084. }
  2085. pChannel->OnChannelClose(CHANNEL_CLOSED);
  2086. return;
  2087. }
  2088. VOID CH323Ctrl::OnTxChannelClose(HRESULT hStatus,
  2089. PCC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS pChannelParams )
  2090. {
  2091. FX_ENTRY("CH323Ctrl::OnTxChannelClose");
  2092. PCC_ADDR pChannelRTPAddr;
  2093. PCC_ADDR pChannelRTCPAddr;
  2094. SOCKADDR_IN sinC, sinD;
  2095. ICtrlCommChan *pChannel;
  2096. if(hStatus != CC_OK)
  2097. {
  2098. ERRORMESSAGE(("%s: hStatus:0x%08lX\r\n",_fx_,hStatus));
  2099. // LOOKLOOK need to interpret hStatus
  2100. }
  2101. if(!(pChannel = FindChannel(pChannelParams->hChannel)))
  2102. {
  2103. CC_CloseChannelResponse(pChannelParams->hChannel, FALSE);
  2104. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2105. return;
  2106. }
  2107. // validate channel - is this really a send channel?
  2108. if(pChannel->IsSendChannel() == FALSE)
  2109. {
  2110. ERRORMESSAGE(("%s:not a send channel:hChannel 0x%08lX\r\n",_fx_,
  2111. pChannelParams->hChannel));
  2112. CC_CloseChannelResponse(pChannelParams->hChannel, FALSE);
  2113. return;
  2114. }
  2115. CC_CloseChannelResponse(pChannelParams->hChannel, TRUE);
  2116. pChannel->OnChannelClose(CHANNEL_CLOSED);
  2117. return;
  2118. }
  2119. BOOL CH323Ctrl::OnCallAccept(PCC_LISTEN_CALLBACK_PARAMS pListenCallbackParams)
  2120. {
  2121. FX_ENTRY ("CH323Ctrl::OnCallAccept");
  2122. BOOL bRet = FALSE;
  2123. CH323Ctrl *pNewConnection = NULL;
  2124. if(m_Phase != CCS_Listening)
  2125. {
  2126. ERRORMESSAGE(("OnCallAccept: unexpected call, m_Phase = 0x%08lX\r\n", m_Phase));
  2127. goto EXIT;
  2128. }
  2129. if((!pListenCallbackParams->pCalleeAddr)
  2130. || (pListenCallbackParams->pCalleeAddr->nAddrType != CC_IP_BINARY))
  2131. {
  2132. if(pListenCallbackParams->pCalleeAddr)
  2133. {
  2134. ERRORMESSAGE(("%s: invalid address type %d\r\n",_fx_,pListenCallbackParams->pCalleeAddr->nAddrType));
  2135. }
  2136. else
  2137. {
  2138. ERRORMESSAGE(("%s: null local address\r\n",_fx_));
  2139. }
  2140. ERRORMESSAGE(("OnCallAccept:where's the local address????\r\n"));
  2141. PHOSTENT phe;
  2142. PSOCKADDR_IN psin;
  2143. char szTemp[200];
  2144. LPCSTR lpHostName;
  2145. gethostname(szTemp,sizeof(szTemp));
  2146. lpHostName = szTemp;
  2147. psin = &local_sin;
  2148. phe = gethostbyname(lpHostName);
  2149. if (phe != NULL)
  2150. {
  2151. memcpy((char FAR *)&(psin->sin_addr), phe->h_addr,phe->h_length);
  2152. psin->sin_family = AF_INET;
  2153. }
  2154. }
  2155. else
  2156. {
  2157. // remember our local address
  2158. local_sin.sin_family = AF_INET;
  2159. // in host byte order
  2160. local_sin.sin_addr.S_un.S_addr = htonl(pListenCallbackParams->pCalleeAddr->Addr.IP_Binary.dwAddr);
  2161. // in host byte order
  2162. local_sin.sin_port = htons(pListenCallbackParams->pCalleeAddr->Addr.IP_Binary.wPort);
  2163. }
  2164. hrLast = m_pConfAdvise->GetAcceptingObject((LPIControlChannel *)&pNewConnection,
  2165. &m_PID);
  2166. if(HR_SUCCEEDED(hrLast) && pNewConnection)
  2167. {
  2168. // NOTE: The UI does not yet know this new object exists, and we may
  2169. // need to silently delete it if there is a disconnect or error
  2170. // Its ref count is 1 at this point. The decision to delete could be
  2171. // made inside pNewConnection->AcceptConnection(), (because sometimes
  2172. // socket reads complete synchronously depending on timing) SO, we need to
  2173. // protect the "unwind path" via AddRef() and Release() around the call
  2174. //
  2175. pNewConnection->AddRef(); //
  2176. hrLast = pNewConnection->AcceptConnection(this, pListenCallbackParams);
  2177. pNewConnection->Release();
  2178. if(HR_SUCCEEDED(hrLast))
  2179. {
  2180. // The Intel Call control DLL already did a socket accept, the
  2181. // Accept() methods simply initialize the handles and states of
  2182. // pNewConnection and get user information (caller ID)
  2183. // BUGBUG - the caller ID may change in Intel's code - it might
  2184. // come via a conference event
  2185. DEBUGMSG(ZONE_CONN,("OnCallAccept:accepted on connection 0x%08lX\r\n",pNewConnection));
  2186. bRet = TRUE;
  2187. }
  2188. else
  2189. {
  2190. ERRORMESSAGE(("OnCallAccept:Accept failed\r\n"));
  2191. // LOOK - Q: where does the accepting object get cleaned up?
  2192. // A: pNewConnection->AcceptConnection((LPIControlChannel)this)
  2193. // must call pNewConnection->DoAdvise(CCEV_ACCEPT_INCOMPLETE, NULL)
  2194. // if the error occurred before the conference object got involved,
  2195. // and must call InternalDisconnect() if the error occurred after
  2196. // the conference object got involved,
  2197. }
  2198. }
  2199. else
  2200. {
  2201. ERRORMESSAGE(("OnCallAccept:GetAcceptingObject failed, hr=0x%08lx\r\n",hrLast));
  2202. }
  2203. EXIT:
  2204. return bRet;
  2205. }
  2206. HRESULT CH323Ctrl::NewConference()
  2207. {
  2208. FX_ENTRY ("CH323Ctrl::NewConference");
  2209. CapsCtl *pCapObject = NULL;
  2210. PCC_TERMCAPLIST pTermCaps = NULL;
  2211. CC_OCTETSTRING TerminalID;
  2212. PCC_TERMCAPDESCRIPTORS pCapsList = NULL;
  2213. LPWSTR lpwUserDisplayName;
  2214. hrLast = m_pConfAdvise->GetCapResolver((LPVOID *)&pCapObject, OID_CAP_ACM_TO_H323);
  2215. if(!HR_SUCCEEDED(hrLast) || (pCapObject == NULL))
  2216. {
  2217. ERRORMESSAGE(("%s: null resolver\r\n",_fx_));
  2218. goto EXIT;
  2219. }
  2220. if(m_hConference)
  2221. {
  2222. ERRORMESSAGE(("%s:leak or uninitialized m_hConference:0x%08lx\r\n",_fx_,
  2223. m_hConference));
  2224. }
  2225. hrLast = pCapObject->CreateCapList(&pTermCaps, &pCapsList);
  2226. if(!HR_SUCCEEDED(hrLast))
  2227. {
  2228. goto EXIT;
  2229. }
  2230. lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2231. if(lpwUserDisplayName)
  2232. {
  2233. TerminalID.pOctetString = (BYTE *)lpwUserDisplayName;
  2234. TerminalID.wOctetStringLength = (WORD)lstrlenW(lpwUserDisplayName)*sizeof(WCHAR);
  2235. }
  2236. // create a conference
  2237. hrLast = CC_CreateConference(&m_hConference, NULL,
  2238. 0, // DWORD dwConferenceConfiguration,
  2239. pTermCaps, // PCC_TERMCAPLIST
  2240. pCapsList, // ptr to term cap descriptors (PCC_TERMCAPDESCRIPTORS)
  2241. &m_VendorInfo, // PVENDORINFO
  2242. (lpwUserDisplayName)? &TerminalID: NULL, // PCC_OCTETSTRING pTerminalID,
  2243. (DWORD_PTR)this,
  2244. NULL, // CC_TERMCAP_CONSTRUCTOR TermCapConstructor,
  2245. NULL, // CC_SESSIONTABLE_CONSTRUCTOR SessionTableConstructor,
  2246. CCConferenceCallback);
  2247. if(hrLast != CC_OK)
  2248. {
  2249. ERRORMESSAGE(("%s: CreateConference returned 0x%08lX\r\n", _fx_, hrLast));
  2250. }
  2251. EXIT:
  2252. pCapObject->DeleteCapList(pTermCaps, pCapsList);
  2253. return hrLast;
  2254. }
  2255. HRESULT CH323Ctrl::AcceptConnection(LPIControlChannel pIListenCtrlChan,
  2256. LPVOID lpvListenCallbackParams)
  2257. {
  2258. FX_ENTRY ("CH323Ctrl::AcceptConnection");
  2259. BOOL bRet = FALSE;
  2260. CREQ_RESPONSETYPE Response;
  2261. DWORD dwCode = CCR_LOCAL_SYSTEM_ERROR; // error variable only used in error case
  2262. ULONG ulNameSize, ulSize;
  2263. PSOCKADDR_IN psin;
  2264. LPWSTR lpwUserDisplayName;
  2265. CH323Ctrl *pListenConnection = (CH323Ctrl *)pIListenCtrlChan;
  2266. P_APP_CALL_SETUP_DATA pAppData = NULL;
  2267. APP_CALL_SETUP_DATA AppData;
  2268. PCC_NONSTANDARDDATA pNSData = ((PCC_LISTEN_CALLBACK_PARAMS)
  2269. lpvListenCallbackParams)->pNonStandardData;
  2270. if(pNSData
  2271. && pNSData->bCountryCode == USA_H221_COUNTRY_CODE
  2272. // why be this picky -> && pNSData->bExtension == USA_H221_COUNTRY_EXTENSION;
  2273. && pNSData->wManufacturerCode == MICROSOFT_H_221_MFG_CODE
  2274. && pNSData->sData.pOctetString
  2275. && pNSData->sData.wOctetStringLength >= sizeof(MSFT_NONSTANDARD_DATA))
  2276. {
  2277. if(((PMSFT_NONSTANDARD_DATA)pNSData->sData.pOctetString)->
  2278. data_type == NSTD_APPLICATION_DATA)
  2279. {
  2280. AppData.lpData = &((PMSFT_NONSTANDARD_DATA)pNSData->sData.pOctetString)->
  2281. nonstd_data.AppData.data;
  2282. AppData.dwDataSize = (DWORD)
  2283. ((PMSFT_NONSTANDARD_DATA)pNSData->sData.pOctetString)->dw_nonstd_data_size;
  2284. pAppData = &AppData;
  2285. }
  2286. }
  2287. SetRemoteVendorID(((PCC_LISTEN_CALLBACK_PARAMS)lpvListenCallbackParams)->pVendorInfo);
  2288. // this object is assuming everything from the listening object, including
  2289. // the "Listening" state
  2290. // enter critical section and make sure another thread is not handling a caller disconnect
  2291. // or timeout
  2292. // EnterCriticalSection()
  2293. if(m_Phase == CCS_Idle)
  2294. {
  2295. GoNextPhase(CCS_Listening);
  2296. // once in this state, a disconnect on another thread will change the state
  2297. // to something besides CCS_Listening
  2298. pListenConnection->GetLocalAddress(&psin);
  2299. SetLocalAddress(psin);
  2300. // steal the conference ID from the listen object
  2301. // m_ConferenceID = pListenConnection->GetConfID();
  2302. memcpy(&m_ConferenceID, pListenConnection->GetConfIDptr(),sizeof(m_ConferenceID));
  2303. ZeroMemory(pListenConnection->GetConfIDptr(),sizeof(m_ConferenceID));
  2304. m_hCall = pListenConnection->GetHCall();
  2305. // steal the user info from the listen object
  2306. m_pRemoteAliasItem = pListenConnection->m_pRemoteAliasItem;
  2307. pListenConnection->m_pRemoteAliasItem = NULL; // make the listen object forget this
  2308. // steal the peer display name
  2309. pwszPeerDisplayName = pListenConnection->pwszPeerDisplayName;
  2310. pListenConnection->pwszPeerDisplayName = NULL;
  2311. lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2312. }
  2313. // else already timing out
  2314. // LeaveCriticalSection()
  2315. if (m_Phase != CCS_Listening) // cleanup before it gets accepted
  2316. {
  2317. goto ACCEPT_ERROR;
  2318. }
  2319. // let the conference object know that caller ID info is available
  2320. ConnectNotify(CCEV_CALLER_ID);
  2321. // Now going to do stuff that might put cleanup responsibility on the
  2322. // conference object or UI. (i.e. the call could be accepted)
  2323. // EnterCriticalSection()
  2324. if(m_Phase == CCS_Listening)
  2325. {
  2326. // state is still OK
  2327. GoNextPhase(CCS_Filtering);
  2328. // once in this state, a disconnect on another thread will change the state
  2329. // to something besides CCS_Filtering
  2330. }
  2331. // else already timing out
  2332. // LeaveCriticalSection()
  2333. if (m_Phase != CCS_Filtering) // one last chance to cleanup before it gets accepted
  2334. {
  2335. goto ERROR_REJECT;
  2336. }
  2337. // can't (should not) do this inside a critical section
  2338. // create a conference to accept the call
  2339. hrLast = NewConference();
  2340. if(!HR_SUCCEEDED(hrLast))
  2341. {
  2342. ERRORMESSAGE(("%s, NewConference returned 0x%08lX\r\n", _fx_, hrLast));
  2343. goto ERROR_REJECT;
  2344. }
  2345. m_pConfAdvise->AddRef();
  2346. Response = m_pConfAdvise->FilterConnectionRequest(this, pAppData);
  2347. m_pConfAdvise->Release();
  2348. // Now it may be in the hands of the Conference object, and the accepted connection will
  2349. // need to go through the "disconnecting" state if cleanup is needed.
  2350. // Because connection code is reentrant, the connection could also have
  2351. // been torn down (via connection methods) while inside
  2352. // m_pConfAdvise->FilterConnectionRequest();
  2353. // In each case below, check validity of the connection state - it might have changed
  2354. // because a connection method was called or because the caller timed out
  2355. switch(Response)
  2356. {
  2357. default:
  2358. case CRR_ACCEPT:
  2359. if(m_Phase != CCS_Filtering)
  2360. {
  2361. ERRORMESSAGE(("%s, accepting state no longer valid 0x%08lX\r\n", _fx_, hrLast));
  2362. goto CANCEL_ACCEPT;
  2363. }
  2364. // accept this request
  2365. hrLast = CC_AcceptCall(m_hConference,
  2366. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2367. lpwUserDisplayName,
  2368. m_hCall,
  2369. 0, // DWORD dwBandwidth,
  2370. (DWORD_PTR)this);
  2371. if(hrLast != CC_OK)
  2372. {
  2373. m_ChanFlags &= ~CTRLF_OPEN;
  2374. goto CANCEL_ACCEPT;
  2375. }
  2376. GoNextPhase(CCS_Accepting);
  2377. bRet = TRUE;
  2378. break;
  2379. case CRR_ASYNC:
  2380. if(m_Phase == CCS_Accepting)
  2381. {
  2382. // then call has already been accepted inside FilterConnectionRequest callback
  2383. bRet = TRUE;
  2384. }
  2385. else
  2386. {
  2387. if(m_Phase != CCS_Filtering)
  2388. {
  2389. ERRORMESSAGE(("%s, accepting state no longer valid 0x%08lX\r\n", _fx_, hrLast));
  2390. goto CANCEL_ACCEPT;
  2391. }
  2392. GoNextPhase(CCS_Ringing);
  2393. bRet = TRUE;
  2394. }
  2395. break;
  2396. case CRR_BUSY:
  2397. hrLast = CC_RejectCall(CC_REJECT_USER_BUSY,
  2398. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2399. m_hCall);
  2400. // always clean up this object that's not accepting the call
  2401. GoNextPhase(CCS_Idle);
  2402. goto ACCEPT_ERROR;
  2403. break;
  2404. case CRR_REJECT:
  2405. hrLast = CC_RejectCall(CC_REJECT_DESTINATION_REJECTION,
  2406. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2407. m_hCall);
  2408. // always clean up this object that's not accepting the call
  2409. GoNextPhase(CCS_Idle);
  2410. goto ACCEPT_ERROR;
  2411. break;
  2412. case CRR_SECURITY_DENIED:
  2413. hrLast = CC_RejectCall(CC_REJECT_SECURITY_DENIED,
  2414. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2415. m_hCall);
  2416. // always clean up this object that's not accepting the call
  2417. GoNextPhase(CCS_Idle);
  2418. goto ACCEPT_ERROR;
  2419. break;
  2420. }
  2421. return hrLast;
  2422. ERROR_REJECT:
  2423. hrLast = CC_RejectCall(CC_REJECT_UNDEFINED_REASON,
  2424. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2425. m_hCall); // always clean up this object that's not accepting the call
  2426. GoNextPhase(CCS_Idle);
  2427. ACCEPT_ERROR:
  2428. DoAdvise(CCEV_ACCEPT_INCOMPLETE, &dwCode);
  2429. return hrLast;
  2430. CANCEL_ACCEPT:
  2431. // InternalDisconnect() can be called from any state, and will do fine if
  2432. // it is already in a disconnecting state.
  2433. InternalDisconnect();
  2434. return hrLast;
  2435. }
  2436. VOID CH323Ctrl::Cleanup()
  2437. {
  2438. POSITION pos = m_ChannelList.GetHeadPosition();
  2439. ICtrlCommChan *pChan = NULL;
  2440. CleanupConferenceAttributes();
  2441. if(m_hConference)
  2442. {
  2443. hrLast = CC_DestroyConference(m_hConference, FALSE);
  2444. // LOOKLOOK - need to check return code!!!
  2445. m_hConference = 0;
  2446. }
  2447. // reset each channel (cleanup underlying socket references)
  2448. while (pos)
  2449. {
  2450. pChan = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  2451. ASSERT(pChan);
  2452. // cleanup RTP sockets
  2453. pChan->Reset();
  2454. }
  2455. // clear "socket(s) are open flags
  2456. m_ChanFlags &= ~CTRLF_OPEN;
  2457. }
  2458. HRESULT CH323Ctrl::GetLocalPort(PORT * lpPort)
  2459. {
  2460. *lpPort = ntohs(local_sin.sin_port);
  2461. return hrSuccess;
  2462. }
  2463. HRESULT CH323Ctrl::GetRemotePort(PORT * lpPort)
  2464. {
  2465. *lpPort = ntohs(remote_sin.sin_port);
  2466. return hrSuccess;
  2467. }
  2468. HRESULT CH323Ctrl::GetLocalAddress(PSOCKADDR_IN *lplpAddr)
  2469. {
  2470. *lplpAddr = &local_sin;
  2471. return hrSuccess;
  2472. }
  2473. HRESULT CH323Ctrl::GetRemoteAddress(PSOCKADDR_IN *lplpAddr)
  2474. {
  2475. *lplpAddr = &remote_sin;
  2476. return hrSuccess;
  2477. }
  2478. HRESULT CH323Ctrl::ListenOn(PORT Port)
  2479. {
  2480. FX_ENTRY ("CH323Ctrl::ListenOn");
  2481. PCC_ALIASNAMES pAliasNames = m_pConfAdvise->GetUserAliases();
  2482. // temporary hack to override UI's ignorance of multiple protocol types
  2483. if(Port != H323_PORT)
  2484. {
  2485. ERRORMESSAGE(("%s, overriding port %d(d) with H323 port %d\r\n",_fx_,
  2486. Port, H323_PORT));
  2487. Port = H323_PORT;
  2488. }
  2489. // do we need to remember this?
  2490. local_sin.sin_addr.S_un.S_addr = INADDR_ANY;
  2491. local_sin.sin_family = AF_INET;
  2492. local_sin.sin_port = htons((u_short)Port); // set port
  2493. CC_ADDR ListenAddr;
  2494. ListenAddr.nAddrType = CC_IP_BINARY;
  2495. ListenAddr.bMulticast = FALSE;
  2496. // in host byte order
  2497. ListenAddr.Addr.IP_Binary.wPort = (u_short)Port;
  2498. ListenAddr.Addr.IP_Binary.dwAddr = ntohl(INADDR_ANY);
  2499. hrLast = CC_CallListen(&m_hListen, &ListenAddr,
  2500. pAliasNames, (DWORD_PTR)this, CCListenCallback);
  2501. if(hrLast != CC_OK)
  2502. {
  2503. ERRORMESSAGE(("CH323Ctrl::ListenOn:CallListen returned 0x%08lX\r\n", hrLast));
  2504. goto EXIT;
  2505. }
  2506. GoNextPhase(CCS_Listening);
  2507. m_ChanFlags = CTRLF_RESET;
  2508. hrLast = hrSuccess;
  2509. EXIT:
  2510. return hrLast;
  2511. }
  2512. HRESULT CH323Ctrl::StopListen(VOID)
  2513. {
  2514. if(m_Phase == CCS_Listening)
  2515. {
  2516. hrLast = CC_CancelListen(m_hListen);
  2517. }
  2518. else
  2519. {
  2520. hrLast = CCO_E_NOT_LISTENING;
  2521. }
  2522. //EXIT:
  2523. return hrLast;
  2524. }
  2525. HRESULT CH323Ctrl::AsyncAcceptRejectCall(CREQ_RESPONSETYPE Response)
  2526. {
  2527. FX_ENTRY ("CH323Ctrl::AsyncAcceptRejectCall");
  2528. HRESULT hr = CCO_E_CONNECT_FAILED;
  2529. LPWSTR lpwUserDisplayName;
  2530. if(Response == CRR_ACCEPT)
  2531. {
  2532. DEBUGMSG(ZONE_CONN,("%s:accepting\r\n",_fx_));
  2533. lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2534. // check call setup phase - send ready if user's acceptance is what
  2535. // was holding us up
  2536. if((m_Phase == CCS_Ringing) || (m_Phase == CCS_Filtering))
  2537. {
  2538. // accept this request
  2539. hrLast = CC_AcceptCall(m_hConference,
  2540. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2541. lpwUserDisplayName,
  2542. m_hCall,
  2543. 0, // DWORD dwBandwidth,
  2544. (DWORD_PTR)this);
  2545. if(hrLast != CC_OK)
  2546. {
  2547. ERRORMESSAGE(("%s, CC_AcceptCall() returned 0x%08lX\r\n",_fx_, hrLast));
  2548. goto EXIT;
  2549. }
  2550. GoNextPhase(CCS_Accepting);
  2551. hr = hrSuccess;
  2552. }
  2553. }
  2554. else
  2555. {
  2556. // reject only if in accepting state(s)
  2557. // deletion is possible while in advise callback, so protect w/ AddRef()
  2558. AddRef();
  2559. DEBUGMSG(ZONE_CONN,("%s:rejecting\r\n",_fx_));
  2560. if((m_Phase == CCS_Ringing) || (m_Phase == CCS_Filtering))
  2561. {
  2562. hrLast = CC_RejectCall((Response == CRR_BUSY) ?
  2563. CC_REJECT_USER_BUSY : CC_REJECT_DESTINATION_REJECTION,
  2564. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2565. m_hCall);
  2566. if(hrLast != CC_OK)
  2567. {
  2568. ERRORMESSAGE(("%s, CC_RejectCall() returned 0x%08lX\r\n",_fx_, hrLast));
  2569. }
  2570. GoNextPhase(CCS_Idle);
  2571. // notify the UI or application code or whatever..
  2572. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2573. }
  2574. else
  2575. {
  2576. hr = CCO_E_INVALID_PARAM; // LOOKLOOK - need INVALID_STATE error code
  2577. }
  2578. Release();
  2579. }
  2580. EXIT:
  2581. return (hr);
  2582. }
  2583. ULONG CH323Ctrl ::AddRef()
  2584. {
  2585. FX_ENTRY ("CH323Ctrl::AddRef");
  2586. uRef++;
  2587. DEBUGMSG(ZONE_REFCOUNT,("%s:(0x%08lX)->AddRef() uRef = 0x%08lX\r\n",_fx_, this, uRef ));
  2588. return uRef;
  2589. }
  2590. ULONG CH323Ctrl ::Release()
  2591. {
  2592. FX_ENTRY("CH323Ctrl ::Release");
  2593. uRef--;
  2594. if(uRef == 0)
  2595. {
  2596. DEBUGMSG(ZONE_CONN,("%s:(0x%08lX)->Releasing in phase:%d\r\n",_fx_, this, m_Phase ));
  2597. if(m_Phase != CCS_Idle)
  2598. {
  2599. ERRORMESSAGE(("CMSIACtrl::uRef zero in non idle (%d) state!\r\n",m_Phase));
  2600. InternalDisconnect();
  2601. }
  2602. delete this;
  2603. return 0;
  2604. }
  2605. DEBUGMSG(ZONE_REFCOUNT,("%s:(0x%08lX)->Release() uRef = 0x%08lX\r\n",_fx_, this, uRef ));
  2606. return uRef;
  2607. }
  2608. // implement IControlChannel::Disconnect(). Map reason codes to the protocol.
  2609. VOID CH323Ctrl::Disconnect(DWORD dwReason)
  2610. {
  2611. // no way to propagate reason through H.323 stack?????
  2612. InternalDisconnect();
  2613. }
  2614. VOID CH323Ctrl::InternalDisconnect()
  2615. {
  2616. FX_ENTRY ("CH323Ctrl::Disconnect");
  2617. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect");
  2618. m_ChanFlags &= ~CTRLF_ORIGINATING; // reset "originating" flag.
  2619. DEBUGMSG(ZONE_CONN,("%s, called in state %d, uRef = 0x%08lX\r\n",_fx_, m_Phase, uRef));
  2620. switch(m_Phase)
  2621. {
  2622. case CCS_Connecting:
  2623. case CCS_Accepting:
  2624. // if we believe the control channel is still connected, disconnect
  2625. if(IsCtlChanOpen(m_ChanFlags))
  2626. {
  2627. //set state to indicate disconnecting.
  2628. GoNextPhase(CCS_Disconnecting);
  2629. DEBUGMSG(ZONE_CONN,("%s, Expecting a CC_HANGUP_INDICATION\r\n",_fx_));
  2630. hrLast = CC_Hangup(m_hConference, FALSE, (DWORD_PTR)this);
  2631. if(hrLast != CC_OK)
  2632. {
  2633. ERRORMESSAGE(("%s:Hangup() returned 0x%08lX\r\n",_fx_, hrLast));
  2634. }
  2635. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect hangup done");
  2636. }
  2637. else
  2638. {
  2639. CC_CancelCall(m_hCall);
  2640. GoNextPhase(CCS_Idle); // no need to ck retval - we're disconnected
  2641. // notify the UI or application code or whatever..
  2642. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2643. }
  2644. break;
  2645. case CCS_Ringing:
  2646. // The call has not yet been accepted!!! Reject it!
  2647. hrLast = CC_RejectCall(CC_REJECT_UNDEFINED_REASON,
  2648. NULL, // PCC_NONSTANDARDDATA pNonStandardData
  2649. m_hCall);
  2650. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect reject done");
  2651. GoNextPhase(CCS_Idle);
  2652. // notify the UI or application code or whatever..
  2653. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2654. break;
  2655. case CCS_Idle:
  2656. case CCS_Disconnecting:
  2657. ERRORMESSAGE(("%s:called in unconnected state %d\r\n",_fx_, m_Phase));
  2658. break;
  2659. default:
  2660. //CCS_Ringing
  2661. //CCS_Opening
  2662. //CCS_Closing
  2663. //CCS_Ready
  2664. //CCS_InUse
  2665. //CCS_Listening
  2666. // if we believe the control channel is still connected, disconnect
  2667. if(IsCtlChanOpen(m_ChanFlags))
  2668. {
  2669. //set state to indicate disconnecting.
  2670. GoNextPhase(CCS_Disconnecting);
  2671. hrLast = CC_Hangup(m_hConference, FALSE, (DWORD_PTR)this);
  2672. if(hrLast != CC_OK)
  2673. {
  2674. ERRORMESSAGE(("%s:Hangup() returned 0x%08lX\r\n",_fx_, hrLast));
  2675. DoAdvise(CCEV_DISCONNECTED ,NULL);
  2676. }
  2677. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect hangup done");
  2678. }
  2679. else
  2680. {
  2681. GoNextPhase(CCS_Idle); // no need to ck retval - we're disconnected
  2682. // notify the UI or application code or whatever..
  2683. DoAdvise(CCEV_DISCONNECTED, &m_hCallCompleteCode);
  2684. }
  2685. break;
  2686. }
  2687. SHOW_OBJ_ETIME("CH323Ctrl::InternalDisconnect done");
  2688. }
  2689. // start the asynchronous stuff that will instantiate a control channel
  2690. HRESULT CH323Ctrl::PlaceCall (BOOL bUseGKResolution, PSOCKADDR_IN pCallAddr,
  2691. P_H323ALIASLIST pDestinationAliases, P_H323ALIASLIST pExtraAliases,
  2692. LPCWSTR pCalledPartyNumber, P_APP_CALL_SETUP_DATA pAppData)
  2693. {
  2694. FX_ENTRY ("CH323Ctrl::PlaceCall");
  2695. CC_ALIASNAMES pstn_alias;
  2696. PCC_ALIASITEM pPSTNAlias = NULL;
  2697. PCC_ALIASNAMES pRemoteAliasNames = NULL;
  2698. PCC_ALIASNAMES pTranslatedAliasNames = NULL;
  2699. PCC_ALIASNAMES pLocalAliasNames = NULL;
  2700. PCC_ADDR pDestinationAddr = NULL;
  2701. PCC_ADDR pConnectAddr = NULL;
  2702. LPWSTR lpwUserDisplayName = m_pConfAdvise->GetUserDisplayName();
  2703. PCC_NONSTANDARDDATA pNSData = NULL;
  2704. PMSFT_NONSTANDARD_DATA lpNonstdContent = NULL;
  2705. int iLen;
  2706. LPWSTR lpwszDest;
  2707. HRESULT hResult = hrSuccess;
  2708. // validate current state, don't allow bad actions
  2709. if(m_Phase != CCS_Idle)
  2710. {
  2711. hResult = CCO_E_NOT_IDLE;
  2712. goto EXIT;
  2713. }
  2714. OBJ_CPT_RESET; // reset elapsed timer
  2715. m_ChanFlags |= CTRLF_INIT_ORIGINATING;
  2716. if(!pCallAddr)
  2717. {
  2718. hResult = CCO_E_BAD_ADDRESS;
  2719. goto EXIT;
  2720. }
  2721. else
  2722. {
  2723. // keep a copy of the address
  2724. SetRemoteAddress(pCallAddr);
  2725. }
  2726. // temporary hack to override UI's ignorance of multiple protocol types
  2727. if(remote_sin.sin_port != htons(H323_PORT))
  2728. {
  2729. ERRORMESSAGE(("%s, overriding port %d(d) with H323 port %d\r\n",_fx_,
  2730. ntohs(remote_sin.sin_port), H323_PORT));
  2731. remote_sin.sin_port = htons(H323_PORT);
  2732. }
  2733. // check for connecting to self (not supported)
  2734. if(local_sin.sin_addr.s_addr == remote_sin.sin_addr.s_addr)
  2735. {
  2736. hResult = CCO_E_BAD_ADDRESS;
  2737. goto EXIT;
  2738. }
  2739. if(m_pRemoteAliasItem)
  2740. {
  2741. MemFree(m_pRemoteAliasItem);
  2742. m_pRemoteAliasItem = NULL;
  2743. }
  2744. // Is this a PSTN or H.320 gateway call?
  2745. if(pCalledPartyNumber)
  2746. {
  2747. // Then, due to the bogus way that CC_PlaceCall() is overloaded, the remote alias names
  2748. // must be overridden with the E.164 phone number. The hack is buried in
  2749. // Q931ConnectCallback() in CALLCONT.DLL (thank you Intel). That hack propagates
  2750. // the phone number to the "CalledPartyNumber" of the SETUP message only if there is
  2751. // exactly one alias, and that one alias is of type E.164.
  2752. // get # of characters
  2753. iLen = lstrlenW(pCalledPartyNumber);
  2754. // need buffer of size CC_ALIASITEM plus the size (in bytes) of the string
  2755. pPSTNAlias = (PCC_ALIASITEM)MemAlloc(sizeof(CC_ALIASITEM)
  2756. + sizeof(WCHAR)* (iLen+1));
  2757. if(!pPSTNAlias)
  2758. {
  2759. ERRORMESSAGE(("%s:failed alloc of pPSTNAlias:0x%08lx\r\n",_fx_));
  2760. hResult = CCO_E_OUT_OF_MEMORY;
  2761. goto EXIT;
  2762. }
  2763. WORD wIndex, wLength =1; // init wLength to count the null terminator
  2764. WCHAR E164Chars[] = {CC_ALIAS_H323_PHONE_CHARS};
  2765. LPCWSTR lpSrc = pCalledPartyNumber;
  2766. pPSTNAlias->wType = CC_ALIAS_H323_PHONE;
  2767. // set offsets - the E.164 address (a phone number) is the only thing
  2768. // in the alias name buffer
  2769. lpwszDest = (LPWSTR)(((char *)pPSTNAlias)+ sizeof(CC_ALIASITEM));
  2770. pPSTNAlias->pData = lpwszDest;
  2771. while(iLen--)
  2772. {
  2773. wIndex = (sizeof(E164Chars)/sizeof (WCHAR)) -1; //scan E164Chars[]
  2774. do
  2775. {
  2776. if(*lpSrc == E164Chars[wIndex])
  2777. {
  2778. *lpwszDest++ = *lpSrc;
  2779. wLength++;
  2780. break;
  2781. }
  2782. }while(wIndex--);
  2783. lpSrc++;
  2784. }
  2785. // terminate it
  2786. *lpwszDest = 0;
  2787. // wDataLength is the # of UNICODE characters
  2788. pPSTNAlias->wDataLength = wLength;
  2789. pstn_alias.wCount = 1;
  2790. pstn_alias.pItems = pPSTNAlias;
  2791. pRemoteAliasNames = &pstn_alias;
  2792. }
  2793. else if (pDestinationAliases && bUseGKResolution)// use the supplied callee alias names
  2794. {
  2795. hrLast = AllocTranslatedAliasList(&pTranslatedAliasNames, pDestinationAliases);
  2796. if(!HR_SUCCEEDED(hrLast))
  2797. {
  2798. ERRORMESSAGE(("%s, AllocTranslatedAliasList returned 0x%08lX\r\n", _fx_, hrLast));
  2799. hResult = CCO_E_SYSTEM_ERROR;
  2800. goto EXIT;
  2801. }
  2802. pRemoteAliasNames = pTranslatedAliasNames;
  2803. }
  2804. // else pRemoteAliasNames is initialized to NULL
  2805. pLocalAliasNames = m_pConfAdvise->GetUserAliases();
  2806. // start!!!
  2807. CC_ADDR ConfAddr;
  2808. // fixup the intel version of the address
  2809. // also note that it's all in host byte order
  2810. ConfAddr.bMulticast = FALSE;
  2811. ConfAddr.nAddrType = CC_IP_BINARY;
  2812. //hrLast = GetRemotePort(&ConfAddr.Addr.IP_Binary.wPort);
  2813. ConfAddr.Addr.IP_Binary.wPort = htons(remote_sin.sin_port);
  2814. ConfAddr.Addr.IP_Binary.dwAddr = ntohl(remote_sin.sin_addr.S_un.S_addr);
  2815. #ifdef DEBUG
  2816. if(m_hConference)
  2817. ERRORMESSAGE(("%s:leak or uninitialized m_hConference:0x%08lx\r\n",_fx_,
  2818. m_hConference));
  2819. #endif // DEBUG
  2820. // create a conference to place the call
  2821. SHOW_OBJ_ETIME("PlaceCall ready to create conference");
  2822. hrLast = NewConference();
  2823. if(!HR_SUCCEEDED(hrLast))
  2824. {
  2825. ERRORMESSAGE(("%s, NewConference returned 0x%08lX\r\n", _fx_, hrLast));
  2826. hResult = CCO_E_SYSTEM_ERROR;
  2827. goto EXIT;
  2828. }
  2829. // Set connect timeout value
  2830. // LOOKLOOK - this is a hardcoded value - !!! Where should this actualy come from?
  2831. // 30 secs == 30000mS
  2832. SHOW_OBJ_ETIME("PlaceCall setting timeout");
  2833. hrLast = CC_SetCallControlTimeout(CC_Q931_ALERTING_TIMEOUT, 30000);
  2834. if(pAppData)
  2835. {
  2836. // typical case - app data should be really small
  2837. if(pAppData->dwDataSize <= APPLICATION_DATA_DEFAULT_SIZE)
  2838. {
  2839. m_NonstdContent.data_type = NSTD_APPLICATION_DATA;
  2840. m_NonstdContent.dw_nonstd_data_size = pAppData->dwDataSize;
  2841. memcpy(&m_NonstdContent.nonstd_data.AppData.data,
  2842. pAppData->lpData, pAppData->dwDataSize);
  2843. m_NonstandardData.sData.pOctetString = (LPBYTE) &m_NonstdContent;
  2844. m_NonstandardData.sData.wOctetStringLength = sizeof(m_NonstdContent);
  2845. }
  2846. else // need some heap
  2847. {
  2848. UINT uTotalSize = sizeof(MSFT_NONSTANDARD_DATA)+ pAppData->dwDataSize;
  2849. lpNonstdContent = (PMSFT_NONSTANDARD_DATA)MemAlloc(uTotalSize);
  2850. if(lpNonstdContent)
  2851. {
  2852. lpNonstdContent->data_type = NSTD_APPLICATION_DATA;
  2853. lpNonstdContent->dw_nonstd_data_size = pAppData->dwDataSize;
  2854. memcpy(&lpNonstdContent->nonstd_data.AppData.data, pAppData->lpData,pAppData->dwDataSize);
  2855. m_NonstandardData.sData.pOctetString = (LPBYTE) lpNonstdContent;
  2856. m_NonstandardData.sData.wOctetStringLength = LOWORD(uTotalSize);
  2857. }
  2858. else
  2859. {
  2860. ERRORMESSAGE(("%s, alloc failed\r\n", _fx_));
  2861. hResult = CCO_E_SYSTEM_ERROR;
  2862. goto EXIT;
  2863. }
  2864. }
  2865. pNSData = &m_NonstandardData;
  2866. }
  2867. m_NonstandardData.bCountryCode = USA_H221_COUNTRY_CODE;
  2868. m_NonstandardData.bExtension = USA_H221_COUNTRY_EXTENSION;
  2869. m_NonstandardData.wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  2870. SHOW_OBJ_ETIME("CH323Ctrl::PlaceCall ready to place call");
  2871. // set destination address pointers
  2872. if(bUseGKResolution)
  2873. {
  2874. // the address passed in pCallAddr is the GK's address
  2875. pConnectAddr = &ConfAddr;
  2876. }
  2877. else
  2878. {
  2879. pDestinationAddr = &ConfAddr;
  2880. }
  2881. hrLast = CC_PlaceCall(
  2882. m_hConference,
  2883. &m_hCall,
  2884. pLocalAliasNames, // PCC_ALIASNAMES pLocalAliasNames,
  2885. pRemoteAliasNames,
  2886. NULL, // PCC_ALIASNAMES pExtraCalleeAliasNames,
  2887. NULL, // PCC_ALIASITEM pCalleeExtension,
  2888. pNSData, // PCC_NONSTANDARDDATA pNonStandardData,
  2889. lpwUserDisplayName, // PWSTR pszDisplay,
  2890. pDestinationAddr, // Destination call signalling address
  2891. pConnectAddr, // address to send the SETUP message to, if different than
  2892. // the destination address. (used for gatekeeper calls?)
  2893. 0, // DWORD dwBandwidth,
  2894. (DWORD_PTR) this);
  2895. SHOW_OBJ_ETIME("CH323Ctrl::PlaceCall placed call");
  2896. // clear these out so that cleanup does not try to free later
  2897. if(lpNonstdContent)
  2898. MemFree(lpNonstdContent);
  2899. m_NonstandardData.sData.pOctetString = NULL;
  2900. m_NonstandardData.sData.wOctetStringLength = 0;
  2901. // check return from CC_PlaceCall
  2902. if(hrLast != CC_OK)
  2903. {
  2904. ERRORMESSAGE(("CH323Ctrl::PlaceCall, PlaceCall returned 0x%08lX\r\n", hrLast));
  2905. hResult = CCO_E_CONNECT_FAILED;
  2906. goto EXIT;
  2907. }
  2908. // wait for an indication
  2909. GoNextPhase(CCS_Connecting);
  2910. EXIT:
  2911. if(pTranslatedAliasNames)
  2912. {
  2913. FreeTranslatedAliasList(pTranslatedAliasNames);
  2914. }
  2915. if(pPSTNAlias)
  2916. {
  2917. MemFree(pPSTNAlias);
  2918. }
  2919. return hResult;
  2920. }
  2921. //
  2922. // Given HCHANNEL, find the channel object.
  2923. //
  2924. ICtrlCommChan *CH323Ctrl::FindChannel(CC_HCHANNEL hChannel)
  2925. {
  2926. FX_ENTRY ("CH323Ctrl::FindChannel");
  2927. // find the channel
  2928. POSITION pos = m_ChannelList.GetHeadPosition();
  2929. ICtrlCommChan *pChannel;
  2930. while (pos)
  2931. {
  2932. pChannel = (ICtrlCommChan *) m_ChannelList.GetNext(pos);
  2933. ASSERT(pChannel);
  2934. if(pChannel->GetHChannel() == hChannel)
  2935. return pChannel;
  2936. }
  2937. #ifdef DEBUG
  2938. // fallout to error case
  2939. ERRORMESSAGE(("%s, did not find hChannel 0x%08lX\r\n",_fx_,hChannel));
  2940. #endif // DEBUG
  2941. return NULL;
  2942. }
  2943. VOID CH323Ctrl::OnMute(HRESULT hStatus,
  2944. PCC_MUTE_CALLBACK_PARAMS pParams)
  2945. {
  2946. FX_ENTRY ("CH323Ctrl::OnMute");
  2947. ICtrlCommChan *pChannel;
  2948. HRESULT hr;
  2949. if(!(pChannel = FindChannel(pParams->hChannel)))
  2950. {
  2951. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2952. return;
  2953. }
  2954. hr = pChannel->PauseNet(TRUE, TRUE);
  2955. if(!HR_SUCCEEDED(hr))
  2956. {
  2957. ERRORMESSAGE(("%s, Pausenet returned 0x%08lx\r\n", _fx_, hr));
  2958. }
  2959. }
  2960. VOID CH323Ctrl::OnUnMute(HRESULT hStatus,
  2961. PCC_UNMUTE_CALLBACK_PARAMS pParams)
  2962. {
  2963. FX_ENTRY ("CH323Ctrl::OnUnMute");
  2964. ICtrlCommChan *pChannel;
  2965. HRESULT hr;
  2966. if(!(pChannel = FindChannel(pParams->hChannel)))
  2967. {
  2968. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2969. return;
  2970. }
  2971. hr = pChannel->PauseNet(FALSE, TRUE);
  2972. if(!HR_SUCCEEDED(hr))
  2973. {
  2974. ERRORMESSAGE(("%s, Pausenet returned 0x%08lx\r\n", _fx_, hr));
  2975. }
  2976. }
  2977. VOID CH323Ctrl::OnMiscCommand(HRESULT hStatus,
  2978. PCC_H245_MISCELLANEOUS_COMMAND_CALLBACK_PARAMS pParams)
  2979. {
  2980. FX_ENTRY ("CH323Ctrl::OnMiscCommand");
  2981. ICtrlCommChan *pChannel;
  2982. // not every command references an individual channel. The 4 exceptions are:
  2983. // case equaliseDelay_chosen:
  2984. // case zeroDelay_chosen:
  2985. // case multipointModeCommand_chosen:
  2986. // case cnclMltpntMdCmmnd_chosen:
  2987. //
  2988. // if we were betting on receiving few of the exceptional cases, we would always
  2989. // try to find the channel.
  2990. //if(!(pChannel = FindChannel(pParams->hChannel)))
  2991. //{
  2992. // ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  2993. // but don't error because of the exceptions
  2994. //}
  2995. switch(pParams->pMiscellaneousCommand->type.choice)
  2996. {
  2997. // the name and spelling of these constants was invented by the OSS compiler
  2998. //
  2999. case videoFreezePicture_chosen:
  3000. if(!(pChannel = FindChannel(pParams->hChannel)))
  3001. {
  3002. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3003. break;
  3004. }
  3005. break;
  3006. case videoFastUpdatePicture_chosen: // the receiver wants an I-Frame
  3007. {
  3008. HRESULT hr;
  3009. IVideoChannel *pIVC=NULL;
  3010. if(!(pChannel = FindChannel(pParams->hChannel)))
  3011. {
  3012. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3013. break;
  3014. }
  3015. hr = pChannel->QueryInterface(IID_IVideoChannel, (void **)&pIVC);
  3016. if(HR_SUCCEEDED(hr))
  3017. {
  3018. pIVC->SendKeyFrame();
  3019. pIVC->Release();
  3020. }
  3021. // else it must not be a video channel
  3022. }
  3023. break;
  3024. case MCd_tp_vdTmprlSptlTrdOff_chosen:
  3025. {
  3026. DWORD dwTradeoff;
  3027. HRESULT hr;
  3028. if(!(pChannel = FindChannel(pParams->hChannel)))
  3029. {
  3030. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3031. break;
  3032. }
  3033. // set TS value of the channel, also propagate to Datapump
  3034. dwTradeoff = MAKELONG(
  3035. pParams->pMiscellaneousCommand->type.u.MCd_tp_vdTmprlSptlTrdOff, 0);
  3036. // set channel property
  3037. // NOTE: when PROP_TS_TRADEOFF is set, the channel does all the
  3038. // local tweaking to make it happen. The channel will also signal the
  3039. // new value to the remote as if the local end initiated it.
  3040. hr = pChannel->CtrlChanSetProperty(PROP_TS_TRADEOFF, &dwTradeoff, sizeof(dwTradeoff));
  3041. }
  3042. break;
  3043. default:
  3044. // the following are not currently handled
  3045. // case equaliseDelay_chosen:
  3046. // case zeroDelay_chosen:
  3047. // case videoSendSyncEveryGOB_chosen:
  3048. // case vdSndSyncEvryGOBCncl_chosen:
  3049. // case videoFastUpdateGOB_chosen: // suposedly required by H.323
  3050. // case videoFastUpdateMB_chosen: // suposedly required by H.323
  3051. // and the remaining 2 are handled by the call control layer
  3052. // so we will never see these
  3053. // case multipointModeCommand_chosen:
  3054. // case cnclMltpntMdCmmnd_chosen:
  3055. break;
  3056. }
  3057. }
  3058. VOID CH323Ctrl::OnMiscIndication(HRESULT hStatus,
  3059. PCC_H245_MISCELLANEOUS_INDICATION_CALLBACK_PARAMS pParams)
  3060. {
  3061. FX_ENTRY ("CH323Ctrl::OnMiscIndication");
  3062. ICtrlCommChan *pChannel;
  3063. HRESULT hr;
  3064. unsigned short choice = pParams->pMiscellaneousIndication->type.choice;
  3065. if(!(pChannel = FindChannel(pParams->hChannel)))
  3066. {
  3067. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3068. // check the exceptional cases for which this is OK
  3069. if((choice == multipointConference_chosen)
  3070. || (choice == cnclMltpntCnfrnc_chosen)
  3071. || (choice == multipointZeroComm_chosen)
  3072. || (choice == cancelMultipointZeroComm_chosen)
  3073. || (choice == mltpntScndryStts_chosen)
  3074. || (choice == cnclMltpntScndryStts_chosen))
  3075. {
  3076. return; // as long as the above choices are not supported......
  3077. }
  3078. }
  3079. switch(choice)
  3080. {
  3081. case logicalChannelActive_chosen:
  3082. if(NULL != pChannel)
  3083. {
  3084. hr = pChannel->PauseNet(FALSE, TRUE);
  3085. }
  3086. break;
  3087. case logicalChannelInactive_chosen:
  3088. if(NULL != pChannel)
  3089. {
  3090. hr = pChannel->PauseNet(TRUE, TRUE);
  3091. }
  3092. break;
  3093. case MIn_tp_vdTmprlSptlTrdOff_chosen:
  3094. {
  3095. DWORD dwTradeoff = MAKELONG(0,
  3096. pParams->pMiscellaneousIndication->type.u.MIn_tp_vdTmprlSptlTrdOff);
  3097. if(!(pChannel = FindChannel(pParams->hChannel)))
  3098. {
  3099. ERRORMESSAGE(("%s, channel not found\r\n", _fx_));
  3100. break;
  3101. }
  3102. // Set the indicated TS value of the channel.
  3103. // This should never occur for send channels.
  3104. //
  3105. hr = pChannel->CtrlChanSetProperty(PROP_TS_TRADEOFF_IND, &dwTradeoff, sizeof(dwTradeoff));
  3106. }
  3107. break;
  3108. // the following are not currently handled
  3109. // case multipointConference_chosen:
  3110. // case cnclMltpntCnfrnc_chosen:
  3111. // case multipointZeroComm_chosen:
  3112. // case cancelMultipointZeroComm_chosen:
  3113. // case mltpntScndryStts_chosen:
  3114. // case cnclMltpntScndryStts_chosen:
  3115. // case vdIndctRdyTActvt_chosen:
  3116. // case videoNotDecodedMBs_chosen:
  3117. }
  3118. }
  3119. HRESULT CH323Ctrl::MiscChannelCommand(
  3120. ICtrlCommChan *pChannel,
  3121. VOID * pCmd)
  3122. {
  3123. #ifdef BETA_2_ASN_PRESENT
  3124. if(m_fAvoidCrashingPDUs)
  3125. return hrSuccess;
  3126. #endif // BETA_2_ASN_PRESENT
  3127. return CC_H245MiscellaneousCommand(m_hCall, pChannel->GetHChannel(),
  3128. (MiscellaneousCommand *)pCmd);
  3129. }
  3130. HRESULT CH323Ctrl::MiscChannelIndication(
  3131. ICtrlCommChan *pChannel,
  3132. VOID * pInd)
  3133. {
  3134. MiscellaneousIndication *pMI = (MiscellaneousIndication *)pInd;
  3135. #ifdef BETA_2_ASN_PRESENT
  3136. if(m_fAvoidCrashingPDUs)
  3137. return hrSuccess;
  3138. #endif
  3139. // Intel decided that they had to wrap two Misc commands with two separate,
  3140. // additional APIs. And it won't allow those to be issued any other way.
  3141. // (it returns an error). Until we fix that, need to catch and reroute those
  3142. // two special ones
  3143. if(pMI->type.choice == logicalChannelActive_chosen)
  3144. {
  3145. return CC_UnMute(pChannel->GetHChannel());
  3146. }
  3147. else if (pMI->type.choice == logicalChannelInactive_chosen )
  3148. {
  3149. return CC_Mute(pChannel->GetHChannel());
  3150. }
  3151. else
  3152. return CC_H245MiscellaneousIndication(m_hCall,pChannel->GetHChannel(),pMI);
  3153. }
  3154. VOID CH323Ctrl::SetRemoteVendorID(PCC_VENDORINFO pVendorInfo)
  3155. {
  3156. if(!pVendorInfo)
  3157. return;
  3158. m_RemoteVendorInfo.bCountryCode = pVendorInfo->bCountryCode;
  3159. m_RemoteVendorInfo.bExtension = pVendorInfo->bExtension;
  3160. m_RemoteVendorInfo.wManufacturerCode = pVendorInfo->wManufacturerCode;
  3161. if(pVendorInfo->pProductNumber
  3162. && pVendorInfo->pProductNumber->wOctetStringLength
  3163. && pVendorInfo->pProductNumber->pOctetString)
  3164. {
  3165. if(m_RemoteVendorInfo.pProductNumber)
  3166. {
  3167. MemFree(m_RemoteVendorInfo.pProductNumber);
  3168. }
  3169. m_RemoteVendorInfo.pProductNumber = (PCC_OCTETSTRING)
  3170. MemAlloc(sizeof(CC_OCTETSTRING)
  3171. + pVendorInfo->pProductNumber->wOctetStringLength);
  3172. if(m_RemoteVendorInfo.pProductNumber)
  3173. {
  3174. m_RemoteVendorInfo.pProductNumber->wOctetStringLength
  3175. = pVendorInfo->pProductNumber->wOctetStringLength;
  3176. m_RemoteVendorInfo.pProductNumber->pOctetString =
  3177. ((BYTE *)m_RemoteVendorInfo.pProductNumber + sizeof(CC_OCTETSTRING));
  3178. memcpy(m_RemoteVendorInfo.pProductNumber->pOctetString,
  3179. pVendorInfo->pProductNumber->pOctetString,
  3180. pVendorInfo->pProductNumber->wOctetStringLength);
  3181. }
  3182. }
  3183. if(pVendorInfo->pVersionNumber)
  3184. {
  3185. if(m_RemoteVendorInfo.pVersionNumber)
  3186. {
  3187. MemFree(m_RemoteVendorInfo.pVersionNumber);
  3188. }
  3189. m_RemoteVendorInfo.pVersionNumber = (PCC_OCTETSTRING)
  3190. MemAlloc(sizeof(CC_OCTETSTRING)
  3191. + pVendorInfo->pVersionNumber->wOctetStringLength);
  3192. if(m_RemoteVendorInfo.pVersionNumber)
  3193. {
  3194. m_RemoteVendorInfo.pVersionNumber->wOctetStringLength
  3195. = pVendorInfo->pVersionNumber->wOctetStringLength;
  3196. m_RemoteVendorInfo.pVersionNumber->pOctetString =
  3197. ((BYTE *)m_RemoteVendorInfo.pVersionNumber + sizeof(CC_OCTETSTRING));
  3198. memcpy(m_RemoteVendorInfo.pVersionNumber->pOctetString,
  3199. pVendorInfo->pVersionNumber->pOctetString,
  3200. pVendorInfo->pVersionNumber->wOctetStringLength);
  3201. }
  3202. }
  3203. #ifdef BETA_2_ASN_PRESENT
  3204. char IntelCrashingID[] = "Intel Internet Video Phone";
  3205. char IntelCrashingVer[] = "1.0";
  3206. m_fAvoidCrashingPDUs = FALSE; // innocent until proven guilty
  3207. if(m_RemoteVendorInfo.bCountryCode == USA_H221_COUNTRY_CODE)
  3208. {
  3209. // then it's possible that it is Intel or Microsoft
  3210. if(m_RemoteVendorInfo.wManufacturerCode == MICROSOFT_H_221_MFG_CODE)
  3211. {
  3212. if((!pVendorInfo->pProductNumber) && (!pVendorInfo->pVersionNumber))
  3213. {
  3214. // safe to assume this is Beta2 or Beta3
  3215. m_fAvoidCrashingPDUs = TRUE;
  3216. }
  3217. else if((pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->wOctetStringLength == 0)
  3218. && (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->wOctetStringLength == 0))
  3219. {
  3220. // safe to assume this is Beta2 or Beta3
  3221. m_fAvoidCrashingPDUs = TRUE;
  3222. }
  3223. }
  3224. else if(m_RemoteVendorInfo.wManufacturerCode == INTEL_H_221_MFG_CODE)
  3225. {
  3226. if(pVendorInfo->pProductNumber
  3227. && pVendorInfo->pVersionNumber
  3228. && pVendorInfo->pProductNumber->wOctetStringLength
  3229. && pVendorInfo->pProductNumber->pOctetString
  3230. && pVendorInfo->pVersionNumber->wOctetStringLength
  3231. && pVendorInfo->pVersionNumber->pOctetString)
  3232. {
  3233. // compare strings, don't care about null terminator
  3234. if((0 == memcmp(pVendorInfo->pProductNumber->pOctetString,
  3235. IntelCrashingID, min(sizeof(IntelCrashingID)-1,pVendorInfo->pProductNumber->wOctetStringLength)))
  3236. && (0 == memcmp(pVendorInfo->pVersionNumber->pOctetString,
  3237. IntelCrashingVer,
  3238. min(sizeof(IntelCrashingVer)-1, pVendorInfo->pVersionNumber->wOctetStringLength)) ))
  3239. {
  3240. m_fAvoidCrashingPDUs = TRUE;
  3241. }
  3242. }
  3243. }
  3244. }
  3245. #endif //BETA_2_ASN_PRESENT
  3246. }
  3247. HRESULT CH323Ctrl::Init(IConfAdvise *pConfAdvise)
  3248. {
  3249. hrLast = hrSuccess;
  3250. if(!(m_pConfAdvise = pConfAdvise))
  3251. {
  3252. hrLast = CCO_E_INVALID_PARAM;
  3253. goto EXIT;
  3254. }
  3255. EXIT:
  3256. return hrLast;
  3257. }
  3258. HRESULT CH323Ctrl::DeInit(IConfAdvise *pConfAdvise)
  3259. {
  3260. hrLast = hrSuccess;
  3261. if(m_pConfAdvise != pConfAdvise)
  3262. {
  3263. hrLast = CCO_E_INVALID_PARAM;
  3264. goto EXIT;
  3265. }
  3266. m_pConfAdvise = NULL;
  3267. EXIT:
  3268. return hrLast;
  3269. }
  3270. BOOL CH323Ctrl::IsAcceptingConference(LPVOID lpvConfID)
  3271. {
  3272. if(memcmp(lpvConfID, &m_ConferenceID, sizeof(m_ConferenceID))==0)
  3273. {
  3274. return TRUE;
  3275. }
  3276. return FALSE;
  3277. }
  3278. HRESULT CH323Ctrl::GetProtocolID(LPGUID lpPID)
  3279. {
  3280. if(!lpPID)
  3281. return CCO_E_INVALID_PARAM;
  3282. *lpPID = m_PID;
  3283. hrLast = hrSuccess;
  3284. return hrLast;
  3285. }
  3286. IH323Endpoint * CH323Ctrl::GetIConnIF()
  3287. {
  3288. if(!m_pConfAdvise)
  3289. return NULL;
  3290. return m_pConfAdvise->GetIConnIF();
  3291. }
  3292. STDMETHODIMP CH323Ctrl::GetVersionInfo(
  3293. PCC_VENDORINFO *ppLocalVendorInfo,
  3294. PCC_VENDORINFO *ppRemoteVendorInfo)
  3295. {
  3296. FX_ENTRY ("CH323Ctrl::GetVersionInfo");
  3297. if(!ppLocalVendorInfo || !ppRemoteVendorInfo)
  3298. {
  3299. return CCO_E_INVALID_PARAM;
  3300. }
  3301. *ppLocalVendorInfo = &m_VendorInfo;
  3302. *ppRemoteVendorInfo = &m_RemoteVendorInfo;
  3303. return hrSuccess;
  3304. }
  3305. CH323Ctrl::CH323Ctrl()
  3306. :m_hListen(0),
  3307. m_hConference(0),
  3308. m_hCall(0),
  3309. m_pRemoteAliases(NULL),
  3310. m_pRemoteAliasItem(NULL),
  3311. pwszPeerDisplayName(NULL),
  3312. pwszPeerAliasName(NULL),
  3313. m_bMultipointController(FALSE),
  3314. m_fLocalT120Cap(TRUE),
  3315. m_fRemoteT120Cap(FALSE),
  3316. hrLast(hrSuccess),
  3317. m_ChanFlags(0),
  3318. m_hCallCompleteCode(0),
  3319. m_pConfAdvise(NULL),
  3320. m_Phase( CCS_Idle ),
  3321. #ifdef BETA_2_ASN_PRESENT
  3322. m_fAvoidCrashingPDUs(FALSE),
  3323. #endif
  3324. uRef(1)
  3325. {
  3326. m_PID = PID_H323;
  3327. ZeroMemory(&m_ConferenceID,sizeof(m_ConferenceID));
  3328. ZeroMemory(&local_sin, sizeof(local_sin));
  3329. ZeroMemory(&remote_sin, sizeof(remote_sin));
  3330. ZeroMemory(&m_RemoteVendorInfo, sizeof(m_RemoteVendorInfo));
  3331. local_sin_len = sizeof(local_sin);
  3332. remote_sin_len = sizeof(remote_sin);
  3333. m_VendorInfo.bCountryCode = USA_H221_COUNTRY_CODE;
  3334. m_VendorInfo.bExtension = USA_H221_COUNTRY_EXTENSION;
  3335. m_VendorInfo.wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  3336. m_VendorInfo.pProductNumber = (PCC_OCTETSTRING)MemAlloc(sizeof(CC_OCTETSTRING)
  3337. + sizeof(DefaultProductID));
  3338. if(m_VendorInfo.pProductNumber)
  3339. {
  3340. m_VendorInfo.pProductNumber->wOctetStringLength = sizeof(DefaultProductID);
  3341. m_VendorInfo.pProductNumber->pOctetString =
  3342. ((BYTE *)m_VendorInfo.pProductNumber + sizeof(CC_OCTETSTRING));
  3343. memcpy(m_VendorInfo.pProductNumber->pOctetString,
  3344. DefaultProductID, sizeof(DefaultProductID));
  3345. }
  3346. m_VendorInfo.pVersionNumber = (PCC_OCTETSTRING)MemAlloc(sizeof(CC_OCTETSTRING)
  3347. + sizeof(DefaultProductVersion));
  3348. if(m_VendorInfo.pVersionNumber)
  3349. {
  3350. m_VendorInfo.pVersionNumber->wOctetStringLength = sizeof(DefaultProductVersion);
  3351. m_VendorInfo.pVersionNumber->pOctetString =
  3352. ((BYTE *)m_VendorInfo.pVersionNumber + sizeof(CC_OCTETSTRING));
  3353. memcpy(m_VendorInfo.pVersionNumber->pOctetString,
  3354. DefaultProductVersion, sizeof(DefaultProductVersion));
  3355. }
  3356. m_NonstandardData.bCountryCode = USA_H221_COUNTRY_CODE;
  3357. m_NonstandardData.bExtension = USA_H221_COUNTRY_EXTENSION;
  3358. m_NonstandardData.wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  3359. m_NonstandardData.sData.pOctetString = NULL;
  3360. m_NonstandardData.sData.wOctetStringLength = 0;
  3361. m_ParticipantList.wLength = 0;
  3362. m_ParticipantList.ParticipantInfoArray = NULL;
  3363. m_ConferenceAttributes.pParticipantList = &m_ParticipantList;
  3364. }
  3365. VOID CH323Ctrl ::ReleaseAllChannels()
  3366. {
  3367. ICtrlCommChan *pChan = NULL;
  3368. if (!m_ChannelList.IsEmpty())
  3369. {
  3370. while (!m_ChannelList.IsEmpty())
  3371. {
  3372. pChan = (ICtrlCommChan *) m_ChannelList.RemoveHead();
  3373. if(pChan)
  3374. {
  3375. pChan->EndControlSession();
  3376. pChan->Release();
  3377. pChan = NULL;
  3378. }
  3379. }
  3380. }
  3381. }
  3382. CH323Ctrl ::~CH323Ctrl()
  3383. {
  3384. Cleanup();
  3385. ReleaseAllChannels();
  3386. if(m_pRemoteAliases)
  3387. FreeTranslatedAliasList(m_pRemoteAliases);
  3388. if(pwszPeerDisplayName)
  3389. MemFree(pwszPeerDisplayName);
  3390. if(pwszPeerAliasName)
  3391. MemFree(pwszPeerAliasName);
  3392. if(m_pRemoteAliasItem)
  3393. MemFree(m_pRemoteAliasItem);
  3394. if(m_NonstandardData.sData.pOctetString)
  3395. MemFree(m_NonstandardData.sData.pOctetString);
  3396. if(m_VendorInfo.pProductNumber)
  3397. MemFree(m_VendorInfo.pProductNumber);
  3398. if(m_VendorInfo.pVersionNumber)
  3399. MemFree(m_VendorInfo.pVersionNumber);
  3400. if(m_RemoteVendorInfo.pProductNumber)
  3401. MemFree(m_RemoteVendorInfo.pProductNumber);
  3402. if(m_RemoteVendorInfo.pVersionNumber)
  3403. MemFree(m_RemoteVendorInfo.pVersionNumber);
  3404. }