nua_session.c 141 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
/*
 * 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_session.c
26
 * @brief SIP session handling
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Wed Mar  8 16:17:27 EET 2006 ppessi
 */

#include "config.h"

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#include <assert.h>

42
#include <sofia-sip/su_string.h>
43 44 45
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sip_util.h>
46
#include <sofia-sip/su_uniqueid.h>
47

48
#define NTA_INCOMING_MAGIC_T struct nua_server_request
Pekka Pessi's avatar
Pekka Pessi committed
49
#define NTA_OUTGOING_MAGIC_T struct nua_client_request
50
#define NTA_RELIABLE_MAGIC_T struct nua_server_request
51 52 53 54 55 56 57 58

#include "nua_stack.h"
#include <sofia-sip/soa.h>

#ifndef SDP_H
typedef struct sdp_session_s sdp_session_t;
#endif

59
/* ---------------------------------------------------------------------- */
60

61 62 63 64 65 66 67 68 69 70 71 72
/** @enum nua_callstate

The states for SIP session established with INVITE.

Initially the call states follow the state of the INVITE transaction. If the
initial INVITE transaction fails, the call is terminated. The status codes
401 and 407 are an exception: if the client (on the left side in the diagram
below) receives them, it enters in #nua_callstate_authenticating state.

If a re-INVITE transaction fails, the result depends on the status code in
failure. The call can return to the ready state, be terminated immediately,
or be terminated gracefully. The proper action to take is determined with
73
sip_response_terminates_dialog().
74 75

@sa @ref nua_call_model, #nua_i_state, nua_invite(), #nua_i_invite
76 77 78 79 80

@par Session State Diagram

@code
  			 +----------+
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
  			 |          |---------------------+
  			 |   Init   |                     |
  			 |          |----------+          |
  			 +----------+          |          |
  			  |        |           |          |
                 --/INVITE|        |INVITE/100 |          |
                          V        V           |          |
     		+----------+      +----------+ |          |
       +--------|          |      |          | |          |
       |  18X +-| Calling  |      | Received | |INVITE/   |
       |   /- | |          |      |          | |  /18X    |
       |      V +----------+      +----------+ V          |
       |   +----------+ |           |     |  +----------+ |
       |---|          | |2XX     -/ |  -/ |  |          | |
       |   | Proceed- | | /-     2XX|  18X|  |  Early   | |INVITE/
       |   |   ing    | |           |     +->|          | |  /200
       |   +----------+ V           V        +----------+ |
       |     |  +----------+      +----------+   | -/     |
       |  2XX|  |          |      |          |<--+ 2XX    |
       |   /-|  | Complet- |      | Complete |<-----------+
       |     +->|   ing    |      |          |------+
       |        +----------+      +----------+      |
       |                  |        |      |         |
       |401,407/     -/ACK|        |ACK/- |timeout/ |
       | /ACK             V        V      | /BYE    |
       |                 +----------+     |         |
       |                 |          |     |         |
       |              +--|  Ready   |     |         |
       |              |  |          |     |         |
       |              |  +----------+     |         |
       |              |       |           |         |
       |         BYE/ |       |-/BYE      |         |BYE/
       V         /200 |       V           |         |/200
  +----------+        |  +----------+     |         |
  |          |        |  |          |     |         |
  |Authentic-|        |  | Terminat-|<----+         |
  |  ating   |        |  |   ing    |               |
  +----------+        |  +----------+               |
                      |       |                     |
                      |       |[23456]XX/-          |
                      |       V                     |
                      |  +----------+               |
                      |  |          |               |
                      +->|Terminated|<--------------+
                         |          |
                         +----------+
127
                              |
128 129 130 131 132
                              V
                         +----------+
        		 |          |
                         |   Init   |
			 |          |
133
          		 +----------+
134 135 136
@endcode
*/

137 138 139
/* ---------------------------------------------------------------------- */
/* Session event usage */

Pekka Pessi's avatar
Pekka Pessi committed
140
/** @internal @brief Session-related state. */
141 142
typedef struct nua_session_usage
{
143
  enum nua_callstate ss_state;		/**< Session status (enum nua_callstate) */
144

145 146
  unsigned        ss_100rel:1;	        /**< Use 100rel, send 183 */
  unsigned        ss_alerting:1;	/**< 180 is sent/received */
147

148 149 150 151
  unsigned        ss_update_needed:2;	/**< Send an UPDATE (do O/A if > 1) */

  unsigned        ss_precondition:1;	/**< Precondition required */

Pekka Pessi's avatar
Pekka Pessi committed
152
  unsigned        ss_reporting:1;       /**< True if reporting state */
153
  unsigned        : 0;
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

  struct session_timer {
    unsigned  interval;		/**< Negotiated expiration time */
    enum nua_session_refresher refresher; /**< Our Negotiated role */

    struct {
      unsigned expires, defaults; /**< Value of Session-Expires (delta) */
      unsigned min_se;	/**< Minimum session expires */
      /** none, local or remote */
      enum nua_session_refresher refresher;
      unsigned    supported:1, require:1, :0;
    } local, remote;

    unsigned      timer_set:1;  /**< We have active session timer. */
  } ss_timer[1];
169

Pekka Pessi's avatar
Pekka Pessi committed
170
  char const     *ss_reason;	        /**< Reason for termination. */
171 172 173

  /* Offer-Answer status */
  char const     *ss_oa_recv, *ss_oa_sent;
174 175

  /**< Version of user SDP from latest successful O/A */
176
  int ss_sdp_version;
177
} nua_session_usage_t;
178

