📄 msg_parser_util.c
字号:
if (dup) d[n++] = su_strdup(home, src[m]); /* XXX */ else d[n++] = src[m]; } d[n] = NULL; return 0;}/**Join header item lists. * * Join items from a source header to the destination header. The item are * compared with the existing ones. If a match is found, it is not added to * the list. If @a duplicate is true, the entries are duplicated while they * are added to the list. * * @param home memory home * @param dst destination header * @param src source header * @param duplicate if true, allocate and copy items that are added * * @return * @retval >= 0 when successful * @retval -1 upon an error * * @NEW_1_12_5. */int msg_header_join_items(su_home_t *home, msg_common_t *dst, msg_common_t const *src, int duplicate){ size_t N, m, M, i, n_before, n_after, total; char *dup = NULL; msg_param_t *d, **dd, *s; msg_param_t t, *temp, temp0[16]; size_t *len, len0[(sizeof temp0)/(sizeof temp0[0])]; msg_update_f *update = NULL; if (dst == NULL || dst->h_class->hc_params == 0 || src == NULL || src->h_class->hc_params == 0) return -1; s = *(msg_param_t **)((char *)src + src->h_class->hc_params); if (s == NULL) return 0; for (M = 0; s[M]; M++); if (M == 0) return 0; if (M <= (sizeof temp0) / (sizeof temp0[0])) { temp = temp0, len = len0; } else { temp = malloc(M * (sizeof *temp) + M * (sizeof *len)); if (!temp) return -1; len = (void *)(temp + M); } dd = (msg_param_t **)((char *)dst + dst->h_class->hc_params); d = *dd; for (N = 0; d && d[N]; N++); for (m = 0, M = 0, total = 0; s[m]; m++) { t = s[m]; for (i = 0; i < N; i++) if (strcmp(t, d[i]) == 0) break; if (i < N) continue; for (i = 0; i < M; i++) if (strcmp(t, temp[i]) == 0) break; if (i < M) continue; temp[M] = t; len[M] = strlen(t); total += len[M++] + 1; } if (M == 0) goto success; dup = su_alloc(home, total); if (!dup) goto error; n_before = MSG_PARAMS_NUM(N + 1); n_after = MSG_PARAMS_NUM(N + M + 1); if (d == NULL || n_before != n_after) { d = su_alloc(home, n_after * sizeof(*d)); if (!d) goto error; if (N) memcpy(d, *dd, N * sizeof(*d)); *dd = d; } update = dst->h_class->hc_update; for (m = 0; m < M; m++) { d[N++] = memcpy(dup, temp[m], len[m] + 1); if (update) update(dst, dup, len[m], dup + len[m]); dup += len[m] + 1; } d[N] = NULL; success: if (temp != temp0) free(temp); return 0; error: if (temp != temp0) free(temp); su_free(home, dup); return -1;}/**Compare parameter lists. * * Compares parameter lists. * * @param a pointer to a parameter list * @param b pointer to a parameter list * * @retval an integer less than zero if @a is less than @a b * @retval an integer zero if @a match with @a b * @retval an integer greater than zero if @a is greater than @a b */int msg_params_cmp(char const * const a[], char const * const b[]){ int c; size_t nlen; if (a == NULL || b == NULL) return (a != NULL) - (b != NULL); for (;;) { if (*a == NULL || *b == NULL) return (*a != NULL) - (*b != NULL); nlen = strcspn(*a, "="); if ((c = strncasecmp(*a, *b, nlen))) return c; if ((c = strcmp(*a + nlen, *b + nlen))) return c; a++, b++; }}/** Unquote string * * Duplicates the string @a q in unquoted form. */char *msg_unquote_dup(su_home_t *home, char const *q){ char *d; size_t total, n, m; /* First, easy case */ if (q[0] == '"') q++; n = strcspn(q, "\"\\"); if (q[n] == '\0' || q[n] == '"') return su_strndup(home, q, n); /* Hairy case - backslash-escaped chars */ total = n; for (;;) { if (q[n] == '\0' || q[n] == '"' || q[n + 1] == '\0') break; m = strcspn(q + n + 2, "\"\\"); total += m + 1; n += m + 2; } if (!(d = su_alloc(home, total + 1))) return NULL; for (n = 0;;) { m = strcspn(q, "\"\\"); memcpy(d + n, q, m); n += m, q += m; if (q[0] == '\0' || q[0] == '"' || q[1] == '\0') break; d[n++] = q[1]; q += 2; } assert(total == n); d[n] = '\0'; return d;}/** Unquote string */char *msg_unquote(char *dst, char const *s){ int copy = dst != NULL; char *d = dst; if (*s++ != '"') return NULL; for (;;) { size_t n = strcspn(s, "\"\\"); if (copy) memmove(d, s, n); s += n; d += n; if (*s == '\0') return NULL; else if (*s == '"') { if (copy) *d = '\0'; return dst; } else { /* Copy quoted char */ if ((copy ? (*d++ = *++s) : *++s) == '\0') return NULL; s++; } }}/** Quote string */issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s){ char *begin = b; char *end = b + bsiz; if (b && b + 1 < end) *b = '"'; b++; for (;*s;) { size_t n = strcspn(s, "\"\\"); if (n == 0) { if (b && b + 2 < end) b[0] = '\\', b[1] = s[0]; b += 2; s++; } else { if (b && b + n < end) memcpy(b, s, n); b += n; s += n; } } if (b && b + 1 < end) *b = '"'; b++; return b - begin;}/** Calculate a simple hash over a string. */unsigned long msg_hash_string(char const *id){ unsigned long hash = 0; if (id) for (; *id; id++) { hash += (unsigned)*id; hash *= 38501U; } else hash *= 38501U; if (hash == 0) hash = (unsigned long)-1; return hash;}/** Calculate the size of a duplicate of a header structure. */isize_t msg_header_size(msg_header_t const *h){ if (h == NULL || h == MSG_HEADER_NONE) return 0; else return h->sh_class->hc_dxtra(h, h->sh_class->hc_size);}/** Encode a message to the buffer. * * The function msg_encode_e encodes a message to a given buffer. * It returns the length of the message to be encoded, even if the * buffer is too small (just like snprintf() is supposed to do). * * @param b buffer (may be NULL) * @param size size of buffer * @param mo public message structure (#sip_t, #http_t) * @param flags see # */issize_t msg_object_e(char b[], isize_t size, msg_pub_t const *mo, int flags){ size_t rv = 0; ssize_t n; msg_header_t const *h; if (mo->msg_request) h = mo->msg_request; else h = mo->msg_status; for (; h; h = h->sh_succ) { n = msg_header_e(b, size, h, flags); if (n < 0) return -1; if ((size_t)n < size) b += n, size -= n; else b = NULL, size = 0; rv += n; } return rv;}/** Encode header contents. */issize_t msg_header_field_e(char b[], isize_t bsiz, msg_header_t const *h, int flags){ assert(h); assert(h->sh_class); return h->sh_class->hc_print(b, bsiz, h, flags);}/** Get offset of header @a h from structure @a mo. */msg_header_t **msg_header_offset(msg_t const *msg, msg_pub_t const *mo, msg_header_t const *h){ if (h == NULL || h->sh_class == NULL) return NULL; return msg_hclass_offset(msg->m_class, mo, h->sh_class);}/**Get a header from the public message structure. * * Gets a pointer to header from a message structure. * * @param pub public message structure from which header is obtained * @param hc header class */msg_header_t *msg_header_access(msg_pub_t const *pub, msg_hclass_t *hc){ msg_header_t * const * hh; if (pub == NULL || hc == NULL) return NULL; hh = msg_hclass_offset((void *)pub->msg_ident, (msg_pub_t *)pub, hc); if (hh) return *hh; else return NULL;}#include <sofia-sip/su_uniqueid.h>/** Generates a random token. * */issize_t msg_random_token(char token[], isize_t tlen, void const *rmemp, isize_t rsize){ uint32_t random = 0, rword; uint8_t rbyte; uint8_t const *rmem = rmemp; size_t i; ssize_t n; static char const token_chars[33] = /* Create aesthetically pleasing raNDom capS LooK */ "aBcDeFgHjKmNpQrStUvXyZ0123456789"; if (rmem == NULL && rsize == 0) rsize = UINT_MAX; if (rsize == 0) { if (token && tlen > 0) strcpy(token, "+"); return 1; } if (token == NULL) { if (rsize >= tlen * 5 / 8) return tlen; else return rsize / 5 * 8; } for (i = 0, n = 0; i < tlen;) { if (n < 5) { if (rsize == 0) ; else if (rmem) { rbyte = *rmem++, rsize--; random = random | (rbyte << n); n += 8; } else { rword = su_random(); random = (rword >> 13) & 31; n = 6; } } token[i] = token_chars[random & 31]; random >>= 5; i++, n -= 5; if (n < 0 || (n == 0 && rsize == 0)) break; } token[i] = 0; return i;}/** Parse a message. * * Parse a text message with parser @a mc. The @a data is copied and it is * not modified or referenced by the parsed message. * * @par Example * Parse a SIP message fragment (e.g., payload of NOTIFY sent in response to * REFER): * @code * msg_t *m = msg_make(sip_default_mclass(), 0, pl->pl_data, pl->pl_len); * sip_t *frag = sip_object(m); * @endcode * * @param mc message class (parser table) * @param flags message flags (see #msg_flg_user) * @param data message text * @param len size of message text (if -1, use strlen(data)) * * @retval A pointer to a freshly allocated and parsed message. * * Upon parsing error, the header structure may be left incomplete. The * #MSG_FLG_ERROR is set in @a msg_object(msg)->msg_flags. * * @since New in @VERSION_1_12_4 * * @sa msg_as_string(), msg_extract() */msg_t *msg_make(msg_mclass_t const *mc, int flags, void const *data, ssize_t len){ msg_t *msg; msg_iovec_t iovec[2]; if (len == -1) len = strlen(data); if (len == 0) return NULL; msg = msg_create(mc, flags); if (msg == NULL) return NULL; su_home_preload(msg_home(msg), 1, len + 1024); if (msg_recv_iovec(msg, iovec, 2, len, 1) < 0) { perror("msg_recv_iovec"); } assert((ssize_t)iovec->mv_len == len); memcpy(iovec->mv_base, data, len); msg_recv_commit(msg, len, 1); if (msg_extract(msg) < 0) msg->m_object->msg_flags |= MSG_FLG_ERROR; return msg;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -