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

📄 subscribe.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Presence Agent, subscribe handling * * $Id: subscribe.c,v 1.24 2004/08/24 09:00:33 janakj Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: *    info@iptel.org * * ser 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 "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 int accepts_to_event_package[N_DOCTYPES] = {	[DOC_XPIDF] = EVENT_PRESENCE,	[DOC_LPIDF] = EVENT_PRESENCE,	[DOC_PIDF] = EVENT_PRESENCE,	[DOC_WINFO] = EVENT_PRESENCE_WINFO,	[DOC_XCAP_CHANGE] = EVENT_XCAP_CHANGE,	[DOC_LOCATION] = EVENT_LOCATION,};/* * A static variable holding document type accepted * by the watcher's user agent */static doctype_t acc;/* * 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 Accept header field body * FIXME: This is ugly parser, write something more clean */int parse_accept(struct hdr_field* _h, doctype_t* _a){	if (_h) {		char* buffer;		/*		 * All implementation must support xpidf so make		 * it the default		 */		*_a = DOC_XPIDF;		buffer = pkg_malloc(_h->body.len + 1);		if (!buffer) {			paerrno = PA_NO_MEMORY;			LOG(L_ERR, "parse_accept(): No memory left\n");			return -1;		}		memcpy(buffer, _h->body.s, _h->body.len);		buffer[_h->body.len] = '\0';			if (strstr(buffer, "application/cpim-pidf+xml")		    || strstr(buffer, "application/pidf+xml")) {			*_a = DOC_PIDF;		} else if (strstr(buffer, "application/xpidf+xml")) {			*_a = DOC_XPIDF;		} else if (strstr(buffer, "text/lpidf")) {			*_a = DOC_LPIDF;		} else if (strstr(buffer, "application/watcherinfo+xml")) {			*_a = DOC_WINFO;		} else if (strstr(buffer, "application/xcap-change+xml")) {			*_a = DOC_XCAP_CHANGE;		} else if (strstr(buffer, "application/location+xml")) {			*_a = DOC_LOCATION;		} else {			*_a = DOC_XPIDF;		}			pkg_free(buffer);		return 0;	} else {		/* XP messenger is not giving an accept field, so default to lpidf */		*_a = DOC_XPIDF;		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){	if ( (parse_headers(_m, HDR_FROM | HDR_EVENT | HDR_EXPIRES | HDR_ACCEPT, 0)				== -1) || (_m->from==0)||(_m->event==0)||(_m->expires==0) ||			(_m->accept==0) ) {		paerrno = PA_PARSE_ERR;		LOG(L_ERR, "parse_hfs(): Error while parsing headers\n");		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;		}	}	if (_m->accept) {		if (parse_accept(_m->accept, &acc) < 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");		acc = DOC_XPIDF;	}	return 0;}/* * Check if a message received has been constructed properly */int check_message(struct sip_msg* _m){	if (_m->event) {		event_t *event;		if (!_m->event->parsed)			parse_event(_m->event);		event = (event_t*)(_m->event->parsed);		if (event && (event->parsed != accepts_to_event_package[acc])) {			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, event->text.len, event->text.s);			return -1;		}	}	return 0;}/* * 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;	if (_m->event) {		event = (event_t*)(_m->event->parsed);		et = event->parsed;	} else {		et = EVENT_PRESENCE;	}	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) {			LOG(L_ERR, "create_presentity(): Error while adding a watcher\n");			tmb.free_dlg(dialog);			free_presentity(*_p);			return -4;		}	} else if (et == EVENT_PRESENCE_WINFO) {		if (add_winfo_watcher(*_p, &watch_uri, e, et, acc, dialog, &watch_dn, _w) < 0) {			LOG(L_ERR, "create_presentity(): Error while adding a winfo watcher\n");			tmb.free_dlg(dialog);			free_presentity(*_p);

⌨️ 快捷键说明

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