nua_register.c 44.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2006 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@CFILE nua_register.c
 * @brief REGISTER and registrations
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Wed Mar  8 11:48:49 EET 2006 ppessi
 */

#include "config.h"

#include <sofia-sip/string0.h>
36
#include <sofia-sip/su_strlst.h>
37 38 39 40 41
#include <sofia-sip/sha1.h>
#include <sofia-sip/su_uniqueid.h>
#include <sofia-sip/token64.h>
#include <sofia-sip/su_tagarg.h>

42 43
#include <sofia-sip/bnf.h>

44
#include <sofia-sip/sip_protos.h>
45
#include <sofia-sip/sip_util.h>
46
#include <sofia-sip/sip_status.h>
47 48 49

#define NTA_LEG_MAGIC_T      struct nua_handle_s
#define NTA_OUTGOING_MAGIC_T struct nua_handle_s
50
#define NTA_UPDATE_MAGIC_T   struct nua_s
51

52
#include "nua_stack.h"
53
#include <sofia-sip/nta_tport.h>
54 55 56 57 58

#if HAVE_SIGCOMP
#include <sigcomp.h>
#endif

59 60 61 62 63 64 65
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#include <assert.h>

66 67 68 69
#if !defined(random) && defined(_WIN32)
#define random rand
#endif

70 71 72 73 74 75 76 77 78 79 80
/* ====================================================================== */
/* Outbound connection */

typedef struct outbound_connect outbound_connect;
typedef struct outbound_owner_vtable outbound_owner_vtable;

int outbound_connect_init(outbound_connect *ru,
			  outbound_owner_vtable const *owner_methods,
			  su_root_t *root,
			  nta_agent_t *agent,
			  char const *options);
81

82
int outbound_connect_set_options(outbound_connect *oc, char const *options);
83

84
int outbound_connect_set_features(outbound_connect *ru, char *features);
85

86
int outbound_connect_check_for_nat(struct outbound_connect *ru,
87 88 89
				 nta_outgoing_t *orq,
				 sip_t const *sip);

90
int outbound_connect_contacts_from_via(outbound_connect *ru,
91 92 93
				     sip_via_t const *via,
				     sip_via_t const *pair);

94
int outbound_connect_set_contact(struct outbound_connect *ru,
95 96
			       sip_contact_t *m);

97
int outbound_connects_from_via(struct outbound_connect **list,
98 99 100 101
			     nua_owner_t *owner,
			     sip_via_t const *via,
			     int public);

102
int outbound_connect_set_contact_by_aor(struct outbound_connect *ru,
103
				      url_t const *aor,
104
				      outbound_connect const *defaults);
105

106
outbound_connect *outbound_connect_by_aor(outbound_connect const *usages,
107 108 109
				      url_t const *aor,
				      int only_default);

110
void outbound_connect_start_keepalive(struct outbound_connect *ru,
111 112
				    unsigned interval,
				    nta_outgoing_t *register_trans);
113

114
void outbound_connect_stop_keepalive(struct outbound_connect *ru);
115

116
int outbound_connect_check_accept(sip_accept_t const *accept);
117

118 119 120
int outbound_connect_process_options(struct outbound_connect *usages,
				     nta_incoming_t *irq,
				     sip_t const *sip);
121

122
sip_contact_t const *outbound_connect_contact(outbound_connect const *ru);
123

124 125
char const * const outbound_connect_content_type;
nua_usage_class const *nua_outbound_connect;
126

127
struct outbound_owner_vtable
128
{
129 130
  int oo_size;
  int (*oo_status)(nua_owner_t *, outbound_connect *ru,
131 132
		   int status, char const *phrase,
		   tag_type_t tag, tag_value_t value, ...);
133 134 135 136 137 138
  int (*oo_probe_error)(nua_owner_t *, outbound_connect *ru,
			int status, char const *phrase,
			tag_type_t tag, tag_value_t value, ...);
  int (*oo_keepalive_error)(nua_owner_t *, outbound_connect *ru,
			    int status, char const *phrase,
			    tag_type_t tag, tag_value_t value, ...);
139
};
140

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
struct outbound_connect {
  struct outbound_connect *oc_next, **oc_prev; /* Doubly linked list */
  outbound_owner_vtable
  const *oc_oo;			/**< Callbacks */
  nua_owner_t *oc_owner;	/**< Backpointer */
  su_root_t *oc_root;		/**< Root for timers and stuff */
  nta_agent_t *oc_nta;		/**< SIP transactions */

  char oc_cookie[32];		/**< Our magic cookie */

  int32_t oc_reg_id;		/**< Flow-id */

  struct outbound_prefs {
    unsigned gruuize:1;		/**< Establish a GRUU */
    unsigned outbound:1;	/**< Try to use outbound */
    unsigned natify:1;		/**< Try to detect NAT */
    unsigned validate:1;	/**< Validate registration with OPTIONS */
    /* How to detect NAT binding or connect to outbound: */
    unsigned use_connect:1;	/**< Use HTTP connect */
    unsigned use_rport:1;	/**< Use received/rport */
    unsigned use_socks:1;	/**< Detect and use SOCKS V5 */
    unsigned use_upnp:1;	/**< Detect and use UPnP */
    unsigned use_stun:1;	/**< Detect and try to use STUN */
    unsigned :0;
  } oc_prefs;

  struct outbound_info {
    /* 0 do not support, 1 - perhaps supports, 2 supports, 4 requires */
    unsigned gruu:2, outbound:2, pref:2;
  } oc_info;

  unsigned oc_default:1, oc_secure:1, oc_public:1;
  unsigned oc_by_application:1;
  unsigned oc_add_contact:1;
175

176
  /* The registration state machine. */
177 178 179 180
  /**< Initial REGISTER containing oc_rcontact has been sent */
  unsigned oc_registering:1;
  /**< 2XX response to REGISTER containg oc_rcontact has been received */
  unsigned oc_registered:1;
181 182 183
  /**< The registration has been validated:
   *   We have successfully sent OPTIONS to ourselves.
   */
184
  unsigned oc_validated:1;
185 186 187 188
  /**< The registration has been validated once.
   *   We have successfully sent OPTIONS to ourselves, so do not give
   *   up if OPTIONS probe fails.
   */
189
  unsigned oc_once_validated:1;
190

191
  unsigned :0;
192

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
  tport_t *oc_tport;		/**< Transport used when registered */
  char const *oc_features;	/**< Feature parameters for rcontact */
  sip_via_t *oc_via;		/**< Our Via (or Via pair) */
  sip_contact_t *oc_rcontact;	/**< Our contact */
  sip_contact_t *oc_dcontact;	/**< Contact for dialogs */
  sip_contact_t *oc_previous;	/**< Stale contact */
  sip_contact_t *oc_gruu;	/**< Contact added to requests */
  sip_route_t *oc_route;	/**< Outgoing Service-Route */
  sip_path_t *oc_path;		/**< Incoming Path */
  sip_contact_t *oc_obp;	/**< Contacts from outbound proxy */

  char *oc_nat_detected;	/**< Our public address */
  char *oc_nat_port;		/**< Our public port number */

  void *oc_stun;		/**< Stun context */
  void *oc_upnp;		/**< UPnP context  */

  char *oc_sipstun;		/**< Stun server usable for keep-alives */
  unsigned oc_keepalive;	/**< Interval. */
  su_timer_t *oc_kalt;		/**< Keep-alive timer */
  msg_t *oc_kalmsg;		/**< Keep-alive OPTIONS message */
  nta_outgoing_t *oc_kalo;	/**< Keep-alive OPTIONS transaction */
215

216
#if HAVE_SIGCOMP
217
  struct sigcomp_compartment *oc_compartment;
218 219
#endif
};
220

221 222 223
/* ======================================================================== */
/* REGISTER */

224 225
static void restart_register(nua_handle_t *nh, tagi_t *tags);
static void refresh_register(nua_handle_t *, nua_dialog_usage_t *, sip_time_t);
226 227 228 229 230

static int process_response_to_register(nua_handle_t *nh,
					nta_outgoing_t *orq,
					sip_t const *sip);

231 232
static void unregister_expires_contacts(msg_t *msg, sip_t *sip);

233
static char *nua_stack_register_features(nua_handle_t *nh);
234

235
static int nua_stack_register_status(nua_handle_t *, outbound_connect *oc,
236 237 238
				     int status, char const *phrase,
				     tag_type_t tag, tag_value_t value, ...);

239
static int nua_stack_register_failed(nua_handle_t *, outbound_connect *oc,
240 241 242
				     int status, char const *phrase,
				     tag_type_t tag, tag_value_t value, ...);

