aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android/async-io-common.h61
-rw-r--r--android/async-socket-connector.c121
-rw-r--r--android/async-socket-connector.h107
-rw-r--r--android/async-socket.c402
-rw-r--r--android/async-socket.h273
5 files changed, 527 insertions, 437 deletions
diff --git a/android/async-io-common.h b/android/async-io-common.h
new file mode 100644
index 0000000..02714a7
--- /dev/null
+++ b/android/async-io-common.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ASYNC_IO_COMMON_H_
+#define ANDROID_ASYNC_IO_COMMON_H_
+
+/*
+ * Contains declarations common for asynchronous socket I/O
+ */
+
+/* Enumerates asynchronous I/O states.
+ * Values from this enum are passed to callbacks associated with an I/O,
+ * indicating at what state the I/O is. */
+typedef enum AsyncIOState {
+ /* Asynchronous I/O has been queued. (0) */
+ ASIO_STATE_QUEUED,
+ /* Asynchronous I/O has started. This state indicates that I/O has been
+ * performed for the first time. (1) */
+ ASIO_STATE_STARTED,
+ /* Asynchronous I/O is continuing. This state indicates that I/O has been
+ * invoked for the second (or more) time. (2) */
+ ASIO_STATE_CONTINUES,
+ /* Asynchronous I/O is about to be retried. (3) */
+ ASIO_STATE_RETRYING,
+ /* Asynchronous I/O has been successfuly completed. (4) */
+ ASIO_STATE_SUCCEEDED,
+ /* Asynchronous I/O has failed. (5) */
+ ASIO_STATE_FAILED,
+ /* Asynchronous I/O has timed out. (6) */
+ ASIO_STATE_TIMED_OUT,
+ /* Asynchronous I/O has been cancelled (due to disconnect, for
+ * instance). (7) */
+ ASIO_STATE_CANCELLED,
+} AsyncIOState;
+
+/* Enumerates actions to perform with an I/O on state transition.
+ * Values from this enum are returned from async I/O callbacks, indicating what
+ * action should be performed with the I/O by I/O handler. */
+typedef enum AsyncIOAction {
+ /* I/O is done. Perform default action depending on I/O type. */
+ ASIO_ACTION_DONE,
+ /* Abort the I/O. */
+ ASIO_ACTION_ABORT,
+ /* Retry the I/O. */
+ ASIO_ACTION_RETRY,
+} AsyncIOAction;
+
+#endif /* ANDROID_ASYNC_IO_COMMON_H_ */
diff --git a/android/async-socket-connector.c b/android/async-socket-connector.c
index daf6a37..41a13e0 100644
--- a/android/async-socket-connector.c
+++ b/android/async-socket-connector.c
@@ -47,7 +47,7 @@ struct AsyncSocketConnector {
LoopTimer connector_timer[1];
/* Asynchronous connector to the socket. */
AsyncConnector connector[1];
- /* Callback to invoke on connection / connection error. */
+ /* Callback to invoke on connection events. */
asc_event_cb on_connected_cb;
/* An opaque parameter to pass to the connection callback. */
void* on_connected_cb_opaque;
@@ -106,8 +106,8 @@ _async_socket_connector_open_socket(AsyncSocketConnector* connector)
/* Open socket. */
connector->fd = socket_create_inet(SOCKET_STREAM);
if (connector->fd < 0) {
- D("Unable to create connector socket for %s. Error: %s",
- _asc_socket_string(connector), strerror(errno));
+ D("Unable to create AsyncSocketConnector socket for '%s'. Error: %d -> %s",
+ _asc_socket_string(connector), errno, strerror(errno));
return -1;
}
@@ -148,45 +148,38 @@ static void
_on_async_socket_connector_connecting(AsyncSocketConnector* connector,
AsyncStatus status)
{
- ASCCbRes action;
- int do_retry = 0;
+ AsyncIOAction action = ASIO_ACTION_DONE;
switch (status) {
case ASYNC_COMPLETE:
loopIo_done(connector->connector_io);
- D("Socket %s is connected", _asc_socket_string(connector));
+ D("Socket '%s' is connected", _asc_socket_string(connector));
/* Invoke "on connected" callback */
action = connector->on_connected_cb(connector->on_connected_cb_opaque,
- connector, ASC_CONNECTION_SUCCEEDED);
- if (action == ASC_CB_RETRY) {
- do_retry = 1;
- } else if (action == ASC_CB_ABORT) {
- _async_socket_connector_close_socket(connector);
- }
+ connector, ASIO_STATE_SUCCEEDED);
break;
case ASYNC_ERROR:
loopIo_done(connector->connector_io);
- D("Error %d while connecting to socket %s: %s",
- errno, _asc_socket_string(connector), strerror(errno));
+ D("Error while connecting to socket '%s': %d -> %s",
+ _asc_socket_string(connector), errno, strerror(errno));
/* Invoke "on connected" callback */
action = connector->on_connected_cb(connector->on_connected_cb_opaque,
- connector, ASC_CONNECTION_FAILED);
- if (action == ASC_CB_RETRY) {
- do_retry = 1;
- } else if (action == ASC_CB_ABORT) {
- _async_socket_connector_close_socket(connector);
- }
+ connector, ASIO_STATE_FAILED);
break;
case ASYNC_NEED_MORE:
return;
}
- if (do_retry) {
- D("Retrying connection to socket %s", _asc_socket_string(connector));
+ if (action == ASIO_ACTION_RETRY) {
+ D("Retrying connection to socket '%s'", _asc_socket_string(connector));
loopTimer_startRelative(connector->connector_timer, connector->retry_to);
} else {
+ if (action == ASIO_ACTION_ABORT) {
+ D("%s: AsyncSocketConnector client for socket '%s' has aborted connection",
+ __FUNCTION__, _asc_socket_string(connector));
+ }
_async_socket_connector_free(connector);
}
}
@@ -196,9 +189,19 @@ _on_async_socket_connector_io(void* opaque, int fd, unsigned events)
{
AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque;
- /* Complete socket connection. */
- const AsyncStatus status = asyncConnector_run(connector->connector);
- _on_async_socket_connector_connecting(connector, status);
+ /* Notify the client that another connection attempt is about to start. */
+ const AsyncIOAction action =
+ connector->on_connected_cb(connector->on_connected_cb_opaque,
+ connector, ASIO_STATE_CONTINUES);
+ if (action != ASIO_ACTION_ABORT) {
+ /* Complete socket connection. */
+ const AsyncStatus status = asyncConnector_run(connector->connector);
+ _on_async_socket_connector_connecting(connector, status);
+ } else {
+ D("%s: AsyncSocketConnector client for socket '%s' has aborted connection",
+ __FUNCTION__, _asc_socket_string(connector));
+ _async_socket_connector_free(connector);
+ }
}
/* Retry connection timer callback.
@@ -208,31 +211,33 @@ _on_async_socket_connector_io(void* opaque, int fd, unsigned events)
static void
_on_async_socket_connector_retry(void* opaque)
{
+ AsyncStatus status;
AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque;
/* Invoke the callback to notify about a connection retry attempt. */
- const ASCCbRes action =
+ AsyncIOAction action =
connector->on_connected_cb(connector->on_connected_cb_opaque,
- connector, ASC_CONNECTION_RETRY);
-
- if (action == ASC_CB_RETRY) {
- AsyncStatus status;
+ connector, ASIO_STATE_RETRYING);
- /* Close handle opened for the previous (failed) attempt. */
- _async_socket_connector_close_socket(connector);
+ if (action == ASIO_ACTION_ABORT) {
+ D("%s: AsyncSocketConnector client for socket '%s' has aborted connection",
+ __FUNCTION__, _asc_socket_string(connector));
+ _async_socket_connector_free(connector);
+ return;
+ }
- /* Retry connection attempt. */
- if (_async_socket_connector_open_socket(connector) == 0) {
- status = asyncConnector_init(connector->connector, &connector->address,
- connector->connector_io);
- } else {
- status = ASYNC_ERROR;
- }
+ /* Close handle opened for the previous (failed) attempt. */
+ _async_socket_connector_close_socket(connector);
- _on_async_socket_connector_connecting(connector, status);
+ /* Retry connection attempt. */
+ if (_async_socket_connector_open_socket(connector) == 0) {
+ status = asyncConnector_init(connector->connector, &connector->address,
+ connector->connector_io);
} else {
- _async_socket_connector_free(connector);
+ status = ASYNC_ERROR;
}
+
+ _on_async_socket_connector_connecting(connector, status);
}
/********************************************************************************
@@ -248,7 +253,7 @@ async_socket_connector_new(const SockAddress* address,
AsyncSocketConnector* connector;
if (cb == NULL) {
- W("No callback for AsyncSocketConnector for %s",
+ W("No callback for AsyncSocketConnector for socket '%s'",
sock_address_to_string(address));
errno = EINVAL;
return NULL;
@@ -275,8 +280,9 @@ async_socket_connector_new(const SockAddress* address,
loopTimer_init(connector->connector_timer, connector->looper,
_on_async_socket_connector_retry, connector);
} else {
- E("Unable to create I/O looper for asynchronous connector to socket %s",
+ E("Unable to create I/O looper for AsyncSocketConnector for socket '%s'",
_asc_socket_string(connector));
+ cb(cb_opaque, connector, ASIO_STATE_FAILED);
_async_socket_connector_free(connector);
return NULL;
}
@@ -284,31 +290,30 @@ async_socket_connector_new(const SockAddress* address,
return connector;
}
-ASCConnectRes
+void
async_socket_connector_connect(AsyncSocketConnector* connector)
{
AsyncStatus status;
if (_async_socket_connector_open_socket(connector) == 0) {
- status = asyncConnector_init(connector->connector, &connector->address,
- connector->connector_io);
+ const AsyncIOAction action =
+ connector->on_connected_cb(connector->on_connected_cb_opaque,
+ connector, ASIO_STATE_STARTED);
+ if (action == ASIO_ACTION_ABORT) {
+ D("%s: AsyncSocketConnector client for socket '%s' has aborted connection",
+ __FUNCTION__, _asc_socket_string(connector));
+ _async_socket_connector_free(connector);
+ return;
+ } else {
+ status = asyncConnector_init(connector->connector,
+ &connector->address,
+ connector->connector_io);
+ }
} else {
status = ASYNC_ERROR;
}
_on_async_socket_connector_connecting(connector, status);
-
- switch (status) {
- case ASYNC_COMPLETE:
- return ASC_CONNECT_SUCCEEDED;
-
- case ASYNC_ERROR:
- return ASC_CONNECT_FAILED;
-
- case ASYNC_NEED_MORE:
- default:
- return ASC_CONNECT_IN_PROGRESS;
- }
}
int
diff --git a/android/async-socket-connector.h b/android/async-socket-connector.h
index 998d0c8..4c05059 100644
--- a/android/async-socket-connector.h
+++ b/android/async-socket-connector.h
@@ -17,15 +17,17 @@
#ifndef ANDROID_ASYNC_SOCKET_CONNECTOR_H_
#define ANDROID_ASYNC_SOCKET_CONNECTOR_H_
+#include "android/async-io-common.h"
+
/*
* Contains declaration of an API that allows asynchronous connection to a
* socket with retries.
*
* The typical usage of this API is as such:
*
- * 1. The client creates an async connector instance by calling async_socket_connector_new
- * routine, supplying there address of the socket to connect, and a callback
- * to invoke on connection events.
+ * 1. The client creates an asynchronous connector instance by calling
+ * async_socket_connector_new routine, supplying there address of the socket
+ * to connect, and a callback to invoke on connection events.
* 2. The client then proceeds with calling async_socket_connector_connect that
* would initiate connection attempts.
*
@@ -38,94 +40,58 @@
* 2. Failure.
* 3. Retry.
*
- * Typically, when client's callback is called for successful connection, the
+ * Typically, when client's callback is called for a successful connection, the
* client will pull connected socket's FD from the connector, and then this FD
- * will be used by the client for I/O on the connected socket. If socket's FD
- * is pulled by the client, it must return ASC_CB_KEEP from the callback.
+ * will be used by the client for I/O on the connected socket.
*
- * When client's callback is invoked with an error (ASC_CONNECTION_FAILED event),
- * the client has an opportunity to review the error (available in 'errno'), and
- * either abort the connection by returning ASC_CB_ABORT, or schedule a retry
- * by returning ASC_CB_RETRY from the callback. If client returns ASC_CB_ABORT
+ * When client's callback is invoked with an error (ASIO_STATE_FAILED event), the
+ * client has an opportunity to review the error (available in 'errno'), and
+ * either abort the connection by returning ASIO_ACTION_ABORT, or schedule a retry
+ * by returning ASIO_ACTION_RETRY from the callback. If client returns ASIO_ACTION_ABORT
* from the callback, the connector will stop connection attempts, and will
- * self-destruct. If ASC_CB_RETRY is returned from the callback, the connector
+ * self-destruct. If ASIO_ACTION_RETRY is returned from the callback, the connector
* will retry connection attempt after timeout that was set by the caller in the
* call to async_socket_connector_new routine.
*
- * When client's callback is invoked with ASC_CONNECTION_RETRY, the client has an
- * opportunity to cancel further connection attempts by returning ASC_CB_ABORT,
- * or it can allow another connection attempt by returning ASC_CB_RETRY.
+ * When client's callback is invoked with ASIO_STATE_RETRYING (indicating that
+ * connector is about to retry a connection attempt), the client has an opportunity
+ * to cancel further connection attempts by returning ASIO_ACTION_ABORT, or it
+ * can allow another connection attempt by returning ASIO_ACTION_RETRY.
*
* The client has no control over the lifespan of initialized connector instance.
* It always self-destructs after client's cllback returns with a status other
- * than ASC_CB_RETRY.
+ * than ASIO_ACTION_RETRY.
*/
/* Declares async socket connector descriptor. */
typedef struct AsyncSocketConnector AsyncSocketConnector;
-/* Enumerates connection events.
- * Values from this enum are passed to the callback that connector's client uses
- * to monitor connection status / progress.
- */
-typedef enum ASCEvent {
- /* Connection with the socket has been successfuly established. */
- ASC_CONNECTION_SUCCEEDED,
- /* A failure has occured while establising connection, with errno containing
- * the actual error. */
- ASC_CONNECTION_FAILED,
- /* Async socket connector is about to retry the connection. */
- ASC_CONNECTION_RETRY,
-} ASCEvent;
-
-/* Enumerates return values from the callback to the connector's client.
- */
-typedef enum ASCCbRes {
- /* Keep established connection. */
- ASC_CB_KEEP,
- /* Abort connection attempts. */
- ASC_CB_ABORT,
- /* Retry connection attempt. */
- ASC_CB_RETRY,
-} ASCCbRes;
-
-/* Enumerates values returned from the connector routine.
- */
-typedef enum ASCConnectRes {
- /* Connection has succeeded in the connector routine. */
- ASC_CONNECT_SUCCEEDED,
- /* Connection has failed in the connector routine. */
- ASC_CONNECT_FAILED,
- /* Connection is in progress, and will be completed asynchronously. */
- ASC_CONNECT_IN_PROGRESS,
-} ASCConnectRes;
-
/* Declares callback that connector's client uses to monitor connection
* status / progress.
* Param:
* opaque - An opaque pointer associated with the client.
- * connector - Connector instance for thecallback.
- * event - Event that has occured. If event is set to ASC_CONNECTION_FAILED,
+ * connector - AsyncSocketConnector instance.
+ * event - Event that has occurred. If event is set to ASIO_STATE_FAILED,
* errno contains connection error.
* Return:
- * One of ASCCbRes values.
+ * One of AsyncIOAction values.
*/
-typedef ASCCbRes (*asc_event_cb)(void* opaque,
- AsyncSocketConnector* connector,
- ASCEvent event);
+typedef AsyncIOAction (*asc_event_cb)(void* opaque,
+ AsyncSocketConnector* connector,
+ AsyncIOState event);
/* Creates and initializes AsyncSocketConnector instance.
* Param:
* address - Initialized socket address to connect to.
- * retry_to - Retry timeout in milliseconds.
+ * retry_to - Timeout to retry a failed connection attempt in milliseconds.
* cb, cb_opaque - Callback to invoke on connection events. This callback is
* required, and must not be NULL.
* Return:
* Initialized AsyncSocketConnector instance. Note that AsyncSocketConnector
* instance returned from this routine will be destroyed by the connector itself,
- * when its work on connecting to the socket is completed. Typically, the
- * connector wil destroy the descriptor after client's callback routine returns
- * with the status other than ASC_CB_RETRY.
+ * when its work on connecting to the socket is completed. Typically, connector
+ * will destroy its descriptor after client's callback routine returns with a
+ * status other than ASIO_ACTION_RETRY.
*/
extern AsyncSocketConnector* async_socket_connector_new(const SockAddress* address,
int retry_to,
@@ -133,21 +99,20 @@ extern AsyncSocketConnector* async_socket_connector_new(const SockAddress* addre
void* cb_opaque);
/* Initiates asynchronous connection.
+ * Note that connection result will be reported via callback set with the call to
+ * async_socket_connector_new routine.
* Param:
- * connector - Initialized AsyncSocketConnector instance.
- * Return:
- * Status indicating state of the connection: completed, failed, or in progress.
- * Note that the connector will always invoke a callback passed to the
- * async_socket_connector_new routine prior to exiting from this routine with
- * statuses other ASC_CONNECT_IN_PROGRESS.
+ * connector - Initialized AsyncSocketConnector instance. Note that this
+ * connector descriptor might be destroyed asynchronously, before this
+ * routine returns.
*/
-extern ASCConnectRes async_socket_connector_connect(AsyncSocketConnector* connector);
+extern void async_socket_connector_connect(AsyncSocketConnector* connector);
/* Pulls socket's file descriptor from the connector.
* This routine should be called from the connection callback on successful
- * connection status. This will provide the connector's client with operational
- * socket FD, and at the same time this will tell the connector not to close
- * the FD when connector descriptor gets destroyed.
+ * connection status. This will provide the connector's client with an operational
+ * socket FD, and at the same time this will tell the connector not to close the
+ * FD when connector descriptor gets destroyed.
* Param:
* connector - Initialized AsyncSocketConnector instance.
* Return:
diff --git a/android/async-socket.c b/android/async-socket.c
index 13e15ca..4be69f6 100644
--- a/android/async-socket.c
+++ b/android/async-socket.c
@@ -37,9 +37,6 @@
* Asynchronous Socket internal API declarations
*******************************************************************************/
-/* Asynchronous socket I/O (reader, or writer) descriptor. */
-typedef struct AsyncSocketIO AsyncSocketIO;
-
/* Gets socket's address string. */
static const char* _async_socket_string(AsyncSocket* as);
@@ -48,10 +45,11 @@ static Looper* _async_socket_get_looper(AsyncSocket* as);
/* Handler for the I/O time out.
* Param:
- * as - Asynchronous socket for the reader.
+ * as - Asynchronous socket for the I/O.
* asio - Desciptor for the timed out I/O.
*/
-static void _async_socket_io_timed_out(AsyncSocket* as, AsyncSocketIO* asio);
+static AsyncIOAction _async_socket_io_timed_out(AsyncSocket* as,
+ AsyncSocketIO* asio);
/********************************************************************************
* Asynchronous Socket Reader / Writer
@@ -72,10 +70,12 @@ struct AsyncSocketIO {
uint32_t to_transfer;
/* Bytes thransferred through the socket in this I/O. */
uint32_t transferred;
- /* I/O callbacks for this I/O. */
- const ASIOCb* io_cb;
+ /* I/O callback for this I/O. */
+ on_as_io_cb on_io;
/* I/O type selector: 1 - read, 0 - write. */
int is_io_read;
+ /* State of the I/O. */
+ AsyncIOState state;
};
/*
@@ -105,7 +105,7 @@ static void _on_async_socket_io_timed_out(void* opaque);
* as - Asynchronous socket for the I/O.
* is_io_read - I/O type selector: 1 - read, 0 - write.
* buffer, len - Reader / writer buffer address.
- * io_cb - Callbacks for this reader / writer.
+ * io_cb - Callback for this reader / writer.
* io_opaque - An opaque pointer associated with the I/O.
* deadline - Deadline to complete the I/O.
* Return:
@@ -116,7 +116,7 @@ _async_socket_rw_new(AsyncSocket* as,
int is_io_read,
void* buffer,
uint32_t len,
- const ASIOCb* io_cb,
+ on_as_io_cb io_cb,
void* io_opaque,
Duration deadline)
{
@@ -137,8 +137,9 @@ _async_socket_rw_new(AsyncSocket* as,
asio->buffer = (uint8_t*)buffer;
asio->to_transfer = len;
asio->transferred = 0;
- asio->io_cb = io_cb;
+ asio->on_io = io_cb;
asio->io_opaque = io_opaque;
+ asio->state = ASIO_STATE_QUEUED;
loopTimer_init(asio->timer, _async_socket_get_looper(as),
_on_async_socket_io_timed_out, asio);
@@ -168,7 +169,7 @@ _async_socket_io_destroy(AsyncSocketIO* asio)
* Param:
* as - Asynchronous socket for the reader.
* buffer, len - Reader's buffer.
- * io_cb - Lists reader's callbacks.
+ * io_cb - Reader's callback.
* reader_opaque - An opaque pointer associated with the reader.
* deadline - Deadline to complete the operation.
* Return:
@@ -178,7 +179,7 @@ static AsyncSocketIO*
_async_socket_reader_new(AsyncSocket* as,
void* buffer,
uint32_t len,
- const ASIOCb* io_cb,
+ on_as_io_cb io_cb,
void* reader_opaque,
Duration deadline)
{
@@ -191,7 +192,7 @@ _async_socket_reader_new(AsyncSocket* as,
* Param:
* as - Asynchronous socket for the writer.
* buffer, len - Writer's buffer.
- * io_cb - Lists writer's callbacks.
+ * io_cb - Writer's callback.
* writer_opaque - An opaque pointer associated with the writer.
* deadline - Deadline to complete the operation.
* Return:
@@ -201,7 +202,7 @@ static AsyncSocketIO*
_async_socket_writer_new(AsyncSocket* as,
const void* buffer,
uint32_t len,
- const ASIOCb* io_cb,
+ on_as_io_cb io_cb,
void* writer_opaque,
Duration deadline)
{
@@ -216,8 +217,76 @@ static void
_on_async_socket_io_timed_out(void* opaque)
{
AsyncSocketIO* const asio = (AsyncSocketIO*)opaque;
- _async_socket_io_timed_out(asio->as, asio);
- _async_socket_io_destroy(asio);
+ const AsyncIOAction action = _async_socket_io_timed_out(asio->as, asio);
+ if (action != ASIO_ACTION_RETRY) {
+ _async_socket_io_destroy(asio);
+ }
+}
+
+/********************************************************************************
+ * Public Asynchronous Socket I/O API
+ *******************************************************************************/
+
+AsyncSocket*
+async_socket_io_get_socket(const AsyncSocketIO* asio)
+{
+ return asio->as;
+}
+
+void
+async_socket_io_cancel_time_out(AsyncSocketIO* asio)
+{
+ loopTimer_stop(asio->timer);
+}
+
+void*
+async_socket_io_get_io_opaque(const AsyncSocketIO* asio)
+{
+ return asio->io_opaque;
+}
+
+void*
+async_socket_io_get_client_opaque(const AsyncSocketIO* asio)
+{
+ return async_socket_get_client_opaque(asio->as);
+}
+
+void*
+async_socket_io_get_buffer_info(const AsyncSocketIO* asio,
+ uint32_t* transferred,
+ uint32_t* to_transfer)
+{
+ if (transferred != NULL) {
+ *transferred = asio->transferred;
+ }
+ if (to_transfer != NULL) {
+ *to_transfer = asio->to_transfer;
+ }
+ return asio->buffer;
+}
+
+void*
+async_socket_io_get_buffer(const AsyncSocketIO* asio)
+{
+ return asio->buffer;
+}
+
+uint32_t
+async_socket_io_get_transferred(const AsyncSocketIO* asio)
+{
+ return asio->transferred;
+}
+
+uint32_t
+async_socket_io_get_to_transfer(const AsyncSocketIO* asio)
+{
+ return asio->to_transfer;
+}
+
+int
+async_socket_io_is_read(const AsyncSocketIO* asio)
+{
+ return asio->is_io_read;
}
/********************************************************************************
@@ -227,8 +296,8 @@ _on_async_socket_io_timed_out(void* opaque)
struct AsyncSocket {
/* TCP address for the socket. */
SockAddress address;
- /* Client callbacks for this socket. */
- const ASClientCb* client_cb;
+ /* Connection callback for this socket. */
+ on_as_connection_cb on_connection;
/* An opaque pointer associated with this socket by the client. */
void* client_opaque;
/* I/O looper for asynchronous I/O on the socket. */
@@ -353,7 +422,7 @@ _async_socket_remove_io(AsyncSocket* as,
* as - Initialized AsyncSocket instance.
* list_head, list_tail - Pointers to the list head and tail.
* Return:
- * Next I/O at the head of the list, or NULL if I/O list become empty.
+ * Next I/O at the head of the list, or NULL if I/O list became empty.
*/
static AsyncSocketIO*
_async_socket_advance_io(AsyncSocket* as,
@@ -375,7 +444,7 @@ _async_socket_advance_io(AsyncSocket* as,
* Param:
* as - Initialized AsyncSocket instance.
* Return:
- * Next reader at the head of the list, or NULL if reader list become empty.
+ * Next reader at the head of the list, or NULL if reader list became empty.
*/
static AsyncSocketIO*
_async_socket_advance_reader(AsyncSocket* as)
@@ -387,7 +456,7 @@ _async_socket_advance_reader(AsyncSocket* as)
* Param:
* as - Initialized AsyncSocket instance.
* Return:
- * Next writer at the head of the list, or NULL if writer list become empty.
+ * Next writer at the head of the list, or NULL if writer list became empty.
*/
static AsyncSocketIO*
_async_socket_advance_writer(AsyncSocket* as)
@@ -399,75 +468,58 @@ _async_socket_advance_writer(AsyncSocket* as)
* Param:
* as - Initialized AsyncSocket instance.
* asio - I/O to complete.
+ * Return:
+ * One of AsyncIOAction values.
*/
-static void
+static AsyncIOAction
_async_socket_complete_io(AsyncSocket* as, AsyncSocketIO* asio)
{
/* Stop the timer. */
loopTimer_stop(asio->timer);
- /* Report I/O completion. First report via I/O callback, and only if it is
- * not set, report via client callback. */
- if (asio->io_cb && asio->io_cb->on_completed) {
- asio->io_cb->on_completed(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer, asio->transferred);
- } else if (as->client_cb->io_cb && as->client_cb->io_cb->on_completed) {
- as->client_cb->io_cb->on_completed(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer,
- asio->transferred);
- }
+ return asio->on_io(asio->io_opaque, asio, ASIO_STATE_SUCCEEDED);
}
/* Timeouts an I/O.
* Param:
* as - Initialized AsyncSocket instance.
* asio - An I/O that has timed out.
+ * Return:
+ * One of AsyncIOAction values.
*/
-static void
+static AsyncIOAction
_async_socket_io_timed_out(AsyncSocket* as, AsyncSocketIO* asio)
{
- /* Remove the I/O from a list of active I/O. */
- if (asio->is_io_read) {
- _async_socket_remove_io(as, &as->readers_head, &as->readers_tail, asio);
- } else {
- _async_socket_remove_io(as, &as->writers_head, &as->writers_tail, asio);
+ /* Report to the client. */
+ const AsyncIOAction action = asio->on_io(asio->io_opaque, asio,
+ ASIO_STATE_TIMED_OUT);
+
+ /* Remove the I/O from a list of active I/O for actions other than retry. */
+ if (action != ASIO_ACTION_RETRY) {
+ if (asio->is_io_read) {
+ _async_socket_remove_io(as, &as->readers_head, &as->readers_tail, asio);
+ } else {
+ _async_socket_remove_io(as, &as->writers_head, &as->writers_tail, asio);
+ }
}
- /* Report I/O time out. First report it via I/O callbacks, and only if it is
- * not set, report it via client callbacks. */
- if (asio->io_cb && asio->io_cb->on_timed_out) {
- asio->io_cb->on_timed_out(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer,
- asio->transferred, asio->to_transfer);
- } else if (as->client_cb->io_cb && as->client_cb->io_cb->on_timed_out) {
- as->client_cb->io_cb->on_timed_out(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer,
- asio->transferred, asio->to_transfer);
- }
+ return action;
}
/* Cancels an I/O.
* Param:
* as - Initialized AsyncSocket instance.
* asio - An I/O to cancel.
+ * Return:
+ * One of AsyncIOAction values.
*/
-static void
+static AsyncIOAction
_async_socket_cancel_io(AsyncSocket* as, AsyncSocketIO* asio)
{
/* Stop the timer. */
loopTimer_stop(asio->timer);
- /* Report I/O cancellation. First report it via I/O callbacks, and only if it
- * is not set, report it via client callbacks. */
- if (asio->io_cb && asio->io_cb->on_cancelled) {
- asio->io_cb->on_cancelled(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer,
- asio->transferred, asio->to_transfer);
- } else if (as->client_cb->io_cb && as->client_cb->io_cb->on_cancelled) {
- as->client_cb->io_cb->on_cancelled(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer,
- asio->transferred, asio->to_transfer);
- }
+ return asio->on_io(asio->io_opaque, asio, ASIO_STATE_CANCELLED);
}
/* Reports an I/O failure.
@@ -475,25 +527,17 @@ _async_socket_cancel_io(AsyncSocket* as, AsyncSocketIO* asio)
* as - Initialized AsyncSocket instance.
* asio - An I/O that has failed. Can be NULL for general failures.
* failure - Failure (errno) that has occurred.
+ * Return:
+ * One of AsyncIOAction values.
*/
-static void
+static AsyncIOAction
_async_socket_io_failure(AsyncSocket* as, AsyncSocketIO* asio, int failure)
{
/* Stop the timer. */
loopTimer_stop(asio->timer);
- /* Report I/O failure. First report it via I/O callbacks, and only if it
- * is not set, report it via client callbacks. */
- if (asio && asio->io_cb && asio->io_cb->on_io_failure) {
- asio->io_cb->on_io_failure(as->client_opaque, as, asio->is_io_read,
- asio->io_opaque, asio->buffer,
- asio->transferred, asio->to_transfer, failure);
- } else if (as->client_cb->io_cb && as->client_cb->io_cb->on_io_failure) {
- as->client_cb->io_cb->on_io_failure(as->client_opaque, as,
- asio->is_io_read, asio->io_opaque,
- asio->buffer, asio->transferred,
- asio->to_transfer, failure);
- }
+ errno = failure;
+ return asio->on_io(asio->io_opaque, asio, ASIO_STATE_FAILED);
}
/* Cancels all the active socket readers.
@@ -505,6 +549,8 @@ _async_socket_cancel_readers(AsyncSocket* as)
{
while (as->readers_head != NULL) {
AsyncSocketIO* const to_cancel = _async_socket_pull_first_reader(as);
+ /* We ignore action returned from the cancellation callback, since we're
+ * in a disconnected state here. */
_async_socket_cancel_io(as, to_cancel);
_async_socket_io_destroy(to_cancel);
}
@@ -519,6 +565,8 @@ _async_socket_cancel_writers(AsyncSocket* as)
{
while (as->writers_head != NULL) {
AsyncSocketIO* const to_cancel = _async_socket_pull_first_writer(as);
+ /* We ignore action returned from the cancellation callback, since we're
+ * in a disconnected state here. */
_async_socket_cancel_io(as, to_cancel);
_async_socket_io_destroy(to_cancel);
}
@@ -607,7 +655,7 @@ _on_async_socket_disconnected(AsyncSocket* as)
{
/* Save error to restore it for the client's callback. */
const int save_errno = errno;
- ASConnectAction action = ASCA_ABORT;
+ AsyncIOAction action = ASIO_ACTION_ABORT;
D("Async socket '%s' is disconnected. Error %d -> %s",
_async_socket_string(as), errno, strerror(errno));
@@ -620,14 +668,11 @@ _on_async_socket_disconnected(AsyncSocket* as)
/* Restore errno, and invoke client's callback. */
errno = save_errno;
- action = as->client_cb->on_connection(as->client_opaque, as,
- ASCS_DISCONNECTED);
+ action = as->on_connection(as->client_opaque, as, ASIO_STATE_FAILED);
- if (action == ASCA_RETRY) {
+ if (action == ASIO_ACTION_RETRY) {
/* Client requested reconnection. */
- if (as->reconnect_to) {
- _async_socket_reconnect(as, as->reconnect_to);
- }
+ _async_socket_reconnect(as, as->reconnect_to);
}
}
@@ -636,14 +681,14 @@ _on_async_socket_disconnected(AsyncSocket* as)
* as - Initialized AsyncSocket instance.
* asio - Descriptor for the failed I/O. Can be NULL for general failures.
*/
-static void
+static AsyncIOAction
_on_async_socket_failure(AsyncSocket* as, AsyncSocketIO* asio)
{
- D("Async socket '%s' I/O failure %d: %s",
+ D("Async socket '%s' I/O failure: %d -> %s",
_async_socket_string(as), errno, strerror(errno));
/* Report the failure. */
- _async_socket_io_failure(as, asio, errno);
+ return _async_socket_io_failure(as, asio, errno);
}
/* A callback that is invoked when there is data available to read.
@@ -656,6 +701,8 @@ _on_async_socket_failure(AsyncSocket* as, AsyncSocketIO* asio)
static int
_on_async_socket_recv(AsyncSocket* as)
{
+ AsyncIOAction action;
+
/* Get current reader. */
AsyncSocketIO* const asr = as->readers_head;
if (asr == NULL) {
@@ -665,6 +712,29 @@ _on_async_socket_recv(AsyncSocket* as)
return 0;
}
+ /* Bump I/O state, and inform the client that I/O is in progress. */
+ if (asr->state == ASIO_STATE_QUEUED) {
+ asr->state = ASIO_STATE_STARTED;
+ } else {
+ asr->state = ASIO_STATE_CONTINUES;
+ }
+ action = asr->on_io(asr->io_opaque, asr, asr->state);
+ if (action == ASIO_ACTION_ABORT) {
+ D("Read is aborted by the client of async socket '%s'",
+ _async_socket_string(as));
+ /* Move on to the next reader. */
+ _async_socket_advance_reader(as);
+ _async_socket_io_destroy(asr);
+ /* Lets see if there are still active readers, and enable, or disable
+ * read I/O callback accordingly. */
+ if (as->readers_head != NULL) {
+ loopIo_wantRead(as->io);
+ } else {
+ loopIo_dontWantRead(as->io);
+ }
+ return 0;
+ }
+
/* Read next chunk of data. */
int res = socket_recv(as->fd, asr->buffer + asr->transferred,
asr->to_transfer - asr->transferred);
@@ -688,7 +758,21 @@ _on_async_socket_recv(AsyncSocket* as)
}
/* An I/O error. */
- _on_async_socket_failure(as, asr);
+ action = _on_async_socket_failure(as, asr);
+ if (action == ASIO_ACTION_ABORT) {
+ D("Read is aborted on failure by the client of async socket '%s'",
+ _async_socket_string(as));
+ /* Move on to the next reader. */
+ _async_socket_advance_reader(as);
+ _async_socket_io_destroy(asr);
+ /* Lets see if there are still active readers, and enable, or disable
+ * read I/O callback accordingly. */
+ if (as->readers_head != NULL) {
+ loopIo_wantRead(as->io);
+ } else {
+ loopIo_dontWantRead(as->io);
+ }
+ }
return -1;
}
@@ -724,6 +808,8 @@ _on_async_socket_recv(AsyncSocket* as)
static int
_on_async_socket_send(AsyncSocket* as)
{
+ AsyncIOAction action;
+
/* Get current writer. */
AsyncSocketIO* const asw = as->writers_head;
if (asw == NULL) {
@@ -733,6 +819,29 @@ _on_async_socket_send(AsyncSocket* as)
return 0;
}
+ /* Bump I/O state, and inform the client that I/O is in progress. */
+ if (asw->state == ASIO_STATE_QUEUED) {
+ asw->state = ASIO_STATE_STARTED;
+ } else {
+ asw->state = ASIO_STATE_CONTINUES;
+ }
+ action = asw->on_io(asw->io_opaque, asw, asw->state);
+ if (action == ASIO_ACTION_ABORT) {
+ D("Write is aborted by the client of async socket '%s'",
+ _async_socket_string(as));
+ /* Move on to the next reader. */
+ _async_socket_advance_reader(as);
+ _async_socket_io_destroy(asw);
+ /* Lets see if there are still active writers, and enable, or disable
+ * write I/O callback accordingly. */
+ if (as->writers_head != NULL) {
+ loopIo_wantWrite(as->io);
+ } else {
+ loopIo_dontWantWrite(as->io);
+ }
+ return 0;
+ }
+
/* Write next chunk of data. */
int res = socket_send(as->fd, asw->buffer + asw->transferred,
asw->to_transfer - asw->transferred);
@@ -756,7 +865,22 @@ _on_async_socket_send(AsyncSocket* as)
}
/* An I/O error. */
- _on_async_socket_failure(as, asw);
+ /* An I/O error. */
+ action = _on_async_socket_failure(as, asw);
+ if (action == ASIO_ACTION_ABORT) {
+ D("Write is aborted on failure by the client of async socket '%s'",
+ _async_socket_string(as));
+ /* Move on to the next reader. */
+ _async_socket_advance_reader(as);
+ _async_socket_io_destroy(asw);
+ /* Lets see if there are still active writers, and enable, or disable
+ * write I/O callback accordingly. */
+ if (as->writers_head != NULL) {
+ loopIo_wantWrite(as->io);
+ } else {
+ loopIo_dontWantWrite(as->io);
+ }
+ }
return -1;
}
@@ -813,51 +937,33 @@ _on_async_socket_io(void* opaque, int fd, unsigned events)
* connector - Connector that is used to connect this socket.
* event - Connection event.
* Return:
- * One of ASCCbRes values.
+ * One of AsyncIOAction values.
*/
-static ASCCbRes
+static AsyncIOAction
_on_connector_events(void* opaque,
AsyncSocketConnector* connector,
- ASCEvent event)
+ AsyncIOState event)
{
- ASConnectAction action;
- ASConnectStatus adsc_status;
+ AsyncIOAction action;
AsyncSocket* const as = (AsyncSocket*)opaque;
- /* Convert connector event into async socket connection event. */
- switch (event) {
- case ASC_CONNECTION_SUCCEEDED:
- /* Accept the connection. */
- adsc_status = ASCS_CONNECTED;
- as->fd = async_socket_connector_pull_fd(connector);
- loopIo_init(as->io, as->looper, as->fd, _on_async_socket_io, as);
- break;
-
- case ASC_CONNECTION_RETRY:
- adsc_status = ASCS_RETRY;
- break;
-
- case ASC_CONNECTION_FAILED:
- default:
- adsc_status = ASCS_FAILURE;
- break;
+ if (event == ASIO_STATE_SUCCEEDED) {
+ /* Accept the connection. */
+ as->fd = async_socket_connector_pull_fd(connector);
+ loopIo_init(as->io, as->looper, as->fd, _on_async_socket_io, as);
}
/* Invoke client's callback. */
- action = as->client_cb->on_connection(as->client_opaque, as, adsc_status);
- if (event == ASC_CONNECTION_SUCCEEDED && action != ASCA_KEEP) {
+ action = as->on_connection(as->client_opaque, as, event);
+ if (event == ASIO_STATE_SUCCEEDED && action != ASIO_ACTION_DONE) {
/* For whatever reason the client didn't want to keep this connection.
* Close it. */
+ D("Connection is discarded by a client of async socket '%s'",
+ _async_socket_string(as));
_async_socket_close_socket(as);
}
- if (action == ASCA_RETRY) {
- return ASC_CB_RETRY;
- } else if (action == ASCA_ABORT) {
- return ASC_CB_ABORT;
- } else {
- return ASC_CB_KEEP;
- }
+ return action;
}
/* Timer callback invoked to reconnect the lost connection.
@@ -879,12 +985,12 @@ _on_async_socket_reconnect(void* opaque)
AsyncSocket*
async_socket_new(int port,
int reconnect_to,
- const ASClientCb* client_cb,
+ on_as_connection_cb client_cb,
void* client_opaque)
{
AsyncSocket* as;
- if (client_cb == NULL || client_cb->on_connection == NULL) {
+ if (client_cb == NULL) {
E("Invalid client_cb parameter");
return NULL;
}
@@ -893,7 +999,7 @@ async_socket_new(int port,
as->fd = -1;
as->client_opaque = client_opaque;
- as->client_cb = client_cb;
+ as->on_connection = client_cb;
as->readers_head = as->readers_tail = NULL;
as->reconnect_to = reconnect_to;
sock_address_init_inet(&as->address, SOCK_ADDRESS_INET_LOOPBACK, port);
@@ -901,6 +1007,7 @@ async_socket_new(int port,
if (as->looper == NULL) {
E("Unable to create I/O looper for async socket '%s'",
_async_socket_string(as));
+ client_cb(client_opaque, as, ASIO_STATE_FAILED);
_async_socket_destroy(as);
return NULL;
}
@@ -909,15 +1016,16 @@ async_socket_new(int port,
return as;
}
-int
+void
async_socket_connect(AsyncSocket* as, int retry_to)
{
AsyncSocketConnector* const connector =
async_socket_connector_new(&as->address, retry_to, _on_connector_events, as);
- if (connector == NULL) {
- return -1;
+ if (connector != NULL) {
+ async_socket_connector_connect(connector);
+ } else {
+ as->on_connection(as->client_opaque, as, ASIO_STATE_FAILED);
}
- return (async_socket_connector_connect(connector) == ASC_CONNECT_FAILED) ? -1 : 0;
}
void
@@ -930,18 +1038,18 @@ async_socket_disconnect(AsyncSocket* as)
}
}
-int
+void
async_socket_reconnect(AsyncSocket* as, int retry_to)
{
_async_socket_cancel_all_io(as);
_async_socket_close_socket(as);
- return async_socket_connect(as, retry_to);
+ async_socket_connect(as, retry_to);
}
-int
+void
async_socket_read_abs(AsyncSocket* as,
void* buffer, uint32_t len,
- const ASIOCb* reader_cb,
+ on_as_io_cb reader_cb,
void* reader_opaque,
Duration deadline)
{
@@ -955,25 +1063,24 @@ async_socket_read_abs(AsyncSocket* as,
as->readers_tail = asr;
}
loopIo_wantRead(as->io);
- return 0;
}
-int
+void
async_socket_read_rel(AsyncSocket* as,
void* buffer, uint32_t len,
- const ASIOCb* reader_cb,
+ on_as_io_cb reader_cb,
void* reader_opaque,
int to)
{
const Duration dl = (to >= 0) ? looper_now(_async_socket_get_looper(as)) + to :
DURATION_INFINITE;
- return async_socket_read_abs(as, buffer, len, reader_cb, reader_opaque, dl);
+ async_socket_read_abs(as, buffer, len, reader_cb, reader_opaque, dl);
}
-int
+void
async_socket_write_abs(AsyncSocket* as,
const void* buffer, uint32_t len,
- const ASIOCb* writer_cb,
+ on_as_io_cb writer_cb,
void* writer_opaque,
Duration deadline)
{
@@ -987,16 +1094,29 @@ async_socket_write_abs(AsyncSocket* as,
as->writers_tail = asw;
}
loopIo_wantWrite(as->io);
- return 0;
}
-int async_socket_write_rel(AsyncSocket* as,
- const void* buffer, uint32_t len,
- const ASIOCb* writer_cb,
- void* writer_opaque,
- int to)
+void
+async_socket_write_rel(AsyncSocket* as,
+ const void* buffer, uint32_t len,
+ on_as_io_cb writer_cb,
+ void* writer_opaque,
+ int to)
{
const Duration dl = (to >= 0) ? looper_now(_async_socket_get_looper(as)) + to :
DURATION_INFINITE;
- return async_socket_write_abs(as, buffer, len, writer_cb, writer_opaque, dl);
+ async_socket_write_abs(as, buffer, len, writer_cb, writer_opaque, dl);
+}
+
+void*
+async_socket_get_client_opaque(const AsyncSocket* as)
+{
+ return as->client_opaque;
+}
+
+Duration
+async_socket_deadline(AsyncSocket* as, int rel)
+{
+ return (rel >= 0) ? looper_now(_async_socket_get_looper(as)) + rel :
+ DURATION_INFINITE;
}
diff --git a/android/async-socket.h b/android/async-socket.h
index 5b5d125..1402126 100644
--- a/android/async-socket.h
+++ b/android/async-socket.h
@@ -17,12 +17,14 @@
#ifndef ANDROID_ASYNC_SOCKET_H_
#define ANDROID_ASYNC_SOCKET_H_
+#include "android/async-io-common.h"
+
/*
- * Contains declaration of an API that encapsulates communication via
+ * Contains declaration of an API that encapsulates communication via an
* asynchronous socket.
*
- * This is pretty basic API that allows to asynchronously connect to a socket,
- * and perform asynchronous read from / write to the connected socket.
+ * This is pretty basic API that allows asynchronous connection to a socket,
+ * and asynchronous read from / write to the connected socket.
*
* Since all the operations (including connection) are asynchronous, all the
* operation results are reported back to the client of this API via set of
@@ -32,32 +34,8 @@
/* Declares asynchronous socket descriptor. */
typedef struct AsyncSocket AsyncSocket;
-/* Enumerates asynchronous socket connection statuses.
- * Values enumerated here are passed to the client's callback that was set to
- * monitor socket connection.
- */
-typedef enum ASConnectStatus {
- /* Socket has been connected. */
- ASCS_CONNECTED,
- /* Socket has been disconnected. */
- ASCS_DISCONNECTED,
- /* An error has occured while connecting to the socket. */
- ASCS_FAILURE,
- /* An attempt to retry connection is about to begin. */
- ASCS_RETRY,
-} ASConnectStatus;
-
-/* Enumerates values returned from the client's callback that was set to
- * monitor socket connection.
- */
-typedef enum ASConnectAction {
- /* Keep the connection. */
- ASCA_KEEP,
- /* Retry connection attempt. */
- ASCA_RETRY,
- /* Abort the connection. */
- ASCA_ABORT,
-} ASConnectAction;
+/* Asynchronous socket I/O (reader, or writer) descriptor. */
+typedef struct AsyncSocketIO AsyncSocketIO;
/* Defines client's callback set to monitor socket connection.
* Param:
@@ -65,216 +43,177 @@ typedef enum ASConnectAction {
* as - Initialized AsyncSocket instance.
* status - Socket connection status.
* Return:
- * One of the ASConnectAction values.
+ * One of the AsyncIOAction values.
*/
-typedef ASConnectAction (*on_as_connection_cb)(void* client_opaque,
- AsyncSocket* as,
- ASConnectStatus status);
+typedef AsyncIOAction (*on_as_connection_cb)(void* client_opaque,
+ AsyncSocket* as,
+ AsyncIOState status);
-/* Defines client's callback set to monitor socket I/O failures.
+/* Defines client's callback set to monitor I/O progress.
* Param:
- * client_opaque - An opaque pointer associated with the client.
- * as - Initialized AsyncSocket instance.
- * is_io_read - I/O type selector: 1 - read, 0 - write.
- * io_opaque - An opaque pointer associated with the I/O that has failed.
- * buffer - Address of the I/O buffer.
- * transferred - Number of bytes that were transferred before I/O has failed.
- * to_transfer - Number of bytes initially requested to transfer with the
- * failed I/O.
- * failure - Error that occured (errno value)
+ * io_opaque - An opaque pointer associated with the I/O.
+ * asio - Async I/O in progress.
+ * status - Status of the I/O.
+ * Return:
+ * One of the AsyncIOAction values.
*/
-typedef void (*on_as_io_failure_cb)(void* client_opaque,
- AsyncSocket* as,
- int is_io_read,
- void* io_opaque,
- void* buffer,
- uint32_t transferred,
- uint32_t to_transfer,
- int failure);
+typedef AsyncIOAction (*on_as_io_cb)(void* io_opaque,
+ AsyncSocketIO* asio,
+ AsyncIOState status);
-/* Defines client's callback invoked when I/O has been completed.
- * Param:
- * client_opaque - An opaque pointer associated with the client.
- * as - Initialized AsyncSocket instance.
- * is_io_read - I/O type selector: 1 - read, 0 - write.
- * io_opaque - An opaque pointer associated with the I/O that has been
- * completed.
- * buffer - Address of the I/O buffer.
- * transferred - Number of bytes that were transferred.
- */
-typedef void (*on_as_io_completed_cb)(void* client_opaque,
- AsyncSocket* as,
- int is_io_read,
- void* io_opaque,
- void* buffer,
- uint32_t transferred);
+/********************************************************************************
+ * AsyncSocketIO API
+ *******************************************************************************/
-/* Defines client's callback invoked when an I/O gets cancelled (due to a
- * disconnection, for instance).
- * Param:
- * client_opaque - An opaque pointer associated with the client.
- * as - Initialized AsyncSocket instance.
- * is_io_read - I/O type selector: 1 - read, 0 - write.
- * io_opaque - An opaque pointer associated with the I/O that has been
- * cancelled.
- * buffer - Address of the I/O buffer.
- * transferred - Number of bytes that were transferred before I/O has been
- * cancelled.
- * to_transfer - Number of bytes initially requested to transfer with the
- * cancelled I/O.
- */
-typedef void (*on_as_io_cancelled_cb)(void* client_opaque,
- AsyncSocket* as,
- int is_io_read,
- void* io_opaque,
- void* buffer,
- uint32_t transferred,
- uint32_t to_transfer);
+/* Gets AsyncSocket instance for an I/O */
+extern AsyncSocket* async_socket_io_get_socket(const AsyncSocketIO* asio);
+
+/* Cancels time out set for an I/O */
+extern void async_socket_io_cancel_time_out(AsyncSocketIO* asio);
+
+/* Gets an opaque pointer associated with an I/O */
+extern void* async_socket_io_get_io_opaque(const AsyncSocketIO* asio);
-/* Defines client's callback invoked when an I/O gets timed out.
+/* Gets an opaque pointer associated with the client that has requested I/O */
+extern void* async_socket_io_get_client_opaque(const AsyncSocketIO* asio);
+
+/* Gets I/O buffer information.
* Param:
- * client_opaque - An opaque pointer associated with the client.
- * as - Initialized AsyncSocket instance.
- * is_io_read - I/O type selector: 1 - read, 0 - write.
- * io_opaque - An opaque pointer associated with the I/O that has timed out.
- * buffer - Address of the I/O buffer.
- * transferred - Number of bytes that were transferred before I/O has timed out.
- * to_transfer - Number of bytes initially requested to transfer with the timed
- * out I/O.
+ * asio - I/O descriptor.
+ * transferred - Optional pointer to receive number of bytes transferred with
+ * this I/O. Can be NULL.
+ * to_transfer - Optional pointer to receive number of bytes requested to
+ * transfer with this I/O. Can be NULL.
+ * Return:
+ * I/O buffer.
*/
-typedef void (*on_as_io_timed_out_cb)(void* client_opaque,
- AsyncSocket* as,
- int is_io_read,
- void* io_opaque,
- void* buffer,
- uint32_t transferred,
- uint32_t to_transfer);
+extern void* async_socket_io_get_buffer_info(const AsyncSocketIO* asio,
+ uint32_t* transferred,
+ uint32_t* to_transfer);
-/* Lists asynchronous socket I/O callbacks. */
-typedef struct ASIOCb {
- on_as_io_completed_cb on_completed;
- on_as_io_cancelled_cb on_cancelled;
- on_as_io_timed_out_cb on_timed_out;
- on_as_io_failure_cb on_io_failure;
-} ASIOCb;
+/* Gets I/O buffer. */
+extern void* async_socket_io_get_buffer(const AsyncSocketIO* asio);
+/* Gets number of bytes transferred with this I/O. */
+extern uint32_t async_socket_io_get_transferred(const AsyncSocketIO* asio);
-/* Lists asynchronous socket client callbacks. */
-typedef struct ASClientCb {
- /* Connection callback (client must have one) */
- on_as_connection_cb on_connection;
- /* Optional client-level I/O callbacks. */
- const ASIOCb* io_cb;
-} ASClientCb;
+/* Gets number of bytes requested to transfer with this I/O. */
+extern uint32_t async_socket_io_get_to_transfer(const AsyncSocketIO* asio);
+
+/* Gets I/O type: read (returns 1), or write (returns 0). */
+extern int async_socket_io_is_read(const AsyncSocketIO* asio);
+
+/********************************************************************************
+ * AsyncSocket API
+ *******************************************************************************/
/* Creates an asynchronous socket descriptor.
* Param:
* port - TCP port to connect the socket to.
- * reconnect_to - Timeout before retrying to reconnect after disconnection.
- * 0 means "don't try to reconnect".
- * client_callbacks - Lists socket client callbacks.
+ * reconnect_to - Timeout before trying to reconnect after disconnection.
+ * connect_cb - Client callback to monitor connection state (must not be NULL).
* client_opaque - An opaque pointer to associate with the socket client.
* Return:
* Initialized AsyncSocket instance on success, or NULL on failure.
*/
extern AsyncSocket* async_socket_new(int port,
int reconnect_to,
- const ASClientCb* client_callbacks,
+ on_as_connection_cb connect_cb,
void* client_opaque);
/* Asynchronously connects to an asynchronous socket.
+ * Note that connection result will be reported via callback passed to the
+ * async_socket_new routine.
* Param:
* as - Initialized AsyncSocket instance.
* retry_to - Number of milliseconds to wait before retrying a failed
- * connection.
- * Return:
- * 0 on success, or -1 on failure. If this routine returns a failure, I/O
- * failure callback has not been invoked.
+ * connection attempt.
*/
-extern int async_socket_connect(AsyncSocket* as, int retry_to);
+extern void async_socket_connect(AsyncSocket* as, int retry_to);
/* Disconnects from an asynchronous socket.
+ * NOTE: AsyncSocket instance referenced in this call will be destroyed in this
+ * routine.
* Param:
* as - Initialized and connected AsyncSocket instance.
*/
extern void async_socket_disconnect(AsyncSocket* as);
/* Asynchronously reconnects to an asynchronous socket.
+ * Note that connection result will be reported via callback passed to the
+ * async_socket_new routine.
* Param:
* as - Initialized AsyncSocket instance.
- * retry_to - Number of milliseconds to wait before retrying to reconnect.
- * Return:
- * 0 on success, or -1 on failure. If this routine returns a failure, I/O
- * failure callback has not been invoked.
+ * retry_to - Number of milliseconds to wait before trying to reconnect.
*/
-extern int async_socket_reconnect(AsyncSocket* as, int retry_to);
+extern void async_socket_reconnect(AsyncSocket* as, int retry_to);
/* Asynchronously reads data from an asynchronous socket with a deadline.
* Param:
* as - Initialized and connected AsyncSocket instance.
* buffer, len - Buffer where to read data.
- * reader_cb - Lists reader's callbacks.
+ * reader_cb - Callback to monitor I/O progress (must not be NULL).
* reader_opaque - An opaque pointer associated with the reader.
* deadline - Deadline to complete the read.
- * Return:
- * 0 on success, or -1 on failure. If this routine returns a failure, I/O
- * failure callback has not been invoked.
*/
-extern int async_socket_read_abs(AsyncSocket* as,
- void* buffer, uint32_t len,
- const ASIOCb* reader_cb,
- void* reader_opaque,
- Duration deadline);
+extern void async_socket_read_abs(AsyncSocket* as,
+ void* buffer, uint32_t len,
+ on_as_io_cb reader_cb,
+ void* reader_opaque,
+ Duration deadline);
/* Asynchronously reads data from an asynchronous socket with a relative timeout.
* Param:
* as - Initialized and connected AsyncSocket instance.
* buffer, len - Buffer where to read data.
- * reader_cb - Lists reader's callbacks.
+ * reader_cb - Callback to monitor I/O progress (must not be NULL).
* reader_opaque - An opaque pointer associated with the reader.
* to - Milliseconds to complete the read. to < 0 indicates "no timeout"
- * Return:
- * 0 on success, or -1 on failure. If this routine returns a failure, I/O
- * failure callback has not been invoked.
*/
-extern int async_socket_read_rel(AsyncSocket* as,
- void* buffer, uint32_t len,
- const ASIOCb* reader_cb,
- void* reader_opaque,
- int to);
+extern void async_socket_read_rel(AsyncSocket* as,
+ void* buffer, uint32_t len,
+ on_as_io_cb reader_cb,
+ void* reader_opaque,
+ int to);
/* Asynchronously writes data to an asynchronous socket with a deadline.
* Param:
* as - Initialized and connected AsyncSocket instance.
* buffer, len - Buffer with writing data.
- * writer_cb - Lists writer's callbacks.
+ * writer_cb - Callback to monitor I/O progress (must not be NULL).
* writer_opaque - An opaque pointer associated with the writer.
* deadline - Deadline to complete the write.
- * Return:
- * 0 on success, or -1 on failure. If this routine returns a failure, I/O
- * failure callback has not been invoked.
*/
-extern int async_socket_write_abs(AsyncSocket* as,
- const void* buffer, uint32_t len,
- const ASIOCb* writer_cb,
- void* writer_opaque,
- Duration deadline);
+extern void async_socket_write_abs(AsyncSocket* as,
+ const void* buffer, uint32_t len,
+ on_as_io_cb writer_cb,
+ void* writer_opaque,
+ Duration deadline);
/* Asynchronously writes data to an asynchronous socket with a relative timeout.
* Param:
* as - Initialized and connected AsyncSocket instance.
* buffer, len - Buffer with writing data.
- * writer_cb - Lists writer's callbacks.
+ * writer_cb - Callback to monitor I/O progress (must not be NULL)
* writer_opaque - An opaque pointer associated with the writer.
* to - Milliseconds to complete the write. to < 0 indicates "no timeout"
+ */
+extern void async_socket_write_rel(AsyncSocket* as,
+ const void* buffer, uint32_t len,
+ on_as_io_cb writer_cb,
+ void* writer_opaque,
+ int to);
+
+/* Get a deadline for the given time interval relative to "now".
+ * Param:
+ * as - Initialized AsyncSocket instance.
+ * rel - Time interval. If < 0 an infinite duration will be returned.
* Return:
- * 0 on success, or -1 on failure. If this routine returns a failure, I/O
- * failure callback has not been invoked.
+ * A deadline for the given time interval relative to "now".
*/
-extern int async_socket_write_rel(AsyncSocket* as,
- const void* buffer, uint32_t len,
- const ASIOCb* writer_cb,
- void* writer_opaque,
- int to);
+extern Duration async_socket_deadline(AsyncSocket* as, int rel);
+
+/* Gets an opaque pointer associated with the socket's client */
+extern void* async_socket_get_client_opaque(const AsyncSocket* as);
#endif /* ANDROID_ASYNC_SOCKET_H_ */