Skip to content

[BUG]after exec rtpengine_answer, opensips memory leak? #3710

@445990772

Description

@445990772

OpenSIPS version you are running

opensips -V
version: opensips 3.6.0 (x86_64/linux)
flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, HP_MALLOC, F_PARALLEL_MALLOC, DBG_MALLOC, FAST_LOCK-ADAPTIVE_WAIT
ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535
poll method support: poll, epoll, sigio_rt, select.
git revision: 07da80880
main.c compiled on 11:05:45 Aug 18 2025 with cc 11
root@ubuntu22:/home/media-proxy# rtpengine -v
Version: 13.3.1.4+0~mr13.3.1.4

this is opensips cfg

####### Global Parameters #########

debug_mode=no

log_level=3
xlog_level=6
stderror_enabled=yes
syslog_enabled=no
syslog_facility=LOG_LOCAL0

udp_workers=1

socket=udp:0.0.0.0:5060   # CUSTOMIZE ME
# socket=tcp:0.0.0.0:5060   # CUSTOMIZE ME
#socket=tls:127.0.0.1:5061   # CUSTOMIZE ME

####### Modules Section ########

#set module path
mpath="/usr/local/lib64/opensips/modules/"

#### SIGNALING module
loadmodule "signaling.so"

loadmodule "textops.so"
#### StateLess module
loadmodule "sl.so"
loadmodule "proto_udp.so"

#### Transaction Module
loadmodule "tm.so"
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 30)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "onreply_avp_mode", 1)

#### Record Route Module
loadmodule "rr.so"
modparam("rr", "append_fromtag", 0)

#### MAX ForWarD module
loadmodule "maxfwd.so"

#### SIP MSG OPerationS module
loadmodule "sipmsgops.so"

#### FIFO Management Interface
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)

#### SQLOPS module
loadmodule "sqlops.so"
modparam("sqlops", "db_url", "postgres://postgres:[email protected]:25432/opensips")
loadmodule "db_postgres.so"

#### DISPATCHER module
loadmodule "dispatcher.so"
modparam("dispatcher", "db_url",
	"postgres://postgres:[email protected]:25432/opensips")
# modparam("dispatcher", "ds_ping_method", "OPTIONS")
# modparam("dispatcher", "ds_probing_mode", 0)
# modparam("dispatcher", "ds_ping_interval", 30)

#### 用户位置和注册
loadmodule "usrloc.so"
loadmodule "registrar.so"
modparam("usrloc", "db_url", "postgres://postgres:[email protected]:25432/opensips")
modparam("usrloc", "db_mode", 1)
#### 告诉 registrar 模块:当客户端通过 NAT 发来 REGISTER 请求时,你(registrar)​​,
#### ​从 Contact 头中提取出 received 参数的值(即客户端真实经过 NAT 映射后的公网 IP 和端口),然后把它存入 AVP 变量 $avp(reg_from) 中,供后续路由或逻辑使用。​​
modparam("registrar", "received_avp", "$avp(reg_from)")

#### NAT 和 RTP 处理
loadmodule "nathelper.so"


loadmodule "rtpengine.so"
modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:22222")

#########################################################################
####### 主路由逻辑:方法分发(route {}) #######
#########################################################################
route {
    # 打印 SIP 信息
   # route(LOG_SIP_INFO);

    # 检查 Max-Forwards
    if (!mf_process_maxfwd_header(10)) {
        sl_send_reply(483, "跳数过多");
        exit;
    }

    # 方法分发
    if (is_method("REGISTER")) {
        route(REGISTER);
    } else if (is_method("INVITE")) {
        route(INVITE);
    } else {
        route(OTHERS);
    }
}

route[LOG_SIP_INFO] {
    # if (is_method("MESSAGE")) {
    if (!is_method("MESSAGE|SUBSCRIBE")) {
        xlog("L_DEBUG", "=============================== 原始 SIP 消息 =============================== \n");
        xlog("L_DEBUG", "\n$mb\n");
        xlog("L_DEBUG", "=============================== SIP 消息结束 =============================== \n");
    }
}


# -------------------------------
# REGISTER
# -------------------------------
route[REGISTER] {
    # 先保存本地注册信息
    if (!save("location")) {
        sl_reply_error();

        exit;
    }
    # Dispatcher 选择目标后端节点
    if (!ds_select_dst(1, 3)) {
        xlog("L_ERR", "dispatcher 未选择到可用后端节点\n");
        exit;
    }
    xlog("L_DEBUG", "➡️ 转发 REGISTER 到后端节点: $du\n");

    # 使用事务转发 REGISTER
    if (!t_relay()) {
        # 如果转发失败,直接返回 503 给客户端
        sl_send_reply(503, "Service Unavailable");
        exit;
    }
}


