[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Tue Nov 10 15:49:14 MST 2009


The branch, master has been updated
       via  2b75933... s3: Convert libsmb/cli_message to the async API
      from  fd4061d... s4:dcesrv_samr - Add more checks for invalid levels

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 2b759339601ad853588cb74e986a7a88301aea17
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Nov 10 19:49:41 2009 +0100

    s3: Convert libsmb/cli_message to the async API

-----------------------------------------------------------------------

Summary of changes:
 source3/client/client.c     |   54 ++----
 source3/include/proto.h     |   15 +-
 source3/libsmb/climessage.c |  445 +++++++++++++++++++++++++++++++++----------
 3 files changed, 372 insertions(+), 142 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/client/client.c b/source3/client/client.c
index 6b273b4..435ede9 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -243,51 +243,29 @@ static size_t push_source(uint8_t *buf, size_t n, void *priv)
 
 static void send_message(const char *username)
 {
-	int total_len = 0;
-	int grp_id;
-
-	if (!cli_message_start(cli, desthost, username, &grp_id)) {
-		d_printf("message start: %s\n", cli_errstr(cli));
-		return;
-	}
-
-
-	d_printf("Connected. Type your message, ending it with a Control-D\n");
-
-	while (!feof(stdin) && total_len < 1600) {
-		int maxlen = MIN(1600 - total_len,127);
-		char msg[1024];
-		int l=0;
-		int c;
-
-		ZERO_ARRAY(msg);
+	char buf[1600];
+	NTSTATUS status;
+	int i;
 
-		for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
-			if (c == '\n')
-				msg[l++] = '\r';
-			msg[l] = c;
-		}
+	d_printf("Type your message, ending it with a Control-D\n");
 
-		if ((total_len > 0) && (strlen(msg) == 0)) {
+	i = 0;
+	while (i<sizeof(buf)-2) {
+		int c = fgetc(stdin);
+		if (c == EOF) {
 			break;
 		}
-
-		if (!cli_message_text(cli, msg, l, grp_id)) {
-			d_printf("SMBsendtxt failed (%s)\n",cli_errstr(cli));
-			return;
+		if (c == '\n') {
+			buf[i++] = '\r';
 		}
-
-		total_len += l;
+		buf[i++] = c;
 	}
+	buf[i] = '\0';
 
-	if (total_len >= 1600)
-		d_printf("the message was truncated to 1600 bytes\n");
-	else
-		d_printf("sent %d bytes\n",total_len);
-
-	if (!cli_message_end(cli, grp_id)) {
-		d_printf("SMBsendend failed (%s)\n",cli_errstr(cli));
-		return;
+	status = cli_message(cli, desthost, username, buf);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_fprintf(stderr, "cli_message returned %s\n",
+			  nt_errstr(status));
 	}
 }
 
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 6955593..0993340 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2732,13 +2732,14 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
 
 /* The following definitions come from libsmb/climessage.c  */
 
-int cli_message_start_build(struct cli_state *cli, const char *host, const char *username);
-bool cli_message_start(struct cli_state *cli, const char *host, const char *username,
-			      int *grp);
-int cli_message_text_build(struct cli_state *cli, const char *msg, int len, int grp);
-bool cli_message_text(struct cli_state *cli, const char *msg, int len, int grp);
-int cli_message_end_build(struct cli_state *cli, int grp);
-bool cli_message_end(struct cli_state *cli, int grp);
+struct tevent_req *cli_message_send(TALLOC_CTX *mem_ctx,
+				    struct tevent_context *ev,
+				    struct cli_state *cli,
+				    const char *host, const char *username,
+				    const char *message);
+NTSTATUS cli_message_recv(struct tevent_req *req);
+NTSTATUS cli_message(struct cli_state *cli, const char *host,
+		     const char *username, const char *message);
 
 /* The following definitions come from libsmb/clioplock.c  */
 
diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c
index 6538902..2c8ef58 100644
--- a/source3/libsmb/climessage.c
+++ b/source3/libsmb/climessage.c
@@ -1,162 +1,413 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    client message handling routines
    Copyright (C) Andrew Tridgell 1994-1998
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 
-/****************************************************************************
- Start a message sequence.
-****************************************************************************/
+struct cli_message_start_state {
+	uint16_t grp;
+};
+
+static void cli_message_start_done(struct tevent_req *subreq);
 
-int cli_message_start_build(struct cli_state *cli, const char *host, const char *username)
+static struct tevent_req *cli_message_start_send(TALLOC_CTX *mem_ctx,
+						 struct tevent_context *ev,
+						 struct cli_state *cli,
+						 const char *host,
+						 const char *username)
 {
-	char *p;
+	struct tevent_req *req, *subreq;
+	struct cli_message_start_state *state;
+	char *htmp = NULL;
+	char *utmp = NULL;
+	size_t hlen, ulen;
+	uint8_t *bytes, *p;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_message_start_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_DOS,
+				   username, strlen(username)+1,
+				   &utmp, &ulen, true)) {
+		goto fail;
+	}
+	if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_DOS,
+				   host, strlen(host)+1,
+				   &htmp, &hlen, true)) {
+		goto fail;
+	}
 
