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><key oid='demo.csharp.drawing' contentMime='text/xml'>
138 <sender>0,803539002222726</sender>
139 </key></value>
140 </param>
141 <param>
142 <value><base64>PGRyYXdpbmdNZXNzYWdlPgo8ZGF0YSB0eXBlPSJsaW5lIj4KIDxwb2ludCB4PSIxODciIHk9Ijg4IiAvPgogPHBvaW50IHg9IjI3MCIgeT0iOTciIC8+CjwvZGF0YT4KPC9kcmF3aW5nTWVzc2FnZT4=</base64></value>
143 </param>
144 <param><value><qos>
145 <sender>/node/xmlBlaster_127_0_0_1_3412/client/guest/-7</sender>
146 <subscribe id='__subId:xmlBlaster_127_0_0_1_3412-1131790644308000000'/>
147 <rcvTimestamp nanos='1131790693990000000'/>
148 <queue index='0' size='1'/>
149 </qos></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