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.

933 lines
25 KiB

  1. #ifndef __h323ics_logchan_h
  2. #define __h323ics_logchan_h
  3. // This decides the maximum number of T120 TCP/IP Connections
  4. // to be allowed. We create so many NAT redirects.
  5. #define MAX_T120_TCP_CONNECTIONS_ALLOWED 5
  6. // Logical channel states. These are
  7. // H245 related but there is one per
  8. // logical channel
  9. // NOTE: there is no enum value for the final closed state
  10. // as the logical channel is destroyed when that state is reached
  11. enum LOGICAL_CHANNEL_STATE
  12. {
  13. LC_STATE_NOT_INIT = 0,
  14. LC_STATE_OPEN_RCVD,
  15. LC_STATE_OPEN_ACK_RCVD,
  16. LC_STATE_CLOSE_RCVD,
  17. LC_STATE_OPENED_CLOSE_RCVD
  18. };
  19. // Media Types of the logical channels
  20. enum MEDIA_TYPE
  21. {
  22. MEDIA_TYPE_UNDEFINED = 0,
  23. MEDIA_TYPE_RTP = 0x1000,
  24. MEDIA_TYPE_T120 = 0x2000,
  25. MEDIA_TYPE_AUDIO = MEDIA_TYPE_RTP | 0x1, //0x1001
  26. MEDIA_TYPE_VIDEO = MEDIA_TYPE_RTP | 0x2, //0x1002
  27. MEDIA_TYPE_DATA = MEDIA_TYPE_T120 | 0x1, //0x2000
  28. };
  29. inline BOOL IsMediaTypeRtp(MEDIA_TYPE MediaType)
  30. {
  31. return (MediaType & MEDIA_TYPE_RTP);
  32. }
  33. inline BOOL IsMediaTypeT120(MEDIA_TYPE MediaType)
  34. {
  35. return (MediaType & MEDIA_TYPE_T120);
  36. }
  37. ///////////////////////////////////////////////////////////////////////////////
  38. // //
  39. // Logical Channel //
  40. // //
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // This is an abstract base class which defines the operations
  43. // for different types of logical channels.
  44. // RTP_LOGICAL_CHANNEL and T120_LOGICAL_CHANNEL are derived from
  45. // this class.
  46. // Only OpenLogicalChannel and OpenLogicalChannelAck PDUs need
  47. // to be handled differently for the RTP and T.120 Logical channels
  48. // So all the other methods are defined in this class.
  49. class LOGICAL_CHANNEL :
  50. public TIMER_PROCESSOR
  51. {
  52. public:
  53. inline LOGICAL_CHANNEL();
  54. HRESULT CreateTimer(DWORD TimeoutValue);
  55. // the event manager tells us about timer expiry via this method
  56. virtual void TimerCallback();
  57. virtual HRESULT HandleCloseLogicalChannelPDU(
  58. IN MultimediaSystemControlMessage *pH245pdu
  59. );
  60. // This is a pure virtual function which is different
  61. // for the RTP and T.120 logical channels.
  62. virtual HRESULT ProcessOpenLogicalChannelAckPDU(
  63. IN MultimediaSystemControlMessage *pH245pdu
  64. )= 0;
  65. virtual HRESULT ProcessOpenLogicalChannelRejectPDU(
  66. IN MultimediaSystemControlMessage *pH245pdu
  67. );
  68. virtual HRESULT ProcessCloseLogicalChannelAckPDU(
  69. IN MultimediaSystemControlMessage *pH245pdu
  70. );
  71. // releases any pending associations
  72. virtual ~LOGICAL_CHANNEL();
  73. inline BYTE GetSessionId();
  74. inline WORD GetLogicalChannelNumber();
  75. inline MEDIA_TYPE GetMediaType();
  76. inline LOGICAL_CHANNEL_STATE GetLogicalChannelState();
  77. void IncrementLifetimeCounter (void);
  78. void DecrementLifetimeCounter (void);
  79. protected:
  80. // Initializes member variables
  81. inline void InitLogicalChannel(
  82. IN H245_INFO *pH245Info,
  83. IN MEDIA_TYPE MediaType,
  84. IN WORD LogicalChannelNumber,
  85. IN BYTE SessionId,
  86. IN LOGICAL_CHANNEL_STATE LogicalChannelState
  87. );
  88. // returns a reference to the source H245 info
  89. inline H245_INFO &GetH245Info();
  90. inline CALL_BRIDGE &GetCallBridge();
  91. inline void DeleteAndRemoveSelf();
  92. // the logical channel belongs to this H245 channel
  93. // this supplies the ip addresses needed for NAT redirect
  94. H245_INFO *m_pH245Info;
  95. // handle for any active timers
  96. // TIMER_HANDLE m_TimerHandle;
  97. // state of the logical channel
  98. LOGICAL_CHANNEL_STATE m_LogicalChannelState;
  99. // logical channel number
  100. // cannot be 0 as that is reserved for the h245 channel
  101. WORD m_LogicalChannelNumber;
  102. // The type of the media (currently Audio/Video/Data)
  103. MEDIA_TYPE m_MediaType;
  104. // session id - this is used to associate with a
  105. // logical channel from the other end if any
  106. BYTE m_SessionId;
  107. }; // class LOGICAL_CHANNEL
  108. inline
  109. LOGICAL_CHANNEL::LOGICAL_CHANNEL(
  110. )
  111. {
  112. InitLogicalChannel(NULL, MEDIA_TYPE_UNDEFINED,
  113. 0,0,LC_STATE_NOT_INIT);
  114. }
  115. inline
  116. LOGICAL_CHANNEL::~LOGICAL_CHANNEL(
  117. )
  118. {}
  119. inline void
  120. LOGICAL_CHANNEL::InitLogicalChannel(
  121. IN H245_INFO *pH245Info,
  122. IN MEDIA_TYPE MediaType,
  123. IN WORD LogicalChannelNumber,
  124. IN BYTE SessionId,
  125. IN LOGICAL_CHANNEL_STATE LogicalChannelState
  126. )
  127. {
  128. m_pH245Info = pH245Info;
  129. m_MediaType = MediaType;
  130. m_LogicalChannelNumber = LogicalChannelNumber;
  131. m_SessionId = SessionId;
  132. m_LogicalChannelState = LogicalChannelState;
  133. }
  134. inline BYTE
  135. LOGICAL_CHANNEL::GetSessionId(
  136. )
  137. {
  138. return m_SessionId;
  139. }
  140. inline WORD
  141. LOGICAL_CHANNEL::GetLogicalChannelNumber(
  142. )
  143. {
  144. return m_LogicalChannelNumber;
  145. }
  146. inline MEDIA_TYPE
  147. LOGICAL_CHANNEL::GetMediaType(
  148. )
  149. {
  150. return m_MediaType;
  151. }
  152. inline LOGICAL_CHANNEL_STATE
  153. LOGICAL_CHANNEL::GetLogicalChannelState(
  154. )
  155. {
  156. return m_LogicalChannelState;
  157. }
  158. // returns a reference to the source H245 info
  159. inline H245_INFO &
  160. LOGICAL_CHANNEL::GetH245Info(
  161. )
  162. {
  163. _ASSERTE(NULL != m_pH245Info);
  164. return *m_pH245Info;
  165. }
  166. ///////////////////////////////////////////////////////////////////////////////
  167. // //
  168. // RTP Logical Channel //
  169. // //
  170. ///////////////////////////////////////////////////////////////////////////////
  171. class RTP_LOGICAL_CHANNEL :
  172. public LOGICAL_CHANNEL
  173. {
  174. public:
  175. inline RTP_LOGICAL_CHANNEL();
  176. // all of these are available in the OPEN LOGICAL CHANNEL message
  177. // except the associated logical channel, which if supplied provides
  178. // the member m_Own*RTP/RTCP Ports. If not, these are allocated.
  179. // the association is implied by a matching session id in a logical
  180. // channel in the other call state
  181. // it modifies the RTCP address information in the OLC PDU
  182. // and passes it on to the other H245 instance for forwarding.
  183. HRESULT HandleOpenLogicalChannelPDU(
  184. IN H245_INFO &H245Info,
  185. IN MEDIA_TYPE MediaType,
  186. IN DWORD LocalIPv4Address,
  187. IN DWORD RemoteIPv4Address,
  188. IN DWORD OtherLocalIPv4Address,
  189. IN DWORD OtherRemoteIPv4Address,
  190. IN WORD LogicalChannelNumber,
  191. IN BYTE SessionId,
  192. IN RTP_LOGICAL_CHANNEL *pAssocLogicalChannel,
  193. IN DWORD SourceRTCPIPv4Address,
  194. IN WORD SourceRTCPPort,
  195. IN MultimediaSystemControlMessage *pH245pdu
  196. );
  197. virtual HRESULT ProcessOpenLogicalChannelAckPDU(
  198. IN MultimediaSystemControlMessage *pH245pdu
  199. );
  200. // releases any pending associations
  201. virtual ~RTP_LOGICAL_CHANNEL();
  202. inline DWORD GetSourceRTCPIPv4Address();
  203. inline WORD GetSourceRTCPPort();
  204. inline WORD GetOwnSourceSendRTCPPort();
  205. inline WORD GetOwnSourceRecvRTCPPort();
  206. inline WORD GetOwnSourceRecvRTPPort();
  207. inline WORD GetOwnDestSendRTCPPort();
  208. inline WORD GetOwnDestRecvRTCPPort();
  209. inline WORD GetOwnDestSendRTPPort();
  210. inline DWORD GetDestRTCPIPv4Address();
  211. inline WORD GetDestRTCPPort();
  212. inline DWORD GetDestRTPIPv4Address();
  213. inline WORD GetDestRTPPort();
  214. protected:
  215. // points to the associated logical channel from the other end if any
  216. // non-NULL iff associated
  217. // need to ensure that the AssocLogicalChannel also points
  218. // to this logical channel
  219. // CODEWORK: Do assertion checks for this condition.
  220. RTP_LOGICAL_CHANNEL *m_pAssocLogicalChannel;
  221. // local and remote addresses for the h245 instance this logical
  222. // channel is associated with (source side)
  223. DWORD m_OwnSourceIPv4Address;
  224. DWORD m_SourceIPv4Address;
  225. // local and remote addresses for the other h245 instance
  226. // (dest side)
  227. DWORD m_OwnDestIPv4Address;
  228. DWORD m_DestIPv4Address;
  229. // these ports are negotiated in h245 OpenLogicalChannel and
  230. // OpenLogicalChannelAck. They are given to NAT for redirecting
  231. // RTP and RTCP traffic
  232. // while the RTP packets flow only one way (source->dest), RTCP
  233. // packets flow both ways
  234. // we only know the source's receive RTCP port. the send port
  235. // is not known
  236. DWORD m_SourceRTCPIPv4Address;
  237. WORD m_SourceRTCPPort;
  238. // these are the send/recv RTP/RTCP ports on the interface that
  239. // communicates with the source. since we don't deal with the
  240. // reverse RTP stream, we don't need a send RTP port
  241. WORD m_OwnSourceSendRTCPPort;
  242. WORD m_OwnSourceRecvRTCPPort;
  243. WORD m_OwnSourceRecvRTPPort;
  244. // these are the send/recv RTP/RTCP ports on the interface that
  245. // communicates with the source. since we don't deal with the
  246. // reverse RTP stream, we don't need a recv RTP port
  247. WORD m_OwnDestSendRTCPPort;
  248. WORD m_OwnDestSendRTPPort;
  249. WORD m_OwnDestRecvRTCPPort;
  250. WORD m_OwnAssocLCRecvRTPPort; // this is used to allocate consecutive
  251. // ports for RTP/RTCP.
  252. WORD m_OwnAssocLCSendRTPPort;
  253. // destination's RTCP ip address, port
  254. DWORD m_DestRTCPIPv4Address;
  255. WORD m_DestRTCPPort;
  256. // destination's RTP ip address, port
  257. DWORD m_DestRTPIPv4Address;
  258. WORD m_DestRTPPort;
  259. // SetAssociationRef, ResetAssociationRef methods can be accessed
  260. // by other LOGICAL_CHANNEL instances but not by other instances of
  261. // classes that are not derived from LOGICAL_CHANNEL
  262. inline void SetAssociationRef(
  263. IN RTP_LOGICAL_CHANNEL &LogicalChannel
  264. );
  265. inline void ResetAssociationRef();
  266. inline void ReleaseAssociationAndPorts();
  267. private:
  268. // set the RTP and RTCP ports. if there is an associated channel,
  269. // we must share the RTCP ports
  270. HRESULT SetPorts();
  271. HRESULT CheckOpenLogicalChannelAckPDU(
  272. IN MultimediaSystemControlMessage &H245pdu,
  273. OUT BYTE &SessionId,
  274. OUT DWORD &DestRTPIPv4Address,
  275. OUT WORD &DestRTPPort,
  276. OUT DWORD &DestRTCPIPv4Address,
  277. OUT WORD &DestRTCPPort
  278. );
  279. // opens the forward RTP, forward RTCP and reverse RTCP streams
  280. HRESULT OpenNATMappings();
  281. // closes any NAT mappings
  282. void CloseNATMappings();
  283. };
  284. inline
  285. RTP_LOGICAL_CHANNEL::RTP_LOGICAL_CHANNEL(
  286. )
  287. : m_pAssocLogicalChannel(NULL),
  288. //m_TimerHandle(NULL),
  289. m_OwnSourceIPv4Address(0),
  290. m_SourceIPv4Address(0),
  291. m_OwnDestIPv4Address(0),
  292. m_DestIPv4Address(0),
  293. m_SourceRTCPIPv4Address(0),
  294. m_SourceRTCPPort(0),
  295. m_OwnSourceSendRTCPPort(0),
  296. m_OwnSourceRecvRTCPPort(0),
  297. m_OwnSourceRecvRTPPort(0),
  298. m_OwnDestSendRTCPPort(0),
  299. m_OwnDestRecvRTCPPort(0),
  300. m_OwnDestSendRTPPort(0),
  301. m_DestRTCPIPv4Address(0),
  302. m_DestRTCPPort(0),
  303. m_DestRTPIPv4Address(0),
  304. m_DestRTPPort(0)
  305. {
  306. InitLogicalChannel(NULL, MEDIA_TYPE_UNDEFINED,
  307. 0,0,LC_STATE_NOT_INIT);
  308. }
  309. inline void
  310. RTP_LOGICAL_CHANNEL::SetAssociationRef(
  311. IN RTP_LOGICAL_CHANNEL &LogicalChannel
  312. )
  313. {
  314. // if the source or dest terminal is generating two logical
  315. // channels (in the same direction) with the same session id, we'll
  316. // find a prior logical channel in the array with the same session id
  317. // and thus never reach here
  318. _ASSERTE(NULL == m_pAssocLogicalChannel);
  319. m_pAssocLogicalChannel = &LogicalChannel;
  320. }
  321. inline void
  322. RTP_LOGICAL_CHANNEL::ResetAssociationRef(
  323. )
  324. {
  325. _ASSERTE(NULL != m_pAssocLogicalChannel);
  326. m_pAssocLogicalChannel = NULL;
  327. // we, now, own the RTP/RTCP ports that were being shared so far
  328. }
  329. inline DWORD
  330. RTP_LOGICAL_CHANNEL::GetSourceRTCPIPv4Address(
  331. )
  332. {
  333. return m_SourceRTCPIPv4Address;
  334. }
  335. inline WORD
  336. RTP_LOGICAL_CHANNEL::GetSourceRTCPPort(
  337. )
  338. {
  339. return m_SourceRTCPPort;
  340. }
  341. inline WORD
  342. RTP_LOGICAL_CHANNEL::GetOwnSourceSendRTCPPort(
  343. )
  344. {
  345. return m_OwnSourceSendRTCPPort;
  346. }
  347. inline WORD
  348. RTP_LOGICAL_CHANNEL::GetOwnSourceRecvRTCPPort(
  349. )
  350. {
  351. return m_OwnSourceRecvRTCPPort;
  352. }
  353. inline WORD
  354. RTP_LOGICAL_CHANNEL::GetOwnSourceRecvRTPPort(
  355. )
  356. {
  357. return m_OwnSourceRecvRTPPort;
  358. }
  359. inline WORD
  360. RTP_LOGICAL_CHANNEL::GetOwnDestSendRTCPPort(
  361. )
  362. {
  363. return m_OwnDestSendRTCPPort;
  364. }
  365. inline WORD
  366. RTP_LOGICAL_CHANNEL::GetOwnDestRecvRTCPPort(
  367. )
  368. {
  369. return m_OwnDestRecvRTCPPort;
  370. }
  371. inline WORD
  372. RTP_LOGICAL_CHANNEL::GetOwnDestSendRTPPort(
  373. )
  374. {
  375. return m_OwnDestSendRTPPort;
  376. }
  377. inline DWORD
  378. RTP_LOGICAL_CHANNEL::GetDestRTCPIPv4Address(
  379. )
  380. {
  381. return m_DestRTCPIPv4Address;
  382. }
  383. inline WORD
  384. RTP_LOGICAL_CHANNEL::GetDestRTCPPort(
  385. )
  386. {
  387. return m_DestRTCPPort;
  388. }
  389. inline DWORD
  390. RTP_LOGICAL_CHANNEL::GetDestRTPIPv4Address(
  391. )
  392. {
  393. return m_DestRTPIPv4Address;
  394. }
  395. inline WORD
  396. RTP_LOGICAL_CHANNEL::GetDestRTPPort(
  397. )
  398. {
  399. return m_DestRTPPort;
  400. }
  401. ///////////////////////////////////////////////////////////////////////////////
  402. // //
  403. // T.120 Logical Channel //
  404. // //
  405. ///////////////////////////////////////////////////////////////////////////////
  406. class T120_LOGICAL_CHANNEL :
  407. public LOGICAL_CHANNEL
  408. {
  409. public:
  410. inline T120_LOGICAL_CHANNEL();
  411. // all of these are available in the OPEN LOGICAL CHANNEL message
  412. // it modifies the OLC PDU and passes it on to the other H245
  413. // instance for forwarding ???
  414. HRESULT HandleOpenLogicalChannelPDU(
  415. IN H245_INFO &H245Info,
  416. IN MEDIA_TYPE MediaType,
  417. IN WORD LogicalChannelNumber,
  418. IN BYTE SessionId,
  419. IN DWORD T120ConnectToIPAddr,
  420. IN WORD T120ConnectToPort,
  421. IN MultimediaSystemControlMessage *pH245pdu
  422. );
  423. virtual HRESULT ProcessOpenLogicalChannelAckPDU(
  424. IN MultimediaSystemControlMessage *pH245pdu
  425. );
  426. // releases any pending associations
  427. virtual ~T120_LOGICAL_CHANNEL();
  428. protected:
  429. // We store all the address and port information in host order.
  430. // We need to convert them to network order before we pass them
  431. // to the NAT functions.
  432. // These are the IP Address and port the T.120 end point is listening
  433. // on for the T.120 connection. We need to connect to this address.
  434. DWORD m_T120ConnectToIPAddr;
  435. WORD m_T120ConnectToPort;
  436. // These are the IP Address and port we will be listening on.
  437. // We send this information in the OLC or OLCAck PDU and the T.120
  438. // end point will connect to this address.
  439. DWORD m_T120ListenOnIPAddr;
  440. WORD m_T120ListenOnPort;
  441. // These are the IP Address and port we will be using in the NAT
  442. // redirect as the new source address of the TCP connection.
  443. // Once the remote T.120 end point receives a TCP conection,
  444. // it thinks that the connection is "from" this address.
  445. // CODEWORK: Any better names ??
  446. DWORD m_T120ConnectFromIPAddr;
  447. // Note that we do not know the actual source address and port
  448. // from which the T.120 endpoint connects. This address is only
  449. // established when the T.120 endpoint actually calls connect.
  450. // We pass 0 (wild card) for these fields in the NAT redirect.
  451. HANDLE m_DynamicRedirectHandle;
  452. private:
  453. // Allocate m_T120ListenOnPort and m_T120ConnectFromPorts
  454. HRESULT SetPorts(
  455. DWORD T120ConnectToIPAddr,
  456. WORD T120ConnectToPort,
  457. DWORD T120ListenOnIPAddr,
  458. DWORD T120ConnectFromIPAddr
  459. );
  460. BOOL IsT120RedirectNeeded(
  461. DWORD T120ConnectToIPAddr,
  462. DWORD T120ListenOnIPAddr,
  463. DWORD T120ListenFromIPAddr);
  464. // Free m_T120ListenOnPort and m_T120ConnectFromPorts
  465. // if they have been allocated.
  466. HRESULT FreePorts();
  467. // opens the bidirectional NAT redirect for the TCP stream
  468. HRESULT CreateNatRedirect();
  469. // closes any NAT redirect
  470. void CancelNatRedirect();
  471. HRESULT CheckOpenLogicalChannelAckPDU(
  472. IN OpenLogicalChannelAck &OlcPDU,
  473. OUT DWORD &T120ConnectToIPAddr,
  474. OUT WORD &T120ConnectToPort
  475. );
  476. };
  477. inline
  478. T120_LOGICAL_CHANNEL::T120_LOGICAL_CHANNEL(
  479. )
  480. : m_T120ConnectToIPAddr(INADDR_NONE),
  481. m_T120ConnectToPort(0),
  482. m_T120ListenOnIPAddr(INADDR_NONE),
  483. m_T120ListenOnPort(0),
  484. m_T120ConnectFromIPAddr(INADDR_NONE),
  485. m_DynamicRedirectHandle(INVALID_HANDLE_VALUE)
  486. {
  487. InitLogicalChannel(NULL,MEDIA_TYPE_UNDEFINED,
  488. 0,0,LC_STATE_NOT_INIT);
  489. }
  490. // expandable array of pointer values
  491. template <class T>
  492. class DYNAMIC_POINTER_ARRAY
  493. {
  494. public:
  495. // number of blocks allocated for a new addition
  496. // when the array becomes full
  497. #define DEFAULT_BLOCK_SIZE 4
  498. inline DYNAMIC_POINTER_ARRAY();
  499. // assumption: other member variables are all 0/NULL
  500. inline void Init(
  501. IN DWORD BlockSize = DEFAULT_BLOCK_SIZE
  502. );
  503. virtual ~DYNAMIC_POINTER_ARRAY();
  504. inline T **GetData()
  505. {
  506. return m_pData;
  507. }
  508. inline DWORD GetSize()
  509. {
  510. return m_NumElements;
  511. }
  512. DWORD Find(
  513. IN T& Val
  514. ) const;
  515. HRESULT Add(
  516. IN T &NewVal
  517. );
  518. inline T *Get(
  519. IN DWORD Index
  520. );
  521. inline HRESULT RemoveAt(
  522. IN DWORD Index
  523. );
  524. inline HRESULT Remove(
  525. IN T &Val
  526. );
  527. protected:
  528. T **m_pData;
  529. DWORD m_NumElements;
  530. DWORD m_AllocElements;
  531. DWORD m_BlockSize;
  532. };
  533. template <class T>
  534. inline
  535. DYNAMIC_POINTER_ARRAY<T>::DYNAMIC_POINTER_ARRAY(
  536. )
  537. : m_pData(NULL),
  538. m_NumElements(0),
  539. m_AllocElements(0),
  540. m_BlockSize(0)
  541. {
  542. }
  543. template <class T>
  544. inline void
  545. DYNAMIC_POINTER_ARRAY<T>::Init(
  546. IN DWORD BlockSize /* = DEFAULT_BLOCK_SIZE */
  547. )
  548. {
  549. _ASSERTE(NULL == m_pData);
  550. if (0 != BlockSize)
  551. {
  552. m_BlockSize = BlockSize;
  553. }
  554. else
  555. {
  556. m_BlockSize = DEFAULT_BLOCK_SIZE;
  557. }
  558. }
  559. // NOTE: uses realloc and free to grow/manage the array of pointers.
  560. // This is better than new/delete as the additional memory is allocated
  561. // in-place (i.e. the array ptr remains same) eliminating the need to copy
  562. // memory from the old block to the new block and also reduces
  563. // heap fragmentation
  564. template <class T>
  565. HRESULT
  566. DYNAMIC_POINTER_ARRAY<T>::Add(
  567. IN T &NewVal
  568. )
  569. {
  570. if(m_NumElements == m_AllocElements)
  571. {
  572. typedef T *T_PTR;
  573. T** ppT = NULL;
  574. DWORD NewAllocElements = m_NumElements + m_BlockSize;
  575. ppT = (class LOGICAL_CHANNEL **)
  576. realloc(m_pData, NewAllocElements * sizeof(T_PTR));
  577. if(NULL == ppT)
  578. {
  579. return E_OUTOFMEMORY;
  580. }
  581. // set the m_pData member to the newly allocated memory
  582. m_pData = ppT;
  583. m_AllocElements = NewAllocElements;
  584. }
  585. m_pData[m_NumElements] = &NewVal;
  586. m_NumElements++;
  587. return S_OK;
  588. }
  589. template <class T>
  590. inline T *
  591. DYNAMIC_POINTER_ARRAY<T>::Get(
  592. IN DWORD Index
  593. )
  594. {
  595. _ASSERTE(Index < m_NumElements);
  596. if (Index < m_NumElements)
  597. {
  598. return m_pData[Index];
  599. }
  600. else
  601. {
  602. return NULL;
  603. }
  604. }
  605. template <class T>
  606. inline HRESULT
  607. DYNAMIC_POINTER_ARRAY<T>::RemoveAt(
  608. IN DWORD Index
  609. )
  610. {
  611. _ASSERTE(Index < m_NumElements);
  612. if (Index >= m_NumElements)
  613. {
  614. return E_FAIL;
  615. }
  616. // move all elements (to the right), left by one block
  617. memmove(
  618. (void*)&m_pData[Index],
  619. (void*)&m_pData[Index + 1],
  620. (m_NumElements - (Index + 1)) * sizeof(T *)
  621. );
  622. m_NumElements--;
  623. return S_OK;
  624. }
  625. template <class T>
  626. inline HRESULT
  627. DYNAMIC_POINTER_ARRAY<T>::Remove(
  628. IN T &Val
  629. )
  630. {
  631. DWORD Index = Find(Val);
  632. if(Index >= m_NumElements)
  633. {
  634. return E_FAIL;
  635. }
  636. return RemoveAt(Index);
  637. }
  638. template <class T>
  639. DWORD
  640. DYNAMIC_POINTER_ARRAY<T>::Find(
  641. IN T& Val
  642. ) const
  643. {
  644. // search for an array element thats same as the passed
  645. // in value
  646. for(DWORD Index = 0; Index < m_NumElements; Index++)
  647. {
  648. if(m_pData[(DWORD)Index] == &Val)
  649. {
  650. return Index;
  651. }
  652. }
  653. return m_NumElements; // not found
  654. }
  655. template <class T>
  656. /* virtual */
  657. DYNAMIC_POINTER_ARRAY<T>::~DYNAMIC_POINTER_ARRAY(
  658. )
  659. {
  660. if (NULL != m_pData)
  661. {
  662. // delete each of the elements in the array
  663. for(DWORD Index = 0; Index < m_NumElements; Index++)
  664. {
  665. _ASSERTE(NULL != m_pData[Index]);
  666. delete m_pData[Index];
  667. }
  668. // free the array memory block
  669. free(m_pData);
  670. }
  671. }
  672. ///////////////////////////////////////////////////////////////////////////////
  673. // //
  674. // Logical Channel Array //
  675. // //
  676. ///////////////////////////////////////////////////////////////////////////////
  677. class LOGICAL_CHANNEL_ARRAY :
  678. public DYNAMIC_POINTER_ARRAY<LOGICAL_CHANNEL>
  679. {
  680. typedef DYNAMIC_POINTER_ARRAY<LOGICAL_CHANNEL> BASE_CLASS;
  681. public:
  682. inline LOGICAL_CHANNEL *FindByLogicalChannelNum(
  683. IN WORD LogicalChannelNumber
  684. );
  685. inline LOGICAL_CHANNEL *FindBySessionId(
  686. IN BYTE SessionId
  687. );
  688. inline void CancelAllTimers();
  689. };
  690. inline LOGICAL_CHANNEL *
  691. LOGICAL_CHANNEL_ARRAY::FindByLogicalChannelNum(
  692. IN WORD LogicalChannelNumber
  693. )
  694. {
  695. // check the logical channel number for each element in the array
  696. // search from back
  697. if (0 == m_NumElements) return NULL;
  698. for(DWORD Index = m_NumElements-1; Index < m_NumElements; Index--)
  699. {
  700. _ASSERTE(NULL != m_pData[Index]);
  701. if (m_pData[Index]->GetLogicalChannelNumber()
  702. == LogicalChannelNumber)
  703. {
  704. return m_pData[Index];
  705. }
  706. }
  707. // nothing found
  708. return NULL;
  709. }
  710. // SessionID is meaningful only for RTP logical channels.
  711. // We look for only RTP logical channels.
  712. inline LOGICAL_CHANNEL *
  713. LOGICAL_CHANNEL_ARRAY::FindBySessionId(
  714. IN BYTE SessionId
  715. )
  716. {
  717. // 0 is used by a slave terminal to request a session id from the master
  718. // hence, we shouldn't be searching for a match with 0
  719. _ASSERTE(0 != SessionId);
  720. // check the session for each element in the array
  721. // search from back
  722. if (0 == m_NumElements) return NULL;
  723. for(DWORD Index = m_NumElements-1; Index < m_NumElements; Index--)
  724. {
  725. _ASSERTE(NULL != m_pData[Index]);
  726. // SessionID is meaningful only for RTP logical channels.
  727. // We look for only RTP logical channels.
  728. if (IsMediaTypeRtp(m_pData[Index]->GetMediaType()) &&
  729. m_pData[Index]->GetSessionId() == SessionId)
  730. {
  731. return m_pData[Index];
  732. }
  733. }
  734. // nothing found
  735. return NULL;
  736. }
  737. inline void LOGICAL_CHANNEL_ARRAY::CancelAllTimers (void)
  738. {
  739. for (DWORD Index = 0; Index < m_NumElements; Index++)
  740. {
  741. m_pData[(DWORD)Index]->TimprocCancelTimer();
  742. }
  743. }
  744. #endif // __h323ics_logchan_h