1 /**
  2  * 
  3  * XML-RPC library :
  4  * http://xml-rpc.net/ by Charles Cook
  5  * I'm using version 0.9.2 (22nd May 2005)
  6  * 
  7  */
  8 using System;
  9 using System.Text ;
 10 using System.Diagnostics ;
 11 using System.Collections.Specialized ;
 12 using System.Xml ;
 13 
 14 using System.Windows.Forms ; // for MessageBox

 15 using System.Net ; // for WebException

 16 
 17 using System.Runtime.Remoting ;
 18 using System.Runtime.Remoting.Channels ;
 19 using System.Runtime.Remoting.Channels.Http ;
 20 
 21 using CookComputing.XmlRpc;
 22 
 23 namespace XmlBlaster
 24 {
 25    /// <summary>

 26    /// Description résumée de Class1.

 27    /// </summary>

 28    public interface IXmlBlasterClient
 29    {
 30       [XmlRpcMethod("authenticate.connect")]
 31       string Connect( string connectQos );
 32 
 33       [XmlRpcMethod("authenticate.disconnect")]
 34       void Disconnect( string sessiondId, string qos );
 35 
 36       [XmlRpcMethod("xmlBlaster.publish")]
 37       string Publish( string sessiondId, string key, string xmlMessage, string qos );
 38 
 39       [XmlRpcMethod("xmlBlaster.subscribe")]
 40       string Subscribe( string sessiondId, string key, string qos );
 41    }
 42 
 43 
 44    public class XmlBlasterException : Exception
 45    {
 46       const string exceptionMessage = "XmlBlaster operation has failed.";
 47 
 48       public XmlBlasterException()
 49          : base( exceptionMessage )
 50       {
 51       }
 52 
 53       public XmlBlasterException( string auxMessage )
 54          : base( String.Format( "{0} - {1}", exceptionMessage, auxMessage ) )
 55       {
 56       }
 57 
 58       public XmlBlasterException( string auxMessage, Exception inner )
 59          : base( String.Format( "{0} - {1}", exceptionMessage, auxMessage ), inner )
 60       {
 61       }
 62 
 63       public XmlBlasterException( Exception inner )
 64          : base( String.Format( "{0} - {1}", exceptionMessage, inner.Message ), inner )
 65       {
 66       }
 67 
 68       internal static void HandleException( Exception ex )
 69       {
 70          //string msgBoxTitle = "Error" ;

 71          try
 72          {
 73             throw ex;
 74          }
 75          catch(XmlRpcFaultException fex)
 76          {
 77             //MessageBox.Show("Fault Response: " + fex.FaultCode + " " 

 78             // + fex.FaultString, msgBoxTitle,

 79             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 80             throw new XmlBlasterException( fex.FaultString, fex ) ;
 81          }
 82          catch(WebException webEx)
 83          {
 84             //MessageBox.Show("WebException: " + webEx.Message, msgBoxTitle,

 85             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 86             if (webEx.Response != null)
 87                webEx.Response.Close();
 88             throw new XmlBlasterException( webEx ) ;
 89          }
 90          catch(XmlRpcServerException xmlRpcEx)
 91          {
 92             //MessageBox.Show("XmlRpcServerException: " + xmlRpcEx.Message, 

 93             // msgBoxTitle,

 94             // MessageBoxButtons.OK, MessageBoxIcon.Error);

 95             throw new XmlBlasterException( xmlRpcEx ) ;
 96          }
 97          catch(Exception defEx)
 98          {
 99             //MessageBox.Show("Exception: " + defEx.Message, msgBoxTitle,

100             // MessageBoxButtons.OK, MessageBoxIcon.Error);

101             throw new XmlBlasterException( defEx ) ;
102          }
103       }
104 
105    }
106 
107 
108    public class XmlBlasterCallback : MarshalByRefObject 
109    {
110       public delegate void MessageArrivedDelegate( string key, string xmlMessage );
111       public static MessageArrivedDelegate messageArrived ;
112 
113 
114       [XmlRpcMethod("ping")] 
115       public string Ping( string msg ) 
116       {
117          // [12-Nov-2005 11:18:15] string(144) "<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>ping</methodName><params><param><value></value></param></params></methodCall>"

118 
119          Debug.WriteLine( "XmlBlasterCallback.Ping()" );
120 
121          //Debug.WriteLine( "\t msg: ", msg );

122 
123          return "<qos><state>OK</state></qos>";
124       }
125 
126       [XmlRpcMethod("update")] 
127       public string Update( string cbSessionId, string key, System.Byte[] msg, string qos ) 
128       {
129          /*
130          [12-Nov-2005 11:18:15] string(811) "
131          <?xml version="1.0" encoding="ISO-8859-1"?>
132             <methodCall>
133                <methodName>update</methodName>
134                <params>
135                   <param><value>unknown</value></param>
136                   <param>
137                      <value>&lt;key oid='demo.csharp.drawing' contentMime='text/xml'&gt;
138                      &lt;sender&gt;0,803539002222726&lt;/sender&gt;
139                      &lt;/key&gt;</value>
140                   </param>
141                   <param>
142                      <value><base64>PGRyYXdpbmdNZXNzYWdlPgo8ZGF0YSB0eXBlPSJsaW5lIj4KIDxwb2ludCB4PSIxODciIHk9Ijg4IiAvPgogPHBvaW50IHg9IjI3MCIgeT0iOTciIC8+CjwvZGF0YT4KPC9kcmF3aW5nTWVzc2FnZT4=</base64></value>
143                   </param>
144                   <param><value>&lt;qos&gt;
145                      &lt;sender&gt;/node/xmlBlaster_127_0_0_1_3412/client/guest/-7&lt;/sender&gt;
146                      &lt;subscribe id='__subId:xmlBlaster_127_0_0_1_3412-1131790644308000000'/&gt;
147                      &lt;rcvTimestamp nanos='1131790693990000000'/&gt;
148                      &lt;queue index='0' size='1'/&gt;
149                      &lt;/qos&gt;</value>
150                   </param>
151                </params>
152             </methodCall>"
153          */
154 
155          Debug.WriteLine( "XmlBlasterCallback.Update()" );
156 
157          //Debug.WriteLine( "\t cbSessionId: ", cbSessionId );

158          Debug.WriteLine( "\t key: ", key );
159          //Debug.WriteLine( "\t messageUnit: ", messageUnit );

160 
161          if( messageArrived != null )
162          {
163             string xml = Encoding.Default.GetString( msg );
164             messageArrived( key, xml );
165          }
166 
167          return "<qos><state>OK</state></qos>";
168       }
169    }
170 
171 
172    public class XmlBlasterClient
173    {
174       IXmlBlasterClient xmlBlasterClientProxy ;
175       XmlRpcClientProtocol xmlBlasterClientProtocol ;
176 
177       Uri callbackServerUri ;
178 
179       string uniqueId ;
180       string sessionId ;
181       public string SessionId
182       {
183          get { return this.sessionId ; }
184       }
185 
186       public string Url
187       {
188          get { return xmlBlasterClientProtocol.Url ; }
189          set { xmlBlasterClientProtocol.Url = value ; }
190       }
191 
192 
193       public XmlBlasterClient()
194       {
195          // Client

196 
197          xmlBlasterClientProxy = (IXmlBlasterClient) XmlRpcProxyGen.Create(typeof(IXmlBlasterClient)) ;
198          xmlBlasterClientProtocol = (XmlRpcClientProtocol) xmlBlasterClientProxy ;
199 
200          // Server for Callback

201 
202          //RemotingConfiguration.Configure("xmlrpc.exe.config"); 

203 
204          HttpChannel channel = null ;
205 
206          try 
207          {
208             //int port = FindFreeHttpPort( 9090 ) ;

209             //Debug.WriteLine( "FindFreeHttpPort() found port "+port );

210             int port = 0 ;
211 
212             ListDictionary channelProperties = new ListDictionary();
213             channelProperties.Add( "port", port );
214 
215             channel = new HttpChannel(
216                channelProperties,
217                new CookComputing.XmlRpc.XmlRpcClientFormatterSinkProvider(),
218                new CookComputing.XmlRpc.XmlRpcServerFormatterSinkProvider(null,null)
219                //new SoapClientFormatterSinkProvider(),

220                //new SoapServerFormatterSinkProvider()

221                );
222          }
223          catch( Exception ex )
224          {
225             // Listener config failed : Une seule utilisation de chaque adresse de socket (protocole/adresse réseau/port) est habituellement autorisée

226 
227             Debug.WriteLine( "Listener config failed : " + ex.Message );
228 
229             XmlBlasterException.HandleException( new Exception("Listener config failed.", ex ) );
230          }
231 
232          ChannelServices.RegisterChannel( channel );
233 
234          RemotingConfiguration.RegisterWellKnownServiceType( 
235             typeof(XmlBlasterCallback), 
236             "XmlBlasterCallback",
237             WellKnownObjectMode.Singleton
238          );
239 
240          // Print out the urls for HelloServer.

241          string[] urls = channel.GetUrlsForUri("XmlBlasterCallback");
242          foreach (string url in urls)
243             System.Console.WriteLine("url: {0}", url);
244          //url: http://127.0.0.1:1038/XmlBlasterCallback

245          if( urls.Length != 1 )
246          {
247             XmlBlasterException.HandleException( new Exception("XmlBlasterCallback server, failed to retreive url." ) );
248          }
249          this.callbackServerUri = new Uri( urls[ 0 ] );
250 
251       }
252 
253 
254       public void Connect( string url, string username, string password )
255       {
256          Debug.WriteLine( "XmlBlaster.Connect()" );
257 
258          this.Url = url ; // Set xml-rpc server url

259 
260          // construct authentification data

261          QosConnect qos ;
262 
263          try
264          {
265             // try connect (login)

266             qos = new QosConnect( username,password,this.callbackServerUri.ToString() );
267             string result = xmlBlasterClientProxy.Connect( qos.ToString() );
268             //Debug.Write( "Connect Result :" );

269             //Debug.WriteLine( result );

270             QosConnectResult qosRes = new QosConnectResult( result );
271             this.sessionId = qosRes.SessionId ;
272 
273             // TODO: sessionId should be secret !

274             // do something better ;o)

275             Random rnd = new Random( );
276             this.uniqueId = rnd.NextDouble().ToString() ;
277          }
278          catch( Exception ex )
279          {
280             XmlBlasterException.HandleException(ex);
281          }
282       }
283 
284       public void Disconnect()
285       {
286          Debug.WriteLine( "XmlBlaster.Disconnect()" );
287 
288          // construct authentification data

289          string qos = @"
290             <qos>
291                <deleteSubjectQueue>true</deleteSubjectQueue>
292                <clearSessions>true</clearSessions>
293             </qos>";
294 
295          try
296          {
297             xmlBlasterClientProxy.Disconnect( this.sessionId, qos );
298          }
299          catch( Exception ex )
300          {
301             XmlBlasterException.HandleException(ex);
302          }
303       }
304 
305       public void Subscribe( string topic )
306       {
307          Debug.WriteLine( "XmlBlaster.Subscribe()" );
308 
309          try
310          {
311             string key = "<key oid=\""+topic+"\" />\n" ;
312             string qos = @"<qos>
313                <local>false</local>
314                </qos>" ;
315 
316             string result = xmlBlasterClientProxy.Subscribe( this.sessionId, key, qos );
317 
318             Debug.Write( "Subscribe Result :" );
319             Debug.WriteLine( result );
320 
321          }
322          catch( Exception ex )
323          {
324             XmlBlasterException.HandleException(ex);
325          }
326       }
327 
328       public void Publish( string topic, string xmlMessage )
329       {
330          Debug.WriteLine( "XmlBlaster.Publish()" );
331 
332          try
333          {
334             string key = "<key oid=\""+topic+"\" contentMime=\"text/xml\" >\n" ;
335             key += "<sender>"+uniqueId+"</sender>\n" ;
336             key += "</key>" ;
337 
338             string qos = "<qos />" ;
339 
340             string result = xmlBlasterClientProxy.Publish( this.sessionId, key, xmlMessage, qos );
341 
342             //Debug.Write( "Publish Result :" );

343             //Debug.WriteLine( result );

344             /*
345                XmlBlaster.Publish()
346                Publish Result :
347                <qos>
348                <key oid='demo.csharp.drawing'/>
349                <rcvTimestamp nanos='1131972554614000000'/>
350                <isPublish/>
351                </qos>
352              */
353 
354          }
355          catch( Exception ex )
356          {
357             XmlBlasterException.HandleException(ex);
358          }
359       }
360 
361    }
362 
363 
364    public class QosConnect
365    {
366       public string securityService_type = "htpasswd" ;
367       public string securityService_version = "1.0" ;
368       public string username ;
369       public string password ;
370       public string callbackUri = null ;
371 
372       public QosConnect()
373       {
374       }
375       public QosConnect( string username, string password )
376       {
377          this.username = username ;
378          this.password = password ;
379          this.callbackUri = null ;
380       }
381       public QosConnect( string username, string password, string callbackUri )
382       {
383          this.username = username ;
384          this.password = password ;
385          this.callbackUri = callbackUri ;
386       }
387 
388       public override string ToString()
389       {
390          StringBuilder sb = new StringBuilder( 255 );
391 
392          sb.Append( "<qos>\n" );
393 
394          sb.Append( " <securityService type=\""+this.securityService_type + "\" version=\""+this.securityService_version+"\">\n" );
395          sb.Append( "  <user>"+ this.username +"</user>\n" );
396          sb.Append( "  <passwd>"+ this.password +"</passwd>\n" );
397          sb.Append( " </securityService>\n" );
398 
399          if( callbackUri != null ){
400             sb.Append( "<callback type=\"XMLRPC\" retries=\"2\" delay=\"2000\" pingInterval=\"5000\" >" );
401             //sb.Append( "http://192.168.0.151:9090/RPC2" );

402             //sb.Append( "http://127.0.0.1:9090/RPC2" );

403 
404             //sb.Append( "http://127.0.0.1:8090/EssaisDivers/xmlBLaster.essais/demo.php/callback.php" );

405             //sb.Append( "http://127.0.0.1:9090/XmlBlasterCallback" );

406             sb.Append( this.callbackUri );
407 
408             sb.Append( "</callback>\n" );
409          }
410 
411          // Subscribe Qos ?

412          //sb.Append( "<local>false</local>\n" );

413 
414          sb.Append( "</qos>\n" );
415 
416          return sb.ToString();
417       }
418 
419    }
420 
421    public class QosConnectResult
422    {
423       /*
424       <qos>
425          <securityService type="htpasswd" version="1.0">
426             <user>guest</user>
427             <passwd>guest</passwd>
428          </securityService>
429          <instanceId>/xmlBlaster/node/xmlBlaster_192_168_0_151_3412/instanceId/1131719045135</instanceId>
430          <session name='/node/xmlBlaster_192_168_0_151_3412/client/guest/-4'
431             timeout='86400000' maxSessions='10' clearSessions='false' reconnectSameClientOnly='false'
432             sessionId='sessionId:192.168.0.151-null-1131720478106-2108614840-5'
433          />
434          <queue relating='connection' maxEntries='10000000' maxEntriesCache='1000'>
435             <address type='IOR' dispatchPlugin='undef'>
436             </address>
437          </queue>
438          <queue relating='subject'/>
439          <queue relating='callback' maxEntries='1000' maxEntriesCache='1000'/>
440       </qos>
441        */
442       protected XmlDocument xmlDoc ;
443       public QosConnectResult( string xml )
444       {
445          this.xmlDoc = new XmlDocument();
446          xmlDoc.LoadXml( xml );
447 
448       }
449 
450       public string SessionId
451       {
452          get {
453             XmlNode root = xmlDoc.DocumentElement ;
454             XmlNode node ;
455 
456             string s ;
457 
458             //node = root.SelectSingleNode("descendant::book[author/last-name='Austen']");

459             node = root.SelectSingleNode("session");
460             s = node.Attributes[ "sessionId" ].Value ;
461 
462             Debug.WriteLine("sessionId : "+s);
463             return s ;
464          }
465       }
466    }
467 
468 }


syntax highlighted by Code2HTML, v. 0.9.1