Compare commits

..

362 Commits

Author SHA1 Message Date
Justin Clark-Casey (justincc)
48a5f10be1 Revert "Revert "refactor: make llGiveInventory() use existing GetInventoryItem() method rather than iterate through TaskInventory itself.""
This reverts commit 59a29f5f22.
The original revert was committed by mistake - it turns out this was not the cause of Mantis 6089

Conflicts:

	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
2012-07-17 23:48:09 +01:00
Justin Clark-Casey (justincc)
ecb759c1e5 Fix regression where llGiveInventory() had stopped asking non-owner receivers to accept/decline.
This appears to be a regression from back in commit db91044 (Mon Aug 22 2011) where we started to send TaskInventoryOffered msg dialog rather than InventoryOffered dialog.
This is probably correct, but failed because the bucket was too large and because we wouldn't have handled the TaskInventoryDeclined option anyway.
This patch handles both of these and make llGiveInventoryList() use TaskInventoryOffered as well
Fixes http://opensimulator.org/mantis/view.php?id=6089
2012-07-17 23:31:38 +01:00
Justin Clark-Casey (justincc)
59a29f5f22 Revert "refactor: make llGiveInventory() use existing GetInventoryItem() method rather than iterate through TaskInventory itself."
This reverts commit 58b13d51a7.
2012-07-17 22:56:21 +01:00
Justin Clark-Casey (justincc)
356d597296 Restore update of inventory item on derez/logout. This is necessary to update the name if this has been changed whilst attached.
Note, this behaviour appears to be at variance with the ll grid as of Tues 17 July 2012, testing with viewer 3.2.1.
The item name in inventory does not change either at the point of detach or after a relog.
2012-07-17 00:17:51 +01:00
Justin Clark-Casey (justincc)
b0facd147a Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-07-17 00:02:45 +01:00
Justin Clark-Casey (justincc)
b6476eaac3 Stop sending the viewer an inventory create message if a known attachment item is updated.
This doesn't seem to make any sense and probably stems from a period when this code was directly involved in attaching objects directly from the scene.
This message is already being sent by InventoryAccessModule code instead.
2012-07-17 00:00:26 +01:00
Melanie
2a85372169 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2012-07-16 23:33:33 +01:00
Melanie
1c3b0da74a Revert "Fix script "Running" behavior"
A better solution using the already present flags must be found.

This reverts commit 6d3ee8bb39.
2012-07-16 23:31:55 +01:00
Justin Clark-Casey (justincc)
c1667d39a6 refactor: factor out common code in WebStatsModule.OnMakeRootAgent() 2012-07-16 23:15:02 +01:00
Justin Clark-Casey (justincc)
217f47b0d5 In WebStatsModule.OnMakeRootAgent(), get region ID directly from SP.Scene.RegionInfo.RegionID instead of manually looking it up from the stored scene list. 2012-07-16 23:09:48 +01:00
Justin Clark-Casey (justincc)
ed14dac0a3 Stop warning about no session from ViewerStats if user teleports to another region in the same simulator that was not next to the source region.
This was because teleporting to the new region invoked the new session setup code before the agent was removed from the old region, which then invoked the session teardown code.
Now, we only invoke the teardown code if the region ID occupied by the agent being removed is the same as the one registered for the current session.
2012-07-16 23:03:23 +01:00
SignpostMarv
ee7478fa16 sending more user-friendly messages to the script error window rather than the thrown exceptions.
Signed-off-by: Melanie <melanie@t-data.com>
2012-07-16 21:32:38 +01:00
dahlia
5d3723a47f update PrimMesher.cs to dll version r72 which fixes some path errors in sliced linear prims. Addresses Mantis #6085 2012-07-13 21:22:15 -07:00
SignpostMarv
84b7ae2573 acting on feedback from justincc 2012-07-14 01:45:34 +01:00
SignpostMarv
423101b425 acting on feedback from justincc 2012-07-14 01:45:34 +01:00
SignpostMarv
e3453dd9ca added in some extra variables, it sometimes thinks it is on the same parcel :(
Signed-off-by: SignpostMarv <github@signpostmarv.name>
2012-07-14 01:45:34 +01:00
SignpostMarv
b6cd3b625e adding workaround for silent failure if position is outside the bounds of a region, implementing parcel prim count check.
Signed-off-by: SignpostMarv <github@signpostmarv.name>
2012-07-14 01:45:34 +01:00
SignpostMarv
8d59385eea Implementation of llSetRegionPos(). Does not implement failure on object entry/prim limit/access restrictions.
Signed-off-by: SignpostMarv <github@signpostmarv.name>
2012-07-14 01:45:34 +01:00
Justin Clark-Casey (justincc)
ec6a195e40 When generating a Warp3D texture, set the detailTexture[i] variable on resize from the JPEG2000 original rather than only saving it to disk.
This appears to be the cause of the warp 3d exception seen when starting a new region for the first time.
Subsequent starts were okay because resized saved bitmap was correctly retrieved from disk.
Should fix http://opensimulator.org/mantis/view.php?id=5204 and http://opensimulator.org/mantis/view.php?id=5272
2012-07-14 01:11:30 +01:00
Justin Clark-Casey (justincc)
2954ceccae Remove a callstack print out I accidentally left in 2 commits ago in 9ccb578 2012-07-13 01:08:49 +01:00
Justin Clark-Casey (justincc)
884d603cac Rather than instantiating a UTF8 encoding everywhere when we want to supress the BOM, use a single Util.UTF8NoBomEncoding.
This class is thread-safe (as evidenced by the provision of the system-wide Encoding.UTF8 which does not suppress BOM on output).
2012-07-13 01:03:28 +01:00
Justin Clark-Casey (justincc)
9ccb578721 Don't cache regions data on the other unused LocalGridServiceConnector that the module code still sets up even if we're using one directly instantiated from the RemoteGridServiceConnector.
Also improves log messages to indicate which regions are sending/receiving various neighbour protocol messages.
2012-07-13 00:44:00 +01:00
Justin Clark-Casey (justincc)
d6f54b25cd Stop redundantly passing in the endpoint to the LLClientView constructor.
This can always be retrieved via the LLUDPClient and is so done in various places already.
2012-07-12 23:48:42 +01:00
Justin Clark-Casey (justincc)
dda999a22c Remove IClientIPEndpoint client interface for now.
This may well come back in the future when this subinterface is actually used but it currently isn't and I feel the name was poor.
Everything uses IClientAPI.RemoveEndPoint which also returned the full endpoint rather than just the ip address.
2012-07-12 23:43:02 +01:00
Justin Clark-Casey (justincc)
3b3d9967b1 Remove IClientAPI.GetClientEP() in favour of existing identical IClientAPI.RemoteEndpoint. 2012-07-12 23:29:57 +01:00
Justin Clark-Casey (justincc)
75ab9b4b88 Change very recent AllowedViewerList and BannedViewerList config setting names in OpenSim.ini.example to AllowedClients and BannedClients to match long-existing settings in [LoginService]
Also changes separator from comma to bar to match existing [LoginService] config features.
Divergence of config names for identical facilities in different places makes for an unnecessarily confusing user experience.
2012-07-12 23:18:30 +01:00
Justin Clark-Casey (justincc)
15283d35f1 Extend "show circuits" to show circuit code, ip and viewer name.
Also change to use standard table formatting
"show circuits" and "show connections" console commands are very similar but access different data structures.
2012-07-12 23:09:36 +01:00
Justin Clark-Casey (justincc)
6a0de355e0 Add active status to "show connections" 2012-07-12 22:37:48 +01:00
Justin Clark-Casey (justincc)
65a25ee510 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-07-12 22:35:38 +01:00
Justin Clark-Casey (justincc)
ca412032e8 Put output for "show connections" command into standard table format.
Also moves into own method.
2012-07-12 21:36:33 +01:00
Robert Adams
743437262e Many explanitory comments added to the link and delink code in
SOG and SOP. Should have no functionality changes.
2012-07-11 16:12:38 -07:00
Justin Clark-Casey (justincc)
916e3bf886 Where possible, use the system Encoding.ASCII and Encoding.UTF8 rather than constructing fresh copies.
The encodings are thread-safe and already used in such a manner in other places.
This isn't done where Byte Order Mark output is suppressed, since Encoding.UTF8 is constructed to output the BOM.
2012-07-11 22:54:22 +01:00
Justin Clark-Casey (justincc)
9c89ad9154 Fix build break for windows with missing package for IScriptEngine in prebuild.xml for OpenSim.Region.CoreModules.Tests.dll 2012-07-11 22:15:53 +01:00
Justin Clark-Casey (justincc)
33cff9b9d7 Allow XEngine StartDelay to be configured in the [XEngine] config section.
This is only currently meant for use by regression tests that don't have any issues if XEngine is started up quickly, since no other operations will be occuring simultaneously.
Therefore, this is not yet documented externally.
2012-07-11 21:55:18 +01:00
Justin Clark-Casey (justincc)
0e611c47d3 Remove WorldComm module from the regression TestCompileAndStartScript() since the infrastructure no longer fails if this module isn't present, at least on the tested codepaths 2012-07-11 21:46:46 +01:00
Justin Clark-Casey (justincc)
fc24563206 Add regression TestDetachScriptedAttachmentToInventory()
This currently only does a relatively crude check for a ScriptState node in the serialized xml
2012-07-11 21:43:35 +01:00
Justin Clark-Casey (justincc)
14d05dc2a9 Add regression TestRezScriptedAttachmentsFromInventory() though this currently only checks for the presence of script items, not for started scripts 2012-07-11 19:54:40 +01:00
Justin Clark-Casey (justincc)
337ea019bd If a part has a sit target and an avatar is already sitting, allow another avatar to sit in the position given if no sit target was set.
Previous behave was that the second avatar could not sit.
This matches behaviour observed on the LL grid.
2012-07-10 23:55:22 +01:00
Justin Clark-Casey (justincc)
cdea572d2e refactor: move management of SOP.SitTargetAvatar into SOP.AddSittingAvatar() and SOP.RemoveSittingAvatar() 2012-07-10 23:50:04 +01:00
Justin Clark-Casey (justincc)
11e0ad6dc8 Revert "refactor: Add SOP.IsSitTargetOccupied to improve readability"
This reverts commit c8f0d476d2.
On reconsideration, I think this is less readable since immediately following code still sets SitTargetAvatar directly
2012-07-10 23:39:05 +01:00
Justin Clark-Casey (justincc)
c8f0d476d2 refactor: Add SOP.IsSitTargetOccupied to improve readability 2012-07-10 23:34:40 +01:00
Justin Clark-Casey (justincc)
69a6f6e3cd refactor: use sit orientation argument passed in to SP.SendSitResponse() rather than creating a new copy
There are no issues with side-effects since this is a struct.
2012-07-10 23:26:40 +01:00
Justin Clark-Casey (justincc)
e8347b7095 Move common code to detect whether a part has a valid sit target into a SOP property rather than being repeated in SP.
This also makes the detection in SP.FindNextAvailableSitTarget() and SendSitResponse() identical.
Previously they varied slightly (SendSitResponse didn't check for an older type of invalid quaternion) but the practical effect is most probably zero.
2012-07-10 23:21:39 +01:00
Justin Clark-Casey (justincc)
506437b684 Remove log line accidentally left in SP.SendSitResponse() 2012-07-10 23:06:34 +01:00
Justin Clark-Casey (justincc)
9f01c3d408 Disable logging in regression test in OSSL_ApiAttachmentTests 2012-07-10 23:04:44 +01:00
Justin Clark-Casey (justincc)
58869e5aa0 Fix recent SOP.GetSittingAvatars() to return null if there are no sitting avatars rather than throwing an exception.
Extends sitting avatar regression tests to test new sitters information
2012-07-10 23:03:52 +01:00
Justin Clark-Casey (justincc)
f3134b5cf6 When an attachment is detached to inv or derezzed, stop the scripts, update the known item with script state still in the script engine and then remove the scripts.
This is to fix a regression starting from 5301648 where attachments had to start being deleted before persistence in order to avoid race conditions with hud update threads.
2012-07-10 22:41:11 +01:00
Justin Clark-Casey (justincc)
eb5ec4a786 If a script is being stopped manually, then give the scriptpool thread 1 second to finish normally before forcibly aborting.
This is to avoid the worst of the problems in mono 2.6, 2.10 where an aborted thread does not always release all its locks.
This very short grace period is identical to the existing behaviour when a script is removed from the scene.
2012-07-10 21:42:51 +01:00
Justin Clark-Casey (justincc)
c8af20f966 This script allows an object to be attached directly from prim inventory to another avatar in the scene.
Very useful in serious game/environment scenarios where its only allowed for trusted creators.
Threat level Severe
2012-07-09 23:08:41 +01:00
Justin Clark-Casey (justincc)
d6f563794e Don't allow a prim to be sat upon if its part of an attachment 2012-07-09 21:43:44 +01:00
Justin Clark-Casey (justincc)
2eaa6d5ace Do not allow a script to attach a prim if its being sat upon.
This prevents a stack overflow where a get position on the avatar will refer to the attachment which will in turn refer back to the avatar.
This required recording of all sitting avatars on a prim which is done separately from recording the sit target avatar.
Recording HashSet is null if there are no sitting avatars in order to save memory.
2012-07-09 21:24:32 +01:00
BlueWall
1a2ab7bc69 More keys for automated ini processing 2012-07-08 22:50:56 -04:00
BlueWall
a96ac73302 Add more keys for OpenSim.ini.defaults automation 2012-07-08 13:45:17 -04:00
BlueWall
57094bd017 Add more automation keys to OpenSim.ini.example 2012-07-08 13:03:37 -04:00
Justin Clark-Casey (justincc)
112cddc9ca minor: rearrange INITIALIZATION COMPLETE log message so that it's clear init is only complete for a particular region at a time 2012-07-07 00:53:17 +01:00
Justin Clark-Casey (justincc)
16d5b79d57 minor: remove some recent mono compiler warnings 2012-07-07 00:36:01 +01:00
Justin Clark-Casey (justincc)
1201307c73 Remove duplicate Warp3DImageModule entry in CoreModulePlugin.addin.xml
This was causing 2 copies of the module to be created for each scene.
Probably no bad consequences other than a small waste of memory (both for the module and for the warp3D renderer it loaded)
2012-07-07 00:26:25 +01:00
Justin Clark-Casey (justincc)
a85741ac37 minor: Make WORLD MAP category log lines consistent 2012-07-07 00:14:16 +01:00
Justin Clark-Casey (justincc)
3bd134474b minor: Get RegionReady module to shout initialization complete status to draw the eye 2012-07-07 00:09:33 +01:00
Justin Clark-Casey (justincc)
b19ead5f9e Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-07-07 00:05:16 +01:00
Justin Clark-Casey (justincc)
7ff4eec79c Remove redundant SetScene() function in Scene.AddSceneObject()
This is always done later on in SceneGraph.AddSceneObject() if the call hasn't failed due to sanity checks.
There's no other purpose for this method to exist and it's dangerous/pointless to call in other conditions.
2012-07-07 00:02:45 +01:00
Robert Adams
7aff238eee Merge branch 'bulletsim2'
Cleanup preceeding major work. No major functional changes.
Collisions reported to simulator more efficiently.
BulletSim binaries updated using a more recent version of Bullet (v2.80-r2527).
2012-07-06 15:59:09 -07:00
Robert Adams
af9d8de515 BulletSim: update the binaries to the current sources 2012-07-06 15:56:35 -07:00
Justin Clark-Casey (justincc)
f1f390cfdf Remove now duplicate interregion object check that should have been removed a few commits ago in 43a2da9 2012-07-06 23:22:40 +01:00
Justin Clark-Casey (justincc)
74014a3854 minor: Remove some wrong comments in attachments regression tests 2012-07-06 23:13:00 +01:00
Robert Adams
e4a6611865 Clean up collision reporting code so they are properly passed to
the simulator in batches.
More comments.
2012-07-06 15:09:19 -07:00
Justin Clark-Casey (justincc)
056c9a59b2 Add assert to attachment regression tests to check that number of objects in the scene graph 2012-07-06 23:07:50 +01:00
Talun
ae1f2114f5 Mantis 6077 trim NPC chat on channel zero.
This patch trims leading and trailing spaces from NPC chat and
suppresses the sending of empty chat strings on open chat channel 0.
2012-07-06 22:49:18 +01:00
Talun
1b1f841c6a Mantis 6063 osNpcTouch.
Allow NPCS to touch obects.
2012-07-06 22:37:19 +01:00
Justin Clark-Casey (justincc)
43a2da9edb Pull prim crossing/teleport checks up into Scene.IncomingCreateObject() from Scene.AddObject()
Only IncomingCreateObject() needs these checks.  General object adding does not need to perform crossing perm checks
2012-07-06 22:33:16 +01:00
Justin Clark-Casey (justincc)
f6e5791ecd refactor: extract method UpdateUserInventoryWithAttachment() from AttachObject() for better code comprehension 2012-07-06 22:07:19 +01:00
Justin Clark-Casey (justincc)
843112340e Log MONO_THREADS_PER_CPU value on simulator startup, or "unset" if it is not set 2012-07-06 00:37:45 +01:00
Justin Clark-Casey (justincc)
7e73f609e5 Log warning if time between invocations of the watchdog thread is twice the timer setting.
This is to help detect situations where thread timeout warnings are being generated because of general machine issues rather than deadlock, network or other problems.
2012-07-05 23:15:59 +01:00
Justin Clark-Casey (justincc)
db9616f7ba minor: add client name to various login service log messages to disambiguate messages from concurrent logins. Also adds destination resolution debug log message showing region endpoint.
Adding endpoint to the log helps to find issues where the region external host information has been wrongly configured
2012-07-05 21:30:20 +01:00
Justin Clark-Casey (justincc)
8674604ff5 regrade osFormatString, osMatchString and osReplaceString to VeryLow.
I can't see that these present any real hazard to sim functioning.
2012-07-05 21:10:59 +01:00
Justin Clark-Casey (justincc)
462f7bccf9 minor: Add more information to OSFunctionThreatLevel and clarify some text in using PARCEL_OWNER, PARCEL_GROUP_MEMBER, ESTATE_MANAGER, ESTATE_OWNER permission categories 2012-07-05 20:58:20 +01:00
SignpostMarv
510e809aba porting console commands from raw2sculpt 3.2 2012-07-05 00:16:31 +01:00
Justin Clark-Casey (justincc)
951b45b80f Add OSSL function osForceAttachToAvatarFromInventory()
This works like osForceAttachToAvatar() but allows an object to be directly specified from the script object's inventory rather than forcing it to be rezzed in the scene first.
Still only attaches objects to the owner of the script.
This allows one to bypass the complicated co-ordination of first rezzing objects in the scene before attaching them.
Threat level high.
2012-07-05 00:05:06 +01:00
Justin Clark-Casey (justincc)
7b327848d0 Use GetInventoryItem() in llRezAtRoot rather than iterating through a cloned dictionary 2012-07-04 22:21:47 +01:00
Justin Clark-Casey (justincc)
2f998fce1f refactor: In llGetNotecardLine() use existing GetInventoryItem() rather than inspecting a clone of the TaskInventory dictionary that was not cloned thread-safe 2012-07-04 22:00:39 +01:00
Justin Clark-Casey (justincc)
1816ecb747 refactor: In llGetNumberOfNotecardLines() use existing GetInventoryItem() rather than inspecting a clone of the TaskInventory dictionary that was not cloned thread-safe 2012-07-04 21:57:57 +01:00
Justin Clark-Casey (justincc)
eacba4fc0b refactor: use existing GetInventoryItem() in GetScriptByName(), itself renamed from ScriptByName() 2012-07-04 21:54:30 +01:00
Justin Clark-Casey (justincc)
9fac7fd932 refactor: In llGetInventoryType() use existing GetInventoryItem() 2012-07-04 21:50:52 +01:00
Justin Clark-Casey (justincc)
f2b0377c28 refactor: In llGetInventoryCreator() use existing GetInventoryItem() 2012-07-04 21:49:21 +01:00
Justin Clark-Casey (justincc)
d933bdbd59 refactor: In llGetInventoryPermMask() use existing GetInventoryItem() 2012-07-04 21:47:20 +01:00
Justin Clark-Casey (justincc)
f9fa34408d refactor: in llGetInventoryPermMask use existing GetInventoryItem() 2012-07-04 21:42:04 +01:00
Justin Clark-Casey (justincc)
857494f6bd refactor: In llRemoteLoadScriptPin() use existing GetInventoryItem() 2012-07-04 21:36:44 +01:00
Justin Clark-Casey (justincc)
dff7cae2ee refactor: replace use of LSL_Api.GetTaskInventoryItem() with existing GetInventoryItem() 2012-07-04 21:33:35 +01:00
Justin Clark-Casey (justincc)
0e3fce9b5c refactor: In llGetInventoryKey() use existing GetInventoryItem() 2012-07-04 21:25:58 +01:00
Justin Clark-Casey (justincc)
4b2b14dad1 In llMessageLinked() use GetInventoryItems() rather than cloning TaskInventory directory
GetInventoryItems() returns a new list and so is equivalent, and creates this list under lock whereas Clone() is not thread-safe
2012-07-04 21:22:43 +01:00
Justin Clark-Casey (justincc)
3769739ca7 In llRequestInventoryData() use GetInventoryItems() rather than cloning TaskInventory directory
GetInventoryItems() returns a new list and so is equivalent, and creates this list under lock whereas Clone() is not thread-safe
2012-07-04 21:19:16 +01:00
Justin Clark-Casey (justincc)
3717812ce0 refactor: In llCollisionSound() use existing GetInventoryItem() method rather than have it iterate through TaskInventory itself. 2012-07-04 21:15:00 +01:00
Justin Clark-Casey (justincc)
ae64d089c6 refactor: In llRemoveInventory() use existing GetInventoryItem() method rather than have it iterate through TaskInventory itself. 2012-07-04 21:05:51 +01:00
Justin Clark-Casey (justincc)
58b13d51a7 refactor: make llGiveInventory() use existing GetInventoryItem() method rather than iterate through TaskInventory itself. 2012-07-04 20:57:48 +01:00
Justin Clark-Casey (justincc)
5691a8b860 refactor: rename Watchdog.WATCHDOG_TIMEOUT_MS to DEFAULT_WATCHDOG_TIMEOUT_MS to reflect what it actually is 2012-07-04 00:15:03 +01:00
Justin Clark-Casey (justincc)
f7b4802577 Correct spelling mistake m_BanedViewers to m_BannedViewers 2012-07-03 23:26:02 +01:00
Justin Clark-Casey (justincc)
8183c2926d minor: Add some method doc to HasGroupChanged and Schedule GroupForFull/PartUpdate() to indicate when region modules need to invoke them 2012-07-03 23:19:11 +01:00
Justin Clark-Casey (justincc)
3c9b9a848f Fix issue in database tests where sogs being stored are not in a scene.
This puts an extra m_part.ParentGroup.Scene == null check at the top of SceneObjectPartInventory.QueryScriptStates()
2012-07-03 22:58:58 +01:00
Michelle Argus
3399596e0e Adds a list of viewers that are allowed or banned from the region.
Signed-off-by: Melanie <melanie@t-data.com>
2012-07-02 18:45:11 +01:00
Melanie
d32cf21576 Add preservation of running state of scripts when drag-copying. 2012-07-01 18:30:59 +01:00
Justin Clark-Casey (justincc)
1926de5a05 Remove some mono compiler warnings 2012-06-30 01:25:39 +01:00
Justin Clark-Casey (justincc)
a4551b027b Removing unused handling of incoming create object by userID and itemID only.
It appears this was never actually used since attachments were rezzed in other code.
This was never available on remote simulator comms, only local.
2012-06-30 01:14:49 +01:00
Justin Clark-Casey (justincc)
56c776066c Remove code listed for removal in 0.7.3 that handled script restart for incoming attachments from pre-fatpack regions (versions of OpenSimulator more than a year old) 2012-06-30 01:06:37 +01:00
Justin Clark-Casey (justincc)
0229e90dcc Move update of the final optional ODE total frame stat inside the OdeLock rather than outside to avoid a very occasional race condition with the stat collection thread 2012-06-29 01:02:35 +01:00
Justin Clark-Casey (justincc)
e420f815dc refactor: rename _collisionEventPrim to m_collisionEventActors and _collisionEventPrimChanges to m_collisionEventActorsChanges to reflect their actual contents.
These dictionaries handle all actor types, not just physical prims.
2012-06-29 00:54:40 +01:00
Justin Clark-Casey (justincc)
1a7be7b00e Fix a regression where we stopped removing avatars from collision event reporting on logout, rather than stopping clearing their collision events.
This occurred in b18c8c8 (Thu May 17 2012).
This was a cause of very occasional race conditions and likely memory leakage as clients came and went from the region.
2012-06-29 00:36:50 +01:00
Justin Clark-Casey (justincc)
0f6b7b6a41 If a link points to a non-existing item in FetchInventory caps, then don't try to add it to the return data rather than suffering an exception later on 2012-06-29 00:11:44 +01:00
Justin Clark-Casey (justincc)
f202c36106 Add IScene.Name for code clarity to replace the RegionInfo.RegionName used in many, many log messages. 2012-06-29 00:03:22 +01:00
Justin Clark-Casey (justincc)
bfa6896678 Change AttachmentsModule.DetachSingleAttachmentToInv() to accept a SOG directly instead of an item ID to then shuffle through attachments, saving CPU busywork.
Almost all callers already had the sog to hand.
Still checking that it's really an attachment, but now by inspecting SOG.AttachedAvatar
2012-06-28 23:31:23 +01:00
Justin Clark-Casey (justincc)
571fd966cb Rather than iterating through all SOGs in the scene looking for the one that matches out fromItemID on detach, go through the agent's attachment sog list instead. 2012-06-28 23:01:12 +01:00
Justin Clark-Casey (justincc)
f263d6a910 Remove code that tried to delete an attachment back to inventory if RezSingleAttachmentFromInventoryInternal() returned null.
null would only ever be returned if the item couldn't be located within inventory and this would happen immediately.
In this case, derezzing wouldn't work anyway since there is no item to derez.
2012-06-28 22:48:49 +01:00
Justin Clark-Casey (justincc)
972b0b52f9 If rest of first line after colon is blank then still warn about running in XEngine if engine specified does not exist.
This is to take account of situations where the user was intending to specify a script engine using colon using its default language.
This probably generates few false positive as scripts are less likely to end a first line colon with a comment for other purposes.
2012-06-28 21:30:36 +01:00
Justin Clark-Casey (justincc)
25baa2d894 Avoid reporting false positives when a colon is in a comment in the first line of a script where the user was not trying to select a different script engine.
This works by only posting the "Selected engine unavailable" message if we're falling back on XEngine and the language is one handled by XEngine.
In cases where the language is not handled or not allowed, the user will still be notified by the later compiler error.
This avoids the overwhelming majority of false positives where the first line contains a : for other reasons (e.g. source control systems, vim settings, etc.)
Ultimately, I think it would be better to detect script language/engine with a mechanism that didn't just rely on : detection (e.g like #! in unix scripts).
2012-06-28 01:01:18 +01:00
Justin Clark-Casey (justincc)
f9769a9fcb minor: reuse colon index calculation in XEngine.OnRezScript. The index if a colon is found on the first line will always be the same as for the whole script. 2012-06-28 00:37:23 +01:00
Justin Clark-Casey (justincc)
bb48060b44 Fix issue in InventoryArchiveTestCase where it didn't call down to OpenSimTestCase.SetUp() 2012-06-27 00:50:36 +01:00
Justin Clark-Casey (justincc)
d043213317 refactor: Move ScenePresence <-> AgentData attachments copying code into AttachmentsModule. 2012-06-27 00:41:46 +01:00
Justin Clark-Casey (justincc)
5bec5bcf71 Automatically disable log4net before each regression test so that logging is confined to a single test if it's turned on.
This involves making test classes inherit from a common OpenSimTestCase.
This will be applied to more classes as required.
2012-06-27 00:01:51 +01:00
Justin Clark-Casey (justincc)
87ca820f9b Replace "kill uuid" console command with the more consistent "delete object uuid", which was present in the last opensim release. 2012-06-26 23:28:48 +01:00
Justin Clark-Casey (justincc)
0b29877790 Fix output for help on some object region console commands 2012-06-26 23:15:15 +01:00
Justin Clark-Casey (justincc)
97437feb06 Show region positions in "show regions" robust console command 2012-06-26 23:05:10 +01:00
Justin Clark-Casey (justincc)
2524517986 minor: correct GridService "show regions" cibsike cinnabd usage statement 2012-06-26 22:54:41 +01:00
Justin Clark-Casey (justincc)
99954c1498 refactor: Remove unnecessary AttachmentModuleTests.m_userId in favour of local variables 2012-06-26 22:53:08 +01:00
Justin Clark-Casey (justincc)
2b82c421ad refactor: Use local attachment module variables instead of global m_attMod.
This also avoids confusion between tests where one sets up m_attMod and another accidentally uses it after failing to set one up itself.
2012-06-26 22:31:25 +01:00
Justin Clark-Casey (justincc)
4329cc7b8a refactor: make m_presence a local variable in all AttachmentsModuleTests since it doesn't need to be global and some tests set up more than one sp 2012-06-26 22:21:54 +01:00
Justin Clark-Casey (justincc)
32a4ce94f0 Add regression test to check that attachments in source region are deleting when an agent teleports to a neighbouring region 2012-06-26 22:16:44 +01:00
Justin Clark-Casey (justincc)
340005c5bf Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-26 22:12:39 +01:00
Justin Clark-Casey (justincc)
4b6c3fd4bb If crossing attachments into another region pre-fatpack, clone objects before changing properties to avoid hud display race condition with update threads.
This matches behaviour in fatpack crossing, where attachments are cloned before their properties are changed.
This only applies to crossings to simulators running code released before April 2011.
2012-06-26 21:06:47 +01:00
BlueWall
988112d446 Add stub for llCastRay 2012-06-26 15:15:25 -04:00
Justin Clark-Casey (justincc)
1f22b29ca3 Add much easier ConsoleDisplayTable AddColumn() and AddRow() methods.
Use these for new "show regions" command rather than old cumbersome stuff.
2012-06-26 00:40:46 +01:00
Justin Clark-Casey (justincc)
5292b8b8be Add "show regions" console command to ROBUST to show all regions currently registered.
Command is not added in standalone, which has its own version of "show regions" that can also show estate name
2012-06-26 00:34:37 +01:00
Justin Clark-Casey (justincc)
854f2a913c Add "show region at" command to grid service to get the details of a region at a specific location. "show region" command becomes "show region name" to disambiguate
This is the same format as used by "show object name", etc.
"deregister region" also becomes "deregister region id"
2012-06-25 23:55:14 +01:00
Justin Clark-Casey (justincc)
f5316984ab minor: update currently commented out log message at top of AvatarFactoryModule.SetAppearance() for future use 2012-06-25 23:31:22 +01:00
Justin Clark-Casey (justincc)
e5b739aaeb When attachments are being saved and deleted for a closing root agent, delete first to avoid a hud race condition with update threads.
If delete doesn't occur first then the update thread can outrace the IsAttachment = false necessary to save attachments and send hud artifacts to other viewers.
2012-06-25 22:48:13 +01:00
Justin Clark-Casey (justincc)
5301648cff In AttachmentsModule.DetachSingleAttachmentToInvInternal(), remove attachment before changing properties for correct inventory serialization.
Serialization of attachments requires IsAttachment = false so that correct positions are serialized instead of avatar position.
However, doing this when a hud is still attached allows race conditions with update threads, resulting in hud artifacts on other viewers.
This change sets SOG.IsDeleted before serialization changes take place (IsDeleted itself is not a serialized property).
LLClientView then screens out any deleted SOGs before sending updates to viewers.
2012-06-25 21:08:19 +01:00
BlueWall
6d3ee8bb39 Fix script "Running" behavior
Unchecking "Running" box in script editor now persists. This fixes http://opensimulator.org/mantis/view.php?id=6057
2012-06-23 04:15:14 -04:00
Justin Clark-Casey (justincc)
78143769bf Resolve various race conditions between accessing and removing external script URLs by more consistently locking on m_UrlMap 2012-06-22 23:49:52 +01:00
Justin Clark-Casey (justincc)
dca04c7b61 Avoid a race condition where an incoming request to a script external URL can trigger an exception is the URL was being removed at the same time.
This involves three steps
1) Return gracefully in UrlModule.HttpRequestHandler() instead of throwing an exception when the url cannot be found in its index
2) Return true instead of false in HasEvents() if no matching request is found in the map.  This call will only happen in the first place for raced requests.
3) Return a 404 in GetEvents() if the request is not in the index, rather than a blank 200 OK.