179 180
static char const Offer[] = "offer", Answer[] = "answer";

181
static char const *nua_session_usage_name(nua_dialog_usage_t const *du);
182
static int nua_session_usage_add(nua_handle_t *nh,
183 184
				 nua_dialog_state_t *ds,
				 nua_dialog_usage_t *du);
185
static void nua_session_usage_remove(nua_handle_t *nh,
186
				     nua_dialog_state_t *ds,
187 188 189
				     nua_dialog_usage_t *du,
				     nua_client_request_t *cr,
				     nua_server_request_t *sr);
190
static void nua_session_usage_refresh(nua_owner_t *,
191
				      nua_dialog_state_t *,
192 193 194
				      nua_dialog_usage_t *,
				      sip_time_t now);
static int nua_session_usage_shutdown(nua_owner_t *,
195 196
				      nua_dialog_state_t *,
				      nua_dialog_usage_t *);
197

198 199 200 201 202
static void signal_call_state_change(nua_handle_t *nh,
				      nua_session_usage_t *ss,
				      int status, char const *phrase,
				      enum nua_callstate next_state);

203
static int nua_invite_client_should_ack(nua_client_request_t const *cr);
204
static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags);
205
static int nua_invite_client_complete(nua_client_request_t *cr);
206

207 208
static nua_usage_class const nua_session_usage[1] = {
  {
209
    sizeof (nua_session_usage_t),
210 211 212 213
    sizeof nua_session_usage,
    nua_session_usage_add,
    nua_session_usage_remove,
    nua_session_usage_name,
214
    nua_base_usage_update_params,
215 216 217
    NULL,
    nua_session_usage_refresh,
    nua_session_usage_shutdown
218 219 220 221 222 223 224
  }};

static char const *nua_session_usage_name(nua_dialog_usage_t const *du)
{
  return "session";
}

225 226
static
int nua_session_usage_add(nua_handle_t *nh,
227 228 229
			   nua_dialog_state_t *ds,
			   nua_dialog_usage_t *du)
{
230
  nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du);
231

232 233 234
  if (ds->ds_has_session)
    return -1;
  ds->ds_has_session = 1;
235
  ds->ds_got_session = 1;
236

237 238 239
  ss->ss_timer->local.refresher = nua_any_refresher;
  ss->ss_timer->remote.refresher = nua_any_refresher;

240 241 242
  return 0;
}

243 244
static
void nua_session_usage_remove(nua_handle_t *nh,
245 246 247 248
			      nua_dialog_state_t *ds,
			      nua_dialog_usage_t *du,
			      nua_client_request_t *cr0,
			      nua_server_request_t *sr0)
249
{
250
  nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du);
251
  nua_client_request_t *cr, *cr_next;
252
  nua_server_request_t *sr;
253 254 255 256 257 258 259

  /* Destroy queued INVITE transactions */
  for (cr = ds->ds_cr; cr; cr = cr_next) {
    cr_next = cr->cr_next;

    if (cr->cr_method != sip_method_invite)
      continue;
260

261 262 263
    if (cr == cr0)
      continue;

264 265
    nua_client_request_ref(cr);

266 267 268 269 270 271
    if (nua_invite_client_should_ack(cr)) {
      ss->ss_reporting = 1;
      nua_invite_client_ack(cr, NULL);
      ss->ss_reporting = 0;
    }

272
    if (cr == du->du_cr && cr->cr_orq)
273 274
      continue;

275
    if (cr->cr_status < 200) {
276
      nua_stack_event(nh->nh_nua, nh,
277
		      NULL,
Kai Samposalo's avatar
Kai Samposalo committed
278
		      (enum nua_event_e)cr->cr_event,
279 280 281
		      SIP_481_NO_TRANSACTION,
		      NULL);
    }
282

283
    nua_client_request_remove(cr);
284

285 286
    nua_client_request_unref(cr);

287 288
    cr_next = ds->ds_cr;
  }
289

290 291 292 293
  if (ss->ss_state != nua_callstate_terminated &&
      ss->ss_state != nua_callstate_init &&
      !ss->ss_reporting) {
    int status = 0; char const *phrase = "Terminated";
294 295

    if (cr0)
296 297 298 299 300 301 302
      status = cr0->cr_status, phrase = cr0->cr_phrase ? cr0->cr_phrase : phrase;
    else if (sr0)
      status = sr0->sr_status, phrase = sr0->sr_phrase;

    signal_call_state_change(nh, ss, status, phrase, nua_callstate_terminated);
  }

303 304 305 306 307 308
  /* Application can respond to BYE after the session usage has terminated */
  for (sr = ds->ds_sr; sr; sr = sr->sr_next) {
    if (sr->sr_usage == du && sr->sr_method == sip_method_bye)
      sr->sr_usage = NULL;
  }

309 310 311 312 313 314 315
  ds->ds_has_session = 0;
  nh->nh_has_invite = 0;
  nh->nh_active_call = 0;
  nh->nh_hold_remote = 0;

  if (nh->nh_soa)
    soa_destroy(nh->nh_soa), nh->nh_soa = NULL;
Pekka Pessi's avatar
Pekka Pessi committed
316
}
317

