---
 include/openobex/obex_const.h |    1 +
 lib/CMakeLists.txt            |    1 +
 lib/Makefile.am               |    2 +-
 lib/btobex.c                  |   12 ++++++++-
 lib/fdobex.c                  |   58 +++++++++++++++++++++++++++++-----------
 lib/inobex.c                  |   12 ++++++++
 lib/irobex.c                  |   21 ++++++++++-----
 lib/nonblock.h                |   43 ++++++++++++++++++++++++++++++
 lib/obex.c                    |    1 +
 lib/obex_main.c               |   19 +++++++++----
 lib/obex_transport.c          |   51 ++++++++++++++++++++++++++----------
 11 files changed, 176 insertions(+), 45 deletions(-)
 create mode 100644 lib/nonblock.h

diff --git a/include/openobex/obex_const.h b/include/openobex/obex_const.h
index b4bad7f..8276aae 100644
--- a/include/openobex/obex_const.h
+++ b/include/openobex/obex_const.h
@@ -167,6 +167,7 @@ typedef union {
 #define OBEX_FL_FILTERHINT     (1 <<  2) /* Filter devices based on hint bit */
 #define OBEX_FL_FILTERIAS      (1 <<  3) /* Filter devices based on IAS entry 
*/
 #define OBEX_FL_CLOEXEC                (1 <<  4) /* Set CLOEXEC flag on file 
descriptors */
+#define OBEX_FL_NONBLOCK       (1 <<  5) /* Set the NONBLOCK flag on file 
descriptors */ 
 
 /* For OBEX_ObjectAddHeader */
 #define OBEX_FL_FIT_ONE_PACKET 0x01    /* This header must fit in one packet */
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index f404529..eacc1dd 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -53,6 +53,7 @@ set ( HEADERS
   fdobex.h
   customtrans.h
   cloexec.h
+  nonblock.h
 )
 
 set ( openobex_PUBLIC_HEADER
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ae92239..8da0860 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -19,7 +19,7 @@ libopenobex_la_SOURCES = \
        irda_wrap.h \
        usbutils.c usbutils.h \
        usbobex.c usb1obex.c usbobex.h \
-       visibility.h defines.h debug.h cloexec.h
+       visibility.h defines.h debug.h cloexec.h nonblock.h
 
 libopenobex_la_CPPFLAGS = -I$(top_srcdir)/include
 libopenobex_la_CFLAGS = -D_GNU_SOURCE @CFLAG_VISIBILITY@ @USB1_CFLAGS@
diff --git a/lib/btobex.c b/lib/btobex.c
index 8df237a..652e3db 100644
--- a/lib/btobex.c
+++ b/lib/btobex.c
@@ -46,6 +46,7 @@ bdaddr_t bluez_compat_bdaddr_any = { BTH_ADDR_NULL };
 #endif
 
 #include "cloexec.h"
+#include "nonblock.h"
 
 static int btobex_init(obex_t *self)
 {
@@ -233,6 +234,8 @@ static int btobex_accept(obex_t *self)
                return -1;
 
        trans->mtu = OBEX_DEFAULT_MTU;
+       if (self->init_flags & OBEX_FL_NONBLOCK)
+               socket_set_nonblocking(trans->fd);      
 
        return 0;
 }
@@ -268,7 +271,14 @@ static int btobex_connect_request(obex_t *self)
 
        ret = connect(trans->fd, (struct sockaddr*) &data->peer,
                                                        sizeof(data->peer));
-       if (ret < 0) {
+#if defined(_WIN32)
+       if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+               ret = 0;
+#else
+       if (ret == -1 && errno == EINPROGRESS)
+               ret = 0;
+#endif
+       if (ret == -1) {
                DEBUG(4, "connect(): error %d\n", errno);
                goto out_freesock;
        }
diff --git a/lib/fdobex.c b/lib/fdobex.c
index fa2d64a..70ae791 100644
--- a/lib/fdobex.c
+++ b/lib/fdobex.c
@@ -68,6 +68,9 @@ static int fdobex_write(obex_t *self, buf_t *msg)
        struct obex_transport *trans = &self->trans;
        int fd = trans->data.fd.writefd;
        size_t size = msg->data_size;
+       int status;
+       fd_set fdset;
+       struct timeval time = {trans->timeout, 0};
 
        if (size == 0)
                return 0;
@@ -76,35 +79,58 @@ static int fdobex_write(obex_t *self, buf_t *msg)
                size = trans->mtu;
        DEBUG(1, "sending %zu bytes\n", size);
 
-       if (trans->timeout >= 0) {
-               /* setup everything to check for blocking writes */
-               fd_set fdset;
-               struct timeval time = {trans->timeout, 0};
-               int status;
-
-               FD_ZERO(&fdset);
-               FD_SET(fd, &fdset);
+       FD_ZERO(&fdset);
+       FD_SET(fd, &fdset);
+       if (trans->timeout >= 0)
                status = select((int)fd+1, NULL, &fdset, NULL, &time);
-               if (status == 0)
-                       return 0;
-       }
+       else
+               status = select((int)fd+1, NULL, &fdset, NULL, NULL);
 
-#ifdef _WIN32
-       return _write(fd, msg->data, size);
+       if (status == 0)
+               return 0;
+
+#if defined(_WIN32)
+       status = _write(fd, msg->data, size);
 #else
-       return write(fd, msg->data, size);
+       status = write(fd, msg->data, size);
+       /* The following are not really transport errors. */
+       if (status == -1 &&
+           (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
+               status = 0;
 #endif
+
+       return status;
 }
 
 static int fdobex_read(obex_t *self, void *buf, int buflen)
 {
        struct obex_transport *trans = &self->trans;
+       int status;
+       int fd = trans->fd;
+       fd_set fdset;
+       struct timeval time = {trans->timeout, 0};
+
+       FD_ZERO(&fdset);
+       FD_SET(fd, &fdset);
+       if (trans->timeout >= 0)
+               status = select((int)fd+1, NULL, &fdset, NULL, &time);
+       else
+               status = select((int)fd+1, NULL, &fdset, NULL, NULL);
+
+       if (status == 0)
+               return 0;
 
 #ifdef _WIN32
-       return  _read(trans->fd, buf, buflen);
+       status = _read(fd, buf, buflen);
 #else
-       return read(trans->fd, buf, buflen);
+       status = read(fd, buf, buflen);
+       /* The following are not really transport errors */
+       if (status == -1 &&
+           (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
+               status = 0;
 #endif
+
+       return status;
 }
 
 void fdobex_get_ops(struct obex_transport_ops* ops)
diff --git a/lib/inobex.c b/lib/inobex.c
index 4ae2b61..51302fd 100644
--- a/lib/inobex.c
+++ b/lib/inobex.c
@@ -40,9 +40,11 @@
 #include "obex_main.h"
 #include "inobex.h"
 
+#include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include "cloexec.h"
+#include "nonblock.h"
 
 #define OBEX_PORT 650
 
@@ -292,6 +294,9 @@ static int inobex_accept(obex_t *self)
 
        /* Just use the default MTU for now */
        trans->mtu = OBEX_DEFAULT_MTU;
+       if (self->init_flags & OBEX_FL_NONBLOCK)
+               socket_set_nonblocking(trans->fd);      
+
        return 1;
 }
 
@@ -346,6 +351,13 @@ static int inobex_connect_request(obex_t *self)
 
        ret = connect(trans->fd, (struct sockaddr *) &data->peer,
                                                        sizeof(data->peer));
+#if defined(_WIN32)
+       if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+               ret = 0;
+#else
+       if (ret == -1 && errno == EINPROGRESS)
+               ret = 0;
+#endif
        if (ret == -1) {
                DEBUG(4, "Connect failed\n");
                obex_delete_socket(self, trans->fd);
diff --git a/lib/irobex.c b/lib/irobex.c
index b0aeaa2..d2512d1 100644
--- a/lib/irobex.c
+++ b/lib/irobex.c
@@ -59,6 +59,7 @@
 #include "obex_main.h"
 #include "irobex.h"
 #include "cloexec.h"
+#include "nonblock.h"
 
 static int irobex_init (obex_t *self)
 {
@@ -363,6 +364,8 @@ static int irobex_accept(obex_t *self)
 
        trans->mtu = irobex_get_mtu(self);
        DEBUG(3, "transport mtu=%d\n", trans->mtu);
+       if (self->init_flags & OBEX_FL_NONBLOCK)
+               socket_set_nonblocking(trans->fd);      
 
        return 1;
 }
@@ -519,20 +522,24 @@ static int irobex_connect_request(obex_t *self)
 
        ret = connect(trans->fd, (struct sockaddr*) &data->peer,
                                                        sizeof(data->peer));
-       if (ret < 0) {
+#if defined(_WIN32)
+       if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+               ret = 0;
+#else
+       if (ret == -1 && errno == EINPROGRESS)
+               ret = 0;
+#endif
+       if (ret == -1) {
                DEBUG(4, "ret=%d\n", ret);
-               goto out_freesock;
+               obex_delete_socket(self, trans->fd);
+               trans->fd = INVALID_SOCKET;
+               return ret;
        }
 
        trans->mtu = irobex_get_mtu(self);
        DEBUG(3, "transport mtu=%d\n", trans->mtu);
 
        return 1;
-
-out_freesock:
-       obex_delete_socket(self, trans->fd);
-       trans->fd = INVALID_SOCKET;
-       return ret;
 }
 
 /*
diff --git a/lib/nonblock.h b/lib/nonblock.h
new file mode 100644
index 0000000..fad6058
--- /dev/null
+++ b/lib/nonblock.h
@@ -0,0 +1,43 @@
+/**
+       \file nonblock.h
+       wrapper functions to enable/disable non-blocking
+       OpenOBEX library - Free implementation of the Object Exchange protocol.
+
+       Copyright (c) 2010 Hendrik Sattler, All Rights Reserved.
+
+       OpenOBEX is free software; you can redistribute it and/or modify
+       it under the terms of the GNU Lesser General Public License as
+       published by the Free Software Foundation; either version 2.1 of
+       the License, or (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+       License along with OpenOBEX. If not, see <http://www.gnu.org/>.
+ */
+
+#if defined(_WIN32)
+#include <winsock2.h>
+#else
+#include <fcntl.h>
+#endif
+
+static __inline void socket_set_nonblocking(socket_t fd)
+{
+#if defined(_WIN32)
+       unsigned long val = 1;
+
+       (void)ioctlsocket(fd, FIONBIO, &val);
+
+#else
+       long status = fcntl(fd, F_GETFL);
+
+       if (status == -1)
+               status = 0;
+
+       (void)fcntl(fd, F_SETFL, status | O_NONBLOCK);
+#endif
+}
diff --git a/lib/obex.c b/lib/obex.c
index 277dbf2..eaa50b0 100644
--- a/lib/obex.c
+++ b/lib/obex.c
@@ -81,6 +81,7 @@
                        - #OBEX_FL_FILTERHINT : Filter target devices based on 
Obex hint bit
                        - #OBEX_FL_FILTERIAS  : Filter target devices based on 
IAS entry
                        - #OBEX_FL_CLOEXEC   : Open all sockets with SO_CLOEXEC 
set
+                       - #OBEX_FL_NONBLOCK   : Open all sockets non-blocking
        \return an OBEX handle or NULL on error.
  */
 LIB_SYMBOL
diff --git a/lib/obex_main.c b/lib/obex_main.c
index b3a8a45..03819a2 100644
--- a/lib/obex_main.c
+++ b/lib/obex_main.c
@@ -56,6 +56,7 @@ int obex_debug;
 int obex_dump;
 
 #include "cloexec.h"
+#include "nonblock.h"
 
 /*
  * Function obex_create_socket()
@@ -80,6 +81,9 @@ socket_t obex_create_socket(obex_t *self, int domain)
        else
                fd = socket(domain, type, proto);
 
+       if (self->init_flags & OBEX_FL_NONBLOCK)
+               socket_set_nonblocking(fd);
+
        return fd;
 }
 
@@ -211,7 +215,11 @@ void obex_response_request(obex_t *self, uint8_t opcode)
 
        msg = buf_reuse(self->tx_msg);
        obex_data_request_prepare(self, msg, opcode | OBEX_FINAL);
-       obex_data_request(self, msg);
+       do {
+               int status = obex_data_request(self, msg);
+               if (status < 0)
+                       break;
+       } while (!buf_empty(msg));
 }
 
 /*
@@ -249,11 +257,10 @@ int obex_data_request(obex_t *self, buf_t *msg)
 
        DEBUG(1, "len = %lu bytes\n", (unsigned long) msg->data_size);
 
-       do {
-               status = obex_transport_write(self, msg);
-               if (status > 0)
-                       buf_remove_begin(msg, status);
-       } while (status >= 0 && !buf_empty(msg));
+       status = obex_transport_write(self, msg);
+       if (status > 0)
+               buf_remove_begin(msg, status);
+
        return status;
 }
 
diff --git a/lib/obex_transport.c b/lib/obex_transport.c
index 6207279..a41f6e6 100644
--- a/lib/obex_transport.c
+++ b/lib/obex_transport.c
@@ -366,6 +366,10 @@ int obex_transport_do_send (obex_t *self, buf_t *msg)
        struct obex_transport *trans = &self->trans;
        int fd = trans->fd;
        size_t size = msg->data_size;
+       int status;
+       fd_set fdset;
+       struct timeval *time_ptr = NULL;
+       struct timeval timeout = {trans->timeout, 0};
 
        if (size == 0)
                return 0;
@@ -374,21 +378,28 @@ int obex_transport_do_send (obex_t *self, buf_t *msg)
                size = trans->mtu;
        DEBUG(1, "sending %zu bytes\n", size);
 
-       if (trans->timeout >= 0) {
-               /* setup everything to check for blocking writes */
-               fd_set fdset;
-               struct timeval time = {trans->timeout, 0};
-               int status;
-
-               FD_ZERO(&fdset);
-               FD_SET(fd, &fdset);
-               status = select((int)fd+1, NULL, &fdset, NULL, &time);
-               if (status == 0)
-                       return 0;
-       }
+       FD_ZERO(&fdset);
+       FD_SET(fd, &fdset);
+       if (trans->timeout >= 0)
+               time_ptr = &timeout;
+       status = select((int)fd+1, NULL, &fdset, NULL, time_ptr);
+       if (status == 0)
+               return 0;
 
        /* call send() if no error */
-       return send(fd, msg->data, size, 0);
+       status = send(fd, msg->data, size, 0);
+
+       /* The following are not really transport errors. */
+#if defined(_WIN32)
+       if (status == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+               status = 0;
+#else
+       if (status == -1 &&
+           (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
+               status = 0;
+#endif
+
+       return status;
 }
 
 /*
@@ -408,7 +419,19 @@ int obex_transport_write(obex_t *self, buf_t *msg)
 int obex_transport_do_recv (obex_t *self, void *buf, int buflen)
 {
        struct obex_transport *trans = &self->trans;
-       return recv(trans->fd, buf, buflen, 0);
+       int status = recv(trans->fd, buf, buflen, 0);
+
+       /* The following are not really transport errors. */
+#if defined(_WIN32)
+       if (status == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+               status = 0;
+#else
+       if (status == -1 &&
+           (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
+               status = 0;
+#endif
+
+       return status;
 }
 
 /*
-- 
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