Many thanks to Tom Haines in http://opensimulator.org/mantis/view.php?id=6051 for doing some of the work on this.
2012-06-22 23:16:18 +01:00
Justin Clark-Casey (justincc)
80a41e670d Avoid race condition between m_PrimObjects iteration in XEngine.PostObjectEvent and places where the list is modified by extending the m_PrimObjects lock. 2012-06-22 02:23:25 +01:00
Justin Clark-Casey (justincc)
9f3feeff8d If starting scripts on initial sim start, provide INFO level log feedback each time 50 scripts have been started.
This is to provide an indication of what's happening now that the default isn't to report every single script start.
Changes XEngine logging level in OpenSim.exe.config from WARN to INFO.
2012-06-22 02:10:27 +01:00
Justin Clark-Casey (justincc)
f907182ab2 Eliminate unnecessary extra call to TriggerEmptyScriptCompileQueue in XEngine.DoOnRezScriptQueue()
The later invocation of this function will happen on an empty compile queue.
2012-06-22 01:57:14 +01:00
Justin Clark-Casey (justincc)
4cf49369b5 Stop flicking IsAttachment false and then true in AttachmentsModule.UpdateAttachmentPosition() in order to avoid a hud update race condition.
Previously, setting IsAttachment to false then true was necessary to serialize the updated attachment object information.
However, UpdateAttachmentPosition no longer does this update.
Whilst IsAttachment is set to false there is a race condition where the update thread can wrongly send hud object updates to clients that do not own the hud, resulting in screen artifacts.
2012-06-22 01:43:26 +01:00
Justin Clark-Casey (justincc)
fda39c11bf Fix bug where attachments would not retain position if just rotated and not moved.
This was because we were not setting AttachedPos in SOG.UpdateGroupPositionPR, unlike UpdateGroupPosition
2012-06-22 01:33:27 +01:00
Justin Clark-Casey (justincc)
798846c5b6 refactor AttachmentsModule tests to use a common method for standard attachment item setup 2012-06-22 00:40:04 +01:00
Justin Clark-Casey (justincc)
06617ffd06 Add regression test for updating attachment position 2012-06-22 00:18:30 +01:00
Justin Clark-Casey (justincc)
d24122b706 Add item id, name, prim name and id to log message when state exists but loading fails.
Drop logging about memory limit exceeded to warn from error
2012-06-21 02:24:44 +01:00
Justin Clark-Casey (justincc)
afcabf5244 Retrigger build - last jenkins run was glitched 2012-06-21 02:13:03 +01:00
Justin Clark-Casey (justincc)
5709bed548 Add state file location to errors logged when there's some issue with retrieving state (e.g. exceeds memory limit) 2012-06-21 02:09:14 +01:00
Justin Clark-Casey (justincc)
68ea096f1b Use HasPrivateAttachmentPoint properties in SOG.DeleteGroupFromScene() instead of magic numbers 2012-06-20 23:25:07 +01:00
Justin Clark-Casey (justincc)
714db90832 refactor: use SOG.HasPrivateAttachmentPoint in SOP.SendTerseUpdateToClient() instead of attachmentpoint magic numbers. 2012-06-20 22:46:01 +01:00
Justin Clark-Casey (justincc)
b23425c7c4 As with LLSDInventoryItem from commit 01a2b0b, send type values in LLSDInventoryFolder for inventory CAPs as integers rather than strings.
Should also resolve some issues with exceptions being thrown in some inventory fetches.
2012-06-20 02:28:00 +01:00
Justin Clark-Casey (justincc)
9ec9dafae6 Lower warn logging on not having friends/group module on permissions to debug.
It's a valid configuration not to have these modules, but I think it's still worth logging the fact that certain permissions won't work (always return true)
2012-06-20 01:33:25 +01:00
Justin Clark-Casey (justincc)
6c312bce7f minor: Lower flotsam asset cache warning about not having a FlotsamCache.ini to debug
It's perfectly okay not to have this section.
2012-06-20 01:30:20 +01:00
Justin Clark-Casey (justincc)
7b6c0232a5 Change default logging level for XEngine to WARN instead of DEBUG.
This is to reduce log spam from script loading, which is especially spammy for avatar movements with scripted attachments.
All important messages are at warn or above.
If you still want/need to see these messages, set <level value="DEBUG"/> in the <logger name="OpenSim.Region.ScriptEngine.XEngine"> section of OpenSim.exe.config.
This affects no other package logs, which still output at the root configured level (currently DEBUG by default).
2012-06-20 01:10:18 +01:00
Justin Clark-Casey (justincc)
4cfaa01c0a Remove STARTUP COMPLETE message from the startuplogo.txt file and into main logging 2012-06-20 01:06:55 +01:00
Justin Clark-Casey (justincc)
6b3f9fcde0 Comment out the neighbour and land in connectors from info logging that they are starting up 2012-06-20 00:42:54 +01:00
Justin Clark-Casey (justincc)
625e5e913a Comment out recently added log message detailing number of scripts started when compile queue empties for now 2012-06-20 00:25:18 +01:00
Justin Clark-Casey (justincc)
881e92a726 Raise some IO associated Exception logging in XEngine to error level, in line with other similar cases.
Remove more unnecessary Close() calls - these are being triggered by the Dispose() called when exiting the using statement for these sdk io objects.
2012-06-20 00:19:50 +01:00
Justin Clark-Casey (justincc)
0fa303b1cf Log how many scripts are candidates for starting and how many are actually started.
Adds DebugLevel infrastructure to XEngine though currently commented out and unused.
2012-06-20 00:10:19 +01:00
Justin Clark-Casey (justincc)
9737e6d52e If RegionReady is active, don't falsely say that logins are enabled in the main scene loop before RegionReady is signalled when initial script compilation finishes.
Also raises this logging level to Info from Debug since this information is of high importance.  This matches the behaviour of the RegionReady module
2012-06-20 00:07:03 +01:00
Justin Clark-Casey (justincc)
e23d7ff9c0 minor: If logging because mesh/sculpt data isn't present for an object, log object UUID rather than local id, since UUID doesn't potentially vary between simulator starts. 2012-06-20 00:05:48 +01:00
Justin Clark-Casey (justincc)
ef686ead37 Like the assembly and text files, only write the c#-lsl linemap in XEngine.SetXMLState() if the trust binaries flag is set.
This doesn't affect other locations where the map is written, such as on script compilation.
2012-06-19 02:11:46 +01:00
Justin Clark-Casey (justincc)
bc06f3dcaf Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-19 01:55:31 +01:00
Justin Clark-Casey (justincc)
8e7032ece8 minor: Add a little more detail to IOException logging in XEngine.SetXMLState()
Also removes superflous Close() commands for statements taking place within using() constructs
Also adds some comment out debug log messages for future use.
2012-06-19 01:53:50 +01:00
BlueWall
5c5b359bcb Oops! putting back the entry for map urls 2012-06-16 07:26:16 -04:00
BlueWall
fc1522ab60 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-16 06:29:49 -04:00
BlueWall
2ed768cbf5 Adjust Robust*.ini.examples V3 webprofile entries 2012-06-16 06:29:15 -04:00
Justin Clark-Casey (justincc)
7119de56ff Change read config paramter from max_urls_per_simulator to max_external_urls_per_simulator, which is what it was meant to be 2012-06-16 04:12:53 +01:00
Justin Clark-Casey (justincc)
ed513fc7be Fix bug introduced in commit c6e3752 (13 Jun 2012) where poll responses would always return OK even if some other status code had been set 2012-06-16 03:43:45 +01:00
Justin Clark-Casey (justincc)
22f25dfcab Implement max_external_urls_per_simulator setting in [LL-Functions] to allow configuration of how many urls can be set up by llRequestURL()
Defaults remains as 100.
This setting is per simulator instead of per region due to how the url script module is structured.
2012-06-16 03:32:47 +01:00
Justin Clark-Casey (justincc)
aaa30dcebc Add region name to UseCircuitCode log messages 2012-06-15 05:01:36 +01:00
Justin Clark-Casey (justincc)
c935f03467 Put all debug console commands into a single Debug section rather than scattering them over other categories 2012-06-15 03:32:43 +01:00
Justin Clark-Casey (justincc)
94517c8d5c Make the "debug http" command available for robust as well as the simulator. This allows one to see incoming requests as they happen.
This required making everything use the common MainServer class for registering and retrieving http servers, rather than duplicate structures.
2012-06-15 02:51:52 +01:00
Justin Clark-Casey (justincc)
257b1b517d Add main instance to internal MainServer.m_Servers list to simplify internal logic.
This does require the server to be added before it is set as the main Instance
2012-06-15 02:03:50 +01:00
Justin Clark-Casey (justincc)
aeed4d3041 minor: Tell user the current debug http level if "debug http" console command is executed without a level parameter 2012-06-15 01:27:29 +01:00
Justin Clark-Casey (justincc)
478acfff34 When setting debug http level, do this for all known http servers, not just the main instance. 2012-06-15 01:24:36 +01:00
Justin Clark-Casey (justincc)
10e87f9cdc Make XMLRPCModule use an existing HTTP server if one already exists on the desired port. 2012-06-15 00:59:53 +01:00
Justin Clark-Casey (justincc)
6993a26ba5 Get rid of some unnecessary null checks in RegionApplicationBase.StartupSpecific() - a constructor can never return null.
Also adds some method doc to MainServer
2012-06-15 00:40:12 +01:00
Justin Clark-Casey (justincc)
93ba0332c4 minor: Extend 'debug http' usage statement to 0..3 from 0..2 2012-06-14 23:54:12 +01:00
Justin Clark-Casey (justincc)
9825861f4a Shuffle "debug http" levels so that 1 and 2 now cause different levels of warn to be logged if we receive invalid xml for xmlrpc. 2012-06-14 23:46:09 +01:00
Justin Clark-Casey (justincc)
f4b02f8e39 Fix a regression in BaseHttpServer.HandleXmlRpcRequests() from recent c6e3752
Accidentally make responseString null by default instead of String.Empty.
It needs to be something in case the XmlRpcRequest deserialize throws an exception due to bad xml (a failure which we silently swallow!)
2012-06-14 04:29:15 +01:00
Justin Clark-Casey (justincc)
2c6555021f Fix very recent regression in 917d753 where I put the ++updatesThisCall outside the batching part of ProcessEntityUpdates()
This stopped any batching happening and since this method is called periodically updates were sent very slowly
2012-06-14 03:49:54 +01:00
Justin Clark-Casey (justincc)
3888b9a670 If we're going to discard a terse update block because it's now someone else's hud, then don't still add it to the list of blocks for the update message. 2012-06-14 03:32:44 +01:00
Justin Clark-Casey (justincc)
1aa7469253 correct wrong incomplete comment from previous commit 3c3ea19 in AttachmentsModule 2012-06-14 02:30:40 +01:00
Justin Clark-Casey (justincc)
3c3ea19620 Fix a bug where scene objects attached as HUDs through scripts would not disappear for other avatars.
We do this by sending a kill message for that object to all other avatars apart from the one that has the hud.
2012-06-14 02:26:38 +01:00
Justin Clark-Casey (justincc)
0d2243a393 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-14 01:38:41 +01:00
Justin Clark-Casey (justincc)
917d753f1c Fix a race condition where an object update for a hud could be sent to non-owner avatars if the hud was attached directly from within the region.
If this happens, then the non-owners would see unremovable huds that they did not own until relog, and sometimes even beyond that.
This was due to a race between the entity update and the attachment code when moving an object from within scene to a hud.
2012-06-14 01:36:37 +01:00
Justin Clark-Casey (justincc)
a4290048e5 Add SOG.HasPrivateAttachmentPoint to tell if a SOG has a private attachment point. HUDs attachment points are private.
Change SOP.SendFullUpdateToClient() and SoundModule.PlayAttachedSound() to use this rather than different magic number formulations.
This also corrects a bug in PlayAttachedSound() where the code assumed that all attachment points over 30 were HUDs.
It appears this is no longer true with Neck and Root (Avatar Center)
2012-06-14 01:20:55 +01:00
Melanie
cba8b4f8b8 Fix not sending TransferInfo when an asset is not found. This clogs
up the sound pipeline in the viewer.
2012-06-14 00:58:17 +01:00
Justin Clark-Casey (justincc)
6a77a65675 minor: remove unnecessary IsAttachment = false setting for new object in UploadObjectAssetModule, property always starts as false 2012-06-14 00:35:26 +01:00
Justin Clark-Casey (justincc)
16ffc764bf minor: refactor part of LLClientView.ProcessEntityUpdates() to remove duplicate code 2012-06-13 23:54:32 +01:00
Justin Clark-Casey (justincc)
cf080a68d6 Remove long obsolete and unused IClientAPI.KillEndDone() 2012-06-13 23:42:22 +01:00
Justin Clark-Casey (justincc)
f726150afd Add ObjectUpdate as one of the packets that can be screened out when setting debug packet level 2012-06-13 23:39:23 +01:00
Justin Clark-Casey (justincc)
1f34c8277d In the osGetGrid functions, if the [GridInfo] section does not exist then return "Configuration Error", as already happens if there is no GridInfoURI 2012-06-13 04:05:02 +01:00
Justin Clark-Casey (justincc)
66cb533f26 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-13 03:51:13 +01:00
Justin Clark-Casey (justincc)
5145356467 Add "deregister region" by uuid command to grid service to allow manual deregistration of simulators.
Useful if a simulator has crashed without removing its regions and those regions have been reconfigured differently
2012-06-13 03:49:22 +01:00
Melanie
77f579dcc8 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2012-06-13 02:34:25 +01:00
BlueWall
7c0843aad1 Add the updated OpenSimDefaults.ini for the prior timer_Interval patch. 2012-06-12 21:55:31 -04:00
Melanie
4e18e71089 Committing the Avination implementation of llCastRay. This is a complete rewrite
wich does it's thing independently of physics. Enjoy!
2012-06-13 02:32:25 +01:00
Justin Clark-Casey (justincc)
94bbbf96c7 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-13 02:25:42 +01:00
Justin Clark-Casey (justincc)
c6e375291a Don't include time to transmit response back to requester when assessing slow handling of requests.
This is to avoid logging a 'slow' request when the source of delay is the viewer in processing a response.
This is not something we can do much about on the server end - it's server-side delay that we're interested in.
To ensure consistency, this commit also had to refactor and simplify inbound non-poll network request handling, though there should be no functional change.
IOSHttpResponse no longer exposes the Send() method, only classes in OpenSim.Framework.Servers.HttpServer should be doing this.
Only the GetTextureHandler was sending its own response.  Now it leaves this to BaseHttpServer, like all other core handlers.
2012-06-13 00:03:44 +01:00
BlueWall
c53c55fed0 Add variable timer configureation for the timer_Script
Added "timer_Interval" to the OpenSimDefaults.ini, leaving the default value set to 1200, as the previous default setting. The value represents seconds. To change the default, copy the entry to OpenSim.ini and multiply the number of minutes for the interval by 60.
2012-06-12 17:15:56 -04:00
Justin Clark-Casey (justincc)
2ca31a9841 Remove accidental timeout left in during earlier debugging. Has been in since two commits ago (b099f26) 2012-06-12 02:46:14 +01:00
Justin Clark-Casey (justincc)
1b1f0a2d77 OnConnectionClosed listeners, retrieve data from IClientAPI.SceneAgent rather than scanning all scene for the presence with the right id
Stop checking IsLoggingOut on these listeners, if called with a root agent then we always want to perform these actions.
This covers cases where the client is closed due to manual kick, simulator shutdown, etc.
2012-06-12 02:43:33 +01:00
Justin Clark-Casey (justincc)
b099f26376 Set IClientAPI.IsActive = false early on client removal due to ack timeout rather than using IsLoggingOut flag.
IsActive is more appropriate since unack timeout is not due to voluntary logout.
This is in line with operations such as manual kick that do not set the IsLoggingOut flag.
It's also slightly better race-wise since it reduces the chance of this operation clashing with another reason for client deactivation (e.g. manual kick).
2012-06-12 02:16:36 +01:00
Justin Clark-Casey (justincc)
c89db34fc4 If the simulator closes a root agent due to ack timeout, then send the client a kick message with that reason, in case it is somehow still listening. 2012-06-12 02:03:31 +01:00
Justin Clark-Casey (justincc)
8c7149063b In PresenceDetector.OnConnectionClose(), use the IsChildAgent check already available on IClientAPI.SceneAgent rather than retrieving it again by scanning all scenes. 2012-06-12 01:25:09 +01:00
Justin Clark-Casey (justincc)
bab7dab4c5 Comment out the scene presence sitting debug log messages for now 2012-06-11 23:37:16 +01:00
Justin Clark-Casey (justincc)
51fe97a00c Set CreateDefaultAvatarEntries = true in Robust.HG.ini.example to match Robust.HG.ini
Thanks to Ai Austin for the spot.
2012-06-11 23:33:32 +01:00
Justin Clark-Casey (justincc)
daad0a3e11 Revert "Bind ~ and ! operators in LSL tighter in order to resolve issues in LSL where these aren't evaluated propertly."
This reverts commit a8a9d13dc0.

Accidentally committed, this patch might not be the correct approach.
2012-06-11 23:30:58 +01:00
Justin Clark-Casey (justincc)
a927787434 Add last frame time monitor to MonitorModule now that this value is useful 2012-06-11 23:30:11 +01:00
Justin Clark-Casey (justincc)
cbb5ddd944 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-11 23:27:48 +01:00
Melanie
71ba85137f Commitig the Avination implementation of llTeleportAgent and
llTeleportAgentGlobalCoords. These do NOT use PERMISSION_TELEPORT like
their SL counterparts because that permission is not yet understood by TPVs
based on v1.x.
2012-06-11 16:45:52 +01:00
Justin Clark-Casey (justincc)
a8a9d13dc0 Bind ~ and ! operators in LSL tighter in order to resolve issues in LSL where these aren't evaluated propertly.
Addresses http://opensimulator.org/mantis/view.php?id=3268
2012-06-09 05:11:08 +01:00
Justin Clark-Casey (justincc)
1f3218e53f Create avatar entries necessary to stop new v3 avatars being clouds (pants, shape, etc.) by default in grid mode.
This only affects avatars created through the "create user" console command or createuser XMLRPC.
This matches the default setting for standalone
2012-06-09 01:11:15 +01:00
Justin Clark-Casey (justincc)
08cd5d2503 Add documentation to AllowGodFunctions setting in [LL-Functions] 2012-06-09 00:33:17 +01:00
Justin Clark-Casey (justincc)
817f2d341d Fix regression in 5f4f9f0 (Fri Jun 8 2012) which stopped "show stats" and json stats from working 2012-06-08 23:36:53 +01:00
Justin Clark-Casey (justincc)
794d184c25 Stop sending a DisableSimulator packet in LLClientView.Close(), which is a duplicate for child agents and unnecessary for root agents.
Close() already calls Scene.RemoveClient() which sends the right eq or udp DisableSimulator message to child agents.
2012-06-08 04:32:51 +01:00
Justin Clark-Casey (justincc)
f94b92df46 Instead of retrieving the known client again in LLUDPServer.RemoveClient(), check the IsLoggingOut flag instead.
This is slightly better thread-race wise
2012-06-08 04:12:22 +01:00
Justin Clark-Casey (justincc)
c215b1ad16 If logging a client out due to ack timeout, do this asynchronously rather than synchronously on the outgoing packet loop.
This is the same async behaviour as normal logouts.
This is necessary because the event queue will sleep the thread for 5 seconds on an ack timeout logout as the client isn't around to pick up the final event queue messages.
2012-06-08 03:53:03 +01:00
Justin Clark-Casey (justincc)
5f4f9f0230 Add regression test for client logout due to ack timeout. 2012-06-08 03:12:23 +01:00
Justin Clark-Casey (justincc)
d73805d7f4 Remove null checks at top of LLUDPServer.ProcessInPacket(). Neither packet nor client are ever null. 2012-06-08 01:51:28 +01:00
Justin Clark-Casey (justincc)
d71c6dea7e Store already retrieve IClientAPI in IncomingPacket structure for later use rather than doing another retrieve on dequeue.
Instead of checking whether the client still exists by trying to retrieve again from the client manager, this patch gets it back from IncomingPacket and checks the IClientAPI.IsActive state.
2012-06-08 01:43:58 +01:00
Justin Clark-Casey (justincc)
30f4a33f01 Don't make duplicate call to ScenePresence.Close() separately in ETM.DoTeleport() if an agent needs closing.
This is always done as part of Scene.RemoveClient()
Also refactors try/catching in Scene.RemoveClient() to log NREs instead of silently discarding, since these are useful symptoms of problems.
2012-06-08 01:26:43 +01:00
Justin Clark-Casey (justincc)
5c162ccd57 Go back to calling IncomingCloseAgent() in the "kick user" command for consistency instead of IClientAPI.Close() directly.
This no longer double counts child agent removals
2012-06-08 00:59:39 +01:00
Justin Clark-Casey (justincc)
d547bcf8d1 Remove duplicate update of user count in Scene.IncomingCloseAgent()
This is already done in Scene.RemoveClient() which IncomingCloseAgent() always ends up calling.
2012-06-08 00:40:38 +01:00
Justin Clark-Casey (justincc)
af2954898e Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-08 00:24:39 +01:00
Justin Clark-Casey (justincc)
b56673c920 Fix bug with "kick user" reducing agent counts by 2 instead of 1.
This is done by making the kick user command call IClientAPI.Close() rather than routing through Scene.IncomingCloseAgent(), which also called IClientAPI.Close()
DisableSimulator for child agents is moved from IncomingCloseAgent() to RemoveClient(), this is not a functional change since IncomingCloseAgent() always ends up calling RemoveClient()
2012-06-08 00:18:25 +01:00
Justin Clark-Casey (justincc)
0c5fefacb4 Record the fact that child agents can have asset transactions.
Also change code to grab the agent asset transaction module once.
2012-06-07 23:51:04 +01:00
Justin Clark-Casey (justincc)
de87e4871b Don't send kill object messages to clients when a child agent is closed. 2012-06-07 23:35:21 +01:00
Melanie
39cb2063bf Add collision sounds to the asset set 2012-06-07 23:35:08 +01:00
Talun
d5cc959683 Mantis 6044 Building master currently fails.
Add missing reference to System.Core

Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-06-07 11:16:18 -04:00
BlueWall
a1e857932a Make change to fix Windows builds 2012-06-07 10:17:37 -04:00
Justin Clark-Casey (justincc)
7550b97e65 Log warning if we try to remove a UDP client that has already been removed. 2012-06-07 04:00:29 +01:00
Justin Clark-Casey (justincc)
98b46d48fe Allow the thread watchdog to accept an alarm method that is invoked if the timeout is breached.
This alarm can then invoke this to log extra information.
This is used in LLUDPServer to show which client was being processed when incoming and outgoing udp watchdog alarms are triggered.
2012-06-07 02:44:13 +01:00
Justin Clark-Casey (justincc)
514dd85199 minor: Change log messages on Warp3DImageModule to show they are from this module 2012-06-06 04:18:38 +01:00
Justin Clark-Casey (justincc)
53c25a4778 Rename MapImageModule for Warp3D to Warp3DImageModule to match its class name and make it easier to distinguish between map image modules. 2012-06-06 04:15:00 +01:00
Justin Clark-Casey (justincc)
2b0de66216 Actively dispose of Bitmaps in Warp3D image module and world map module once we've finished with them.
This might help with memory leakage issues though I suspect it won't.
2012-06-06 04:11:16 +01:00
SignpostMarv
3b25021180 enabling all corners of a sim to be set in one call 2012-06-06 02:47:47 +01:00
Justin Clark-Casey (justincc)
abf94627f6 Ensure closure of bitmap and memory stream with using() statements in WorldViewModule.
If this has any effect then it will only be to the map images returned via requests to the /worldview simulator HTTP path (not enabled by default)
2012-06-06 02:45:36 +01:00
Justin Clark-Casey (justincc)
6adc810eaa Stop accidentally reading 4 Int16s instead of 2 in SIZE section of Terragen file when loaded from a stream.
Fixes a bug introduced 2 weeks ago in 67ebe80
Thanks to Plugh for pointing this out.
2012-06-05 19:40:16 +01:00
Justin Clark-Casey (justincc)
a5410c2c19 minor: Add user feedback when executing fix-phantoms 2012-06-05 01:37:40 +01:00
Justin Clark-Casey (justincc)
42179578fc Allow fix-phantoms command to appear even if CombineContiguousRegions = false, since this allows one to go back from a megaregion to normal regions.
Adapted from a patch by Garmin Kawaguichi in http://opensimulator.org/mantis/view.php?id=6027
Garmin says that fix-phantoms allows one to reset objects when going back from megaregion to normal regions as well as the othe rway around.
Thanks!
2012-06-05 01:33:58 +01:00
Talun
008c6a4610 Mantis 4597 AgentPaused packet is ignored.
The packet was actually being handled but not acted on.
This change extends the default timeout for paused clients to 5 minutes
and makes both the paused and non-paused timeout periods configurable.
2012-06-05 01:22:05 +01:00
Justin Clark-Casey (justincc)
01280e9b94 Remove unused ScenePresence list structure in llGetAgentList() 2012-06-05 00:34:18 +01:00
Justin Clark-Casey (justincc)
96d1ba90d7 Scale down per frame MS stats to match scaled simulator FPS stat.
This makes frame time stats properly tally with fps, which saves confusion and makes it easier to interpret numbers.
In some ways this is not so artifical - physics FPS runs at the higher rate.
2012-06-05 00:27:51 +01:00
Justin Clark-Casey (justincc)
655625ab87 Start sending spare frame time MS viewer stat. Make frame time correctly display total frame time, not just non-spare time.
This makes it easier to see when components of frame time exceed normal permitted frame time.
Currently reflect scene frame times.
2012-06-05 00:17:55 +01:00
Justin Clark-Casey (justincc)
c3d9acc9a9 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-06-05 00:15:29 +01:00
Justin Clark-Casey (justincc)
a7f4804f53 Properly show per frame millisecond statistics per frame, not as amount of time taken per second.
This is to make these statistics actually match their names (and also be more accurate as number of frames can vary under heavy load)
Currently using scene frames (11.23 every second) instead of physics frames (56.18 per second)
2012-06-04 23:07:53 +01:00
BlueWall
3229e32b4e Add replaceable region modules to the "show modules" command 2012-06-04 17:25:38 -04:00
Melanie
9707a2d57c Remove profile from basic configuration 2012-06-04 18:24:02 +01:00
Melanie
d9d4fb10d9 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2012-06-04 18:22:43 +01:00
Robert Adams
f94ef37b46 Correct the delegate specification in EventManager.TriggerTerrainTainted. Looks like the wrong one was cut and pasted. 2012-06-04 10:26:39 -07:00
Melanie
5c646e2603 Remove the "Profile" config as it's covered by the replaceable interface 2012-06-04 18:22:09 +01:00
Justin Clark-Casey (justincc)
729d90173f Fix build break whree accidentally did inv.Folders rather than inv.Folders.Count in a minor change. 2012-06-02 05:03:56 +01:00
Justin Clark-Casey (justincc)
2de5479c3f minor: tidy up some comments 2012-06-02 05:01:56 +01:00
Justin Clark-Casey (justincc)
01a2b0b289 Fix various issues with http inventory
1) The return messages were being wrongly populated with the names of asset, inventory and sale types when their corresponding integers should have been used instead.
2) Folders with links were including the linked items in the descendents figure, when only the links should be included.
3) Links and linked items in link folders were not being included in the return data, and not in the correct order.

Now that these issues have been addressed, outfits and attachments appear to work consistently when HTTP inventory is enabled (as is now the default).
2012-06-02 04:57:10 +01:00
Justin Clark-Casey (justincc)
72219eae7d Instead of updating sim stats root agent, child, objects and scripts accounts every single scene frame, update in the once every 3 seconds SimStatsReporter run 2012-06-01 04:47:11 +01:00
Justin Clark-Casey (justincc)
6375db1533 Add optional total avatars, total prims and active prims stats to ODE plugin.
These will act as a sanity check with the main scene stats, to show that physics scene entities are being managed properly.
Total prims will not match scene total prims since physics total does not include phantom prims
2012-06-01 04:23:36 +01:00
Justin Clark-Casey (justincc)
4e06a46dc5 If OdeScene.Near() returns no collision contacts, then exit as early as possible. All subsequent code is only relevant if there are contacts. 2012-06-01 04:07:39 +01:00
Justin Clark-Casey (justincc)
200376b3c4 Add optional stat for the other collision time per frame not spent in ODE native spaces or geom collision code 2012-06-01 03:49:42 +01:00
Justin Clark-Casey (justincc)
d34b84b531 Add avatar forces calculation, prim force and raycasting per frame millisecond optional stats 2012-06-01 03:23:19 +01:00
Justin Clark-Casey (justincc)
9ff8efc720 Collection optional avatar and prim taint frame millisecond times 2012-06-01 03:03:48 +01:00
Justin Clark-Casey (justincc)
d1b5f8d9d7 Remove recent optional native collision frame milliseconds stat
Unnecessary since this has now been broken down into space collisions and geom collisions
2012-06-01 02:35:11 +01:00
Justin Clark-Casey (justincc)
31343aa7c3 Add optional stat that records milliseconds spent notifying collision listeners in physics frames 2012-06-01 02:33:44 +01:00
Justin Clark-Casey (justincc)
5f44be99ef Add avatar and prim update milliseconds per frame optional stats 2012-06-01 02:25:42 +01:00
Justin Clark-Casey (justincc)
5cc9b820e5 Add option native step frame ms stat 2012-06-01 01:58:28 +01:00
Justin Clark-Casey (justincc)
f2c8c7a7b8 Add total ODE frame time optional stat, as a sanity check on the main scene physics stat 2012-06-01 01:37:19 +01:00
Justin Clark-Casey (justincc)
8333b928fa Break down native ODE collision frame time stat into native space collision and geom collision stats 2012-06-01 01:27:19 +01:00
Justin Clark-Casey (justincc)
c33c8db825 Rename new collision stats to 'contacts' - there are/can be multiple contacts per collision and this is what is actually being measured. 2012-06-01 01:15:27 +01:00
Justin Clark-Casey (justincc)
e1f8d2adb0 Stop adding an unnecessary duplicate _perloopcontact if the avatar is standing on a prim.
This has already been added earlier on in the method.
2012-06-01 01:12:30 +01:00
Justin Clark-Casey (justincc)
8301f7b17f minor: comment out currently unused OdeScene.sCollisionData 2012-06-01 00:57:55 +01:00
Justin Clark-Casey (justincc)
93fa9e8991 Add ODE avatar and prim collision numbers if extra stats collection is enabled. 2012-06-01 00:56:13 +01:00
Justin Clark-Casey (justincc)
878b67b333 Fix OdeScene.GetTopColliders() to return the top 25 colliders rather than the first 25 that had non-zero collision scores.
Also zeros collisions scores on all prims after report collection, not just the top 25.
As before, this collision scores are only reset after a report is requested, which may give unrealistic numbers on the first request.
So to see more realistic scores, ignore the first report and then refresh the request after a couple of seconds or so.
2012-06-01 00:26:11 +01:00
Justin Clark-Casey (justincc)
0b02a4d42e Add an optional mechanism for physics modules to collect and return arbitrary stats.
If active, the physics module can return arbitrary stat counters that can be seen via the MonitoringModule
(http://opensimulator.org/wiki/Monitoring_Module)
This is only active in OdeScene if collect_stats = true in [ODEPhysicsSettings].
This patch allows OdeScene to collect elapsed time information for calls to the ODE native collision methods to assess what proportion of time this takes compared to total physics processing.
This data is returned as ODENativeCollisionFrameMS in the monitoring module, updated every 3 seconds.
The performance effect of collecting stats is probably extremely minor, dwarfed by the rest of the physics code.
2012-05-31 01:52:26 +01:00
Justin Clark-Casey (justincc)
bf0b8170f7 Add console command "teleport user" to allow teleport from the region console
See "help teleport user" on the console for more details
2012-05-29 23:35:20 +01:00
Melanie
b660c4991b Fix collision filtering. The filter should be checked on the receiving part! 2012-05-29 18:18:47 +01:00
Justin Clark-Casey (justincc)
79f3ce2e9f refactor: factor out entity transfer state machine into a separate class to make code more analyzable 2012-05-28 23:06:00 +01:00
Justin Clark-Casey (justincc)
8f87f55d05 If handling the failure of teleport, move agent state to CleaningUp when we start the handling.
Also fixes the log warning from ResetInTransit() if the state is cleared direct from Transferring or ReceiveAtDestination, as pointed out in mantis 5426
2012-05-28 22:16:06 +01:00
Justin Clark-Casey (justincc)
7fd38788b4 minor: code formatting from 0b72f773 2012-05-26 02:14:32 +01:00
Talun
0b72f773c7 Mantis 6025 llRequestPermissions auto grant for NPCs.
If the script requesting permissions is owned by either the NPC or
the NPCs owner (if the NPC is created as owned) then grant any
permissions automatically.
2012-05-26 02:09:22 +01:00
Justin Clark-Casey (justincc)
43a6f28620 If restating a region, clean up the physics scene after the main scene has been closed not before.
If this is done before then on ODE agent update calls still incoming can fail as they try to use a raycastmanager that has been disposed.
Bullet plugin does nothing on Dispose()
However, I wouldn't be at all surprised if individual region restarting was buggy in lots of other areas.
2012-05-26 01:55:35 +01:00
Justin Clark-Casey (justincc)
3ac3be99ae Add Blake/Techplex to CONTRIBUTORS. Thanks! 2012-05-26 01:35:33 +01:00
Blake.Bourque
33b66009e4 One can now get hyoergrid region co-ordinates with llRequestSimulatorData 2012-05-26 01:32:42 +01:00
Justin Clark-Casey (justincc)
d6476b6277 Use GetInventoryItem() in LSL_Api.InventoryKey(string name, int type).
Also removes small bug where calling this method would add 1 to LPS, evne though all callers already did this.
2012-05-26 01:03:53 +01:00
Justin Clark-Casey (justincc)
f2a5fad18f Use SceneObjectPartInventory.GetInventoryItem() in OSSL.AvatarStopAnimation instead of searching the task inventory manually. 2012-05-26 00:54:00 +01:00
Justin Clark-Casey (justincc)
ff53add54d refactor: replace LSL_Api.InventoryKey(string) largely with SceneObjectPartInventory.GetInventoryItem(string)
Also gets llStopAnimation() to call KeyOrName rather than duplicating logic.
2012-05-26 00:36:01 +01:00
Talun
120f8145fc Mantis 6028 osAvatarStopAnimation not stopping animations via UUID
Corrected to stop animations using the animation UUID similar to llStopAnimation.
See http://opensimulator.org/wiki/OsAvatarStopAnimation
2012-05-25 23:45:03 +01:00
Justin Clark-Casey (justincc)
67ebe80dd9 Resolve some mono compiler warnings. 2012-05-25 04:03:16 +01:00
Justin Clark-Casey (justincc)
ab59c0a658 on agent cross, remove from physics scene after its been placed in transit, not before. 2012-05-25 03:39:10 +01:00
Justin Clark-Casey (justincc)
888210ea4a refactor: make ETM.CrossAgentToNewRegionAsync neighbourRegion == null check return earlier to simplify method 2012-05-25 03:06:26 +01:00
Justin Clark-Casey (justincc)
9f1fc7ea88 Remove a call stack debugging line accidentally left in from a few days ago at SceneObjectPartInventory.ApplyNextOwnerPermissions(). 2012-05-25 02:54:37 +01:00
Justin Clark-Casey (justincc)
96cde407ab Fix bug where a failed QueryAccess to a remove region would always have the reason "Communications failure" no matter what the destination region actually returned 2012-05-25 02:37:22 +01:00
Justin Clark-Casey (justincc)
40c78b0624 Stop it being possible for an agent to teleport back to its source region before the source region has finished cleaning up old agent data and structures.
If this is allowed, then the client usually gets forcibly logged out and data structures might be put into bad states.
To prevent this, the binary state machine of EMT.m_agentsInTransit is replaced with a 4 state machine (Preparing, Transferring, ReceivedAtDestination, CleaningUp).
This is necessary because the source region needs to know when the destination region has received the user but a teleport back cannot happen until the source region has cleaned up.
Tested on standalone, grid and with v1 and v3 clients.
2012-05-25 02:02:53 +01:00
Justin Clark-Casey (justincc)
7cceab1295 In remote QueryAccess, also receive the actual status (true|false) instead of always true no matter what the callee actually returned.
This was due to two things
1) SimulationServiceConnector.QueryAccess was always looking to the outer result["success"].
But if a "_Result" map is returned (which is certainly the case right now), then the true success is _Result["success"], result["success"] is always true no matter what
2) If QueryAccess was false at the destination, then AgentHandlers.DoQueryAccess() was never putting this in the result.
The default action of SerializeJsonString() is not to put false booleans in the JSON!!!, so this has to be explicitly set.
2012-05-25 01:41:00 +01:00
Justin Clark-Casey (justincc)
93ff27053a Don't actually proceed on a within-region teleport if another is already taking place, rather than just (falsely) logging that we're not going to proceed.
An oversight from recent commit 9ab0c81
2012-05-24 22:59:52 +01:00
Justin Clark-Casey (justincc)
cc53d91d2f On inter-region teleport, only stand the avatar up if the QueryAccess call to the destination scene actually succeeds. 2012-05-24 22:46:45 +01:00
Justin Clark-Casey (justincc)
cd225215b1 Now that the EntityTransferModule is per-region, fetch the event queue module once rather than repeatedly via scene presences 2012-05-24 22:40:24 +01:00
Justin Clark-Casey (justincc)
5c9086ade6 Fix issue where a dns resolution failure on the final destination might leave the user unable to teleport since the transit flag was not being reset.
This moves the 'already in transit' check further up and resets the flag if dns resolution fails and in the new required places.
2012-05-24 22:26:02 +01:00
SignpostMarv
99cebec4ab adding status codes from rfc 6585
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-05-24 12:09:15 -04:00
SignpostMarv
87f9aa9d08 porting IDE tooltip-friendly documentation tweaks from Aurora-Sim
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-05-24 12:09:15 -04:00
Justin Clark-Casey (justincc)
f4cd4c8e28 Comment out accidentally left in log line that was printing out the control file on OAR save 2012-05-24 04:33:36 +01:00
Justin Clark-Casey (justincc)
38ce9d45a5 Make ISimulationScene.GetScene() used the more efficient region id for lookup rather than the region handle. 2012-05-24 01:00:18 +01:00
Justin Clark-Casey (justincc)
459c7635af If an agent is still registered as 'in transit' by the source region, don't allow an immediate teleport back.
This is to help relieve a race condition when an agent teleports then immediately attempts to teleport back before the source region has properly cleaned up/demoted the old ScenePresence.
This is rare in viewers but much more possible via scripting or region module.
However, more needs to be done since virtually all clean up happens after the transit flag is cleared .
Possibly need to add a 'cleaning up' state to in transit.
This change required making the EntityTransferModule and HGEntityTransferModule per-region rather than shared, in order to allow separate transit lists.
Changes were also required in LocalSimulationConnector.
Tested in standalone, grid and with local and remote region crossings with attachments.
2012-05-24 00:31:14 +01:00
PixelTomsen
bc543c1797 Environment Module - allows Environment settings for Viewer3 warning: includes database region store migrations for mssql, mysql, sqlite
enable/disable this module:
Cap_EnvironmentSettings = "localhost" (for enable)
Cap_EnvironmentSettings = "" (for disable) at ClientStack.LindenCaps section (OpenSimDefaults.ini file)
 or owerwrite in OpenSim.ini

