Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

SIP

...

Component

...

Available

...

as

...

of

...

Camel

...

2.5

...

The

...

sip

...

component

...

in

...

Camel

...

is

...

a

...

communication

...

component,

...

based

...

on

...

the

...

Jain

...

SIP

...

implementation

...

(available

...

under

...

the

...

JCP

...

license).

...

Session

...

Initiation

...

Protocol

...

(SIP)

...

is

...

an

...

IETF-defined

...

signaling

...

protocol,

...

widely

...

used

...

for

...

controlling

...

multimedia

...

communication

...

sessions

...

such

...

as

...

voice

...

and

...

video

...

calls

...

over

...

Internet

...

Protocol

...

(IP).The

...

SIP

...

protocol

...

is

...

an

...

Application

...

Layer

...

protocol

...

designed

...

to

...

be

...

independent

...

of

...

the

...

underlying

...

transport

...

layer;

...

it

...

can

...

run

...

on

...

Transmission

...

Control

...

Protocol

...

(TCP),

...

User

...

Datagram

...

Protocol

...

(UDP) or

...

Stream

...

Control

...

Transmission

...

Protocol

...

(SCTP).

The Jain SIP implementation supports TCP and UDP only.

The Camel SIP component only supports the SIP Publish and Subscribe capability as described in the RFC3903 - Session Initiation Protocol (SIP) Extension for Event

This camel component supports both producer and consumer endpoints.

Camel SIP Producers (Event Publishers) and SIP Consumers (Event Subscribers) communicate event & state information to each other using an intermediary entity called a SIP Presence Agent (a stateful brokering entity).

For SIP based communication, a SIP Stack with a listener must be instantiated on both the SIP Producer and Consumer (using separate ports if using localhost). This is necessary in order to support the handshakes & acknowledgements exchanged between the SIP Stacks during communication.

Maven users will need to add the following dependency to their pom.xml for this component:

Code Block
xml
xml
 SCTP is not supported by the Jain SIP implementation.

The Jain SIP implementation supports TCP and UDP only.

