[sccp] Split Connection Confirm handling into two parts

This commit is contained in:
Holger Hans Peter Freyther 2010-01-29 04:03:00 +01:00
parent fe5de4e524
commit ca1d1d1493
1 changed files with 40 additions and 27 deletions

View File

@ -320,9 +320,41 @@ int _sccp_parse_connection_refused(struct msgb *msgb, struct sccp_parse_result *
return 0; return 0;
} }
int _sccp_parse_connection_confirm(struct msgb *msg, struct sccp_parse_result *result) int _sccp_parse_connection_confirm(struct msgb *msgb, struct sccp_parse_result *result)
{ {
return -1; static u_int32_t header_size =
sizeof(struct sccp_connection_confirm);
static const u_int32_t optional_offset =
offsetof(struct sccp_connection_confirm, optional_start);
struct sccp_optional_data optional_data;
struct sccp_connection_confirm *con;
/* header check */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
con = (struct sccp_connection_confirm *) msgb->l2h;
result->destination_local_reference = &con->destination_local_reference;
result->source_local_reference = &con->source_local_reference;
memset(&optional_data, 0, sizeof(optional_data));
if (_sccp_parse_optional_data(optional_offset + con->optional_start, msgb, &optional_data) != 0) {
DEBUGP(DSCCP, "parsing of optional data failed.\n");
return -1;
}
if (optional_data.data_len != 0) {
msgb->l3h = &msgb->l2h[optional_data.data_start];
result->data_len = optional_data.data_len;
} else {
result->data_len = 0;
}
return 0;
} }
int _sccp_parse_connection_release_complete(struct msgb *msg, struct sccp_parse_result *result) int _sccp_parse_connection_release_complete(struct msgb *msg, struct sccp_parse_result *result)
@ -1017,29 +1049,17 @@ found:
static int _sccp_handle_connection_confirm(struct msgb *msgb) static int _sccp_handle_connection_confirm(struct msgb *msgb)
{ {
static u_int32_t header_size = struct sccp_parse_result result;
sizeof(struct sccp_connection_confirm);
static const u_int32_t optional_offset =
offsetof(struct sccp_connection_confirm, optional_start);
struct sccp_optional_data optional_data;
struct sccp_connection *conn; struct sccp_connection *conn;
struct sccp_connection_confirm *con;
/* header check */ if (_sccp_parse_connection_confirm(msgb, &result) != 0)
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1; return -1;
}
con = (struct sccp_connection_confirm *) msgb->l2h;
/* lookup if we have a connection with the given reference */ /* lookup if we have a connection with the given reference */
llist_for_each_entry(conn, &sccp_connections, list) { llist_for_each_entry(conn, &sccp_connections, list) {
if (conn->incoming == 0 && conn->data_cb if (conn->incoming == 0 && conn->data_cb
&& memcmp(&conn->source_local_reference, && memcmp(&conn->source_local_reference,
&con->destination_local_reference, result.destination_local_reference,
sizeof(conn->source_local_reference)) == 0) { sizeof(conn->source_local_reference)) == 0) {
goto found; goto found;
} }
@ -1050,19 +1070,12 @@ static int _sccp_handle_connection_confirm(struct msgb *msgb)
found: found:
/* copy the addresses of the connection */ /* copy the addresses of the connection */
conn->destination_local_reference = con->source_local_reference; conn->destination_local_reference = *result.source_local_reference;
_sccp_set_connection_state(conn, SCCP_CONNECTION_STATE_ESTABLISHED); _sccp_set_connection_state(conn, SCCP_CONNECTION_STATE_ESTABLISHED);
memset(&optional_data, 0, sizeof(optional_data));
if (_sccp_parse_optional_data(optional_offset + con->optional_start, msgb, &optional_data) != 0) {
DEBUGP(DSCCP, "parsing of optional data failed.\n");
return -1;
}
/* optional data */ /* optional data */
if (optional_data.data_len != 0 && conn->data_cb) { if (result.data_len != 0 && conn->data_cb) {
msgb->l3h = &msgb->l2h[optional_data.data_start]; conn->data_cb(conn, msgb, result.data_len);
conn->data_cb(conn, msgb, optional_data.data_len);
} }
return 0; return 0;