PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list, char *buf, pj_size_t size, const pj_cis_t *pname_spec, const pj_cis_t *pvalue_spec, int sep) { const pjsip_param *p; char *startbuf; char *endbuf; int printed; p = param_list->next; if (p == NULL || p == param_list) return 0; startbuf = buf; endbuf = buf + size; PJ_UNUSED_ARG(pname_spec); do { *buf++ = (char)sep; copy_advance_escape(buf, p->name, (*pname_spec)); if (p->value.slen) { *buf++ = '='; if (*p->value.ptr == '"') copy_advance(buf, p->value); else copy_advance_escape(buf, p->value, (*pvalue_spec)); } p = p->next; if (sep == '?') sep = '&'; } while (p != param_list); return buf-startbuf; }
/* Print tel: URI */ static pj_ssize_t tel_uri_print( pjsip_uri_context_e context, const pjsip_tel_uri *uri, char *buf, pj_size_t size) { int printed; char *startbuf = buf; char *endbuf = buf+size-1; const pjsip_parser_const_t *pc = pjsip_parser_const(); PJ_UNUSED_ARG(context); /* Print scheme. */ copy_advance(buf, pc->pjsip_TEL_STR); *buf++ = ':'; /* Print number. */ copy_advance_escape(buf, uri->number, pjsip_TEL_NUMBER_SPEC); /* ISDN sub-address or extension must appear first. */ /* Extension param. */ copy_advance_pair_escape(buf, ";ext=", 5, uri->ext_param, pjsip_TEL_EXT_VALUE_SPEC); /* ISDN sub-address. */ copy_advance_pair_escape(buf, ";isub=", 6, uri->isub_param, pjsip_TEL_URIC_SPEC); /* Followed by phone context, if present. */ copy_advance_pair_escape(buf, ";phone-context=", 15, uri->context, pjsip_TEL_PHONE_CONTEXT_SPEC); /* Print other parameters. */ printed = (int)pjsip_param_print_on(&uri->other_param, buf, (endbuf-buf), &pjsip_TEL_PNAME_SPEC, &pjsip_TEL_PVALUE_SPEC, ';'); if (printed < 0) return -1; buf += printed; *buf = '\0'; return (buf-startbuf); }
static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr, char *buf, pj_size_t size) { char *p = buf; char *endbuf = buf+size; pj_ssize_t printed; const pjsip_parser_const_t *pc = pjsip_parser_const(); copy_advance(p, hdr->name); *p++ = ':'; *p++ = ' '; copy_advance_escape(p, hdr->sub_state, pc->pjsip_TOKEN_SPEC); copy_advance_pair_escape(p, ";reason=", 8, hdr->reason_param, pc->pjsip_TOKEN_SPEC); if (hdr->expires_param >= 0) { pj_memcpy(p, ";expires=", 9); p += 9; printed = pj_utoa(hdr->expires_param, p); p += printed; } if (hdr->retry_after >= 0) { pj_memcpy(p, ";retry-after=", 13); p += 13; printed = pj_utoa(hdr->retry_after, p); p += printed; } printed = pjsip_param_print_on( &hdr->other_param, p, endbuf-p, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) return (int)printed; p += printed; return (int)(p - buf); }
static pj_ssize_t pjsip_url_print( pjsip_uri_context_e context, const pjsip_sip_uri *url, char *buf, pj_size_t size) { int printed; char *startbuf = buf; char *endbuf = buf+size; const pj_str_t *scheme; const pjsip_parser_const_t *pc = pjsip_parser_const(); *buf = '\0'; /* Print scheme ("sip:" or "sips:") */ scheme = pjsip_uri_get_scheme(url); copy_advance_check(buf, *scheme); *buf++ = ':'; /* Print "user:password@", if any. */ if (url->user.slen) { copy_advance_escape(buf, url->user, pc->pjsip_USER_SPEC); if (url->passwd.slen) { *buf++ = ':'; copy_advance_escape(buf, url->passwd, pc->pjsip_PASSWD_SPEC); } *buf++ = '@'; } /* Print host. */ pj_assert(url->host.slen != 0); /* Detect IPv6 IP address */ if (pj_memchr(url->host.ptr, ':', url->host.slen)) { copy_advance_pair_quote_cond(buf, "", 0, url->host, '[', ']'); } else { copy_advance_check(buf, url->host); } /* Only print port if it is explicitly specified. * Port is not allowed in To and From header, see Table 1 in * RFC 3261 Section 19.1.1 */ /* Note: ticket #1141 adds run-time setting to allow port number to * appear in From/To header. Default is still false. */ if (url->port && (context != PJSIP_URI_IN_FROMTO_HDR || pjsip_cfg()->endpt.allow_port_in_fromto_hdr)) { if (endbuf - buf < 10) return -1; *buf++ = ':'; printed = pj_utoa(url->port, buf); buf += printed; } /* User param is allowed in all contexes */ copy_advance_pair_check(buf, ";user="******";method=", 8, url->method_param, pc->pjsip_PARAM_CHAR_SPEC); } /* Transport is not allowed in From/To header. */ if (context != PJSIP_URI_IN_FROMTO_HDR) { copy_advance_pair_escape(buf, ";transport=", 11, url->transport_param, pc->pjsip_PARAM_CHAR_SPEC); } /* TTL param is not allowed in From, To, Route, and Record-Route header. */ if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR && context != PJSIP_URI_IN_ROUTING_HDR) { if (endbuf - buf < 15) return -1; pj_memcpy(buf, ";ttl=", 5); printed = pj_utoa(url->ttl_param, buf+5); buf += printed + 5; } /* maddr param is not allowed in From and To header. */ if (context != PJSIP_URI_IN_FROMTO_HDR && url->maddr_param.slen) { /* Detect IPv6 IP address */ if (pj_memchr(url->maddr_param.ptr, ':', url->maddr_param.slen)) { copy_advance_pair_quote_cond(buf, ";maddr=", 7, url->maddr_param, '[', ']'); } else { copy_advance_pair_escape(buf, ";maddr=", 7, url->maddr_param, pc->pjsip_PARAM_CHAR_SPEC); } } /* lr param is not allowed in From, To, and Contact header. */ if (url->lr_param && context != PJSIP_URI_IN_FROMTO_HDR && context != PJSIP_URI_IN_CONTACT_HDR) { pj_str_t lr = { ";lr", 3 }; if (endbuf - buf < 3) return -1; copy_advance_check(buf, lr); } /* Other param. */ printed = pjsip_param_print_on(&url->other_param, buf, endbuf-buf, &pc->pjsip_PARAM_CHAR_SPEC, &pc->pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return -1; buf += printed; /* Header param. * Header param is only allowed in these contexts: * - PJSIP_URI_IN_CONTACT_HDR * - PJSIP_URI_IN_OTHER */ if (context == PJSIP_URI_IN_CONTACT_HDR || context == PJSIP_URI_IN_OTHER) { printed = pjsip_param_print_on(&url->header_param, buf, endbuf-buf, &pc->pjsip_HDR_CHAR_SPEC, &pc->pjsip_HDR_CHAR_SPEC, '?'); if (printed < 0) return -1; buf += printed; } *buf = '\0'; return buf-startbuf; }
static pj_ssize_t pjsip_url_print( pjsip_uri_context_e context, const pjsip_sip_uri *url, char *buf, pj_size_t size) { int printed; char *startbuf = buf; char *endbuf = buf+size; const pj_str_t *scheme; *buf = '\0'; /* Print scheme ("sip:" or "sips:") */ scheme = pjsip_uri_get_scheme(url); copy_advance_check(buf, *scheme); *buf++ = ':'; /* Print "user:password@", if any. */ if (url->user.slen) { copy_advance_escape(buf, url->user, pjsip_USER_SPEC); if (url->passwd.slen) { *buf++ = ':'; copy_advance_escape(buf, url->passwd, pjsip_PASSWD_SPEC); } *buf++ = '@'; } /* Print host. */ pj_assert(url->host.slen != 0); copy_advance_check(buf, url->host); /* Only print port if it is explicitly specified. * Port is not allowed in To and From header. */ /* Unfortunately some UA requires us to send back the port * number exactly as it was sent. We don't remember whether an * UA has sent us port, so we'll just send the port indiscrimately */ //PJ_TODO(SHOULD_DISALLOW_URI_PORT_IN_FROM_TO_HEADER) if (url->port && context != PJSIP_URI_IN_FROMTO_HDR) { if (endbuf - buf < 10) return -1; *buf++ = ':'; printed = pj_utoa(url->port, buf); buf += printed; } /* User param is allowed in all contexes */ copy_advance_pair_check(buf, ";user="******";method=", 8, url->method_param, pjsip_PARAM_CHAR_SPEC); } /* Transport is not allowed in From/To header. */ if (context != PJSIP_URI_IN_FROMTO_HDR) { copy_advance_pair_escape(buf, ";transport=", 11, url->transport_param, pjsip_PARAM_CHAR_SPEC); } /* TTL param is not allowed in From, To, Route, and Record-Route header. */ if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR && context != PJSIP_URI_IN_ROUTING_HDR) { if (endbuf - buf < 15) return -1; pj_memcpy(buf, ";ttl=", 5); printed = pj_utoa(url->ttl_param, buf+5); buf += printed + 5; } /* maddr param is not allowed in From and To header. */ if (context != PJSIP_URI_IN_FROMTO_HDR) { copy_advance_pair_escape(buf, ";maddr=", 7, url->maddr_param, pjsip_PARAM_CHAR_SPEC); } /* lr param is not allowed in From, To, and Contact header. */ if (url->lr_param && context != PJSIP_URI_IN_FROMTO_HDR && context != PJSIP_URI_IN_CONTACT_HDR) { pj_str_t lr = { ";lr", 3 }; if (endbuf - buf < 3) return -1; copy_advance_check(buf, lr); } /* Other param. */ printed = pjsip_param_print_on(&url->other_param, buf, endbuf-buf, &pjsip_PARAM_CHAR_SPEC, &pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return -1; buf += printed; /* Header param. * Header param is only allowed in these contexts: * - PJSIP_URI_IN_CONTACT_HDR * - PJSIP_URI_IN_OTHER */ if (context == PJSIP_URI_IN_CONTACT_HDR || context == PJSIP_URI_IN_OTHER) { printed = pjsip_param_print_on(&url->header_param, buf, endbuf-buf, &pjsip_HDR_CHAR_SPEC, &pjsip_HDR_CHAR_SPEC, '?'); if (printed < 0) return -1; buf += printed; } *buf = '\0'; return buf-startbuf; }