blob: 93148c1aa83aaea1ada0a43d64620c69f57c951b [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
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +010035/**************************************************************************
36 **************************************************************************
37 *****
38 ***** A S Y N C R E A D E R
39 *****
40 *****/
41
David 'Digit' Turner6d448802010-11-18 16:14:03 +010042/* 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;
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +010054 LoopIo* io;
David 'Digit' Turner6d448802010-11-18 16:14:03 +010055} 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 */
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +010079AsyncStatus asyncReader_read(AsyncReader* ar);
80
81/**************************************************************************
82 **************************************************************************
83 *****
84 ***** A S Y N C W R I T E R
85 *****
86 *****/
David 'Digit' Turner6d448802010-11-18 16:14:03 +010087
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;
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +010095 LoopIo* io;
David 'Digit' Turner6d448802010-11-18 16:14:03 +010096} AsyncWriter;
97
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080098/* Setup an ASyncWriter, by giving the address of the write buffer,
99 * and the number of bytes we want to write.
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100100 *
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'
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800118 * doesn't contain LOOP_IO_WRITE).
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100119 */
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100120AsyncStatus asyncWriter_write(AsyncWriter* aw);
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100121
122
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100123/**************************************************************************
124 **************************************************************************
125 *****
126 ***** A S Y N C L I N E R E A D E R
127 *****
128 *****/
129
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100130/* 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;
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100139 LoopIo* io;
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100140} 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 */
153void 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 */
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100173AsyncStatus asyncLineReader_read(AsyncLineReader* alr);
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100174
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 */
186const 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 */
191const char* asyncLineReader_getLine(AsyncLineReader* alr);
192
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100193/**************************************************************************
194 **************************************************************************
195 *****
196 ***** A S Y N C C O N N E C T O R
197 *****
198 *****/
199
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100200/* Asynchronous connection to a socket
201 */
202typedef struct {
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100203 int error;
204 int state;
205 LoopIo* io;
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100206} AsyncConnector;
207
208AsyncStatus
209asyncConnector_init(AsyncConnector* ac,
210 const SockAddress* address,
211 LoopIo* io);
212
213AsyncStatus
David 'Digit' Turnerf9e333a2011-03-17 14:57:51 +0100214asyncConnector_run(AsyncConnector* ac);
David 'Digit' Turner6d448802010-11-18 16:14:03 +0100215
216#endif /* ANDROID_ASYNC_UTILS_H */