diff options
Diffstat (limited to 'OpenSim/Region/Communications/Local/LocalLoginService.cs')
-rw-r--r-- | OpenSim/Region/Communications/Local/LocalLoginService.cs | 257 |
1 files changed, 128 insertions, 129 deletions
diff --git a/OpenSim/Region/Communications/Local/LocalLoginService.cs b/OpenSim/Region/Communications/Local/LocalLoginService.cs index 93a1e46..2f7fdb7 100644 --- a/OpenSim/Region/Communications/Local/LocalLoginService.cs +++ b/OpenSim/Region/Communications/Local/LocalLoginService.cs | |||
@@ -41,8 +41,7 @@ namespace OpenSim.Region.Communications.Local | |||
41 | 41 | ||
42 | public class LocalLoginService : LoginService | 42 | public class LocalLoginService : LoginService |
43 | { | 43 | { |
44 | private static readonly ILog m_log | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
46 | 45 | ||
47 | private CommunicationsLocal m_Parent; | 46 | private CommunicationsLocal m_Parent; |
48 | 47 | ||
@@ -120,167 +119,167 @@ namespace OpenSim.Region.Communications.Local | |||
120 | } | 119 | } |
121 | } | 120 | } |
122 | 121 | ||
123 | private Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); | 122 | /// <summary> |
124 | 123 | /// Customises the login response and fills in missing values. | |
124 | /// </summary> | ||
125 | /// <param name="response">The existing response</param> | ||
126 | /// <param name="theUser">The user profile</param> | ||
127 | /// <param name="startLocationRequest">The requested start location</param> | ||
125 | public override bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest) | 128 | public override bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest) |
126 | { | 129 | { |
127 | ulong currentRegion = 0; | 130 | // HomeLocation |
128 | 131 | RegionInfo homeInfo = null; | |
129 | uint locX = 0; | 132 | // use the homeRegionID if it is stored already. If not, use the regionHandle as before |
130 | uint locY = 0; | 133 | if (theUser.HomeRegionID != UUID.Zero) |
131 | uint locZ = 0; | 134 | homeInfo = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegionID); |
132 | bool specificStartLocation = false; | 135 | else |
136 | homeInfo = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegion); | ||
137 | if (homeInfo != null) | ||
138 | { | ||
139 | response.Home = | ||
140 | string.Format( | ||
141 | "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", | ||
142 | (homeInfo.RegionLocX*Constants.RegionSize), | ||
143 | (homeInfo.RegionLocY*Constants.RegionSize), | ||
144 | theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, | ||
145 | theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | // Emergency mode: Home-region isn't available, so we can't request the region info. | ||
150 | // Use the stored home regionHandle instead. | ||
151 | // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again | ||
152 | ulong regionX = theUser.HomeRegion >> 32; | ||
153 | ulong regionY = theUser.HomeRegion & 0xffffffff; | ||
154 | response.Home = | ||
155 | string.Format( | ||
156 | "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", | ||
157 | regionX, regionY, | ||
158 | theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, | ||
159 | theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); | ||
160 | m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}", | ||
161 | theUser.FirstName, theUser.SurName, | ||
162 | regionX, regionY); | ||
163 | } | ||
133 | 164 | ||
134 | // get start location | 165 | // StartLocation |
135 | if (startLocationRequest == "last") | 166 | RegionInfo regionInfo = null; |
167 | if (startLocationRequest == "home") | ||
136 | { | 168 | { |
137 | currentRegion = theUser.CurrentAgent.Handle; | 169 | regionInfo = homeInfo; |
138 | locX = (UInt32)theUser.CurrentAgent.Position.X; | 170 | theUser.CurrentAgent.Position = theUser.HomeLocation; |
139 | locY = (UInt32)theUser.CurrentAgent.Position.Y; | 171 | response.LookAt = "[r" + theUser.HomeLookAt.X.ToString() + ",r" + theUser.HomeLookAt.Y.ToString() + ",r" + theUser.HomeLookAt.Z.ToString() + "]"; |
140 | locZ = (UInt32)theUser.CurrentAgent.Position.Z; | ||
141 | response.StartLocation = "last"; | ||
142 | specificStartLocation = true; | ||
143 | } | 172 | } |
144 | else if (startLocationRequest == "home") | 173 | else if (startLocationRequest == "last") |
145 | { | 174 | { |
146 | currentRegion = theUser.HomeRegion; | 175 | regionInfo = m_Parent.GridService.RequestNeighbourInfo(theUser.CurrentAgent.Region); |
147 | response.StartLocation = "home"; | 176 | response.LookAt = "[r" + theUser.CurrentAgent.LookAt.X.ToString() + ",r" + theUser.CurrentAgent.LookAt.Y.ToString() + ",r" + theUser.CurrentAgent.LookAt.Z.ToString() + "]"; |
148 | } | 177 | } |
149 | else | 178 | else |
150 | { | 179 | { |
151 | // use last location as default | 180 | Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); |
152 | currentRegion = theUser.CurrentAgent.Handle; | ||
153 | |||
154 | Match uriMatch = reURI.Match(startLocationRequest); | 181 | Match uriMatch = reURI.Match(startLocationRequest); |
155 | if (null == uriMatch) | 182 | if (uriMatch == null) |
156 | { | 183 | { |
157 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest); | 184 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest); |
158 | } | 185 | } |
159 | else | 186 | else |
160 | { | 187 | { |
161 | string region = uriMatch.Groups["region"].ToString(); | 188 | string region = uriMatch.Groups["region"].ToString(); |
162 | 189 | regionInfo = m_Parent.GridService.RequestClosestRegion(region); | |
163 | RegionInfo r = m_Parent.GridService.RequestClosestRegion(region); | 190 | if (regionInfo == null) |
164 | if (null == r) | ||
165 | { | 191 | { |
166 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", | 192 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region); |
167 | startLocationRequest, region); | ||
168 | } | 193 | } |
169 | else | 194 | else |
170 | { | 195 | { |
171 | currentRegion = r.RegionHandle; | 196 | theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value), |
172 | locX = UInt32.Parse(uriMatch.Groups["x"].ToString()); | 197 | float.Parse(uriMatch.Groups["y"].Value), float.Parse(uriMatch.Groups["x"].Value)); |
173 | locY = UInt32.Parse(uriMatch.Groups["y"].ToString()); | ||
174 | locZ = UInt32.Parse(uriMatch.Groups["z"].ToString()); | ||
175 | // can be: last, home, safe, url | ||
176 | response.StartLocation = "url"; | ||
177 | specificStartLocation = true; | ||
178 | } | 198 | } |
179 | } | 199 | } |
200 | response.LookAt = "[r0,r1,r0]"; | ||
201 | // can be: last, home, safe, url | ||
202 | response.StartLocation = "url"; | ||
180 | } | 203 | } |
181 | 204 | ||
182 | RegionInfo homeReg = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegion); | 205 | if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response))) |
183 | RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion); | ||
184 | |||
185 | if ((homeReg != null) || (reg != null)) | ||
186 | { | 206 | { |
187 | if (homeReg != null) | 207 | return true; |
188 | { | 208 | } |
189 | response.Home = "{'region_handle':[r" + | ||
190 | (homeReg.RegionLocX * Constants.RegionSize).ToString() + ",r" + | ||
191 | (homeReg.RegionLocY * Constants.RegionSize).ToString() + "], " + | ||
192 | "'position':[r" + | ||
193 | theUser.HomeLocation.X.ToString() + ",r" + | ||
194 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
195 | theUser.HomeLocation.Z.ToString() + "], " + | ||
196 | "'look_at':[r" + | ||
197 | theUser.HomeLocation.X.ToString() + ",r" + | ||
198 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
199 | theUser.HomeLocation.Z.ToString() + "]}"; | ||
200 | } | ||
201 | else | ||
202 | { | ||
203 | m_log.Warn("[LOGIN]: Your home region doesn't exist"); | ||
204 | response.Home = "{'region_handle':[r" + | ||
205 | (reg.RegionLocX * Constants.RegionSize).ToString() + ",r" + | ||
206 | (reg.RegionLocY * Constants.RegionSize).ToString() + "], " + | ||
207 | "'position':[r" + | ||
208 | theUser.HomeLocation.X.ToString() + ",r" + | ||
209 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
210 | theUser.HomeLocation.Z.ToString() + "], " + | ||
211 | "'look_at':[r" + | ||
212 | theUser.HomeLocation.X.ToString() + ",r" + | ||
213 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
214 | theUser.HomeLocation.Z.ToString() + "]}"; | ||
215 | } | ||
216 | string capsPath = Util.GetRandomCapsPath(); | ||
217 | response.SimAddress = reg.ExternalEndPoint.Address.ToString(); | ||
218 | response.SimPort = (uint) reg.ExternalEndPoint.Port; | ||
219 | response.RegionX = reg.RegionLocX; | ||
220 | response.RegionY = reg.RegionLocY; | ||
221 | |||
222 | m_log.DebugFormat( | ||
223 | "[CAPS][LOGIN]: RegionX {0} RegionY {0}", response.RegionX, response.RegionY); | ||
224 | |||
225 | response.SeedCapability = "http://" + reg.ExternalHostName + ":" + | ||
226 | serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/"; | ||
227 | |||
228 | m_log.DebugFormat( | ||
229 | "[CAPS]: Sending new CAPS seed url {0} to client {1}", | ||
230 | response.SeedCapability, response.AgentID); | ||
231 | |||
232 | theUser.CurrentAgent.Region = reg.RegionID; | ||
233 | theUser.CurrentAgent.Handle = reg.RegionHandle; | ||
234 | |||
235 | // LoginResponse.BuddyList buddyList = new LoginResponse.BuddyList(); | ||
236 | |||
237 | response.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(theUser.ID)); | ||
238 | |||
239 | Login _login = new Login(); | ||
240 | //copy data to login object | ||
241 | _login.First = response.Firstname; | ||
242 | _login.Last = response.Lastname; | ||
243 | _login.Agent = response.AgentID; | ||
244 | _login.Session = response.SessionID; | ||
245 | _login.SecureSession = response.SecureSessionID; | ||
246 | _login.CircuitCode = (uint) response.CircuitCode; | ||
247 | if (specificStartLocation) | ||
248 | _login.StartPos = new Vector3(locX, locY, locZ); | ||
249 | else | ||
250 | _login.StartPos = new Vector3(128, 128, 128); | ||
251 | _login.CapsPath = capsPath; | ||
252 | 209 | ||
253 | m_log.InfoFormat( | 210 | // StartLocation not available, send him to a nearby region instead |
254 | "[LOGIN]: Telling region {0} @ {1},{2} ({3}:{4}) to expect user connection", | 211 | // regionInfo = m_Parent.GridService.RequestClosestRegion(""); |
255 | reg.RegionName, response.RegionX, response.RegionY, response.SimAddress, response.SimPort); | 212 | //m_log.InfoFormat("[LOGIN]: StartLocation not available sending to region {0}", regionInfo.regionName); |
256 | 213 | ||
257 | handlerLoginToRegion = OnLoginToRegion; | 214 | // Send him to default region instead |
258 | if (handlerLoginToRegion != null) | 215 | ulong defaultHandle = (((ulong)defaultHomeX * Constants.RegionSize) << 32) | |
259 | { | 216 | ((ulong)defaultHomeY * Constants.RegionSize); |
260 | handlerLoginToRegion(currentRegion, _login); | 217 | |
261 | } | 218 | if ((regionInfo != null) && (defaultHandle == regionInfo.RegionHandle)) |
262 | } | ||
263 | else | ||
264 | { | 219 | { |
265 | m_log.Warn("[LOGIN]: Not found region " + currentRegion); | 220 | m_log.ErrorFormat("[LOGIN]: Not trying the default region since this is the same as the selected region"); |
266 | return false; | 221 | return false; |
267 | } | 222 | } |
268 | 223 | ||
269 | return true; | 224 | m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead"); |
225 | regionInfo = m_Parent.GridService.RequestNeighbourInfo(defaultHandle); | ||
226 | |||
227 | // Customise the response | ||
228 | //response.Home = | ||
229 | // string.Format( | ||
230 | // "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", | ||
231 | // (SimInfo.regionLocX * Constants.RegionSize), | ||
232 | // (SimInfo.regionLocY*Constants.RegionSize), | ||
233 | // theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, | ||
234 | // theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); | ||
235 | theUser.CurrentAgent.Position = new Vector3(128,128,0); | ||
236 | response.StartLocation = "safe"; | ||
237 | |||
238 | return PrepareLoginToRegion(regionInfo, theUser, response); | ||
270 | } | 239 | } |
271 | 240 | ||
272 | private LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL) | 241 | /// <summary> |
242 | /// Prepare a login to the given region. This involves both telling the region to expect a connection | ||
243 | /// and appropriately customising the response to the user. | ||
244 | /// </summary> | ||
245 | /// <param name="sim"></param> | ||
246 | /// <param name="user"></param> | ||
247 | /// <param name="response"></param> | ||
248 | /// <returns>true if the region was successfully contacted, false otherwise</returns> | ||
249 | private bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response) | ||
273 | { | 250 | { |
274 | LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList(); | 251 | response.SimAddress = regionInfo.ExternalEndPoint.Address.ToString(); |
275 | foreach (FriendListItem fl in LFL) | 252 | response.SimPort = (uint)regionInfo.ExternalEndPoint.Port; |
276 | { | 253 | response.RegionX = regionInfo.RegionLocX; |
277 | LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend); | 254 | response.RegionY = regionInfo.RegionLocY; |
278 | buddyitem.BuddyID = fl.Friend; | 255 | |
279 | buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms; | 256 | string capsPath = Util.GetRandomCapsPath(); |
280 | buddyitem.BuddyRightsGiven = (int)fl.FriendPerms; | 257 | response.SeedCapability = regionInfo.ServerURI + "/CAPS/" + capsPath + "0000/"; |
281 | buddylistreturn.AddNewBuddy(buddyitem); | 258 | |
282 | } | 259 | // Notify the target of an incoming user |
283 | return buddylistreturn; | 260 | m_log.InfoFormat( |
261 | "[LOGIN]: Telling {0} @ {1},{2} ({3}) to prepare for client connection", | ||
262 | regionInfo.RegionName, response.RegionX, response.RegionY, regionInfo.ServerURI); | ||
263 | // Update agent with target sim | ||
264 | user.CurrentAgent.Region = regionInfo.RegionID; | ||
265 | user.CurrentAgent.Handle = regionInfo.RegionHandle; | ||
266 | // Prepare notification | ||
267 | Login loginParams = new Login(); | ||
268 | loginParams.Session = user.CurrentAgent.SessionID.ToString(); | ||
269 | loginParams.SecureSession = user.CurrentAgent.SecureSessionID.ToString(); | ||
270 | loginParams.First = user.FirstName; | ||
271 | loginParams.Last = user.SurName; | ||
272 | loginParams.Agent = user.ID.ToString(); | ||
273 | loginParams.CircuitCode = Convert.ToUInt32(response.CircuitCode); | ||
274 | loginParams.StartPos = user.CurrentAgent.Position; | ||
275 | loginParams.CapsPath = capsPath; | ||
276 | |||
277 | handlerLoginToRegion = OnLoginToRegion; | ||
278 | if (handlerLoginToRegion == null) | ||
279 | return false; | ||
280 | |||
281 | handlerLoginToRegion(user.CurrentAgent.Handle, loginParams); | ||
282 | return true; | ||
284 | } | 283 | } |
285 | 284 | ||
286 | // See LoginService | 285 | // See LoginService |