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

📄 sip_pref_util.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * @retval 1 if string is a feature tag parameter * @retval 0 otherwise */int sip_is_callerpref(char const *param){#define MATCH(s) \  (strncasecmp(param + 1, s + 1, strlen(s) - 1) == 0 && \   (param[strlen(s)] == '=' || param[strlen(s)] == '\0'))  int xor = 0, base = 0;  if (!param || !param[0])    return 0;  if (param[0] == '+')    param++, xor = 1;  switch (param[0]) {  case 'a': case 'A':    base = MATCH("audio") || MATCH("automata") || MATCH("application") ||      MATCH("actor");    break;  case 'c': case 'C':    base = MATCH("class") || MATCH("control");    break;  case 'd': case 'D':    base = MATCH("duplex") || MATCH("data") || MATCH("description");    break;  case 'e': case 'E':    base = MATCH("events");    break;  case 'i': case 'I':    base = MATCH("isfocus");    break;  case 'l': case 'L':    base = MATCH("language");    break;  case 'm': case 'M':    base = MATCH("mobility") || MATCH("methods");    break;  case 'p': case 'P':    base = MATCH("priority");    break;  case 's': case 'S':    base = MATCH("schemes");    break;  case 't': case 'T':    base = MATCH("type");    break;  case 'v': case 'V':    base = MATCH("video");    break;  default:    base = 0;    break;  }#undef MATCH  return base ^ xor;}/** Check if @Contact is immune to callerprefs. */int sip_contact_is_immune(sip_contact_t const *m){  unsigned i;  if (m->m_params)    for (i = 0; m->m_params[i]; i++) {      if (sip_is_callerpref(m->m_params[i]))	return 0;    }  return 1;}/**Check if @Contact matches by @AcceptContact. *  * Matching @AcceptContact and @Contact headers is done as explained in * @RFC3841 section 7.2.4. The caller score can be calculated from the * returned S and N values. * * @par Matching * The @AcceptContact header contains number of feature tag parameters. The * count of feature tags is returned in @a return_N. For each feature tag in * @AcceptContact, the feature tag with same name is searched from the * @Contact header. If both headers contain the feature tag with same name, * their values are compared. If the value in @AcceptContact does not match * with the value in @Contact, there is mismatch and 0 is returned. If they * match, S is increased by 1. * * @param m   pointer to @Contact header structure * @param cp   pointer to @AcceptContact header structure * @param return_N   return-value parameter for number of  *                   feature tags in @AcceptContact * @param return_S   return-value parameter for number of  *                   matching feature tags * @param return_error   return-value parameter for parsing error * * For example, * @code * if (sip_contact_accept(contact, accept_contact, &S, &N, &error)) { *   if (N == 0) *     score == 1.0; *   else *     score = (double)S / (double)N; *   if (accept_contact->cp_explicit) { *     if (accept_contact->cp_require) *       goto drop; *     else *       score = 0.0; *   } * } * else if (!error) { *   score = 0.0; * } * @endcode * * @retval 1 if @Contact matches * @return @a return_S contains number of matching feature tags * @return @a return_N contains number of feature tags in @AcceptContact * @retval 0 if @Contact does not match * @return @a return_error contains -1 if feature tag value was malformed * * @sa @RFC3841 section 7.2.4, sip_contact_score(), sip_contact_reject(), * sip_contact_is_immune(), sip_contact_immunize(), sip_is_callerpref(), * sip_prefs_matching(). */int sip_contact_accept(sip_contact_t const *m, 		       sip_accept_contact_t const *cp,		       unsigned *return_S,		       unsigned *return_N,		       int *return_error){  char const *cap, *acc;  unsigned i, S, N;  size_t eq;  if (!return_N) return_N = &N;  if (!return_S) return_S = &S;  *return_S = 0, *return_N = 0;  if (!m || !cp || !m->m_params || !cp->cp_params)    return 1;  for (i = 0, S = 0, N = 0; cp->cp_params[i]; i++) {    acc = cp->cp_params[i];    if (!sip_is_callerpref(acc))      continue;    N++;    cap = msg_params_find(m->m_params, acc);    if (cap) {      eq = strcspn(acc, "=");      acc += eq + (acc[eq] == '=');      if (!sip_prefs_matching(cap, acc, return_error)) 	return 0;            S++;    }  }  *return_S = S; /* Matched feature tags */  *return_N = N; /* Number of feature tags in @AcceptContact */  return 1; }/** Check if @Contact is rejected by @RejectContact. * * @param m pointer to @Contact header * @param reject pointer to @RejectContact header * * @retval 1 when rejecting * @retval 0 when @Contact does not match with @RejectContact * * @sa sip_contact_score(), sip_contact_accept(), sip_contact_immunize(), * sip_contact_is_immune(), @RFC3841, @RejectContact, @Contact */int sip_contact_reject(sip_contact_t const *m, 		       sip_reject_contact_t const *reject){  unsigned S, N;  int error;  if (!m || !m->m_params || !reject || !reject->cp_params)    return 0;  return sip_contact_accept(m, reject, &S, &N, &error) && S == N && N > 0;}/**Immunize @Contact to callerprefs. * * Make a copy of @Contact header @a m and remove all parameters which * affect caller preferences. * * @param home   home object used when allocating copy * @param m   pointer to @Contact header structure to immunize * * @retval pointer to immunized copy if successful * @retval NULL upon an error *  * @sa @RFC3841, sip_is_callerpref(), sip_contact_score(), * sip_contact_accept(), sip_contact_reject(), @Contact */sip_contact_t *sip_contact_immunize(su_home_t *home, sip_contact_t const *m){  unsigned i, j;  sip_contact_t m0[1], *m1;  msg_param_t *params;  if (!m)    return NULL;  *m0 = *m, m0->m_next = NULL;  m1 = sip_contact_copy(home, m0);  if (m1 == NULL || !m1->m_params)    return m1;  params = (msg_param_t *)m1->m_params;  for (i = 0, j = 0; params[i]; i++) {    if (!sip_is_callerpref(params[i]))      params[j++] = params[i];  }  params[j] = NULL;  return m1;}/** Calculate score for contact. * * The caller preference score is an integer in range of 0 to 1000. *  * @retval -1 if the contact is rejected * @retval 1000 if contact is immune to caller preferences * @retval 0..1000 reflecting @RFC3841 score in 0.000 - 1.000. * * @sa sip_q_value(), * sip_contact_accept(), sip_contact_reject(), sip_contact_is_immune(), * sip_contact_immunize(), sip_is_callerpref(), sip_prefs_matching(), * @RFC3841, @AcceptContact, @RejectContact, @Contact */int sip_contact_score(sip_contact_t const *m,		      sip_accept_contact_t const *ac,		      sip_reject_contact_t const *rc){  unsigned long S_total = 0;  unsigned M = 0, scale = 1000;  int error = 0;  if (sip_contact_is_immune(m))    return 1000;		/* Immune */  for (; rc; rc = rc->cp_next)    if (sip_contact_reject(m, rc))       break;  if (rc)    return -1;			/* Rejected */  for (; ac; ac = ac->cp_next) {    unsigned S, N;	    if (!sip_contact_accept(m, ac, &S, &N, &error)) {      if (ac->cp_require)	return 0;		/* Discarded */      continue;    }    M++;    /* Apply score */    if (S < N && ac->cp_explicit) {      S = 0;      if (ac->cp_require)	return 0;		/* Dropped */    }    if (S > 0 && N > 0)       S_total += sip_q_value(ac->cp_q) * (scale * S / N + (2 * S >= N));  }  if (!M)     return 0;  S_total /= M;  if (S_total < scale * 1000)    return S_total / scale;  else    return 1000;}

⌨️ 快捷键说明

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