The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Net::SIP::Dispatcher - dispatch SIP packets between legs and endpoint

SYNOPSIS

  my $disp = Net::SIP::Dispatcher->new( ... );
  $disp->deliver( $request );

DESCRIPTION

This module dispatches Net::SIP::Packets between Net::SIP::Legs and endpoints like Net::SIP::Endpoint, Net::SIP::Registrar and Net::SIP::StatelessProxy.

It manages retransmission of outgoing packets and redelivery of responses to incoming requests.

It is asssociated with an event handling like Net::SIP::Dispatcher::Eventloop.

CONSTRUCTOR

new ( \@LEGS, EVENTLOOP, %ARGS )

Creates a new dispatcher object.

@LEGS is a list of legs or specification for legs. See add_leg for possible formats.

EVENTLOOP is a eventloop which provides handling of events on file descriptors and timers. If not given a new Net::SIP::Dispatcher::Eventloop object will be created and used. See there how to define your own event loop package.

%ARGS are parameters for the behavior of the dispatcher:

outgoing_proxy

Specifies "ip:port" of outgoing proxy, e.g the proxy which will be used for all outgoing packets.

If no leg but an outgoing proxy is specified a leg will be created which can reach the outgoing proxy by udp.

do_retransmits

If TRUE retransmits will be done accoring to RFC3261. If FALSE no retransmits will be done, which is used in the case of stateless proxies. Defaults to TRUE.

This is the default for the delivery and can be overwritten in sub deliver.

domain2proxy

Optional mapping between target SIP domain and proxy to use. This is usually a hash of ( domain, "ip_proxy:port_proxy" ) pairs. Special domain '*' can be used to specify a fallback and '*.domain' to include not only the domain but the subdomains too. See sub deliver for more details.

domain2leg

Optional mapping between target SIP domain and leg to use, similar to domain2proxy. It is a reference to a hash where the key is the domain and the value the Net::SIP::Leg object.

leg2proxy

Optional mapping between legs and outgoing proxies. This is a reference to a list of \@pairs, where the first part of the pair is the Net::SIP::Leg object and the second part is the "ip:port" of the proxy.

The constructor will create a timer using the eventloop which will regularly (each second) call queue_expire.

METHODS

set_receiver ( ENDPOINT )

This sets ENDPOINT as a receiver for incoming packets. ENDPOINT is an object with a method receive or a callback usable by invoke_callback in Net::SIP::Util.

add_leg ( LEG )

Adds LEG as a leg to the dispatcher $self. LEG can be either a Net::SIP::Leg object, a IO::Handle or a hash reference which is usable in the constructor of Net::SIP::Leg.

The leg will be added to the dispatchers eventloop for receiving incoming packets.

remove_leg ( LEG )

Removes Net::SIP::Leg object LEG from the dispatcher.

get_legs ( %ARGS )

Get a list of all Net::SIP::Leg objects matching the criteria given by %ARGS. %ARGS can be a combination of:

addr

Matches if given address matches the legs source address.

port

Matches if given port matches the legs source port.

proto

Matches if given proto ('udp','tcp') matches the legs protocol.

sock

Matches if the given IO::Handle is used as the socket in the leg.

sub

Call given sub with the Net::SIP::Leg as argument. Matches if the sub returns TRUE.

The leg matches %ARGS if the all conditions specified in %ARGS match.

add_timer ( WHEN, CALLBACK, [ REPEAT ] )

Adds a timer using the eventloop.

WHEN is either an absolute or a relative time (what it is will be decided based on the value of WHEN). Absolute times will be specified in time_t (seconds since 1970-01-01 00:00:00) and relative time will be specified in seconds. WHEN can be floating point to specifiy subseconds. WHEN can be 0 to trigger the timer immediatly.

CALLBACK is a callback usable by invoke_callback in Net::SIP::Util.

REPEAT is the optional repeat interval for the timer.

deliver ( PACKET, %ARGS )

Delivers Net::SIP::Packet PACKET. %ARGS can speciffy hints for delivery:

id

ID for packet, used in cancel_delivery. If not given the transaction ID of PACKET given by method tid will be used.

callback

callback which will be called on definite delivery of packet (only possible for TCP) or on definite failure. Callback will be invoked using invoke_callback from Net::SIP::Util with the additional argument of $!. See sub deliver in Net::SIP::Leg.

leg

Specifies outgoing Net::SIP::Leg object. For responses created by the endpoint the outgoing leg is usually known, because it's the same as the incoming leg for the request.

dst_addr

"ip:port" where to deliver the packet. This is necessary for responses, for requests it can be find out based on the requests URI.

do_retransmits

Specifies if retransmits should be done according to RFC3261. This is usually the case, except for stateless proxies. Overwrites the global parameter with the same name from the constructor for the delivery of the specific packet.

Delivery of the packet itself will be handled in multiple steps (in the code done mainly by sub __deliver:

  • If a leg is specified it will be used for delivery. dst_addr needs to be specified in this case too. This is usually the case for locally generated responses.

  • Otherwise leg and dst_addr will be retrieved using resolve_uri. See there.

If the packets could be retransmitted appropriate setups will be done. Retransmission will be done until final failure or until cancel_delivery will be called for the packet, which usually means, that the packet was successfully delivered because a response to the packet was received.

resolve_uri ( URI, ADDR_REF, LEG_REF, CALLBACK )

Resolves URI to get the destination address and the outgoing leg. ADDR_REF and LEG_REF are references which will get filled with the computed values.

Because the method can be asynchronous (DNS lookups can be involved) it will call CALLBACK once it is done. If no errors occured CALLBACK will be invoked without additional arguments, otherwise with the errno as additional argument.

Resolving will be done as follows:

  • If domain2proxy is given it will try to get the dst_addr from this, e.g. the address of the proxy responsable for the domain (if any). From dst_addr it will then get the leg.

  • If still no leg is known but domain2leg it will try to get the leg from this (but still no dst_addr). This option makes usually only sense in connection with leg2proxy and without domain2proxy.

  • If no dst_addr is known but a leg (mostly when domain2leg is used) it will try to use leg2proxy to find out the outgoing proxy for the leg.

  • If still no dst_addr is known it will use outgoing_proxy as the dst_addr.

  • If still no dst_addr is known but the SIP domain is an IP address this will be used as dst_addr.

  • The last effort will be made by looking up the SIP domain using DNS with a partial implementation of RFC3263, e.g. it looks at the DNS SRV records but not at NAPTR records.

  • The outgoing leg will be computed based on dst_addr. This will be done in sub __find_leg4addr by going through all legs and checking, if the leg could deliver to this address by calling can_deliver_to on the leg (see Net::SIP::Leg).

cancel_delivery ( ID )

Cancels retransmission of packet with id ID. Called from endpoint if response to packet came in, which means that the packet was successfully delivered.

receive ( PACKET, LEG, FROM )

Called from the eventloop (e.g was setup as a callback) for incoming packets. The new Net::SIP::Packet is PACKET, LEG is the Net::SIP::Leg where the packet came in and FROM is "ip:port" of the sender.

queue_expire ( [ NOW ] )

Expires retransmission queue, e.g. deletes packet where retransmissions failed permanently (and calls appropriate callbacks) and initiates pending retransmissions. Called from a timer setup in the constructor.