From 8edf6ff627456c8cfa5c496e44c477e9ba8852a6 Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Wed, 16 Mar 2022 11:58:08 +0000 Subject: [PATCH 1/3] b2b_entities: properly handle PRACK after dlg is matched Otherwise, simply relay the PRACK. --- modules/b2b_entities/dlg.c | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/b2b_entities/dlg.c b/modules/b2b_entities/dlg.c index 6b1e2f21d20..953b2876856 100644 --- a/modules/b2b_entities/dlg.c +++ b/modules/b2b_entities/dlg.c @@ -807,26 +807,6 @@ int b2b_prescript_f(struct sip_msg *msg, void *uparam) } } - if(method_value == METHOD_PRACK) - { - LM_DBG("Received a PRACK - send 200 reply\n"); - str reason={"OK", 2}; - /* send 200 OK and exit */ - tmb.t_newtran( msg ); - tm_tran = tmb.t_gett(); - // FIXME run here the transactional tracing, but we do not have - // the matching dlg, in order to grab the tracing function - tmb.t_reply(msg, 200, &reason); - if(tm_tran && tm_tran!=T_UNDEFINED) - tmb.unref_cell(tm_tran); - - /* No need to apply lumps */ - if(req_routeid > 0) - run_top_route(sroutes->request[req_routeid], msg); - - goto done; - } - search_dialog: if( msg->callid==NULL || msg->callid->body.s==NULL) { @@ -966,7 +946,7 @@ int b2b_prescript_f(struct sip_msg *msg, void *uparam) } else /* if also not a client request - not for us */ { - if(method_value != METHOD_UPDATE) + if(method_value != METHOD_UPDATE && method_value != METHOD_PRACK) { LM_DBG("Not a b2b request\n"); return SCB_RUN_ALL; @@ -981,7 +961,7 @@ int b2b_prescript_f(struct sip_msg *msg, void *uparam) if(dlg == NULL) { lock_release(&server_htable[hash_index].lock); - LM_DBG("No dialog found for cancel\n"); + LM_DBG("No dialog found for UPDATE/PRACK\n"); return SCB_RUN_ALL; } } @@ -1016,6 +996,26 @@ int b2b_prescript_f(struct sip_msg *msg, void *uparam) return SCB_RUN_ALL; } } + if (method_value == METHOD_PRACK) + { + lock_release(&table[hash_index].lock); + LM_DBG("Received a PRACK - send 200 reply\n"); + str reason={"OK", 2}; + /* send 200 OK and exit */ + tmb.t_newtran( msg ); + tm_tran = tmb.t_gett(); + if (dlg) + b2b_run_tracer(dlg, msg, tm_tran); + tmb.t_reply(msg, 200, &reason); + if(tm_tran && tm_tran!=T_UNDEFINED) + tmb.unref_cell(tm_tran); + + /* No need to apply lumps */ + if(req_routeid > 0) + run_top_route(sroutes->request[req_routeid], msg); + + goto done; + } ctx = b2b_get_context(); if (!ctx) { From cbc016dbc943db2ebdce1e5a7d8cc21b1d203808 Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Wed, 16 Mar 2022 19:20:00 +0200 Subject: [PATCH 2/3] b2b_entities: allocate mem for b2bl parameter --- modules/b2b_entities/b2b_entities.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/b2b_entities/b2b_entities.c b/modules/b2b_entities/b2b_entities.c index 7881789d2d3..e42cd308667 100644 --- a/modules/b2b_entities/b2b_entities.c +++ b/modules/b2b_entities/b2b_entities.c @@ -555,8 +555,7 @@ int b2b_update_b2bl_param(enum b2b_entity_type type, str* key, lock_release(&table[hash_index].lock); return -1; } - memcpy(dlg->logic_key.s, logic_key->s, logic_key->len); - dlg->logic_key.len = logic_key->len; + shm_str_sync(&dlg->logic_key, logic_key); if (unlock) lock_release(&table[hash_index].lock); From 690790182effa980539604e7054f46023c246dc0 Mon Sep 17 00:00:00 2001 From: Bogdan-Andrei Iancu Date: Wed, 16 Mar 2022 19:35:39 +0200 Subject: [PATCH 3/3] [proto_msrp] added REPORT support (generating and fwd'ing) --- modules/proto_msrp/msrp_api.c | 1 + modules/proto_msrp/msrp_api.h | 4 + modules/proto_msrp/msrp_signaling.c | 275 +++++++++++++++++++++++----- modules/proto_msrp/msrp_signaling.h | 3 + 4 files changed, 237 insertions(+), 46 deletions(-) diff --git a/modules/proto_msrp/msrp_api.c b/modules/proto_msrp/msrp_api.c index f9c2670b4b3..9462c08bcb1 100644 --- a/modules/proto_msrp/msrp_api.c +++ b/modules/proto_msrp/msrp_api.c @@ -29,6 +29,7 @@ void load_msrp( struct msrp_binds *binds) binds->register_msrp_handler = register_msrp_handler; binds->send_reply = msrp_send_reply; binds->send_reply_on_cell = msrp_send_reply_on_cell; + binds->send_report = msrp_send_report; binds->forward_request = msrp_fwd_request; binds->forward_reply = msrp_fwd_reply; } diff --git a/modules/proto_msrp/msrp_api.h b/modules/proto_msrp/msrp_api.h index cf13b5d314d..799b165522b 100644 --- a/modules/proto_msrp/msrp_api.h +++ b/modules/proto_msrp/msrp_api.h @@ -40,6 +40,9 @@ typedef int (*send_reply_on_cell_f)( void *hdl, struct msrp_cell *cell, int code, str* reason, str *hdrs, int hdrs_no); +typedef int (*send_report_f)( void *hdl, str *status, + struct msrp_msg *req, struct msrp_cell *cell ); + typedef int (*fwd_request_f)( void *hdl, struct msrp_msg *req, str *hdrs, int hdrs_no); @@ -51,6 +54,7 @@ struct msrp_binds { register_msrp_handler_f register_msrp_handler; send_reply_f send_reply; send_reply_on_cell_f send_reply_on_cell; + send_report_f send_report; fwd_request_f forward_request; fwd_reply_f forward_reply; }; diff --git a/modules/proto_msrp/msrp_signaling.c b/modules/proto_msrp/msrp_signaling.c index 04a394fb81b..6b0a9d80baf 100644 --- a/modules/proto_msrp/msrp_signaling.c +++ b/modules/proto_msrp/msrp_signaling.c @@ -41,6 +41,18 @@ #define FROM_PATH_PREFIX "From-Path: " #define FROM_PATH_PREFIX_LEN (sizeof(FROM_PATH_PREFIX) - 1) +#define MESSAGE_ID_PREFIX "Message-ID: " +#define MESSAGE_ID_PREFIX_LEN (sizeof(MESSAGE_ID_PREFIX) - 1) + +#define BYTE_RANGE_PREFIX "Byte-Range: " +#define BYTE_RANGE_PREFIX_LEN (sizeof(BYTE_RANGE_PREFIX) - 1) + +#define STATUS_PREFIX "Status: " +#define STATUS_PREFIX_LEN (sizeof(STATUS_PREFIX) - 1) + +#define MSRP_REPORT_METHOD "REPORT" +#define MSRP_REPORT_METHOD_LEN (sizeof(MSRP_REPORT_METHOD) - 1) + /* convenience macro */ #define append_string(_d,_s,_len) \ do{\ @@ -84,6 +96,10 @@ int msrp_send_reply( void *hdl, struct msrp_msg *req, int code, str* reason, LM_ERR("invalid status reply %d, must be [100..999]\n",code); return -1; } + if (req->fl.u.request.method_id==MSRP_METHOD_REPORT) { + LM_ERR("cannot send reply for REPORT request\n"); + return -1; + } /* compute the lenght of the reply*/ @@ -229,7 +245,7 @@ int msrp_fwd_request( void *hdl, struct msrp_msg *req, str *hdrs, int hdrs_no) return -1; } - /* before doing and heavy lifting (as building the out buffer), let's + /* before doing the heavy lifting (as building the out buffer), let's * resolve the destination first. */ bk = to->next->host.s[to->next->host.len]; // usual hack to->next->host.s[to->next->host.len] = 0; @@ -249,27 +265,36 @@ int msrp_fwd_request( void *hdl, struct msrp_msg *req, str *hdrs, int hdrs_no) return -2; } + /* REPORT request do not get a new ident on fwd, but use the + * received one */ + if (req->fl.u.request.method_id==MSRP_METHOD_REPORT) { - /* decide which hash to use for the transaction */ - lock_start_read( ident_lock ); - idx = table_curr_idx; - lock_stop_read( ident_lock ); + ident = req->fl.ident; + + } else { + + /* decide which hash to use for the transaction */ + lock_start_read( ident_lock ); + idx = table_curr_idx; + lock_stop_read( ident_lock ); redo_ident: - /* compute the new ident first */ - hash = hash_entry( msrp_table[idx] , req->fl.ident); + /* compute the new ident first */ + hash = hash_entry( msrp_table[idx] , req->fl.ident); #ifdef MSRP_DEBUG - LM_DBG("using idx %d, hash %d over [%.*s] (size is %d)\n", - idx, hash, req->fl.ident.len, req->fl.ident.s, msrp_table[idx]->size); + LM_DBG("using idx %d, hash %d over [%.*s] (size is %d)\n", + idx, hash, req->fl.ident.len, req->fl.ident.s, + msrp_table[idx]->size); #endif - i = 0; - md5_src[i++] = to->whole; - md5_src[i++] = from->whole; - if (req->message_id) - md5_src[i++] = req->message_id->body; - MD5StringArray( md5, md5_src, i); - ident.s = _ident_builder( hash, idx, md5, MD5_LEN, &ident.len); + i = 0; + md5_src[i++] = to->whole; + md5_src[i++] = from->whole; + if (req->message_id) + md5_src[i++] = req->message_id->body; + MD5StringArray( md5, md5_src, i); + ident.s = _ident_builder( hash, idx, md5, MD5_LEN, &ident.len); + } /* the len will be the same after moving the URL, the only diff will * be imposed by any extra hdrs and diff in ident len (twice!) */ @@ -334,34 +359,39 @@ int msrp_fwd_request( void *hdl, struct msrp_msg *req, str *hdrs, int hdrs_no) LM_DBG("----|\n%.*s|-----\n",len,buf); #endif - /* do transactional stuff */ - cell = _build_transaction( req, hash, &ident); - if (cell==NULL) { - LM_ERR("failed to build transaction, not sending request out\n"); - goto error; - } - /* remember the handler that created this transaction */ - cell->msrp_hdl = hdl; - /* add trasaction to hash table.... */ - hash_lock( msrp_table[idx], hash); + /* REPORT request do not create transaction */ + if (req->fl.u.request.method_id!=MSRP_METHOD_REPORT) { + + /* do transactional stuff */ + cell = _build_transaction( req, hash, &ident); + if (cell==NULL) { + LM_ERR("failed to build transaction, not sending request out\n"); + goto error; + } + /* remember the handler that created this transaction */ + cell->msrp_hdl = hdl; + /* add trasaction to hash table.... */ + hash_lock( msrp_table[idx], hash); + + val = hash_get( msrp_table[idx], hash, ident); + if (val==NULL) { + hash_unlock( msrp_table[idx], hash); + msrp_free_transaction( cell ); + LM_ERR("failed to insert transaction into hash, " + "dropping everything\n"); + goto error; + } else + if (*val!=NULL) { + /* duplicate :O, try generating another ident */ + hash_unlock( msrp_table[idx], hash); + pkg_free(buf); + goto redo_ident; + } + *val = cell; - val = hash_get( msrp_table[idx], hash, ident); - if (val==NULL) { - hash_unlock( msrp_table[idx], hash); - msrp_free_transaction( cell ); - LM_ERR("failed to insert transaction into hash, " - "dropping everything\n"); - goto error; - } else - if (*val!=NULL) { - /* duplicate :O, try generating another ident */ hash_unlock( msrp_table[idx], hash); - pkg_free(buf); - goto redo_ident; - } - *val = cell; - hash_unlock( msrp_table[idx], hash); + } /* now, send it out*/ // TODO - for now we use the same socket (as the received one), but @@ -372,11 +402,13 @@ int msrp_fwd_request( void *hdl, struct msrp_msg *req, str *hdrs, int hdrs_no) if (i<0) { /* sending failed, TODO - close the connection */ LM_ERR("failed to fwd MSRP request\n"); - /* trash the current transaction */ - hash_lock( msrp_table[idx], hash); - hash_remove( msrp_table[idx], hash, ident); - hash_unlock( msrp_table[idx], hash); - msrp_free_transaction( cell ); + if (req->fl.u.request.method_id!=MSRP_METHOD_REPORT) { + /* trash the current transaction */ + hash_lock( msrp_table[idx], hash); + hash_remove( msrp_table[idx], hash, ident); + hash_unlock( msrp_table[idx], hash); + msrp_free_transaction( cell ); + } goto error; } @@ -598,6 +630,157 @@ int msrp_send_reply_on_cell( void *hdl, struct msrp_cell *cell, } +/* Builds and sends back a REPORT request for a given request/transaction + */ +int msrp_send_report(void *hdl, str *status, + struct msrp_msg *req, struct msrp_cell *cell) +{ + int i, len, hash, idx; + char md5[MD5_LEN]; + str ident, md5_src[3]; + str *to, *from, *mid, *recv_ident, *br; + char *buf, *p; + + if ((cell==NULL && req==NULL) || status==NULL || status->len==0) + return -1; + + /* extract needed info*/ + if (cell) { + recv_ident = &cell->recv_ident; + to = &cell->to_top; + from = &cell->from_full; + mid = cell->message_id.len ? &cell->message_id : NULL; + br = cell->byte_range.len ? &cell->byte_range : NULL; + } else { + recv_ident = &req->fl.ident; + /* full FROM path is used */ + from = &req->from_path->body; + /* top TO URL is used (TO hdr already parsed) */ + to = &((struct msrp_url*)(req->to_path->parsed))->whole; + mid = req->message_id ? &req->message_id->body : NULL ; + br = req->byte_range ? &req->byte_range->body : NULL ; + } + + if (mid==NULL) { + LM_ERR("cannot generate REPORT for a request without Message-ID\n"); + return -1; + } + if (br==NULL) { + LM_ERR("cannot generate REPORT for a request without Byte-Range\n"); + return -1; + } + + /* compute its ident first */ + /* decide which hash/idx to use for this pseudo transaction (we do + * not actually build a transaction here, we just get an ident) */ + lock_start_read( ident_lock ); + idx = table_curr_idx; + lock_stop_read( ident_lock ); + + hash = hash_entry( msrp_table[idx] , *recv_ident); + i = 0; + md5_src[i++] = *to; + md5_src[i++] = *from; + if (mid) + md5_src[i++] = *mid; + MD5StringArray( md5, md5_src, i); + ident.s = _ident_builder( hash, idx, md5, MD5_LEN, &ident.len); + + + /* compute the len */ + /* first line + * MSRP SP transact-id SP method CRLF + */ + len = MSRP_PREFIX_LEN + ident.len + 1 + 3 + + MSRP_REPORT_METHOD_LEN + CRLF_LEN; + + /* headers + * headers = To-Path CRLF From-Path CRLF 1*( header CRLF ) + */ + len += TO_PATH_PREFIX_LEN + from->len + CRLF_LEN + + FROM_PATH_PREFIX_LEN + to->len + CRLF_LEN + + MESSAGE_ID_PREFIX_LEN + mid->len + CRLF_LEN + + BYTE_RANGE_PREFIX_LEN + br->len + CRLF_LEN + + STATUS_PREFIX_LEN + status->len + CRLF_LEN ; + + /* EOM + * end-line = "-------" transact-id continuation-flag CRLF + */ + len += EOM_PREFIX_LEN + ident.len + 1 + CRLF_LEN; + + /* allocate the buffer */ + buf = pkg_malloc( len ); + if (buf==NULL) { + LM_ERR("failed to pkg allocate the request buffer\n"); + return -3; + } + + /* start building */ + p = buf; + + /* first line */ + append_string( p, MSRP_PREFIX, MSRP_PREFIX_LEN); + append_string( p, ident.s, ident.len); + *(p++) = ' '; + append_string( p, MSRP_REPORT_METHOD, MSRP_REPORT_METHOD_LEN); + append_string( p, CRLF, CRLF_LEN); + + /* headers */ + append_string( p, TO_PATH_PREFIX, TO_PATH_PREFIX_LEN); + append_string( p, from->s, from->len); + append_string( p, CRLF, CRLF_LEN); + + append_string( p, FROM_PATH_PREFIX, FROM_PATH_PREFIX_LEN); + append_string( p, to->s, to->len); + append_string( p, CRLF, CRLF_LEN); + + append_string( p, MESSAGE_ID_PREFIX, MESSAGE_ID_PREFIX_LEN); + append_string( p, mid->s, mid->len); + append_string( p, CRLF, CRLF_LEN); + + append_string( p, BYTE_RANGE_PREFIX, BYTE_RANGE_PREFIX_LEN); + append_string( p, br->s, br->len); + append_string( p, CRLF, CRLF_LEN); + + append_string( p, STATUS_PREFIX, STATUS_PREFIX_LEN); + append_string( p, status->s, status->len); + append_string( p, CRLF, CRLF_LEN); + + /* EOM */ + append_string( p, EOM_PREFIX, EOM_PREFIX_LEN); + append_string( p, ident.s, ident.len); + *(p++) = '$'; + append_string( p, CRLF, CRLF_LEN); + + if (p-buf!=len) { + LM_BUG("computed %d, but wrote %d :(\n",len,(int)(p-buf)); + goto error; + } + + /* now, send it out*/ + if (cell) { + i = msg_send( cell->recv.send_sock, PROTO_MSRP, + &cell->recv.to, cell->recv.proto_reserved1, + buf, len, NULL); + } else { + i = msg_send( req->rcv.bind_address, PROTO_MSRP, + &req->rcv.src_su, req->rcv.proto_reserved1, + buf, len, NULL); + } + if (i<0) { + /* sending failed, FIXME - close the connection */ + LM_ERR("failed to send MSRP REPORT request\n"); + goto error; + } + + pkg_free(buf); + return 0; + +error: + pkg_free(buf); + return -1; + +} /********* transactional layer ************/ diff --git a/modules/proto_msrp/msrp_signaling.h b/modules/proto_msrp/msrp_signaling.h index d664dabdc96..9a986a3ff04 100644 --- a/modules/proto_msrp/msrp_signaling.h +++ b/modules/proto_msrp/msrp_signaling.h @@ -69,6 +69,9 @@ int msrp_send_reply_on_cell( void *hdl, struct msrp_cell *cell, int code, str* reason, str *hdrs, int hdrs_no); +int msrp_send_report(void *hdl, str *status, + struct msrp_msg *req, struct msrp_cell *cell); + int msrp_fwd_request( void *hdl, struct msrp_msg *req, str *hdrs, int hdrs_no);