r3304: changed the API to lib/socket/ a little.
authorAndrew Tridgell <tridge@samba.org>
Thu, 28 Oct 2004 04:00:43 +0000 (04:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:04:52 +0000 (13:04 -0500)
The main change is to make socket_recv() take a pre-allocated buffer,
rather than allocating one itself. This allows non-blocking users of
this API to avoid a memcpy(). As a result our messaging code is now
about 10% faster, and the ncacn_ip_tcp and ncalrpc code is also
faster.

The second change was to remove the unused mem_ctx argument from
socket_send(). Having it there implied that memory could be allocated,
which meant the caller had to worry about freeing that memory (if for
example it is sending in a tight loop using the same memory
context). Removing that unused argument keeps life simpler for users.
(This used to be commit a16e4756cd68ca8aab4ffc59d4d9db0b6e44dbd1)

source4/ldap_server/ldap_server.c
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/librpc/rpc/dcerpc_sock.c
source4/rpc_server/dcerpc_sock.c
source4/smb_server/request.c
source4/smb_server/smb_server.c

index 6ce2dfdd79fd8a542c888a0b4c19c55f1e40260f..70191c48277f1c54a144f04ade3f80fd05dca3af 100644 (file)
@@ -155,10 +155,17 @@ static BOOL read_into_buf(struct socket_context *sock, struct rw_buffer *buf)
        NTSTATUS status;
        DATA_BLOB tmp_blob;
        BOOL ret;
+       size_t nread;
 
-       status = socket_recv(sock, sock, &tmp_blob, 1024, 0);
+       tmp_blob = data_blob_talloc(sock, NULL, 1024);
+       if (tmp_blob.data == NULL) {
+               return False;
+       }
+
+       status = socket_recv(sock, tmp_blob.data, tmp_blob.length, &nread, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
+               talloc_free(tmp_blob.data);
                return False;
        }
 
@@ -179,6 +186,7 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
        int buf_length, sasl_length;
        struct socket_context *sock = conn->connection->socket;
        TALLOC_CTX *mem_ctx;
+       size_t nread;
 
        if (!conn->gensec || !conn->session_info ||
           !(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
@@ -192,12 +200,19 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
                return False;
        }
 
-       status = socket_recv(sock, mem_ctx, &tmp_blob, 1024, 0);
+       tmp_blob = data_blob_talloc(mem_ctx, NULL, 1024);
+       if (tmp_blob.data == NULL) {
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       status = socket_recv(sock, tmp_blob.data, tmp_blob.length, &nread, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
                talloc_free(mem_ctx);
                return False;
        }
+       tmp_blob.length = nread;
 
        ret = ldapsrv_append_to_buf(&conn->sasl_in_buffer, tmp_blob.data, tmp_blob.length);
        if (!ret) {
@@ -276,7 +291,7 @@ static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
        tmp_blob.data = buf->data;
        tmp_blob.length = buf->length;
 
-       status = socket_send(sock, sock, &tmp_blob, &sendlen, 0);
+       status = socket_send(sock, &tmp_blob, &sendlen, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
                return False;
@@ -360,7 +375,7 @@ nodata:
        tmp_blob.data = conn->sasl_out_buffer.data;
        tmp_blob.length = conn->sasl_out_buffer.length;
 
-       status = socket_send(sock, mem_ctx, &tmp_blob, &sendlen, 0);
+       status = socket_send(sock, &tmp_blob, &sendlen, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
                talloc_free(mem_ctx);
index afd18b4f2fa5596a49cb8908c9e6c369f084a455..09d0c439347d2574e33c1340000253ef70fbec86 100644 (file)
@@ -123,22 +123,21 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd
 
        if (rec->ndone < sizeof(rec->header)) {
                /* receive the header */
-               DATA_BLOB blob;
-               blob.length = 0;
-               status = socket_recv(rec->sock, rec, 
-                                    &blob, sizeof(rec->header) - rec->ndone, 0);
+               size_t nread;
+
+               status = socket_recv(rec->sock, 
+                                    rec->ndone + (char *)&rec->header,
+                                    sizeof(rec->header) - rec->ndone, &nread, 0);
                if (NT_STATUS_IS_ERR(status)) {
                        talloc_free(rec);
                        return;
                }
 
-               if (blob.length == 0) {
+               if (nread == 0) {
                        return;
                }
 
-               memcpy(rec->ndone + (char *)&rec->header, blob.data, blob.length);
-               rec->ndone += blob.length;
-               data_blob_free(&blob);
+               rec->ndone += nread;
 
                if (rec->ndone == sizeof(rec->header)) {
                        if (rec->header.version != MESSAGING_VERSION) {
@@ -158,23 +157,22 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd
        if (rec->ndone >= sizeof(rec->header) && 
            rec->ndone < sizeof(rec->header) + rec->header.length) {
                /* receive the body, if any */
-               DATA_BLOB blob;
-               blob.length = 0;
-               status = socket_recv(rec->sock, rec, 
-                                    &blob, sizeof(rec->header) + rec->header.length - rec->ndone, 0);
+               size_t nread;
+
+               status = socket_recv(rec->sock, 
+                                    rec->data.data + (rec->ndone - sizeof(rec->header)),
+                                    sizeof(rec->header) + rec->header.length - rec->ndone, 
+                                    &nread, 0);
                if (NT_STATUS_IS_ERR(status)) {
                        talloc_free(rec);
                        return;
                }
 
-               if (blob.length == 0) {
+               if (nread == 0) {
                        return;
                }
 
-               memcpy(rec->data.data + (rec->ndone - sizeof(rec->header)), 
-                      blob.data, blob.length);
-
-               rec->ndone += blob.length;
+               rec->ndone += nread;
        }
 
        if (rec->ndone == sizeof(rec->header) + rec->header.length) {
@@ -283,7 +281,7 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd
                blob.data = rec->ndone + (char *)&rec->header;
                blob.length = sizeof(rec->header) - rec->ndone;
 
-               status = socket_send(rec->sock, rec, &blob, &nsent, 0);
+               status = socket_send(rec->sock, &blob, &nsent, 0);
                if (NT_STATUS_IS_ERR(status)) {
                        talloc_free(rec);
                        return;
@@ -305,7 +303,7 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd
                blob.data = rec->data.data + (rec->ndone - sizeof(rec->header));
                blob.length = rec->header.length - (rec->ndone - sizeof(rec->header));
 
-               status = socket_send(rec->sock, rec, &blob, &nsent, 0);
+               status = socket_send(rec->sock, &blob, &nsent, 0);
                if (NT_STATUS_IS_ERR(status)) {
                        talloc_free(rec);
                        return;
index f5ee84a7cc1cdc304732976bdfa98219942ba414..94d8b5badaa464f2eaffdbeabb7ccb9cffe1a7cc 100644 (file)
@@ -133,8 +133,8 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_
        return status;
 }
 
-NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
-                    DATA_BLOB *blob, size_t wantlen, uint32_t flags)
+NTSTATUS socket_recv(struct socket_context *sock, void *buf, 
+                    size_t wantlen, size_t *nread, uint32_t flags)
 {
        if (sock->type != SOCKET_TYPE_STREAM) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -149,11 +149,11 @@ NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       return sock->ops->recv(sock, mem_ctx, blob, wantlen, flags);
+       return sock->ops->recv(sock, buf, wantlen, nread, flags);
 }
 
-NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
-                       const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
+NTSTATUS socket_send(struct socket_context *sock, 
+                    const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
 {
        if (sock->type != SOCKET_TYPE_STREAM) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -168,7 +168,7 @@ NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       return sock->ops->send(sock, mem_ctx, blob, sendlen, flags);
+       return sock->ops->send(sock, blob, sendlen, flags);
 }
 
 NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
index a089a1b78a7b4aeee97bc500383641ace57abb98..6562bb376b95d0476f40571bcc53179321326d75 100644 (file)
@@ -46,10 +46,10 @@ struct socket_ops {
                                struct socket_context **new_sock, uint32_t flags);
 
        /* general ops */
-       NTSTATUS (*recv)(struct socket_context *sock, TALLOC_CTX *mem_ctx, 
-                               DATA_BLOB *blob, size_t wantlen, uint32_t flags);
-       NTSTATUS (*send)(struct socket_context *sock, TALLOC_CTX *mem_ctx,
-                               const DATA_BLOB *blob, size_t *sendlen, uint32_t flags);
+       NTSTATUS (*recv)(struct socket_context *sock, void *buf,
+                        size_t wantlen, size_t *nread, uint32_t flags);
+       NTSTATUS (*send)(struct socket_context *sock, 
+                        const DATA_BLOB *blob, size_t *sendlen, uint32_t flags);
 
        void (*close)(struct socket_context *sock);
 
index f280f804ef8aed417a75fc39fe61e2f2066779ab..4de0d8cebee833da8e7c5350d9d9248a28957986 100644 (file)
@@ -166,18 +166,12 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
-                             DATA_BLOB *blob, size_t wantlen, uint32_t flags)
+static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, void *buf, 
+                             size_t wantlen, size_t *nread, uint32_t flags)
 {
        ssize_t gotlen;
-       void *buf;
        int flgs = 0;
 
-       buf = talloc(mem_ctx, wantlen);
-       if (!buf) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* TODO: we need to map all flags here */
        if (flags & SOCKET_FLAG_PEEK) {
                flgs |= MSG_PEEK;
@@ -187,42 +181,21 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
                flgs |= MSG_WAITALL;
        }
 
+       *nread = 0;
+
        gotlen = recv(sock->fd, buf, wantlen, flgs);
        if (gotlen == 0) {
-               talloc_free(buf);
                return NT_STATUS_END_OF_FILE;
        } else if (gotlen == -1) {
-               NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-               switch (errno) {
-                       case EBADF:
-                       case ENOTCONN:
-                       case ENOTSOCK:
-                       case EFAULT:
-                       case EINVAL:
-                               status = NT_STATUS_INVALID_PARAMETER;
-                               break;
-                       case EAGAIN:
-                       case EINTR:
-                               status = STATUS_MORE_ENTRIES;
-                               break;
-                       case ECONNREFUSED:
-                               status = NT_STATUS_CONNECTION_REFUSED;
-                               break;
-               }
-               talloc_free(buf);
-               return status;
+               return map_nt_error_from_unix(errno);
        }
 
-       blob->length = gotlen;
-       blob->data = talloc_realloc(mem_ctx, buf, gotlen);
-       if (!blob->data) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       *nread = gotlen;
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+static NTSTATUS ipv4_tcp_send(struct socket_context *sock, 
                              const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
 {
        ssize_t len;
index eda1597df7d85c7e992ba60af928d1aaaf12cfe4..3a3ce5fe8afbd839c25143b8e5d97f8c4760cddd 100644 (file)
@@ -155,18 +155,12 @@ static NTSTATUS unixdom_accept(struct socket_context *sock,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
-                            DATA_BLOB *blob, size_t wantlen, uint32_t flags)
+static NTSTATUS unixdom_recv(struct socket_context *sock, void *buf, 
+                            size_t wantlen, size_t *nread, uint32_t flags)
 {
        ssize_t gotlen;
-       void *buf;
        int flgs = 0;
 
-       buf = talloc(mem_ctx, wantlen);
-       if (!buf) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* TODO: we need to map all flags here */
        if (flags & SOCKET_FLAG_PEEK) {
                flgs |= MSG_PEEK;
@@ -176,26 +170,21 @@ static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
                flgs |= MSG_WAITALL;
        }
 
+       *nread = 0;
+
        gotlen = recv(sock->fd, buf, wantlen, flgs);
        if (gotlen == 0) {
-               talloc_free(buf);
                return NT_STATUS_END_OF_FILE;
        } else if (gotlen == -1) {
-               NTSTATUS status = unixdom_error(errno);
-               talloc_free(buf);
-               return status;
+               return unixdom_error(errno);
        }
 
-       blob->length = gotlen;
-       blob->data = talloc_realloc(mem_ctx, buf, gotlen);
-       if (!blob->data) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       *nread = gotlen;
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
+static NTSTATUS unixdom_send(struct socket_context *sock,
                             const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
 {
        ssize_t len;
index fa2d5650845b458de404cc02001d66bececdd42b..819d5698b1485b33159ecf5f99d6f911f282bb06 100644 (file)
@@ -83,7 +83,7 @@ static void sock_process_send(struct dcerpc_pipe *p)
                struct sock_blob *blob = sock->pending_send;
                NTSTATUS status;
                size_t sent;
-               status = socket_send(sock->sock, blob, &blob->data, &sent, 0);
+               status = socket_send(sock->sock, &blob->data, &sent, 0);
                if (NT_STATUS_IS_ERR(status)) {
                        sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
                        break;
@@ -116,7 +116,7 @@ static void sock_process_recv(struct dcerpc_pipe *p)
 {
        struct sock_private *sock = p->transport.private;
        NTSTATUS status;
-       DATA_BLOB blob;
+       size_t nread;
 
        if (sock->recv.data.data == NULL) {
                sock->recv.data = data_blob_talloc(sock, NULL, MIN_HDR_SIZE);
@@ -126,19 +126,19 @@ static void sock_process_recv(struct dcerpc_pipe *p)
        if (sock->recv.received < MIN_HDR_SIZE) {
                uint32_t frag_length;
 
-               status = socket_recv(sock->sock, sock, &blob, MIN_HDR_SIZE - sock->recv.received, 0);
+               status = socket_recv(sock->sock, 
+                                    sock->recv.data.data + sock->recv.received, 
+                                    MIN_HDR_SIZE - sock->recv.received, 
+                                    &nread, 0);
                if (NT_STATUS_IS_ERR(status)) {
                        sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
                        return;
                }
-               if (blob.length == 0) {
+               if (nread == 0) {
                        return;
                }
                
-               memcpy(sock->recv.data.data + sock->recv.received,
-                      blob.data, blob.length);
-               sock->recv.received += blob.length;
-               talloc_free(blob.data);
+               sock->recv.received += nread;
 
                if (sock->recv.received != MIN_HDR_SIZE) {
                        return;
@@ -155,18 +155,18 @@ static void sock_process_recv(struct dcerpc_pipe *p)
        }
 
        /* read in the rest of the packet */
-       status = socket_recv(sock->sock, sock, &blob, sock->recv.data.length - sock->recv.received, 0);
+       status = socket_recv(sock->sock, 
+                            sock->recv.data.data + sock->recv.received, 
+                            sock->recv.data.length - sock->recv.received, 
+                            &nread, 0);
        if (NT_STATUS_IS_ERR(status)) {
                sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
                return;
        }
-       if (blob.length == 0) {
+       if (nread == 0) {
                return;
        }
-       memcpy(sock->recv.data.data + sock->recv.received,
-              blob.data, blob.length);
-       sock->recv.received += blob.length;
-       talloc_free(blob.data);
+       sock->recv.received += nread;
 
        if (sock->recv.received != sock->recv.data.length) {
                return;
index 79d1f5a3bb36746e330323cb258e95e52c087524..32d1f0df3588c81113395471b80d2339b0d75c92 100644 (file)
@@ -38,7 +38,7 @@ static ssize_t dcerpc_write_fn(void *private, DATA_BLOB *out)
        struct socket_context *sock = private;
        size_t sendlen;
 
-       status = socket_send(sock, sock, out, &sendlen, 0);
+       status = socket_send(sock, out, &sendlen, 0);
        if (!NT_STATUS_IS_OK(status)) {
                return -1;
        }
@@ -131,7 +131,7 @@ static void add_socket_rpc_tcp_iface(struct server_service *service,
        struct server_socket *sock;
        struct dcesrv_socket_context *dcesrv_sock;
        uint16_t port = 0;
-       const char *ip_str = talloc_strdup(service, inet_ntoa(*ifip));
+       char *ip_str = talloc_strdup(service, inet_ntoa(*ifip));
                        
        if (e->ep_description.endpoint) 
                port = atoi(e->ep_description.endpoint);
@@ -251,22 +251,30 @@ void dcesrv_sock_recv(struct server_connection *conn, time_t t, uint16_t flags)
        NTSTATUS status;
        struct dcesrv_connection *dce_conn = conn->private_data;
        DATA_BLOB tmp_blob;
+       size_t nread;
 
-       DEBUG(10,("dcesrv_sock_recv\n"));
+       tmp_blob = data_blob_talloc(conn->socket, NULL, 0x1000);
+       if (tmp_blob.data == NULL) {
+               dcesrv_terminate_connection(dce_conn, "out of memory");
+               return;
+       }
 
-       status = socket_recv(conn->socket, conn->socket, &tmp_blob, 0x4000, 0);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_IS_ERR(status)) {
-                       dcesrv_terminate_connection(dce_conn, "eof on socket");
-                       return;
-               }
+       status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0);
+       if (NT_STATUS_IS_ERR(status)) {
+               dcesrv_terminate_connection(dce_conn, nt_errstr(status));
                return;
        }
+       if (nread == 0) {
+               return;
+       }
+
+       tmp_blob.length = nread;
 
        status = dcesrv_input(dce_conn, &tmp_blob);
        talloc_free(tmp_blob.data);
+
        if (!NT_STATUS_IS_OK(status)) {
-               dcesrv_terminate_connection(dce_conn, "eof on socket");
+               dcesrv_terminate_connection(dce_conn, nt_errstr(status));
                return;
        }
 
index 8bb77af759464730e65b66722e37b0b4028d1637..4ca9c9ffda0b00e32d0ccb1b69e0a10558ddb881 100644 (file)
@@ -252,7 +252,7 @@ void req_send_reply_nosign(struct smbsrv_request *req)
        tmp_blob.data = req->out.buffer;
        tmp_blob.length = req->out.size;
 
-       status = socket_send(req->smb_conn->connection->socket, req, &tmp_blob, &sendlen, SOCKET_FLAG_BLOCK);
+       status = socket_send(req->smb_conn->connection->socket, &tmp_blob, &sendlen, SOCKET_FLAG_BLOCK);
        if (!NT_STATUS_IS_OK(status) || (req->out.size != sendlen)) {
                smbsrv_terminate_connection(req->smb_conn, "failed to send reply\n");
                return;
index b7d54c8deee49d14392133d28a3506eb7c29c357..d6022ef63eea6980dad807671b1a058eb823c9a3 100644 (file)
@@ -64,17 +64,19 @@ static struct smbsrv_request *receive_smb_request(struct smbsrv_connection *smb_
        ssize_t len, len2;
        DATA_BLOB tmp_blob;
        struct smbsrv_request *req;
+       char hdr[4];
+       size_t nread;
 
-       status = socket_recv(smb_conn->connection->socket, smb_conn, &tmp_blob, 4, SOCKET_FLAG_BLOCK|SOCKET_FLAG_PEEK);
+       status = socket_recv(smb_conn->connection->socket, hdr, 
+                            4, &nread, SOCKET_FLAG_BLOCK|SOCKET_FLAG_PEEK);
        if (!NT_STATUS_IS_OK(status)) {
                return NULL;
        }
-       if (tmp_blob.length != 4) {
+       if (nread != 4) {
                return NULL;
        }
 
-       len = smb_len(tmp_blob.data);
-       talloc_free(tmp_blob.data);
+       len = smb_len(hdr);
 
        req = init_smb_request(smb_conn);
 
@@ -83,11 +85,18 @@ static struct smbsrv_request *receive_smb_request(struct smbsrv_connection *smb_
 
        len2 = len + NBT_HDR_SIZE;
 
-       status = socket_recv(smb_conn->connection->socket, req, &tmp_blob, len2, SOCKET_FLAG_BLOCK);
+       tmp_blob = data_blob_talloc(req, NULL, len2);
+       if (tmp_blob.data == NULL) {
+               return NULL;
+       }
+
+       status = socket_recv(smb_conn->connection->socket, 
+                            tmp_blob.data, len2, 
+                            &nread, SOCKET_FLAG_BLOCK);
        if (!NT_STATUS_IS_OK(status)) {
                return NULL;
        }
-       if (tmp_blob.length != len2) {
+       if (nread != len2) {
                return NULL;
        }