route[OTHERS] {
    route(PROXY);
}

# -------------------------------
# INVITE
# -------------------------------
route[INVITE] {

    # 获取 X-Device-ID 的值
    route(GET_DEVICE_ID);

    # route(LOG_SIP_INFO);

    #在转发前判断是否有sdp部分,有的话获取后输出先,后续处理
    if (has_body("application/sdp")) {
     
        $var(ssrc) = $sdp.stream(v[0]/y[0]=);
        $sdp.stream(v[0]/y[0]=)=NULL;   

        if(rtpengine_offer("SIP-source-address rtcp-mux-offer",$var(socket), $var(body),$sdp)) {
            remove_body_part();
            $var(body) = $var(body)+$var(ssrc);
        }
           t_on_reply("INVITE_REPLY");
    }
    

    # 查找usrloc
    if (!lookup("location")) {
        # xlog("L_ERR", "[$rm] 未找到设备 $avp(dev_id) 的注册记录\n");
        send_reply(404,"Device Not Found");
        exit;
    }

    # 找到就转发给设备
    # xlog("L_DEBUG", "[$rm] 已找到设备 $avp(dev_id),转发到 $ru\n");
    if (!t_relay()) {
        sl_reply_error();
    }
    exit;
}

route[GET_DEVICE_ID] {
    $avp(dev_id) = $hdr(X-Device-ID);
    $ru = "sip:" + $avp(dev_id) + "@dummy-domain";
}

route[PROXY] {
    route(HANDLE_MESSAGE);
    exit;
}

route[HANDLE_MESSAGE]{
    # ============================
    # 步骤 1:提取目标用户(即 Request-URI 中的用户部分)
    # 目标可能是设备,也可能是平台
    # 我们尝试先查找这个目标是否是一个已注册的设备
    # ============================
    if (is_present_hf("X-Device-ID")) {

        # 使用设备ID作为username,domain随便给一个(lookup只比user部分)
        route(GET_DEVICE_ID);
    }
    # 先尝试查找 Request-URI 中的目标用户是否在 location(已注册设备)
    if (lookup("location")) {
        # xlog("L_DEBUG", "✅ 目标用户 [$ru] 是一个已注册的设备\n");

        # lookup() 会把 $ru 设置为设备的 contact
        # xlog("L_DEBUG", "📤 location查找后,将 MESSAGE 直接转发至目标地址: $ru\n");
        # 使用 t_relay 转发给设备
        if (!t_relay()) {
            sl_send_reply(502, "Bad Gateway");
            xlog("L_ERR", "转发 MESSAGE 到设备失败\n");
            exit;
        }
        exit;
    } else {
        # ============================
        # 步骤 2:如果目标不是已注册设备,则走原有逻辑:转发给平台(通过 Dispatcher)
        # ============================
        # xlog("L_DEBUG", "⚠️ 目标用户 [$ru] 未在 location 中找到注册信息,可能不是设备或未注册\n");

        # Dispatcher 选择后端节点
        if (!ds_select_dst(1, 3)) {
            sl_send_reply(500, "没有可用后端节点");
            xlog("L_ERR", "dispatcher 未选择到可用后端节点\n");
            exit;
        }

        xlog("L_DEBUG", "➡️ 转发 MESSAGE 到后端节点: $du\n");

        # 事务转发到后端
        if (!t_relay()) {
            sl_send_reply(503, "Service Unavailable");
            xlog("L_ERR", "MESSAGE 转发失败\n");
            exit;
        }
    }
}
# 200 OK 回应处理
onreply_route[INVITE_REPLY] {

    # route(LOG_SIP_INFO);
    if (has_body("application/sdp")) {
        xlog("L_INFO", "📥 原始 reply SDP:\n$sdp\n");

        $var(f_line) = $sdp.stream(v[0]/f[0]=);

        $sdp.stream(v[0]/f[0]=) = NULL;

        if (rtpengine_answer("SIP-source-address rtcp-mux-offer", $var(socket), $var(body), $sdp)) {

            xlog("L_INFO", "✅ after rtpengine_answer SDP:\n$sdp\n");
        } else {
            xlog("L_ERR", "❌ rtpengine_answer 失败\n");
        }

    }
      
}

