From: Willy Tarreau Date: Mon, 23 Jul 2012 16:53:03 +0000 (+0200) Subject: MEDIUM: stream_interface: pass connection instead of fd in sock_ops X-Git-Tag: v1.5-dev12~106 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=239d7189fc525c2119b021b8719baed98087ea62;p=thirdparty%2Fhaproxy.git MEDIUM: stream_interface: pass connection instead of fd in sock_ops The sock_ops I/O callbacks made use of an FD till now. This has become inappropriate and the struct connection is much more useful. It also fixes the race condition introduced by previous change. --- diff --git a/include/proto/proto_tcp.h b/include/proto/proto_tcp.h index 66f29fcdbe..6a60121d21 100644 --- a/include/proto/proto_tcp.h +++ b/include/proto/proto_tcp.h @@ -31,7 +31,7 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so void tcpv4_add_listener(struct listener *listener); void tcpv6_add_listener(struct listener *listener); int tcp_connect_server(struct stream_interface *si); -int tcp_connect_probe(int fd); +int tcp_connect_probe(struct connection *conn); int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit); diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index 88b55abbc7..851870fb30 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -114,8 +114,8 @@ struct sock_ops { void (*shutw)(struct stream_interface *); /* shutw function */ void (*chk_rcv)(struct stream_interface *); /* chk_rcv function */ void (*chk_snd)(struct stream_interface *); /* chk_snd function */ - int (*read)(int fd); /* read callback after poll() */ - int (*write)(int fd); /* write callback after poll() */ + int (*read)(struct connection *conn); /* read callback after poll() */ + int (*write)(struct connection *conn); /* write callback after poll() */ void (*close)(struct connection *); /* close the data channel on the connection */ }; diff --git a/src/connection.c b/src/connection.c index 6b84c94e1a..ef5838ab92 100644 --- a/src/connection.c +++ b/src/connection.c @@ -38,14 +38,14 @@ int conn_fd_handler(int fd) goto leave; if (fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR)) - if (!conn->data->read(fd)) + if (!conn->data->read(conn)) ret |= FD_WAIT_READ; if (conn->flags & CO_FL_ERROR) goto leave; if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR)) - if (!conn->data->write(fd)) + if (!conn->data->write(conn)) ret |= FD_WAIT_WRITE; if (conn->flags & CO_FL_ERROR) @@ -55,7 +55,7 @@ int conn_fd_handler(int fd) /* still waiting for a connection to establish and no data to * send in order to probe it ? Then let's retry the connect(). */ - if (!tcp_connect_probe(fd)) + if (!tcp_connect_probe(conn)) ret |= FD_WAIT_WRITE; } diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 9fb03c44fe..cebc477107 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -524,9 +524,9 @@ int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir) * once the connection is established. It returns zero if it needs some polling * before being called again. */ -int tcp_connect_probe(int fd) +int tcp_connect_probe(struct connection *conn) { - struct connection *conn = fdtab[fd].owner; + int fd = conn->t.sock.fd; struct stream_interface *si = container_of(conn, struct stream_interface, conn); struct buffer *b = si->ob; int retval = 0; diff --git a/src/sock_raw.c b/src/sock_raw.c index 74ad127751..cdb0e27140 100644 --- a/src/sock_raw.c +++ b/src/sock_raw.c @@ -42,8 +42,8 @@ #include /* main event functions used to move data between sockets and buffers */ -static int sock_raw_read(int fd); -static int sock_raw_write(int fd); +static int sock_raw_read(struct connection *conn); +static int sock_raw_write(struct connection *conn); static void sock_raw_data_finish(struct stream_interface *si); static void sock_raw_shutr(struct stream_interface *si); static void sock_raw_shutw(struct stream_interface *si); @@ -226,9 +226,9 @@ static int sock_raw_splice_in(struct buffer *b, struct stream_interface *si) * able to read more data without polling first. Returns non-zero * otherwise. */ -static int sock_raw_read(int fd) +static int sock_raw_read(struct connection *conn) { - struct connection *conn = fdtab[fd].owner; + int fd = conn->t.sock.fd; struct stream_interface *si = container_of(conn, struct stream_interface, conn); struct buffer *b = si->ib; int ret, max, retval, cur_read; @@ -240,9 +240,6 @@ static int sock_raw_read(int fd) retval = 1; - if (!conn) - goto out_wakeup; - /* stop immediately on errors. Note that we DON'T want to stop on * POLL_ERR, as the poller might report a write error while there * are still data available in the recv buffer. This typically @@ -631,9 +628,9 @@ static int sock_raw_write_loop(struct stream_interface *si, struct buffer *b) * It returns 0 if the caller needs to poll before calling it again, otherwise * non-zero. */ -static int sock_raw_write(int fd) +static int sock_raw_write(struct connection *conn) { - struct connection *conn = fdtab[fd].owner; + int fd = conn->t.sock.fd; struct stream_interface *si = container_of(conn, struct stream_interface, conn); struct buffer *b = si->ob; int retval = 1; @@ -642,10 +639,6 @@ static int sock_raw_write(int fd) fprintf(stderr,"sock_raw_write : fd=%d, owner=%p\n", fd, fdtab[fd].owner); #endif - retval = 1; - if (!conn) - goto out_wakeup; - if (conn->flags & CO_FL_ERROR) goto out_error;