diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | 152 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 138 |
2 files changed, 230 insertions, 60 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 2359bd6..b77ead3 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | |||
@@ -27,12 +27,15 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | ||
30 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
31 | using log4net; | 33 | using log4net; |
32 | using Nini.Config; | 34 | using Nini.Config; |
33 | using Mono.Addins; | 35 | using Mono.Addins; |
34 | using OpenMetaverse; | 36 | using OpenMetaverse; |
35 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Servers; | ||
36 | using OpenSim.Framework.Servers.HttpServer; | 39 | using OpenSim.Framework.Servers.HttpServer; |
37 | using OpenSim.Region.Framework.Interfaces; | 40 | using OpenSim.Region.Framework.Interfaces; |
38 | using OpenSim.Region.Framework.Scenes; | 41 | using OpenSim.Region.Framework.Scenes; |
@@ -48,67 +51,49 @@ namespace OpenSim.Region.ClientStack.Linden | |||
48 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] | 51 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] |
49 | public class WebFetchInvDescModule : INonSharedRegionModule | 52 | public class WebFetchInvDescModule : INonSharedRegionModule |
50 | { | 53 | { |
51 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | 55 | ||
53 | private Scene m_scene; | 56 | private Scene m_scene; |
54 | 57 | ||
55 | private IInventoryService m_InventoryService; | 58 | private IInventoryService m_InventoryService; |
56 | private ILibraryService m_LibraryService; | 59 | private ILibraryService m_LibraryService; |
57 | 60 | ||
58 | private bool m_Enabled; | 61 | private WebFetchInvDescHandler m_webFetchHandler; |
59 | 62 | ||
60 | private string m_fetchInventoryDescendents2Url; | 63 | private ManualResetEvent m_ev = new ManualResetEvent(true); |
61 | private string m_webFetchInventoryDescendentsUrl; | 64 | private object m_lock = new object(); |
62 | 65 | ||
63 | private WebFetchInvDescHandler m_webFetchHandler; | 66 | private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); |
67 | private Dictionary<UUID, Hashtable> m_requests = new Dictionary<UUID, Hashtable>(); | ||
64 | 68 | ||
65 | #region ISharedRegionModule Members | 69 | #region ISharedRegionModule Members |
66 | 70 | ||
67 | public void Initialise(IConfigSource source) | 71 | public void Initialise(IConfigSource source) |
68 | { | 72 | { |
69 | IConfig config = source.Configs["ClientStack.LindenCaps"]; | ||
70 | if (config == null) | ||
71 | return; | ||
72 | |||
73 | m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty); | ||
74 | m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty); | ||
75 | |||
76 | if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) | ||
77 | { | ||
78 | m_Enabled = true; | ||
79 | } | ||
80 | } | 73 | } |
81 | 74 | ||
82 | public void AddRegion(Scene s) | 75 | public void AddRegion(Scene s) |
83 | { | 76 | { |
84 | if (!m_Enabled) | ||
85 | return; | ||
86 | |||
87 | m_scene = s; | 77 | m_scene = s; |
88 | } | 78 | } |
89 | 79 | ||
90 | public void RemoveRegion(Scene s) | 80 | public void RemoveRegion(Scene s) |
91 | { | 81 | { |
92 | if (!m_Enabled) | ||
93 | return; | ||
94 | |||
95 | m_scene.EventManager.OnRegisterCaps -= RegisterCaps; | 82 | m_scene.EventManager.OnRegisterCaps -= RegisterCaps; |
83 | m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; | ||
96 | m_scene = null; | 84 | m_scene = null; |
97 | } | 85 | } |
98 | 86 | ||
99 | public void RegionLoaded(Scene s) | 87 | public void RegionLoaded(Scene s) |
100 | { | 88 | { |
101 | if (!m_Enabled) | ||
102 | return; | ||
103 | |||
104 | m_InventoryService = m_scene.InventoryService; | 89 | m_InventoryService = m_scene.InventoryService; |
105 | m_LibraryService = m_scene.LibraryService; | 90 | m_LibraryService = m_scene.LibraryService; |
106 | 91 | ||
107 | // We'll reuse the same handler for all requests. | 92 | // We'll reuse the same handler for all requests. |
108 | if (m_fetchInventoryDescendents2Url == "localhost" || m_webFetchInventoryDescendentsUrl == "localhost") | 93 | m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); |
109 | m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); | ||
110 | 94 | ||
111 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; | 95 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; |
96 | m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; | ||
112 | } | 97 | } |
113 | 98 | ||
114 | public void PostInitialise() | 99 | public void PostInitialise() |
@@ -128,41 +113,110 @@ namespace OpenSim.Region.ClientStack.Linden | |||
128 | 113 | ||
129 | private void RegisterCaps(UUID agentID, Caps caps) | 114 | private void RegisterCaps(UUID agentID, Caps caps) |
130 | { | 115 | { |
131 | if (m_webFetchInventoryDescendentsUrl != "") | 116 | string capUrl = "/CAPS/" + UUID.Random() + "/"; |
132 | RegisterFetchCap(agentID, caps, "WebFetchInventoryDescendents", m_webFetchInventoryDescendentsUrl); | 117 | |
118 | // Register this as a poll service | ||
119 | PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, agentID, 300000); | ||
120 | args.Type = PollServiceEventArgs.EventType.Inventory; | ||
121 | MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); | ||
122 | |||
123 | string hostName = m_scene.RegionInfo.ExternalHostName; | ||
124 | uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; | ||
125 | string protocol = "http"; | ||
126 | |||
127 | if (MainServer.Instance.UseSSL) | ||
128 | { | ||
129 | hostName = MainServer.Instance.SSLCommonName; | ||
130 | port = MainServer.Instance.SSLPort; | ||
131 | protocol = "https"; | ||
132 | } | ||
133 | caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); | ||
133 | 134 | ||
134 | if (m_fetchInventoryDescendents2Url != "") | 135 | m_capsDict[agentID] = capUrl; |
135 | RegisterFetchCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url); | ||
136 | } | 136 | } |
137 | 137 | ||
138 | private void RegisterFetchCap(UUID agentID, Caps caps, string capName, string url) | 138 | private void DeregisterCaps(UUID agentID, Caps caps) |
139 | { | 139 | { |
140 | string capUrl; | 140 | string capUrl; |
141 | 141 | ||
142 | if (url == "localhost") | 142 | if (m_capsDict.TryGetValue(agentID, out capUrl)) |
143 | { | 143 | { |
144 | capUrl = "/CAPS/" + UUID.Random(); | 144 | MainServer.Instance.RemoveHTTPHandler("", capUrl); |
145 | m_capsDict.Remove(agentID); | ||
146 | } | ||
147 | } | ||
145 | 148 | ||
146 | IRequestHandler reqHandler | 149 | public void HttpRequestHandler(UUID requestID, Hashtable request) |
147 | = new RestStreamHandler( | 150 | { |
148 | "POST", | 151 | // m_log.DebugFormat("[FETCH2]: Received request {0}", requestID); |
149 | capUrl, | 152 | m_requests[requestID] = request; |
150 | m_webFetchHandler.FetchInventoryDescendentsRequest, | 153 | } |
151 | "FetchInventoryDescendents2", | ||
152 | agentID.ToString()); | ||
153 | 154 | ||
154 | caps.RegisterHandler(capName, reqHandler); | 155 | private bool HasEvents(UUID requestID, UUID sessionID) |
156 | { | ||
157 | lock (m_lock) | ||
158 | { | ||
159 | if (m_ev.WaitOne(0)) | ||
160 | { | ||
161 | m_ev.Reset(); | ||
162 | return true; | ||
163 | } | ||
164 | return false; | ||
155 | } | 165 | } |
156 | else | 166 | } |
167 | |||
168 | private Hashtable NoEvents(UUID requestID, UUID sessionID) | ||
169 | { | ||
170 | m_requests.Remove(requestID); | ||
171 | |||
172 | Hashtable response = new Hashtable(); | ||
173 | |||
174 | response["int_response_code"] = 500; | ||
175 | response["str_response_string"] = "Script timeout"; | ||
176 | response["content_type"] = "text/plain"; | ||
177 | response["keepalive"] = false; | ||
178 | response["reusecontext"] = false; | ||
179 | |||
180 | return response; | ||
181 | } | ||
182 | |||
183 | private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) | ||
184 | { | ||
185 | Hashtable response = new Hashtable(); | ||
186 | |||
187 | response["int_response_code"] = 500; | ||
188 | response["str_response_string"] = "Internal error"; | ||
189 | response["content_type"] = "text/plain"; | ||
190 | response["keepalive"] = false; | ||
191 | response["reusecontext"] = false; | ||
192 | |||
193 | try | ||
157 | { | 194 | { |
158 | capUrl = url; | 195 | Hashtable requestHash; |
196 | if (!m_requests.TryGetValue(requestID, out requestHash)) | ||
197 | { | ||
198 | lock (m_lock) | ||
199 | m_ev.Set(); | ||
200 | response["str_response_string"] = "Invalid request"; | ||
201 | return response; | ||
202 | } | ||
203 | |||
204 | // m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID); | ||
159 | 205 | ||
160 | caps.RegisterHandler(capName, capUrl); | 206 | string reply = m_webFetchHandler.FetchInventoryDescendentsRequest(requestHash["body"].ToString(), String.Empty, String.Empty, null, null); |
207 | |||
208 | m_requests.Remove(requestID); | ||
209 | |||
210 | response["int_response_code"] = 200; | ||
211 | response["str_response_string"] = reply; | ||
212 | } | ||
213 | finally | ||
214 | { | ||
215 | lock (m_lock) | ||
216 | m_ev.Set(); | ||
161 | } | 217 | } |
162 | 218 | ||
163 | // m_log.DebugFormat( | 219 | return response; |
164 | // "[WEB FETCH INV DESC MODULE]: Registered capability {0} at {1} in region {2} for {3}", | ||
165 | // capName, capUrl, m_scene.RegionInfo.RegionName, agentID); | ||
166 | } | 220 | } |
167 | } | 221 | } |
168 | } \ No newline at end of file | 222 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index fb73e1d..60ab70e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -110,7 +110,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
110 | /// <summary>Handlers for incoming packets</summary> | 110 | /// <summary>Handlers for incoming packets</summary> |
111 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 111 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
112 | /// <summary>Incoming packets that are awaiting handling</summary> | 112 | /// <summary>Incoming packets that are awaiting handling</summary> |
113 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 113 | //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
114 | |||
115 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | ||
116 | |||
114 | /// <summary></summary> | 117 | /// <summary></summary> |
115 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 118 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
116 | /// <summary>Bandwidth throttle for this UDP server</summary> | 119 | /// <summary>Bandwidth throttle for this UDP server</summary> |
@@ -919,7 +922,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
919 | #endregion Ping Check Handling | 922 | #endregion Ping Check Handling |
920 | 923 | ||
921 | // Inbox insertion | 924 | // Inbox insertion |
922 | packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); | 925 | if (packet.Type == PacketType.AgentUpdate || |
926 | packet.Type == PacketType.ChatFromViewer) | ||
927 | packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); | ||
928 | else | ||
929 | packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); | ||
930 | // packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); | ||
923 | } | 931 | } |
924 | 932 | ||
925 | #region BinaryStats | 933 | #region BinaryStats |
@@ -1471,8 +1479,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1471 | Packet packet = incomingPacket.Packet; | 1479 | Packet packet = incomingPacket.Packet; |
1472 | LLClientView client = incomingPacket.Client; | 1480 | LLClientView client = incomingPacket.Client; |
1473 | 1481 | ||
1474 | if (client.IsActive) | 1482 | // if (client.IsActive) |
1475 | { | 1483 | // { |
1476 | m_currentIncomingClient = client; | 1484 | m_currentIncomingClient = client; |
1477 | 1485 | ||
1478 | try | 1486 | try |
@@ -1499,13 +1507,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1499 | { | 1507 | { |
1500 | m_currentIncomingClient = null; | 1508 | m_currentIncomingClient = null; |
1501 | } | 1509 | } |
1502 | } | 1510 | // } |
1503 | else | 1511 | // else |
1504 | { | 1512 | // { |
1505 | m_log.DebugFormat( | 1513 | // m_log.DebugFormat( |
1506 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 1514 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
1507 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 1515 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
1508 | } | 1516 | // } |
1509 | } | 1517 | } |
1510 | 1518 | ||
1511 | protected void LogoutHandler(IClientAPI client) | 1519 | protected void LogoutHandler(IClientAPI client) |
@@ -1519,4 +1527,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1519 | } | 1527 | } |
1520 | } | 1528 | } |
1521 | } | 1529 | } |
1530 | |||
1531 | internal class DoubleQueue<T> where T:class | ||
1532 | { | ||
1533 | private Queue<T> m_lowQueue = new Queue<T>(); | ||
1534 | private Queue<T> m_highQueue = new Queue<T>(); | ||
1535 | |||
1536 | private object m_syncRoot = new object(); | ||
1537 | private Semaphore m_s = new Semaphore(0, 1); | ||
1538 | |||
1539 | public DoubleQueue() | ||
1540 | { | ||
1541 | } | ||
1542 | |||
1543 | public virtual int Count | ||
1544 | { | ||
1545 | get { return m_highQueue.Count + m_lowQueue.Count; } | ||
1546 | } | ||
1547 | |||
1548 | public virtual void Enqueue(T data) | ||
1549 | { | ||
1550 | Enqueue(m_lowQueue, data); | ||
1551 | } | ||
1552 | |||
1553 | public virtual void EnqueueLow(T data) | ||
1554 | { | ||
1555 | Enqueue(m_lowQueue, data); | ||
1556 | } | ||
1557 | |||
1558 | public virtual void EnqueueHigh(T data) | ||
1559 | { | ||
1560 | Enqueue(m_highQueue, data); | ||
1561 | } | ||
1562 | |||
1563 | private void Enqueue(Queue<T> q, T data) | ||
1564 | { | ||
1565 | lock (m_syncRoot) | ||
1566 | { | ||
1567 | m_lowQueue.Enqueue(data); | ||
1568 | m_s.WaitOne(0); | ||
1569 | m_s.Release(); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | public virtual T Dequeue() | ||
1574 | { | ||
1575 | return Dequeue(Timeout.Infinite); | ||
1576 | } | ||
1577 | |||
1578 | public virtual T Dequeue(int tmo) | ||
1579 | { | ||
1580 | return Dequeue(TimeSpan.FromMilliseconds(tmo)); | ||
1581 | } | ||
1582 | |||
1583 | public virtual T Dequeue(TimeSpan wait) | ||
1584 | { | ||
1585 | T res = null; | ||
1586 | |||
1587 | if (!Dequeue(wait, ref res)) | ||
1588 | return null; | ||
1589 | |||
1590 | return res; | ||
1591 | } | ||
1592 | |||
1593 | public bool Dequeue(int timeout, ref T res) | ||
1594 | { | ||
1595 | return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res); | ||
1596 | } | ||
1597 | |||
1598 | public bool Dequeue(TimeSpan wait, ref T res) | ||
1599 | { | ||
1600 | if (!m_s.WaitOne(wait)) | ||
1601 | return false; | ||
1602 | |||
1603 | lock (m_syncRoot) | ||
1604 | { | ||
1605 | if (m_highQueue.Count > 0) | ||
1606 | res = m_highQueue.Dequeue(); | ||
1607 | else | ||
1608 | res = m_lowQueue.Dequeue(); | ||
1609 | |||
1610 | if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) | ||
1611 | return true; | ||
1612 | |||
1613 | try | ||
1614 | { | ||
1615 | m_s.Release(); | ||
1616 | } | ||
1617 | catch | ||
1618 | { | ||
1619 | } | ||
1620 | |||
1621 | return true; | ||
1622 | } | ||
1623 | } | ||
1624 | |||
1625 | public virtual void Clear() | ||
1626 | { | ||
1627 | |||
1628 | lock (m_syncRoot) | ||
1629 | { | ||
1630 | // Make sure sem count is 0 | ||
1631 | m_s.WaitOne(0); | ||
1632 | |||
1633 | m_lowQueue.Clear(); | ||
1634 | m_highQueue.Clear(); | ||
1635 | } | ||
1636 | } | ||
1637 | } | ||
1522 | } | 1638 | } |