aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Client/MXP/PacketHandler
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs561
1 files changed, 0 insertions, 561 deletions
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
deleted file mode 100644
index dcecb8b..0000000
--- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
+++ /dev/null
@@ -1,561 +0,0 @@
1/*
2 * Copyright (c) Contributors, 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 OpenSimulator 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
28/* This file borrows heavily from MXPServer.cs - the reference MXPServer
29 * See http://www.bubblecloud.org for a copy of the original file and
30 * implementation details. */
31
32using System;
33using System.Collections.Generic;
34using System.Reflection;
35using System.Threading;
36using log4net;
37using MXP;
38using MXP.Messages;
39using OpenMetaverse;
40using OpenSim.Client.MXP.ClientStack;
41using OpenSim.Framework;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Framework.Communications;
44using OpenSim.Services.Interfaces;
45using System.Security.Cryptography;
46
47namespace OpenSim.Client.MXP.PacketHandler
48{
49 public class MXPPacketServer
50 {
51 internal static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 #region Fields
54
55 private readonly List<MXPClientView> m_clients = new List<MXPClientView>();
56 private readonly Dictionary<UUID, Scene> m_scenes;
57 private readonly Transmitter m_transmitter;
58
59// private readonly Thread m_clientThread;
60
61 private readonly IList<Session> m_sessions = new List<Session>();
62 private readonly IList<Session> m_sessionsToClient = new List<Session>();
63 private readonly IList<MXPClientView> m_sessionsToRemove = new List<MXPClientView>();
64
65 private readonly int m_port;
66// private readonly bool m_accountsAuthenticate;
67
68 private readonly String m_programName;
69 private readonly byte m_programMajorVersion;
70 private readonly byte m_programMinorVersion;
71
72 #endregion
73
74 #region Constructors
75
76 public MXPPacketServer(int port, Dictionary<UUID, Scene> scenes, bool accountsAuthenticate)
77 {
78 m_port = port;
79// m_accountsAuthenticate = accountsAuthenticate;
80
81 m_scenes = scenes;
82
83 m_programMinorVersion = 63;
84 m_programMajorVersion = 0;
85 m_programName = "OpenSimulator";
86
87 m_transmitter = new Transmitter(port);
88
89 StartListener();
90 }
91
92 public void StartListener()
93 {
94 m_log.Info("[MXP ClientStack] Transmitter starting on UDP server port: " + m_port);
95 m_transmitter.Startup();
96 m_log.Info("[MXP ClientStack] Transmitter started. MXP version: "+MxpConstants.ProtocolMajorVersion+"."+MxpConstants.ProtocolMinorVersion+" Source Revision: "+MxpConstants.ProtocolSourceRevision);
97 }
98
99 #endregion
100
101 #region Properties
102
103 /// <summary>
104 /// Number of sessions pending. (Process() accepts pending sessions).
105 /// </summary>
106 public int PendingSessionCount
107 {
108 get
109 {
110 return m_transmitter.PendingSessionCount;
111 }
112 }
113 /// <summary>
114 /// Number of connected sessions.
115 /// </summary>
116 public int SessionCount
117 {
118 get
119 {
120 return m_sessions.Count;
121 }
122 }
123 /// <summary>
124 /// Property reflecting whether client transmitter threads are alive.
125 /// </summary>
126 public bool IsTransmitterAlive
127 {
128 get
129 {
130 return m_transmitter != null && m_transmitter.IsAlive;
131 }
132 }
133 /// <summary>
134 /// Number of packets sent.
135 /// </summary>
136 public ulong PacketsSent
137 {
138 get
139 {
140 return m_transmitter != null ? m_transmitter.PacketsSent : 0;
141 }
142 }
143 /// <summary>
144 /// Number of packets received.
145 /// </summary>
146 public ulong PacketsReceived
147 {
148 get
149 {
150 return m_transmitter != null ? m_transmitter.PacketsReceived : 0;
151 }
152 }
153 /// <summary>
154 /// Bytes client has received so far.
155 /// </summary>
156 public ulong BytesReceived
157 {
158 get
159 {
160 return m_transmitter != null ? m_transmitter.BytesReceived : 0;
161 }
162 }
163 /// <summary>
164 /// Bytes client has sent so far.
165 /// </summary>
166 public ulong BytesSent
167 {
168 get
169 {
170 return m_transmitter != null ? m_transmitter.BytesSent : 0;
171 }
172 }
173 /// <summary>
174 /// Number of bytes received (bytes per second) during past second.
175 /// </summary>
176 public double ReceiveRate
177 {
178 get
179 {
180 return m_transmitter != null ? m_transmitter.ReceiveRate : 0;
181 }
182 }
183 /// <summary>
184 /// Number of bytes sent (bytes per second) during past second.
185 /// </summary>
186 public double SendRate
187 {
188 get
189 {
190 return m_transmitter != null ? m_transmitter.SendRate : 0;
191 }
192 }
193
194 #endregion
195
196 #region Session Management
197
198 public void Disconnect(Session session)
199 {
200 if (session.IsConnected)
201 {
202 Message message = MessageFactory.Current.ReserveMessage(typeof(LeaveRequestMessage));
203 session.Send(message);
204 MessageFactory.Current.ReleaseMessage(message);
205 }
206 else
207 {
208 throw new Exception("Not connected.");
209 }
210 }
211
212 #endregion
213
214 #region Processing
215
216 public void Process()
217 {
218 ProcessMessages();
219 Clean();
220 }
221
222 public void Clean()
223 {
224 foreach (MXPClientView clientView in m_clients)
225 {
226 if (clientView.Session.SessionState == SessionState.Disconnected)
227 {
228 m_sessionsToRemove.Add(clientView);
229 }
230 }
231
232 foreach (MXPClientView clientView in m_sessionsToRemove)
233 {
234 clientView.Scene.RemoveClient(clientView.AgentId);
235 clientView.OnClean();
236 m_clients.Remove(clientView);
237 m_sessions.Remove(clientView.Session);
238 }
239
240 m_sessionsToRemove.Clear();
241 }
242
243 public void ProcessMessages()
244 {
245 if (m_transmitter.PendingSessionCount > 0)
246 {
247 Session tmp = m_transmitter.AcceptPendingSession();
248 m_sessions.Add(tmp);
249 m_sessionsToClient.Add(tmp);
250
251 }
252
253 List<Session> tmpRemove = new List<Session>();
254
255 foreach (Session session in m_sessionsToClient)
256 {
257 while (session.AvailableMessages > 0)
258 {
259 Message message = session.Receive();
260
261 if (message.GetType() == typeof (JoinRequestMessage))
262 {
263
264 JoinRequestMessage joinRequestMessage = (JoinRequestMessage) message;
265
266 m_log.Info("[MXP ClientStack]: Session join request: " + session.SessionId + " (" +
267 (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
268 session.RemoteEndPoint.Port + ")");
269
270 try
271 {
272
273 if (joinRequestMessage.BubbleId == Guid.Empty)
274 {
275 foreach (Scene scene in m_scenes.Values)
276 {
277 if (scene.RegionInfo.RegionName == joinRequestMessage.BubbleName)
278 {
279 m_log.Info("[MXP ClientStack]: Resolved region by name: " + joinRequestMessage.BubbleName + " (" + scene.RegionInfo.RegionID + ")");
280 joinRequestMessage.BubbleId = scene.RegionInfo.RegionID.Guid;
281 }
282 }
283 }
284
285 if (joinRequestMessage.BubbleId == Guid.Empty)
286 {
287 m_log.Warn("[MXP ClientStack]: Failed to resolve region by name: " + joinRequestMessage.BubbleName);
288 }
289
290 UUID sceneId = new UUID(joinRequestMessage.BubbleId);
291
292 bool regionExists = true;
293 if (!m_scenes.ContainsKey(sceneId))
294 {
295 m_log.Info("[MXP ClientStack]: No such region: " + sceneId);
296 regionExists = false;
297 }
298
299 UUID userId = UUID.Zero;
300 UserAccount account = null;
301 bool authorized = regionExists ? AuthoriseUser(joinRequestMessage.ParticipantName,
302 joinRequestMessage.ParticipantPassphrase,
303 new UUID(joinRequestMessage.BubbleId), out account)
304 : false;
305
306 if (authorized)
307 {
308 Scene scene = m_scenes[sceneId];
309 UUID mxpSessionID = UUID.Random();
310
311 string reason;
312
313 m_log.Debug("[MXP ClientStack]: Session join request success: " + session.SessionId + " (" +
314 (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
315 session.RemoteEndPoint.Port + ")");
316
317 m_log.Debug("[MXP ClientStack]: Attaching UserAgent to UserProfile...");
318 UUID secureSession = UUID.Zero;
319 AttachUserAgentToUserProfile(account, session, mxpSessionID, sceneId, out secureSession);
320 m_log.Debug("[MXP ClientStack]: Attached UserAgent to UserProfile.");
321 m_log.Debug("[MXP ClientStack]: Preparing Scene to Connection...");
322 if (!PrepareSceneForConnection(mxpSessionID, secureSession, sceneId, account, out reason))
323 {
324 m_log.DebugFormat("[MXP ClientStack]: Scene refused connection: {0}", reason);
325 DeclineConnection(session, joinRequestMessage);
326 tmpRemove.Add(session);
327 continue;
328 }
329 m_log.Debug("[MXP ClientStack]: Prepared Scene to Connection.");
330 m_log.Debug("[MXP ClientStack]: Accepting connection...");
331 AcceptConnection(session, joinRequestMessage, mxpSessionID, userId);
332 m_log.Info("[MXP ClientStack]: Accepted connection.");
333
334 m_log.Debug("[MXP ClientStack]: Creating ClientView....");
335 MXPClientView client = new MXPClientView(session, mxpSessionID, userId, scene, account.FirstName, account.LastName);
336 m_clients.Add(client);
337 m_log.Debug("[MXP ClientStack]: Created ClientView.");
338
339 client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount());
340
341 m_log.Debug("[MXP ClientStack]: Starting ClientView...");
342 try
343 {
344 client.Start();
345 m_log.Debug("[MXP ClientStack]: Started ClientView.");
346 }
347 catch (Exception e)
348 {
349 m_log.Error(e);
350 }
351
352 m_log.Debug("[MXP ClientStack]: Connected");
353 }
354 else
355 {
356 m_log.Info("[MXP ClientStack]: Session join request failure: " + session.SessionId + " (" +
357 (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
358 session.RemoteEndPoint.Port + ")");
359
360 DeclineConnection(session, joinRequestMessage);
361 }
362 }
363 catch (Exception e)
364 {
365 m_log.Error("[MXP ClientStack]: Session join request failure: " + session.SessionId + " (" +
366 (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
367 session.RemoteEndPoint.Port + "): "+e.ToString()+" :"+e.StackTrace.ToString());
368 }
369 tmpRemove.Add(session);
370 }
371 }
372 }
373
374 foreach (Session session in tmpRemove)
375 {
376 m_sessionsToClient.Remove(session);
377 }
378
379 foreach (MXPClientView clientView in m_clients)
380 {
381 int messagesProcessedCount = 0;
382 Session session = clientView.Session;
383
384 while (session.AvailableMessages > 0)
385 {
386 Message message = session.Receive();
387
388 if (message.GetType() == typeof(LeaveRequestMessage))
389 {
390 LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)MessageFactory.Current.ReserveMessage(
391 typeof(LeaveResponseMessage));
392
393 m_log.Debug("[MXP ClientStack]: Session leave request: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")");
394
395 leaveResponseMessage.RequestMessageId = message.MessageId;
396 leaveResponseMessage.FailureCode = 0;
397 session.Send(leaveResponseMessage);
398
399 if (session.SessionState != SessionState.Disconnected)
400 {
401 session.SetStateDisconnected();
402 }
403
404 m_log.Debug("[MXP ClientStack]: Removing Client from Scene");
405 //clientView.Scene.RemoveClient(clientView.AgentId);
406 }
407 if (message.GetType() == typeof(LeaveResponseMessage))
408 {
409 LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)message;
410
411 m_log.Debug("[MXP ClientStack]: Session leave response: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")");
412
413 if (leaveResponseMessage.FailureCode == 0)
414 {
415 session.SetStateDisconnected();
416 }
417
418 m_log.Debug("[MXP ClientStack]: Removing Client from Scene");
419 //clientView.Scene.RemoveClient(clientView.AgentId);
420 }
421 else
422 {
423 clientView.MXPPRocessMessage(message);
424 }
425
426 MessageFactory.Current.ReleaseMessage(message);
427 messagesProcessedCount++;
428 if (messagesProcessedCount > 1000)
429 {
430 break;
431 }
432 }
433 }
434 }
435
436 private void AcceptConnection(Session session, JoinRequestMessage joinRequestMessage, UUID mxpSessionID, UUID userId)
437 {
438 JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage(
439 typeof(JoinResponseMessage));
440
441 joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId;
442 joinResponseMessage.FailureCode = MxpResponseCodes.SUCCESS;
443
444 joinResponseMessage.BubbleId = joinRequestMessage.BubbleId;
445 joinResponseMessage.ParticipantId = userId.Guid;
446 joinResponseMessage.AvatarId = userId.Guid;
447 joinResponseMessage.BubbleAssetCacheUrl = "http://" +
448 NetworkUtil.GetHostFor(session.RemoteEndPoint.Address,
449 m_scenes[
450 new UUID(joinRequestMessage.BubbleId)].
451 RegionInfo.
452 ExternalHostName) + ":" +
453 m_scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo.
454 HttpPort + "/assets/";
455
456 joinResponseMessage.BubbleName = m_scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo.RegionName;
457
458 joinResponseMessage.BubbleRange = 128;
459 joinResponseMessage.BubblePerceptionRange = 128 + 256;
460 joinResponseMessage.BubbleRealTime = 0;
461 joinResponseMessage.ProgramName = m_programName;
462 joinResponseMessage.ProgramMajorVersion = m_programMajorVersion;
463 joinResponseMessage.ProgramMinorVersion = m_programMinorVersion;
464 joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion;
465 joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion;
466 joinResponseMessage.ProtocolSourceRevision = MxpConstants.ProtocolSourceRevision;
467
468 session.Send(joinResponseMessage);
469
470 session.SetStateConnected();
471 }
472
473 private void DeclineConnection(Session session, Message joinRequestMessage)
474 {
475 JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage(typeof(JoinResponseMessage));
476
477 joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId;
478 joinResponseMessage.FailureCode = MxpResponseCodes.UNAUTHORIZED_OPERATION;
479
480 joinResponseMessage.ProgramName = m_programName;
481 joinResponseMessage.ProgramMajorVersion = m_programMajorVersion;
482 joinResponseMessage.ProgramMinorVersion = m_programMinorVersion;
483 joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion;
484 joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion;
485 joinResponseMessage.ProtocolSourceRevision = MxpConstants.ProtocolSourceRevision;
486
487 session.Send(joinResponseMessage);
488
489 session.SetStateDisconnected();
490 }
491
492 public bool AuthoriseUser(string participantName, string password, UUID sceneId, out UserAccount account)
493 {
494 string firstName = "";
495 string lastName = "";
496 account = null;
497
498 string[] nameParts = participantName.Split(' ');
499 if (nameParts.Length != 2)
500 {
501 m_log.Error("[MXP ClientStack]: Login failed as user name is not formed of first and last name separated by space: " + participantName);
502 return false;
503 }
504 firstName = nameParts[0];
505 lastName = nameParts[1];
506
507 account = m_scenes[sceneId].UserAccountService.GetUserAccount(m_scenes[sceneId].RegionInfo.ScopeID, firstName, lastName);
508 if (account != null)
509 return (m_scenes[sceneId].AuthenticationService.Authenticate(account.PrincipalID, password, 1) != string.Empty);
510
511 return false;
512 }
513
514 private void AttachUserAgentToUserProfile(UserAccount account, Session session, UUID sessionId, UUID sceneId, out UUID secureSessionId)
515 {
516 secureSessionId = UUID.Random();
517 Scene scene = m_scenes[sceneId];
518 scene.PresenceService.LoginAgent(account.PrincipalID.ToString(), sessionId, secureSessionId);
519 }
520
521 private bool PrepareSceneForConnection(UUID sessionId, UUID secureSessionId, UUID sceneId, UserAccount account, out string reason)
522 {
523 Scene scene = m_scenes[sceneId];
524
525 AgentCircuitData agent = new AgentCircuitData();
526 agent.AgentID = account.PrincipalID;
527 agent.firstname = account.FirstName;
528 agent.lastname = account.LastName;
529 agent.SessionID = sessionId;
530 agent.SecureSessionID = secureSessionId;
531 agent.circuitcode = sessionId.CRC();
532 agent.BaseFolder = UUID.Zero;
533 agent.InventoryFolder = UUID.Zero;
534 agent.startpos = new Vector3(0, 0, 0); // TODO Fill in region start position
535 agent.CapsPath = "http://localhost/";
536 agent.Appearance = scene.AvatarService.GetAppearance(account.PrincipalID);
537
538 if (agent.Appearance == null)
539 {
540 m_log.WarnFormat("[INTER]: Appearance not found for {0} {1}. Creating default.", agent.firstname, agent.lastname);
541 agent.Appearance = new AvatarAppearance();
542 }
543
544 return scene.NewUserConnection(agent, 0, out reason);
545 }
546
547 public void PrintDebugInformation()
548 {
549 m_log.Info("[MXP ClientStack]: Statistics report");
550 m_log.Info("Pending Sessions: " + PendingSessionCount);
551 m_log.Info("Sessions: " + SessionCount + " (Clients: " + m_clients.Count + " )");
552 m_log.Info("Transmitter Alive?: " + IsTransmitterAlive);
553 m_log.Info("Packets Sent/Received: " + PacketsSent + " / " + PacketsReceived);
554 m_log.Info("Bytes Sent/Received: " + BytesSent + " / " + BytesReceived);
555 m_log.Info("Send/Receive Rate (bps): " + SendRate + " / " + ReceiveRate);
556 }
557
558 #endregion
559
560 }
561}