Pekka Pessi's avatar
Pekka Pessi committed
318 319 320 321 322
static
nua_dialog_usage_t *nua_dialog_usage_for_session(nua_dialog_state_t const *ds)
{
  if (ds == ((nua_handle_t *)NULL)->nh_ds)
    return NULL;
323

Pekka Pessi's avatar
Pekka Pessi committed
324
  return nua_dialog_usage_get(ds, nua_session_usage, NULL);
325 326 327
}

static
328
nua_session_usage_t *nua_session_usage_for_dialog(nua_dialog_state_t const *ds)
329 330 331 332 333 334 335 336 337
{
  nua_dialog_usage_t *du;

  if (ds == ((nua_handle_t *)NULL)->nh_ds)
    return NULL;

  du = nua_dialog_usage_get(ds, nua_session_usage, NULL);

  return (nua_session_usage_t *)nua_dialog_usage_private(du);
338 339
}

Pekka Pessi's avatar
Pekka Pessi committed
340 341 342 343 344 345
/** Zap the session associated with the handle */
static
void nua_session_usage_destroy(nua_handle_t *nh,
			       nua_session_usage_t *ss)
{
  /* Remove usage */
346
  nua_dialog_usage_remove(nh, nh->nh_ds, nua_dialog_usage_public(ss), NULL, NULL);
347

348
  SU_DEBUG_5(("nua: terminated session %p\n", (void *)nh));
Pekka Pessi's avatar
Pekka Pessi committed
349
}
350

Pekka Pessi's avatar
Pekka Pessi committed
351 352
/* ======================================================================== */
/* INVITE and call (session) processing */
353

354 355 356 357 358 359 360 361
static int session_timer_is_supported(struct session_timer const *t);

static void session_timer_preferences(struct session_timer *t,
				      sip_t const *sip,
				      sip_supported_t const *supported,
				      unsigned expires, int isset,
				      enum nua_session_refresher refresher,
				      unsigned min_se);
Pekka Pessi's avatar
Pekka Pessi committed
362

363 364
static void session_timer_store(struct session_timer *t,
				sip_t const *sip);
Pekka Pessi's avatar
Pekka Pessi committed
365

366 367 368
static int session_timer_check_min_se(msg_t *msg, sip_t *sip,
				      sip_t const *request,
				      unsigned long min_se);
369

370 371 372 373
static int session_timer_add_headers(struct session_timer *t,
				     int initial,
				     msg_t *msg, sip_t *sip);

374
static void session_timer_negotiate(struct session_timer *t, int uas);
375

376
static void session_timer_set(nua_session_usage_t *ss, int uas);
377

Pekka Pessi's avatar
Pekka Pessi committed
378 379 380
static int session_timer_check_restart(nua_client_request_t *cr,
				       int status, char const *phrase,
				       sip_t const *sip);
381

382 383 384
static int nh_referral_check(nua_handle_t *nh, tagi_t const *tags);
static void nh_referral_respond(nua_handle_t *,
				int status, char const *phrase);
385 386

static
387
int session_get_description(sip_t const *sip,
388
			    char const **return_sdp,
389 390 391
			    size_t *return_len);

static
392
int session_include_description(soa_session_t *soa,
393
				int session,
394
				msg_t *msg,
395 396 397
				sip_t *sip);

static
398 399
int session_make_description(su_home_t *home,
			     soa_session_t *soa,
400
			     int session,
401 402 403 404
			     sip_content_disposition_t **return_cd,
			     sip_content_type_t **return_ct,
			     sip_payload_t **return_pl);

405
static
406 407 408
int nua_server_retry_after(nua_server_request_t *sr,
			   int status, char const *phrase,
			   int min, int max);
409

