diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 3a2832436..d5aec3080 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -73,5 +73,6 @@ struct mgcp_msg_ptr { int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg, struct mgcp_msg_ptr *ptr, int size, const char **transaction_id, struct mgcp_endpoint **endp); +int mgcp_send_dummy(struct mgcp_endpoint *endp); #endif diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c index 80b7b543c..f7f1f80fc 100644 --- a/openbsc/src/mgcp/mgcp_main.c +++ b/openbsc/src/mgcp/mgcp_main.c @@ -128,6 +128,15 @@ static int mgcp_rsip_cb(struct mgcp_config *cfg) return 0; } +static int mgcp_change_cb(struct mgcp_config *cfg, int endpoint, int state, int local_rtp) +{ + if (state != MGCP_ENDP_MDCX) + return 0; + + mgcp_send_dummy(&cfg->endpoints[endpoint]); + return 0; +} + static int read_call_agent(struct bsc_fd *fd, unsigned int what) { struct sockaddr_in addr; @@ -200,6 +209,7 @@ int main(int argc, char** argv) /* set some callbacks */ cfg->reset_cb = mgcp_rsip_cb; + cfg->change_cb = mgcp_change_cb; /* we need to bind a socket */ if (rc == 0) { diff --git a/openbsc/src/mgcp/mgcp_network.c b/openbsc/src/mgcp/mgcp_network.c index 5a982608e..73356f759 100644 --- a/openbsc/src/mgcp/mgcp_network.c +++ b/openbsc/src/mgcp/mgcp_network.c @@ -73,6 +73,8 @@ enum { PROTO_RTCP, }; +#define DUMMY_LOAD 0x23 + static int udp_send(int fd, struct in_addr *addr, int port, char *buf, int len) { @@ -84,6 +86,14 @@ static int udp_send(int fd, struct in_addr *addr, int port, char *buf, int len) return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out)); } +int mgcp_send_dummy(struct mgcp_endpoint *endp) +{ + static char buf[] = { DUMMY_LOAD }; + + return udp_send(endp->local_rtp.fd, &endp->remote, + endp->net_rtp, buf, 1); +} + static void patch_payload(int payload, char *data, int len) { struct rtp_hdr *rtp_hdr; @@ -161,9 +171,17 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what) LOGP(DMGCP, LOGL_NOTICE, "Found BTS for endpoint: 0x%x on port: %d/%d of %s\n", ENDPOINT_NUMBER(endp), ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp), inet_ntoa(addr.sin_addr)); + } } + /* throw away dummy message */ + if (rc == 1 && buf[0] == DUMMY_LOAD) { + LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy on 0x%x\n", + ENDPOINT_NUMBER(endp)); + return 0; + } + /* do this before the loop handling */ if (dest == DEST_NETWORK) ++endp->in_bts; diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c index 76eb7c2a0..d82bd68f9 100644 --- a/openbsc/src/mgcp/mgcp_protocol.c +++ b/openbsc/src/mgcp/mgcp_protocol.c @@ -389,6 +389,7 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg) if (cfg->force_realloc) { LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n", ENDPOINT_NUMBER(endp)); + mgcp_free_endp(endp); } else { LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n", ENDPOINT_NUMBER(endp)); @@ -485,6 +486,7 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg) const char *trans_id; struct mgcp_endpoint *endp; int error_code = 500; + int silent = 0; found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) @@ -517,6 +519,9 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg) goto error3; } break; + case 'Z': + silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0; + break; case '\0': /* SDP file begins */ break; @@ -562,6 +567,8 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg) case MGCP_POLICY_REJECT: LOGP(DMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n", ENDPOINT_NUMBER(endp)); + if (silent) + goto out_silent; return create_response(500, "MDCX", trans_id); break; case MGCP_POLICY_DEFER: @@ -579,6 +586,9 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg) ENDPOINT_NUMBER(endp), inet_ntoa(endp->remote), ntohs(endp->net_rtp)); if (cfg->change_cb) cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX, endp->rtp_port); + if (silent) + goto out_silent; + return create_response_with_sdp(endp, "MDCX", trans_id); error: @@ -589,6 +599,10 @@ error: error3: return create_response(error_code, "MDCX", trans_id); + + +out_silent: + return NULL; } static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) @@ -598,6 +612,7 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) const char *trans_id; struct mgcp_endpoint *endp; int error_code = 500; + int silent = 0; found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) @@ -619,6 +634,9 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) if (verify_ci(endp, (const char *)&msg->l3h[line_start + 3]) != 0) goto error3; break; + case 'Z': + silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0; + break; } default: LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n", @@ -634,6 +652,8 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) case MGCP_POLICY_REJECT: LOGP(DMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n", ENDPOINT_NUMBER(endp)); + if (silent) + goto out_silent; return create_response(500, "DLCX", trans_id); break; case MGCP_POLICY_DEFER: @@ -647,10 +667,14 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) } /* free the connection */ + LOGP(DMGCP, LOGL_NOTICE, "Deleted endpoint on: 0x%x Server: %s:%u\n", + ENDPOINT_NUMBER(endp), inet_ntoa(endp->remote), ntohs(endp->net_rtp)); mgcp_free_endp(endp); if (cfg->change_cb) cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX, endp->rtp_port); + if (silent) + goto out_silent; return create_response(250, "DLCX", trans_id); error: @@ -661,6 +685,9 @@ error: error3: return create_response(error_code, "DLCX", trans_id); + +out_silent: + return NULL; } static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg)