Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #ifndef ANDROID_ASYNC_UTILS_H
     17 #define ANDROID_ASYNC_UTILS_H
     18 
     19 #include "android/looper.h"
     20 #include "android/sockets.h"
     21 
     22 /* A set of useful data types to perform asynchronous operations.
     23  *
     24  * IMPORTANT NOTE:
     25  *    In case of network disconnection, read() and write() just return 0
     26  *    the first time they are called. As a convenience, these functions
     27  *    will return ASYNC_ERROR and set 'errno' to ECONNRESET instead.
     28  */
     29 typedef enum {
     30     ASYNC_COMPLETE = 0,   /* asynchronous operation completed */
     31     ASYNC_ERROR,          /* an error occurred, look at errno */
     32     ASYNC_NEED_MORE       /* more data is needed, try again later */
     33 } AsyncStatus;
     34 
     35 /**************************************************************************
     36  **************************************************************************
     37  *****
     38  *****  A S Y N C   R E A D E R
     39  *****
     40  *****/
     41 
     42 /* An AsyncReader makes it easier to read a given number of bytes into
     43  * a target buffer asynchronously. Usage is the following:
     44  *
     45  * 1/ setup the reader with asyncReader_init(ar, buffer, buffsize,io);
     46  * 2/ call asyncReader_read(ar, io), where 'io' is a LoopIo whenever
     47  *    you can receive data, i.e. just after the init() or in your
     48  *    own callback.
     49  */
     50 typedef struct {
     51     uint8_t*  buffer;
     52     size_t    buffsize;
     53     size_t    pos;
     54     LoopIo*   io;
     55 } AsyncReader;
     56 
     57 /* Setup an ASyncReader, by giving the address of the read buffer,
     58  * and the number of bytes we want to read.
     59  *
     60  * This also calls loopIo_wantRead(io) for you.
     61  */
     62 void asyncReader_init(AsyncReader* ar,
     63                       void*        buffer,
     64                       size_t       buffsize,
     65                       LoopIo*      io);
     66 
     67 /* Try to read data from 'io' and return the state of the read operation.
     68  *
     69  * Returns:
     70  *    ASYNC_COMPLETE: If the read operation was complete. This will also
     71  *                    call loopIo_dontWantRead(io) for you.
     72  *
     73  *    ASYNC_ERROR: If an error occured (see errno). The error will be
     74  *                 ECONNRESET in case of disconnection.
     75  *
     76  *    ASYNC_NEED_MORE: If there was not enough incoming data to complete
     77  *                     the read (or if 'events' doesn't contain LOOP_IO_READ).
     78  */
     79 AsyncStatus  asyncReader_read(AsyncReader*  ar);
     80 
     81 /**************************************************************************
     82  **************************************************************************
     83  *****
     84  *****  A S Y N C   W R I T E R
     85  *****
     86  *****/
     87 
     88 /* An AsyncWriter is the counterpart of an AsyncReader, but for writing
     89  * data to a file descriptor asynchronously.
     90  */
     91 typedef struct {
     92     const uint8_t* buffer;
     93     size_t         buffsize;
     94     size_t         pos;
     95     LoopIo*        io;
     96 } AsyncWriter;
     97 
     98 /* Setup an ASyncWriter, by giving the address of the write buffer,
     99  * and the number of bytes we want to write.
    100  *
    101  * This also calls loopIo_wantWrite(io) for you.
    102  */
    103 void asyncWriter_init(AsyncWriter*  aw,
    104                       const void*   buffer,
    105                       size_t        buffsize,
    106                       LoopIo*       io);
    107 
    108 /* Try to write data to 'io' and return the state of the write operation.
    109  *
    110  * Returns:
    111  *    ASYNC_COMPLETE: If the write operation was complete. This will also
    112  *                    call loopIo_dontWantWrite(io) for you.
    113  *
    114  *    ASYNC_ERROR: If an error occured (see errno). The error will be
    115  *                 ECONNRESET in case of disconnection.
    116  *
    117  *    ASYNC_NEED_MORE: If not all bytes could be sent yet (or if 'events'
    118  *                     doesn't contain LOOP_IO_WRITE).
    119  */
    120 AsyncStatus asyncWriter_write(AsyncWriter* aw);
    121 
    122 
    123 /**************************************************************************
    124  **************************************************************************
    125  *****
    126  *****  A S Y N C   L I N E   R E A D E R
    127  *****
    128  *****/
    129 
    130 /* An AsyncLineReader allows you to read one line of text asynchronously.
    131  * The biggest difference with AsyncReader is that you don't know the line
    132  * size in advance, so the object will read data byte-by-byte until it
    133  * encounters a '\n'.
    134  */
    135 typedef struct {
    136     uint8_t*  buffer;
    137     size_t    buffsize;
    138     size_t    pos;
    139     LoopIo*   io;
    140     char      eol;
    141 } AsyncLineReader;
    142 
    143 /* Setup an AsyncLineReader to read at most 'buffsize' characters (bytes)
    144  * into 'buffer'. The reader will stop when it finds a '\n' which will be
    145  * part of the buffer by default.
    146  *
    147  * NOTE: buffsize must be > 0. If not, asyncLineReader_getLine will return
    148  *       ASYNC_ERROR with errno == ENOMEM.
    149  *
    150  *        buffsize must also sufficiently big to hold the final '\n'.
    151  *
    152  * Also calls loopIo_wantRead(io) for you.
    153  */
    154 void asyncLineReader_init(AsyncLineReader* alr,
    155                           void*            buffer,
    156                           size_t           buffsize,
    157                           LoopIo*          io);
    158 
    159 /* Sets line terminator character for the reader.
    160  * By default, asyncLineReader_init will set EOL to be '\n'. Sometimes it's more
    161  * convenient to have '\0' as line terminator, so "line" reader easily becomes
    162  * a "string" reader.
    163  */
    164 AINLINED void
    165 asyncLineReader_setEOL(AsyncLineReader* alr, char eol)
    166 {
    167     alr->eol = eol;
    168 }
    169 
    170 /* Try to read line characters from 'io'.
    171  * Returns:
    172  *    ASYNC_COMPLETE: An end-of-line was detected, call asyncLineReader_getLine
    173  *                    to extract the line content.
    174  *
    175  *    ASYNC_ERROR: An error occured. Note that in case of disconnection,
    176  *                 errno will be set to ECONNRESET, but you should be able
    177  *                 to call asyncLineReader_getLine to read the partial line
    178  *                 that was read.
    179  *
    180  *                 In case of overflow, errno will be set to ENOMEM.
    181  *
    182  *    ASYNC_NEED_MORE: If there was not enough incoming data (or events
    183  *                     does not contain LOOP_IO_READ).
    184  */
    185 AsyncStatus asyncLineReader_read(AsyncLineReader* alr);
    186 
    187 /* Return a pointer to the NON-ZERO-TERMINATED line characters, if any.
    188  * If 'pLength" is not NULL, the function sets '*pLength' to the length
    189  * in bytes of the line.
    190  *
    191  * Returns:
    192  *    NULL if 'buffsize' was initially 0, otherwise, a pointer to 'buffer'
    193  *    as passed in asyncLineReader_setup().
    194  *
    195  *    NOTE: The data is *not* zero terminated, but its last character
    196  *           should be '\n' unless an error occured.
    197  */
    198 const char* asyncLineReader_getLineRaw(AsyncLineReader* alr, int *pLength);
    199 
    200 /* Return a pointer to the ZERO-TERMINATED line, with final '\n' or '\r\n'
    201  * stripped. This will be NULL in case of error though.
    202  */
    203 const char* asyncLineReader_getLine(AsyncLineReader* alr);
    204 
    205 /**************************************************************************
    206  **************************************************************************
    207  *****
    208  *****  A S Y N C   C O N N E C T O R
    209  *****
    210  *****/
    211 
    212 /* Asynchronous connection to a socket
    213  */
    214 typedef struct {
    215     int     error;
    216     int     state;
    217     LoopIo* io;
    218 } AsyncConnector;
    219 
    220 AsyncStatus
    221 asyncConnector_init(AsyncConnector*    ac,
    222                     const SockAddress* address,
    223                     LoopIo*            io);
    224 
    225 AsyncStatus
    226 asyncConnector_run(AsyncConnector* ac);
    227 
    228 /* Stops connection in progress.
    229  * Return:
    230  *  0 if connection in progress has been stopped, or -1 if no connection has been
    231  *  in progress.
    232  */
    233 int
    234 asyncConnector_stop(AsyncConnector* ac);
    235 
    236 #endif /* ANDROID_ASYNC_UTILS_H */
    237