Merge "res_odbc: fix missing SQL error diagnostic"
[asterisk/asterisk.git] / res / res_pjsip_transport_websocket.c
index cdda8c1..2abbf15 100644 (file)
@@ -145,6 +145,7 @@ static int transport_create(void *data)
 {
        struct transport_create_data *create_data = data;
        struct ws_transport *newtransport = NULL;
+       pjsip_tp_state_callback state_cb;
 
        pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
        struct pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt);
@@ -161,6 +162,10 @@ static int transport_create(void *data)
                goto on_error;
        }
 
+       /* Give websocket transport a unique name for its lifetime */
+       snprintf(newtransport->transport.obj_name, PJ_MAX_OBJ_NAME, "ws%p",
+               &newtransport->transport);
+
        newtransport->transport.endpt = endpt;
 
        if (!(pool = pjsip_endpt_create_pool(endpt, "ws", 512, 512))) {
@@ -198,27 +203,26 @@ static int transport_create(void *data)
        ast_debug(4, "Creating websocket transport for %s:%s\n",
                newtransport->transport.type_name, ws_addr_str);
 
+       newtransport->transport.info = (char *) pj_pool_alloc(newtransport->transport.pool,
+               strlen(newtransport->transport.type_name) + strlen(ws_addr_str) + sizeof(" to "));
+       sprintf(newtransport->transport.info, "%s to %s", newtransport->transport.type_name, ws_addr_str);
+
        pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);
        if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) {
                newtransport->transport.key.type = transport_type_wss_ipv6;
-               newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN);
-               pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0);
        } else {
                newtransport->transport.key.type = transport_type_wss;
-               newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN);
-               pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0);
        }
 
        newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);
 
-       pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);
-
-       newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
-       newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);
+       ws_addr_str = ast_sockaddr_stringify(ast_websocket_local_address(newtransport->ws_session));
+       pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.local_addr);
+       pj_strdup2(pool, &newtransport->transport.local_name.host, ast_sockaddr_stringify_host(ast_websocket_local_address(newtransport->ws_session)));
+       newtransport->transport.local_name.port = ast_sockaddr_port(ast_websocket_local_address(newtransport->ws_session));
 
        newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);
-       newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);
-
+       newtransport->transport.dir = PJSIP_TP_DIR_INCOMING;
        newtransport->transport.tpmgr = tpmgr;
        newtransport->transport.send_msg = &ws_send_msg;
        newtransport->transport.destroy = &ws_destroy;
@@ -242,6 +246,16 @@ static int transport_create(void *data)
        }
 
        create_data->transport = newtransport;
+
+       /* Notify application of transport state */
+       state_cb = pjsip_tpmgr_get_state_cb(newtransport->transport.tpmgr);
+       if (state_cb) {
+               pjsip_transport_state_info state_info;
+
+               memset(&state_info, 0, sizeof(state_info));
+               state_cb(&newtransport->transport, PJSIP_TP_STATE_CONNECTED, &state_info);
+       }
+
        return 0;
 
 on_error:
@@ -279,7 +293,7 @@ static int transport_read(void *data)
        pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(session))), &rdata->pkt_info.src_addr);
        rdata->pkt_info.src_addr_len = sizeof(rdata->pkt_info.src_addr);
 
-       pj_ansi_strcpy(rdata->pkt_info.src_name, ast_sockaddr_stringify_host(ast_websocket_remote_address(session)));
+       pj_ansi_strcpy(rdata->pkt_info.src_name, ast_sockaddr_stringify_addr(ast_websocket_remote_address(session)));
        rdata->pkt_info.src_port = ast_sockaddr_port(ast_websocket_remote_address(session));
 
        recvd = pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr, rdata);