-	/* construct a SMBsendstrt command */
-	memset(cli->outbuf,'\0',smb_size);
-	cli_set_message(cli->outbuf,0,0,True);
-	SCVAL(cli->outbuf,smb_com,SMBsendstrt);
-	SSVAL(cli->outbuf,smb_tid,cli->cnum);
-	cli_setup_packet(cli);
+	bytes = talloc_array(state, uint8_t, ulen+hlen+2);
+	if (bytes == NULL) {
+		goto fail;
+	}
+	p = bytes;
 
-	p = smb_buf(cli->outbuf);
 	*p++ = 4;
-	p += clistr_push(cli, p, username,
-			cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_ASCII|STR_TERMINATE);
+	memcpy(p, utmp, ulen);
 	*p++ = 4;
-	p += clistr_push(cli, p, host,
-			cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_ASCII|STR_TERMINATE);
+	memcpy(p, htmp, hlen);
+	TALLOC_FREE(htmp);
+	TALLOC_FREE(utmp);
+
+	subreq = cli_smb_send(state, ev, cli, SMBsendstrt, 0, 0, NULL,
+			      talloc_get_size(bytes), bytes);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_message_start_done, req);
+	return req;
+fail:
+	TALLOC_FREE(htmp);
+	TALLOC_FREE(utmp);
+	tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+	return tevent_req_post(req, ev);
+}
 
-	cli_setup_bcc(cli, p);
+static void cli_message_start_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_message_start_state *state = tevent_req_data(
+		req, struct cli_message_start_state);
+	NTSTATUS status;
+	uint8_t wct;
+	uint16_t *vwv;
+
+	status = cli_smb_recv(subreq, 0, &wct, &vwv, NULL, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(subreq);
+		tevent_req_nterror(req, status);
+		return;
+	}
+	if (wct >= 1) {
+		state->grp = SVAL(vwv+0, 0);
+	} else {
+		state->grp = 0;
+	}
+	TALLOC_FREE(subreq);
+	tevent_req_done(req);
+}
 
-	return(PTR_DIFF(p, cli->outbuf));
+static NTSTATUS cli_message_start_recv(struct tevent_req *req,
+				       uint16_t *pgrp)
+{
+	struct cli_message_start_state *state = tevent_req_data(
+		req, struct cli_message_start_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	*pgrp = state->grp;
+	return NT_STATUS_OK;
 }
 
-bool cli_message_start(struct cli_state *cli, const char *host, const char *username,
-			      int *grp)
+struct cli_message_text_state {
+	uint16_t vwv;
+};
+
+static void cli_message_text_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_message_text_send(TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct cli_state *cli,
+						uint16_t grp,
+						const char *msg,
+						int msglen)
 {
-	cli_message_start_build(cli, host, username);
-	cli_send_smb(cli);
+	struct tevent_req *req, *subreq;
+	struct cli_message_text_state *state;
+	char *tmp;
+	size_t tmplen;
+	uint8_t *bytes;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_message_text_state);
+	if (req == NULL) {
+		return NULL;
+	}
 
-	if (!cli_receive_smb(cli)) {
-		return False;
+	SSVAL(&state->vwv, 0, grp);
+
+	if (convert_string_talloc(talloc_tos(), CH_UNIX, CH_DOS, msg, msglen,
+				  &tmp, &tmplen, true)) {
+		msg = tmp;
+		msglen = tmplen;
+	} else {
+		DEBUG(3, ("Conversion failed, sending message in UNIX "
+			  "charset\n"));
+		tmp = NULL;
 	}
 
-	if (cli_is_error(cli)) return False;
+	bytes = talloc_array(state, uint8_t, msglen+3);
+	if (tevent_req_nomem(bytes, req)) {
+		TALLOC_FREE(tmp);
+		return tevent_req_post(req, ev);
+	}
+	SCVAL(bytes, 0, 0);	/* pad */
+	SSVAL(bytes, 1, msglen);
+	memcpy(bytes+3, msg, msglen);
+	TALLOC_FREE(tmp);
+
+	subreq = cli_smb_send(state, ev, cli, SMBsendtxt, 0, 1, &state->vwv,
+			      talloc_get_size(bytes), bytes);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_message_text_done, req);
+	return req;
+}
 
