nua_dialog.h 9.06 KB
Newer Older
1 2 3
/*
 * This file is part of the Sofia-SIP package
 *
4
 * Copyright (C) 2006 Nokia Corporation.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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
 *
 */

25 26
#ifndef NUA_DIALOG_H
/** Defined when <nua_dialog.h> has been included. */
27 28
#define NUA_DIALOG_H

29
/**@IFILE nua_dialog.h 
30 31 32 33 34 35 36 37 38 39
 * @brief Dialog and dialog usage handling
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 * @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
 *
 * @date Created: Wed Mar  8 11:38:18 EET 2006  ppessi
 */

typedef struct nua_dialog_state nua_dialog_state_t;
typedef struct nua_dialog_usage nua_dialog_usage_t;
40
typedef struct nua_remote_s nua_remote_t;
41

42 43
#ifndef NUA_OWNER_T
#define NUA_OWNER_T struct nua_owner_s
44
#endif
45 46
typedef NUA_OWNER_T nua_owner_t;

47 48 49 50
#ifndef NTA_H
#include <sofia-sip/nta.h>
#endif

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 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
typedef struct nua_server_request nua_server_request_t; 
typedef struct nua_client_request nua_client_request_t; 

/** Respond to an incoming request. */
typedef int nua_server_respond_f(nua_server_request_t *, tagi_t const *);

/** Restart an outgoing request. */
typedef void nua_creq_restart_f(nua_owner_t *, tagi_t *tags);

/** Server side transaction */
struct nua_server_request {
  struct nua_server_request *sr_next, **sr_prev;

  nua_owner_t *sr_owner;	/**< Backpointer to handle */
  nua_dialog_usage_t *sr_usage;	/**< Backpointer to usage */

  /** When the application responds to an request with
   * nua_respond(), the sr_respond() is called
   */
  nua_server_respond_f *sr_respond;
  
  nta_incoming_t *sr_irq;	/**< Server transaction object */
  msg_t *sr_msg;		/**< Request message */

  sip_method_t sr_method;	/**< Request method */
  int sr_status;		/**< Status code */
  char const *sr_phrase;	/**< Status phrase */

  unsigned sr_auto:1;		/**< Autoresponse - no event has been sent */
  unsigned sr_initial:1;	/**< Handle was created by this request */

  /* Flags used with offer-answer */
  unsigned sr_offer_recv:1;	/**< We have received an offer */
  unsigned sr_answer_sent:2;	/**< We have answered (reliably, if >1) */

  unsigned sr_offer_sent:1;	/**< We have offered SDP */
  unsigned sr_answer_recv:1;	/**< We have received SDP answer */
};

#define SR_INIT(sr) \
  (memset((sr), 0, sizeof (sr)[0]), SR_STATUS1((sr), SIP_100_TRYING), sr)

#define SR_STATUS(sr, status, phrase) \
  ((sr)->sr_phrase = (phrase), (sr)->sr_status = (status))

#define SR_STATUS1(sr, statusphrase)					\
  sr_status(sr, statusphrase)

su_inline 
int sr_status(nua_server_request_t *sr, int status, char const *phrase)
{
  return (void)(sr->sr_phrase = phrase), (sr->sr_status = status);
}

struct nua_client_request
{
  nua_client_request_t *cr_next;        /**< Linked list of requests */
  /*nua_event_t*/ int cr_event;		/**< Request event */
  nua_creq_restart_f *cr_restart;
  nta_outgoing_t     *cr_orq;
  msg_t              *cr_msg;
  nua_dialog_usage_t *cr_usage;
  unsigned short      cr_retry_count;   /**< Retry count for this request */

  /* Flags used with offer-answer */
  unsigned short      cr_answer_recv;   /**< Recv answer in response 
					 *  with this status.
					 */
  unsigned            cr_offer_sent:1;  /**< Sent offer in this request */

  unsigned            cr_offer_recv:1;  /**< Recv offer in a response */
  unsigned            cr_answer_sent:1; /**< Sent answer in (PR)ACK */
};


126 127
struct nua_dialog_state
{
128 129 130
  nua_client_request_t ds_cr[1];
  nua_server_request_t *ds_sr;

131 132 133 134 135 136 137 138 139 140
  /** Dialog usages. */
  nua_dialog_usage_t     *ds_usage;

  /* Dialog and subscription state */
  unsigned ds_route:1;		/**< We have route */
  unsigned ds_terminated:1;	/**< Being terminated */

  unsigned ds_has_session:1;	/**< We have session */
  unsigned ds_has_register:1;	/**< We have registration */
  unsigned ds_has_publish:1;	/**< We have publish */
141 142 143

  unsigned ds_has_referrals:1;	/**< We have (or have had) referrals */

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
  unsigned :0;

  unsigned ds_has_events;	/**< We have events */
  unsigned ds_has_subscribes;   /**< We have subscriptions */
  unsigned ds_has_notifys;	/**< We have notifiers */

  sip_from_t const *ds_local;		/**< Local address */
  sip_to_t const *ds_remote;		/**< Remote address */
  nta_leg_t      *ds_leg;
  char const     *ds_remote_tag;	/**< Remote tag (if any). 
					 * Should be non-NULL 
					 * if dialog is established.
					 */

  struct nua_remote_s {
    sip_allow_t      *nr_allow;
    sip_accept_t     *nr_accept;
    sip_require_t    *nr_require;
    sip_supported_t  *nr_supported;
    sip_user_agent_t *nr_user_agent;
  } ds_remote_ua[1];
};