mantis: http://opensimulator.org/mantis/view.php?id=5860

Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2012-05-23 17:04:19 -04:00
BlueWall
b490050165 Format cleanup 2012-05-23 16:58:04 -04:00
BlueWall
682d4075e3 Fix llGetSimulatorHostname to return configured hostname 2012-05-23 15:08:39 -04:00
Justin Clark-Casey (justincc)
4d1986c0e4 minor: Change [OBJECT COMMANDS MODULE] log strings to [REGION COMMANDS MODULE] strings, though all these are currently commented out anyway 2012-05-23 04:20:54 +01:00
Justin Clark-Casey (justincc)
ee98b9c394 Add "show scene" command which lists stats for the currently selected console scene(s)
This includes prim count, script count, avatar count, etc.
Information is currently the same as "show stats", though show stats can only show one scene at a time because it listens for the latest outgoing stats packet (a bad approach that needs to change).
Might be better to tie this module into the other stats module to display arbitrary stats rather than fetching directly from scene.SimStatsReporter.
Console command is "show scene" because "show region" already exists for the grid service, which is unfortunate.
Might need to make a distinction between "scene" relating to a live scene and "region" relating to more static region data (url, coords, etc.)
2012-05-23 04:10:45 +01:00
Justin Clark-Casey (justincc)
8f88c17df9 refactor: Rename ConsoleTableRow and ConsoleTableColumn to ConsoleDisplayTableRow and ConsoleDisplayTableColumn 2012-05-23 03:23:37 +01:00
Justin Clark-Casey (justincc)
059a1e90b9 Add ConsoleDisplayList for more consistent formatting of console output in list form.
Convert "show region" to use this structure rather than hand-constructing
2012-05-23 03:19:25 +01:00
Justin Clark-Casey (justincc)
2222d979cc refactor: rename ConsoleTable -> ConsoleDisplayTable for clarity 2012-05-23 02:37:38 +01:00
Justin Clark-Casey (justincc)
c6ce41bfba Add missing Y co-ord in "show region" console command information 2012-05-23 02:31:53 +01:00
Justin Clark-Casey (justincc)
050007b44d Lay out "show region" information in an easier to read line by line format 2012-05-23 02:30:16 +01:00
Justin Clark-Casey (justincc)
68918d632f Fetch the dialog module reference in AttachmentsModule in RegionLoaded() not AddRegion()
The reference is not guaranteed to be there when AddRegion() is called but will definitely be present at RegionLoaded() if it's going to be present at all.
2012-05-23 02:09:31 +01:00
Justin Clark-Casey (justincc)
ec8745cf51 minor: Make log class names in InventoryAccessModule uniform 2012-05-23 02:05:48 +01:00
Justin Clark-Casey (justincc)
ff429a259b Fix bug where an avatar that had an object they owned attached through llAttachToAvatar() or osForceAttachToAvatar() would wrongly have next permissions come into play when they detached that object and rezzed it in scene.
This is because the attachments module code was setting the 'object slam' bit by using PermissionMask.All
Solution here is to route the attachment item creation call through the existing inventory code in BasicInventoryAccessModule rather than copy/pasted code in AttachmentsModule itself.
2012-05-23 01:58:10 +01:00
Justin Clark-Casey (justincc)
9ab0c81c1d Setting 'in transit' on a local teleport as well as inter-region teleports.
This is to eliminate possible race conditions if two teleport calls are made concurrently, where at least one is a local teleport.
This is pretty much impossible on a manual user teleport but can happen on script-invoked teleports.
2012-05-21 21:33:59 +01:00
Justin Clark-Casey (justincc)
7e97f0e898 minor: extend commented out LinkInventoryItem log message for future use 2012-05-21 21:00:22 +01:00
Justin Clark-Casey (justincc)
16d303f7cd Fix bug where outfit folders could not be renamed.
Outfit folders are a type of system folder whose details are allowed to change.
2012-05-21 19:38:43 +01:00
Justin Clark-Casey (justincc)
0db60eea85 Improve locking of RegionCombinerModule.m_regions 2012-05-19 04:59:36 +01:00
Justin Clark-Casey (justincc)
5759313f7f Add size of region to OAR control file. Megaregions (sw root OARs when saved) will have a size larger than 256x256
Not yet read.  Do not rely on this information yet, it may change.
2012-05-19 04:56:47 +01:00
Justin Clark-Casey (justincc)
824a3a114b refactor: Add RegionConnection.PosX and PosY to return position in meters rather than copy/pasting the necessary calculations in lots of places. 2012-05-19 04:22:30 +01:00
Justin Clark-Casey (justincc)
fb8705dd4d refactor: Rename connection paramaters from "conn" and "regionConnections" so that it's easy to tell whether they refer to the root region connection or a new region connection 2012-05-19 04:01:05 +01:00
Justin Clark-Casey (justincc)
d7f90dee1c Correct some log messages in RegionCombinerModule about the position of the root region of a megaregion relative to an added region 2012-05-19 03:56:25 +01:00
Justin Clark-Casey (justincc)
4e5ac27928 Make the megaregion total area given to the physics module accurate instead of over-inflated.
This was previously over-inflated because adding a region to the NE of the root region resulted in double counting of regions already added.
An accurate extent will also be necessary for other purposes.
2012-05-19 03:45:58 +01:00
Justin Clark-Casey (justincc)
3f2a727b6d Remove recent IRegionCombinerModule.IsMegaregion(). In theory, there can be more than one megaregion in a simulator, separated by water.
Rename IsRootRegion() to IsRootForMegaregion()
2012-05-19 03:17:21 +01:00
Justin Clark-Casey (justincc)
26dfcf5395 Add some method doc to RegionCombinerModule. Clean up log messages. 2012-05-19 03:07:24 +01:00
Justin Clark-Casey (justincc)
33247c8d85 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-05-19 02:46:37 +01:00
Justin Clark-Casey (justincc)
2b60a5c5d6 Add is_megaregion flag into oar control file. Not currently read - for future use. Please do not rely on this remaining here.
An adaptation of part of Garmin's patch from http://opensimulator.org/mantis/view.php?id=5975, thanks!
Flag only written if the SW corner OAR is saved - this is the only one that captures object data presently (though not land or terrain data).
This adds an IRegionCombinerModule interface and the necessary methods on RegionCombinerModule
2012-05-19 02:45:17 +01:00
BlueWall
247a56593f Further refinement on properties 2012-05-18 20:02:32 -04:00
BlueWall
e338c15433 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-05-18 19:34:19 -04:00
BlueWall
895dadbdbd Cleanup + change properties to set fields with private set : Thanks Justin for the tip. 2012-05-18 19:34:12 -04:00
Justin Clark-Casey (justincc)
9fa0577c7e Enable FetchInventoryDescendents2 and FetchInventory2 caps by default. This appears to be required now for LL 3.3.1 to work properly.
Without this, LL 3.3.1 continually pushes LLInventoryModelFetchDescendentsResponder::error 499 to its log.
This cap will be ignored by older viewers - UDP inventory will work normally.
2012-05-19 00:00:52 +01:00
Justin Clark-Casey (justincc)
fc5d274229 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-05-18 23:56:44 +01:00
Justin Clark-Casey (justincc)
896cd45939 Fix issue where a new outfit folder is not created when a new outfit is saved if there are no previous outfits
This was because AddFolder() was disallowing these though they are legal.
2012-05-18 23:55:18 +01:00
BlueWall
c05f87b50c Provide Telehub setting to allow use of landmarks
Setting to allow use of landmarks to override telehub routing. Default is off.
2012-05-18 17:51:38 -04:00
Justin Clark-Casey (justincc)
0147dc6302 Fix build break. Comment out EQG deregister/register logging. 2012-05-18 03:50:23 +01:00
Justin Clark-Casey (justincc)
90722875e8 Add millisecond logging to pCampBot for debugging purposes 2012-05-18 03:44:31 +01:00
Justin Clark-Casey (justincc)
45af29291a Add level 2 debug eq logging which logs event queue polls.
Refactor: eq message logging into common method.
2012-05-18 03:43:36 +01:00
Justin Clark-Casey (justincc)
565c73751c Invoke log4net configurator in pCampBot.exe in order to get OpenSim sylte logging 2012-05-18 00:49:39 +01:00
Justin Clark-Casey (justincc)
6501b1b1bb refactor: move EventQueueGet path generation into common method. Rename some local variables in line with code conventions. Add commented out EQG log lines for future use. 2012-05-18 00:38:29 +01:00
Justin Clark-Casey (justincc)
b18c8c8e78 Don't eagerly clear frame collision events when physics actors subscribe and unsubscribe from collisions, in order to avoid a race condition.
Since this is done directly from ScenePresence, it can lead to a race condition with the simulator loop.
There's no real point doing it anyway since the clear will be done very shortly afterwards by the simulate loop and either there are no events (for a new avatar) or events don't matter (for a departing avatar).
This matches existing behaviour in OdePrim
2012-05-17 23:59:43 +01:00
Justin Clark-Casey (justincc)
521ad080f1 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-05-17 23:56:36 +01:00
Justin Clark-Casey (justincc)
4d34763f8c Check agent limit against root agent count rather than both root and child agents
From sl docs such as http://community.secondlife.com/t5/English-Knowledge-Base/Managing-Private-Regions/ta-p/700115
agent should apply to avatars only.
This makes sense from a user perspective, and also from a code perspective since child agents with no physics or actions take up a fraction of root agent resources.
As such, the check is now only performed in Scene.QueryAccess() - cross and teleport check this before allowing an agent to translocate.
This also removes an off-by-one error that could occur in certain circumstances on teleport when a new child agent was double counted when a pre-teleport agent update was performed.
This does not affect an existing bug where limits or other QueryAccess() checks are not applied to avatars logging directly into a region.
2012-05-17 23:33:26 +01:00
BlueWall
2af11fea37 Merge branch 'master' of /home/opensim/lib/osgrid/opensim 2012-05-17 00:49:33 -04:00
BlueWall
295bb3227d Force the default Telehub router if no matches are found in the config. 2012-05-17 00:47:19 -04:00
BlueWall
bd39f5f803 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-05-16 23:20:37 -04:00
BlueWall
0aa7baf49a Fix boo-boo in OpenSim.ini.example affecting telehub sequential routing
Configuration value should be "sequence" instead of "sequential"
2012-05-16 23:17:42 -04:00
Justin Clark-Casey (justincc)
c45b5a3d1c minor: improve method doc for TestSameSimulatorSeparatedRegionsCreateAgentFails() 2012-05-17 03:27:05 +01:00
Justin Clark-Casey (justincc)
d19fb6fb0c Add regression TestSameSimulatorSeparatedRegionsCreateAgentFails() 2012-05-17 03:12:31 +01:00
Justin Clark-Casey (justincc)
f0c9cb8dc0 Comment out TestSameSimulatorSeparatedRegionsQueryAccessFails() regression test logging accidentally left in 2012-05-17 01:34:04 +01:00
Justin Clark-Casey (justincc)
6b6a00a3d5 minor: Remove redundant EstateOwner != UUID.Zero check in IsAdministrator because checking EstateOwner == user
Due to an earlier check we already know that user != UUID.Zero so if EstateOwner == UUID.Zero, EstateOwner == user can never be true
2012-05-17 01:30:50 +01:00
Justin Clark-Casey (justincc)
bdcf2d1348 Add regression TestSameSimulatorSeparatedRegionsQueryAccessFails() 2012-05-17 01:27:59 +01:00
Justin Clark-Casey (justincc)
e444cb9da4 Remove redundant "Teleport failed:" from reason when QueryAccess fails for the destination simulator. This part of the string is already provided by the viewer.
Also adds more reason logging for diagnostics when teleports are refused/fail.
2012-05-17 00:33:04 +01:00
Justin Clark-Casey (justincc)
23ae24b406 Route OAR SOG loading through the common SceneObjectSerializer.FromXml2Format() rather than the functionally identical but buggy Xml2ToSOG().
Remove buggy Xml2ToSOG().
2012-05-16 00:10:42 +01:00
Justin Clark-Casey (justincc)
e644e34545 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2012-05-15 23:47:42 +01:00
Justin Clark-Casey (justincc)
1b5ce8c10e Fix issue where loading OARs could sometimes result in link numbers being reordered.
This was because the parts in scene objects were sometimes not serialized in link order.
This is perfectly fine since the parts still have the right link numbers, but an extra fix to adjust for this
had not been done in the SerialiserModule methods that OAR loading used.
Add regression test for same.
Addresses http://opensimulator.org/mantis/view.php?id=5948, http://opensimulator.org/mantis/view.php?id=5749
2012-05-15 23:43:59 +01:00
Justin Clark-Casey (justincc)
02f3b116c6 Allow use of regular expressions in "show object name", "show part name" and "delete object name" console commands if --regex switch is used.
Deleteing objects by name, creator uuid or owner uuid now requires confirmation to avoid accidental deletion.
2012-05-15 23:42:49 +01:00
Melanie
ef94c31ef8 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2012-05-15 03:17:42 +01:00
dahlia
1ce576b115 Add another null check to Melanie's last commit. Seems to eliminate sqlite errors in log but no idea if it's working properly 2012-05-14 19:34:18 -07:00
Melanie
65e1d7b2d7 Guard against null root part on SQLite. This really needs to be fixed so SQLite
loads roots before children like MySQL does.
2012-05-15 03:16:12 +01:00
Melanie
069bcd45e5 Try to fix sqlite breakage 2012-05-15 02:27:21 +01:00
291 changed files with 10507 additions and 5185 deletions

View File

@@ -146,6 +146,7 @@ what it is today.
* Stefan_Boom / stoehr
* Strawberry Fride
* Talun
* TechplexEngineer (Blake Bourque)
* TBG Renfold
* tglion
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)

View File

@@ -539,7 +539,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
/// path has not already been registered, the method is added to the active
/// handler table.
/// </summary>
public void AddStreamHandler(string httpMethod, string path, RestMethod method)
{
if (!IsEnabled)

View File

@@ -101,18 +101,8 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
try
{
llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType);
llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}",
invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
}
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
@@ -126,21 +116,7 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
switch (invItem.SaleType)
{
default:
llsdItem.sale_info.sale_type = "not";
break;
case 1:
llsdItem.sale_info.sale_type = "original";
break;
case 2:
llsdItem.sale_info.sale_type = "copy";
break;
case 3:
llsdItem.sale_info.sale_type = "contents";
break;
}
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}

View File

@@ -77,7 +77,6 @@ namespace OpenSim.Capabilities.Handlers
{
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return null;
}
UUID textureID;
@@ -115,7 +114,6 @@ namespace OpenSim.Capabilities.Handlers
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
httpResponse.Send();
return null;
}

View File

@@ -156,11 +156,12 @@ namespace OpenSim.Capabilities.Handlers
inv.Folders = new List<InventoryFolderBase>();
inv.Items = new List<InventoryItemBase>();
int version = 0;
int descendents = 0;
inv
= Fetch(
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
if (inv != null && inv.Folders != null)
{
@@ -168,6 +169,8 @@ namespace OpenSim.Capabilities.Handlers
{
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
}
descendents += inv.Folders.Count;
}
if (inv != null && inv.Items != null)
@@ -178,7 +181,7 @@ namespace OpenSim.Capabilities.Handlers
}
}
contents.descendents = contents.items.Array.Count + contents.categories.Array.Count;
contents.descendents = descendents;
contents.version = version;
// m_log.DebugFormat(
@@ -206,7 +209,7 @@ namespace OpenSim.Capabilities.Handlers
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
private InventoryCollection Fetch(
UUID agentID, UUID folderID, UUID ownerID,
bool fetchFolders, bool fetchItems, int sortOrder, out int version)
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
@@ -215,6 +218,8 @@ namespace OpenSim.Capabilities.Handlers
// FIXME MAYBE: We're not handling sortOrder!
version = 0;
descendents = 0;
InventoryFolderImpl fold;
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
{
@@ -223,6 +228,7 @@ namespace OpenSim.Capabilities.Handlers
InventoryCollection ret = new InventoryCollection();
ret.Folders = new List<InventoryFolderBase>();
ret.Items = fold.RequestListOfItems();
descendents = ret.Folders.Count + ret.Items.Count;
return ret;
}
@@ -246,24 +252,72 @@ namespace OpenSim.Capabilities.Handlers
version = containingFolder.Version;
// if (fetchItems)
if (fetchItems)
{
List<InventoryItemBase> itemsToReturn = contents.Items;
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
// descendents must only include the links, not the linked items we add
descendents = originalItems.Count;
// Add target items for links in this folder before the links themselves.
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.Link)
{
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
itemsToReturn.Insert(0, linkedItem);
}
}
// Now scan for folder links and insert the items they target and those links at the head of the return data
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.LinkFolder)
{
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
List<InventoryItemBase> links = linkedFolderContents.Items;
itemsToReturn.InsertRange(0, links);
foreach (InventoryItemBase link in linkedFolderContents.Items)
{
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (link != null)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
InventoryItemBase linkedItem
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
if (linkedItem != null)
itemsToReturn.Insert(0, linkedItem);
}
}
}
}
}
// foreach (InventoryItemBase item in contents.Items)
// {
// List<InventoryItemBase> linkedItemsToAdd = new List<InventoryItemBase>();
//
// foreach (InventoryItemBase item in contents.Items)
// {
// if (item.AssetType == (int)AssetType.Link)
// {
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
//
// // Take care of genuinely broken links where the target doesn't exist
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// // rather than having to keep track of every folder requested in the recursion.
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
// linkedItemsToAdd.Insert(0, linkedItem);
// }
// }
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
// }
// =====
//
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
// {
@@ -340,12 +394,8 @@ namespace OpenSim.Capabilities.Handlers
llsdFolder.folder_id = invFolder.ID;
llsdFolder.parent_id = invFolder.ParentID;
llsdFolder.name = invFolder.Name;
if (invFolder.Type == (short)AssetType.Unknown || !Enum.IsDefined(typeof(AssetType), (sbyte)invFolder.Type))
llsdFolder.type = "-1";
else
llsdFolder.type = Utils.AssetTypeToString((AssetType)invFolder.Type);
llsdFolder.preferred_type = "-1";
llsdFolder.type = invFolder.Type;
llsdFolder.preferred_type = -1;
return llsdFolder;
}
@@ -365,18 +415,8 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
try
{
llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType);
llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}",
invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
}
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
@@ -390,21 +430,7 @@ namespace OpenSim.Capabilities.Handlers
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
switch (invItem.SaleType)
{
default:
llsdItem.sale_info.sale_type = "not";
break;
case 1:
llsdItem.sale_info.sale_type = "original";
break;
case 2:
llsdItem.sale_info.sale_type = "copy";
break;
case 3:
llsdItem.sale_info.sale_type = "contents";
break;
}
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDEnvironmentRequest
{
public UUID messageID;
public UUID regionID;
}
[OSDMap]
public class LLSDEnvironmentSetResponse
{
public UUID regionID;
public UUID messageID;
public Boolean success;
public String fail_reason;
}
public class EnvironmentSettings
{
/// <summary>
/// generates a empty llsd settings response for viewer
/// </summary>
/// <param name="messageID">the message UUID</param>
/// <param name="regionID">the region UUID</param>
public static string EmptySettings(UUID messageID, UUID regionID)
{
OSDArray arr = new OSDArray();
LLSDEnvironmentRequest msg = new LLSDEnvironmentRequest();
msg.messageID = messageID;
msg.regionID = regionID;
arr.Array.Add(msg);
return LLSDHelpers.SerialiseLLSDReply(arr);
}
}
}

View File

@@ -35,7 +35,7 @@ namespace OpenSim.Framework.Capabilities
public UUID folder_id;
public UUID parent_id;
public string name;
public string type;
public string preferred_type;
public int type;
public int preferred_type;
}
}

View File

@@ -37,8 +37,8 @@ namespace OpenSim.Framework.Capabilities
public UUID asset_id;
public UUID item_id;
public LLSDPermissions permissions;
public string type;
public string inv_type;
public int type;
public int inv_type;
public int flags;
public LLSDSaleInfo sale_info;
@@ -65,7 +65,7 @@ namespace OpenSim.Framework.Capabilities
public class LLSDSaleInfo
{
public int sale_price;
public string sale_type;
public int sale_type;
}
[OSDMap]

View File

@@ -66,9 +66,7 @@ namespace OpenSim.Framework.Capabilities
TResponse response = m_method(llsdRequest);
Encoding encoding = new UTF8Encoding(false);
return encoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
return Util.UTF8NoBomEncoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
}
}
}

View File

@@ -50,7 +50,7 @@ namespace OpenSim.ConsoleClient
request.ContentType = "application/x-www-form-urlencoded";
byte[] buffer = new System.Text.ASCIIEncoding().GetBytes(data);
byte[] buffer = Encoding.ASCII.GetBytes(data);
int length = (int) buffer.Length;
request.ContentLength = length;

View File

@@ -1181,6 +1181,72 @@ VALUES
// }
#endregion
}
#region Environment Settings
public string LoadRegionEnvironmentSettings(UUID regionUUID)
{
string sql = "select * from [regionenvironment] where region_id = @region_id";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
conn.Open();
using (SqlDataReader result = cmd.ExecuteReader())
{
if (!result.Read())
{
return String.Empty;
}
else
{
return Convert.ToString(result["llsd_settings"]);
}
}
}
}
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
{
{
string sql = "DELETE FROM [regionenvironment] WHERE region_id = @region_id";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
conn.Open();
cmd.ExecuteNonQuery();
}
sql = "INSERT INTO [regionenvironment] (region_id, llsd_settings) VALUES (@region_id, @llsd_settings)";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
cmd.Parameters.Add(_Database.CreateParameter("@llsd_settings", settings));
conn.Open();
cmd.ExecuteNonQuery();
}
}
}
public void RemoveRegionEnvironmentSettings(UUID regionUUID)
{
string sql = "delete from [regionenvironment] where region_id = @region_id";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
conn.Open();
cmd.ExecuteNonQuery();
}
}
#endregion
/// <summary>
/// Loads the settings of a region.
/// </summary>

View File

@@ -1134,3 +1134,17 @@ ALTER TABLE landaccesslist ADD Expires integer NOT NULL DEFAULT 0;
COMMIT
:VERSION 37 #---------------- Environment Settings
BEGIN TRANSACTION
CREATE TABLE [dbo].[regionenvironment](
[region_id] [uniqueidentifier] NOT NULL,
[llsd_settings] [varchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
PRIMARY KEY CLUSTERED
(
[region_id] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
COMMIT

View File

@@ -969,6 +969,68 @@ namespace OpenSim.Data.MySQL
}
}
#region RegionEnvironmentSettings
public string LoadRegionEnvironmentSettings(UUID regionUUID)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
string command = "select * from `regionenvironment` where region_id = ?region_id";
using (MySqlCommand cmd = new MySqlCommand(command))
{
cmd.Connection = dbcon;
cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
IDataReader result = ExecuteReader(cmd);
if (!result.Read())
{
return String.Empty;
}
else
{
return Convert.ToString(result["llsd_settings"]);
}
}
}
}
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
cmd.Parameters.AddWithValue("region_id", regionUUID);
cmd.Parameters.AddWithValue("llsd_settings", settings);
ExecuteNonQuery(cmd);
}
}
}
public void RemoveRegionEnvironmentSettings(UUID regionUUID)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
ExecuteNonQuery(cmd);
}
}
}
#endregion
public void StoreRegionSettings(RegionSettings rs)
{
lock (m_dbLock)

View File

@@ -883,4 +883,15 @@ ALTER TABLE `regionsettings` MODIFY COLUMN `TelehubObject` VARCHAR(36) NOT NULL
COMMIT;
:VERSION 44 #--------------------- Environment Settings
BEGIN;
CREATE TABLE `regionenvironment` (
`region_id` varchar(36) NOT NULL,
`llsd_settings` TEXT NOT NULL,
PRIMARY KEY (`region_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
COMMIT;

View File

@@ -76,9 +76,27 @@ namespace OpenSim.Data.Null
//This connector doesn't support the windlight module yet
}
#region Environment Settings
public string LoadRegionEnvironmentSettings(UUID regionUUID)
{
//This connector doesn't support the Environment module yet
return string.Empty;
}
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
{
//This connector doesn't support the Environment module yet
}
public void RemoveRegionEnvironmentSettings(UUID regionUUID)
{
//This connector doesn't support the Environment module yet
}
#endregion
public RegionSettings LoadRegionSettings(UUID regionUUID)
{
RegionSettings rs = new RegionSettings();
{
RegionSettings rs = new RegionSettings();
rs.RegionUUID = regionUUID;
return rs;
}

View File

@@ -564,3 +564,14 @@ COMMIT;
BEGIN;
ALTER TABLE `regionsettings` ADD COLUMN `parcel_tile_ID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
COMMIT;
:VERSION 26
BEGIN;
CREATE TABLE `regionenvironment` (
`region_id` varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000' PRIMARY KEY,
`llsd_settings` TEXT NOT NULL
);
COMMIT;

View File

@@ -61,6 +61,7 @@ namespace OpenSim.Data.SQLite
private const string regionbanListSelect = "select * from regionban";
private const string regionSettingsSelect = "select * from regionsettings";
private const string regionWindlightSelect = "select * from regionwindlight";
private const string regionEnvironmentSelect = "select * from regionenvironment";
private const string regionSpawnPointsSelect = "select * from spawn_points";
private DataSet ds;
@@ -72,6 +73,7 @@ namespace OpenSim.Data.SQLite
private SqliteDataAdapter landAccessListDa;
private SqliteDataAdapter regionSettingsDa;
private SqliteDataAdapter regionWindlightDa;
private SqliteDataAdapter regionEnvironmentDa;
private SqliteDataAdapter regionSpawnPointsDa;
private SqliteConnection m_conn;
@@ -146,6 +148,9 @@ namespace OpenSim.Data.SQLite
SqliteCommand regionWindlightSelectCmd = new SqliteCommand(regionWindlightSelect, m_conn);
regionWindlightDa = new SqliteDataAdapter(regionWindlightSelectCmd);
SqliteCommand regionEnvironmentSelectCmd = new SqliteCommand(regionEnvironmentSelect, m_conn);
regionEnvironmentDa = new SqliteDataAdapter(regionEnvironmentSelectCmd);
SqliteCommand regionSpawnPointsSelectCmd = new SqliteCommand(regionSpawnPointsSelect, m_conn);
regionSpawnPointsDa = new SqliteDataAdapter(regionSpawnPointsSelectCmd);
@@ -179,6 +184,9 @@ namespace OpenSim.Data.SQLite
ds.Tables.Add(createRegionWindlightTable());
setupRegionWindlightCommands(regionWindlightDa, m_conn);
ds.Tables.Add(createRegionEnvironmentTable());
setupRegionEnvironmentCommands(regionEnvironmentDa, m_conn);
ds.Tables.Add(createRegionSpawnPointsTable());
setupRegionSpawnPointsCommands(regionSpawnPointsDa, m_conn);
@@ -258,6 +266,15 @@ namespace OpenSim.Data.SQLite
m_log.ErrorFormat("[SQLITE REGION DB]: Caught fill error on regionwindlight table :{0}", e.Message);
}
try
{
regionEnvironmentDa.Fill(ds.Tables["regionenvironment"]);
}
catch (Exception e)
{
m_log.ErrorFormat("[SQLITE REGION DB]: Caught fill error on regionenvironment table :{0}", e.Message);
}
try
{
regionSpawnPointsDa.Fill(ds.Tables["spawn_points"]);
@@ -278,12 +295,13 @@ namespace OpenSim.Data.SQLite
CreateDataSetMapping(landAccessListDa, "landaccesslist");
CreateDataSetMapping(regionSettingsDa, "regionsettings");
CreateDataSetMapping(regionWindlightDa, "regionwindlight");
CreateDataSetMapping(regionEnvironmentDa, "regionenvironment");
CreateDataSetMapping(regionSpawnPointsDa, "spawn_points");
}
}
catch (Exception e)
{
m_log.ErrorFormat("[SQLITE REGION DB]: ", e);
m_log.ErrorFormat("[SQLITE REGION DB]: {0} - {1}", e.Message, e.StackTrace);
Environment.Exit(23);
}
return;
@@ -341,6 +359,11 @@ namespace OpenSim.Data.SQLite
regionWindlightDa.Dispose();
regionWindlightDa = null;
}
if (regionEnvironmentDa != null)
{
regionEnvironmentDa.Dispose();
regionEnvironmentDa = null;
}
if (regionSpawnPointsDa != null)
{
regionSpawnPointsDa.Dispose();
@@ -474,6 +497,63 @@ namespace OpenSim.Data.SQLite
}
}
#region Region Environment Settings
public string LoadRegionEnvironmentSettings(UUID regionUUID)
{
lock (ds)
{
DataTable environmentTable = ds.Tables["regionenvironment"];
DataRow row = environmentTable.Rows.Find(regionUUID.ToString());
if (row == null)
{
return String.Empty;
}
return (String)row["llsd_settings"];
}
}
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
{
lock (ds)
{
DataTable environmentTable = ds.Tables["regionenvironment"];
DataRow row = environmentTable.Rows.Find(regionUUID.ToString());
if (row == null)
{
row = environmentTable.NewRow();
row["region_id"] = regionUUID.ToString();
row["llsd_settings"] = settings;
environmentTable.Rows.Add(row);
}
else
{
row["llsd_settings"] = settings;
}
regionEnvironmentDa.Update(ds, "regionenvironment");
}
}
public void RemoveRegionEnvironmentSettings(UUID regionUUID)
{
lock (ds)
{
DataTable environmentTable = ds.Tables["regionenvironment"];
DataRow row = environmentTable.Rows.Find(regionUUID.ToString());
if (row != null)
{
row.Delete();
}
regionEnvironmentDa.Update(ds, "regionenvironment");
}
}
#endregion
public RegionSettings LoadRegionSettings(UUID regionUUID)
{
lock (ds)
@@ -1430,6 +1510,17 @@ namespace OpenSim.Data.SQLite
return regionwindlight;
}
private static DataTable createRegionEnvironmentTable()
{
DataTable regionEnvironment = new DataTable("regionenvironment");
createCol(regionEnvironment, "region_id", typeof(String));
createCol(regionEnvironment, "llsd_settings", typeof(String));
regionEnvironment.PrimaryKey = new DataColumn[] { regionEnvironment.Columns["region_id"] };
return regionEnvironment;
}
private static DataTable createRegionSpawnPointsTable()
{
DataTable spawn_points = new DataTable("spawn_points");
@@ -2691,6 +2782,14 @@ namespace OpenSim.Data.SQLite
da.UpdateCommand.Connection = conn;
}
private void setupRegionEnvironmentCommands(SqliteDataAdapter da, SqliteConnection conn)
{
da.InsertCommand = createInsertCommand("regionenvironment", ds.Tables["regionenvironment"]);
da.InsertCommand.Connection = conn;
da.UpdateCommand = createUpdateCommand("regionenvironment", "region_id=:region_id", ds.Tables["regionenvironment"]);
da.UpdateCommand.Connection = conn;
}
private void setupRegionSpawnPointsCommands(SqliteDataAdapter da, SqliteConnection conn)
{
da.InsertCommand = createInsertCommand("spawn_points", ds.Tables["spawn_points"]);

View File

@@ -1069,8 +1069,6 @@ namespace OpenSim.Data.Tests
regionInfo.RegionLocX = 0;
regionInfo.RegionLocY = 0;
Scene scene = new Scene(regionInfo);
SceneObjectPart sop = new SceneObjectPart();
sop.Name = name;
sop.Description = name;
@@ -1081,7 +1079,7 @@ namespace OpenSim.Data.Tests
sop.Shape = PrimitiveBaseShape.Default;
SceneObjectGroup sog = new SceneObjectGroup(sop);
sog.SetScene(scene);
// sog.SetScene(scene);
return sog;
}

View File

@@ -98,6 +98,11 @@ namespace OpenSim.Framework
/// </summary>
public string lastname;
/// <summary>
/// Agent's full name.
/// </summary>
public string Name { get { return string.Format("{0} {1}", firstname, lastname); } }
/// <summary>
/// Random Unique GUID for this session. Client gets this at login and it's
/// only supposed to be disclosed over secure channels

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenSim.Framework.Console
{
/// <summary>
/// Used to generated a formatted table for the console.
/// </summary>
/// <remarks>
/// Currently subject to change. If you use this, be prepared to change your code when this class changes.
/// </remarks>
public class ConsoleDisplayList
{
/// <summary>
/// The default divider between key and value for a list item.
/// </summary>
public const string DefaultKeyValueDivider = " : ";
/// <summary>
/// The divider used between key and value for a list item.
/// </summary>
public string KeyValueDivider { get; set; }
/// <summary>
/// Table rows
/// </summary>
public List<KeyValuePair<string, string>> Rows { get; private set; }
/// <summary>
/// Number of spaces to indent the list.
/// </summary>
public int Indent { get; set; }
public ConsoleDisplayList()
{
Rows = new List<KeyValuePair<string, string>>();
KeyValueDivider = DefaultKeyValueDivider;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
AddToStringBuilder(sb);
return sb.ToString();
}
public void AddToStringBuilder(StringBuilder sb)
{
string formatString = GetFormatString();
// System.Console.WriteLine("FORMAT STRING [{0}]", formatString);
// rows
foreach (KeyValuePair<string, string> row in Rows)
sb.AppendFormat(formatString, row.Key, row.Value);
}
/// <summary>
/// Gets the format string for the table.
/// </summary>
private string GetFormatString()
{
StringBuilder formatSb = new StringBuilder();
int longestKey = -1;
foreach (KeyValuePair<string, string> row in Rows)
if (row.Key.Length > longestKey)
longestKey = row.Key.Length;
formatSb.Append(' ', Indent);
// Can only do left formatting for now
formatSb.AppendFormat("{{0,-{0}}}{1}{{1}}\n", longestKey, KeyValueDivider);
return formatSb.ToString();
}
public void AddRow(object key, object value)
{
Rows.Add(new KeyValuePair<string, string>(key.ToString(), value.ToString()));
}
}
}

View File

@@ -38,7 +38,7 @@ namespace OpenSim.Framework.Console
/// <remarks>
/// Currently subject to change. If you use this, be prepared to change your code when this class changes.
/// </remarks>
public class ConsoleTable
public class ConsoleDisplayTable
{
/// <summary>
/// Default number of spaces between table columns.
@@ -48,12 +48,12 @@ namespace OpenSim.Framework.Console
/// <summary>
/// Table columns.
/// </summary>
public List<ConsoleTableColumn> Columns { get; private set; }
public List<ConsoleDisplayTableColumn> Columns { get; private set; }
/// <summary>
/// Table rows
/// </summary>
public List<ConsoleTableRow> Rows { get; private set; }
public List<ConsoleDisplayTableRow> Rows { get; private set; }
/// <summary>
/// Number of spaces to indent the table.
@@ -65,11 +65,11 @@ namespace OpenSim.Framework.Console
/// </summary>
public int TableSpacing { get; set; }
public ConsoleTable()
public ConsoleDisplayTable()
{
TableSpacing = DefaultTableSpacing;
Columns = new List<ConsoleTableColumn>();
Rows = new List<ConsoleTableRow>();
Columns = new List<ConsoleDisplayTableColumn>();
Rows = new List<ConsoleDisplayTableRow>();
}
public override string ToString()
@@ -79,6 +79,16 @@ namespace OpenSim.Framework.Console
return sb.ToString();
}
public void AddColumn(string name, int width)
{
Columns.Add(new ConsoleDisplayTableColumn(name, width));
}
public void AddRow(params string[] cells)
{
Rows.Add(new ConsoleDisplayTableRow(cells));
}
public void AddToStringBuilder(StringBuilder sb)
{
string formatString = GetFormatString();
@@ -88,7 +98,7 @@ namespace OpenSim.Framework.Console
sb.AppendFormat(formatString, Columns.ConvertAll(c => c.Header).ToArray());
// rows
foreach (ConsoleTableRow row in Rows)
foreach (ConsoleDisplayTableRow row in Rows)
sb.AppendFormat(formatString, row.Cells.ToArray());
}
@@ -115,25 +125,30 @@ namespace OpenSim.Framework.Console
}
}
public struct ConsoleTableColumn
public struct ConsoleDisplayTableColumn
{
public string Header { get; set; }
public int Width { get; set; }
public ConsoleTableColumn(string header, int width) : this()
public ConsoleDisplayTableColumn(string header, int width) : this()
{
Header = header;
Width = width;
}
}
public struct ConsoleTableRow
public struct ConsoleDisplayTableRow
{
public List<string> Cells { get; private set; }
public ConsoleTableRow(List<string> cells) : this()
public ConsoleDisplayTableRow(List<string> cells) : this()
{
Cells = cells;
}
public ConsoleDisplayTableRow(params string[] cells) : this()
{
Cells = new List<string>(cells);
}
}
}

View File

@@ -740,14 +740,21 @@ namespace OpenSim.Framework
/// </summary>
string Name { get; }
/// <value>
/// Determines whether the client thread is doing anything or not.
/// </value>
/// <summary>
/// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
/// </summary>
bool IsActive { get; set; }
/// <value>
/// Determines whether the client is or has been removed from a given scene
/// </value>
/// <summary>
/// Set if the client is closing due to a logout request
/// </summary>
/// <remarks>
/// Do not use this flag if you want to know if the client is closing, since it will not be set in other
/// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
/// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
///
/// Only set for root agents.
/// </remarks>
bool IsLoggingOut { get; set; }
bool SendLogoutPacketWhenClosing { set; }
@@ -1346,7 +1353,6 @@ namespace OpenSim.Framework
void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message);
void SendLogoutPacket();
EndPoint GetClientEP();
// WARNING WARNING WARNING
//
@@ -1407,8 +1413,6 @@ namespace OpenSim.Framework
void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes);
void KillEndDone();
bool AddGenericPacketHandler(string MethodName, GenericMessage handler);
void SendRebakeAvatarTextures(UUID textureID);

View File

@@ -56,6 +56,11 @@ namespace OpenSim.Framework
public interface IScene
{
/// <summary>
/// The name of this scene.
/// </summary>
string Name { get; }
RegionInfo RegionInfo { get; }
RegionStatus RegionStatus { get; set; }

View File

@@ -26,6 +26,7 @@
*/
using System;
using OpenMetaverse;
namespace OpenSim.Framework
{
@@ -71,5 +72,11 @@ namespace OpenSim.Framework
/// This includes scene object data and the appearance data of other avatars.
/// </remarks>
void SendInitialDataToMe();
/// <summary>
/// Direction in which the scene presence is looking.
/// </summary>
/// <remarks>Will be Vector3.Zero for a child agent.</remarks>
Vector3 Lookat { get; }
}
}

