int pjsip_reject_contact_hdr_print_on(void* void_hdr, char* buf, pj_size_t size) { int printed; char *startbuf = buf; char *endbuf = buf + size; pjsip_reject_contact_hdr* hdr = (pjsip_reject_contact_hdr *)void_hdr; const pjsip_parser_const_t *pc = pjsip_parser_const(); /* Route and Record-Route don't compact forms */ copy_advance(buf, hdr->name); *buf++ = ':'; *buf++ = ' '; *buf++ = '*'; printed = pjsip_param_print_on(&hdr->feature_set, buf, endbuf-buf, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { return -1; } buf += printed; return buf-startbuf; }
static int print_digest_challenge( pjsip_digest_challenge *chal, char *buf, pj_size_t size) { pj_ssize_t printed; char *startbuf = buf; char *endbuf = buf + size; const pjsip_parser_const_t *pc = pjsip_parser_const(); /* Allow empty realm, see http://trac.pjsip.org/repos/ticket/1061 */ copy_advance_pair_quote(buf, " realm=", 7, chal->realm, '"', '"'); copy_advance_pair_quote_cond(buf, ",domain=", 8, chal->domain, '"', '"'); copy_advance_pair_quote_cond(buf, ",nonce=", 7, chal->nonce, '"', '"'); copy_advance_pair_quote_cond(buf, ",opaque=", 8, chal->opaque, '"', '"'); if (chal->stale) { pj_str_t true_str = { "true", 4 }; copy_advance_pair(buf, ",stale=", 7, true_str); } copy_advance_pair(buf, ",algorithm=", 11, chal->algorithm); copy_advance_pair_quote_cond(buf, ",qop=", 5, chal->qop, '"', '"'); printed = pjsip_param_print_on(&chal->other_param, buf, endbuf-buf, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ','); if (printed < 0) return -1; buf += printed; return (int)(buf-startbuf); }
static int print_digest_credential(pjsip_digest_credential *cred, char *buf, pj_size_t size) { pj_ssize_t printed; char *startbuf = buf; char *endbuf = buf + size; const pjsip_parser_const_t *pc = pjsip_parser_const(); copy_advance_pair_quote_cond(buf, "username="******"', '"'); copy_advance_pair_quote_cond_always(buf, ", realm=", 8, cred->realm, '"', '"'); copy_advance_pair_quote(buf, ", nonce=", 8, cred->nonce, '"', '"'); copy_advance_pair_quote_cond(buf, ", uri=", 6, cred->uri, '"', '"'); copy_advance_pair_quote(buf, ", response=", 11, cred->response, '"', '"'); copy_advance_pair(buf, ", algorithm=", 12, cred->algorithm); copy_advance_pair_quote_cond(buf, ", cnonce=", 9, cred->cnonce, '"', '"'); copy_advance_pair_quote_cond(buf, ", opaque=", 9, cred->opaque, '"', '"'); //Note: there's no dbl-quote in qop in Authorization header // (unlike WWW-Authenticate) //copy_advance_pair_quote_cond(buf, ", qop=", 6, cred->qop, '"', '"'); copy_advance_pair(buf, ", qop=", 6, cred->qop); copy_advance_pair(buf, ", nc=", 5, cred->nc); printed = pjsip_param_print_on(&cred->other_param, buf, endbuf-buf, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ','); if (printed < 0) return -1; buf += printed; return (int) (buf-startbuf); }
/* * Parse Session-Expires header. */ static pjsip_hdr *parse_hdr_se(pjsip_parse_ctx *ctx) { pjsip_sess_expires_hdr *hdr = pjsip_sess_expires_hdr_create(ctx->pool); const pjsip_parser_const_t *pc = pjsip_parser_const(); pj_str_t token; pj_scan_get(ctx->scanner, &pc->pjsip_DIGIT_SPEC, &token); hdr->sess_expires = pj_strtoul(&token); while (*ctx->scanner->curptr == ';') { pj_str_t pname, pvalue; pj_scan_get_char(ctx->scanner); pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0); if (pj_stricmp(&pname, &STR_REFRESHER)==0) { hdr->refresher = pvalue; } else { pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); param->name = pname; param->value = pvalue; pj_list_push_back(&hdr->other_param, param); } } pjsip_parse_end_hdr_imp( ctx->scanner ); return (pjsip_hdr*)hdr; }
int pjsip_accept_contact_hdr_print_on(void* void_hdr, char* buf, pj_size_t size) { int printed; char *startbuf = buf; char *endbuf = buf + size; pjsip_accept_contact_hdr* hdr = (pjsip_accept_contact_hdr *)void_hdr; const pjsip_parser_const_t *pc = pjsip_parser_const(); /* Route and Record-Route don't compact forms */ copy_advance(buf, hdr->name); copy_advance(buf, pj_str(": *")); printed = pjsip_param_print_on(&hdr->feature_set, buf, endbuf-buf, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { return -1; } buf += printed; if (hdr->explicit_match) { copy_advance(buf, pj_str(";explicit")); } if (hdr->required_match) { copy_advance(buf, pj_str(";require")); } return buf-startbuf; }
int identity_hdr_print(pjsip_routing_hdr* hdr, char* buf, pj_size_t size) { int printed; char *startbuf = buf; char *endbuf = buf + size; const pjsip_parser_const_t *pc = pjsip_parser_const(); /* Route and Record-Route don't compact forms */ copy_advance(buf, hdr->name); *buf++ = ':'; *buf++ = ' '; printed = pjsip_uri_print(PJSIP_URI_IN_ROUTING_HDR, &hdr->name_addr, buf, endbuf-buf); if (printed < 1) { return -1; // LCOV_EXCL_LINE } buf += printed; printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { return -1; // LCOV_EXCL_LINE } buf += printed; return buf-startbuf; }
/* * Min-SE header vptr. */ static int min_se_hdr_print(pjsip_min_se_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(); /* Print header name and value */ if ((endbuf - p) < (hdr->name.slen + 16)) return -1; copy_advance(p, hdr->name); *p++ = ':'; *p++ = ' '; printed = pj_utoa(hdr->min_se, p); p += printed; /* Print generic params */ 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 int replaces_hdr_print( pjsip_replaces_hdr *hdr, char *buf, pj_size_t size) { char *p = buf; char *endbuf = buf+size; int printed; const pjsip_parser_const_t *pc = pjsip_parser_const(); copy_advance(p, hdr->name); *p++ = ':'; *p++ = ' '; copy_advance(p, hdr->call_id); copy_advance_pair(p, ";to-tag=", 8, hdr->to_tag); copy_advance_pair(p, ";from-tag=", 10, hdr->from_tag); if (hdr->early_only) { const pj_str_t str_early_only = { ";early-only", 11 }; copy_advance(p, str_early_only); } printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) return printed; p += printed; return p - buf; }
static void int_parse_hdr_authenticate( pj_scanner *scanner, pj_pool_t *pool, pjsip_www_authenticate_hdr *hdr) { const pjsip_parser_const_t *pc = pjsip_parser_const(); if (*scanner->curptr == '"') { pj_scan_get_quote(scanner, '"', '"', &hdr->scheme); hdr->scheme.ptr++; hdr->scheme.slen -= 2; } else { pj_scan_get(scanner, &pc->pjsip_TOKEN_SPEC, &hdr->scheme); } if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) { parse_digest_challenge(scanner, pool, &hdr->challenge.digest); } else if (!pj_stricmp(&hdr->scheme, &pjsip_PGP_STR)) { parse_pgp_challenge(scanner, pool, &hdr->challenge.pgp); } else { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } pjsip_parse_end_hdr_imp( scanner ); }
/* * Parse Event header. */ static pjsip_hdr *parse_hdr_event(pjsip_parse_ctx *ctx) { pjsip_event_hdr *hdr = pjsip_event_hdr_create(ctx->pool); const pj_str_t id_param = { "id", 2 }; const pjsip_parser_const_t *pc = pjsip_parser_const(); pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->event_type); while (*ctx->scanner->curptr == ';') { pj_str_t pname, pvalue; pj_scan_get_char(ctx->scanner); pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0); if (pj_stricmp(&pname, &id_param)==0) { hdr->id_param = pvalue; } else { pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); param->name = pname; param->value = pvalue; pj_list_push_back(&hdr->other_param, param); } } pjsip_parse_end_hdr_imp( ctx->scanner ); return (pjsip_hdr*)hdr; }
int pjsip_session_expires_hdr_print_on(void* h, char* buf, pj_size_t len) { char* p = buf; const pjsip_session_expires_hdr* hdr = (pjsip_session_expires_hdr*)h; const pjsip_parser_const_t *pc = pjsip_parser_const(); // As per pjsip_generic_int_hdr_print, integers are fewer then 15 characters long. if ((pj_ssize_t)len < hdr->name.slen + 15) { return -1; } pj_memcpy(p, hdr->name.ptr, hdr->name.slen); p += hdr->name.slen; *p++ = ':'; *p++ = ' '; p += pj_utoa(hdr->expires, p); if (hdr->refresher != SESSION_REFRESHER_UNKNOWN) { // Check the refresher parameter will fit. if (buf+len-p < 14) { return -1; } // Fill it in *p++ = ';'; pj_memcpy(p, "refresher=", 10); p += 10; if (hdr->refresher == SESSION_REFRESHER_UAC) { pj_memcpy(p, "uac", 3); } else { pj_memcpy(p, "uas", 3); } p += 3; } // Try to add the other params. pj_ssize_t printed = pjsip_param_print_on(&hdr->other_param, p, buf+len-p, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { return -1; } p += printed; *p = '\0'; return p - buf; }
pjsip_hdr* parse_hdr_session_expires(pjsip_parse_ctx* ctx) { pj_pool_t* pool = ctx->pool; pj_scanner* scanner = ctx->scanner; pjsip_session_expires_hdr* hdr = pjsip_session_expires_hdr_create(pool); const pjsip_parser_const_t* pc = pjsip_parser_const(); // Parse the expiry number pj_str_t int_str; pj_scan_get(scanner, &pc->pjsip_DIGIT_SPEC, &int_str); hdr->expires = pj_strtoul(&int_str); pj_scan_skip_whitespace(scanner); // Parse the rest of the params, looking for the refresher param while (*scanner->curptr == ';') { // Consume the ';'. pj_scan_get_char(scanner); pj_scan_skip_whitespace(scanner); // Parse the param. pj_str_t name; pj_str_t value; pjsip_parse_param_imp(scanner, pool, &name, &value, PJSIP_PARSE_REMOVE_QUOTE); if (!pj_stricmp2(&name, "refresher")) { if (!pj_stricmp2(&value, "uac")) { hdr->refresher = SESSION_REFRESHER_UAC; } else if (!pj_stricmp2(&value, "uas")) { hdr->refresher = SESSION_REFRESHER_UAS; } else { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); // LCOV_EXCL_LINE } } else { pjsip_param* param = PJ_POOL_ALLOC_T(pool, pjsip_param); param->name = name; param->value = value; pj_list_insert_before(&hdr->other_param, param); } } // We're done parsing this header. pjsip_parse_end_hdr_imp(scanner); return (pjsip_hdr*)hdr; }
pjsip_hdr* parse_hdr_reject_contact(pjsip_parse_ctx* ctx) { // The Reject-Contact header has the following ABNF: // // Reject-Contact = ("Reject-Contact" / "j") HCOLON rc-value // *(COMMA rc-value) // rc-value = "*" *(SEMI rc-params) // rc-params = feature-param / generic-param // // But we allow any value for the header (not just *). pj_pool_t* pool = ctx->pool; pj_scanner* scanner = ctx->scanner; const pjsip_parser_const_t* pc = pjsip_parser_const(); pjsip_reject_contact_hdr* hdr = pjsip_reject_contact_hdr_create(pool); pj_str_t name; pj_str_t value; pjsip_param *param; // Read and ignore the value. pj_str_t header_value; pj_scan_get(scanner, &pc->pjsip_TOKEN_SPEC, &header_value); for (;;) { // We might need to swallow the ';'. if (!pj_scan_is_eof(scanner) && *scanner->curptr == ';') { pj_scan_get_char(scanner); } pjsip_parse_param_imp(scanner, pool, &name, &value, 0); param = PJ_POOL_ALLOC_T(pool, pjsip_param); param->name = name; param->value = value; pj_list_insert_before(&hdr->feature_set, param); // If we're EOF or looking at a newline, we're done. pj_scan_skip_whitespace(scanner); if (pj_scan_is_eof(scanner) || (*scanner->curptr == '\r') || (*scanner->curptr == '\n')) { break; } } // We're done parsing this header. pjsip_parse_end_hdr_imp(scanner); return (pjsip_hdr*)hdr; }
/* 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); }
/* * Session-Expires header vptr. */ static int se_hdr_print(pjsip_sess_expires_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(); const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name; /* Print header name and value */ if ((endbuf - p) < (hname->slen + 16)) return -1; copy_advance(p, (*hname)); *p++ = ':'; *p++ = ' '; printed = pj_utoa(hdr->sess_expires, p); p += printed; /* Print 'refresher' param */ if (hdr->refresher.slen) { if ((endbuf - p) < (STR_REFRESHER.slen + 2 + hdr->refresher.slen)) return -1; *p++ = ';'; copy_advance(p, STR_REFRESHER); *p++ = '='; copy_advance(p, hdr->refresher); } /* Print generic params */ 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 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); }
/* * Parse Min-SE header. */ static pjsip_hdr *parse_hdr_min_se(pjsip_parse_ctx *ctx) { pjsip_min_se_hdr *hdr = pjsip_min_se_hdr_create(ctx->pool); const pjsip_parser_const_t *pc = pjsip_parser_const(); pj_str_t token; pj_scan_get(ctx->scanner, &pc->pjsip_DIGIT_SPEC, &token); hdr->min_se = pj_strtoul(&token); while (*ctx->scanner->curptr == ';') { pj_str_t pname, pvalue; pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); pj_scan_get_char(ctx->scanner); pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0); param->name = pname; param->value = pvalue; pj_list_push_back(&hdr->other_param, param); } pjsip_parse_end_hdr_imp( ctx->scanner ); return (pjsip_hdr*)hdr; }
static int pjsip_event_hdr_print( pjsip_event_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(p, hdr->event_type); copy_advance_pair(p, ";id=", 4, hdr->id_param); 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); }
/* * Parse Subscription-State header. */ static pjsip_hdr* parse_hdr_sub_state( pjsip_parse_ctx *ctx ) { pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(ctx->pool); const pj_str_t reason = { "reason", 6 }, expires = { "expires", 7 }, retry_after = { "retry-after", 11 }; const pjsip_parser_const_t *pc = pjsip_parser_const(); pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->sub_state); while (*ctx->scanner->curptr == ';') { pj_str_t pname, pvalue; pj_scan_get_char(ctx->scanner); pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0); if (pj_stricmp(&pname, &reason) == 0) { hdr->reason_param = pvalue; } else if (pj_stricmp(&pname, &expires) == 0) { hdr->expires_param = pj_strtoul(&pvalue); } else if (pj_stricmp(&pname, &retry_after) == 0) { hdr->retry_after = pj_strtoul(&pvalue); } else { pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); param->name = pname; param->value = pvalue; pj_list_push_back(&hdr->other_param, param); } } pjsip_parse_end_hdr_imp( ctx->scanner ); return (pjsip_hdr*)hdr; }
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. */ /* 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, 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 const pj_str_t *tel_uri_get_scheme( const pjsip_tel_uri *uri ) { PJ_UNUSED_ARG(uri); return &pjsip_parser_const()->pjsip_TEL_STR; }
int pjsip_p_c_f_a_hdr_print_on(void *h, char* buf, pj_size_t len) { const pjsip_parser_const_t *pc = pjsip_parser_const(); pjsip_p_c_f_a_hdr* hdr = (pjsip_p_c_f_a_hdr*)h; char* p = buf; // Check that at least the header name will fit. int needed = 0; needed += hdr->name.slen; // Header name needed += 2; // : and space if (needed > (pj_ssize_t)len) { return -1; } // Now write the header name out. pj_memcpy(p, hdr->name.ptr, hdr->name.slen); p += hdr->name.slen; *p++ = ':'; *p++ = ' '; // Now try to write out the three parameter lists. Annoyingly, // pjsip_param_print_on() will always print the separator before each // parameter, including the first parameter in this case. // // The P-Charging-Function-Addresses header has no body (technically // invalid SIP) and thus we need to print the first parameter without the // separator. Since this first parameter could be in any of the parameter // lists, we have to track (with the found_first_param flag) when we've // handled it. bool found_first_param = false; int printed; pjsip_param* param_list = NULL; for (int i = 0; i < 3; i++) { switch (i) { case 0: param_list = &hdr->ccf; break; case 1: param_list = &hdr->ecf; break; case 2: param_list = &hdr->other_param; break; } if (pj_list_empty(param_list)) { continue; // LCOV_EXCL_LINE } if (found_first_param) { // Simply write out the parameters printed = pjsip_param_print_on(param_list, p, buf+len-p, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { return -1; } p += printed; } else { // We print the first parameter manually then print the rest. pjsip_param* first_param = param_list->next; pj_list_erase(first_param); // Check we have space for the first param before printing it out. needed = pj_strlen(&first_param->name); if (first_param->value.slen) { needed += 1 + pj_strlen(&first_param->value); } if (needed > buf+len-p) { pj_list_insert_after(param_list, first_param); return -1; } pj_memcpy(p, first_param->name.ptr, first_param->name.slen); p += first_param->name.slen; if (first_param->value.slen) { *p++ = '='; pj_memcpy(p, first_param->value.ptr, first_param->value.slen); p += first_param->value.slen; } // Now print the rest of this parameter list (may be empty). printed = pjsip_param_print_on(param_list, p, buf+len-p, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { pj_list_insert_after(param_list, first_param); return -1; } p += printed; // Finally, restore the first param to the head of the parameter list. pj_list_insert_after(param_list, first_param); // We've found the first parameter, everything else is simple. found_first_param = true; } } *p = '\0'; return p - buf; }
int pjsip_p_c_v_hdr_print_on(void* h, char* buf, pj_size_t len) { const pjsip_parser_const_t *pc = pjsip_parser_const(); pjsip_p_c_v_hdr* hdr = (pjsip_p_c_v_hdr*)h; char* p = buf; // Check the fixed parts of the header will fit. int needed = 0; needed += hdr->name.slen; // Header name needed += 2; // : and space needed += 11; // icid-value= needed += 2; // Quote the icid-value needed += hdr->icid.slen; // <icid> needed += 1; // ; if (hdr->orig_ioi.slen) { needed += 9; // orig-ioi= needed += hdr->orig_ioi.slen; // <orig-ioi> needed += 1; // ; } if (hdr->term_ioi.slen) { needed += 9; // term-ioi= needed += hdr->term_ioi.slen; // <term-ioi> needed += 1; // ; } if (hdr->icid_gen_addr.slen) { needed += 18; // icid-generated-at= needed += hdr->icid_gen_addr.slen; // <icid-generated-at> } if (needed > (pj_ssize_t)len) { return -1; } // Now write the fixed header out. pj_memcpy(p, hdr->name.ptr, hdr->name.slen); p += hdr->name.slen; *p++ = ':'; *p++ = ' '; pj_memcpy(p, "icid-value=", 11); p += 11; *p++ = '"'; pj_memcpy(p, hdr->icid.ptr, hdr->icid.slen); p += hdr->icid.slen; *p++ = '"'; if (hdr->orig_ioi.slen) { *p++ = ';'; pj_memcpy(p, "orig-ioi=", 9); p += 9; pj_memcpy(p, hdr->orig_ioi.ptr, hdr->orig_ioi.slen); p += hdr->orig_ioi.slen; } if (hdr->term_ioi.slen) { *p++ = ';'; pj_memcpy(p, "term-ioi=", 9); p += 9; pj_memcpy(p, hdr->term_ioi.ptr, hdr->term_ioi.slen); p += hdr->term_ioi.slen; } if (hdr->icid_gen_addr.slen) { *p++ = ';'; pj_memcpy(p, "icid-generated-at=", 18); p += 18; pj_memcpy(p, hdr->icid_gen_addr.ptr, hdr->icid_gen_addr.slen); p += hdr->icid_gen_addr.slen; } // Attempt to write out the other params. pj_ssize_t printed = pjsip_param_print_on(&hdr->other_param, p, buf+len-p, &pc->pjsip_TOKEN_SPEC, &pc->pjsip_TOKEN_SPEC, ';'); if (printed < 0) { return -1; } p += printed; *p = '\0'; return p - buf; }
/* Parse tel: URI * THis actually returns (pjsip_tel_uri *) type. */ static void* tel_uri_parse( pj_scanner *scanner, pj_pool_t *pool, pj_bool_t parse_params) { pjsip_tel_uri *uri; pj_str_t token; int skip_ws = scanner->skip_ws; const pjsip_parser_const_t *pc = pjsip_parser_const(); scanner->skip_ws = 0; /* Parse scheme. */ pj_scan_get(scanner, &pc->pjsip_TOKEN_SPEC, &token); if (pj_scan_get_char(scanner) != ':') PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); if (pj_stricmp_alnum(&token, &pc->pjsip_TEL_STR) != 0) PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); /* Create URI */ uri = pjsip_tel_uri_create(pool); /* Get the phone number. */ #if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0 pj_scan_get_unescape(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number); #else pj_scan_get(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number); uri->number = pj_str_unescape(pool, &uri->number); #endif /* Get all parameters. */ if (parse_params && *scanner->curptr==';') { pj_str_t pname, pvalue; const pjsip_parser_const_t *pc = pjsip_parser_const(); do { /* Eat the ';' separator. */ pj_scan_get_char(scanner); /* Get pname. */ pj_scan_get(scanner, &pc->pjsip_PARAM_CHAR_SPEC, &pname); if (*scanner->curptr == '=') { pj_scan_get_char(scanner); # if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0 pj_scan_get_unescape(scanner, &pjsip_TEL_PARSING_PVALUE_SPEC_ESC, &pvalue); # else pj_scan_get(scanner, &pjsip_TEL_PARSING_PVALUE_SPEC, &pvalue); pvalue = pj_str_unescape(pool, &pvalue); # endif } else { pvalue.slen = 0; pvalue.ptr = NULL; } /* Save the parameters. */ if (pj_stricmp_alnum(&pname, &pjsip_ISUB_STR)==0) { uri->isub_param = pvalue; } else if (pj_stricmp_alnum(&pname, &pjsip_EXT_STR)==0) { uri->ext_param = pvalue; } else if (pj_stricmp_alnum(&pname, &pjsip_PH_CTX_STR)==0) { uri->context = pvalue; } else { pjsip_param *param = PJ_POOL_ALLOC_T(pool, pjsip_param); param->name = pname; param->value = pvalue; pj_list_insert_before(&uri->other_param, param); } } while (*scanner->curptr==';'); } scanner->skip_ws = skip_ws; pj_scan_skip_whitespace(scanner); return uri; }
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; }