diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2016-03-24 22:45:03 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2016-03-24 22:45:03 +0100 |
commit | 9b6b73207d503524057d008875835b627cd70b6c (patch) | |
tree | c42bb8507a1526c3033463af0616567a5a0db31e | |
parent | 47e5dc5de9c569b8c22c7af90bc8a07d25c33059 (diff) |
WIP..
-rw-r--r-- | doc/examples/osmo-sip-connector.cfg | 8 | ||||
-rw-r--r-- | src/app.c | 4 | ||||
-rw-r--r-- | src/call.h | 8 | ||||
-rw-r--r-- | src/mncc.c | 5 | ||||
-rw-r--r-- | src/sip.c | 96 | ||||
-rw-r--r-- | src/sip.h | 3 |
6 files changed, 120 insertions, 4 deletions
diff --git a/doc/examples/osmo-sip-connector.cfg b/doc/examples/osmo-sip-connector.cfg index ad42969..3d3c685 100644 --- a/doc/examples/osmo-sip-connector.cfg +++ b/doc/examples/osmo-sip-connector.cfg @@ -2,5 +2,9 @@ app mncc socket-path /tmp/bsc_mncc sip - local 0.0.0.0 5060 - remote pbx 5060 +! local 0.0.0.0 5060 + local 10.8.254.2 5060 + remote 10.8.0.6 5060 + +log stderr + logging level all debug @@ -58,8 +58,8 @@ void app_setup(struct app_config *cfg) static void route_to_sip(struct call *call, const char *source, const char *dest) { - LOGP(DAPP, LOGL_ERROR, "Can not route call(%u) to SIP yet\n", call->id); - call->initial->release_call(call->initial); + if (sip_create_remote_leg(&g_app.sip.agent, call, source, dest) != 0) + call->initial->release_call(call->initial); } void app_route_call(struct call *call, const char *source, const char *dest) @@ -10,6 +10,9 @@ struct sip_agent; struct mncc_connection; + +struct nua_handle_s; + struct call_leg; /** @@ -63,9 +66,14 @@ struct call_leg { }; struct sip_call_leg { + /* base class */ struct call_leg base; + /* back pointer */ struct sip_agent *agent; + + /* per instance members */ + struct nua_handle_s *nua_handle; }; enum mncc_cc_state { @@ -348,6 +348,7 @@ static void check_disc_ind(struct mncc_connection *conn, char *buf, int rc) { struct gsm_mncc *data; struct mncc_call_leg *leg; + struct call_leg *other_leg; leg = find_leg(conn, buf, rc, &data); if (!leg) @@ -358,6 +359,10 @@ static void check_disc_ind(struct mncc_connection *conn, char *buf, int rc) leg->base.in_release = true; start_cmd_timer(leg, MNCC_REL_CNF); mncc_send(leg->conn, MNCC_REL_REQ, leg->callref); + + other_leg = call_leg_other(&leg->base); + if (other_leg) + other_leg->release_call(other_leg); } static void check_rel_ind(struct mncc_connection *conn, char *buf, int rc) @@ -20,6 +20,10 @@ #include "sip.h" #include "app.h" +#include "call.h" +#include "logging.h" + +#include <osmocom/core/utils.h> #include <talloc.h> @@ -29,6 +33,98 @@ extern void *tall_mncc_ctx; void nua_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { + LOGP(DSIP, LOGL_DEBUG, "SIP event(%u) status(%d) phrase(%s) %p\n", + event, status, phrase, hmagic); +} + + +static void sip_release_call(struct call_leg *_leg) +{ + struct sip_call_leg *leg; + + OSMO_ASSERT(_leg->type == CALL_TYPE_SIP); + leg = (struct sip_call_leg *) _leg; + + /* + * If a dialogue is not confirmed yet, we can probably not do much + * but wait for the timeout. For a confirmed one we can send cancel + * and for a connected one bye. I don't see how sofia-sip is going + * to help us here. + */ + nua_cancel(leg->nua_handle, TAG_END()); +} + +static const char *media_name(int ptmsg) +{ + return "GSM"; +} + +static int send_invite(struct sip_agent *agent, struct sip_call_leg *leg, + const char *calling_num, const char *called_num) +{ + struct call_leg *other = leg->base.call->initial; + struct in_addr net = { .s_addr = ntohl(other->ip) }; + + char *from = talloc_asprintf(leg, "sip:%s@%s", + calling_num, + agent->app->sip.local_addr); + char *to = talloc_asprintf(leg, "sip:%s@%s", + called_num, + agent->app->sip.remote_addr); + char *sdp = talloc_asprintf(leg, + "v=0\r\n" + "o=Osmocom 0 0 IN IP4 %s\r\n" + "s=GSM Call\r\n" + "c=IN IP4 %s\r\n" + "t=0 0\r\n" + "m=audio %d RTP/AVP %d\r\n" + "a=rtpmap:%d %s/8000\r\n", + inet_ntoa(net), inet_ntoa(net), /* never use diff. addr! */ + other->port, other->payload_type, + other->payload_type, + media_name(other->payload_msg_type)); + + nua_invite(leg->nua_handle, + SIPTAG_FROM_STR(from), + SIPTAG_TO_STR(to), + NUTAG_MEDIA_ENABLE(0), + SIPTAG_CONTENT_TYPE_STR("application/sdp"), + SIPTAG_PAYLOAD_STR(sdp), + TAG_END()); + + leg->base.call->remote = &leg->base; + talloc_free(from); + talloc_free(to); + talloc_free(sdp); + return 0; +} + +int sip_create_remote_leg(struct sip_agent *agent, struct call *call, + const char *source, const char *dest) +{ + struct sip_call_leg *leg; + + leg = talloc_zero(call, struct sip_call_leg); + if (!leg) { + LOGP(DSIP, LOGL_ERROR, "Failed to allocate leg for call(%u)\n", + call->id); + return -1; + } + + leg->base.type = CALL_TYPE_SIP; + leg->base.call = call; + leg->base.release_call = sip_release_call; + leg->agent = agent; + + leg->nua_handle = nua_handle(agent->nua, leg, TAG_END()); + if (!leg->nua_handle) { + LOGP(DSIP, LOGL_ERROR, "Failed to allocate nua for call(%u)\n", + call->id); + talloc_free(leg); + return -2; + } + + return send_invite(agent, leg, source, dest); } char *make_sip_uri(struct sip_agent *agent) @@ -8,6 +8,7 @@ #include <sofia-sip/nua.h> struct app_config; +struct call; struct sip_agent { struct app_config *app; @@ -19,3 +20,5 @@ struct sip_agent { void sip_agent_init(struct sip_agent *agent, struct app_config *app); int sip_agent_start(struct sip_agent *agent); + +int sip_create_remote_leg(struct sip_agent *agent, struct call *call, const char *local, const char *remote); |