aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs134
1 files changed, 101 insertions, 33 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs
index 4ec80e5..94032fd 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs
@@ -54,6 +54,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
54 54
55 private List<Scene> m_Scenes = new List<Scene>(); 55 private List<Scene> m_Scenes = new List<Scene>();
56 56
57 // we currently are only interested in root-agents. If the root isn't here, we don't know the region the
58 // user is in, so we have to ask the messaging server anyway.
57 private Dictionary<UUID, Scene> m_RootAgents = 59 private Dictionary<UUID, Scene> m_RootAgents =
58 new Dictionary<UUID, Scene>(); 60 new Dictionary<UUID, Scene>();
59 61
@@ -86,14 +88,14 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
86 if (m_Gridmode) 88 if (m_Gridmode)
87 NotifyMessageServerOfStartup(scene); 89 NotifyMessageServerOfStartup(scene);
88 90
89 scene.RegisterModuleInterface<IPresenceModule>(this);
90
91 scene.EventManager.OnNewClient += OnNewClient;
92 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
93 //scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
94
95 m_Scenes.Add(scene); 91 m_Scenes.Add(scene);
96 } 92 }
93
94 scene.RegisterModuleInterface<IPresenceModule>(this);
95
96 scene.EventManager.OnNewClient += OnNewClient;
97 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
98 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
97 } 99 }
98 100
99 public void PostInitialise() 101 public void PostInitialise()
@@ -105,6 +107,18 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
105 if (!m_Gridmode || !m_Enabled) 107 if (!m_Gridmode || !m_Enabled)
106 return; 108 return;
107 109
110 if (OnPresenceChange != null)
111 {
112 lock (m_RootAgents)
113 {
114 // on shutdown, users are kicked, too
115 foreach (KeyValuePair<UUID, Scene> pair in m_RootAgents)
116 {
117 OnPresenceChange(new PresenceInfo(pair.Key, UUID.Zero));
118 }
119 }
120 }
121
108 lock (m_Scenes) 122 lock (m_Scenes)
109 { 123 {
110 foreach (Scene scene in m_Scenes) 124 foreach (Scene scene in m_Scenes)
@@ -130,10 +144,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
130 if (m_Gridmode) 144 if (m_Gridmode)
131 { 145 {
132 // TODO process local info first and only do a server lookup if necessary. 146 // TODO process local info first and only do a server lookup if necessary.
133 // TODO fix m_RootAgents contents. Currently, they won't work right in a
134 // non standalone server. Consider two servers, with one sim each in a
135 // 2x1 grid. Clients will never be closed, just the root moves from
136 // server to server. But it stays in m_RootAgents on both servers.
137 Dictionary<UUID, FriendRegionInfo> infos = m_initialScene.GetFriendRegionInfos(new List<UUID>(users)); 147 Dictionary<UUID, FriendRegionInfo> infos = m_initialScene.GetFriendRegionInfos(new List<UUID>(users));
138 for (int i = 0; i < users.Length; ++i) 148 for (int i = 0; i < users.Length; ++i)
139 { 149 {
@@ -178,22 +188,27 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
178 } 188 }
179 } 189 }
180 190
191 // new client doesn't mean necessarily that user logged in, it just means it entered one of the
192 // the regions on this server
181 public void OnNewClient(IClientAPI client) 193 public void OnNewClient(IClientAPI client)
182 { 194 {
183 client.OnConnectionClosed += OnConnectionClosed; 195 client.OnConnectionClosed += OnConnectionClosed;
184 client.OnLogout += OnConnectionClosed; 196 client.OnLogout += OnLogout;
197
198 // KLUDGE: See handler for details.
199 client.OnEconomyDataRequest += OnEconomyDataRequest;
185 } 200 }
186 201
202 // connection closed just means *one* client connection has been closed. It doesn't mean that the
203 // user has logged off; it might have just TPed away.
187 public void OnConnectionClosed(IClientAPI client) 204 public void OnConnectionClosed(IClientAPI client)
188 { 205 {
206 // TODO: Have to think what we have to do here...
207 // Should we just remove the root from the list (if scene matches)?
189 if (!(client.Scene is Scene)) 208 if (!(client.Scene is Scene))
190 return; 209 return;
191
192 Scene scene = (Scene)client.Scene; 210 Scene scene = (Scene)client.Scene;
193 211
194 // OnConnectionClosed can be called from several threads at once (with different client, of course)
195 // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
196 // correct locking).
197 lock (m_RootAgents) 212 lock (m_RootAgents)
198 { 213 {
199 Scene rootScene; 214 Scene rootScene;
@@ -202,7 +217,28 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
202 217
203 m_RootAgents.Remove(client.AgentId); 218 m_RootAgents.Remove(client.AgentId);
204 } 219 }
220
221 // Should it have logged off, we'll do the logout part in OnLogout, even if no root is stored
222 // anymore. It logged off, after all...
223 }
224
225 // Triggered when the user logs off.
226 public void OnLogout(IClientAPI client)
227 {
228 m_log.DebugFormat("[PRESENCE]: Got OnLogout from {0}", client.Name);
229 if (!(client.Scene is Scene))
230 return;
231 Scene scene = (Scene)client.Scene;
232
233 // On logout, we really remove the client from rootAgents, even if the scene doesn't match
234 lock (m_RootAgents)
235 {
236 if (m_RootAgents.ContainsKey(client.AgentId)) m_RootAgents.Remove(client.AgentId);
237 }
238
239 // now inform the messaging server and anyone who is interested
205 NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); 240 NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
241 if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(client.AgentId, UUID.Zero));
206 } 242 }
207 243
208 public void OnSetRootAgentScene(UUID agentID, Scene scene) 244 public void OnSetRootAgentScene(UUID agentID, Scene scene)
@@ -219,27 +255,59 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
219 } 255 }
220 m_RootAgents[agentID] = scene; 256 m_RootAgents[agentID] = scene;
221 } 257 }
258 // inform messaging server that agent changed the region
222 NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); 259 NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
223 } 260 }
224 261
225// TODO not sure about that yet 262 private void OnEconomyDataRequest(UUID agentID)
226// public void OnMakeChildAgent(ScenePresence agent) 263 {
227// { 264 // KLUDGE: This is the only way I found to get a message (only) after login was completed and the
228// // OnMakeChildAgent can be called from several threads at once (with different agent). 265 // client is connected enough to receive UDP packets.
229// // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without 266 // This packet seems to be sent only once, just after connection was established to the first
230// // correct locking). 267 // region after login.
231// lock (m_RootAgents) 268 // We use it here to trigger a presence update; the old update-on-login was never be heard by
232// { 269 // the freshly logged in viewer, as it wasn't connected to the region at that time.
233// Scene rootScene; 270 // TODO: Feel free to replace this by a better solution if you find one.
234// if (m_RootAgents.TryGetValue(agentID, out rootScene) && agent.Scene == rootScene) 271
235// { 272 // get the agent. This should work every time, as we just got a packet from it
236// m_RootAgents[agentID] = scene; 273 ScenePresence agent = null;
237// } 274 lock (m_Scenes)
238// } 275 {
239// // don't notify the messaging-server; either this is just downgraded and another one will be upgraded 276 foreach (Scene scene in m_Scenes)
240// // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment, 277 {
241// // which will update the messaging-server, too. 278 agent = scene.GetScenePresence(agentID);
242// } 279 if (agent != null) break;
280 }
281 }
282
283 // just to be paranoid...
284 if (agent == null)
285 {
286 m_log.ErrorFormat("[PRESENCE]: Got a packet from agent {0} who can't be found anymore!?", agentID);
287 return;
288 }
289
290 // we are a bit premature here, but the next packet will switch this child agent to root.
291 if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(agentID, agent.Scene.RegionInfo.RegionID));
292 }
293
294 public void OnMakeChildAgent(ScenePresence agent)
295 {
296 // OnMakeChildAgent can be called from several threads at once (with different agent).
297 // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
298 // correct locking).
299 lock (m_RootAgents)
300 {
301 Scene rootScene;
302 if (m_RootAgents.TryGetValue(agent.UUID, out rootScene) && agent.Scene == rootScene)
303 {
304 m_RootAgents.Remove(agent.UUID);
305 }
306 }
307 // don't notify the messaging-server; either this agent just had been downgraded and another one will be upgraded
308 // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment,
309 // which will update the messaging-server, too.
310 }
243 311
244 private void NotifyMessageServerOfStartup(Scene scene) 312 private void NotifyMessageServerOfStartup(Scene scene)
245 { 313 {