View File

@@ -42,9 +42,7 @@ namespace OpenSim.Framework.Serialization.External
/// </summary>
public class LandDataSerializer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<string, Action<LandData, XmlTextReader>> m_ldProcessors
= new Dictionary<string, Action<LandData, XmlTextReader>>();
@@ -163,7 +161,7 @@ namespace OpenSim.Framework.Serialization.External
/// <exception cref="System.Xml.XmlException"></exception>
public static LandData Deserialize(byte[] serializedLandData)
{
return Deserialize(m_utf8Encoding.GetString(serializedLandData, 0, serializedLandData.Length));
return Deserialize(Encoding.UTF8.GetString(serializedLandData, 0, serializedLandData.Length));
}
/// <summary>

View File

@@ -40,8 +40,6 @@ namespace OpenSim.Framework.Serialization.External
/// </summary>
public class RegionSettingsSerializer
{
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
/// <summary>
/// Deserialize settings
/// </summary>
@@ -50,7 +48,7 @@ namespace OpenSim.Framework.Serialization.External
/// <exception cref="System.Xml.XmlException"></exception>
public static RegionSettings Deserialize(byte[] serializedSettings)
{
return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length));
return Deserialize(Encoding.ASCII.GetString(serializedSettings, 0, serializedSettings.Length));
}
/// <summary>

View File

@@ -44,7 +44,7 @@ namespace OpenSim.Framework.Serialization.External
/// </summary>
public class UserInventoryItemSerializer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<string, Action<InventoryItemBase, XmlTextReader>> m_InventoryItemXmlProcessors
= new Dictionary<string, Action<InventoryItemBase, XmlTextReader>>();

View File

@@ -53,8 +53,6 @@ namespace OpenSim.Framework.Serialization
TYPE_CONTIGUOUS_FILE = 8,
}
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
/// <summary>
/// Binary reader for the underlying stream
/// </summary>
@@ -120,13 +118,13 @@ namespace OpenSim.Framework.Serialization
if (header[156] == (byte)'L')
{
int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11);
tarHeader.FilePath = m_asciiEncoding.GetString(ReadData(longNameLength));
tarHeader.FilePath = Encoding.ASCII.GetString(ReadData(longNameLength));
//m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath);
header = m_br.ReadBytes(512);
}
else
{
tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100);
tarHeader.FilePath = Encoding.ASCII.GetString(header, 0, 100);
tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
//m_log.DebugFormat("[TAR ARCHIVE READER]: Got short file name {0}", tarHeader.FilePath);
}
@@ -205,7 +203,7 @@ namespace OpenSim.Framework.Serialization
{
// Trim leading white space: ancient tars do that instead
// of leading 0s :-( don't ask. really.
string oString = m_asciiEncoding.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
string oString = Encoding.ASCII.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
int d = 0;

View File

@@ -41,9 +41,6 @@ namespace OpenSim.Framework.Serialization
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
/// <summary>
/// Binary writer for the underlying stream
/// </summary>
@@ -74,7 +71,7 @@ namespace OpenSim.Framework.Serialization
/// <param name="data"></param>
public void WriteFile(string filePath, string data)
{
WriteFile(filePath, m_utf8Encoding.GetBytes(data));
WriteFile(filePath, Util.UTF8NoBomEncoding.GetBytes(data));
}
/// <summary>
@@ -85,7 +82,7 @@ namespace OpenSim.Framework.Serialization
public void WriteFile(string filePath, byte[] data)
{
if (filePath.Length > 100)
WriteEntry("././@LongLink", m_asciiEncoding.GetBytes(filePath), 'L');
WriteEntry("././@LongLink", Encoding.ASCII.GetBytes(filePath), 'L');
char fileType;
@@ -137,7 +134,7 @@ namespace OpenSim.Framework.Serialization
oString = "0" + oString;
}
byte[] oBytes = m_asciiEncoding.GetBytes(oString);
byte[] oBytes = Encoding.ASCII.GetBytes(oString);
return oBytes;
}
@@ -156,20 +153,20 @@ namespace OpenSim.Framework.Serialization
byte[] header = new byte[512];
// file path field (100)
byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
byte[] nameBytes = Encoding.ASCII.GetBytes(filePath);
int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
Array.Copy(nameBytes, header, nameSize);
// file mode (8)
byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
byte[] modeBytes = Encoding.ASCII.GetBytes("0000777");
Array.Copy(modeBytes, 0, header, 100, 7);
// owner user id (8)
byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
byte[] ownerIdBytes = Encoding.ASCII.GetBytes("0000764");
Array.Copy(ownerIdBytes, 0, header, 108, 7);
// group user id (8)
byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
byte[] groupIdBytes = Encoding.ASCII.GetBytes("0000764");
Array.Copy(groupIdBytes, 0, header, 116, 7);
// file size in bytes (12)
@@ -181,17 +178,17 @@ namespace OpenSim.Framework.Serialization
Array.Copy(fileSizeBytes, 0, header, 124, 11);
// last modification time (12)
byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
byte[] lastModTimeBytes = Encoding.ASCII.GetBytes("11017037332");
Array.Copy(lastModTimeBytes, 0, header, 136, 11);
// entry type indicator (1)
header[156] = m_asciiEncoding.GetBytes(new char[] { fileType })[0];
header[156] = Encoding.ASCII.GetBytes(new char[] { fileType })[0];
Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 329, 7);
Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 337, 7);
// check sum for header block (8) [calculated last]
Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
Array.Copy(Encoding.ASCII.GetBytes(" "), 0, header, 148, 8);
int checksum = 0;
foreach (byte b in header)

View File

@@ -320,7 +320,9 @@ namespace OpenSim.Framework.Servers
TimeSpan timeTaken = DateTime.Now - m_startuptime;
m_log.InfoFormat("[STARTUP]: Startup took {0}m {1}s", timeTaken.Minutes, timeTaken.Seconds);
m_log.InfoFormat(
"[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.",
timeTaken.Minutes, timeTaken.Seconds);
}
/// <summary>
@@ -589,8 +591,8 @@ namespace OpenSim.Framework.Servers
{
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
FileStream fs = File.Create(path);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
Byte[] buf = enc.GetBytes(pidstring);
Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
fs.Write(buf, 0, buf.Length);
fs.Close();
m_pidFile = path;

View File

@@ -53,6 +53,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
public int DebugLevel { get; set; }
private volatile int NotSocketErrors = 0;
public volatile bool HTTPDRunning = false;
@@ -79,11 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
private PollServiceRequestManager m_PollServiceManager;
/// <summary>
/// Control the printing of certain debug messages.
/// </summary>
public int DebugLevel { get; set; }
public uint SSLPort
{
get { return m_sslport; }
@@ -408,7 +405,10 @@ namespace OpenSim.Framework.Servers.HttpServer
string uriString = request.RawUrl;
// string reqnum = "unknown";
int tickstart = Environment.TickCount;
int requestStartTick = Environment.TickCount;
// Will be adjusted later on.
int requestEndTick = requestStartTick;
IRequestHandler requestHandler = null;
@@ -433,6 +433,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
if (HandleAgentRequest(agentHandler, request, response))
{
requestEndTick = Environment.TickCount;
return;
}
}
@@ -442,17 +443,15 @@ namespace OpenSim.Framework.Servers.HttpServer
string path = request.RawUrl;
string handlerKey = GetHandlerKey(request.HttpMethod, path);
byte[] buffer = null;
if (TryGetStreamHandler(handlerKey, out requestHandler))
{
if (DebugLevel >= 1)
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
// Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
byte[] buffer = null;
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
if (requestHandler is IStreamedRequestHandler)
@@ -507,8 +506,8 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_log.Warn("[HTTP]: " + requestBody);
}
DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
return;
buffer = DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
}
else
{
@@ -521,133 +520,99 @@ namespace OpenSim.Framework.Servers.HttpServer
buffer = memoryStream.ToArray();
}
}
}
else
{
switch (request.ContentType)
{
case null:
case "text/html":
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
buffer = HandleHTTPRequest(request, response);
break;
case "application/llsd+xml":
case "application/xml+llsd":
case "application/llsd+json":
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
buffer = HandleLLSDRequests(request, response);
break;
case "text/xml":
case "application/xml":
case "application/json":
default:
//m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
// Point of note.. the DoWeHaveA methods check for an EXACT path
// if (request.RawUrl.Contains("/CAPS/EQG"))
// {
// int i = 1;
// }
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
if (DoWeHaveALLSDHandler(request.RawUrl))
{
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
buffer = HandleLLSDRequests(request, response);
}
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
else if (DoWeHaveAHTTPHandler(request.RawUrl))
{
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
buffer = HandleHTTPRequest(request, response);
}
else
{
if (DebugLevel >= 3)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// generic login request.
buffer = HandleXmlRpcRequests(request, response);
}
break;
}
}
request.InputStream.Close();
// HTTP IN support. The script engine takes it from here
// Nothing to worry about for us.
//
if (buffer == null)
return;
request.InputStream.Close();
if (buffer != null)
{
if (!response.SendChunked)
response.ContentLength64 = buffer.LongLength;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
//response.OutputStream.Close();
}
catch (HttpListenerException)
{
m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
}
//response.OutputStream.Close();
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
catch (IOException e)
{
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}. ", e.Message), e);
}
return;
response.OutputStream.Write(buffer, 0, buffer.Length);
}
if (request.AcceptTypes != null && request.AcceptTypes.Length > 0)
{
foreach (string strAccept in request.AcceptTypes)
{
if (strAccept.Contains("application/llsd+xml") ||
strAccept.Contains("application/llsd+json"))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found application/llsd+xml accept header handler for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// Do not include the time taken to actually send the response to the caller in the measurement
// time. This is to avoid logging when it's the client that is slow to process rather than the
// server
requestEndTick = Environment.TickCount;
HandleLLSDRequests(request, response);
return;
}
}
}
response.Send();
switch (request.ContentType)
{
case null:
case "text/html":
//response.OutputStream.Close();
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleHTTPRequest(request, response);
return;
case "application/llsd+xml":
case "application/xml+llsd":
case "application/llsd+json":
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleLLSDRequests(request, response);
return;
case "text/xml":
case "application/xml":
case "application/json":
default:
//m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
// Point of note.. the DoWeHaveA methods check for an EXACT path
// if (request.RawUrl.Contains("/CAPS/EQG"))
// {
// int i = 1;
// }
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
if (DoWeHaveALLSDHandler(request.RawUrl))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleLLSDRequests(request, response);
return;
}
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
if (DoWeHaveAHTTPHandler(request.RawUrl))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
HandleHTTPRequest(request, response);
return;
}
if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// generic login request.
HandleXmlRpcRequests(request, response);
return;
}
//response.FreeContext();
}
catch (SocketException e)
{
@@ -672,8 +637,8 @@ namespace OpenSim.Framework.Servers.HttpServer
finally
{
// Every month or so this will wrap and give bad numbers, not really a problem
// since its just for reporting, tickdiff limit can be adjusted
int tickdiff = Environment.TickCount - tickstart;
// since its just for reporting
int tickdiff = requestEndTick - requestStartTick;
if (tickdiff > 3000)
{
m_log.InfoFormat(
@@ -805,7 +770,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
private void HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
{
Stream requestStream = request.InputStream;
@@ -824,8 +789,23 @@ namespace OpenSim.Framework.Servers.HttpServer
{
xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody);
}
catch (XmlException)
catch (XmlException e)
{
if (DebugLevel >= 1)
{
if (DebugLevel >= 2)
m_log.Warn(
string.Format(
"[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}. XML was '{1}'. Sending blank response. Exception ",
request.RemoteIPEndPoint, requestBody),
e);
else
{
m_log.WarnFormat(
"[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}, length {1}. Sending blank response.",
request.RemoteIPEndPoint, requestBody.Length);
}
}
}
if (xmlRprcRequest != null)
@@ -895,6 +875,7 @@ namespace OpenSim.Framework.Servers.HttpServer
String.Format("Requested method [{0}] not found", methodName));
}
response.ContentType = "text/xml";
responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);
}
else
@@ -904,82 +885,25 @@ namespace OpenSim.Framework.Servers.HttpServer
response.StatusCode = 404;
response.StatusDescription = "Not Found";
response.ProtocolVersion = "HTTP/1.0";
byte[] buf = Encoding.UTF8.GetBytes("Not found");
responseString = "Not found";
response.KeepAlive = false;
m_log.ErrorFormat(
"[BASE HTTP SERVER]: Handler not found for http request {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
response.SendChunked = false;
response.ContentLength64 = buf.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buf, 0, buf.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
catch (IOException e)
{
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0} ", e.Message), e);
}
}
return;
//responseString = "Error";
}
}
response.ContentType = "text/xml";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
catch (IOException e)
{
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0} ", e.Message), e);
}
}
return buffer;
}
private void HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
{
//m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
Stream requestStream = request.InputStream;
@@ -1065,34 +989,7 @@ namespace OpenSim.Framework.Servers.HttpServer
response.ContentEncoding = Encoding.UTF8;
response.KeepAlive = true;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.Send();
response.OutputStream.Flush();
//response.FreeContext();
//response.OutputStream.Close();
}
catch (IOException e)
{
m_log.Warn(String.Format("[BASE HTTP SERVER]: LLSD IOException {0} ", e.Message), e);
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER]: LLSD issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
}
return buffer;
}
private byte[] BuildLLSDResponse(OSHttpRequest request, OSHttpResponse response, OSD llsdResponse)
@@ -1357,7 +1254,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
{
// m_log.DebugFormat(
// "[BASE HTTP SERVER]: HandleHTTPRequest for request to {0}, method {1}",
@@ -1367,15 +1264,14 @@ namespace OpenSim.Framework.Servers.HttpServer
{
case "OPTIONS":
response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
return;
return null;
default:
HandleContentVerbs(request, response);
return;
return HandleContentVerbs(request, response);
}
}
private void HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
private byte[] HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
{
// m_log.DebugFormat("[BASE HTTP SERVER]: HandleContentVerbs for request to {0}", request.RawUrl);
@@ -1391,6 +1287,8 @@ namespace OpenSim.Framework.Servers.HttpServer
// to display the form, or process it.
// a better way would be nifty.
byte[] buffer;
Stream requestStream = request.InputStream;
Encoding encoding = Encoding.UTF8;
@@ -1451,14 +1349,14 @@ namespace OpenSim.Framework.Servers.HttpServer
if (foundHandler)
{
Hashtable responsedata1 = requestprocessor(keysvals);
DoHTTPGruntWork(responsedata1,response);
buffer = DoHTTPGruntWork(responsedata1,response);
//SendHTML500(response);
}
else
{
// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found");
SendHTML404(response, host);
buffer = SendHTML404(response, host);
}
}
else
@@ -1468,16 +1366,18 @@ namespace OpenSim.Framework.Servers.HttpServer
if (foundHandler)
{
Hashtable responsedata2 = requestprocessor(keysvals);
DoHTTPGruntWork(responsedata2, response);
buffer = DoHTTPGruntWork(responsedata2, response);
//SendHTML500(response);
}
else
{
// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found2");
SendHTML404(response, host);
buffer = SendHTML404(response, host);
}
}
return buffer;
}
private bool TryGetHTTPHandlerPathBased(string path, out GenericHTTPMethod httpHandler)
@@ -1545,14 +1445,13 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
{
//m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
int responsecode = (int)responsedata["int_response_code"];
string responseString = (string)responsedata["str_response_string"];
string contentType = (string)responsedata["content_type"];
if (responsedata.ContainsKey("error_status_text"))
{
response.StatusDescription = (string)responsedata["error_status_text"];
@@ -1616,38 +1515,10 @@ namespace OpenSim.Framework.Servers.HttpServer
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[HTTPD]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
catch (IOException e)
{
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0} ", e.Message), e);
}
}
return buffer;
}
public void SendHTML404(OSHttpResponse response, string host)
public byte[] SendHTML404(OSHttpResponse response, string host)
{
// I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
response.StatusCode = 404;
@@ -1660,31 +1531,10 @@ namespace OpenSim.Framework.Servers.HttpServer
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
}
return buffer;
}
public void SendHTML500(OSHttpResponse response)
public byte[] SendHTML500(OSHttpResponse response)
{
// I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
@@ -1696,28 +1546,8 @@ namespace OpenSim.Framework.Servers.HttpServer
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
}
finally
{
//response.OutputStream.Close();
try
{
response.Send();
//response.FreeContext();
}
catch (SocketException e)
{
// This has to be here to prevent a Linux/Mono crash
m_log.Warn(String.Format("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
}
}
return buffer;
}
public void Start()
@@ -1727,6 +1557,9 @@ namespace OpenSim.Framework.Servers.HttpServer
private void StartHTTP()
{
m_log.InfoFormat(
"[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
try
{
//m_httpListener = new HttpListener();

View File

@@ -128,11 +128,5 @@ namespace OpenSim.Framework.Servers.HttpServer
/// <param name="value">string containing the header field
/// value</param>
void AddHeader(string key, string value);
/// <summary>
/// Send the response back to the remote client
/// </summary>
void Send();
}
}
}

View File

@@ -107,7 +107,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public bool IsSecured
{
get { return _context.Secured; }
get { return _context.IsSecured; }
}
public bool KeepAlive

View File

@@ -321,13 +321,12 @@ namespace OpenSim.Framework.Servers.HttpServer
{
_httpResponse.Body.Flush();
_httpResponse.Send();
}
public void FreeContext()
{
if (_httpClientContext != null)
_httpClientContext.Close();
}
}
}

View File

@@ -28,143 +28,252 @@
namespace OpenSim.Framework.Servers.HttpServer
{
/// <summary>
/// HTTP status codes (almost) as defined by W3C in
/// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
/// HTTP status codes (almost) as defined by W3C in http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html and IETF in http://tools.ietf.org/html/rfc6585
/// </summary>
public enum OSHttpStatusCode: int
public enum OSHttpStatusCode : int
{
// 1xx Informational status codes providing a provisional
// response.
// 100 Tells client that to keep on going sending its request
InfoContinue = 100,
// 101 Server understands request, proposes to switch to different
// application level protocol
InfoSwitchingProtocols = 101,
#region 1xx Informational status codes providing a provisional response.
/// <summary>
/// 100 Tells client that to keep on going sending its request
/// </summary>
InfoContinue = 100,
// 2xx Success codes
// 200 Request successful
SuccessOk = 200,
// 201 Request successful, new resource created
SuccessOkCreated = 201,
// 202 Request accepted, processing still on-going
SuccessOkAccepted = 202,
// 203 Request successful, meta information not authoritative
SuccessOkNonAuthoritativeInformation = 203,
// 204 Request successful, nothing to return in the body
SuccessOkNoContent = 204,
// 205 Request successful, reset displayed content
SuccessOkResetContent = 205,
// 206 Request successful, partial content returned
SuccessOkPartialContent = 206,
/// <summary>
/// 101 Server understands request, proposes to switch to different application level protocol
/// </summary>
InfoSwitchingProtocols = 101,
// 3xx Redirect code: user agent needs to go somewhere else
// 300 Redirect: different presentation forms available, take
// a pick
RedirectMultipleChoices = 300,
// 301 Redirect: requested resource has moved and now lives
// somewhere else
RedirectMovedPermanently = 301,
// 302 Redirect: Resource temporarily somewhere else, location
// might change
RedirectFound = 302,
// 303 Redirect: See other as result of a POST
RedirectSeeOther = 303,
// 304 Redirect: Resource still the same as before
RedirectNotModified = 304,
// 305 Redirect: Resource must be accessed via proxy provided
// in location field
RedirectUseProxy = 305,
// 307 Redirect: Resource temporarily somewhere else, location
// might change
RedirectMovedTemporarily = 307,
#endregion
// 4xx Client error: the client borked the request
// 400 Client error: bad request, server does not grok what
// the client wants
ClientErrorBadRequest = 400,
// 401 Client error: the client is not authorized, response
// provides WWW-Authenticate header field with a challenge
ClientErrorUnauthorized = 401,
// 402 Client error: Payment required (reserved for future use)
ClientErrorPaymentRequired = 402,
// 403 Client error: Server understood request, will not
// deliver, do not try again.
ClientErrorForbidden = 403,
// 404 Client error: Server cannot find anything matching the
// client request.
ClientErrorNotFound = 404,
// 405 Client error: The method specified by the client in the
// request is not allowed for the resource requested
ClientErrorMethodNotAllowed = 405,
// 406 Client error: Server cannot generate suitable response
// for the resource and content characteristics requested by
// the client
ClientErrorNotAcceptable = 406,
// 407 Client error: Similar to 401, Server requests that
// client authenticate itself with the proxy first
ClientErrorProxyAuthRequired = 407,
// 408 Client error: Server got impatient with client and
// decided to give up waiting for the client's request to
// arrive
ClientErrorRequestTimeout = 408,
// 409 Client error: Server could not fulfill the request for
// a resource as there is a conflict with the current state of
// the resource but thinks client can do something about this
ClientErrorConflict = 409,
// 410 Client error: The resource has moved somewhere else,
// but server has no clue where.
ClientErrorGone = 410,
// 411 Client error: The server is picky again and insists on
// having a content-length header field in the request
ClientErrorLengthRequired = 411,
// 412 Client error: one or more preconditions supplied in the
// client's request is false
ClientErrorPreconditionFailed = 412,
// 413 Client error: For fear of reflux, the server refuses to
// swallow that much data.
ClientErrorRequestEntityToLarge = 413,
// 414 Client error: The server considers the Request-URI to
// be indecently long and refuses to even look at it.
ClientErrorRequestURITooLong = 414,
// 415 Client error: The server has no clue about the media
// type requested by the client (contrary to popular belief it
// is not a warez server)
ClientErrorUnsupportedMediaType = 415,
// 416 Client error: The requested range cannot be delivered
// by the server.
#region 2xx Success codes
/// <summary>
/// 200 Request successful
/// </summary>
SuccessOk = 200,
/// <summary>
/// 201 Request successful, new resource created
/// </summary>
SuccessOkCreated = 201,
/// <summary>
/// 202 Request accepted, processing still on-going
/// </summary>
SuccessOkAccepted = 202,
/// <summary>
/// 203 Request successful, meta information not authoritative
/// </summary>
SuccessOkNonAuthoritativeInformation = 203,
/// <summary>
/// 204 Request successful, nothing to return in the body
/// </summary>
SuccessOkNoContent = 204,
/// <summary>
/// 205 Request successful, reset displayed content
/// </summary>
SuccessOkResetContent = 205,
/// <summary>
/// 206 Request successful, partial content returned
/// </summary>
SuccessOkPartialContent = 206,
#endregion
#region 3xx Redirect code: user agent needs to go somewhere else
/// <summary>
/// 300 Redirect: different presentation forms available, take a pick
/// </summary>
RedirectMultipleChoices = 300,
/// <summary>
/// 301 Redirect: requested resource has moved and now lives somewhere else
/// </summary>
RedirectMovedPermanently = 301,
/// <summary>
/// 302 Redirect: Resource temporarily somewhere else, location might change
/// </summary>
RedirectFound = 302,
/// <summary>
/// 303 Redirect: See other as result of a POST
/// </summary>
RedirectSeeOther = 303,
/// <summary>
/// 304 Redirect: Resource still the same as before
/// </summary>
RedirectNotModified = 304,
/// <summary>
/// 305 Redirect: Resource must be accessed via proxy provided in location field
/// </summary>
RedirectUseProxy = 305,
/// <summary>
/// 307 Redirect: Resource temporarily somewhere else, location might change
/// </summary>
RedirectMovedTemporarily = 307,
#endregion
#region 4xx Client error: the client borked the request
/// <summary>
/// 400 Client error: bad request, server does not grok what the client wants
/// </summary>
ClientErrorBadRequest = 400,
/// <summary>
/// 401 Client error: the client is not authorized, response provides WWW-Authenticate header field with a challenge
/// </summary>
ClientErrorUnauthorized = 401,
/// <summary>
/// 402 Client error: Payment required (reserved for future use)
/// </summary>
ClientErrorPaymentRequired = 402,
/// <summary>
/// 403 Client error: Server understood request, will not deliver, do not try again.
ClientErrorForbidden = 403,
/// <summary>
/// 404 Client error: Server cannot find anything matching the client request.
/// </summary>
ClientErrorNotFound = 404,
/// <summary>
/// 405 Client error: The method specified by the client in the request is not allowed for the resource requested
/// </summary>
ClientErrorMethodNotAllowed = 405,
/// <summary>
/// 406 Client error: Server cannot generate suitable response for the resource and content characteristics requested by the client
/// </summary>
ClientErrorNotAcceptable = 406,
/// <summary>
/// 407 Client error: Similar to 401, Server requests that client authenticate itself with the proxy first
/// </summary>
ClientErrorProxyAuthRequired = 407,
/// <summary>
/// 408 Client error: Server got impatient with client and decided to give up waiting for the client's request to arrive
/// </summary>
ClientErrorRequestTimeout = 408,
/// <summary>
/// 409 Client error: Server could not fulfill the request for a resource as there is a conflict with the current state of the resource but thinks client can do something about this
/// </summary>
ClientErrorConflict = 409,
/// <summary>
/// 410 Client error: The resource has moved somewhere else, but server has no clue where.
/// </summary>
ClientErrorGone = 410,
/// <summary>
/// 411 Client error: The server is picky again and insists on having a content-length header field in the request
/// </summary>
ClientErrorLengthRequired = 411,
/// <summary>
/// 412 Client error: one or more preconditions supplied in the client's request is false
/// </summary>
ClientErrorPreconditionFailed = 412,
/// <summary>
/// 413 Client error: For fear of reflux, the server refuses to swallow that much data.
/// </summary>
ClientErrorRequestEntityToLarge = 413,
/// <summary>
/// 414 Client error: The server considers the Request-URI to be indecently long and refuses to even look at it.
/// </summary>
ClientErrorRequestURITooLong = 414,
/// <summary>
/// 415 Client error: The server has no clue about the media type requested by the client (contrary to popular belief it is not a warez server)
/// </summary>
ClientErrorUnsupportedMediaType = 415,
/// <summary>
/// 416 Client error: The requested range cannot be delivered by the server.
/// </summary>
ClientErrorRequestRangeNotSatisfiable = 416,
// 417 Client error: The expectations of the client as
// expressed in one or more Expect header fields cannot be met
// by the server, the server is awfully sorry about this.
ClientErrorExpectationFailed = 417,
// 499 Client error: Wildcard error.
ClientErrorJoker = 499,
// 5xx Server errors (rare)
// 500 Server error: something really strange and unexpected
// happened
ServerErrorInternalError = 500,
// 501 Server error: The server does not do the functionality
// required to carry out the client request. not at
// all. certainly not before breakfast. but also not after
// breakfast.
ServerErrorNotImplemented = 501,
// 502 Server error: While acting as a proxy or a gateway, the
// server got ditched by the upstream server and as a
// consequence regretfully cannot fulfill the client's request
ServerErrorBadGateway = 502,
// 503 Server error: Due to unforseen circumstances the server
// cannot currently deliver the service requested. Retry-After
// header might indicate when to try again.
ServerErrorServiceUnavailable = 503,
// 504 Server error: The server blames the upstream server
// for not being able to deliver the service requested and
// claims that the upstream server is too slow delivering the
// goods.
ServerErrorGatewayTimeout = 504,
// 505 Server error: The server does not support the HTTP
// version conveyed in the client's request.
ServerErrorHttpVersionNotSupported = 505,
/// <summary>
/// 417 Client error: The expectations of the client as expressed in one or more Expect header fields cannot be met by the server, the server is awfully sorry about this.
/// </summary>
ClientErrorExpectationFailed = 417,
/// <summary>
/// 428 Client error :The 428 status code indicates that the origin server requires the request to be conditional.
/// </summary>
ClientErrorPreconditionRequired = 428,
/// <summary>
/// 429 Client error: The 429 status code indicates that the user has sent too many requests in a given amount of time ("rate limiting").
/// </summary>
ClientErrorTooManyRequests = 429,
/// <summary>
/// 431 Client error: The 431 status code indicates that the server is unwilling to process the request because its header fields are too large. The request MAY be resubmitted after reducing the size of the request header fields.
/// </summary>
ClientErrorRequestHeaderFieldsTooLarge = 431,
/// <summary>
/// 499 Client error: Wildcard error.
/// </summary>
ClientErrorJoker = 499,
#endregion
#region 5xx Server errors (rare)
/// <summary>
/// 500 Server error: something really strange and unexpected happened
/// </summary>
ServerErrorInternalError = 500,
/// <summary>
/// 501 Server error: The server does not do the functionality required to carry out the client request. not at all. certainly not before breakfast. but also not after breakfast.
/// </summary>
ServerErrorNotImplemented = 501,
/// <summary>
/// 502 Server error: While acting as a proxy or a gateway, the server got ditched by the upstream server and as a consequence regretfully cannot fulfill the client's request
/// </summary>
ServerErrorBadGateway = 502,
/// <summary>
/// 503 Server error: Due to unforseen circumstances the server cannot currently deliver the service requested. Retry-After header might indicate when to try again.
/// </summary>
ServerErrorServiceUnavailable = 503,
/// <summary>
/// 504 Server error: The server blames the upstream server for not being able to deliver the service requested and claims that the upstream server is too slow delivering the goods.
/// </summary>
ServerErrorGatewayTimeout = 504,
/// <summary>
/// 505 Server error: The server does not support the HTTP version conveyed in the client's request.
/// </summary>
ServerErrorHttpVersionNotSupported = 505,
/// <summary>
/// 511 Server error: The 511 status code indicates that the client needs to authenticate to gain network access.
/// </summary>
ServerErrorNetworkAuthenticationRequired = 511,
#endregion
}
}

View File

@@ -28,6 +28,7 @@
using System;
using System.Collections;
using OpenMetaverse;
namespace OpenSim.Framework.Servers.HttpServer
{
public delegate void RequestMethod(UUID requestID, Hashtable request);
@@ -44,7 +45,11 @@ namespace OpenSim.Framework.Servers.HttpServer
public NoEventsMethod NoEvents;
public RequestMethod Request;
public UUID Id;
public PollServiceEventArgs(RequestMethod pRequest, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId)
public PollServiceEventArgs(
RequestMethod pRequest,
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
UUID pId)
{
Request = pRequest;
HasEvents = pHasEvents;
@@ -53,4 +58,4 @@ namespace OpenSim.Framework.Servers.HttpServer
Id = pId;
}
}
}
}

View File

@@ -31,7 +31,6 @@ using OpenMetaverse;
namespace OpenSim.Framework.Servers.HttpServer
{
public class PollServiceHttpRequest
{
public readonly PollServiceEventArgs PollServiceArgs;
@@ -39,7 +38,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public readonly IHttpRequest Request;
public readonly int RequestTime;
public readonly UUID RequestID;
public PollServiceHttpRequest(PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
public PollServiceHttpRequest(
PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
{
PollServiceArgs = pPollServiceArgs;
HttpContext = pHttpContext;
@@ -48,4 +49,4 @@ namespace OpenSim.Framework.Servers.HttpServer
RequestID = UUID.Random();
}
}
}
}

View File

@@ -66,6 +66,7 @@ namespace OpenSim.Framework.Servers.HttpServer
ThreadPriority.Normal,
false,
true,
null,
int.MaxValue);
}
@@ -75,6 +76,7 @@ namespace OpenSim.Framework.Servers.HttpServer
ThreadPriority.Normal,
false,
true,
null,
1000 * 60 * 10);
}
@@ -138,9 +140,8 @@ namespace OpenSim.Framework.Servers.HttpServer
foreach (object o in m_requests)
{
PollServiceHttpRequest req = (PollServiceHttpRequest) o;
m_server.DoHTTPGruntWork(
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
PollServiceWorkerThread.DoHTTPGruntWork(
m_server, req, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
m_requests.Clear();
@@ -149,6 +150,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
t.Abort();
}
m_running = false;
}
}

View File

@@ -90,15 +90,16 @@ namespace OpenSim.Framework.Servers.HttpServer
}
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
m_server.DoHTTPGruntWork(responsedata,
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
DoHTTPGruntWork(m_server, req, responsedata);
}
else
{
if ((Environment.TickCount - req.RequestTime) > m_timeout)
{
m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
DoHTTPGruntWork(
m_server,
req,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
else
{
@@ -119,5 +120,45 @@ namespace OpenSim.Framework.Servers.HttpServer
{
m_request.Enqueue(pPollServiceHttpRequest);
}
/// <summary>
/// FIXME: This should be part of BaseHttpServer
/// </summary>
internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
{
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (Exception e)
{
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
}
}
}
}
}
}

View File

@@ -25,57 +25,209 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Net;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.Framework.Servers
{
public class MainServer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static BaseHttpServer instance = null;
private static Dictionary<uint, BaseHttpServer> m_Servers =
new Dictionary<uint, BaseHttpServer>();
private static Dictionary<uint, BaseHttpServer> m_Servers = new Dictionary<uint, BaseHttpServer>();
/// <summary>
/// Control the printing of certain debug messages.
/// </summary>
/// <remarks>
/// If DebugLevel >= 1, then short warnings are logged when receiving bad input data.
/// If DebugLevel >= 2, then long warnings are logged when receiving bad input data.
/// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged.
/// </remarks>
public static int DebugLevel
{
get { return s_debugLevel; }
set
{
s_debugLevel = value;
lock (m_Servers)
foreach (BaseHttpServer server in m_Servers.Values)
server.DebugLevel = s_debugLevel;
}
}
private static int s_debugLevel;
/// <summary>
/// Set the main HTTP server instance.
/// </summary>
/// <remarks>
/// This will be used to register all handlers that listen to the default port.
/// </remarks>
/// <exception cref='Exception'>
/// Thrown if the HTTP server has not already been registered via AddHttpServer()
/// </exception>
public static BaseHttpServer Instance
{
get { return instance; }
set { instance = value; }
set
{
lock (m_Servers)
if (!m_Servers.ContainsValue(value))
throw new Exception("HTTP server must already have been registered to be set as the main instance");
instance = value;
}
}
public static IHttpServer GetHttpServer(uint port)
/// <summary>
/// Get all the registered servers.
/// </summary>
/// <remarks>
/// Returns a copy of the dictionary so this can be iterated through without locking.
/// </remarks>
/// <value></value>
public static Dictionary<uint, BaseHttpServer> Servers
{
return GetHttpServer(port,null);
get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
}
public static void RegisterHttpConsoleCommands(ICommandConsole console)
{
console.Commands.AddCommand(
"Debug", false, "debug http", "debug http [<level>]",
"Turn on inbound non-poll http request debugging.",
"If level <= 0, then no extra logging is done.\n"
+ "If level >= 1, then short warnings are logged when receiving bad input data.\n"
+ "If level >= 2, then long warnings are logged when receiving bad input data.\n"
+ "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
+ "If no level is specified then the current level is returned.",
HandleDebugHttpCommand);
}
/// <summary>
/// Turn on some debugging values for OpenSim.
/// </summary>
/// <param name="args"></param>
private static void HandleDebugHttpCommand(string module, string[] args)
{
if (args.Length == 3)
{
int newDebug;
if (int.TryParse(args[2], out newDebug))
{
MainServer.DebugLevel = newDebug;
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
}
}
else if (args.Length == 2)
{
MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel);
}
else
{
MainConsole.Instance.Output("Usage: debug http 0..3");
}
}
/// <summary>
/// Register an already started HTTP server to the collection of known servers.
/// </summary>
/// <param name='server'></param>
public static void AddHttpServer(BaseHttpServer server)
{
m_Servers.Add(server.Port, server);
lock (m_Servers)
{
if (m_Servers.ContainsKey(server.Port))
throw new Exception(string.Format("HTTP server for port {0} already exists.", server.Port));
m_Servers.Add(server.Port, server);
}
}
/// <summary>
/// Removes the http server listening on the given port.
/// </summary>
/// <remarks>
/// It is the responsibility of the caller to do clean up.
/// </remarks>
/// <param name='port'></param>
/// <returns></returns>
public static bool RemoveHttpServer(uint port)
{
lock (m_Servers)
return m_Servers.Remove(port);
}
/// <summary>
/// Does this collection of servers contain one with the given port?
/// </summary>
/// <remarks>
/// Unlike GetHttpServer, this will not instantiate a server if one does not exist on that port.
/// </remarks>
/// <param name='port'></param>
/// <returns>true if a server with the given port is registered, false otherwise.</returns>
public static bool ContainsHttpServer(uint port)
{
lock (m_Servers)
return m_Servers.ContainsKey(port);
}
/// <summary>
/// Get the default http server or an http server for a specific port.
/// </summary>
/// <remarks>
/// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
/// </remarks>
/// <returns></returns>
/// <param name='port'>If 0 then the default HTTP server is returned.</param>
public static IHttpServer GetHttpServer(uint port)
{
return GetHttpServer(port, null);
}
/// <summary>
/// Get the default http server, an http server for a specific port
/// and/or an http server bound to a specific address
/// </summary>
/// <remarks>
/// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
/// </remarks>
/// <returns></returns>
/// <param name='port'>If 0 then the default HTTP server is returned.</param>
/// <param name='ipaddr'>A specific IP address to bind to. If null then the default IP address is used.</param>
public static IHttpServer GetHttpServer(uint port, IPAddress ipaddr)
{
if (port == 0)
return Instance;
if (instance != null && port == Instance.Port)
return Instance;
if (m_Servers.ContainsKey(port))
lock (m_Servers)
{
if (m_Servers.ContainsKey(port))
return m_Servers[port];
m_Servers[port] = new BaseHttpServer(port);
if (ipaddr != null)
m_Servers[port].ListenIPAddress = ipaddr;
m_Servers[port].Start();
return m_Servers[port];
m_Servers[port] = new BaseHttpServer(port);
if (ipaddr != null)
m_Servers[port].ListenIPAddress = ipaddr;
m_log.InfoFormat("[MAIN HTTP SERVER]: Starting main http server on port {0}", port);
m_Servers[port].Start();
return m_Servers[port];
}
}
}
}
}

