⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nea_server.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 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 * *//**@file nea_server.c * @brief Nokia Event API - event notifier implementation. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Martti Mela <Martti.Mela@nokia.com> * * @date Created: Wed Feb 14 18:37:04 EET 2001 ppessi */#include "config.h"#include <sofia-sip/sip.h>#include <sofia-sip/sip_header.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/su_tagarg.h>#include "nea_debug.h"#define NONE ((void *)- 1)#define SU_ROOT_MAGIC_T      struct nea_server_s#define SU_MSG_ARG_T         tagi_t#define NTA_AGENT_MAGIC_T    struct nea_server_s#define NTA_LEG_MAGIC_T      struct nea_sub_s#define NTA_INCOMING_MAGIC_T struct nea_sub_s#define NTA_OUTGOING_MAGIC_T struct nea_sub_s#include <sofia-sip/nea.h>#include <sofia-sip/htable.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <stdarg.h>#include <assert.h>#include <limits.h>/** Number of primary views (with different MIME type or content) */#define NEA_VIEW_MAX (8)/** Server object, created for every notifier. */struct nea_server_s {  su_home_t                 nes_home[1];  su_root_t                *nes_root;  su_timer_t               *nes_timer;    nta_agent_t              *nes_agent;  nta_leg_t                *nes_leg;  nea_sub_t                *nes_subscribers;  sip_require_t            *nes_require;  sip_time_t                nes_min_expires;  sip_time_t                nes_expires;  sip_time_t                nes_max_expires;  int                       nes_max_subs;  unsigned                  nes_throttle; /**< Default throttle */  unsigned                  nes_min_throttle; /**< Minimum throttle */  unsigned                  nes_eventlist:1; /**< Eventlist only */  unsigned                  nes_in_callback : 1;  unsigned                  nes_pending_destroy : 1;  unsigned                  nes_pending_flush : 1;  unsigned                  nes_202_before_notify:1;  unsigned                  nes_in_list;  unsigned                  nes_throttled; /**< Throttled notifications? */  char const               *nes_server;  sip_contact_t            *nes_eventity_uri;  sip_allow_events_t       *nes_allow_events;  sip_allow_t              *nes_allow_methods;  nea_new_event_f          *nes_callback;  nea_smagic_t             *nes_context;  /** Events.     * Each subscriber will be added to one of these. */   nea_event_t              *nes_events;};/** Supported events and their subscribers  */struct nea_event_s {  nea_event_t              *ev_next;  nea_event_t             **ev_prev;  nea_watcher_f            *ev_callback;  nea_emagic_t             *ev_magic;  unsigned                  ev_throttle; /**< Default throttle */  unsigned                  ev_min_throttle; /**< Minimum throttle */  unsigned                  ev_eventlist:1; /**< Eventlist is supported */  unsigned                  ev_reliable:1;  /**< Keep all notifications */  unsigned                  :0;  /** Sequence number of first unsent update */  unsigned                  ev_throttling;  unsigned                  ev_updated;	/**< Sequence number for updates */  sip_require_t            *ev_require; /**< Required features */  sip_supported_t          *ev_supported; /**< Supported features */  sip_event_t              *ev_event;  sip_accept_t const       *ev_default;/**< Default content type */  sip_accept_t const       *ev_accept; /**< Supported content types */  nea_event_view_t         *ev_views[NEA_VIEW_MAX + 1];};typedef struct nea_event_queue_s nea_event_queue_t;/** Object representing particular view of event */struct nea_event_view_s{  nea_event_view_t *evv_next;  nea_event_view_t *evv_primary; 	/**< Backpointer to the primary view */  nea_evmagic_t    *evv_magic;  unsigned          evv_throttle; /**< Default throttle */  unsigned          evv_min_throttle; /**< Minimum throttle */  unsigned          evv_fake:1;		/**< This is "fake" (ie. default) view */  unsigned          evv_private:1;	/**< This is private view */  unsigned          evv_reliable:1;     /**< Keep all notifications */  unsigned:0;  /** Queued notification */  struct nea_event_queue_s  {    nea_event_queue_t  *evq_next;    unsigned            evq_updated;    unsigned            evq_version;    sip_content_type_t *evq_content_type;    sip_payload_t      *evq_payload;  } evv_head[1];};#define evv_version evv_head->evq_version#define evv_updated evv_head->evq_updated#define evv_content_type evv_head->evq_content_type#define evv_payload evv_head->evq_payload/** Subscription object  */struct nea_sub_s {  nea_sub_t        *s_next;  nea_sub_t       **s_prev;    nta_leg_t        *s_leg;  nta_incoming_t   *s_irq;  nta_outgoing_t   *s_oreq;    nea_server_t     *s_nes;  sip_contact_t    *s_local;	/**< Local contact */  sip_from_t       *s_from;  sip_contact_t    *s_remote;	/**< Remote contact  */  /* sip_accept_t  *s_accept; */  sip_event_t      *s_id;  nea_event_t      *s_event;  nea_event_view_t *s_view;  nea_state_t       s_state;  char const       *s_extended;  sip_content_type_t *s_content_type; /** Content-Type of SUBSCRIBE body. */  sip_payload_t    *s_payload;      /**< Body of SUBSCRIBE. */  unsigned          s_processing : 1;  unsigned          s_rejected : 1;   unsigned          s_pending_flush : 1;  unsigned          s_garbage : 1;  unsigned          s_fake : 1; /**< Do not send real information to user */  unsigned          s_eventlist : 1; /**< Subscriber supported eventlist */  sip_time_t        s_subscribed; /**< When first SUBSCRIBE was recv */  sip_time_t        s_notified; /**< When last notification was sent */  sip_time_t        s_expires;  /**< Expiration time. */  unsigned          s_version;	/**< Version number set by application */  unsigned          s_latest;	/**< External version of latest payload */  unsigned          s_updated;	/**< Internal version of latest payload */  unsigned          s_throttle;	/**< Minimum time between notifications */};/* Prototypes */static void nea_server_pending_flush(nea_server_t *nes);static int nea_view_update(nea_server_t *nes,			   nea_event_t *ev,			   nea_event_view_t **evvp,			   int private,			   int fake,			   tag_type_t tag,			   tag_value_t value,			   ...);static nea_sub_t *nea_sub_create(nea_server_t *nes);static int nea_sub_is_removed(nea_sub_t const *s);static void nea_sub_remove(nea_sub_t *s);static void nea_sub_destroy(nea_sub_t *s);staticint nea_server_callback(nea_sub_t *nes_as_sub,			nta_leg_t *leg,			nta_incoming_t *irq, 			sip_t const *sip);static int nea_sub_process_incoming(nea_sub_t *s,				    nta_leg_t *leg,				    nta_incoming_t *irq,				    sip_t const *sip);static int nea_sub_process_subscribe(nea_sub_t *s,				     nta_leg_t *leg,				     nta_incoming_t *irq,				     sip_t const *sip);static int nea_sub_notify(nea_server_t *nes, 			  nea_sub_t *s, 			  sip_time_t now, 			  tag_type_t tag, tag_value_t value, ...);static int response_to_notify(nea_sub_t *s,			      nta_outgoing_t *oreq,			      sip_t const *sip);static void nes_event_timer(nea_server_t *nes,			    su_timer_t *timer,			    su_timer_arg_t *arg);static int nea_view_queue(nea_server_t *nes, 			  nea_event_view_t *evv, 			  nea_event_queue_t *evq);/** Assign an event view to subscriber. */static inlinevoid nea_sub_assign_view(nea_sub_t *s, nea_event_view_t *evv){  if (s->s_view != evv)    /* Make sure we send a notification */    s->s_updated = evv->evv_updated - 1;  s->s_view = evv;  s->s_throttle = evv->evv_throttle;}static inline void nea_subnode_init(nea_subnode_t *sn, nea_sub_t *s, sip_time_t now){  sn->sn_state = s->s_state;  sn->sn_fake = s->s_fake;  sn->sn_subscriber = s;  sn->sn_event = s->s_event;  sn->sn_remote = s->s_from;  sn->sn_contact = s->s_remote;  sn->sn_content_type = s->s_content_type;  sn->sn_payload = s->s_payload;  if (s->s_expires != 0 && (int)(s->s_expires - now) > 0)    sn->sn_expires = s->s_expires - now;  else    sn->sn_expires = 0;  sn->sn_latest = s->s_latest;  sn->sn_throttle = s->s_throttle;  sn->sn_eventlist = s->s_eventlist;  sn->sn_version = s->s_version;  sn->sn_subscribed = now - s->s_subscribed;  sn->sn_notified = s->s_notified;  sn->sn_view = s->s_view;}/** Create an event server. * * The function nea_server_create() initializes an event server object and * registers it with @b nta. An event server object takes care of all events * for a particular URI (@em eventity). *  * @param agent       pointer to an @b nta agent object * @param root        pointer to an @b root object *燖param url         url of the server to be created * @param max_subs    maximum number of subscriptions * @param callback    authorization function,  *                    or @c NULL if no authorization is required * @param context     server context (pointer to application data) * @param tag, value, ... optional list of tag parameters * * @TAGS * The function nea_server_create() takes the following tag values as its  * arguments: * <dl> * * <dt>SIPTAG_CONTACT() or SIPTAG_CONTACT_STR() * <dd>The target address of the event server. * * <dt>SIPTAG_ALLOW_EVENTS() * <dd>The initial list of events supported by eventity. This list is * extended whenever a new event is created with nea_event_tcreate(). * * <dt>SIPTAG_SERVER_STR() * <dd>The @b Server header for the event server. * * <dt>NEATAG_MINSUB() * <dd>Minimum duration of a subscription. *  * <dt>NEATAG_THROTTLE() * <dd>Default value for event throttle (by default, 5 seconds). * Throttle determines the minimum interval betweeen notifications. Note * that the notification indicating that the subscription has terminated * will be sent regardless of throttle. *  * The default throttle value is used if the subscriber does not include * a throttle parameter in @ref sip_event "Event" header of SUBSCRIBE request. *  * <dt>NEATAG_MINTHROTTLE() * <dd>Minimum allowed throttle value (by default, 5 seconds). *  * <dt>NEATAG_EVENTLIST() * <dd>If true, the subscribers must support eventlists. If SIPTAG_REQUIRE() * is given, it must contain the "eventlist" feature. * * <dt>NEATAG_DIALOG() * <dd>Give an optional NTA destination leg to event server. *  * <dt>SIPTAG_REQUIRE()/SIPTAG_REQUIRE_STR() * <dd>The @b Require header for the event server. The subscribers must * indicate support the specified features. * * </dl> * * @return * The function nea_server_create() returns a pointer to an event server * object, or @c NULL upon an error. */nea_server_t *nea_server_create(nta_agent_t *agent,				su_root_t *root,				url_t const *url,				int max_subs,				nea_new_event_f *callback,				nea_smagic_t *context,				tag_type_t tag, tag_value_t value, ...){  nea_server_t *nes = NULL;  sip_contact_t const *contact = NULL;  sip_allow_events_t const *allow_events = NULL;  sip_require_t const *rq = NULL;  char const *contact_str = NULL;  char const *server_str = NULL;  char const *rq_str = NULL;  unsigned     min_expires = 15 * 60,     expires = NEA_DEFAULT_EXPIRES,    max_expires = 24 * 60 * 60;  nta_leg_t *leg = NONE;  unsigned throttle = 5, min_throttle = throttle;  int eventlist = 0;  {    ta_list ta;    ta_start(ta, tag, value);    tl_gets(ta_args(ta), 	    SIPTAG_CONTACT_REF(contact),	    SIPTAG_CONTACT_STR_REF(contact_str),	    SIPTAG_ALLOW_EVENTS_REF(allow_events),	    SIPTAG_SERVER_STR_REF(server_str),	    SIPTAG_REQUIRE_REF(rq),	    SIPTAG_REQUIRE_STR_REF(rq_str),	    NEATAG_MIN_EXPIRES_REF(min_expires),	    NEATAG_EXPIRES_REF(expires),	    NEATAG_MAX_EXPIRES_REF(max_expires),	    NEATAG_DIALOG_REF(leg),	    NEATAG_THROTTLE_REF(throttle),	    NEATAG_MINTHROTTLE_REF(min_throttle),	    NEATAG_EVENTLIST_REF(eventlist),	    TAG_NULL());    ta_end(ta);  }  if (throttle < min_throttle)    throttle = min_throttle;  if (!url) {    SU_DEBUG_5(("nea_server_create(): invalid url\n"));    return NULL;  }  if (min_expires > expires || expires > max_expires) {    SU_DEBUG_5(("nea_server_create(): invalid expiration range\n"));    return NULL;  }    nes = su_home_new(sizeof(nea_server_t));  if (nes) {    su_home_t *home = nes->nes_home;    nes->nes_root = root;    nes->nes_agent = agent;    nes->nes_max_subs = max_subs;    nes->nes_min_expires = min_expires;    nes->nes_expires = expires;    nes->nes_max_expires = max_expires;    nes->nes_throttle = throttle;    nes->nes_min_throttle = min_throttle;    if (allow_events)      nes->nes_allow_events = sip_allow_events_dup(home, allow_events);    else      nes->nes_allow_events = sip_allow_events_make(home, "");    nes->nes_allow_methods = sip_allow_make(home, "SUBSCRIBE");    nes->nes_server =       su_sprintf(home, "%s%snea/" NEA_VERSION_STR " %s", 		 server_str ? server_str : "",		 server_str ? " " : "", 		 nta_agent_version(agent));    if (contact)      nes->nes_eventity_uri = sip_contact_dup(home, contact);    else if (contact_str)      nes->nes_eventity_uri = sip_contact_make(home, contact_str);    else      nes->nes_eventity_uri = sip_contact_create(home, (url_string_t *)url, NULL);    if (leg != NONE) {      nes->nes_leg = leg;      if (leg != NULL)	nta_leg_bind(leg, nea_server_callback, (nea_sub_t*)nes);    } else {      nes->nes_leg = nta_leg_tcreate(agent, 				     nea_server_callback, 				     (nea_sub_t*)nes, 				     NTATAG_NO_DIALOG(1),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -