To be backward compatible, the old obex_event_t callback type is still supported but the documentation only refers to the new type and its functions. --- doc/openobex.coverpage | 20 +---- include/openobex/obex.h | 44 ++++++++++-- lib/obex.c | 185 ++++++++++++++++++++++------------------------- lib/obex.sym | 3 + lib/obex_main.c | 111 +++++++++++++++++++++++++++- lib/obex_main.h | 6 ++- 6 files changed, 246 insertions(+), 123 deletions(-)
diff --git a/doc/openobex.coverpage b/doc/openobex.coverpage index 1f75eb4..1f7715b 100644 --- a/doc/openobex.coverpage +++ b/doc/openobex.coverpage @@ -31,9 +31,9 @@ You might also find the OpenOBEX test applications useful. To be able to use the OpenOBEX API you must include the files openobex/obex_const.h and openobex/obex.h. -First of all you must create an OBEX instance by calling #OBEX_Init. +First of all you must create an OBEX instance by calling #OBEX_New. In this call you specify what transport you want to use, an event callback, and optional flags. -#OBEX_Init will return a handle which shall be passed to almost all other functions. +#OBEX_New will return a handle which shall be passed to almost all other functions. To let the parser do some work you must call #OBEX_HandleInput. It will block for at-most the specified timeout for read and write actions. @@ -41,19 +41,7 @@ You can call #OBEX_GetFD if you want to do select() yourself (this may not work \subsection callback_sec The event callback -The event callback shall be a function with the #obex_event_t prototype: - \code -void *obex_event_t(obex_t *handle, obex_object_t *obj, int mode, int event, int obex_cmd, int obex_rsp) - \endcode - -Arguments: - - handle : OBEX handle - - obj : OBEX object - - mode : OBEX_MODE_CLIENT for client event or OBEX_MODE_SERVER, for server event - - event : The event. See obex_const.h for possible events (OBEX_EV_*) - - obex_cmd : Command if any (depending on event type). See obex_const.h for commands (OBEX_CMD_*) - - obex_rsp : Response if any (depending on event type). See obex_const.h for responses (OBEX_RSP_*) - +The event callback shall be a function with the #obex_event_cb_t prototype. To this function events from the library will be passed to you, for example when an operation finishes. #OBEX_SetUserData and #OBEX_GetUserData are useful if you need to access your own private data from inside the event callback. @@ -125,7 +113,7 @@ generic function #OBEX_ServerRegister or one of the specialized: - #BtOBEX_ServerRegister. When an incoming connection is coming you'll get an #OBEX_EV_ACCEPTHINT event. -If you ignore this event no more incoming connections will be accepted but if you call #OBEX_ServerAccept, +If you ignore this event no more incoming connections will be accepted but if you call #OBEX_Accept, you'll get back a new OBEX handle and the old handle will still be listening to connections. When an incoming request comes, you will first get an #OBEX_EV_REQHINT event. The supplied diff --git a/include/openobex/obex.h b/include/openobex/obex.h index 6bf91d4..ae91f6e 100644 --- a/include/openobex/obex.h +++ b/include/openobex/obex.h @@ -60,18 +60,52 @@ struct obex_object; typedef struct obex obex_t; typedef struct obex_object obex_object_t; -typedef void (*obex_event_t)(obex_t *handle, obex_object_t *obj, int mode, int event, int obex_cmd, int obex_rsp); - #include <openobex/obex_const.h> /* + * OBEX API (deprecated) + */ +/** The user event callback. + * \deprecated Use #obex_event_cb_t and its functions instead. + * \param handle the obex handle + * \param obj the object that this callback is about + * \param mode one of the OBEX_MODE_* + * \param event one of the OBEX_EV_* + * \param obex_cmd the current OBEX command code + * \param obex_rsp the current OBEX response code (client only) + */ +typedef void (*obex_event_t)(obex_t *handle, obex_object_t *obj, int mode, + int event, int obex_cmd, int obex_rsp); + +OPENOBEX_SYMBOL(obex_t *) OBEX_Init(int transport, obex_event_t eventcb, + unsigned int flags); +OPENOBEX_SYMBOL(void) OBEX_SetUserCallBack(obex_t *self, + obex_event_t eventcb, + void * data); +OPENOBEX_SYMBOL(obex_t *) OBEX_ServerAccept(obex_t *server, + obex_event_t eventcb, void * data); + +/* * OBEX API */ -OPENOBEX_SYMBOL(obex_t *) OBEX_Init(int transport, obex_event_t eventcb, unsigned int flags); +/** The user event callback. + * \param handle the obex handle + * \param obj the object that this callback is about + * \param mode the current #obex_mode + * \param event the current #obex_event + * \param obex_cmd the current OBEX command code + * \param obex_rsp the current OBEX response code (client only) + */ +typedef void (*obex_event_cb_t)(obex_t *handle, obex_object_t *obj, + enum obex_mode mode, enum obex_event event, + uint8_t cmd, uint8_t rsp); + +OPENOBEX_SYMBOL(obex_t *) OBEX_New(enum obex_transport_type transport, + obex_event_cb_t eventcb, unsigned int flags); OPENOBEX_SYMBOL(void) OBEX_Cleanup(obex_t *self); OPENOBEX_SYMBOL(void) OBEX_SetUserData(obex_t *self, void * data); OPENOBEX_SYMBOL(void *) OBEX_GetUserData(obex_t *self); -OPENOBEX_SYMBOL(void) OBEX_SetUserCallBack(obex_t *self, obex_event_t eventcb, void * data); +OPENOBEX_SYMBOL(void) OBEX_SetEventCb(obex_t *self, obex_event_cb_t eventcb, void * data); OPENOBEX_SYMBOL(int) OBEX_SetTransportMTU(obex_t *self, uint16_t mtu_rx, uint16_t mtu_tx_max); OPENOBEX_SYMBOL(int) OBEX_GetFD(obex_t *self); @@ -85,7 +119,7 @@ OPENOBEX_SYMBOL(int) OBEX_CustomDataFeed(obex_t *self, uint8_t *inputbuf, int ac OPENOBEX_SYMBOL(int) OBEX_HandleInput(obex_t *self, int timeout); OPENOBEX_SYMBOL(int) OBEX_ServerRegister(obex_t *self, struct sockaddr *saddr, int addrlen); -OPENOBEX_SYMBOL(obex_t *) OBEX_ServerAccept(obex_t *server, obex_event_t eventcb, void * data); +OPENOBEX_SYMBOL(obex_t *) OBEX_Accept(obex_t *server); OPENOBEX_SYMBOL(int) OBEX_Request(obex_t *self, obex_object_t *object); OPENOBEX_SYMBOL(int) OBEX_CancelRequest(obex_t *self, int nice); diff --git a/lib/obex.c b/lib/obex.c index 7bb5bfb..460b0be 100644 --- a/lib/obex.c +++ b/lib/obex.c @@ -44,7 +44,6 @@ #include "obex_main.h" #include "obex_object.h" #include "obex_connect.h" -#include "databuffer.h" #include "fdobex.h" #include "customtrans.h" @@ -66,6 +65,7 @@ /** Initialize OBEX. + \deprecated Use OBEX_New() instead of this function. \param transport Which transport to use. The following transports are available : - #OBEX_TRANS_IRDA : Use regular IrDA socket (need an IrDA stack) - #OBEX_TRANS_INET : Use regular TCP/IP socket @@ -89,65 +89,41 @@ obex_t * CALLAPI OBEX_Init(int transport, obex_event_t eventcb, unsigned int flags) { obex_t *self; - char *env; -#if OBEX_DEBUG - obex_debug = OBEX_DEBUG; -#else - obex_debug = -1; -#endif -#if OBEX_DUMP - obex_dump = OBEX_DUMP; -#else - obex_dump = 0; -#endif - - env = getenv("OBEX_DEBUG"); - if (env) - obex_debug = atoi(env); + obex_return_val_if_fail(eventcb != NULL, NULL); - env = getenv("OBEX_DUMP"); - if (env) - obex_dump = atoi(env); + self = obex_new((enum obex_transport_type)transport, flags); + if (self) + self->old_eventcb = eventcb; - obex_return_val_if_fail(eventcb != NULL, NULL); + return self; +} - self = calloc(1, sizeof(*self)); - if (self == NULL) - return NULL; +/** + Create a new OBEX instance + \param transport Which transport to use. + \param eventcb Function pointer to your event callback. + \param flags Bitmask of flags. The following flags can be used here: + - #OBEX_FL_KEEPSERVER : Keep the server alive after incomming request + - #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 +obex_t * CALLAPI OBEX_New(enum obex_transport_type transport, + obex_event_cb_t eventcb, unsigned int flags) +{ + obex_t *self; - self->eventcb = eventcb; - self->init_flags = flags; - self->mode = OBEX_MODE_SERVER; - self->state = STATE_IDLE; - self->rsp_mode = OBEX_RSP_MODE_NORMAL; - - /* Safe values. - * Both self->mtu_rx and self->mtu_tx_max can be increased by app - * self->mtu_tx will be whatever the other end sends us - Jean II */ - self->mtu_rx = OBEX_DEFAULT_MTU; - self->mtu_tx = OBEX_MINIMUM_MTU; - self->mtu_tx_max = OBEX_DEFAULT_MTU; - - if (obex_transport_init(self, transport) < 0) - goto out_err; - - /* Allocate message buffers */ - /* It's safe to allocate them smaller than OBEX_MAXIMUM_MTU - * because buf_t will realloc data as needed. - Jean II */ - self->rx_msg = buf_new(self->mtu_rx); - if (self->rx_msg == NULL) - goto out_err; + obex_return_val_if_fail(eventcb != NULL, NULL); - self->tx_msg = buf_new(self->mtu_tx_max); - if (self->tx_msg == NULL) - goto out_err; + self = obex_new(transport, flags); + if (self) + self->eventcb = eventcb; return self; - -out_err: - OBEX_Cleanup(self); - return NULL; } /** @@ -222,6 +198,7 @@ void * CALLAPI OBEX_GetUserData(obex_t *self) /** Change user callback on an OBEX handle. + \deprecated Use OBEX_SetEventCb() instead. \param self OBEX handle \param eventcb Function pointer to your new event callback. \param data Pointer to the new user data to pass to the new @@ -234,6 +211,27 @@ void CALLAPI OBEX_SetUserCallBack(obex_t *self, obex_event_t eventcb, obex_return_if_fail(self != NULL); /* The callback can't be NULL */ if (eventcb != NULL) { + self->old_eventcb = eventcb; + /* Optionaly change the user data */ + if (data != NULL) + self->userdata = data; + } +} + +/** + Change event callback on an OBEX handle. + \param self OBEX handle + \param eventcb Function pointer to your new event callback. + \param data Pointer to the new user data to pass to the new + callback (optional) + */ +LIB_SYMBOL +void CALLAPI OBEX_SetEventCb(obex_t *self, obex_event_cb_t eventcb, + void *data) +{ + obex_return_if_fail(self != NULL); + /* The callback can't be NULL */ + if (eventcb != NULL) { self->eventcb = eventcb; /* Optionaly change the user data */ if (data != NULL) @@ -312,6 +310,8 @@ int CALLAPI OBEX_ServerRegister(obex_t *self, struct sockaddr *saddr, int addrle /** Accept an incoming connection. + \deprecated Use OBEX_Accept() in combination with OBEX_SetEventCb() + instead. \param server OBEX handle \param eventcb Event callback for client (use NULL for same as server) \param data Userdata for client (use NULL for same as server) @@ -332,6 +332,38 @@ LIB_SYMBOL obex_t *CALLAPI OBEX_ServerAccept(obex_t *server, obex_event_t eventcb, void *data) { + obex_t * client = OBEX_Accept(server); + + if (client) { + if (eventcb == NULL) + eventcb = client->old_eventcb; + if (data == NULL) + data = client->userdata; + OBEX_SetUserCallBack(client, eventcb, data); + } + + return client; +} + +/** + Accept an incoming connection. + \param server OBEX handle + \return the client instance or NULL on error + + Create a new OBEX instance to handle the incomming connection. + The old OBEX instance will continue to listen for new connections. + The two OBEX instances become totally independant from each other. + + This function should be called after the library generates + an #OBEX_EV_ACCEPTHINT event to the user, but before the user + start to pull data out of the incomming connection. + + Using this function also requires that the OBEX handle was created + with the #OBEX_FL_KEEPSERVER flag set while calling #OBEX_New(). + */ +LIB_SYMBOL +obex_t *CALLAPI OBEX_Accept(obex_t *server) +{ obex_t *self; DEBUG(3, "\n"); @@ -348,54 +380,11 @@ obex_t *CALLAPI OBEX_ServerAccept(obex_t *server, obex_event_t eventcb, if (server->object != NULL) return NULL; - /* Allocate new instance */ - self = calloc(1, sizeof(*self)); - if (self == NULL) - return NULL; - - /* Set callback and callback data as needed */ - if (eventcb != NULL) - self->eventcb = eventcb; - else - self->eventcb = server->eventcb; - - if (data != NULL) - self->userdata = data; - else - self->userdata = server->userdata; - - self->init_flags = server->init_flags; - - obex_transport_clone(self, server); - - self->mtu_rx = server->mtu_rx; - self->mtu_tx = server->mtu_tx; - self->mtu_tx_max = server->mtu_tx_max; - - /* Allocate message buffers */ - self->rx_msg = buf_new(self->mtu_rx); - if (self->rx_msg == NULL) - goto out_err; - - /* Note : mtu_tx not yet negociated, so let's be safe here - Jean II */ - self->tx_msg = buf_new(self->mtu_tx_max); - if (self->tx_msg == NULL) - goto out_err; - - obex_transport_split(self, server); - self->mode = OBEX_MODE_SERVER; - self->state = STATE_IDLE; - self->rsp_mode = server->rsp_mode; + self = obex_clone(server); + if (self) + obex_transport_split(self, server); return self; - -out_err: - if (self->tx_msg != NULL) - buf_free(self->tx_msg); - if (self->rx_msg != NULL) - buf_free(self->rx_msg); - free(self); - return NULL; } /** diff --git a/lib/obex.sym b/lib/obex.sym index 0c33b63..6483738 100644 --- a/lib/obex.sym +++ b/lib/obex.sym @@ -1,8 +1,10 @@ OBEX_Init +OBEX_New OBEX_Cleanup OBEX_SetUserData OBEX_GetUserData OBEX_SetUserCallBack +OBEX_SetEventCb OBEX_SetTransportMTU OBEX_GetFD OBEX_RegisterCTransport @@ -14,6 +16,7 @@ OBEX_CustomDataFeed OBEX_HandleInput OBEX_ServerRegister OBEX_ServerAccept +OBEX_Accept OBEX_Request OBEX_CancelRequest OBEX_SuspendRequest diff --git a/lib/obex_main.c b/lib/obex_main.c index 690dd97..1233120 100644 --- a/lib/obex_main.c +++ b/lib/obex_main.c @@ -38,6 +38,7 @@ #include <stdio.h> #endif /* _WIN32 */ +#include <stdlib.h> #ifdef HAVE_BLUETOOTH #include "bluez_compat.h" @@ -52,12 +53,110 @@ #include <openobex/obex_const.h> -int obex_debug; -int obex_dump; +#ifndef OBEX_DEBUG +#define OBEX_DEBUG -1 +#endif +#ifndef OBEX_DUMP +#define OBEX_DUMP 0 +#endif + +int obex_debug = OBEX_DEBUG; +int obex_dump = OBEX_DUMP; #include "cloexec.h" #include "nonblock.h" +obex_t * obex_new(enum obex_transport_type transport, unsigned int flags) +{ + obex_t *self; + char *env; + + env = getenv("OBEX_DEBUG"); + if (env) + obex_debug = atoi(env); + + env = getenv("OBEX_DUMP"); + if (env) + obex_dump = atoi(env); + + self = calloc(1, sizeof(*self)); + if (self == NULL) + return NULL; + + self->init_flags = flags; + self->mode = OBEX_MODE_SERVER; + self->state = STATE_IDLE; + self->rsp_mode = OBEX_RSP_MODE_NORMAL; + + /* Safe values. + * Both self->mtu_rx and self->mtu_tx_max can be increased by app + * self->mtu_tx will be whatever the other end sends us - Jean II */ + self->mtu_rx = OBEX_DEFAULT_MTU; + self->mtu_tx = OBEX_MINIMUM_MTU; + self->mtu_tx_max = OBEX_DEFAULT_MTU; + + if (obex_transport_init(self, transport) < 0) + goto out_err; + + /* Allocate message buffers */ + /* It's safe to allocate them smaller than OBEX_MAXIMUM_MTU + * because buf_t will realloc data as needed. - Jean II */ + self->rx_msg = buf_new(self->mtu_rx); + if (self->rx_msg == NULL) + goto out_err; + + self->tx_msg = buf_new(self->mtu_tx_max); + if (self->tx_msg == NULL) + goto out_err; + + return self; + +out_err: + OBEX_Cleanup(self); + return NULL; +} + +obex_t *obex_clone(obex_t *from) +{ + /* Allocate new instance */ + obex_t *self = calloc(1, sizeof(*self)); + if (self == NULL) + return NULL; + + /* Set callback and callback data as needed */ + self->eventcb = from->eventcb; + self->userdata = from->userdata; + + self->init_flags = from->init_flags; + + obex_transport_clone(self, from); + + self->mtu_rx = from->mtu_rx; + self->mtu_tx = from->mtu_tx; + self->mtu_tx_max = from->mtu_tx_max; + + /* Allocate message buffers */ + self->rx_msg = buf_new(self->mtu_rx); + if (self->rx_msg == NULL) + goto out_err; + + /* Note : mtu_tx not negotiated, yet, so let's be safe here */ + self->tx_msg = buf_new(self->mtu_tx_max); + if (self->tx_msg == NULL) + goto out_err; + + self->mode = OBEX_MODE_SERVER; + self->state = STATE_IDLE; + self->rsp_mode = from->rsp_mode; + + return self; + +out_err: + OBEX_Cleanup(self); + return NULL; + +} + /* * Function obex_create_socket() * @@ -192,7 +291,13 @@ void obex_deliver_event(obex_t *self, int event, int cmd, int rsp, int del) if (del == TRUE) self->object = NULL; - self->eventcb(self, object, self->mode, event, cmd, rsp); + if (self->eventcb) + self->eventcb(self, object, self->mode, event, cmd, rsp); + + else if (self->old_eventcb) + self->old_eventcb(self, object, (int)self->mode, (int)event, + (int)cmd, (int)rsp); + if (del == TRUE) obex_object_delete(object); diff --git a/lib/obex_main.h b/lib/obex_main.h index 24d37c5..d880bb8 100644 --- a/lib/obex_main.h +++ b/lib/obex_main.h @@ -52,7 +52,9 @@ struct obex { struct databuffer *rx_msg; /* Reusable receive message */ struct obex_object *object; /* Current object being transfered */ - obex_event_t eventcb; /* Event-callback */ + + obex_event_t old_eventcb; /* Old, deprecated event-callback */ + obex_event_cb_t eventcb; /* Event-callback */ obex_transport_t trans; /* Transport being used */ @@ -62,6 +64,8 @@ struct obex { void * userdata; /* For user */ }; +obex_t * obex_new(enum obex_transport_type transport, unsigned int flags); +obex_t * obex_clone(obex_t *from); socket_t obex_create_socket(struct obex *self, int domain); socket_t obex_create_packet_socket(obex_t *self, int domain); int obex_delete_socket(struct obex *self, socket_t fd); -- 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