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