diff options
-rw-r--r-- | openbsc/include/openbsc/bsc_msc.h | 20 | ||||
-rw-r--r-- | openbsc/src/bsc_msc.c | 87 | ||||
-rw-r--r-- | openbsc/src/bsc_msc_ip.c | 43 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 29 |
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"); |