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

=head1 NAME

Net::SIP::Endpoint::Context - Call context for endpoint

=head1 SYNOPSIS

  my $ctx = Net::SIP::Endpoint::Context->new( to => .., from => .. );
  my $request = $ctx->new_request(..);

=head1 DESCRIPTION

This package manages the call context (from,to,call-id, recorded routes..) for
a call to an L<Net::SIP::Endpoint>. It maintains the state of the current
call (local and remote cseq, current state within INVITE transaction)
and handles requests and responses according to this state.

=head1 CONSTRUCTOR

=over 4

=item new ( ARGS )

ARGS is either a hash reference or a hash.
It contains the following mandatory keys:

=over 8

=item from

Initiator of call. This is the local address for outgoing calls
and the peers address for incoming calls.

=item to

Target of call.

=back

And the following optional keys:

=over 8

=item contact

Contact info for context.

=item incoming

Flag, if the context resulted from an incoming call.

=item auth

Authorization info, used if outgoing requests need authorization.
See method B<authorize> in L<Net::SIP::Request>
for information on the format.

=item route

\@List of predefined routes (which will be used to create B<Route> SIP
header in requests).

=item via

\@List of predefined B<Via> values used in locally generated responses.
This is usually set if the context was created by an incoming request
from the B<Via> header in the request.

=item callid

Value of B<Call-Id> header. If not given it will be generated.
It's usually given for incoming calls, but not for outgoing calls.

=item cseq

Initial local sequence number for the B<CSeq> SIP header.
Defaults to 0, e.g. the first request will get the sequence number 1.

=back

=back

=head1 METHODS

=over 4

=item callid

Returns callid of current call.

=item peer

Returns peer of call. For incoming calls this is the sender, for
outgoing calls the recipient of the call.

=item new_request ( METHOD, [ BODY, %ARGS ] )

Creates a new requests for method METHOD with body BODY and additional
SIP headers defined by %ARGS. The headers for C<to>, C<from>, C<contact>,
C<route> will be created from the call context info in C<$self>.

One special ARGS can be B<resp40x> which should point to a 401/407 SIP 
response containing the offer from the server for authorization. This way
authorization can be fully controlled, e.g. first trying w/o authorization
and then retrying with authorization credentials and the 40x response.

METHOD might be already a L<Net::SIP::Request> object in which case it
will be used unmodified. BODY might be a string or object (see constructor
of L<Net::SIP::Request>).

It will add the request to the list of active transactions within the
context C<$self>, e.g. will be prepared to get responses for it.
The callback for the transaction is copied from the default callback
for the context, so that it stays the same, even if the default callback
changes.

It returns the created request object.

=item find_outstanding_requests ( %FILTER )

Returns list of outstanding requests (e.g INVITE w/o reply) for this
context. Returns a list of outstanding request (L<Net::SIP::Request>
objects) with the most recent requests first.

FILTER might be used to restrict the search. With key B<request> a
L<Net::SIP::Request> object is expected and it will restrict the search to
this object (e.g. it will return the object if it is outstanding). With key
B<method> a method can be specified and only requests with this method will
be returned.

=item set_callback ( CALLBACK )

Sets callback for context, which will be used if the upper layer need to
be notified, e.g on incoming requests or an permanent delivery errors.
CALLBACK is a callback usable by B<invoke_callback> in L<Net::SIP::Util> and will be
invoked with the following arguments (some arguments make only sense for
incoming packets).

=over 8

=item CTX

The call context, e.g. C<$self>.

=item ENDPOINT

The L<Net::SIP::Endpoint> object managing CTX.

=item ERROR

The errno of the error occurred ( undef or 0 if no error ).
These are the same numbers defined in L<Errno>, but they are
usually not set by a system call, but by the dispatcher
(like ETIMEDOUT if delivery failed permanently after none of
the retransmits succeeded or EHOSTUNREACH if it cannot resolve
the SIP URI).

=item CODE

This is the response CODE from an incoming response packet.
Undef if the incoming packet was no response.

=item PACKET

This is the packet which caused the callback. Only for incoming
packets.

=item LEG

