From 63ba8383e196bc41d18c7b9a8a80578eb9430188 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 23 Jan 2005 23:23:26 +0000 Subject: r4949: First version of a fetchfile composite function which connects to a server and loads a file. Needs a smb url parsing wrapper. Volker (This used to be commit fa435bf7c878d4a5beb6afb2ed6e2990abc11e82) --- source4/include/structs.h | 1 + source4/libcli/composite/composite.h | 19 ++++ source4/libcli/composite/fetchfile.c | 187 +++++++++++++++++++++++++++++++++++ source4/libcli/config.mk | 3 +- source4/torture/raw/composite.c | 99 +++++++++++++++++++ 5 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 source4/libcli/composite/fetchfile.c diff --git a/source4/include/structs.h b/source4/include/structs.h index 11519fd56e..29a6589a86 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -143,6 +143,7 @@ struct smb_composite_loadfile; struct smb_composite_savefile; struct smb_composite_connect; struct smb_composite_sesssetup; +struct smb_composite_fetchfile; struct nbt_name; struct nbt_name_packet; diff --git a/source4/libcli/composite/composite.h b/source4/libcli/composite/composite.h index 35d6d94878..cb8cee779c 100644 --- a/source4/libcli/composite/composite.h +++ b/source4/libcli/composite/composite.h @@ -65,6 +65,25 @@ struct smb_composite_loadfile { } out; }; +struct smb_composite_fetchfile { + struct { + const char *dest_host; + int port; + const char *called_name; + const char *calling_name; + const char *service; + const char *service_type; + const char *user; + const char *domain; + const char *password; + const char *filename; + } in; + struct { + uint8_t *data; + uint32_t size; + } out; +}; + /* a composite open/write(s)/close request that saves a whole file from memory. Used as a demo of the composite system. diff --git a/source4/libcli/composite/fetchfile.c b/source4/libcli/composite/fetchfile.c new file mode 100644 index 0000000000..f18657c452 --- /dev/null +++ b/source4/libcli/composite/fetchfile.c @@ -0,0 +1,187 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Volker Lendecke 2005 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for loading a whole file into memory +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "librpc/gen_ndr/ndr_security.h" + +enum fetchfile_stage {FETCHFILE_CONNECT, + FETCHFILE_READ}; + +struct fetchfile_state { + enum fetchfile_stage stage; + struct smb_composite_fetchfile *io; + struct smbcli_composite *req; + struct smb_composite_connect *connect; + struct smb_composite_loadfile *loadfile; +}; + +static void fetchfile_composite_handler(struct smbcli_composite *req); + +static NTSTATUS fetchfile_connect(struct smbcli_composite *c, + struct smb_composite_fetchfile *io) +{ + NTSTATUS status; + struct fetchfile_state *state; + state = talloc_get_type(c->private, struct fetchfile_state); + + status = smb_composite_connect_recv(state->req, c); + NT_STATUS_NOT_OK_RETURN(status); + + printf("connect done\n"); + + state->loadfile = talloc(state, struct smb_composite_loadfile); + NT_STATUS_NOT_OK_RETURN(status); + + state->loadfile->in.fname = io->in.filename; + + state->req = smb_composite_loadfile_send(state->connect->out.tree, + state->loadfile); + NT_STATUS_HAVE_NO_MEMORY(state->req); + + state->req->async.private = c; + state->req->async.fn = fetchfile_composite_handler; + + state->stage = FETCHFILE_READ; + c->event_ctx = talloc_reference(c, state->req->event_ctx); + + printf("load started\n"); + + return NT_STATUS_OK; +} + +static NTSTATUS fetchfile_read(struct smbcli_composite *c, + struct smb_composite_fetchfile *io) +{ + NTSTATUS status; + struct fetchfile_state *state; + state = talloc_get_type(c->private, struct fetchfile_state); + + printf("read event\n"); + + status = smb_composite_loadfile_recv(state->req, NULL); + NT_STATUS_NOT_OK_RETURN(status); + + printf("read done\n"); + + io->out.data = state->loadfile->out.data; + io->out.size = state->loadfile->out.size; + + c->state = SMBCLI_REQUEST_DONE; + if (c->async.fn) + c->async.fn(c); + + return NT_STATUS_OK; +} + +static void fetchfile_state_handler(struct smbcli_composite *c) +{ + struct fetchfile_state *state; + NTSTATUS status; + + state = talloc_get_type(c->private, struct fetchfile_state); + + /* when this handler is called, the stage indicates what + call has just finished */ + switch (state->stage) { + case FETCHFILE_CONNECT: + status = fetchfile_connect(c, state->io); + break; + case FETCHFILE_READ: + status = fetchfile_read(c, state->io); + break; + } + + if (!NT_STATUS_IS_OK(status)) { + c->status = status; + c->state = SMBCLI_REQUEST_ERROR; + if (c->async.fn) { + c->async.fn(c); + } + } +} + +static void fetchfile_composite_handler(struct smbcli_composite *req) +{ + struct smbcli_composite *c = talloc_get_type(req->async.private, + struct smbcli_composite); + return fetchfile_state_handler(c); +} + +struct smbcli_composite *smb_composite_fetchfile_send(struct smb_composite_fetchfile *io, + struct event_context *event_ctx) +{ + struct smbcli_composite *c; + struct fetchfile_state *state; + + c = talloc_zero(NULL, struct smbcli_composite); + if (c == NULL) goto failed; + + state = talloc(c, struct fetchfile_state); + if (state == NULL) goto failed; + + state->connect = talloc(state, struct smb_composite_connect); + if (state->connect == NULL) goto failed; + + state->io = io; + + state->connect->in.dest_host = io->in.dest_host; + state->connect->in.port = io->in.port; + state->connect->in.called_name = io->in.called_name; + state->connect->in.calling_name = io->in.calling_name; + state->connect->in.service = io->in.service; + state->connect->in.service_type = io->in.service_type; + state->connect->in.user = io->in.user; + state->connect->in.domain = io->in.domain; + state->connect->in.password = io->in.password; + + state->req = smb_composite_connect_send(state->connect, event_ctx); + if (state->req == NULL) goto failed; + + state->req->async.private = c; + state->req->async.fn = fetchfile_composite_handler; + + c->state = SMBCLI_REQUEST_SEND; + state->stage = FETCHFILE_CONNECT; + c->event_ctx = talloc_reference(c, state->req->event_ctx); + c->private = state; + + return c; + failed: + talloc_free(c); + return NULL; +} + +NTSTATUS smb_composite_fetchfile_recv(struct smbcli_composite *c, + TALLOC_CTX *mem_ctx) +{ + return smb_composite_wait(c); +} + +NTSTATUS smb_composite_fetchfile(struct smb_composite_fetchfile *io, + TALLOC_CTX *mem_ctx) +{ + struct smbcli_composite *c = smb_composite_fetchfile_send(io, NULL); + return smb_composite_fetchfile_recv(c, mem_ctx); +} diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index a43644f197..806ef775dc 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -18,7 +18,8 @@ ADD_OBJ_FILES = \ libcli/composite/loadfile.o \ libcli/composite/savefile.o \ libcli/composite/connect.o \ - libcli/composite/sesssetup.o + libcli/composite/sesssetup.o \ + libcli/composite/fetchfile.o [SUBSYSTEM::LIBCLI_NBT] ADD_OBJ_FILES = \ diff --git a/source4/torture/raw/composite.c b/source4/torture/raw/composite.c index 080db4f2c2..5c09848f52 100644 --- a/source4/torture/raw/composite.c +++ b/source4/torture/raw/composite.c @@ -108,6 +108,104 @@ static BOOL test_loadfile(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) return True; } +/* + test a simple savefile/loadfile combination +*/ +static BOOL test_fetchfile(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + const char *fname = BASEDIR "\\test.txt"; + NTSTATUS status; + struct smb_composite_savefile io1; + struct smb_composite_fetchfile io2; + struct smbcli_composite **c; + char *data; + int i; + size_t len = random() % 10000; + const int num_ops = 10; + struct event_context *event_ctx; + int *count = talloc_zero(mem_ctx, int); + + data = talloc_array(mem_ctx, uint8_t, len); + + generate_random_buffer(data, len); + + io1.in.fname = fname; + io1.in.data = data; + io1.in.size = len; + + printf("testing savefile\n"); + + status = smb_composite_savefile(cli->tree, &io1); + if (!NT_STATUS_IS_OK(status)) { + printf("savefile failed: %s\n", nt_errstr(status)); + return False; + } + + io2.in.dest_host = lp_parm_string(-1, "torture", "host"); + io2.in.port = 0; + io2.in.called_name = lp_parm_string(-1, "torture", "host"); + io2.in.calling_name = lp_netbios_name(); + io2.in.service = lp_parm_string(-1, "torture", "share"); + io2.in.service_type = "A:"; + io2.in.user = lp_parm_string(-1, "torture", "username"); + io2.in.domain = lp_parm_string(-1, "torture", "userdomain"); + io2.in.password = lp_parm_string(-1, "torture", "password"); + io2.in.filename = fname; + + printf("testing parallel fetchfile with %d ops\n", num_ops); + + event_ctx = event_context_init(mem_ctx); + c = talloc_array(mem_ctx, struct smbcli_composite *, num_ops); + + for (i=0; iasync.fn = loadfile_complete; + c[i]->async.private = count; + } + + printf("waiting for completion\n"); + + while (*count != num_ops) { + event_loop_once(event_ctx); +#if 0 + /* Attempt to kill the event ... To fix -- vl */ + for (i=0; istate == SMBCLI_REQUEST_ERROR) { + printf("error in %d\n", i); msleep(1000); + talloc_free(c[i]); c[i]=NULL; + } + } +#endif + printf("count=%d\r", *count); + fflush(stdout); + } + printf("count=%d\n", *count); + + for (i=0;isession); -- cgit