410
/**@fn void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...);
411
 *
412
 * Place a call using SIP @b INVITE method.
413
 *
414 415
 * The INVITE method is used to initiate a call between two parties. The
 * call is also known as <i>SIP session</i>.
416
 *
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
 * At SIP level the session is represented as @e Dialog, which is a
 * peer-to-peer association between two SIP User-Agents. The dialog is
 * established by a successful 2XX response to the INVITE. The dialog is
 * terminated by BYE transaction, which application can initiate with
 * nua_bye() call.
 *
 * An @e early @e dialog is established by an preliminary response
 * (101..199), such as <i>180 Ringing</i>. An early dialog is terminated
 * with an error response with response code in range 300...699.
 *
 * The media session belonging to the SIP session is usually represented by
 * SDP, Session Description Protocol. The media session it is usually
 * established during the call set-up with procedure known as SDP
 * Offer/Answer exchange, defined by @RFC3264. See <b>Media Session
 * Handling</b> below for details.
432 433 434 435
 *
 * @param nh              Pointer to operation handle
 * @param tag, value, ... List of tagged parameters
 *
436
 * @return
437 438 439 440
 *    nothing
 *
 * @par Events:
 *    #nua_r_invite \n
441
 *    #nua_i_state (#nua_i_active, #nua_i_terminated) \n
442 443 444
 *    #nua_i_media_error \n
 *    #nua_i_fork \n
 *
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
 * @par Tags:
 *   NUTAG_AUTH_CACHE() \n
 *   NUTAG_AUTOACK() \n
 *   NUTAG_AUTOANSWER() \n
 *   NUTAG_EARLY_MEDIA() \n
 *   NUTAG_ENABLEINVITE() \n
 *   NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR() \n
 *   NUTAG_INVITE_TIMER() \n
 *   NUTAG_MEDIA_ENABLE() \n
 *   NUTAG_MEDIA_FEATURES() \n
 *   NUTAG_MIN_SE() \n
 *   NUTAG_RETRY_COUNT() \n
 *   NUTAG_SERVICE_ROUTE_ENABLE() \n
 *   NUTAG_SESSION_REFRESHER() \n
 *   NUTAG_SESSION_TIMER() \n
 *   NUTAG_SOA_NAME() \n
 *   NUTAG_UPDATE_REFRESH() \n
 *
463 464 465 466 467
 * @par Populating SIP Request Message with Tagged Arguments
 * The tagged arguments can be used to pass values for any SIP headers to
 * the stack. When the INVITE message (or any other SIP message) is created,
 * the tagged values saved with nua_handle() are used first, next the tagged
 * values given with the operation (nua_invite()) are added.
468 469
 *
 * @par
470 471
 * When multiple tags for the same header are specified, the behaviour
 * depends on the header type. If only a single header field can be included
472
 * in a SIP message, the latest non-NULL value is used, e.g., @Subject.
473 474 475
 * However, if the SIP header can consist of multiple lines or header fields
 * separated by comma, e.g., @Accept, all the tagged
 * values are concatenated.
476
 *
477
 * @par
478 479 480
 * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), the
 * values from previous tags are ignored.
 *
481
 * @par
482 483 484 485
 * Next, values previously set with nua_set_params() or nua_set_hparams()
 * are used: @Allow, @Supported, @Organization, and @UserAgent headers are
 * added to the request if they are not already set.
 *
486
 * @par
487 488
 * Now, the target URI for the request needs to be determined.
 *
489
 * @par
490 491 492
 * For initial INVITE requests, values from tags are used. If NUTAG_URL() is
 * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, it
 * is used as target URI. If neither is given, the complete request line
493
 * already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() is used.
494 495
 * If none of the tags above are given, an internal error is returned to the
 * application. At this point, the target URI is stored in the request line,
496
 * together with method name ("INVITE") and protocol version ("SIP/2.0").
497
 * The initial dialog information is also created: @CallID, @CSeq headers
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
 * are generated, if they do not exist, and an unique tag is added to @From
 * header.
 *
 * @par
 * For the initial INVITE requests, the @Route headers specified by
 * SIPTAG_ROUTE()/SIPTAG_ROUTER_STR() tags in nua_handle() and nua_invite()
 * calls are inserted to the request. Next the initial route set specified
 * by NUTAG_INITIAL_ROUTE()/NUTAG_INITIAL_ROUTE_STR() tags is prepended to
 * the route. Finally (unless NUTAG_SERVICE_ROUTE_ENABLE(0) is used) the
 * @ServiceRoute set received from the registrar is also appended to the
 * route set of the initial request message.
 *
 * @par
 * Next, the stack generates a @Contact header for the request (Unless the
 * application already gave a @Contact header or it does not want to use
 * @Contact and indicates that by including SIPTAG_CONTACT(NULL) or
 * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the application
 * has a registration active, the @Contact header used with registration is
 * used. Otherwise, the @Contact header is generated from the local IP
 * address and port number, taking also the values from NUTAG_M_DISPLAY(),
 * NUTAG_M_FEATURES(), NUTAG_M_PARAMS(), and NUTAG_M_USERNAME().
519
 *
520
 * @par
521 522 523
 * For in-dialog INVITE (re-INVITE), the request URI is taken from the
 * @Contact header received from the remote party during the dialog
 * establishment. Also, the @CallID and @CSeq headers and @From and @To tags
524
 * are generated based on the dialog information and added to the request.
525 526 527
 * If the dialog has a route (set by @RecordRoute headers), it is added to
 * the request, too.
 *
528
 * @par
529 530
 * @MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is
 * also added now, if it does not exist.
531
 *
532
 * @par
533 534
 * The INVITE request message created by nua_invite() operation is saved as
 * a template for automatic re-INVITE requests sent by the session timer
Pekka Pessi's avatar
Pekka Pessi committed
535 536 537 538 539
 * ("timer") feature (see NUTAG_SESSION_TIMER() for more details). Please
 * note that the template message is not used when ACK, PRACK, UPDATE or
 * INFO requests are created (however, these requests will include
 * dialog-specific headers like @To, @From, and @CallID as well as
 * preference headers @Allow, @Supported, @UserAgent, @Organization).
540
 *
541 542
 * @par Tags Related to SIP Headers and Request-URI
 *    NUTAG_URL(), SIPTAG_REQUEST(), SIPTAG_REQUEST_STR() \n
543 544
 *    NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR(),
 *    SIPTAG_ROUTE(), SIPTAG_ROUTE_STR(),
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
 *    NUTAG_SERVICE_ROUTE_ENABLE() \n
 *    SIPTAG_MAX_FORWARDS(), SIPTAG_MAX_FORWARDS_STR() \n
 *    SIPTAG_PROXY_REQUIRE(), SIPTAG_PROXY_REQUIRE_STR() \n
 *    SIPTAG_FROM(), SIPTAG_FROM_STR() \n
 *    SIPTAG_TO(), SIPTAG_TO_STR() \n
 *    SIPTAG_CALL_ID(), SIPTAG_CALL_ID_STR() \n
 *    SIPTAG_CSEQ(), SIPTAG_CSEQ_STR()
 *    (note that @CSeq value is incremented if request gets retried)\n
 *    SIPTAG_CONTACT(), SIPTAG_CONTACT_STR() \n
 *    SIPTAG_REQUEST_DISPOSITION(), SIPTAG_REQUEST_DISPOSITION_STR() \n
 *    SIPTAG_ACCEPT_CONTACT(), SIPTAG_ACCEPT_CONTACT_STR() \n
 *    SIPTAG_REJECT_CONTACT(), SIPTAG_REJECT_CONTACT_STR() \n
 *    SIPTAG_EXPIRES(), SIPTAG_EXPIRES_STR() \n
 *    SIPTAG_DATE(), SIPTAG_DATE_STR() \n
 *    SIPTAG_TIMESTAMP(), SIPTAG_TIMESTAMP_STR() \n
 *    SIPTAG_SUBJECT(), SIPTAG_SUBJECT_STR() \n
 *    SIPTAG_PRIORITY(), SIPTAG_PRIORITY_STR() \n
 *    SIPTAG_CALL_INFO(), SIPTAG_CALL_INFO_STR() \n
 *    SIPTAG_ORGANIZATION(), SIPTAG_ORGANIZATION_STR() \n
 *    NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n
 *    SIPTAG_IN_REPLY_TO(), SIPTAG_IN_REPLY_TO_STR() \n
 *    SIPTAG_ACCEPT(), SIPTAG_ACCEPT_STR() \n
 *    SIPTAG_ACCEPT_ENCODING(), SIPTAG_ACCEPT_ENCODING_STR() \n
 *    SIPTAG_ACCEPT_LANGUAGE(), SIPTAG_ACCEPT_LANGUAGE_STR() \n
 *    NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n
 *    NUTAG_EARLY_MEDIA(), SIPTAG_REQUIRE(), and SIPTAG_REQUIRE_STR() \n
 *    NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n
 *    SIPTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS_STR() \n
 *    SIPTAG_PROXY_AUTHORIZATION(), SIPTAG_PROXY_AUTHORIZATION_STR() \n
 *    SIPTAG_AUTHORIZATION(), SIPTAG_AUTHORIZATION_STR() \n
 *    SIPTAG_REFERRED_BY(), SIPTAG_REFERRED_BY_STR() \n
 *    SIPTAG_REPLACES(), SIPTAG_REPLACES_STR() \n
577
 *    NUTAG_SESSION_TIMER(), NUTAG_SESSION_REFRESHER(),
578 579 580 581 582 583 584 585 586 587 588 589 590
 *    SIPTAG_SESSION_EXPIRES(), SIPTAG_SESSION_EXPIRES_STR() \n
 *    NUTAG_MIN_SE(), SIPTAG_MIN_SE(), SIPTAG_MIN_SE_STR() \n
 *    SIPTAG_SECURITY_CLIENT(), SIPTAG_SECURITY_CLIENT_STR() \n
 *    SIPTAG_SECURITY_VERIFY(), SIPTAG_SECURITY_VERIFY_STR() \n
 *    SIPTAG_PRIVACY(), SIPTAG_PRIVACY_STR() \n
 *    SIPTAG_MIME_VERSION(), SIPTAG_MIME_VERSION_STR() \n
 *    SIPTAG_CONTENT_TYPE(), SIPTAG_CONTENT_TYPE_STR() \n
 *    SIPTAG_CONTENT_ENCODING(), SIPTAG_CONTENT_ENCODING_STR() \n
 *    SIPTAG_CONTENT_LANGUAGE(), SIPTAG_CONTENT_LANGUAGE_STR() \n
 *    SIPTAG_CONTENT_DISPOSITION(), SIPTAG_CONTENT_DISPOSITION_STR() \n
 *    SIPTAG_HEADER(), SIPTAG_HEADER_STR() \n
 *    SIPTAG_PAYLOAD(), SIPTAG_PAYLOAD_STR() \n
 *
591
 * @par SDP Handling
592 593 594
 * By default the nua_invite() uses an @ref soa_session_t "SOA media
 * session" object to take care of the Offer/Answer exchange. The SOA can
 * be disabled with tag NUTAG_MEDIA_ENABLE(0).
595
 *
596
 * @par
597 598
 * The SDP description of the
 * @ref soa_session_t "soa media session" is included in the INVITE request
599
 * as a message body.
600 601 602
 * The SDP in the message body of the 1XX or 2XX response message is
 * interpreted as an answer, given to the @ref soa_session_t "soa media
 * session" object for processing.
603 604
 *
 * @bug If the INVITE request already contains a message body, SDP is not
605 606 607 608 609 610
 * added.  Also, if the response contains a multipart body, it is not parsed.
 *
 * @par Tags Related to SDP Management and Offer/Answer Model:
 *    NUTAG_MEDIA_ENABLE(), \n
 *    NUTAG_INCLUDE_EXTRA_SDP(), \n
 *    SOATAG_HOLD(), SOATAG_AF(), SOATAG_ADDRESS(),
611 612
 *    SOATAG_ORDERED_USER(), SOATAG_REUSE_REJECTED(),
 *    SOATAG_RTP_SELECT(), SOATAG_RTP_SORT(), SOATAG_RTP_MISMATCH(),
613 614 615 616 617 618 619 620 621 622 623 624 625
 *    SOATAG_AUDIO_AUX(), \n
 *    SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() \n
 *
 * @par Alternative Call Models
 * In addition to the basic SIP call model described in @RFC3261 and
 * @RFC3264, the early media model described in @RFC3262 is available. The
 * use of 100rel and early media can be use can be forced with
 * NUTAG_EARLY_MEDIA(1).
 *
 * Also, the "precondition" call model described in @RFC3312 is supported at
 * SIP level, that is, the SIP PRACK and UPDATE requests are sent if
 * "precondition" is added to the @Require header in the INVITE request.
 *
626
 * Optionally
627 628
 * - uses early media if NUTAG_EARLY_MEDIA() tag is used with non zero-value
 * - media parameters can be set by SOA tags
629
 * - nua_invite() can be used to change status of an existing call:
630 631
 *   - #SOATAG_HOLD tag can be used to list the media that will be put on hold,
 *     the value "*" sets all the media beloginging to the session on hold
632 633 634 635 636 637
 *
 * @par Authentication
 * The INVITE request may need authentication. Each proxy or server
 * requiring authentication can respond with 401 or 407 response. The
 * nua_authenticate() operation stores authentication information (username
 * and password) to the handle, and stack tries to authenticate all the rest
638 639
 * of the requests (e.g., PRACK, ACK, UPDATE, re-INVITE, BYE) using the
 * stored username and password.
640
 *
641 642
 * @sa @ref nua_call_model, #nua_r_invite, #nua_i_state, \n
 *     nua_handle_has_active_call() \n
643 644 645 646 647
 *     nua_handle_has_call_on_hold()\n
 *     nua_handle_has_invite() \n
 *     nua_authenticate() \n
 *     nua_prack() \n
 *     nua_update() \n
648
 *     nua_info() \n
649 650
 *     nua_cancel() \n
 *     nua_bye() \n
651
 *     #nua_i_invite, nua_respond()
652 653
 */

