From 5ec20cab698055029198b10afb4db20bee06ce72 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 11 Sep 2006 20:55:05 +0000 Subject: fixed error handling in sdp_process( ) --- include/sdp_lib.h | 10 +++++++ src/sdp.c | 89 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 25 deletions(-) diff --git a/include/sdp_lib.h b/include/sdp_lib.h index 343493b1..9a83586f 100644 --- a/include/sdp_lib.h +++ b/include/sdp_lib.h @@ -105,6 +105,15 @@ typedef enum { SDP_ATTR_REQ_RANGE } sdp_attrreq_type_t; +/* + * When the pdu_id(type) is a sdp error response, check the status value + * to figure out the error reason. For status values 0x0001-0x0006 check + * Bluetooth SPEC. If the status is 0xffff, call sdp_get_error function + * to get the real reason: + * - wrong transaction ID(EPROTO) + * - wrong PDU id or(EPROTO) + * - I/O error + */ typedef void sdp_callback_t(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *udata); /* @@ -127,6 +136,7 @@ int sdp_get_socket(const sdp_session_t *session); * SDP transaction: functions for asynchronous search. */ sdp_session_t *sdp_create(int sk, uint32_t flags); +int sdp_get_error(sdp_session_t *session); int sdp_process(sdp_session_t *session); int sdp_set_notify(sdp_session_t *session, sdp_callback_t *func, void *udata); diff --git a/src/sdp.c b/src/sdp.c index ccbc1657..e311f014 100644 --- a/src/sdp.c +++ b/src/sdp.c @@ -3050,6 +3050,7 @@ struct sdp_transaction { uint8_t *reqbuf; /* pointer to request PDU */ sdp_buf_t rsp_concat_buf; uint32_t reqsize; /* without cstate */ + int err; /* ZERO if success or the errno if failed */ }; /* @@ -3437,6 +3438,35 @@ end: return -1; } +/* + * Function used to get the error reason after sdp_callback_t function has been called + * and the status is 0xffff. It indicates that an error NOT related to SDP_ErrorResponse + * happened. Get errno directly is not safe because multiple transactions can be triggered. + * This function must be used with asynchronous sdp functions only. + * + * INPUT: + * sdp_session_t *session + * Current sdp session to be handled + * RETURN: + * 0 = No error in the current transaction + * -1 - if the session is invalid + * positive value - the errno value + * + */ +int sdp_get_error(sdp_session_t *session) +{ + struct sdp_transaction *t; + + if (!session || !session->priv) { + SDPERR("Invalid session"); + return -1; + } + + t = session->priv; + + return t->err; +} + /* * Receive the incomming SDP PDU. This function must be called when there is data * available to be read. On continuation state, the original request (with a new @@ -3452,14 +3482,14 @@ end: */ int sdp_process(sdp_session_t *session) { - struct sdp_transaction *t = NULL; - sdp_pdu_hdr_t *reqhdr = NULL; - sdp_pdu_hdr_t *rsphdr = NULL; - sdp_cstate_t *pcstate = NULL; - uint8_t *pdata = NULL, *rspbuf = NULL, *targetPtr = NULL; - int rsp_count = 0, err = -1; + struct sdp_transaction *t; + sdp_pdu_hdr_t *reqhdr, *rsphdr; + sdp_cstate_t *pcstate; + uint8_t *pdata, *rspbuf, *targetPtr; + int rsp_count, err = -1; size_t size = 0; - uint16_t status = 0; + uint16_t status = 0xffff; + uint8_t pdu_id = 0x00; if (!session || !session->priv) { SDPERR("Invalid session"); @@ -3467,8 +3497,11 @@ int sdp_process(sdp_session_t *session) } rspbuf = malloc(SDP_RSP_BUFFER_SIZE); - if (!rspbuf) + if (!rspbuf) { + SDPERR("Response buffer alloc failure:%s (%d)", + strerror(errno), errno); return -1; + } memset(rspbuf, 0, SDP_RSP_BUFFER_SIZE); @@ -3476,20 +3509,21 @@ int sdp_process(sdp_session_t *session) reqhdr = (sdp_pdu_hdr_t *)t->reqbuf; rsphdr = (sdp_pdu_hdr_t *)rspbuf; - if (sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE) <= 0) - goto end; + pdata = rspbuf + sizeof(sdp_pdu_hdr_t); - if (reqhdr->tid != rsphdr->tid) + if (sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE) <= 0) { + SDPERR("Read response:%s (%d)", strerror(errno), errno); + t->err = errno; goto end; + } - pdata = rspbuf + sizeof(sdp_pdu_hdr_t); - - if (rsphdr->pdu_id == SDP_ERROR_RSP) { - status = ntohs(bt_get_unaligned((uint16_t *) pdata)); - size = rsphdr->plen; + if (reqhdr->tid != rsphdr->tid) { + t->err = EPROTO; + SDPERR("Wrong transaction ID."); goto end; } + pdu_id = rsphdr->pdu_id; switch (rsphdr->pdu_id) { uint8_t *ssr_pdata; uint16_t tsrc, csrc; @@ -3512,6 +3546,7 @@ int sdp_process(sdp_session_t *session) pdata += 2 * sizeof(uint16_t); /* Ignore TSRC and CSRC */ rsp_count = csrc * 4; } + status = 0x0000; break; case SDP_SVC_ATTR_RSP: case SDP_SVC_SEARCH_ATTR_RSP: @@ -3519,10 +3554,15 @@ int sdp_process(sdp_session_t *session) SDPDBG("Attrlist byte count : %d\n", rsp_count); pdata += sizeof(uint16_t); // points to attribute list + status = 0x0000; break; + case SDP_ERROR_RSP: + status = ntohs(bt_get_unaligned((uint16_t *) pdata)); + size = rsphdr->plen; + goto end; default: - /* FIXME: how handle this situation? */ - SDPDBG("Illegal PDU ID!"); + t->err = EPROTO; + SDPERR("Illegal PDU ID: 0x%x", rsphdr->pdu_id); goto end; } @@ -3531,7 +3571,7 @@ int sdp_process(sdp_session_t *session) SDPDBG("Cstate length : %d\n", pcstate->length); /* * This is a split response, need to concatenate intermediate - * responses and the last one which will have cstate_len == 0 + * responses and the last one which will have cstate length == 0 */ // build concatenated response buffer @@ -3546,7 +3586,7 @@ int sdp_process(sdp_session_t *session) reqhdr->tid = htons(sdp_gen_tid(session)); - // add continuation state (can be null) + // add continuation state cstate_len = copy_cstate(t->reqbuf + t->reqsize, pcstate); reqsize = t->reqsize + cstate_len; @@ -3555,8 +3595,9 @@ int sdp_process(sdp_session_t *session) reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); if (sdp_send_req(session, t->reqbuf, reqsize) < 0) { - SDPERR("Error sendind data:%s", strerror(errno)); - /* FIXME: how handle this error ? */ + SDPERR("Error sendind data:%s(%d)", strerror(errno), errno); + status = 0xffff; + t->err = errno; goto end; } err = 0; @@ -3568,10 +3609,8 @@ end: pdata = t->rsp_concat_buf.data; size = t->rsp_concat_buf.data_size; } - if (t->cb) - t->cb(rsphdr->pdu_id, status, pdata, - size, t->udata); + t->cb(pdu_id, status, pdata, size, t->udata); } if (rspbuf) -- cgit