The old way of aborting objects does not work anymore, neither with SRM nor
with the new possibilities of incomplete writes, as that may break the
synchronisation between server and client.
This patch integrates the abort action right within the affected states.
---
 lib/defines.h     |    1 +
 lib/obex_client.c |  126 ++++++++++++++++++++++++++++++++++++++++-------------
 lib/obex_main.c   |   35 ++-------------
 lib/obex_server.c |   91 +++++++++++++++++++++++++++++++++-----
 4 files changed, 179 insertions(+), 74 deletions(-)

diff --git a/lib/defines.h b/lib/defines.h
index eb2257b..5935930 100644
--- a/lib/defines.h
+++ b/lib/defines.h
@@ -27,6 +27,7 @@ enum obex_state {
        STATE_IDLE,
        STATE_SEND,
        STATE_REC,
+       STATE_ABORT,
 };
 
 enum obex_substate {
diff --git a/lib/obex_client.c b/lib/obex_client.c
index c8dc843..efaf9f3 100644
--- a/lib/obex_client.c
+++ b/lib/obex_client.c
@@ -49,6 +49,61 @@ static __inline uint16_t msg_get_len(const buf_t *msg)
                return 0;
 }
 
+static int obex_client_abort_transmit(obex_t *self)
+{
+       int ret = 0;
+       int rsp = OBEX_RSP_CONTINUE;
+
+       DEBUG(4, "STATE: ABORT/TRANSMIT_TX\n");
+
+       ret = obex_object_send_transmit(self, NULL);
+       if (ret == -1) {
+               obex_deliver_event(self, OBEX_EV_LINKERR,
+                                  self->object->opcode, rsp, TRUE);
+               self->state = STATE_IDLE;
+
+       } else if (ret == 1) {
+               self->substate = SUBSTATE_RECEIVE_RX;
+       }
+
+       return ret;
+}
+
+static int obex_client_abort_prepare(obex_t *self)
+{
+       buf_t *msg = buf_reuse(self->tx_msg);
+
+       DEBUG(4, "STATE: ABORT/PREPARE_TX\n");
+
+       obex_data_request_prepare(self, msg, OBEX_CMD_ABORT);
+       self->substate = SUBSTATE_TRANSMIT_TX;
+       return obex_client_abort_transmit(self);
+}
+
+static int obex_client_abort(obex_t *self)
+{
+       int ret = 0;
+       buf_t *msg = obex_data_receive(self);
+       int rsp;
+       int event = OBEX_EV_LINKERR;
+
+       DEBUG(4, "STATE: ABORT/RECEIVE_RX\n");
+
+       if (msg == NULL)
+               return 0;
+       rsp = msg_get_rsp(msg);
+
+       if (rsp == OBEX_RSP_SUCCESS)
+               event = OBEX_EV_ABORT;
+       obex_deliver_event(self, event, self->object->opcode, rsp, TRUE);
+       if (event == OBEX_EV_LINKERR)
+               ret = -1;
+
+       self->mode = MODE_SRV;
+       self->state = STATE_IDLE;
+       return ret;
+}
+
 static int obex_client_recv_transmit_tx(obex_t *self)
 {
        int ret = 0;
@@ -75,12 +130,19 @@ static int obex_client_recv_prepare_tx(obex_t *self)
 {
        DEBUG(4, "STATE: RECV/PREPARE_TX\n");
 
+       /* Sending ABORT is allowed even during SRM */
+       if (self->object->abort == 1) {
+               self->state = STATE_ABORT;
+               return obex_client_abort_prepare(self);
+       }
+
        if (self->object->rsp_mode == OBEX_RSP_MODE_NORMAL ||
            (self->object->rsp_mode == OBEX_RSP_MODE_SINGLE &&
             self->srm_flags & OBEX_SRM_FLAG_WAIT_REMOTE))
        {
-               int ret = obex_object_prepare_send(self, self->object, TRUE,
-                                                  FALSE);
+               int ret;
+
+               ret = obex_object_prepare_send(self, self->object, TRUE, FALSE);
                if (ret == 1) {
                        self->substate = SUBSTATE_TRANSMIT_TX;
                        return obex_client_recv_transmit_tx(self);
@@ -130,50 +192,33 @@ static int obex_client_recv(obex_t *self)
                break;
        }
 
-       /* Receive any headers */
-       ret = obex_object_receive(self, msg);
-       if (ret < 0) {
-               obex_deliver_event(self, OBEX_EV_PARSEERR,
+       if (self->object->abort == 0) {
+               /* Receive any headers */
+               ret = obex_object_receive(self, msg);
+               if (ret < 0) {
+                       obex_deliver_event(self, OBEX_EV_PARSEERR,
                                                self->object->opcode, 0, TRUE);
-               self->mode = MODE_SRV;
-               self->state = STATE_IDLE;
-               return -1;
+                       self->mode = MODE_SRV;
+                       self->state = STATE_IDLE;
+                       return -1;
+               }
        }
        obex_data_receive_finished(self);
 
        /* Are we done yet? */
        if (rsp == OBEX_RSP_CONTINUE) {
                DEBUG(3, "Continue...\n");
-               if (self->object->abort) {
-                       DEBUG(3, "Ignoring CONTINUE because request was 
aborted\n");
-                       return 0;
-               }
                self->substate = SUBSTATE_PREPARE_TX;
                return obex_client_recv_prepare_tx(self);
 
        } else {
                /* Notify app that client-operation is done! */
-               ret = 0;
                DEBUG(3, "Done! Rsp=%02x!\n", rsp);
-               if (self->object->abort) {
-                       if (rsp == OBEX_RSP_SUCCESS)
-                               obex_deliver_event(self, OBEX_EV_ABORT,
-                                                       self->object->opcode,
-                                                       rsp, TRUE);
-                       else {
-                               obex_deliver_event(self, OBEX_EV_LINKERR,
-                                                       self->object->opcode,
-                                                       rsp, TRUE);
-                               ret = -1;
-                       }
-
-               } else
-                       obex_deliver_event(self, OBEX_EV_REQDONE,
-                                                       self->object->opcode,
-                                                       rsp, TRUE);
+               obex_deliver_event(self, OBEX_EV_REQDONE, self->object->opcode,
+                                                                    rsp, TRUE);
                self->mode = MODE_SRV;
                self->state = STATE_IDLE;
-               return ret;
+               return 0;
        }
 
 }
@@ -225,6 +270,12 @@ static int obex_client_send_prepare_tx(obex_t *self)
 
        DEBUG(4, "STATE: SEND/PREPARE_TX\n");
 
+       if (self->object->abort == 1) {
+               self->state = STATE_ABORT;
+               return obex_client_abort_prepare(self);
+       }
+
+
        ret = obex_object_prepare_send(self, self->object, TRUE, FALSE);
        if (ret == 1) {
                self->substate = SUBSTATE_TRANSMIT_TX;
@@ -347,6 +398,19 @@ int obex_client(obex_t *self)
                }
                break;
 
+       case STATE_ABORT:
+               switch (self->substate) {
+               case SUBSTATE_RECEIVE_RX:
+                       return obex_client_abort(self);
+
+               case SUBSTATE_PREPARE_TX:
+                       return obex_client_abort_prepare(self);
+
+               case SUBSTATE_TRANSMIT_TX:
+                       return obex_client_abort_transmit(self);
+               }
+               break;
+
        default:
                DEBUG(0, "Unknown state\n");
                break;
diff --git a/lib/obex_main.c b/lib/obex_main.c
index bc55661..b3a8a45 100644
--- a/lib/obex_main.c
+++ b/lib/obex_main.c
@@ -436,39 +436,12 @@ int obex_cancelrequest(obex_t *self, int nice)
                 * signal link error to app */
                obex_deliver_event(self, OBEX_EV_LINKERR, 0, 0, FALSE);
                return 1;
-       } else {
-               obex_object_t *object;
-
-               object = obex_object_new();
-               if (object == NULL)
-                       return -1;
-
-               if (self->mode == MODE_SRV) {
-                       /* Do not send continue */
-                       if (self->object->opcode != OBEX_RSP_CONTINUE)
-                               obex_object_setrsp(object, self->object->opcode,
-                                                       
self->object->lastopcode);
-                       else
-                               obex_object_setrsp(object,
-                                               OBEX_RSP_INTERNAL_SERVER_ERROR,
-                                               OBEX_RSP_INTERNAL_SERVER_ERROR);
-               } else
-                       obex_object_setcmd(object, OBEX_CMD_ABORT);
-
-               if (obex_object_send(self, object, TRUE, TRUE) < 0) {
-                       obex_object_delete(object);
-                       return -1;
-               }
-
-               obex_object_delete(object);
 
+       } else {
+               /* The client or server code will take action at the
+                * right time. */
                self->object->abort = TRUE;
-               self->state = self->mode == MODE_SRV ? STATE_IDLE : STATE_REC;
 
-               if (self->state == STATE_IDLE)
-                       /* Deliver event will delete the object */
-                       obex_deliver_event(self, OBEX_EV_ABORT, 0, 0, TRUE);
-
-               return 0;
+               return 1;
        }
 }
diff --git a/lib/obex_server.c b/lib/obex_server.c
index 351d710..3a8d179 100644
--- a/lib/obex_server.c
+++ b/lib/obex_server.c
@@ -58,6 +58,42 @@ static __inline int msg_get_final(const buf_t *msg)
                return 0;
 }
 
+static int obex_server_abort_transmit(obex_t *self)
+{
+       int ret = 0;
+       int rsp = OBEX_RSP_CONTINUE;
+
+       DEBUG(4, "STATE: ABORT/TRANSMIT_TX\n");
+
+       ret = obex_object_send_transmit(self, NULL);
+       if (ret == -1) {
+               obex_deliver_event(self, OBEX_EV_LINKERR,
+                                  self->object->opcode, rsp, TRUE);
+
+       } else if (ret == 1) {
+               obex_deliver_event(self, OBEX_EV_ABORT,
+                                  self->object->opcode, rsp, FALSE);
+       }
+
+       self->state = STATE_IDLE;
+       return ret;
+}
+
+static int obex_server_abort_prepare(obex_t *self)
+{
+       buf_t *msg = buf_reuse(self->tx_msg);
+       int opcode = OBEX_RSP_INTERNAL_SERVER_ERROR;
+
+       DEBUG(4, "STATE: ABORT/PREPARE_TX\n");
+
+       /* Do not send continue */
+       if (self->object->opcode != OBEX_RSP_CONTINUE)
+               opcode = self->object->lastopcode;
+       obex_data_request_prepare(self, msg, opcode | OBEX_FINAL);
+       self->substate = SUBSTATE_TRANSMIT_TX;
+       return obex_server_abort_transmit(self);
+}
+
 static int obex_server_send_transmit_tx(obex_t *self)
 {
        int ret;
@@ -102,6 +138,11 @@ static int obex_server_send_prepare_tx(obex_t *self)
 
        DEBUG(4, "STATE: SEND/PREPARE_TX\n");
 
+       if (self->object->abort == 1) {
+               self->state = STATE_ABORT;
+               return obex_server_abort_prepare(self);
+       }
+
        /* As a server, the final bit is always SET, and the "real final" packet
         * is distinguished by being SUCCESS instead of CONTINUE.
         * So, force the final bit here. */
@@ -139,7 +180,7 @@ static int obex_server_send(obex_t *self)
                DEBUG(1, "Got OBEX_ABORT request!\n");
                obex_response_request(self, OBEX_RSP_SUCCESS);
                self->state = STATE_IDLE;
-               obex_deliver_event(self, OBEX_EV_ABORT, self->object->opcode, 
cmd, TRUE);
+               obex_deliver_event(self, OBEX_EV_ABORT, self->object->opcode, 
0, TRUE);
                /* This is not an Obex error, it is just that the peer
                 * aborted the request, so return 0 - Jean II */
                return 0;
@@ -220,8 +261,14 @@ static int obex_server_recv_prepare_tx(obex_t *self)
            (self->object->rsp_mode == OBEX_RSP_MODE_SINGLE &&
             self->srm_flags & OBEX_SRM_FLAG_WAIT_REMOTE))
        {
-               int ret = obex_object_prepare_send(self, self->object,
-                                                  FALSE, TRUE);
+               int ret;
+
+               if (self->object->abort == 1) {
+                       self->state = STATE_ABORT;
+                       return obex_server_abort_prepare(self);
+               }
+
+               ret = obex_object_prepare_send(self, self->object, FALSE, TRUE);
                if (ret == 1) {
                        self->substate = SUBSTATE_TRANSMIT_TX;
                        return obex_server_recv_transmit_tx(self);
@@ -256,7 +303,7 @@ static int obex_server_recv(obex_t *self, int first)
                obex_response_request(self, OBEX_RSP_SUCCESS);
                self->state = STATE_IDLE;
                obex_deliver_event(self, OBEX_EV_ABORT, self->object->opcode,
-                                                               cmd, TRUE);
+                                                               0, TRUE);
                /* This is not an Obex error, it is just that the peer
                 * aborted the request, so return 0 - Jean II */
                return 0;
@@ -364,6 +411,17 @@ static int obex_server_idle(obex_t *self)
                return -1;
        }
 
+       /* If ABORT command is done while we are not handling another command,
+        * we don't need to send a request hint to the application */
+       if (cmd == OBEX_CMD_ABORT) {
+               DEBUG(1, "Got OBEX_ABORT request!\n");
+               obex_response_request(self, OBEX_RSP_SUCCESS);
+               self->state = STATE_IDLE;
+               obex_deliver_event(self, OBEX_EV_ABORT, cmd, 0, TRUE);
+               obex_data_receive_finished(self);
+               return 0;
+       }
+
        self->object = obex_object_new();
        if (self->object == NULL) {
                DEBUG(1, "Allocation of object failed!\n");
@@ -374,14 +432,10 @@ static int obex_server_idle(obex_t *self)
        self->object->cmd = cmd;
        self->object->rsp_mode = self->rsp_mode;
 
-       /* If ABORT command is done while we are not handling another command,
-        * we don't need to send a request hint to the application */
-       if (cmd != OBEX_CMD_ABORT) {
-               /* Hint app that something is about to come so that
-                * the app can deny a PUT-like request early, or
-                * set the header-offset */
-               obex_deliver_event(self, OBEX_EV_REQHINT, cmd, 0, FALSE);
-       }
+       /* Hint app that something is about to come so that
+        * the app can deny a PUT-like request early, or
+        * set the header-offset */
+       obex_deliver_event(self, OBEX_EV_REQHINT, cmd, 0, FALSE);
 
        /* Some commands needs special treatment (data outside headers) */
        switch (cmd) {
@@ -458,6 +512,19 @@ int obex_server(obex_t *self)
                }
                break;
 
+       case STATE_ABORT:
+               switch (self->substate) {
+               case SUBSTATE_PREPARE_TX:
+                       return obex_server_abort_prepare(self);
+
+               case SUBSTATE_TRANSMIT_TX:
+                       return obex_server_abort_transmit(self);
+
+               default:
+                       break;
+               }
+               break;
+
        default:
                DEBUG(0, "Unknown state\n");
                break;
-- 
1.7.5.4


------------------------------------------------------------------------------
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
_______________________________________________
Openobex-users mailing list
Openobex-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/openobex-users

Reply via email to