654 655 656
/* Tags not implemented
 *    NUTAG_REFER_PAUSE() \n
 */
657

658
static int nua_invite_client_init(nua_client_request_t *cr,
Pekka Pessi's avatar
Pekka Pessi committed
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
				  msg_t *msg, sip_t *sip,
				  tagi_t const *tags);
static int nua_invite_client_request(nua_client_request_t *cr,
				     msg_t *msg, sip_t *sip,
				     tagi_t const *tags);
static int nua_invite_client_preliminary(nua_client_request_t *cr,
					 int status, char const *phrase,
					 sip_t const *sip);
static int nua_invite_client_response(nua_client_request_t *cr,
				      int status, char const *phrase,
				      sip_t const *sip);
static int nua_session_client_response(nua_client_request_t *cr,
				       int status, char const *phrase,
				       sip_t const *sip);
static int nua_invite_client_report(nua_client_request_t *cr,
				    int status, char const *phrase,
				    sip_t const *sip,
				    nta_outgoing_t *orq,
				    tagi_t const *tags);

679
nua_client_methods_t const nua_invite_client_methods = {
680 681 682
  SIP_METHOD_INVITE,		/* crm_method, crm_method_name */
  0,				/* crm_extra */
  {				/* crm_flags */
Pekka Pessi's avatar
Pekka Pessi committed
683 684 685 686
    /* create_dialog */ 1,
    /* in_dialog */ 1,
    /* target refresh */ 1
  },
687 688 689 690 691 692 693 694
  NULL,				/* crm_template */
  nua_invite_client_init,	/* crm_init */
  nua_invite_client_request,	/* crm_send */
  session_timer_check_restart,	/* crm_check_restart */
  nua_invite_client_response,	/* crm_recv */
  nua_invite_client_preliminary, /* crm_preliminary */
  nua_invite_client_report,	/* crm_report */
  nua_invite_client_complete,	/* crm_complete */
Pekka Pessi's avatar
Pekka Pessi committed
695 696
};

