diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs | 134 |
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 | { |