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 */
29typedef 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 */
50typedef 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 */
62void 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 */
79AsyncStatus  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 */
91typedef 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 */
103void 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 */
120AsyncStatus 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 */
135typedef 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 */
154void 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 */
164AINLINED void
165asyncLineReader_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 */
185AsyncStatus 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 */
198const 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 */
203const 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 */
214typedef struct {
215    int     error;
216    int     state;
217    LoopIo* io;
218} AsyncConnector;
219
220AsyncStatus
221asyncConnector_init(AsyncConnector*    ac,
222                    const SockAddress* address,
223                    LoopIo*            io);
224
225AsyncStatus
226asyncConnector_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 */
233int
234asyncConnector_stop(AsyncConnector* ac);
235
236#endif /* ANDROID_ASYNC_UTILS_H */
237