diff options
author | Adam Frisby | 2009-02-22 08:48:55 +0000 |
---|---|---|
committer | Adam Frisby | 2009-02-22 08:48:55 +0000 |
commit | 937a2e6dcae6c4369ee6952a2697ae31aaba4903 (patch) | |
tree | c205d090b7595a16bd261723a1e3f1bef5dbada8 /OpenSim/Client/MXP/PacketHandler | |
parent | Refactor log4net logger handling in script engine. (#3148) (diff) | |
download | opensim-SC-937a2e6dcae6c4369ee6952a2697ae31aaba4903.zip opensim-SC-937a2e6dcae6c4369ee6952a2697ae31aaba4903.tar.gz opensim-SC-937a2e6dcae6c4369ee6952a2697ae31aaba4903.tar.bz2 opensim-SC-937a2e6dcae6c4369ee6952a2697ae31aaba4903.tar.xz |
* Adds initial support for the MXP Virtual Worlds protocol (http://www.bubblecloud.org)
* Handled via the MXPModule.cs located in OpenSim.Client.MXP namespace.
* Also implements MXPClientView and MXPPacketServer for IClientAPI compatibility.
* No changes were required to Core to implement this - the thing is self contained in OpenSim.Client.MXP.dll.
* Includes reference implementation of MXP as MXP.dll - this is under the Apache 2.0 license.
* Requires OpenSim.ini setting to enable. "[MXP] \n Enabled=true \n Port=1253"
* May break. Highly untested.
Diffstat (limited to 'OpenSim/Client/MXP/PacketHandler')
-rw-r--r-- | OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs new file mode 100644 index 0000000..b35ab9c --- /dev/null +++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs | |||
@@ -0,0 +1,367 @@ | |||
1 | /* This file borrows heavily from MXPServer.cs - the reference MXPServer | ||
2 | * See http://www.bubblecloud.org for a copy of the original file and | ||
3 | * implementation details. */ | ||
4 | using System; | ||
5 | using System.Collections.Generic; | ||
6 | using System.Reflection; | ||
7 | using log4net; | ||
8 | using MXP; | ||
9 | using MXP.Messages; | ||
10 | using OpenMetaverse; | ||
11 | using OpenSim.Client.MXP.ClientStack; | ||
12 | using OpenSim.Region.Framework.Scenes; | ||
13 | |||
14 | namespace OpenSim.Client.MXP.PacketHandler | ||
15 | { | ||
16 | class MXPPacketServer | ||
17 | { | ||
18 | internal static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
19 | |||
20 | private readonly List<MXPClientView> Clients = new List<MXPClientView>(); | ||
21 | private readonly Dictionary<UUID, Scene> Scenes; | ||
22 | |||
23 | #region Fields | ||
24 | |||
25 | private readonly Transmitter transmitter; | ||
26 | |||
27 | private readonly IList<Session> sessions = new List<Session>(); | ||
28 | private readonly IList<MXPClientView> sessionsToRemove = new List<MXPClientView>(); | ||
29 | |||
30 | private readonly String cloudUrl; | ||
31 | private readonly String programName; | ||
32 | private readonly byte programMajorVersion; | ||
33 | private readonly byte programMinorVersion; | ||
34 | |||
35 | #endregion | ||
36 | |||
37 | #region Constructors | ||
38 | |||
39 | public MXPPacketServer(string cloudUrl, int port, Dictionary<UUID, Scene> scenes) | ||
40 | { | ||
41 | this.cloudUrl = cloudUrl; | ||
42 | |||
43 | Scenes = scenes; | ||
44 | |||
45 | programMinorVersion = 63; | ||
46 | programMajorVersion = 0; | ||
47 | programName = "OpenSimulator"; | ||
48 | |||
49 | transmitter = new Transmitter(port); | ||
50 | } | ||
51 | |||
52 | #endregion | ||
53 | |||
54 | #region Properties | ||
55 | |||
56 | /// <summary> | ||
57 | /// Number of sessions pending. (Process() accepts pending sessions). | ||
58 | /// </summary> | ||
59 | public int PendingSessionCount | ||
60 | { | ||
61 | get | ||
62 | { | ||
63 | return transmitter.PendingSessionCount; | ||
64 | } | ||
65 | } | ||
66 | /// <summary> | ||
67 | /// Number of connected sessions. | ||
68 | /// </summary> | ||
69 | public int SessionCount | ||
70 | { | ||
71 | get | ||
72 | { | ||
73 | return sessions.Count; | ||
74 | } | ||
75 | } | ||
76 | /// <summary> | ||
77 | /// Property reflecting whether client transmitter threads are alive. | ||
78 | /// </summary> | ||
79 | public bool IsTransmitterAlive | ||
80 | { | ||
81 | get | ||
82 | { | ||
83 | return transmitter != null && transmitter.IsAlive; | ||
84 | } | ||
85 | } | ||
86 | /// <summary> | ||
87 | /// Number of packets sent. | ||
88 | /// </summary> | ||
89 | public ulong PacketsSent | ||
90 | { | ||
91 | get | ||
92 | { | ||
93 | return transmitter != null ? transmitter.PacketsSent : 0; | ||
94 | } | ||
95 | } | ||
96 | /// <summary> | ||
97 | /// Number of packets received. | ||
98 | /// </summary> | ||
99 | public ulong PacketsReceived | ||
100 | { | ||
101 | get | ||
102 | { | ||
103 | return transmitter != null ? transmitter.PacketsReceived : 0; | ||
104 | } | ||
105 | } | ||
106 | /// <summary> | ||
107 | /// Bytes client has received so far. | ||
108 | /// </summary> | ||
109 | public ulong BytesReceived | ||
110 | { | ||
111 | get | ||
112 | { | ||
113 | return transmitter != null ? transmitter.BytesReceived : 0; | ||
114 | } | ||
115 | } | ||
116 | /// <summary> | ||
117 | /// Bytes client has sent so far. | ||
118 | /// </summary> | ||
119 | public ulong BytesSent | ||
120 | { | ||
121 | get | ||
122 | { | ||
123 | return transmitter != null ? transmitter.BytesSent : 0; | ||
124 | } | ||
125 | } | ||
126 | /// <summary> | ||
127 | /// Number of bytes received (bytes per second) during past second. | ||
128 | /// </summary> | ||
129 | public double ReceiveRate | ||
130 | { | ||
131 | get | ||
132 | { | ||
133 | return transmitter != null ? transmitter.ReceiveRate : 0; | ||
134 | } | ||
135 | } | ||
136 | /// <summary> | ||
137 | /// Number of bytes sent (bytes per second) during past second. | ||
138 | /// </summary> | ||
139 | public double SendRate | ||
140 | { | ||
141 | get | ||
142 | { | ||
143 | return transmitter != null ? transmitter.SendRate : 0; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | #endregion | ||
148 | |||
149 | #region Session Management | ||
150 | |||
151 | public void Disconnect(Session session) | ||
152 | { | ||
153 | if (session.IsConnected) | ||
154 | { | ||
155 | Message message = MessageFactory.Current.ReserveMessage(typeof(LeaveRequestMessage)); | ||
156 | session.Send(message); | ||
157 | MessageFactory.Current.ReleaseMessage(message); | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | throw new Exception("Not connected."); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | #endregion | ||
166 | |||
167 | |||
168 | #region Processing | ||
169 | |||
170 | public void PrintDebugInformation() | ||
171 | { | ||
172 | m_log.Info("[MXP ClientStack] Statistics report"); | ||
173 | m_log.Info("Pending Sessions: " + PendingSessionCount); | ||
174 | m_log.Info("Sessions: " + SessionCount + " (Clients: " + Clients.Count + " )"); | ||
175 | m_log.Info("Transmitter Alive?: " + IsTransmitterAlive); | ||
176 | m_log.Info("Packets Sent/Recieved: " + PacketsSent + " / " + PacketsReceived); | ||
177 | m_log.Info("Bytes Sent/Recieved: " + BytesSent + " / " + BytesReceived); | ||
178 | m_log.Info("Send/Recieve Rate (bps): " + SendRate + " / " + ReceiveRate); | ||
179 | } | ||
180 | |||
181 | public void Process() | ||
182 | { | ||
183 | ProcessMessages(); | ||
184 | Clean(); | ||
185 | } | ||
186 | |||
187 | public void Clean() | ||
188 | { | ||
189 | foreach (MXPClientView clientView in Clients) | ||
190 | { | ||
191 | if (clientView.Session.SessionState == SessionState.Disconnected) | ||
192 | { | ||
193 | sessionsToRemove.Add(clientView); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | foreach (MXPClientView clientView in sessionsToRemove) | ||
198 | { | ||
199 | clientView.Scene.RemoveClient(clientView.AgentId); | ||
200 | Clients.Remove(clientView); | ||
201 | sessions.Remove(clientView.Session); | ||
202 | } | ||
203 | |||
204 | sessionsToRemove.Clear(); | ||
205 | } | ||
206 | |||
207 | public bool AuthoriseUser(string participantName, string pass, UUID scene) | ||
208 | { | ||
209 | if (Scenes.ContainsKey(scene)) | ||
210 | return true; | ||
211 | |||
212 | return false; | ||
213 | } | ||
214 | |||
215 | public void ProcessMessages() | ||
216 | { | ||
217 | if (transmitter.PendingSessionCount > 0) | ||
218 | { | ||
219 | sessions.Add(transmitter.AcceptPendingSession()); | ||
220 | } | ||
221 | |||
222 | foreach (MXPClientView clientView in Clients) | ||
223 | { | ||
224 | |||
225 | int messagesProcessedCount = 0; | ||
226 | Session session = clientView.Session; | ||
227 | |||
228 | while (session.AvailableMessages > 0) | ||
229 | { | ||
230 | |||
231 | Message message = session.Receive(); | ||
232 | |||
233 | if (message.GetType() == typeof(JoinRequestMessage)) | ||
234 | { | ||
235 | |||
236 | JoinRequestMessage joinRequestMessage = (JoinRequestMessage)message; | ||
237 | |||
238 | bool authorized = AuthoriseUser(joinRequestMessage.ParticipantName, | ||
239 | joinRequestMessage.ParticipantPassphrase, | ||
240 | new UUID(joinRequestMessage.BubbleId)); | ||
241 | |||
242 | if (authorized) | ||
243 | { | ||
244 | Scene target = Scenes[new UUID(joinRequestMessage.BubbleId)]; | ||
245 | |||
246 | UUID mxpSessionID = UUID.Random(); | ||
247 | |||
248 | m_log.Info("[MXP ClientStack] Session join request success: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")"); | ||
249 | |||
250 | AcceptConnection(session, joinRequestMessage, mxpSessionID); | ||
251 | |||
252 | MXPClientView client = new MXPClientView(session, mxpSessionID, target, | ||
253 | joinRequestMessage.ParticipantName); | ||
254 | Clients.Add(client); | ||
255 | |||
256 | target.AddNewClient(client); | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | m_log.Info("[MXP ClientStack] Session join request failure: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")"); | ||
261 | |||
262 | DeclineConnection(session, joinRequestMessage); | ||
263 | } | ||
264 | |||
265 | } | ||
266 | if (message.GetType() == typeof(LeaveRequestMessage)) | ||
267 | { | ||
268 | |||
269 | LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)MessageFactory.Current.ReserveMessage( | ||
270 | typeof(LeaveResponseMessage)); | ||
271 | |||
272 | m_log.Info("[MXP ClientStack] Session leave request: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")"); | ||
273 | |||
274 | leaveResponseMessage.RequestMessageId = message.MessageId; | ||
275 | leaveResponseMessage.FailureCode = 0; | ||
276 | session.Send(leaveResponseMessage); | ||
277 | |||
278 | if (session.SessionState != SessionState.Disconnected) | ||
279 | { | ||
280 | session.SetStateDisconnected(); | ||
281 | } | ||
282 | |||
283 | m_log.Info("[MXP ClientStack] Removing Client from Scene"); | ||
284 | clientView.Scene.RemoveClient(clientView.AgentId); | ||
285 | } | ||
286 | if (message.GetType() == typeof(LeaveResponseMessage)) | ||
287 | { | ||
288 | |||
289 | LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)message; | ||
290 | |||
291 | m_log.Info("[MXP ClientStack] Session leave response: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")"); | ||
292 | |||
293 | if (leaveResponseMessage.FailureCode == 0) | ||
294 | { | ||
295 | session.SetStateDisconnected(); | ||
296 | } | ||
297 | |||
298 | m_log.Info("[MXP ClientStack] Removing Client from Scene"); | ||
299 | clientView.Scene.RemoveClient(clientView.AgentId); | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | clientView.ProcessMXPPacket(message); | ||
304 | } | ||
305 | |||
306 | MessageFactory.Current.ReleaseMessage(message); | ||
307 | messagesProcessedCount++; | ||
308 | if (messagesProcessedCount > 1000) | ||
309 | { | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
316 | private void AcceptConnection(Session session, JoinRequestMessage joinRequestMessage, UUID mxpSessionID) | ||
317 | { | ||
318 | JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage( | ||
319 | typeof(JoinResponseMessage)); | ||
320 | |||
321 | joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId; | ||
322 | joinResponseMessage.FailureCode = 0; | ||
323 | |||
324 | joinResponseMessage.ParticipantId = mxpSessionID.Guid; | ||
325 | joinResponseMessage.CloudUrl = cloudUrl; | ||
326 | |||
327 | joinResponseMessage.BubbleName = Scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo.RegionName; | ||
328 | |||
329 | joinResponseMessage.BubbleRealTime = 0; | ||
330 | joinResponseMessage.ProgramName = programName; | ||
331 | joinResponseMessage.ProgramMajorVersion = programMajorVersion; | ||
332 | joinResponseMessage.ProgramMinorVersion = programMinorVersion; | ||
333 | joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion; | ||
334 | joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion; | ||
335 | |||
336 | session.Send(joinResponseMessage); | ||
337 | |||
338 | session.SetStateConnected(); | ||
339 | } | ||
340 | |||
341 | private void DeclineConnection(Session session, Message joinRequestMessage) | ||
342 | { | ||
343 | JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage(typeof(JoinResponseMessage)); | ||
344 | |||
345 | joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId; | ||
346 | joinResponseMessage.FailureCode = 1; | ||
347 | |||
348 | joinResponseMessage.CloudUrl = cloudUrl; | ||
349 | |||
350 | joinResponseMessage.BubbleName = "Declined OpenSim Region"; // Dont reveal anything about the sim in the disconnect notice | ||
351 | |||
352 | joinResponseMessage.BubbleRealTime = 0; | ||
353 | joinResponseMessage.ProgramName = programName; | ||
354 | joinResponseMessage.ProgramMajorVersion = programMajorVersion; | ||
355 | joinResponseMessage.ProgramMinorVersion = programMinorVersion; | ||
356 | joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion; | ||
357 | joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion; | ||
358 | |||
359 | session.Send(joinResponseMessage); | ||
360 | |||
361 | session.SetStateDisconnected(); | ||
362 | } | ||
363 | |||
364 | #endregion | ||
365 | |||
366 | } | ||
367 | } | ||