aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Client/MXP/PacketHandler
diff options
context:
space:
mode:
authorAdam Frisby2009-02-22 08:48:55 +0000
committerAdam Frisby2009-02-22 08:48:55 +0000
commit937a2e6dcae6c4369ee6952a2697ae31aaba4903 (patch)
treec205d090b7595a16bd261723a1e3f1bef5dbada8 /OpenSim/Client/MXP/PacketHandler
parentRefactor log4net logger handling in script engine. (#3148) (diff)
downloadopensim-SC_OLD-937a2e6dcae6c4369ee6952a2697ae31aaba4903.zip
opensim-SC_OLD-937a2e6dcae6c4369ee6952a2697ae31aaba4903.tar.gz
opensim-SC_OLD-937a2e6dcae6c4369ee6952a2697ae31aaba4903.tar.bz2
opensim-SC_OLD-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.cs367
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. */
4using System;
5using System.Collections.Generic;
6using System.Reflection;
7using log4net;
8using MXP;
9using MXP.Messages;
10using OpenMetaverse;
11using OpenSim.Client.MXP.ClientStack;
12using OpenSim.Region.Framework.Scenes;
13
14namespace 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}