r11603: converted the smb server to use the new generic packet code
authorAndrew Tridgell <tridge@samba.org>
Wed, 9 Nov 2005 10:51:26 +0000 (10:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:45:57 +0000 (13:45 -0500)
(This used to be commit 0fc496bb6f520ddf6d85cc2f3df80f93b871cfe9)

source4/smb_server/config.mk
source4/smb_server/smb_server.c
source4/smb_server/smb_server.h

index 03a49d728a72fb05ac82cec26b5b395c85e7f168..c1eadf9397d7ba568dd028d01f0e6e06c6914ead 100644 (file)
@@ -20,6 +20,6 @@ ADD_OBJ_FILES = \
                signing.o \
                management.o
 REQUIRED_SUBSYSTEMS = \
-               NTVFS
+               NTVFS LIBPACKET
 # End SUBSYSTEM SMB
 #######################
index ccfc6c9c7bf94931538695305cc96cd596a99f94..0cdc2dc7e44f5248bf2c37b39062c19c7b6ab364 100644 (file)
@@ -27,6 +27,7 @@
 #include "smbd/service_stream.h"
 #include "smb_server/smb_server.h"
 #include "lib/messaging/irpc.h"
+#include "lib/stream/packet.h"
 
 
 /*
@@ -68,85 +69,18 @@ static void construct_reply(struct smbsrv_request *req);
 receive a SMB request header from the wire, forming a request_context
 from the result
 ****************************************************************************/
-static NTSTATUS receive_smb_request(struct smbsrv_connection *smb_conn)
+static NTSTATUS receive_smb_request(void *private, DATA_BLOB blob)
 {
-       NTSTATUS status;
-       ssize_t len;
+       struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection);
        struct smbsrv_request *req;
-       size_t nread;
-
-       /* allocate the request if needed */
-       if (smb_conn->partial_req == NULL) {
-               req = init_smb_request(smb_conn);
-               if (req == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               req->in.buffer = talloc_array(req, uint8_t, NBT_HDR_SIZE);
-               if (req->in.buffer == NULL) {
-                       talloc_free(req);
-                       return NT_STATUS_NO_MEMORY;
-               }
-               req->in.size = 0;
-               smb_conn->partial_req = req;
-       }
-
-       req = smb_conn->partial_req;
-
-       /* read in the header */
-       if (req->in.size < NBT_HDR_SIZE) {
-               status = socket_recv(smb_conn->connection->socket, 
-                                    req->in.buffer + req->in.size,
-                                    NBT_HDR_SIZE - req->in.size, 
-                                    &nread, 0);
-               if (NT_STATUS_IS_ERR(status)) {
-                       return status;
-               }
-               if (!NT_STATUS_IS_OK(status)) {
-                       return NT_STATUS_OK;
-               }
-               if (nread == 0) {
-                       return NT_STATUS_END_OF_FILE;
-               }
-               req->in.size += nread;
-
-               /* when we have a full NBT header, then allocate the packet */
-               if (req->in.size == NBT_HDR_SIZE) {
-                       len = smb_len(req->in.buffer) + NBT_HDR_SIZE;
-                       req->in.buffer = talloc_realloc(req, req->in.buffer, 
-                                                       uint8_t, len);
-                       if (req->in.buffer == NULL) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               } else {
-                       return NT_STATUS_OK;
-               }
-       }
-
-       /* read in the main packet */
-       len = smb_len(req->in.buffer) + NBT_HDR_SIZE;
-
-       status = socket_recv(smb_conn->connection->socket, 
-                            req->in.buffer + req->in.size,
-                            len - req->in.size, 
-                            &nread, 0);
-       if (NT_STATUS_IS_ERR(status)) {
-               return status;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_OK;
-       }
-       if (nread == 0) {
-               return NT_STATUS_END_OF_FILE;
-       }
-
-       req->in.size += nread;
 
-       if (req->in.size != len) {
-               return NT_STATUS_OK;
+       req = init_smb_request(smb_conn);
+       if (req == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
-       /* we have a full packet */
+       req->in.buffer = talloc_steal(req, blob.data);
+       req->in.size = blob.length;
        req->request_time = timeval_current();
        req->chained_fnum = -1;
        req->in.allocated = req->in.size;
@@ -171,8 +105,6 @@ static NTSTATUS receive_smb_request(struct smbsrv_connection *smb_conn)
                }
        }
 
-       smb_conn->partial_req = NULL;
-
        construct_reply(req);
 
        return NT_STATUS_OK;
@@ -659,7 +591,7 @@ error:
 */
 void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char *reason)
 {
-       smb_conn->terminate = True;
+       smb_conn->terminate = reason;
 }
 
 /*
@@ -668,31 +600,17 @@ void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char
 static void smbsrv_recv(struct stream_connection *conn, uint16_t flags)
 {
        struct smbsrv_connection *smb_conn = talloc_get_type(conn->private, struct smbsrv_connection);
-       NTSTATUS status;
 
        DEBUG(10,("smbsrv_recv\n"));
 
-       /* our backends are designed to process one request at a time,
-          unless they deliberately mark the request as async and
-          process it later on a timer or other event. This enforces
-          that ordering. */
-       if (smb_conn->processing) {
-               EVENT_FD_NOT_READABLE(conn->event.fde);
-               return;
-       }
-
-       smb_conn->processing = True;
-       status = receive_smb_request(smb_conn);
-       smb_conn->processing = False;
-       if (NT_STATUS_IS_ERR(status) || smb_conn->terminate) {
+       packet_recv(smb_conn->packet);
+       if (smb_conn->terminate) {
                talloc_free(conn->event.fde);
                conn->event.fde = NULL;
-               stream_terminate_connection(smb_conn->connection, nt_errstr(status));
+               stream_terminate_connection(smb_conn->connection, smb_conn->terminate);
                return;
        }
 
-       EVENT_FD_READABLE(conn->event.fde);
-
        /* free up temporary memory */
        lp_talloc_free();
 }
@@ -734,7 +652,7 @@ static void smbsrv_send(struct stream_connection *conn, uint16_t flags)
        }
 
        if (smb_conn->terminate) {
-               stream_terminate_connection(smb_conn->connection, "send termination");
+               stream_terminate_connection(smb_conn->connection, smb_conn->terminate);
                return;
        }
 