The Camel SIP component *only* supports the SIP Publish and Subscribe capability as described in the [RFC3903 - Session Initiation Protocol (SIP) Extension for Event|http://www.ietf.org/rfc/rfc3903.txt]

This camel component supports both producer and consumer endpoints.

Camel SIP Producers (Event Publishers) and SIP Consumers (Event Subscribers) communicate event & state information to each other using an intermediary entity called a SIP Presence Agent (a stateful brokering entity).
 
For SIP based communication, a SIP Stack with a listener *must* be instantiated on both the SIP Producer and Consumer (using separate ports if using localhost). This is necessary in order to support the handshakes & acknowledgements exchanged between the SIP Stacks during communication.

Maven users will need to add the following dependency to their {{pom.xml}} for this component:
{code:xml}
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-sip</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
{code}

h3. URI format

The URI scheme for a netty component is as follows

{code}

URI format

The URI scheme for a sip endpoint is as follows:

Code Block
sip://johndoe@localhost:99999[?options]
sips://johndoe@localhost:99999/[?options]
{code}

This

...

component

...

supports

...

producer

...

and

...

consumer

...

endpoints

...

for

...

both

...

TCP

...

and

...

UDP.

...

You

...

can

...

append

...

query

...

options

...

to

...

the

...

URI

...

in

...

the

...

following

...

format,

...

?option=value&option=value&...

Options

The SIP Component offers an extensive set of configuration options & capability to create custom stateful headers needed to propagate state via the SIP protocol.

Div
classconfluenceTableSmall

Name

Default Value

Description

stackName

NAME_NOT_SET

Name of the SIP Stack instance associated with an SIP Endpoint.

transport

tcp

Setting for choice of transport potocol. Valid choices are "tcp" or "udp".

fromUser

 

Username of the message originator. Mandatory setting unless a registry based custom FromHeader is specified.

fromHost

 

Hostname of the message originator. Mandatory setting unless a registry based FromHeader is specified

fromPort

 

Port of the message originator. Mandatory setting unless a registry based FromHeader is specified

toUser

 

Username of the message receiver. Mandatory setting unless a registry based custom ToHeader is specified.

toHost

 

Hostname of the message receiver. Mandatory setting unless a registry based ToHeader is specified

toPort

 

Portname of the message receiver. Mandatory setting unless a registry based ToHeader is specified

maxforwards

0

the number of intermediaries that may forward the message to the message receiver. Optional setting. May alternatively be set using as registry based MaxForwardsHeader

eventId

 

Setting for a String based event Id. Mandatory setting unless a registry based FromHeader is specified

eventHeaderName

 

Setting for a String based event Id. Mandatory setting unless a registry based FromHeader is specified

maxMessageSize

1048576

Setting for maximum allowed Message size in bytes.

cacheConnections

false

Should connections be cached by the SipStack to reduce cost of connection creation. This is useful if the connection is used for long running conversations.

consumer

false

This setting is used to determine whether the kind of header (FromHeader,ToHeader etc) that needs to be created for this endpoint

contentType

text

Setting for contentType can be set to any valid MimeType.

contentSubType

xml

Setting for contentSubType can be set to any valid MimeSubType.

receiveTimeoutMillis

10000

Setting for specifying amount of time to wait for a Response and/or Acknowledgement can be received from another SIP stack

useRouterForAllUris

false

This setting is used when requests are sent to the Presence Agent via a proxy.

msgExpiration

3600

The amount of time a message received at an endpoint is considered valid

presenceAgent

false

This setting is used to distingish between a Presence Agent & a consumer. This is due to the fact that the SIP Camel component ships with a basic Presence Agent (for testing purposes only). Consumers have to set this flag to true.

Registry based Options

SIP requires a number of headers to be sent/received as part of a request. These SIP header can be enlisted in the Registry, such as in the Spring XML file.

The values that could be passed in, are the following:

Div
classconfluenceTableSmall

Name

Description

fromHeader

a custom Header object containing message originator settings. Must implement the type javax.sip.header.FromHeader

toHeader

a custom Header object containing message receiver settings. Must implement the type javax.sip.header.ToHeader

viaHeaders

List of custom Header objects of the type javax.sip.header.ViaHeader. Each ViaHeader containing a proxy address for request forwarding. (Note this header is automatically updated by each proxy when the request arrives at its listener)

contentTypeHeader

a custom Header object containing message content details. Must implement the type javax.sip.header.ContentTypeHeader

callIdHeader

a custom Header object containing call details. Must implement the type javax.sip.header.CallIdHeader

maxForwardsHeader

a custom Header object containing details on maximum proxy forwards. This header places a limit on the viaHeaders possible. Must implement the type javax.sip.header.MaxForwardsHeader

eventHeader

a custom Header object containing event details. Must implement the type javax.sip.header.EventHeader

contactHeader

an optional custom Header object containing verbose contact details (email, phone number etc). Must implement the type javax.sip.header.ContactHeader

expiresHeader

a custom Header object containing message expiration details. Must implement the type javax.sip.header.ExpiresHeader

extensionHeader

a custom Header object containing user/application specific details. Must implement the type javax.sip.header.ExtensionHeader

Sending Messages to/from a SIP endpoint

Creating a Camel SIP Publisher

In the example below, a SIP Publisher is created to send SIP Event publications to
a user "agent@localhost:5152". This is the address of the SIP Presence Agent which acts as a broker between the SIP Publisher and Subscriber

  • using a SIP Stack named client
  • using a registry based eventHeader called evtHdrName
  • using a registry based eventId called evtId
  • from a SIP Stack with Listener set up as user2@localhost:3534
  • The Event being published is EVENT_A
  • A Mandatory Header called REQUEST_METHOD is set to Request.Publish thereby setting up the endpoint as a Event publisher"
Code Block
producerTemplate.sendBodyAndHeader(  
    "sip://agent@localhost:5152?stackName=client&eventHeaderName=evtHdrName&eventId=evtid&fromUser=user2&fromHost=localhost&fromPort=3534",   
    "EVENT_A",  
    "REQUEST_METHOD",   
    Request.PUBLISH);  

Creating a Camel SIP Subscriber

In the example below, a SIP Subscriber is created to receive SIP Event publications sent to
a user "johndoe@localhost:5154"

  • using a SIP Stack named Subscriber
  • registering with a Presence Agent user called agent@localhost:5152
  • using a registry based eventHeader called evtHdrName. The evtHdrName contains the Event which is se to "Event_A"
  • using a registry based eventId called evtId
Code Block
@Override  
protected RouteBuilder createRouteBuilder() throws Exception {  
    return new RouteBuilder() {  
        @Override  
        public void configure() throws Exception {    
            // Create PresenceAgent  
            from("sip://agent@localhost:5152?stackName=PresenceAgent&presenceAgent=true&eventHeaderName=evtHdrName&eventId=evtid")  
                .to("mock:neverland");  
                  
            // Create Sip Consumer(Event Subscriber)  
            from("sip://johndoe@localhost:5154?stackName=Subscriber&toUser=agent&toHost=localhost&toPort=5152&eventHeaderName=evtHdrName&eventId=evtid")  
                .to("log:ReceivedEvent?level=DEBUG")  }}

h3. Options

The SIP Component offers an extensive set of configuration options & capability to create custom stateful headers needed to propagate state via the SIP protocol.

{div:class=confluenceTableSmall}
|| Name || Default Value || Description ||
| {{stackName}} | {{NAME_NOT_SET}} | Name of the SIP Stack instance associated with an SIP Endpoint. |
| {{transport}} | {{tcp}} | Setting for choice of transport potocol. Valid choices are "tcp" or "udp". |
| {{fromUser}} |  | Username of the message originator. *Mandatory setting unless a registry based custom FromHeader is specified.* |
| {{fromHost}} |  | Hostname of the message originator. *Mandatory setting unless a registry based FromHeader is specified* |
| {{fromPort}} |  | Port of the message originator. *Mandatory setting unless a registry based FromHeader is specified* |
| {{toUser}} |  | Username of the message receiver. *Mandatory setting unless a registry based custom ToHeader is specified.* |
| {{toHost}} |  | Hostname of the message receiver. *Mandatory setting unless a registry based ToHeader is specified* |
| {{toPort}} |  | Portname of the message receiver. *Mandatory setting unless a registry based ToHeader is specified* |
| {{maxMessageSize}} | {{1048576}} | Setting for maximum allowed Message size in bytes. |
| {{cacheConnections}} | {{false}} | Should connections be cached by the SipStack to reduce cost of connection creation. This is useful if the connection is used for long running conversations. |
| {{consumer}} | {{false}} | This setting is used to determine whether the kind of header (FromHeader,ToHeader etc) that needs to be created for this endpoint|
| {{automaticDialogSupport}} | {{off}} | Setting to specify whether every communication should be associated with a dialog. |
| {{contentType}} | {{text}} | Setting for contentType can be set to any valid MimeType. |
| {{contentSubType}} | {{xml}} | Setting for contentSubType can be set to any valid MimeSubType. |
| {{receiveTimeoutMillis}} | {{10000}} | Setting for specifying amount of time to wait for a Response and/or Acknowledgement can be received from another SIP stack |
| {{useRouterForAllUris}} | {{false}} | This setting is used when requests are sent to the Presence Agent via a proxy. |
| {{msgExpiration}} | {{3600}} | The amount of time a message received at an endpoint is considered valid |
| {{presenceAgent}} | {{false}} | This setting is used to distingish between a Presence Agent & a consumer. This is due to the fact that the SIP Camel component ships with a basic Presence Agent (for testing purposes only). Consumers have to set this flag to true. |
{div}

h3. Registry based Options

SIP requires a number of headers to be sent/received as part of a request. These SIP header can be enlisted in the [Registry], such as in the Spring XML file.

The values that could be passed in, are the following:

{div:class=confluenceTableSmall}
|| Name || Description ||
| {{passphrase}} | password setting to use in order to encrypt/decrypt payloads sent using SSH |
| {{keyStoreFormat}} | keystore format to be used for payload encryption. Defaults to "JKS" if not set |
| {{securityProvider}} | Security provider to be used for payload encryption. Defaults to "SunX509" if not set. |
| {{keyStoreFile}} | Client side certificate keystore to be used for encryption |
| {{trustStoreFile}} | Server side certificate keystore to be used for encryption |
| {{sslHandler}} | Reference to a class that could be used to return an SSL Handler |
| {{encoder}} | A custom Handler class that can be used to perform special marshalling of outbound payloads. Must override {{org.jboss.netty.channel.ChannelDownStreamHandler}}. |
| {{encorders}} | A list of encoder to be used. You can use a String which have values separated by comma, and have the values be looked up in the [Registry]. Just remember to prefix the value with # so Camel knows it should lookup. |
| {{decoder}} | A custom Handler class that can be used to perform special marshalling of inbound payloads. Must override {{org.jboss.netty.channel.ChannelUpStreamHandler}}. |
| {{decoders}} | A list of decorder to be used. You can use a String which have values separated by comma, and have the values be looked up in the [Registry]. Just remember to prefix the value with # so Camel knows it should lookup. |
{div}

h3. Sending Messages to/from a Netty endpoint

h4. Netty Producer

In Producer mode, the component provides the ability to send payloads to a socket endpoint
using either TCP or UDP protocols (with optional SSL support).

The producer mode supports both one-way and request-response based operations.

h4. Netty Consumer

In Consumer mode, the component provides the ability to:
- listen on a specified socket using either TCP or UDP protocols (with optional SSL support),
- receive requests on the socket using text/xml, binary and serialized object based payloads and
- send them along on a route as message exchanges.

The consumer mode supports both one-way and request-response based operations.

h3. Usage Samples

h4. A UDP Netty endpoint using Request-Reply and serialized object payload
{code}
RouteBuilder builder = new RouteBuilder() {
  public void configure() {
    from("netty:udp://localhost:5155?sync=true")
      .process(new Processor() {
         public void process(Exchange exchange) throws Exception {
  .to("mock:notification");  
        Poetry poetry = (Poetry) exchange.getIn().getBody();
      
     poetry.setPoet("Dr. Sarojini Naidu");
 }  
    };    exchange.getOut().setBody(poetry);
         }
       }
    }
};
{code}

h4. A TCP based Netty consumer endpoint using One-way communication
{code}
RouteBuilder builder = new RouteBuilder() {
  public void configure() {
       from("netty:tcp://localhost:5150")
           .to("mock:result");
  }
};
{code}

h4. An SSL/TCP based Netty consumer endpoint using Request-Reply communication
{code}
JndiRegistry registry = new JndiRegistry(createJndiContext());
registry.bind("password", "changeit");
registry.bind("ksf", new File("src/test/resources/keystore.jks"));
registry.bind("tsf", new File("src/test/resources/keystore.jks"));

context.createRegistry(registry);
context.addRoutes(new RouteBuilder() {
  public void configure() {
      String netty_ssl_endpoint =
         "netty:tcp://localhost:5150?sync=true&ssl=true&passphrase=#password"
         + "&keyStoreFile=#ksf&trustStoreFile=#tsf";
      String return_string =
         "When You Go Home, Tell Them Of Us And Say,"
         + "For Your Tomorrow, We Gave Our Today.";

      from(netty_ssl_endpoint)
       .process(new Processor() {
          public void process(Exchange exchange) throws Exception {
            exchange.getOut().setBody(return_string);
          }
       }
  }
});
{code}

h4. Using Multiple Codecs

In certain cases it may be necessary to add chains of encoders and decoders to the netty pipeline. To add multpile codecs to a camel netty endpoint the 'encoders' and 'decoders' uri parameters should be used. Like the 'encoder' and 'decoder' parameters they are used to supply references (to lists of ChannelUpstreamHandlers and ChannelDownstreamHandlers) that should be added to the  pipeline. Note that if encoders is specified then the encoder param will be ignored, similarly for decoders and the decoder param.

The lists of codecs need to be added to the Camel's registry so they can be resolved when the endpoint is created.

{snippet:id=registry-beans|lang=java|url=camel/trunk/components/camel-netty/src/test/java/org/apache/camel/component/netty/MultipleCodecsTest.java}

Spring's native collections support can be used to specify the codec lists in an application context

{snippet:id=registry-beans|lang=xml|url=camel/trunk/components/camel-netty/src/test/resources/org/apache/camel/component/netty/multiple-codecs.xml}

The bean names can then be used in netty endpoint definitions either as a comma separated list or contained in a List e.g.

{snippet:id=routes|lang=java|url=camel/trunk/components/camel-netty/src/test/java/org/apache/camel/component/netty/MultipleCodecsTest.java}

or via spring.

{snippet:id=routes|lang=xml|url=camel/trunk/components/camel-netty/src/test/resources/org/apache/camel/component/netty/multiple-codecs.xml}

h3. Closing Channel When Complete

When acting as a server you sometimes want to close the channel when, for example, a client conversion is finished.
You can do this by simply setting the endpoint option {{disconnect=true}}.

However you can also instruct Camel on a per message basis as follows.
To instruct Camel to close the channel, you should add a header with the key {{CamelNettyCloseChannelWhenComplete}} set to a boolean {{true}} value.
For instance, the example below will close the channel after it has written the bye message back to the client:
{code}
        from("netty:tcp://localhost:8080").process(new Processor() {
            public void process(Exchange exchange) throws Exception {
                String body = exchange.getIn().getBody(String.class);
                exchange.getOut().setBody("Bye " + body);
                // some condition which determines if we should close
                if (close) {
                    exchange.getOut().setHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, true);
                }
            }
        });
{code}

h3. Adding custom channel pipeline factories to gain complete control over a created pipeline

*Available as of Camel 2.5*

Custom channel pipelines provide complete control to the user over the handler/interceptor chain by inserting custom handler(s), encoder(s) & decoders without having to specify them in the Netty Endpoint URL in a very simple way.

In order to add a custom pipeline, a custom channel pipeline factory must be created and registered with the context via the context registry (JNDIRegistry,or the camel-spring ApplicationContextRegistry etc).

A custom pipeline factory must be constructed as follows
* A Producer linked channel pipeline factory must extend the abstract class ClientPipelineFactory.
* A Consumer linked channel pipeline factory must extend the abstract class ServerPipelineFactory.
* The classes can optionally override the getPipeline() method in order to insert custom handler(s), encoder(s) and decoder(s). Not overriding the getPipeline() method creates a pipeline with no handlers, encoders or decoders wired to the pipeline.

The example below shows how ServerChannel Pipeline factory may be created
{code}
public class SampleServerChannelPipelineFactory extends ServerPipelineFactory {
    private int maxLineSize = 1024;
    private boolean invoked;

    public ChannelPipeline getPipeline() throws Exception {
        invoked = true;

        ChannelPipeline channelPipeline = Channels.pipeline();

        channelPipeline.addLast("encoder-SD", new StringEncoder(CharsetUtil.UTF_8));
        channelPipeline.addLast("decoder-DELIM", new DelimiterBasedFrameDecoder(maxLineSize, true, Delimiters.lineDelimiter()));
        channelPipeline.addLast("decoder-SD", new StringDecoder(CharsetUtil.UTF_8));
        channelPipeline.addLast("handler", new ServerChannelHandler(consumer));

        return channelPipeline;
    }

    public boolean isfactoryInvoked() {
        return invoked;
    }
}
{code}

The custom channel pipeline factory can then be added to the registry and instantiated/utilized on a camel route in the following way
{code}
Registry registry = camelContext.getRegistry();
serverPipelineFactory = new TestServerChannelPipelineFactory();
registry.bind("spf", serverPipelineFactory);
context.addRoutes(new RouteBuilder() {
  public void configure() {
      String netty_ssl_endpoint =
         "netty:tcp://localhost:5150?serverPipelineFactory=#spf"
      String return_string =
         "When You Go Home, Tell Them Of Us And Say,"
         + "For Your Tomorrow, We Gave Our Today.";

      from(netty_ssl_endpoint)
       .process(new Processor() {
          public void process(Exchange exchange) throws Exception {
            exchange.getOut().setBody(return_string);
          }
       }
  }
});

{code}

}  

The Camel SIP component also ships with a Presence Agent that is meant to be used for Testing and Demo purposes only. An example of instantiating a Presence Agent is given above.

Note that the Presence Agent is set up as a user agent@localhost:5152 and is capable of communicating with both Publisher as well as Subscriber. It has a separate SIP stackName distinct from Publisher as well as Subscriber. While it is set up as a Camel Consumer, it does not actually send any messages along the route to the endpoint "mock:neverland".