697 698 699 700
extern nua_client_methods_t const nua_bye_client_methods;
extern nua_client_methods_t const nua_cancel_client_methods;
extern nua_client_methods_t const nua_update_client_methods;
extern nua_client_methods_t const nua_prack_client_methods;
Pekka Pessi's avatar
Pekka Pessi committed
701 702 703 704 705

int nua_stack_invite(nua_t *nua, nua_handle_t *nh, nua_event_t e,
		     tagi_t const *tags)
{
  return nua_client_create(nh, e, &nua_invite_client_methods, tags);
706 707
}

708
static int nua_invite_client_init(nua_client_request_t *cr,
Pekka Pessi's avatar
Pekka Pessi committed
709 710
				  msg_t *msg, sip_t *sip,
				  tagi_t const *tags)
711
{
Pekka Pessi's avatar
Pekka Pessi committed
712
  nua_handle_t *nh = cr->cr_owner;
713
  nua_dialog_usage_t *du;
714
  nua_session_usage_t *ss;
715

Pekka Pessi's avatar
Pekka Pessi committed
716
  cr->cr_usage = du = nua_dialog_usage_for_session(nh->nh_ds);
717
  /* Errors returned by nua_invite_client_init()
718
     do not change the session state */
719 720 721
  cr->cr_neutral = 1;

  if (nh_is_special(nh) ||
Pekka Pessi's avatar
Pekka Pessi committed
722 723 724 725
      nua_stack_set_handle_special(nh, nh_has_invite, nua_i_error))
    return nua_client_return(cr, 900, "Invalid handle for INVITE", msg);
  else if (nh_referral_check(nh, tags) < 0)
    return nua_client_return(cr, 900, "Invalid referral", msg);
726

727 728 729 730 731 732 733
  if (du) {
    nua_server_request_t *sr;
    for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next)
      /* INVITE in progress? */
      if (sr->sr_usage == du && sr->sr_method == sip_method_invite &&
	  nua_server_request_is_pending(sr))
	return nua_client_return(cr, SIP_491_REQUEST_PENDING, msg);
734
    cr->cr_initial = 0;
735
  }
