mirror of https://github.com/tongzx/nt5src
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.
1457 lines
28 KiB
1457 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1998 - 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
cbridge.cpp
|
|
|
|
Abstract:
|
|
|
|
Contains the call bridge class declaration.
|
|
Associated Q931 and H245 protocol stack related classes
|
|
and constants are also declared here.
|
|
|
|
Revision History:
|
|
1. created
|
|
Byrisetty Rajeev (rajeevb) 12-Jun-1998
|
|
2. moved several inline functions to q931.cpp, h245.cpp
|
|
(rajeevb, 21-Aug-1998)
|
|
--*/
|
|
|
|
#ifndef __h323ics_call_bridge_h
|
|
#define __h323ics_call_bridge_h
|
|
|
|
/*---------------------------------------------------
|
|
DESIGN OVERVIEW:
|
|
|
|
The CALL_BRIDGE completely describes an H.323 call being proxied. The
|
|
proxy receives a call from the source and then originates a call
|
|
to the destination. Each of these calls is represented by an H323_STATE.
|
|
PDUs received on one call are processed and passed on to the other call.
|
|
|
|
A source leads an H.323 call with Q.931. The SETUP PDU contains info for
|
|
the proxy to locate the destination. The two end points exchange their
|
|
H.245 channel addresses at this stage. This portion of the call is
|
|
encapsulated in Q931_INFO. *The proxy must replace any end-point address
|
|
and port with its own address and port to protect internal corporate
|
|
addresses and retain control of the multi-layered H.323 call setup*.
|
|
|
|
The H.245 channel is used to exchange end-point capabilities. This
|
|
information is of no significance today (in future, security exchanges
|
|
etc. may be done). H245_INFO represents an H.245 channel end-point. We
|
|
merely pass on the source/destination PDUs.
|
|
|
|
The H.245 channel is used to maintain (open, close) logical channels.
|
|
The logical channel messages exchange end-point address and port to
|
|
send audio/video media to. These addresses/ports are replaced with the
|
|
proxy's address/ports. Each logical channel is represented by a
|
|
LOGICAL_CHANNEL instance. An H245_INFO instance contains an array of
|
|
LOGICAL_CHANNELs which were originated from the corresponding client
|
|
end-point. Hence, all of the logical channel related state is contained
|
|
in a single LOGICAL_CHANNEL instance (unlike two instances for the
|
|
Q931_INFO and H245_INFO which have a SOURCE and DEST instance).
|
|
|
|
Audio/video media are sent in RTP streams (with RTCP for control info).
|
|
The proxy uses NAT to forward these packets after replacing the
|
|
source and destination address/port.
|
|
|
|
|
|
CLASS HIERARCHY :
|
|
|
|
The Q931_INFO and H323_INFO classes need to make overlapped calls to
|
|
accept connections, send and receive data. The OVERLAPPED_PROCESSOR
|
|
provides call back methods to the event manager and completely
|
|
encapsulates the socket representing a connection. Both Q931_INFO and
|
|
H323_INFO are derived from it and pass themselves as OVERLAPPED_PROCESSOR
|
|
to the event manager while registering callbacks.
|
|
|
|
When making an overlapped call, a context is also passed in. This context
|
|
enables the caller to retrieve relevant information when the corresponding
|
|
callback is received. The EVENT_MANAGER_CONTEXT provides the base class
|
|
abstraction for the callback context. Q931/H245 Source/Dest instances
|
|
derive their own contexts from this base class (for storing their state).
|
|
|
|
The Q931_INFO and H323_INFO classes need to create and cancel timers. The
|
|
TIMER_PROCESSOR provides call back methods to the event manager and
|
|
helper methods for this.
|
|
|
|
Both SOURCE and DEST versions are derived from the base classes for
|
|
Q931_INFO, H245_INFO and H323_STATE. While the states and transitions
|
|
for H.245 (for the proxy) are more or less symmetric, those for Q.931
|
|
are quite different. A SOURCE_H323_STATE contains a SOURCE_Q931_INFO and
|
|
a SOURCE_H245_INFO (similarly for the DEST version).
|
|
|
|
A CALL_BRIDGE contains a SOURCE_H323_STATE and a DEST_H323_STATE. Hence
|
|
all the Q931, H245 and generic data is stored in a single memory block for
|
|
the CALL_BRIDGE. Additional memory is needed for the LOGICAL_CHANNEL_ARRAY
|
|
(one per H245_INFO instance) and each of the LOGICAL_CHANNEL instances. There
|
|
might be a better way to allocate this memory to reduce memory allocations/freeing.
|
|
|
|
A single critical section protects all accesses to a CALL_BRIDGE and
|
|
is acquired inside the CALL_BRIDGE method being called. The CALL_BRIDGE
|
|
also destroys itself when it is appropriate and releases the critical
|
|
section before doing so (The CALL_BRIDGE cannot get called at such a point)
|
|
|
|
SCALABILITY ISSUES :
|
|
|
|
1. We currently use a single critical section per instance of the CALL_BRIDGE.
|
|
This is clearly not scalable to a large number of connections. We plan
|
|
to use dynamic critical sections for this. This involves using a pool of
|
|
critical sections and a critical section from the pool is assigned to
|
|
a CALL_BRIDGE instance dynamically.
|
|
|
|
2. We currently need 4 ports (RTP/RTCP send/receive) for each of the two
|
|
calls being bridged in a CALL_BRIDGE for a total of 8 ports per
|
|
proxied call. This also means that we would need a socket for each of
|
|
the ports to actually reserve the port. The following approaches will
|
|
make this scalable -
|
|
* AjayCh is talking with NKSrin for an IOCTL to the TCP/IP stack for
|
|
reserving a pool of ports at a time (just like memory). This would
|
|
thus preclude any need for keeeping a socket open just for reserving
|
|
a port and reduce the number of calls needed to do so.
|
|
* The TCP/IP stack treats ports as global objects and would make the
|
|
reserved port unavailable on ALL interfaces. However, a port can be
|
|
reused several times as long as it satisfies the unique 5tuple
|
|
requirement for sockets
|
|
(protocol, src addr, src port, dest addr, dest port). We can reuse
|
|
the allocated port in the following ways -
|
|
** for each interface on the machine.
|
|
** for each different remote end-point address/port pairs
|
|
---------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------
|
|
NOTES:
|
|
|
|
1. Typically, constructors are avoided and replaced by Init fns as
|
|
they can return error codes.
|
|
|
|
2. The attempt is to convert all error codes to HRESULTs as early in
|
|
the execution as possible.
|
|
|
|
3. Separate heaps are used for different classes. This reduces heap
|
|
contention as well as fragmentation. This is done by over-riding
|
|
new/delete.
|
|
|
|
4. inline fns are used where
|
|
- a virtual fn is not needed
|
|
- amount of code is small AND/OR
|
|
- number of calls to the fn is few (1-2).
|
|
|
|
since some inline fn definitions involve calling other inline
|
|
functions, there are several dependencies among the classes
|
|
declared below. This forces declaration of all these classes
|
|
in a single header file.
|
|
|
|
5. We need to count all outstanding overlapped calls and make sure
|
|
there are none before destroying a CALL_BRIDGE instance (to avoid
|
|
avs when the event manager calls back and to release the associated
|
|
contexts). We try to keep track of all this inside the CALL_BRIDGE
|
|
centrally.
|
|
|
|
6. We try to maintain the abstraction of two separate calls being bridged
|
|
as far as possible. As a convention, methods processing PDUs/messages
|
|
directly received from a socket start with "Handle". These methods pass
|
|
on the received PDU/message to the "other" H245 or Q931 instance (for the
|
|
bridged call). The "other" methods which process these start with
|
|
"Process". They decide whether or not the PDU/message must be sent to
|
|
the other end-point.
|
|
|
|
7. NAT has problems with unidirectional redirects. If a unidirectional
|
|
redirect X is setup and we later try to setup a unidirectional redirect
|
|
Y in the reverse direction that shares all the parameters of X, NAT
|
|
exhibits undefined behaviour. This is solved by the following steps -
|
|
* We only setup unidirectional redirects. Thus, RTCP requires 2
|
|
separate redirects.
|
|
* Logical channel signaling only exchanges addresses/ports to receive
|
|
media on. We exploit that by using different ports for sending and
|
|
receiving media.
|
|
|
|
8. We have tried to restrict the use of virtual functions and use inline
|
|
functions wherever possible. Proliferation of short virtual fns can
|
|
result in performance problems.
|
|
|
|
9. Overlapped callbacks pass in H245, Q931 pdus that were read along
|
|
with the corresponding context. We follow a flexible convention for
|
|
freeing them -
|
|
* if the callback or any called method frees them or reuses
|
|
them for sending out the opposite end, it sets them to null.
|
|
* if not set to null on return, the event manager which called the
|
|
callback frees these.
|
|
|
|
10. Currently all state transitions are in code (ex.
|
|
if current state == b1, current state = b2 etc.). Its usually
|
|
better to do this in data (ex. an array {current state, new state}).
|
|
However, I haven't been able to figure out an appropriate model for
|
|
this so far.
|
|
|
|
11. Commenting doesn't have the NT standard blocks explaining each fn,
|
|
parameters, return code etc. I have instead, written a small block of
|
|
comments at the top of the function when appropriate. I have also tried
|
|
to comment logical blocks of code.
|
|
---------------------------------------------------*/
|
|
|
|
#include "sockinfo.h"
|
|
#include "q931info.h"
|
|
#include "logchan.h"
|
|
#include "h245info.h"
|
|
#include "ipnatapi.h"
|
|
|
|
// Call state description - one side of a call
|
|
class H323_STATE
|
|
{
|
|
public:
|
|
|
|
inline
|
|
H323_STATE (
|
|
void
|
|
);
|
|
|
|
// initialize when a tcp connection is established on a listening
|
|
// interface
|
|
inline
|
|
void
|
|
Init (
|
|
IN CALL_BRIDGE &CallBridge,
|
|
IN Q931_INFO &Q931Info,
|
|
IN H245_INFO &H245Info,
|
|
IN BOOL fIsSource // source call state iff TRUE
|
|
);
|
|
|
|
inline
|
|
CALL_BRIDGE &
|
|
GetCallBridge (
|
|
void
|
|
);
|
|
|
|
inline
|
|
BOOL
|
|
IsSourceCall (
|
|
void
|
|
);
|
|
|
|
inline
|
|
Q931_INFO &
|
|
GetQ931Info (
|
|
void
|
|
);
|
|
|
|
inline
|
|
H245_INFO &
|
|
GetH245Info (
|
|
void
|
|
);
|
|
|
|
inline
|
|
H323_STATE &
|
|
GetOtherH323State (
|
|
void
|
|
);
|
|
|
|
protected:
|
|
|
|
// it belongs to this call bridge
|
|
CALL_BRIDGE *m_pCallBridge;
|
|
|
|
// TRUE iff its the source call state
|
|
BOOL m_fIsSourceCall;
|
|
|
|
// contains the Q931 tcp info, timeout, remote end info
|
|
Q931_INFO *m_pQ931Info;
|
|
|
|
// contains the H.245 tcp info, timeout, remote end info
|
|
H245_INFO *m_pH245Info;
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Constructor for H323_STATE class
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
inline
|
|
H323_STATE::H323_STATE (
|
|
void
|
|
)
|
|
: m_pCallBridge (
|
|
NULL
|
|
),
|
|
m_fIsSourceCall (
|
|
FALSE
|
|
),
|
|
m_pQ931Info(
|
|
NULL
|
|
),
|
|
m_pH245Info(
|
|
NULL)
|
|
{
|
|
|
|
} // H323_STATE::H323_STATE
|
|
|
|
|
|
inline
|
|
void
|
|
H323_STATE::Init (
|
|
IN CALL_BRIDGE &CallBridge,
|
|
IN Q931_INFO &Q931Info,
|
|
IN H245_INFO &H245Info,
|
|
IN BOOL fIsSource
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Initializes an instance of H323_STATE class
|
|
|
|
Arguments:
|
|
CallBridge -- parent call-bridge
|
|
Q931Info -- contained Q931 information
|
|
H245Info -- contained H245 information
|
|
fIsSource -- TRUE if this is source call state, FALSE otherwise
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
_ASSERTE(NULL == m_pCallBridge);
|
|
_ASSERTE(NULL == m_pQ931Info);
|
|
_ASSERTE(NULL == m_pH245Info);
|
|
|
|
m_pCallBridge = &CallBridge;
|
|
m_pQ931Info = &Q931Info;
|
|
m_pH245Info = &H245Info;
|
|
m_fIsSourceCall = fIsSource;
|
|
} // H323_STATE::Init
|
|
|
|
|
|
inline
|
|
CALL_BRIDGE &
|
|
H323_STATE::GetCallBridge (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the parent call-bridge
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
_ASSERTE(NULL != m_pCallBridge);
|
|
|
|
return *m_pCallBridge;
|
|
} // H323_STATE::GetCallBridge
|
|
|
|
inline
|
|
BOOL
|
|
H323_STATE::IsSourceCall (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Indication of whether this is a source
|
|
call state, or destination call state
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_fIsSourceCall;
|
|
} // H323_STATE::IsSourceCall
|
|
|
|
inline
|
|
Q931_INFO &
|
|
H323_STATE::GetQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the contained Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
_ASSERTE(NULL != m_pQ931Info);
|
|
|
|
return *m_pQ931Info;
|
|
} // H323_STATE::GetQ931Info
|
|
|
|
inline
|
|
H245_INFO &
|
|
H323_STATE::GetH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the contained H.245 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
_ASSERTE(NULL != m_pH245Info);
|
|
return *m_pH245Info;
|
|
} // H323_STATE::GetH245Info
|
|
|
|
|
|
// Source call state description - one side of a call
|
|
class SOURCE_H323_STATE :
|
|
public H323_STATE
|
|
{
|
|
public:
|
|
|
|
// initialize when a tcp connection is established on a listening
|
|
// interface
|
|
inline
|
|
void
|
|
Init (
|
|
IN CALL_BRIDGE &CallBridge
|
|
);
|
|
|
|
inline
|
|
SOURCE_Q931_INFO &
|
|
GetSourceQ931Info (
|
|
void
|
|
);
|
|
|
|
inline
|
|
SOURCE_H245_INFO &
|
|
GetSourceH245Info (
|
|
void
|
|
);
|
|
|
|
inline
|
|
DEST_H323_STATE &
|
|
GetDestH323State (
|
|
void
|
|
);
|
|
|
|
protected:
|
|
|
|
// contains the source Q931 tcp info, timeout, remote end info
|
|
SOURCE_Q931_INFO m_SourceQ931Info;
|
|
|
|
// contains the H.245 tcp info, timeout, remote end info
|
|
SOURCE_H245_INFO m_SourceH245Info;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline
|
|
void
|
|
SOURCE_H323_STATE::Init (
|
|
IN CALL_BRIDGE &CallBridge
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Initialize H323 state when a tcp connection is established
|
|
on a listening interface
|
|
|
|
Arguments:
|
|
CallBridge -- "parent" call-bridge
|
|
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
m_SourceQ931Info.Init(*this);
|
|
|
|
m_SourceH245Info.Init(*this);
|
|
|
|
H323_STATE::Init(
|
|
CallBridge,
|
|
m_SourceQ931Info,
|
|
m_SourceH245Info,
|
|
TRUE
|
|
);
|
|
} // SOURCE_H323_STATE::Init
|
|
|
|
|
|
inline
|
|
SOURCE_Q931_INFO &
|
|
SOURCE_H323_STATE::GetSourceQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
Retrieves a reference to the contained Q.931 information
|
|
|
|
--*/
|
|
{
|
|
return m_SourceQ931Info;
|
|
} // SOURCE_H323_STATE::GetSourceQ931Info
|
|
|
|
|
|
|
|
inline
|
|
SOURCE_H245_INFO &
|
|
SOURCE_H323_STATE::GetSourceH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
Retrieves a reference to the contained H.245 information
|
|
|
|
--*/
|
|
{
|
|
return m_SourceH245Info;
|
|
} // SOURCE_H323_STATE::GetSourceH245Info
|
|
|
|
|
|
// Destination call state description - one side of a call
|
|
class DEST_H323_STATE :
|
|
public H323_STATE
|
|
{
|
|
public:
|
|
|
|
inline
|
|
DEST_H323_STATE (
|
|
void
|
|
);
|
|
|
|
// initialize when a tcp connection is established on a listening
|
|
// interface
|
|
inline
|
|
HRESULT Init (
|
|
IN CALL_BRIDGE &CallBridge
|
|
);
|
|
|
|
inline
|
|
DEST_Q931_INFO &
|
|
GetDestQ931Info (
|
|
void
|
|
);
|
|
|
|
inline
|
|
DEST_H245_INFO &
|
|
GetDestH245Info (
|
|
void
|
|
);
|
|
|
|
inline
|
|
SOURCE_H323_STATE &
|
|
GetSourceH323State (
|
|
void);
|
|
|
|
protected:
|
|
|
|
// contains the destination Q931 tcp info, timeout, remote end info
|
|
DEST_Q931_INFO m_DestQ931Info;
|
|
|
|
// contains the H.245 tcp info, timeout, remote end info
|
|
DEST_H245_INFO m_DestH245Info;
|
|
};
|
|
|
|
|
|
inline
|
|
DEST_H323_STATE::DEST_H323_STATE (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Constructor for DEST_H323_STATE class
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
} // DEST_H323_STATE::DEST_H323_STATE
|
|
|
|
|
|
inline
|
|
HRESULT
|
|
DEST_H323_STATE::Init (
|
|
IN CALL_BRIDGE &CallBridge
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Initialize instance of DEST_H323_STATE when a tcp connection
|
|
is established on a listening interface
|
|
|
|
Arguments:
|
|
CallBridge -- reference to the "parent" call-bridge
|
|
|
|
Return Values:
|
|
S_OK if successful
|
|
Otherwise passes through status code of initializing contained sockets
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT HResult = m_DestQ931Info.Init(*this);
|
|
if (FAILED(HResult))
|
|
{
|
|
return HResult;
|
|
}
|
|
_ASSERTE(S_FALSE != HResult);
|
|
|
|
m_DestH245Info.Init(*this);
|
|
|
|
H323_STATE::Init(
|
|
CallBridge,
|
|
m_DestQ931Info,
|
|
m_DestH245Info,
|
|
FALSE
|
|
);
|
|
|
|
return S_OK;
|
|
} // DEST_H323_STATE::Init (
|
|
|
|
|
|
|
|
inline
|
|
DEST_Q931_INFO &
|
|
DEST_H323_STATE::GetDestQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves reference to the contained Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_DestQ931Info;
|
|
} // DEST_H323_STATE::GetDestQ931Info (
|
|
|
|
|
|
inline
|
|
DEST_H245_INFO &
|
|
DEST_H323_STATE::GetDestH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves reference to the contained H.245 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_DestH245Info;
|
|
} // DEST_H323_STATE::GetDestH245Info
|
|
|
|
// The CALL_BRIDGE represents an active call that is being proxied.
|
|
// Number of outstanding i/os is stored only in the call bridge instance
|
|
// it is only needed to determine when the call bridge instance can safely
|
|
// be shut down
|
|
class CALL_BRIDGE :
|
|
public SIMPLE_CRITICAL_SECTION_BASE,
|
|
public LIFETIME_CONTROLLER
|
|
{
|
|
public:
|
|
|
|
enum STATE {
|
|
STATE_NONE,
|
|
STATE_CONNECTED,
|
|
STATE_TERMINATED,
|
|
};
|
|
|
|
protected:
|
|
|
|
STATE State;
|
|
|
|
// call state info for the source side. i.e. the side which
|
|
// sends the Setup packet
|
|
SOURCE_H323_STATE m_SourceH323State;
|
|
SOCKADDR_IN SourceAddress; // address of the source (originator of the connection)
|
|
DWORD SourceInterfaceAddress; // address of the interface on which the connection was accepted, host order
|
|
|
|
// call state info for the destination side. i.e. the recipient
|
|
// of the setup packet
|
|
DEST_H323_STATE m_DestH323State;
|
|
SOCKADDR_IN DestinationAddress; // address of the destination (recipient of the connection)
|
|
public:
|
|
DWORD DestinationInterfaceAddress; // address of the interface to which the connection is destined, host order
|
|
|
|
private:
|
|
|
|
HRESULT
|
|
InitializeLocked (
|
|
IN SOCKET IncomingSocket,
|
|
IN SOCKADDR_IN * LocalAddress,
|
|
IN SOCKADDR_IN * RemoteAddress,
|
|
IN NAT_KEY_SESSION_MAPPING_EX_INFORMATION * RedirectInformation
|
|
);
|
|
|
|
public:
|
|
|
|
CALL_BRIDGE (
|
|
IN NAT_KEY_SESSION_MAPPING_EX_INFORMATION * RedirectInformation
|
|
);
|
|
|
|
~CALL_BRIDGE (
|
|
void
|
|
);
|
|
|
|
// initialize member call state instances
|
|
HRESULT
|
|
Initialize (
|
|
IN SOCKET IncomingSocket,
|
|
IN SOCKADDR_IN * LocalAddress,
|
|
IN SOCKADDR_IN * RemoteAddress ,
|
|
IN NAT_KEY_SESSION_MAPPING_EX_INFORMATION * RedirectInformation
|
|
);
|
|
|
|
DWORD
|
|
GetSourceInterfaceAddress (
|
|
void
|
|
) const;
|
|
|
|
VOID
|
|
CALL_BRIDGE::GetSourceAddress (
|
|
OUT SOCKADDR_IN* ReturnSourceAddress
|
|
);
|
|
|
|
void
|
|
GetDestinationAddress (
|
|
OUT SOCKADDR_IN * ReturnDestinationAddress
|
|
);
|
|
|
|
// this function may be called by any thread that holds a safe,
|
|
// counted reference to this object.
|
|
void
|
|
TerminateExternal (
|
|
void
|
|
);
|
|
|
|
BOOL
|
|
IsConnectionThrough (
|
|
IN DWORD InterfaceAddress // host order
|
|
);
|
|
|
|
void
|
|
OnInterfaceShutdown (
|
|
void
|
|
);
|
|
|
|
// private:
|
|
|
|
friend class Q931_INFO;
|
|
friend class H245_INFO;
|
|
friend class SOURCE_H245_INFO;
|
|
friend class DEST_H245_INFO;
|
|
friend class LOGICAL_CHANNEL;
|
|
|
|
inline
|
|
BOOL
|
|
IsTerminated (
|
|
void
|
|
);
|
|
|
|
inline
|
|
BOOL
|
|
IsTerminatedExternal (
|
|
void
|
|
);
|
|
|
|
inline
|
|
void
|
|
CancelAllTimers (
|
|
void
|
|
);
|
|
|
|
void
|
|
TerminateCallOnReleaseComplete (
|
|
void
|
|
);
|
|
|
|
void
|
|
Terminate (
|
|
void
|
|
);
|
|
|
|
inline
|
|
SOURCE_H323_STATE &
|
|
GetSourceH323State (
|
|
void
|
|
);
|
|
|
|
inline
|
|
DEST_H323_STATE &
|
|
GetDestH323State (
|
|
void
|
|
);
|
|
};
|
|
|
|
|
|
inline
|
|
void
|
|
CALL_BRIDGE::CancelAllTimers (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Cancels outstanding timers for all H.245 logical channels and Q.931 connections
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
m_SourceH323State.GetQ931Info().TimprocCancelTimer();
|
|
m_DestH323State.GetQ931Info().TimprocCancelTimer();
|
|
GetSourceH323State().GetH245Info().GetLogicalChannelArray().CancelAllTimers();
|
|
GetDestH323State().GetH245Info().GetLogicalChannelArray().CancelAllTimers();
|
|
} // CALL_BRIDGE::CancelAllTimers
|
|
|
|
|
|
inline
|
|
BOOL
|
|
CALL_BRIDGE::IsTerminated (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Checks whether the instance is terminated.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
|
|
Return Values:
|
|
TRUE - if the instance is terminated
|
|
FALSE - if the instance is not terminated
|
|
|
|
Notes:
|
|
1. To be called for locked instance only
|
|
|
|
--*/
|
|
|
|
{
|
|
return State == STATE_TERMINATED;
|
|
} // CALL_BRIDGE::IsTerminated
|
|
|
|
|
|
inline
|
|
BOOL
|
|
CALL_BRIDGE::IsTerminatedExternal (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Checks whether the instance is terminated
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
TRUE - if the instance is terminated
|
|
FALSE - if the instance is not terminated
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL IsCallBridgeTerminated = TRUE;
|
|
|
|
Lock ();
|
|
|
|
IsCallBridgeTerminated = IsTerminated ();
|
|
|
|
Unlock ();
|
|
|
|
return IsCallBridgeTerminated;
|
|
} // CALL_BRIDGE::IsTerminatedExternal
|
|
|
|
|
|
inline
|
|
SOURCE_H323_STATE &
|
|
CALL_BRIDGE::GetSourceH323State (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves reference to the source H.323 state
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_SourceH323State;
|
|
} // CALL_BRIDGE::GetSourceH323State
|
|
|
|
|
|
inline
|
|
DEST_H323_STATE &
|
|
CALL_BRIDGE::GetDestH323State (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves reference to the destination H.323 state
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_DestH323State;
|
|
} // CALL_BRIDGE::GetDestH323State
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Misc. inline functions that require declarations //
|
|
// which are made after them //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//
|
|
// OVERLAPPED_PROCESSOR
|
|
|
|
|
|
inline
|
|
CALL_BRIDGE &
|
|
OVERLAPPED_PROCESSOR::GetCallBridge (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the call-bridge for this
|
|
overlapped processor
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_pH323State->GetCallBridge();
|
|
} // OVERLAPPED_PROCESSOR::GetCallBridge
|
|
|
|
|
|
|
|
inline
|
|
CALL_REF_TYPE
|
|
Q931_INFO::GetCallRefVal (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference value for the call
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return m_CallRefVal;
|
|
} // Q931_INFO::GetCallRefVal
|
|
|
|
|
|
inline
|
|
HRESULT
|
|
SOURCE_Q931_INFO::SetIncomingSocket (
|
|
IN SOCKET IncomingSocket,
|
|
IN SOCKADDR_IN * LocalAddress,
|
|
IN SOCKADDR_IN * RemoteAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Socket initialization
|
|
|
|
Arguments:
|
|
IncomingSocket -- socket on which connection was accepted
|
|
LocalAddress -- address of the local side of the connection
|
|
RemoteAddress -- address of the remote side of the connection
|
|
|
|
Return Values:
|
|
Result of issuing an async receive
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
assert (IncomingSocket != INVALID_SOCKET);
|
|
assert (m_pH323State->IsSourceCall());
|
|
assert (Q931_SOURCE_STATE_INIT == m_Q931SourceState);
|
|
|
|
m_SocketInfo.Init(
|
|
IncomingSocket,
|
|
LocalAddress,
|
|
RemoteAddress);
|
|
|
|
m_Q931SourceState = Q931_SOURCE_STATE_CON_ESTD;
|
|
|
|
return QueueReceive();
|
|
} // SOURCE_Q931_INFO::SetIncomingSocket
|
|
|
|
|
|
inline
|
|
DEST_Q931_INFO &
|
|
SOURCE_Q931_INFO::GetDestQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the destination Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((SOURCE_H323_STATE *)m_pH323State)->GetDestH323State().GetDestQ931Info();
|
|
} // SOURCE_Q931_INFO::GetDestQ931Info
|
|
|
|
|
|
|
|
inline
|
|
SOURCE_H245_INFO &
|
|
SOURCE_Q931_INFO::GetSourceH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the source H.245 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((SOURCE_H323_STATE *)m_pH323State)->GetSourceH245Info();
|
|
} // SOURCE_Q931_INFO::GetSourceH245Info
|
|
|
|
|
|
inline
|
|
SOURCE_Q931_INFO &
|
|
DEST_Q931_INFO::GetSourceQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the source Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((DEST_H323_STATE *)m_pH323State)->GetSourceH323State().GetSourceQ931Info();
|
|
} // DEST_Q931_INFO::GetSourceQ931Info
|
|
|
|
|
|
inline
|
|
DEST_H245_INFO &
|
|
DEST_Q931_INFO::GetDestH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the source Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((DEST_H323_STATE *)m_pH323State)->GetDestH245Info();
|
|
} // DEST_Q931_INFO::GetDestH245Info
|
|
|
|
|
|
inline
|
|
CALL_BRIDGE &
|
|
LOGICAL_CHANNEL::GetCallBridge (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor method
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Reference to the "parent" call-bridge
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetH245Info().GetCallBridge();
|
|
} // LOGICAL_CHANNEL::GetCallBridge
|
|
|
|
|
|
inline
|
|
void
|
|
LOGICAL_CHANNEL::DeleteAndRemoveSelf (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Remove logical channel from the array of those,
|
|
and terminate it.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
// remove self from the logical channel array
|
|
m_pH245Info->GetLogicalChannelArray().Remove(*this);
|
|
|
|
TimprocCancelTimer ();
|
|
|
|
// destroy self
|
|
delete this;
|
|
} // LOGICAL_CHANNEL::DeleteAndRemoveSelf
|
|
|
|
|
|
inline
|
|
H245_INFO &
|
|
H245_INFO::GetOtherH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
"The other" H.245 information (source for destination, and
|
|
destination for source)
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetH323State().GetOtherH323State().GetH245Info();
|
|
} // H245_INFO::GetOtherH245Info (
|
|
|
|
|
|
inline
|
|
SOURCE_Q931_INFO &
|
|
SOURCE_H245_INFO::GetSourceQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves source Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((SOURCE_H323_STATE *)m_pH323State)->GetSourceQ931Info();
|
|
} // SOURCE_H245_INFO::GetSourceQ931Info
|
|
|
|
|
|
inline
|
|
DEST_H245_INFO &
|
|
SOURCE_H245_INFO::GetDestH245Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves destination H.245 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((SOURCE_H323_STATE *)m_pH323State)->GetDestH323State().GetDestH245Info();
|
|
} // SOURCE_H245_INFO::GetDestH245Info
|
|
|
|
|
|
inline
|
|
DEST_Q931_INFO &
|
|
DEST_H245_INFO::GetDestQ931Info (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves destination Q.931 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((DEST_H323_STATE *)m_pH323State)->GetDestQ931Info();
|
|
} // DEST_H245_INFO::GetDestQ931Info
|
|
|
|
|
|
inline
|
|
H323_STATE &
|
|
H323_STATE::GetOtherH323State (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves "the other" H.323 state (source for destination, and
|
|
destination for source)
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
return (TRUE == m_fIsSourceCall)?
|
|
(H323_STATE &)m_pCallBridge->GetDestH323State() :
|
|
(H323_STATE &)m_pCallBridge->GetSourceH323State();
|
|
} // H323_STATE::GetOtherH323State
|
|
|
|
|
|
inline
|
|
DEST_H323_STATE &
|
|
SOURCE_H323_STATE::GetDestH323State (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves destination H.323 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetCallBridge().GetDestH323State();
|
|
} // SOURCE_H323_STATE::GetDestH323State
|
|
|
|
|
|
inline SOURCE_H323_STATE &
|
|
DEST_H323_STATE::GetSourceH323State (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Accessor function
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Values:
|
|
Retrieves source H.323 information
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetCallBridge().GetSourceH323State();
|
|
} // DEST_H323_STATE::GetSourceH323State
|
|
|
|
#endif // __h323ics_call_bridge_h
|