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

📄 subscribe.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Presence Agent, subscribe handling * * $Id: subscribe.c,v 1.2 2005/06/16 12:41:52 bogdan_iancu Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser 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 General Public License for more details. * * You should have received a copy of the GNU General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * History: * --------- * 2003-02-29 scratchpad compatibility abandoned * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) */#include <string.h>#include "../../str.h"#include "../../dprint.h"#include "../../mem/mem.h"#include "../../parser/parse_uri.h"#include "../../parser/parse_from.h"#include "../../parser/parse_expires.h"#include "../../parser/parse_event.h"#include "../../parser/parse_content.h"#include "presentity.h"#include "watcher.h"#include "pstate.h"#include "notify.h"#include "paerrno.h"#include "pdomain.h"#include "pa_mod.h"#include "ptime.h"#include "reply.h"#include "subscribe.h"#define DOCUMENT_TYPE "application/cpim-pidf+xml"#define DOCUMENT_TYPE_L (sizeof(DOCUMENT_TYPE) - 1)static struct {	int event_type;	int mimes[MAX_MIMES_NR];} event_package_mimetypes[] = {	{ EVENT_PRESENCE, { MIMETYPE(APPLICATION,PIDFXML), #ifdef SUBTYPE_XML_MSRTC_PIDF			    MIMETYPE(APPLICATION,XML_MSRTC_PIDF),#endif			    MIMETYPE(APPLICATION,XPIDFXML), MIMETYPE(APPLICATION,LPIDFXML), 0 } },	{ EVENT_PRESENCE_WINFO, { MIMETYPE(APPLICATION,WATCHERINFOXML), 0 }},#ifdef EVENT_SIP_PROFILE	{ EVENT_SIP_PROFILE, { MIMETYPE(MESSAGE,EXTERNAL_BODY), 0 }},#endif//	{ EVENT_XCAP_CHANGE, { MIMETYPE(APPLICATION,WINFO+XML), 0 } },	{ -1, { 0 }},};/* * contact will be NULL if user is offline * fixme:locking */void callback(str* _user, str *_contact, int state, void* data){     presentity_t *presentity;     get_act_time();     presentity = (struct presentity*)data;     if (presentity && callback_update_db) {	  presence_tuple_t *tuple = NULL;	  int orig;	  LOG(L_ERR, "callback: uri=%.*s contact=%.*s state=%d\n",	      presentity->uri.len, presentity->uri.s, (_contact ? _contact->len : 0), (_contact ? _contact->s : ""), state);	  if (_contact) {	       if (callback_lock_pdomain)		    lock_pdomain(presentity->pdomain);	       find_presence_tuple(_contact, presentity, &tuple);	       if (!tuple) {		    new_presence_tuple(_contact, act_time + default_expires, presentity, &tuple);		    add_presence_tuple(presentity, tuple);	       };	       orig = tuple->state;	       if (state == 0) {		    tuple->state = PS_OFFLINE;	       } else {		    tuple->state = PS_ONLINE;	       }	       tuple->expires = act_time + default_expires;	       db_update_presentity(presentity);	       if (orig != state) {		    presentity->flags |= PFLAG_PRESENCE_CHANGED;	       }	       if (callback_lock_pdomain)		    unlock_pdomain(presentity->pdomain);	  }     }}/* * Extract plain uri -- return URI without parameters * The uri will be in form username@domain * */static int extract_plain_uri(str* _uri){	struct sip_uri puri;	if (parse_uri(_uri->s, _uri->len, &puri) < 0) {		paerrno = PA_URI_PARSE;		LOG(L_ERR, "extract_plain_uri(): Error while parsing URI\n");		return -1;	}		_uri->s = puri.user.s;	_uri->len = puri.host.s + puri.host.len - _uri->s;	return 0;}/* * Get presentity URI, which is stored in R-URI */int get_pres_uri(struct sip_msg* _m, str* _puri){	if (_m->new_uri.s) {		_puri->s = _m->new_uri.s;		_puri->len = _m->new_uri.len;	} else {		_puri->s = _m->first_line.u.request.uri.s;		_puri->len = _m->first_line.u.request.uri.len;	}	LOG(L_ERR, "get_pres_uri: _puri=%.*s\n", _puri->len, _puri->s);		if (extract_plain_uri(_puri) < 0) {		LOG(L_ERR, "get_pres_uri(): Error while extracting plain URI\n");		return -1;	}	return 0;}static int get_watch_uri(struct sip_msg* _m, str* _wuri, str *_dn){	_wuri->s = get_from(_m)->uri.s;	_wuri->len = get_from(_m)->uri.len;	_dn->s = get_from(_m)->body.s;	_dn->len = get_from(_m)->body.len;	if (extract_plain_uri(_wuri) < 0) {		LOG(L_ERR, "get_watch_uri(): Error while extracting plain URI\n");		return -1;	}		return 0;}/* * Parse all header fields that will be needed * to handle a SUBSCRIBE request */static int parse_hfs(struct sip_msg* _m, int accept_header_required){	int rc = 0;	if ( ((rc = parse_headers(_m, HDR_FROM_F | HDR_EVENT_F | HDR_EXPIRES_F | HDR_ACCEPT_F, 0)) == -1) 	     || (_m->from==0) || (_m->event==0) ) {		paerrno = PA_PARSE_ERR;		LOG(L_ERR, "parse_hfs(): Error while parsing headers: rc=%d\n", rc);		return -1;	}	if (parse_from_header(_m) < 0) {		paerrno = PA_FROM_ERR;		LOG(L_ERR, "parse_hfs(): From malformed or missing\n");		return -6;	}	if (_m->event) {		if (parse_event(_m->event) < 0) {			paerrno = PA_EVENT_PARSE;			LOG(L_ERR, "parse_hfs(): Error while parsing Event header field\n");			return -8;		}	}	if (_m->expires) {		if (parse_expires(_m->expires) < 0) {			paerrno = PA_EXPIRES_PARSE;			LOG(L_ERR, "parse_hfs(): Error while parsing Expires header field\n");			return -9;		}	}	/* now look for Accept header */	if (_m->accept) {		LOG(L_ERR, "parsing accept header\n");		if (parse_accept_hdr(_m) < 0) {			paerrno = PA_ACCEPT_PARSE;			LOG(L_ERR, "parse_hfs(): Error while parsing Accept header field\n");			return -10;		}	} else if (accept_header_required) {		LOG(L_ERR, "no accept header\n");		return -11;	}	return 0;}/* * Check if a message received has been constructed properly */int check_message(struct sip_msg* _m){	LOG(L_ERR, "check_message -0- _m=%p\n", _m);	if (_m->event) {		event_t *parsed_event;		int *accepts_mimes = NULL;		LOG(L_ERR, "check_message -1-");		if (_m->accept) {			accepts_mimes = get_accept(_m);			if (accepts_mimes) {				char buf[100];				int offset = 0;				int *a = accepts_mimes;				buf[0] = '0';				while (*a) {					offset += sprintf(buf+offset, ":%#06x", *a);					a++;				}				LOG(L_ERR, "pa check_message: accept=%.*s parsed=%s\n",				    _m->accept->body.len, _m->accept->body.s, buf);			}		}		LOG(L_ERR, "check_message -2- accepts_mimes=%p\n", accepts_mimes);		if (!_m->event->parsed)			parse_event(_m->event);		LOG(L_ERR, "check_message -3-\n");		parsed_event = (event_t*)(_m->event->parsed);		LOG(L_ERR, "check_message -4- parsed_event=%p\n", parsed_event);		if (parsed_event && accepts_mimes) {			int i = 0;			int eventtype = parsed_event->parsed;			LOG(L_ERR, "check_message -4- eventtype=%#06x\n", eventtype);			while (event_package_mimetypes[i].event_type != -1) {				LOG(L_ERR, "check_message -4a- eventtype=%#x epm[i].event_type=%#x", 				    eventtype, event_package_mimetypes[i].event_type);				if (eventtype == event_package_mimetypes[i].event_type) {					int j = 0;					int mimetype;					while ((mimetype = event_package_mimetypes[i].mimes[j]) != 0) {						int k = 0;						while (accepts_mimes[k]) {							LOG(L_ERR, "check_message -4c- eventtype=%#x mimetype=%#x accepts_mimes[k]=%#x\n", eventtype, mimetype, accepts_mimes[k]);							if (accepts_mimes[k] == mimetype) {								int am0 = accepts_mimes[0];								/* we have a match */								LOG(L_ERR, "check_message -4b- eventtype=%#x accepts_mime=%#x\n", eventtype, mimetype);								/* move it to front for later */								accepts_mimes[0] = mimetype;								accepts_mimes[k] = am0;								return 0;							}							k++;						}						j++;					}				}				i++;			}			/* else, none of the mimetypes accepted are generated for this event package */			{				char *accept_s = NULL;				int accept_len = 0;				if (_m->accept && _m->accept->body.len) {					accept_s = _m->accept->body.s;					accept_len = _m->accept->body.len;				}				LOG(L_ERR, "check_message(): Accepts %.*s not valid for event package et=%.*s\n",				    _m->accept->body.len, _m->accept->body.s, _m->event->body.len, _m->event->body.s);				return -1;			}		}		LOG(L_ERR, "check_message -5-\n");	}	return 0;}int get_preferred_event_mimetype(struct sip_msg *_m, int et){	int acc = 0;	if (_m->accept) {		//LOG(L_ERR, "%s: has accept header\n", __FUNCTION__);		int *accepts_mimes = get_accept(_m);		acc = accepts_mimes[0];	} else {		int i = 0;		//LOG(L_ERR, "%s: no accept header\n", __FUNCTION__);		while (event_package_mimetypes[i].event_type != -1) {			if (event_package_mimetypes[i].event_type == et) {				acc = event_package_mimetypes[i].mimes[0];				LOG(L_ERR, "%s: defaulting to mimetype %x for event_type=%d\n", __FUNCTION__, acc, et);				break;			}			i++;		}	}	return acc;}/* * Create a new presentity and corresponding watcher list */int create_presentity(struct sip_msg* _m, struct pdomain* _d, str* _puri, 			     struct presentity** _p, struct watcher** _w){	time_t e;	dlg_t* dialog;	str watch_uri;	str watch_dn;	event_t *event = NULL;	int et = 0;	int acc = 0;	if (_m->event) {		event = (event_t*)(_m->event->parsed);		et = event->parsed;	} else {		et = EVENT_PRESENCE;	}	acc = get_preferred_event_mimetype(_m, et);	if (_m->expires) {		e = ((exp_body_t*)_m->expires->parsed)->val;	} else {		e = default_expires;	}		if (e == 0) {		*_p = 0;		*_w = 0;		DBG("create_presentity(): expires = 0\n");		return 0;	}	/* Convert to absolute time */	e += act_time;	if (get_watch_uri(_m, &watch_uri, &watch_dn) < 0) {		LOG(L_ERR, "create_presentity(): Error while extracting watcher URI\n");		return -1;	}	if (new_presentity(_d, _puri, _p) < 0) {		LOG(L_ERR, "create_presentity(): Error while creating presentity\n");		return -2;	}	if (tmb.new_dlg_uas(_m, 200, &dialog) < 0) {		paerrno = PA_DIALOG_ERR;		LOG(L_ERR, "create_presentity(): Error while creating dialog state\n");		free_presentity(*_p);		return -3;	}	if (et != EVENT_PRESENCE_WINFO) {		if (add_watcher(*_p, &watch_uri, e, et, acc, dialog, &watch_dn, _w) < 0) {

⌨️ 快捷键说明

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