@@ -363,8 +377,9 @@ static void websocket_cb(struct ast_websocket *session, struct ast_variable *par
 
        create_data.ws_session = session;
 
-       if (ast_sip_push_task_synchronous(serializer, transport_create, &create_data)) {
+       if (ast_sip_push_task_wait_serializer(serializer, transport_create, &create_data)) {
                ast_log(LOG_ERROR, "Could not create WebSocket transport.\n");
+               ast_taskprocessor_unreference(serializer);
                ast_websocket_unref(session);
                return;
        }
@@ -381,13 +396,13 @@ static void websocket_cb(struct ast_websocket *session, struct ast_variable *par
                }
 
                if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) {
-                       ast_sip_push_task_synchronous(serializer, transport_read, &read_data);
+                       ast_sip_push_task_wait_serializer(serializer, transport_read, &read_data);
                } else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
                        break;
                }
        }
 
-       ast_sip_push_task_synchronous(serializer, transport_shutdown, transport);
+       ast_sip_push_task_wait_serializer(serializer, transport_shutdown, transport);
 
        ast_taskprocessor_unreference(serializer);
        ast_websocket_unref(session);
@@ -414,12 +429,23 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
                pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
                const pj_str_t *txp_str = &STR_WS;
 
-               ast_debug(4, "%s re-writing Contact URI from %.*s:%d%s%.*s to %s:%d;transport=%s\n",
-                       pjsip_rx_data_get_info(rdata),
-                       (int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port,
-                       pj_strlen(&uri->transport_param) ? ";transport=" : "",
-                       (int)pj_strlen(&uri->transport_param), pj_strbuf(&uri->transport_param),
-                       rdata->pkt_info.src_name ?: "", rdata->pkt_info.src_port, pj_strbuf(txp_str));
+               if (DEBUG_ATLEAST(4)) {
+                       char src_addr_buffer[AST_SOCKADDR_BUFLEN];
+                       const char *ipv6_s = "", *ipv6_e = "";
+
+                       if (pj_strchr(&uri->host, ':')) {
+                               ipv6_s = "[";
+                               ipv6_e = "]";
+                       }
+
+                       ast_log(LOG_DEBUG, "%s re-writing Contact URI from %s%.*s%s:%d%s%.*s to %s;transport=%s\n",
+                               pjsip_rx_data_get_info(rdata),
+                               ipv6_s, (int) pj_strlen(&uri->host), pj_strbuf(&uri->host), ipv6_e, uri->port,
+                               pj_strlen(&uri->transport_param) ? ";transport=" : "",
+                               (int) pj_strlen(&uri->transport_param), pj_strbuf(&uri->transport_param),
+                               pj_sockaddr_print(&rdata->pkt_info.src_addr, src_addr_buffer, sizeof(src_addr_buffer), 3),
+                               pj_strbuf(txp_str));
+               }
 
                pj_cstr(&uri->host, rdata->pkt_info.src_name);
                uri->port = rdata->pkt_info.src_port;
@@ -456,8 +482,6 @@ static struct ast_sip_session_supplement websocket_supplement = {
 
 static int load_module(void)
 {
-       CHECK_PJSIP_MODULE_LOADED();
-
        /*
         * We only need one transport type name (ws) defined.  Firefox
         * and Chrome do not support anything other than secure websockets
@@ -475,10 +499,7 @@ static int load_module(void)
                return AST_MODULE_LOAD_DECLINE;
        }
 
-       if (ast_sip_session_register_supplement(&websocket_supplement)) {
-               ast_sip_unregister_service(&websocket_module);
-               return AST_MODULE_LOAD_DECLINE;
-       }
+       ast_sip_session_register_supplement(&websocket_supplement);
 
        if (ast_websocket_add_protocol("sip", websocket_cb)) {
                ast_sip_session_unregister_supplement(&websocket_supplement);
@@ -503,4 +524,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP WebSocket Trans
        .load = load_module,
        .unload = unload_module,
        .load_pri = AST_MODPRI_APP_DEPEND,
+       .requires = "res_pjsip,res_http_websocket",
 );