1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

r3306: the main smb server code now handles non-blocking socket receives. I

haven't marked the socket non-blocking yet as I haven't checked that
the send path is OK for non-blocking.
This commit is contained in:
Andrew Tridgell 2004-10-28 04:36:12 +00:00 committed by Gerald (Jerry) Carter
parent e4216da824
commit bda978cc2a
2 changed files with 80 additions and 46 deletions

View File

@ -55,54 +55,87 @@ BOOL req_send_oplock_break(struct smbsrv_tcon *tcon, uint16_t fnum, uint8_t leve
return True;
}
static void construct_reply(struct smbsrv_request *req);
/****************************************************************************
receive a SMB request from the wire, forming a request_context from the result
receive a SMB request header from the wire, forming a request_context
from the result
****************************************************************************/
static struct smbsrv_request *receive_smb_request(struct smbsrv_connection *smb_conn)
static NTSTATUS receive_smb_request(struct smbsrv_connection *smb_conn)
{
NTSTATUS status;
ssize_t len, len2;
DATA_BLOB tmp_blob;
ssize_t len;
struct smbsrv_request *req;
char hdr[4];
size_t nread;
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 (nread != 4) {
return NULL;
/* 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_p(req, char, 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;
}
len = smb_len(hdr);
req = smb_conn->partial_req;
req = init_smb_request(smb_conn);
/* 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 (nread == 0) {
return NT_STATUS_OK;
}
req->in.size += nread;
GetTimeOfDay(&req->request_time);
req->chained_fnum = -1;
len2 = len + NBT_HDR_SIZE;
tmp_blob = data_blob_talloc(req, NULL, len2);
if (tmp_blob.data == NULL) {
return NULL;
/* 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, 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,
tmp_blob.data, len2,
&nread, SOCKET_FLAG_BLOCK);
if (!NT_STATUS_IS_OK(status)) {
return NULL;
req->in.buffer + req->in.size,
len - req->in.size,
&nread, 0);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
if (nread != len2) {
return NULL;
if (nread == 0) {
return NT_STATUS_OK;
}
/* fill in the rest of the req->in structure */
req->in.buffer = tmp_blob.data;
req->in.size = len2;
req->in.size += nread;
if (req->in.size != len) {
return NT_STATUS_OK;
}
/* we have a full packet */
GetTimeOfDay(&req->request_time);
req->chained_fnum = -1;
req->in.allocated = req->in.size;
req->in.hdr = req->in.buffer + NBT_HDR_SIZE;
req->in.vwv = req->in.hdr + HDR_VWV;
@ -125,7 +158,11 @@ static struct smbsrv_request *receive_smb_request(struct smbsrv_connection *smb_
}
}
return req;
smb_conn->partial_req = NULL;
construct_reply(req);
return NT_STATUS_OK;
}
/*
@ -746,23 +783,20 @@ static void smbsrv_init(struct server_service *service, const struct model_ops *
*/
static void smbsrv_recv(struct server_connection *conn, time_t t, uint16_t flags)
{
struct smbsrv_request *req;
struct smbsrv_connection *smb_conn = conn->private_data;
NTSTATUS status;
DEBUG(10,("smbsrv_recv\n"));
req = receive_smb_request(smb_conn);
if (!req) {
status = receive_smb_request(smb_conn);
if (NT_STATUS_IS_ERR(status)) {
conn->event.fde->flags = 0;
smbsrv_terminate_connection(smb_conn, "receive error");
smbsrv_terminate_connection(smb_conn, nt_errstr(status));
return;
}
construct_reply(req);
/* free up temporary memory */
lp_talloc_free();
return;
}
/*
@ -806,15 +840,12 @@ static void smbsrv_close(struct server_connection *conn, const char *reason)
*/
void smbd_process_async(struct smbsrv_connection *smb_conn)
{
struct smbsrv_request *req;
NTSTATUS status;
req = receive_smb_request(smb_conn);
if (!req) {
smbsrv_terminate_connection(smb_conn, "receive error");
return;
status = receive_smb_request(smb_conn);
if (NT_STATUS_IS_ERR(status)) {
smbsrv_terminate_connection(smb_conn, nt_errstr(status));
}
construct_reply(req);
}

View File

@ -286,4 +286,7 @@ struct smbsrv_connection {
pid_t pid;
struct server_connection *connection;
/* this holds a partially received request */
struct smbsrv_request *partial_req;
};