View File

@@ -34,14 +34,12 @@ namespace OpenSim.Framework.Statistics
{
private static AssetStatsCollector assetStats;
private static UserStatsCollector userStats;
private static SimExtraStatsCollector simExtraStats;
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
public static AssetStatsCollector AssetStats { get { return assetStats; } }
public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
private StatsManager() {}
/// <summary>
/// Start collecting statistics related to assets.
/// Should only be called once.
@@ -63,16 +61,5 @@ namespace OpenSim.Framework.Statistics
return userStats;
}
/// <summary>
/// Start collecting extra sim statistics apart from those collected for the client.
/// Should only be called once.
/// </summary>
public static SimExtraStatsCollector StartCollectingSimExtraStats()
{
simExtraStats = new SimExtraStatsCollector();
return simExtraStats;
}
}
}
}

View File

@@ -73,6 +73,9 @@ namespace OpenSim.Framework
private bool _ownerChanged = false;
// This used ONLY during copy. It can't be relied on at other times!
private bool _scriptRunning = true;
public UUID AssetID {
get {
return _assetID;
@@ -350,6 +353,15 @@ namespace OpenSim.Framework
}
}
public bool ScriptRunning {
get {
return _scriptRunning;
}
set {
_scriptRunning = value;
}
}
// See ICloneable
#region ICloneable Members

View File

@@ -148,6 +148,7 @@ namespace OpenSim.Framework
}
public static Encoding UTF8 = Encoding.UTF8;
public static Encoding UTF8NoBomEncoding = new UTF8Encoding(false);
/// <value>
/// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
@@ -1236,8 +1237,7 @@ namespace OpenSim.Framework
public static string Base64ToString(string str)
{
UTF8Encoding encoder = new UTF8Encoding();
Decoder utf8Decode = encoder.GetDecoder();
Decoder utf8Decode = Encoding.UTF8.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(str);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);

View File

@@ -41,8 +41,8 @@ namespace OpenSim.Framework
/// <summary>Timer interval in milliseconds for the watchdog timer</summary>
const double WATCHDOG_INTERVAL_MS = 2500.0d;
/// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary>
const int WATCHDOG_TIMEOUT_MS = 5000;
/// <summary>Default timeout in milliseconds before a thread is considered dead</summary>
public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000;
[System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
public class ThreadWatchdogInfo
@@ -58,7 +58,7 @@ namespace OpenSim.Framework
public int FirstTick { get; private set; }
/// <summary>
/// First time this heartbeat update was invoked
/// Last time this heartbeat update was invoked
/// </summary>
public int LastTick { get; set; }
@@ -77,6 +77,11 @@ namespace OpenSim.Framework
/// </summary>
public bool AlarmIfTimeout { get; set; }
/// <summary>
/// Method execute if alarm goes off. If null then no alarm method is fired.
/// </summary>
public Func<string> AlarmMethod { get; set; }
public ThreadWatchdogInfo(Thread thread, int timeout)
{
Thread = thread;
@@ -87,27 +92,33 @@ namespace OpenSim.Framework
}
/// <summary>
/// This event is called whenever a tracked thread is stopped or
/// has not called UpdateThread() in time
/// </summary>
/// <param name="thread">The thread that has been identified as dead</param>
/// <param name="lastTick">The last time this thread called UpdateThread()</param>
public delegate void WatchdogTimeout(Thread thread, int lastTick);
/// <summary>This event is called whenever a tracked thread is
/// stopped or has not called UpdateThread() in time</summary>
public static event WatchdogTimeout OnWatchdogTimeout;
/// This event is called whenever a tracked thread is
/// stopped or has not called UpdateThread() in time<
/// /summary>
public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<int, ThreadWatchdogInfo> m_threads;
private static System.Timers.Timer m_watchdogTimer;
/// <summary>
/// Last time the watchdog thread ran.
/// </summary>
/// <remarks>
/// Should run every WATCHDOG_INTERVAL_MS
/// </remarks>
public static int LastWatchdogThreadTick { get; private set; }
static Watchdog()
{
m_threads = new Dictionary<int, ThreadWatchdogInfo>();
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
m_watchdogTimer.AutoReset = false;
m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
m_watchdogTimer.Start();
}
@@ -123,7 +134,7 @@ namespace OpenSim.Framework
public static Thread StartThread(
ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
{
return StartThread(start, name, priority, isBackground, alarmIfTimeout, WATCHDOG_TIMEOUT_MS);
return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS);
}
/// <summary>
@@ -135,17 +146,24 @@ namespace OpenSim.Framework
/// <param name="isBackground">True to run this thread as a background
/// thread, otherwise false</param>
/// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
/// <param name="alarmMethod">
/// Alarm method to call if alarmIfTimeout is true and there is a timeout.
/// Normally, this will just return some useful debugging information.
/// </param>
/// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param>
/// <returns>The newly created Thread object</returns>
public static Thread StartThread(
ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, int timeout)
ThreadStart start, string name, ThreadPriority priority, bool isBackground,
bool alarmIfTimeout, Func<string> alarmMethod, int timeout)
{
Thread thread = new Thread(start);
thread.Name = name;
thread.Priority = priority;
thread.IsBackground = isBackground;
ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout) { AlarmIfTimeout = alarmIfTimeout };
ThreadWatchdogInfo twi
= new ThreadWatchdogInfo(thread, timeout)
{ AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
m_log.DebugFormat(
"[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
@@ -258,7 +276,17 @@ namespace OpenSim.Framework
/// <param name="e"></param>
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
WatchdogTimeout callback = OnWatchdogTimeout;
int now = Environment.TickCount & Int32.MaxValue;
int msElapsed = now - LastWatchdogThreadTick;
if (msElapsed > WATCHDOG_INTERVAL_MS * 2)
m_log.WarnFormat(
"[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms",
msElapsed, WATCHDOG_INTERVAL_MS);
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
Action<ThreadWatchdogInfo> callback = OnWatchdogTimeout;
if (callback != null)
{
@@ -266,8 +294,6 @@ namespace OpenSim.Framework
lock (m_threads)
{
int now = Environment.TickCount & Int32.MaxValue;
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
{
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
@@ -296,7 +322,7 @@ namespace OpenSim.Framework
if (callbackInfos != null)
foreach (ThreadWatchdogInfo callbackInfo in callbackInfos)
callback(callbackInfo.Thread, callbackInfo.LastTick);
callback(callbackInfo);
}
m_watchdogTimer.Start();

View File

@@ -92,9 +92,14 @@ namespace OpenSim
m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
}
m_log.DebugFormat(
m_log.InfoFormat(
"[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture);
string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU");
m_log.InfoFormat(
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
int workerThreads, iocpThreads;
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
@@ -109,7 +114,6 @@ namespace OpenSim
// Check if the system is compatible with OpenSimulator.
// Ensures that the minimum system requirements are met
m_log.Info("Performing compatibility checks... \n");
string supported = String.Empty;
if (Util.IsEnvironmentSupported(ref supported))
{

View File

@@ -28,6 +28,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
@@ -69,6 +70,7 @@ namespace OpenSim
private Regex m_consolePromptRegex = new Regex(@"([^\\])\\(\w)", RegexOptions.Compiled);
private string m_timedScript = "disabled";
private int m_timeInterval = 1200;
private Timer m_scriptTimer;
public OpenSim(IConfigSource configSource) : base(configSource)
@@ -98,6 +100,10 @@ namespace OpenSim
m_consolePort = (uint)networkConfig.GetInt("console_port", 0);
m_timedScript = startupConfig.GetString("timer_Script", "disabled");
if (m_timedScript != "disabled")
{
m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
}
if (m_logFileAppender != null)
{
@@ -138,7 +144,7 @@ namespace OpenSim
m_log.Info("====================================================================");
m_log.Info("========================= STARTING OPENSIM =========================");
m_log.Info("====================================================================");
//m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString());
// http://msdn.microsoft.com/en-us/library/bb384202.aspx
//GCSettings.LatencyMode = GCLatencyMode.Batch;
@@ -215,7 +221,7 @@ namespace OpenSim
{
m_scriptTimer = new Timer();
m_scriptTimer.Enabled = true;
m_scriptTimer.Interval = 1200*1000;
m_scriptTimer.Interval = m_timeInterval*1000;
m_scriptTimer.Elapsed += RunAutoTimerScript;
}
}
@@ -225,12 +231,14 @@ namespace OpenSim
/// </summary>
private void RegisterConsoleCommands()
{
MainServer.RegisterHttpConsoleCommands(m_console);
m_console.Commands.AddCommand("Objects", false, "force update",
"force update",
"Force the update of all objects on clients",
HandleForceUpdate);
m_console.Commands.AddCommand("Comms", false, "debug packet",
m_console.Commands.AddCommand("Debug", false, "debug packet",
"debug packet <level> [<avatar-first-name> <avatar-last-name>]",
"Turn on packet debugging",
"If level > 255 then all incoming and outgoing packets are logged.\n"
@@ -242,17 +250,9 @@ namespace OpenSim
+ "If an avatar name is given then only packets from that avatar are logged",
Debug);
m_console.Commands.AddCommand("Comms", false, "debug http",
"debug http <level>",
"Turn on inbound http request debugging for everything except the event queue (see debug eq).",
"If level >= 2 then the handler used to service the request is logged.\n"
+ "If level >= 1 then incoming HTTP requests are logged.\n"
+ "If level <= 0 then no extra http logging is done.\n",
Debug);
m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
m_console.Commands.AddCommand("Comms", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
m_console.Commands.AddCommand("Regions", false, "debug scene",
m_console.Commands.AddCommand("Debug", false, "debug scene",
"debug scene <scripting> <collisions> <physics>",
"Turn on scene debugging", Debug);
@@ -409,10 +409,6 @@ namespace OpenSim
m_console.Commands.AddCommand("General", false, "modules unload",
"modules unload <name>",
"Unload a module", HandleModules);
m_console.Commands.AddCommand("Objects", false, "kill uuid",
"kill uuid <UUID>",
"Kill an object by UUID", KillUUID);
}
public override void ShutdownSpecific()
@@ -437,12 +433,16 @@ namespace OpenSim
}
}
private void WatchdogTimeoutHandler(System.Threading.Thread thread, int lastTick)
private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi)
{
int now = Environment.TickCount & Int32.MaxValue;
m_log.ErrorFormat("[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago",
thread.Name, thread.ThreadState, now - lastTick);
m_log.ErrorFormat(
"[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}",
twi.Thread.Name,
twi.Thread.ThreadState,
now - twi.LastTick,
twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : "");
}
#region Console Commands
@@ -481,10 +481,10 @@ namespace OpenSim
else
presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
// ...and close on our side
presence.Scene.IncomingCloseAgent(presence.UUID);
}
}
MainConsole.Instance.Output("");
}
@@ -904,21 +904,6 @@ namespace OpenSim
break;
case "http":
if (args.Length == 3)
{
int newDebug;
if (int.TryParse(args[2], out newDebug))
{
MainServer.Instance.DebugLevel = newDebug;
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
break;
}
}
MainConsole.Instance.Output("Usage: debug http 0..2");
break;
case "scene":
if (args.Length == 4)
{
@@ -970,8 +955,7 @@ namespace OpenSim
if (showParams.Length > 1 && showParams[1] == "full")
{
agents = m_sceneManager.GetCurrentScenePresences();
}
else
} else
{
agents = m_sceneManager.GetCurrentSceneAvatars();
}
@@ -980,7 +964,8 @@ namespace OpenSim
MainConsole.Instance.Output(
String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname",
"Agent ID", "Root/Child", "Region", "Position"));
"Agent ID", "Root/Child", "Region", "Position")
);
foreach (ScenePresence presence in agents)
{
@@ -990,8 +975,7 @@ namespace OpenSim
if (regionInfo == null)
{
regionName = "Unresolvable";
}
else
} else
{
regionName = regionInfo.RegionName;
}
@@ -1004,43 +988,19 @@ namespace OpenSim
presence.UUID,
presence.IsChildAgent ? "Child" : "Root",
regionName,
presence.AbsolutePosition.ToString()));
presence.AbsolutePosition.ToString())
);
}
MainConsole.Instance.Output(String.Empty);
break;
case "connections":
System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n");
m_sceneManager.ForEachScene(
delegate(Scene scene)
{
scene.ForEachClient(
delegate(IClientAPI client)
{
connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode);
}
);
}
);
MainConsole.Instance.Output(connections.ToString());
HandleShowConnections();
break;
case "circuits":
System.Text.StringBuilder acd = new System.Text.StringBuilder("Agent Circuits:\n");
m_sceneManager.ForEachScene(
delegate(Scene scene)
{
//this.HttpServer.
acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName);
foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values)
acd.AppendFormat("\t{0} {1} ({2})\n", aCircuit.firstname, aCircuit.lastname, (aCircuit.child ? "Child" : "Root"));
}
);
MainConsole.Instance.Output(acd.ToString());
HandleShowCircuits();
break;
case "http-handlers":
@@ -1078,17 +1038,29 @@ namespace OpenSim
}
m_sceneManager.ForEachScene(
delegate(Scene scene)
delegate(Scene scene) {
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModule module in scene.Modules.Values)
{
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModule module in scene.Modules.Values)
if (!module.IsSharedModule)
{
if (!module.IsSharedModule)
{
m_log.Error("Region Module: " + module.Name);
}
m_log.Error("Region Module: " + module.Name);
}
});
}
}
);
m_sceneManager.ForEachScene(
delegate(Scene scene) {
MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModuleBase module in scene.RegionModules.Values)
{
Type type = module.GetType().GetInterface("ISharedRegionModule");
string module_type = type != null ? "Shared" : "Non-Shared";
MainConsole.Instance.OutputFormat("New Region Module ({0}): {1}", module_type, module.Name);
}
}
);
MainConsole.Instance.Output("");
break;
@@ -1133,6 +1105,53 @@ namespace OpenSim
}
}
private void HandleShowCircuits()
{
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
cdt.AddColumn("Region", 20);
cdt.AddColumn("Avatar name", 24);
cdt.AddColumn("Type", 5);
cdt.AddColumn("Code", 10);
cdt.AddColumn("IP", 16);
cdt.AddColumn("Viewer Name", 24);
m_sceneManager.ForEachScene(
s =>
{
foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
cdt.AddRow(
s.Name,
aCircuit.Name,
aCircuit.child ? "child" : "root",
aCircuit.circuitcode.ToString(),
aCircuit.IPAddress.ToString(),
aCircuit.Viewer);
});
MainConsole.Instance.Output(cdt.ToString());
}
private void HandleShowConnections()
{
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
cdt.AddColumn("Region", 20);
cdt.AddColumn("Avatar name", 24);
cdt.AddColumn("Circuit code", 12);
cdt.AddColumn("Endpoint", 23);
cdt.AddColumn("Active?", 7);
m_sceneManager.ForEachScene(
s => s.ForEachClient(
c => cdt.AddRow(
s.Name,
c.Name,
c.RemoteEndPoint.ToString(),
c.CircuitCode.ToString(),
c.IsActive.ToString())));
MainConsole.Instance.Output(cdt.ToString());
}
/// <summary>
/// Use XML2 format to serialize data to a file
/// </summary>
@@ -1300,58 +1319,6 @@ namespace OpenSim
return result;
}
/// <summary>
/// Kill an object given its UUID.
/// </summary>
/// <param name="cmdparams"></param>
protected void KillUUID(string module, string[] cmdparams)
{
if (cmdparams.Length > 2)
{
UUID id = UUID.Zero;
SceneObjectGroup grp = null;
Scene sc = null;
if (!UUID.TryParse(cmdparams[2], out id))
{
MainConsole.Instance.Output("[KillUUID]: Error bad UUID format!");
return;
}
m_sceneManager.ForEachScene(
delegate(Scene scene)
{
SceneObjectPart part = scene.GetSceneObjectPart(id);
if (part == null)
return;
grp = part.ParentGroup;
sc = scene;
});
if (grp == null)
{
MainConsole.Instance.Output(String.Format("[KillUUID]: Given UUID {0} not found!", id));
}
else
{
MainConsole.Instance.Output(String.Format("[KillUUID]: Found UUID {0} in scene {1}", id, sc.RegionInfo.RegionName));
try
{
sc.DeleteSceneObject(grp, false);
}
catch (Exception e)
{
m_log.ErrorFormat("[KillUUID]: Error while removing objects from scene: " + e);
}
}
}
else
{
MainConsole.Instance.Output("[KillUUID]: Usage: kill uuid <UUID>");
}
}
#endregion
}
}

View File

@@ -223,7 +223,7 @@ namespace OpenSim
base.StartupSpecific();
m_stats = StatsManager.StartCollectingSimExtraStats();
m_stats = StatsManager.SimExtraStats;
// Create a ModuleLoader instance
m_moduleLoader = new ModuleLoader(m_config.Source);

View File

@@ -106,13 +106,14 @@ namespace OpenSim.Region.ClientStack.Linden
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
MainConsole.Instance.Commands.AddCommand(
"Comms",
"Debug",
false,
"debug eq",
"debug eq [0|1]",
"Turn on event queue debugging",
"debug eq 1 will turn on event queue debugging. This will log all outgoing event queue messages to clients.\n"
+ "debug eq 0 will turn off event queue debugging.",
"debug eq [0|1|2]",
"Turn on event queue debugging"
+ "<= 0 - turns off all event queue logging"
+ ">= 1 - turns on outgoing event logging"
+ ">= 2 - turns on poll notification",
HandleDebugEq);
}
else
@@ -235,19 +236,19 @@ namespace OpenSim.Region.ClientStack.Linden
// ClientClosed(client.AgentId);
// }
private void ClientClosed(UUID AgentID, Scene scene)
private void ClientClosed(UUID agentID, Scene scene)
{
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
int count = 0;
while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
while (queues.ContainsKey(agentID) && queues[agentID].Count > 0 && count++ < 5)
{
Thread.Sleep(1000);
}
lock (queues)
{
queues.Remove(AgentID);
queues.Remove(agentID);
}
List<UUID> removeitems = new List<UUID>();
@@ -256,7 +257,7 @@ namespace OpenSim.Region.ClientStack.Linden
foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
{
// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
if (ky == AgentID)
if (ky == agentID)
{
removeitems.Add(ky);
}
@@ -267,7 +268,12 @@ namespace OpenSim.Region.ClientStack.Linden
UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
m_AvatarQueueUUIDMapping.Remove(ky);
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + eventQueueGetUuid.ToString() + "/");
string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
// eqgPath, agentID, m_scene.RegionInfo.RegionName);
}
}
@@ -281,7 +287,7 @@ namespace OpenSim.Region.ClientStack.Linden
{
searchval = m_QueueUUIDAvatarMapping[ky];
if (searchval == AgentID)
if (searchval == agentID)
{
removeitems.Add(ky);
}
@@ -305,6 +311,15 @@ namespace OpenSim.Region.ClientStack.Linden
//}
}
/// <summary>
/// Generate an Event Queue Get handler path for the given eqg uuid.
/// </summary>
/// <param name='eqgUuid'></param>
private string GenerateEqgCapPath(UUID eqgUuid)
{
return string.Format("/CAPS/EQG/{0}/", eqgUuid);
}
public void OnRegisterCaps(UUID agentID, Caps caps)
{
// Register an event queue for the client
@@ -316,8 +331,7 @@ namespace OpenSim.Region.ClientStack.Linden
// Let's instantiate a Queue for this agent right now
TryGetQueue(agentID);
string capsBase = "/CAPS/EQG/";
UUID EventQueueGetUUID = UUID.Zero;
UUID eventQueueGetUUID;
lock (m_AvatarQueueUUIDMapping)
{
@@ -325,37 +339,35 @@ namespace OpenSim.Region.ClientStack.Linden
if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
{
//m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
}
else
{
EventQueueGetUUID = UUID.Random();
eventQueueGetUUID = UUID.Random();
//m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
}
}
lock (m_QueueUUIDAvatarMapping)
{
if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID))
m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID);
if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID))
m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID);
}
lock (m_AvatarQueueUUIDMapping)
{
if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID);
m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
}
string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID);
// Register this as a caps handler
// FIXME: Confusingly, we need to register separate as a capability so that the client is told about
// EventQueueGet when it receive capability information, but then we replace the rest handler immediately
// afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
// really it should be possible to directly register the poll handler as a capability.
caps.RegisterHandler(
"EventQueueGet",
new RestHTTPHandler(
"POST", capsBase + EventQueueGetUUID.ToString() + "/", null));
caps.RegisterHandler("EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null));
// delegate(Hashtable m_dhttpMethod)
// {
// return ProcessQueue(m_dhttpMethod, agentID, caps);
@@ -364,9 +376,13 @@ namespace OpenSim.Region.ClientStack.Linden
// This will persist this beyond the expiry of the caps handlers
// TODO: Add EventQueueGet name/description for diagnostics
MainServer.Instance.AddPollServiceHTTPHandler(
capsBase + EventQueueGetUUID.ToString() + "/",
eventQueueGetPath,
new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
Random rnd = new Random(Environment.TickCount);
lock (m_ids)
{
@@ -388,9 +404,25 @@ namespace OpenSim.Region.ClientStack.Linden
return false;
}
/// <summary>
/// Logs a debug line for an outbound event queue message if appropriate.
/// </summary>
/// <param name='element'>Element containing message</param>
private void LogOutboundDebugMessage(OSD element, UUID agentId)
{
if (element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"Eq OUT {0,-30} to {1,-20} {2,-20}",
ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName);
}
}
public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request)
{
// m_log.DebugFormat("[EVENT QUEUE GET MODULE]: Invoked GetEvents() for {0}", pAgentId);
if (DebugLevel >= 2)
m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
Queue<OSD> queue = TryGetQueue(pAgentId);
OSD element;
@@ -414,13 +446,8 @@ namespace OpenSim.Region.ClientStack.Linden
}
else
{
if (DebugLevel > 0 && element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
ev["message"], m_scene.GetScenePresence(pAgentId).Name);
}
if (DebugLevel > 0)
LogOutboundDebugMessage(element, pAgentId);
array.Add(element);
@@ -430,13 +457,8 @@ namespace OpenSim.Region.ClientStack.Linden
{
element = queue.Dequeue();
if (DebugLevel > 0 && element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
ev["message"], m_scene.GetScenePresence(pAgentId).Name);
}
if (DebugLevel > 0)
LogOutboundDebugMessage(element, pAgentId);
array.Add(element);
thisID++;

View File

@@ -51,7 +51,16 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
[SetUp]
public void SetUp()
{
MainServer.Instance = new BaseHttpServer(9999, false, 9998, "");
uint port = 9999;
uint sslPort = 9998;
// This is an unfortunate bit of clean up we have to do because MainServer manages things through static
// variables and the VM is not restarted between tests.
MainServer.RemoveHttpServer(port);
BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
MainServer.AddHttpServer(server);
MainServer.Instance = server;
IConfigSource config = new IniConfigSource();
config.AddConfig("Startup");

View File

@@ -333,7 +333,6 @@ namespace OpenSim.Region.ClientStack.Linden
grp.AbsolutePosition = obj.Position;
prim.RotationOffset = obj.Rotation;
grp.IsAttachment = false;
// Required for linking
grp.RootPart.ClearUpdateSchedule();

View File

@@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public sealed class IncomingPacket
{
/// <summary>Client this packet came from</summary>
public LLUDPClient Client;
public LLClientView Client;
/// <summary>Packet data that has been received</summary>
public Packet Packet;
@@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary>
/// <param name="client">Reference to the client this packet came from</param>
/// <param name="packet">Packet data</param>
public IncomingPacket(LLUDPClient client, Packet packet)
public IncomingPacket(LLClientView client, Packet packet)
{
Client = client;
Packet = packet;

View File

@@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Handles new client connections
/// Constructor takes a single Packet and authenticates everything
/// </summary>
public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IClientIPEndpoint, IStatsCollector
public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector
{
/// <value>
/// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
@@ -357,7 +357,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected string m_lastName;
protected Thread m_clientThread;
protected Vector3 m_startpos;
protected EndPoint m_userEndPoint;
protected UUID m_activeGroupID;
protected string m_activeGroupName = String.Empty;
protected ulong m_activeGroupPowers;
@@ -442,7 +441,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>
/// Constructor
/// </summary>
public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
public LLClientView(Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
UUID agentId, UUID sessionId, uint circuitCode)
{
// DebugPacketLevel = 1;
@@ -450,7 +449,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RegisterInterface<IClientIM>(this);
RegisterInterface<IClientInventory>(this);
RegisterInterface<IClientChat>(this);
RegisterInterface<IClientIPEndpoint>(this);
m_scene = scene;
m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
@@ -467,7 +465,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_sessionId = sessionId;
m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
m_circuitCode = circuitCode;
m_userEndPoint = remoteEP;
m_firstName = sessionInfo.LoginInfo.First;
m_lastName = sessionInfo.LoginInfo.Last;
m_startpos = sessionInfo.LoginInfo.StartPos;
@@ -490,16 +487,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary>
public void Close()
{
IsActive = false;
m_log.DebugFormat(
"[CLIENT]: Close has been called for {0} attached to scene {1}",
Name, m_scene.RegionInfo.RegionName);
// Send the STOP packet
DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
OutPacket(disable, ThrottleOutPacketType.Unknown);
IsActive = false;
// Shutdown the image manager
ImageManager.Close();
@@ -2723,6 +2716,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
public void SendAssetNotFound(AssetRequestToClient req)
{
TransferInfoPacket Transfer = new TransferInfoPacket();
Transfer.TransferInfo.ChannelType = 2;
Transfer.TransferInfo.Status = -2;
Transfer.TransferInfo.TargetType = 0;
Transfer.TransferInfo.Params = req.Params;
Transfer.TransferInfo.Size = 0;
Transfer.TransferInfo.TransferID = req.TransferRequestID;
Transfer.Header.Zerocoded = true;
OutPacket(Transfer, ThrottleOutPacketType.Asset);
}
public void SendTexture(AssetBase TextureAsset)
{
@@ -3726,8 +3732,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
++updatesThisCall;
#region UpdateFlags to packet type conversion
PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
@@ -3784,20 +3788,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (!canUseImproved && !canUseCompressed)
{
ObjectUpdatePacket.ObjectDataBlock updateBlock;
if (update.Entity is ScenePresence)
{
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
objectUpdates.Value.Add(update);
updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
}
else
{
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
objectUpdates.Value.Add(update);
SceneObjectPart part = (SceneObjectPart)update.Entity;
updateBlock = CreatePrimUpdateBlock(part, AgentId);
// If the part has become a private hud since the update was scheduled then we do not
// want to send it to other avatars.
if (part.ParentGroup.IsAttachment
&& part.ParentGroup.HasPrivateAttachmentPoint
&& part.ParentGroup.AttachedAvatar != AgentId)
continue;
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
}
objectUpdateBlocks.Value.Add(updateBlock);
objectUpdates.Value.Add(update);
}
else if (!canUseImproved)
{
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
SceneObjectPart part = (SceneObjectPart)update.Entity;
ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
= CreateCompressedUpdateBlock(part, updateFlags);
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
compressedUpdateBlocks.Value.Add(compressedBlock);
compressedUpdates.Value.Add(update);
}
else
@@ -3810,15 +3847,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
else
{
ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
= CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
// Everything else goes here
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
if (update.Entity is SceneObjectPart)
{
SceneObjectPart part = (SceneObjectPart)update.Entity;
// If the part has become a private hud since the update was scheduled then we do not
// want to send it to other avatars.
if (part.ParentGroup.IsAttachment
&& part.ParentGroup.HasPrivateAttachmentPoint
&& part.ParentGroup.AttachedAvatar != AgentId)
continue;
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
}
terseUpdateBlocks.Value.Add(terseUpdateBlock);
terseUpdates.Value.Add(update);
}
}
++updatesThisCall;
#endregion Block Construction
}
#region Packet Sending
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
@@ -11654,7 +11716,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
logPacket = false;
if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
if (DebugPacketLevel <= 50
& (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
logPacket = false;
if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -11767,7 +11830,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
ClientInfo info = m_udpClient.GetClientInfo();
info.userEP = m_userEndPoint;
info.proxyEP = null;
info.agentcircuit = RequestClientInfo();
@@ -11779,11 +11841,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_udpClient.SetClientInfo(info);
}
public EndPoint GetClientEP()
{
return m_userEndPoint;
}
#region Media Parcel Members
public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
@@ -11864,10 +11921,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return string.Empty;
}
public void KillEndDone()
{
}
#region IClientCore
private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
@@ -11985,14 +12038,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="asset"></param>
protected void AssetReceived(string id, Object sender, AssetBase asset)
{
if (asset == null)
return;
TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
UUID requestID = UUID.Zero;
byte source = (byte)SourceType.Asset;
AssetRequestToClient req = new AssetRequestToClient();
if (asset == null)
{
req.AssetInf = null;
req.AssetRequestSource = source;
req.IsTextureRequest = false;
req.NumPackets = 0;
req.Params = transferRequest.TransferInfo.Params;
req.RequestAssetID = requestID;
req.TransferRequestID = transferRequest.TransferInfo.TransferID;
SendAssetNotFound(req);
return;
}
if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
{
requestID = new UUID(transferRequest.TransferInfo.Params, 0);
@@ -12009,7 +12075,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return;
// The asset is known to exist and is in our cache, so add it to the AssetRequests list
AssetRequestToClient req = new AssetRequestToClient();
req.AssetInf = asset;
req.AssetRequestSource = source;
req.IsTextureRequest = false;
@@ -12045,24 +12110,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return numPackets;
}
#region IClientIPEndpoint Members
public IPAddress EndPoint
{
get
{
if (m_userEndPoint is IPEndPoint)
{
IPEndPoint ep = (IPEndPoint)m_userEndPoint;
return ep.Address;
}
return null;
}
}
#endregion
public void SendRebakeAvatarTextures(UUID textureID)
{
RebakeAvatarTexturesPacket pack =

View File

@@ -147,21 +147,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_elapsed500MSOutgoingPacketHandler;
/// <summary>Flag to signal when clients should check for resends</summary>
private bool m_resendUnacked;
protected bool m_resendUnacked;
/// <summary>Flag to signal when clients should send ACKs</summary>
private bool m_sendAcks;
protected bool m_sendAcks;
/// <summary>Flag to signal when clients should send pings</summary>
private bool m_sendPing;
protected bool m_sendPing;
private int m_defaultRTO = 0;
private int m_maxRTO = 0;
private int m_ackTimeout = 0;
private int m_pausedAckTimeout = 0;
private bool m_disableFacelights = false;
public Socket Server { get { return null; } }
private int m_malformedCount = 0; // Guard against a spamming attack
/// <summary>
/// Record current outgoing client for monitoring purposes.
/// </summary>
private IClientAPI m_currentOutgoingClient;
/// <summary>
/// Recording current incoming client for monitoring purposes.
/// </summary>
private IClientAPI m_currentIncomingClient;
public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
: base(listenIP, (int)port)
{
@@ -198,11 +211,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_defaultRTO = config.GetInt("DefaultRTO", 0);
m_maxRTO = config.GetInt("MaxRTO", 0);
m_disableFacelights = config.GetBoolean("DisableFacelights", false);
m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60);
m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300);
}
else
{
PrimUpdatesPerCallback = 100;
TextureSendLimit = 20;
m_ackTimeout = 1000 * 60; // 1 minute
m_pausedAckTimeout = 1000 * 300; // 5 minutes
}
#region BinaryStats
@@ -239,19 +256,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (m_scene == null)
throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode");
m_log.InfoFormat(
"[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
m_asyncPacketHandling ? "asynchronous" : "synchronous");
base.Start(m_recvBufferSize, m_asyncPacketHandling);
// Start the packet processing threads
Watchdog.StartThread(
IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true);
IncomingPacketHandler,
string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
ThreadPriority.Normal,
false,
true,
GetWatchdogIncomingAlarmData,
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
Watchdog.StartThread(
OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true);
OutgoingPacketHandler,
string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
ThreadPriority.Normal,
false,
true,
GetWatchdogOutgoingAlarmData,
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
m_elapsedMSSinceLastStatReport = Environment.TickCount;
}
/// <summary>
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
/// </summary>
/// <returns></returns>
private string GetWatchdogIncomingAlarmData()
{
return string.Format(
"Client is {0}",
m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none");
}
/// <summary>
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
/// </summary>
/// <returns></returns>
private string GetWatchdogOutgoingAlarmData()
{
return string.Format(
"Client is {0}",
m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
}
public new void Stop()
{
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
@@ -485,19 +539,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
}
public void HandleUnacked(LLUDPClient udpClient)
public void HandleUnacked(LLClientView client)
{
LLUDPClient udpClient = client.UDPClient;
if (!udpClient.IsConnected)
return;
// Disconnect an agent if no packets are received for some time
//FIXME: Make 60 an .ini setting
if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
{
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
int timeoutTicks = m_ackTimeout;
// Allow more slack if the client is "paused" eg file upload dialogue is open
// Some sort of limit is needed in case the client crashes, loses its network connection
// or some other disaster prevents it from sendung the AgentResume
if (udpClient.IsPaused)
timeoutTicks = m_pausedAckTimeout;
if (client.IsActive &&
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
{
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
// though it's set later on by LLClientView.Close()
client.IsActive = false;
// Fire this out on a different thread so that we don't hold up outgoing packet processing for
// everybody else if this is being called due to an ack timeout.
// This is the same as processing as the async process of a logout request.
Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
RemoveClient(udpClient);
return;
}
@@ -820,7 +889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Ping Check Handling
// Inbox insertion
packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
}
#region BinaryStats
@@ -917,8 +986,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
m_log.DebugFormat(
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} from {1}",
uccp.CircuitCode.Code, buffer.RemoteEndPoint);
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
@@ -947,8 +1016,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// Don't create clients for unauthorized requesters.
m_log.WarnFormat(
"[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint);
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
}
// m_log.DebugFormat(
@@ -1034,7 +1103,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client.OnLogout += LogoutHandler;
((LLClientView)client).DisableFacelights = m_disableFacelights;
@@ -1046,15 +1115,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return client;
}
private void RemoveClient(LLUDPClient udpClient)
/// <summary>
/// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
/// </summary>
/// <remarks>
/// If a connection is active then we will always receive packets even if nothing else is happening, due to
/// regular client pings.
/// </remarks>
/// <param name='client'></param>
private void DeactivateClientDueToTimeout(IClientAPI client)
{
// Remove this client from the scene
IClientAPI client;
if (m_scene.TryGetClient(udpClient.AgentID, out client))
{
client.IsLoggingOut = true;
client.Close();
}
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
// though it's set later on by LLClientView.Close()
client.IsActive = false;
m_log.WarnFormat(
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
if (!client.SceneAgent.IsChildAgent)
client.Kick("Simulator logged you out due to connection timeout");
client.Close();
}
private void IncomingPacketHandler()
@@ -1161,6 +1245,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// client. m_packetSent will be set to true if a packet is sent
m_scene.ForEachClient(clientPacketHandler);
m_currentOutgoingClient = null;
// If nothing was sent, sleep for the minimum amount of time before a
// token bucket could get more tokens
if (!m_packetSent)
@@ -1177,18 +1263,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Watchdog.RemoveThread();
}
private void ClientOutgoingPacketHandler(IClientAPI client)
protected void ClientOutgoingPacketHandler(IClientAPI client)
{
m_currentOutgoingClient = client;
try
{
if (client is LLClientView)
{
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
LLClientView llClient = (LLClientView)client;
LLUDPClient udpClient = llClient.UDPClient;
if (udpClient.IsConnected)
{
if (m_resendUnacked)
HandleUnacked(udpClient);
HandleUnacked(llClient);
if (m_sendAcks)
SendAcks(udpClient);
@@ -1204,8 +1293,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
catch (Exception ex)
{
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
" threw an exception: " + ex.Message, ex);
m_log.Error(
string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
}
}
@@ -1231,11 +1320,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
nticks++;
watch1.Start();
m_currentOutgoingClient = client;
try
{
if (client is LLClientView)
{
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
LLClientView llClient = (LLClientView)client;
LLUDPClient udpClient = llClient.UDPClient;
if (udpClient.IsConnected)
{
@@ -1244,7 +1336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
nticksUnack++;
watch2.Start();
HandleUnacked(udpClient);
HandleUnacked(llClient);
watch2.Stop();
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
@@ -1315,23 +1407,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
private void ProcessInPacket(object state)
private void ProcessInPacket(IncomingPacket incomingPacket)
{
IncomingPacket incomingPacket = (IncomingPacket)state;
Packet packet = incomingPacket.Packet;
LLUDPClient udpClient = incomingPacket.Client;
IClientAPI client;
LLClientView client = incomingPacket.Client;
// Sanity check
if (packet == null || udpClient == null)
if (client.IsActive)
{
m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
packet, udpClient);
}
m_currentIncomingClient = client;
// Make sure this client is still alive
if (m_scene.TryGetClient(udpClient.AgentID, out client))
{
try
{
// Process this packet
@@ -1346,23 +1430,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
catch (Exception e)
{
// Don't let a failure in an individual client thread crash the whole sim.
m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
m_log.Error(e.Message, e);
m_log.Error(
string.Format(
"[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
client.Name, packet.Type),
e);
}
finally
{
m_currentIncomingClient = null;
}
}
else
{
m_log.DebugFormat(
"[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
packet.Type, udpClient.AgentID, m_scene.RegionInfo.RegionName);
packet.Type, client.Name, m_scene.RegionInfo.RegionName);
}
}
protected void LogoutHandler(IClientAPI client)
{
client.SendLogoutPacket();
if (client.IsActive)
RemoveClient(((LLClientView)client).UDPClient);
if (!client.IsLoggingOut)
{
client.IsLoggingOut = true;
client.Close();
}
}
}
}
}

View File

@@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
[TestFixture]
public class BasicCircuitTests
{
private Scene m_scene;
private TestLLUDPServer m_udpServer;
[TestFixtureSetUp]
public void FixtureInit()
{
@@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
}
// /// <summary>
// /// Add a client for testing
// /// </summary>
// /// <param name="scene"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="testPacketServer"></param>
// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
// protected void SetupStack(
// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
// out AgentCircuitManager acm)
// {
// IConfigSource configSource = new IniConfigSource();
// ClientStackUserSettings userSettings = new ClientStackUserSettings();
// testLLUDPServer = new TestLLUDPServer();
// acm = new AgentCircuitManager();
//
// uint port = 666;
// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
// testLLUDPServer.LocalScene = scene;
// }
// /// <summary>
// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
// /// tested
// /// </summary>
// /// <param name="circuitCode"></param>
// /// <param name="epSender"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="acm"></param>
// protected void AddClient(
// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
// {
// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
//
// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
// }
// /// <summary>
// /// Set up a client for tests which aren't concerned with this process itself
// /// </summary>
// /// <param name="circuitCode"></param>
// /// <param name="epSender"></param>
// /// <param name="agentId"></param>
// /// <param name="sessionId"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="acm"></param>
// protected void AddClient(
// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
// {
// AgentCircuitData acd = new AgentCircuitData();
// acd.AgentID = agentId;
// acd.SessionID = sessionId;
//
// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
//
// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
// = new UseCircuitCodePacket.CircuitCodeBlock();
// uccpCcBlock.Code = circuitCode;
// uccpCcBlock.ID = agentId;
// uccpCcBlock.SessionID = sessionId;
// uccp.CircuitCode = uccpCcBlock;
//
// acm.AddNewCircuit(circuitCode, acd);
//
// testLLUDPServer.LoadReceive(uccp, epSender);
// testLLUDPServer.ReceiveData(null);
// }
[SetUp]
public void SetUp()
{
m_scene = new SceneHelpers().SetupScene();
}
/// <summary>
/// Build an object name packet for test purposes
/// </summary>
/// <param name="objectLocalId"></param>
/// <param name="objectName"></param>
protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
{
ObjectNamePacket onp = new ObjectNamePacket();
ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
@@ -148,29 +86,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
return onp;
}
/// <summary>
/// Test adding a client to the stack
/// </summary>
[Test]
public void TestAddClient()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
TestScene scene = new SceneHelpers().SetupScene();
uint myCircuitCode = 123456;
private void AddUdpServer()
{
AddUdpServer(new IniConfigSource());
}
private void AddUdpServer(IniConfigSource configSource)
{
uint port = 0;
AgentCircuitManager acm = m_scene.AuthenticateHandler;
m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm);
m_udpServer.AddScene(m_scene);
}
/// <summary>
/// Used by tests that aren't testing this stage.
/// </summary>
private ScenePresence AddClient()
{
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
uint myCircuitCode = 123456;
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
uint port = 0;
AgentCircuitManager acm = scene.AuthenticateHandler;
TestLLUDPServer llUdpServer
= new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
llUdpServer.AddScene(scene);
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
@@ -185,26 +125,67 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
llUdpServer.PacketReceived(upb);
AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid;
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
m_udpServer.PacketReceived(upb);
return m_scene.GetScenePresence(myAgentUuid);
}
/// <summary>
/// Test adding a client to the stack
/// </summary>
[Test]
public void TestAddClient()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
AddUdpServer();
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
uint myCircuitCode = 123456;
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
= new UseCircuitCodePacket.CircuitCodeBlock();
uccpCcBlock.Code = myCircuitCode;
uccpCcBlock.ID = myAgentUuid;
uccpCcBlock.SessionID = mySessionUuid;
uccp.CircuitCode = uccpCcBlock;
byte[] uccpBytes = uccp.ToBytes();
UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
m_udpServer.PacketReceived(upb);
// Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null);
Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);
AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid;
acm.AddNewCircuit(myCircuitCode, acd);
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
llUdpServer.PacketReceived(upb);
m_udpServer.PacketReceived(upb);
// Should succeed now
ScenePresence sp = scene.GetScenePresence(myAgentUuid);
ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1));
Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));
Packet packet = llUdpServer.PacketsSent[0];
Packet packet = m_udpServer.PacketsSent[0];
Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
PacketAckPacket ackPacket = packet as PacketAckPacket;
@@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
}
[Test]
public void TestLogoutClientDueToAck()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
IniConfigSource ics = new IniConfigSource();
IConfig config = ics.AddConfig("ClientStack.LindenUDP");
config.Set("AckTimeout", -1);
AddUdpServer(ics);
ScenePresence sp = AddClient();
m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false);
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
Assert.That(spAfterAckTimeout, Is.Null);
// TestHelpers.DisableLogging();
}
// /// <summary>
// /// Test removing a client from the stack
// /// </summary>

