initial commit
This commit is contained in:
commit
636959b37b
2474 files changed
+1343178
No files matched your search
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -0,0 +1,107 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_ICE ICE: Interactive Connectivity Establishment
|
||||
@brief Interactive Connectivity Establishment (ICE)
|
||||
@ingroup PJNATH
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_ICE_STREAM_TRANSPORT ICE stream transport
|
||||
@brief Transport for media streams using ICE
|
||||
@ingroup PJNATH_ICE
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_ICE_SESSION ICE Session
|
||||
@brief Transport Independent ICE Session
|
||||
@ingroup PJNATH_ICE
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup PJNATH_ICE
|
||||
\section org Library organizations
|
||||
|
||||
See <b>Table of Contents</b> below.
|
||||
|
||||
\section ice_intro_sec Introduction to ICE
|
||||
|
||||
Interactive Connectivity Establishment (ICE) is the ultimate
|
||||
weapon a client can have in its NAT traversal solution arsenals,
|
||||
as it promises that if there is indeed one path for two clients
|
||||
to communicate, then ICE will find this path. And if there are
|
||||
more than one paths which the clients can communicate, ICE will
|
||||
use the best/most efficient one.
|
||||
|
||||
ICE works by combining several protocols (such as STUN and TURN)
|
||||
altogether and offering several candidate paths for the communication,
|
||||
thereby maximising the chance of success, but at the same time also
|
||||
has the capability to prioritize the candidates, so that the more
|
||||
expensive alternative (namely relay) will only be used as the last
|
||||
resort when else fails. ICE negotiation process involves several
|
||||
stages:
|
||||
|
||||
- candidate gathering, where the client finds out all the possible
|
||||
addresses that it can use for the communication. It may find
|
||||
three types of candidates: host candidate to represent its
|
||||
physical NICs, server reflexive candidate for the address that
|
||||
has been resolved from STUN, and relay candidate for the address
|
||||
that the client has allocated from a TURN relay.
|
||||
- prioritizing these candidates. Typically the relay candidate will
|
||||
have the lowest priority to use since it's the most expensive.
|
||||
- encoding these candidates, sending it to remote peer, and
|
||||
negotiating it with offer-answer.
|
||||
- pairing the candidates, where it pairs every local candidates
|
||||
with every remote candidates that it receives from the remote peer.
|
||||
- checking the connectivity for each candidate pairs.
|
||||
- concluding the result. Since every possible path combinations are
|
||||
checked, if there is a path to communicate ICE will find it.
|
||||
|
||||
|
||||
\section icestrans_sec Using ICE transport
|
||||
|
||||
The \ref PJNATH_ICE_STREAM_TRANSPORT is a ready to use object which
|
||||
performs the above ICE operations as well as provides application with
|
||||
interface to send and receive data using the negotiated path.
|
||||
|
||||
Please see \ref PJNATH_ICE_STREAM_TRANSPORT on how to use this object.
|
||||
|
||||
|
||||
\section ice_owntransport_sec Creating custom ICE transport
|
||||
|
||||
If the \ref PJNATH_ICE_STREAM_TRANSPORT is not suitable for use
|
||||
for some reason, you will need to implement your own ICE transport,
|
||||
by combining the \ref PJNATH_ICE_SESSION with your own means to
|
||||
send and receive packets. The \ref PJNATH_ICE_STREAM_TRANSPORT
|
||||
provides the best example on how to do this.
|
||||
|
||||
|
||||
\section ice_samples_sec Samples
|
||||
|
||||
The \ref ice_demo_sample sample demonstrates how to use
|
||||
\ref PJNATH_ICE_STREAM_TRANSPORT <b>without</b> using signaling
|
||||
protocol such as <b>SIP</b>. It provides interactive user interface
|
||||
to create and manage the ICE sessions as well as to exchange SDP
|
||||
with another ice_demo instance.
|
||||
|
||||
Also see <b>\ref samples_page</b> for other samples.
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@mainpage PJNATH - Open Source ICE, STUN, and TURN Library
|
||||
|
||||
PJNATH (PJSIP NAT Helper) is an open source library providing NAT traversal
|
||||
functionalities by using standard based protocols such as STUN, TURN, and ICE.
|
||||
|
||||
|
||||
\section background Background
|
||||
|
||||
|
||||
Network Address Translation (NAT) is commonly deployed everywhere primarily to
|
||||
alleviate the exhaustion of IPv4 address space by allowing multiple hosts to
|
||||
share a public/Internet address. While NAT would work well for typical client
|
||||
server communications (such as web and email), since it's always the client
|
||||
that initiates the conversation and normally client doesn't need to maintain
|
||||
the connection for a long time, installation of NAT would cause major problem
|
||||
for peer-to-peer communication, such as (and especially) VoIP.
|
||||
|
||||
<strong>\ref nat_intro "Read more.."</strong>
|
||||
|
||||
|
||||
\section intro Introduction to PJNATH
|
||||
|
||||
PJSIP NAT Helper (PJNATH) is a library which contains the implementation of
|
||||
standard based NAT traversal solutions. PJNATH can be used as a stand-alone
|
||||
library for your software, or you may use PJSUA-LIB library, a very high level
|
||||
library integrating PJSIP, PJMEDIA, and PJNATH into simple to use APIs.
|
||||
|
||||
PJNATH has the following features:
|
||||
|
||||
- <strong>STUNbis</strong> implementation,\n
|
||||
providing both ready to use
|
||||
STUN-aware socket and framework to implement higher level STUN based
|
||||
protocols such as TURN and ICE. The implementation complies to
|
||||
<A HREF="http://www.ietf.org/rfc/rfc5389.txt">RFC 5389</A>
|
||||
standard.\n\n
|
||||
|
||||
- <strong>NAT type detection</strong>, \n
|
||||
performs detection of the NAT type in front of the endpoint, according
|
||||
to <A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>.
|
||||
While the practice to detect the NAT type to assist NAT
|
||||
traversal has been deprecated in favor of ICE, the information may still
|
||||
be useful for troubleshooting purposes, hence the utility is provided.\n\n
|
||||
|
||||
- <strong>Traversal Using Relays around NAT (TURN)</strong> implementation.\n
|
||||
TURN is a protocol for relaying communications by means of using relay,
|
||||
and combined with ICE it provides efficient last effort alternative for
|
||||
the communication path. The TURN implementation in PJNATH complies to
|
||||
<A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-14.txt">
|
||||
draft-ietf-behave-turn-14</A> draft.\n\n
|
||||
|
||||
- <strong>Interactive Connectivity Establishmen (ICE)</strong> implementation.\n
|
||||
ICE is a protocol for discovering communication path(s) between two
|
||||
endpoints. The implementation in PJNATH complies to
|
||||
<A HREF="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-ice-19.txt">
|
||||
draft-ietf-mmusic-ice-19.txt</A> draft
|
||||
|
||||
In the future, more protocols will be implemented (such as UPnP IGD, and
|
||||
SOCKS5).
|
||||
|
||||
|
||||
\section pjnath_organization_sec Library Organization
|
||||
|
||||
The library provides the following main component groups:
|
||||
|
||||
- \ref PJNATH_STUN\n\n
|
||||
- \ref PJNATH_TURN\n\n
|
||||
- \ref PJNATH_ICE\n\n
|
||||
- \ref PJNATH_NAT_DETECT\n\n
|
||||
|
||||
Apart from the \ref PJNATH_NAT_DETECT, each component group are further
|
||||
divided into two functionalities:
|
||||
|
||||
- <b>Transport objects</b>\n
|
||||
The transport objects (such as STUN transport, TURN transport, and ICE
|
||||
stream transport) are the implementation of the session object
|
||||
<strong>with</strong> particular transport/sockets. They are provided
|
||||
as ready to use objects for applications.\n\n
|
||||
|
||||
- <b>Transport independent/session layer</b>\n
|
||||
The session objects (such as STUN session, TURN session, and ICE session)
|
||||
are the core object for maintaining the protocol session, and it is
|
||||
independent of transport (i.e. it does not "own" a socket). This way
|
||||
developers can reuse these session objects for any kind of transports,
|
||||
such as UDP, TCP, or TLS, with or without using PJLIB socket API.
|
||||
The session objects provide function and callback to send and receive
|
||||
packets respectively.
|
||||
|
||||
For more information about each component groups, please click the component
|
||||
link above.
|
||||
|
||||
|
||||
\section pjnath_start_sec Getting Started with PJNATH
|
||||
|
||||
\subsection dependency Library Dependencies
|
||||
|
||||
The PJNATH library depends (and only depends) on PJLIB and PJLIB-UTIL
|
||||
libraries. All these libraries should have been packaged together with
|
||||
the main PJSIP distribution. You can download the PJSIP distribution
|
||||
from <A HREF="http://www.pjsip.org">PJSIP website</A>
|
||||
|
||||
|
||||
\subsection pjnath_using_sec Using the libraries
|
||||
|
||||
Please click on the appropriate component under \ref pjnath_organization_sec
|
||||
section above, which will take you to the documentation on how to use the
|
||||
component.
|
||||
|
||||
|
||||
\subsection samples_sec Samples
|
||||
|
||||
We attempt to provide simple samples to use each functionality of the PJNATH
|
||||
library.
|
||||
|
||||
Please see <b>\ref samples_page</b> page for the list of samples.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@defgroup samples_page PJNATH Samples and screenshots
|
||||
@brief Sample applications and screenshots
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,415 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@defgroup nat_intro Introduction to Network Address Translation (NAT) and NAT Traversal
|
||||
@brief This page describes NAT and the problems caused by it and the solutions
|
||||
|
||||
|
||||
|
||||
\section into Introduction to NAT
|
||||
|
||||
|
||||
NAT (Network Address Translation) is a mechanism where a device performs
|
||||
modifications to the TCP/IP address/port number of a packet and maps the
|
||||
IP address from one realm to another (usually from private IP address to
|
||||
public IP address and vice versa). This works by the NAT device allocating
|
||||
a temporary port number on the public side of the NAT upon forwarding
|
||||
outbound packet from the internal host towards the Internet, maintaining
|
||||
this mapping for some predefined time, and forwarding the inbound packets
|
||||
received from the Internet on this public port back to the internal host.
|
||||
|
||||
|
||||
NAT devices are installed primarily to alleviate the exhaustion of IPv4
|
||||
address space by allowing multiple hosts to share a public/Internet address.
|
||||
Also due to its mapping nature (i.e. a mapping can only be created by
|
||||
a transmission from an internal host), NAT device is preferred to be
|
||||
installed even when IPv4 address exhaustion is not a problem (for example
|
||||
when there is only one host at home), to provide some sort of security/shield
|
||||
for the internal hosts against threats from the Internet.
|
||||
|
||||
|
||||
Despite the fact that NAT provides some shields for the internal network,
|
||||
one must distinguish NAT solution from firewall solution. NAT is not
|
||||
a firewall solution. A firewall is a security solution designed to enforce
|
||||
the security policy of an organization, while NAT is a connectivity solution
|
||||
to allow multiple hosts to use a single public IP address. Understandably
|
||||
both functionalities are difficult to separate at times, since many
|
||||
(typically consumer) products claims to do both with the same device and
|
||||
simply label the device a “NAT box”. But we do want to make this distinction
|
||||
rather clear, as PJNATH is a NAT traversal helper and not a firewall bypass
|
||||
solution (yet).
|
||||
|
||||
|
||||
|
||||
\section problems The NAT traversal problems
|
||||
|
||||
|
||||
While NAT would work well for typical client server communications (such as
|
||||
web and email), since it's always the client that initiates the conversation
|
||||
and normally client doesn't need to maintain the connection for a long time,
|
||||
installation of NAT would cause major problem for peer-to-peer communication,
|
||||
such as (and especially) VoIP. These problems will be explained in more detail
|
||||
below.
|
||||
|
||||
|
||||
\subsection peer_addr Peer address problem
|
||||
|
||||
|
||||
In VoIP, normally we want the media (audio, and video) to flow directly
|
||||
between the clients, since relaying is costly (both in terms of bandwidth
|
||||
cost for service provider, and additional latency introduced by relaying).
|
||||
To do this, each client informs its media transport address to the other
|
||||
client , by sending it via the VoIP signaling path, and the other side would
|
||||
send its media to this transport address.
|
||||
|
||||
|
||||
And there lies the problem. If the client software is not NAT aware, then
|
||||
it would send its private IP address to the other client, and the other
|
||||
client would not be able to send media to this address.
|
||||
|
||||
|
||||
Traditionally this was solved by using STUN. With this mechanism, the client
|
||||
first finds out its public IP address/port by querying a STUN server, then
|
||||
send sthis public address instead of its private address to the other
|
||||
client. When both sides are using this mechanism, they can then send media
|
||||
packets to these addresses, thereby creating a mapping in the NAT (also
|
||||
called opening a "hole", hence this mechanism is also popularly called
|
||||
"hole punching") and both can then communicate with each other.
|
||||
|
||||
|
||||
But this mechanism does not work in all cases, as will be explained below.
|
||||
|
||||
|
||||
|
||||
\subsection hairpin Hairpinning behavior
|
||||
|
||||
|
||||
Hairpin is a behavior where a NAT device forwards packets from a host in
|
||||
internal network (lets call it host A) back to some other host (host B) in
|
||||
the same internal network, when it detects that the (public IP address)
|
||||
destination of the packet is actually a mapped IP address that was created
|
||||
for the internal host (host B). This is a desirable behavior of a NAT,
|
||||
but unfortunately not all NAT devices support this.
|
||||
|
||||
|
||||
Lacking this behavior, two (internal) hosts behind the same NAT will not
|
||||
be able to communicate with each other if they exchange their public
|
||||
addresses (resolved by STUN above) to each other.
|
||||
|
||||
|
||||
|
||||
\subsection symmetric Symmetric behavior
|
||||
|
||||
|
||||
NAT devices don't behave uniformly and people have been trying to classify
|
||||
their behavior into different classes. Traditionally NAT devices are
|
||||
classified into Full Cone, Restricted Cone, Port Restricted Cone, and
|
||||
Symmetric types, according to <A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>
|
||||
section 5. A more recent method of classification, as explained by
|
||||
<A HREF="http://www.ietf.org/rfc/rfc4787.txt">RFC 4787</A>, divides
|
||||
the NAT behavioral types into two attributes: the mapping behavior
|
||||
attribute and the filtering behavior attribute. Each attribute can be
|
||||
one of three types: <i>Endpoint-Independent</i>, <i>Address-Dependent</i>,
|
||||
or <i>Address and Port-Dependent</i>. With this new classification method,
|
||||
a Symmetric NAT actually is an Address and Port-Dependent mapping NAT.
|
||||
|
||||
|
||||
Among these types, the Symmetric type is the hardest one to work with.
|
||||
The problem is because the NAT allocates different mapping (of the same
|
||||
internal host) for the communication to the STUN server and the
|
||||
communication to the other (external) hosts, so the IP address/port that
|
||||
is informed by one host to the other is meaningless for the recipient
|
||||
since this is not the actual IP address/port mapping that the NAT device
|
||||
creates. The result is when the recipient host tries to send a packet to
|
||||
this address, the NAT device would drop the packet since it does not
|
||||
recognize the sender of the packet as the "authorized" hosts to send
|
||||
to this address.
|
||||
|
||||
|
||||
There are two solutions for this. The first, we could make the client
|
||||
smarter by switching transmission of the media to the source address of
|
||||
the media packets. This would work since normally clients uses a well
|
||||
known trick called symmetric RTP, where they use one socket for both
|
||||
transmitting and receiving RTP/media packets. We also use this
|
||||
mechanism in PJMEDIA media transport. But this solution only works
|
||||
if a client behind a symmetric NAT is not communicating with other
|
||||
client behind either symmetric NAT or port-restricted NAT.
|
||||
|
||||
|
||||
The second solution is to use media relay, but as have been mentioned
|
||||
above, relaying is costly, both in terms of bandwidth cost for service
|
||||
provider and additional latency introduced by relaying.
|
||||
|
||||
|
||||
|
||||
\subsection binding_timeout Binding timeout
|
||||
|
||||
When a NAT device creates a binding (a public-private IP address
|
||||
mapping), it will associate a timer with it. The timer is used to
|
||||
destroy the binding once there is no activity/traffic associated with
|
||||
the binding. Because of this, a NAT aware application that wishes to
|
||||
keep the binding open must periodically send outbound packets,
|
||||
a mechanism known as keep-alive, or otherwise it will ultimately
|
||||
loose the binding and unable to receive incoming packets from Internet.
|
||||
|
||||
|
||||
\section solutions The NAT traversal solutions
|
||||
|
||||
|
||||
\subsection stun Old STUN (RFC 3489)
|
||||
|
||||
The original STUN (Simple Traversal of User Datagram Protocol (UDP)
|
||||
Through Network Address Translators (NATs)) as defined by
|
||||
<A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>
|
||||
(published in 2003, but the work was started as early as 2001) was
|
||||
meant to be a standalone, standard-based solution for the NAT
|
||||
connectivity problems above. It is equipped with NAT type detection
|
||||
algoritm and methods to hole-punch the NAT in order to let traffic
|
||||
to get through and has been proven to be quite successful in
|
||||
traversing many types of NATs, hence it has gained a lot of popularity
|
||||
as a simple and effective NAT traversal solution.
|
||||
|
||||
But since then the smart people at IETF has realized that STUN alone
|
||||
is not going to be enough. Besides its nature that STUN solution cannot
|
||||
solve the symmetric-to-symmetric or port-restricted connection,
|
||||
people have also discovered that NAT behavior can change for different
|
||||
traffic (or for the same traffic overtime) hence it was concluded that
|
||||
NAT type detection could produce unreliable results hence one should not
|
||||
rely too much on it.
|
||||
|
||||
Because of this, STUN has since moved its efforts to different strategy.
|
||||
Instead of attempting to provide a standalone solution, it's now providing
|
||||
a part solution and framework to build other (STUN based) protocols
|
||||
on top of it, such as TURN and ICE.
|
||||
|
||||
|
||||
\subsection stunbis STUN/STUNbis (RFC 5389)
|
||||
|
||||
The Session Traversal Utilities for NAT (STUN) is the further development
|
||||
of the old STUN. While it still provides a mechanism for a client to
|
||||
query its public/mapped address to a STUN server, it has deprecated
|
||||
the use of NAT type detection, and now it serves as a framework to build
|
||||
other protocols on top of it (such as TURN and ICE).
|
||||
|
||||
|
||||
\subsection midcom_turn Old TURN (draft-rosenberg-midcom-turn)
|
||||
|
||||
Traversal Using Relay NAT (TURN), a standard-based effort started as early
|
||||
as in November 2001, was meant to be the complementary method for the
|
||||
(old) STUN to complete the solution. The original idea was the host to use
|
||||
STUN to detect the NAT type, and when it has found that the NAT type is
|
||||
symmetric it would use TURN to relay the traffic. But as stated above,
|
||||
this approach was deemed to be unreliable, and now the prefered way to use
|
||||
TURN (and it's a new TURN specification as well) is to combine it with ICE.
|
||||
|
||||
|
||||
\subsection turn TURN (draft-ietf-behave-turn)
|
||||
|
||||
Traversal Using Relays around NAT (TURN) is the latest development of TURN.
|
||||
While the protocol details have changed a lot, the objective is still
|
||||
the same, that is to provide relaying control for the application.
|
||||
As mentioned above, preferably TURN should be used with ICE since relaying
|
||||
is costly in terms of both bandwidth and latency, hence it should be used
|
||||
as the last resort.
|
||||
|
||||
|
||||
\subsection b2bua B2BUA approach
|
||||
|
||||
A SIP Back to Back User Agents (B2BUA) is a SIP entity that sits in the
|
||||
middle of SIP traffic and acts as SIP user agents on both call legs.
|
||||
The primary motivations to have a B2BUA are to be able to provision
|
||||
the call (e.g. billing, enforcing policy) and to help with NAT traversal
|
||||
for the clients. Normally a B2BUA would be equipped with media relaying
|
||||
or otherwise it wouldn't be very useful.
|
||||
|
||||
Products that fall into this category include SIP Session Border
|
||||
Controllers (SBC), and PBXs such as Asterisk are technically a B2BUA
|
||||
as well.
|
||||
|
||||
The benefit of B2BUA with regard to helping NAT traversal is it does not
|
||||
require any modifications to the client to make it go through NATs.
|
||||
And since basically it is a relay, it should be able to traverse
|
||||
symmetric NAT successfully.
|
||||
|
||||
However, since it is a relay, the usual relaying drawbacks apply,
|
||||
namely the bandwidth and latency issue. More over, since a B2BUA acts
|
||||
as user agent in either call-legs (i.e. it terminates the SIP
|
||||
signaling/call on one leg, albeit it creates another call on the other
|
||||
leg), it may also introduce serious issues with end-to-end SIP signaling.
|
||||
|
||||
|
||||
\subsection alg ALG approach
|
||||
|
||||
Nowdays many NAT devices (such as consumer ADSL routers) are equipped
|
||||
with intelligence to inspect and fix VoIP traffic in its effort to help
|
||||
it with the NAT traversal. This feature is called Application Layer
|
||||
Gateway (ALG) intelligence. The idea is since the NAT device knows about
|
||||
the mapping, it might as well try to fix the application traffic so that
|
||||
the traffic could better traverse the NAT. Some tricks that are
|
||||
performed include for example replacing the private IP addresses/ports
|
||||
in the SIP/SDP packet with the mapped public address/port of the host
|
||||
that sends the packet.
|
||||
|
||||
Despite many claims about its usefullness, in reality this has given us
|
||||
more problems than the fix. Too many devices such as these break the
|
||||
SIP signaling, and in more advanced case, ICE negotiation. Some
|
||||
examples of bad situations that we have encountered in the past:
|
||||
|
||||
- NAT device alters the Via address/port fields in the SIP response
|
||||
message, making the response fail to pass SIP response verification
|
||||
as defined by SIP RFC.
|
||||
- In other case, the modifications in the Via headers of the SIP
|
||||
response hides the important information from the SIP server,
|
||||
nameny the actual IP address/port of the client as seen by the SIP
|
||||
server.
|
||||
- Modifications in the Contact URI of REGISTER request/response makes
|
||||
the client unable to detect it's registered binding.
|
||||
- Modifications in the IP addresses/ports in SDP causes ICE
|
||||
negotiation to fail with ice-mismatch status.
|
||||
- The complexity of the ALG processing in itself seems to have caused
|
||||
the device to behave erraticly with managing the address bindings
|
||||
(e.g. it creates a new binding for the second packet sent by the
|
||||
client, even when the previous packet was sent just second ago, or
|
||||
it just sends inbound packet to the wrong host).
|
||||
|
||||
|
||||
Many man-months efforts have been spent just to troubleshoot issues
|
||||
caused by these ALG (mal)functioning, and as it adds complexity to
|
||||
the problem rather than solving it, in general we do not like this
|
||||
approach at all and would prefer it to go away.
|
||||
|
||||
|
||||
\subsection upnp UPnP
|
||||
|
||||
The Universal Plug and Play (UPnP) is a set of protocol specifications
|
||||
to control network appliances and one of its specification is to
|
||||
control NAT device. With this protocol, a client can instruct the
|
||||
NAT device to open a port in the NAT's public side and use this port
|
||||
for its communication. UPnP has gained popularity due to its
|
||||
simplicity, and one can expect it to be available on majority of
|
||||
NAT devices.
|
||||
|
||||
The drawback of UPnP is since it uses multicast in its communication,
|
||||
it will only allow client to control one NAT device that is in the
|
||||
same multicast domain. While this normally is not a problem in
|
||||
household installations (where people normally only have one NAT
|
||||
router), it will not work if the client is behind cascaded routers
|
||||
installation. More over uPnP has serious issues with security due to
|
||||
its lack of authentication, it's probably not the prefered solution
|
||||
for organizations.
|
||||
|
||||
\subsection other Other solutions
|
||||
|
||||
Other solutions to NAT traversal includes:
|
||||
|
||||
- SOCKS, which supports UDP protocol since SOCKS5.
|
||||
|
||||
|
||||
|
||||
\section ice ICE Solution - The Protocol that Works Harder
|
||||
|
||||
A new protocol is being standardized (it's in Work Group Last Call/WGLC
|
||||
stage at the time this article was written) by the IETF, called
|
||||
Interactive Connectivity Establishment (ICE). ICE is the ultimate
|
||||
weapon a client can have in its NAT traversal solution arsenals,
|
||||
as it promises that if there is indeed one path for two clients
|
||||
to communicate, then ICE will find this path. And if there are
|
||||
more than one paths which the clients can communicate, ICE will
|
||||
use the best/most efficient one.
|
||||
|
||||
ICE works by combining several protocols (such as STUN and TURN)
|
||||
altogether and offering several candidate paths for the communication,
|
||||
thereby maximising the chance of success, but at the same time also
|
||||
has the capability to prioritize the candidates, so that the more
|
||||
expensive alternative (namely relay) will only be used as the last
|
||||
resort when else fails. ICE negotiation process involves several
|
||||
stages:
|
||||
|
||||
- candidate gathering, where the client finds out all the possible
|
||||
addresses that it can use for the communication. It may find
|
||||
three types of candidates: host candidate to represent its
|
||||
physical NICs, server reflexive candidate for the address that
|
||||
has been resolved from STUN, and relay candidate for the address
|
||||
that the client has allocated from a TURN relay.
|
||||
- prioritizing these candidates. Typically the relay candidate will
|
||||
have the lowest priority to use since it's the most expensive.
|
||||
- encoding these candidates, sending it to remote peer, and
|
||||
negotiating it with offer-answer.
|
||||
- pairing the candidates, where it pairs every local candidates
|
||||
with every remote candidates that it receives from the remote peer.
|
||||
- checking the connectivity for each candidate pairs.
|
||||
- concluding the result. Since every possible path combinations are
|
||||
checked, if there is a path to communicate ICE will find it.
|
||||
|
||||
|
||||
There are many benetifs of ICE:
|
||||
|
||||
- it's standard based.
|
||||
- it works where STUN works (and more)
|
||||
- unlike standalone STUN solution, it solves the hairpinning issue,
|
||||
since it also offers host candidates.
|
||||
- just as relaying solutions, it works with symmetric NATs. But unlike
|
||||
plain relaying, relay is only used as the last resort, thereby
|
||||
minimizing the bandwidth and latency issue of relaying.
|
||||
- it offers a generic framework for offering and checking address
|
||||
candidates. While the ICE core standard only talks about using STUN
|
||||
and TURN, implementors can add more types of candidates in the ICE
|
||||
offer, for example UDP over TCP or HTTP relays, or even uPnP
|
||||
candidates, and this could be done transparently for the remote
|
||||
peer hence it's compatible and usable even when the remote peer
|
||||
does not support these.
|
||||
- it also adds some kind of security particularly against DoS attacks,
|
||||
since media address must be acknowledged before it can be used.
|
||||
|
||||
|
||||
Having said that, ICE is a complex protocol to implement, making
|
||||
interoperability an issue, and at this time of writing we don't see
|
||||
many implementations of it yet. Fortunately, PJNATH has been one of
|
||||
the first hence more mature ICE implementation, being first released
|
||||
on mid-2007, and we have been testing our implementation at
|
||||
<A HREF="http://www.sipit.net">SIP Interoperability Test (SIPit)</A>
|
||||
events regularly, so hopefully we are one of the most stable as well.
|
||||
|
||||
|
||||
\section pjnath PJNATH - The building blocks for effective NAT traversal solution
|
||||
|
||||
PJSIP NAT Helper (PJNATH) is a library which contains the implementation
|
||||
of standard based NAT traversal solutions. PJNATH can be used as a
|
||||
stand-alone library for your software, or you may use PJSUA-LIB library,
|
||||
a very high level library integrating PJSIP, PJMEDIA, and PJNATH into
|
||||
simple to use APIs.
|
||||
|
||||
PJNATH has the following features:
|
||||
|
||||
- STUNbis implementation, providing both ready to use STUN-aware socket
|
||||
and framework to implement higher level STUN based protocols such as
|
||||
TURN and ICE.
|
||||
- NAT type detection, useful for troubleshooting purposes.
|
||||
- TURN implementation.
|
||||
- ICE implementation.
|
||||
|
||||
|
||||
More protocols will be implemented in the future.
|
||||
|
||||
Go back to \ref index.
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,93 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@addtogroup samples_page
|
||||
|
||||
Several samples that are included in the PJSIP distributions. The screenshots
|
||||
below were taken on a Windows machine, but the library is very portable and
|
||||
it is known to run on platforms such as Linux, MacOS X, Windows Mobile,
|
||||
Symbian, and so on.
|
||||
|
||||
- @ref ice_demo_sample\n
|
||||
This sample demonstrates how to use \ref PJNATH_ICE_STREAM_TRANSPORT
|
||||
<b>without</b> using signaling protocol such as <b>SIP</b>. It provides
|
||||
interactive user interface to create and manage the ICE sessions as well
|
||||
as to exchange SDP with another ice_demo instance.\n\n
|
||||
\image html ice_demo.jpg "ice_demo on WinXP"
|
||||
|
||||
- @ref turn_client_sample\n
|
||||
This sample demonstrates how to use \ref PJNATH_TURN_SOCK
|
||||
and also \ref PJNATH_STUN_SOCK. It provides interactive
|
||||
user interface to manage allocation, permissions, and
|
||||
channel bindings.\n\n
|
||||
\image html pjturn_client.jpg "pjturn_client on WinXP"
|
||||
|
||||
- TURN server sample\n
|
||||
This is a simple sample TURN server application, which
|
||||
we mainly use for testing (as back then there is no TURN
|
||||
server available).\n
|
||||
The source code for this application are in <tt><b>pjnath/src/pjturn-srv</b></tt>
|
||||
directory.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
\page turn_client_sample pjturn-client, a sample TURN client
|
||||
|
||||
This is a simple, interactive TURN client application, with the
|
||||
following features:
|
||||
- DNS SRV resolution
|
||||
- TCP connection to TURN server
|
||||
- Optional fingerprint
|
||||
|
||||
This file is pjnath/src/pjturn-client/client_main.c.
|
||||
|
||||
Screenshot on WinXP: \image html pjturn_client.jpg "pjturn_client on WinXP"
|
||||
|
||||
\includelineno client_main.c.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
\page ice_demo_sample ice_demo, an interactive ICE endpoint
|
||||
|
||||
This sample demonstrates how to use \ref PJNATH_ICE_STREAM_TRANSPORT
|
||||
<b>without</b> using signaling protocol such as SIP. It provides
|
||||
interactive user interface to create and manage the ICE sessions as well
|
||||
as to exchange SDP with another ice_demo instance.
|
||||
|
||||
Features of the demo application:
|
||||
- supports host, STUN, and TURN candidates
|
||||
- disabling of host candidates
|
||||
- DNS SRV resolution for STUN and TURN servers
|
||||
- TCP connection to TURN server
|
||||
- Optional use of fingerprint for TURN
|
||||
- prints and parse SDP containing ICE infos
|
||||
- exchange SDP with copy/paste
|
||||
|
||||
This file is pjsip-apps/src/samples/icedemo.c
|
||||
|
||||
Screenshot on WinXP: \image html ice_demo.jpg "ice_demo on WinXP"
|
||||
|
||||
\includelineno icedemo.c.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_STUN STUN: Session Traversal Utilities for NAT
|
||||
@ingroup PJNATH
|
||||
@brief Open source STUN library
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_STUN_SOCK STUN-aware socket transport
|
||||
@brief STUN aware UDP socket transport
|
||||
@ingroup PJNATH_STUN
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_STUN_SESSION STUN session
|
||||
@brief STUN client and server session
|
||||
@ingroup PJNATH_STUN
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_STUN_BASE Base STUN objects
|
||||
@ingroup PJNATH_STUN
|
||||
@brief STUN data structures, objects, and configurations
|
||||
|
||||
These section contains STUN base data structures as well as
|
||||
configurations. Among other things it contains STUN message
|
||||
representation and parsing, transactions, authentication
|
||||
framework, as well as compile-time and run-time configurations.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@addtogroup PJNATH_STUN
|
||||
|
||||
This module contains implementation of STUN library in PJNATH -
|
||||
the open source NAT helper containing STUN and ICE.
|
||||
|
||||
\section stun_org_sec Library organizations
|
||||
|
||||
The STUN part of PJNATH consists of the the following sections (see
|
||||
<b>Table of Contents</b> below).
|
||||
|
||||
|
||||
\section stun_using_sec Using the STUN transport
|
||||
|
||||
The \ref PJNATH_STUN_SOCK is a ready to use object which provides
|
||||
send and receive interface for communicating UDP packets as well as
|
||||
means to communicate with the STUN server and manage the STUN mapped
|
||||
address.
|
||||
|
||||
Some features of the \ref PJNATH_STUN_SOCK:
|
||||
- API to send and receive UDP packets,
|
||||
- interface to query the STUN mapped address info,
|
||||
- multiplex STUN and non-STUN incoming packets and distinguish between
|
||||
STUN responses that belong to internal requests with application data
|
||||
(the application data may be STUN packets as well),
|
||||
- resolution of the STUN server with DNS SRV query (if wanted),
|
||||
- maintaining STUN keep-alive, and
|
||||
- handle changes in STUN mapped address binding.
|
||||
|
||||
Please see \ref PJNATH_STUN_SOCK for more information.
|
||||
|
||||
|
||||
\section stun_advanced_sec Advanced use of the STUN components
|
||||
|
||||
The rest of the STUN part of the library provides lower level objects
|
||||
which can be used to build your own STUN based transport or
|
||||
protocols (officially called STUN usages). These will be explained
|
||||
briefly below.
|
||||
|
||||
|
||||
\subsection stun_sess_sec The STUN session
|
||||
|
||||
A STUN session is interactive information exchange between two STUN
|
||||
endpoints that lasts for some period of time. It is typically started by
|
||||
an outgoing or incoming request, and consists of several requests,
|
||||
responses, and indications. All requests and responses within the session
|
||||
typically share a same credential.
|
||||
|
||||
The \ref PJNATH_STUN_SESSION is a transport-independent object to
|
||||
manage a client or server STUN session. It is one of the core object in
|
||||
PJNATH, and it is used by several higher level objects including the
|
||||
\ref PJNATH_STUN_SOCK, \ref PJNATH_TURN_SESSION, and \ref PJNATH_ICE_SESSION.
|
||||
|
||||
The \ref PJNATH_STUN_SESSION has the following features:
|
||||
- transport independent
|
||||
- authentication management
|
||||
- static or dynamic credential
|
||||
- client transaction management
|
||||
- server transaction management
|
||||
|
||||
For more information, including how to use it please see
|
||||
\ref PJNATH_STUN_SESSION.
|
||||
|
||||
|
||||
\subsection stun_extending_sec Extending STUN to support other usages
|
||||
|
||||
At present, the STUN subsystem in PJNATH supports STUN Binding, TURN, and
|
||||
ICE usages. If other usages are to be supported, typically you would need
|
||||
to add new STUN methods (and the corresponding request and response message
|
||||
types), attributes, and error codes to \ref PJNATH_STUN_MSG subsystem of
|
||||
PJNATH, as well as implementing the logic for the STUN usage.
|
||||
|
||||
|
||||
\section stunsamples_sec STUN samples
|
||||
|
||||
The \ref turn_client_sample sample application also contains sample
|
||||
code to use \ref PJNATH_STUN_SOCK.
|
||||
|
||||
Also see <b>\ref samples_page</b> for other samples.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@defgroup PJNATH_TURN TURN: Traversal Using Relays around NAT
|
||||
@brief TURN protocol implementation
|
||||
@ingroup PJNATH
|
||||
|
||||
\section turn_intro_sec Introduction to TURN
|
||||
|
||||
When a direct communication path cannot be found, it is necessary to
|
||||
use the services of an intermediate host that acts as a relay for the
|
||||
packets. This relay typically sits in the public Internet and relays
|
||||
packets between two hosts that both sit behind NATs.
|
||||
|
||||
TURN allows a host behind a NAT (called the TURN client) to request that
|
||||
another host (called the TURN server) act as a relay. The client can
|
||||
arrange for the server to relay packets to and from certain other hosts
|
||||
(called peers) and can control aspects of how the relaying is done.
|
||||
The client does this by obtaining an IP address and port on the
|
||||
server, called the relayed-transport-address. When a peer sends a
|
||||
packet to the relayed-transport-address, the server relays the packet
|
||||
to the client. When the client sends a data packet to the server,
|
||||
the server relays it to the appropriate peer using the relayed-
|
||||
transport-address as the source.
|
||||
|
||||
|
||||
\section turn_op_sec Overview of TURN operations
|
||||
|
||||
<b>Discovering TURN server</b>.\n
|
||||
Client learns the IP address of the TURN
|
||||
server either through some privisioning or by querying DNS SRV records
|
||||
for TURN service for the specified domain. Client may use UDP or TCP (or
|
||||
TLS) to connect to the TURN server.
|
||||
|
||||
<b>Authentication</b>.\n
|
||||
All TURN operations requires the use of authentication
|
||||
(it uses STUN long term autentication method), hence client must be
|
||||
configured with the correct credential to use the service.
|
||||
|
||||
<b>Allocation</b>.\n
|
||||
Client creates one "relay port" (or called <b>relayed-transport-address</b>
|
||||
in TURN terminology) in the TURN server by sending TURN \a Allocate request,
|
||||
hence this process is called creating allocation. Once the allocation is
|
||||
successful, client will be given the IP address and port of the "relay
|
||||
port" in the Allocate response.
|
||||
|
||||
<b>Sending data through the relay</b>.\n
|
||||
Once allocation has been created, client may send data to any remote
|
||||
endpoints (called peers in TURN terminology) via the "relay port". It does
|
||||
so by sending Send Indication to the TURN server, giving the peer address
|
||||
in the indication message. But note that at this point peers are not allowed
|
||||
to send data towards the client (via the "relay port") before permission is
|
||||
installed for that peer.
|
||||
|
||||
<b>Creating permissions</b>.\n
|
||||
Permission needs to be created in the TURN server so that a peer can send
|
||||
data to the client via the relay port (a peer in this case is identified by
|
||||
its IP address). Without this, when the TURN server receives data from the
|
||||
peer in the "relay port", it will drop this data.
|
||||
|
||||
<b>Receiving data from peers</b>.\n
|
||||
Once permission has been installed for the peer, any data received by the
|
||||
TURN server (from that peer) in the "relay port" will be relayed back to
|
||||
client by using Data Indication.
|
||||
|
||||
<b>Using ChannelData</b>.\n
|
||||
TURN provides optimized framing to the data by using ChannelData
|
||||
packetization. The client activates this format by sending ChannelBind
|
||||
request to the TURN server, which provides (channel) binding which maps a
|
||||
particular peer address with a channel number. Data sent or received to/for
|
||||
this peer will then use ChannelData format instead of Send or Data
|
||||
Indications.
|
||||
|
||||
<b>Refreshing the allocation, permissions, and channel bindings</b>.\n
|
||||
Allocations, permissions, and channel bindings need to be refreshed
|
||||
periodically by client, or otherwise they will expire.
|
||||
|
||||
<b>Destroying the allocation</b>.\n
|
||||
Once the "relay port" is no longer needed, client destroys the allocation
|
||||
by sending Refresh request with LIFETIME attribute set to zero.
|
||||
|
||||
|
||||
\section turn_org_sec Library organizations
|
||||
|
||||
The TURN functionalities in PJNATH primarily consist of
|
||||
\ref PJNATH_TURN_SOCK and \ref PJNATH_TURN_SESSION. Please see more
|
||||
below.
|
||||
|
||||
|
||||
\section turn_using_sec Using TURN transport
|
||||
|
||||
The \ref PJNATH_TURN_SOCK is a ready to use object for relaying
|
||||
application data via a TURN server, by managing all the operations
|
||||
above.
|
||||
|
||||
Among other things it provides the following features:
|
||||
- resolution of the TURN server with DNS SRV
|
||||
- interface to create allocation, permissions, and channel
|
||||
bindings
|
||||
- interface to send and receive packets through the relay
|
||||
- provides callback to notify the application about incoming data
|
||||
- managing the allocation, permissions, and channel bindings
|
||||
|
||||
Please see \ref PJNATH_TURN_SOCK for more documentation about and
|
||||
on how to use this object.
|
||||
|
||||
|
||||
\section turn_owntransport_sec Creating custom TURN transport
|
||||
|
||||
The \ref PJNATH_TURN_SESSION is a transport-independent object to
|
||||
manage a client TURN session. It contains the core logic for managing
|
||||
the TURN client session as listed in TURN operations above, but
|
||||
in transport-independent manner (i.e. it doesn't have a socket), so
|
||||
that developer can integrate TURN client functionality into existing
|
||||
framework that already has its own means to send and receive data,
|
||||
or to support new transport types to TURN, such as TLS.
|
||||
|
||||
You can create your own (custom) TURN transport by wrapping this
|
||||
into your own object, and provide it with the means to send and
|
||||
receive packets.
|
||||
|
||||
Please see \ref PJNATH_TURN_SESSION for more information.
|
||||
|
||||
|
||||
\section turn_samples_sec Samples
|
||||
|
||||
The \ref turn_client_sample is a sample application to use the
|
||||
\ref PJNATH_TURN_SOCK. Also there is a sample TURN server in
|
||||
the distribution as well.
|
||||
|
||||
Also see <b>\ref samples_page</b> for other samples.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJNATH_TURN_SOCK TURN client transport
|
||||
* @brief Client transport utilizing TURN relay
|
||||
* @ingroup PJNATH_TURN
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJNATH_TURN_SESSION TURN client session
|
||||
* @brief Transport independent TURN client session
|
||||
* @ingroup PJNATH_TURN
|
||||
*/
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,305 @@
|
||||
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
|
||||
font-family: Geneva, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
BODY,TD {
|
||||
font-size: 80%;
|
||||
}
|
||||
CODE {
|
||||
font-size: 120%;
|
||||
font-family: monospace;
|
||||
}
|
||||
.fragment, pre {
|
||||
font-size: 110%;
|
||||
font-family: monospace;
|
||||
}
|
||||
H1 {
|
||||
text-align: center;
|
||||
font-size: 240%;
|
||||
}
|
||||
H2 {
|
||||
font-size: 200%;
|
||||
margin-top : 60px;
|
||||
}
|
||||
H3 {
|
||||
font-size: 160%;
|
||||
}
|
||||
H4 {
|
||||
font-size: 120%;
|
||||
}
|
||||
CAPTION { font-weight: bold }
|
||||
DIV.qindex {
|
||||
width: 100%;
|
||||
background-color: #eeeeff;
|
||||
border: 1px solid #b0b0b0;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.nav {
|
||||
width: 100%;
|
||||
background-color: #eeeeff;
|
||||
border: 1px solid #b0b0b0;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
A.qindex {
|
||||
text-decoration: none;
|
||||
font-size: 120%;
|
||||
color: #1A419D;
|
||||
}
|
||||
A.qindex:visited {
|
||||
text-decoration: none;
|
||||
color: #1A419D
|
||||
}
|
||||
A.qindex:hover {
|
||||
text-decoration: none;
|
||||
background-color: #ddddff;
|
||||
}
|
||||
A.qindexHL {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
border: 1px double #9295C2;
|
||||
}
|
||||
A.qindexHL:hover {
|
||||
text-decoration: none;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
}
|
||||
A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
|
||||
A.el { text-decoration: none; font-weight: bold }
|
||||
A.elRef { font-weight: bold }
|
||||
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF; }
|
||||
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
|
||||
A.codeRef:link { font-weight: normal; color: #0000FF}
|
||||
A.codeRef:visited { font-weight: normal; color: #0000FF}
|
||||
A:hover { text-decoration: none; background-color: #f2f2ff }
|
||||
DL.el { margin-left: -1cm }
|
||||
PRE.fragment {
|
||||
border: 1px solid #CCCCCC;
|
||||
background-color: #f5f5f5;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
margin-left: 2px;
|
||||
margin-right: 8px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
|
||||
TD.md { background-color: #F4F4FB; font-weight: bold; }
|
||||
TD.mdPrefix {
|
||||
background-color: #F4F4FB;
|
||||
color: #606060;
|
||||
font-size: 80%;
|
||||
}
|
||||
TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
|
||||
TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
|
||||
DIV.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
|
||||
BODY {
|
||||
background: white;
|
||||
color: black;
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
TD.indexkey {
|
||||
background-color: #eeeeff;
|
||||
font-weight: bold;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
TD.indexvalue {
|
||||
background-color: #eeeeff;
|
||||
font-style: italic;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
TR.memlist {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
P.formulaDsp { text-align: center; }
|
||||
IMG.formulaDsp { }
|
||||
IMG.formulaInl { vertical-align: middle; }
|
||||
SPAN.keyword { color: #008000 }
|
||||
SPAN.keywordtype { color: #604020 }
|
||||
SPAN.keywordflow { color: #e08000 }
|
||||
SPAN.comment { color: #800000 }
|
||||
SPAN.preprocessor { color: #806020 }
|
||||
SPAN.stringliteral { color: #002080 }
|
||||
SPAN.charliteral { color: #008080 }
|
||||
.mdTable {
|
||||
border: 1px solid #868686;
|
||||
background-color: #F4F4FB;
|
||||
}
|
||||
.mdRow {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
.mdescLeft {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.mdescRight {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.memItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplParams {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
color: #606060;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.search { color: #003399;
|
||||
font-weight: bold;
|
||||
}
|
||||
FORM.search {
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
INPUT.search { font-size: 75%;
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
background-color: #eeeeff;
|
||||
}
|
||||
TD.tiny { font-size: 75%;
|
||||
}
|
||||
a {
|
||||
color: #252E78;
|
||||
}
|
||||
a:visited {
|
||||
color: #3D2185;
|
||||
}
|
||||
.dirtab { padding: 4px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #b0b0b0;
|
||||
}
|
||||
TH.dirtab { background: #eeeeff;
|
||||
font-weight: bold;
|
||||
}
|
||||
HR { height: 1px;
|
||||
border: none;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
</TD></TD></TABLE>
|
||||
<p> </p>
|
||||
<hr><center>
|
||||
PJNATH - Open Source NAT traversal helper library supporting STUN, TURN, and ICE<br>
|
||||
Copyright (C) 2006-2009 Teluu Inc.
|
||||
</center>
|
||||
|
||||
|
||||
<!--#include virtual="/footer.html" -->
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
|
||||
<title>$title ($projectnumber)</title>
|
||||
<link href="/style/style.css" rel="stylesheet" type="text/css">
|
||||
</head><body>
|
||||
<!--#include virtual="/header.html" -->
|
||||
<TABLE border=0 width="90%"><TR><TD>
|
||||
<p><A HREF="/">Home</A> --> <A HREF="/docs.htm">Documentations</A> --> <A HREF="/pjnath/docs/html/index.htm">PJNATH Reference</A></p>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Reference in new issue
Block a user