aboutsummaryrefslogtreecommitdiffstats
path: root/android/async-socket-connector.c
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2012-04-02 07:48:19 -0700
committerVladimir Chtchetkine <vchtchetkine@google.com>2012-04-02 07:48:19 -0700
commit6dc5c2cef91004488f04fc6e9c0946f6d3a29705 (patch)
tree41fdf1c93fef544aea1a08a5066dbb3f26df6351 /android/async-socket-connector.c
parenta7383ef4eb8d3863c8d582ea0d6b2ddb42125cba (diff)
downloadexternal_qemu-6dc5c2cef91004488f04fc6e9c0946f6d3a29705.zip
external_qemu-6dc5c2cef91004488f04fc6e9c0946f6d3a29705.tar.gz
external_qemu-6dc5c2cef91004488f04fc6e9c0946f6d3a29705.tar.bz2
Refactor asynchronous socket APIs
The initial implementation was a bit too complex in two ways: 1. Each component (the connector, and async socket) had its own set of state and action enums, which was confusing, required value translation, and was not really needed. So, all these enums have been combined into two common enums that are now declared in android/async-io-common.h 2. Too many callbacks, which really complicated implementation of the clients. It is much more efficient to have just two callbacks (one to monitor connection, and another to monitor I/O), letting the client to dispatch on particular event (success/timeout/etc.) This CL fixes these two issues. Change-Id: I545c93dee2e9e9c72c1d25e6cd218c8680933ee3
Diffstat (limited to 'android/async-socket-connector.c')
-rw-r--r--android/async-socket-connector.c121
1 files changed, 63 insertions, 58 deletions
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