Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 225 lines (178 sloc) 4.859 kb
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
1 // atom.c
2 // Scott Bronson
3 // 22 Feb 2006
4
5
0d880c6 The select poller is now thread safe and I've stubbed out the beginnings...
Scott Bronson authored
6 // Some utility functions that are common to all IO Atom pollers
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
7
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <errno.h>
d65f89e Add mocked support for readv and writev. Support is still a little bugg...
Scott Bronson authored
11 #include <sys/uio.h> // for readv/writev
12
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
13 #include "atom.h"
b1af1dd Prepare for mock tests by moving io_read, io_write, io_connect, io_liste...
Scott Bronson authored
14 #include "poller.h"
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
15
16
17 /** Reads from the given io_atom.
18 *
19 * @param io The io_atom to read from.
20 * @param buf the buffer to fill with data
21 * @param cnt the number of bytes to read
22 * @param readlen returns the number of bytes you need to process.
7385ea3 Make io_read and io_write recognize the distinction between a closed
Scott Bronson authored
23 * If there was an error then readlen will always be zero.
24 * If readlen > 0 is returned, no error was reported.
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
25 *
26 * @returns 0 on success, or the error code in errno if there was
27 * an error. If there was an error but errno doesn't say what it was
7385ea3 Make io_read and io_write recognize the distinction between a closed
Scott Bronson authored
28 * then -1 is returned.
29 * EPIPE: means you hit EOF (file) or the remote peer closed its
30 * connection normally (pipe, socket).
31 * ECONNRESET: the connection was reset. Maybe the peer disappeared?
32 *
33 * This routine should be thread safe even though it appears to use the
34 * global variable ::errno. On a system with a threads
35 * library, errno should expand into a funtion that returns a per-thread
36 * errno value.
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
37 */
38
b1af1dd Prepare for mock tests by moving io_read, io_write, io_connect, io_liste...
Scott Bronson authored
39 int io_atom_read(struct io_poller *poller, io_atom *io, char *buf, size_t cnt, size_t *readlen)
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
40 {
41 ssize_t len;
42
43 *readlen = 0;
44 do {
45 len = read(io->fd, buf, cnt);
46 } while (errno == EINTR); // stupid posix
47
48 if(len > 0) {
49 // success!
50 *readlen = len;
51 return 0;
52 }
53
54 if(len == 0) {
55 // the remote has closed the connection.
56 return EPIPE;
57 }
58
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
59 #if EAGAIN != EWOULDBLOCK
60 if(errno == EWOULDBLOCK) errno = EAGAIN;
61 #endif
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
62
63 return errno ? errno : -1;
64 }
65
66
d65f89e Add mocked support for readv and writev. Support is still a little bugg...
Scott Bronson authored
67 int io_atom_readv(struct io_poller *poller, io_atom *io, const struct iovec *vec, int cnt, size_t *readlen)
68 {
69 ssize_t len;
70
71 *readlen = 0;
72 do {
73 len = readv(io->fd, vec, cnt);
74 } while (errno == EINTR); // stupid posix
75
76 if(len > 0) {
77 // success!
78 *readlen = len;
79 return 0;
80 }
81
82 if(len == 0) {
83 // the remote has closed the connection.
84 return EPIPE;
85 }
86
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
87 #if EAGAIN != EWOULDBLOCK
88 if(errno == EWOULDBLOCK) errno = EAGAIN;
89 #endif
d65f89e Add mocked support for readv and writev. Support is still a little bugg...
Scott Bronson authored
90
91 return errno ? errno : -1;
92 }
93
94
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
95 /**
96 * Writes to the given atom.
97 *
98 * You should always be able to write all data.
99 *
100 * @returns 0 on success, the error code if there was a failure.
101 *
cc8fe6b Try to ensure all calls return an error code.
Scott Bronson authored
102 * A return value of EPIPE means that the remote peer closed its
103 * connection. If it's a real EPIPE, your app will already have
104 * received a SIGPIPE.
105 *
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
106 * We treat handle the remote resetting the connection the same as
107 * it closing the connection. So, when errno is ECONNRESET, this
108 * routine will return EPIPE to tell you that the remote is gone.
109 * You don't need to worry about this: EPIPE means no more remote.
7385ea3 Make io_read and io_write recognize the distinction between a closed
Scott Bronson authored
110 *
111 * See io_read() for a description on errno and thread safety.
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
112 */
113
b1af1dd Prepare for mock tests by moving io_read, io_write, io_connect, io_liste...
Scott Bronson authored
114 int io_atom_write(struct io_poller *poller, io_atom *io, const char *buf, size_t cnt, size_t *wrlen)
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
115 {
116 ssize_t len;
117
118 *wrlen = 0;
119 do {
120 len = write(io->fd, buf, cnt);
121 } while(errno == EINTR);
122
123 if(len > 0) {
124 *wrlen = len;
125 return 0;
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
126 }
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
127
128 if(len < 0) {
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
129 #if EAGAIN != EWOULDBLOCK
130 if(errno == EWOULDBLOCK) errno = EAGAIN;
131 #endif
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
132 return errno ? errno : -1;
133 }
134
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
135 // nothing was written but there was no error?! This is an OS error right?
d65f89e Add mocked support for readv and writev. Support is still a little bugg...
Scott Bronson authored
136 return 0;
137 }
138
139
140 int io_atom_writev(struct io_poller *poller, io_atom *io, const struct iovec *vec, int cnt, size_t *wrlen)
141 {
142 ssize_t len;
143
144 *wrlen = 0;
145 do {
146 len = writev(io->fd, vec, cnt);
147 } while(errno == EINTR);
148
149 if(len > 0) {
150 *wrlen = len;
151 return 0;
152 }
153
154 if(len < 0) {
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
155 #if EAGAIN != EWOULDBLOCK
156 if(errno == EWOULDBLOCK) errno = EAGAIN;
157 #endif
d65f89e Add mocked support for readv and writev. Support is still a little bugg...
Scott Bronson authored
158 return errno ? errno : -1;
159 }
160
9c20a70 Make io_read and io_write return EAGAIN again, fix writev typo
Scott Bronson authored
161 // nothing was written but there was no error?!
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
162 return 0;
163 }
164
165
5642350 Mock tests actually work now, added io_close call.
Scott Bronson authored
166 int io_atom_close(struct io_poller *poller, io_atom *io)
167 {
168 int fd;
169
170 io_remove(poller, io);
171 fd = io->fd;
172 io->fd = -1;
a2515eb Minor change to make io_close more consistent.
Scott Bronson authored
173
174 if(fd < 0) {
175 return EBADF;
176 }
177
cc8fe6b Try to ensure all calls return an error code.
Scott Bronson authored
178 if(close(fd)) {
179 return errno ? errno : -1;
180 }
a2515eb Minor change to make io_close more consistent.
Scott Bronson authored
181
cc8fe6b Try to ensure all calls return an error code.
Scott Bronson authored
182 return 0;
5642350 Mock tests actually work now, added io_close call.
Scott Bronson authored
183 }
184
185
6f4e067 Initial checkin of the shared IO Atom code. It was written for gatekeep...
Scott Bronson authored
186 /**
187 * Converts a string into an integer.
188 *
189 * It is unfortunate that this routine has to be included
190 * in the core library but I don't know where else to put
191 * it...
192 *
193 * Unlinke the standard C routines,
194 * this routine returns an error if the conversion fails.
195 * C generally just gives you a garbage number.
196 *
197 * Also, unlinke the standard routine, the string must be
198 * null terminated and contain only the number.
199 *
200 * @returns 1 if the conversion was successful, 0 if not.
201 */
202
203 int io_safe_atoi(const char *str, int *num)
204 {
205 char *remainder;
206
207 if(*str == '\0') {
208 // blank string (strtol would parse this as "0").
209 return 0;
210 }
211
212 errno = 0;
213 *num = strtol(str, &remainder, 10);
214 if(errno) {
215 return 0;
216 }
217
218 if(*remainder != '\0') {
219 return 0;
220 }
221
222 return 1;
223 }
224
Something went wrong with that request. Please try again.