diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-10-28 04:00:43 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:04:52 -0500 |
commit | c6888da1487ab301292c3d4d05d0464833f3ce57 (patch) | |
tree | 35660282f621edb23885c40bfc4634489def3d6d | |
parent | 9d1e2b29ebf14beae4fc63b2cb85f4e2d1798021 (diff) | |
download | samba-c6888da1487ab301292c3d4d05d0464833f3ce57.tar.gz samba-c6888da1487ab301292c3d4d05d0464833f3ce57.tar.bz2 samba-c6888da1487ab301292c3d4d05d0464833f3ce57.zip |
r3304: changed the API to lib/socket/ a little.
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)
-rw-r--r-- | source4/ldap_server/ldap_server.c | 23 | ||||
-rw-r--r-- | source4/lib/messaging/messaging.c | 36 | ||||
-rw-r--r-- | source4/lib/socket/socket.c | 12 | ||||
-rw-r--r-- | source4/lib/socket/socket.h | 8 | ||||
-rw-r--r-- | source4/lib/socket/socket_ipv4.c | 41 | ||||
-rw-r--r-- | source4/lib/socket/socket_unix.c | 25 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_sock.c | 28 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_sock.c | 28 | ||||
-rw-r--r-- | source4/smb_server/request.c | 2 | ||||
-rw-r--r-- | source4/smb_server/smb_server.c | 21 |
10 files changed, 108 insertions, 116 deletions
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 6ce2dfdd79..70191c4827 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -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); diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index afd18b4f2f..09d0c43934 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -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; diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index f5ee84a7cc..94d8b5bada 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -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) diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index a089a1b78a..6562bb376b 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -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); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index f280f804ef..4de0d8cebe 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -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; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index eda1597df7..3a3ce5fe8a 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -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; diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c index fa2d565084..819d5698b1 100644 --- a/source4/librpc/rpc/dcerpc_sock.c +++ b/source4/librpc/rpc/dcerpc_sock.c @@ -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; diff --git a/source4/rpc_server/dcerpc_sock.c b/source4/rpc_server/dcerpc_sock.c index 79d1f5a3bb..32d1f0df35 100644 --- a/source4/rpc_server/dcerpc_sock.c +++ b/source4/rpc_server/dcerpc_sock.c @@ -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; } diff --git a/source4/smb_server/request.c b/source4/smb_server/request.c index 8bb77af759..4ca9c9ffda 100644 --- a/source4/smb_server/request.c +++ b/source4/smb_server/request.c @@ -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; diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index b7d54c8dee..d6022ef63e 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -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; } |