aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-03-26 05:44:21 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-03-26 05:44:21 +0100
commit3c1221e2b23876cf0cb4170281eceb73e3395efd (patch)
treefd2ff8da05ef1b374915fd610b2dd8ff3c4df250
parent92e9caed63c4f8fbd31845badd39d3fbe7a8ffc4 (diff)
sccp: Change the ownership of the msgb passed to the callback
Instead of deleting the msgb within the SCCP library the implementor of the write callback needs to free it. This is required for non blocking io with the server.
-rw-r--r--openbsc/include/sccp/sccp.h2
-rw-r--r--openbsc/src/sccp/sccp.c62
-rw-r--r--openbsc/tests/sccp/sccp_test.c24
3 files changed, 35 insertions, 53 deletions
diff --git a/openbsc/include/sccp/sccp.h b/openbsc/include/sccp/sccp.h
index 643479adc..2e1478812 100644
--- a/openbsc/include/sccp/sccp.h
+++ b/openbsc/include/sccp/sccp.h
@@ -94,7 +94,7 @@ struct sccp_connection {
* call sccp_system_incoming for incoming data (from the network)
* sccp will call outgoing whenever outgoing data exists
*/
-int sccp_system_init(int (*outgoing)(struct msgb *data, void *ctx), void *context);
+int sccp_system_init(void (*outgoing)(struct msgb *data, void *ctx), void *context);
int sccp_system_incoming(struct msgb *data);
/**
diff --git a/openbsc/src/sccp/sccp.c b/openbsc/src/sccp/sccp.c
index b1da2c721..4bd87c8ed 100644
--- a/openbsc/src/sccp/sccp.c
+++ b/openbsc/src/sccp/sccp.c
@@ -45,7 +45,7 @@ const struct sockaddr_sccp sccp_ssn_bssap = {
struct sccp_system {
/* layer3 -> layer2 */
- int (*write_data)(struct msgb *data, void *context);
+ void (*write_data)(struct msgb *data, void *context);
void *write_context;
};
@@ -91,9 +91,9 @@ static struct sccp_data_callback *_find_ssn(u_int8_t ssn)
}
-static int _send_msg(struct msgb *msg)
+static void _send_msg(struct msgb *msg)
{
- return sccp_system.write_data(msg, sccp_system.write_context);
+ sccp_system.write_data(msg, sccp_system.write_context);
}
/*
@@ -499,7 +499,6 @@ static int _sccp_send_data(int class, const struct sockaddr_sccp *in,
{
struct sccp_data_unitdata *udt;
u_int8_t *data;
- int ret;
if (msgb_l3len(payload) > 256) {
DEBUGP(DSCCP, "The payload is too big for one udt\n");
@@ -533,10 +532,8 @@ static int _sccp_send_data(int class, const struct sockaddr_sccp *in,
data[0] = msgb_l3len(payload);
memcpy(&data[1], payload->l3h, msgb_l3len(payload));
- ret = _send_msg(msg);
- msgb_free(msg);
-
- return ret;
+ _send_msg(msg);
+ return 0;
}
static int _sccp_handle_read(struct msgb *msgb)
@@ -627,7 +624,6 @@ static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
struct msgb *msgb;
struct sccp_connection_refused *ref;
u_int8_t *data;
- int ret;
msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
SCCP_MSG_HEADROOM, "sccp ref");
@@ -643,9 +639,8 @@ static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
data = msgb_put(msgb, 1);
data[0] = SCCP_PNC_END_OF_OPTIONAL;
- ret = _send_msg(msgb);
- msgb_free(msgb);
- return ret;
+ _send_msg(msgb);
+ return 0;
}
static int _sccp_send_connection_confirm(struct sccp_connection *connection)
@@ -653,7 +648,6 @@ static int _sccp_send_connection_confirm(struct sccp_connection *connection)
struct msgb *response;
struct sccp_connection_confirm *confirm;
u_int8_t *optional_data;
- int ret;
if (assign_source_local_reference(connection) != 0)
return -1;
@@ -677,11 +671,9 @@ static int _sccp_send_connection_confirm(struct sccp_connection *connection)
optional_data = (u_int8_t *) msgb_put(response, 1);
optional_data[0] = SCCP_PNC_END_OF_OPTIONAL;
- ret = _send_msg(response);
- msgb_free(response);
-
+ _send_msg(response);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_ESTABLISHED);
- return ret;
+ return 0;
}
static int _sccp_send_connection_request(struct sccp_connection *connection,
@@ -691,7 +683,6 @@ static int _sccp_send_connection_request(struct sccp_connection *connection,
struct sccp_connection_request *req;
u_int8_t *data;
u_int8_t extra_size = 3 + 1;
- int ret;
if (msg && (msgb_l3len(msg) < 3 || msgb_l3len(msg) > 130)) {
@@ -741,10 +732,8 @@ static int _sccp_send_connection_request(struct sccp_connection *connection,
llist_add_tail(&connection->list, &sccp_connections);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_REQUEST);
- ret = _send_msg(request);
- msgb_free(request);
-
- return ret;
+ _send_msg(request);
+ return 0;
}
static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb *_data)
@@ -753,7 +742,6 @@ static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb
struct sccp_data_form1 *dt1;
u_int8_t *data;
int extra_size;
- int ret;
if (msgb_l3len(_data) < 2 || msgb_l3len(_data) > 256) {
DEBUGP(DSCCP, "data size too big, segmenting unimplemented.\n");
@@ -777,17 +765,14 @@ static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb
data[0] = extra_size - 1;
memcpy(&data[1], _data->l3h, extra_size - 1);
- ret = _send_msg(msgb);
- msgb_free(msgb);
-
- return ret;
+ _send_msg(msgb);
+ return 0;
}
static int _sccp_send_connection_it(struct sccp_connection *conn)
{
struct msgb *msgb;
struct sccp_data_it *it;
- int ret;
msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
SCCP_MSG_HEADROOM, "sccp it");
@@ -803,9 +788,8 @@ static int _sccp_send_connection_it(struct sccp_connection *conn)
it->sequencing[0] = it->sequencing[1] = 0;
it->credit = 0;
- ret = _send_msg(msgb);
- msgb_free(msgb);
- return ret;
+ _send_msg(msgb);
+ return 0;
}
static int _sccp_send_connection_released(struct sccp_connection *conn, int cause)
@@ -813,7 +797,6 @@ static int _sccp_send_connection_released(struct sccp_connection *conn, int caus
struct msgb *msg;
struct sccp_connection_released *rel;
u_int8_t *data;
- int ret;
msg = msgb_alloc_headroom(SCCP_MSG_SIZE, SCCP_MSG_HEADROOM,
"sccp: connection released");
@@ -832,10 +815,8 @@ static int _sccp_send_connection_released(struct sccp_connection *conn, int caus
data[0] = SCCP_PNC_END_OF_OPTIONAL;
_sccp_set_connection_state(conn, SCCP_CONNECTION_STATE_RELEASE);
- ret = _send_msg(msg);
- msgb_free(msg);
-
- return ret;
+ _send_msg(msg);
+ return 0;
}
/*
@@ -982,7 +963,6 @@ static int _sccp_send_connection_release_complete(struct sccp_connection *connec
{
struct msgb *msgb;
struct sccp_connection_release_complete *rlc;
- int ret;
msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
SCCP_MSG_HEADROOM, "sccp rlc");
@@ -995,8 +975,7 @@ static int _sccp_send_connection_release_complete(struct sccp_connection *connec
memcpy(&rlc->source_local_reference,
&connection->source_local_reference, sizeof(struct sccp_source_reference));
- ret = _send_msg(msgb);
- msgb_free(msgb);
+ _send_msg(msgb);
/*
* Remove from the list of active connections and set the state. User code
@@ -1004,8 +983,7 @@ static int _sccp_send_connection_release_complete(struct sccp_connection *connec
*/
llist_del(&connection->list);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_RELEASE_COMPLETE);
-
- return ret;
+ return 0;
}
/* connection released, send a released confirm */
@@ -1118,7 +1096,7 @@ found:
}
-int sccp_system_init(int (*outgoing)(struct msgb *data, void *ctx), void *ctx)
+int sccp_system_init(void (*outgoing)(struct msgb *data, void *ctx), void *ctx)
{
sccp_system.write_data = outgoing;
sccp_system.write_context = ctx;
diff --git a/openbsc/tests/sccp/sccp_test.c b/openbsc/tests/sccp/sccp_test.c
index eb41d3eaf..0c2adc83f 100644
--- a/openbsc/tests/sccp/sccp_test.c
+++ b/openbsc/tests/sccp/sccp_test.c
@@ -354,14 +354,14 @@ int sccp_read_cb(struct msgb *data, unsigned len, void *context)
return 0;
}
-int sccp_write_cb(struct msgb *data, void *ctx)
+void sccp_write_cb(struct msgb *data, void *ctx)
{
int i = 0;
const u_int8_t *got, *wanted;
if (test_data[current_test].response == NULL) {
FAIL("Didn't expect write callback\n");
- return -1;
+ goto exit;
} else if (test_data[current_test].response_length != msgb_l2len(data)) {
FAIL("Size does not match. Got: %d Wanted: %d\n",
msgb_l2len(data), test_data[current_test].response_length);
@@ -374,12 +374,14 @@ int sccp_write_cb(struct msgb *data, void *ctx)
if (got[i] != wanted[i]) {
FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n",
got[i], wanted[i], i);
- return -1;
+ goto exit;
}
}
write_called = 1;
- return 0;
+
+exit:
+ msgb_free(data);
}
void sccp_c_read(struct sccp_connection *connection, struct msgb *msgb, unsigned int len)
@@ -409,7 +411,7 @@ int sccp_accept_cb(struct sccp_connection *connection, void *user_data)
return 0;
}
-static int sccp_udt_write_cb(struct msgb *data, void *context)
+static void sccp_udt_write_cb(struct msgb *data, void *context)
{
const u_int8_t *got, *wanted;
int i;
@@ -419,7 +421,7 @@ static int sccp_udt_write_cb(struct msgb *data, void *context)
if (send_data[current_test].length != msgb_l2len(data)) {
FAIL("Size does not match. Got: %d Wanted: %d\n",
msgb_l2len(data), send_data[current_test].length);
- return -1;
+ goto exit;
}
got = &data->l2h[0];
@@ -429,12 +431,14 @@ static int sccp_udt_write_cb(struct msgb *data, void *context)
if (got[i] != wanted[i]) {
FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n",
got[i], wanted[i], i);
- return -1;
+ goto exit;
}
}
matched = 1;
- return 0;
+
+exit:
+ msgb_free(data);
}
static void test_sccp_system(void)
@@ -504,11 +508,11 @@ static int sccp_udt_read(struct msgb *data, unsigned int len, void *context)
return 0;
}
-static int sccp_write_loop(struct msgb *data, void *context)
+static void sccp_write_loop(struct msgb *data, void *context)
{
/* send it back to us */
sccp_system_incoming(data);
- return 0;
+ msgb_free(data);
}
static void test_sccp_udt_communication(void)