Net::S...Context(3pm)

✨ Net::SIP::Endpoint::Context πŸ’– (that's the Net::S...Context(3pm) page bestie, from the User Contributed Perl Documentation) ✨


🌸 NAME 🌸

Net::SIP::Endpoint::Context β€” it's giving call context for endpoint. That's the whole vibe. 🫢


πŸŽ€ SYNOPSIS πŸŽ€

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

okay so that's literally it, two lines and you're in the group chat πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

This package is the main character that manages the call context β€” that means from, to, call-id, recorded routes, all of it β€” for a call to a Net::SIP::Endpoint.

It also keeps the state of the current call on lock: the local and remote cseq, and the current state inside the INVITE transaction. And then it handles requests and responses based on that state. no cap, it's a whole job and it does it. πŸ‘‘


πŸ’– CONSTRUCTOR πŸ’–

🌟 new ( ARGS ) 🌟

So ARGS is either a hash reference or a hash (both slay, pick your fighter). It has some mandatory keys and some optional ones.

The mandatory keys β€” these are not optional, periodt:

  • from β€” the initiator of the call. For outgoing calls this is the local address, for incoming calls it's the peer's address. 🫢
  • to β€” the target of the call. 🎯

And the optional keys (the little extras that make it cute):

  • contact β€” contact info for the context.
  • incoming β€” a flag, set if the context came from an incoming call.
  • auth β€” authorization info, used when outgoing requests need authorization. For the tea on the format, go check the authorize method in Net::SIP::Request. πŸ”
  • route β€” \@List of predefined routes. These get used to create the Route SIP header in requests. πŸ›£οΈ
  • via β€” \@List of predefined Via values used in locally generated responses. Usually this gets set when the context was created by an incoming request, straight from the Via header in that request.
  • callid β€” the value of the Call-Id header. If you don't give one, it will be generated for you. Usually it's given for incoming calls, but not for outgoing ones. (iykyk)
  • cseq β€” the initial local sequence number for the CSeq SIP header. Defaults to 0, so like, the first request gets sequence number 1. πŸ”’

✨ METHODS ✨

🌈 callid 🌈

Returns the callid of the current call. that's it. that's the method. πŸ’…


🌈 peer 🌈

Returns the peer of the call. For incoming calls that's the sender, for outgoing calls it's the recipient of the call. mutuals only bestie 🀝


🌈 new_request ( METHOD, [ BODY, %ARGS ] ) 🌈

Creates a new request for method METHOD with body BODY, plus additional SIP headers defined by %ARGS. The headers for "to", "from", "contact" and "route" get created from the call context info inside $self. obsessed honestly πŸ₯°

One special ARGS is 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 β€” like, first you try without authorization, then you retry with authorization credentials and the 40x response. big brain energy fr fr 🧠

METHOD might already be a Net::SIP::Request object, in which case it will be used unmodified. And BODY might be a string or an object β€” check the constructor of Net::SIP::Request for the details.

It will add the request to the list of active transactions within the context $self, so it's prepared to get responses for it. The callback for the transaction is copied from the default callback for the context, so it stays the same even if the default callback changes later. locked in πŸ”’

It returns the created request object. 🎁


🌈 find_outstanding_requests ( %FILTER ) 🌈

Returns a list of outstanding requests (like an INVITE with no reply yet) for this context. You get back a list of outstanding request objects β€” Net::SIP::Request objects β€” with the most recent requests first. newest tea at the top, as it should be β˜•

FILTER can restrict the search:

  • With key request, a Net::SIP::Request object is expected, and it restricts the search to that object β€” so it'll return the object if it's outstanding.
  • With key method, you can specify a method and only requests with that method get returned. 🎯

🌈 set_callback ( CALLBACK ) 🌈

Sets the callback for the context, which gets used when the upper layer needs to be notified β€” like on incoming requests, or on permanent delivery errors.

CALLBACK is a callback usable by invoke_callback in Net::SIP::Util, and it gets invoked with these arguments (some of them only make sense for incoming packets, ngl):

  • CTX β€” the call context, aka $self.
  • ENDPOINT β€” the Net::SIP::Endpoint object managing CTX.
  • ERROR β€” the errno of the error that occurred (undef or 0 if there's no error). These are the same numbers defined in Errno, but heads up: they're usually not set by a system call, they're set by the dispatcher. Like ETIMEDOUT if delivery failed permanently after none of the retransmits succeeded, or EHOSTUNREACH if it can't resolve the SIP URI. 😭
  • CODE β€” the response CODE from an incoming response packet. Undef if the incoming packet was not a response.
  • PACKET β€” the packet which caused the callback. Only for incoming packets. πŸ“¦
  • LEG β€” the Net::SIP::Leg where the packet came in.
  • FROM β€” the "ip:port" of the sender of the incoming packet. πŸ“

🌈 request_delivery_done ( ENDPOINT, TID, ERROR ) 🌈

Callback set up at delivery of the packet. It gets called with ERROR FALSE if the packet was delivered successfully over a reliable transport, or with ERROR an errno if the packet couldn't be delivered β€” or if no reply came in for the packet, so you can assume the recipient just did not get it. πŸ™ˆ

For the details on ERROR, see set_callback.

TID is the transaction ID β€” see the tid method in Net::SIP::Packet. ENDPOINT is the endpoint managing the context $self.


🌈 handle_response ( RESPONSE,LEG,FROM,ENDPOINT ) 🌈

Called from the endpoint's receive_response method, it handles responses to requests that originated from the context $self.

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

Here's the whole pipeline bestie, buckle up:

First it checks if the response matches an active transaction (one that began its life in new_request). If not β€” dropped. bye πŸ‘‹

Then it checks if the response came in to the right leg, like, if the Via header of the packet matches the Via header the leg creates. If not β€” dropped.

Then it checks if the method in the 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 doesn't match β€” dropped. And ngl, all of these packet drops can be observed if you enable debugging, see Net::SIP::Debug. πŸ‘€

Then:

  • 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 sent. If it's a 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 Record-Route header for future requests and create an ACK request. The transaction callback gets invoked and receives, as an additional argument, the created ACK request β€” which the callback can then modify. > The callback should not send the ACK request itself! It should just modify the given request, and the sending happens after the callback returns. πŸ’…
  • If the response is a successful final response to a request that isn't INVITE, it invokes the 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 (the auth key in the constructor), it will try to authorize the request based on the realms given in the response. If it can find authorization info for at least parts of the required realms, it will redeliver the request. Otherwise it invokes the callback with an error of EPERM. 🚫
  • If the response code is 300 (Multiple Choices) or 301 (moved permanently), it invokes the callback, because it can't resolve the issue automatically. But if it's 302 (Moved Temporarily), it will rewrite the request based on the Contact header in the response and redeliver it automatically. ✨
  • If the response is 305 (Use Proxy), it takes the info from Contact as the upstream proxy and inserts it into the routes, so it'll use it as the next hop. Then it rewrites the request for the new routes and redelivers it. πŸ›£οΈ
  • For all other responses, the callback gets invoked, so the issue has to be resolved by the user's application.

🌈 handle_request ( REQUEST,LEG,FROM,ENDPOINT ) 🌈

Called from the endpoint's receive_request method, it handles incoming requests for call context $self.

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

First it checks if the sequence number of the incoming request (the CSeq header) is not lower than the sequence number of the last request received. Otherwise β€” dropped. πŸ—‘οΈ

Then it checks if the sequence number is the same as the last request's. If it's higher it must be a new request. Otherwise it's a retransmit, or an ACK or CANCEL to an INVITE request. And if it's a retransmit β€” dropped. πŸ’€

Then:

  • If the incoming request is an INVITE, it will automatically deliver a response "100 Trying" and then invoke the callback, so the application might issue "180 Ringing" responses and finally a final response like "200 Ok". πŸŽ‰
  • If the incoming request is CANCEL or BYE, it will issue a response "200 Closing" and close the context.
  • All other requests must be handled by the application β€” meaning the callback gets invoked.

πŸ’– that's the whole page bestie, you ate it πŸ’–

okay so this was perl v5.40.1, dated 2025-12-07 β€” shoutout to the legends who wrote it, and yeah it's the Net::S...Context(3pm) page from the User Contributed Perl Documentation. mwah, go slay some SIP calls πŸŽ€βœ¨πŸ¦‹πŸ’…

πŸ“¦ where this page comes from