243
outbound_owner_vtable nua_stack_register_callbacks = {
244 245 246 247 248 249
    sizeof nua_stack_register_callbacks,
    nua_stack_register_status,
    nua_stack_register_failed,
    nua_stack_register_failed,
  };

250
int
251 252
nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e,
		   tagi_t const *tags)
253 254
{
  nua_dialog_usage_t *du;
255
  struct outbound_connect *oc = NULL;
256 257 258
  struct nua_client_request *cr = nh->nh_cr;
  msg_t *msg = NULL;
  sip_t *sip;
259
  int terminating = e != nua_r_register;
260 261 262 263 264 265

  if (nh->nh_special && nh->nh_special != nua_r_register)
    return UA_EVENT2(e, 500, "Invalid handle for REGISTER");
  if (cr->cr_orq)
    return UA_EVENT2(e, 500, "Request already in progress");

266
  nua_stack_init_handle(nua, nh, nh_has_register, "", TAG_NEXT(tags));
267
  nh->nh_special = nua_r_register;
268

269
  du = nua_dialog_usage_add(nh, nh->nh_ds, nua_outbound_connect, NULL);
270 271
  if (!du)
    return UA_EVENT1(e, NUA_500_ERROR);
272 273 274 275 276
  oc = nua_dialog_usage_private(du); assert(oc);

  outbound_connect_init(oc, &nua_stack_register_callbacks,
			nh->nh_nua->nua_root, nh->nh_nua->nua_nta,
			NH_PGET(nh, outbound));
277

278
  outbound_connect_set_features(oc, nua_stack_register_features(nh));
279

280
  outbound_connect_stop_keepalive(oc);
281

282 283
  if (du->du_msg)
    cr->cr_msg = msg_ref_create(du->du_msg);
284

285
  msg = nua_creq_msg(nua, nh, cr, cr->cr_msg != NULL,
286
		     SIP_METHOD_REGISTER,
287
		     TAG_IF(!terminating, NUTAG_USE_DIALOG(1)),
288 289 290
		     TAG_NEXT(tags));
  sip = sip_object(msg);

291 292
  if (sip) {
    du->du_terminating = terminating;
293

294 295 296 297
    if (du->du_msg)
      msg_destroy(du->du_msg);
    du->du_msg = msg_ref_create(cr->cr_msg);

298
    if (sip->sip_contact)
299
      outbound_connect_set_contact(oc, sip->sip_contact);
300

301 302 303
    if (!oc->oc_rcontact) {
      outbound_connect_set_contact_by_aor(oc, sip->sip_to->a_url,
					  nh->nh_nua->nua_registrations);
304
      /* Try first time without contact if we are not natifying */
305
      oc->oc_add_contact = !oc->oc_prefs.natify;
306 307 308 309 310 311 312
    }

    if (terminating)
      /* Add Expires: 0 and remove expire parameter from contacts */
      unregister_expires_contacts(msg, sip);

    cr->cr_orq =
313 314 315
      nta_outgoing_mcreate(nua->nua_nta,
			   process_response_to_register, nh, NULL,
			   msg,
316 317 318 319
			   TAG_IF(oc->oc_add_contact,
				  SIPTAG_CONTACT(oc->oc_rcontact)),
			   TAG_IF(oc->oc_add_contact,
				  SIPTAG_CONTACT(oc->oc_previous)),
320 321 322
			   SIPTAG_END(),
			   TAG_IF(terminating, NTATAG_SIGCOMP_CLOSE(1)),
			   TAG_IF(!terminating, NTATAG_COMP("sigcomp")),
323
			   TAG_NEXT(tags));
324 325

    if (cr->cr_orq)
326
      oc->oc_registering = 1;
327
  }
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344

  if (!cr->cr_orq) {
    msg_destroy(msg);
    msg_destroy(cr->cr_msg), cr->cr_msg = NULL;
    return UA_EVENT1(e, NUA_500_ERROR);
  }

  cr->cr_usage = du;

  return cr->cr_event = e;
}

