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 "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 } AsyncLineReader; 141 142 /* Setup an AsyncLineReader to read at most 'buffsize' characters (bytes) 143 * into 'buffer'. The reader will stop when it finds a '\n' which will be 144 * part of the buffer by default. 145 * 146 * NOTE: buffsize must be > 0. If not, asyncLineReader_getLine will return 147 * ASYNC_ERROR with errno == ENOMEM. 148 * 149 * buffsize must also sufficiently big to hold the final '\n'. 150 * 151 * Also calls loopIo_wantRead(io) for you. 152 */ 153 void asyncLineReader_init(AsyncLineReader* alr, 154 void* buffer, 155 size_t buffsize, 156 LoopIo* io); 157 158 /* Try to read line characters from 'io'. 159 * Returns: 160 * ASYNC_COMPLETE: An end-of-line was detected, call asyncLineReader_getLine 161 * to extract the line content. 162 * 163 * ASYNC_ERROR: An error occured. Note that in case of disconnection, 164 * errno will be set to ECONNRESET, but you should be able 165 * to call asyncLineReader_getLine to read the partial line 166 * that was read. 167 * 168 * In case of overflow, errno will be set to ENOMEM. 169 * 170 * ASYNC_NEED_MORE: If there was not enough incoming data (or events 171 * does not contain LOOP_IO_READ). 172 */ 173 AsyncStatus asyncLineReader_read(AsyncLineReader* alr); 174 175 /* Return a pointer to the NON-ZERO-TERMINATED line characters, if any. 176 * If 'pLength" is not NULL, the function sets '*pLength' to the length 177 * in bytes of the line. 178 * 179 * Returns: 180 * NULL if 'buffsize' was initially 0, otherwise, a pointer to 'buffer' 181 * as passed in asyncLineReader_setup(). 182 * 183 * NOTE: The data is *not* zero terminated, but its last character 184 * should be '\n' unless an error occured. 185 */ 186 const char* asyncLineReader_getLineRaw(AsyncLineReader* alr, int *pLength); 187 188 /* Return a pointer to the ZERO-TERMINATED line, with final '\n' or '\r\n' 189 * stripped. This will be NULL in case of error though. 190 */ 191 const char* asyncLineReader_getLine(AsyncLineReader* alr); 192 193 /************************************************************************** 194 ************************************************************************** 195 ***** 196 ***** A S Y N C C O N N E C T O R 197 ***** 198 *****/ 199 200 /* Asynchronous connection to a socket 201 */ 202 typedef struct { 203 int error; 204 int state; 205 LoopIo* io; 206 } AsyncConnector; 207 208 AsyncStatus 209 asyncConnector_init(AsyncConnector* ac, 210 const SockAddress* address, 211 LoopIo* io); 212 213 AsyncStatus 214 asyncConnector_run(AsyncConnector* ac); 215 216 #endif /* ANDROID_ASYNC_UTILS_H */ 217