@@ -745,6 +663,17 @@ static void smbsrv_send(struct stream_connection *conn, uint16_t flags)
        }
 }
 
+
+/*
+  handle socket recv errors
+*/
+static void smbsrv_recv_error(void *private, NTSTATUS status)
+{
+       struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection);
+       
+       smbsrv_terminate_connection(smb_conn, nt_errstr(status));
+}
+
 /*
   initialise a server_context from a open socket and register a event handler
   for reading from that socket
@@ -770,6 +699,15 @@ static void smbsrv_accept(struct stream_connection *conn)
        smb_conn->negotiate.called_name = NULL;
        smb_conn->negotiate.calling_name = NULL;
 
+       smb_conn->packet = packet_init(smb_conn);
+       packet_set_private(smb_conn->packet, smb_conn);
+       packet_set_socket(smb_conn->packet, conn->socket);
+       packet_set_callback(smb_conn->packet, receive_smb_request);
+       packet_set_full_request(smb_conn->packet, packet_full_request_nbt);
+       packet_set_error_handler(smb_conn->packet, smbsrv_recv_error);
+       packet_set_event_context(smb_conn->packet, conn->event.ctx);
+       packet_set_serialise(smb_conn->packet, conn->event.fde);
+
        smbsrv_vuid_init(smb_conn);
 
        srv_init_signing(smb_conn);
@@ -777,7 +715,6 @@ static void smbsrv_accept(struct stream_connection *conn)
        smbsrv_tcon_init(smb_conn);
 
        smb_conn->connection = conn;
-       smb_conn->processing = False;
        smb_conn->config.security = lp_security();
        smb_conn->config.nt_status_support = lp_nt_status_support();
 
index 360ea7ddfb90441ea23292ff27ae275fd5d00514..b6c9d5f98581703d72f85fc34a38fc742d572813 100644 (file)
@@ -252,7 +252,7 @@ struct smbsrv_connection {
        struct stream_connection *connection;
 
        /* this holds a partially received request */
-       struct smbsrv_request *partial_req;
+       struct packet_context *packet;
 
        /* this holds list of replies that are waiting to be sent
           to the client */
@@ -266,10 +266,8 @@ struct smbsrv_connection {
                uint8_t command;
        } *trans_partial;
 
-       BOOL processing;
-
        /* mark a connection for termination */
-       BOOL terminate;
+       const char *terminate;
 
        /* configuration parameters */
        struct {