r3314: added a option "socket:testnonblock" to the generic socket code. If
authorAndrew Tridgell <tridge@samba.org>
Thu, 28 Oct 2004 07:55:33 +0000 (07:55 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:04:53 +0000 (13:04 -0500)
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
source4/lib/socket/socket.c
source4/lib/socket/socket.h
source4/lib/socket/socket_ipv4.c
source4/lib/socket/socket_unix.c
source4/smbd/process_single.c
source4/smbd/process_standard.c
source4/smbd/process_thread.c

index 09d0c439347d2574e33c1340000253ef70fbec86..7f90bd4e409385a036d317811464ef7be696e404 100644 (file)
@@ -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");
        }
index 94d8b5badaa464f2eaffdbeabb7ccb9cffe1a7cc..22b40e076c684fad8a72d7e0f25b0858653045a1 100644 (file)
@@ -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);
 }
 
index 6562bb376b95d0476f40571bcc53179321326d75..6e54a37b8066ee231cc9fb660506cdc10aa87b1e 100644 (file)
@@ -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;
index 71e1c62235f9c82b2abc8f6f55709b2144916027..f9318a29bb5e4d7e49e3de024630e489b73e9163 100644 (file)
@@ -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;
 
index 239e4eb0694deea61331a04c60d9536295d75e39..d160d897ee21ec9cb17cacd2e3b369aa2beef9f2 100644 (file)
@@ -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;
 
index b96a1d0b2cb5d8d8634ff6b05626d66cdd5e9d7b..603726e22d9d6a9e4892571e0da257e0ceddee7c 100644 (file)
@@ -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)));
index 98810af0283fd0536f031e72955e34d1af5c22c8..106be7792549496ecfa2c4e523cc8e0913ab53c7 100644 (file)
@@ -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)));
index 108b098b8a7fce3ec271a23880349771344bfb98..2b8746efb2ecef32bdfcce51e038d1b67675d04c 100644 (file)
@@ -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)));