L<Net::SIP::Leg> where the packet came in.

=item FROM

C<< "ip:port" >> of sender of incoming packet.

=back


=item request_delivery_done ( ENDPOINT, TID, ERROR )

Callback setup at delivery of the packet and called with
ERROR FALSE if the packet was delivered successfully over
a reliable transport or with ERROR an errno if the packet
could not be delivered (or no reply came in for packet, so
one can assume that the recipient did not get it).

For details on ERROR see B<set_callback>.

TID is the transaction ID, see method B<tid> in L<Net::SIP::Packet>.
ENDPOINT is the endpoint managing the context C<$self>.


=item handle_response ( RESPONSE,LEG,FROM,ENDPOINT )

Called from the endpoints B<receive_response> method it handles
responses to requests originated from the context C<$self>.

RESPONSE is the response packet, LEG the leg where the packet
came in and FROM the C<< "ip:port" >> of the sender. ENDPOINT
is the endpoint managing the context C<$self>.

First it checks if the response matches an active transaction
(which begun its life in B<new_request>) and if not it drops
the response.

Then it checks if the response came in to the right leg, e.g. if
the B<Via> header of the packet matches the B<Via> header
the leg creates. If not the packet will be dropped.

Then it checks if the method in the B<CSeq> header of the response
matches the expected method in the transaction (for INVITEs this
could be either INVITE or ACK, depending on the state of the
transaction). If it not matches the packet will be dropped.
(All of these packet drops could be observed if you enable
debugging, see L<Net::SIP::Debug>.

If the response is for a BYE or CANCEL request the call
will be closed.

If the response is the unsuccessful final response for an
INVITE an ACK will be send, if it's preliminary response
it will invoke the callback for the transaction.

If the response is a successful final response for an INVITE
it will save the routes from the B<Record-Route> header for
future requests and create an ACK request. The transaction
callback will be invoked and gets as an additional argument
the created ACK request, which then can be modified by the
callback. The callback should not send the ACK request by
itself, it should just modify the given request and sending
will be done after the callback returned.

If the response is a successful final response to a request
other then INVITE it will invoke callback which should fully
handle the response.

If the response code is 401 (Unauthorized) or
407 (Proxy Authentication Required) and if the context has
authorization info (key B<auth> in the constructor)) it
will try to authorize the request based on the realms
given in the response and if it can find authorization info
for at least parts of the required realms it will
redeliver the request. Otherwise it will invoke the callback
with an error of EPERM.

If the response code is 300 (Multiple Choices) or 301
(moved permanently) it will invoke the callback because
it cannot resolve the issue automatically.
But if it's 302 (Moved Temporarily) it will rewrite the
request based on the B<Contact> header in the response
and redeliver it automatically.

If the response is 305 (Use Proxy) it will take the information
from B<Contact> as the upstream proxy and insert it into
the routes, so that it will use it as the next hop.
Then it rewrites the request for the new routes and redelivers it.

For all other responses the callback will be invoked, e.g
the issue has to be resolved by the users application.


=item handle_request ( REQUEST,LEG,FROM,ENDPOINT )

Called from the endpoints B<receive_request> method it handles
incoming requests for call context C<$self>.

REQUEST is the request packet, LEG the leg where the packet
came in and FROM the C<< "ip:port" >> of the sender. ENDPOINT
is the endpoint managing the context C<$self>.

First it checks if the sequence number of the incoming
request (B<CSeq> header) is not lower then the sequence
number of the last request received. Otherwise it will drop
the request.

The it checks if the sequence number is the same as for the
last request. If it is higher it must be a new request, otherwise
it is a retransmit or an ACK or CANCEL to an INVITE request.
If it's a retransmit it will be dropped.

If the incoming request is an INVITE it will automatically
deliver a response C<< 100 Trying >> and then invoke the
callback, so that the application might issue C<< 180 Ringing >>
responses and finally a final response, like C<< 200 Ok >>.

If the incoming request is CANCEL or BYE it will issue a
response C<< 200 Closing >> and close the context.

All other requests must be handled by the application, e.g.
the callback will be invoked.

=back