1 // NativeC.cs

  2 // deprecated: Please use the PInvokeCE.cs plugin

  3 // Remains for .NET 1.x code and for older Mono 'mcs' compiler.

  4 //

  5 // Simple layer to delegate C# calls to xmlBlaster client C library (using P/Invoke).

  6 // libxmlBlasterClientC.so on Mono/Linux is accessed and must be available

  7 // xmlBlasterClientC.dll on Windows is needed and must be available

  8 //

  9 // This code is functional but still beta (2006-08)

 10 //

 11 // Currently only tested on Linux with Mono and on Windows XP

 12 //

 13 // It will NOT work with Windows CE because of the limited compact framework .net (CF)

 14 // Please use the PInvokeCE.cs plugin instead.

 15 //

 16 // Mono/Linux 1.2 ships with complete C# 1.0 and C# 2.0 compilers, both of them can be used here

 17 //

 18 // Features: All features of the client C library (compression, tunnel callbacks), see

 19 //           http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.socket.html

 20 //

 21 // IMPORTANT: Please edit/change the lookup path below for xmlBlasterClientC.dll

 22 //            and set the PATH to access it

 23 //

 24 // @todo     port content from 'string' to byte[]

 25 //           publishOneway crashes

 26 //           OnUpdate() throwing exception seems not to be passed to C

 27 //           logging with log4net

 28 //           port C to WindowsCE

 29 //           write a testsuite

 30 //           write a requirement

 31 //           create an assembly with ant or nant

 32 //           create the same wrapper for the xmlBlaster C++ library

 33 //

 34 // @author   mr@marcelruff.info

 35 //

 36 // @prepare Linux: cd ~/xmlBlaster; build c-lib; cd ~/xmlBlaster/src/csharp; ln -s ../../lib/libxmlBlasterClientCD.so .

 37 // @compile Linux: mcs /d:NATIVE_C_MAIN /d:XMLBLASTER_MONO -debug+ -out:NativeC.exe NativeC.cs XmlBlasterAccess.cs

 38 //

 39 // @prepare Windows: Compile the C client library first (see xmlBlaster\src\c\xmlBlasterClientC.sln)

 40 // @compile Windows: csc /d:NATIVE_C_MAIN -debug+ -out:NativeC.exe NativeC.cs XmlBlasterAccess.cs   (Windows)

 41 //

 42 // @run      mono NativeC.exe

 43 //           mono NativeC.exe --help

 44 //           mono NativeC.exe -logLevel TRACE

 45 // @see      http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.csharp.html

 46 // @c        http://www.xmlBlaster/org

 47 //

 48 /*
 49 Usage:
 50 XmlBlaster C SOCKET client
 51 
 52    -dispatch/connection/plugin/socket/hostname [localhost]
 53                        Where to find xmlBlaster.
 54    -dispatch/connection/plugin/socket/port [7607]
 55                        The port where xmlBlaster listens.
 56    -dispatch/connection/plugin/socket/localHostname [NULL]
 57                        Force the local IP, useful on multi homed computers.
 58    -dispatch/connection/plugin/socket/localPort [0]
 59                        Force the local port, useful to tunnel firewalls.
 60    -dispatch/connection/plugin/socket/compress/type []
 61                        Switch on compression with 'zlib:stream'.
 62    -dispatch/connection/plugin/socket/useUdpForOneway [false]
 63                        Use UDP for publishOneway() calls.
 64    -dispatch/callback/plugin/socket/hostname [localhost]
 65                        The IP where to establish the callback server.
 66                        Can be useful on multi homed hosts.
 67    -dispatch/callback/plugin/socket/port [7611]
 68                        The port of the callback server.
 69    -plugin/socket/multiThreaded  [true]
 70                        If true the update() call to your client code is a separate thread.
 71    -plugin/socket/responseTimeout  [60000 (one minute)]
 72                        The time in millis to wait on a response, 0 is forever.
 73    -logLevel            ERROR | WARN | INFO | TRACE | DUMP [WARN]
 74 
 75 Example:
 76   mono NativeC -logLevel TRACE -dispatch/connection/plugin/socket/hostname 192.168.2.9
 77 */
 78 using System;
 79 using System.Runtime.InteropServices;
 80 using System.Collections;
 81 
 82 namespace org.xmlBlaster.client
 83 {
 84    /// Calling unmanagegd code: libxmlBlasterClientC.so (Mono) or xmlBlasterClientC.dll (Windows)

 85    public class NativeC : I_XmlBlasterAccess
 86    {
 87       bool verbose = false; // TODO: log4net

 88 
 89 #     if XMLBLASTER_MONO // Linux Debug, set LD_LIBRARY_PATH to find the shared library

 90          const string XMLBLASTER_C_LIBRARY = "xmlBlasterClientCD"; //libxmlBlasterClientCD.so

 91 #     else // Windows

 92       // http://msdn2.microsoft.com/en-us/library/e765dyyy.aspx

 93       //[DllImport("user32.dll", CharSet = CharSet.Auto)]

 94       // Throw the DLL to the current directory or set your PATH pointing to the dll:

 95       const string XMLBLASTER_C_LIBRARY = "xmlBlasterClientC.dll";
 96       // or provide an absolute name:

 97       //const string XMLBLASTER_C_LIBRARY = "..\\..\\lib\\xmlBlasterClientC.dll";

 98 #     endif

 99 
100       // Helper struct for DLL calls to avoid 'fixed' and unsafe

101       struct XmlBlasterUnmanagedException
102       {
103          public int remote;
104          public string errorCode;
105          public string message;
106       }
107 
108       public struct QosArr
109       {
110          public int len;  /* Number of XML QoS strings */
111          public string[] qosArr;
112       }
113 
114       public struct MsgUnitUnmanagedArr
115       {
116          public string secretSessionId;
117          public int len;
118          public MsgUnit_[] msgUnitArr;
119       }
120 
121       // SEE http://msdn2.microsoft.com/en-us/library/2k1k68kw.aspx

122       // Declares a class member for each structure element.

123       // Must match exactly the C struct MsgUnit (sequence!)

124       [StructLayout(LayoutKind.Sequential/*, CharSet=CharSet.Unicode*/ )]
125       public class MsgUnit_
126       {
127          public string key;
128          public int contentLen;
129          // Without MarshalAs: ** ERROR **: Structure field of type Byte[] can't be marshalled as LPArray

130          //[MarshalAs (UnmanagedType.ByValArray, SizeConst=100)] // does not work unlimited without SizeConst -> SIGSEGV

131          // public byte[] content; // Ensure UTF8 encoding for strings

132          public string content;
133          public string qos;
134          public string responseQos;
135          public MsgUnit_() { }
136          public MsgUnit_(string key, string contentStr, string qos)
137          {
138             this.key = key;
139             this.contentLen = contentStr.Length;
140             setContentStr(contentStr);
141             this.qos = qos;
142          }
143          /// We return a string in the default codeset

144          public string getContentStr()
145          {
146             //System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();

147             //return enc.GetString(this.content);

148             // How does this work? System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();

149             return this.content;
150          }
151          /// The binary string is UTF8 encoded (xmlBlaster default)

152          public void setContentStr(string contentStr)
153          {
154             //this.content = System.Text.Encoding.UTF8.GetBytes(contentStr);

155             this.content = contentStr;
156          }
157          public byte[] getContent()
158          {
159             return System.Text.Encoding.UTF8.GetBytes(content);
160          }
161          public override string ToString()
162          {
163             return key + "\n" + content + "\n" + qos;
164          }
165       }
166 
167 
168       [StructLayout(LayoutKind.Sequential)]
169       public class StringArr
170       {
171          public string str;
172       }
173 
174       public void logger(String str)
175       {
176          if (verbose) Console.WriteLine(str);
177       }
178 
179       // How to pass byte[] content, how to tell the Marshal the contentLen to allocate for byte[]?

180 #     if !XMLBLASTER_MONO

181       [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
182 #     endif

183       delegate string UpdateUnmanagedFp(string cbSessionId, string key, string content, int contentLen, string qos, ref XmlBlasterUnmanagedException exception);
184 
185       string updateUnmanaged(string cbSessionId, string key, string content, int contentLen, string qos, ref XmlBlasterUnmanagedException exception)
186       {
187          byte[] bytes = new byte[contentLen];
188          for (int i = 0; i < bytes.Length; i++)
189             bytes[i] = (byte)content[i];
190          MsgUnitUpdate msgUnit = new MsgUnitUpdate(key, bytes, qos);
191          if (null != onUpdate)
192          {
193             try
194             {
195                return onUpdate(cbSessionId, msgUnit);
196                //onUpdate(cbSessionId, msgUnit);

197                //return;

198             }
199             // TODO: Exception seems not to reach the C code

200             catch (XmlBlasterException e)
201             {
202                logger("OnUpdate() exception: " + e.ToString());
203                exception.errorCode = e.ErrorCode;
204                exception.message = e.Message;
205                exception.remote = 1;
206                return null;
207             }
208             catch (Exception e)
209             {
210                logger("OnUpdate() exception: " + e.ToString());
211                exception.errorCode = "user.update.internalError";
212                exception.message = e.ToString();
213                exception.remote = 1;
214                return null;
215             }
216          }
217          logger("C# updateUnmanaged invoked START ==================");
218          logger(msgUnit.GetKeyStr());
219          logger(msgUnit.GetContentStr());
220          logger(msgUnit.GetQosStr());
221          string ret = "<qos><state id='OK'/></qos>";
222          logger("C# updateUnmanaged invoked DONE ===================");
223          return ret;
224       }
225 
226       // Convert a string to a byte array.

227       public static byte[] StrToByteArray(string str)
228       {
229          //return (new UnicodeEncoding()).GetBytes(stringToConvert);

230          //byte[] data = System.Text.Encoding.UTF8.GetBytes(str); // TODO

231          System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
232          return encoding.GetBytes(str);
233       }
234 
235       // Convert a byte array to a string.

236       public static string ByteArrayToString(byte[] dBytes)
237       {
238          string str;
239          System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
240          str = enc.GetString(dBytes, 0, dBytes.Length);
241          return str;
242       }
243 
244       /*
245          [StructLayout(LayoutKind.Explicit)]
246          public struct Rect {
247              [FieldOffset(0)] public int left;
248              [FieldOffset(4)] public int top;
249              [FieldOffset(8)] public int right;
250              [FieldOffset(12)] public int bottom;
251          }
252       */
253 
254       [DllImport(XMLBLASTER_C_LIBRARY)]
255       private extern static IntPtr getXmlBlasterAccessUnparsedUnmanaged(int argc, string[] argv);
256 
257       [DllImport(XMLBLASTER_C_LIBRARY)]
258       private extern static void freeXmlBlasterAccessUnparsedUnmanaged(IntPtr xa);
259 
260       [DllImport(XMLBLASTER_C_LIBRARY)]
261       private extern static string xmlBlasterUnmanagedConnect(IntPtr xa, string qos, UpdateUnmanagedFp updateUnmanaged, ref XmlBlasterUnmanagedException exception);
262 
263       [DllImport(XMLBLASTER_C_LIBRARY)]
264       private extern static bool xmlBlasterUnmanagedInitialize(IntPtr xa, UpdateUnmanagedFp updateUnmanaged, ref XmlBlasterUnmanagedException exception);
265 
266       [DllImport(XMLBLASTER_C_LIBRARY)]
267       private extern static bool xmlBlasterUnmanagedDisconnect(IntPtr xa, string qos, ref XmlBlasterUnmanagedException exception);
268 
269       [DllImport(XMLBLASTER_C_LIBRARY)]
270       private extern static string xmlBlasterUnmanagedPublish(IntPtr xa, MsgUnit_ msgUnit, ref XmlBlasterUnmanagedException exception);
271 
272       //[DllImport(XMLBLASTER_C_LIBRARY )]

273       //private extern static QosArr xmlBlasterUnmanagedPublishArr(IntPtr xa, MsgUnitArr msgUnitArr, ref XmlBlasterUnmanagedException exception);

274 
275       [DllImport(XMLBLASTER_C_LIBRARY)]
276       private extern static void xmlBlasterUnmanagedPublishOneway(IntPtr xa, MsgUnit_[] msgUnitArr, int length, ref XmlBlasterUnmanagedException exception);
277 
278       [DllImport(XMLBLASTER_C_LIBRARY)]
279       private extern static string xmlBlasterUnmanagedSubscribe(IntPtr xa, string key, string qos, ref XmlBlasterUnmanagedException exception);
280 
281       [DllImport(XMLBLASTER_C_LIBRARY)]
282       private extern static void xmlBlasterUnmanagedUnSubscribe(IntPtr xa, string key, string qos, ref XmlBlasterUnmanagedException exception, out int size, out IntPtr ptr);
283 
284       [DllImport(XMLBLASTER_C_LIBRARY)]
285       private extern static void xmlBlasterUnmanagedErase(IntPtr xa, string key, string qos, ref XmlBlasterUnmanagedException exception, out int size, out IntPtr ptr);
286 
287       [DllImport(XMLBLASTER_C_LIBRARY)]
288       private extern static void xmlBlasterUnmanagedGet(IntPtr xa, string key, string qos, ref XmlBlasterUnmanagedException exception, out int size, out IntPtr ptr);
289 
290       [DllImport(XMLBLASTER_C_LIBRARY)]
291       private extern static string xmlBlasterUnmanagedPing(IntPtr xa, string qos, ref XmlBlasterUnmanagedException exception);
292 
293       [DllImport(XMLBLASTER_C_LIBRARY)]
294       private extern static bool xmlBlasterUnmanagedIsConnected(IntPtr xa);
295 
296       [DllImport(XMLBLASTER_C_LIBRARY)]
297       private extern static string xmlBlasterUnmanagedUsage();
298 
299 
300       private IntPtr xa;
301       private UpdateUnmanagedFp updateUnmanagedFp;
302 
303       public NativeC()
304       {
305       }
306 
307       public void Initialize(string[] argv)
308       {
309          if (argv == null) argv = new String[0];
310 
311          updateUnmanagedFp = new UpdateUnmanagedFp(this.updateUnmanaged);
312 
313          // Convert command line arguments: C client lib expects the executable name as first entry

314          string[] c_argv = new string[argv.Length + 1];
315          c_argv[0] = "NativC"; // my executable name

316          for (int i = 0; i < argv.Length; ++i)
317          {
318             if (argv[i] == "--help")
319             {
320                Console.WriteLine("Usage:\n" + xmlBlasterUnmanagedUsage());
321                throw new XmlBlasterException("user.usage", "Good bye");
322             }
323             c_argv[i + 1] = argv[i];
324          }
325 
326          xa = getXmlBlasterAccessUnparsedUnmanaged(c_argv.Length, c_argv);
327 
328          logger("NativeC() ...");
329       }
330 
331       public void Initialize(Hashtable properties)
332       {
333          throw new XmlBlasterException("internal.notImplemented", "Please call initialize(string[]");
334       }
335 
336       /**
337        * @see org.xmlBlaster.client.I_XmlBlasterAccess#registerConnectionListener(I_ConnectionStateListener)
338        */
339       public void RegisterConnectionListener(I_ConnectionStateListener connectionListener) {
340          logger("RegisterConnectionListener() is not implemented, TODO");
341          //this.connectionListener = connectionListener;

342       }
343 
344       ~NativeC()
345       {
346          if (xa != new IntPtr(0))
347             freeXmlBlasterAccessUnparsedUnmanaged(xa);
348          logger("~NativeC() ...");
349       }
350 
351       void check(string methodName)
352       {
353          logger(methodName + "() ...");
354          if (xa == new IntPtr(0))
355             throw new XmlBlasterException("internal.illegalState", "Can't process " + methodName + ", xmlBlaster pointer is reset, please create a new instance of NativeC.cs class after a disconnect() call");
356       }
357 
358       private delegate string OnUpdate(string cbSessionId, MsgUnitUpdate msgUnit);
359       private event OnUpdate onUpdate;
360 
361       public ConnectReturnQos Connect(string qos, I_Callback listener)
362       {
363          check("connect");
364          if (listener != null)
365          {
366             onUpdate += new OnUpdate(listener.OnUpdate);
367          }
368          try
369          {
370             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
371             bool bb = xmlBlasterUnmanagedInitialize(xa, updateUnmanagedFp, ref exception);
372             if (exception.errorCode.Length > 0)
373             {
374                logger("xmlBlasterUnmanagedInitialize: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
375                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
376             }
377             else
378                logger("xmlBlasterUnmanagedInitialize: SUCCESS '" + bb + "' xa:"/* + xa.isInitialized*/);
379 
380             string ret = xmlBlasterUnmanagedConnect(xa, qos, updateUnmanagedFp, ref exception);
381             if (exception.errorCode.Length > 0)
382             {
383                logger("xmlBlasterUnmanagedConnect: Got exception from C: '" + ret + "' exception=" + exception.errorCode + " - " + exception.message);
384                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
385             }
386             else
387                logger("xmlBlasterUnmanagedConnect: SUCCESS '" + ret + "'");
388             return new ConnectReturnQos(ret);
389          }
390          catch (XmlBlasterException e)
391          {
392             throw e;
393          }
394          catch (Exception e)
395          {
396             throw new XmlBlasterException("internal.unknown", "connect failed", e);
397          }
398       }
399 
400       public void LeaveServer()
401       {
402          check("LeaveServer");
403          try
404          {
405             IntPtr tmp = xa;
406             xa = IntPtr.Zero;
407             freeXmlBlasterAccessUnparsedUnmanaged(tmp);
408             logger("freeXmlBlasterAccessUnparsedUnmanaged: SUCCESS freed all resources");
409          }
410          catch (Exception e)
411          {
412             throw new XmlBlasterException("internal.unknown", "LeaveServer failed", e);
413          }
414       }
415 
416       /// After calling diconnect() this class is not usable anymore

417       /// you need to create a new instance to connect again

418       public bool Disconnect(string qos)
419       {
420          check("disconnect");
421          try
422          {
423             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
424             bool bb = xmlBlasterUnmanagedDisconnect(xa, qos, ref exception);
425             if (exception.errorCode.Length > 0)
426             {
427                logger("xmlBlasterUnmanagedDisconnect: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
428                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
429             }
430             else
431                logger("xmlBlasterUnmanagedDisconnect: SUCCESS '" + bb + "'");
432 
433             freeXmlBlasterAccessUnparsedUnmanaged(xa);
434             xa = new IntPtr(0);
435             logger("xmlBlasterUnmanagedDisconnect: SUCCESS freed all resources");
436 
437             return bb;
438          }
439          catch (XmlBlasterException e)
440          {
441             throw e;
442          }
443          catch (Exception e)
444          {
445             throw new XmlBlasterException("internal.unknown", "disconnect failed", e);
446          }
447       }
448 
449       public PublishReturnQos Publish(string key, string content, string qos)
450       {
451          return Publish(new MsgUnit(key, content, qos));
452       }
453 
454       public PublishReturnQos Publish(MsgUnit msgUnit)
455       {
456          check("publish");
457          try
458          {
459             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
460             MsgUnit_ msgUnit_ = new MsgUnit_(msgUnit.GetKeyStr(), msgUnit.GetContentStr(), msgUnit.GetQosStr());
461             string ret = xmlBlasterUnmanagedPublish(xa, msgUnit_, ref exception);
462             if (exception.errorCode.Length > 0)
463             {
464                logger("xmlBlasterUnmanagedPublish: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
465                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
466             }
467             else
468                logger("xmlBlasterUnmanagedPublish: SUCCESS '" + ret + "'");
469             return new PublishReturnQos(ret);
470          }
471          catch (XmlBlasterException e)
472          {
473             throw e;
474          }
475          catch (Exception e)
476          {
477             throw new XmlBlasterException("internal.unknown", "publish failed", e);
478          }
479       }
480 
481       // TODO: Crashs for array size > 2

482       /*
483        Invalid read of size 1
484          at 0x63FFF14: encodeMsgUnitArr (xmlBlasterSocket.c:222)
485             by 0x63FD11E: xmlBlasterPublishOneway (XmlBlasterConnectionUnparsed.c:1004)
486             by 0x63F9125: xmlBlasterPublishOneway (XmlBlasterAccessUnparsed.c:726)
487             by 0x63FF0B8: xmlBlasterUnmanagedPublishOneway (XmlBlasterUnmanaged.c:365)
488             by 0x6524CC8: ???
489       */
490       public void PublishOneway(MsgUnit[] msgUnitArr)
491       {
492          check("publishOneway");
493          try
494          {
495             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
496             MsgUnit_[] msgUnitArr_ = new MsgUnit_[msgUnitArr.Length];
497             for (int i = 0; i < msgUnitArr.Length; i++)
498                msgUnitArr_[i] = new MsgUnit_(msgUnitArr[i].GetKeyStr(), msgUnitArr[i].GetContentStr(), msgUnitArr[i].GetQosStr());
499             xmlBlasterUnmanagedPublishOneway(xa, msgUnitArr_, msgUnitArr.Length, ref exception);
500             if (exception.errorCode.Length > 0)
501             {
502                logger("publishOneway: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
503                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
504             }
505             else
506                logger("publishOneway: SUCCESS");
507          }
508          catch (XmlBlasterException e)
509          {
510             throw e;
511          }
512          catch (Exception e)
513          {
514             throw new XmlBlasterException("internal.unknown", "publishOneway failed", e);
515          }
516       }
517 
518       public SubscribeReturnQos Subscribe(string key, string qos)
519       {
520          check("subscribe");
521          try
522          {
523             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
524             string ret = xmlBlasterUnmanagedSubscribe(xa, key, qos, ref exception);
525             if (exception.errorCode.Length > 0)
526             {
527                logger("xmlBlasterUnmanagedSubscribe: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
528                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
529             }
530             else
531                logger("xmlBlasterUnmanagedSubscribe: SUCCESS '" + ret + "'");
532             return new SubscribeReturnQos(ret);
533          }
534          catch (XmlBlasterException e)
535          {
536             throw e;
537          }
538          catch (Exception e)
539          {
540             throw new XmlBlasterException("internal.unknown", "subscribe failed", e);
541          }
542       }
543 
544       public UnSubscribeReturnQos[] UnSubscribe(string key, string qos)
545       {
546          check("unSubscribe");
547          try
548          {
549             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
550             int size;
551             IntPtr outArray;
552             xmlBlasterUnmanagedUnSubscribe(xa, key, qos, ref exception, out size, out outArray);
553             if (exception.errorCode.Length > 0)
554             {
555                logger("xmlBlasterUnmanagedUnSubscribe: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
556                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
557             }
558             StringArr[] manArray = new StringArr[size];
559             UnSubscribeReturnQos[] retQosArr = new UnSubscribeReturnQos[size];
560             IntPtr current = outArray;
561             for (int i = 0; i < size; i++)
562             {
563                manArray[i] = new StringArr();
564                Marshal.PtrToStructure(current, manArray[i]);
565 #              if PocketPC || Smartphone

566 #              else

567                Marshal.DestroyStructure(current, typeof(StringArr));
568 #              endif

569                current = (IntPtr)((long)current + Marshal.SizeOf(manArray[i]));
570                //Console.WriteLine( "Element {0}: str={1}", i, manArray[ i ].str );

571                retQosArr[i] = new UnSubscribeReturnQos(manArray[i].str);
572             }
573 #           if Smartphone

574 #           else

575             Marshal.FreeCoTaskMem(outArray);
576 #           endif

577             logger("xmlBlasterUnmanagedUnSubscribe: SUCCESS");
578             return retQosArr;
579          }
580          catch (XmlBlasterException e)
581          {
582             throw e;
583          }
584          catch (Exception e)
585          {
586             //try {

587             //   disconnect("<qos/>");

588             //}

589             //catch (Exception e2) {

590             //   logger("xmlBlasterUnmanagedUnSubscribe: Ignoring " + e2.ToString() + " root was " +e.ToString());

591             //}

592             throw new XmlBlasterException("internal.unknown", "unSubscribe failed", e);
593          }
594       }
595 
596       public EraseReturnQos[] Erase(string key, string qos)
597       {
598          check("erase");
599          try
600          {
601             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
602             int size;
603             IntPtr outArray;
604             xmlBlasterUnmanagedErase(xa, key, qos, ref exception, out size, out outArray);
605             if (exception.errorCode.Length > 0)
606             {
607                logger("xmlBlasterUnmanagedErase: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
608                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
609             }
610             StringArr[] manArray = new StringArr[size];
611             EraseReturnQos[] retQosArr = new EraseReturnQos[size];
612             IntPtr current = outArray;
613             for (int i = 0; i < size; i++)
614             {
615                manArray[i] = new StringArr();
616                Marshal.PtrToStructure(current, manArray[i]);
617 #              if PocketPC || Smartphone

618 #              else

619                Marshal.DestroyStructure(current, typeof(StringArr));
620 #              endif

621                current = (IntPtr)((long)current + Marshal.SizeOf(manArray[i]));
622                //Console.WriteLine( "Element {0}: str={1}", i, manArray[ i ].str );

623                string ret = manArray[i].str;
624                retQosArr[i] = new EraseReturnQos(ret);
625             }
626 #           if Smartphone

627 #           else

628             Marshal.FreeCoTaskMem(outArray);
629 #           endif

630             logger("xmlBlasterUnmanagedErase: SUCCESS");
631             return retQosArr;
632          }
633          catch (XmlBlasterException e)
634          {
635             throw e;
636          }
637          catch (Exception e)
638          {
639             throw new XmlBlasterException("internal.unknown", "erase failed", e);
640          }
641       }
642 
643       public MsgUnitGet[] Get(string key, string qos)
644       {
645          check("get");
646          try
647          {
648             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
649             int size;
650             IntPtr outArray;
651             xmlBlasterUnmanagedGet(xa, key, qos, ref exception, out size, out outArray);
652             if (exception.errorCode.Length > 0)
653             {
654                logger("xmlBlasterUnmanagedGet: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
655                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
656             }
657 
658             logger("get() size=" + size);
659             MsgUnitGet[] msgUnitArr = new MsgUnitGet[size];
660             IntPtr current = outArray;
661             for (int i = 0; i < size; i++)
662             {
663                MsgUnit_ msgUnit_ = new MsgUnit_();
664                Marshal.PtrToStructure(current, msgUnit_);
665                //Marshal.FreeCoTaskMem( (IntPtr)Marshal.ReadInt32( current ));

666 #              if PocketPC || Smartphone

667 #              else

668                Marshal.DestroyStructure(current, typeof(MsgUnit_));
669 #              endif

670                current = (IntPtr)((long)current +
671                Marshal.SizeOf(msgUnit_));
672                //Console.WriteLine( "Element {0}: key={1} qos={2} buffer={3} contentLength={4}", i, 

673                //   manArray[ i ].key, manArray[ i ].qos, manArray[ i ].content, manArray[ i ].contentLen );

674                msgUnitArr[i] = new MsgUnitGet(msgUnit_.key, msgUnit_.getContent(), msgUnit_.qos);
675             }
676 #           if Smartphone

677 #           else

678             Marshal.FreeCoTaskMem(outArray);
679 #           endif

680             logger("xmlBlasterUnmanagedGet: SUCCESS");
681             return msgUnitArr;
682          }
683          catch (XmlBlasterException e)
684          {
685             throw e;
686          }
687          catch (Exception e)
688          {
689             throw new XmlBlasterException("internal.unknown", "get failed", e);
690          }
691       }
692 
693       public string Ping(string qos)
694       {
695          check("ping");
696          try
697          {
698             XmlBlasterUnmanagedException exception = new XmlBlasterUnmanagedException();
699             string ret = xmlBlasterUnmanagedPing(xa, qos, ref exception);
700             if (exception.errorCode.Length > 0)
701             {
702                logger("xmlBlasterUnmanagedPing: Got exception from C: exception=" + exception.errorCode + " - " + exception.message);
703                throw new XmlBlasterException(exception.remote != 0, exception.errorCode, exception.message);
704             }
705             else
706                logger("xmlBlasterUnmanagedPing: SUCCESS '" + ret + "'");
707             return ret;
708          }
709          catch (XmlBlasterException e)
710          {
711             throw e;
712          }
713          catch (Exception e)
714          {
715             throw new XmlBlasterException("internal.unknown", "ping failed", e);
716          }
717       }
718 
719       public bool IsConnected()
720       {
721          logger("isConnected() ...");
722          if (xa == new IntPtr(0)) return false;
723          try
724          {
725             bool bb = xmlBlasterUnmanagedIsConnected(xa);
726             logger("xmlBlasterUnmanagedIsConnected: SUCCESS '" + bb + "'");
727             return bb;
728          }
729          catch (XmlBlasterException e)
730          {
731             throw e;
732          }
733          catch (Exception e)
734          {
735             throw new XmlBlasterException("internal.unknown", "isConnected failed", e);
736          }
737       }
738 
739       public void AddLoggingListener(I_LoggingCallback listener)
740       {
741          logger("Sorry, AddLoggingListener() is not implemented");
742          //throw new XmlBlasterException("internal.notImplemented", "Sorry, addLoggingListener is not implemented");

743       }
744 
745       public void RemoveLoggingListener(I_LoggingCallback listener)
746       {
747          logger("Sorry, RemoveLoggingListener() is not implemented");
748       }
749 
750       public void AddCallbackProgressListener(I_ProgressCallback listener)
751       {
752          logger("Sorry, AddCallbackProgressListener() is not implemented");
753       }
754 
755       public void RemoveCallbackProgressListener(I_ProgressCallback listener)
756       {
757          logger("Sorry, RemoveCallbackProgressListener() is not implemented");
758       }
759 
760      public string GetUsage()
761       {
762          return xmlBlasterUnmanagedUsage();
763       }
764 
765       public string GetVersion()
766       {
767          return "?";
768       }
769 
770       public string GetEmeiId()
771       {
772          logger("Sorry, getEmeiId() is not implemented");
773          return null;
774       }
775 
776       public string GetDeviceUniqueId()
777       {
778          logger("Sorry, getDeviceUniqueId() is not implemented");
779          return null;
780       }
781    }
782 }


syntax highlighted by Code2HTML, v. 0.9.1