summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-03-24 22:45:03 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-03-24 22:45:03 +0100
commit9b6b73207d503524057d008875835b627cd70b6c (patch)
treec42bb8507a1526c3033463af0616567a5a0db31e
parent47e5dc5de9c569b8c22c7af90bc8a07d25c33059 (diff)
WIP..
-rw-r--r--doc/examples/osmo-sip-connector.cfg8
-rw-r--r--src/app.c4
-rw-r--r--src/call.h8
-rw-r--r--src/mncc.c5
-rw-r--r--src/sip.c96
-rw-r--r--src/sip.h3
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
diff --git a/src/app.c b/src/app.c
index 38a935e..747625e 100644
--- a/src/app.c
+++ b/src/app.c
@@ -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)
diff --git a/src/call.h b/src/call.h
index a7f03ee..ed5e104 100644
--- a/src/call.h
+++ b/src/call.h
@@ -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 {
diff --git a/src/mncc.c b/src/mncc.c
index 4436a3f..f44e01e 100644
--- a/src/mncc.c
+++ b/src/mncc.c
@@ -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)
diff --git a/src/sip.c b/src/sip.c
index 4e4d569..8ee7bef 100644
--- a/src/sip.c
+++ b/src/sip.c
@@ -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)
diff --git a/src/sip.h b/src/sip.h
index 14ec8dc..4ba0a0e 100644
--- a/src/sip.h
+++ b/src/sip.h
@@ -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);