static void
restart_register(nua_handle_t *nh, tagi_t *tags)
{
  struct nua_client_request *cr = nh->nh_cr;
  msg_t *msg;
345
  nua_dialog_usage_t *du = cr->cr_usage;
346
  struct outbound_connect *oc = nua_dialog_usage_private(du);
347
  int unregistering = du && du->du_terminating;
348
  sip_contact_t *contact = NULL, *previous = NULL;
349 350 351 352 353 354 355

  cr->cr_restart = NULL;

  if (!cr->cr_msg)
    return;

  msg = nua_creq_msg(nh->nh_nua, nh, cr, 1,
356 357 358 359 360 361 362 363
		     SIP_METHOD_UNKNOWN,
		     TAG_NEXT(tags));

  if (!msg)
    return;			/* Uh-oh */

  if (unregistering)
    unregister_expires_contacts(msg, sip_object(msg));
364

365 366 367 368 369
  if (oc) {
    if (oc->oc_add_contact) {
      contact = oc->oc_rcontact;
      if (oc->oc_previous && oc->oc_previous->m_expires)
	previous = oc->oc_previous;
370 371
    }
  }
372

373 374 375 376 377
  cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta,
				    process_response_to_register, nh, NULL,
				    msg,
				    SIPTAG_CONTACT(contact),
				    SIPTAG_CONTACT(previous),
378 379
				    SIPTAG_END(), TAG_NEXT(tags));

380
  if (cr->cr_orq) {
381
    oc->oc_registering = 1;
382 383
  }
  else
384 385 386 387 388 389 390 391 392 393
    msg_destroy(msg);
}

static
int process_response_to_register(nua_handle_t *nh,
				 nta_outgoing_t *orq,
				 sip_t const *sip)
{
  struct nua_client_request *cr = nh->nh_cr;
  nua_dialog_usage_t *du = cr->cr_usage;
394
  struct outbound_connect *oc = nua_dialog_usage_private(du);
395 396 397 398 399
  int status;
  char const *phrase;
  sip_t *req = sip_object(cr->cr_msg);

  assert(sip);
400
  assert(du && du->du_class == nua_outbound_connect);
401 402 403 404 405 406
  status = sip->sip_status->st_status;
  phrase = sip->sip_status->st_phrase;

  if (status < 200 || !du)
    return nua_stack_process_response(nh, cr, orq, sip, TAG_END());

407 408
  nua_dialog_store_peer_info(nh, nh->nh_ds, sip);

409
  if (oc->oc_prefs.natify && status >= 200) {
410 411
    int reregister;

412
    reregister = outbound_connect_check_for_nat(oc, orq, sip);
413 414 415 416

    if (reregister < 0)
      SET_STATUS2(500, nua_500_error);
    else if (reregister > 0) {
417 418 419
      msg_t *msg = msg_ref_create(cr->cr_msg);
      if (nua_creq_check_restart(nh, cr, orq, sip, restart_register)) {
	msg_destroy(msg);
420
	return 0;
421 422 423 424
      }

      assert(cr->cr_msg == NULL);
      cr->cr_msg = msg;
425

426
      if (reregister > 1) {
427
	/* We can try to reregister immediately */
428 429 430
	nua_creq_restart_with(nh, cr, orq, 100, "Updated Contact",
			      restart_register,
			      TAG_END());
431 432 433 434 435
      }
      else {
	nua_creq_save_restart(nh, cr, orq, 100, "Updated Contact",
			      restart_register);
      }
436

437 438 439
      return 0;
    }
  }
440

441 442 443 444 445 446
  if (status >= 300) {
    if (nua_creq_check_restart(nh, cr, orq, sip, restart_register))
      return 0;
    du->du_ready = 0;
  }
  else if (status < 300) {
447 448
    du->du_ready = 1;

449
    if (!du->du_terminating && sip->sip_contact)
450
      oc->oc_registered = oc->oc_registering;
451
    else
452
      oc->oc_registered = 0;
453

454
    if (oc->oc_registered) {
455 456 457 458
      sip_time_t now = sip_now(), delta, mindelta;
      sip_contact_t const *m, *m0;

      /** Search for lowest delta of SIP contacts in sip->sip_contact */
459
      mindelta = SIP_TIME_MAX;
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474

      for (m = sip->sip_contact; m; m = m->m_next) {
	if (m->m_url->url_type != url_sip)
	  continue;
	for (m0 = req->sip_contact; m0; m0 = m0->m_next)
	  if (url_cmp(m->m_url, m0->m_url) == 0) {
	    delta = sip_contact_expires(m, sip->sip_expires, sip->sip_date,
					3600, /* XXX */
					now);
	    if (delta > 0 && delta < mindelta)
	      mindelta = delta;
	    break;
	  }
      }

475 476 477
      if (mindelta == SIP_TIME_MAX)
	mindelta = 3600;

478 479
      nua_dialog_usage_set_refresh(du, mindelta);
      du->du_pending = refresh_register;
480 481 482 483 484 485
    }

    if (!du->du_terminating) {
#if HAVE_SIGCOMP
      struct sigcomp_compartment *cc;
      cc = nta_outgoing_compartment(orq);
486 487
      sigcomp_compartment_unref(oc->oc_compartment);
      oc->oc_compartment = cc;
488 489 490
#endif
    }
  }
491

492
  /*  RFC 3608 Section 6.1 Procedures at the UA
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507

   The UA performs a registration as usual.  The REGISTER response may
   contain a Service-Route header field.  If so, the UA MAY store the
   value of the Service-Route header field in an association with the
   address-of-record for which the REGISTER transaction had registered a
   contact.  If the UA supports multiple addresses-of-record, it may be
   able to store multiple service routes, one per address-of-record.  If
   the UA refreshes the registration, the stored value of the Service-
   Route is updated according to the Service-Route header field of the
   latest 200 class response.  If there is no Service-Route header field
   in the response, the UA clears any service route for that address-
   of-record previously stored by the UA.  If the re-registration
   request is refused or if an existing registration expires and the UA
   chooses not to re-register, the UA SHOULD discard any stored service
   route for that address-of-record.
508

509 510
  */
  if (!du->du_terminating && status < 300) {
511 512
    su_free(nh->nh_home, oc->oc_route);
    oc->oc_route = sip_route_dup(nh->nh_home, sip->sip_service_route);
513 514
  }
  else {
515 516
    su_free(nh->nh_home, oc->oc_route);
    oc->oc_route = NULL;
517
  }
518

519 520 521 522 523
  /* RFC 3327 */
  /* We are mainly interested in the last part of the Path header */
  if (!du->du_terminating && status < 300) {
    sip_path_t *path = sip->sip_path;

524
    while (path && path->r_next)
525 526
      path = path->r_next;

527 528 529 530
    if (!oc->oc_path || !path ||
	url_cmp_all(oc->oc_path->r_url, path->r_url)) {
      su_free(nh->nh_home, oc->oc_path);
      oc->oc_path = sip_path_dup(nh->nh_home, path);
531 532 533
    }
  }

534
  if (!du->du_terminating && status < 300) {
535
    if (!oc->oc_prev) {
536
      /* Add to the list of registrations */
537 538 539 540
      if ((oc->oc_next = nh->nh_nua->nua_registrations))
	oc->oc_next->oc_prev = &oc->oc_next;
      oc->oc_prev = &nh->nh_nua->nua_registrations;
      nh->nh_nua->nua_registrations = oc;
541 542 543
    }
  }

544 545
  if (!du->du_terminating && status < 300 && oc->oc_nat_detected)
    outbound_connect_start_keepalive(oc, 15, orq);
546
  else
547
    outbound_connect_stop_keepalive(oc);
548

549 550 551
  return nua_stack_process_response(nh, cr, orq, sip, TAG_END());
}

552
void
553 554 555 556
refresh_register(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now)
{
  nua_t *nua = nh->nh_nua;
  nua_client_request_t *cr = nh->nh_cr;
557
  outbound_connect *oc = nua_dialog_usage_private(du);
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
  nua_event_t e;
  msg_t *msg;
  sip_t *sip;

  if (cr->cr_msg) {
    /* Delay of 5 .. 15 seconds */
    nua_dialog_usage_set_refresh(du, 5 + (unsigned)random() % 11U);
    du->du_pending = refresh_register;
    return;
  }

  if (now > 0)
    e = nua_r_register;
  else
    e = nua_r_destroy, du->du_terminating = 1;

574
  outbound_connect_stop_keepalive(oc);
575

576 577 578 579 580 581 582 583
  cr->cr_msg = msg_ref_create(du->du_msg);
  msg = nua_creq_msg(nua, nh, cr, 1,
		     SIP_METHOD_REGISTER,
		     NUTAG_USE_DIALOG(1),
		     TAG_END());
  sip = sip_object(msg);

  if (sip) {
584
    int unregistering = now == 0;
585
    sip_contact_t *contact, *previous;
586 587 588 589

    if (unregistering)
      unregister_expires_contacts(msg, sip);

590 591 592 593 594
    if (oc) {
      if (oc->oc_add_contact) {
	contact = oc->oc_rcontact;
	if (oc->oc_previous && oc->oc_previous->m_expires)
	  previous = oc->oc_previous;
595 596 597
      }
    }

598 599 600
    cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta,
				      process_response_to_register, nh, NULL,
				      msg,
601 602
				      SIPTAG_CONTACT(contact),
				      SIPTAG_CONTACT(previous),
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
				      SIPTAG_END(), TAG_NEXT(NULL));
  }

  if (!cr->cr_orq) {
    if (du->du_terminating)
      nua_dialog_usage_remove(nh, nh->nh_ds, du);
    msg_destroy(msg);
    msg_destroy(cr->cr_msg);
    UA_EVENT2(e, NUA_500_ERROR, TAG_END());
    return;
  }

  cr->cr_usage = du;
  cr->cr_event = e;
}
618

619
/* ---------------------------------------------------------------------- */
620
/* Register usage interface */
621

622
static void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta);
623

624 625 626 627 628 629
int
nua_stack_registrations_init(nua_t *nua)
{
  /* Create initial identities: peer-to-peer, public, sips */
  sip_via_t const *v;
  nua_handle_t *dnh = nua->nua_dhandle;
630

631 632
  v = nta_agent_public_via(nua->nua_nta);
  if (v) {
633
    outbound_connects_from_via(&nua->nua_registrations, dnh, v, 1);
634
  }
635

636 637
  v = nta_agent_via(nua->nua_nta);
  if (v) {
638
    outbound_connects_from_via(&nua->nua_registrations, dnh, v, 0);
639
  }
640 641
  else {
    sip_via_t v[2];
642

643 644 645 646 647 648
    sip_via_init(v)->v_next = v + 1;
    v[0].v_protocol = sip_transport_udp;
    v[0].v_host = "addr.is.invalid.";
    sip_via_init(v + 1);
    v[1].v_protocol = sip_transport_tcp;
    v[1].v_host = "addr.is.invalid.";
649

650
    outbound_connects_from_via(&nua->nua_registrations, dnh, v, 0);
651 652
  }

653
  nta_agent_bind_tport_update(nua->nua_nta, nua,
654
			      nua_stack_tport_update);
655

656 657 658 659 660 661
  return 0;
}

static
void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta)
{
662 663
  outbound_connect *default_oc;
  outbound_connect const *defaults = nua->nua_registrations;
664 665
  sip_via_t *via = nta_agent_via(nta);
  
666
  default_oc = outbound_connect_by_aor(defaults, NULL, 1);
667

668 669
  if (default_oc) {
    assert(default_oc->oc_via);
670

671
    outbound_connect_contacts_from_via(default_oc,
672 673 674 675 676 677 678
				     via,
				     via->v_next);

    /* refresh_register(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now); */
  }

  return;
679 680
}

681

682 683 684 685
sip_contact_t const *nua_contact_by_aor(nua_t *nua,
					url_t const *aor,
					int only_default)
{
686
  outbound_connect *oc = nua->nua_registrations;
687

688
  oc = outbound_connect_by_aor(oc, aor, only_default);
689

690
  return outbound_connect_contact(oc);
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
}

/** Return a string descibing our features. */
static
char *nua_stack_register_features(nua_handle_t *nh)
{
  char *retval;
  su_strlst_t *l = su_strlst_create(NULL);
  su_home_t *home = su_strlst_home(l);

  if (!l)
    return NULL;

  if (NH_PGET(nh, instance))
    su_slprintf(l, ";+sip.instance=\"<%s>\"", NH_PGET(nh, instance));

  if (NH_PGET(nh, callee_caps)) {
    sip_allow_t const *allow = NH_PGET(nh, allow);

    if (allow) {
      su_strlst_append(l, ";methods=\"");
      if (allow->k_items) {
	int i;
	for (i = 0; allow->k_items[i]; i++) {
	  su_strlst_append(l, allow->k_items[i]);
	  if (allow->k_items[i + 1])
	    su_strlst_append(l, ",");
	}
      }
      su_strlst_append(l, "\"");
    }

    if (nh->nh_soa) {
      char **media = soa_media_features(nh->nh_soa, 0, home);

      while (*media) {
	su_strlst_append(l, ";");
	su_strlst_append(l, *media++);
      }
    }
  }

  retval = su_strlst_join(l, nh->nh_home, "");

  su_strlst_destroy(l);

  return retval;
}

