3
Example streaming DIME client for DIME server (dimeserver.cpp).
4
Supports three methods:
6
putData stores multiple data sets on the server and returns
7
named references to each data set
8
getData retrieves data sets given named references.
9
getImage is an example file-based image retrieval method
11
Change the endpoint in dime.h to your needs.
13
Copyright (C) 2000-2003 Robert A. van Engelen, Genivia, Inc.
18
Start dimeserver on your host at port 8085 (see dimeserver.cpp):
24
dimeclient [-p] [-g] [-i] name ...
27
Without args retrieves image.jpg
29
Retrieves image stored under name
30
dimeclient -p name1 name2 ...
31
Stores files name1, name2, etc. The storage keys are printed.
32
The keys provide access to the data on the server.
33
dimeclient -g name1 name2 ...
34
Retrieves files stored under keys name1, name2, etc.
35
The keys must correspond to the keys returned when storing
36
files. Files are stored locally under the key name.
38
Unix/Linux: add a sigpipe handler to avoid broken pipes.
45
// use the default endpoint set in dime.h for demo:
46
const char *endpoint = NULL;
47
// use the localhost for -p and -g (put and get):
48
const char *localhost = "http://localhost:8085";
50
////////////////////////////////////////////////////////////////////////////////
54
////////////////////////////////////////////////////////////////////////////////
56
static void putData(struct soap*, int, char**);
57
static void getData(struct soap*, int, char**);
58
static void getImage(struct soap*, char*);
59
static void saveData(ns__Data&, const char*);
61
////////////////////////////////////////////////////////////////////////////////
63
// Streaming DIME attachment content handlers
65
////////////////////////////////////////////////////////////////////////////////
67
static void *dime_read_open(struct soap*, void*, const char*, const char*, const char*);
68
static void dime_read_close(struct soap*, void*);
69
static size_t dime_read(struct soap*, void*, char*, size_t);
70
static void *dime_write_open(struct soap*, const char*, const char*, const char*);
71
static void dime_write_close(struct soap*, void*);
72
static int dime_write(struct soap*, void*, const char*, size_t);
74
////////////////////////////////////////////////////////////////////////////////
78
////////////////////////////////////////////////////////////////////////////////
80
int main(int argc, char **argv)
82
// use HTTP 1.1 chunking
83
// HTTP chunking allows streaming of DIME content without requiring DIME attachment size to be set
84
// DIME attachments can be streamed without chunking ONLY if the attachment size is set
85
soap_init1(&soap, SOAP_IO_CHUNK);
87
soap.fdimereadopen = dime_read_open;
88
soap.fdimereadclose = dime_read_close;
89
soap.fdimeread = dime_read;
90
soap.fdimewriteopen = dime_write_open;
91
soap.fdimewriteclose = dime_write_close;
92
soap.fdimewrite = dime_write;
93
// connect timeout value (not supported by Linux)
94
soap.connect_timeout = 10;
96
soap.send_timeout = 30;
97
soap.recv_timeout = 30;
98
// Unix/Linux SIGPIPE, this is OS dependent:
99
// soap.accept_flags = SO_NOSIGPIPE; // some systems like this
100
// soap.socket_flags = MSG_NOSIGNAL; // others need this
101
// signal(SIGPIPE, sigpipe_handle); // or a sigpipe handler (portable)
108
getImage(&soap, name);
111
{ switch (argv[1][1])
113
endpoint = localhost;
114
putData(&soap, argc, argv);
117
endpoint = localhost;
118
getData(&soap, argc, argv);
121
fprintf(stderr, "Usage: [-p] [-g] name ...\n");
131
////////////////////////////////////////////////////////////////////////////////
135
////////////////////////////////////////////////////////////////////////////////
137
static void putData(struct soap *soap, int argc, char **argv)
140
data.resize(argc - 2);
141
for (int i = 2; i < argc; i++)
142
{ data[i - 2].__ptr = (unsigned char*)argv[i];
143
// MUST set id or type to enable DIME
144
// zero size indicates streaming DIME (this requires HTTP chunking)
145
data[i - 2].type = "";
147
if (soap_call_ns__putData(soap, endpoint, NULL, &data, &names))
148
soap_print_fault(soap, stderr);
150
{ printf("Data stored with keys:\n");
151
for (int j = 0; j < names.size(); j++)
152
printf("\t%s\n", names[j]);
153
printf("Use these keys to retrieve the data\n");
157
static void getData(struct soap *soap, int argc, char **argv)
160
names.resize(argc - 2);
161
for (int i = 2; i < argc; i++)
162
names[i - 2] = argv[i];
163
soap->user = (void*)names.__ptr;
164
if (soap_call_ns__getData(soap, endpoint, NULL, &names, &data))
165
soap_print_fault(soap, stderr);
167
{ for (int j = 0; j < data.size(); j++)
169
saveData(data[j], argv[j + 2]);
170
printf("Data retrieved\n");
174
static void getImage(struct soap *soap, char *name)
179
soap->user = (void*)temp.__ptr;
180
if (soap_call_ns__getImage(soap, endpoint, NULL, name, image))
181
soap_print_fault(soap, stderr);
184
printf("Got image %s size=%d type=%s through streaming DIME\n", name, image.__size, image.type?image.type:"");
186
printf("Got image %s type=%s through chunked streaming DIME\n", name, image.type?image.type:"");
189
{ printf("Got image %s\n", name);
190
saveData(image, name);
194
static void saveData(ns__Data& data, const char *name)
195
{ char *buf = (char*)data.__ptr;
196
int len = data.__size;
197
FILE *fd = fopen(name, "wb");
199
{ fprintf(stderr, "Cannot save file %s\n", name);
203
{ size_t nwritten = fwrite(buf, 1, len, fd);
205
{ fprintf(stderr, "Cannot write to %s\n", name);
211
printf("Saved file %s\n", name);
214
////////////////////////////////////////////////////////////////////////////////
216
// Streaming DIME attachment content handlers
218
////////////////////////////////////////////////////////////////////////////////
220
static void *dime_read_open(struct soap *soap, void *handle, const char *id, const char *type, const char *options)
222
// we should return NULL without setting soap->error if we don't want to use the streaming callback for this DIME attachment. The handle contains the non-NULL __ptr field value which should have been set in the application.
223
// return value of this function will be passed on to the fdimeread and fdimereadclose callbacks. The return value will not affect the __ptr field.
224
fd = fopen((char*)handle, "rb");
228
static void dime_read_close(struct soap *soap, void *handle)
229
{ fclose((FILE*)handle);
232
static size_t dime_read(struct soap *soap, void *handle, char *buf, size_t len)
233
{ return fread(buf, 1, len, (FILE*)handle);
236
static void *dime_write_open(struct soap *soap, const char *id, const char *type, const char *options)
237
{ // we can return NULL without setting soap->error if we don't want to use the streaming callback for this DIME attachment
240
// get file name from options (not '\0' terminated)
242
{ size_t len = ((unsigned char)options[2] << 8) | ((unsigned char)options[3]); // option string length
243
name = (char*)soap_malloc(soap, len + 1);
244
strncpy(name, options + 4, len);
246
handle = fopen(name, "wb");
248
{ soap->error = SOAP_EOF; // could not open file for writing
249
soap->errnum = errno; // get reason
254
soap->error = soap_receiver_fault(soap, "Cannot save to file, because no file name was present in attachment", NULL);
255
return (void*)handle;
258
static void dime_write_close(struct soap *soap, void *handle)
259
{ fclose((FILE*)handle);
262
static int dime_write(struct soap *soap, void *handle, const char *buf, size_t len)
264
{ size_t nwritten = fwrite(buf, 1, len, (FILE*)handle);
266
{ soap->errnum = errno; // get reason
275
////////////////////////////////////////////////////////////////////////////////
279
////////////////////////////////////////////////////////////////////////////////
290
////////////////////////////////////////////////////////////////////////////////
294
////////////////////////////////////////////////////////////////////////////////
296
arrayOfData::arrayOfData()
302
arrayOfData::arrayOfData(struct soap *soap, int n)
309
arrayOfData::~arrayOfData()
313
int arrayOfData::size()
317
void arrayOfData::resize(int n)
319
{ if (soap) // if created by soap environment
320
soap_delete(soap, __ptr); // then delete
328
__ptr = soap_new_ns__Data(soap, n);
330
__ptr = new ns__Data[n];
333
ns__Data& arrayOfData::operator[](int i) const
334
{ assert(__ptr && i >= 0 && i < __size);
338
////////////////////////////////////////////////////////////////////////////////
342
////////////////////////////////////////////////////////////////////////////////
344
arrayOfName::arrayOfName()
350
arrayOfName::arrayOfName(struct soap *soap, int n)
357
arrayOfName::~arrayOfName()
361
int arrayOfName::size()
365
void arrayOfName::resize(int n)
367
{ if (soap) // if created by soap environment
368
soap_delete(soap, __ptr); // then delete
377
__ptr = (char**)soap_malloc(soap, sizeof(char*) * n);
379
__ptr = (char**)malloc(sizeof(char*) * n);
384
char*& arrayOfName::operator[](int i) const
385
{ assert(__ptr && i >= 0 && i < __size);