View File

@@ -44,9 +44,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
}
protected int m_objectNameCallsReceived;
public MockScene()
public MockScene() : base(new RegionInfo(1000, 1000, null, null))
{
m_regInfo = new RegionInfo(1000, 1000, null, null);
m_regStatus = RegionStatus.Up;
}

View File

@@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
PacketsSent.Add(packet);
}
public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing)
{
m_resendUnacked = resendUnacked;
m_sendAcks = sendAcks;
m_sendPing = sendPing;
ClientOutgoingPacketHandler(client);
}
//// /// <summary>
//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
//// /// </summary>

View File

@@ -94,22 +94,19 @@ namespace OpenSim.Region.ClientStack
m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0}", m_httpServerPort);
m_httpServer.Start();
MainServer.AddHttpServer(m_httpServer);
MainServer.Instance = m_httpServer;
// "OOB" Server
if (m_networkServersInfo.ssl_listener)
{
BaseHttpServer server = null;
server = new BaseHttpServer(
BaseHttpServer server = new BaseHttpServer(
m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path,
m_networkServersInfo.cert_pass);
// Add the server to m_Servers
if(server != null)
{
m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
MainServer.AddHttpServer(server);
server.Start();
}
m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
MainServer.AddHttpServer(server);
server.Start();
}
base.StartupSpecific();

View File

@@ -42,8 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
public class AssetTransactionModule : INonSharedRegionModule,
IAgentAssetTransactions
{
// private static readonly ILog m_log = LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_Scene;
private bool m_dumpAssetsToFile = false;
@@ -209,15 +208,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// and comes through this method.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="part"></param>
/// <param name="transactionID"></param>
/// <param name="item"></param>
public void HandleTaskItemUpdateFromTransaction(IClientAPI remoteClient,
SceneObjectPart part, UUID transactionID,
TaskInventoryItem item)
public void HandleTaskItemUpdateFromTransaction(
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
{
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}",
// item.Name);
m_log.DebugFormat(
"[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);

View File

@@ -143,7 +143,7 @@ namespace Flotsam.RegionModules.AssetCache
IConfig assetConfig = source.Configs["AssetCache"];
if (assetConfig == null)
{
m_log.Warn(
m_log.Debug(
"[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults.");
}
else

View File

@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
private IDialogModule m_dialogModule;
private IInventoryAccessModule m_invAccessModule;
/// <summary>
/// Are attachments enabled?
@@ -70,7 +70,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public void AddRegion(Scene scene)
{
m_scene = scene;
m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
if (Enabled)
@@ -87,7 +86,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
}
public void RegionLoaded(Scene scene) {}
public void RegionLoaded(Scene scene)
{
m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
}
public void Close()
{
@@ -98,6 +100,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
#region IAttachmentsModule
public void CopyAttachments(IScenePresence sp, AgentData ad)
{
lock (sp.AttachmentsSyncLock)
{
// Attachment objects
List<SceneObjectGroup> attachments = sp.GetAttachments();
if (attachments.Count > 0)
{
ad.AttachmentObjects = new List<ISceneObject>();
ad.AttachmentObjectStates = new List<string>();
// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
sp.InTransitScriptStates.Clear();
foreach (SceneObjectGroup sog in attachments)
{
// We need to make a copy and pass that copy
// because of transfers withn the same sim
ISceneObject clone = sog.CloneForNewScene();
// Attachment module assumes that GroupPosition holds the offsets...!
((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
((SceneObjectGroup)clone).IsAttachment = false;
ad.AttachmentObjects.Add(clone);
string state = sog.GetStateSnapshot();
ad.AttachmentObjectStates.Add(state);
sp.InTransitScriptStates.Add(state);
// Let's remove the scripts of the original object here
sog.RemoveScriptInstances(true);
}
}
}
}
public void CopyAttachments(AgentData ad, IScenePresence sp)
{
if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0)
{
lock (sp.AttachmentsSyncLock)
sp.ClearAttachments();
int i = 0;
foreach (ISceneObject so in ad.AttachmentObjects)
{
((SceneObjectGroup)so).LocalId = 0;
((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
so.SetState(ad.AttachmentObjectStates[i++], m_scene);
m_scene.IncomingCreateObject(Vector3.Zero, so);
}
}
}
/// <summary>
/// RezAttachments. This should only be called upon login on the first region.
/// Attachment rezzings on crossings and TPs are done in a different way.
@@ -150,31 +202,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
}
public void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted)
public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted)
{
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
if (!Enabled)
return;
foreach (SceneObjectGroup grp in sp.GetAttachments())
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
lock (sp.AttachmentsSyncLock)
{
grp.IsAttachment = false;
grp.AbsolutePosition = grp.RootPart.AttachedPos;
UpdateKnownItem(sp, grp, saveAllScripted);
grp.IsAttachment = true;
foreach (SceneObjectGroup so in sp.GetAttachments())
{
// We can only remove the script instances from the script engine after we've retrieved their xml state
// when we update the attachment item.
m_scene.DeleteSceneObject(so, false, false);
if (saveChanged || saveAllScripted)
{
so.IsAttachment = false;
so.AbsolutePosition = so.RootPart.AttachedPos;
UpdateKnownItem(sp, so, saveAllScripted);
}
so.RemoveScriptInstances(true);
}
sp.ClearAttachments();
}
}
public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
// m_scene.RegionInfo.RegionName, sp.Name, silent);
if (!Enabled)
return;
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
// m_scene.RegionInfo.RegionName, sp.Name, silent);
foreach (SceneObjectGroup sop in sp.GetAttachments())
{
sop.Scene.DeleteSceneObject(sop, silent);
@@ -190,6 +255,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
if (group.GetSittingAvatarsCount() != 0)
{
// m_log.WarnFormat(
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
return false;
}
if (sp.GetAttachments(attachmentPt).Contains(group))
{
@@ -231,33 +305,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
group.AttachmentPoint = attachmentPt;
group.AbsolutePosition = attachPos;
// We also don't want to do any of the inventory operations for an NPC.
if (sp.PresenceType != PresenceType.Npc)
{
// Remove any previous attachments
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
// At the moment we can only deal with a single attachment
if (attachments.Count != 0)
{
UUID oldAttachmentItemID = attachments[0].FromItemID;
if (oldAttachmentItemID != UUID.Zero)
DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID);
else
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
}
// Add the new attachment to inventory if we don't already have it.
UUID newAttachmentItemID = group.FromItemID;
if (newAttachmentItemID == UUID.Zero)
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
}
UpdateUserInventoryWithAttachment(sp, group, attachmentPt);
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
}
@@ -265,7 +315,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return true;
}
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt)
{
// Remove any previous attachments
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
// At the moment we can only deal with a single attachment
if (attachments.Count != 0)
{
if (attachments[0].FromItemID != UUID.Zero)
DetachSingleAttachmentToInvInternal(sp, attachments[0]);
else
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
}
// Add the new attachment to inventory if we don't already have it.
UUID newAttachmentItemID = group.FromItemID;
if (newAttachmentItemID == UUID.Zero)
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
}
public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
{
if (!Enabled)
return null;
@@ -304,12 +378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return null;
}
SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt);
if (att == null)
DetachSingleAttachmentToInv(sp, itemID);
return att;
return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt);
}
public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -386,18 +455,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
}
public void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID)
public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
{
lock (sp.AttachmentsSyncLock)
{
// Save avatar attachment information
// m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
bool changed = sp.Appearance.DetachAttachment(itemID);
if (so.AttachedAvatar != sp.UUID)
{
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}",
so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName);
return;
}
bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
DetachSingleAttachmentToInvInternal(sp, itemID);
DetachSingleAttachmentToInvInternal(sp, so);
}
}
@@ -406,17 +484,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (!Enabled)
return;
// First we save the
// attachment point information, then we update the relative
// positioning. Then we have to mark the object as NOT an
// attachment. This is necessary in order to correctly save
// and retrieve GroupPosition information for the attachment.
// Finally, we restore the object's attachment status.
uint attachmentPoint = sog.AttachmentPoint;
sog.UpdateGroupPosition(pos);
sog.IsAttachment = false;
sog.AbsolutePosition = sog.RootPart.AttachedPos;
sog.AttachmentPoint = attachmentPoint;
sog.HasGroupChanged = true;
}
@@ -459,6 +527,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// </remarks>
/// <param name="sp"></param>
/// <param name="grp"></param>
/// <param name="saveAllScripted"></param>
private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted)
{
// Saving attachments for NPCs messes them up for the real owner!
@@ -498,10 +567,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
m_scene.InventoryService.UpdateItem(item);
// this gets called when the agent logs off!
// If the name of the object has been changed whilst attached then we want to update the inventory
// item in the viewer.
if (sp.ControllingClient != null)
sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
}
grp.HasGroupChanged = false; // Prevent it being saved over and over
}
// else
@@ -560,6 +631,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{
m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
}
else if (so.HasPrivateAttachmentPoint)
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
// so.Name, sp.Name, so.AttachmentPoint);
// As this scene object can now only be seen by the attaching avatar, tell everybody else in the
// scene that it's no longer in their awareness.
m_scene.ForEachClient(
client =>
{ if (client.AgentId != so.AttachedAvatar)
client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId });
});
}
so.IsSelected = false; // fudge....
so.ScheduleGroupForFullUpdate();
@@ -578,201 +663,118 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <returns>The user inventory item created that holds the attachment.</returns>
private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp)
{
if (m_invAccessModule == null)
return null;
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
// grp.Name, grp.LocalId, remoteClient.Name);
Vector3 inventoryStoredPosition = new Vector3
(((grp.AbsolutePosition.X > (int)Constants.RegionSize)
? Constants.RegionSize - 6
: grp.AbsolutePosition.X)
,
(grp.AbsolutePosition.Y > (int)Constants.RegionSize)
? Constants.RegionSize - 6
: grp.AbsolutePosition.Y,
grp.AbsolutePosition.Z);
Vector3 originalPosition = grp.AbsolutePosition;
grp.AbsolutePosition = inventoryStoredPosition;
// If we're being called from a script, then trying to serialize that same script's state will not complete
// in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
// the client/server crashes rather than logging out normally, the attachment's scripts will resume
// without state on relog. Arguably, this is what we want anyway.
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
grp.AbsolutePosition = originalPosition;
AssetBase asset = m_scene.CreateAsset(
grp.GetPartName(grp.LocalId),
grp.GetPartDescription(grp.LocalId),
(sbyte)AssetType.Object,
Utils.StringToBytes(sceneObjectXml),
sp.UUID);
m_scene.AssetService.Store(asset);
InventoryItemBase item = new InventoryItemBase();
item.CreatorId = grp.RootPart.CreatorID.ToString();
item.CreatorData = grp.RootPart.CreatorData;
item.Owner = sp.UUID;
item.ID = UUID.Random();
item.AssetID = asset.FullID;
item.Description = asset.Description;
item.Name = asset.Name;
item.AssetType = asset.Type;
item.InvType = (int)InventoryType.Object;
InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
if (folder != null)
item.Folder = folder.ID;
else // oopsies
item.Folder = UUID.Zero;
if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
{
item.BasePermissions = grp.RootPart.NextOwnerMask;
item.CurrentPermissions = grp.RootPart.NextOwnerMask;
item.NextPermissions = grp.RootPart.NextOwnerMask;
item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
}
else
{
item.BasePermissions = grp.RootPart.BaseMask;
item.CurrentPermissions = grp.RootPart.OwnerMask;
item.NextPermissions = grp.RootPart.NextOwnerMask;
item.EveryOnePermissions = grp.RootPart.EveryoneMask;
item.GroupPermissions = grp.RootPart.GroupMask;
}
item.CreationDate = Util.UnixTimeSinceEpoch();
InventoryItemBase newItem
= m_invAccessModule.CopyToInventory(
DeRezAction.TakeCopy,
m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
new List<SceneObjectGroup> { grp },
sp.ControllingClient, true)[0];
// sets itemID so client can show item as 'attached' in inventory
grp.FromItemID = item.ID;
grp.FromItemID = newItem.ID;
if (m_scene.AddInventoryItem(item))
{
sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
}
else
{
if (m_dialogModule != null)
m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed");
}
return item;
return newItem;
}
// What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
// To LocalId or UUID, *THAT* is the question. How now Brown UUID??
private void DetachSingleAttachmentToInvInternal(IScenePresence sp, UUID itemID)
private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
{
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
if (itemID == UUID.Zero) // If this happened, someone made a mistake....
return;
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
sp.RemoveAttachment(so);
// We can NOT use the dictionries here, as we are looking
// for an entity by the fromAssetID, which is NOT the prim UUID
EntityBase[] detachEntities = m_scene.GetEntities();
SceneObjectGroup group;
// We can only remove the script instances from the script engine after we've retrieved their xml state
// when we update the attachment item.
m_scene.DeleteSceneObject(so, false, false);
lock (sp.AttachmentsSyncLock)
{
foreach (EntityBase entity in detachEntities)
{
if (entity is SceneObjectGroup)
{
group = (SceneObjectGroup)entity;
if (group.FromItemID == itemID)
{
m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
sp.RemoveAttachment(group);
// Prepare sog for storage
so.AttachedAvatar = UUID.Zero;
so.RootPart.SetParentLocalId(0);
so.IsAttachment = false;
so.AbsolutePosition = so.RootPart.AttachedPos;
// Prepare sog for storage
group.AttachedAvatar = UUID.Zero;
group.RootPart.SetParentLocalId(0);
group.IsAttachment = false;
group.AbsolutePosition = group.RootPart.AttachedPos;
UpdateKnownItem(sp, group, true);
m_scene.DeleteSceneObject(group, false);
return;
}
}
}
}
UpdateKnownItem(sp, so, true);
so.RemoveScriptInstances(true);
}
private SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt)
{
IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
if (invAccess != null)
if (m_invAccessModule == null)
return null;
lock (sp.AttachmentsSyncLock)
{
lock (sp.AttachmentsSyncLock)
SceneObjectGroup objatt;
if (itemID != UUID.Zero)
objatt = m_invAccessModule.RezObject(sp.ControllingClient,
itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, sp.UUID, true);
else
objatt = m_invAccessModule.RezObject(sp.ControllingClient,
null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, sp.UUID, true);
if (objatt != null)
{
SceneObjectGroup objatt;
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
// objatt.Name, sp.Name, attachmentPt, m_scene.Name);
if (itemID != UUID.Zero)
objatt = invAccess.RezObject(sp.ControllingClient,
itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, sp.UUID, true);
else
objatt = invAccess.RezObject(sp.ControllingClient,
null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, sp.UUID, true);
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
objatt.HasGroupChanged = false;
bool tainted = false;
if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
tainted = true;
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
// objatt.Name, remoteClient.Name, AttachmentPt);
if (objatt != null)
// FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
// course of events. If not, then it's probably not worth trying to recover the situation
// since this is more likely to trigger further exceptions and confuse later debugging. If
// exceptions can be thrown in expected error conditions (not NREs) then make this consistent
// since other normal error conditions will simply return false instead.
// This will throw if the attachment fails
try
{
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
objatt.HasGroupChanged = false;
bool tainted = false;
if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
tainted = true;
// This will throw if the attachment fails
try
{
AttachObject(sp, objatt, attachmentPt, false);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
// Make sure the object doesn't stick around and bail
sp.RemoveAttachment(objatt);
m_scene.DeleteSceneObject(objatt, false);
return null;
}
if (tainted)
objatt.HasGroupChanged = true;
// Fire after attach, so we don't get messy perms dialogs
// 4 == AttachedRez
objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
objatt.ResumeScripts();
// Do this last so that event listeners have access to all the effects of the attachment
m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
return objatt;
AttachObject(sp, objatt, attachmentPt, false);
}
else
catch (Exception e)
{
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
itemID, sp.Name, attachmentPt);
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
// Make sure the object doesn't stick around and bail
sp.RemoveAttachment(objatt);
m_scene.DeleteSceneObject(objatt, false);
return null;
}
if (tainted)
objatt.HasGroupChanged = true;
// Fire after attach, so we don't get messy perms dialogs
// 4 == AttachedRez
objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
objatt.ResumeScripts();
// Do this last so that event listeners have access to all the effects of the attachment
m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
return objatt;
}
else
{
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
itemID, sp.Name, attachmentPt);
}
}
@@ -808,7 +810,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
item = m_scene.InventoryService.GetItem(item);
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
if (changed && m_scene.AvatarFactory != null)
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
// sp.Name, att.Name, AttachmentPt);
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
}
}
#endregion
@@ -912,8 +920,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
if (sp != null && group != null)
DetachSingleAttachmentToInv(sp, group.FromItemID);
DetachSingleAttachmentToInv(sp, group);
}
private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient)
@@ -923,7 +932,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
if (sp != null)
DetachSingleAttachmentToInv(sp, itemID);
{
lock (sp.AttachmentsSyncLock)
{
List<SceneObjectGroup> attachments = sp.GetAttachments();
foreach (SceneObjectGroup group in attachments)
{
if (group.FromItemID == itemID)
{
DetachSingleAttachmentToInv(sp, group);
return;
}
}
}
}
}
private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient)

View File

@@ -31,6 +31,7 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Timers;
using System.Xml;
using Timer=System.Timers.Timer;
using Nini.Config;
using NUnit.Framework;
@@ -38,11 +39,16 @@ using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Region.CoreModules.Avatar.Attachments;
using OpenSim.Region.CoreModules.Framework;
using OpenSim.Region.CoreModules.Framework.EntityTransfer;
using OpenSim.Region.CoreModules.Framework.InventoryAccess;
using OpenSim.Region.CoreModules.World.Serialiser;
using OpenSim.Region.CoreModules.Scripting.WorldComm;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
using OpenSim.Region.CoreModules.World.Serialiser;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.ScriptEngine.XEngine;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
@@ -52,11 +58,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
/// Attachment tests
/// </summary>
[TestFixture]
public class AttachmentsModuleTests
public class AttachmentsModuleTests : OpenSimTestCase
{
private Scene scene;
private AttachmentsModule m_attMod;
private ScenePresence m_presence;
private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
private OSChatMessage m_osChatMessageReceived;
[TestFixtureSetUp]
public void FixtureInit()
@@ -65,18 +70,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
Util.FireAndForgetMethod = FireAndForgetMethod.None;
}
[SetUp]
public void Init()
{
IConfigSource config = new IniConfigSource();
config.AddConfig("Modules");
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
scene = new SceneHelpers().SetupScene();
m_attMod = new AttachmentsModule();
SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule());
}
[TestFixtureTearDown]
public void TearDown()
{
@@ -85,32 +78,121 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
}
/// <summary>
/// Add the standard presence for a test.
/// </summary>
private void AddPresence()
private void OnChatFromWorld(object sender, OSChatMessage oscm)
{
UUID userId = TestHelpers.ParseTail(0x1);
UserAccountHelpers.CreateUserWithInventory(scene, userId);
m_presence = SceneHelpers.AddScenePresence(scene, userId);
// Console.WriteLine("Got chat [{0}]", oscm.Message);
m_osChatMessageReceived = oscm;
m_chatEvent.Set();
}
private Scene CreateTestScene()
{
IConfigSource config = new IniConfigSource();
List<object> modules = new List<object>();
AddCommonConfig(config, modules);
Scene scene
= new SceneHelpers().SetupScene(
"attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
return scene;
}
private Scene CreateScriptingEnabledTestScene()
{
IConfigSource config = new IniConfigSource();
List<object> modules = new List<object>();
AddCommonConfig(config, modules);
AddScriptingConfig(config, modules);
Scene scene
= new SceneHelpers().SetupScene(
"attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
scene.StartScripts();
return scene;
}
private void AddCommonConfig(IConfigSource config, List<object> modules)
{
config.AddConfig("Modules");
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
modules.Add(new AttachmentsModule());
modules.Add(new BasicInventoryAccessModule());
}
private void AddScriptingConfig(IConfigSource config, List<object> modules)
{
IConfig startupConfig = config.AddConfig("Startup");
startupConfig.Set("DefaultScriptEngine", "XEngine");
IConfig xEngineConfig = config.AddConfig("XEngine");
xEngineConfig.Set("Enabled", "true");
xEngineConfig.Set("StartDelay", "0");
// These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
// to AssemblyResolver.OnAssemblyResolve fails.
xEngineConfig.Set("AppDomainLoading", "false");
modules.Add(new XEngine());
// Necessary to stop serialization complaining
// FIXME: Stop this being necessary if at all possible
// modules.Add(new WorldCommModule());
}
/// <summary>
/// Creates an attachment item in the given user's inventory. Does not attach.
/// </summary>
/// <remarks>
/// A user with the given ID and an inventory must already exist.
/// </remarks>
/// <returns>
/// The attachment item.
/// </returns>
/// <param name='scene'></param>
/// <param name='userId'></param>
/// <param name='attName'></param>
/// <param name='rawItemId'></param>
/// <param name='rawAssetId'></param>
private InventoryItemBase CreateAttachmentItem(
Scene scene, UUID userId, string attName, int rawItemId, int rawAssetId)
{
return UserInventoryHelpers.CreateInventoryItem(
scene,
attName,
TestHelpers.ParseTail(rawItemId),
TestHelpers.ParseTail(rawAssetId),
userId,
InventoryType.Object);
}
[Test]
public void TestAddAttachmentFromGround()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
// TestHelpers.EnableLogging();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
AddPresence();
string attName = "att";
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup;
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false);
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
// Check status on scene presence
Assert.That(m_presence.HasAttachments(), Is.True);
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
Assert.That(sp.HasAttachments(), Is.True);
List<SceneObjectGroup> attachments = sp.GetAttachments();
Assert.That(attachments.Count, Is.EqualTo(1));
SceneObjectGroup attSo = attachments[0];
Assert.That(attSo.Name, Is.EqualTo(attName));
@@ -121,42 +203,107 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
// Check item status
Assert.That(
m_presence.Appearance.GetAttachpoint(attSo.FromItemID),
sp.Appearance.GetAttachpoint(attSo.FromItemID),
Is.EqualTo((int)AttachmentPoint.Chest));
InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
Assert.That(attachmentItem, Is.Not.Null);
Assert.That(attachmentItem.Name, Is.EqualTo(attName));
InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
// TestHelpers.DisableLogging();
}
/// <summary>
/// Test that we do not attempt to attach an in-world object that someone else is sitting on.
/// </summary>
[Test]
public void TestAddSatOnAttachmentFromGround()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
string attName = "att";
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2);
ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2);
// Put avatar within 10m of the prim so that sit doesn't fail.
sp2.AbsolutePosition = new Vector3(0, 0, 0);
sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
Assert.That(sp.HasAttachments(), Is.False);
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
}
[Test]
public void TestAddAttachmentFromInventory()
public void TestRezAttachmentFromInventory()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
AddPresence();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
m_attMod.RezSingleAttachmentFromInventory(
m_presence, attItemId, (uint)AttachmentPoint.Chest);
scene.AttachmentsModule.RezSingleAttachmentFromInventory(
sp, attItem.ID, (uint)AttachmentPoint.Chest);
// Check scene presence status
Assert.That(m_presence.HasAttachments(), Is.True);
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
Assert.That(sp.HasAttachments(), Is.True);
List<SceneObjectGroup> attachments = sp.GetAttachments();
Assert.That(attachments.Count, Is.EqualTo(1));
SceneObjectGroup attSo = attachments[0];
Assert.That(attSo.Name, Is.EqualTo(attName));
Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
Assert.That(attSo.IsAttachment);
Assert.That(attSo.UsesPhysics, Is.False);
Assert.That(attSo.IsTemporary, Is.False);
// Check appearance status
Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(1));
Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
}
/// <summary>
/// Test specific conditions associated with rezzing a scripted attachment from inventory.
/// </summary>
[Test]
public void TestRezScriptedAttachmentFromInventory()
{
TestHelpers.InMethod();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
TaskInventoryHelpers.AddScript(scene, so.RootPart);
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
// TODO: Need to have a test that checks the script is actually started but this involves a lot more
// plumbing of the script engine and either pausing for events or more infrastructure to turn off various
// script engine delays/asychronicity that isn't helpful in an automated regression testing context.
SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
Assert.That(attSo.ContainsScripts(), Is.True);
}
[Test]
@@ -165,29 +312,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
AddPresence();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
ISceneEntity so = m_attMod.RezSingleAttachmentFromInventory(
m_presence, attItemId, (uint)AttachmentPoint.Chest);
m_attMod.DetachSingleAttachmentToGround(m_presence, so.LocalId);
ISceneEntity so
= scene.AttachmentsModule.RezSingleAttachmentFromInventory(
sp, attItem.ID, (uint)AttachmentPoint.Chest);
scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
// Check scene presence status
Assert.That(m_presence.HasAttachments(), Is.False);
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
Assert.That(sp.HasAttachments(), Is.False);
List<SceneObjectGroup> attachments = sp.GetAttachments();
Assert.That(attachments.Count, Is.EqualTo(0));
// Check appearance status
Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(0));
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0));
// Check item status
Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItemId)), Is.Null);
Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null);
// Check object in scene
Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
@@ -197,28 +342,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
public void TestDetachAttachmentToInventory()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
AddPresence();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
m_attMod.RezSingleAttachmentFromInventory(
m_presence, attItemId, (uint)AttachmentPoint.Chest);
m_attMod.DetachSingleAttachmentToInv(m_presence, attItemId);
SceneObjectGroup so
= (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
sp, attItem.ID, (uint)AttachmentPoint.Chest);
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
// Check status on scene presence
Assert.That(m_presence.HasAttachments(), Is.False);
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
Assert.That(sp.HasAttachments(), Is.False);
List<SceneObjectGroup> attachments = sp.GetAttachments();
Assert.That(attachments.Count, Is.EqualTo(0));
// Check item status
Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0));
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
}
/// <summary>
/// Test specific conditions associated with detaching a scripted attachment from inventory.
/// </summary>
[Test]
public void TestDetachScriptedAttachmentToInventory()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
Scene scene = CreateScriptingEnabledTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
TaskInventoryHelpers.AddScript(scene, so.RootPart);
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
// FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
// In the future, we need to be able to do this programatically more predicably.
scene.EventManager.OnChatFromWorld += OnChatFromWorld;
SceneObjectGroup soRezzed
= scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
// Wait for chat to signal rezzed script has been started.
m_chatEvent.WaitOne(60000);
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed);
InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
XmlDocument soXml = new XmlDocument();
soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
}
/// <summary>
@@ -230,17 +413,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
UserAccountHelpers.CreateUserWithInventory(scene, userId);
InventoryItemBase attItem
= UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
acd.Appearance = new AvatarAppearance();
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
@@ -259,17 +436,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
UserAccountHelpers.CreateUserWithInventory(scene, userId);
InventoryItemBase attItem
= UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
acd.Appearance = new AvatarAppearance();
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
@@ -279,7 +450,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
Assert.That(attachments.Count, Is.EqualTo(1));
SceneObjectGroup attSo = attachments[0];
Assert.That(attSo.Name, Is.EqualTo(attName));
Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
Assert.That(attSo.IsAttachment);
Assert.That(attSo.UsesPhysics, Is.False);
@@ -289,9 +460,125 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments();
Assert.That(retreivedAttachments.Count, Is.EqualTo(1));
Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItemId));
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attAssetId));
Assert.That(presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID));
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
}
[Test]
public void TestUpdateAttachmentPosition()
{
TestHelpers.InMethod();
Scene scene = CreateTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
acd.Appearance = new AvatarAppearance();
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, acd);
SceneObjectGroup attSo = sp.GetAttachments()[0];
Vector3 newPosition = new Vector3(1, 2, 4);
scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
}
[Test]
public void TestSameSimulatorNeighbouringRegionsTeleport()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
AttachmentsModule attModA = new AttachmentsModule();
AttachmentsModule attModB = new AttachmentsModule();
EntityTransferModule etmA = new EntityTransferModule();
EntityTransferModule etmB = new EntityTransferModule();
LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
IConfigSource config = new IniConfigSource();
IConfig modulesConfig = config.AddConfig("Modules");
modulesConfig.Set("EntityTransferModule", etmA.Name);
modulesConfig.Set("SimulationServices", lscm.Name);
IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
// In order to run a single threaded regression test we do not want the entity transfer module waiting
// for a callback from the destination scene before removing its avatar data.
entityTransferConfig.Set("wait_for_callback", false);
modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
SceneHelpers sh = new SceneHelpers();
TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
SceneHelpers.SetupSceneModules(
sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
SceneHelpers.SetupSceneModules(
sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager);
beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
Vector3 teleportPosition = new Vector3(10, 11, 12);
Vector3 teleportLookAt = new Vector3(20, 21, 22);
sceneA.RequestTeleportLocation(
beforeTeleportSp.ControllingClient,
sceneB.RegionInfo.RegionHandle,
teleportPosition,
teleportLookAt,
(uint)TeleportFlags.ViaLocation);
((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide();
// Check attachments have made it into sceneB
ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
// This is appearance data, as opposed to actually rezzed attachments
List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
// This is the actual attachment
List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
// Check attachments have been removed from sceneA
ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
// Since this is appearance data, it is still present on the child avatar!
List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
// This is the actual attachment, which should no longer exist
List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
}
// I'm commenting this test because scene setup NEEDS InventoryService to

View File

@@ -128,7 +128,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// <param name="visualParam"></param>
public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
// m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId);
// m_log.DebugFormat(
// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
// sp.Name, textureEntry, visualParams);
// TODO: This is probably not necessary any longer, just assume the
// textureEntry set implies that the appearance transaction is complete

View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using log4net;
using Mono.Addins;
using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.Avatars.Commands
{
/// <summary>
/// A module that holds commands for manipulating objects in the scene.
/// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserCommandsModule")]
public class UserCommandsModule : ISharedRegionModule
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public const string TeleportUserCommandSyntax = "teleport user <first-name> <last-name> <destination>";
public static Regex InterRegionDestinationRegex
= new Regex(@"^(?<regionName>.+)/(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
public static Regex WithinRegionDestinationRegex
= new Regex(@"^(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
public string Name { get { return "User Commands Module"; } }
public Type ReplaceableInterface { get { return null; } }
public void Initialise(IConfigSource source)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
}
public void PostInitialise()
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
}
public void Close()
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
}
public void AddRegion(Scene scene)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
lock (m_scenes)
m_scenes[scene.RegionInfo.RegionID] = scene;
scene.AddCommand(
"Users",
this,
"teleport user",
TeleportUserCommandSyntax,
"Teleport a user in this simulator to the given destination",
"<destination> is in format [<region-name>]/<x>/<y>/<z>, e.g. regionone/20/30/40 or just 20/30/40 to teleport within same region."
+ "\nIf the region contains a space then the whole destination must be in quotes, e.g. \"region one/20/30/40\"",
HandleTeleportUser);
}
public void RemoveRegion(Scene scene)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
lock (m_scenes)
m_scenes.Remove(scene.RegionInfo.RegionID);
}
public void RegionLoaded(Scene scene)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
}
private ScenePresence GetUser(string firstName, string lastName)
{
ScenePresence userFound = null;
lock (m_scenes)
{
foreach (Scene scene in m_scenes.Values)
{
ScenePresence user = scene.GetScenePresence(firstName, lastName);
if (user != null && !user.IsChildAgent)
{
userFound = user;
break;
}
}
}
return userFound;
}
private void HandleTeleportUser(string module, string[] cmd)
{
if (cmd.Length < 5)
{
MainConsole.Instance.OutputFormat("Usage: " + TeleportUserCommandSyntax);
return;
}
string firstName = cmd[2];
string lastName = cmd[3];
string rawDestination = cmd[4];
ScenePresence user = GetUser(firstName, lastName);
if (user == null)
{
MainConsole.Instance.OutputFormat("No user found with name {0} {1}", firstName, lastName);
return;
}
// MainConsole.Instance.OutputFormat("rawDestination [{0}]", rawDestination);
Match m = WithinRegionDestinationRegex.Match(rawDestination);
if (!m.Success)
{
m = InterRegionDestinationRegex.Match(rawDestination);
if (!m.Success)
{
MainConsole.Instance.OutputFormat("Invalid destination {0}", rawDestination);
return;
}
}
string regionName
= m.Groups["regionName"].Success ? m.Groups["regionName"].Value : user.Scene.RegionInfo.RegionName;
MainConsole.Instance.OutputFormat(
"Teleporting {0} to {1},{2},{3} in {4}",
user.Name,
m.Groups["x"], m.Groups["y"], m.Groups["z"],
regionName);
user.Scene.RequestTeleportLocation(
user.ControllingClient,
regionName,
new Vector3(
float.Parse(m.Groups["x"].Value),
float.Parse(m.Groups["y"].Value),
float.Parse(m.Groups["z"].Value)),
user.Lookat,
(uint)TeleportFlags.ViaLocation);
}
}
}