/** Remove (possible non-zero) "expires" parameters from contacts and extra
 *  contacts, add Expire: 0.
 */
static
void unregister_expires_contacts(msg_t *msg, sip_t *sip)
{
  sip_contact_t *m;
  int unregister_all;

  /* Remove payload */
  while (sip->sip_payload)
    sip_header_remove(msg, sip, (sip_header_t *)sip->sip_payload);
  while (sip->sip_content_type)
    sip_header_remove(msg, sip, (sip_header_t *)sip->sip_content_type);

  for (m = sip->sip_contact; m; m = m->m_next) {
    if (m->m_url->url_type == url_any)
      break;
    msg_header_remove_param(m->m_common, "expires");
#if 0
    msg_header_add_param(msg_home(msg), m->m_common, "expires=0");
#endif
  }

  unregister_all = m && (m != sip->sip_contact || m->m_next);

  sip_add_tl(msg, sip,
	     /* Remove existing contacts */
	     TAG_IF(unregister_all, SIPTAG_CONTACT(NONE)),
	     /* Add '*' contact: 0 */
	     TAG_IF(unregister_all, SIPTAG_CONTACT_STR("*")),
	     SIPTAG_EXPIRES_STR("0"),
	     TAG_END());
}


776 777
/** Callback from outbound_connect */
static int nua_stack_register_status(nua_handle_t *nh, outbound_connect *oc,
778 779 780 781 782 783 784
				     int status, char const *phrase,
				     tag_type_t tag, tag_value_t value, ...)
{
  ta_list ta;

  ta_start(ta, tag, value);

785 786
  nua_stack_event(nh->nh_nua, nh, NULL,
		  nua_i_outbound, status, phrase,
787 788 789 790 791 792 793
		  ta_tags(ta));

  ta_end(ta);

  return 0;
}

794 795
/** Callback from outbound_connect */
static int nua_stack_register_failed(nua_handle_t *nh, outbound_connect *oc,
796 797 798 799 800 801
				     int status, char const *phrase,
				     tag_type_t tag, tag_value_t value, ...)
{
  ta_list ta;
  ta_start(ta, tag, value);

802 803
  nua_stack_event(nh->nh_nua, nh, NULL,
		  nua_i_outbound, status, phrase,
804 805 806 807 808 809 810 811 812 813 814
		  ta_tags(ta));

  ta_end(ta);

  return 0;
}

/* ====================================================================== */
/* Register-usage side */

static
815
int outbound_connect_nat_detect(outbound_connect *oc, sip_via_t const *v);
816 817 818 819

/* ---------------------------------------------------------------------- */

/** Check if there is a NAT between us and registrar */
820
int outbound_connect_check_for_nat(struct outbound_connect *oc,
821 822 823 824 825
				 nta_outgoing_t *orq,
				 sip_t const *sip)
{
  sip_via_t *v = sip->sip_via;
  int binding_changed;
826
  sip_contact_t *m = oc->oc_rcontact;
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842

#if 0
  if (host_is_domain(v->v_host)) {
    /*
     * If we use domain name in Via, we assume that application
     * knows something we don't.
     * Just use ordinary contact unless domain name ends with ".invalid"
     */
    char const *invalid = strcasestr(v->v_host, ".invalid");

    if (invalid)
      invalid += (sizeof ".invalid") - 1;
    if (invalid && invalid[0] == '.') /* ... or .invalid. */
      invalid++;

    if (!invalid || invalid[0] != '\0') {
843
      if (!oc->oc_rcontact)
844
	...
845
      if (!oc->oc_rcontact)
846 847 848 849 850 851
	return -1;
      return 0;
    }
  }
#endif

852
  binding_changed = outbound_connect_nat_detect(oc, v);
853 854

  /* Contact was set by application, do not change it */
855
  if (oc->oc_by_application)
856 857
    return 0;

858 859
  if (!oc->oc_nat_detected) {
    if (oc->oc_add_contact)
860
      return 0;
861
    oc->oc_add_contact = 1;
862 863 864 865 866 867 868 869 870 871 872 873
    return 2;
  }

  /* We have detected NAT. Now, what to do?
   * 1) do nothing - register as usual and let proxy take care of it?
   * 2) try to detect our public nat binding and use it
   * 2A) use public vias from nta generated by STUN or UPnP
   * 2B) use SIP Via header
   */

  /* Do we have to ask for reregistration */
  if (!m || binding_changed > 1) {
874
    if (oc->oc_stun) {
875 876 877
      /* Use STUN? */
      return 1;
    }
878
    else if (oc->oc_upnp) {
879
      /* Use UPnP */
880 881 882
      return 1;
    }
    else {
883
      if (outbound_connect_contacts_from_via(oc, sip->sip_via, NULL) < 0)
884
	return -1;
885
      oc->oc_add_contact = 1;
886 887
    }

888
    return 2;
889 890 891 892 893
  }

  return 0;
}

