1 #include "sock_fd.h" |
|
2 |
|
3 #include <fcntl.h> |
|
4 #include <unistd.h> |
|
5 #include <assert.h> |
|
6 |
|
7 void sock_fd_event_handler (evutil_socket_t fd, short what, void *arg) |
|
8 { |
|
9 struct sock_fd *sock = arg; |
|
10 |
|
11 (void) fd; |
|
12 |
|
13 // invoke appropriate callback |
|
14 sock_stream_invoke_callbacks(SOCK_FD_BASE(sock), what); |
|
15 } |
|
16 |
|
17 err_t sock_fd_read (struct sock_stream *base_sock, void *buf, size_t *len, struct error_info *err) |
|
18 { |
|
19 struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd); |
|
20 int ret; |
|
21 |
|
22 // read(), and detect non-EAGAIN or EOF |
|
23 if ((ret = read(sock->fd, buf, *len)) < 0 && errno != EAGAIN) |
|
24 // unexpected error |
|
25 RETURN_SET_ERROR_ERRNO(err, ERR_READ); |
|
26 |
|
27 else if (ret == 0) |
|
28 // EOF |
|
29 return SET_ERROR(err, ERR_READ_EOF); |
|
30 |
|
31 |
|
32 if (ret < 0) { |
|
33 // EAGAIN -> zero bytes |
|
34 *len = 0; |
|
35 |
|
36 } else { |
|
37 // normal -> bytes read |
|
38 *len = ret; |
|
39 } |
|
40 |
|
41 // ok |
|
42 return SUCCESS; |
|
43 } |
|
44 |
|
45 err_t sock_fd_write (struct sock_stream *base_sock, const void *buf, size_t *len, struct error_info *err) |
|
46 { |
|
47 struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd); |
|
48 int ret; |
|
49 |
|
50 // write(), and detect non-EAGAIN or EOF |
|
51 if ((ret = write(sock->fd, buf, *len)) < 0 && errno != EAGAIN) |
|
52 // unexpected error |
|
53 RETURN_SET_ERROR_ERRNO(err, ERR_WRITE); |
|
54 |
|
55 else if (ret == 0) |
|
56 // EOF |
|
57 return SET_ERROR(err, ERR_WRITE_EOF); |
|
58 |
|
59 |
|
60 if (ret < 0) { |
|
61 // EAGAIN -> zero bytes |
|
62 *len = 0; |
|
63 |
|
64 } else { |
|
65 // normal -> bytes read |
|
66 *len = ret; |
|
67 } |
|
68 |
|
69 return SUCCESS; |
|
70 } |
|
71 |
|
72 err_t sock_fd_event_init (struct sock_stream *base_sock) |
|
73 { |
|
74 struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd); |
|
75 err_t err; |
|
76 |
|
77 // set nonblocking |
|
78 if ((err = sock_fd_set_nonblock(sock, 1))) |
|
79 return err; |
|
80 |
|
81 // add ourselves as the event handler |
|
82 if ((err = sock_fd_init_ev(sock, &sock_fd_event_handler, sock))) |
|
83 return err; |
|
84 |
|
85 // done |
|
86 return SUCCESS; |
|
87 } |
|
88 |
|
89 err_t sock_fd_event_enable (struct sock_stream *base_sock, short mask) |
|
90 { |
|
91 struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd); |
|
92 |
|
93 // implemented in sock_fd_add_event |
|
94 return sock_fd_enable_events(sock, mask); |
|
95 } |
|
96 |
|
97 void sock_fd_init (struct sock_fd *sock, int fd) |
|
98 { |
|
99 assert(!sock->ev_read && !sock->ev_write); |
|
100 |
|
101 // initialize |
|
102 sock->fd = fd; |
|
103 } |
|
104 |
|
105 err_t sock_fd_set_nonblock (struct sock_fd *sock, bool nonblock) |
|
106 { |
|
107 // fcntl it |
|
108 // XXX: maintain old flags? |
|
109 if (fcntl(sock->fd, F_SETFL, nonblock ? O_NONBLOCK : 0) < 0) |
|
110 RETURN_SET_ERROR_ERRNO(SOCK_FD_ERR(sock), ERR_FCNTL); |
|
111 |
|
112 // ok |
|
113 return SUCCESS; |
|
114 } |
|
115 |
|
116 err_t sock_fd_init_ev (struct sock_fd *sock, void (*ev_cb)(evutil_socket_t, short, void *), void *cb_arg) |
|
117 { |
|
118 // require valid fd |
|
119 assert(sock->fd >= 0); |
|
120 |
|
121 // this is initialization |
|
122 assert(sock->ev_read == NULL && sock->ev_write == NULL); |
|
123 |
|
124 // store |
|
125 sock->ev_cb = ev_cb; |
|
126 sock->ev_arg = cb_arg; |
|
127 |
|
128 // create new event |
|
129 if ((sock->ev_read = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL) |
|
130 return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_NEW); |
|
131 |
|
132 if ((sock->ev_write = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_WRITE, ev_cb, cb_arg)) == NULL) |
|
133 return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_NEW); |
|
134 |
|
135 // ok |
|
136 return SUCCESS; |
|
137 } |
|
138 |
|
139 err_t sock_fd_enable_events (struct sock_fd *sock, short mask) |
|
140 { |
|
141 // just add the appropraite events |
|
142 if (mask & EV_READ && event_add(sock->ev_read, NULL)) |
|
143 return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_ADD); |
|
144 |
|
145 if (mask & EV_WRITE && event_add(sock->ev_write, NULL)) |
|
146 return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_ADD); |
|
147 |
|
148 // done |
|
149 return SUCCESS; |
|
150 } |
|
151 |
|
152 static void sock_fd_free_ev (struct sock_fd *sock) |
|
153 { |
|
154 if (sock->ev_read) { |
|
155 event_free(sock->ev_read); |
|
156 |
|
157 sock->ev_read = NULL; |
|
158 } |
|
159 |
|
160 if (sock->ev_write) { |
|
161 event_free(sock->ev_write); |
|
162 |
|
163 sock->ev_write = NULL; |
|
164 } |
|
165 } |
|
166 |
|
167 void sock_fd_deinit_ev (struct sock_fd *sock) |
|
168 { |
|
169 sock_fd_free_ev(sock); |
|
170 sock->ev_cb = NULL; |
|
171 sock->ev_arg = NULL; |
|
172 } |
|
173 |
|
174 err_t sock_fd_set (struct sock_fd *sock, int fd) |
|
175 { |
|
176 // close the old one? |
|
177 if (sock->fd >= 0) |
|
178 // XXX: warn on errors |
|
179 close(sock->fd); |
|
180 |
|
181 // remove any old events |
|
182 sock_fd_free_ev(sock); |
|
183 |
|
184 // set the new one |
|
185 sock->fd = fd; |
|
186 |
|
187 // restore them |
|
188 if (sock->ev_cb) |
|
189 return sock_fd_init_ev(sock, sock->ev_cb, sock->ev_arg); |
|
190 |
|
191 // ok |
|
192 return SUCCESS; |
|
193 } |
|
194 |
|
195 err_t sock_fd_close (struct sock_fd *sock) |
|
196 { |
|
197 struct error_info *err = SOCK_FD_ERR(sock); |
|
198 |
|
199 // no errors yet |
|
200 RESET_ERROR(err); |
|
201 |
|
202 // must be connected |
|
203 assert(sock->fd >= 0); |
|
204 |
|
205 // kill any events |
|
206 sock_fd_deinit_ev(sock); |
|
207 |
|
208 // close the socket itself |
|
209 if (close(sock->fd)) |
|
210 SET_ERROR_ERRNO(err, ERR_CLOSE); |
|
211 |
|
212 // invalidate |
|
213 sock->fd = -1; |
|
214 |
|
215 return ERROR_CODE(err); |
|
216 } |
|
217 |
|