View File

@@ -415,12 +415,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected override void StoreBackwards(UUID friendID, UUID agentID)
{
Boolean agentIsLocal = true;
Boolean friendIsLocal = true;
bool agentIsLocal = true;
// bool friendIsLocal = true;
if (UserManagementModule != null)
{
agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
// friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
}
// Is the requester a local user?
@@ -507,7 +508,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
friendUUI = finfo.Friend;
theFriendUUID = friendUUI;
UUID utmp = UUID.Zero; String url = String.Empty; String first = String.Empty, last = String.Empty, tmp = String.Empty;
UUID utmp = UUID.Zero;
string url = String.Empty;
string first = String.Empty;
string last = String.Empty;
// If it's confirming the friendship, we already have the full UUI with the secret
if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
{

View File

@@ -137,13 +137,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
foreach (Scene scene in m_Scenes)
{
// m_log.DebugFormat(
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
// toAgentID.ToString(), scene.RegionInfo.RegionName);
ScenePresence sp = scene.GetScenePresence(toAgentID);
if (sp != null && !sp.IsChildAgent)
{
// Local message
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
sp.ControllingClient.SendInstantMessage(im);
// Message sent
@@ -155,13 +157,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
// try child avatar second
foreach (Scene scene in m_Scenes)
{
// m_log.DebugFormat(
// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
m_log.DebugFormat(
"[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
ScenePresence sp = scene.GetScenePresence(toAgentID);
if (sp != null)
{
// Local message
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
sp.ControllingClient.SendInstantMessage(im);
// Message sent
@@ -170,10 +174,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
SendGridInstantMessageViaXMLRPC(im, result);
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
return;
SendGridInstantMessageViaXMLRPC(im, result);
}
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)

View File

@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
{
[TestFixture]
public class InventoryArchiveTestCase
public class InventoryArchiveTestCase : OpenSimTestCase
{
protected ManualResetEvent mre = new ManualResetEvent(false);
@@ -84,8 +84,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
protected string m_coaItemName = "Coalesced Item";
[SetUp]
public virtual void SetUp()
public override void SetUp()
{
base.SetUp();
m_iarStream = new MemoryStream(m_iarStreamBytes);
}

View File

@@ -297,7 +297,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
});
}
}
else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
else if (
im.dialog == (byte)InstantMessageDialog.InventoryDeclined
|| im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
{
// Here, the recipient is local and we can assume that the
// inventory is loaded. Courtesy of the above bulk update,

View File

@@ -57,14 +57,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
public void Initialise(IConfigSource config)
{
// This can be reduced later as the loader will determine
// whether we are needed
if (config.Configs["Profile"] != null)
{
if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule")
return;
}
m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
m_Enabled = true;
}

View File

@@ -0,0 +1,269 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using System.Threading;
using OpenMetaverse;
using log4net;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Client;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
using OpenSim.Services.Interfaces;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
/// <summary>
/// The possible states that an agent can be in when its being transferred between regions.
/// </summary>
/// <remarks>
/// This is a state machine.
///
/// [Entry] => Preparing
/// Preparing => { Transferring || CleaningUp || [Exit] }
/// Transferring => { ReceivedAtDestination || CleaningUp }
/// ReceivedAtDestination => CleaningUp
/// CleaningUp => [Exit]
///
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
/// However, any state can transition to CleaningUp if the teleport has failed.
/// </remarks>
enum AgentTransferState
{
Preparing, // The agent is being prepared for transfer
Transferring, // The agent is in the process of being transferred to a destination
ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
CleaningUp // The agent is being changed to child/removed after a transfer
}
/// <summary>
/// Records the state of entities when they are in transfer within or between regions (cross or teleport).
/// </summary>
public class EntityTransferStateMachine
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// If true then on a teleport, the source region waits for a callback from the destination region. If
/// a callback fails to arrive within a set time then the user is pulled back into the source region.
/// </summary>
public bool EnableWaitForAgentArrivedAtDestination { get; set; }
private EntityTransferModule m_mod;
private Dictionary<UUID, AgentTransferState> m_agentsInTransit = new Dictionary<UUID, AgentTransferState>();
public EntityTransferStateMachine(EntityTransferModule module)
{
m_mod = module;
}
/// <summary>
/// Set that an agent is in transit.
/// </summary>
/// <param name='id'>The ID of the agent being teleported</param>
/// <returns>true if the agent was not already in transit, false if it was</returns>
internal bool SetInTransit(UUID id)
{
lock (m_agentsInTransit)
{
if (!m_agentsInTransit.ContainsKey(id))
{
m_agentsInTransit[id] = AgentTransferState.Preparing;
return true;
}
}
return false;
}
/// <summary>
/// Updates the state of an agent that is already in transit.
/// </summary>
/// <param name='id'></param>
/// <param name='newState'></param>
/// <returns></returns>
/// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
internal void UpdateInTransit(UUID id, AgentTransferState newState)
{
lock (m_agentsInTransit)
{
// Illegal to try and update an agent that's not actually in transit.
if (!m_agentsInTransit.ContainsKey(id))
throw new Exception(
string.Format(
"Agent with ID {0} is not registered as in transit in {1}",
id, m_mod.Scene.RegionInfo.RegionName));
AgentTransferState oldState = m_agentsInTransit[id];
bool transitionOkay = false;
if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
transitionOkay = true;
else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing)
transitionOkay = true;
else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring)
transitionOkay = true;
if (transitionOkay)
m_agentsInTransit[id] = newState;
else
throw new Exception(
string.Format(
"Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}",
id, oldState, newState, m_mod.Scene.RegionInfo.RegionName));
}
}
internal bool IsInTransit(UUID id)
{
lock (m_agentsInTransit)
return m_agentsInTransit.ContainsKey(id);
}
/// <summary>
/// Removes an agent from the transit state machine.
/// </summary>
/// <param name='id'></param>
/// <returns>true if the agent was flagged as being teleported when this method was called, false otherwise</returns>
internal bool ResetFromTransit(UUID id)
{
lock (m_agentsInTransit)
{
if (m_agentsInTransit.ContainsKey(id))
{
AgentTransferState state = m_agentsInTransit[id];
if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination)
{
// FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed
// to be handled properly - ResetFromTransit() could be invoked at any step along the process
m_log.WarnFormat(
"[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}",
id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName);
// throw new Exception(
// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first",
// state, AgentTransferState.CleaningUp);
}
m_agentsInTransit.Remove(id);
m_log.DebugFormat(
"[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}",
id, m_mod.Scene.RegionInfo.RegionName);
return true;
}
}
m_log.WarnFormat(
"[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared",
id, m_mod.Scene.RegionInfo.RegionName);
return false;
}
internal bool WaitForAgentArrivedAtDestination(UUID id)
{
if (!m_mod.WaitForAgentArrivedAtDestination)
return true;
lock (m_agentsInTransit)
{
if (!IsInTransit(id))
throw new Exception(
string.Format(
"Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit",
id, m_mod.Scene.RegionInfo.RegionName));
AgentTransferState currentState = m_agentsInTransit[id];
if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination)
throw new Exception(
string.Format(
"Asked to wait for destination callback for agent with ID {0} in {1} but agent is in state {2}",
id, m_mod.Scene.RegionInfo.RegionName, currentState));
}
int count = 200;
// There should be no race condition here since no other code should be removing the agent transfer or
// changing the state to another other than Transferring => ReceivedAtDestination.
while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0)
{
// m_log.Debug(" >>> Waiting... " + count);
Thread.Sleep(100);
}
return count > 0;
}
internal void SetAgentArrivedAtDestination(UUID id)
{
lock (m_agentsInTransit)
{
if (!m_agentsInTransit.ContainsKey(id))
{
m_log.WarnFormat(
"[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but no teleport request is active",
m_mod.Scene.RegionInfo.RegionName, id);
return;
}
AgentTransferState currentState = m_agentsInTransit[id];
if (currentState == AgentTransferState.ReceivedAtDestination)
{
// An anomoly but don't make this an outright failure - destination region could be overzealous in sending notification.
m_log.WarnFormat(
"[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but notification has already previously been received",
m_mod.Scene.RegionInfo.RegionName, id);
}
else if (currentState != AgentTransferState.Transferring)
{
m_log.ErrorFormat(
"[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but agent is in state {2}",
m_mod.Scene.RegionInfo.RegionName, id, currentState);
return;
}
m_agentsInTransit[id] = AgentTransferState.ReceivedAtDestination;
}
}
}
}

View File

@@ -45,11 +45,11 @@ using Nini.Config;
namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
public class HGEntityTransferModule : EntityTransferModule, ISharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
public class HGEntityTransferModule
: EntityTransferModule, INonSharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool m_Initialized = false;
private int m_levelHGTeleport = 0;
private GatekeeperServiceConnector m_GatekeeperConnector;
@@ -64,6 +64,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public override void Initialise(IConfigSource source)
{
IConfig moduleConfig = source.Configs["Modules"];
if (moduleConfig != null)
{
string name = moduleConfig.GetString("EntityTransferModule", "");
@@ -82,10 +83,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public override void AddRegion(Scene scene)
{
base.AddRegion(scene);
if (m_Enabled)
{
scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
}
}
protected override void OnNewClient(IClientAPI client)
@@ -98,24 +98,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public override void RegionLoaded(Scene scene)
{
base.RegionLoaded(scene);
if (m_Enabled)
if (!m_Initialized)
{
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
m_Initialized = true;
}
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
}
public override void RemoveRegion(Scene scene)
{
base.AddRegion(scene);
if (m_Enabled)
{
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
}
}
if (m_Enabled)
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
}
#endregion
@@ -123,8 +117,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected override GridRegion GetFinalDestination(GridRegion region)
{
int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, region.RegionID);
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
@@ -135,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: GetHyperlinkRegion to Gatekeeper {0} failed", region.ServerURI);
return real_destination;
}
return region;
}
@@ -143,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
return true;
int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID);
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
return true;
@@ -156,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (logout)
{
// Log them out of this grid
m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
}
}
@@ -165,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
reason = string.Empty;
logout = false;
int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID);
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
{
// this user is going to another grid
@@ -205,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
// Let's find out if this is a foreign user or a local user
IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>();
IUserManagement uMan = Scene.RequestModuleInterface<IUserManagement>();
if (uMan != null && uMan.IsLocalGridUser(id))
{
// local grid user
@@ -262,19 +258,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}",
(lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position);
if (lm.Gatekeeper == string.Empty)
{
base.RequestTeleportLandmark(remoteClient, lm);
return;
}
GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
GridRegion info = Scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
// Local region?
if (info != null)
{
((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
return;
}
else
@@ -285,6 +283,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
GridRegion gatekeeper = new GridRegion();
gatekeeper.ServerURI = lm.Gatekeeper;
GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID));
if (finalDestination != null)
{
ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId);
@@ -314,49 +313,48 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
IUserAgentService security = new UserAgentServiceConnector(url);
return security.VerifyClient(aCircuit.SessionID, token);
}
else
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent {0} {1} does not have a HomeURI OH NO!", aCircuit.firstname, aCircuit.lastname);
else
{
m_log.DebugFormat(
"[HG ENTITY TRANSFER MODULE]: Agent {0} {1} does not have a HomeURI OH NO!",
aCircuit.firstname, aCircuit.lastname);
}
return false;
}
void OnConnectionClosed(IClientAPI obj)
{
if (obj.IsLoggingOut)
if (obj.SceneAgent.IsChildAgent)
return;
// Let's find out if this is a foreign user or a local user
IUserManagement uMan = Scene.RequestModuleInterface<IUserManagement>();
// UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, obj.AgentId);
if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
{
object sp = null;
if (obj.Scene.TryGetScenePresence(obj.AgentId, out sp))
{
if (((ScenePresence)sp).IsChildAgent)
return;
}
// local grid user
return;
}
// Let's find out if this is a foreign user or a local user
IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>();
UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, obj.AgentId);
if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
{
// local grid user
return;
}
AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
{
string url = aCircuit.ServiceURLs["HomeURI"].ToString();
IUserAgentService security = new UserAgentServiceConnector(url);
security.LogoutAgent(obj.AgentId, obj.SessionId);
//m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
}
else
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
{
string url = aCircuit.ServiceURLs["HomeURI"].ToString();
IUserAgentService security = new UserAgentServiceConnector(url);
security.LogoutAgent(obj.AgentId, obj.SessionId);
//m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
}
else
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: HomeURI not found for agent {0} logout", obj.AgentId);
}
}
#endregion
private GridRegion MakeRegion(AgentCircuitData aCircuit)
{
GridRegion region = new GridRegion();
@@ -373,6 +371,5 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0);
return region;
}
}
}
}

View File

@@ -364,8 +364,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
{
m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name);
InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
List<UUID> fids = new List<UUID>();
List<UUID> iids = new List<UUID>();
List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
foreach (InventoryFolderBase f in content.Folders)
@@ -395,4 +394,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
#endregion
}
}
}

View File

@@ -175,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
sbyte assetType,
byte wearableType, uint nextOwnerMask, int creationDate)
{
m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID);
m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}", name, folderID);
if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
return;
@@ -210,13 +210,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
else
{
m_log.ErrorFormat(
"ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
"[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
remoteClient.AgentId);
}
}
else
{
IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface<IAgentAssetTransactions>();
IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
if (agentTransactions != null)
{
agentTransactions.HandleItemCreationFromTransaction(
@@ -288,16 +288,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
else
{
m_log.ErrorFormat(
"[AGENT INVENTORY]: Could not find item {0} for caps inventory update",
"[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update",
itemID);
}
return UUID.Zero;
}
public virtual UUID CopyToInventory(DeRezAction action, UUID folderID,
List<SceneObjectGroup> objectGroups, IClientAPI remoteClient)
public virtual List<InventoryItemBase> CopyToInventory(
DeRezAction action, UUID folderID,
List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment)
{
List<InventoryItemBase> copiedItems = new List<InventoryItemBase>();
Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
if (CoalesceMultipleObjectsToInventory)
@@ -324,16 +327,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
}
// This is method scoped and will be returned. It will be the
// last created asset id
UUID assetID = UUID.Zero;
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}",
// bundlesToCopy.Count, folderID, action, remoteClient.Name);
// Each iteration is really a separate asset being created,
// with distinct destinations as well.
foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient);
copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment));
return assetID;
return copiedItems;
}
/// <summary>
@@ -344,12 +347,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
/// <param name="folderID"></param>
/// <param name="objlist"></param>
/// <param name="remoteClient"></param>
/// <returns></returns>
protected UUID CopyBundleToInventory(
DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient)
/// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents
/// attempted serialization of any script state which would abort any operating scripts.</param>
/// <returns>The inventory item created by the copy</returns>
protected InventoryItemBase CopyBundleToInventory(
DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
bool asAttachment)
{
UUID assetID = UUID.Zero;
CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
@@ -385,18 +389,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
string itemXml;
// If we're being called from a script, then trying to serialize that same script's state will not complete
// in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
// the client/server crashes rather than logging out normally, the attachment's scripts will resume
// without state on relog. Arguably, this is what we want anyway.
if (objlist.Count > 1)
itemXml = CoalescedSceneObjectsSerializer.ToXml(coa);
itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment);
else
itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]);
itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
// Restore the position of each group now that it has been stored to inventory.
foreach (SceneObjectGroup objectGroup in objlist)
objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Created item is {0}",
// item != null ? item.ID.ToString() : "NULL");
if (item == null)
return UUID.Zero;
return null;
// Can't know creator is the same, so null it in inventory
if (objlist.Count > 1)
@@ -406,7 +419,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
else
{
item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
item.CreatorData = objlist[0].RootPart.CreatorData;
item.SaleType = objlist[0].RootPart.ObjectSaleType;
item.SalePrice = objlist[0].RootPart.SalePrice;
}
@@ -419,8 +433,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
objlist[0].OwnerID.ToString());
m_Scene.AssetService.Store(asset);
item.AssetID = asset.FullID;
assetID = asset.FullID;
item.AssetID = asset.FullID;
if (DeRezAction.SaveToExistingUserInventoryItem == action)
{
@@ -453,9 +466,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// This is a hook to do some per-asset post-processing for subclasses that need that
if (remoteClient != null)
ExportAsset(remoteClient.AgentId, assetID);
ExportAsset(remoteClient.AgentId, asset.FullID);
return assetID;
return item;
}
protected virtual void ExportAsset(UUID agentID, UUID assetID)
@@ -592,7 +605,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (null == item)
{
m_log.DebugFormat(
"[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
"[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.",
so.Name, so.UUID);
return null;
@@ -643,7 +656,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
{
// Catch all. Use lost & found
//
folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
}
}
@@ -694,7 +706,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (item == null)
{
m_log.WarnFormat(
"[InventoryAccessModule]: Could not find item {0} for {1} in RezObject()",
"[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()",
itemID, remoteClient.Name);
return null;
@@ -726,7 +738,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
else
{
m_log.WarnFormat(
"[InventoryAccessModule]: Could not find asset {0} for {1} in RezObject()",
"[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()",
assetID, remoteClient.Name);
}
@@ -803,7 +815,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group = objlist[i];
// m_log.DebugFormat(
// "[InventoryAccessModule]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
// group.Name, group.LocalId, group.UUID,
// group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask,
// remoteClient.Name);
@@ -811,7 +823,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// Vector3 storedPosition = group.AbsolutePosition;
if (group.UUID == UUID.Zero)
{
m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3");
m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
}
foreach (SceneObjectPart part in group.Parts)
@@ -874,7 +886,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
// m_log.DebugFormat(
// "[InventoryAccessModule]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
// "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
// group.Name, group.LocalId, group.UUID,
// group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask,
// remoteClient.Name);
@@ -964,8 +976,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
so.FromFolderID = item.Folder;
// Console.WriteLine("rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
if ((rootPart.OwnerID != item.Owner) ||
(item.CurrentPermissions & 16) != 0)
@@ -1088,7 +1101,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (assetRequestItem.AssetID != requestID)
{
m_log.WarnFormat(
"[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}",
"[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}",
Name, requestID, itemID, assetRequestItem.AssetID);
return false;

View File

@@ -49,7 +49,16 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public bool Enabled { get; private set; }
private Scene m_scene;
private readonly List<IMonitor> m_monitors = new List<IMonitor>();
/// <summary>
/// These are monitors where we know the static details in advance.
/// </summary>
/// <remarks>
/// Dynamic monitors also exist (we don't know any of the details of what stats we get back here)
/// but these are currently hardcoded.
/// </remarks>
private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>();
private readonly List<IAlert> m_alerts = new List<IAlert>();
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -84,9 +93,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public void DebugMonitors(string module, string[] args)
{
foreach (IMonitor monitor in m_monitors)
foreach (IMonitor monitor in m_staticMonitors)
{
m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue());
m_log.InfoFormat(
"[MONITOR MODULE]: {0} reports {1} = {2}",
m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
}
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
{
m_log.InfoFormat(
"[MONITOR MODULE]: {0} reports {1} = {2}",
m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
}
}
@@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
{
string monID = (string) request["monitor"];
foreach (IMonitor monitor in m_monitors)
foreach (IMonitor monitor in m_staticMonitors)
{
string elemName = monitor.ToString();
if (elemName.StartsWith(monitor.GetType().Namespace))
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
if (elemName == monID || monitor.ToString() == monID)
{
Hashtable ereply3 = new Hashtable();
@@ -123,6 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
}
}
// FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
// is even doing. Why are we inspecting the type of the monitor???
// No monitor with that name
Hashtable ereply2 = new Hashtable();
@@ -134,12 +156,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
}
string xml = "<data>";
foreach (IMonitor monitor in m_monitors)
foreach (IMonitor monitor in m_staticMonitors)
{
string elemName = monitor.GetName();
xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
}
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
{
xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
}
xml += "</data>";
Hashtable ereply = new Hashtable();
@@ -156,20 +184,20 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
if (!Enabled)
return;
m_monitors.Add(new AgentCountMonitor(m_scene));
m_monitors.Add(new ChildAgentCountMonitor(m_scene));
m_monitors.Add(new GCMemoryMonitor());
m_monitors.Add(new ObjectCountMonitor(m_scene));
m_monitors.Add(new PhysicsFrameMonitor(m_scene));
m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
m_monitors.Add(new PWSMemoryMonitor());
m_monitors.Add(new ThreadCountMonitor());
m_monitors.Add(new TotalFrameMonitor(m_scene));
m_monitors.Add(new EventFrameMonitor(m_scene));
m_monitors.Add(new LandFrameMonitor(m_scene));
m_monitors.Add(new LastFrameTimeMonitor(m_scene));
m_staticMonitors.Add(new AgentCountMonitor(m_scene));
m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
m_staticMonitors.Add(new GCMemoryMonitor());
m_staticMonitors.Add(new ObjectCountMonitor(m_scene));
m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene));
m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
m_staticMonitors.Add(new PWSMemoryMonitor());
m_staticMonitors.Add(new ThreadCountMonitor());
m_staticMonitors.Add(new TotalFrameMonitor(m_scene));
m_staticMonitors.Add(new EventFrameMonitor(m_scene));
m_staticMonitors.Add(new LandFrameMonitor(m_scene));
m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"TimeDilationMonitor",
@@ -177,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[0],
m => m.GetValue().ToString()));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"SimFPSMonitor",
@@ -185,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[1],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PhysicsFPSMonitor",
@@ -193,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[2],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"AgentUpdatesPerSecondMonitor",
@@ -201,15 +229,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[3],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"ObjectUpdatesPerSecondMonitor",
"Object Updates",
m => m.Scene.StatsReporter.LastReportedObjectUpdates,
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ActiveObjectCountMonitor",
@@ -217,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[7],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ActiveScriptsMonitor",
@@ -225,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[19],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ScriptEventsPerSecondMonitor",
@@ -233,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[20],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"InPacketsPerSecondMonitor",
@@ -241,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[13],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"OutPacketsPerSecondMonitor",
@@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[14],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"UnackedBytesMonitor",
@@ -257,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[15],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PendingDownloadsMonitor",
@@ -265,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[17],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PendingUploadsMonitor",
@@ -273,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[18],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"TotalFrameTimeMonitor",
@@ -281,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[8],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"NetFrameTimeMonitor",
@@ -289,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[9],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PhysicsFrameTimeMonitor",
@@ -297,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[10],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"SimulationFrameTimeMonitor",
@@ -305,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[12],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"AgentFrameTimeMonitor",
@@ -313,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[16],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ImagesFrameTimeMonitor",
@@ -321,7 +341,15 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[11],
m => string.Format("{0} ms", m.GetValue())));
m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"SpareFrameTimeMonitor",
"Spare Frame Time",
m => m.Scene.StatsReporter.LastReportedSimStats[21],
m => string.Format("{0} ms", m.GetValue())));
m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
foreach (IAlert alert in m_alerts)
{

View File

@@ -0,0 +1,224 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Reflection;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
using Nini.Config;
using Mono.Addins;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Region.CoreModules.World.LightShare
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EnvironmentModule")]
public class EnvironmentModule : INonSharedRegionModule, IEnvironmentModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene = null;
private UUID regionID = UUID.Zero;
private static bool Enabled = false;
private static readonly string capsName = "EnvironmentSettings";
private static readonly string capsBase = "/CAPS/0020/";
private LLSDEnvironmentSetResponse setResponse = null;
#region INonSharedRegionModule
public void Initialise(IConfigSource source)
{
IConfig config = source.Configs["ClientStack.LindenCaps"];
if (null == config)
return;
if (config.GetString("Cap_EnvironmentSettings", String.Empty) != "localhost")
{
m_log.InfoFormat("[{0}]: Module is disabled.", Name);
return;
}
Enabled = true;
m_log.InfoFormat("[{0}]: Module is enabled.", Name);
}
public void Close()
{
}
public string Name
{
get { return "EnvironmentModule"; }
}
public Type ReplaceableInterface
{
get { return null; }
}
public void AddRegion(Scene scene)
{
if (!Enabled)
return;
scene.RegisterModuleInterface<IEnvironmentModule>(this);
m_scene = scene;
regionID = scene.RegionInfo.RegionID;
}
public void RegionLoaded(Scene scene)
{
if (!Enabled)
return;
setResponse = new LLSDEnvironmentSetResponse();
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
}
public void RemoveRegion(Scene scene)
{
if (Enabled)
return;
scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene = null;
}
#endregion
#region IEnvironmentModule
public void ResetEnvironmentSettings(UUID regionUUID)
{
if (!Enabled)
return;
m_scene.SimulationDataService.RemoveRegionEnvironmentSettings(regionUUID);
}
#endregion
#region Events
private void OnRegisterCaps(UUID agentID, Caps caps)
{
// m_log.DebugFormat("[{0}]: Register capability for agentID {1} in region {2}",
// Name, agentID, caps.RegionName);
string capsPath = capsBase + UUID.Random();
// Get handler
caps.RegisterHandler(
capsName,
new RestStreamHandler(
"GET",
capsPath,
(request, path, param, httpRequest, httpResponse)
=> GetEnvironmentSettings(request, path, param, agentID, caps),
capsName,
agentID.ToString()));
// Set handler
caps.HttpListener.AddStreamHandler(
new RestStreamHandler(
"POST",
capsPath,
(request, path, param, httpRequest, httpResponse)
=> SetEnvironmentSettings(request, path, param, agentID, caps),
capsName,
agentID.ToString()));
}
#endregion
private string GetEnvironmentSettings(string request, string path, string param,
UUID agentID, Caps caps)
{
// m_log.DebugFormat("[{0}]: Environment GET handle for agentID {1} in region {2}",
// Name, agentID, caps.RegionName);
string env = String.Empty;
try
{
env = m_scene.SimulationDataService.LoadRegionEnvironmentSettings(regionID);
}
catch (Exception e)
{
m_log.ErrorFormat("[{0}]: Unable to load environment settings for region {1}, Exception: {2} - {3}",
Name, caps.RegionName, e.Message, e.StackTrace);
}
if (String.IsNullOrEmpty(env))
env = EnvironmentSettings.EmptySettings(UUID.Zero, regionID);
return env;
}
private string SetEnvironmentSettings(string request, string path, string param,
UUID agentID, Caps caps)
{
// m_log.DebugFormat("[{0}]: Environment SET handle from agentID {1} in region {2}",
// Name, agentID, caps.RegionName);
setResponse.regionID = regionID;
setResponse.success = false;
if (!m_scene.Permissions.CanIssueEstateCommand(agentID, false))
{
setResponse.fail_reason = "Insufficient estate permissions, settings has not been saved.";
return LLSDHelpers.SerialiseLLSDReply(setResponse);
}
try
{
m_scene.SimulationDataService.StoreRegionEnvironmentSettings(regionID, request);
setResponse.success = true;
m_log.InfoFormat("[{0}]: New Environment settings has been saved from agentID {1} in region {2}",
Name, agentID, caps.RegionName);
}
catch (Exception e)
{
m_log.ErrorFormat("[{0}]: Environment settings has not been saved for region {1}, Exception: {2} - {3}",
Name, caps.RegionName, e.Message, e.StackTrace);
setResponse.success = false;
setResponse.fail_reason = String.Format("Environment Set for region {0} has failed, settings has not been saved.", caps.RegionName);
}
return LLSDHelpers.SerialiseLLSDReply(setResponse);
}
}
}

View File

@@ -79,7 +79,6 @@
<RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" />
<RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \
<RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \
<RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" /> \
</Extension>

View File

@@ -41,13 +41,39 @@ using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
{
/// <summary>
/// Data describing an external URL set up by a script.
/// </summary>
public class UrlData
{
/// <summary>
/// Scene object part hosting the script
/// </summary>
public UUID hostID;
/// <summary>
/// The item ID of the script that requested the URL.
/// </summary>
public UUID itemID;
/// <summary>
/// The script engine that runs the script.
/// </summary>
public IScriptModule engine;
/// <summary>
/// The generated URL.
/// </summary>
public string url;
/// <summary>
/// The random UUID component of the generated URL.
/// </summary>
public UUID urlcode;
/// <summary>
/// The external requests currently being processed or awaiting retrieval for this URL.
/// </summary>
public Dictionary<UUID, RequestData> requests;
}
@@ -64,19 +90,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public string uri;
}
/// <summary>
/// This module provides external URLs for in-world scripts.
/// </summary>
public class UrlModule : ISharedRegionModule, IUrlModule
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<UUID, UrlData> m_RequestMap =
new Dictionary<UUID, UrlData>();
private Dictionary<string, UrlData> m_UrlMap =
new Dictionary<string, UrlData>();
/// <summary>
/// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID
/// randomly generated when a request is received for this URL.
/// </summary>
/// <remarks>
/// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with
/// m_UrlMap
/// </remarks>
private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>();
/// <summary>
/// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL
/// </summary>
private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>();
/// <summary>
/// Maximum number of external urls that can be set up by this module.
/// </summary>
private int m_TotalUrls = 100;
private uint https_port = 0;
@@ -84,6 +124,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
private IHttpServer m_HttpsServer = null;
private string m_ExternalHostNameForLSL = "";
public string ExternalHostNameForLSL
{
get { return m_ExternalHostNameForLSL; }
}
public Type ReplaceableInterface
{
@@ -99,10 +143,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
{
m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName);
bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener",false);
if (ssl_enabled)
{
https_port = (uint) config.Configs["Network"].GetInt("https_port",0);
}
IConfig llFunctionsConfig = config.Configs["LL-Functions"];
if (llFunctionsConfig != null)
m_TotalUrls = llFunctionsConfig.GetInt("max_external_urls_per_simulator", m_TotalUrls);
}
public void PostInitialise()
@@ -213,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
urlData.urlcode = urlcode;
urlData.requests = new Dictionary<UUID, RequestData>();
m_UrlMap[url] = urlData;
string uri = "/lslhttps/" + urlcode.ToString() + "/";
@@ -257,39 +304,47 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public void HttpResponse(UUID request, int status, string body)
{
if (m_RequestMap.ContainsKey(request))
lock (m_UrlMap)
{
UrlData urlData = m_RequestMap[request];
urlData.requests[request].responseCode = status;
urlData.requests[request].responseBody = body;
//urlData.requests[request].ev.Set();
urlData.requests[request].requestDone =true;
}
else
{
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
if (m_RequestMap.ContainsKey(request))
{
UrlData urlData = m_RequestMap[request];
urlData.requests[request].responseCode = status;
urlData.requests[request].responseBody = body;
//urlData.requests[request].ev.Set();
urlData.requests[request].requestDone =true;
}
else
{
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
}
}
}
public string GetHttpHeader(UUID requestId, string header)
{
if (m_RequestMap.ContainsKey(requestId))
lock (m_UrlMap)
{
UrlData urlData=m_RequestMap[requestId];
string value;
if (urlData.requests[requestId].headers.TryGetValue(header,out value))
return value;
}
else
{
m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
if (m_RequestMap.ContainsKey(requestId))
{
UrlData urlData = m_RequestMap[requestId];
string value;
if (urlData.requests[requestId].headers.TryGetValue(header, out value))
return value;
}
else
{
m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
}
}
return String.Empty;
}
public int GetFreeUrls()
{
return m_TotalUrls - m_UrlMap.Count;
lock (m_UrlMap)
return m_TotalUrls - m_UrlMap.Count;
}
public void ScriptRemoved(UUID itemID)
@@ -328,6 +383,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
{
RemoveUrl(url.Value);
removeURLs.Add(url.Key);
foreach (UUID req in url.Value.requests.Keys)
m_RequestMap.Remove(req);
}
@@ -338,145 +394,165 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
}
}
private void RemoveUrl(UrlData data)
{
m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/");
}
private Hashtable NoEvents(UUID requestID, UUID sessionID)
{
Hashtable response = new Hashtable();
UrlData url;
lock (m_RequestMap)
UrlData urlData;
lock (m_UrlMap)
{
// We need to return a 404 here in case the request URL was removed at exactly the same time that a
// request was made. In this case, the request thread can outrace llRemoveURL() and still be polling
// for the request ID.
if (!m_RequestMap.ContainsKey(requestID))
return response;
url = m_RequestMap[requestID];
}
if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
{
response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
//remove from map
lock (url)
{
url.requests.Remove(requestID);
m_RequestMap.Remove(requestID);
response["int_response_code"] = 404;
response["str_response_string"] = "";
response["keepalive"] = false;
response["reusecontext"] = false;
return response;
}
return response;
urlData = m_RequestMap[requestID];
if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
{
response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
//remove from map
urlData.requests.Remove(requestID);
m_RequestMap.Remove(requestID);
return response;
}
}
return response;
}
private bool HasEvents(UUID requestID, UUID sessionID)
{
UrlData url=null;
lock (m_RequestMap)
lock (m_UrlMap)
{
// We return true here because an external URL request that happened at the same time as an llRemoveURL()
// can still make it through to HttpRequestHandler(). That will return without setting up a request
// when it detects that the URL has been removed. The poller, however, will continue to ask for
// events for that request, so here we will signal that there are events and in GetEvents we will
// return a 404.
if (!m_RequestMap.ContainsKey(requestID))
{
return false;
return true;
}
url = m_RequestMap[requestID];
if (!url.requests.ContainsKey(requestID))
UrlData urlData = m_RequestMap[requestID];
if (!urlData.requests.ContainsKey(requestID))
{
return false;
return true;
}
// Trigger return of timeout response.
if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
{
return true;
}
return urlData.requests[requestID].requestDone;
}
if (System.Environment.TickCount-url.requests[requestID].startTime>25000)
{
return true;
}
if (url.requests[requestID].requestDone)
return true;
else
return false;
}
private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
{
UrlData url = null;
RequestData requestData = null;
Hashtable response;
lock (m_RequestMap)
lock (m_UrlMap)
{
UrlData url = null;
RequestData requestData = null;
if (!m_RequestMap.ContainsKey(requestID))
return NoEvents(requestID,sessionID);
return NoEvents(requestID, sessionID);
url = m_RequestMap[requestID];
requestData = url.requests[requestID];
}
if (!requestData.requestDone)
return NoEvents(requestID,sessionID);
Hashtable response = new Hashtable();
if (!requestData.requestDone)
return NoEvents(requestID, sessionID);
if (System.Environment.TickCount - requestData.startTime > 25000)
{
response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout";
response = new Hashtable();
if (System.Environment.TickCount - requestData.startTime > 25000)
{
response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
return response;
}
//put response
response["int_response_code"] = requestData.responseCode;
response["str_response_string"] = requestData.responseBody;
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
return response;
}
//put response
response["int_response_code"] = requestData.responseCode;
response["str_response_string"] = requestData.responseBody;
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
//remove from map
lock (url)
{
//remove from map
url.requests.Remove(requestID);
m_RequestMap.Remove(requestID);
}
return response;
}
public void HttpRequestHandler(UUID requestID, Hashtable request)
{
lock (request)
{
string uri = request["uri"].ToString();
bool is_ssl = uri.Contains("lslhttps");
string uri = request["uri"].ToString();
bool is_ssl = uri.Contains("lslhttps");
try
{
Hashtable headers = (Hashtable)request["headers"];
try
{
Hashtable headers = (Hashtable)request["headers"];
// string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/";
int pos1 = uri.IndexOf("/");// /lslhttp
int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
string uri_tmp = uri.Substring(0, pos3 + 1);
//HTTP server code doesn't provide us with QueryStrings
string pathInfo;
string queryString;
queryString = "";
int pos1 = uri.IndexOf("/");// /lslhttp
int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
string uri_tmp = uri.Substring(0, pos3 + 1);
//HTTP server code doesn't provide us with QueryStrings
string pathInfo;
string queryString;
queryString = "";
pathInfo = uri.Substring(pos3);
pathInfo = uri.Substring(pos3);
UrlData url = null;
if (!is_ssl)
url = m_UrlMap["http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp];
UrlData urlData = null;
lock (m_UrlMap)
{
string url;
if (is_ssl)
url = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
else
url = m_UrlMap["https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp];
url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
// Avoid a race - the request URL may have been released via llRequestUrl() whilst this
// request was being processed.
if (!m_UrlMap.TryGetValue(url, out urlData))
return;
//for llGetHttpHeader support we need to store original URI here
//to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
@@ -496,6 +572,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
string value = (string)header.Value;
requestData.headers.Add(key, value);
}
foreach (DictionaryEntry de in request)
{
if (de.Key.ToString() == "querystringkeys")
@@ -509,11 +586,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
queryString = queryString + key + "=" + val + "&";
}
}
if (queryString.Length > 1)
queryString = queryString.Substring(0, queryString.Length - 1);
}
}
//if this machine is behind DNAT/port forwarding, currently this is being
@@ -521,34 +597,23 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
requestData.headers["x-path-info"] = pathInfo;
requestData.headers["x-query-string"] = queryString;
requestData.headers["x-script-url"] = url.url;
//requestData.ev = new ManualResetEvent(false);
lock (url.requests)
{
url.requests.Add(requestID, requestData);
}
lock (m_RequestMap)
{
//add to request map
m_RequestMap.Add(requestID, url);
}
url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
//send initial response?
// Hashtable response = new Hashtable();
return;
requestData.headers["x-script-url"] = urlData.url;
urlData.requests.Add(requestID, requestData);
m_RequestMap.Add(requestID, urlData);
}
catch (Exception we)
{
//Hashtable response = new Hashtable();
m_log.Warn("[HttpRequestHandler]: http-in request failed");
m_log.Warn(we.Message);
m_log.Warn(we.StackTrace);
}
urlData.engine.PostScriptEvent(
urlData.itemID,
"http_request",
new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
}
catch (Exception we)
{
//Hashtable response = new Hashtable();
m_log.Warn("[HttpRequestHandler]: http-in request failed");
m_log.Warn(we.Message);
m_log.Warn(we.StackTrace);
}
}
@@ -557,4 +622,4 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
ScriptRemoved(itemID);
}
}
}
}