894 895 896 897 898 899 900 901
/** Based on "received" and possible "rport" parameters, check and update
 *  our NAT status.
 *
 * @retval 2 change in public NAT binding detected
 * @retval 1 NAT binding detected
 * @retval 0 no NAT binding detected
 * @retval -1 an error occurred
 */
902
static
903 904
int outbound_connect_nat_detect(outbound_connect *oc,
				sip_via_t const *v)
905
{
906 907 908 909 910 911
  int one = 1;
  char const *received, *rport;
  char *nat_detected, *nat_port;
  char *new_detected, *new_port;
  su_home_t *home;

912
  if (!oc || !v)
913 914 915 916 917 918 919
    return -1;

  received = v->v_received;
  if (!received)
    return 0;

  rport = sip_via_port(v, &one); assert(rport);
920

921 922
  nat_detected = oc->oc_nat_detected;
  nat_port = oc->oc_nat_port;
923 924 925

  if (nat_detected && strcasecmp(received, nat_detected) == 0 &&
      nat_port && strcasecmp(rport, nat_port) == 0)
926
    return 1;
927 928

  if (!nat_detected) {
929
    SU_DEBUG_1(("outbound_connect: detected NAT: %s != %s\n",
930
		v->v_host, received));
931 932
    if (oc->oc_oo && oc->oc_oo->oo_status)
      oc->oc_oo->oo_status(oc->oc_owner, oc, 101, "NAT detected", TAG_END());
933
  }
934
  else {
935
    SU_DEBUG_1(("outbound_connect: NAT binding changed: "
936 937
		"[%s]:%s != [%s]:%s\n",
		nat_detected, nat_port, received, rport));
938 939
    if (oc->oc_oo && oc->oc_oo->oo_status)
      oc->oc_oo->oo_status(oc->oc_owner, oc, 102, "NAT binding changed", TAG_END());
940 941 942 943
  }

  /* Save our nat binding */

944
  home = (su_home_t *)oc->oc_owner;
945 946 947 948 949 950 951 952 953 954

  new_detected = su_strdup(home, received);
  new_port = su_strdup(home, rport);

  if (!new_detected || !new_port) {
    su_free(home, new_detected);
    su_free(home, new_port);
    return -1;
  }

955 956
  oc->oc_nat_detected = new_detected;
  oc->oc_nat_port = new_port;
957 958 959 960 961

  su_free(home, nat_detected);
  su_free(home, nat_port);

  return 2;
962
}
963

964
/* ---------------------------------------------------------------------- */
965

966
static int create_keepalive_message(struct outbound_connect *oc,
967
				    sip_t const *register_request);
968

969 970
static int keepalive_options(outbound_connect *oc);
static int keepalive_options_with_registration_probe(outbound_connect *oc);
971

972
static int response_to_keepalive_options(nua_owner_t *oc_casted_as_owner,
973 974
					 nta_outgoing_t *orq,
					 sip_t const *sip);
975

976 977
static void keepalive_timer(su_root_magic_t *root_magic,
			    su_timer_t *t,
978
			    su_timer_arg_t *oc_as_timer_arg);
979

980
void outbound_connect_start_keepalive(struct outbound_connect *oc,
981 982 983
				    unsigned interval,
				    nta_outgoing_t *register_transaction)
{
984 985
  if (oc->oc_kalt)
    su_timer_destroy(oc->oc_kalt), oc->oc_kalt = NULL;
986

987
  if (interval)
988
    oc->oc_kalt = su_timer_create(su_root_task(oc->oc_root),
989
				  /* 1000 * */ 100 * interval);
990

991
  oc->oc_keepalive = interval;