167
typedef void nh_pending_f(nua_owner_t *, 
168 169 170
			  nua_dialog_usage_t *du,
			  sip_time_t now);

171
/** Virtual function pointer table for dialog usage. */
172 173
typedef struct {
  unsigned usage_size, usage_class_size;
174 175 176 177
  int (*usage_add)(nua_owner_t *, 
		   nua_dialog_state_t *ds,
		   nua_dialog_usage_t *du);
  void (*usage_remove)(nua_owner_t *, 
178 179 180
		       nua_dialog_state_t *ds,
		       nua_dialog_usage_t *du);
  char const *(*usage_name)(nua_dialog_usage_t const *du);
181 182 183
  void (*usage_peer_info)(nua_dialog_usage_t *du,
			  nua_dialog_state_t const *ds,
			  sip_t const *sip);
184 185 186 187
  void (*usage_refresh)(nua_owner_t *, nua_dialog_state_t *ds,
			nua_dialog_usage_t *, sip_time_t now);
  int (*usage_shutdown)(nua_owner_t *, nua_dialog_state_t *ds, 
			nua_dialog_usage_t *);
188 189
} nua_usage_class;

190 191

/** Base structure for dialog usage. */
192 193 194 195 196 197
struct nua_dialog_usage {
  nua_dialog_usage_t *du_next;
  nua_usage_class const *du_class;

  unsigned     du_terminating:1;	/**< Now trying to terminate usage */
  unsigned     du_ready:1;	        /**< Established usage */
198
  unsigned     du_shutdown:1;	        /**< Shutdown in progress */
199 200
  unsigned:0;

201 202 203
  /** When usage expires.
   * Non-zero if the usage is established, SIP_TIME_MAX if there no
   * expiration time.
204
   */
205 206 207
  sip_time_t      du_expires;		

  sip_time_t      du_refresh;		/**< When to refresh */
208 209

  sip_event_t const *du_event;		/**< Event of usage */
210

211 212 213
  msg_t *du_msg;			/**< Template message */
};

214 215 216 217 218 219
void nua_dialog_uac_route(nua_owner_t *, nua_dialog_state_t *ds,
			  sip_t const *sip, int rtag);
void nua_dialog_uas_route(nua_owner_t *, nua_dialog_state_t *ds,
			  sip_t const *sip, int rtag);
void nua_dialog_store_peer_info(nua_owner_t *, nua_dialog_state_t *ds,
				sip_t const *sip);
220 221 222
int nua_dialog_remove(nua_owner_t *own,
		      nua_dialog_state_t *ds,
		      nua_dialog_usage_t *usage);
223 224 225

char const *nua_dialog_usage_name(nua_dialog_usage_t const *du);

226
nua_dialog_usage_t *nua_dialog_usage_add(nua_owner_t *, 
227 228 229 230 231 232 233 234
					 struct nua_dialog_state *ds,
					 nua_usage_class const *uclass,
					 sip_event_t const *event);

nua_dialog_usage_t *nua_dialog_usage_get(nua_dialog_state_t const *ds, 
					 nua_usage_class const *uclass,
					 sip_event_t const *event);

235
void nua_dialog_usage_remove(nua_owner_t *, 
236 237 238
			     nua_dialog_state_t *ds,
			     nua_dialog_usage_t *du);

239 240 241
void nua_dialog_deinit(nua_owner_t *own,
		       nua_dialog_state_t *ds);

242
void nua_dialog_terminated(nua_owner_t *,
243 244 245 246
			   struct nua_dialog_state *ds,
			   int status,
			   char const *phrase);

247 248
void nua_dialog_usage_set_expires(nua_dialog_usage_t *du, unsigned delta);

249 250
void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta);

251 252 253
void nua_dialog_usage_refresh_range(nua_dialog_usage_t *du, 
				    unsigned min, unsigned max);

254 255
void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du);

256
void nua_dialog_usage_refresh(nua_owner_t *owner,
257
			      nua_dialog_state_t *ds,
258 259 260
			      nua_dialog_usage_t *du, 
			      sip_time_t now);

261 262 263 264 265 266 267 268 269 270
static inline
int nua_dialog_is_established(nua_dialog_state_t const *ds)
{
  return ds->ds_remote_tag != NULL;
}

#if 0
static inline
void *nua_dialog_usage_private(nua_dialog_usage_t const *du)
{
271 272 273 274 275 276 277
  return du ? (void *)(du + 1) : NULL;
}

static inline
nua_dialog_usage_t *nua_dialog_usage_public(void const *p)
{
  return p ? (nua_dialog_usage_t *)p - 1 : NULL;
278 279
}
#else
280 281
#define nua_dialog_usage_private(du) ((du) ? (void*)((du) + 1) : NULL)
#define nua_dialog_usage_public(p) ((p) ? (nua_dialog_usage_t*)(p) - 1 : NULL)
282 283
#endif

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
/* ---------------------------------------------------------------------- */

void nua_server_request_destroy(nua_server_request_t *sr);

int nua_server_respond(nua_server_request_t *sr,
		       int status, char const *phrase,
		       tag_type_t tag, tag_value_t value, ...);

msg_t *nua_server_response(nua_server_request_t *sr,
			   int status, char const *phrase,
			   tag_type_t tag, tag_value_t value, ...);

int nua_default_respond(nua_server_request_t *sr,
			tagi_t const *tags);


300
#endif /* NUA_DIALOG_H */