summaryrefslogtreecommitdiff
path: root/res/res_pjsip_pubsub.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2015-08-06 12:48:07 -0500
committerMark Michelson <mmichelson@digium.com>2015-08-06 13:13:29 -0500
commite25569ef95c6de6e9267df4673bd1d774b82a000 (patch)
tree43acc7d84ef70423a44b685f0eb0ad614dd551e5 /res/res_pjsip_pubsub.c
parent56d11d41988908f3ae1dc5fd9c1fd5bf3ab8ef7e (diff)
res_pjsip_pubsub: More accurately persist packet.
The pjsip_rx_data structure has a pkt_info.packet field on it that is the packet that was read from the transport. For datagram transports, the packet read from the transport will correspond to the SIP message that arrived. For streamed transports, however, it is possible to read multiple SIP messages in one packet. In a recent case, Asterisk crashed on a system where TCP was being used. This is because at some point, a read from the TCP socket resulted in a 200 OK response as well as an incoming SUBSCRIBE request being stored in rdata->pkt_info.packet. When the SUBSCRIBE was processed, the combination 200 OK and SUBSCRIBE was saved in persistent storage. Later, a restart of Asterisk resulted in the crash because the persistent subscription recreation code ended up building the 200 OK response instead of a SUBSCRIBE request, and we attempted to access request-specific data. The fix here is to use the pjsip_msg_print() function in order to persist SUBSCRIBE requests. This way, rather than using the raw socket data, we use the parsed SIP message that PJSIP has given us. If we receive multiple SIP messages from a single read, we will be sure only to save off the relevant SIP message. There also is a safeguard put in place to make sure that if we do end up reconstructing a SIP response, it will not cause a crash. ASTERISK-25306 #close Reported by Mark Michelson Change-Id: I4bf16f7b76a2541d10b55de82bcd14c6e542afb2
Diffstat (limited to 'res/res_pjsip_pubsub.c')
-rw-r--r--res/res_pjsip_pubsub.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 650f5c5c8..3e3ced71f 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -561,7 +561,7 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
sub_tree->persistence->expires = ast_tvadd(ast_tvnow(), ast_samp2tv(expires, 1));
- ast_copy_string(sub_tree->persistence->packet, rdata->pkt_info.packet,
+ pjsip_msg_print(rdata->msg_info.msg, sub_tree->persistence->packet,
sizeof(sub_tree->persistence->packet));
ast_copy_string(sub_tree->persistence->src_name, rdata->pkt_info.src_name,
sizeof(sub_tree->persistence->src_name));
@@ -1338,6 +1338,13 @@ static int subscription_persistence_recreate(void *obj, void *arg, int flags)
return 0;
}
+ if (rdata.msg_info.msg->type != PJSIP_REQUEST_MSG) {
+ ast_log(LOG_NOTICE, "Endpoint %s persisted a SIP response instead of a subscribe request. Unable to reload subscription.\n",
+ ast_sorcery_object_get_id(endpoint));
+ ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
+ return 0;
+ }
+
request_uri = pjsip_uri_get_uri(rdata.msg_info.msg->line.req.uri);
resource_size = pj_strlen(&request_uri->user) + 1;
resource = alloca(resource_size);