On date Thursday 2009-01-08 17:37:21 +0200, Pekka Pessi phoned this:
> 2009/1/8 Stefano Sabatini <ssabat...@reilabs.com>:
> > I mean that when the REGISTER recipient doesn't reply, sofia-sip sends
> > again and again the REGISTER. I would like to catch this condition say
> > after N tries and when a certain timeout expires, and notify the
> > sofia-sip stack of this.
> >
> > Currently I see no way to say to the stack to stop to send the
> > REGISTER requests.
>
> The retransmissions are done as specified in RFC 3261. NTATAG_SIP_T1()
> defines the initial retransmission timer (500 ms), NTATAG_SIP_T1X64()
> defines the timeout (as the name implies it is 64 times T1 or 32
> seconds).
Hi Pekka and friends,
the attached sample catches the timeout event, which is sent
non-unexpectedly as a nua_r_register event with status 408 (the
application crashes with an assert when it is called nua_shutdown(), I
don't know exactly when it should be called).
As Inca Rose noted, the timeout defined by NTATAG_SIP_T1 and
NTATAG_SIP_T1X64 is defined *per user* rather than *per transaction*,
so in this case will be used that defined in the nua object.
Also as the RFC states it is duty of the agent to *retransmit* the
REGISTER request when it expires (the expiration time may be specified
in the request, otherwise it is set per registrar policy).
Maybe I'm missin something in the RFC, but the timeout specifics is
defined in the section 17.1.1., page 125, where it states:
If an unreliable transport is being
used, the client transaction MUST start timer A with a value of T1.
If a reliable transport is being used, the client transaction SHOULD
NOT start timer A (Timer A controls request retransmissions). For
any transport, the client transaction MUST start timer B with a value
of 64*T1 seconds (Timer B controls transaction timeouts).
When timer A fires, the client transaction MUST retransmit the
request by passing it to the transport layer, and MUST reset the
timer with a value of 2*T1.
[...]
If the client transaction is still in the "Calling" state when timer
B fires, the client transaction SHOULD inform the TU that a timeout
has occurred. The client transaction MUST NOT generate an ACK. The
value of 64*T1 is equal to the amount of time required to send seven
requests in the case of an unreliable transport.
Grepping the log I got this sequence of values for the retransmissions
timer:
nta: timer set next to 1000 ms
nta: timer set next to 2000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 489 ms
nta: timer set next to 500 ms
nta: timer set next to 1000 ms
nta: timer set next to 2000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 488 ms
nta: timer set next to 500 ms
nta: timer set next to 1000 ms
nta: timer set next to 2000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 495 ms
nta: timer set next to 500 ms
nta: timer set next to 1000 ms
nta: timer set next to 2000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 4000 ms
nta: timer set next to 496 ms
nta: timer set next to 5000 ms
using sofia sip 1.12.9, while I expect the sequence:
500
1000
2000
4000
8000
16000
32000
Am I missing something or there is some bug in the stack?
Again many thanks in advance, regards.
#include <stdlib.h>
#include <stdio.h>
#include <sofia-sip/nua.h>
#include <sofia-sip/su_log.h>
#include <sofia-sip/soa.h>
#include <sofia-sip/nua_tag.h>
#include <sofia-sip/sip_header.h>
/**
* Processes incoming events. This callback will be called by the SIP
* stack.
*/
void event_callback(nua_event_t event,
int status,
char const *phrase,
nua_t *nua,
nua_magic_t *magic,
nua_handle_t *nh,
nua_hmagic_t *hmagic,
sip_t const *sip,
tagi_t tags[])
{
static unsigned int count = 1;
msg_t* msg = NULL;
/* msg = nua_current_request(nua); */
printf("Event: number(%d) name(%s) status(%d) phrase(%s)\n",
count++, nua_event_name(event), status, phrase);
switch (event) {
case nua_r_register:
if (status == 408) {
printf("Timeout detected\n");
su_root_break((su_root_t *)magic);
}
break;
}
}
int send_register (nua_t *nua, const url_string_t* registrar)
{
nua_handle_t *handle;
sip_to_t* registrar_to;
registrar_to = sip_to_create(NULL, registrar);
if (!registrar_to)
return -1;
handle = nua_handle(nua,
NULL,
SIPTAG_TO(registrar_to),
TAG_END());
if (!handle) {
fprintf(stderr, "Failed to instantiate an handle for the registrar\n");
fprintf(stderr, "Maybe you are using an invalid SIP address or another instance of a sip client is running on the same port\n");
return -1;
}
fprintf(stderr, "Sending the registrar to %s\n", registrar);
nua_register(handle, TAG_END());
return 0;
}
int main (int argc, char *argv[])
{
su_root_t *root;
nua_t *nua;
su_log_set_level(NULL, 9);
setenv("TPORT_LOG", "1", 1);
if (argc <= 1) {
fprintf(stderr, "Missing the destination target sip uri");
exit(1);
}
const char* registrar = argv[1];
/* Initialize Sofia-SIP library */
su_init();
/* no context is passed to the root object */
/* create the root object */
root = su_root_create (NULL);
if (!root) {
fprintf(stderr, "Impossible to create a root thread, aborting.");
exit(1);
}
/* register the callback function to be executed in the root thread */
/* bind to the ports and register the callback function for events coming from the
* network (originating/incoming and response messages) */
nua = nua_create(root, /* Event loop */
event_callback, /* Callback for processing events */
root, /* Additional data to pass to callback */
NUTAG_URL("sip:gu...@*:5060"), /* try to bind to all the host interfaces */
TAG_END()); /* Last tag should always finish the sequence */
if (send_register(nua, URL_STRING_MAKE(registrar)) < 0)
exit(1);
/* Run event loop */
/* this should also handle sort of a disconnection event, when it arrives the
* thread exits from the event loop */
su_root_run(root);
/* cleanup */
nua_shutdown(nua);
nua_destroy(nua);
su_root_destroy(root);
su_deinit ();
exit(0);
}
------------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB
_______________________________________________
Sofia-sip-devel mailing list
Sofia-sip-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sofia-sip-devel