int msrp_parse_hdr_to_path(msrp_frame_t *mf) { msrp_hdr_t *hdr; hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return -1; if(hdr->parsed.flags&MSRP_DATA_SET) return 0; return msrp_parse_hdr_uri_list(hdr); }
int msrp_frame_get_expires(msrp_frame_t *mf, int *expires) { msrp_hdr_t *hdr; if(msrp_parse_hdr_expires(mf)<0) return -1; hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_AUTH); if(hdr==NULL) return -1; *expires = (int)(long)hdr->parsed.data; return 0; }
int msrp_frame_get_first_from_path(msrp_frame_t *mf, str *sres) { str s = {0}; msrp_hdr_t *hdr; str_array_t *sar; if(msrp_parse_hdr_from_path(mf)<0) return -1; hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH); if(hdr==NULL) return -1; sar = (str_array_t*)hdr->parsed.data; s = sar->list[sar->size-1]; trim(&s); *sres = s; return 0; }
int msrp_frame_get_sessionid(msrp_frame_t *mf, str *sres) { str s = {0}; msrp_hdr_t *hdr; str_array_t *sar; msrp_uri_t uri; if(msrp_parse_hdr_to_path(mf)<0) return -1; hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return -1; sar = (str_array_t*)hdr->parsed.data; s = sar->list[0]; trim(&s); if(msrp_parse_uri(s.s, s.len, &uri)<0 || uri.session.len<=0) return -1; s = uri.session; trim(&s); *sres = s; return 0; }
int msrp_parse_hdr_expires(msrp_frame_t *mf) { msrp_hdr_t *hdr; str hbody; int expires; hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_EXPIRES); if(hdr==NULL) return -1; if(hdr->parsed.flags&MSRP_DATA_SET) return 0; hbody = hdr->body; trim(&hbody); if(str2sint(&hbody, &expires)<0) { LM_ERR("invalid expires value\n"); return -1; } hdr->parsed.flags |= MSRP_DATA_SET; hdr->parsed.free_fn = NULL; hdr->parsed.data = (void*)(long)expires; return 0; }
int pv_get_msrp(sip_msg_t *msg, pv_param_t *param, pv_value_t *res) { msrp_frame_t *mf; msrp_hdr_t *hdr; str_array_t *sar; msrp_uri_t uri; str s; char *p; mf = msrp_get_current_frame(); if(mf==NULL || param==NULL) return -1; sar = NULL; hdr = NULL; switch(param->pvn.u.isname.name.n) { case 1: s.s = mf->buf.s; s.len = mf->buf.len; return pv_get_strval(msg, param, res, &s); case 2: if(mf->mbody.s==NULL) return pv_get_null(msg, param, res); s.s = mf->mbody.s; s.len = mf->mbody.len; return pv_get_strval(msg, param, res, &s); case 3: if(mf->fline.msgtypeid==MSRP_REQUEST) return pv_get_null(msg, param, res); return pv_get_intstrval(msg, param, res, MSRP_RPL_CODE(mf->fline.rtypeid), &mf->fline.rtype); case 4: if(mf->hbody.s==NULL) return pv_get_null(msg, param, res); s.s = mf->hbody.s; s.len = mf->hbody.len; return pv_get_strval(msg, param, res, &s); case 5: hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_MESSAGE_ID); if(hdr==NULL) return pv_get_null(msg, param, res); s.s = hdr->body.s; s.len = hdr->body.len; trim(&s); return pv_get_strval(msg, param, res, &s); case 6: if(mf->fline.msgtypeid==MSRP_REPLY) return pv_get_null(msg, param, res); return pv_get_strintval(msg, param, res, &mf->fline.rtype, mf->fline.rtypeid); case 7: return pv_get_uintval(msg, param, res, mf->buf.len); case 8: if(msrp_parse_hdr_to_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; s = sar->list[0]; trim(&s); if(msrp_parse_uri(s.s, s.len, &uri)<0 || uri.session.len<=0) return pv_get_null(msg, param, res); s = uri.session; trim(&s); return pv_get_strval(msg, param, res, &s); case 9: if(mf->fline.msgtypeid==MSRP_REQUEST || mf->fline.rtext.s==NULL) return pv_get_null(msg, param, res); return pv_get_strval(msg, param, res, &mf->fline.rtext); case 10: return pv_get_uintval(msg, param, res, mf->mbody.len); case 11: s = mf->fline.transaction; trim(&s); return pv_get_strval(msg, param, res, &s); case 12: if(msrp_parse_hdr_to_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; s = sar->list[0]; trim(&s); return pv_get_strval(msg, param, res, &s); case 13: if(msrp_parse_hdr_from_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; s = sar->list[0]; trim(&s); return pv_get_strval(msg, param, res, &s); case 14: if(msrp_parse_hdr_to_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; if(sar->size<2) return pv_get_null(msg, param, res); s = sar->list[1]; trim(&s); return pv_get_strval(msg, param, res, &s); case 15: if(msrp_parse_hdr_to_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; s = sar->list[sar->size-1]; trim(&s); return pv_get_strval(msg, param, res, &s); case 16: if(msrp_parse_hdr_from_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; s = sar->list[sar->size-1]; trim(&s); return pv_get_strval(msg, param, res, &s); case 17: if(msrp_parse_hdr_from_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; return pv_get_uintval(msg, param, res, sar->size); case 18: if(msrp_parse_hdr_to_path(mf)<0) return pv_get_null(msg, param, res); hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) return pv_get_null(msg, param, res); sar = (str_array_t*)hdr->parsed.data; return pv_get_uintval(msg, param, res, sar->size-1); case 19: if(pv_get_buffer_size()<100) return pv_get_null(msg, param, res); s.s = pv_get_buffer(); p = s.s; if(mf->tcpinfo->rcv->proto==PROTO_TLS) { memcpy(p, "msrps://", 8); p+=8; } else { memcpy(p, "msrp://", 7); p+=7; } strcpy(p, ip_addr2a(&mf->tcpinfo->rcv->src_ip)); strcat(p, ":"); strcat(p, int2str(mf->tcpinfo->rcv->src_port, NULL)); s.len = strlen(s.s); return pv_get_strval(msg, param, res, &s); case 20: return pv_get_strval(msg, param, res, &mf->tcpinfo->rcv->bind_address->sock_str); case 21: if(mf->tcpinfo->con==NULL) return pv_get_null(msg, param, res); return pv_get_sintval(msg, param, res, mf->tcpinfo->con->id); default: return pv_get_null(msg, param, res); } return 0; }
int msrp_relay(msrp_frame_t *mf) { struct dest_info *dst; struct tcp_connection *con = NULL; char reqbuf[MSRP_MAX_FRAME_SIZE]; msrp_hdr_t *tpath; msrp_hdr_t *fpath; msrp_env_t *env; str_array_t *sar; char *p; char *l; int port; if(mf->buf.len>=MSRP_MAX_FRAME_SIZE-1) return -1; tpath = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(tpath==NULL) { LM_ERR("To-Path header not found\n"); return -1; } fpath = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH); if(fpath==NULL) { LM_ERR("From-Path header not found\n"); return -1; } l = q_memchr(tpath->body.s, ' ', tpath->body.len); if(l==NULL) { LM_DBG("To-Path has only one URI -- nowehere to forward\n"); return -1; } p = reqbuf; memcpy(p, mf->buf.s, tpath->body.s - mf->buf.s); p += tpath->body.s - mf->buf.s; memcpy(p, l + 1, fpath->body.s - l - 1); p += fpath->body.s - l - 1; memcpy(p, tpath->body.s, l + 1 - tpath->body.s); p += l + 1 - tpath->body.s; memcpy(p, fpath->name.s + 11, mf->buf.s + mf->buf.len - fpath->name.s - 11); p += mf->buf.s + mf->buf.len - fpath->name.s - 11; env = msrp_get_env(); if(env->envflags&MSRP_ENV_DSTINFO) { dst = &env->dstinfo; goto done; } if(msrp_parse_hdr_to_path(mf)<0) { LM_ERR("error parsing To-Path header\n"); return -1; } sar = (str_array_t*)tpath->parsed.data; if(sar==NULL || sar->size<2) { LM_DBG("To-Path has no next hop URI -- nowehere to forward\n"); return -1; } if(msrp_env_set_dstinfo(mf, &sar->list[1], NULL, 0)<0) { LM_ERR("unable to set destination address\n"); return -1; } dst = &env->dstinfo; done: if (dst->send_flags.f & SND_F_FORCE_CON_REUSE) { port = su_getport(&dst->to); if (likely(port)) { ticks_t con_lifetime; struct ip_addr ip; con_lifetime = cfg_get(tcp, tcp_cfg, con_lifetime); su2ip_addr(&ip, &dst->to); con = tcpconn_get(dst->id, &ip, port, NULL, con_lifetime); } else if (likely(dst->id)) { con = tcpconn_get(dst->id, 0, 0, 0, 0); } if (con == NULL) { LM_WARN("TCP/TLS connection not found\n"); return -1; } if (unlikely((con->rcv.proto == PROTO_WS || con->rcv.proto == PROTO_WSS) && sr_event_enabled(SREV_TCP_WS_FRAME_OUT))) { ws_event_info_t wsev; memset(&wsev, 0, sizeof(ws_event_info_t)); wsev.type = SREV_TCP_WS_FRAME_OUT; wsev.buf = reqbuf; wsev.len = p - reqbuf; wsev.id = con->id; return sr_event_exec(SREV_TCP_WS_FRAME_OUT, (void *) &wsev); } else if (tcp_send(dst, 0, reqbuf, p - reqbuf) < 0) { LM_ERR("forwarding frame failed\n"); return -1; } } else if (tcp_send(dst, 0, reqbuf, p - reqbuf) < 0) { LM_ERR("forwarding frame failed\n"); return -1; } return 0; }
int msrp_reply(msrp_frame_t *mf, str *code, str *text, str *xhdrs) { char rplbuf[MSRP_MAX_FRAME_SIZE]; msrp_hdr_t *hdr; msrp_env_t *env; char *p; char *l; /* no reply for a reply */ if(mf->fline.msgtypeid==MSRP_REPLY) return 0; if(mf->fline.msgtypeid==MSRP_REQ_REPORT) { /* it does not take replies */ return 0; } p = rplbuf; memcpy(p, mf->fline.protocol.s, mf->fline.protocol.len); p += mf->fline.protocol.len; *p = ' '; p++; memcpy(p, mf->fline.transaction.s, mf->fline.transaction.len); p += mf->fline.transaction.len; *p = ' '; p++; memcpy(p, code->s, code->len); p += code->len; *p = ' '; p++; memcpy(p, text->s, text->len); p += text->len; memcpy(p, "\r\n", 2); p += 2; memcpy(p, "To-Path: ", 9); p += 9; hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH); if(hdr==NULL) { LM_ERR("From-Path header not found\n"); return -1; } if(mf->fline.msgtypeid==MSRP_REQ_SEND) { l = q_memchr(hdr->body.s, ' ', hdr->body.len); if(l==NULL) { memcpy(p, hdr->body.s, hdr->body.len + 2); p += hdr->body.len + 2; } else { memcpy(p, hdr->body.s, l - hdr->body.s); p += l - hdr->body.s; memcpy(p, "\r\n", 2); p += 2; } } else { memcpy(p, hdr->body.s, hdr->body.len + 2); p += hdr->body.len + 2; } hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH); if(hdr==NULL) { LM_ERR("To-Path header not found\n"); return -1; } memcpy(p, "From-Path: ", 11); p += 11; l = q_memchr(hdr->body.s, ' ', hdr->body.len); if(l==NULL) { memcpy(p, hdr->body.s, hdr->body.len + 2); p += hdr->body.len + 2; } else { memcpy(p, hdr->body.s, l - hdr->body.s); p += l - hdr->body.s; memcpy(p, "\r\n", 2); p += 2; } hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_MESSAGE_ID); if(hdr!=NULL) { memcpy(p, hdr->buf.s, hdr->buf.len); p += hdr->buf.len; } if(xhdrs!=NULL && xhdrs->s!=NULL) { memcpy(p, xhdrs->s, xhdrs->len); p += xhdrs->len; } memcpy(p, mf->endline.s, mf->endline.len); p += mf->endline.len; *(p-3) = '$'; env = msrp_get_env(); if (unlikely((env->srcinfo.proto == PROTO_WS || env->srcinfo.proto == PROTO_WSS) && sr_event_enabled(SREV_TCP_WS_FRAME_OUT))) { struct tcp_connection *con = tcpconn_get(env->srcinfo.id, 0, 0, 0, 0); ws_event_info_t wsev; if (con == NULL) { LM_WARN("TCP/TLS connection for WebSocket could not be" "found\n"); return -1; } memset(&wsev, 0, sizeof(ws_event_info_t)); wsev.type = SREV_TCP_WS_FRAME_OUT; wsev.buf = rplbuf; wsev.len = p - rplbuf; wsev.id = con->id; return sr_event_exec(SREV_TCP_WS_FRAME_OUT, (void *) &wsev); } else if (tcp_send(&env->srcinfo, 0, rplbuf, p - rplbuf) < 0) { LM_ERR("sending reply failed\n"); return -1; } return 0; }