123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- using libsecondlife;
- using OpenSim.Region.ScriptEngine.Common.TRPC;
- namespace OpenSim.Region.ScriptEngine.Common
- {
- public class TRPC_Remote
- {
- public readonly int MaxQueueSize = 1024 * 10;
- public readonly TCPCommon.ServerAndClientInterface TCPS;
- public delegate void ReceiveCommandDelegate(int ID, string Command, params object[] p);
- public event ReceiveCommandDelegate ReceiveCommand;
- System.Collections.Generic.Dictionary<string, Type> TypeDictionary = new Dictionary<string, Type>();
- Type[] Types =
- {
- typeof(System.String),
- typeof(System.Int16),
- typeof(System.Int32),
- typeof(System.Int64),
- typeof(System.Double),
- typeof(System.Decimal),
- typeof(System.Array),
- typeof(LLUUID),
- typeof(System.UInt16),
- typeof(System.UInt32),
- typeof(System.UInt64)
- };
- // TODO: Maybe we should move queue into TCPSocket so we won't have to keep one queue instance per connection
- private System.Collections.Generic.Dictionary<int, InQueueStruct> InQueue = new Dictionary<int, InQueueStruct>();
- private class InQueueStruct
- {
- public byte[] Queue;
- public int QueueSize;
- public object QueueLockObject = new object();
- }
- public TRPC_Remote(TCPCommon.ServerAndClientInterface TCPClientOrServer)
- {
- TCPS = TCPClientOrServer;
- TCPS.Close += new TCPCommon.CloseDelegate(TCPS_Close);
- TCPS.ClientConnected += new TCPCommon.ClientConnectedDelegate(TCPS_ClientConnected);
- TCPS.DataReceived += new TCPCommon.DataReceivedDelegate(TCPS_DataReceived);
- //TCPS.StartListen();
- // Make a lookup dictionary for types
- foreach (Type t in Types)
- {
- TypeDictionary.Add(t.ToString(), t);
- }
- }
- void TCPS_ClientConnected(int ID, System.Net.EndPoint Remote)
- {
- // Create a incoming queue for this connection
- InQueueStruct iq = new InQueueStruct();
- iq.Queue = new byte[MaxQueueSize];
- iq.QueueSize = 0;
- InQueue.Add(ID, iq);
- }
- void TCPS_Close(int ID)
- {
- // Remove queue
- InQueue.Remove(ID);
- }
- void TCPS_DataReceived(int ID, byte[] data, int offset, int length)
- {
- // Copy new data to incoming queue
- lock (InQueue[ID].QueueLockObject)
- {
- Array.Copy(data, offset, InQueue[ID].Queue, InQueue[ID].QueueSize, length);
- InQueue[ID].QueueSize += length;
- // Process incoming queue
- ProcessQueue(ID);
- }
- }
- private void ProcessQueue(int ID)
- {
- // This is just a temp implementation -- not so fast :)
- InQueueStruct myIQS = InQueue[ID];
- if (myIQS.QueueSize == 0)
- return;
- string receivedData = Encoding.ASCII.GetString(myIQS.Queue, 0, myIQS.QueueSize);
- Debug.WriteLine("RAW: " + receivedData);
- byte newLine = 10;
- while (true)
- {
- bool ShouldProcess = false;
- int lineEndPos = 0;
- // Look for newline
- for (int i = 0; i < myIQS.QueueSize; i++)
- {
- if (myIQS.Queue[i] == newLine)
- {
- ShouldProcess = true;
- lineEndPos = i;
- break;
- }
- }
- // Process it?
- if (!ShouldProcess)
- return;
- // Yes
- string cmdLine = Encoding.ASCII.GetString(myIQS.Queue, 0, lineEndPos);
- Debug.WriteLine("Command: " + cmdLine);
- // Fix remaining queue in an inefficient way
- byte[] newQueue = new byte[MaxQueueSize];
- Array.Copy(myIQS.Queue, lineEndPos, newQueue, 0, myIQS.QueueSize - lineEndPos);
- myIQS.Queue = newQueue;
- myIQS.QueueSize -= (lineEndPos + 1);
- // Now back to the command
- string[] parts = cmdLine.Split(',');
- if (parts.Length > 0)
- {
- string cmd = parts[0];
- int paramCount = parts.Length - 1;
- object[] param = null;
- if (paramCount > 0)
- {
- // Process all parameters (decoding them from URL encoding)
- param = new object[paramCount];
- for (int i = 1; i < parts.Length; i++)
- {
- string[] spl;
- spl = System.Web.HttpUtility.UrlDecode(parts[i]).Split('|');
- string t = spl[0];
- param[i - 1] = Convert.ChangeType(spl[1], TypeLookup(t));
- }
- }
- ReceiveCommand(ID, cmd, param);
- }
- }
- }
- private Type TypeLookup(string t)
- {
- Type ret = TypeDictionary[t];
- if (ret != null)
- return ret;
- return typeof(object);
- }
- public void SendCommand(int ID, string Command, params object[] p)
- {
- // Call PacketFactory to have it create a packet for us
- //string[] tmpP = new string[p.Length];
- string tmpStr = Command;
- for (int i = 0; i < p.Length; i++)
- {
- tmpStr += "," + p[i].GetType().ToString() + "|" + System.Web.HttpUtility.UrlEncode(p[i].ToString()); // .Replace(",", "%44")
- }
- tmpStr += "\n";
- byte[] byteData = Encoding.ASCII.GetBytes(tmpStr);
- TCPS.Send(ID, byteData, 0, byteData.Length);
- }
- }
- }
|