View File

@@ -131,11 +131,12 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
{
// Start http server
// Attach xmlrpc handlers
m_log.Info("[XML RPC MODULE]: " +
"Starting up XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands.");
BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort);
// m_log.InfoFormat(
// "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.",
// m_remoteDataPort);
IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort);
httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
httpServer.Start();
}
}

View File

@@ -122,7 +122,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
Object[] args = new Object[] { m_Config };
IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
// IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args)
ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);

View File

@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
if (!m_Enabled)
return;
m_log.Info("[LAND IN CONNECTOR]: Starting...");
// m_log.Info("[LAND IN CONNECTOR]: Starting...");
}
public void Close()

View File

@@ -74,7 +74,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour
if (!m_Enabled)
return;
m_log.Info("[NEIGHBOUR IN CONNECTOR]: Starting...");
// m_log.Info("[NEIGHBOUR IN CONNECTOR]: Starting...");
}
public void Close()

View File

@@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
m_aScene = scene;
scene.RegisterModuleInterface<IAssetService>(this);
m_aScene.RegisterModuleInterface<IAssetService>(this);
}
public void RemoveRegion(Scene scene)

View File

@@ -41,8 +41,7 @@ using OpenMetaverse;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
{
public class LocalGridServicesConnector :
ISharedRegionModule, IGridService
public class LocalGridServicesConnector : ISharedRegionModule, IGridService
{
private static readonly ILog m_log =
LogManager.GetLogger(
@@ -51,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
private IGridService m_GridService;
private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
private bool m_Enabled = false;
private bool m_Enabled;
public LocalGridServicesConnector()
{
@@ -59,7 +58,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public LocalGridServicesConnector(IConfigSource source)
{
m_log.Debug("[LOCAL GRID CONNECTOR]: LocalGridServicesConnector instantiated");
m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector instantiated directly.");
InitialiseService(source);
}
@@ -84,8 +83,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
if (name == Name)
{
InitialiseService(source);
m_Enabled = true;
m_log.Info("[LOCAL GRID CONNECTOR]: Local grid connector enabled");
m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
}
}
}
@@ -95,7 +93,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
IConfig assetConfig = source.Configs["GridService"];
if (assetConfig == null)
{
m_log.Error("[LOCAL GRID CONNECTOR]: GridService missing from OpenSim.ini");
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
return;
}
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
if (serviceDll == String.Empty)
{
m_log.Error("[LOCAL GRID CONNECTOR]: No LocalServiceModule named in section GridService");
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
return;
}
@@ -115,16 +113,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
if (m_GridService == null)
{
m_log.Error("[LOCAL GRID CONNECTOR]: Can't load grid service");
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
return;
}
m_Enabled = true;
}
public void PostInitialise()
{
// FIXME: We will still add this command even if we aren't enabled since RemoteGridServiceConnector
// will have instantiated us directly.
MainConsole.Instance.Commands.AddCommand("Regions", false, "show neighbours",
"show neighbours",
"Shows the local regions' neighbours", NeighboursCommand);
"Shows the local regions' neighbours", HandleShowNeighboursCommand);
}
public void Close()
@@ -133,17 +135,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public void AddRegion(Scene scene)
{
if (m_Enabled)
scene.RegisterModuleInterface<IGridService>(this);
if (!m_Enabled)
return;
scene.RegisterModuleInterface<IGridService>(this);
if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
m_log.ErrorFormat("[LOCAL GRID CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
else
m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
m_LocalCache[scene.RegionInfo.RegionID].Clear();
m_LocalCache.Remove(scene.RegionInfo.RegionID);
}
@@ -232,7 +239,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
#endregion
public void NeighboursCommand(string module, string[] cmdparams)
public void HandleShowNeighboursCommand(string module, string[] cmdparams)
{
System.Text.StringBuilder caps = new System.Text.StringBuilder();

View File

@@ -79,29 +79,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
public void OnConnectionClose(IClientAPI client)
{
if (client.IsLoggingOut)
{
object sp = null;
Vector3 position = new Vector3(128, 128, 0);
Vector3 lookat = new Vector3(0, 1, 0);
if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
{
if (sp is ScenePresence)
{
if (((ScenePresence)sp).IsChildAgent)
return;
position = ((ScenePresence)sp).AbsolutePosition;
lookat = ((ScenePresence)sp).Lookat;
}
}
// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
m_GridUserService.LoggedOut(client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, position, lookat);
}
if (client.SceneAgent.IsChildAgent)
return;
// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
m_GridUserService.LoggedOut(
client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
}
}
}

View File

@@ -125,13 +125,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
uint x, y;
Utils.LongToUInts(regionHandle, out x, out y);
m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: HelloNeighbour from region {0} to region at {1}-{2}",
thisRegion.RegionName, x / Constants.RegionSize, y / Constants.RegionSize);
foreach (Scene s in m_Scenes)
{
if (s.RegionInfo.RegionHandle == regionHandle)
{
m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize);
//m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
return s.IncomingHelloNeighbour(thisRegion);
}

View File

@@ -64,7 +64,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
scene.EventManager.OnNewClient -= OnNewClient;
m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID);
}
public void OnMakeRootAgent(ScenePresence sp)
@@ -80,18 +79,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
public void OnConnectionClose(IClientAPI client)
{
if (client.IsLoggingOut)
if (!client.SceneAgent.IsChildAgent)
{
object sp = null;
if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
{
if (sp is ScenePresence)
{
if (((ScenePresence)sp).IsChildAgent)
return;
}
}
// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
m_PresenceService.LogoutAgent(client.SessionId);
}

View File

@@ -26,6 +26,7 @@
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using log4net;
using Nini.Config;
@@ -41,22 +42,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// Version of this service
/// <summary>
/// Version of this service
/// </summary>
private const string m_Version = "SIMULATION/0.1";
private List<Scene> m_sceneList = new List<Scene>();
private IEntityTransferModule m_AgentTransferModule;
protected IEntityTransferModule AgentTransferModule
{
get
{
if (m_AgentTransferModule == null)
m_AgentTransferModule = m_sceneList[0].RequestModuleInterface<IEntityTransferModule>();
return m_AgentTransferModule;
}
}
/// <summary>
/// Map region ID to scene.
/// </summary>
private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
/// <summary>
/// Is this module enabled?
/// </summary>
private bool m_ModuleEnabled = false;
#region IRegionModule
@@ -129,12 +128,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
/// <param name="scene"></param>
public void RemoveScene(Scene scene)
{
lock (m_sceneList)
lock (m_scenes)
{
if (m_sceneList.Contains(scene))
{
m_sceneList.Remove(scene);
}
if (m_scenes.ContainsKey(scene.RegionInfo.RegionID))
m_scenes.Remove(scene.RegionInfo.RegionID);
else
m_log.WarnFormat(
"[LOCAL SIMULATION CONNECTOR]: Tried to remove region {0} but it was not present",
scene.RegionInfo.RegionName);
}
}
@@ -144,13 +145,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
/// <param name="scene"></param>
public void Init(Scene scene)
{
if (!m_sceneList.Contains(scene))
lock (m_scenes)
{
lock (m_sceneList)
{
m_sceneList.Add(scene);
}
if (!m_scenes.ContainsKey(scene.RegionInfo.RegionID))
m_scenes[scene.RegionInfo.RegionID] = scene;
else
m_log.WarnFormat(
"[LOCAL SIMULATION CONNECTOR]: Tried to add region {0} but it is already present",
scene.RegionInfo.RegionName);
}
}
@@ -158,15 +160,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#region ISimulation
public IScene GetScene(ulong regionhandle)
public IScene GetScene(UUID regionId)
{
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(regionId))
{
if (s.RegionInfo.RegionHandle == regionhandle)
return s;
return m_scenes[regionId];
}
else
{
// FIXME: This was pre-existing behaviour but possibly not a good idea, since it hides an error rather
// than making it obvious and fixable. Need to see if the error message comes up in practice.
Scene s = m_scenes.Values.ToArray()[0];
m_log.ErrorFormat(
"[LOCAL SIMULATION CONNECTOR]: Region with id {0} not found. Returning {1} {2} instead",
regionId, s.RegionInfo.RegionName, s.RegionInfo.RegionID);
return s;
}
// ? weird. should not happen
return m_sceneList[0];
}
public ISimulationService GetInnerService()
@@ -187,13 +198,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(destination.RegionID))
{
if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
// m_log.DebugFormat("[LOCAL SIMULATION CONNECTOR]: Found region {0} to send SendCreateChildAgent", destination.RegionName);
return s.NewUserConnection(aCircuit, teleportFlags, out reason);
}
return m_scenes[destination.RegionID].NewUserConnection(aCircuit, teleportFlags, out reason);
}
reason = "Did not find region " + destination.RegionName;
@@ -205,17 +213,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
if (destination == null)
return false;
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(destination.RegionID))
{
if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
// m_log.DebugFormat(
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
s.IncomingChildAgentDataUpdate(cAgentData);
return true;
}
return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData);
}
// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle);
@@ -231,11 +235,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
// simulator so when we receive the update we need to hand it to each of the
// scenes; scenes each check to see if the is a scene presence for the avatar
// note that we really don't need the GridRegion for this call
foreach (Scene s in m_sceneList)
foreach (Scene s in m_scenes.Values)
{
//m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
s.IncomingChildAgentDataUpdate(cAgentData);
}
//m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
return true;
}
@@ -247,14 +252,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
if (destination == null)
return false;
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(destination.RegionID))
{
if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
return s.IncomingRetrieveRootAgent(id, out agent);
}
// m_log.DebugFormat(
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
return m_scenes[destination.RegionID].IncomingRetrieveRootAgent(id, out agent);
}
//m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
return false;
}
@@ -266,27 +272,31 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
if (destination == null)
return false;
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(destination.RegionID))
{
if (s.RegionInfo.RegionID == destination.RegionID)
return s.QueryAccess(id, position, out reason);
// m_log.DebugFormat(
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
return m_scenes[destination.RegionID].QueryAccess(id, position, out reason);
}
//m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess");
return false;
}
public bool ReleaseAgent(UUID origin, UUID id, string uri)
public bool ReleaseAgent(UUID originId, UUID agentId, string uri)
{
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(originId))
{
if (s.RegionInfo.RegionID == origin)
{
// m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent");
AgentTransferModule.AgentArrivedAtDestination(id);
return true;
// return s.IncomingReleaseAgent(id);
}
// m_log.DebugFormat(
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
m_scenes[originId].EntityTransferModule.AgentArrivedAtDestination(agentId);
return true;
}
//m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent " + origin);
return false;
}
@@ -296,17 +306,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
if (destination == null)
return false;
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(destination.RegionID))
{
if (s.RegionInfo.RegionID == destination.RegionID)
{
//m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
// Let's spawn a threadlet right here, because this may take
// a while
Util.FireAndForget(delegate { s.IncomingCloseAgent(id); });
return true;
}
// m_log.DebugFormat(
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); });
return true;
}
//m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
return false;
}
@@ -320,64 +329,49 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
if (destination == null)
return false;
foreach (Scene s in m_sceneList)
if (m_scenes.ContainsKey(destination.RegionID))
{
if (s.RegionInfo.RegionHandle == destination.RegionHandle)
// m_log.DebugFormat(
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
Scene s = m_scenes[destination.RegionID];
if (isLocalCall)
{
//m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject");
if (isLocalCall)
{
// We need to make a local copy of the object
ISceneObject sogClone = sog.CloneForNewScene();
sogClone.SetState(sog.GetStateSnapshot(), s);
return s.IncomingCreateObject(newPosition, sogClone);
}
else
{
// Use the object as it came through the wire
return s.IncomingCreateObject(newPosition, sog);
}
// We need to make a local copy of the object
ISceneObject sogClone = sog.CloneForNewScene();
sogClone.SetState(sog.GetStateSnapshot(), s);
return s.IncomingCreateObject(newPosition, sogClone);
}
else
{
// Use the object as it came through the wire
return s.IncomingCreateObject(newPosition, sog);
}
}
return false;
}
public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
{
if (destination == null)
return false;
foreach (Scene s in m_sceneList)
{
if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
return s.IncomingCreateObject(userID, itemID);
}
}
return false;
}
#endregion /* IInterregionComms */
#region Misc
public bool IsLocalRegion(ulong regionhandle)
{
foreach (Scene s in m_sceneList)
foreach (Scene s in m_scenes.Values)
if (s.RegionInfo.RegionHandle == regionhandle)
return true;
return false;
}
public bool IsLocalRegion(UUID id)
{
foreach (Scene s in m_sceneList)
if (s.RegionInfo.RegionID == id)
return true;
return false;
return m_scenes.ContainsKey(id);
}
#endregion
}
}
}

View File

@@ -151,9 +151,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#region IInterregionComms
public IScene GetScene(ulong handle)
public IScene GetScene(UUID regionId)
{
return m_localBackend.GetScene(handle);
return m_localBackend.GetScene(regionId);
}
public ISimulationService GetInnerService()
@@ -226,13 +226,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return m_remoteConnector.RetrieveAgent(destination, id, out agent);
return false;
}
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
{
reason = "Communications failure";
version = "Unknown";
if (destination == null)
return false;
@@ -245,7 +245,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return m_remoteConnector.QueryAccess(destination, id, position, out version, out reason);
return false;
}
public bool ReleaseAgent(UUID origin, UUID id, string uri)
@@ -301,13 +300,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
{
// Not Implemented
return false;
}
#endregion /* IInterregionComms */
}
}
}

View File

@@ -41,6 +41,7 @@ using OpenSim.Framework.Serialization.External;
using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.World.Archiver

View File

@@ -67,7 +67,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// Determine whether this archive will save assets. Default is true.
/// </summary>
public bool SaveAssets { get; set; }
protected ArchiverModule m_module;
protected Scene m_scene;
protected Stream m_saveStream;
protected Guid m_requestId;
@@ -75,13 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <summary>
/// Constructor
/// </summary>
/// <param name="scene"></param>
/// <param name="module">Calling module</param>
/// <param name="savePath">The path to which to save data.</param>
/// <param name="requestId">The id associated with this request</param>
/// <exception cref="System.IO.IOException">
/// If there was a problem opening a stream for the file specified by the savePath
/// </exception>
public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId)
public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId)
{
try
{
@@ -99,17 +100,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <summary>
/// Constructor.
/// </summary>
/// <param name="scene"></param>
/// <param name="module">Calling module</param>
/// <param name="saveStream">The stream to which to save data.</param>
/// <param name="requestId">The id associated with this request</param>
public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId)
public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId)
{
m_saveStream = saveStream;
}
protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId)
protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId)
{
m_scene = scene;
m_module = module;
// FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
// this.
if (m_module != null)
m_scene = m_module.Scene;
m_requestId = requestId;
SaveAssets = true;
@@ -364,32 +371,66 @@ namespace OpenSim.Region.CoreModules.World.Archiver
//if (majorVersion == 1)
//{
// m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR");
//}
//}
String s;
StringWriter sw = new StringWriter();
XmlTextWriter xtw = new XmlTextWriter(sw);
xtw.Formatting = Formatting.Indented;
xtw.WriteStartDocument();
xtw.WriteStartElement("archive");
xtw.WriteAttributeString("major_version", majorVersion.ToString());
xtw.WriteAttributeString("minor_version", minorVersion.ToString());
using (StringWriter sw = new StringWriter())
{
using (XmlTextWriter xtw = new XmlTextWriter(sw))
{
xtw.Formatting = Formatting.Indented;
xtw.WriteStartDocument();
xtw.WriteStartElement("archive");
xtw.WriteAttributeString("major_version", majorVersion.ToString());
xtw.WriteAttributeString("minor_version", minorVersion.ToString());
xtw.WriteStartElement("creation_info");
DateTime now = DateTime.UtcNow;
TimeSpan t = now - new DateTime(1970, 1, 1);
xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
xtw.WriteElementString("id", UUID.Random().ToString());
xtw.WriteEndElement();
xtw.WriteStartElement("creation_info");
DateTime now = DateTime.UtcNow;
TimeSpan t = now - new DateTime(1970, 1, 1);
xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
xtw.WriteElementString("id", UUID.Random().ToString());
xtw.WriteEndElement();
xtw.WriteStartElement("region_info");
xtw.WriteElementString("assets_included", SaveAssets.ToString());
bool isMegaregion;
Vector2 size;
IRegionCombinerModule rcMod = null;
xtw.WriteEndElement();
// FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
// this, possibly by doing control file creation somewhere else.
if (m_module != null)
rcMod = m_module.RegionCombinerModule;
xtw.Flush();
xtw.Close();
if (rcMod != null)
isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID);
else
isMegaregion = false;
String s = sw.ToString();
sw.Close();
if (isMegaregion)
size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
else
size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
xtw.WriteEndElement();
xtw.WriteElementString("assets_included", SaveAssets.ToString());
xtw.WriteEndElement();
xtw.Flush();
}
s = sw.ToString();
}
// if (m_scene != null)
// Console.WriteLine(
// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s);
return s;
}

View File

@@ -45,7 +45,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
public Scene Scene { get; private set; }
public IRegionCombinerModule RegionCombinerModule { get; private set; }
/// <value>
/// The file used to load and save an opensimulator archive if no filename has been specified
@@ -70,13 +71,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void AddRegion(Scene scene)
{
m_scene = scene;
m_scene.RegisterModuleInterface<IRegionArchiverModule>(this);
Scene = scene;
Scene.RegisterModuleInterface<IRegionArchiverModule>(this);
//m_log.DebugFormat("[ARCHIVER]: Enabled for region {0}", scene.RegionInfo.RegionName);
}
public void RegionLoaded(Scene scene)
{
RegionCombinerModule = scene.RequestModuleInterface<IRegionCombinerModule>();
}
public void RemoveRegion(Scene scene)
@@ -165,9 +167,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void ArchiveRegion(string savePath, Guid requestId, Dictionary<string, object> options)
{
m_log.InfoFormat(
"[ARCHIVER]: Writing archive for region {0} to {1}", m_scene.RegionInfo.RegionName, savePath);
"[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
new ArchiveWriteRequestPreparation(m_scene, savePath, requestId).ArchiveRegion(options);
new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options);
}
public void ArchiveRegion(Stream saveStream)
@@ -182,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
{
new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(options);
new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options);
}
public void DearchiveRegion(string loadPath)
@@ -193,9 +195,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId)
{
m_log.InfoFormat(
"[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath);
"[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
new ArchiveReadRequest(m_scene, loadPath, merge, skipAssets, requestId).DearchiveRegion();
new ArchiveReadRequest(Scene, loadPath, merge, skipAssets, requestId).DearchiveRegion();
}
public void DearchiveRegion(Stream loadStream)
@@ -205,7 +207,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId)
{
new ArchiveReadRequest(m_scene, loadStream, merge, skipAssets, requestId).DearchiveRegion();
new ArchiveReadRequest(Scene, loadStream, merge, skipAssets, requestId).DearchiveRegion();
}
}
}

View File

@@ -46,8 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
/// <summary>
/// Store for asset data we received before we get the metadata
/// </summary>

View File

@@ -291,6 +291,59 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
// TODO: Test presence of more files and contents of files.
}
/// <summary>
/// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
/// 2 can come after 3).
/// </summary>
[Test]
public void TestLoadOarUnorderedParts()
{
TestHelpers.InMethod();
UUID ownerId = TestHelpers.ParseTail(0xaaaa);
MemoryStream archiveWriteStream = new MemoryStream();
TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
tar.WriteFile(
ArchiveConstants.CONTROL_FILE_PATH,
new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
SceneObjectPart sop2
= SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
SceneObjectPart sop3
= SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
// Add the parts so they will be written out in reverse order to the oar
sog1.AddPart(sop3);
sop3.LinkNum = 3;
sog1.AddPart(sop2);
sop2.LinkNum = 2;
tar.WriteFile(
ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
SceneObjectSerializer.ToXml2Format(sog1));
tar.Close();
MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
lock (this)
{
m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
m_archiverModule.DearchiveRegion(archiveReadStream);
}
Assert.That(m_lastErrorMessage, Is.Null);
SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
Assert.That(part2.LinkNum, Is.EqualTo(2));
SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
Assert.That(part3.LinkNum, Is.EqualTo(3));
}
/// <summary>
/// Test loading an OpenSim Region Archive.
/// </summary>

View File

@@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
"set terrain heights <corner> <min> <max> [<x>] [<y>]",
"Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " +
"set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" +
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3.",
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
consoleSetTerrainHeights);
m_module.Scene.AddCommand(
@@ -143,6 +143,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
switch (corner)
{
case -1:
m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation1NW = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2NW = highValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation1SE = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2SE = highValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation1NE = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
break;
case 0:
m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;

View File

@@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene);
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
MediaEntry me = new MediaEntry();
m_module.SetMediaEntry(part, 1, me);
@@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
string homeUrl = "opensimulator.org";
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene);
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
MediaEntry me = new MediaEntry() { HomeURL = homeUrl };
m_module.SetMediaEntry(part, 1, me);

View File

@@ -29,8 +29,10 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using log4net;
using Mono.Addins;
using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
@@ -78,25 +80,32 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
m_scene = scene;
m_console = MainConsole.Instance;
m_console.Commands.AddCommand("Objects", false, "delete object owner",
"delete object owner <UUID>",
"Delete a scene object by owner", HandleDeleteObject);
m_console.Commands.AddCommand(
"Objects", false, "delete object owner",
"delete object owner <UUID>",
"Delete a scene object by owner", HandleDeleteObject);
m_console.Commands.AddCommand("Objects", false, "delete object creator",
"delete object creator <UUID>",
"Delete a scene object by creator", HandleDeleteObject);
m_console.Commands.AddCommand(
"Objects", false, "delete object creator",
"delete object creator <UUID>",
"Delete a scene object by creator", HandleDeleteObject);
m_console.Commands.AddCommand("Objects", false, "delete object uuid",
"delete object uuid <UUID>",
"Delete a scene object by uuid", HandleDeleteObject);
m_console.Commands.AddCommand(
"Objects", false, "delete object uuid",
"delete object uuid <UUID>",
"Delete a scene object by uuid", HandleDeleteObject);
m_console.Commands.AddCommand("Objects", false, "delete object name",
"delete object name <name>",
"Delete a scene object by name", HandleDeleteObject);
m_console.Commands.AddCommand(
"Objects", false, "delete object name",
"delete object name [--regex] <name>",
"Delete a scene object by name.",
"If --regex is specified then the name is treatead as a regular expression",
HandleDeleteObject);
m_console.Commands.AddCommand("Objects", false, "delete object outside",
"delete object outside",
"Delete all scene objects outside region boundaries", HandleDeleteObject);
m_console.Commands.AddCommand(
"Objects", false, "delete object outside",
"delete object outside",
"Delete all scene objects outside region boundaries", HandleDeleteObject);
m_console.Commands.AddCommand(
"Objects",
@@ -109,8 +118,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
"Objects",
false,
"show object name",
"show object name <name>",
"Show details of scene objects with the given name", HandleShowObjectByName);
"show object name [--regex] <name>",
"Show details of scene objects with the given name.",
"If --regex is specified then the name is treatead as a regular expression",
HandleShowObjectByName);
m_console.Commands.AddCommand(
"Objects",
@@ -123,8 +134,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
"Objects",
false,
"show part name",
"show part name <name>",
"Show details of scene object parts with the given name", HandleShowPartByName);
"show part name [--regex] <name>",
"Show details of scene object parts with the given name.",
"If --regex is specified then the name is treatead as a regular expression",
HandleShowPartByName);
}
public void RemoveRegion(Scene scene)
@@ -169,22 +182,38 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
m_console.OutputFormat(sb.ToString());
}
private void HandleShowObjectByName(string module, string[] cmd)
private void HandleShowObjectByName(string module, string[] cmdparams)
{
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
return;
if (cmd.Length < 4)
bool useRegex = false;
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
List<string> mainParams = options.Parse(cmdparams);
if (mainParams.Count < 4)
{
m_console.OutputFormat("Usage: show object name <name>");
m_console.OutputFormat("Usage: show object name [--regex] <name>");
return;
}
string name = cmd[3];
string name = mainParams[3];
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
Action<SceneObjectGroup> searchAction;
m_scene.ForEachSOG(so => { if (so.Name == name) { sceneObjects.Add(so); }});
if (useRegex)
{
Regex nameRegex = new Regex(name);
searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
}
else
{
searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
}
m_scene.ForEachSOG(searchAction);
if (sceneObjects.Count == 0)
{
@@ -235,22 +264,39 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
m_console.OutputFormat(sb.ToString());
}
private void HandleShowPartByName(string module, string[] cmd)
private void HandleShowPartByName(string module, string[] cmdparams)
{
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
return;
if (cmd.Length < 4)
bool useRegex = false;
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
List<string> mainParams = options.Parse(cmdparams);
if (mainParams.Count < 4)
{
m_console.OutputFormat("Usage: show part name <name>");
m_console.OutputFormat("Usage: show part name [--regex] <name>");
return;
}
string name = cmd[3];
string name = mainParams[3];
List<SceneObjectPart> parts = new List<SceneObjectPart>();
m_scene.ForEachSOG(so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }));
Action<SceneObjectGroup> searchAction;
if (useRegex)
{
Regex nameRegex = new Regex(name);
searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } });
}
else
{
searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } });
}
m_scene.ForEachSOG(searchAction);
if (parts.Count == 0)
{
@@ -312,96 +358,121 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
o = cmd[3];
}
List<SceneObjectGroup> deletes = new List<SceneObjectGroup>();
List<SceneObjectGroup> deletes = null;
UUID match;
bool requireConfirmation = true;
switch (mode)
{
case "owner":
if (!UUID.TryParse(o, out match))
return;
case "owner":
if (!UUID.TryParse(o, out match))
return;
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
if (g.OwnerID == match && !g.IsAttachment)
deletes.Add(g);
});
deletes = new List<SceneObjectGroup>();
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with owner {0}", match);
break;
case "creator":
if (!UUID.TryParse(o, out match))
return;
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
if (g.RootPart.CreatorID == match && !g.IsAttachment)
deletes.Add(g);
});
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with creator {0}", match);
break;
case "uuid":
if (!UUID.TryParse(o, out match))
return;
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
if (g.UUID == match && !g.IsAttachment)
deletes.Add(g);
});
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with uuid {0}", match);
break;
case "name":
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
if (g.RootPart.Name == o && !g.IsAttachment)
deletes.Add(g);
});
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with name {0}", o);
break;
case "outside":
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
SceneObjectPart rootPart = g.RootPart;
bool delete = false;
if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0)
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
delete = true;
}
else
{
ILandObject parcel
= m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
if (g.OwnerID == match && !g.IsAttachment)
deletes.Add(g);
});
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with owner {0}", match);
break;
case "creator":
if (!UUID.TryParse(o, out match))
return;
if (parcel == null || parcel.LandData.Name == "NO LAND")
deletes = new List<SceneObjectGroup>();
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
if (g.RootPart.CreatorID == match && !g.IsAttachment)
deletes.Add(g);
});
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with creator {0}", match);
break;
case "uuid":
if (!UUID.TryParse(o, out match))
return;
requireConfirmation = false;
deletes = new List<SceneObjectGroup>();
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
if (g.UUID == match && !g.IsAttachment)
deletes.Add(g);
});
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found with uuid {0}", match);
break;
case "name":
deletes = GetDeleteCandidatesByName(module, cmd);
break;
case "outside":
deletes = new List<SceneObjectGroup>();
m_scene.ForEachSOG(delegate (SceneObjectGroup g)
{
SceneObjectPart rootPart = g.RootPart;
bool delete = false;
if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0)
{
delete = true;
}
}
else
{
ILandObject parcel
= m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
if (parcel == null || parcel.LandData.Name == "NO LAND")
delete = true;
}
if (delete && !g.IsAttachment && !deletes.Contains(g))
deletes.Add(g);
});
if (deletes.Count == 0)
m_console.OutputFormat("No objects were found outside region bounds");
break;
if (delete && !g.IsAttachment && !deletes.Contains(g))
deletes.Add(g);
});
default:
m_console.OutputFormat("Unrecognized mode {0}", mode);
return;
}
// if (deletes.Count == 0)
// m_console.OutputFormat("No objects were found outside region bounds");
if (deletes == null || deletes.Count <= 0)
return;
break;
if (requireConfirmation)
{
string response = MainConsole.Instance.CmdPrompt(
string.Format(
"Are you sure that you want to delete {0} objects from {1}",
deletes.Count, m_scene.RegionInfo.RegionName),
"n");
if (response.ToLower() != "y")
{
MainConsole.Instance.OutputFormat(
"Aborting delete of {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName);
return;
}
}
m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName);
@@ -412,5 +483,44 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
m_scene.DeleteSceneObject(g, false);
}
}
private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
{
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
return null;
bool useRegex = false;
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
List<string> mainParams = options.Parse(cmdparams);
if (mainParams.Count < 4)
{
m_console.OutputFormat("Usage: delete object name [--regex] <name>");
return null;
}
string name = mainParams[3];
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
Action<SceneObjectGroup> searchAction;
if (useRegex)
{
Regex nameRegex = new Regex(name);
searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
}
else
{
searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
}
m_scene.ForEachSOG(searchAction);
if (sceneObjects.Count == 0)
m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
return sceneObjects;
}
}
}

View File

@@ -221,7 +221,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
"Force permissions on or off",
HandleForcePermissions);
m_scene.AddCommand("Users", this, "debug permissions",
m_scene.AddCommand("Debug", this, "debug permissions",
"debug permissions <true / false>",
"Turn on permissions debugging",
HandleDebugPermissions);
@@ -348,12 +348,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
if (m_friendsModule == null)
m_log.Warn("[PERMISSIONS]: Friends module not found, friend permissions will not work");
m_log.Debug("[PERMISSIONS]: Friends module not found, friend permissions will not work");
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
if (m_groupsModule == null)
m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work");
m_log.Debug("[PERMISSIONS]: Groups module not found, group permissions will not work");
m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
@@ -450,19 +450,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
}
/// <summary>
/// Is the given user an administrator (in other words, a god)?
/// Is the user regarded as an administrator?
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
protected bool IsAdministrator(UUID user)
{
if (user == UUID.Zero) return false;
if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
{
if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod)
return true;
}
if (user == UUID.Zero)
return false;
if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod)
return true;
if (IsEstateManager(user) && m_RegionManagerIsGod)
return true;

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using log4net;
using Mono.Addins;
using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.World.Objects.Commands
{
/// <summary>
/// A module that holds commands for manipulating objects in the scene.
/// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionCommandsModule")]
public class RegionCommandsModule : INonSharedRegionModule
{
private Scene m_scene;
private ICommandConsole m_console;
public string Name { get { return "Region Commands Module"; } }
public Type ReplaceableInterface { get { return null; } }
public void Initialise(IConfigSource source)
{
// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE");
}
public void PostInitialise()
{
// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE");
}
public void Close()
{
// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE");
}
public void AddRegion(Scene scene)
{
// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
m_scene = scene;
m_console = MainConsole.Instance;
m_console.Commands.AddCommand(
"Regions", false, "show scene",
"show scene",
"Show live scene information for the currently selected region.", HandleShowScene);
}
public void RemoveRegion(Scene scene)
{
// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
}
public void RegionLoaded(Scene scene)
{
// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
}
private void HandleShowScene(string module, string[] cmd)
{
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
return;
SimStatsReporter r = m_scene.StatsReporter;
float[] stats = r.LastReportedSimStats;
float timeDilation = stats[0];
float simFps = stats[1];
float physicsFps = stats[2];
float agentUpdates = stats[3];
float rootAgents = stats[4];
float childAgents = stats[5];
float totalPrims = stats[6];
float activePrims = stats[7];
float totalFrameTime = stats[8];
// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator
float physicsFrameTime = stats[10];
float otherFrameTime = stats[11];
// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored
float inPacketsPerSecond = stats[13];
float outPacketsPerSecond = stats[14];
float unackedBytes = stats[15];
// float agentFrameTime = stats.StatsBlock[16].StatValue; // Not really used
float pendingDownloads = stats[17];
float pendingUploads = stats[18];
float activeScripts = stats[19];
float scriptLinesPerSecond = stats[20];
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName);
ConsoleDisplayList dispList = new ConsoleDisplayList();
dispList.AddRow("Time Dilation", timeDilation);
dispList.AddRow("Sim FPS", simFps);
dispList.AddRow("Physics FPS", physicsFps);
dispList.AddRow("Avatars", rootAgents);
dispList.AddRow("Child agents", childAgents);
dispList.AddRow("Total prims", totalPrims);
dispList.AddRow("Scripts", activeScripts);
dispList.AddRow("Script lines processed per second", scriptLinesPerSecond);
dispList.AddRow("Physics enabled prims", activePrims);
dispList.AddRow("Total frame time", totalFrameTime);
dispList.AddRow("Physics frame time", physicsFrameTime);
dispList.AddRow("Other frame time", otherFrameTime);
dispList.AddRow("Agent Updates per second", agentUpdates);
dispList.AddRow("Packets processed from clients per second", inPacketsPerSecond);
dispList.AddRow("Packets sent to clients per second", outPacketsPerSecond);
dispList.AddRow("Bytes unacknowledged by clients", unackedBytes);
dispList.AddRow("Pending asset downloads to clients", pendingDownloads);
dispList.AddRow("Pending asset uploads from clients", pendingUploads);
dispList.AddToStringBuilder(sb);
MainConsole.Instance.Output(sb.ToString());
}
}
}

View File

@@ -78,11 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Sound
if (grp.IsAttachment)
{
if (grp.AttachmentPoint > 30) // HUD
{
if (sp.ControllingClient.AgentId != grp.OwnerID)
return;
}
if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID)
return;
if (sp.ControllingClient.AgentId == grp.OwnerID)
dis = 0;

View File

@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
}
//Returns true if this extension is supported for terrain save-tile
public bool SupportsTileSave()
public override bool SupportsTileSave()
{
return false;
}

Some files were not shown because too many files have changed in this diff Show More