-	*grp = SVAL(cli->inbuf,smb_vwv0);
+static void cli_message_text_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+	tevent_req_done(req);
+}
 
-	return True;
+static NTSTATUS cli_message_text_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
 }
 
-/****************************************************************************
- Send a message
-****************************************************************************/
+struct cli_message_end_state {
+	uint16_t vwv;
+};
 
-int cli_message_text_build(struct cli_state *cli, const char *msg, int len, int grp)
+static void cli_message_end_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_message_end_send(TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct cli_state *cli,
+						uint16_t grp)
 {
-	char *msgdos;
-	size_t lendos;
-	char *p;
-
-	memset(cli->outbuf,'\0',smb_size);
-	cli_set_message(cli->outbuf,1,0,True);
-	SCVAL(cli->outbuf,smb_com,SMBsendtxt);
-	SSVAL(cli->outbuf,smb_tid,cli->cnum);
-	cli_setup_packet(cli);
-
-	SSVAL(cli->outbuf,smb_vwv0,grp);
-
-	p = smb_buf(cli->outbuf);
-	*p++ = 1;
-
-	if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_DOS, msg, len,
-		(void **)(void *)&msgdos, &lendos, True) || !msgdos) {
-		DEBUG(3,("Conversion failed, sending message in UNIX charset\n"));
-		SSVAL(p, 0, len); p += 2;
-		if (len > cli->bufsize - PTR_DIFF(p,cli->outbuf)) {
-			return -1;
-		}
-		memcpy(p, msg, len);
-		p += len;
-	} else {
-		SSVAL(p, 0, lendos); p += 2;
-		if (lendos > cli->bufsize - PTR_DIFF(p,cli->outbuf)) {
-			return -1;
-		}
-		memcpy(p, msgdos, lendos);
-		p += lendos;
-		TALLOC_FREE(msgdos);
+	struct tevent_req *req, *subreq;
+	struct cli_message_end_state *state;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_message_end_state);
+	if (req == NULL) {
+		return NULL;
 	}
 
-	cli_setup_bcc(cli, p);
+	SSVAL(&state->vwv, 0, grp);
+
+	subreq = cli_smb_send(state, ev, cli, SMBsendend, 0, 1, &state->vwv,
+			      0, NULL);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_message_end_done, req);
+	return req;
+}
 
-	return(PTR_DIFF(p, cli->outbuf));
+static void cli_message_end_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+	tevent_req_done(req);
 }
 
-bool cli_message_text(struct cli_state *cli, const char *msg, int len, int grp)
+static NTSTATUS cli_message_end_recv(struct tevent_req *req)
 {
-	cli_message_text_build(cli, msg, len, grp);
+	return tevent_req_simple_recv_ntstatus(req);
+}
 
-	cli_send_smb(cli);
+struct cli_message_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+	size_t sent;
+	const char *message;
+	uint16_t grp;
+};
+
+static void cli_message_started(struct tevent_req *subreq);
+static void cli_message_sent(struct tevent_req *subreq);
+static void cli_message_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_message_send(TALLOC_CTX *mem_ctx,
+				    struct tevent_context *ev,
+				    struct cli_state *cli,
+				    const char *host, const char *username,
+				    const char *message)
+{
+	struct tevent_req *req, *subreq;
+	struct cli_message_state *state;
 
-	if (!cli_receive_smb(cli)) {
-		return False;
+	req = tevent_req_create(mem_ctx, &state, struct cli_message_state);
+	if (req == NULL) {
+		return NULL;
 	}
+	state->ev = ev;
+	state->cli = cli;
+	state->sent = 0;
+	state->message = message;
+
+	subreq = cli_message_start_send(state, ev, cli, host, username);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_message_started, req);
+	return req;
+}
 
-	if (cli_is_error(cli)) return False;
+static void cli_message_started(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_message_state *state = tevent_req_data(
+		req, struct cli_message_state);
+	NTSTATUS status;
+	size_t thistime;
+
+	status = cli_message_start_recv(subreq, &state->grp);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
 
-	return True;
-}
+	thistime = MIN(127, strlen(state->message));
 
-/****************************************************************************
- End a message.
-****************************************************************************/
+	subreq = cli_message_text_send(state, state->ev, state->cli,
+				       state->grp, state->message, thistime);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	state->sent += thistime;
+	tevent_req_set_callback(subreq, cli_message_sent, req);
+}
 
-int cli_message_end_build(struct cli_state *cli, int grp)
+static void cli_message_sent(struct tevent_req *subreq)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list