Lines Matching full:io

1 /*	$OpenBSD: io.c,v 1.1.1.1 2018/04/27 16:14:36 eric Exp $	*/
32 #include "io.h"
58 struct io { struct
61 void (*cb)(struct io*, int, void *); argument
77 static void io_reload(struct io *); argument
78 static void io_reset(struct io *, short, void (*)(int, short, void*));
79 static void io_frame_enter(const char *, struct io *, int);
80 static void io_frame_leave(struct io *);
81 static void io_hold(struct io *);
82 static void io_release(struct io *);
83 static void io_callback(struct io*, int);
86 static int io_connect_next(struct io *);
95 static void io_reload_tls(struct io *io);
98 static struct io *current = NULL;
111 #define IO_READING(io) (((io)->flags & IO_RW) != IO_WRITE) argument
112 #define IO_WRITING(io) (((io)->flags & IO_RW) != IO_READ) argument
121 io_strio(struct io *io) in io_strio() argument
128 if (io->tls) { in io_strio()
130 SSL_get_version(io->tls), in io_strio()
131 SSL_get_cipher_name(io->tls), in io_strio()
132 SSL_get_cipher_bits(io->tls, NULL)); in io_strio()
136 "<io:%p st=%s, fd=%d to=%d fl=%s%s ib=%zu ob=%zu>", in io_strio()
137 io, states[io->state], io->sock, io->timeout, in io_strio()
138 io_strflags(io->flags), ssl, io_datalen(io), io_queued(io)); in io_strio()
173 struct io *
176 struct io *io; in io_new() local
178 io = calloc(1, sizeof(*io)); in io_new()
179 if (io == NULL) in io_new()
182 iobuf_init(&io->iobuf, 0, 0); in io_new()
183 io->sock = -1; in io_new()
184 io->timeout = -1; in io_new()
186 return io; in io_new()
190 io_free(struct io *io) in io_free() argument
192 io_debug("%s(%p)", __func__, io); in io_free()
194 /* the current io is virtually dead */ in io_free()
195 if (io == current) in io_free()
199 if (io->tls) { in io_free()
200 SSL_free(io->tls); in io_free()
201 io->tls = NULL; in io_free()
205 if (io->ai) in io_free()
206 freeaddrinfo(io->ai); in io_free()
207 if (event_initialized(&io->ev)) in io_free()
208 event_del(&io->ev); in io_free()
209 if (io->sock != -1) { in io_free()
210 (void)close(io->sock); in io_free()
211 io->sock = -1; in io_free()
214 iobuf_clear(&io->iobuf); in io_free()
215 free(io->bind); in io_free()
216 free(io); in io_free()
220 io_set_callback(struct io *io, void(*cb)(struct io *, int, void *), void *arg) in io_set_callback() argument
222 io->cb = cb; in io_set_callback()
223 io->arg = arg; in io_set_callback()
229 io_set_bindaddr(struct io *io, const struct sockaddr *sa) in io_set_bindaddr() argument
233 if (io->state != IO_STATE_DOWN) { in io_set_bindaddr()
243 free(io->bind); in io_set_bindaddr()
244 io->bind = t; in io_set_bindaddr()
250 io_set_bufsize(struct io *io, size_t sz) in io_set_bufsize() argument
257 io_set_timeout(struct io *io, int msec) in io_set_timeout() argument
259 io_debug("%s(%p, %d)", __func__, io, msec); in io_set_timeout()
261 io->timeout = msec; in io_set_timeout()
265 io_set_lowat(struct io *io, size_t lowat) in io_set_lowat() argument
267 io_debug("%s(%p, %zu)", __func__, io, lowat); in io_set_lowat()
269 io->lowat = lowat; in io_set_lowat()
273 io_error(struct io *io) in io_error() argument
277 e = io->error; in io_error()
278 io->error = NULL; in io_error()
283 io_fileno(struct io *io) in io_fileno() argument
285 return io->sock; in io_fileno()
289 io_attach(struct io *io, int sock) in io_attach() argument
291 if (io->state != IO_STATE_DOWN) { in io_attach()
296 io->state = IO_STATE_UP; in io_attach()
297 io->sock = sock; in io_attach()
298 io_reload(io); in io_attach()
303 io_detach(struct io *io) in io_detach() argument
310 io_close(struct io *io) in io_close() argument
317 io_connect(struct io *io, struct addrinfo *ai) in io_connect() argument
325 if (io->state != IO_STATE_DOWN) { in io_connect()
332 io->ai = ai; in io_connect()
333 return io_connect_next(io); in io_connect()
337 io_disconnect(struct io *io) in io_disconnect() argument
345 io_starttls(struct io *io, void *ssl) in io_starttls() argument
350 mode = io->flags & IO_RW; in io_starttls()
354 if (io->tls) in io_starttls()
356 io->tls = ssl; in io_starttls()
358 if (SSL_set_fd(io->tls, io->sock) == 0) { in io_starttls()
364 io->state = IO_STATE_CONNECT_TLS; in io_starttls()
365 SSL_set_connect_state(io->tls); in io_starttls()
366 io_reset(io, EV_WRITE, io_dispatch_connect_tls); in io_starttls()
368 io->state = IO_STATE_ACCEPT_TLS; in io_starttls()
369 SSL_set_accept_state(io->tls); in io_starttls()
370 io_reset(io, EV_READ, io_dispatch_accept_tls); in io_starttls()
381 io_pause(struct io *io, int dir) in io_pause() argument
383 io_debug("%s(%p, %x)", __func__, io, dir); in io_pause()
385 io->flags |= dir & (IO_IN | IO_OUT); in io_pause()
386 io_reload(io); in io_pause()
390 io_resume(struct io *io, int dir) in io_resume() argument
392 io_debug("%s(%p, %x)", __func__, io, dir); in io_resume()
394 io->flags &= ~(dir & (IO_IN | IO_OUT)); in io_resume()
395 io_reload(io); in io_resume()
399 io_set_read(struct io *io) in io_set_read() argument
403 io_debug("%s(%p)", __func__, io); in io_set_read()
405 mode = io->flags & IO_RW; in io_set_read()
409 io->flags &= ~IO_RW; in io_set_read()
410 io->flags |= IO_READ; in io_set_read()
411 io_reload(io); in io_set_read()
415 io_set_write(struct io *io) in io_set_write() argument
419 io_debug("%s(%p)", __func__, io); in io_set_write()
421 mode = io->flags & IO_RW; in io_set_write()
425 io->flags &= ~IO_RW; in io_set_write()
426 io->flags |= IO_WRITE; in io_set_write()
427 io_reload(io); in io_set_write()
431 io_write(struct io *io, const void *buf, size_t len) in io_write() argument
435 r = iobuf_queue(&io->iobuf, buf, len); in io_write()
437 io_reload(io); in io_write()
443 io_writev(struct io *io, const struct iovec *iov, int iovcount) in io_writev() argument
447 r = iobuf_queuev(&io->iobuf, iov, iovcount); in io_writev()
449 io_reload(io); in io_writev()
455 io_print(struct io *io, const char *s) in io_print() argument
457 return io_write(io, s, strlen(s)); in io_print()
461 io_printf(struct io *io, const char *fmt, ...) in io_printf() argument
467 r = io_vprintf(io, fmt, ap); in io_printf()
474 io_vprintf(struct io *io, const char *fmt, va_list ap) in io_vprintf() argument
484 len = io_write(io, buf, len); in io_vprintf()
491 io_queued(struct io *io) in io_queued() argument
493 return iobuf_queued(&io->iobuf); in io_queued()
497 io_data(struct io *io) in io_data() argument
499 return iobuf_data(&io->iobuf); in io_data()
503 io_datalen(struct io *io) in io_datalen() argument
505 return iobuf_len(&io->iobuf); in io_datalen()
509 io_getline(struct io *io, size_t *sz) in io_getline() argument
511 return iobuf_getline(&io->iobuf, sz); in io_getline()
515 io_drop(struct io *io, size_t sz) in io_drop() argument
517 return iobuf_drop(&io->iobuf, sz); in io_drop()
607 * Setup the necessary events as required by the current io state,
611 io_reload(struct io *io) in io_reload() argument
615 /* The io will be reloaded at release time. */ in io_reload()
616 if (io->flags & IO_HELD) in io_reload()
620 if (io->sock == -1) in io_reload()
624 if (io->tls) { in io_reload()
625 io_reload_tls(io); in io_reload()
630 io_debug("%s(%p)", __func__, io); in io_reload()
633 if (IO_READING(io) && !(io->flags & IO_PAUSE_IN)) in io_reload()
635 if (IO_WRITING(io) && !(io->flags & IO_PAUSE_OUT) && io_queued(io)) in io_reload()
638 io_reset(io, events, io_dispatch); in io_reload()
642 io_reset(struct io *io, short events, void (*dispatch)(int, short, void*)) in io_reset() argument
646 io_debug("%s(%p, %s, %p) -> %s", __func__, io, in io_reset()
647 io_strevents(events), dispatch, io_strio(io)); in io_reset()
653 io->flags |= IO_RESET; in io_reset()
655 if (event_initialized(&io->ev)) in io_reset()
656 event_del(&io->ev); in io_reset()
659 * The io is paused by the user, so we don't want the timeout to be in io_reset()
665 event_set(&io->ev, io->sock, events, dispatch, io); in io_reset()
666 if (io->timeout >= 0) { in io_reset()
667 tv.tv_sec = io->timeout / 1000; in io_reset()
668 tv.tv_usec = (io->timeout % 1000) * 1000; in io_reset()
673 event_add(&io->ev, ptv); in io_reset()
677 io_frame_enter(const char *where, struct io *io, int ev) in io_frame_enter() argument
679 io_debug("io: BEGIN %llu", frame); in io_frame_enter()
681 io_strio(io)); in io_frame_enter()
686 current = io; in io_frame_enter()
688 io_hold(io); in io_frame_enter()
692 io_frame_leave(struct io *io) in io_frame_leave() argument
696 if (current && current != io) in io_frame_leave()
697 fatalx("%s: io mismatch", __func__); in io_frame_leave()
699 /* The io has been cleared. */ in io_frame_leave()
706 * the io is waiting to read a request, and when done, it queues in io_frame_leave()
715 /* Reload the io if it has not been reset already. */ in io_frame_leave()
716 io_release(io); in io_frame_leave()
719 io_debug("io: END %llu", frame); in io_frame_leave()
725 io_hold(struct io *io) in io_hold() argument
727 io_debug("%s(%p)", __func__, io); in io_hold()
729 if (io->flags & IO_HELD) in io_hold()
732 io->flags &= ~IO_RESET; in io_hold()
733 io->flags |= IO_HELD; in io_hold()
737 io_release(struct io *io) in io_release() argument
739 io_debug("%s(%p)", __func__, io); in io_release()
741 if (!(io->flags & IO_HELD)) in io_release()
744 io->flags &= ~IO_HELD; in io_release()
745 if (!(io->flags & IO_RESET)) in io_release()
746 io_reload(io); in io_release()
750 io_callback(struct io *io, int evt) in io_callback() argument
752 io_debug("%s(%s, %s)", __func__, io_strio(io), io_strevent(evt)); in io_callback()
754 io->cb(io, evt, io->arg); in io_callback()
760 struct io *io = arg; in io_dispatch() local
765 io_frame_enter(__func__, io, ev); in io_dispatch()
768 io_callback(io, IO_TIMEOUT); in io_dispatch()
772 if (ev & EV_WRITE && (w = io_queued(io))) { in io_dispatch()
773 if ((n = iobuf_write(&io->iobuf, io->sock)) < 0) { in io_dispatch()
777 io_callback(io, IO_DISCONNECTED); in io_dispatch()
781 io->error = strerror(errno); in io_dispatch()
783 io_callback(io, IO_ERROR); in io_dispatch()
787 if (w > io->lowat && w - n <= io->lowat) in io_dispatch()
788 io_callback(io, IO_LOWAT); in io_dispatch()
793 iobuf_normalize(&io->iobuf); in io_dispatch()
794 if ((n = iobuf_read(&io->iobuf, io->sock)) < 0) { in io_dispatch()
796 io_callback(io, IO_DISCONNECTED); in io_dispatch()
800 io->error = strerror(errno); in io_dispatch()
802 io_callback(io, IO_ERROR); in io_dispatch()
807 io_callback(io, IO_DATAIN); in io_dispatch()
811 io_frame_leave(io); in io_dispatch()
817 struct io *io = arg; in io_dispatch_connect() local
821 io_frame_enter(__func__, io, ev); in io_dispatch_connect()
839 io->state = IO_STATE_UP; in io_dispatch_connect()
840 io_callback(io, IO_CONNECTED); in io_dispatch_connect()
844 while (io->ai) { in io_dispatch_connect()
845 r = io_connect_next(io); in io_dispatch_connect()
852 io->sock = -1; in io_dispatch_connect()
853 io->error = strerror(e); in io_dispatch_connect()
854 io->state = IO_STATE_DOWN; in io_dispatch_connect()
855 io_callback(io, e == ETIMEDOUT ? IO_TIMEOUT : IO_ERROR); in io_dispatch_connect()
857 io_frame_leave(io); in io_dispatch_connect()
861 io_connect_next(struct io *io) in io_connect_next() argument
867 while ((ai = io->ai)) { in io_connect_next()
868 io->ai = ai->ai_next; in io_connect_next()
881 if ((io->sock = socket(ai->ai_family, ai->ai_socktype | SOCK_NONBLOCK, in io_connect_next()
888 if (setsockopt(io->sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) { in io_connect_next()
893 if (io->bind && bind(io->sock, io->bind, io->bind->sa_len) == -1) { in io_connect_next()
898 if (connect(io->sock, ai->ai_addr, ai->ai_addr->sa_len) == -1) in io_connect_next()
905 io->state = IO_STATE_CONNECT; in io_connect_next()
906 io_reset(io, EV_WRITE, io_dispatch_connect); in io_connect_next()
910 if (io->sock != -1) { in io_connect_next()
912 close(io->sock); in io_connect_next()
914 io->error = strerror(errno); in io_connect_next()
915 io->sock = -1; in io_connect_next()
918 if (io->ai) { in io_connect_next()
919 freeaddrinfo(io->ai); in io_connect_next()
920 io->ai = NULL; in io_connect_next()
945 struct io *io = arg; in io_dispatch_accept_tls() local
948 io_frame_enter(__func__, io, event); in io_dispatch_accept_tls()
951 io_callback(io, IO_TIMEOUT); in io_dispatch_accept_tls()
955 if ((ret = SSL_accept(io->tls)) > 0) { in io_dispatch_accept_tls()
956 io->state = IO_STATE_UP; in io_dispatch_accept_tls()
957 io_callback(io, IO_TLSREADY); in io_dispatch_accept_tls()
961 switch ((e = SSL_get_error(io->tls, ret))) { in io_dispatch_accept_tls()
963 io_reset(io, EV_READ, io_dispatch_accept_tls); in io_dispatch_accept_tls()
966 io_reset(io, EV_WRITE, io_dispatch_accept_tls); in io_dispatch_accept_tls()
969 io->error = io_ssl_error(); in io_dispatch_accept_tls()
971 io_callback(io, IO_TLSERROR); in io_dispatch_accept_tls()
976 io_frame_leave(io); in io_dispatch_accept_tls()
982 struct io *io = arg; in io_dispatch_connect_tls() local
985 io_frame_enter(__func__, io, event); in io_dispatch_connect_tls()
988 io_callback(io, IO_TIMEOUT); in io_dispatch_connect_tls()
992 if ((ret = SSL_connect(io->tls)) > 0) { in io_dispatch_connect_tls()
993 io->state = IO_STATE_UP; in io_dispatch_connect_tls()
994 io_callback(io, IO_TLSREADY); in io_dispatch_connect_tls()
998 switch ((e = SSL_get_error(io->tls, ret))) { in io_dispatch_connect_tls()
1000 io_reset(io, EV_READ, io_dispatch_connect_tls); in io_dispatch_connect_tls()
1003 io_reset(io, EV_WRITE, io_dispatch_connect_tls); in io_dispatch_connect_tls()
1006 io->error = io_ssl_error(); in io_dispatch_connect_tls()
1008 io_callback(io, IO_TLSERROR); in io_dispatch_connect_tls()
1013 io_frame_leave(io); in io_dispatch_connect_tls()
1019 struct io *io = arg; in io_dispatch_read_tls() local
1022 io_frame_enter(__func__, io, event); in io_dispatch_read_tls()
1025 io_callback(io, IO_TIMEOUT); in io_dispatch_read_tls()
1030 iobuf_normalize(&io->iobuf); in io_dispatch_read_tls()
1031 switch ((n = iobuf_read_ssl(&io->iobuf, (SSL*)io->tls))) { in io_dispatch_read_tls()
1033 io_reset(io, EV_READ, io_dispatch_read_tls); in io_dispatch_read_tls()
1036 io_reset(io, EV_WRITE, io_dispatch_read_tls); in io_dispatch_read_tls()
1039 io_callback(io, IO_DISCONNECTED); in io_dispatch_read_tls()
1043 io->error = strerror(errno); in io_dispatch_read_tls()
1046 io_callback(io, IO_ERROR); in io_dispatch_read_tls()
1049 io->error = io_ssl_error(); in io_dispatch_read_tls()
1051 io_callback(io, IO_TLSERROR); in io_dispatch_read_tls()
1055 io_callback(io, IO_DATAIN); in io_dispatch_read_tls()
1056 if (current == io && IO_READING(io) && SSL_pending(io->tls)) in io_dispatch_read_tls()
1061 io_frame_leave(io); in io_dispatch_read_tls()
1067 struct io *io = arg; in io_dispatch_write_tls() local
1071 io_frame_enter(__func__, io, event); in io_dispatch_write_tls()
1074 io_callback(io, IO_TIMEOUT); in io_dispatch_write_tls()
1078 w = io_queued(io); in io_dispatch_write_tls()
1079 switch ((n = iobuf_write_ssl(&io->iobuf, (SSL*)io->tls))) { in io_dispatch_write_tls()
1081 io_reset(io, EV_READ, io_dispatch_write_tls); in io_dispatch_write_tls()
1084 io_reset(io, EV_WRITE, io_dispatch_write_tls); in io_dispatch_write_tls()
1087 io_callback(io, IO_DISCONNECTED); in io_dispatch_write_tls()
1091 io->error = strerror(errno); in io_dispatch_write_tls()
1094 io_callback(io, IO_ERROR); in io_dispatch_write_tls()
1097 io->error = io_ssl_error(); in io_dispatch_write_tls()
1099 io_callback(io, IO_TLSERROR); in io_dispatch_write_tls()
1103 w2 = io_queued(io); in io_dispatch_write_tls()
1104 if (w > io->lowat && w2 <= io->lowat) in io_dispatch_write_tls()
1105 io_callback(io, IO_LOWAT); in io_dispatch_write_tls()
1110 io_frame_leave(io); in io_dispatch_write_tls()
1114 io_reload_tls(struct io *io) in io_reload_tls() argument
1119 switch (io->state) { in io_reload_tls()
1130 if (IO_READING(io) && !(io->flags & IO_PAUSE_IN)) { in io_reload_tls()
1134 else if (IO_WRITING(io) && !(io->flags & IO_PAUSE_OUT) && in io_reload_tls()
1135 io_queued(io)) { in io_reload_tls()
1143 fatalx("%s: unexpected state %d", __func__, io->state); in io_reload_tls()
1146 io_reset(io, ev, dispatch); in io_reload_tls()