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 278 279 280 281
		      NULL,
		      cr->cr_event,
		      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 701
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_info_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
702 703 704 705 706

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);
707 708
}

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

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

  if (nh_is_special(nh) ||
Pekka Pessi's avatar
Pekka Pessi committed
723 724 725 726
      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);
727

728 729 730 731 732 733 734
  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);
735
    cr->cr_initial = 0;
736
  }
737
  else {
Pekka Pessi's avatar
Pekka Pessi committed
738
    du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL);
739 740
    cr->cr_initial = 1;
  }
741

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

745 746 747 748 749
  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
750 751
  if (nua_client_bind(cr, du) < 0)
    return nua_client_return(cr, 900, "INVITE already in progress", msg);
752

753
  cr->cr_neutral = 0;
754 755 756

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

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

Pekka Pessi's avatar
Pekka Pessi committed
766 767 768 769 770 771
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;
772
  nua_session_usage_t *ss;
Pekka Pessi's avatar
Pekka Pessi committed
773 774
  int offer_sent = 0, retval;
  sip_time_t invite_timeout;
775

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

779 780
  ss = NUA_DIALOG_USAGE_PRIVATE(du);

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

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

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

Pekka Pessi's avatar
Pekka Pessi committed
796 797 798 799
  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;
800 801

  if (nh->nh_soa) {
802 803 804
    soa_init_offer_answer(nh->nh_soa);

    if (sip->sip_payload)
Pekka Pessi's avatar
Pekka Pessi committed
805
      offer_sent = 0;		/* XXX - kludge */
806
    else if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0)
Pekka Pessi's avatar
Pekka Pessi committed
807
      return -1;
808 809 810
    else
      offer_sent = 1;

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

815 816 817 818 819
    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);
820

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

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

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

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

Pekka Pessi's avatar
Pekka Pessi committed
846 847
  return retval;
}
848

Pekka Pessi's avatar
Pekka Pessi committed
849 850 851 852 853 854
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);
855
  int uas;
856

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

863 864 865
    if (session_timer_is_supported(ss->ss_timer))
      session_timer_store(ss->ss_timer, sip);

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

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

Pekka Pessi's avatar
Pekka Pessi committed
872 873 874 875 876 877 878
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);
879

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

  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;

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

Pekka Pessi's avatar
Pekka Pessi committed
893 894 895 896 897 898 899 900 901 902 903 904
      /* 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\"";
      }
    }
905

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

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

Pekka Pessi's avatar
Pekka Pessi committed
926 927 928 929
/** 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)
930
{
Pekka Pessi's avatar
Pekka Pessi committed
931 932 933 934 935 936
  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;
937 938
  char const *received = NULL;

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

947
  if (!ss || !sip || 300 <= status)
Pekka Pessi's avatar
Pekka Pessi committed
948 949 950 951 952 953 954
    /* 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;
955
  }
Pekka Pessi's avatar
Pekka Pessi committed
956
  else if (cr->cr_offer_sent) {
957
    /* case 1: answer to our offer */
Pekka Pessi's avatar
Pekka Pessi committed
958
    cr->cr_answer_recv = status;
959
    received = Answer;
960

961 962 963
    if (nh->nh_soa == NULL)
      LOG5("got SDP");
    else if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) {
Pekka Pessi's avatar
Pekka Pessi committed
964 965 966 967 968 969 970 971 972 973
      LOG3("error parsing SDP");