]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip_transport_websocket: Prevent transport from being destroyed before message...
authorTinet-mucw <mucw@ti-net.com.cn>
Wed, 13 Sep 2023 09:12:12 +0000 (17:12 +0800)
committerTinet-mucw <mucw@ti-net.com.cn>
Thu, 21 Sep 2023 14:47:54 +0000 (14:47 +0000)
From the gdb information, ast_websocket_read reads a message successfully,
then transport_read is called in the serializer. During execution of pjsip_transport_down,
ws_session->stream->fd is closed; ast_websocket_read encounters an error and exits the while loop.
After executing transport_shutdown, the transport's reference count becomes 0, causing a crash when sending SIP messages.
This was due to pjsip_transport_dec_ref executing earlier than pjsip_rx_data_clone, leading to this issue.
In websocket_cb executeing pjsip_transport_add_ref, this we now ensure the transport is not destroyed while in the loop.

Resolves: asterisk#299

res/res_pjsip_transport_websocket.c

index 3772097d3d9cfff7a308f5c10fe669b14771ac3c..d76c1536c062d797de707067aa27d6f8eded70f2 100644 (file)
@@ -83,6 +83,20 @@ static pj_status_t ws_send_msg(pjsip_transport *transport,
  * Called by pjsip transport manager.
  */
 static pj_status_t ws_destroy(pjsip_transport *transport)
+{
+       struct ws_transport *wstransport = (struct ws_transport *)transport;
+
+       ao2_ref(wstransport, -1);
+
+       return PJ_SUCCESS;
+}
+
+/*!
+ * \brief Shut down the pjsip transport.
+ *
+ * Called by pjsip transport manager.
+ */
+static pj_status_t ws_shutdown(pjsip_transport *transport)
 {
        struct ws_transport *wstransport = (struct ws_transport *)transport;
        int fd = ast_websocket_fd(wstransport->ws_session);
@@ -92,8 +106,6 @@ static pj_status_t ws_destroy(pjsip_transport *transport)
                shutdown(fd, SHUT_RDWR);
        }
 
-       ao2_ref(wstransport, -1);
-
        return PJ_SUCCESS;
 }
 
@@ -232,6 +244,7 @@ static int transport_create(void *data)
        newtransport->transport.dir = PJSIP_TP_DIR_INCOMING;
        newtransport->transport.tpmgr = tpmgr;
        newtransport->transport.send_msg = &ws_send_msg;
+       newtransport->transport.do_shutdown = &ws_shutdown;
        newtransport->transport.destroy = &ws_destroy;
 
        status = pjsip_transport_register(newtransport->transport.tpmgr,
@@ -394,6 +407,7 @@ static void websocket_cb(struct ast_websocket *session, struct ast_variable *par
        transport = create_data.transport;
        read_data.transport = transport;
 
+       pjsip_transport_add_ref(&transport->transport);
        while (ast_websocket_wait_for_input(session, -1) > 0) {
                enum ast_websocket_opcode opcode;
                int fragmented;
@@ -410,6 +424,7 @@ static void websocket_cb(struct ast_websocket *session, struct ast_variable *par
                        break;
                }
        }
+       pjsip_transport_dec_ref(&transport->transport);
 
        ast_sip_push_task_wait_serializer(serializer, transport_shutdown, transport);