---
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
[email protected]
http://lists.sourceforge.net/lists/listinfo/openobex-users