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