736
  else {
Pekka Pessi's avatar
Pekka Pessi committed
737
    du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL);
738 739
    cr->cr_initial = 1;
  }
740

Pekka Pessi's avatar
Pekka Pessi committed
741 742
  if (!du)
    return -1;
743

744 745 746 747 748
  ss = nua_dialog_usage_private(du);

  if (ss->ss_state >= nua_callstate_terminating)
    return nua_client_return(cr, 900, "Session is terminating", msg);

Pekka Pessi's avatar
Pekka Pessi committed
749 750
  if (nua_client_bind(cr, du) < 0)
    return nua_client_return(cr, 900, "INVITE already in progress", msg);
751

752
  cr->cr_neutral = 0;
753 754 755

  session_timer_preferences(ss->ss_timer,
			    sip,
756
			    NH_PGET(nh, supported),
Pekka Pessi's avatar
Pekka Pessi committed
757
			    NH_PGET(nh, session_timer),
758 759 760
			    NUA_PISSET(nh->nh_nua, nh, session_timer),
			    NH_PGET(nh, refresher),
			    NH_PGET(nh, min_se));
761

Pekka Pessi's avatar
Pekka Pessi committed
762 763
  return 0;
}
764

Pekka Pessi's avatar
Pekka Pessi committed
765 766 767 768 769 770
static int nua_invite_client_request(nua_client_request_t *cr,
				     msg_t *msg, sip_t *sip,
				     tagi_t const *tags)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
771
  nua_session_usage_t *ss;
Pekka Pessi's avatar
Pekka Pessi committed
772 773
  int offer_sent = 0, retval;
  sip_time_t invite_timeout;
774

775
  if (du == NULL)		/* Call terminated */
Pekka Pessi's avatar
Pekka Pessi committed
776
    return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg);
777

778 779
  ss = NUA_DIALOG_USAGE_PRIVATE(du);

780 781 782
  if (ss->ss_state >= nua_callstate_terminating)
    return nua_client_return(cr, 900, "Session is terminating", msg);

Pekka Pessi's avatar
Pekka Pessi committed
783 784 785
  invite_timeout = NH_PGET(nh, invite_timeout);
  if (invite_timeout == 0)
    invite_timeout = UINT_MAX;
786
  /* Send CANCEL if we don't get response within timeout*/
787
  /* nua_dialog_usage_set_expires(du, invite_timeout); Xyzzy */
788
  nua_dialog_usage_reset_refresh(du);
789

Pekka Pessi's avatar
Pekka Pessi committed
790
  /* Add session timer headers */
791 792 793
  if (session_timer_is_supported(ss->ss_timer))
    session_timer_add_headers(ss->ss_timer, ss->ss_state == nua_callstate_init,
			      msg, sip);
794

Pekka Pessi's avatar
Pekka Pessi committed
795 796 797 798
  ss->ss_100rel = NH_PGET(nh, early_media);
  ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition");
  if (ss->ss_precondition)
    ss->ss_update_needed = ss->ss_100rel = 1;
799 800

  if (nh->nh_soa) {
801 802
    soa_init_offer_answer(nh->nh_soa);

803 804
    if (soa_is_delayed_offer(nh->nh_soa))
      offer_sent = 0;
805 806 807
    else if (sip->sip_payload)
      /* Kludge, we should probably use multipart */
      offer_sent = 0;
808
    else if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0)
Pekka Pessi's avatar
Pekka Pessi committed
809
      return -1;
810 811 812
    else
      offer_sent = 1;

813 814 815
    if (offer_sent > 0 &&
	session_include_description(nh->nh_soa, 1, msg, sip) < 0)
      return nua_client_return(cr, 900, "Internal media error", msg);
816

817 818 819 820 821
    if (NH_PGET(nh, media_features) &&
	!nua_dialog_is_established(nh->nh_ds) &&
	!sip->sip_accept_contact && !sip->sip_reject_contact) {
      sip_accept_contact_t ac[1];
      sip_accept_contact_init(ac);
822

823 824
      ac->cp_params = (msg_param_t *)
	soa_media_features(nh->nh_soa, 1, msg_home(msg));
825

826 827 828 829
      if (ac->cp_params) {
	msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit");
	sip_add_dup(msg, sip, (sip_header_t *)ac);
      }
830
    }
Pekka Pessi's avatar
Pekka Pessi committed
831
  }
832 833 834
  else {
    offer_sent = session_get_description(sip, NULL, NULL);
  }
835

Pekka Pessi's avatar
Pekka Pessi committed
836 837 838 839
  retval = nua_base_client_trequest(cr, msg, sip,
				    NTATAG_REL100(ss->ss_100rel),
				    TAG_NEXT(tags));
  if (retval == 0) {
840 841
    if ((cr->cr_offer_sent = offer_sent))
      ss->ss_oa_sent = Offer;
842

843
    if (!cr->cr_restarting) /* Restart logic calls nua_invite_client_report */
844
      signal_call_state_change(nh, ss, 0, "INVITE sent",
Pekka Pessi's avatar
Pekka Pessi committed
845 846
			       nua_callstate_calling);
  }
847

