blob: e34e1bbc2e2336e5ad83d242e7e11040425cedab [file] [log] [blame]
David 'Digit' Turner6d448802010-11-18 16:14:03 +01001/*
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/* An AsyncReader makes it easier to read a given number of bytes into
36 * a target buffer asynchronously. Usage is the following:
37 *
38 * 1/ setup the reader with asyncReader_init(ar, buffer, buffsize,io);
39 * 2/ call asyncReader_read(ar, io), where 'io' is a LoopIo whenever
40 * you can receive data, i.e. just after the init() or in your
41 * own callback.
42 */
43typedef struct {
44 uint8_t* buffer;
45 size_t buffsize;
46 size_t pos;
47} AsyncReader;
48
49/* Setup an ASyncReader, by giving the address of the read buffer,
50 * and the number of bytes we want to read.
51 *
52 * This also calls loopIo_wantRead(io) for you.
53 */
54void asyncReader_init(AsyncReader* ar,
55 void* buffer,
56 size_t buffsize,
57 LoopIo* io);
58
59/* Try to read data from 'io' and return the state of the read operation.
60 *
61 * Returns:
62 * ASYNC_COMPLETE: If the read operation was complete. This will also
63 * call loopIo_dontWantRead(io) for you.
64 *
65 * ASYNC_ERROR: If an error occured (see errno). The error will be
66 * ECONNRESET in case of disconnection.
67 *
68 * ASYNC_NEED_MORE: If there was not enough incoming data to complete
69 * the read (or if 'events' doesn't contain LOOP_IO_READ).
70 */
71AsyncStatus asyncReader_read(AsyncReader* ar,
72 LoopIo* io);
73
74/* An AsyncWriter is the counterpart of an AsyncReader, but for writing
75 * data to a file descriptor asynchronously.
76 */
77typedef struct {
78 const uint8_t* buffer;
79 size_t buffsize;
80 size_t pos;
81} AsyncWriter;
82
83/* Setup an ASyncReader, by giving the address of the read buffer,
84 * and the number of bytes we want to read.
85 *
86 * This also calls loopIo_wantWrite(io) for you.
87 */
88void asyncWriter_init(AsyncWriter* aw,
89 const void* buffer,
90 size_t buffsize,
91 LoopIo* io);
92
93/* Try to write data to 'io' and return the state of the write operation.
94 *
95 * Returns:
96 * ASYNC_COMPLETE: If the write operation was complete. This will also
97 * call loopIo_dontWantWrite(io) for you.
98 *
99 * ASYNC_ERROR: If an error occured (see errno). The error will be
100 * ECONNRESET in case of disconnection.
101 *
102 * ASYNC_NEED_MORE: If not all bytes could be sent yet (or if 'events'
103 * doesn't contain LOOP_IO_READ).
104 */
105AsyncStatus asyncWriter_write(AsyncWriter* aw,
106 LoopIo* io);
107
108
109/* An AsyncLineReader allows you to read one line of text asynchronously.
110 * The biggest difference with AsyncReader is that you don't know the line
111 * size in advance, so the object will read data byte-by-byte until it
112 * encounters a '\n'.
113 */
114typedef struct {
115 uint8_t* buffer;
116 size_t buffsize;
117 size_t pos;
118} AsyncLineReader;
119
120/* Setup an AsyncLineReader to read at most 'buffsize' characters (bytes)
121 * into 'buffer'. The reader will stop when it finds a '\n' which will be
122 * part of the buffer by default.
123 *
124 * NOTE: buffsize must be > 0. If not, asyncLineReader_getLine will return
125 * ASYNC_ERROR with errno == ENOMEM.
126 *
127 * buffsize must also sufficiently big to hold the final '\n'.
128 *
129 * Also calls loopIo_wantRead(io) for you.
130 */
131void asyncLineReader_init(AsyncLineReader* alr,
132 void* buffer,
133 size_t buffsize,
134 LoopIo* io);
135
136/* Try to read line characters from 'io'.
137 * Returns:
138 * ASYNC_COMPLETE: An end-of-line was detected, call asyncLineReader_getLine
139 * to extract the line content.
140 *
141 * ASYNC_ERROR: An error occured. Note that in case of disconnection,
142 * errno will be set to ECONNRESET, but you should be able
143 * to call asyncLineReader_getLine to read the partial line
144 * that was read.
145 *
146 * In case of overflow, errno will be set to ENOMEM.
147 *
148 * ASYNC_NEED_MORE: If there was not enough incoming data (or events
149 * does not contain LOOP_IO_READ).
150 */
151AsyncStatus asyncLineReader_read(AsyncLineReader* alr,
152 LoopIo* io);
153
154/* Return a pointer to the NON-ZERO-TERMINATED line characters, if any.
155 * If 'pLength" is not NULL, the function sets '*pLength' to the length
156 * in bytes of the line.
157 *
158 * Returns:
159 * NULL if 'buffsize' was initially 0, otherwise, a pointer to 'buffer'
160 * as passed in asyncLineReader_setup().
161 *
162 * NOTE: The data is *not* zero terminated, but its last character
163 * should be '\n' unless an error occured.
164 */
165const char* asyncLineReader_getLineRaw(AsyncLineReader* alr, int *pLength);
166
167/* Return a pointer to the ZERO-TERMINATED line, with final '\n' or '\r\n'
168 * stripped. This will be NULL in case of error though.
169 */
170const char* asyncLineReader_getLine(AsyncLineReader* alr);
171
172/* Asynchronous connection to a socket
173 */
174typedef struct {
175 int error;
176 int state;
177} AsyncConnector;
178
179AsyncStatus
180asyncConnector_init(AsyncConnector* ac,
181 const SockAddress* address,
182 LoopIo* io);
183
184AsyncStatus
185asyncConnector_run(AsyncConnector* ac, LoopIo* io);
186
187#endif /* ANDROID_ASYNC_UTILS_H */