1 /*----------------------------------------------------------------------------
2 Name: xmlBlaster/demo/c/socket/HelloWorld4.c
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Example for all remote method invocations.
6 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info>
7 Compile: cd xmlBlaster; build c
8 (Win: copy xmlBlaster\src\c\socket\pthreadVC2.dll to your PATH)
9 Manually:
10 cd xmlBlaster/src/c
11 gcc -g -Wall -pedantic -Wno-long-long -D_REENTRANT -I. -o HelloWorld4
12 ../../demo/c/socket/HelloWorld4.c util/?*.c socket/?*.c -pthread
13 Invoke: HelloWorld4 -help
14 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/protocol.socket.html
15 -----------------------------------------------------------------------------*/
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <XmlBlasterAccess.h>
20
21 /**
22 * Here we receive the callback messages from xmlBlaster
23 * @param xa 'this' pointer
24 * @param msgUnitArr The received messages, it is freed by the call after this method ends
25 * @param exception An OUT parameter to transport back an exception
26 * @see UpdateFp in XmlBlasterAccess.h
27 * @see UpdateFp in CallbackServerUnparsed.h
28 */
29 static bool myUpdate(struct XmlBlasterAccess* xa, MsgUnitArr *msgUnitArr,
30 XmlBlasterException *exception) {
31 size_t i;
32 bool testException = false;
33
34 for (i = 0; i < msgUnitArr->len; i++) {
35 char *xml = messageUnitToXml(&msgUnitArr->msgUnitArr[i]);
36 printf(
37 "[client4] CALLBACK update(): %p Asynchronous message update arrived:%s\n",
38 (void *) xa, xml);
39 xmlBlasterFree(xml);
40 msgUnitArr->msgUnitArr[i].responseQos = strcpyAlloc(
41 "<qos><state id='OK'/></qos>");
42 /* Return QoS: Everything is OK */
43 }
44 if (testException) {
45 strncpy0(exception->errorCode, "user.clientCode",
46 XMLBLASTEREXCEPTION_ERRORCODE_LEN);
47 strncpy0(exception->message, "I don't want these messages",
48 XMLBLASTEREXCEPTION_MESSAGE_LEN);
49 return false;
50 }
51
52 return true;
53 }
54
55 static void connectionListenerCb(struct XmlBlasterAccess *xa,
56 XBCONSTATE oldState, XBCONSTATE newState, XmlBlasterException *exception,
57 void *userData) {
58 const char *conStateUserData = (const char *) userData;
59 const char *errorCode = (exception == 0 || exception->errorCode == 0) ? ""
60 : exception->errorCode;
61 const char *message = (exception == 0 || exception->message == 0) ? ""
62 : exception->message;
63 printf("%p [%s] connectionListenerCb transition %s to %s %s %s\n",
64 (void *) xa, conStateUserData, connectionStateToStr(oldState),
65 connectionStateToStr(newState), errorCode, message);
66 }
67
68 #if defined(WINCE)
69 int _tmain(int argc, _TCHAR** argv_wcs) { /* wchar_t==_TCHAR */
70 char **argv = convertWcsArgv(argv_wcs, argc);
71 #else
72 /**
73 * Invoke: HelloWorld4 -logLevel TRACE
74 */
75 int main(int argc, const char* const * argv) {
76 #endif
77 int iarg;
78
79 /*
80 * callbackSessionId:
81 * Is created by the client and used to validate callback messages in update.
82 * This is sent on connect in ConnectQos.
83 * (Is different from the xmlBlaster secret session ID)
84 */
85 const char *callbackSessionId = "topSecret";
86 const char *conStateUserData = "client4";
87 XmlBlasterException xmlBlasterException;
88 XmlBlasterAccess *xa = 0;
89 int sleepInterval = 0;
90 char inchar;
91
92 printf(
93 "[client4] XmlBlaster %s C SOCKET client, try option '-help' if you need"
94 " usage informations\n", getXmlBlasterVersion());
95
96 for (iarg = 0; iarg < argc; iarg++) {
97 if (strcmp(argv[iarg], "-help") == 0 || strcmp(argv[iarg], "--help") == 0) {
98 char usage[XMLBLASTER_MAX_USAGE_LEN];
99 const char *pp =
100 "\n -sleepInterval Milliseconds to wait on callback messages [0]"
101 "\n\nExample:"
102 "\n HelloWorld4 -logLevel TRACE"
103 " -dispatch/connection/plugin/socket/hostname 192.168.2.9"
104 " -sleepInterval 100000";
105 printf("Usage:\nXmlBlaster C SOCKET client %s\n%s%s\n",
106 getXmlBlasterVersion(), XmlBlasterAccessUsage(usage), pp);
107 exit(EXIT_FAILURE);
108 } else if (strcmp(argv[iarg], "-sleepInterval") == 0 && iarg < argc - 1)
109 sleepInterval = atoi(argv[++iarg]);
110 }
111
112 xa = getXmlBlasterAccess(argc, (const char* const *) argv);
113 xa->registerConnectionListener(xa, connectionListenerCb,
114 (void*) conStateUserData);
115
116 { /* connect */
117 ConnectQos *connectQos;
118 ConnectReturnQos *connectReturnQos;
119 char connectQosStr[2048];
120 char callbackQos[1024];
121 sprintf(callbackQos,
122 "<queue relating='callback' maxEntries='50000' maxEntriesCache='10000'>"
123 " <callback type='SOCKET' sessionId='%.120s' pingInterval='30000'>"
124 " socket://127.0.0.1"
125 " </callback>"
126 "</queue>", callbackSessionId);
127 sprintf(connectQosStr, "<qos>"
128 " <securityService type='htpasswd' version='1.0'>"
129 " <![CDATA["
130 " <user>fritz</user>"
131 " <passwd>secret</passwd>"
132 " ]]>"
133 " </securityService>"
134 " <session name='client/fritz' timeout='0' maxSessions='1'/>"
135 "%.1024s"
136 "</qos>", callbackQos);
137
138 connectQos = createXmlBlasterQos(connectQosStr);
139 connectReturnQos = xa->connect(xa, connectQos, myUpdate,
140 &xmlBlasterException);
141 if (*xmlBlasterException.errorCode != 0) {
142 if (startsWith(xmlBlasterException.errorCode, "user.security")) {
143 printf(
144 "[client4] Caught exception during connect, giving up: errorCode=%s, message=%s\n",
145 xmlBlasterException.errorCode, xmlBlasterException.message);
146 freeXmlBlasterQos(connectQos);
147 freeXmlBlasterAccess(xa);
148 exit(EXIT_FAILURE);
149 }
150 printf(
151 "[client4] Caught exception during connect errorCode=%s, message=%s we continue in fail safe mode\n",
152 xmlBlasterException.errorCode, xmlBlasterException.message);
153 } else
154 printf("[client4] Connected to xmlBlaster, do some tests ...\n");
155 freeXmlBlasterQos(connectQos);
156 freeXmlBlasterReturnQos(connectReturnQos);
157 }
158
159 while ((inchar = getInputKey("Hit 'c' to continue or 'q' to quit")) != 'c') {
160 if (inchar == 'q') {
161 freeXmlBlasterAccess(xa);
162 exit(0);
163 }
164 }
165
166 { /* ping */
167 PingReturnQos *pingReturn = xa->ping(xa, 0, &xmlBlasterException);
168 if (pingReturn == 0) {
169 printf(
170 "[client4] ERROR: Pinging a connected server failed: errorCode=%s, message=%s\n",
171 xmlBlasterException.errorCode, xmlBlasterException.message);
172 freeXmlBlasterAccess(xa);
173 exit(EXIT_FAILURE);
174 } else {
175 printf("[client4] Pinging a connected server, response=%s\n",
176 pingReturn->returnQos);
177 freeXmlBlasterReturnQos(pingReturn);
178 }
179 }
180
181 { /* subscribe ... */
182 SubscribeKey *key = createXmlBlasterKey("<key oid='HelloWorld'/>");
183 /*const char *key = "<key queryType='XPATH'>//key</key>";*/
184 SubscribeQos *qos = createXmlBlasterQos(0); /* "<qos/>" */
185 SubscribeReturnQos *returnQos = 0;
186 printf("[client4] Subscribe message 'HelloWorld' ...\n");
187 returnQos = xa->subscribe(xa, key, qos, &xmlBlasterException);
188 if (*xmlBlasterException.errorCode != 0) {
189 printf(
190 "[client4] Caught exception in subscribe errorCode=%s, message=%s\n",
191 xmlBlasterException.errorCode, xmlBlasterException.message);
192 xa->disconnect(xa, 0, &xmlBlasterException);
193 freeXmlBlasterKey(key);
194 freeXmlBlasterQos(qos);
195 freeXmlBlasterAccess(xa);
196 exit(EXIT_FAILURE);
197 }
198 printf("[client4] Subscribe success, returned status is '%s' isOk=%d\n",
199 returnQos->returnQos, returnQos->isOk(returnQos));
200 freeXmlBlasterKey(key);
201 freeXmlBlasterQos(qos);
202 freeXmlBlasterReturnQos(returnQos);
203 }
204
205 if (sleepInterval > 0) {
206 printf(
207 "[client4] Sleeping now and wait on 'HelloWorld' updates (start a publisher somewhere) ...\n");
208 sleepMillis(sleepInterval);
209 }
210
211 { /* publish ... */
212 MsgUnit msgUnit;
213 PublishReturnQos *returnQos = 0;
214 memset(&msgUnit, 0, sizeof(MsgUnit));
215 printf("[client4] Publishing message 'HelloWorld' ...\n");
216 msgUnit.key = strcpyAlloc("<key oid='HelloWorld'/>");
217 msgUnit.content = strcpyAlloc("Some message payload");
218 msgUnit.contentLen = strlen(msgUnit.content);
219 msgUnit.qos = strcpyAlloc("<qos><persistent/></qos>");
220 returnQos = xa->publish(xa, &msgUnit, &xmlBlasterException);
221 freeMsgUnitData(&msgUnit);
222 if (*xmlBlasterException.errorCode != 0) {
223 printf(
224 "[client4] Caught exception in publish errorCode=%s, message=%s\n",
225 xmlBlasterException.errorCode, xmlBlasterException.message);
226 xa->disconnect(xa, 0, &xmlBlasterException);
227 freeXmlBlasterReturnQos(returnQos);
228 freeXmlBlasterAccess(xa);
229 exit(EXIT_FAILURE);
230 }
231 printf("[client4] Publish success, returned status is '%s'\n",
232 returnQos->returnQos);
233 freeXmlBlasterReturnQos(returnQos);
234 }
235
236 if (true) { /* publishArr */
237 PublishReturnQosArr* resp = 0;
238 MsgUnitArr holder;
239 memset(&holder, 0, sizeof(MsgUnitArr));
240 printf(
241 "[client4] Publishing messages 'HelloWorld0' and 'HelloWorld1' ...\n");
242 holder.len = 2;
243 holder.msgUnitArr = (MsgUnit *) calloc(holder.len, sizeof(MsgUnit));
244 holder.msgUnitArr[0].key = strcpyAlloc("<key oid='HelloWorld0'/>");
245 holder.msgUnitArr[0].content = strcpyAlloc("Some message payload");
246 holder.msgUnitArr[0].contentLen = strlen(holder.msgUnitArr[0].content);
247 holder.msgUnitArr[0].qos = strcpyAlloc("<qos><persistent/></qos>");
248
249 holder.msgUnitArr[1].key = strcpyAlloc("<key oid='HelloWorld1'/>");
250 holder.msgUnitArr[1].content = strcpyAlloc("Some message payload");
251 holder.msgUnitArr[1].contentLen = strlen(holder.msgUnitArr[1].content);
252 holder.msgUnitArr[1].qos = strcpyAlloc("<qos><persistent/></qos>");
253
254 resp = xa->publishArr(xa, &holder, &xmlBlasterException);
255
256 freeMsgUnitArrInternal(&holder);
257 if (*xmlBlasterException.errorCode != 0) {
258 printf(
259 "[client4] Caught exception in publishArr errorCode=%s, message=%s\n",
260 xmlBlasterException.errorCode, xmlBlasterException.message);
261 xa->disconnect(xa, 0, &xmlBlasterException);
262 freeXmlBlasterReturnQosArr(resp);
263 freeXmlBlasterAccess(xa);
264 exit(EXIT_FAILURE);
265 }
266 if (resp) {
267 size_t i;
268 for (i = 0; i < resp->len; i++) {
269 printf("[client4] PublishArr success, returned status is '%s'\n",
270 resp->returnQosArr[i].returnQos);
271 }
272 freeXmlBlasterReturnQosArr(resp);
273 }
274 }
275
276 if (true) { /* publishOneway */
277 MsgUnitArr holder;
278 memset(&holder, 0, sizeof(MsgUnitArr));
279 printf(
280 "[client4] Publishing oneway messages 'HelloWorld0' and 'HelloWorld1' ...\n");
281 holder.len = 2;
282 holder.msgUnitArr = (MsgUnit *) calloc(holder.len, sizeof(MsgUnit));
283 holder.msgUnitArr[0].key = strcpyAlloc("<key oid='HelloWorld0'/>");
284 holder.msgUnitArr[0].content = strcpyAlloc("Some message payload");
285 holder.msgUnitArr[0].contentLen = strlen(holder.msgUnitArr[0].content);
286 holder.msgUnitArr[0].qos = strcpyAlloc("<qos><persistent/></qos>");
287
288 holder.msgUnitArr[1].key = strcpyAlloc("<key oid='HelloWorld1'/>");
289 holder.msgUnitArr[1].content = strcpyAlloc("Some message payload");
290 holder.msgUnitArr[1].contentLen = strlen(holder.msgUnitArr[1].content);
291 holder.msgUnitArr[1].qos = strcpyAlloc("<qos><persistent/></qos>");
292
293 xa->publishOneway(xa, &holder, &xmlBlasterException);
294
295 freeMsgUnitArrInternal(&holder);
296 if (*xmlBlasterException.errorCode != 0) {
297 printf(
298 "[client4] Caught exception in publishOneway errorCode=%s, message=%s\n",
299 xmlBlasterException.errorCode, xmlBlasterException.message);
300 xa->disconnect(xa, 0, &xmlBlasterException);
301 freeXmlBlasterAccess(xa);
302 exit(EXIT_FAILURE);
303 }
304 }
305
306 { /* unSubscribe ... */
307 UnSubscribeReturnQosArr* resp;
308 UnSubscribeKey *key = createXmlBlasterKey("<key oid='HelloWorld'/>");
309 UnSubscribeQos *qos = createXmlBlasterQos(0);
310 printf("[client4] UnSubscribe message 'HelloWorld' ...\n");
311 resp = xa->unSubscribe(xa, key, qos, &xmlBlasterException);
312 if (resp) {
313 size_t i;
314 for (i = 0; i < resp->len; i++) {
315 printf("[client4] Unsubscribe success, returned status is '%s'\n",
316 resp->returnQosArr[i].returnQos);
317 }
318 freeXmlBlasterKey(key);
319 freeXmlBlasterQos(qos);
320 freeXmlBlasterReturnQosArr(resp);
321 } else {
322 printf(
323 "[client4] Caught exception in unSubscribe errorCode=%s, message=%s\n",
324 xmlBlasterException.errorCode, xmlBlasterException.message);
325 xa->disconnect(xa, 0, &xmlBlasterException);
326 freeXmlBlasterKey(key);
327 freeXmlBlasterQos(qos);
328 freeXmlBlasterAccess(xa);
329 exit(EXIT_FAILURE);
330 }
331 }
332
333 { /* get synchronous ... */
334 size_t i;
335 /*const char *key = "<key oid='HelloWorld'/>";*/
336 GetKey *key = createXmlBlasterKey("<key queryType='XPATH'>//key</key>");
337 GetQos *qos = createXmlBlasterQos("<qos/>");
338 MsgUnitArr *msgUnitArr;
339 printf("[client4] Get synchronous messages with XPath '//key' ...\n");
340 msgUnitArr = xa->get(xa, key, qos, &xmlBlasterException);
341 if (*xmlBlasterException.errorCode != 0) {
342 printf("[client4] Caught exception in get errorCode=%s, message=%s\n",
343 xmlBlasterException.errorCode, xmlBlasterException.message);
344 xa->disconnect(xa, 0, &xmlBlasterException);
345 freeXmlBlasterAccess(xa);
346 exit(EXIT_FAILURE);
347 }
348 if (msgUnitArr != (MsgUnitArr *) 0) {
349 for (i = 0; i < msgUnitArr->len; i++) {
350 char *m = messageUnitToXmlLimited(&msgUnitArr->msgUnitArr[i], 100);
351 printf("\n[client4] Get synchronous returned message#%lu/%lu:\n"
352 "-------------------------------------"
353 "%s\n"
354 "-------------------------------------\n", (unsigned long) (i
355 + 1), (unsigned long) msgUnitArr->len, m);
356 xmlBlasterFree(m);
357 }
358 freeXmlBlasterKey(key);
359 freeXmlBlasterQos(qos);
360 freeMsgUnitArr(msgUnitArr);
361 } else {
362 printf("[client4] Caught exception in get errorCode=%s, message=%s\n",
363 xmlBlasterException.errorCode, xmlBlasterException.message);
364 xa->disconnect(xa, 0, &xmlBlasterException);
365 freeXmlBlasterKey(key);
366 freeXmlBlasterQos(qos);
367 freeXmlBlasterAccess(xa);
368 exit(EXIT_FAILURE);
369 }
370 }
371
372 { /* erase ... */
373 EraseReturnQosArr *resp;
374 EraseKey *key = createXmlBlasterKey("<key oid='HelloWorld'/>");
375 EraseQos *qos = createXmlBlasterQos("<qos/>");
376 printf("[client4] Erasing message 'HelloWorld' ...\n");
377 resp = xa->erase(xa, key, qos, &xmlBlasterException);
378 if (*xmlBlasterException.errorCode != 0) {
379 printf(
380 "[client4] Caught exception in erase errorCode=%s, message=%s\n",
381 xmlBlasterException.errorCode, xmlBlasterException.message);
382 xa->disconnect(xa, 0, &xmlBlasterException);
383 freeXmlBlasterAccess(xa);
384 exit(EXIT_FAILURE);
385 }
386 if (resp != 0) {
387 size_t i;
388 for (i = 0; i < resp->len; i++) {
389 printf("[client4] Erase success, returned status is '%s'\n",
390 resp->returnQosArr[i].returnQos);
391 }
392 freeXmlBlasterKey(key);
393 freeXmlBlasterQos(qos);
394 freeXmlBlasterReturnQosArr(resp);
395 }
396 }
397
398 sleepMillis(200); /* To allow the callback thread to publish */
399
400 if (xa->disconnect(xa, 0, &xmlBlasterException) == false) {
401 printf(
402 "[client4] Caught exception in disconnect, errorCode=%s, message=%s\n",
403 xmlBlasterException.errorCode, xmlBlasterException.message);
404 freeXmlBlasterAccess(xa);
405 exit(EXIT_FAILURE);
406 }
407
408 freeXmlBlasterAccess(xa);
409 printf("[client4] Good bye.\n");
410 # if defined(WINCE)
411 freeArgv(argv, argc);
412 # endif
413 return 0;
414 }
syntax highlighted by Code2HTML, v. 0.9.1