Pekka Pessi's avatar
Pekka Pessi committed
848 849
  return retval;
}
850

Pekka Pessi's avatar
Pekka Pessi committed
851 852 853 854 855 856
static int nua_invite_client_response(nua_client_request_t *cr,
				      int status, char const *phrase,
				      sip_t const *sip)
{
  nua_dialog_usage_t *du = cr->cr_usage;
  nua_session_usage_t *ss = nua_dialog_usage_private(du);
857
  int uas;
858

Pekka Pessi's avatar
Pekka Pessi committed
859 860
  if (ss == NULL || sip == NULL) {
    /* Xyzzy */
861
  }
Pekka Pessi's avatar
Pekka Pessi committed
862 863
  else if (status < 300) {
    du->du_ready = 1;
864

865 866 867
    if (session_timer_is_supported(ss->ss_timer))
      session_timer_store(ss->ss_timer, sip);

868
    session_timer_set(ss, uas = 0);
Pekka Pessi's avatar
Pekka Pessi committed
869
  }
870

Pekka Pessi's avatar
Pekka Pessi committed
871 872
  return nua_session_client_response(cr, status, phrase, sip);
}
873

Pekka Pessi's avatar
Pekka Pessi committed
874 875 876 877 878 879 880
static int nua_invite_client_preliminary(nua_client_request_t *cr,
					 int status, char const *phrase,
					 sip_t const *sip)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
  nua_session_usage_t *ss = nua_dialog_usage_private(du);
881

882
  assert(sip);
Pekka Pessi's avatar
Pekka Pessi committed
883 884 885 886 887 888 889 890 891

  if (ss && sip && sip->sip_rseq) {
    /* Handle 100rel responses */
    sip_rseq_t *rseq = sip->sip_rseq;

    /* Establish early dialog - we should fork here */
    if (!nua_dialog_is_established(nh->nh_ds)) {
      nta_outgoing_t *tagged;

892
      nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, 1);
Pekka Pessi's avatar
Pekka Pessi committed
893
      nua_dialog_store_peer_info(nh, nh->nh_ds, sip);
894

Pekka Pessi's avatar
Pekka Pessi committed
895 896 897 898 899 900 901 902 903 904 905 906
      /* Tag the INVITE request */
      tagged = nta_outgoing_tagged(cr->cr_orq,
				   nua_client_orq_response, cr,
				   sip->sip_to->a_tag, sip->sip_rseq);
      if (tagged) {
	nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = tagged;
      }
      else {
	cr->cr_graceful = 1;
	ss->ss_reason = "SIP;cause=500;text=\"Cannot Create Early Dialog\"";
      }
    }
907

Pekka Pessi's avatar
Pekka Pessi committed
908
    if (!rseq) {
909
      SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", (void *)nh));
Pekka Pessi's avatar
Pekka Pessi committed
910 911
    }
    else if (nta_outgoing_rseq(cr->cr_orq) > rseq->rs_response) {
912
      SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", (void *)nh,
Pekka Pessi's avatar
Pekka Pessi committed
913 914 915 916 917
		  (unsigned)rseq->rs_response,
		  nta_outgoing_rseq(cr->cr_orq)));
      return 1;    /* Do not send event */
    }
    else if (nta_outgoing_setrseq(cr->cr_orq, rseq->rs_response) < 0) {
918
      SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", (void *)nh,
Pekka Pessi's avatar
Pekka Pessi committed
919 920 921 922 923
		  (unsigned)rseq->rs_response));
      cr->cr_graceful = 1;
      ss->ss_reason = "SIP;cause=400;text=\"Bad RSeq\"";
    }
  }
924

Pekka Pessi's avatar
Pekka Pessi committed
925
  return nua_session_client_response(cr, status, phrase, sip);
926 927
}

Pekka Pessi's avatar
Pekka Pessi committed
928 929 930 931
/** Process response to a session request (INVITE, PRACK, UPDATE) */
static int nua_session_client_response(nua_client_request_t *cr,
				       int status, char const *phrase,
				       sip_t const *sip)
932
{
Pekka Pessi's avatar
Pekka Pessi committed
933 934 935 936 937 938
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
  nua_session_usage_t *ss = nua_dialog_usage_private(du);

  char const *sdp = NULL;
  size_t len;
939 940
  char const *received = NULL;

Pekka Pessi's avatar
Pekka Pessi committed
941 942
#define LOG3(m) \
  SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \
943
	      (void *)nh, cr->cr_method_name, (m), \
Pekka Pessi's avatar
Pekka Pessi committed
944 945 946
	      received ? received : "SDP", status, phrase))
#define LOG5(m) \
  SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \
947
	      (void *)nh, cr->cr_method_name, (m), received, status, phrase))
948

949
  if (!ss || !sip || 300 <= status)
Pekka Pessi's avatar
Pekka Pessi committed
950 951 952 953 954 955 956
    /* Xyzzy */;
  else if (!session_get_description(sip, &sdp, &len))
    /* No SDP */;
  else if (cr->cr_answer_recv) {
    /* Ignore spurious answers after completing O/A */
    LOG3("ignoring duplicate");
    sdp = NULL;
957
  }
Pekka Pessi's avatar
Pekka Pessi committed
958
  else if (cr->cr_offer_sent) {
959
    /* case 1: answer to our offer */
Pekka Pessi's avatar
Pekka Pessi committed
960
    cr->cr_answer_recv = status;
961
    received = Answer;
962

963 964