aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_msc.h20
-rw-r--r--openbsc/src/bsc_msc.c87
-rw-r--r--openbsc/src/bsc_msc_ip.c43
-rw-r--r--openbsc/src/nat/bsc_nat.c29
4 files changed, 140 insertions, 39 deletions
diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h
index 49fe68cdc..29ce065d1 100644
--- a/openbsc/include/openbsc/bsc_msc.h
+++ b/openbsc/include/openbsc/bsc_msc.h
@@ -23,8 +23,24 @@
#ifndef BSC_MSC_H
#define BSC_MSC_H
-#include <osmocore/select.h>
+#include <osmocore/write_queue.h>
+#include <osmocore/timer.h>
-int connect_to_msc(struct bsc_fd *fd, const char *ip, int port);
+struct bsc_msc_connection {
+ struct write_queue write_queue;
+ int is_connected;
+ const char *ip;
+ int port;
+
+ void (*connection_loss) (struct bsc_msc_connection *);
+ void (*connected) (struct bsc_msc_connection *);
+ struct timer_list reconnect_timer;
+};
+
+struct bsc_msc_connection *bsc_msc_create(const char *ip, int port);
+int bsc_msc_connect(struct bsc_msc_connection *);
+void bsc_msc_schedule_connect(struct bsc_msc_connection *);
+
+void bsc_msc_lost(struct bsc_msc_connection *);
#endif
diff --git a/openbsc/src/bsc_msc.c b/openbsc/src/bsc_msc.c
index 9df4696a6..5682767b8 100644
--- a/openbsc/src/bsc_msc.c
+++ b/openbsc/src/bsc_msc.c
@@ -24,6 +24,7 @@
#include <openbsc/debug.h>
#include <osmocore/write_queue.h>
+#include <osmocore/talloc.h>
#include <arpa/inet.h>
#include <sys/socket.h>
@@ -33,11 +34,27 @@
#include <string.h>
#include <unistd.h>
+static void connection_loss(struct bsc_msc_connection *con)
+{
+ struct bsc_fd *fd;
+
+ fd = &con->write_queue.bfd;
+
+ close(fd->fd);
+ fd->fd = -1;
+ fd->cb = write_queue_bfd_cb;
+ fd->when = 0;
+
+ con->is_connected = 0;
+ con->connection_loss(con);
+}
+
/* called in the case of a non blocking connect */
static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
{
int rc;
int val;
+ struct bsc_msc_connection *con;
struct write_queue *queue;
socklen_t len = sizeof(val);
@@ -47,6 +64,9 @@ static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
return -1;
}
+ queue = container_of(fd, struct write_queue, bfd);
+ con = container_of(queue, struct bsc_msc_connection, write_queue);
+
/* check the socket state */
rc = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &val, &len);
if (rc != 0) {
@@ -60,19 +80,17 @@ static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
/* go to full operation */
- queue = container_of(fd, struct write_queue, bfd);
fd->cb = write_queue_bfd_cb;
fd->when = BSC_FD_READ;
- if (!llist_empty(&queue->msg_queue))
- fd->when |= BSC_FD_WRITE;
+
+ con->is_connected = 1;
+ if (con->connected)
+ con->connected(con);
return 0;
error:
bsc_unregister_fd(fd);
- close(fd->fd);
- fd->fd = -1;
- fd->cb = write_queue_bfd_cb;
- fd->when = 0;
+ connection_loss(con);
return -1;
}
static void setnonblocking(struct bsc_fd *fd)
@@ -97,13 +115,17 @@ static void setnonblocking(struct bsc_fd *fd)
}
}
-int connect_to_msc(struct bsc_fd *fd, const char *ip, int port)
+int bsc_msc_connect(struct bsc_msc_connection *con)
{
+ struct bsc_fd *fd;
struct sockaddr_in sin;
int on = 1, ret;
- printf("Attempting to connect MSC at %s:%d\n", ip, port);
+ LOGP(DMSC, LOGL_NOTICE, "Attempting to connect MSC at %s:%d\n", con->ip, con->port);
+ con->is_connected = 0;
+
+ fd = &con->write_queue.bfd;
fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
fd->data = NULL;
fd->priv_nr = 1;
@@ -118,8 +140,8 @@ int connect_to_msc(struct bsc_fd *fd, const char *ip, int port)
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- inet_aton(ip, &sin.sin_addr);
+ sin.sin_port = htons(con->port);
+ inet_aton(con->ip, &sin.sin_addr);
setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin));
@@ -130,12 +152,14 @@ int connect_to_msc(struct bsc_fd *fd, const char *ip, int port)
fd->cb = msc_connection_connect;
} else if (ret < 0) {
perror("Connection failed");
- close(fd->fd);
- fd->fd = -1;
+ connection_loss(con);
return ret;
} else {
fd->when = BSC_FD_READ;
fd->cb = write_queue_bfd_cb;
+ con->is_connected = 1;
+ if (con->connected)
+ con->connected(con);
}
ret = bsc_register_fd(fd);
@@ -149,3 +173,40 @@ int connect_to_msc(struct bsc_fd *fd, const char *ip, int port)
}
+struct bsc_msc_connection *bsc_msc_create(const char *ip, int port)
+{
+ struct bsc_msc_connection *con;
+
+ con = talloc_zero(NULL, struct bsc_msc_connection);
+ if (!con) {
+ LOGP(DMSC, LOGL_FATAL, "Failed to create the MSC connection.\n");
+ return NULL;
+ }
+
+ con->ip = ip;
+ con->port = port;
+ write_queue_init(&con->write_queue, 100);
+ return con;
+}
+
+void bsc_msc_lost(struct bsc_msc_connection *con)
+{
+ bsc_unregister_fd(&con->write_queue.bfd);
+ connection_loss(con);
+}
+
+static void reconnect_msc(void *_msc)
+{
+ struct bsc_msc_connection *con = _msc;
+
+ LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
+ bsc_msc_connect(con);
+}
+
+void bsc_msc_schedule_connect(struct bsc_msc_connection *con)
+{
+ LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
+ con->reconnect_timer.cb = reconnect_msc;
+ con->reconnect_timer.data = con;
+ bsc_schedule_timer(&con->reconnect_timer, 5, 0);
+}
diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c
index b8f2279a0..2effc8e7b 100644
--- a/openbsc/src/bsc_msc_ip.c
+++ b/openbsc/src/bsc_msc_ip.c
@@ -58,7 +58,7 @@ static struct debug_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *config_file = "openbsc.cfg";
static char *msc_address = "127.0.0.1";
-static struct write_queue msc_queue;
+static struct bsc_msc_connection *msc_con;
static struct in_addr local_addr;
static LLIST_HEAD(active_connections);
extern int ipacc_rtp_direct;
@@ -540,7 +540,7 @@ static int msc_sccp_do_write(struct bsc_fd *fd, struct msgb *msg)
DEBUGP(DMSC, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
DEBUGP(DMI, "MSC TX %s\n", hexdump(msg->l2h, msgb_l2len(msg)));
- ret = write(msc_queue.bfd.fd, msg->data, msg->len);
+ ret = write(msc_con->write_queue.bfd.fd, msg->data, msg->len);
if (ret < msg->len)
perror("MSC: Failed to send SCCP");
@@ -550,7 +550,7 @@ static int msc_sccp_do_write(struct bsc_fd *fd, struct msgb *msg)
static void msc_sccp_write_ipa(struct msgb *msg, void *data)
{
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
- if (write_queue_enqueue(&msc_queue, msg) != 0) {
+ if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DMSC, LOGL_FATAL, "Failed to queue IPA/SCCP\n");
msgb_free(msg);
}
@@ -647,6 +647,17 @@ static void send_id_get_response(int fd)
}
/*
+ * The connection to the MSC was lost and we will need to free all
+ * resources and then attempt to reconnect.
+ */
+static void msc_connection_was_lost(struct bsc_msc_connection *con)
+{
+ LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freeing information.\n");
+
+ exit(0);
+}
+
+/*
* callback with IP access data
*/
static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
@@ -657,8 +668,9 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
if (!msg) {
if (error == 0) {
- fprintf(stderr, "The connection to the MSC was lost, exiting\n");
- exit(-2);
+ LOGP(DMSC, LOGL_ERROR, "The connection to the MSC was lost.\n");
+
+ return -1;
}
fprintf(stderr, "Failed to parse ip access message: %d\n", error);
@@ -771,6 +783,9 @@ static void signal_handler(int signal)
case SIGUSR1:
talloc_report_full(tall_bsc_ctx, stderr);
break;
+ case SIGUSR2:
+ bsc_msc_lost(msc_con);
+ break;
default:
break;
}
@@ -822,8 +837,6 @@ extern int bts_model_nanobts_init(void);
int main(int argc, char **argv)
{
- int rc;
-
debug_init();
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
stderr_target = debug_target_create_stderr();
@@ -851,15 +864,19 @@ int main(int argc, char **argv)
register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
- write_queue_init(&msc_queue, 100);
- msc_queue.read_cb = ipaccess_a_fd_cb;
- msc_queue.write_cb = msc_sccp_do_write;
- rc = connect_to_msc(&msc_queue.bfd, msc_address, 5000);
- if (rc < 0) {
- fprintf(stderr, "Opening the MSC connection failed.\n");
+ /* setup MSC Connection handling */
+ msc_con = bsc_msc_create(msc_address, 5000);
+ if (!msc_con) {
+ fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
exit(1);
}
+ msc_con->connection_loss = msc_connection_was_lost;
+ msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
+ msc_con->write_queue.write_cb = msc_sccp_do_write;
+ bsc_msc_connect(msc_con);
+
+
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index f50e47f35..3bf4b998f 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -53,7 +53,7 @@ struct debug_target *stderr_target;
static const char *config_file = "bsc-nat.cfg";
static char *msc_address = "127.0.0.1";
static struct in_addr local_addr;
-static struct write_queue msc_queue;
+static struct bsc_msc_connection *msc_con;
static struct bsc_fd bsc_listen;
@@ -420,6 +420,12 @@ exit:
return 0;
}
+static void msc_connection_was_lost(struct bsc_msc_connection *con)
+{
+ LOGP(DMSC, LOGL_FATAL, "Lost the connection.\n");
+ exit(0);
+}
+
static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
{
int error;
@@ -429,7 +435,8 @@ static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
if (!msg) {
if (error == 0) {
LOGP(DNAT, LOGL_FATAL, "The connection the MSC was lost, exiting\n");
- exit(-2);
+ bsc_msc_lost(msc_con);
+ return -1;
}
LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
@@ -576,7 +583,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
}
/* send the non-filtered but maybe modified msg */
- if (write_queue_enqueue(&msc_queue, msg) != 0) {
+ if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DNAT, LOGL_ERROR, "Can not queue message for the MSC.\n");
msgb_free(msg);
}
@@ -822,8 +829,6 @@ static void signal_handler(int signal)
int main(int argc, char** argv)
{
- int rc;
-
debug_init();
stderr_target = debug_target_create_stderr();
debug_add_target(stderr_target);
@@ -851,15 +856,17 @@ int main(int argc, char** argv)
srand(time(NULL));
/* connect to the MSC */
- write_queue_init(&msc_queue, 100);
- msc_queue.read_cb = ipaccess_msc_read_cb;
- msc_queue.write_cb = ipaccess_msc_write_cb;
- rc = connect_to_msc(&msc_queue.bfd, msc_address, 5000);
- if (rc < 0) {
- fprintf(stderr, "Opening the MSC connection failed.\n");
+ msc_con = bsc_msc_create(msc_address, 5000);
+ if (!msc_con) {
+ fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
exit(1);
}
+ msc_con->connection_loss = msc_connection_was_lost;
+ msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
+ msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
+ bsc_msc_connect(msc_con);
+
/* wait for the BSC */
if (listen_for_bsc(&bsc_listen, &local_addr, 5000) < 0) {
fprintf(stderr, "Failed to listen for BSC.\n");