📄 msg_parser.c
字号:
case msg_kind_single: case msg_kind_list: old = (*hh); break; case msg_kind_append: case msg_kind_apndlist: while (*hh) hh = &(*hh)->sh_next; break; case msg_kind_prepend: for (end = h; end->sh_next; end = end->sh_next) ; end->sh_next = *hh; } if (*head) { /* Insert into existing fragment chain */ msg_insert_chain(msg, pub, msg_is_prepend(h), head, h); /* Remove replaced fragment */ if (old) msg_chain_remove(msg, old); } /* Insert into header list */ *hh = h; return 0;}/**Prepend a (list of) header(s) to the header structure and fragment chain. * * The function @c msg_header_prepend() adds a header or list of headers into * the given place within the message structure. It also inserts the headers * into the the message fragment chain, if it exists. * * Unlike msg_header_add(), msg_header_prepend() always inserts header @a h * before other headers of the same class. If the header is a singleton, * existing headers of the same class are removed. If the header is a list * header, the values in the new header are prepended to the existing list. * * @param msg message owning the fragment chain * @param pub public message structure * @param hh place in message structure to which header is added * @param h list of header(s) to be added */int msg_header_prepend(msg_t *msg, msg_pub_t *pub, msg_header_t **hh, msg_header_t *h){ msg_header_t **head, *old = NULL, *end; assert(msg && pub); if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || hh == NULL) return -1; if (pub == NULL) pub = msg->m_object; head = _msg_chain_head(msg); if (*head) { msg_header_t *sh, **prev; for (sh = h, prev = NULL; sh; sh = sh->sh_next) { sh->sh_succ = sh->sh_next; sh->sh_prev = prev; prev = &sh->sh_succ; } } switch (h->sh_class->hc_kind) { case msg_kind_single: case msg_kind_list: old = (*hh); break; case msg_kind_append: case msg_kind_apndlist: case msg_kind_prepend: for (end = h; end->sh_next; end = end->sh_next) ; end->sh_next = *hh; break; } if (*head) { /* Insert into existing fragment chain */ msg_insert_chain(msg, pub, 1, head, h); /* Remove replaced fragment */ if (old) msg_chain_remove(msg, old); } /* Insert into header list */ *hh = h; return 0;}/** Find place to insert header of the class @a hc. */msg_header_t **msg_hclass_offset(msg_mclass_t const *mc, msg_pub_t const *mo, msg_hclass_t *hc){ int i; assert(mc && hc); if (mc == NULL || hc == NULL) return NULL; if (hc->hc_hash > 0) { unsigned j, N = mc->mc_hash_size; for (j = hc->hc_hash % N; mc->mc_hash[j].hr_class; j = (j + 1) % N) if (mc->mc_hash[j].hr_class == hc) { return (msg_header_t **)((char *)mo + mc->mc_hash[j].hr_offset); } } else /* Header has no name. */ for (i = 0; i <= 6; i++) if (hc->hc_hash == mc->mc_request[i].hr_class->hc_hash) return (msg_header_t **)((char *)mo + mc->mc_request[i].hr_offset); return NULL;}/** Append a parsed header object into the message structure */static inline voidappend_parsed(msg_t *msg, msg_pub_t *mo, msg_header_t **hh, msg_header_t *h, int always_into_chain){ assert(msg); assert(hh); assert(hh != (void *)mo); if (msg->m_chain || always_into_chain) msg_insert_here_in_chain(msg, msg_chain_tail(msg), h); if (*hh && msg_is_single(h)) { /* If there is multiple instances of single headers, put the extra headers into the list of erroneous headers */ hh = (msg_header_t**)&mo->msg_error; /* Flag this as fatal error */ mo->msg_flags |= MSG_FLG_ERROR; } while (*hh) hh = &(*hh)->sh_next; *hh = h;}/**Duplicate and add a (list of) header(s) to the message. * * The function @c msg_header_add_dup() duplicates and adds a (list of) * header(s) into a message structure. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param src list of header(s) to be added */int msg_header_add_dup(msg_t *msg, msg_pub_t *pub, msg_header_t const *src){ msg_header_t *h, **hh = NULL; msg_hclass_t *hc = NULL; if (msg == NULL) return -1; if (src == NULL || src == MSG_HEADER_NONE) return 0; if (pub == NULL) pub = msg->m_object; for ( ;src; src = src->sh_next) { assert(src->sh_class); if (!src->sh_class) return -1; if (hc != src->sh_class) hh = msg_hclass_offset(msg->m_class, pub, hc = src->sh_class); if (hh == NULL) return -1; if (!*hh || hc->hc_kind != msg_kind_list) { int size = hc->hc_size; int xtra = hc->hc_dxtra(src, size) - size; char *end; if (!(h = msg_header_alloc(msg_home(msg), hc, xtra))) return -1; /* error */ if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra))) return -1; /* error */ if (hc->hc_update) msg_header_update_params(h->sh_common, 0); assert(end == (char *)h + size + xtra); if (msg_header_add(msg, pub, hh, h) < 0) return -1; hh = &h->sh_next; } else { /* Add list items */ msg_header_t *h = *hh; msg_param_t **d, **s; d = msg_header_params(h->sh_common); assert(d); s = msg_header_params(src->sh_common); if (!s || !*s) return 0; msg_fragment_clear(h->sh_common); /* Remove empty headers */ for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next) msg_chain_remove(msg, *hh); if (msg_params_join(msg_home(msg), d, *s, 2 /* prune case */, 1) < 0) return -1; } } if (src) return -1; return 0;}/**Duplicate a header as a given type and add the duplicate into message. * * The function @c msg_header_add_dup_as() duplicates a header as a instance * of the given header class. It adds the new copy into the message. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param hc header class for header target type * @param src list of header(s) to be duplicated and added */int msg_header_add_dup_as(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *src){ if (msg == NULL || hc == NULL) return -1; if (src == NULL || src == MSG_HEADER_NONE) return 0; if (pub == NULL) pub = msg->m_object; return _msg_header_add_dup_as(msg, pub, hc, src);}/** Duplicate and add a (list of) header to a message */staticint _msg_header_add_dup_as(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *src){ msg_header_t *h, **hh; hh = msg_hclass_offset(msg->m_class, pub, hc); if (hh == NULL) return -1; if (*hh && hc->hc_kind == msg_kind_list) { /* Add list items */ msg_header_t *h = *hh; msg_param_t **d, **s; d = msg_header_params(h->sh_common); assert(d); s = msg_header_params(src->sh_common); if (!s || !*s) return 0; msg_fragment_clear(h->sh_common); /* Remove empty headers */ for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next) msg_chain_remove(msg, *hh); return msg_params_join(msg_home(msg), d, *s, 2 /* prune case */, 1); } if (!(h = msg_header_dup_as(msg_home(msg), hc, src))) return -1; return msg_header_add(msg, pub, hh, h);}/** Parse a string as a given header field and add result to the message. */int msg_header_add_make(msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, char const *s){ msg_header_t *h, **hh; if (msg == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh = msg_hclass_offset(msg->m_class, pub, hc); if (hh == NULL) return -1; if (!s) return 0; if (*hh && hc->hc_kind == msg_kind_list) { /* Add list items */ msg_header_t *h = *hh; msg_param_t **d; char *s0; skip_lws(&s); d = msg_header_params(h->sh_common); assert(d); msg_fragment_clear(h->sh_common); /* Remove empty headers */ for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next) msg_chain_remove(msg, *hh); s0 = su_strdup(msg_home(msg), s); if (!s0 || msg_commalist_d(msg_home(msg), &s0, d, msg_token_scan) < 0) return -1; return 0; } if (!(h = msg_header_make(msg_home(msg), hc, s))) return -1; return msg_header_add(msg, pub, hh, h);}/** Parse a string and add resulting headers to the message. * * The function @a msg_header_add_str() parses a string and adds resulting * header objects to the message object. */int msg_header_add_str(msg_t *msg, msg_pub_t *pub, char const *str){ char *s; if (!msg) return -1; if (pub == NULL) pub = msg->m_object; if (!str) return 0; s = su_strdup(msg_home(msg), str); if (s) { int ssiz = strlen(s), used = 0, n = 1; while (ssiz > used) { if (IS_CRLF(s[used])) break; n = msg_extract_header(msg, pub, s + used, ssiz - used, 1); if (n <= 0) break; used += n; } if (n > 0 && ssiz > used) { used += CRLF_TEST(s + used); if (ssiz > used) msg_extract_payload(msg, pub, NULL, ssiz - used, s + used, ssiz - used, 1); } if (n <= 0) return -1; return 0; } return -1;}/** Insert a (list of) header(s) to the fragment chain. * * The function @c msg_header_insert() inserts header or list of headers * into a message structure. It also inserts them into the the message * fragment chain, if it exists. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status). Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message object owning the fragment chain * @param pub public message structure to which header is added * @param h list of header(s) to be added */int msg_header_insert(msg_t *msg, msg_pub_t *pub, msg_header_t *h){ msg_header_t **hh; assert(msg); if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh = msg_hclass_offset(msg->m_class, pub, h->sh_class); return msg_header_add(msg, pub, hh, h);}/**Remove a header from the header structure and fragment chain. * * The function @c msg_header_remove() removes a header from a message * structure. It also removes the message from the message fragment chain * and clears the encoding of other headers objects that share same * encoding. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param h header to be removed */int msg_header_remove(msg_t *msg, msg_pub_t *pub, msg_header_t *h){ msg_header_t **hh, **hh0; if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return -1; if (pub == NULL) pub = msg->m_object; /* First, remove from public structure (msg_pub_t) */ hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class); if (!hh0) return -1; for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (*hh == h) { *hh = h->sh_next; break; } } if (h->sh_data) { void const *data = (char *)h->sh_data + h->sh_len; for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (data == (char *)(*hh)->sh_data + (*hh)->sh_len) { (*hh)->sh_data = NULL, (*hh)->sh_len = 0; } } } msg_chain_remove(msg, h); return 0;}/**Remove a header list from the header structure and fragment chain. * * The function @c msg_header_remove_all() removes a list of headers from a * message structure. It also removes the message from the message fragment * chain and clears the encoding of other headers objects that share same * encoding. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param h header list to be removed */int msg_header_remove_all(msg_t *msg, msg_pub_t *pub, msg_header_t *h){ msg_header_t **hh, **hh0; void const *data; if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL) return -1; if (pub == NULL) pub = msg->m_object; hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class); if (!hh0) return -1; data = (char *)h->sh_data + h->sh_len; /* First, remove from public structure (msg_pub_t) */ for (hh = hh0; *hh; hh = &(*hh)->sh_next) { if (*hh == h) { break; } if (data && data == (char *)(*hh)->sh_data + (*hh)->sh_len) { h->sh_data = NULL, h->sh_len = 0; (*hh)->sh_data = NULL, (*hh)->sh_len = 0; } } /* Remove from header chain */ while (h) { h->sh_data = NULL, h->sh_len = 0; msg_chain_remove(msg, h); h = h->sh_nex
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -