| /* |
| * Copyright (C) 2010 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_UTILS_H |
| #define ANDROID_ASYNC_UTILS_H |
| |
| #include "android/looper.h" |
| #include "sockets.h" |
| |
| /* A set of useful data types to perform asynchronous operations. |
| * |
| * IMPORTANT NOTE: |
| * In case of network disconnection, read() and write() just return 0 |
| * the first time they are called. As a convenience, these functions |
| * will return ASYNC_ERROR and set 'errno' to ECONNRESET instead. |
| */ |
| typedef enum { |
| ASYNC_COMPLETE = 0, /* asynchronous operation completed */ |
| ASYNC_ERROR, /* an error occurred, look at errno */ |
| ASYNC_NEED_MORE /* more data is needed, try again later */ |
| } AsyncStatus; |
| |
| /************************************************************************** |
| ************************************************************************** |
| ***** |
| ***** A S Y N C R E A D E R |
| ***** |
| *****/ |
| |
| /* An AsyncReader makes it easier to read a given number of bytes into |
| * a target buffer asynchronously. Usage is the following: |
| * |
| * 1/ setup the reader with asyncReader_init(ar, buffer, buffsize,io); |
| * 2/ call asyncReader_read(ar, io), where 'io' is a LoopIo whenever |
| * you can receive data, i.e. just after the init() or in your |
| * own callback. |
| */ |
| typedef struct { |
| uint8_t* buffer; |
| size_t buffsize; |
| size_t pos; |
| LoopIo* io; |
| } AsyncReader; |
| |
| /* Setup an ASyncReader, by giving the address of the read buffer, |
| * and the number of bytes we want to read. |
| * |
| * This also calls loopIo_wantRead(io) for you. |
| */ |
| void asyncReader_init(AsyncReader* ar, |
| void* buffer, |
| size_t buffsize, |
| LoopIo* io); |
| |
| /* Try to read data from 'io' and return the state of the read operation. |
| * |
| * Returns: |
| * ASYNC_COMPLETE: If the read operation was complete. This will also |
| * call loopIo_dontWantRead(io) for you. |
| * |
| * ASYNC_ERROR: If an error occured (see errno). The error will be |
| * ECONNRESET in case of disconnection. |
| * |
| * ASYNC_NEED_MORE: If there was not enough incoming data to complete |
| * the read (or if 'events' doesn't contain LOOP_IO_READ). |
| */ |
| AsyncStatus asyncReader_read(AsyncReader* ar); |
| |
| /************************************************************************** |
| ************************************************************************** |
| ***** |
| ***** A S Y N C W R I T E R |
| ***** |
| *****/ |
| |
| /* An AsyncWriter is the counterpart of an AsyncReader, but for writing |
| * data to a file descriptor asynchronously. |
| */ |
| typedef struct { |
| const uint8_t* buffer; |
| size_t buffsize; |
| size_t pos; |
| LoopIo* io; |
| } AsyncWriter; |
| |
| /* Setup an ASyncWriter, by giving the address of the write buffer, |
| * and the number of bytes we want to write. |
| * |
| * This also calls loopIo_wantWrite(io) for you. |
| */ |
| void asyncWriter_init(AsyncWriter* aw, |
| const void* buffer, |
| size_t buffsize, |
| LoopIo* io); |
| |
| /* Try to write data to 'io' and return the state of the write operation. |
| * |
| * Returns: |
| * ASYNC_COMPLETE: If the write operation was complete. This will also |
| * call loopIo_dontWantWrite(io) for you. |
| * |
| * ASYNC_ERROR: If an error occured (see errno). The error will be |
| * ECONNRESET in case of disconnection. |
| * |
| * ASYNC_NEED_MORE: If not all bytes could be sent yet (or if 'events' |
| * doesn't contain LOOP_IO_WRITE). |
| */ |
| AsyncStatus asyncWriter_write(AsyncWriter* aw); |
| |
| |
| /************************************************************************** |
| ************************************************************************** |
| ***** |
| ***** A S Y N C L I N E R E A D E R |
| ***** |
| *****/ |
| |
| /* An AsyncLineReader allows you to read one line of text asynchronously. |
| * The biggest difference with AsyncReader is that you don't know the line |
| * size in advance, so the object will read data byte-by-byte until it |
| * encounters a '\n'. |
| */ |
| typedef struct { |
| uint8_t* buffer; |
| size_t buffsize; |
| size_t pos; |
| LoopIo* io; |
| char eol; |
| } AsyncLineReader; |
| |
| /* Setup an AsyncLineReader to read at most 'buffsize' characters (bytes) |
| * into 'buffer'. The reader will stop when it finds a '\n' which will be |
| * part of the buffer by default. |
| * |
| * NOTE: buffsize must be > 0. If not, asyncLineReader_getLine will return |
| * ASYNC_ERROR with errno == ENOMEM. |
| * |
| * buffsize must also sufficiently big to hold the final '\n'. |
| * |
| * Also calls loopIo_wantRead(io) for you. |
| */ |
| void asyncLineReader_init(AsyncLineReader* alr, |
| void* buffer, |
| size_t buffsize, |
| LoopIo* io); |
| |
| /* Sets line terminator character for the reader. |
| * By default, asyncLineReader_init will set EOL to be '\n'. Sometimes it's more |
| * convenient to have '\0' as line terminator, so "line" reader easily becomes |
| * a "string" reader. |
| */ |
| AINLINED void |
| asyncLineReader_setEOL(AsyncLineReader* alr, char eol) |
| { |
| alr->eol = eol; |
| } |
| |
| /* Try to read line characters from 'io'. |
| * Returns: |
| * ASYNC_COMPLETE: An end-of-line was detected, call asyncLineReader_getLine |
| * to extract the line content. |
| * |
| * ASYNC_ERROR: An error occured. Note that in case of disconnection, |
| * errno will be set to ECONNRESET, but you should be able |
| * to call asyncLineReader_getLine to read the partial line |
| * that was read. |
| * |
| * In case of overflow, errno will be set to ENOMEM. |
| * |
| * ASYNC_NEED_MORE: If there was not enough incoming data (or events |
| * does not contain LOOP_IO_READ). |
| */ |
| AsyncStatus asyncLineReader_read(AsyncLineReader* alr); |
| |
| /* Return a pointer to the NON-ZERO-TERMINATED line characters, if any. |
| * If 'pLength" is not NULL, the function sets '*pLength' to the length |
| * in bytes of the line. |
| * |
| * Returns: |
| * NULL if 'buffsize' was initially 0, otherwise, a pointer to 'buffer' |
| * as passed in asyncLineReader_setup(). |
| * |
| * NOTE: The data is *not* zero terminated, but its last character |
| * should be '\n' unless an error occured. |
| */ |
| const char* asyncLineReader_getLineRaw(AsyncLineReader* alr, int *pLength); |
| |
| /* Return a pointer to the ZERO-TERMINATED line, with final '\n' or '\r\n' |
| * stripped. This will be NULL in case of error though. |
| */ |
| const char* asyncLineReader_getLine(AsyncLineReader* alr); |
| |
| /************************************************************************** |
| ************************************************************************** |
| ***** |
| ***** A S Y N C C O N N E C T O R |
| ***** |
| *****/ |
| |
| /* Asynchronous connection to a socket |
| */ |
| typedef struct { |
| int error; |
| int state; |
| LoopIo* io; |
| } AsyncConnector; |
| |
| AsyncStatus |
| asyncConnector_init(AsyncConnector* ac, |
| const SockAddress* address, |
| LoopIo* io); |
| |
| AsyncStatus |
| asyncConnector_run(AsyncConnector* ac); |
| |
| #endif /* ANDROID_ASYNC_UTILS_H */ |