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

📄 sip_pref_util.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 * *//**@CFILE sip_pref_util.c *  * SIP callercaps and callerprefs utility functions. * * @author Pekka Pessi <Pekka.Pessi@nokia.com>. * * @date Created: Tue Nov  2 16:39:33 EET 2004 ppessi */#include "config.h"#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <float.h>#include "sofia-sip/sip_parser.h"#include <sofia-sip/sip_header.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/sip_status.h>static double parse_number(char const *str, char **return_end);/** Parse a single preference */int sip_prefs_parse(union sip_pref *sp, 		    char const **in_out_s, 		    int *return_negation){  char const *s;  size_t n;  enum sp_type old_type;  assert(sp && in_out_s && *in_out_s && return_negation);  old_type = sp->sp_type;  sp->sp_type = sp_error;  s = *in_out_s;  if (!s)    return 0;  if (old_type == sp_init) {    if (s[0] == '\0' || 	strcasecmp(s, "TRUE") == 0 ||	strcasecmp(s, "\"TRUE\"") == 0) {      /* Boolean */      sp->sp_type = sp_literal;      sp->sp_literal.spl_value = "TRUE";      sp->sp_literal.spl_length = 4;      *return_negation = 0;      *in_out_s = s + strlen(s);      return 1;    } else if (strcasecmp(s, "FALSE") == 0 || 	       strcasecmp(s, "\"FALSE\"") == 0) {      /* Boolean */      sp->sp_type = sp_literal;      sp->sp_literal.spl_value = "FALSE";      sp->sp_literal.spl_length = 5;      *return_negation = 0;      *in_out_s = s + strlen(s);      return 1;    } else if (s[0] == '"' && s[1] != '\0') {      for (s++; IS_LWS(s[0]); s++);    } else      old_type = sp_error;        } else if (!s[0]) {    sp->sp_type = sp_init;    return 0;  }  if (old_type == sp_error)    return 0;  if ((*return_negation = s[0] == '!'))      for (s++; IS_LWS(s[0]); s++);  if (*s == '#') {    /* Numeric */    double n1, n2;    char s0, *e;    for (s++; IS_LWS(s[0]); s++);        s0 = s[0];    if (s0 == '=')      sp->sp_type = sp_range, n1 = n2 = parse_number(s = s + 1, &e);    else if (s0 == '<' && s[1] == '=')      sp->sp_type = sp_range, n1 = -DBL_MAX, n2 = parse_number(s = s + 2, &e);    else if (s0 == '>' && s[1] == '=')      sp->sp_type = sp_range, n1 = parse_number(s = s + 2, &e), n2 = DBL_MAX;    else if (((n1 = parse_number(s, &e)) != 0.0 || s != e) && e[0] == ':')      sp->sp_type = sp_range, n2 = parse_number(s = e + 1, &e);    else      /* Error in conversion */      sp->sp_type = sp_error, n1 = DBL_MAX, n2 = -DBL_MAX;    if (s == e && (n1 == 0.0 || n2 == 0.0))      sp->sp_type = sp_error;      /* Error in conversion */    sp->sp_range.spr_lower = n1;    sp->sp_range.spr_upper = n2;    s = e;  } else if (*s == '<') {    /* Quoted string */    n = strcspn(++s, ">");    sp->sp_type = sp_string;    sp->sp_string.sps_value = s;    sp->sp_string.sps_length = n;    s += n + 1;  } else if ((n = span_token(s))) {    /* Literal */    sp->sp_type = sp_literal;    sp->sp_literal.spl_value = s;    sp->sp_literal.spl_length = n;    s += n;  }  for (; IS_LWS(s[0]); s++);  if (s[0] == ',' || (s[0] == '"' && s[1] == '\0'))    for (s++; IS_LWS(s[0]); s++);  else    old_type = sp_error;  if (old_type != sp_init && old_type != sp->sp_type)     sp->sp_type = sp_error;      *in_out_s = s;  return sp->sp_type != sp_error;}/** Parse number: * number          =  [ "+" / "-" ] 1*DIGIT ["." 0*DIGIT] */static double parse_number(char const *str, char **return_end){  double value = 0.0;  double decimal = 0.1;  char d, sign = '+';  if (return_end)    *return_end = (char *)str;  d = *str;  if (d == '+' || d == '-')    sign = d, d = *++str;  if (!('0' <= d && d <= '9'))    return value;  for (; '0' <= d && d <= '9'; d = *++str)    value = value * 10 + (d - '0');  if (d == '.') for (d = *++str; '0' <= d && d <= '9'; d = *++str) {    value += (d - '0') * decimal; decimal *= 0.1;  }  if (value > DBL_MAX)    value = DBL_MAX;  if (sign == '-')    value = -value;  if (return_end)    *return_end = (char *)str;  return value;}/** Return true if preferences match */int sip_prefs_match(union sip_pref const *a, 		    union sip_pref const *b){  if (!a || !b)    return 0;  if (a->sp_type != b->sp_type)    return 0;  switch (a->sp_type) {  default:  case sp_error:     return 0;  case sp_literal:    return       a->sp_literal.spl_length == b->sp_literal.spl_length &&      strncasecmp(a->sp_literal.spl_value, b->sp_literal.spl_value,		  a->sp_literal.spl_length) == 0;  case sp_string:    return       a->sp_string.sps_length == b->sp_string.sps_length &&      strncmp(a->sp_string.sps_value, b->sp_string.sps_value,	      a->sp_string.sps_length) == 0;  case sp_range:    return       a->sp_range.spr_lower <= b->sp_range.spr_upper &&      a->sp_range.spr_upper >= b->sp_range.spr_lower;  }}/**Find a matching parameter-value pair from a parameter list. * * Check if the given feature values match with each other. * * @param pvalue first feature parameter * @param nvalue second feature parameter * @param return_parse_error return-value parameter for error (may be NULL) * * @retval 1 if given feature parameters match * @retval 0 if there is no match or a parse or type error occurred. * * If there is a parsing or type error, 0 is returned and @a * *return_parse_error is set to -1. * * @sa sip_prefs_parse(), sip_prefs_match(), union #sip_pref. */int sip_prefs_matching(char const *pvalue,		       char const *nvalue,		       int *return_parse_error){  int error;  char const *p;  union sip_pref np[1], pp[1];  int n_negated, p_negated;  if (!return_parse_error)    return_parse_error = &error;  if (!pvalue || !nvalue)    return 0;  memset(np, 0, sizeof np);  /* Usually nvalue is from Accept/Reject-Contact,      pvalue is from Contact */  while (sip_prefs_parse(np, &nvalue, &n_negated)) {    memset(pp, 0, sizeof pp);    p = pvalue;    while (sip_prefs_parse(pp, &p, &p_negated)) {      if (pp->sp_type != np->sp_type) /* Types do not match */	return 0;      if (sip_prefs_match(np, pp) /* We found matching value */	  ? !p_negated	/* without negative */	  : p_negated)	/* Negative did not match */	break;    }    if (pp->sp_type == sp_error)      return *return_parse_error = -1, 0;    if (pp->sp_type != sp_init /* We found matching value */	? !n_negated		/* and we expected one */	: n_negated)		/* We found none and expected none */      return 1;  }  if (np->sp_type == sp_error)    *return_parse_error = -1;  return 0;}/** Check if the parameter is a valid feature tag.  * * A feature tag is a parameter starting with a single plus, or a well-known * feature tag listed in @RFC3841: "audio", "automata", "application", * "class", "control", "duplex", "data", "description", "events", "isfocus", * "language", "mobility", "methods", "priority", "schemes", "type", or * "video". However, well-known feature tag can not start with plus. So, * "+alarm" or "audio" is a feature tag, "alarm", "++alarm", or "+audio" are * not.

⌨️ 快捷键说明

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