PageRenderTime 39ms CodeModel.GetById 23ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Modules/Scripting/XMLRPC/XMLRPCModule.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 793 lines | 584 code | 99 blank | 110 comment | 62 complexity | 70af6071e193f2996ad262000e2ecbd8 MD5 | raw file
  1/*
  2 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions are met:
  7 *     * Redistributions of source code must retain the above copyright
  8 *       notice, this list of conditions and the following disclaimer.
  9 *     * Redistributions in binary form must reproduce the above copyright
 10 *       notice, this list of conditions and the following disclaimer in the
 11 *       documentation and/or other materials provided with the distribution.
 12 *     * Neither the name of the Aurora-Sim Project nor the
 13 *       names of its contributors may be used to endorse or promote products
 14 *       derived from this software without specific prior written permission.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 */
 27
 28using Aurora.Framework;
 29using Aurora.Framework.ConsoleFramework;
 30using Aurora.Framework.Modules;
 31using Aurora.Framework.SceneInfo;
 32using Aurora.Framework.Servers;
 33using Aurora.Framework.Servers.HttpServer;
 34using Aurora.Framework.Servers.HttpServer.Interfaces;
 35using Aurora.Framework.Utilities;
 36using Nini.Config;
 37using Nwc.XmlRpc;
 38using OpenMetaverse;
 39using System;
 40using System.Collections;
 41using System.Collections.Generic;
 42using System.Linq;
 43using System.Net;
 44using System.Threading;
 45
 46/*****************************************************
 47 *
 48 * XMLRPCModule
 49 *
 50 * Module for accepting incoming communications from
 51 * external XMLRPC client and calling a remote data
 52 * procedure for a registered data channel/prim.
 53 *
 54 *
 55 * 1. On module load, open a listener port
 56 * 2. Attach an XMLRPC handler
 57 * 3. When a request is received:
 58 * 3.1 Parse into components: channel key, int, string
 59 * 3.2 Look up registered channel listeners
 60 * 3.3 Call the channel (prim) remote data method
 61 * 3.4 Capture the response (llRemoteDataReply)
 62 * 3.5 Return response to client caller
 63 * 3.6 If no response from llRemoteDataReply within
 64 *     RemoteReplyScriptTimeout, generate script timeout fault
 65 *
 66 * Prims in script must:
 67 * 1. Open a remote data channel
 68 * 1.1 Generate a channel ID
 69 * 1.2 Register primid,channelid pair with module
 70 * 2. Implement the remote data procedure handler
 71 *
 72 * llOpenRemoteDataChannel
 73 * llRemoteDataReply
 74 * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval)
 75 * llCloseRemoteDataChannel
 76 *
 77 * **************************************************/
 78
 79namespace Aurora.Modules.Scripting
 80{
 81    public class XMLRPCModule : INonSharedRegionModule, IXMLRPC
 82    {
 83        private readonly object XMLRPCListLock = new object();
 84        private int RemoteReplyScriptTimeout = 9000;
 85        private int RemoteReplyScriptWait = 300;
 86        private bool m_httpServerStarted;
 87
 88        private string m_name = "XMLRPCModule";
 89
 90        // <channel id, RPCChannelInfo>
 91        private Dictionary<UUID, RPCChannelInfo> m_openChannels;
 92        private Dictionary<UUID, SendRemoteDataRequest> m_pendingSRDResponses;
 93        private int m_remoteDataPort;
 94
 95        private Dictionary<UUID, RPCRequestInfo> m_rpcPending;
 96        private Dictionary<UUID, RPCRequestInfo> m_rpcPendingResponses;
 97        private IScriptModule m_scriptModule;
 98
 99        #region INonSharedRegionModule Members
100
101        public void Initialise(IConfigSource config)
102        {
103            // We need to create these early because the scripts might be calling
104            // But since this gets called for every region, we need to make sure they
105            // get called only one time (or we lose any open channels)
106            if (null == m_openChannels)
107            {
108                m_openChannels = new Dictionary<UUID, RPCChannelInfo>();
109                m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
110                m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
111                m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
112
113                if (config.Configs["XMLRPC"] != null)
114                    m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
115            }
116        }
117
118        public void AddRegion(IScene scene)
119        {
120            scene.RegisterModuleInterface<IXMLRPC>(this);
121        }
122
123        public void RemoveRegion(IScene scene)
124        {
125            scene.UnregisterModuleInterface<IXMLRPC>(this);
126        }
127
128        public void RegionLoaded(IScene scene)
129        {
130            if (IsEnabled() && !m_httpServerStarted)
131            {
132                m_httpServerStarted = true;
133                // Start http server
134                // Attach xmlrpc handlers
135                MainConsole.Instance.Info("[XMLRPC MODULE]: " +
136                                          "Starting up XMLRPC Server on port " + m_remoteDataPort +
137                                          " for llRemoteData commands.");
138                IHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort, MainServer.Instance.HostName,
139                                                            false);
140                httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
141                httpServer.Start();
142            }
143            m_scriptModule = scene.RequestModuleInterface<IScriptModule>();
144        }
145
146        public Type ReplaceableInterface
147        {
148            get { return null; }
149        }
150
151        public void Close()
152        {
153        }
154
155        public string Name
156        {
157            get { return m_name; }
158        }
159
160        #endregion
161
162        #region IXMLRPC Members
163
164        public int Port
165        {
166            get { return m_remoteDataPort; }
167        }
168
169        public bool IsEnabled()
170        {
171            return (m_remoteDataPort > 0);
172        }
173
174        /**********************************************
175         * OpenXMLRPCChannel
176         *
177         * Generate a UUID channel key and add it and
178         * the prim id to dictionary <channelUUID, primUUID>
179         *
180         * A custom channel key can be proposed.
181         * Otherwise, passing UUID.Zero will generate
182         * and return a random channel
183         *
184         * First check if there is a channel assigned for
185         * this itemID.  If there is, then someone called
186         * llOpenRemoteDataChannel twice.  Just return the
187         * original channel.  Other option is to delete the
188         * current channel and assign a new one.
189         *
190         * ********************************************/
191
192        public UUID OpenXMLRPCChannel(UUID primID, UUID itemID, UUID channelID)
193        {
194            UUID newChannel = UUID.Zero;
195
196            // This should no longer happen, but the check is reasonable anyway
197            if (null == m_openChannels)
198            {
199                MainConsole.Instance.Warn("[XML RPC MODULE]: Attempt to open channel before initialization is complete");
200                return newChannel;
201            }
202
203            //Is a dupe?
204#if (!ISWIN)
205            foreach (RPCChannelInfo ci in m_openChannels.Values)
206            {
207                if (ci.GetItemID().Equals(itemID))
208                {
209                    // return the original channel ID for this item
210                    newChannel = ci.GetChannelID();
211                    break;
212                }
213            }
214#else
215            foreach (RPCChannelInfo ci in m_openChannels.Values.Where(ci => ci.GetItemID().Equals(itemID)))
216            {
217                // return the original channel ID for this item
218                newChannel = ci.GetChannelID();
219                break;
220            }
221#endif
222
223            if (newChannel == UUID.Zero)
224            {
225                newChannel = (channelID == UUID.Zero) ? UUID.Random() : channelID;
226                RPCChannelInfo rpcChanInfo = new RPCChannelInfo(primID, itemID, newChannel);
227                lock (XMLRPCListLock)
228                {
229                    m_openChannels.Add(newChannel, rpcChanInfo);
230                }
231            }
232
233            //Make sure that the cmd handler thread is running
234            m_scriptModule.PokeThreads(itemID);
235
236            return newChannel;
237        }
238
239        // Delete channels based on itemID
240        // for when a script is deleted
241        public void DeleteChannels(UUID itemID)
242        {
243            if (m_openChannels != null)
244            {
245                ArrayList tmp = new ArrayList();
246
247                lock (XMLRPCListLock)
248                {
249#if (!ISWIN)
250                    foreach (RPCChannelInfo li in m_openChannels.Values)
251                    {
252                        if (li.GetItemID().Equals(itemID))
253                        {
254                            tmp.Add(itemID);
255                        }
256                    }
257#else
258                    foreach (RPCChannelInfo li in m_openChannels.Values.Where(li => li.GetItemID().Equals(itemID)))
259                    {
260                        tmp.Add(itemID);
261                    }
262#endif
263
264                    IEnumerator tmpEnumerator = tmp.GetEnumerator();
265                    while (tmpEnumerator.MoveNext())
266                        m_openChannels.Remove((UUID) tmpEnumerator.Current);
267                }
268            }
269
270            //Make sure that the cmd handler thread is running
271            m_scriptModule.PokeThreads(itemID);
272        }
273
274        /**********************************************
275         * Remote Data Reply
276         *
277         * Response to RPC message
278         *
279         *********************************************/
280
281        public void RemoteDataReply(string channel, string message_id, string sdata, int idata)
282        {
283            UUID message_key = new UUID(message_id);
284            UUID channel_key = new UUID(channel);
285
286            RPCRequestInfo rpcInfo = null;
287
288            if (message_key == UUID.Zero)
289            {
290#if (!ISWIN)
291                foreach (RPCRequestInfo oneRpcInfo in m_rpcPendingResponses.Values)
292                {
293                    if (oneRpcInfo.GetChannelKey() == channel_key) rpcInfo = oneRpcInfo;
294                }
295#else
296                foreach (
297                    RPCRequestInfo oneRpcInfo in
298                        m_rpcPendingResponses.Values.Where(oneRpcInfo => oneRpcInfo.GetChannelKey() == channel_key))
299                    rpcInfo = oneRpcInfo;
300#endif
301            }
302            else
303            {
304                m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo);
305            }
306
307            if (rpcInfo != null)
308            {
309                rpcInfo.SetStrRetval(sdata);
310                rpcInfo.SetIntRetval(idata);
311                rpcInfo.SetProcessed(true);
312                m_rpcPendingResponses.Remove(message_key);
313
314                //Make sure that the cmd handler thread is running
315                m_scriptModule.PokeThreads(rpcInfo.GetItemID());
316            }
317            else
318            {
319                MainConsole.Instance.Warn("[XML RPC MODULE]: Channel or message_id not found");
320            }
321        }
322
323        /**********************************************
324         * CloseXMLRPCChannel
325         *
326         * Remove channel from dictionary
327         *
328         *********************************************/
329
330        public void CloseXMLRPCChannel(UUID channelKey)
331        {
332            if (m_openChannels.ContainsKey(channelKey))
333                m_openChannels.Remove(channelKey);
334        }
335
336
337        public bool hasRequests()
338        {
339            lock (XMLRPCListLock)
340            {
341                if (m_rpcPending != null)
342                    if (m_rpcPending.Count > 0)
343                        return true;
344                if (m_pendingSRDResponses != null)
345                    if (m_pendingSRDResponses.Count > 0)
346                        return true;
347                return false;
348            }
349        }
350
351        public IXmlRpcRequestInfo GetNextCompletedRequest()
352        {
353            if (m_rpcPending != null)
354            {
355                if (m_rpcPending.Count == 0)
356                    return null;
357                lock (XMLRPCListLock)
358                {
359#if (!ISWIN)
360                    foreach (RPCRequestInfo luid in m_rpcPending.Values)
361                    {
362                        if (!luid.IsProcessed())
363                        {
364                            return luid;
365                        }
366                    }
367#else
368                    foreach (RPCRequestInfo luid in m_rpcPending.Values.Where(luid => !luid.IsProcessed()))
369                    {
370                        return luid;
371                    }
372#endif
373                }
374            }
375            return null;
376        }
377
378        public void RemoveCompletedRequest(UUID id)
379        {
380            lock (XMLRPCListLock)
381            {
382                RPCRequestInfo tmp;
383                if (m_rpcPending.TryGetValue(id, out tmp))
384                {
385                    m_rpcPending.Remove(id);
386                    m_rpcPendingResponses.Add(id, tmp);
387                }
388                else
389                {
390                    MainConsole.Instance.Error("[XML RPC MODULE]: UNABLE TO REMOVE COMPLETED REQUEST");
391                }
392            }
393        }
394
395        public UUID SendRemoteData(UUID primID, UUID itemID, string channel, string dest, int idata, string sdata)
396        {
397            SendRemoteDataRequest req = new SendRemoteDataRequest(
398                primID, itemID, channel, dest, idata, sdata
399                );
400            m_pendingSRDResponses.Add(req.GetReqID(), req);
401            req.Process();
402
403            //Make sure that the cmd handler thread is running
404            m_scriptModule.PokeThreads(itemID);
405            return req.ReqID;
406        }
407
408        public IServiceRequest GetNextCompletedSRDRequest()
409        {
410            if (m_pendingSRDResponses != null)
411            {
412                if (m_pendingSRDResponses.Count == 0)
413                    return null;
414                lock (XMLRPCListLock)
415                {
416#if (!ISWIN)
417                    foreach (SendRemoteDataRequest luid in m_pendingSRDResponses.Values)
418                    {
419                        if (luid.Finished)
420                        {
421                            return luid;
422                        }
423                    }
424#else
425                    foreach (SendRemoteDataRequest luid in m_pendingSRDResponses.Values.Where(luid => luid.Finished))
426                    {
427                        return luid;
428                    }
429#endif
430                }
431            }
432            return null;
433        }
434
435        public void RemoveCompletedSRDRequest(UUID id)
436        {
437            lock (XMLRPCListLock)
438            {
439                SendRemoteDataRequest tmpReq;
440                if (m_pendingSRDResponses.TryGetValue(id, out tmpReq))
441                {
442                    m_pendingSRDResponses.Remove(id);
443                }
444            }
445        }
446
447        public void CancelSRDRequests(UUID itemID)
448        {
449            if (m_pendingSRDResponses != null)
450            {
451                lock (XMLRPCListLock)
452                {
453#if (!ISWIN)
454                    foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values)
455                    {
456                        if (li.ItemID.Equals(itemID))
457                        {
458                            m_pendingSRDResponses.Remove(li.GetReqID());
459                        }
460                    }
461#else
462                    foreach (
463                        SendRemoteDataRequest li in m_pendingSRDResponses.Values.Where(li => li.ItemID.Equals(itemID)))
464                    {
465                        m_pendingSRDResponses.Remove(li.GetReqID());
466                    }
467#endif
468                }
469            }
470        }
471
472        #endregion
473
474        public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request, IPEndPoint remoteClient)
475        {
476            XmlRpcResponse response = new XmlRpcResponse();
477
478            Hashtable requestData = (Hashtable) request.Params[0];
479            bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") &&
480                            requestData.Contains("StringValue"));
481
482            if (GoodXML)
483            {
484                UUID channel = new UUID((string) requestData["Channel"]);
485                RPCChannelInfo rpcChanInfo;
486                if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
487                {
488                    string intVal = Convert.ToInt32(requestData["IntValue"]).ToString();
489                    string strVal = (string) requestData["StringValue"];
490
491                    RPCRequestInfo rpcInfo;
492
493                    lock (XMLRPCListLock)
494                    {
495                        rpcInfo =
496                            new RPCRequestInfo(rpcChanInfo.GetPrimID(), rpcChanInfo.GetItemID(), channel, strVal,
497                                               intVal);
498                        m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo);
499                    }
500
501                    int timeoutCtr = 0;
502
503                    while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout))
504                    {
505                        Thread.Sleep(RemoteReplyScriptWait);
506                        timeoutCtr += RemoteReplyScriptWait;
507                    }
508                    if (rpcInfo.IsProcessed())
509                    {
510                        Hashtable param = new Hashtable();
511                        param["StringValue"] = rpcInfo.GetStrRetval();
512                        param["IntValue"] = rpcInfo.GetIntRetval();
513
514                        ArrayList parameters = new ArrayList {param};
515
516                        response.Value = parameters;
517                        rpcInfo = null;
518                    }
519                    else
520                    {
521                        response.SetFault(-1, "Script timeout");
522                        rpcInfo = null;
523                    }
524                }
525                else
526                {
527                    response.SetFault(-1, "Invalid channel");
528                }
529            }
530
531            //Make sure that the cmd handler thread is running
532            m_scriptModule.PokeThreads(UUID.Zero);
533
534            return response;
535        }
536    }
537
538    public class RPCRequestInfo : IXmlRpcRequestInfo
539    {
540        private readonly UUID m_ChannelKey;
541        private readonly string m_IntVal;
542        private readonly UUID m_ItemID;
543        private readonly UUID m_MessageID;
544        private readonly UUID m_PrimID;
545        private readonly string m_StrVal;
546        private bool m_processed;
547        private int m_respInt;
548        private string m_respStr;
549
550        public RPCRequestInfo(UUID primID, UUID itemID, UUID channelKey, string strVal, string intVal)
551        {
552            m_PrimID = primID;
553            m_StrVal = strVal;
554            m_IntVal = intVal;
555            m_ItemID = itemID;
556            m_ChannelKey = channelKey;
557            m_MessageID = UUID.Random();
558            m_processed = false;
559            m_respStr = String.Empty;
560            m_respInt = 0;
561        }
562
563        #region IXmlRpcRequestInfo Members
564
565        public bool IsProcessed()
566        {
567            return m_processed;
568        }
569
570        public UUID GetChannelKey()
571        {
572            return m_ChannelKey;
573        }
574
575        public void SetProcessed(bool processed)
576        {
577            m_processed = processed;
578        }
579
580        public void SetStrRetval(string resp)
581        {
582            m_respStr = resp;
583        }
584
585        public string GetStrRetval()
586        {
587            return m_respStr;
588        }
589
590        public void SetIntRetval(int resp)
591        {
592            m_respInt = resp;
593        }
594
595        public int GetIntRetval()
596        {
597            return m_respInt;
598        }
599
600        public UUID GetPrimID()
601        {
602            return m_PrimID;
603        }
604
605        public UUID GetItemID()
606        {
607            return m_ItemID;
608        }
609
610        public string GetStrVal()
611        {
612            return m_StrVal;
613        }
614
615        public int GetIntValue()
616        {
617            return int.Parse(m_IntVal);
618        }
619
620        public UUID GetMessageID()
621        {
622            return m_MessageID;
623        }
624
625        #endregion
626    }
627
628    public class RPCChannelInfo
629    {
630        private readonly UUID m_ChannelKey;
631        private readonly UUID m_itemID;
632        private readonly UUID m_primID;
633
634        public RPCChannelInfo(UUID primID, UUID itemID, UUID channelID)
635        {
636            m_ChannelKey = channelID;
637            m_primID = primID;
638            m_itemID = itemID;
639        }
640
641        public UUID GetItemID()
642        {
643            return m_itemID;
644        }
645
646        public UUID GetChannelID()
647        {
648            return m_ChannelKey;
649        }
650
651        public UUID GetPrimID()
652        {
653            return m_primID;
654        }
655    }
656
657    public class SendRemoteDataRequest : ISendRemoteDataRequest
658    {
659        public string Channel { get; set; }
660        public string DestURL { get; set; }
661        public int Idata { get; set; }
662
663        public XmlRpcRequest Request { get; set; }
664        public int ResponseIdata { get; set; }
665        public string ResponseSdata { get; set; }
666        public string Sdata { get; set; }
667        private bool _finished;
668        private Thread httpThread;
669
670        public SendRemoteDataRequest(UUID primID, UUID itemID, string channel, string dest, int idata, string sdata)
671        {
672            this.Channel = channel;
673            DestURL = dest;
674            this.Idata = idata;
675            this.Sdata = sdata;
676            ItemID = itemID;
677            PrimID = primID;
678
679            ReqID = UUID.Random();
680        }
681
682        #region IServiceRequest Members
683
684        public bool Finished
685        {
686            get { return _finished; }
687            set { _finished = value; }
688        }
689
690        public UUID ItemID { get; set; }
691
692        public UUID PrimID { get; set; }
693
694        public UUID ReqID { get; set; }
695
696        public void Process()
697        {
698            httpThread = new Thread(SendRequest)
699                             {Name = "HttpRequestThread", Priority = ThreadPriority.BelowNormal, IsBackground = true};
700            _finished = false;
701            httpThread.Start();
702        }
703
704        /*
705         * TODO: More work on the response codes.  Right now
706         * returning 200 for success or 499 for exception
707         */
708
709        public void SendRequest()
710        {
711            Culture.SetCurrentCulture();
712            Hashtable param = new Hashtable();
713
714            // Check if channel is an UUID
715            // if not, use as method name
716            UUID parseUID;
717            string mName = "llRemoteData";
718            if (!string.IsNullOrEmpty(Channel))
719                if (!UUID.TryParse(Channel, out parseUID))
720                    mName = Channel;
721                else
722                    param["Channel"] = Channel;
723
724            param["StringValue"] = Sdata;
725            param["IntValue"] = Convert.ToString(Idata);
726
727            ArrayList parameters = new ArrayList {param};
728            XmlRpcRequest req = new XmlRpcRequest(mName, parameters);
729            try
730            {
731                XmlRpcResponse resp = req.Send(DestURL, 30000);
732                if (resp != null)
733                {
734                    Hashtable respParms;
735                    if (resp.Value.GetType().Equals(typeof (Hashtable)))
736                    {
737                        respParms = (Hashtable) resp.Value;
738                    }
739                    else
740                    {
741                        ArrayList respData = (ArrayList) resp.Value;
742                        respParms = (Hashtable) respData[0];
743                    }
744                    if (respParms != null)
745                    {
746                        if (respParms.Contains("StringValue"))
747                        {
748                            Sdata = (string) respParms["StringValue"];
749                        }
750                        if (respParms.Contains("IntValue"))
751                        {
752                            Idata = Convert.ToInt32(respParms["IntValue"]);
753                        }
754                        if (respParms.Contains("faultString"))
755                        {
756                            Sdata = (string) respParms["faultString"];
757                        }
758                        if (respParms.Contains("faultCode"))
759                        {
760                            Idata = Convert.ToInt32(respParms["faultCode"]);
761                        }
762                    }
763                }
764            }
765            catch (Exception we)
766            {
767                Sdata = we.Message;
768                MainConsole.Instance.Warn("[SendRemoteDataRequest]: Request failed");
769                MainConsole.Instance.Warn(we.StackTrace);
770            }
771
772            _finished = true;
773        }
774
775        public void Stop()
776        {
777            try
778            {
779                httpThread.Abort();
780            }
781            catch (Exception)
782            {
783            }
784        }
785
786        #endregion
787
788        public UUID GetReqID()
789        {
790            return ReqID;
791        }
792    }
793}