Describe the bug

when i try to invite camera, opensips shows log like this, i try to remove some args , and i tried to config it like rtpengine_offer, but it doesn't work.

rtpengine_answer reply is ok.

this is rtpengine's log

m, local 192.168.33.62:10077 remote 192.168.33.159:15061
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: INFO: [[email protected]]: [control] Replying to 'answer' from 127.0.0.1:38973 (elapsed time 0.000909 sec)
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: [control] Response dump for 'answer' to 127.0.0.1:38973: { "sdp": "v=0 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... o=34020000002000000158 1144 1144 IN IP4 192.168.33.159 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... s=Play ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... t=0 0 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... m=video 10050 RTP/AVP 96 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... c=IN IP4 192.168.33.62 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... a=rtpmap:96 PS/90000 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... a=streamnumber:0 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... a=filesize:0 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... a=sendonly ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... a=rtcp:10051 ...
Aug 26 17:27:54 ubuntu22 rtpengine[1367835]: DEBUG: [[email protected]]: ... ", "result": "ok" }

this is opensips log context

 ================================ 开始 INVITE 点播 🎬 ================================ 
Aug 26 17:27:54 [1367925] INFO:📥 原始 reply SDP:
v=0
o=34020000002000000158 1144 1144 IN IP4 192.168.33.159
s=Play
c=IN IP4 192.168.33.159
t=0 0
m=video 15060 RTP/AVP 96
a=sendonly
a=streamnumber:0
a=rtpmap:96 PS/90000
a=filesize:0
f=v/2/6/25/1/2048a/-1/8/1


Aug 26 17:27:54 [1367925] INFO:✅ after rtpengine_answer SDP:   <---- Show rtpengine is working properly
v=0
o=34020000002000000158 1144 1144 IN IP4 192.168.33.159
s=Play
c=IN IP4 192.168.33.159
t=0 0
m=video 15060 RTP/AVP 96
a=sendonly
a=streamnumber:0
a=rtpmap:96 PS/90000
a=filesize:0


Aug 26 17:27:54 [1367925] CRITICAL:core:build_res_buf_from_sip_res: 
>>> len mismatch : calculated 1150460859, written 652

It seems you have hit a programming bug.
Please help us make OpenSIPS better by reporting it at https://github.com/OpenSIPS/opensips/issues

Aug 26 17:28:16 [1367920] INFO:core:handle_sigs: child process 1367925 exited by a signal 6
Aug 26 17:28:16 [1367920] INFO:core:handle_sigs: core was generated
Aug 26 17:28:16 [1367920] INFO:core:handle_sigs: terminating due to SIGCHLD
Aug 26 17:28:16 [1367923] INFO:core:sig_usr: signal 15 received
Aug 26 17:28:16 [1367924] INFO:core:sig_usr: signal 15 received
Aug 26 17:28:16 [1367920] INFO:core:shutdown_opensips: process 1(1367922) [MI FIFO] terminated, still waiting for 3 more
Aug 26 17:28:16 [1367920] INFO:core:shutdown_opensips: process 2(1367923) [time_keeper] terminated, still waiting for 2 more
Aug 26 17:28:16 [1367920] INFO:core:shutdown_opensips: process 5(1367926) [Timer handler] terminated, still waiting for 1 more
Aug 26 17:28:16 [1367920] INFO:core:shutdown_opensips: process 3(1367924) [timer] terminated, still waiting for 0 more
Aug 26 17:28:16 [1367920] INFO:core:cleanup: cleanup

even if i make onreply_route part like this

   # 调用 rtpengine_answer,直接传递修改后的 SDP
        if (rtpengine_answer("SIP-source-address rtcp-mux-offer", $var(socket), $var(body), $sdp)) {
            xlog("L_INFO", "✅ after rtpengine_answer SDP:\n$sdp\n");
            remove_body_part("application/sdp");
            add_body_part($var(body), "application/sdp");     
        } else {
            xlog("L_ERR", "❌ rtpengine_answer 失败\n");
        }

opensips still throw execption info Aug 26 17:27:54 [1367925] CRITICAL:core:build_res_buf_from_sip_res:

len mismatch : calculated 1150460859, written 652

so how can i reply camera the correct sdp info?

To Reproduce

Expected behavior

Relevant System Logs

OS/environment information

  • Operating System:
  • OpenSIPS installation:
  • other relevant information:

Additional context

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions