From 990d76f7cbd4339c30f650781c40463234fc47e1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 07:55:33 +0000 Subject: r3314: added a option "socket:testnonblock" to the generic socket code. If you set this option (either on the command line using --option or in smb.conf) then every socket recv or send will return short by random amounts. This allows you to test that the non-blocking socket logic in your code works correctly. I also removed the flags argument to socket_accept(), and instead made the new socket inherit the flags of the old socket, which makes more sense to me. (This used to be commit 406d356e698da01c84e8aa5b7894752b4403f63c) --- source4/lib/messaging/messaging.c | 2 +- source4/lib/socket/socket.c | 22 ++++++++++++++++++++-- source4/lib/socket/socket.h | 8 ++++---- source4/lib/socket/socket_ipv4.c | 6 +++--- source4/lib/socket/socket_unix.c | 7 +++---- source4/smbd/process_single.c | 2 +- source4/smbd/process_standard.c | 2 +- source4/smbd/process_thread.c | 2 +- 8 files changed, 34 insertions(+), 17 deletions(-) (limited to 'source4') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 09d0c43934..7f90bd4e40 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -208,7 +208,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * smb_panic("Unable to allocate messaging_rec"); } - status = socket_accept(msg->sock, &rec->sock, 0); + status = socket_accept(msg->sock, &rec->sock); if (!NT_STATUS_IS_OK(status)) { smb_panic("Unable to accept messaging_rec"); } diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 94d8b5bada..22b40e076c 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -60,6 +60,14 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co return status; } + /* by enabling "testnonblock" mode, all socket receive and + send calls on non-blocking sockets will randomly recv/send + less data than requested */ + if (!(flags & SOCKET_FLAG_BLOCK) && + lp_parm_bool(-1, "socket", "testnonblock", False)) { + (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK; + } + talloc_set_destructor(*new_sock, socket_destructor); return NT_STATUS_OK; @@ -108,7 +116,7 @@ NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int return sock->ops->listen(sock, my_address, port, queue_size, flags); } -NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) +NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock) { NTSTATUS status; @@ -124,7 +132,7 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ return NT_STATUS_NOT_IMPLEMENTED; } - status = sock->ops->accept(sock, new_sock, flags); + status = sock->ops->accept(sock, new_sock); if (NT_STATUS_IS_OK(status)) { talloc_set_destructor(*new_sock, socket_destructor); @@ -149,6 +157,10 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, return NT_STATUS_NOT_IMPLEMENTED; } + if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) && wantlen > 1) { + return sock->ops->recv(sock, buf, 1+(random() % (wantlen-1)), nread, flags); + } + return sock->ops->recv(sock, buf, wantlen, nread, flags); } @@ -168,6 +180,12 @@ NTSTATUS socket_send(struct socket_context *sock, return NT_STATUS_NOT_IMPLEMENTED; } + if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) && blob->length > 1) { + DATA_BLOB blob2 = *blob; + blob2.length = 1+(random() % (blob2.length-1)); + return sock->ops->send(sock, &blob2, sendlen, flags); + } + return sock->ops->send(sock, blob, sendlen, flags); } diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 6562bb376b..6e54a37b80 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -42,8 +42,7 @@ struct socket_ops { /* server ops */ NTSTATUS (*listen)(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags); - NTSTATUS (*accept)(struct socket_context *sock, - struct socket_context **new_sock, uint32_t flags); + NTSTATUS (*accept)(struct socket_context *sock, struct socket_context **new_sock); /* general ops */ NTSTATUS (*recv)(struct socket_context *sock, void *buf, @@ -78,8 +77,9 @@ enum socket_state { SOCKET_STATE_SERVER_ERROR }; -#define SOCKET_FLAG_BLOCK 0x00000001 -#define SOCKET_FLAG_PEEK 0x00000002 +#define SOCKET_FLAG_BLOCK 0x00000001 +#define SOCKET_FLAG_PEEK 0x00000002 +#define SOCKET_FLAG_TESTNONBLOCK 0x00000004 struct socket_context { enum socket_type type; diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 71e1c62235..f9318a29bb 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -130,7 +130,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) +static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock) { struct sockaddr_in cli_addr; socklen_t cli_addr_len = sizeof(cli_addr); @@ -141,7 +141,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte return map_nt_error_from_unix(errno); } - if (!(flags & SOCKET_FLAG_BLOCK)) { + if (!(sock->flags & SOCKET_FLAG_BLOCK)) { int ret = set_blocking(new_fd, False); if (ret == -1) { close(new_fd); @@ -164,7 +164,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte /* copy the socket_context */ (*new_sock)->type = sock->type; (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; - (*new_sock)->flags = flags; + (*new_sock)->flags = sock->flags; (*new_sock)->fd = new_fd; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 239e4eb069..d160d897ee 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -124,8 +124,7 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, } static NTSTATUS unixdom_accept(struct socket_context *sock, - struct socket_context **new_sock, - uint32_t flags) + struct socket_context **new_sock) { struct sockaddr_un cli_addr; socklen_t cli_addr_len = sizeof(cli_addr); @@ -136,7 +135,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, return unixdom_error(errno); } - if (!(flags & SOCKET_FLAG_BLOCK)) { + if (!(sock->flags & SOCKET_FLAG_BLOCK)) { int ret = set_blocking(new_fd, False); if (ret == -1) { close(new_fd); @@ -153,7 +152,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, /* copy the socket_context */ (*new_sock)->type = sock->type; (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; - (*new_sock)->flags = flags; + (*new_sock)->flags = sock->flags; (*new_sock)->fd = new_fd; diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index b96a1d0b2c..603726e22d 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -42,7 +42,7 @@ static void single_accept_connection(struct event_context *ev, struct fd_event * struct server_connection *conn; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock, 0); + status = socket_accept(server_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("accept_connection_single: accept: %s\n", nt_errstr(status))); diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index 98810af028..106be77925 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -43,7 +43,7 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event pid_t pid; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock, 0); + status = socket_accept(server_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); diff --git a/source4/smbd/process_thread.c b/source4/smbd/process_thread.c index 108b098b8a..2b8746efb2 100644 --- a/source4/smbd/process_thread.c +++ b/source4/smbd/process_thread.c @@ -58,7 +58,7 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event * struct server_connection *conn; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock, 0); + status = socket_accept(server_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("accept_connection_single: accept: %s\n", nt_errstr(status))); -- cgit