Compare commits

...

359 Commits

Author SHA1 Message Date
Justin Clark-Casey (justincc) a315aee803 Move SenseRepeaters.Count check inside the SenseRepeatListLock.
No methods in the List class are thread safe in the MS specification/documentation
2012-03-02 00:36:29 +00:00
Justin Clark-Casey (justincc) 0c931e3657 lock SenseRepeatListLock when added a new sensor during script reconstitution.
This is already being done in the other place where a sensor is added.
Adding a sensor whilst another thread is iterating over the sensor list can cause a concurrency exception.
2012-03-02 00:36:20 +00:00
Justin Clark-Casey (justincc) 9f4d772d6a Add line numbers to Util.PrintCallStack() 2012-02-14 20:47:53 +00:00
Justin Clark-Casey (justincc) d6cf029860 Fix bug where somebody taking a copy of an object they didn't own that was rezzed before the region was restarted would wrongly place the copy in the object owner's inventory.
Addresses http://opensimulator.org/mantis/view.php?id=5825
2012-02-14 20:47:40 +00:00
Justin Clark-Casey (justincc) 083587eb32 Stop a scene object from attempting to link with itself (which results in an exception and constant complaints in v3 viewers).
Aims to address http://opensimulator.org/mantis/view.php?id=5878
2012-02-14 20:47:10 +00:00
Justin Clark-Casey (justincc) 8c8e3ad3ff Make WebStats logging report consistently as WEB STATS MODULE instead of VC, VS and WEBSTATS 2012-02-14 20:46:59 +00:00
Justin Clark-Casey (justincc) 91d5495e26 Temporarily remove ScenePresenceAgentTests since getting them operational in this branch may require considerable changes 2012-02-14 20:45:16 +00:00
Justin Clark-Casey (justincc) 2030377d2c Only look for an uploaded transactional asset in Scene.UpdateTaskInventory if we have been passed a non-zero transaction ID.
This resolves the recent regression from deeb728 where notecards could not be saved in prim inventories.
This looks like a better solution than deeb728 since only non-caps updates pass in a transaction ID.
Hopefully resolves http://opensimulator.org/mantis/view.php?id=5873
2012-02-14 20:37:58 +00:00
Justin Clark-Casey (justincc) 31a0f75aff D'oh - we want to call llGetLinkNumberOfSides() in the LSL_Stub, not llGetLinkNumber(). 2012-02-14 20:36:09 +00:00
Justin Clark-Casey (justincc) c1d84ffc6c Add llGetLinkNumberOfSides to LSL_Stub and ILSL_Api
It already existed in LSL_Api but it also needs to exist in these two other places for a script to be able to see it.
Hopefully resolves http://opensimulator.org/mantis/view.php?id=5489
2012-02-14 20:36:00 +00:00
Justin Clark-Casey (justincc) 6c72381732 Lay out script status in property per row format, since getting too long for console lines. 2012-02-02 23:59:01 +00:00
Justin Clark-Casey (justincc) 8c271802ac Add count of events queued for a particular script in "scripts show" console command 2012-02-02 23:58:51 +00:00
Justin Clark-Casey (justincc) 20a76fd224 Make script console commands only show for selected region. 2012-02-02 23:58:42 +00:00
Justin Clark-Casey (justincc) 4473f00e63 Implement "xengine status" console command to show various xengine stats 2012-02-02 23:58:36 +00:00
Justin Clark-Casey (justincc) 0b5210dd6a Add "show part uuid" and "show part name" console commands.
These commands will display part/prim details for a given uuid or name
The "show object uuid" and "show object name" commands will now only display details for objects (i.e. not child parts in a linkset).
This is for consistency with the "delete object" commands which only delete objects, not parts.
2012-02-02 23:58:27 +00:00
Justin Clark-Casey (justincc) 34d4bde585 Implement "show object name <name>" console command to show details of an object with the given name 2012-02-02 23:58:17 +00:00
Justin Clark-Casey (justincc) 4c20c2045c Get rid of the "no objects found" feedback for now - this doesn't work well if a command is executed over multiple scenes. 2012-02-02 23:58:09 +00:00
Justin Clark-Casey (justincc) d9a8f5f16d Implement "show object uuid <uuid>" console command.
This will show details about a part with the given uuid if it's found.
2012-02-02 23:57:18 +00:00
Justin Clark-Casey (justincc) 79c2081741 Add more user feedback if an object isn't found for which delete was requested. 2012-02-02 23:57:07 +00:00
Justin Clark-Casey (justincc) eb49c356e2 Add the name of a deleted object to the console output 2012-02-02 23:56:59 +00:00
Justin Clark-Casey (justincc) 717942e81b If a particular region is selected in the console, only try to delete objects in that region, rather than in every region on the simulator
The old wrong behaviour was in place before the command was extracted to a module.
2012-02-02 23:56:52 +00:00
Justin Clark-Casey (justincc) 6d47c394b2 Move object delete commands into a commands region module, in preparation for adding similar show commands. 2012-02-02 23:56:45 +00:00
Justin Clark-Casey (justincc) 8305c5d369 Use Environment.TickCount & Int32.MaxValue; instead of Util.EnvironmentTickCount(); when producing the threads report to reduce wraparound.
This matches the tickcount masking in the thread watchdog.
For some reason, Util.EnvironmentTickCount() masks ticks by 0x3fffffff instead of 0xffffffff
2012-02-02 23:56:29 +00:00
Justin Clark-Casey (justincc) 9e5f5f3d80 lock SceneObjectGroupsByFullID in SceneGraph.ForEachSOG() to stop failure if SceneObjectGroupsByFullID is updated elsewhere at the same time. 2012-02-02 23:55:13 +00:00
Justin Clark-Casey (justincc) 0a277a64a7 Comment out xfer section in Scene.UpdateTaskInventory() which was causing spurious errors and "script saved" messages when script properties were changed.
Viewers since at least Linden Lab 1.23 use the script upload capability to save script changes.
It's unknown whether the commented out code was working for very old viewers or not.
Code is commented out to reduce complexity and so that useful error messages don't need to be removed.
If there is a substantial population using extremely old viewers that can't upgrade to a newer version 1 viewer (e.g. 1.23) or similar TPV then this can be revisited.
2012-02-02 23:54:42 +00:00
Justin Clark-Casey (justincc) 7dd0b7ea2f minor: stop the WebStatsModule logging UPDATE or INSERT every time it updates bin/LocalUserStatistics.db 2012-02-02 23:54:00 +00:00
Justin Clark-Casey (justincc) cd666a3d2c Serialize calls to ODE Collide() function across OdeScene instances to prevent ODE crashes on simulators running more than one region.
It turns out that calls to Collide() are not thread-safe even for objects in different ODE physics worlds due to ODE static caches.
For simulators running multiple regions, not serializing calls from different scene loops will sooner or later cause OpenSim to crash with a native stack trace referencing OBBCollider.
This affects the default OPCODE collider but not GIMPACT.  However, GIMPACT fails for other reasons under some current simulator loads.
ODE provides a thread local storage option, but as of ODE r1755 (and r1840) DLLs compiled with this crash OpenSim immediately.
2012-02-02 23:53:46 +00:00
Justin Clark-Casey (justincc) 681502473e Fix "Abnormal client thread terminations" stat in period CONNECTION STATISTICS to count the number of times clients are disconnected due to ack timeouts.
This has been broken for a long period and would only ever show 0.
2012-02-02 23:53:23 +00:00
Justin Clark-Casey (justincc) 0ffe293692 minor: correct text and usage for "image queues show" reigon console command. 2012-02-02 23:52:59 +00:00
Justin Clark-Casey (justincc) 356e8516f0 Restrict accessible of ODECharacter Shell and Body. Add method doc and some error log lines. 2012-02-02 23:52:32 +00:00
Justin Clark-Casey (justincc) 71b11f557d Allow a viewer UDP image request retry to trigger another asset fetch if an existing fetch hasn't responded before a timeout.
This is to stop a high priority image/texture request from blocking the entire download queue if its asset fetch got dropped for some reason.
2012-01-23 21:35:25 +00:00
Justin Clark-Casey (justincc) 26be9ed08e Add image not in database test for LLImageManager 2012-01-23 21:35:16 +00:00
Justin Clark-Casey (justincc) f43d63240d refactor: separate out common parts of LLImageManagerTests 2012-01-23 21:34:46 +00:00
Justin Clark-Casey (justincc) 5c982c98aa Add LLImageManager regression test for discard case 2012-01-23 21:34:35 +00:00
Justin Clark-Casey (justincc) 63f0ec9aeb Add "image queues clear <first-name> <last-name>" console command
This allows a way to manually clear pending image queue requests for debug purposes
2012-01-23 21:33:56 +00:00
Justin Clark-Casey (justincc) e90cfc17ca Add basic request and send image regression tests for LLImageManager 2012-01-23 21:33:44 +00:00
Justin Clark-Casey (justincc) 16d5ce16b6 Extend scripts show command to accept a single item UUID parameter to display one script's status
Usage is now scripts show [<script-item-uuid>]
2012-01-16 21:24:15 +00:00
Justin Clark-Casey (justincc) ab4c4a362f Register the UrlModule for script engine events OnScriptRemoved and OnObjectRemoved just once in the UrlModule itself, rather than repeatedly for every script.
Doing this in every script is unnecessary since the event trigger is parameterized by the item id.
All that would happen is 2000 scripts would trigger 1999 unnecessary calls, and a large number of initialized scripts may eventually trigger a StackOverflowException.
Registration moved to UrlModule so that the handler is registered for all script engine implementations.
This required moving the OnScriptRemoved and OnObjectRemoved events (only used by UrlModule in core) from IScriptEngine to IScriptModule to avoid circular references.
2012-01-16 21:24:05 +00:00
Justin Clark-Casey (justincc) b5971db76c minor: Fix wrong column length in image queues report 2012-01-16 21:23:03 +00:00
Justin Clark-Casey (justincc) 0c39c9e84d rename "show image queue" to "show image queues" in line with other udp info commands.
Eliminate redundant one line methods
2012-01-16 21:22:54 +00:00
Justin Clark-Casey (justincc) 0b49773ab3 Add "show image queue <first-name> <last-name>" region console command
This is so that we can inspect the image download queue (texture download via udp) for debugging purposes.
2012-01-16 21:22:44 +00:00
Justin Clark-Casey (justincc) 820a39621e correct very minor typo in "debug scene" help 2012-01-16 21:20:36 +00:00
Justin Clark-Casey (justincc) 7a0f4cf8e1 Add "app find <uuid-or-start-of-uuid>" command to find the appearance using a particular baked texture, if any.
This is for debugging to relate texture console entries back to particular users on the simulator end.
2012-01-16 21:20:18 +00:00
Justin Clark-Casey (justincc) 2853b78f16 Improve "j2k decode" command to tell us how many layers and components were decoded, instead of just success/failure 2012-01-09 13:14:50 +00:00
Justin Clark-Casey (justincc) a3ada745bd Add a "j2k decode" region console command that allows a manual request for a JPEG2000 decode of an asset
For debugging purposes.
2012-01-09 13:14:39 +00:00
Justin Clark-Casey (justincc) ff0f90bc35 Make "show asset" command available simulator side. Actually make the service command be "show asset" instead of "show digest" this time.
Last time I accidnetally just changed the usage message.
2012-01-09 13:14:26 +00:00
Justin Clark-Casey (justincc) 7b564b8b35 Rename 'show digest' console command to 'show asset' 2012-01-09 13:14:19 +00:00
Justin Clark-Casey (justincc) 19a818017d Add size and temporary information to "show asset" command 2012-01-09 13:14:00 +00:00
Justin Clark-Casey (justincc) 7bc03a54e5 Move simulator asset info commands to an optional module from the connector. Make them conform with service side commands.
This stops them appearing twice when Hypergrid is enabled.
2012-01-09 13:13:40 +00:00
Justin Clark-Casey (justincc) aef6a9571c Move asset commands from AssetService to AssetServerConnector so that we can harmonise the same commands on the simulator side.
No functional change.
2012-01-09 13:13:33 +00:00
Justin Clark-Casey (justincc) 0a3b2f904e recomment log messages I accidentally left uncommented 2012-01-09 13:13:11 +00:00
Justin Clark-Casey (justincc) 023023a5fc Improve "app rebake" command to return a better message if no uploaded texture ids were available for the rebake request 2012-01-09 13:12:52 +00:00
Justin Clark-Casey (justincc) eebcea22ba Commenting out DataSnapShot message "Registering service discovery capability" for now.
Please uncomment if/when needed.
2012-01-09 13:08:02 +00:00
Justin Clark-Casey (justincc) 9474bdb6df Add "appearance rebake" command to ask a specific viewer to rebake textures from the server end.
This is not as useful as it sounds, since you can only request rebakes for texture IDs already received.
In other words, if the viewer has never sent the server this information (which happens quite often) then it will have no effect.
Nonetheless, this is useful for diagnostic/debugging purposes.
2012-01-09 13:07:39 +00:00
Justin Clark-Casey (justincc) 4d28bac9bb Separate out rebake request code from cache validation code AvatarFactoryModule.
This allows some logic simplification and allows an external caller to manually request rebakes even if textures are uploaded (future command).
2012-01-09 13:00:56 +00:00
Justin Clark-Casey (justincc) de746cd987 Minor formatting changes and commented out log lines for future debugging of image manager (udp texture fetch). No significant functional changes. 2012-01-09 12:37:51 +00:00
Justin Clark-Casey (justincc) 0ef16f9f5b Remove the pointless LLClientView.m_imageManager null check.
Despite the code comments we never actually null it.
2012-01-09 12:37:38 +00:00
Justin Clark-Casey (justincc) de0a45d9a3 Update C5.dll to version 1.1.1 from 1.1.0
C5 is a collections library and can be found at http://www.itu.dk/research/c5/
This is used in the UDP texture (image) sending code.
2012-01-09 12:37:26 +00:00
Justin Clark-Casey (justincc) a2071e5b13 Reduce accessibility of some J2KImage/LLImageManager properties and methods to reduce potential code complexity and make code reading easier. 2012-01-09 12:37:04 +00:00
Justin Clark-Casey (justincc) 1b3ae566e8 Adding commented out log messages and some minor formatting for future bug hunting. No functional changes. 2012-01-09 12:37:00 +00:00
Mic Bowman 674baa39ed fix the UsesPhysics flag to reference the physics flag rather than the temponrez flag 2012-01-09 12:33:51 +00:00
Justin Clark-Casey (justincc) 1cf57c83e1 Align default ODE_STEPSIZE with that already used through OpenSimDefaults.ini 2012-01-09 12:33:39 +00:00
Justin Clark-Casey (justincc) e98e580900 rename Scene.m_physicalPrim to PhysicalPrims since its public and access external as a property 2012-01-09 12:31:53 +00:00
Justin Clark-Casey (justincc) 292ab783e4 Remove unused m_physicalPrim parameter from SOG.ApplyPhysics() 2012-01-09 12:30:04 +00:00
Justin Clark-Casey (justincc) 0563530bf8 remove now redundant m_physical_prim flag from SOP.ApplyPhysics() 2012-01-09 12:26:49 +00:00
Justin Clark-Casey (justincc) 2135b89c07 Make it possible to force all prims to be phantom via the collidable_prim boolean setting in the OpenSim.ini config [Startup] section.
Naturally, default is true.
When set to false, "phantom" flags on prims can be set as usual but all prims remain phantom.
This setting is for test purposes.
This switch does not affect the collision of avatars with the terrain.
2012-01-09 12:04:45 +00:00
Dan Lake 2b19a112d9 Remove unused SetAcceleration and add set on Acceleration parameter 2012-01-09 12:02:46 +00:00
Justin Clark-Casey (justincc) cd78f50632 Though the viewer warns about receiving this, not sending appears to break baked texture caching when crossing region boundaries.
Needs further investigation.

Revert "Stop sending the viewer its own AvatarAppearance packet."

This reverts commit 92039f295d.
2011-12-20 20:58:37 +00:00
Justin Clark-Casey (justincc) b300db9e0a Stop sending the viewer its own AvatarAppearance packet.
The viewer warns in the log if it receives this.
Stopping this doesn't appear to have adverse effects on viewer 1 or viewer 3 - the viewer gets its own appearance from body parts/clothes and self-baked textures.
2011-12-19 21:16:34 +00:00
Justin Clark-Casey (justincc) 4370f0e181 Stop unnecessarily sending the TextureEntry in client avatar updates.
As far as I know, viewers don't use this mechanism to recieve new TextureEntry data for avatars.  This is done via the AvatarAppearance packet instead.
Tested this back to viewer 1.23.
Replacing with Utils.EmptyBytes since converting the texture entry to bytes on each AvatarUpdate (or which there are many) is not cost-free.
2011-12-19 21:16:24 +00:00
Justin Clark-Casey (justincc) 48ea503c33 Fix race condition where the appearance update timer could be stopped just after another thread had started it on QueueAppearanceSave() or *Send()
However, the window for this race is very small, and the next queued appearance save or send would restart the timer anyway.
2011-12-19 21:16:14 +00:00
nebadon 546eb88112 addresses mantis #5827
RAdmin - admin_save_oar fails if noassets parameter missing
thanks Michelle Argus
2011-12-19 21:09:36 +00:00
Justin Clark-Casey (justincc) 52710b48ac Provide user feedback on execution of "backup" region console command 2011-12-19 21:09:28 +00:00
Justin Clark-Casey (justincc) cc5e28c1c1 Fix bug where objects couldn't be set back to the "none" group.
This is handled by treating UUID.Zero as a special case.
Currently, asking for the "none" group returns nothing because XMLRPC groups, at least, is not properly handling this case.
It may be better in the future to have GroupsModule return an appropriate GroupsData structure instead or require the underlying services to behave appropriately.
This is a further component of http://opensimulator.org/mantis/view.php?id=5588
2011-12-19 21:09:19 +00:00
Justin Clark-Casey (justincc) 67a2d6d855 Fix bug where objects could not be set to a new group if the group had been created in that client session, or if no other action has been performed on the object.
There were two problems here:
1) On object group update, we looked for the group is the IClientAPI group cache rather than in the groups service.  This fails to groups created newly in that session
2) On object group update, we weren't setting the HasGroupChanged flag.  This meant that the change was not persisted unless some other action set this flag.
This commit fixes these issues and hopefully addresses http://opensimulator.org/mantis/view.php?id=5588
This commit also moves HandleObjectGroupUpdate() to the GroupsModule from the Scene.PacketHandlers.cs file
2011-12-19 21:09:09 +00:00
Justin Clark-Casey (justincc) 7d426debd3 refactor: simplify methods in Scene.PacketHandlers.cs by using GetGroupByPrim() rather than retrieving GetEntities() and inspecting the entire list 2011-12-19 21:05:27 +00:00
Justin Clark-Casey (justincc) 4de98ca4c8 Add SceneViewer changes for removing unused client flags 2011-12-19 21:01:46 +00:00
Justin Clark-Casey (justincc) deb50cd410 Stop generating client flags when we send out full object updates.
These were entirely unused.
2011-12-19 20:59:18 +00:00
Justin Clark-Casey (justincc) b3cfc5b76e Stop pointlessly setting the m_colliderarr[] to false in the ODECharacter constructor 2011-12-19 20:49:31 +00:00
Justin Clark-Casey (justincc) 27644bcce6 Stop having to call SetHeight again in ScenePresence.AddToPhysicalScene() when we've already passed size information to the avatar at PhysicsScene.AddAvatar()
Eliminate some copypasta for height setting in OdeCharacter
2011-12-19 20:49:09 +00:00
Justin Clark-Casey (justincc) 903da8acbd Simplify some manipulation of _taintedActors in OdeScene 2011-12-19 20:31:57 +00:00
Justin Clark-Casey (justincc) cfdccdd71c Eliminate _taintedPrimsH and _taintedPrimsL (and _taintedPrimLock) in favour of just a _taintedPrims HashSet.
There's no point maintaining a list because any pending taint operations are all carried out in the same call anyway.
2011-12-19 20:30:52 +00:00
Justin Clark-Casey (justincc) 93e65fb9d5 In AvatarFactoryModule.SetApperance(), perform ValidateBakedTextureCache() in the same thread rather than on another one.
The caller is already an async thread from LLClientView so this doesn't hold up the client.
However, launching on a separate thread does remove the effect of m_setAppearanceLock
This was potentially allowing two different SetAppearance threads to interfere with each other, though this probably rarely happens, if at all.
2011-12-19 20:30:26 +00:00
Justin Clark-Casey (justincc) af117fe4d4 Get rid of the 'lolcat' library asset.
This was both unused and an invalid jpeg2000 texture from way back in 2008
2011-12-19 20:26:19 +00:00
Justin Clark-Casey (justincc) 986f6b39ca Fix build 2011-12-12 20:32:47 +00:00
Justin Clark-Casey (justincc) 7a8dd539fd minor: remove pointless comment from OdeScene.cs 2011-12-12 20:24:03 +00:00
Justin Clark-Casey (justincc) 382cda662f minor: comment out "unpacked appearance" log mesasge for now 2011-12-12 20:23:17 +00:00
Justin Clark-Casey (justincc) ede9aea45f Comment out ChildAgentDataUpdate.Pack() "Pack data" message for now. 2011-12-12 20:23:07 +00:00
Justin Clark-Casey (justincc) 52b8518fc2 Do some clean up Scene.cs log messages.
This prints out both exception message and stacktrace (Exception.ToString()) isn't enough on Windows.
This also uses m_log.*Format() which is more efficient than string concat.
2011-12-12 20:22:57 +00:00
Justin Clark-Casey (justincc) c3d16955a7 Get rid of IScene.PresenceChildStatus() which always had to execute a lookup in favour of IClientAPI.ISceneAgent.IsChildAgent instead. 2011-12-12 20:22:54 +00:00
Justin Clark-Casey (justincc) 61df0da7f9 remove some unused fields in ScenePresence 2011-12-12 20:18:13 +00:00
Justin Clark-Casey (justincc) f8b0427086 Move client id check in Scene.Inventory.cs:UpdateInventoryItemAsset so that it doesn't trigger an exception if the item hasn't been found.
In this situation we will now put out a slightly more meaningful log error message instead.
2011-12-12 20:17:43 +00:00
Justin Clark-Casey (justincc) 5b0d0ef1e9 Don't reply with an ack packet if the client is not authorized. 2011-12-12 20:17:22 +00:00
Justin Clark-Casey (justincc) 7ca688f5c5 Extend TestAddClient() to check that the first packet received is an ack packet 2011-12-12 20:17:14 +00:00
Justin Clark-Casey (justincc) 9dc1000c27 Add OpenSim.Region.ClientStack.LindenUDP.Tests.dll back into the test suite 2011-12-12 20:15:28 +00:00
Justin Clark-Casey (justincc) 638afca5aa Reactivate BasicCircuitTests.TestAddClient()
This checks that the initial UseCircuitCode packet is handled correctly for a normal client login.
2011-12-12 20:15:16 +00:00
Justin Clark-Casey (justincc) 7e415e3f85 Remove unnecessary AgentCircuitData null check from Scene.AddNewClient().
The only caller is the LLUDP stack and this has to validate the UDP circuit itself, so we know that it exists.
This allows us to eliminate another null check elsewhere and simplifies the method contract
2011-12-12 20:11:26 +00:00
Justin Clark-Casey (justincc) 8c4e58995d When a client connects to a scene, send other avatar appearance data asynchronously to reduce hold up in the IN UDP packet processing loop.
This is already being done for the initial object data send.
2011-12-12 20:09:04 +00:00
Justin Clark-Casey (justincc) d26ded4788 fix build 2011-12-12 20:08:49 +00:00
Justin Clark-Casey (justincc) 5268334c61 On a new client circuit, send the initial reply ack to let the client know it's live before sending other data.
This means that avatar/appearance data of other avatars and scene objects for a client will be sent after the ack rather than possibly before.
This may stop some avatars appearing grey on login.
This introduces a new OpenSim.Framework.ISceneAgent to accompany the existing OpenSim.Framework.ISceneObject and ISceneEntity
This allows IClientAPI to handle this as it can't reference OpenSim.Region.Framework.Interfaces
2011-12-12 20:08:02 +00:00
Justin Clark-Casey (justincc) 6ba4cbc259 Simplify Scene.AddNewClient()
If sp becomes null right after we've checked or created it, then behaviour down the line is going to be wrong anyway.
So instead retain the check/create ScenePresence reference and use this.
2011-12-12 20:00:15 +00:00
Melanie ac445463e9 Remove a left over log output 2011-12-08 23:54:33 +00:00
Justin Clark-Casey (justincc) 1e83800d32 Remove warning in admin_save_oar xmlrpc method where noassets == true was comparing against an object rather than a string 2011-12-08 23:54:25 +00:00
Justin Clark-Casey (justincc) 3d94984eee Have admin_load_heighmap and admin_save_heightmap xmlrpcadmin methods return success = true on success rather than false 2011-12-08 23:54:18 +00:00
Justin Clark-Casey (justincc) fd8734b22c Refactor RemoteAdminPlugin so that every xmlrpc method calls a common block of code to do password checks, etc., instead of copy/pasting this code into every method 2011-12-08 23:54:11 +00:00
Justin Clark-Casey (justincc) 9b229efdc5 Remove unused SceneManager.TryGetAvatarsScene()
It makes far more sense anyway to use TryGetRootScenePresence().Scene, in common with the rest of the code
This method could also return any scene for child or root agents, depending in which order the scenes happened to lie in the list
2011-12-08 23:54:04 +00:00
Justin Clark-Casey (justincc) 81daedcfe3 Implement XMLRPCAdmin command admin_teleport_agent.
This allows someone with access to this command on the XMLRPCAdmin interface to teleport an avatar to an arbitrary region and/or position.
2011-12-08 23:53:43 +00:00
Michelle Argus b819771919 RemoteAdmin - Added optional terrain loading on region create using parameter heightmap_file to specify the terrain file to be loaded 2011-12-08 23:53:18 +00:00
Justin Clark-Casey (justincc) 2f536f92c0 Remove the inconsistently applied now pointless FailIfRemoteAdminDisabled() check on XMLRPC RemoteAdmin handlers.
If admin is disabled then the XMLRPC handlers are never registered, which means that they cannot be called anyway.
2011-12-08 23:52:04 +00:00
Justin Clark-Casey (justincc) 0b4774c50c replace List used by m_accessIP in RemoteAdminPlugin with the more efficient HashSet 2011-12-08 23:51:58 +00:00
Justin Clark-Casey (justincc) 139b0d03b6 Improve explanation of access_ip_addresses in [RemoteAdmin] to say that there are no restrictions if not set 2011-12-08 23:51:51 +00:00
Justin Clark-Casey (justincc) c13916d392 Add option to allow only explicitly listed IPs to access RemoteAdmin facilities.
Also adds password check to some functions where this was missing and fixes some parameter checking.
This is a patch from http://opensimulator.org/mantis/view.php?id=5715 with a few small unrelated spacing tweaks from me.
Thanks Michelle Argus.
2011-12-08 23:51:16 +00:00
Justin Clark-Casey (justincc) 3ebb56734d properly lock CapsHandlers.m_capsHandlers 2011-12-08 23:47:45 +00:00
Justin Clark-Casey (justincc) 235147c857 Make "show appearance" a synonym for "appearance show" 2011-12-06 22:24:11 +00:00
Justin Clark-Casey (justincc) ddb74bc68d In "appearance show", if a particular avatar is specified, print out texture UUID for each bake type and whether the simulator can find it. 2011-12-06 22:23:52 +00:00
Justin Clark-Casey (justincc) cd132966df Actually send the avatar data if an individual avatar is specified, rather than accidentally doing nothing 2011-12-06 22:21:02 +00:00
Justin Clark-Casey (justincc) 5d4fee6eb9 conflict resolution due to drift in ValidateBakedTextureCache args 2011-12-06 22:20:44 +00:00
Justin Clark-Casey (justincc) cc80377325 Allow "appearance show" command to take an optional avatar name 2011-12-06 22:20:01 +00:00
Justin Clark-Casey (justincc) 7dce33ce69 Make it possible to manually send appearance information via the "appearance send" command for a chosen avatar as well as all 2011-12-06 22:16:49 +00:00
Justin Clark-Casey (justincc) 0dd45f6ca4 Provide feedback as to which avatars are resending appearance informion on "appearance send" console command 2011-12-06 22:16:40 +00:00
Justin Clark-Casey (justincc) ac3d88804f Stop accidentally setting up the UploadTexture caps handler with the same url for all users
This meant that if a user exited the region, the UploadTexture handler would be effectively removed for everyone, causing subsequent failures.
This hopefully resolves the recent UploadTexture LLSD problems
This was a regression in 5640f2e (Thu Dec 1 23:24:15 2011 +0000)
2011-12-06 22:13:58 +00:00
Justin Clark-Casey (justincc) f1698552f9 For the GetTexture capability, if a data range is requested that covers the whole asset length, return HTTP PartialContent instead of NotFound
NotFound is obviously wrong, and this change stops viewer 3.2.2 (and v probably earlier) complaining in the log about missing textures that are actually present.
We still return PartialContent even if the range requested is a superset of the data range as per httpd's behaviour
https://issues.apache.org/bugzilla/show_bug.cgi?id=51878
Viewer 3.2.2 and very probably earlier appear happy with this.
Whether fixing this NotFound bug has any practical effect apart from resolve viewer log messages is unknown.
2011-12-05 21:06:16 +00:00
Justin Clark-Casey (justincc) dfeb424afd Add "appearance send" command to allow manual sending of appearance. 2011-12-05 16:02:26 +00:00
Justin Clark-Casey (justincc) 2380980975 Stop performing the asset save part of baked texture uploading on the UploadBakedTexture cap asynchronously.
This prevents a possible race condition where the client would be told all baked textures had updated before they were in the asset service.
The client would then trigger a set appearance which, after a delay, would send the avatar appearance out to other clients.
The race condition seems unlikely because of this delay but it's still possible.
Might help with grey avatar appearances.
2011-12-05 16:00:36 +00:00
Justin Clark-Casey (justincc) 52ec854c42 refactor: Separate the upload baked texture handler out from BunchOfCaps 2011-12-05 16:00:27 +00:00
Justin Clark-Casey (justincc) 4dbfcc26a2 Provide more user feedback when "debug http" is set 2011-12-05 16:00:15 +00:00
Justin Clark-Casey (justincc) a262d2492f On "show caps", stop excluding the seed cap but do exclude it elsewhere 2011-12-05 16:00:06 +00:00
Justin Clark-Casey (justincc) e5b7e2fd40 With "debug http 1", show the path with the query string instead of just the path.
Also simplifies debug levels to just 0 and 1
2011-12-05 15:59:53 +00:00
Justin Clark-Casey (justincc) 7505f23f80 Improve some of the debug help messages 2011-12-05 15:59:45 +00:00
Justin Clark-Casey (justincc) 7562e63ae6 minor: remove mono compile warning, a Vector3 can never be null since it's a struct 2011-12-05 15:59:38 +00:00
Justin Clark-Casey (justincc) 7987a6da95 tabulate "show caps" output for easier readability 2011-12-05 15:59:27 +00:00
Justin Clark-Casey (justincc) fcd60c6b74 Correct mistake in "debug eq" help 2011-12-05 15:59:19 +00:00
Justin Clark-Casey (justincc) 1e88bf78f1 When setting packet level logging via "debug packet", apply to all clients, not just root ones.
Also adds scene name and client type (root|child) to logged information.
2011-12-05 15:58:24 +00:00
Justin Clark-Casey (justincc) a819890137 Add a "debug eq" console command for debugging.
This will log outgoing event queue message names if turned on.
2011-12-05 15:55:32 +00:00
Justin Clark-Casey (justincc) 5c85a98f6a Add "debug http" command for currently simple extra debug logging of non-event queue inbound http requests to a simulator 2011-12-05 15:54:10 +00:00
Justin Clark-Casey (justincc) e58daf052d minor: remove mono compiler warning 2011-12-05 15:50:20 +00:00
Justin Clark-Casey (justincc) 0a0e285919 remove some mono compiler warnings 2011-11-28 15:59:43 +00:00
Justin Clark-Casey (justincc) c693bd51a0 Remove bizarre call to PhysicsScene.Simulate(0) in Scene.GetNearestAllowedPosition()
At least on ODE, this wasn't doing any harm but there wasn't any point to it either
2011-11-28 15:59:30 +00:00
Justin Clark-Casey (justincc) 808ace0696 minor: remove mono compiler warning 2011-11-28 15:59:20 +00:00
Justin Clark-Casey (justincc) 9730a862db Log error if we attempt to add/remove an OdeCharacter from the _characters list inappropriately 2011-11-28 15:58:06 +00:00
Justin Clark-Casey (justincc) 754d6036ea Stop removing actor from the hash maps in OdeScene.RemoveCharacter() since this is now being down in OdeCharacter.DestroyOdeStructures() 2011-11-28 15:54:57 +00:00
Justin Clark-Casey (justincc) 476d893630 Comment out uncalled OdeScene.UnCombine() 2011-11-28 15:54:49 +00:00
Justin Clark-Casey (justincc) 0a6374d37a Comment out unimplemented and uncalled RegionCombinerModule.UnCombineRegion() 2011-11-28 15:54:40 +00:00
Justin Clark-Casey (justincc) 0337f2e2a0 minor: remove mono compiler warning 2011-11-28 15:54:32 +00:00
Justin Clark-Casey (justincc) 7be35d5a9a Stop an exception being thrown and a teleport/border cross failing if the desintation sim has no active script engines.
This involves getting IScene.RequestModuleInterfaces() to return an empty array (as was stated in the method doc) rather than an array containing one null entry.
Callers adjusted to stop checking for the list reference being null (which never happened anyway)
2011-11-28 15:54:25 +00:00
Justin Clark-Casey (justincc) 8ab2d42143 slightly simplify OdeScene.Simulate() by removing bool processtaints, since we can inspect count of taint lists instead.
also groups OdeCharacter.CreateOdeStructures() and DestroyOdeStructures() together
2011-11-28 15:54:13 +00:00
Justin Clark-Casey (justincc) dc8ce9ec5d Improve the error messages returned if the HelloNeighbour call fails.
This is the message a region sends to its neighbours when it comes up
2011-11-28 15:54:04 +00:00
Justin Clark-Casey (justincc) 7171913400 Slightly improve "Unable to space collide" logging message, though I don't think I've ever seen this. 2011-11-28 15:53:53 +00:00
Justin Clark-Casey (justincc) 0cf5c0837b Get rid of OdeCharacter != null checks since OdeScene._characters can never contain a null character.
Ignoring the ancient code glyphs not to do this....
2011-11-28 15:53:45 +00:00
Justin Clark-Casey (justincc) 1edfe05c16 remove unnecessary OdeScene._activeprims locking. Code is single-threaded 2011-11-28 15:53:36 +00:00
Justin Clark-Casey (justincc) bba4577d88 Restore defects list. In hindsight, the reason for this is becuase we can't remove the character whilst iterating over the list.
This commit also removes locking on OdeScene._characters since code is single threaded
2011-11-28 15:53:28 +00:00
Justin Clark-Casey (justincc) 5c305494ae simplify operation of OdeScene._perloopContact 2011-11-28 15:53:19 +00:00
Justin Clark-Casey (justincc) 4b2b0d4a05 don't bother locking OdeScene._perloopContact in single threaded code 2011-11-28 15:53:11 +00:00
Justin Clark-Casey (justincc) 61848ebe0d don't lock OdeScene.contacts since only ever accessed by a single thread 2011-11-28 15:53:04 +00:00
Justin Clark-Casey (justincc) f48431345b rename ODECharacter.AvatarGeomAndBodyCreation() -> CreateOdeStructures() to match existing DestroyOdeStructures() 2011-11-28 15:52:53 +00:00
Justin Clark-Casey (justincc) 9c4597a00f refactor: Eliminate one line ODECharacter.doForce() method for code clarity 2011-11-28 15:49:37 +00:00
Justin Clark-Casey (justincc) b528150d16 Comment out calls to OdeScene.waitForSpaceUnlock() since that method does nothing right now 2011-11-28 15:42:36 +00:00
Justin Clark-Casey (justincc) 4a99619bc0 Reduce complexity of OdeScene.Simulate() by fully removing bad characters at point of detection rather than later on. 2011-11-28 15:42:21 +00:00
Justin Clark-Casey (justincc) 5bd27b7b22 move geom/actor map maintenance into DestroyODEStructures()/AvatarGeomAndBodyCreation().
This saves us having to do it separately when a character capsule size is changed
2011-11-28 15:38:50 +00:00
Justin Clark-Casey (justincc) 8ea97cc608 When changing avatar size in ODE, remove the old actor from the name and actor maps 2011-11-28 15:38:42 +00:00
Justin Clark-Casey (justincc) 1850b778e2 When an ODECharacter is removed (e.g. when an avatar leaves a scene), remove the actor reference in OdeScene.actor_name_map rather than leaving it dangling.
This also largely centralizes adds/removes in OdeScene.AddCharacter()/RemoveCharacter()
2011-11-28 15:37:57 +00:00
Justin Clark-Casey (justincc) 5cd33f5e21 Have ODECharacter and ODEPrim both use PhysicsActor.Name instead of maintaining their own properties 2011-11-28 15:37:49 +00:00
Justin Clark-Casey (justincc) cd3d5379d6 Actually remove PhysicsActor.SOPDescription this time 2011-11-28 15:37:04 +00:00
Justin Clark-Casey (justincc) 58021b5300 Chain SOP constructors together rather than having copy/paste code 2011-11-28 15:36:53 +00:00
Justin Clark-Casey (justincc) 3b141e5eee refactor: Make SOP.Description an automatic property 2011-11-28 15:34:29 +00:00
Justin Clark-Casey (justincc) 08bc6622dd Remove unused PhysicsActor.SOPDescription 2011-11-28 15:30:00 +00:00
Justin Clark-Casey (justincc) c253539c04 Instead of generating a new list for bad characters on every physics pass, keep reusing the same list. 2011-11-28 15:29:51 +00:00
Justin Clark-Casey (justincc) f3b45be9c0 Move DeleteScriptsOnStartup switch from [Startup] to [XEngine] in OpenSim.ini.example.
If anybody was changing this and wondering why there was no effect, this is why.
2011-11-28 15:29:38 +00:00
Justin Clark-Casey (justincc) 59c19110e4 Remove the "[LOCAL SIMULATION CONNECTOR]: Did not find region {0} for SendCreateChildAgent" message
This is misleading since a simulator will call this method before successfully trying remote regions.
Also comments out spammy "[SIMULATION]: Stream handler called" AgentHandlers messages for now.
2011-11-28 15:28:35 +00:00
Justin Clark-Casey (justincc) 7c03fba3fc minor: Make HelloNeighbour messages more informative 2011-11-28 15:28:28 +00:00
Justin Clark-Casey (justincc) 2593a446ac Get rid of the spurious [WEB UTIL] couldn't decode <OpenSim agent 57956c4b-ff2e-4fc1-9995-613c6256cc98>: Invalid character 'O' in input string messages
These are just the result of an attempt to canonicalize received messages - it's not important that we constantly log them.
Also finally get the deregister grid service message working properly
2011-11-28 15:28:14 +00:00
Justin Clark-Casey (justincc) 011c1279f5 Enable v2/v3 map tile url setting on robust as default in config
This is necessary to see map tiles on v2/v3 viewers and appears to work fine
2011-11-28 15:28:05 +00:00
Justin Clark-Casey (justincc) 25133cbdf6 Remove mono compiler warnings. Fix problem with co-ordinate given in deregister region message 2011-11-28 15:27:53 +00:00
Justin Clark-Casey (justincc) 06ed824711 Improve some grid region log messages to express regions at co-ordinate (e.g. 1000, 1000) rather than meter positions (256000, 256000) 2011-11-28 15:27:43 +00:00
Justin Clark-Casey (justincc) 63aa448608 improve region deregistration log message 2011-11-28 15:27:36 +00:00
justincc 4afb773399 Replace HttpServer_OpenSim.dll with Oren Hurvitz's patch applied.
This will hopefully address mantis 5471, 5694 and 5718.
This code is now in opensim-libs, along with Diva's slightly older patches (which were already applied to the DLLs in the opensim tree).
Thanks Oren!
2011-11-28 15:23:11 +00:00
Justin Clark-Casey (justincc) dafe65ad81 Turn the [RegionReady] module on by default and login_disable = true while scripts are loading.
From field experience, we know that simulators can be unstable if a user logs in before the scripts have finished loading.
This commit turns login_disable = true in [RegionReady] on by default which prevents this from happening.
If you want the old behaviour, please copy these section from OpenSimDefaults.ini into OpenSim.ini and set login_disable = false
2011-11-28 15:23:01 +00:00
Justin Clark-Casey (justincc) b107a8ec2a Turn SellEnabled in the [EconomyModule] on by default.
This only provides enough functionality to allow operations for no money (e.g. sell for $0).
2011-11-28 15:22:51 +00:00
Justin Clark-Casey (justincc) e31d7fe424 minor: remove some mono compiler warnings 2011-11-17 23:55:45 +00:00
justincc cc9888f28b Fix Windows build break 2011-11-17 23:40:45 +00:00
Justin Clark-Casey (justincc) fef3baf107 For TerrainModule.SaveToFile(), don't bother throwing the exception onwards after printing out the error, since this method is invoked by users.
Still throwing the exception on the stream method since this invoked programatically
2011-11-17 23:24:58 +00:00
Justin Clark-Casey (justincc) 123322569d Make "terrain save" more friendly by telling the user if we have saved and putting out a useful complaint message if we haven't for some reason 2011-11-17 23:24:50 +00:00
Justin Clark-Casey (justincc) 8c0d8e72aa If the entire simulator is shutting down then don't bother to unload the scripts from the appdomain in XEngine.
All the other actions (script state save, etc.) still occur.
This makes shutdown where there are many scripts vastly quicker.
2011-11-17 23:24:43 +00:00
Justin Clark-Casey (justincc) 1e69845869 Make tracked per scene thread names conform to the majorirty format.
This is <thread-name> (<region-name>)
2011-11-17 23:24:23 +00:00
Justin Clark-Casey (justincc) 1bc0d0fac6 improve formatting of "show threads" 2011-11-17 23:24:05 +00:00
Justin Clark-Casey (justincc) f7b5d17aa2 send a watchdog heartbeat for a poll worker thread when it's actually run 2011-11-17 23:23:57 +00:00
Justin Clark-Casey (justincc) 85170f5d5d distinguish between FriendsSimConnector and FriendsServiceConnector in log 2011-11-17 23:23:48 +00:00
Justin Clark-Casey (justincc) 66863fdd34 Add number of milliseconds since last update to "show threads" 2011-11-17 23:23:42 +00:00
Justin Clark-Casey (justincc) 6b0553ed7c Dont' bother with a userAgentService != null check right after we've constructed it 2011-11-17 23:23:35 +00:00
Justin Clark-Casey (justincc) 57cffcd1ec Remove prebuild reference to now gone PumaCode.SvnDotNet.dll 2011-11-17 23:23:06 +00:00
Justin Clark-Casey (justincc) 78739067d1 Remove unused RegionCommsListener/IRegionCommsListener.
All this is now being handled through IEntityTransferModule and SimulationService instead, and has been for some time.
2011-11-17 23:22:57 +00:00
Justin Clark-Casey (justincc) 310c2403b0 remove SceneCommunicationService.OnAvatarCrossingIntoRegion. This stuff is not being used any more - it's now IEntityTransferModule and SimulationService instead 2011-11-17 23:22:48 +00:00
Justin Clark-Casey (justincc) a88381ba82 Rename FetchFriendslist() -> CacheFriends() and RefetchFriends() -> RecacheFriends() to reflect their intended function 2011-11-17 23:22:27 +00:00
Justin Clark-Casey (justincc) 1fa0c2f9b0 refactor: rename m_NeedsListOfFriends => m_NeedsListOfOnlineFriends to better reflect its actual function 2011-11-17 23:22:16 +00:00
Justin Clark-Casey (justincc) 1069390b3e For clients that are entering a simulator from initial login, stop executing FriendsModule.FetchFriendslist() asychronously.
Executing this asynchronously allows a race condition where subsequent friends fetches hit a cache that FetchFriendsList() had not yet populated.
Changing this to synchronous may improve issues where a user does not see friends as online even though they are.
I don't believe synchronous is a problem here, but if it is, then a more complicated signalling mechanism is required.  Locking the cache isn't sufficient.
2011-11-17 23:22:07 +00:00
Justin Clark-Casey (justincc) 3068cc3618 refactor: Don't create a new UUID for passing uuids to client - UUIDs are structs are so not passed by reference (and they're immutable!) 2011-11-17 23:21:59 +00:00
Justin Clark-Casey (justincc) b5a69833f8 Add test for removing a friendship. 2011-11-17 23:21:40 +00:00
Justin Clark-Casey (justincc) 8b5bacc78b Improved method doc for AddFriend() - it actually does set up a two-way relationship.
Rename IFriendsModule.AddFriend() to AddFriendship()
2011-11-17 23:21:27 +00:00
Justin Clark-Casey (justincc) 8f7f03e7fd Add test for adding a friend whilst online 2011-11-17 23:20:47 +00:00
Justin Clark-Casey (justincc) 80bea38c07 Add very simple FriendsModuleTests.TestNoFriends() 2011-11-17 23:20:36 +00:00
Justin Clark-Casey (justincc) 9742491a63 doh - correct build break 2011-11-17 23:18:45 +00:00
Justin Clark-Casey (justincc) acad65a832 Add threads to the watchdog thread list before we start them.
Hopefully this wil make "WATCHDOG: Asked to update thread ## which is not being monitored" messages." go away.
2011-11-17 23:18:35 +00:00
Justin Clark-Casey (justincc) b527901556 As with prim sitting avatars, make an avatar phantom when it sits on the ground and solid again when it stands.
This is to avoid http://opensimulator.org/mantis/view.php?id=5783 when a collision with a ground sitting avatar causes that avatar to automatically stand and sometimes not be able to move
A better solution may be to keep gound sitting avatars solid but remove their collision status.  However, this requires some physics code work.
2011-11-17 23:18:24 +00:00
Justin Clark-Casey (justincc) 3c9654d5d6 Bump warp sit distance up to 10 meters, as discussed on opensim-dev mailing list last week.
This means that if the avatar is within 10 meters of the selected target, it sits on it immediately without walking.
Existing autopilot outside this range will be disabled in a later commit
2011-11-17 22:48:10 +00:00
Justin Clark-Casey (justincc) 4be42b3f75 Get some hopefully more useful exception information when OpenJPEG.EncodeFromImage() fails in VectorRender and DynamicTexture modules 2011-11-02 19:08:01 +00:00
Justin Clark-Casey (justincc) 6a994f8c9c Fix race condition that would sometimes send or save appearance for the wrong avatar.
In AvatarFactoryModule.HandleAppearanceUpdateTimer(), we loop through appearance save and send requests and dispatch via a FireAndForget thread.
If there was more than one request in the save or send queue, then this led to a subtle race condition where the foreach loop would load in the next KeyValuePair before the thread was dispatched.
This gave the thread the wrong avatar ID, leaving some avatar appearance cloudy since appearance data was never sent.
This change loads the fields into local references so that this doesn't happen.
2011-11-02 19:07:56 +00:00
Justin Clark-Casey (justincc) f9e6e32ce2 Catch any exceptions exiting the top of the robust console, as we already do for the main simulator.
This prevents issues such as transient mono console problems from crashing the server.
2011-11-02 19:00:56 +00:00
Melanie 6bbf4fdc0f Plug a security hole in the inventory service 2011-11-02 18:59:54 +00:00
Dan Lake 10aee2f0ec Fix line endings 2011-11-02 18:59:47 +00:00
Dan Lake 0ed6149463 Experimental reorder of Heartbeat loop now simulates physics and sends updates to clients prior to sleep. Existing behavior was to sleep BEFORE sending updates. We found this patch reduced latency to clients by 1-2 heartbeat periods. 2011-11-02 18:59:38 +00:00
Justin Clark-Casey (justincc) a64be59c3b Add missing max_listens_per_region to [LL_Functions] config section in OpenSimDefaults.ini + explanation.
This setting controls the maximum number of listeners in a region
2011-11-02 18:59:30 +00:00
Justin Clark-Casey (justincc) b720454950 Remove the SyncRoot locking from Scene which was only being done around the main physics loop and ScenePresence position and velocity setting
This is no longer necessary with ODECharacter taints (ODEPrim was already not taking part in this).  BSCharacter was already tainting.
2011-11-02 18:57:04 +00:00
Justin Clark-Casey (justincc) dd3dc5cd91 Add taint target velocity for ODECharacters as is already done for ODECharacter position and position and velocity for ODEPrims.
This is to help stop surprises if the velocity is set in the middle of physics calculations, though this probably isn't a huge problem.
It's more for consistency and for the next step of removing some scene locks
2011-11-02 18:51:55 +00:00
Justin Clark-Casey (justincc) 9cd94ac6ec tidy up OdeCharacter so that we just use OpenMetaverse.Vector3 assignment directly where possible, instead of transferring X, Y and Z components separately
some of this is probably a hold over from using ODE.Vector3, which is still necessary in some places.
2011-11-02 18:51:46 +00:00
Justin Clark-Casey (justincc) 2cc49d7d9a Move position set from taint to logically better position at top of ODECharacter.ProcessTaints() though this makes no practical difference 2011-11-02 18:51:31 +00:00
Justin Clark-Casey (justincc) 69e11af475 Stop setting _position as well as m_taint_position in ODECharacter.Position
setting position at the same time as taint appears to undermine the whole purpose of taint
testing doesn't reveal any obvious regressions in doing this
2011-11-02 18:51:20 +00:00
Dan Lake aa6915f1ba Continuation of previous checkin. Found more places where ForEachScenePresence can be changed to ForEachRootScenePresence. 2011-11-02 18:50:17 +00:00
Dan Lake b36ff0fd24 Added new ForEachRootScenePresence to Scene since almost every delegate passed to ForEachScenePresence checks for !IsChildAgent first. It consolidates child and root handling for coming refactors. 2011-11-02 18:48:21 +00:00
Justin Clark-Casey (justincc) a16c9206b4 For now, comment out error message on new script engine console commands.
This causes false positives if a simulator has more than 1 region and the current region is 'root' since this sends the command separately to each region and each region has its own XEngine
2011-10-28 22:19:46 +01:00
Justin Clark-Casey (justincc) b5b2541d1a Comment out inventory folder bulk update code on InventoryAccepted message introduced in commit db91044 on Aug 22 2011
This should be unecessary since the folder update is already made at the time of the offer (and moved to trash if not accepted).
This code was also not taking into account the situation where an item was accepted.
Needs more fixing if this results in an aggression elsewhere.
2011-10-28 22:19:36 +01:00
Justin Clark-Casey (justincc) 1baadac59a Don't blow our brains out if LLClientView.BulkInventoryUpdate() is wrongly passed a null node reference.
Addresses worst aspect of http://opensimulator.org/mantis/view.php?id=5752
2011-10-28 22:19:26 +01:00
Justin Clark-Casey (justincc) 88ef35cb23 Fix a bug I introduced yesterday in ODE physics where prim scripts would only receive the very first collision. 2011-10-28 22:19:17 +01:00
Justin Clark-Casey (justincc) 05dff4987b Restart the event queue worker threads that I accidentally disabled earlier today in 8a0a78c.
Also adds these to the watchdogs with very large timeouts (should really be infinite)
2011-10-28 22:19:04 +01:00
Justin Clark-Casey (justincc) e1e0f20c7f In Watchdog, add ability to specific timeout for a thread.
This also changes the point of registration to the StartThread() call rather than the first Update()
2011-10-28 22:18:56 +01:00
Justin Clark-Casey (justincc) 70d559d1af Add m_threads dictionary locking to Watchdog.GetThreads() 2011-10-28 22:18:48 +01:00
Justin Clark-Casey (justincc) 6c92b48143 Clear OdeCharacter CollisionEventUpdate when we subscribe or unsubscribe from collision events 2011-10-28 22:18:42 +01:00
Justin Clark-Casey (justincc) 127626edd8 Remove unused fields from CollisionEventUpdate 2011-10-28 22:18:35 +01:00
Justin Clark-Casey (justincc) aba26c098d Get rid of the pointless null checks on collision listeners. Add warning about synchronicity for PhysicsActor.OnCollisionUpdate event doc 2011-10-28 22:18:23 +01:00
Justin Clark-Casey (justincc) 9f19405490 When sending object collision updates, don't null out and recreate the CollisionEventUpdate() if the number of collisions falls to zero. Reuse the existing one instead. 2011-10-28 22:18:17 +01:00
Justin Clark-Casey (justincc) 871f1d0ae7 For ScenePresence collision events, instead of creating a new CollisionEventsThisFrame every time we need to send some new ones, reuse the existing one instead.
This assumes that the listener is using the data synchronously, which is currently the case.
2011-10-28 22:18:11 +01:00
Justin Clark-Casey (justincc) 057b78bfbe Fix bug where collision event listeners were not removed once the listener had gone away.
This was causing continuous use of temporary memory even when all avatars had left the scene.
Memory does leak but it does cause more calls to the garbage collector, which would pause the scene thread for a very short while during collection.
2011-10-28 22:18:03 +01:00
Justin Clark-Casey (justincc) d4fc07aae1 minor: rename a parameter in OdeScene.Simulate() from actor -> prim since it's an OdePrim 2011-10-28 22:17:55 +01:00
Justin Clark-Casey (justincc) 750e8ec3da Add new LindenCaps test dll to panda run as well as "nant test" 2011-10-28 22:17:44 +01:00
Justin Clark-Casey (justincc) 15142093ad minor: add "threads show" as synonym for "show threads" for consistency 2011-10-28 22:17:32 +01:00
Justin Clark-Casey (justincc) f050f0fc0b Add "threads abort <thread-id>" simulator console command that allows us to abort a watchdog managed thread.
This is for diagnostic purposes.
2011-10-28 22:17:20 +01:00
Justin Clark-Casey (justincc) a3c79b399e Make OpenSim.Framework.Servers.HttpServer rely on OpenSim.Framework instead of the other way around.
This is necessary so that code in HttpServer can use framework facilities such as the thread watchdog for monitoring purposes.
Doing this shuffle meant that MainServer was moved into OpenSim/Framework/Servers
Also had to make OpenSim.Framework.Console rely on OpenSim.Framework rather than the other way around since it in turn relies on HttpServer
MainConsole and some new interfaces had to be moved into OpenSim/Framework to allow this.  This can be reverted if parts of OpenSim.Framework stop relying on console presence (cheifly RegionInfo)
2011-10-28 22:17:10 +01:00
Justin Clark-Casey (justincc) 424735efee separate out future common setup code from EventQueueTests.AddForClient() 2011-10-28 22:16:49 +01:00
Justin Clark-Casey (justincc) d5dfbc3844 Add new EventQueueTests with basic test to check that adding a client registers an http poll 2011-10-28 22:16:31 +01:00
Justin Clark-Casey (justincc) c3127d1323 Remove earlier mistaken addition of EventQueueTests.cs 2011-10-28 22:15:03 +01:00
Justin Clark-Casey (justincc) 03c98c3b8f Fix bugs in EventQueueGetModule.ClientClosed() and BaseHttpServer.RemovePollServerHTTPHandler() that stopped existing code in ClientClosed() from actually tearing down the poll handler
Actually doing the tear down appear to have no ill effects with region crossing and teleport.
2011-10-28 22:09:53 +01:00
Justin Clark-Casey (justincc) 24e02afeac Comment out the uuid gatherer lines that I accidentally left in. 2011-10-28 22:02:54 +01:00
Justin Clark-Casey (justincc) 8d5606e09b Rename some of the example commented out server names to mygridserver.com like all the others.
This is to make it easier to change all these names at once, where all grids services are running from the same location.
Also rearranges some lines in [Modules] so that StandaloneCommon.ini.example and GridCommon.ini.exmaple are consistent.
2011-10-28 22:02:43 +01:00
Justin Clark-Casey (justincc) bd3d119a03 Make config comments about choosing assetcache modules clearer.
OpenSim needs an asset cache.  Running without one will cause problems.
Thanks to Ai Austin for the suggestions in http://opensimulator.org/mantis/view.php?id=4850
2011-10-28 22:02:37 +01:00
Justin Clark-Casey (justincc) cf2405385d Get UUIDGatherer to scan notecards in the graph for asset uuids.
This is to support npc baked texture saving in oars and iars.
May address http://opensimulator.org/mantis/view.php?id=5743
2011-10-28 22:02:25 +01:00
Justin Clark-Casey (justincc) a6eba09dac redirect UserInventoryHelpers to use a different CreateNotecardAsset() so we can comment out some inconsistency 2011-10-28 22:02:18 +01:00
Justin Clark-Casey (justincc) b2ca7c0927 correct misleading method doc on CreateNotecardAsset() 2011-10-28 22:02:09 +01:00
Justin Clark-Casey (justincc) dd6c236253 in AssetHelpers, store the actual text passed in to the method, not the string "data" 2011-10-28 22:02:02 +01:00
Justin Clark-Casey (justincc) b2ff680cca encode notecard assets in proper format for tests, rather than just using whatever string is given 2011-10-28 22:01:54 +01:00
Justin Clark-Casey (justincc) 23a9a7daa7 refactor: rename some AssetHelpers.CreateAsset() methods to CreateNotecardAsset() 2011-10-28 22:01:47 +01:00
Justin Clark-Casey (justincc) 19fde57fca Change wording on asset requests.
Not all 'notified missing' assets are a problem.  Some are invalid references which happen to be buried in other text.
2011-10-28 21:59:53 +01:00
Justin Clark-Casey (justincc) a556930456 Store scene identifier passed in to OdeScene for later debug messages 2011-10-28 21:58:30 +01:00
Justin Clark-Casey (justincc) 1a008b237b Don't bother taking OdeLock during OdeScene construction, since there can be no contention until the object is constructed. 2011-10-28 21:58:21 +01:00
Justin Clark-Casey (justincc) d6456b9ea8 Remove unnecessary lock of OdeLock in OdePrim.changeadd()
This taint can only ever be processed from the OdeScene.Simulate() loop, which already locks OdeLock.
2011-10-28 21:58:12 +01:00
Justin Clark-Casey (justincc) 5980d57b7a minor: method doc to explain a lock of OdeLock 2011-10-28 21:58:01 +01:00
Justin Clark-Casey (justincc) 7c409eff53 Remove the unused CollisionLocker from ODE
Despite its name, this wasn't actually being used in any collision checking
2011-10-28 21:56:04 +01:00
Justin Clark-Casey (justincc) 614ea5a48a refactor: Use SOP.SitTargetAvatar instead of calling a special GetAvatarOnSitTarget() which returned exactly the same thing 2011-10-28 21:47:08 +01:00
Justin Clark-Casey (justincc) 8905f34e18 rename OS_NPC_SIT_IMMEDIATE to OS_NPC_SIT_NOW since it's shorter and more understandable
This makes something like osNpcSit(npc, llGetKey(), OS_NPC_IMMEDIATE) now become
osNpcSit(npc, llGetKey(), OS_NPC_SIT_NOW);
This is why it's in development :)
2011-10-28 21:47:00 +01:00
Justin Clark-Casey (justincc) 380f2a1719 Implement osNpcStand(<npc-id>)
Allows you to stand an NPC that has sat.
2011-10-28 21:46:53 +01:00
Justin Clark-Casey (justincc) 1c66e08964 Implement osNpcSit(). This is still in development so don't trust it
Format is osNpcSit(<npc-uuid>, <target-uuid>, OS_NPC_SIT_IMMEDIATE)
e.g. osNpcSit(npc, llGetKey(), OS_NPC_SIT_IMMEDIATE);
At the moment, sit only succeeds if the part has a sit target set.
NPC immediately sits on the target even if miles away - they do not walk up to it.
This method is in development - it may change so please don't trust it yet.
Standing will follow shortly since that's kind of important once you're sitting :)
2011-10-28 21:46:36 +01:00
Justin Clark-Casey (justincc) af564291f2 improve method doc on Scene.OtherRegionUp()
this is really just to trigger panda.
2011-10-28 21:45:58 +01:00
Justin Clark-Casey (justincc) 250eed5141 move see_into_this_sim_from_neighbor [Startup] flag parsing into Scene with the others 2011-10-28 21:45:50 +01:00
Justin Clark-Casey (justincc) a2c9b3d83d fetch physical_prim switch from [Startup] config from inside scene, as is done for most other scene config params 2011-10-28 21:45:41 +01:00
Justin Clark-Casey (justincc) 3a047b2bdb Restore [Startup] physical_prim flag which can stop any prims being subject to physics
This had stopped working.  However, at the moment it still allows the physics flag to be set even though this has no effect.  This needs to be fixed.
Default for this flag is true as previously.
2011-10-28 21:45:00 +01:00
Justin Clark-Casey (justincc) f8deca7f2d remove redundant PhysActor.IsPhysical call from SOP.UpdatePrimFlags() as its done immediately afterwards in DoPhysicsPropertyUpdate() 2011-10-28 21:44:52 +01:00
Justin Clark-Casey (justincc) 63a6bc93e4 refactor: Remove redundant code in SOP.UpdatePrimFlags() 2011-10-28 21:44:44 +01:00
Justin Clark-Casey (justincc) 50c340ef35 factor common code out into SOP.RemoveFromPhysics() 2011-10-28 21:44:36 +01:00
Justin Clark-Casey (justincc) 41e7e613a2 reduce access to ODECharacter methods to make code analysis easier. Eliminate redundant argument on ProcessTaints() 2011-10-28 21:44:28 +01:00
Justin Clark-Casey (justincc) 4d1ab38068 restrict unnecessary access levels on ODEPrim fields/properties 2011-10-28 21:44:20 +01:00
Justin Clark-Casey (justincc) 47c412ca1e refactor: make methods that do not need to be public in ODE private or internal to aid code reading/analysis. Remove some unused method arguments 2011-10-28 21:44:12 +01:00
Justin Clark-Casey (justincc) acb0a5b6c1 refactor: rename IClientAPI.SendPrimUpdate() to SendEntityUpdate() since it sends entity updates (including presence ones), not just prims. 2011-10-28 21:43:39 +01:00
Justin Clark-Casey (justincc) 1b8716a99a Get rid of some traces of the old pre-ROBUST grid architecture config 2011-10-28 21:41:48 +01:00
Justin Clark-Casey (justincc) 9edbb4f77a Bring LindenUDP.Tests back from the dead. No tests are running.
Code drift means that most of this stuff doesn't compile but the structure is still useful.

Conflicts:

	OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLPacketServer.cs
2011-10-28 21:40:53 +01:00
Justin Clark-Casey (justincc) 753f11273f re-enable running linden udp tests in local.include, though no tests are currently active there 2011-10-28 21:31:44 +01:00
Justin Clark-Casey (justincc) 435aefe1bf Drop some unnecessary ContainsKey() checking before Remove() in BaseHttpServer()
Remove() presumably does this check anyway since it just returns false if the key is not in the collection.
2011-10-28 21:30:36 +01:00
Justin Clark-Casey (justincc) e5286b7b7c Fix bugs in EventQueueGetModule.ClientClosed() and BaseHttpServer.RemovePollServerHTTPHandler() that stopped existing code in ClientClosed() from actually tearing down the poll handler
Actually doing the tear down appear to have no ill effects with region crossing and teleport.
2011-10-28 21:29:44 +01:00
Justin Clark-Casey (justincc) aa4637db47 Add optional getauthinfo and setauthinfo authentication service calls.
These are disabled by default, as before.  Please only turn these on in secure grids, since they allow the same facilities as the existing SetPassword call (also disabled by default)
These facilities can be helpful when integrating external systems, in addition to the existing option of adapting an IAuthenticationService or using WebLoginKey
2011-10-24 23:28:02 +01:00
Justin Clark-Casey (justincc) 73c201449f very minor removal of old commented out line of code in OdeScene 2011-10-21 00:08:59 +01:00
Justin Clark-Casey (justincc) 36be226dc8 remove unnecessary null check on _collisionEventPrim 2011-10-21 00:08:45 +01:00
Justin Clark-Casey (justincc) ea5d1d0ff0 Get OdeScene to use passed in time step rather than hard-coded 0.089
However, I still don't recommend changing MinFrameTime from 0.089, high values do not work well and lower values don't seem to make much difference
2011-10-21 00:08:32 +01:00
Justin Clark-Casey (justincc) 299cc2d12d Pass PhysicsScene.Simulate() only the MinFrameTime rather than the useless Math.Max(SinceLastFrame.TotalSeconds, MinFrameTime)
SinceLastFrame was calculating the interval between any sleep that had occurred to pad out the frame time and the start of the next frame.
This would usually be below MinFrameTime but occasionally if the sleep was long it would be above, often due to the time required to update the watchdog.
This doesn't appear to play much practical role right now.
ODE was actually ignoring it entirely.  Bullet might be helped slightly by receiving a non-varying value.
2011-10-21 00:06:20 +01:00
Justin Clark-Casey (justincc) 4ecd3fbff1 For now, stop passing timeStep into methods where it's not actually used. 2011-10-21 00:06:13 +01:00
Justin Clark-Casey (justincc) 1b32d5c6a4 Extend scripts stop/start/suspend/resume console commands to allow action on a single script by giving the script item id (which can be found via scripts show).
Not an ideal way to do this on a region with many scripts.  Needs refinement later.
2011-10-19 23:03:59 +01:00
Justin Clark-Casey (justincc) c404760731 Add "scripts stop" and "scripts start" console commands.
These will stop all running scripts and start all stopped scripts respectively.
A stopped script does not save any events for later processing.
2011-10-19 23:03:28 +01:00
Justin Clark-Casey (justincc) 7d4e224620 minor: improve command help on scripts suspend/resume 2011-10-19 23:03:22 +01:00
Justin Clark-Casey (justincc) 986ded5a72 Fix resume scripts.
On resume, we need to place requeue the script for event processing if there are any events on the queue.
Also need to do this under m_Script lock in order to avoid a race
2011-10-19 23:03:14 +01:00
Justin Clark-Casey (justincc) 8340bd7e20 Add "scripts suspend" and "scripts resume" commands.
These aim currently to suspend and resume all scripts.
However, resume isn't currently working due to what looks like a bug in resume functionality itself.
2011-10-19 23:03:05 +01:00
Justin Clark-Casey (justincc) 9d59fc0587 on log and "show scripts" messages, show script item UUID rather than asset UUID
The item ID is the one required for any script manipulation on the command line, so I think it's somewhat more useful to show this bearing in mind the limited space available
2011-10-19 23:02:56 +01:00
Justin Clark-Casey (justincc) 22e1298e97 add current script status to "scripts show" command (running, suspended, etc.) 2011-10-19 23:02:50 +01:00
Justin Clark-Casey (justincc) 1a29ddf328 Add "show scripts" command to show all scripts currently known to the script engine in the current region.
Also added synonym of "scripts show"
2011-10-19 23:02:43 +01:00
Justin Clark-Casey (justincc) 8a2c3a0267 Add option to allow remote http calls to setpassword in the AuthenticationService.
This is switched on by setting AllowSetPassword = true in the [AuthenticationService] section of Robust.ini or Robust.HG.ini
Default is false as before.
2011-10-19 23:02:36 +01:00
Justin Clark-Casey (justincc) ea65d4f5ce Make ScopeID optional for http GetAccount and GetAccounts
If not specified then it assumes UUID.Zero. as occurs elsewhere in the codebase
2011-10-19 00:36:49 +01:00
Justin Clark-Casey (justincc) eb65f5072d Make PrincipalID a synonym for UserID in GetUserAccount 2011-10-19 00:36:38 +01:00
Justin Clark-Casey (justincc) aad13a4c76 Get new NewUser and SetUserAccount calls to accept PrincipalID instead of UserID for consistency with output 2011-10-19 00:36:31 +01:00
Justin Clark-Casey (justincc) 233127c696 Allow an http call to set account details if AllowSetAccount = true in [UserAccountService].
As before, default is false to not allow these calls.
2011-10-19 00:36:24 +01:00
Justin Clark-Casey (justincc) b7fcd6871e Provide an option to allow remote calls to the CreateUser method on the UserAccountService
Default is false, as before.
Enabling AllowCreateUser in [UserAccountService] for ROBUST allows avatars to be created via an http call, with viewer 2 appropriate bits and pieces.
Only Ruths can be created at present.
Please don't rely on the config since at some point CreateUser will be moved to a separate co-ordinating service.
2011-10-18 22:56:43 +01:00
Justin Clark-Casey (justincc) c06cd3b2b9 Allow an avatar to be explicitly named to the "debug packet" command 2011-10-17 21:12:00 +01:00
Justin Clark-Casey (justincc) 31ac7571f4 refactor: Make IClientAPI.DebugPacketFormat a property rather than a setter without a getter 2011-10-17 21:11:50 +01:00
Justin Clark-Casey (justincc) 2a7a5c4c90 Add avatar names to debug packet output 2011-10-17 21:11:43 +01:00
Justin Clark-Casey (justincc) d8ad649957 Add back the missing bin/addon-modules directory that I somehow managed to accidentally delete in 2fbc98f (Jul 7 2011) 2011-10-17 21:11:04 +01:00
Justin Clark-Casey (justincc) a1f232af2b change default ODE world_stepsize to 0.0178 from 0.02
This exactly fits five ODE steps in the default frame time (0.089).
This means that ODE execution time now matches the default minimum frame time.
This eliminates errors between distance travelled as calculated by ODE in clear air and simple extrapolation.
On the old values, ODE would actually do calculations over 0.1 seconds rather than 0.089.
This means that once the avatar is at top speed, no additional packets need to be sent for smooth movement, since no error develops between server and viewer.
This approach replaces the tweaks previously discussed on the opensim-dev mailing list
2011-10-17 21:10:52 +01:00
Justin Clark-Casey (justincc) 14bddb6af9 Change hardcoded ODE total frame time to match the default total frame time (0.09375 -> 0.089).
No apparant ill effects - because the default stepsize is 0.2, there are still 5 physics steps per physics frame.
This is a precursor to using the elapsed value passed in (and now changeable in config).
2011-10-17 21:10:43 +01:00
Justin Clark-Casey (justincc) f93635fe85 Extract NullPhysicsScene from PhysicsScene to improve code readability 2011-10-17 21:10:25 +01:00
Justin Clark-Casey (justincc) 3a635507cc Don't execute rest of code in XEngine.RemoveRegion() and Close() if the module is disabled. 2011-10-17 21:10:17 +01:00
Justin Clark-Casey (justincc) 0506ccb51a Expose minimum frame time and update periods for experimentation.
Settings are at bottom of [Startup] in OpenSimDefaults.ini, override in OpenSim.ini to change
Defaults are the same as previously.
More information to come on opensim-dev shortly.
Feel free to tweak but if you do please don't expect any support unless feedback on certain tweaks is explicitly requested.
2011-10-17 21:09:56 +01:00
Justin Clark-Casey (justincc) 4bce90d0ab refactor: Put the frame update period when temporary objects are cleaned up in a field, like all the other update periods 2011-10-17 21:06:03 +01:00
Justin Clark-Casey (justincc) 4d93ab06c9 refactor: chain the two scene constructors together to eliminate more copypasta 2011-10-17 21:05:47 +01:00
Justin Clark-Casey (justincc) e2c807a0d0 Tie reported FPS correction factor into the minimum frame time rather than setting separately.
This makes reported FPS scale as required if min frame time changes
2011-10-17 21:05:37 +01:00
Justin Clark-Casey (justincc) 23a9a98d5d Move fps stat adjustment factor into field rather than hard-coded. 2011-10-17 21:05:29 +01:00
Justin Clark-Casey (justincc) 32ba06a55c More method doc and formatting changes. Makes DestroyOdeStructures() private 2011-10-17 21:05:21 +01:00
Justin Clark-Casey (justincc) 64c42a729a refactor: move 3x copy/pasted ode structure removal code in ODECharacter into a DestroyOdeStructures() method
also adds some method doc
2011-10-17 21:05:12 +01:00
Justin Clark-Casey (justincc) b342fb9c0a When shutting down XEngine, log how many scripts are being shutdown so the user knows why they are waiting. 2011-10-17 21:03:51 +01:00
Justin Clark-Casey (justincc) 3f70f54fa6 minor: insert some commented out log lines which are a blunt but useful instrument to see packet expiry and received acks 2011-10-17 21:03:41 +01:00
Justin Clark-Casey (justincc) c4ce7b8162 Improve some method doc for LLUDPClient, LLUDPServer and UnackedPacketCollection 2011-10-17 21:03:30 +01:00
Justin Clark-Casey (justincc) 4c9226be7b Start recording object updates per second statistic (analogue of agent updates per secod) and expose via monitoring module as ObjectUpdatePerSecondMonitor
A useful diagnostic to find out how object updates are burdening a scene
2011-10-17 21:03:04 +01:00
Diva Canto 58f2c9e224 Bug fix on the bug fix on UserAccountService.cs 2011-10-16 16:14:43 -07:00
Diva Canto 8ba0cc470a Guard HGAssetService against uninitialized variables and null arguments. 2011-10-15 20:25:06 -07:00
Justin Clark-Casey (justincc) 2a654974c9 flip release flavour to post-fixes 2011-10-14 02:11:58 +01:00
Diva Canto b72753dc81 Bug fix -- Test User on first run standalone might not be created properly: let all instances of UserAccountService have all its service references properly initialized, and register console commands on only one. 2011-10-13 18:09:20 -07:00
Justin Clark-Casey (justincc) 2ecfa29eb6 Allow monitoring of stats by region name 2011-10-11 00:07:08 +01:00
Justin Clark-Casey (justincc) 3678b8f1f7 Add other region stats (total frame time, physics fps, etc.) currently missing from MonitorModule
Unlike the other 3 stats mechanisms, monitor data can be queried per individual region, which makes this useful.
This doesn't affect an of the existing monitored stats.
2011-10-11 00:07:00 +01:00
Justin Clark-Casey (justincc) 29a62abc6d Convert getLastReportedSimFPS() and getLastReportedSimStats() into more idiomatic LastReportedSimFPS and LastReportedSimStats on SimStatsReporter 2011-10-11 00:06:51 +01:00
Justin Clark-Casey (justincc) 31ef2f9a2e Provide a way to turn the MonitorModule on and off
Default is currently on since this is the historical setting
2011-10-11 00:06:44 +01:00
Justin Clark-Casey (justincc) 21e3f8e53a refactor: have lsl and ossl interrogate scene.StatsReporter directly rather than going through scene
I know this goes against the law of demeter but I don't think it's that useful here and I'd rather get rid of nasty little wrapper methods
2011-10-11 00:06:36 +01:00
Justin Clark-Casey (justincc) 579aa9c6a0 Go back to lying that sim fps is 55 when it's actually locked at a maximum of 11.
We're been lying since 2008 so I'm sure another few years can't hurt.
To know the real fps, either divide sim fps by 5 and/or look at the frame time.
2011-10-11 00:06:09 +01:00
BlueWall 8b374daae9 Add note to docs
This method is used by externasl/3rd party management tools to
  create users and they depend on us to generate the UUID.
2011-10-11 00:05:54 +01:00
Justin Clark-Casey (justincc) 31d1b3310d remove the pointless slashes on the end of the (5!) different server stat retrieval mechanisms.
Original request URLs that end with / will still work, but this will allow one to type /simstatus as well as /simstatus/
Can't do this with webstats yet since it does insane things to the path.
2011-10-11 00:05:41 +01:00
Pixel Tomsen d1711519a0 WebStats - Home Link Fix
http://opensimulator.org/mantis/view.php?id=4536
2011-10-11 00:05:31 +01:00
BlueWall 71fa970990 Added back UserAccount that creates random UUID for new account.
This should fix recent issues with 3rd party apps that use the
old interface w/o breaking the new one.
2011-10-11 00:05:15 +01:00
Justin Clark-Casey (justincc) 6fa4f88d39 Instead of adding stat agentMS in all kinds of places, calculate it instead in the main Scene.Update() loop, like the other stats
Some of the places where agentMS was added were in separate threads launched by the update loop.  I don't believe this is correct, since such threads are no longer contributing to frame time.
Some of the places were also driven by client input rather than the scene loop.  I don't believe it's appropriate to add this kind of stuff to scene loop stats.
These changes hopefully have the nice affect of making the broken out frame stats actually add up to the total frame time
2011-10-11 00:05:09 +01:00
Justin Clark-Casey (justincc) 9ff3d9221b Remove vestigal RegionStatus.SlaveScene.
This appears to be code clutter since the code that uses this has long gone.
2011-10-11 00:04:50 +01:00
Justin Clark-Casey (justincc) 3920e56dd4 Add user ID to new estate user prompt, to make it clearer and consistent with the main create user prompts 2011-10-11 00:03:52 +01:00
Justin Clark-Casey (justincc) 6700f1edd9 Make reported sim fps more accurate, in line with frame time ms
Also remove some unused fields and improve naming on others.
2011-10-11 00:03:35 +01:00
Justin Clark-Casey (justincc) e6d1182dec When creating a new user on the comand line, give the option of allowing a UUID to be specified to override the randomly generated one.
This can be useful in some migration cases where recreating user accounts with known IDs will preserve region scene object ownership.
2011-10-11 00:03:22 +01:00
Justin Clark-Casey (justincc) a3316f1eac For llGetTexture(), if the face texture asset is in the inventory, return the inventory name rather than the asset UUID
This is as per http://wiki.secondlife.com/wiki/LlGetTexture
Applied patch in http://opensimulator.org/mantis/view.php?id=4552 with an additional break statement if an inventory item is found to exit early.
Thanks Michelle Argus!
2011-10-11 00:02:43 +01:00
Pixel Tomsen 5f281716a9 llGetLinkKey, llGetLinkName Fix for sitting Avatar
when an avatar sits on a prim, we get now his key & name ;-)

http://opensimulator.org/mantis/view.php?id=4476
2011-10-11 00:02:21 +01:00
Pixel Tomsen f90c3d0633 llAvatarOnLinkSitTarget Implementation
http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget
2011-10-11 00:02:12 +01:00
Justin Clark-Casey (justincc) 633d4f3e6e Correct DeleteScriptsOnRestart to DeleteScriptsOnStartup in comments in OpenSim.ini.example 2011-10-07 21:45:43 +01:00
Justin Clark-Casey (justincc) 43bbdbe760 flip rc2 to release 2011-10-07 21:29:51 +01:00
Justin Clark-Casey (justincc) 494e5867a3 Comment out [SCENE PRESENCE] SendAppearanceToAllOtherAgents: log message
As per earlier discussions with dslake
2011-10-07 21:15:37 +01:00
Justin Clark-Casey (justincc) 270f0d5ae3 Clarify explanation of DeleteScriptsOnStartup switch in [XEngine]. 2011-10-07 20:29:12 +01:00
Dan Lake d079ee9ef1 Add execute permission to runprebuild2010.bat 2011-10-07 20:28:41 +01:00
Justin Clark-Casey (justincc) cd46bf6fad Remove OpenSim.Region.Examples.SimpleModule
This module is more than 2 years old and at least some of the 'example' code it gives is now misleading.
Even the logs say it say some bits were broken where it was put in!
2011-10-07 20:28:23 +01:00
Justin Clark-Casey (justincc) bb419044ef Add ability to pass in the permissions option (perm) to save oar via RemoteAdmin
Applies patch in http://opensimulator.org/mantis/view.php?id=5686
Thanks Michelle Argus!
2011-10-07 20:28:13 +01:00
Justin Clark-Casey (justincc) 549fdc8b11 copy config information on allow/disallow individual os functions into OpenSim.ini.example
I this is generally useful rather than a 'default' setting
2011-10-07 20:27:57 +01:00
Justin Clark-Casey (justincc) 550d1fea96 remove unused postgresql dll 2011-10-07 20:27:49 +01:00
Justin Clark-Casey (justincc) 94f49e859b Add en_US culture setting to the async delete to inventory thread, to avoid any issues with float serialization with machines set to non en_US locales.
Doing this to see if addresses inventory object deserialization problems in http://opensimulator.org/mantis/view.php?id=5708, though if it does I'm really surprised not to have seen it before now.
Really need to go through and systematically set the culture for every timer and change all BeginInvoke calls to FireAndForget instead.
But don't want to do something like that this close to a release.
2011-10-07 20:27:31 +01:00
Snoopy Pfeffer c2586b0ea9 Fix for rezzing and derezzing HUDs (see Mantis #5406). From now on updates are only sent to affected clients. 2011-10-07 20:27:18 +01:00
Justin Clark-Casey (justincc) 2905288545 Remove the unimplented "clear assets" command.
This was a bizarre relic of a bygone age that had no implementations.
If you're using and want to clear the flotsam asset cache then please use the existing "fcache clear" command
2011-10-07 20:26:15 +01:00
Justin Clark-Casey (justincc) 353170589b Improve locking when access queue in EventQueueGetModule 2011-10-07 20:25:13 +01:00
Justin Clark-Casey (justincc) ee78c4d2a8 Clarify explanation of the "DeleteScriptsOnStartup" config switch and add this to OpenSim.ini.example since it's very useful if you're not updating OpenSim from source.
On reflection, "DeleteScriptsOnStartup" isn't a great name since it suggests real script deletion rather than compiled versions.
2011-10-07 20:22:16 +01:00
Justin Clark-Casey (justincc) 084df4b7ef make distribution creating code to copy FlotsamCache.ini.example to FlotsamCache.ini 2011-10-07 20:22:08 +01:00
Justin Clark-Casey (justincc) 53ffc7ff8c bump version up to 0.7.2-rc2 2011-09-23 22:47:23 +01:00
Justin Clark-Casey (justincc) d8d048cfa1 oops, reinstate the try catching of async_call_method but leave the logging disabled 2011-09-23 22:45:02 +01:00
Justin Clark-Casey (justincc) a4e1d29e3c Catch but don't print out exceptions that make it to the top of the async_call_method stack.
This is not helpful for release code.
2011-09-23 22:40:34 +01:00
Justin Clark-Casey (justincc) 8c4dd6b330 Merge branch 'master' into 0.7.2-post-fixes 2011-09-23 22:36:20 +01:00
Justin Clark-Casey (justincc) f1612997a6 Use a copy of the inventory items list to register users in the thread started by GetFolderContent(), to protect ourselves against callers modifying lists
Hopefully this addresses http://opensimulator.org/mantis/view.php?id=5681
2011-09-09 01:00:41 +01:00
Justin Clark-Casey (justincc) c574c80011 Fix unit tests from RegionSettings commit 2011-09-09 00:47:52 +01:00
Justin Clark-Casey (justincc) 9f76bc4fff Save the default terrain texture UUIDs for a new region instead of leaving them as UUID.Zero.
Leaving them at UUID.Zero meant that when a viewer 2 logged into a region that had been freshly created, it received UUID.Zero for these textures, and hence display the land as plain white.
On a simulator restart, the problem would go away since when the database adapators loaded the new region settings, RegionSettings itself has code to use default textures instead of UUID.Zero.
This commit resolves the problem by saving the default texture UUIDs instead of Zero.
However, we currently have to do this in a roundabout way by resaving once the RegionSettings have been created by the database for the first time.  This needless complexity should be addressed.
This change will also have the effect of replacing any existing UUID.Zero terrain textures with the default ones.
However, this shouldn't have any effect since the UUID.Zeros were already being replaced in memory with those same UUIDs.
2011-09-09 00:29:59 +01:00
Justin Clark-Casey (justincc) 79f3de6ba8 change version to rc1 2011-09-08 22:16:42 +01:00
253 changed files with 15510 additions and 14202 deletions

View File

@ -8,6 +8,7 @@
<target name="distbin"> <target name="distbin">
<copy file="bin/OpenSim.ini.example" tofile="bin/OpenSim.ini"/> <copy file="bin/OpenSim.ini.example" tofile="bin/OpenSim.ini"/>
<copy file="bin/config-include/StandaloneCommon.ini.example" tofile="bin/config-include/StandaloneCommon.ini"/> <copy file="bin/config-include/StandaloneCommon.ini.example" tofile="bin/config-include/StandaloneCommon.ini"/>
<copy file="bin/config-include/FlotsamCache.ini.example" tofile="bin/config-include/FlotsamCache.ini"/>
<delete dir="${distbindir}"/> <delete dir="${distbindir}"/>
<copy todir="${distbindir}"> <copy todir="${distbindir}">
<fileset> <fileset>
@ -111,12 +112,15 @@
</exec> </exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.serialization.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.serialization.tests)==0}" />
<!-- <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindencaps.tests">
<arg value="./bin/OpenSim.Region.ClientStack.LindenCaps.Tests.dll" />
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindencaps.tests)==0}" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests"> <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests">
<arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" /> <arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" />
</exec> </exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
-->
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.scriptengine.tests"> <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.scriptengine.tests">
<arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" /> <arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" />
@ -297,12 +301,15 @@
<arg value="-xml=test-results/OpenSim.Framework.Servers.Tests.dll-Results.xml" /> <arg value="-xml=test-results/OpenSim.Framework.Servers.Tests.dll-Results.xml" />
</exec> </exec>
<!-- <exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindencaps.tests">
<arg value="./bin/OpenSim.Region.ClientStack.LindenCaps.Tests.dll" />
<arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenCaps.Tests.dll-Results.xml" />
</exec>
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests"> <exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests">
<arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" /> <arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" />
<arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenUDP.Tests.dll-Results.xml" /> <arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenUDP.Tests.dll-Results.xml" />
</exec> </exec>
-->
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.scriptengine.tests"> <exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.scriptengine.tests">
<arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" /> <arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" />
@ -332,7 +339,7 @@
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />
<!-- <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" /> --> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" /> <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />

View File

@ -51,11 +51,10 @@ namespace OpenSim.Framework.Capabilities
/// supplied BaseHttpServer. /// supplied BaseHttpServer.
/// </summary> /// </summary>
/// <param name="httpListener">base HTTP server</param> /// <param name="httpListener">base HTTP server</param>
/// <param name="httpListenerHostname">host name of the HTTP /// <param name="httpListenerHostname">host name of the HTTP server</param>
/// server</param>
/// <param name="httpListenerPort">HTTP port</param> /// <param name="httpListenerPort">HTTP port</param>
public CapsHandlers(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort) public CapsHandlers(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort)
: this (httpListener,httpListenerHostname,httpListenerPort, false) : this(httpListener,httpListenerHostname,httpListenerPort, false)
{ {
} }
@ -87,14 +86,18 @@ namespace OpenSim.Framework.Capabilities
/// <param name="capsName">name of the capability of the cap /// <param name="capsName">name of the capability of the cap
/// handler to be removed</param> /// handler to be removed</param>
public void Remove(string capsName) public void Remove(string capsName)
{
lock (m_capsHandlers)
{ {
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
m_capsHandlers.Remove(capsName); m_capsHandlers.Remove(capsName);
} }
}
public bool ContainsCap(string cap) public bool ContainsCap(string cap)
{ {
lock (m_capsHandlers)
return m_capsHandlers.ContainsKey(cap); return m_capsHandlers.ContainsKey(cap);
} }
@ -102,19 +105,22 @@ namespace OpenSim.Framework.Capabilities
/// The indexer allows us to treat the CapsHandlers object /// The indexer allows us to treat the CapsHandlers object
/// in an intuitive dictionary like way. /// in an intuitive dictionary like way.
/// </summary> /// </summary>
/// <Remarks> /// <remarks>
/// The indexer will throw an exception when you try to /// The indexer will throw an exception when you try to
/// retrieve a cap handler for a cap that is not contained in /// retrieve a cap handler for a cap that is not contained in
/// CapsHandlers. /// CapsHandlers.
/// </Remarks> /// </remarks>
public IRequestHandler this[string idx] public IRequestHandler this[string idx]
{ {
get get
{ {
lock (m_capsHandlers)
return m_capsHandlers[idx]; return m_capsHandlers[idx];
} }
set set
{
lock (m_capsHandlers)
{ {
if (m_capsHandlers.ContainsKey(idx)) if (m_capsHandlers.ContainsKey(idx))
{ {
@ -128,6 +134,7 @@ namespace OpenSim.Framework.Capabilities
m_httpListener.AddStreamHandler(value); m_httpListener.AddStreamHandler(value);
} }
} }
}
/// <summary> /// <summary>
/// Return the list of cap names for which this CapsHandlers /// Return the list of cap names for which this CapsHandlers
@ -136,20 +143,22 @@ namespace OpenSim.Framework.Capabilities
public string[] Caps public string[] Caps
{ {
get get
{
lock (m_capsHandlers)
{ {
string[] __keys = new string[m_capsHandlers.Keys.Count]; string[] __keys = new string[m_capsHandlers.Keys.Count];
m_capsHandlers.Keys.CopyTo(__keys, 0); m_capsHandlers.Keys.CopyTo(__keys, 0);
return __keys; return __keys;
} }
} }
}
/// <summary> /// <summary>
/// Return an LLSD-serializable Hashtable describing the /// Return an LLSD-serializable Hashtable describing the
/// capabilities and their handler details. /// capabilities and their handler details.
/// </summary> /// </summary>
public Hashtable CapsDetails /// <param name="excludeSeed">If true, then exclude the seed cap.</param>
{ public Hashtable GetCapsDetails(bool excludeSeed)
get
{ {
Hashtable caps = new Hashtable(); Hashtable caps = new Hashtable();
string protocol = "http://"; string protocol = "http://";
@ -158,14 +167,19 @@ namespace OpenSim.Framework.Capabilities
protocol = "https://"; protocol = "https://";
string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString(); string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString();
lock (m_capsHandlers)
{
foreach (string capsName in m_capsHandlers.Keys) foreach (string capsName in m_capsHandlers.Keys)
{ {
// skip SEED cap if (excludeSeed && "SEED" == capsName)
if ("SEED" == capsName) continue; continue;
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path; caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
} }
}
return caps; return caps;
} }
} }
}
} }

View File

@ -111,6 +111,10 @@ namespace OpenSim.Capabilities.Handlers
m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
} }
// m_log.DebugFormat(
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
httpResponse.Send(); httpResponse.Send();
return null; return null;
} }
@ -210,7 +214,7 @@ namespace OpenSim.Capabilities.Handlers
private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format) private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format)
{ {
string range = request.Headers.GetOne("Range"); string range = request.Headers.GetOne("Range");
//m_log.DebugFormat("[GETTEXTURE]: Range {0}", range);
if (!String.IsNullOrEmpty(range)) // JP2's only if (!String.IsNullOrEmpty(range)) // JP2's only
{ {
// Range request // Range request
@ -222,16 +226,19 @@ namespace OpenSim.Capabilities.Handlers
if (start >= texture.Data.Length) if (start >= texture.Data.Length)
{ {
response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
return;
} }
else
{
end = Utils.Clamp(end, 0, texture.Data.Length - 1); end = Utils.Clamp(end, 0, texture.Data.Length - 1);
start = Utils.Clamp(start, 0, end); start = Utils.Clamp(start, 0, end);
int len = end - start + 1; int len = end - start + 1;
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
if (len < texture.Data.Length) // Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentLength = len; response.ContentLength = len;
@ -240,6 +247,7 @@ namespace OpenSim.Capabilities.Handlers
response.Body.Write(texture.Data, start, len); response.Body.Write(texture.Data, start, len);
} }
}
else else
{ {
m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
@ -257,6 +265,10 @@ namespace OpenSim.Capabilities.Handlers
response.ContentType = "image/" + format; response.ContentType = "image/" + format;
response.Body.Write(texture.Data, 0, texture.Data.Length); response.Body.Write(texture.Data, 0, texture.Data.Length);
} }
// m_log.DebugFormat(
// "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
} }
private bool TryParseRange(string header, out int start, out int end) private bool TryParseRange(string header, out int start, out int end)
@ -275,7 +287,6 @@ namespace OpenSim.Capabilities.Handlers
return false; return false;
} }
private byte[] ConvertTextureData(AssetBase texture, string format) private byte[] ConvertTextureData(AssetBase texture, string format)
{ {
m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format); m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
@ -350,7 +361,5 @@ namespace OpenSim.Capabilities.Handlers
} }
return null; return null;
} }
} }
} }

View File

@ -0,0 +1,181 @@
/*
* 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;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
using System.Web;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class UploadBakedTextureHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Caps m_HostCapsObj;
private IAssetService m_assetService;
private bool m_persistBakedTextures;
public UploadBakedTextureHandler(Caps caps, IAssetService assetService, bool persistBakedTextures)
{
m_HostCapsObj = caps;
m_assetService = assetService;
m_persistBakedTextures = persistBakedTextures;
}
/// <summary>
/// Handle a request from the client for a Uri to upload a baked texture.
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <returns>The upload response if the request is successful, null otherwise.</returns>
public string UploadBakedTexture(
string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
try
{
string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
BakedTextureUploader uploader =
new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener);
uploader.OnUpLoad += BakedTextureUploaded;
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler("POST", capsBase + uploaderPath,
uploader.uploaderCaps));
string protocol = "http://";
if (m_HostCapsObj.SSLCaps)
protocol = "https://";
string uploaderURL = protocol + m_HostCapsObj.HostName + ":" +
m_HostCapsObj.Port.ToString() + capsBase + uploaderPath;
LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
uploadResponse.uploader = uploaderURL;
uploadResponse.state = "upload";
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
}
catch (Exception e)
{
m_log.Error("[UPLOAD BAKED TEXTURE HANDLER]: " + e.ToString());
}
return null;
}
/// <summary>
/// Called when a baked texture has been successfully uploaded by a client.
/// </summary>
/// <param name="assetID"></param>
/// <param name="data"></param>
private void BakedTextureUploaded(UUID assetID, byte[] data)
{
// m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString());
AssetBase asset;
asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
asset.Data = data;
asset.Temporary = true;
asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
m_assetService.Store(asset);
}
}
class BakedTextureUploader
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public event Action<UUID, byte[]> OnUpLoad;
private string uploaderPath = String.Empty;
private UUID newAssetID;
private IHttpServer httpListener;
public BakedTextureUploader(string path, IHttpServer httpServer)
{
newAssetID = UUID.Random();
uploaderPath = path;
httpListener = httpServer;
// m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
}
/// <summary>
/// Handle raw uploaded baked texture data.
/// </summary>
/// <param name="data"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <returns></returns>
public string uploaderCaps(byte[] data, string path, string param)
{
Action<UUID, byte[]> handlerUpLoad = OnUpLoad;
// Don't do this asynchronously, otherwise it's possible for the client to send set appearance information
// on another thread which might send out avatar updates before the asset has been put into the asset
// service.
if (handlerUpLoad != null)
handlerUpLoad(newAssetID, data);
string res = String.Empty;
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
uploadComplete.new_asset = newAssetID.ToString();
uploadComplete.new_inventory_item = UUID.Zero;
uploadComplete.state = "complete";
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
httpListener.RemoveStreamHandler("POST", uploaderPath);
// m_log.DebugFormat("[BAKED TEXTURE UPLOADER]: baked texture upload completed for {0}", newAssetID);
return res;
}
}
}

View File

@ -208,7 +208,86 @@ namespace OpenSim.Capabilities.Handlers
containingFolder.Owner = agentID; containingFolder.Owner = agentID;
containingFolder = m_InventoryService.GetFolder(containingFolder); containingFolder = m_InventoryService.GetFolder(containingFolder);
if (containingFolder != null) if (containingFolder != null)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
// containingFolder.Name, containingFolder.ID, agentID);
version = containingFolder.Version; version = containingFolder.Version;
//
// if (fetchItems)
// {
// 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);
// }
// }
//
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
// linkedItem.Name, folderID, agentID);
//
// contents.Items.Add(linkedItem);
// }
//
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
// // will be broken in the viewer.
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
// 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)
// {
// // We don't need to send the folder if source and destination of the link are in the same
// // folder.
// if (linkedItem.Folder != containingFolder.ID)
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
// }
// }
// }
//
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
// linkedItemFolderId, folderID, agentID);
//
// int dummyVersion;
// InventoryCollection linkedCollection
// = Fetch(
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
//
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
// linkedFolder.Owner = agentID;
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
//
//// contents.Folders.AddRange(linkedCollection.Folders);
//
// contents.Folders.Add(linkedFolder);
// contents.Items.AddRange(linkedCollection.Items);
// }
// }
}
} }
else else
{ {

View File

@ -33,6 +33,7 @@ using System.IO;
using System.Xml; using System.Xml;
using System.Collections.Generic; using System.Collections.Generic;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Framework;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using OpenMetaverse; using OpenMetaverse;

View File

@ -37,10 +37,30 @@ namespace OpenSim.Data
public UUID RegionID; public UUID RegionID;
public UUID ScopeID; public UUID ScopeID;
public string RegionName; public string RegionName;
/// <summary>
/// The position in meters of this region.
/// </summary>
public int posX; public int posX;
/// <summary>
/// The position in meters of this region.
/// </summary>
public int posY; public int posY;
public int sizeX; public int sizeX;
public int sizeY; public int sizeY;
/// <summary>
/// Return the x-coordinate of this region.
/// </summary>
public int coordX { get { return posX / (int)Constants.RegionSize; } }
/// <summary>
/// Return the y-coordinate of this region.
/// </summary>
public int coordY { get { return posY / (int)Constants.RegionSize; } }
public Dictionary<string, object> Data; public Dictionary<string, object> Data;
} }

View File

@ -794,7 +794,8 @@ namespace OpenSim.Data.MySQL
{ {
dbcon.Open(); dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid", dbcon)) // System folders can never be deleted. Period.
using (MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid and type=-1", dbcon))
{ {
cmd.Parameters.AddWithValue("?uuid", folderID.ToString()); cmd.Parameters.AddWithValue("?uuid", folderID.ToString());

View File

@ -56,13 +56,21 @@ namespace OpenSim.Data.Null
/// <returns></returns> /// <returns></returns>
public FriendsData[] GetFriends(string userID) public FriendsData[] GetFriends(string userID)
{ {
List<FriendsData> lst = m_Data.FindAll(delegate (FriendsData fdata) List<FriendsData> lst = m_Data.FindAll(fdata =>
{ {
return fdata.PrincipalID == userID.ToString(); return fdata.PrincipalID == userID.ToString();
}); });
if (lst != null) if (lst != null)
{
lst.ForEach(f =>
{
FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID);
if (f2 != null) { f.Data["TheirFlags"] = f2.Data["Flags"]; }
});
return lst.ToArray(); return lst.ToArray();
}
return new FriendsData[0]; return new FriendsData[0];
} }

View File

@ -311,7 +311,7 @@ namespace OpenSim.Framework
if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map))
{ {
Appearance.Unpack((OSDMap)args["packed_appearance"]); Appearance.Unpack((OSDMap)args["packed_appearance"]);
m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance"); // m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance");
} }
else else
{ {

View File

@ -335,7 +335,7 @@ namespace OpenSim.Framework
public virtual OSDMap Pack() public virtual OSDMap Pack()
{ {
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); // m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
OSDMap args = new OSDMap(); OSDMap args = new OSDMap();
args["message_type"] = OSD.FromString("AgentData"); args["message_type"] = OSD.FromString("AgentData");

View File

@ -31,19 +31,10 @@ namespace OpenSim.Framework
{ {
public string PhysicsEngine { get; set; } public string PhysicsEngine { get; set; }
public string MeshEngineName { get; set; } public string MeshEngineName { get; set; }
public bool See_into_region_from_neighbor { get; set; }
public string StorageDll { get; set; } public string StorageDll { get; set; }
public string ClientstackDll { get; set; } public string ClientstackDll { get; set; }
public bool PhysicalPrim { get; set; }
public string LibrariesXMLFile { get; set; } public string LibrariesXMLFile { get; set; }
public const uint DefaultAssetServerHttpPort = 8003;
public const uint DefaultRegionHttpPort = 9000; public const uint DefaultRegionHttpPort = 9000;
public const uint DefaultUserServerHttpPort = 8002;
public const bool DefaultUserServerHttpSSL = false;
public const uint DefaultMessageServerHttpPort = 8006;
public const bool DefaultMessageServerHttpSSL = false;
public const uint DefaultGridServerHttpPort = 8003;
public const uint DefaultInventoryServerHttpPort = 8003;
} }
} }

View File

@ -33,7 +33,7 @@ using System.Reflection;
using System.Xml; using System.Xml;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework.Console; //using OpenSim.Framework.Console;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {

View File

@ -33,12 +33,11 @@ using System.Reflection;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using log4net; using log4net;
using OpenSim.Framework;
namespace OpenSim.Framework.Console namespace OpenSim.Framework.Console
{ {
public delegate void CommandDelegate(string module, string[] cmd); public class Commands : ICommands
public class Commands
{ {
/// <summary> /// <summary>
/// Encapsulates a command that can be invoked from the console /// Encapsulates a command that can be invoked from the console
@ -564,14 +563,16 @@ namespace OpenSim.Framework.Console
/// <summary> /// <summary>
/// A console that processes commands internally /// A console that processes commands internally
/// </summary> /// </summary>
public class CommandConsole : ConsoleBase public class CommandConsole : ConsoleBase, ICommandConsole
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public Commands Commands = new Commands(); public ICommands Commands { get; private set; }
public CommandConsole(string defaultPrompt) : base(defaultPrompt) public CommandConsole(string defaultPrompt) : base(defaultPrompt)
{ {
Commands = new Commands();
Commands.AddCommand("console", false, "help", "help [<command>]", Commands.AddCommand("console", false, "help", "help [<command>]",
"Get general command list or more detailed help on a specific command", Help); "Get general command list or more detailed help on a specific command", Help);
} }

View File

@ -41,7 +41,7 @@ namespace OpenSim.Framework.Console
protected string prompt = "# "; protected string prompt = "# ";
public object ConsoleScene = null; public object ConsoleScene { get; set; }
/// <summary> /// <summary>
/// The default prompt text. /// The default prompt text.

View File

@ -703,6 +703,12 @@ namespace OpenSim.Framework
UUID AgentId { get; } UUID AgentId { get; }
/// <summary>
/// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it
/// is connected).
/// </summary>
ISceneAgent SceneAgent { get; }
UUID SessionId { get; } UUID SessionId { get; }
UUID SecureSessionId { get; } UUID SecureSessionId { get; }
@ -1011,7 +1017,7 @@ namespace OpenSim.Framework
/// <summary> /// <summary>
/// Set the debug level at which packet output should be printed to console. /// Set the debug level at which packet output should be printed to console.
/// </summary> /// </summary>
void SetDebugPacketLevel(int newDebug); int DebugPacketLevel { get; set; }
void InPacket(object NewPack); void InPacket(object NewPack);
void ProcessInPacket(Packet NewPack); void ProcessInPacket(Packet NewPack);
@ -1096,7 +1102,14 @@ namespace OpenSim.Framework
void SetChildAgentThrottle(byte[] throttle); void SetChildAgentThrottle(byte[] throttle);
void SendAvatarDataImmediate(ISceneEntity avatar); void SendAvatarDataImmediate(ISceneEntity avatar);
void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
/// <summary>
/// Send a positional, velocity, etc. update to the viewer for a given entity.
/// </summary>
/// <param name="entity"></param>
/// <param name="updateFlags"></param>
void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
void ReprioritizeUpdates(); void ReprioritizeUpdates();
void FlushPrimUpdates(); void FlushPrimUpdates();

View File

@ -0,0 +1,90 @@
/*
* 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.Xml;
namespace OpenSim.Framework
{
public delegate void CommandDelegate(string module, string[] cmd);
public interface ICommands
{
void FromXml(XmlElement root, CommandDelegate fn);
/// <summary>
/// Get help for the given help string
/// </summary>
/// <param name="helpParts">Parsed parts of the help string. If empty then general help is returned.</param>
/// <returns></returns>
List<string> GetHelp(string[] cmd);
/// <summary>
/// Add a command to those which can be invoked from the console.
/// </summary>
/// <param name="module"></param>
/// <param name="command"></param>
/// <param name="help"></param>
/// <param name="longhelp"></param>
/// <param name="fn"></param>
void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn);
/// <summary>
/// Add a command to those which can be invoked from the console.
/// </summary>
/// <param name="module"></param>
/// <param name="command"></param>
/// <param name="help"></param>
/// <param name="longhelp"></param>
/// <param name="descriptivehelp"></param>
/// <param name="fn"></param>
void AddCommand(string module, bool shared, string command,
string help, string longhelp, string descriptivehelp,
CommandDelegate fn);
string[] FindNextOption(string[] cmd, bool term);
string[] Resolve(string[] cmd);
XmlElement GetXml(XmlDocument doc);
}
public interface ICommandConsole : IConsole
{
ICommands Commands { get; }
/// <summary>
/// Display a command prompt on the console and wait for user input
/// </summary>
void Prompt();
void RunCommand(string cmd);
string ReadLine(string p, bool isCommand, bool e);
}
}

View File

@ -25,27 +25,29 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.IO; using System;
using OpenMetaverse; using System.Collections.Generic;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Examples.SimpleModule namespace OpenSim.Framework
{ {
public class FileSystemObject : SceneObjectGroup public interface IConsole
{ {
public FileSystemObject(FileInfo fileInfo, Vector3 pos) object ConsoleScene { get; }
: base(UUID.Zero, pos, PrimitiveBaseShape.Default)
{
Text = fileInfo.Name;
}
protected override bool InSceneBackup void Output(string text, string level);
{ void Output(string text);
get void OutputFormat(string format, params object[] components);
{
return false; string CmdPrompt(string p);
} string CmdPrompt(string p, string def);
} string CmdPrompt(string p, List<char> excludedCharacters);
string CmdPrompt(string p, string def, List<char> excludedCharacters);
// Displays a command prompt and returns a default value, user may only enter 1 of 2 options
string CmdPrompt(string prompt, string defaultresponse, List<string> options);
// Displays a prompt and waits for the user to enter a string, then returns that string
// (Done with no echo and suitable for passwords)
string PasswdPrompt(string p);
} }
} }

View File

@ -26,22 +26,19 @@
*/ */
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework.Console; //using OpenSim.Framework.Console;
using Nini.Config; using Nini.Config;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
public delegate void restart(RegionInfo thisRegion); public delegate void restart(RegionInfo thisRegion);
//public delegate void regionup (RegionInfo thisRegion);
public enum RegionStatus : int public enum RegionStatus : int
{ {
Down = 0, Down = 0,
Up = 1, Up = 1,
Crashed = 2, Crashed = 2,
Starting = 3, Starting = 3,
SlaveScene = 4
}; };
/// <value> /// <value>
@ -71,12 +68,14 @@ namespace OpenSim.Framework
event restart OnRestart; event restart OnRestart;
/// <summary> /// <summary>
/// Register the new client with the scene. The client starts off as a child agent - the later agent crossing /// Add a new client and create a presence for it. All clients except initial login clients will starts off as a child agent
/// will promote it to a root agent. /// - the later agent crossing will promote it to a root agent.
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="type">The type of agent to add.</param> /// <param name="type">The type of agent to add.</param>
void AddNewClient(IClientAPI client, PresenceType type); /// <returns>
/// The scene agent if the new client was added or if an agent that already existed.</returns>
ISceneAgent AddNewClient(IClientAPI client, PresenceType type);
/// <summary> /// <summary>
/// Remove the given client from the scene. /// Remove the given client from the scene.
@ -90,28 +89,31 @@ namespace OpenSim.Framework
string GetSimulatorVersion(); string GetSimulatorVersion();
/// <summary>
/// Is the agent denoted by the given agentID a child presence in this scene?
/// </summary>
///
/// Used by ClientView when a 'kick everyone' or 'estate message' occurs
///
/// <param name="avatarID">AvatarID to lookup</param>
/// <returns>true if the presence is a child agent, false if the presence is a root exception</returns>
/// <exception cref="System.NullReferenceException">
/// Thrown if the agent does not exist.
/// </exception>
bool PresenceChildStatus(UUID agentId);
bool TryGetScenePresence(UUID agentID, out object scenePresence); bool TryGetScenePresence(UUID agentID, out object scenePresence);
T RequestModuleInterface<T>(); /// <summary>
T[] RequestModuleInterfaces<T>(); /// Register an interface to a region module. This allows module methods to be called directly as
/// well as via events. If there is already a module registered for this interface, it is not replaced
/// (is this the best behaviour?)
/// </summary>
/// <param name="mod"></param>
void RegisterModuleInterface<M>(M mod); void RegisterModuleInterface<M>(M mod);
void StackModuleInterface<M>(M mod); void StackModuleInterface<M>(M mod);
void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback); /// <summary>
/// For the given interface, retrieve the region module which implements it.
/// </summary>
/// <returns>null if there is no registered module implementing that interface</returns>
T RequestModuleInterface<T>();
/// <summary>
/// For the given interface, retrieve an array of region modules that implement it.
/// </summary>
/// <returns>an empty array if there are no registered modules implementing that interface</returns>
T[] RequestModuleInterfaces<T>();
// void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback);
ISceneObject DeserializeObject(string representation); ISceneObject DeserializeObject(string representation);

View File

@ -25,44 +25,51 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Collections.Generic; using System;
using OpenMetaverse;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
public delegate void ExpectUserDelegate(AgentCircuitData agent); /// <summary>
/// An agent in the scene.
/// </summary>
public delegate void UpdateNeighbours(List<RegionInfo> neighbours); /// <remarks>
/// Interface is a work in progress. Please feel free to add other required properties and methods.
public delegate void AgentCrossing(UUID agentID, Vector3 position, bool isFlying); /// </remarks>
public interface ISceneAgent : ISceneEntity
public delegate void PrimCrossing(UUID primID, Vector3 position, bool isPhysical);
public delegate void AcknowledgeAgentCross(UUID agentID);
public delegate void AcknowledgePrimCross(UUID PrimID);
public delegate bool CloseAgentConnection(UUID agentID);
public delegate bool ChildAgentUpdate(ChildAgentDataUpdate cAgentData);
public delegate void LogOffUser(UUID agentID, UUID regionSecret, string message);
public delegate LandData GetLandData(uint x, uint y);
public interface IRegionCommsListener
{ {
event ExpectUserDelegate OnExpectUser; /// <value>
event GenericCall2 OnExpectChildAgent; /// The client controlling this presence
event AgentCrossing OnAvatarCrossingIntoRegion; /// </value>
event PrimCrossing OnPrimCrossingIntoRegion; IClientAPI ControllingClient { get; }
event AcknowledgeAgentCross OnAcknowledgeAgentCrossed;
event AcknowledgePrimCross OnAcknowledgePrimCrossed; /// <summary>
event UpdateNeighbours OnNeighboursUpdate; /// What type of presence is this? User, NPC, etc.
event CloseAgentConnection OnCloseAgentConnection; /// </summary>
event ChildAgentUpdate OnChildAgentUpdate; PresenceType PresenceType { get; }
event LogOffUser OnLogOffUser;
event GetLandData OnGetLandData; /// <summary>
/// If true, then the agent has no avatar in the scene.
/// The agent exists to relay data from a region that neighbours the current position of the user's avatar.
/// Occasionally data is relayed, such as which a user clicks an item in a neighbouring region.
/// </summary>
bool IsChildAgent { get; }
/// <summary>
/// Avatar appearance data.
/// </summary>
/// <remarks>
// Because appearance setting is in a module, we actually need
// to give it access to our appearance directly, otherwise we
// get a synchronization issue.
/// </remarks>
AvatarAppearance Appearance { get; set; }
/// <summary>
/// Send initial scene data to the client controlling this agent
/// </summary>
/// <remarks>
/// This includes scene object data and the appearance data of other avatars.
/// </remarks>
void SendInitialDataToMe();
} }
} }

View File

@ -34,6 +34,7 @@ namespace OpenSim.Framework
string Name { get; set; } string Name { get; set; }
UUID UUID { get; } UUID UUID { get; }
uint LocalId { get; } uint LocalId { get; }
Vector3 AbsolutePosition { get; } Vector3 AbsolutePosition { get; }
} }
} }

View File

@ -33,6 +33,12 @@ namespace OpenSim.Framework
public interface ISceneObject public interface ISceneObject
{ {
UUID UUID { get; } UUID UUID { get; }
/// <summary>
/// The owner of this object.
/// </summary>
UUID OwnerID { get; set; }
ISceneObject CloneForNewScene(); ISceneObject CloneForNewScene();
string ToXml2(); string ToXml2();
string ExtraToXmlString(); string ExtraToXmlString();

View File

@ -25,13 +25,13 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
namespace OpenSim.Framework.Console namespace OpenSim.Framework
{ {
public class MainConsole public class MainConsole
{ {
private static CommandConsole instance; private static ICommandConsole instance;
public static CommandConsole Instance public static ICommandConsole Instance
{ {
get { return instance; } get { return instance; }
set { instance = value; } set { instance = value; }

View File

@ -32,19 +32,9 @@ namespace OpenSim.Framework
{ {
public class NetworkServersInfo public class NetworkServersInfo
{ {
public string AssetSendKey = String.Empty;
public string AssetURL = "http://127.0.0.1:" + ConfigSettings.DefaultAssetServerHttpPort.ToString() + "/";
public string GridRecvKey = String.Empty;
public string GridSendKey = String.Empty;
public string GridURL = String.Empty;
public uint HttpListenerPort = ConfigSettings.DefaultRegionHttpPort; public uint HttpListenerPort = ConfigSettings.DefaultRegionHttpPort;
public string InventoryURL = String.Empty;
public bool secureInventoryServer = false; public bool secureInventoryServer = false;
public bool isSandbox; public bool isSandbox;
public string UserRecvKey = String.Empty;
public string UserSendKey = String.Empty;
public string UserURL = String.Empty;
public bool HttpUsesSSL = false; public bool HttpUsesSSL = false;
public string HttpSSLCN = ""; public string HttpSSLCN = "";
public uint httpSSLPort = 9001; public uint httpSSLPort = 9001;
@ -55,8 +45,6 @@ namespace OpenSim.Framework
public string cert_path = String.Empty; public string cert_path = String.Empty;
public string cert_pass = String.Empty; public string cert_pass = String.Empty;
public string MessagingURL = String.Empty;
public NetworkServersInfo() public NetworkServersInfo()
{ {
} }
@ -65,33 +53,14 @@ namespace OpenSim.Framework
{ {
} }
public void loadFromConfiguration(IConfigSource config) public void loadFromConfiguration(IConfigSource config)
{ {
HttpListenerPort = HttpListenerPort =
(uint) config.Configs["Network"].GetInt("http_listener_port", (int) ConfigSettings.DefaultRegionHttpPort); (uint) config.Configs["Network"].GetInt("http_listener_port", (int) ConfigSettings.DefaultRegionHttpPort);
httpSSLPort = httpSSLPort =
(uint)config.Configs["Network"].GetInt("http_listener_sslport", ((int)ConfigSettings.DefaultRegionHttpPort+1)); (uint)config.Configs["Network"].GetInt("http_listener_sslport", ((int)ConfigSettings.DefaultRegionHttpPort+1));
HttpUsesSSL = config.Configs["Network"].GetBoolean("http_listener_ssl", false); HttpUsesSSL = config.Configs["Network"].GetBoolean("http_listener_ssl", false);
HttpSSLCN = config.Configs["Network"].GetString("http_listener_cn", "localhost"); HttpSSLCN = config.Configs["Network"].GetString("http_listener_cn", "localhost");
GridURL =
config.Configs["Network"].GetString("grid_server_url",
"http://127.0.0.1:" + ConfigSettings.DefaultGridServerHttpPort.ToString());
GridSendKey = config.Configs["Network"].GetString("grid_send_key", "null");
GridRecvKey = config.Configs["Network"].GetString("grid_recv_key", "null");
UserURL =
config.Configs["Network"].GetString("user_server_url",
"http://127.0.0.1:" + ConfigSettings.DefaultUserServerHttpPort.ToString());
UserSendKey = config.Configs["Network"].GetString("user_send_key", "null");
UserRecvKey = config.Configs["Network"].GetString("user_recv_key", "null");
AssetURL = config.Configs["Network"].GetString("asset_server_url", AssetURL);
InventoryURL = config.Configs["Network"].GetString("inventory_server_url",
"http://127.0.0.1:" +
ConfigSettings.DefaultInventoryServerHttpPort.ToString());
secureInventoryServer = config.Configs["Network"].GetBoolean("secure_inventory_server", true);
MessagingURL = config.Configs["Network"].GetString("messaging_server_url", string.Empty);
// "Out of band management https" // "Out of band management https"
ssl_listener = config.Configs["Network"].GetBoolean("https_listener",false); ssl_listener = config.Configs["Network"].GetBoolean("https_listener",false);

View File

@ -1,204 +0,0 @@
/*
* 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
{
/// <summary>
/// Sandbox mode region comms listener. There is one of these per region
/// </summary>
public class RegionCommsListener : IRegionCommsListener
{
public string debugRegionName = String.Empty;
private AcknowledgeAgentCross handlerAcknowledgeAgentCrossed = null; // OnAcknowledgeAgentCrossed;
private AcknowledgePrimCross handlerAcknowledgePrimCrossed = null; // OnAcknowledgePrimCrossed;
private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
private GenericCall2 handlerExpectChildAgent = null; // OnExpectChildAgent;
private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser
private UpdateNeighbours handlerNeighboursUpdate = null; // OnNeighboursUpdate;
// private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
private LogOffUser handlerLogOffUser = null;
private GetLandData handlerGetLandData = null;
#region IRegionCommsListener Members
public event ExpectUserDelegate OnExpectUser;
public event GenericCall2 OnExpectChildAgent;
public event AgentCrossing OnAvatarCrossingIntoRegion;
public event PrimCrossing OnPrimCrossingIntoRegion;
public event UpdateNeighbours OnNeighboursUpdate;
public event AcknowledgeAgentCross OnAcknowledgeAgentCrossed;
public event AcknowledgePrimCross OnAcknowledgePrimCrossed;
public event CloseAgentConnection OnCloseAgentConnection;
public event ChildAgentUpdate OnChildAgentUpdate;
public event LogOffUser OnLogOffUser;
public event GetLandData OnGetLandData;
#endregion
/// <summary>
///
/// </summary>
/// <param name="agent"></param>
/// <returns></returns>
public virtual bool TriggerExpectUser(AgentCircuitData agent)
{
handlerExpectUser = OnExpectUser;
if (handlerExpectUser != null)
{
handlerExpectUser(agent);
return true;
}
return false;
}
// From User Server
public virtual void TriggerLogOffUser(UUID agentID, UUID RegionSecret, string message)
{
handlerLogOffUser = OnLogOffUser;
if (handlerLogOffUser != null)
{
handlerLogOffUser(agentID, RegionSecret, message);
}
}
public virtual bool TriggerChildAgentUpdate(ChildAgentDataUpdate cAgentData)
{
handlerChildAgentUpdate = OnChildAgentUpdate;
if (handlerChildAgentUpdate != null)
{
handlerChildAgentUpdate(cAgentData);
return true;
}
return false;
}
public virtual bool TriggerExpectAvatarCrossing(UUID agentID, Vector3 position, bool isFlying)
{
handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
if (handlerAvatarCrossingIntoRegion != null)
{
handlerAvatarCrossingIntoRegion(agentID, position, isFlying);
return true;
}
return false;
}
public virtual bool TriggerAcknowledgeAgentCrossed(UUID agentID)
{
handlerAcknowledgeAgentCrossed = OnAcknowledgeAgentCrossed;
if (handlerAcknowledgeAgentCrossed != null)
{
handlerAcknowledgeAgentCrossed(agentID);
return true;
}
return false;
}
public virtual bool TriggerAcknowledgePrimCrossed(UUID primID)
{
handlerAcknowledgePrimCrossed = OnAcknowledgePrimCrossed;
if (handlerAcknowledgePrimCrossed != null)
{
handlerAcknowledgePrimCrossed(primID);
return true;
}
return false;
}
public virtual bool TriggerCloseAgentConnection(UUID agentID)
{
handlerCloseAgentConnection = OnCloseAgentConnection;
if (handlerCloseAgentConnection != null)
{
handlerCloseAgentConnection(agentID);
return true;
}
return false;
}
/// <summary>
///
/// </summary>
/// <remarks>TODO: Doesnt take any args??</remarks>
/// <returns></returns>
public virtual bool TriggerExpectChildAgent()
{
handlerExpectChildAgent = OnExpectChildAgent;
if (handlerExpectChildAgent != null)
{
handlerExpectChildAgent();
return true;
}
return false;
}
/// <summary>
///
/// </summary>
/// <remarks>Added to avoid a unused compiler warning on OnNeighboursUpdate, TODO: Check me</remarks>
/// <param name="neighbours"></param>
/// <returns></returns>
public virtual bool TriggerOnNeighboursUpdate(List<RegionInfo> neighbours)
{
handlerNeighboursUpdate = OnNeighboursUpdate;
if (handlerNeighboursUpdate != null)
{
handlerNeighboursUpdate(neighbours);
return true;
}
return false;
}
public bool TriggerTellRegionToCloseChildConnection(UUID agentID)
{
handlerCloseAgentConnection = OnCloseAgentConnection;
if (handlerCloseAgentConnection != null)
return handlerCloseAgentConnection(agentID);
return false;
}
public LandData TriggerGetLandData(uint x, uint y)
{
handlerGetLandData = OnGetLandData;
if (handlerGetLandData != null)
return handlerGetLandData(x, y);
return null;
}
}
}

View File

@ -36,7 +36,7 @@ using log4net;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
using OpenSim.Framework.Console; //using OpenSim.Framework.Console;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {

View File

@ -192,6 +192,15 @@ namespace OpenSim.Framework.Servers
m_console.Commands.AddCommand("base", false, "show version", m_console.Commands.AddCommand("base", false, "show version",
"show version", "show version",
"Show server version", HandleShow); "Show server version", HandleShow);
m_console.Commands.AddCommand("base", false, "threads abort",
"threads abort <thread-id>",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
m_console.Commands.AddCommand("base", false, "threads show",
"threads show",
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
} }
} }
@ -234,17 +243,28 @@ namespace OpenSim.Framework.Servers
/// </summary> /// </summary>
protected string GetThreadsReport() protected string GetThreadsReport()
{ {
// This should be a constant field.
string reportFormat = "{0,6} {1,35} {2,16} {3,10} {4,30}";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreads(); Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreads();
sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine); sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
int timeNow = Environment.TickCount & Int32.MaxValue;
sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "PRIORITY", "STATE");
sb.Append(Environment.NewLine);
foreach (Watchdog.ThreadWatchdogInfo twi in threads) foreach (Watchdog.ThreadWatchdogInfo twi in threads)
{ {
Thread t = twi.Thread; Thread t = twi.Thread;
sb.Append( sb.AppendFormat(
"ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", TimeRunning: " reportFormat,
+ "Pri: " + t.Priority + ", State: " + t.ThreadState); //t.ManagedThreadId, t.Name, string.Format("{0} ms", timeNow - twi.LastTick), t.Priority, t.ThreadState);
t.ManagedThreadId, t.Name, timeNow - twi.LastTick, t.Priority, t.ThreadState);
sb.Append(Environment.NewLine); sb.Append(Environment.NewLine);
} }
@ -396,6 +416,27 @@ namespace OpenSim.Framework.Servers
} }
} }
public virtual void HandleThreadsAbort(string module, string[] cmd)
{
if (cmd.Length != 3)
{
MainConsole.Instance.Output("Usage: threads abort <thread-id>");
return;
}
int threadId;
if (!int.TryParse(cmd[2], out threadId))
{
MainConsole.Instance.Output("ERROR: Thread id must be an integer");
return;
}
if (Watchdog.AbortThread(threadId))
MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
else
MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
}
protected void ShowInfo() protected void ShowInfo()
{ {
Notice(GetVersionText()); Notice(GetVersionText());

View File

@ -79,6 +79,11 @@ namespace OpenSim.Framework.Servers.HttpServer
private PollServiceRequestManager m_PollServiceManager; private PollServiceRequestManager m_PollServiceManager;
/// <summary>
/// Control the printing of certain debug messages.
/// </summary>
public int DebugLevel { get; set; }
public uint SSLPort public uint SSLPort
{ {
get { return m_sslport; } get { return m_sslport; }
@ -442,17 +447,18 @@ namespace OpenSim.Framework.Servers.HttpServer
string path = request.RawUrl; string path = request.RawUrl;
string handlerKey = GetHandlerKey(request.HttpMethod, path); string handlerKey = GetHandlerKey(request.HttpMethod, path);
//m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
if (TryGetStreamHandler(handlerKey, out requestHandler)) if (TryGetStreamHandler(handlerKey, out requestHandler))
{ {
//m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found stream handler for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
// Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
byte[] buffer = null; byte[] buffer = null;
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
if (requestHandler is IStreamedRequestHandler) if (requestHandler is IStreamedRequestHandler)
{ {
IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
@ -480,7 +486,6 @@ namespace OpenSim.Framework.Servers.HttpServer
string[] querystringkeys = request.QueryString.AllKeys; string[] querystringkeys = request.QueryString.AllKeys;
string[] rHeaders = request.Headers.AllKeys; string[] rHeaders = request.Headers.AllKeys;
foreach (string queryname in querystringkeys) foreach (string queryname in querystringkeys)
{ {
keysvals.Add(queryname, request.QueryString[queryname]); keysvals.Add(queryname, request.QueryString[queryname]);
@ -556,6 +561,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message); m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
} }
return; return;
} }
@ -566,7 +572,11 @@ namespace OpenSim.Framework.Servers.HttpServer
if (strAccept.Contains("application/llsd+xml") || if (strAccept.Contains("application/llsd+xml") ||
strAccept.Contains("application/llsd+json")) strAccept.Contains("application/llsd+json"))
{ {
//m_log.Info("[Debug BASE HTTP SERVER]: Found an application/llsd+xml accept header"); if (DebugLevel >= 1)
m_log.DebugFormat(
"[BASE HTTP SERVER]: Found application/llsd+xml accept header handler for {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
HandleLLSDRequests(request, response); HandleLLSDRequests(request, response);
return; return;
} }
@ -577,15 +587,24 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
case null: case null:
case "text/html": case "text/html":
// m_log.DebugFormat(
// "[BASE HTTP SERVER]: Found a text/html content type for request {0}", 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); HandleHTTPRequest(request, response);
return; return;
case "application/llsd+xml": case "application/llsd+xml":
case "application/xml+llsd": case "application/xml+llsd":
case "application/llsd+json": case "application/llsd+json":
//m_log.Info("[Debug BASE HTTP SERVER]: found a application/llsd+xml content type");
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); HandleLLSDRequests(request, response);
return; return;
@ -602,7 +621,11 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler"); //m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
if (DoWeHaveALLSDHandler(request.RawUrl)) if (DoWeHaveALLSDHandler(request.RawUrl))
{ {
//m_log.Info("[Debug BASE HTTP SERVER]: Found LLSD Handler"); 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); HandleLLSDRequests(request, response);
return; return;
} }
@ -610,12 +633,20 @@ namespace OpenSim.Framework.Servers.HttpServer
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl); // m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
if (DoWeHaveAHTTPHandler(request.RawUrl)) if (DoWeHaveAHTTPHandler(request.RawUrl))
{ {
// m_log.DebugFormat("[BASE HTTP SERVER]: Found HTTP Handler for request {0}", 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); HandleHTTPRequest(request, response);
return; return;
} }
//m_log.Info("[Debug BASE HTTP SERVER]: Generic XMLRPC"); 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. // generic login request.
HandleXmlRpcRequests(request, response); HandleXmlRpcRequests(request, response);
@ -872,7 +903,9 @@ namespace OpenSim.Framework.Servers.HttpServer
byte[] buf = Encoding.UTF8.GetBytes("Not found"); byte[] buf = Encoding.UTF8.GetBytes("Not found");
response.KeepAlive = false; response.KeepAlive = false;
m_log.ErrorFormat("[BASE HTTP SERVER]: Handler not found for http request {0}", request.RawUrl); m_log.ErrorFormat(
"[BASE HTTP SERVER]: Handler not found for http request {0} {1}",
request.HttpMethod, request.Url.PathAndQuery);
response.SendChunked = false; response.SendChunked = false;
response.ContentLength64 = buf.Length; response.ContentLength64 = buf.Length;
@ -978,7 +1011,6 @@ namespace OpenSim.Framework.Servers.HttpServer
if (llsdRequest != null)// && m_defaultLlsdHandler != null) if (llsdRequest != null)// && m_defaultLlsdHandler != null)
{ {
LLSDMethod llsdhandler = null; LLSDMethod llsdhandler = null;
if (TryGetLLSDHandler(request.RawUrl, out llsdhandler) && !LegacyLLSDLoginLibOMV) if (TryGetLLSDHandler(request.RawUrl, out llsdhandler) && !LegacyLLSDLoginLibOMV)
@ -1002,13 +1034,14 @@ namespace OpenSim.Framework.Servers.HttpServer
llsdResponse = GenerateNoLLSDHandlerResponse(); llsdResponse = GenerateNoLLSDHandlerResponse();
} }
} }
} }
else else
{ {
llsdResponse = GenerateNoLLSDHandlerResponse(); llsdResponse = GenerateNoLLSDHandlerResponse();
} }
byte[] buffer = new byte[0]; byte[] buffer = new byte[0];
if (llsdResponse.ToString() == "shutdown404!") if (llsdResponse.ToString() == "shutdown404!")
{ {
response.ContentType = "text/plain"; response.ContentType = "text/plain";
@ -1814,12 +1847,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public void RemovePollServiceHTTPHandler(string httpMethod, string path) public void RemovePollServiceHTTPHandler(string httpMethod, string path)
{ {
lock (m_pollHandlers) lock (m_pollHandlers)
{ m_pollHandlers.Remove(path);
if (m_pollHandlers.ContainsKey(httpMethod))
{
m_pollHandlers.Remove(httpMethod);
}
}
RemoveHTTPHandler(httpMethod, path); RemoveHTTPHandler(httpMethod, path);
} }
@ -1843,13 +1871,8 @@ namespace OpenSim.Framework.Servers.HttpServer
public void RemoveXmlRPCHandler(string method) public void RemoveXmlRPCHandler(string method)
{ {
lock (m_rpcHandlers) lock (m_rpcHandlers)
{
if (m_rpcHandlers.ContainsKey(method))
{
m_rpcHandlers.Remove(method); m_rpcHandlers.Remove(method);
} }
}
}
public bool RemoveLLSDHandler(string path, LLSDMethod handler) public bool RemoveLLSDHandler(string path, LLSDMethod handler)
{ {

View File

@ -49,7 +49,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// <summary> /// <summary>
/// Add a handler for an HTTP request. /// Add a handler for an HTTP request.
/// </summary> /// </summary>
/// /// <remarks>
/// This handler can actually be invoked either as /// This handler can actually be invoked either as
/// ///
/// http://<hostname>:<port>/?method=<methodName> /// http://<hostname>:<port>/?method=<methodName>
@ -70,7 +70,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// In addition, the handler invoked by the HTTP server for any request is the one when best matches the request /// In addition, the handler invoked by the HTTP server for any request is the one when best matches the request
/// URI. So if a handler for "/myapp/" is registered and a request for "/myapp/page" is received, then /// URI. So if a handler for "/myapp/" is registered and a request for "/myapp/page" is received, then
/// the "/myapp/" handler is invoked if no "/myapp/page" handler exists. /// the "/myapp/" handler is invoked if no "/myapp/page" handler exists.
/// /// </remarks>
/// <param name="methodName"></param> /// <param name="methodName"></param>
/// <param name="handler"></param> /// <param name="handler"></param>
/// <returns> /// <returns>

View File

@ -28,12 +28,17 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Threading; using System.Threading;
using System.Reflection;
using log4net;
using HttpServer; using HttpServer;
using OpenSim.Framework;
namespace OpenSim.Framework.Servers.HttpServer namespace OpenSim.Framework.Servers.HttpServer
{ {
public class PollServiceRequestManager public class PollServiceRequestManager
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly BaseHttpServer m_server; private readonly BaseHttpServer m_server;
private static Queue m_requests = Queue.Synchronized(new Queue()); private static Queue m_requests = Queue.Synchronized(new Queue());
private uint m_WorkerThreadCount = 0; private uint m_WorkerThreadCount = 0;
@ -42,8 +47,6 @@ namespace OpenSim.Framework.Servers.HttpServer
private Thread m_watcherThread; private Thread m_watcherThread;
private bool m_running = true; private bool m_running = true;
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
{ {
m_server = pSrv; m_server = pSrv;
@ -52,22 +55,27 @@ namespace OpenSim.Framework.Servers.HttpServer
m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount]; m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
//startup worker threads //startup worker threads
for (uint i=0;i<m_WorkerThreadCount;i++) for (uint i = 0; i < m_WorkerThreadCount; i++)
{ {
m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, pTimeout); m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, pTimeout);
m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent; m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent;
m_workerThreads[i] = new Thread(m_PollServiceWorkerThreads[i].ThreadStart); m_workerThreads[i]
m_workerThreads[i].Name = String.Format("PollServiceWorkerThread{0}",i); = Watchdog.StartThread(
//Can't add to thread Tracker here Referencing OpenSim.Framework creates circular reference m_PollServiceWorkerThreads[i].ThreadStart,
m_workerThreads[i].Start(); String.Format("PollServiceWorkerThread{0}", i),
ThreadPriority.Normal,
false,
int.MaxValue);
} }
//start watcher threads m_watcherThread
m_watcherThread = new Thread(ThreadStart); = Watchdog.StartThread(
m_watcherThread.Name = "PollServiceWatcherThread"; this.ThreadStart,
m_watcherThread.Start(); "PollServiceWatcherThread",
ThreadPriority.Normal,
false,
1000 * 60 * 10);
} }
internal void ReQueueEvent(PollServiceHttpRequest req) internal void ReQueueEvent(PollServiceHttpRequest req)
@ -82,10 +90,11 @@ namespace OpenSim.Framework.Servers.HttpServer
m_requests.Enqueue(req); m_requests.Enqueue(req);
} }
public void ThreadStart(object o) public void ThreadStart()
{ {
while (m_running) while (m_running)
{ {
Watchdog.UpdateThread();
ProcessQueuedRequests(); ProcessQueuedRequests();
Thread.Sleep(1000); Thread.Sleep(1000);
} }
@ -98,12 +107,15 @@ namespace OpenSim.Framework.Servers.HttpServer
if (m_requests.Count == 0) if (m_requests.Count == 0)
return; return;
// m_log.DebugFormat("[POLL SERVICE REQUEST MANAGER]: Processing {0} requests", m_requests.Count);
int reqperthread = (int) (m_requests.Count/m_WorkerThreadCount) + 1; int reqperthread = (int) (m_requests.Count/m_WorkerThreadCount) + 1;
// For Each WorkerThread // For Each WorkerThread
for (int tc = 0; tc < m_WorkerThreadCount && m_requests.Count > 0; tc++) for (int tc = 0; tc < m_WorkerThreadCount && m_requests.Count > 0; tc++)
{ {
//Loop over number of requests each thread handles. //Loop over number of requests each thread handles.
for (int i=0;i<reqperthread && m_requests.Count > 0;i++) for (int i = 0; i < reqperthread && m_requests.Count > 0; i++)
{ {
try try
{ {
@ -121,14 +133,14 @@ namespace OpenSim.Framework.Servers.HttpServer
} }
~PollServiceRequestManager() ~PollServiceRequestManager()
{ {
foreach (object o in m_requests) foreach (object o in m_requests)
{ {
PollServiceHttpRequest req = (PollServiceHttpRequest) o; 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)); m_server.DoHTTPGruntWork(
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
} }
m_requests.Clear(); m_requests.Clear();

View File

@ -59,7 +59,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_timeout = pTimeout; m_timeout = pTimeout;
} }
public void ThreadStart(object o) public void ThreadStart()
{ {
Run(); Run();
} }
@ -69,6 +69,9 @@ namespace OpenSim.Framework.Servers.HttpServer
while (m_running) while (m_running)
{ {
PollServiceHttpRequest req = m_request.Dequeue(); PollServiceHttpRequest req = m_request.Dequeue();
Watchdog.UpdateThread();
try try
{ {
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))

View File

@ -31,7 +31,7 @@ using System.Net;
using log4net; using log4net;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.Framework namespace OpenSim.Framework.Servers
{ {
public class MainServer public class MainServer
{ {

View File

@ -30,7 +30,7 @@ namespace OpenSim
public class VersionInfo public class VersionInfo
{ {
private const string VERSION_NUMBER = "0.7.2"; private const string VERSION_NUMBER = "0.7.2";
private const Flavour VERSION_FLAVOUR = Flavour.Dev; private const Flavour VERSION_FLAVOUR = Flavour.Post_Fixes;
public enum Flavour public enum Flavour
{ {

View File

@ -146,9 +146,9 @@ namespace OpenSim.Framework.Tests
Assert.IsFalse(Util.isUUID("FOOBAR67-89ab-Cdef-0123-456789AbCdEf"), Assert.IsFalse(Util.isUUID("FOOBAR67-89ab-Cdef-0123-456789AbCdEf"),
"UUIDs with non-hex characters are recognized as correct UUIDs."); "UUIDs with non-hex characters are recognized as correct UUIDs.");
Assert.IsFalse(Util.isUUID("01234567"), Assert.IsFalse(Util.isUUID("01234567"),
"Too short UUIDs are regognized as correct UUIDs."); "Too short UUIDs are recognized as correct UUIDs.");
Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123-456789AbCdEf0"), Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123-456789AbCdEf0"),
"Too long UUIDs are regognized as correct UUIDs."); "Too long UUIDs are recognized as correct UUIDs.");
Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123+456789AbCdEf"), Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123+456789AbCdEf"),
"UUIDs with wrong format are recognized as correct UUIDs."); "UUIDs with wrong format are recognized as correct UUIDs.");
} }

View File

@ -46,7 +46,6 @@ using System.Threading;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using Nwc.XmlRpc; using Nwc.XmlRpc;
// using BclExtras;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
using Amib.Threading; using Amib.Threading;
@ -59,10 +58,12 @@ namespace OpenSim.Framework
/// <remarks> /// <remarks>
/// None is used to execute the method in the same thread that made the call. It should only be used by regression /// None is used to execute the method in the same thread that made the call. It should only be used by regression
/// test code that relies on predictable event ordering. /// test code that relies on predictable event ordering.
/// RegressionTest is used by regression tests. It fires the call synchronously and does not catch any exceptions.
/// </remarks> /// </remarks>
public enum FireAndForgetMethod public enum FireAndForgetMethod
{ {
None, None,
RegressionTest,
UnsafeQueueUserWorkItem, UnsafeQueueUserWorkItem,
QueueUserWorkItem, QueueUserWorkItem,
BeginInvoke, BeginInvoke,
@ -91,8 +92,10 @@ namespace OpenSim.Framework
private static readonly DateTime unixEpoch = private static readonly DateTime unixEpoch =
DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
public static readonly Regex UUIDPattern private static readonly string rawUUIDPattern
= new Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
public static readonly Regex PermissiveUUIDPattern = new Regex(rawUUIDPattern);
public static readonly Regex UUIDPattern = new Regex(string.Format("^{0}$", rawUUIDPattern));
public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
@ -1542,11 +1545,20 @@ namespace OpenSim.Framework
} }
public static void FireAndForget(System.Threading.WaitCallback callback, object obj) public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
{
WaitCallback realCallback;
if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
{
// If we're running regression tests, then we want any exceptions to rise up to the test code.
realCallback = o => { Culture.SetCurrentCulture(); callback(o); };
}
else
{ {
// When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture // When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture
// so that we don't encounter problems where, for instance, data is saved with a culture that uses commas // so that we don't encounter problems where, for instance, data is saved with a culture that uses commas
// for decimals places but is read by a culture that treats commas as number seperators. // for decimals places but is read by a culture that treats commas as number seperators.
WaitCallback realCallback = delegate(object o) realCallback = o =>
{ {
Culture.SetCurrentCulture(); Culture.SetCurrentCulture();
@ -1561,9 +1573,11 @@ namespace OpenSim.Framework
e.Message, e.StackTrace); e.Message, e.StackTrace);
} }
}; };
}
switch (FireAndForgetMethod) switch (FireAndForgetMethod)
{ {
case FireAndForgetMethod.RegressionTest:
case FireAndForgetMethod.None: case FireAndForgetMethod.None:
realCallback.Invoke(obj); realCallback.Invoke(obj);
break; break;
@ -1650,13 +1664,14 @@ namespace OpenSim.Framework
/// </summary> /// </summary>
public static void PrintCallStack() public static void PrintCallStack()
{ {
StackTrace stackTrace = new StackTrace(); // get call stack StackTrace stackTrace = new StackTrace(true); // get call stack
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
// write call stack method names // write call stack method names
foreach (StackFrame stackFrame in stackFrames) foreach (StackFrame stackFrame in stackFrames)
{ {
m_log.Debug(stackFrame.GetMethod().DeclaringType + "." + stackFrame.GetMethod().Name); // write method name MethodBase mb = stackFrame.GetMethod();
m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name
} }
} }

View File

@ -40,19 +40,41 @@ namespace OpenSim.Framework
{ {
/// <summary>Timer interval in milliseconds for the watchdog timer</summary> /// <summary>Timer interval in milliseconds for the watchdog timer</summary>
const double WATCHDOG_INTERVAL_MS = 2500.0d; const double WATCHDOG_INTERVAL_MS = 2500.0d;
/// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary> /// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary>
const int WATCHDOG_TIMEOUT_MS = 5000; const int WATCHDOG_TIMEOUT_MS = 5000;
[System.Diagnostics.DebuggerDisplay("{Thread.Name}")] [System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
public class ThreadWatchdogInfo public class ThreadWatchdogInfo
{ {
public Thread Thread; public Thread Thread { get; private set; }
public int LastTick;
public ThreadWatchdogInfo(Thread thread) /// <summary>
/// Approximate tick when this thread was started.
/// </summary>
public int StartTick { get; private set; }
/// <summary>
/// Last time this heartbeat update was invoked
/// </summary>
public int LastTick { get; set; }
/// <summary>
/// Number of milliseconds before we notify that the thread is having a problem.
/// </summary>
public int Timeout { get; set; }
/// <summary>
/// Is this thread considered timed out?
/// </summary>
public bool IsTimedOut { get; set; }
public ThreadWatchdogInfo(Thread thread, int timeout)
{ {
Thread = thread; Thread = thread;
LastTick = Environment.TickCount & Int32.MaxValue; Timeout = timeout;
StartTick = Environment.TickCount & Int32.MaxValue;
LastTick = StartTick;
} }
} }
@ -82,7 +104,7 @@ namespace OpenSim.Framework
} }
/// <summary> /// <summary>
/// Start a new thread that is tracked by the watchdog timer /// Start a new thread that is tracked by the watchdog timer.
/// </summary> /// </summary>
/// <param name="start">The method that will be executed in a new thread</param> /// <param name="start">The method that will be executed in a new thread</param>
/// <param name="name">A name to give to the new thread</param> /// <param name="name">A name to give to the new thread</param>
@ -91,11 +113,37 @@ namespace OpenSim.Framework
/// thread, otherwise false</param> /// thread, otherwise false</param>
/// <returns>The newly created Thread object</returns> /// <returns>The newly created Thread object</returns>
public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground) public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground)
{
return StartThread(start, name, priority, isBackground, WATCHDOG_TIMEOUT_MS);
}
/// <summary>
/// Start a new thread that is tracked by the watchdog timer
/// </summary>
/// <param name="start">The method that will be executed in a new thread</param>
/// <param name="name">A name to give to the new thread</param>
/// <param name="priority">Priority to run the thread at</param>
/// <param name="isBackground">True to run this thread as a background
/// thread, otherwise false</param>
/// <param name="timeout">
/// Number of milliseconds to wait until we issue a warning about timeout.
/// </para>
/// <returns>The newly created Thread object</returns>
public static Thread StartThread(
ThreadStart start, string name, ThreadPriority priority, bool isBackground, int timeout)
{ {
Thread thread = new Thread(start); Thread thread = new Thread(start);
thread.Name = name; thread.Name = name;
thread.Priority = priority; thread.Priority = priority;
thread.IsBackground = isBackground; thread.IsBackground = isBackground;
ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout);
m_log.Debug("[WATCHDOG]: Started tracking thread \"" + twi.Thread.Name + "\" (ID " + twi.Thread.ManagedThreadId + ")");
lock (m_threads)
m_threads.Add(twi.Thread.ManagedThreadId, twi);
thread.Start(); thread.Start();
return thread; return thread;
@ -112,27 +160,40 @@ namespace OpenSim.Framework
/// <summary> /// <summary>
/// Stops watchdog tracking on the current thread /// Stops watchdog tracking on the current thread
/// </summary> /// </summary>
/// <returns>True if the thread was removed from the list of tracked /// <returns>
/// threads, otherwise false</returns> /// True if the thread was removed from the list of tracked
/// threads, otherwise false
/// </returns>
public static bool RemoveThread() public static bool RemoveThread()
{ {
return RemoveThread(Thread.CurrentThread.ManagedThreadId); return RemoveThread(Thread.CurrentThread.ManagedThreadId);
} }
private static void AddThread(ThreadWatchdogInfo threadInfo)
{
m_log.Debug("[WATCHDOG]: Started tracking thread \"" + threadInfo.Thread.Name + "\" (ID " + threadInfo.Thread.ManagedThreadId + ")");
lock (m_threads)
m_threads.Add(threadInfo.Thread.ManagedThreadId, threadInfo);
}
private static bool RemoveThread(int threadID) private static bool RemoveThread(int threadID)
{ {
lock (m_threads) lock (m_threads)
return m_threads.Remove(threadID); return m_threads.Remove(threadID);
} }
public static bool AbortThread(int threadID)
{
lock (m_threads)
{
if (m_threads.ContainsKey(threadID))
{
ThreadWatchdogInfo twi = m_threads[threadID];
twi.Thread.Abort();
RemoveThread(threadID);
return true;
}
else
{
return false;
}
}
}
private static void UpdateThread(int threadID) private static void UpdateThread(int threadID)
{ {
ThreadWatchdogInfo threadInfo; ThreadWatchdogInfo threadInfo;
@ -144,9 +205,14 @@ namespace OpenSim.Framework
try try
{ {
if (m_threads.TryGetValue(threadID, out threadInfo)) if (m_threads.TryGetValue(threadID, out threadInfo))
{
threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; threadInfo.LastTick = Environment.TickCount & Int32.MaxValue;
threadInfo.IsTimedOut = false;
}
else else
AddThread(new ThreadWatchdogInfo(Thread.CurrentThread)); {
m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID);
}
} }
catch { } catch { }
} }
@ -157,6 +223,7 @@ namespace OpenSim.Framework
/// <returns></returns> /// <returns></returns>
public static ThreadWatchdogInfo[] GetThreads() public static ThreadWatchdogInfo[] GetThreads()
{ {
lock (m_threads)
return m_threads.Values.ToArray(); return m_threads.Values.ToArray();
} }
@ -174,10 +241,16 @@ namespace OpenSim.Framework
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
{ {
if (threadInfo.Thread.ThreadState == ThreadState.Stopped || now - threadInfo.LastTick >= WATCHDOG_TIMEOUT_MS) if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
{ {
timedOut = threadInfo; timedOut = threadInfo;
m_threads.Remove(threadInfo.Thread.ManagedThreadId); RemoveThread(threadInfo.Thread.ManagedThreadId);
break;
}
else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout)
{
threadInfo.IsTimedOut = true;
timedOut = threadInfo;
break; break;
} }
} }

View File

@ -39,9 +39,7 @@ using System.Text;
using System.Web; using System.Web;
using System.Xml; using System.Xml;
using System.Xml.Serialization; using System.Xml.Serialization;
using log4net; using log4net;
using OpenSim.Framework.Servers.HttpServer;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
namespace OpenSim.Framework namespace OpenSim.Framework
@ -65,35 +63,35 @@ namespace OpenSim.Framework
// a "long" call for warning & debugging purposes // a "long" call for warning & debugging purposes
public const int LongCallTime = 500; public const int LongCallTime = 500;
/// <summary> // /// <summary>
/// Send LLSD to an HTTP client in application/llsd+json form // /// Send LLSD to an HTTP client in application/llsd+json form
/// </summary> // /// </summary>
/// <param name="response">HTTP response to send the data in</param> // /// <param name="response">HTTP response to send the data in</param>
/// <param name="body">LLSD to send to the client</param> // /// <param name="body">LLSD to send to the client</param>
public static void SendJSONResponse(OSHttpResponse response, OSDMap body) // public static void SendJSONResponse(OSHttpResponse response, OSDMap body)
{ // {
byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body)); // byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body));
//
response.ContentEncoding = Encoding.UTF8; // response.ContentEncoding = Encoding.UTF8;
response.ContentLength = responseData.Length; // response.ContentLength = responseData.Length;
response.ContentType = "application/llsd+json"; // response.ContentType = "application/llsd+json";
response.Body.Write(responseData, 0, responseData.Length); // response.Body.Write(responseData, 0, responseData.Length);
} // }
//
/// <summary> // /// <summary>
/// Send LLSD to an HTTP client in application/llsd+xml form // /// Send LLSD to an HTTP client in application/llsd+xml form
/// </summary> // /// </summary>
/// <param name="response">HTTP response to send the data in</param> // /// <param name="response">HTTP response to send the data in</param>
/// <param name="body">LLSD to send to the client</param> // /// <param name="body">LLSD to send to the client</param>
public static void SendXMLResponse(OSHttpResponse response, OSDMap body) // public static void SendXMLResponse(OSHttpResponse response, OSDMap body)
{ // {
byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body); // byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body);
//
response.ContentEncoding = Encoding.UTF8; // response.ContentEncoding = Encoding.UTF8;
response.ContentLength = responseData.Length; // response.ContentLength = responseData.Length;
response.ContentType = "application/llsd+xml"; // response.ContentType = "application/llsd+xml";
response.Body.Write(responseData, 0, responseData.Length); // response.Body.Write(responseData, 0, responseData.Length);
} // }
/// <summary> /// <summary>
/// Make a GET or GET-like request to a web service that returns LLSD /// Make a GET or GET-like request to a web service that returns LLSD
@ -296,10 +294,10 @@ namespace OpenSim.Framework
return result; return result;
} }
} }
catch (Exception e) catch
{ {
// don't need to treat this as an error... we're just guessing anyway // don't need to treat this as an error... we're just guessing anyway
m_log.DebugFormat("[WEB UTIL] couldn't decode <{0}>: {1}",response,e.Message); // m_log.DebugFormat("[WEB UTIL] couldn't decode <{0}>: {1}",response,e.Message);
} }
return result; return result;

View File

@ -362,10 +362,6 @@ namespace OpenSim
{ {
m_configSettings.PhysicsEngine = startupConfig.GetString("physics"); m_configSettings.PhysicsEngine = startupConfig.GetString("physics");
m_configSettings.MeshEngineName = startupConfig.GetString("meshing"); m_configSettings.MeshEngineName = startupConfig.GetString("meshing");
m_configSettings.PhysicalPrim = startupConfig.GetBoolean("physical_prim", true);
m_configSettings.See_into_region_from_neighbor = startupConfig.GetBoolean("see_into_this_sim_from_neighbor", true);
m_configSettings.StorageDll = startupConfig.GetString("storage_plugin"); m_configSettings.StorageDll = startupConfig.GetString("storage_plugin");
m_configSettings.ClientstackDll m_configSettings.ClientstackDll

View File

@ -37,6 +37,7 @@ using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Statistics; using OpenSim.Framework.Statistics;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
@ -210,28 +211,33 @@ namespace OpenSim
/// </summary> /// </summary>
private void RegisterConsoleCommands() private void RegisterConsoleCommands()
{ {
m_console.Commands.AddCommand("region", false, "clear assets",
"clear assets",
"Clear the asset cache", HandleClearAssets);
m_console.Commands.AddCommand("region", false, "force update", m_console.Commands.AddCommand("region", false, "force update",
"force update", "force update",
"Force the update of all objects on clients", "Force the update of all objects on clients",
HandleForceUpdate); HandleForceUpdate);
m_console.Commands.AddCommand("region", false, "debug packet", m_console.Commands.AddCommand("region", false, "debug packet",
"debug packet <level>", "debug packet <level> [<avatar-first-name> <avatar-last-name>]",
"Turn on packet debugging", "Turn on packet debugging",
"If level > 255 then all incoming and outgoing packets are logged.\n" "If level > 255 then all incoming and outgoing packets are logged.\n"
+ "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n" + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
+ "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n" + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
+ "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n" + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
+ "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n" + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
+ "If level <= 0 then no packets are logged.", + "If level <= 0 then no packets are logged.\n"
+ "If an avatar name is given then only packets from that avatar are logged",
Debug);
m_console.Commands.AddCommand("region", 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); Debug);
m_console.Commands.AddCommand("region", false, "debug scene", m_console.Commands.AddCommand("region", false, "debug scene",
"debug scene <cripting> <collisions> <physics>", "debug scene <scripting> <collisions> <physics>",
"Turn on scene debugging", Debug); "Turn on scene debugging", Debug);
m_console.Commands.AddCommand("region", false, "change region", m_console.Commands.AddCommand("region", false, "change region",
@ -325,7 +331,7 @@ namespace OpenSim
m_console.Commands.AddCommand("region", false, "backup", m_console.Commands.AddCommand("region", false, "backup",
"backup", "backup",
"Persist objects to the database now", RunCommand); "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand);
m_console.Commands.AddCommand("region", false, "create region", m_console.Commands.AddCommand("region", false, "create region",
"create region [\"region name\"] <region_file.ini>", "create region [\"region name\"] <region_file.ini>",
@ -509,11 +515,6 @@ namespace OpenSim
} }
} }
private void HandleClearAssets(string module, string[] args)
{
MainConsole.Instance.Output("Not implemented.");
}
/// <summary> /// <summary>
/// Force resending of all updates to all clients in active region(s) /// Force resending of all updates to all clients in active region(s)
/// </summary> /// </summary>
@ -781,6 +782,7 @@ namespace OpenSim
break; break;
case "backup": case "backup":
MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
m_sceneManager.BackupCurrentScene(); m_sceneManager.BackupCurrentScene();
break; break;
@ -791,7 +793,7 @@ namespace OpenSim
if (m_sceneManager.TryGetScene(regRemoveName, out removeScene)) if (m_sceneManager.TryGetScene(regRemoveName, out removeScene))
RemoveRegion(removeScene, false); RemoveRegion(removeScene, false);
else else
MainConsole.Instance.Output("no region with that name"); MainConsole.Instance.Output("No region with that name");
break; break;
case "delete-region": case "delete-region":
@ -854,22 +856,42 @@ namespace OpenSim
switch (args[1]) switch (args[1])
{ {
case "packet": case "packet":
string name = null;
if (args.Length == 5)
name = string.Format("{0} {1}", args[3], args[4]);
if (args.Length > 2) if (args.Length > 2)
{ {
int newDebug; int newDebug;
if (int.TryParse(args[2], out newDebug)) if (int.TryParse(args[2], out newDebug))
{ {
m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug); m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
// We provide user information elsewhere if any clients had their debug level set.
// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
} }
else else
{ {
MainConsole.Instance.Output("packet debug should be 0..255"); MainConsole.Instance.Output("Usage: debug packet 0..255");
} }
MainConsole.Instance.Output(String.Format("New packet debug: {0}", newDebug));
} }
break; 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": case "scene":
if (args.Length == 5) if (args.Length == 5)
{ {
@ -892,13 +914,13 @@ namespace OpenSim
} }
else else
{ {
MainConsole.Instance.Output("debug scene <scripting> <collisions> <physics> (where inside <> is true/false)"); MainConsole.Instance.Output("Usage: debug scene <scripting> <collisions> <physics> (where inside <> is true/false)");
} }
break; break;
default: default:
MainConsole.Instance.Output("Unknown debug"); MainConsole.Instance.Output("Unknown debug command");
break; break;
} }
} }

View File

@ -462,9 +462,18 @@ namespace OpenSim
string password = MainConsole.Instance.PasswdPrompt("Password"); string password = MainConsole.Instance.PasswdPrompt("Password");
string email = MainConsole.Instance.CmdPrompt("Email", ""); string email = MainConsole.Instance.CmdPrompt("Email", "");
string rawPrincipalId = MainConsole.Instance.CmdPrompt("User ID", UUID.Random().ToString());
UUID principalId = UUID.Zero;
if (!UUID.TryParse(rawPrincipalId, out principalId))
{
m_log.ErrorFormat("[OPENSIM]: ID {0} is not a valid UUID", rawPrincipalId);
return;
}
account account
= ((UserAccountService)scene.UserAccountService).CreateUser( = ((UserAccountService)scene.UserAccountService).CreateUser(
regionInfo.ScopeID, first, last, password, email); regionInfo.ScopeID, principalId, first, last, password, email);
} }
// } // }
} }
@ -650,8 +659,8 @@ namespace OpenSim
return new Scene( return new Scene(
regionInfo, circuitManager, sceneGridService, regionInfo, circuitManager, sceneGridService,
simDataService, estateDataService, m_moduleLoader, false, m_configSettings.PhysicalPrim, simDataService, estateDataService, m_moduleLoader, false,
m_configSettings.See_into_region_from_neighbor, m_config.Source, m_version); m_config.Source, m_version);
} }
protected void ShutdownClientServer(RegionInfo whichRegion) protected void ShutdownClientServer(RegionInfo whichRegion)
@ -719,7 +728,7 @@ namespace OpenSim
public string Path public string Path
{ {
get { return "/simstatus/"; } get { return "/simstatus"; }
} }
} }
@ -757,7 +766,7 @@ namespace OpenSim
public string Path public string Path
{ {
// This is for the OpenSimulator instance and is the osSecret hashed // This is for the OpenSimulator instance and is the osSecret hashed
get { return "/" + osXStatsURI + "/"; } get { return "/" + osXStatsURI; }
} }
} }
@ -798,7 +807,7 @@ namespace OpenSim
public string Path public string Path
{ {
// This is for the OpenSimulator instance and is the user provided URI // This is for the OpenSimulator instance and is the user provided URI
get { return "/" + osUXStatsURI + "/"; } get { return "/" + osUXStatsURI; }
} }
} }

View File

@ -56,8 +56,6 @@ namespace OpenSim.Region.ClientStack.Linden
string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
byte[] data, string inventoryType, string assetType); byte[] data, string inventoryType, string assetType);
public delegate void UploadedBakedTexture(UUID assetID, byte[] data);
public delegate UUID UpdateItem(UUID itemID, byte[] data); public delegate UUID UpdateItem(UUID itemID, byte[] data);
public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
@ -97,7 +95,6 @@ namespace OpenSim.Region.ClientStack.Linden
private static readonly string m_notecardTaskUpdatePath = "0005/"; private static readonly string m_notecardTaskUpdatePath = "0005/";
// private static readonly string m_fetchInventoryPath = "0006/"; // private static readonly string m_fetchInventoryPath = "0006/";
// private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule.
// These are callbacks which will be setup by the scene so that we can update scene data when we // These are callbacks which will be setup by the scene so that we can update scene data when we
@ -165,8 +162,6 @@ namespace OpenSim.Region.ClientStack.Linden
IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory); IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory);
m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
m_HostCapsObj.RegisterHandler("UploadBakedTexture", new RestStreamHandler("POST", capsBase + m_uploadBakedTexturePath, UploadBakedTexture));
} }
catch (Exception e) catch (Exception e)
{ {
@ -239,7 +234,8 @@ namespace OpenSim.Region.ClientStack.Linden
return string.Empty; return string.Empty;
} }
Hashtable caps = m_HostCapsObj.CapsHandlers.CapsDetails; Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true);
// Add the external too // Add the external too
foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers) foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
caps[kvp.Key] = kvp.Value; caps[kvp.Key] = kvp.Value;
@ -330,74 +326,6 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
/// <summary>
/// Handle a request from the client for a Uri to upload a baked texture.
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <returns>The upload response if the request is successful, null otherwise.</returns>
public string UploadBakedTexture(string request, string path,
string param, OSHttpRequest httpRequest,
OSHttpResponse httpResponse)
{
try
{
// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName);
string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
BakedTextureUploader uploader =
new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener);
uploader.OnUpLoad += BakedTextureUploaded;
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler("POST", capsBase + uploaderPath,
uploader.uploaderCaps));
string protocol = "http://";
if (m_HostCapsObj.SSLCaps)
protocol = "https://";
string uploaderURL = protocol + m_HostCapsObj.HostName + ":" +
m_HostCapsObj.Port.ToString() + capsBase + uploaderPath;
LLSDAssetUploadResponse uploadResponse =
new LLSDAssetUploadResponse();
uploadResponse.uploader = uploaderURL;
uploadResponse.state = "upload";
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
}
catch (Exception e)
{
m_log.Error("[CAPS]: " + e.ToString());
}
return null;
}
/// <summary>
/// Called when a baked texture has been successfully uploaded by a client.
/// </summary>
/// <param name="assetID"></param>
/// <param name="data"></param>
public void BakedTextureUploaded(UUID assetID, byte[] data)
{
// m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString());
AssetBase asset;
asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
asset.Data = data;
asset.Temporary = true;
asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
m_assetService.Store(asset);
}
/// <summary> /// <summary>
/// Called when new asset data for an agent inventory item update has been uploaded. /// Called when new asset data for an agent inventory item update has been uploaded.
/// </summary> /// </summary>
@ -1067,6 +995,7 @@ namespace OpenSim.Region.ClientStack.Linden
// XXX Maybe this should be some meaningful error packet // XXX Maybe this should be some meaningful error packet
return null; return null;
} }
///Left this in and commented in case there are unforseen issues ///Left this in and commented in case there are unforseen issues
//private void SaveAssetToFile(string filename, byte[] data) //private void SaveAssetToFile(string filename, byte[] data)
//{ //{
@ -1090,53 +1019,4 @@ namespace OpenSim.Region.ClientStack.Linden
fs.Close(); fs.Close();
} }
} }
public class BakedTextureUploader
{
public event UploadedBakedTexture OnUpLoad;
private UploadedBakedTexture handlerUpLoad = null;
private string uploaderPath = String.Empty;
private UUID newAssetID;
private IHttpServer httpListener;
public BakedTextureUploader(string path, IHttpServer httpServer)
{
newAssetID = UUID.Random();
uploaderPath = path;
httpListener = httpServer;
// m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
}
/// <summary>
/// Handle raw uploaded baked texture data.
/// </summary>
/// <param name="data"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <returns></returns>
public string uploaderCaps(byte[] data, string path, string param)
{
handlerUpLoad = OnUpLoad;
if (handlerUpLoad != null)
{
Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); });
}
string res = String.Empty;
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
uploadComplete.new_asset = newAssetID.ToString();
uploadComplete.new_inventory_item = UUID.Zero;
uploadComplete.state = "complete";
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
httpListener.RemoveStreamHandler("POST", uploaderPath);
// m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID);
return res;
}
}
} }

View File

@ -39,6 +39,7 @@ using OpenMetaverse.Messages.Linden;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
@ -58,9 +59,15 @@ namespace OpenSim.Region.ClientStack.Linden
public class EventQueueGetModule : IEventQueue, IRegionModule public class EventQueueGetModule : IEventQueue, IRegionModule
{ {
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 = null;
/// <value>
/// Debug level.
/// </value>
public int DebugLevel { get; set; }
protected Scene m_scene;
private IConfigSource m_gConfig; private IConfigSource m_gConfig;
bool enabledYN = false; bool enabledYN;
private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
@ -97,12 +104,21 @@ namespace OpenSim.Region.ClientStack.Linden
scene.EventManager.OnClientClosed += ClientClosed; scene.EventManager.OnClientClosed += ClientClosed;
scene.EventManager.OnMakeChildAgent += MakeChildAgent; scene.EventManager.OnMakeChildAgent += MakeChildAgent;
scene.EventManager.OnRegisterCaps += OnRegisterCaps; scene.EventManager.OnRegisterCaps += OnRegisterCaps;
MainConsole.Instance.Commands.AddCommand(
"event queue",
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.",
HandleDebugEq);
} }
else else
{ {
m_gConfig = null; m_gConfig = null;
} }
} }
private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p)
@ -129,6 +145,22 @@ namespace OpenSim.Region.ClientStack.Linden
} }
#endregion #endregion
protected void HandleDebugEq(string module, string[] args)
{
int debugLevel;
if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
{
MainConsole.Instance.OutputFormat("Usage: debug eq [0|1]");
}
else
{
DebugLevel = debugLevel;
MainConsole.Instance.OutputFormat(
"Set event queue debug level to {0} in {1}", DebugLevel, m_scene.RegionInfo.RegionName);
}
}
/// <summary> /// <summary>
/// Always returns a valid queue /// Always returns a valid queue
/// </summary> /// </summary>
@ -179,9 +211,10 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
Queue<OSD> queue = GetQueue(avatarID); Queue<OSD> queue = GetQueue(avatarID);
if (queue != null) if (queue != null)
lock (queue)
queue.Enqueue(ev); queue.Enqueue(ev);
} }
catch(NullReferenceException e) catch (NullReferenceException e)
{ {
m_log.Error("[EVENTQUEUE] Caught exception: " + e); m_log.Error("[EVENTQUEUE] Caught exception: " + e);
return false; return false;
@ -204,7 +237,7 @@ namespace OpenSim.Region.ClientStack.Linden
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; int count = 0;
while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5) while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
@ -216,11 +249,13 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
queues.Remove(AgentID); queues.Remove(AgentID);
} }
List<UUID> removeitems = new List<UUID>(); List<UUID> removeitems = new List<UUID>();
lock (m_AvatarQueueUUIDMapping) lock (m_AvatarQueueUUIDMapping)
{ {
foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys) 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); removeitems.Add(ky);
@ -229,11 +264,13 @@ namespace OpenSim.Region.ClientStack.Linden
foreach (UUID ky in removeitems) foreach (UUID ky in removeitems)
{ {
UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
m_AvatarQueueUUIDMapping.Remove(ky); m_AvatarQueueUUIDMapping.Remove(ky);
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + eventQueueGetUuid.ToString() + "/");
}
} }
}
UUID searchval = UUID.Zero; UUID searchval = UUID.Zero;
removeitems.Clear(); removeitems.Clear();
@ -252,7 +289,6 @@ namespace OpenSim.Region.ClientStack.Linden
foreach (UUID ky in removeitems) foreach (UUID ky in removeitems)
m_QueueUUIDAvatarMapping.Remove(ky); m_QueueUUIDAvatarMapping.Remove(ky);
} }
} }
@ -320,7 +356,9 @@ namespace OpenSim.Region.ClientStack.Linden
// This will persist this beyond the expiry of the caps handlers // This will persist this beyond the expiry of the caps handlers
MainServer.Instance.AddPollServiceHTTPHandler( MainServer.Instance.AddPollServiceHTTPHandler(
capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); capsBase + EventQueueGetUUID.ToString() + "/",
EventQueuePoll,
new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
Random rnd = new Random(Environment.TickCount); Random rnd = new Random(Environment.TickCount);
lock (m_ids) lock (m_ids)
@ -338,12 +376,8 @@ namespace OpenSim.Region.ClientStack.Linden
Queue<OSD> queue = GetQueue(agentID); Queue<OSD> queue = GetQueue(agentID);
if (queue != null) if (queue != null)
lock (queue) lock (queue)
{ return queue.Count > 0;
if (queue.Count > 0)
return true;
else
return false;
}
return false; return false;
} }
@ -358,8 +392,6 @@ namespace OpenSim.Region.ClientStack.Linden
element = queue.Dequeue(); // 15s timeout element = queue.Dequeue(); // 15s timeout
} }
int thisID = 0; int thisID = 0;
lock (m_ids) lock (m_ids)
thisID = m_ids[pAgentId]; thisID = m_ids[pAgentId];
@ -373,12 +405,31 @@ namespace OpenSim.Region.ClientStack.Linden
} }
else 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);
}
array.Add(element); array.Add(element);
lock (queue) lock (queue)
{ {
while (queue.Count > 0) while (queue.Count > 0)
{ {
array.Add(queue.Dequeue()); 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);
}
array.Add(element);
thisID++; thisID++;
} }
} }
@ -431,7 +482,10 @@ namespace OpenSim.Region.ClientStack.Linden
// } // }
Queue<OSD> queue = TryGetQueue(agentID); Queue<OSD> queue = TryGetQueue(agentID);
OSD element = queue.Dequeue(); // 15s timeout OSD element;
lock (queue)
element = queue.Dequeue(); // 15s timeout
Hashtable responsedata = new Hashtable(); Hashtable responsedata = new Hashtable();
@ -470,12 +524,34 @@ namespace OpenSim.Region.ClientStack.Linden
else else
{ {
array.Add(element); array.Add(element);
if (element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
ev["message"], m_scene.GetScenePresence(agentID).Name);
}
lock (queue)
{
while (queue.Count > 0) while (queue.Count > 0)
{ {
array.Add(queue.Dequeue()); element = queue.Dequeue();
if (element is OSDMap)
{
OSDMap ev = (OSDMap)element;
m_log.DebugFormat(
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
ev["message"], m_scene.GetScenePresence(agentID).Name);
}
array.Add(element);
thisID++; thisID++;
} }
} }
}
OSDMap events = new OSDMap(); OSDMap events = new OSDMap();
events.Add("events", array); events.Add("events", array);
@ -490,7 +566,8 @@ namespace OpenSim.Region.ClientStack.Linden
responsedata["content_type"] = "application/xml"; responsedata["content_type"] = "application/xml";
responsedata["keepalive"] = false; responsedata["keepalive"] = false;
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
//m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
return responsedata; return responsedata;
} }
@ -520,6 +597,7 @@ namespace OpenSim.Region.ClientStack.Linden
AvatarID = m_QueueUUIDAvatarMapping[capUUID]; AvatarID = m_QueueUUIDAvatarMapping[capUUID];
} }
} }
if (AvatarID != UUID.Zero) if (AvatarID != UUID.Zero)
{ {
return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID)); return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
@ -712,6 +790,7 @@ namespace OpenSim.Region.ClientStack.Linden
OSD item = EventQueueHelper.GroupMembership(groupUpdate); OSD item = EventQueueHelper.GroupMembership(groupUpdate);
Enqueue(item, avatarID); Enqueue(item, avatarID);
} }
public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID) public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
{ {
OSD item = EventQueueHelper.PlacesQuery(groupUpdate); OSD item = EventQueueHelper.PlacesQuery(groupUpdate);

View File

@ -25,48 +25,55 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
using log4net.Config;
using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.ClientStack.Linden;
using OpenSim.Region.CoreModules.Framework;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.ClientStack.LindenUDP.Tests namespace OpenSim.Region.ClientStack.Linden.Tests
{ {
public class TestLLPacketServer : LLPacketServer [TestFixture]
public class EventQueueTests
{ {
/// <summary> private TestScene m_scene;
/// Record counts of packets received
/// </summary>
protected Dictionary<PacketType, int> m_packetsReceived = new Dictionary<PacketType, int>();
public TestLLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings) [SetUp]
: base(networkHandler, userSettings) public void SetUp()
{}
public override void InPacket(uint circuitCode, Packet packet)
{ {
base.InPacket(circuitCode, packet); MainServer.Instance = new BaseHttpServer(9999, false, 9998, "");
if (m_packetsReceived.ContainsKey(packet.Type)) IConfigSource config = new IniConfigSource();
m_packetsReceived[packet.Type]++; config.AddConfig("Startup");
else config.Configs["Startup"].Set("EventQueue", "true");
m_packetsReceived[packet.Type] = 1;
CapabilitiesModule capsModule = new CapabilitiesModule();
EventQueueGetModule eqgModule = new EventQueueGetModule();
m_scene = SceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(m_scene, config, capsModule, eqgModule);
} }
public int GetTotalPacketsReceived() [Test]
public void AddForClient()
{ {
int totalCount = 0; TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
foreach (int count in m_packetsReceived.Values) SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
totalCount += count;
return totalCount; // TODO: Add more assertions for the other aspects of event queues
} Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(1));
public int GetPacketsReceivedFor(PacketType packetType)
{
if (m_packetsReceived.ContainsKey(packetType))
return m_packetsReceived[packetType];
else
return 0;
} }
} }
} }

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;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
using System.Web;
using log4net;
using Nini.Config;
using Mono.Addins;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OpenSim.Capabilities.Handlers;
namespace OpenSim.Region.ClientStack.Linden
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class UploadBakedTextureModule : INonSharedRegionModule
{
// private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// For historical reasons this is fixed, but there
/// </summary>
private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule.
private Scene m_scene;
private bool m_persistBakedTextures;
public void Initialise(IConfigSource source)
{
IConfig sconfig = source.Configs["Startup"];
if (sconfig != null)
m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
}
public void AddRegion(Scene s)
{
m_scene = s;
}
public void RemoveRegion(Scene s)
{
}
public void RegionLoaded(Scene s)
{
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
}
public void PostInitialise()
{
}
public void Close() { }
public string Name { get { return "UploadBakedTextureModule"; } }
public Type ReplaceableInterface
{
get { return null; }
}
public void RegisterCaps(UUID agentID, Caps caps)
{
caps.RegisterHandler(
"UploadBakedTexture",
new RestStreamHandler(
"POST",
"/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
new UploadBakedTextureHandler(
caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture));
}
}
}

View File

@ -45,6 +45,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private const int IMAGE_PACKET_SIZE = 1000; private const int IMAGE_PACKET_SIZE = 1000;
private const int FIRST_PACKET_SIZE = 600; private const int FIRST_PACKET_SIZE = 600;
/// <summary>
/// If we've requested an asset but not received it in this ticks timeframe, then allow a duplicate
/// request from the client to trigger a fresh asset request.
/// </summary>
/// <remarks>
/// There are 10,000 ticks in a millisecond
/// </remarks>
private const int ASSET_REQUEST_TIMEOUT = 100000000;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public uint LastSequence; public uint LastSequence;
@ -56,9 +65,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public IAssetService AssetService; public IAssetService AssetService;
public UUID AgentID; public UUID AgentID;
public IInventoryAccessModule InventoryAccessModule; public IInventoryAccessModule InventoryAccessModule;
public OpenJPEG.J2KLayerInfo[] Layers; private OpenJPEG.J2KLayerInfo[] m_layers;
public bool IsDecoded;
public bool HasAsset; /// <summary>
/// Has this request decoded the asset data?
/// </summary>
public bool IsDecoded { get; private set; }
/// <summary>
/// Has this request received the required asset data?
/// </summary>
public bool HasAsset { get; private set; }
/// <summary>
/// Time in milliseconds at which the asset was requested.
/// </summary>
public long AssetRequestTime { get; private set; }
public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle; public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle;
private uint m_currentPacket; private uint m_currentPacket;
@ -82,7 +105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="packetsToSend">Maximum number of packets to send during this call</param> /// <param name="packetsToSend">Maximum number of packets to send during this call</param>
/// <param name="packetsSent">Number of packets sent during this call</param> /// <param name="packetsSent">Number of packets sent during this call</param>
/// <returns>True if the transfer completes at the current discard level, otherwise false</returns> /// <returns>True if the transfer completes at the current discard level, otherwise false</returns>
public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent) public bool SendPackets(IClientAPI client, int packetsToSend, out int packetsSent)
{ {
packetsSent = 0; packetsSent = 0;
@ -114,17 +137,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return (m_currentPacket > m_stopPacket); return (m_currentPacket > m_stopPacket);
} }
/// <summary>
/// This is where we decide what we need to update
/// and assign the real discardLevel and packetNumber
/// assuming of course that the connected client might be bonkers
/// </summary>
public void RunUpdate() public void RunUpdate()
{ {
//This is where we decide what we need to update
//and assign the real discardLevel and packetNumber
//assuming of course that the connected client might be bonkers
if (!HasAsset) if (!HasAsset)
{ {
if (!m_assetRequested) if (!m_assetRequested || DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT)
{ {
// m_log.DebugFormat(
// "[J2KIMAGE]: Requesting asset {0} from request in packet {1}, already requested? {2}, due to timeout? {3}",
// TextureID, LastSequence, m_assetRequested, DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT);
m_assetRequested = true; m_assetRequested = true;
AssetRequestTime = DateTime.UtcNow.Ticks;
AssetService.Get(TextureID.ToString(), this, AssetReceived); AssetService.Get(TextureID.ToString(), this, AssetReceived);
} }
} }
@ -137,6 +167,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
//Request decode //Request decode
m_decodeRequested = true; m_decodeRequested = true;
// m_log.DebugFormat("[J2KIMAGE]: Requesting decode of asset {0}", TextureID);
// Do we have a jpeg decoder? // Do we have a jpeg decoder?
if (J2KDecoder != null) if (J2KDecoder != null)
{ {
@ -149,7 +182,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Send it off to the jpeg decoder // Send it off to the jpeg decoder
J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback); J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback);
} }
} }
else else
{ {
@ -170,14 +202,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (DiscardLevel >= 0 || m_stopPacket == 0) if (DiscardLevel >= 0 || m_stopPacket == 0)
{ {
// This shouldn't happen, but if it does, we really can't proceed // This shouldn't happen, but if it does, we really can't proceed
if (Layers == null) if (m_layers == null)
{ {
m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing Layers. Canceling texture transfer"); m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing Layers. Canceling texture transfer");
m_currentPacket = m_stopPacket; m_currentPacket = m_stopPacket;
return; return;
} }
int maxDiscardLevel = Math.Max(0, Layers.Length - 1); int maxDiscardLevel = Math.Max(0, m_layers.Length - 1);
// Treat initial texture downloads with a DiscardLevel of -1 a request for the highest DiscardLevel // Treat initial texture downloads with a DiscardLevel of -1 a request for the highest DiscardLevel
if (DiscardLevel < 0 && m_stopPacket == 0) if (DiscardLevel < 0 && m_stopPacket == 0)
@ -187,9 +219,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
DiscardLevel = (sbyte)Math.Min(DiscardLevel, maxDiscardLevel); DiscardLevel = (sbyte)Math.Min(DiscardLevel, maxDiscardLevel);
//Calculate the m_stopPacket //Calculate the m_stopPacket
if (Layers.Length > 0) if (m_layers.Length > 0)
{ {
m_stopPacket = (uint)GetPacketForBytePosition(Layers[(Layers.Length - 1) - DiscardLevel].End); m_stopPacket = (uint)GetPacketForBytePosition(m_layers[(m_layers.Length - 1) - DiscardLevel].End);
//I don't know why, but the viewer seems to expect the final packet if the file //I don't know why, but the viewer seems to expect the final packet if the file
//is just one packet bigger. //is just one packet bigger.
if (TexturePacketCount() == m_stopPacket + 1) if (TexturePacketCount() == m_stopPacket + 1)
@ -208,7 +240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
private bool SendFirstPacket(LLClientView client) private bool SendFirstPacket(IClientAPI client)
{ {
if (client == null) if (client == null)
return false; return false;
@ -243,7 +275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return false; return false;
} }
private bool SendPacket(LLClientView client) private bool SendPacket(IClientAPI client)
{ {
if (client == null) if (client == null)
return false; return false;
@ -328,20 +360,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
if (m_currentPacket == 0) if (m_currentPacket == 0)
return 0; return 0;
if (m_currentPacket == 1) if (m_currentPacket == 1)
return FIRST_PACKET_SIZE; return FIRST_PACKET_SIZE;
int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE; int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE;
if (result < 0) if (result < 0)
{
result = FIRST_PACKET_SIZE; result = FIRST_PACKET_SIZE;
}
return result; return result;
} }
private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers) private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers)
{ {
Layers = layers; m_layers = layers;
IsDecoded = true; IsDecoded = true;
RunUpdate(); RunUpdate();
} }
@ -372,9 +405,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private void AssetReceived(string id, Object sender, AssetBase asset) private void AssetReceived(string id, Object sender, AssetBase asset)
{ {
// m_log.DebugFormat(
// "[J2KIMAGE]: Received asset {0} ({1} bytes)", id, asset != null ? asset.Data.Length.ToString() : "n/a");
UUID assetID = UUID.Zero; UUID assetID = UUID.Zero;
if (asset != null) if (asset != null)
{
assetID = asset.FullID; assetID = asset.FullID;
}
else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule)) else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule))
{ {
// Unfortunately we need this here, there's no other way. // Unfortunately we need this here, there's no other way.
@ -392,7 +430,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
AssetDataCallback(assetID, asset); AssetDataCallback(assetID, asset);
} }
} }
} }

View File

@ -64,7 +64,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <value> /// <value>
/// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
/// </value> /// </value>
protected int m_debugPacketLevel = 0; public int DebugPacketLevel { get; set; }
#region Events #region Events
@ -303,6 +303,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
/// <summary>
/// Handles UDP texture download.
/// </summary>
public LLImageManager ImageManager { get; private set; }
private readonly LLUDPServer m_udpServer; private readonly LLUDPServer m_udpServer;
private readonly LLUDPClient m_udpClient; private readonly LLUDPClient m_udpClient;
private readonly UUID m_sessionId; private readonly UUID m_sessionId;
@ -347,7 +352,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
protected Scene m_scene; protected Scene m_scene;
protected LLImageManager m_imageManager;
protected string m_firstName; protected string m_firstName;
protected string m_lastName; protected string m_lastName;
protected Thread m_clientThread; protected Thread m_clientThread;
@ -379,6 +383,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
set { m_startpos = value; } set { m_startpos = value; }
} }
public UUID AgentId { get { return m_agentId; } } public UUID AgentId { get { return m_agentId; } }
public ISceneAgent SceneAgent { get; private set; }
public UUID ActiveGroupId { get { return m_activeGroupID; } } public UUID ActiveGroupId { get { return m_activeGroupID; } }
public string ActiveGroupName { get { return m_activeGroupName; } } public string ActiveGroupName { get { return m_activeGroupName; } }
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
@ -455,7 +460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_assetService = m_scene.RequestModuleInterface<IAssetService>(); m_assetService = m_scene.RequestModuleInterface<IAssetService>();
m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>()); ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion()); m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
m_agentId = agentId; m_agentId = agentId;
m_sessionId = sessionId; m_sessionId = sessionId;
@ -477,11 +482,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RegisterLocalPacketHandlers(); RegisterLocalPacketHandlers();
} }
public void SetDebugPacketLevel(int newDebug)
{
m_debugPacketLevel = newDebug;
}
#region Client Methods #region Client Methods
/// <summary> /// <summary>
@ -500,8 +500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
IsActive = false; IsActive = false;
// Shutdown the image manager // Shutdown the image manager
if (m_imageManager != null) ImageManager.Close();
m_imageManager.Close();
// Fire the callback for this connection closing // Fire the callback for this connection closing
if (OnConnectionClosed != null) if (OnConnectionClosed != null)
@ -513,6 +512,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Remove ourselves from the scene // Remove ourselves from the scene
m_scene.RemoveClient(AgentId, true); m_scene.RemoveClient(AgentId, true);
SceneAgent = null;
// We can't reach into other scenes and close the connection // We can't reach into other scenes and close the connection
// We need to do this over grid communications // We need to do this over grid communications
@ -528,7 +528,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void Kick(string message) public void Kick(string message)
{ {
if (!ChildAgentStatus()) if (!SceneAgent.IsChildAgent)
{ {
KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser); KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
kupack.UserInfo.AgentID = AgentId; kupack.UserInfo.AgentID = AgentId;
@ -577,8 +577,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary> /// <summary>
/// Add a handler for the given packet type. /// Add a handler for the given packet type.
/// </summary> /// </summary>
/// <remarks>The packet is handled on its own thread. If packets must be handled in the order in which thye /// <remarks>
/// are received then please us ethe synchronous version of this method.</remarks> /// The packet is handled on its own thread. If packets must be handled in the order in which they
/// are received then please use the synchronous version of this method.
/// </remarks>
/// <param name="packetType"></param> /// <param name="packetType"></param>
/// <param name="handler"></param> /// <param name="handler"></param>
/// <returns>true if the handler was added. This is currently always the case.</returns> /// <returns>true if the handler was added. This is currently always the case.</returns>
@ -692,7 +694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public virtual void Start() public virtual void Start()
{ {
m_scene.AddNewClient(this, PresenceType.User); SceneAgent = m_scene.AddNewClient(this, PresenceType.User);
RefreshGroupMembership(); RefreshGroupMembership();
} }
@ -1963,8 +1965,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SendBulkUpdateInventoryItem((InventoryItemBase)node); SendBulkUpdateInventoryItem((InventoryItemBase)node);
else if (node is InventoryFolderBase) else if (node is InventoryFolderBase)
SendBulkUpdateInventoryFolder((InventoryFolderBase)node); SendBulkUpdateInventoryFolder((InventoryFolderBase)node);
else if (node != null)
m_log.ErrorFormat("[CLIENT]: {0} sent unknown inventory node named {1}", Name, node.Name);
else else
m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name); m_log.ErrorFormat("[CLIENT]: {0} sent null inventory node", Name);
} }
protected void SendBulkUpdateInventoryItem(InventoryItemBase item) protected void SendBulkUpdateInventoryItem(InventoryItemBase item)
@ -2444,7 +2448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="Message"></param> /// <param name="Message"></param>
public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
{ {
if (!ChildAgentStatus()) if (!SceneAgent.IsChildAgent)
SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3()));
//SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
@ -3592,7 +3596,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Generate one of the object update packets based on PrimUpdateFlags /// Generate one of the object update packets based on PrimUpdateFlags
/// and broadcast the packet to clients /// and broadcast the packet to clients
/// </summary> /// </summary>
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{ {
//double priority = m_prioritizer.GetUpdatePriority(this, entity); //double priority = m_prioritizer.GetUpdatePriority(this, entity);
uint priority = m_prioritizer.GetUpdatePriority(this, entity); uint priority = m_prioritizer.GetUpdatePriority(this, entity);
@ -3625,7 +3629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary> /// </summary>
private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket) private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
{ {
// m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime); // m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber);
// Remove the update packet from the list of packets waiting for acknowledgement // Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets // because we are requeuing the list of updates. They will be resent in new packets
@ -3931,15 +3935,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
{ ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
ProcessTextureRequests();
}
}
void ProcessTextureRequests()
{
if (m_imageManager != null)
m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
} }
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
@ -4744,6 +4740,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
position = presence.OffsetPosition; position = presence.OffsetPosition;
velocity = presence.Velocity; velocity = presence.Velocity;
acceleration = Vector3.Zero; acceleration = Vector3.Zero;
// Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
// in that direction, even though we don't model this on the server. Implementing this in the future
// may improve movement smoothness.
// acceleration = new Vector3(1, 0, 0);
angularVelocity = Vector3.Zero; angularVelocity = Vector3.Zero;
rotation = presence.Rotation; rotation = presence.Rotation;
@ -4854,8 +4856,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
data.CollisionPlane.ToBytes(objectData, 0); data.CollisionPlane.ToBytes(objectData, 0);
data.OffsetPosition.ToBytes(objectData, 16); data.OffsetPosition.ToBytes(objectData, 16);
//data.Velocity.ToBytes(objectData, 28); // data.Velocity.ToBytes(objectData, 28);
//data.Acceleration.ToBytes(objectData, 40); // data.Acceleration.ToBytes(objectData, 40);
data.Rotation.ToBytes(objectData, 52); data.Rotation.ToBytes(objectData, 52);
//data.AngularVelocity.ToBytes(objectData, 64); //data.AngularVelocity.ToBytes(objectData, 64);
@ -4880,8 +4882,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.Scale = new Vector3(0.45f, 0.6f, 1.9f); update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
update.Text = Utils.EmptyBytes; update.Text = Utils.EmptyBytes;
update.TextColor = new byte[4]; update.TextColor = new byte[4];
// Don't send texture anim for avatars - this has no meaning for them.
update.TextureAnim = Utils.EmptyBytes; update.TextureAnim = Utils.EmptyBytes;
update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
// Don't send texture entry for avatars here - this is accomplished via the AvatarAppearance packet
update.TextureEntry = Utils.EmptyBytes;
// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
update.UpdateFlags = (uint)( update.UpdateFlags = (uint)(
PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
@ -5044,14 +5052,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return 0; return 0;
} }
/// <summary>
/// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
/// </summary>
public bool ChildAgentStatus()
{
return m_scene.PresenceChildStatus(AgentId);
}
#endregion #endregion
/// <summary> /// <summary>
@ -7465,12 +7465,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if ((ImageType)block.Type == ImageType.Baked) if ((ImageType)block.Type == ImageType.Baked)
args.Priority *= 2.0f; args.Priority *= 2.0f;
// in the end, we null this, so we have to check if it's null ImageManager.EnqueueReq(args);
if (m_imageManager != null)
{
m_imageManager.EnqueueReq(args);
}
} }
return true; return true;
} }
@ -10328,6 +10325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
return true; return true;
} }
private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack) private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack)
{ {
GroupRoleMembersRequestPacket groupRoleMembersRequest = GroupRoleMembersRequestPacket groupRoleMembersRequest =
@ -11588,29 +11586,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// provide your own method.</param> /// provide your own method.</param>
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
{ {
if (m_debugPacketLevel > 0) if (DebugPacketLevel > 0)
{ {
bool logPacket = true; bool logPacket = true;
if (m_debugPacketLevel <= 255 if (DebugPacketLevel <= 255
&& (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage)) && (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage))
logPacket = false; logPacket = false;
if (m_debugPacketLevel <= 200 if (DebugPacketLevel <= 200
&& (packet.Type == PacketType.ImagePacket && (packet.Type == PacketType.ImagePacket
|| packet.Type == PacketType.ImageData || packet.Type == PacketType.ImageData
|| packet.Type == PacketType.LayerData || packet.Type == PacketType.LayerData
|| packet.Type == PacketType.CoarseLocationUpdate)) || packet.Type == PacketType.CoarseLocationUpdate))
logPacket = false; logPacket = false;
if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
logPacket = false; logPacket = false;
if (m_debugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
logPacket = false; logPacket = false;
if (logPacket) if (logPacket)
m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); m_log.DebugFormat(
"[CLIENT]: PACKET OUT to {0} ({1}) in {2} - {3}",
Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type);
} }
m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
@ -11651,21 +11651,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="Pack">OpenMetaverse.packet</param> /// <param name="Pack">OpenMetaverse.packet</param>
public void ProcessInPacket(Packet packet) public void ProcessInPacket(Packet packet)
{ {
if (m_debugPacketLevel > 0) if (DebugPacketLevel > 0)
{ {
bool outputPacket = true; bool logPacket = true;
if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate) if (DebugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
outputPacket = false; logPacket = false;
if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage) if (DebugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
outputPacket = false; logPacket = false;
if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation)) if (DebugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
outputPacket = false; logPacket = false;
if (outputPacket) if (logPacket)
m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type); m_log.DebugFormat(
"[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}",
Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type);
} }
if (!ProcessPacketMethod(packet)) if (!ProcessPacketMethod(packet))

View File

@ -39,6 +39,9 @@ using log4net;
namespace OpenSim.Region.ClientStack.LindenUDP namespace OpenSim.Region.ClientStack.LindenUDP
{ {
/// <summary>
/// This class handles UDP texture requests.
/// </summary>
public class LLImageManager public class LLImageManager
{ {
private sealed class J2KImageComparer : IComparer<J2KImage> private sealed class J2KImageComparer : IComparer<J2KImage>
@ -52,18 +55,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool m_shuttingdown; private bool m_shuttingdown;
private AssetBase m_missingImage; private AssetBase m_missingImage;
private LLClientView m_client; //Client we're assigned to private IAssetService m_assetCache;
private IAssetService m_assetCache; //Asset Cache private IJ2KDecoder m_j2kDecodeModule;
private IJ2KDecoder m_j2kDecodeModule; //Our J2K module
/// <summary>
/// Priority queue for determining which image to send first.
/// </summary>
private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer()); private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer());
/// <summary>
/// Used to control thread access to the priority queue.
/// </summary>
private object m_syncRoot = new object(); private object m_syncRoot = new object();
public LLClientView Client { get { return m_client; } } /// <summary>
/// Client served by this image manager
/// </summary>
public IClientAPI Client { get; private set; }
public AssetBase MissingImage { get { return m_missingImage; } } public AssetBase MissingImage { get { return m_missingImage; } }
public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) public LLImageManager(IClientAPI client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule)
{ {
m_client = client; Client = client;
m_assetCache = pAssetCache; m_assetCache = pAssetCache;
if (pAssetCache != null) if (pAssetCache != null)
@ -81,7 +95,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="newRequest"></param> /// <param name="newRequest"></param>
public void EnqueueReq(TextureRequestArgs newRequest) public void EnqueueReq(TextureRequestArgs newRequest)
{ {
//Make sure we're not shutting down..
if (!m_shuttingdown) if (!m_shuttingdown)
{ {
J2KImage imgrequest; J2KImage imgrequest;
@ -105,8 +118,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
else else
{ {
//m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", // m_log.DebugFormat(
// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); // "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}",
// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name);
// m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}",
// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
//Check the packet sequence to make sure this isn't older than //Check the packet sequence to make sure this isn't older than
//one we've already received //one we've already received
@ -123,11 +140,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//Update the requested priority //Update the requested priority
imgrequest.Priority = newRequest.Priority; imgrequest.Priority = newRequest.Priority;
UpdateImageInQueue(imgrequest); UpdateImageInQueue(imgrequest);
//Run an update
imgrequest.RunUpdate(); imgrequest.RunUpdate();
// J2KImage imgrequest2 = new J2KImage(this);
// imgrequest2.J2KDecoder = m_j2kDecodeModule;
// imgrequest2.AssetService = m_assetCache;
// imgrequest2.AgentID = m_client.AgentId;
// imgrequest2.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>();
// imgrequest2.DiscardLevel = newRequest.DiscardLevel;
// imgrequest2.StartPacket = Math.Max(1, newRequest.PacketNumber);
// imgrequest2.Priority = newRequest.Priority;
// imgrequest2.TextureID = newRequest.RequestedAssetID;
// imgrequest2.Priority = newRequest.Priority;
//
// //Add this download to the priority queue
// AddImageToQueue(imgrequest2);
//
// imgrequest2.RunUpdate();
} }
// else
// {
// m_log.DebugFormat(
// "[LL IMAGE MANAGER]: Ignoring duplicate of existing request for {0} (sequence {1}) from {2} as its request sequence {3} is not greater",
// newRequest.RequestedAssetID, imgrequest.LastSequence, m_client.Name, newRequest.requestSequence);
// }
} }
} }
else else
@ -139,14 +179,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
else else
{ {
// m_log.DebugFormat(
// "[LL IMAGE MANAGER]: Received request for {0}, start packet {1} from {2}",
// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name);
//m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}", //m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}",
// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
imgrequest = new J2KImage(this); imgrequest = new J2KImage(this);
imgrequest.J2KDecoder = m_j2kDecodeModule; imgrequest.J2KDecoder = m_j2kDecodeModule;
imgrequest.AssetService = m_assetCache; imgrequest.AssetService = m_assetCache;
imgrequest.AgentID = m_client.AgentId; imgrequest.AgentID = Client.AgentId;
imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>(); imgrequest.InventoryAccessModule = Client.Scene.RequestModuleInterface<IInventoryAccessModule>();
imgrequest.DiscardLevel = newRequest.DiscardLevel; imgrequest.DiscardLevel = newRequest.DiscardLevel;
imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber);
imgrequest.Priority = newRequest.Priority; imgrequest.Priority = newRequest.Priority;
@ -156,7 +200,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//Add this download to the priority queue //Add this download to the priority queue
AddImageToQueue(imgrequest); AddImageToQueue(imgrequest);
//Run an update
imgrequest.RunUpdate(); imgrequest.RunUpdate();
} }
} }
@ -173,12 +216,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// If null was returned, the texture priority queue is currently empty // If null was returned, the texture priority queue is currently empty
if (image == null) if (image == null)
return false; break;
if (image.IsDecoded) if (image.IsDecoded)
{ {
int sent; int sent;
bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); bool imageDone = image.SendPackets(Client, packetsToSend - packetsSent, out sent);
packetsSent += sent; packetsSent += sent;
// If the send is complete, destroy any knowledge of this transfer // If the send is complete, destroy any knowledge of this transfer
@ -191,10 +234,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// written. Undecoded textures should not be going into the priority // written. Undecoded textures should not be going into the priority
// queue, because a high priority undecoded texture will clog up the // queue, because a high priority undecoded texture will clog up the
// pipeline for a client // pipeline for a client
return true; // m_log.DebugFormat(
// "[LL IMAGE MANAGER]: Exiting image queue processing early on encountering undecoded image {0}",
// image.TextureID);
break;
} }
} }
// if (packetsSent != 0)
// m_log.DebugFormat("[LL IMAGE MANAGER]: Processed {0} packets from image queue", packetsSent);
return m_priorityQueue.Count > 0; return m_priorityQueue.Count > 0;
} }
@ -206,9 +256,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_shuttingdown = true; m_shuttingdown = true;
} }
/// <summary>
/// Clear the image queue.
/// </summary>
/// <returns>The number of requests cleared.</returns>
public int ClearImageQueue()
{
int requestsDeleted;
lock (m_priorityQueue)
{
requestsDeleted = m_priorityQueue.Count;
// Surprisingly, there doesn't seem to be a clear method at this time.
while (!m_priorityQueue.IsEmpty)
m_priorityQueue.DeleteMax();
}
return requestsDeleted;
}
/// <summary>
/// Returns an array containing all the images in the queue.
/// </summary>
/// <returns></returns>
public J2KImage[] GetImages()
{
lock (m_priorityQueue)
return m_priorityQueue.ToArray();
}
#region Priority Queue Helpers #region Priority Queue Helpers
J2KImage GetHighestPriorityImage() private J2KImage GetHighestPriorityImage()
{ {
J2KImage image = null; J2KImage image = null;
@ -216,34 +296,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
if (m_priorityQueue.Count > 0) if (m_priorityQueue.Count > 0)
{ {
try { image = m_priorityQueue.FindMax(); } try
{
image = m_priorityQueue.FindMax();
}
catch (Exception) { } catch (Exception) { }
} }
} }
return image; return image;
} }
void AddImageToQueue(J2KImage image) private void AddImageToQueue(J2KImage image)
{ {
image.PriorityQueueHandle = null; image.PriorityQueueHandle = null;
lock (m_syncRoot) lock (m_syncRoot)
try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); }
catch (Exception) { }
}
void RemoveImageFromQueue(J2KImage image)
{ {
lock (m_syncRoot) try
try { m_priorityQueue.Delete(image.PriorityQueueHandle); } {
m_priorityQueue.Add(ref image.PriorityQueueHandle, image);
}
catch (Exception) { } catch (Exception) { }
} }
}
void UpdateImageInQueue(J2KImage image) private void RemoveImageFromQueue(J2KImage image)
{ {
lock (m_syncRoot) lock (m_syncRoot)
{ {
try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); } try
{
m_priorityQueue.Delete(image.PriorityQueueHandle);
}
catch (Exception) { }
}
}
private void UpdateImageInQueue(J2KImage image)
{
lock (m_syncRoot)
{
try
{
m_priorityQueue.Replace(image.PriorityQueueHandle, image);
}
catch (Exception) catch (Exception)
{ {
image.PriorityQueueHandle = null; image.PriorityQueueHandle = null;

View File

@ -169,7 +169,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="circuitCode">Circuit code for this connection</param> /// <param name="circuitCode">Circuit code for this connection</param>
/// <param name="agentID">AgentID for the connected agent</param> /// <param name="agentID">AgentID for the connected agent</param>
/// <param name="remoteEndPoint">Remote endpoint for this connection</param> /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO) /// <param name="defaultRTO">
/// Default retransmission timeout for unacked packets. The RTO will never drop
/// beyond this number.
/// </param>
/// <param name="maxRTO">
/// The maximum retransmission timeout for unacked packets. The RTO will never exceed this number.
/// </param>
public LLUDPClient(
LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID,
IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
{ {
AgentID = agentID; AgentID = agentID;
RemoteEndPoint = remoteEndPoint; RemoteEndPoint = remoteEndPoint;
@ -197,7 +206,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
} }
// Default the retransmission timeout to three seconds // Default the retransmission timeout to one second
RTO = m_defaultRTO; RTO = m_defaultRTO;
// Initialize this to a sane value to prevent early disconnects // Initialize this to a sane value to prevent early disconnects
@ -262,9 +271,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary> /// <summary>
/// Return statistics information about client packet queues. /// Return statistics information about client packet queues.
/// </summary> /// </summary>
/// /// <remarks>
/// FIXME: This should really be done in a more sensible manner rather than sending back a formatted string. /// FIXME: This should really be done in a more sensible manner rather than sending back a formatted string.
/// /// </remarks>
/// <returns></returns> /// <returns></returns>
public string GetStats() public string GetStats()
{ {
@ -583,8 +592,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RTO = rto; RTO = rto;
//m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + //if (RTO != rto)
// RTTVAR + " based on new RTT of " + r + "ms"); // m_log.Debug("[LLUDPCLIENT]: Setting RTO to " + RTO + "ms from " + rto + "ms with an RTTVAR of " +
//RTTVAR + " based on new RTT of " + r + "ms");
} }
/// <summary> /// <summary>
@ -606,8 +616,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Does an early check to see if this queue empty callback is already /// Does an early check to see if this queue empty callback is already
/// running, then asynchronously firing the event /// running, then asynchronously firing the event
/// </summary> /// </summary>
/// <param name="throttleIndex">Throttle category to fire the callback /// <param name="categories">Throttle categories to fire the callback for</param>
/// for</param>
private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
{ {
if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)

View File

@ -324,7 +324,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="packet"></param> /// <param name="packet"></param>
/// <param name="category"></param> /// <param name="category"></param>
/// <param name="allowSplitting"></param> /// <param name="allowSplitting"></param>
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method) /// <param name="method">
/// The method to call if the packet is not acked by the client. If null, then a standard
/// resend of the packet is done.
/// </param>
public virtual void SendPacket(
LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
{ {
// CoarseLocationUpdate packets cannot be split in an automated way // CoarseLocationUpdate packets cannot be split in an automated way
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
@ -358,7 +363,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="category"></param> /// <param name="category"></param>
public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) /// <param name="method">
/// The method to call if the packet is not acked by the client. If null, then a standard
/// resend of the packet is done.
/// </param>
public void SendPacketData(
LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
{ {
int dataLength = data.Length; int dataLength = data.Length;
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
@ -482,6 +492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
{ {
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
RemoveClient(udpClient); RemoveClient(udpClient);
return; return;
@ -601,11 +612,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
} }
protected override void PacketReceived(UDPPacketBuffer buffer) public override void PacketReceived(UDPPacketBuffer buffer)
{ {
// Debugging/Profiling // Debugging/Profiling
//try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
//catch (Exception) { } //catch (Exception) { }
// m_log.DebugFormat(
// "[LLUDPSERVER]: Packet received from {0} in {1}", buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
LLUDPClient udpClient = null; LLUDPClient udpClient = null;
Packet packet = null; Packet packet = null;
@ -615,7 +628,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Decoding #region Decoding
if (buffer.DataLength < 7) if (buffer.DataLength < 7)
{
// m_log.WarnFormat(
// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
return; // Drop undersizd packet return; // Drop undersizd packet
}
int headerLen = 7; int headerLen = 7;
if (buffer.Data[6] == 0xFF) if (buffer.Data[6] == 0xFF)
@ -627,7 +646,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
if (buffer.DataLength < headerLen) if (buffer.DataLength < headerLen)
{
// m_log.WarnFormat(
// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
return; // Malformed header return; // Malformed header
}
try try
{ {
@ -640,6 +665,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
catch (IndexOutOfRangeException) catch (IndexOutOfRangeException)
{ {
// m_log.WarnFormat(
// "[LLUDPSERVER]: Dropping short packet received from {0} in {1}",
// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
return; // Drop short packet return; // Drop short packet
} }
catch(Exception e) catch(Exception e)
@ -877,23 +906,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// DateTime startTime = DateTime.Now; // DateTime startTime = DateTime.Now;
object[] array = (object[])o; object[] array = (object[])o;
UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1]; UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint); m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint);
IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
AuthenticateResponse sessionInfo;
if (IsClientAuthorized(uccp, out sessionInfo))
{
// Begin the process of adding the client to the simulator // Begin the process of adding the client to the simulator
AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); IClientAPI client
= AddClient(
uccp.CircuitCode.Code,
uccp.CircuitCode.ID,
uccp.CircuitCode.SessionID,
remoteEndPoint,
sessionInfo);
// Send ack // Send ack straight away to let the viewer know that the connection is active.
SendAckImmediate(remoteEndPoint, packet.Header.Sequence); // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
// circuit code to the existing child agent. This is not particularly obvious.
SendAckImmediate(remoteEndPoint, uccp.Header.Sequence);
// We only want to send initial data to new clients, not ones which are being converted from child to root.
if (client != null)
client.SceneAgent.SendInitialDataToMe();
}
else
{
// 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);
}
// m_log.DebugFormat( // m_log.DebugFormat(
// "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
// buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
} }
/// <summary>
/// Send an ack immediately to the given endpoint.
/// </summary>
/// <remarks>
/// FIXME: Might be possible to use SendPacketData() like everything else, but this will require refactoring so
/// that we can obtain the UDPClient easily at this point.
/// </remarks>
/// <param name="remoteEndpoint"></param>
/// <param name="sequenceNumber"></param>
private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
{ {
PacketAckPacket ack = new PacketAckPacket(); PacketAckPacket ack = new PacketAckPacket();
@ -902,6 +963,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ack.Packets[0] = new PacketAckPacket.PacketsBlock(); ack.Packets[0] = new PacketAckPacket.PacketsBlock();
ack.Packets[0].ID = sequenceNumber; ack.Packets[0].ID = sequenceNumber;
SendAckImmediate(remoteEndpoint, ack);
}
public virtual void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack)
{
byte[] packetData = ack.ToBytes(); byte[] packetData = ack.ToBytes();
int length = packetData.Length; int length = packetData.Length;
@ -923,63 +989,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return sessionInfo.Authorised; return sessionInfo.Authorised;
} }
private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) /// <summary>
/// Add a client.
/// </summary>
/// <param name="circuitCode"></param>
/// <param name="agentID"></param>
/// <param name="sessionID"></param>
/// <param name="remoteEndPoint"></param>
/// <param name="sessionInfo"></param>
/// <returns>The client if it was added. Null if the client already existed.</returns>
protected virtual IClientAPI AddClient(
uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
{ {
UUID agentID = useCircuitCode.CircuitCode.ID; IClientAPI client = null;
UUID sessionID = useCircuitCode.CircuitCode.SessionID;
uint circuitCode = useCircuitCode.CircuitCode.Code;
if (m_scene.RegionStatus != RegionStatus.SlaveScene)
{
AuthenticateResponse sessionInfo;
if (IsClientAuthorized(useCircuitCode, out sessionInfo))
{
AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
}
else
{
// Don't create circuits for unauthorized clients
m_log.WarnFormat(
"[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
}
}
else
{
// Slave regions don't accept new clients
m_log.Debug("[LLUDPSERVER]: Slave region " + m_scene.RegionInfo.RegionName + " ignoring UseCircuitCode packet");
}
}
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
{
// In priciple there shouldn't be more than one thread here, ever. // In priciple there shouldn't be more than one thread here, ever.
// But in case that happens, we need to synchronize this piece of code // But in case that happens, we need to synchronize this piece of code
// because it's too important // because it's too important
lock (this) lock (this)
{ {
IClientAPI existingClient; if (!m_scene.TryGetClient(agentID, out client))
if (!m_scene.TryGetClient(agentID, out existingClient))
{ {
// Create the LLUDPClient
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
// Create the LLClientView
LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client.OnLogout += LogoutHandler; client.OnLogout += LogoutHandler;
client.DisableFacelights = m_disableFacelights; ((LLClientView)client).DisableFacelights = m_disableFacelights;
// Start the IClientAPI
client.Start(); client.Start();
}
}
} return client;
else
{
m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
existingClient.AgentId, remoteEndPoint, circuitCode);
}
}
} }
private void RemoveClient(LLUDPClient udpClient) private void RemoveClient(LLUDPClient udpClient)
@ -1108,7 +1150,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
} }
} }
Watchdog.RemoveThread(); Watchdog.RemoveThread();

View File

@ -44,7 +44,7 @@ namespace OpenMetaverse
/// This method is called when an incoming packet is received /// This method is called when an incoming packet is received
/// </summary> /// </summary>
/// <param name="buffer">Incoming packet buffer</param> /// <param name="buffer">Incoming packet buffer</param>
protected abstract void PacketReceived(UDPPacketBuffer buffer); public abstract void PacketReceived(UDPPacketBuffer buffer);
/// <summary>UDP port to bind to in server mode</summary> /// <summary>UDP port to bind to in server mode</summary>
protected int m_udpPort; protected int m_udpPort;

View File

@ -25,14 +25,15 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System;
using System.Net; using System.Net;
using log4net.Config; using log4net.Config;
using Nini.Config; using Nini.Config;
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Mock;
@ -44,89 +45,92 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
[TestFixture] [TestFixture]
public class BasicCircuitTests public class BasicCircuitTests
{ {
[SetUp] [TestFixtureSetUp]
public void Init() public void FixtureInit()
{ {
try // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
{ Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
XmlConfigurator.Configure();
}
catch
{
// I don't care, just leave log4net off
}
} }
/// <summary> [TestFixtureTearDown]
/// Add a client for testing public void TearDown()
/// </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(); // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
ClientStackUserSettings userSettings = new ClientStackUserSettings(); // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
testLLUDPServer = new TestLLUDPServer(); // tests really shouldn't).
acm = new AgentCircuitManager(); Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
uint port = 666;
testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
testLLUDPServer.LocalScene = scene;
} }
/// <summary> // /// <summary>
/// Set up a client for tests which aren't concerned with this process itself and where only one client is being // /// Add a client for testing
/// tested // /// </summary>
/// </summary> // /// <param name="scene"></param>
/// <param name="circuitCode"></param> // /// <param name="testLLUDPServer"></param>
/// <param name="epSender"></param> // /// <param name="testPacketServer"></param>
/// <param name="testLLUDPServer"></param> // /// <param name="acm">Agent circuit manager used in setting up the stack</param>
/// <param name="acm"></param> // protected void SetupStack(
protected void AddClient( // IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm) // out AgentCircuitManager acm)
{ // {
UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); // IConfigSource configSource = new IniConfigSource();
UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); // 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;
// }
AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm); // /// <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> // /// <summary>
/// Set up a client for tests which aren't concerned with this process itself // /// Set up a client for tests which aren't concerned with this process itself
/// </summary> // /// </summary>
/// <param name="circuitCode"></param> // /// <param name="circuitCode"></param>
/// <param name="epSender"></param> // /// <param name="epSender"></param>
/// <param name="agentId"></param> // /// <param name="agentId"></param>
/// <param name="sessionId"></param> // /// <param name="sessionId"></param>
/// <param name="testLLUDPServer"></param> // /// <param name="testLLUDPServer"></param>
/// <param name="acm"></param> // /// <param name="acm"></param>
protected void AddClient( // protected void AddClient(
uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId, // uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
TestLLUDPServer testLLUDPServer, AgentCircuitManager acm) // TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
{ // {
AgentCircuitData acd = new AgentCircuitData(); // AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = agentId; // acd.AgentID = agentId;
acd.SessionID = sessionId; // acd.SessionID = sessionId;
//
UseCircuitCodePacket uccp = new UseCircuitCodePacket(); // UseCircuitCodePacket uccp = new UseCircuitCodePacket();
//
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock // UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
= new UseCircuitCodePacket.CircuitCodeBlock(); // = new UseCircuitCodePacket.CircuitCodeBlock();
uccpCcBlock.Code = circuitCode; // uccpCcBlock.Code = circuitCode;
uccpCcBlock.ID = agentId; // uccpCcBlock.ID = agentId;
uccpCcBlock.SessionID = sessionId; // uccpCcBlock.SessionID = sessionId;
uccp.CircuitCode = uccpCcBlock; // uccp.CircuitCode = uccpCcBlock;
//
acm.AddNewCircuit(circuitCode, acd); // acm.AddNewCircuit(circuitCode, acd);
//
testLLUDPServer.LoadReceive(uccp, epSender); // testLLUDPServer.LoadReceive(uccp, epSender);
testLLUDPServer.ReceiveData(null); // testLLUDPServer.ReceiveData(null);
} // }
/// <summary> /// <summary>
/// Build an object name packet for test purposes /// Build an object name packet for test purposes
@ -148,23 +152,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
/// <summary> /// <summary>
/// Test adding a client to the stack /// Test adding a client to the stack
/// </summary> /// </summary>
[Test, LongRunning] [Test]
public void TestAddClient() public void TestAddClient()
{ {
TestHelper.InMethod(); TestHelpers.InMethod();
// XmlConfigurator.Configure();
TestScene scene = SceneHelpers.SetupScene();
uint myCircuitCode = 123456; uint myCircuitCode = 123456;
UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); UUID mySessionUuid = TestHelpers.ParseTail(0x2);
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
TestLLUDPServer testLLUDPServer; uint port = 0;
TestLLPacketServer testLLPacketServer; AgentCircuitManager acm = scene.AuthenticateHandler;
AgentCircuitManager acm;
SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
AgentCircuitData acd = new AgentCircuitData(); TestLLUDPServer llUdpServer
acd.AgentID = myAgentUuid; = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
acd.SessionID = mySessionUuid; llUdpServer.AddScene(scene);
UseCircuitCodePacket uccp = new UseCircuitCodePacket(); UseCircuitCodePacket uccp = new UseCircuitCodePacket();
@ -175,125 +180,139 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
uccpCcBlock.SessionID = mySessionUuid; uccpCcBlock.SessionID = mySessionUuid;
uccp.CircuitCode = uccpCcBlock; uccp.CircuitCode = uccpCcBlock;
EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); 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);
testLLUDPServer.LoadReceive(uccp, testEp); llUdpServer.PacketReceived(upb);
testLLUDPServer.ReceiveData(null);
// Circuit shouildn't exist since the circuit manager doesn't know about this circuit for authentication yet // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode)); Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null);
AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid;
acm.AddNewCircuit(myCircuitCode, acd); acm.AddNewCircuit(myCircuitCode, acd);
testLLUDPServer.LoadReceive(uccp, testEp); llUdpServer.PacketReceived(upb);
testLLUDPServer.ReceiveData(null);
// Should succeed now // Should succeed now
Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode)); ScenePresence sp = scene.GetScenePresence(myAgentUuid);
Assert.IsFalse(testLLUDPServer.HasCircuit(101)); Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1));
Packet packet = llUdpServer.PacketsSent[0];
Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
PacketAckPacket ackPacket = packet as PacketAckPacket;
Assert.That(ackPacket.Packets.Length, Is.EqualTo(1));
Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
} }
/// <summary> // /// <summary>
/// Test removing a client from the stack // /// Test removing a client from the stack
/// </summary> // /// </summary>
[Test] // [Test]
public void TestRemoveClient() // public void TestRemoveClient()
{ // {
TestHelper.InMethod(); // TestHelper.InMethod();
//
uint myCircuitCode = 123457; // uint myCircuitCode = 123457;
//
TestLLUDPServer testLLUDPServer; // TestLLUDPServer testLLUDPServer;
TestLLPacketServer testLLPacketServer; // TestLLPacketServer testLLPacketServer;
AgentCircuitManager acm; // AgentCircuitManager acm;
SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm); // SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
AddClient(myCircuitCode, new IPEndPoint(IPAddress.Loopback, 1000), testLLUDPServer, acm); // AddClient(myCircuitCode, new IPEndPoint(IPAddress.Loopback, 1000), testLLUDPServer, acm);
//
testLLUDPServer.RemoveClientCircuit(myCircuitCode); // testLLUDPServer.RemoveClientCircuit(myCircuitCode);
Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode)); // Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode));
//
// Check that removing a non-existant circuit doesn't have any bad effects // // Check that removing a non-existant circuit doesn't have any bad effects
testLLUDPServer.RemoveClientCircuit(101); // testLLUDPServer.RemoveClientCircuit(101);
Assert.IsFalse(testLLUDPServer.HasCircuit(101)); // Assert.IsFalse(testLLUDPServer.HasCircuit(101));
} // }
//
/// <summary> // /// <summary>
/// Make sure that the client stack reacts okay to malformed packets // /// Make sure that the client stack reacts okay to malformed packets
/// </summary> // /// </summary>
[Test] // [Test]
public void TestMalformedPacketSend() // public void TestMalformedPacketSend()
{ // {
TestHelper.InMethod(); // TestHelper.InMethod();
//
uint myCircuitCode = 123458; // uint myCircuitCode = 123458;
EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 1001); // EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 1001);
MockScene scene = new MockScene(); // MockScene scene = new MockScene();
//
TestLLUDPServer testLLUDPServer; // TestLLUDPServer testLLUDPServer;
TestLLPacketServer testLLPacketServer; // TestLLPacketServer testLLPacketServer;
AgentCircuitManager acm; // AgentCircuitManager acm;
SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm); // SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
AddClient(myCircuitCode, testEp, testLLUDPServer, acm); // AddClient(myCircuitCode, testEp, testLLUDPServer, acm);
//
byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 }; // byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 };
//
// Send two garbled 'packets' in succession // // Send two garbled 'packets' in succession
testLLUDPServer.LoadReceive(data, testEp); // testLLUDPServer.LoadReceive(data, testEp);
testLLUDPServer.LoadReceive(data, testEp); // testLLUDPServer.LoadReceive(data, testEp);
testLLUDPServer.ReceiveData(null); // testLLUDPServer.ReceiveData(null);
//
// Check that we are still here // // Check that we are still here
Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode)); // Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode));
Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(0)); // Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(0));
//
// Check that sending a valid packet to same circuit still succeeds // // Check that sending a valid packet to same circuit still succeeds
Assert.That(scene.ObjectNameCallsReceived, Is.EqualTo(0)); // Assert.That(scene.ObjectNameCallsReceived, Is.EqualTo(0));
//
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "helloooo"), testEp); // testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "helloooo"), testEp);
testLLUDPServer.ReceiveData(null); // testLLUDPServer.ReceiveData(null);
//
Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(1)); // Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(1));
Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(1)); // Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(1));
} // }
//
/// <summary> // /// <summary>
/// Test that the stack continues to work even if some client has caused a // /// Test that the stack continues to work even if some client has caused a
/// SocketException on Socket.BeginReceive() // /// SocketException on Socket.BeginReceive()
/// </summary> // /// </summary>
[Test] // [Test]
public void TestExceptionOnBeginReceive() // public void TestExceptionOnBeginReceive()
{ // {
TestHelper.InMethod(); // TestHelper.InMethod();
//
MockScene scene = new MockScene(); // MockScene scene = new MockScene();
//
uint circuitCodeA = 130000; // uint circuitCodeA = 130000;
EndPoint epA = new IPEndPoint(IPAddress.Loopback, 1300); // EndPoint epA = new IPEndPoint(IPAddress.Loopback, 1300);
UUID agentIdA = UUID.Parse("00000000-0000-0000-0000-000000001300"); // UUID agentIdA = UUID.Parse("00000000-0000-0000-0000-000000001300");
UUID sessionIdA = UUID.Parse("00000000-0000-0000-0000-000000002300"); // UUID sessionIdA = UUID.Parse("00000000-0000-0000-0000-000000002300");
//
uint circuitCodeB = 130001; // uint circuitCodeB = 130001;
EndPoint epB = new IPEndPoint(IPAddress.Loopback, 1301); // EndPoint epB = new IPEndPoint(IPAddress.Loopback, 1301);
UUID agentIdB = UUID.Parse("00000000-0000-0000-0000-000000001301"); // UUID agentIdB = UUID.Parse("00000000-0000-0000-0000-000000001301");
UUID sessionIdB = UUID.Parse("00000000-0000-0000-0000-000000002301"); // UUID sessionIdB = UUID.Parse("00000000-0000-0000-0000-000000002301");
//
TestLLUDPServer testLLUDPServer; // TestLLUDPServer testLLUDPServer;
TestLLPacketServer testLLPacketServer; // TestLLPacketServer testLLPacketServer;
AgentCircuitManager acm; // AgentCircuitManager acm;
SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm); // SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
AddClient(circuitCodeA, epA, agentIdA, sessionIdA, testLLUDPServer, acm); // AddClient(circuitCodeA, epA, agentIdA, sessionIdA, testLLUDPServer, acm);
AddClient(circuitCodeB, epB, agentIdB, sessionIdB, testLLUDPServer, acm); // AddClient(circuitCodeB, epB, agentIdB, sessionIdB, testLLUDPServer, acm);
//
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet1"), epA); // testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet1"), epA);
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet2"), epB); // testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet2"), epB);
testLLUDPServer.LoadReceiveWithBeginException(epA); // testLLUDPServer.LoadReceiveWithBeginException(epA);
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(2, "packet3"), epB); // testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(2, "packet3"), epB);
testLLUDPServer.ReceiveData(null); // testLLUDPServer.ReceiveData(null);
//
Assert.IsFalse(testLLUDPServer.HasCircuit(circuitCodeA)); // Assert.IsFalse(testLLUDPServer.HasCircuit(circuitCodeA));
//
Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(3)); // Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(3));
Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(3)); // Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(3));
} // }
} }
} }

View File

@ -0,0 +1,160 @@
/*
* 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.IO;
using System.Net;
using System.Reflection;
using log4net.Config;
using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Agent.TextureSender;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.ClientStack.LindenUDP.Tests
{
[TestFixture]
public class LLImageManagerTests
{
private AssetBase m_testImageAsset;
private Scene scene;
private LLImageManager llim;
private TestClient tc;
[TestFixtureSetUp]
public void FixtureInit()
{
using (
Stream resource
= GetType().Assembly.GetManifestResourceStream(
"OpenSim.Region.ClientStack.LindenUDP.Tests.Resources.4-tile2.jp2"))
{
using (BinaryReader br = new BinaryReader(resource))
{
m_testImageAsset
= new AssetBase(
TestHelpers.ParseTail(0x1),
"Test Image",
(sbyte)AssetType.Texture,
TestHelpers.ParseTail(0x2).ToString());
m_testImageAsset.Data = br.ReadBytes(99999999);
}
}
}
[SetUp]
public void SetUp()
{
UUID userId = TestHelpers.ParseTail(0x3);
J2KDecoderModule j2kdm = new J2KDecoderModule();
scene = SceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(scene, j2kdm);
tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene);
llim = new LLImageManager(tc, scene.AssetService, j2kdm);
}
[Test]
public void TestSendImage()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
scene.AssetService.Store(m_testImageAsset);
TextureRequestArgs args = new TextureRequestArgs();
args.RequestedAssetID = m_testImageAsset.FullID;
args.DiscardLevel = 0;
args.PacketNumber = 1;
args.Priority = 5;
args.requestSequence = 1;
llim.EnqueueReq(args);
llim.ProcessImageQueue(20);
Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1));
}
[Test]
public void TestDiscardImage()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
scene.AssetService.Store(m_testImageAsset);
TextureRequestArgs args = new TextureRequestArgs();
args.RequestedAssetID = m_testImageAsset.FullID;
args.DiscardLevel = 0;
args.PacketNumber = 1;
args.Priority = 5;
args.requestSequence = 1;
llim.EnqueueReq(args);
// Now create a discard request
TextureRequestArgs discardArgs = new TextureRequestArgs();
discardArgs.RequestedAssetID = m_testImageAsset.FullID;
discardArgs.DiscardLevel = -1;
discardArgs.PacketNumber = 1;
discardArgs.Priority = 0;
discardArgs.requestSequence = 2;
llim.EnqueueReq(discardArgs);
llim.ProcessImageQueue(20);
Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0));
}
[Test]
public void TestMissingImage()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
TextureRequestArgs args = new TextureRequestArgs();
args.RequestedAssetID = m_testImageAsset.FullID;
args.DiscardLevel = 0;
args.PacketNumber = 1;
args.Priority = 5;
args.requestSequence = 1;
llim.EnqueueReq(args);
llim.ProcessImageQueue(20);
Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0));
Assert.That(tc.SentImageNotInDatabasePackets.Count, Is.EqualTo(1));
}
}
}

View File

@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
@ -52,15 +53,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
public override void Update() {} public override void Update() {}
public override void LoadWorldMap() {} public override void LoadWorldMap() {}
public override void AddNewClient(IClientAPI client) public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
{ {
client.OnObjectName += RecordObjectNameCall; client.OnObjectName += RecordObjectNameCall;
// FIXME
return null;
} }
public override void RemoveClient(UUID agentID) {} public override void RemoveClient(UUID agentID, bool someReason) {}
public override void CloseAllAgents(uint circuitcode) {} // public override void CloseAllAgents(uint circuitcode) {}
public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; }
public override void OtherRegionUp(GridRegion otherRegion) { } public override void OtherRegionUp(GridRegion otherRegion) { }
public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; }
/// <summary> /// <summary>
/// Doesn't really matter what the call is - we're using this to test that a packet has actually been received /// Doesn't really matter what the call is - we're using this to test that a packet has actually been received
/// </summary> /// </summary>

View File

@ -27,7 +27,6 @@
using Nini.Config; using Nini.Config;
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenSim.Framework; using OpenSim.Framework;
@ -42,65 +41,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
[TestFixture] [TestFixture]
public class PacketHandlerTests public class PacketHandlerTests
{ {
[Test] // [Test]
/// <summary> // /// <summary>
/// More a placeholder, really // /// More a placeholder, really
/// </summary> // /// </summary>
public void InPacketTest() // public void InPacketTest()
{ // {
TestHelper.InMethod(); // TestHelper.InMethod();
//
AgentCircuitData agent = new AgentCircuitData(); // AgentCircuitData agent = new AgentCircuitData();
agent.AgentID = UUID.Random(); // agent.AgentID = UUID.Random();
agent.firstname = "testfirstname"; // agent.firstname = "testfirstname";
agent.lastname = "testlastname"; // agent.lastname = "testlastname";
agent.SessionID = UUID.Zero; // agent.SessionID = UUID.Zero;
agent.SecureSessionID = UUID.Zero; // agent.SecureSessionID = UUID.Zero;
agent.circuitcode = 123; // agent.circuitcode = 123;
agent.BaseFolder = UUID.Zero; // agent.BaseFolder = UUID.Zero;
agent.InventoryFolder = UUID.Zero; // agent.InventoryFolder = UUID.Zero;
agent.startpos = Vector3.Zero; // agent.startpos = Vector3.Zero;
agent.CapsPath = "http://wibble.com"; // agent.CapsPath = "http://wibble.com";
//
TestLLUDPServer testLLUDPServer; // TestLLUDPServer testLLUDPServer;
TestLLPacketServer testLLPacketServer; // TestLLPacketServer testLLPacketServer;
AgentCircuitManager acm; // AgentCircuitManager acm;
IScene scene = new MockScene(); // IScene scene = new MockScene();
SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm); // SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
//
TestClient testClient = new TestClient(agent, scene); // TestClient testClient = new TestClient(agent, scene);
//
LLPacketHandler packetHandler // LLPacketHandler packetHandler
= new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings()); // = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings());
//
packetHandler.InPacket(new AgentAnimationPacket()); // packetHandler.InPacket(new AgentAnimationPacket());
LLQueItem receivedPacket = packetHandler.PacketQueue.Dequeue(); // LLQueItem receivedPacket = packetHandler.PacketQueue.Dequeue();
//
Assert.That(receivedPacket, Is.Not.Null); // Assert.That(receivedPacket, Is.Not.Null);
Assert.That(receivedPacket.Incoming, Is.True); // Assert.That(receivedPacket.Incoming, Is.True);
Assert.That(receivedPacket.Packet, Is.TypeOf(typeof(AgentAnimationPacket))); // Assert.That(receivedPacket.Packet, Is.TypeOf(typeof(AgentAnimationPacket)));
} // }
//
/// <summary> // /// <summary>
/// Add a client for testing // /// Add a client for testing
/// </summary> // /// </summary>
/// <param name="scene"></param> // /// <param name="scene"></param>
/// <param name="testLLUDPServer"></param> // /// <param name="testLLUDPServer"></param>
/// <param name="testPacketServer"></param> // /// <param name="testPacketServer"></param>
/// <param name="acm">Agent circuit manager used in setting up the stack</param> // /// <param name="acm">Agent circuit manager used in setting up the stack</param>
protected void SetupStack( // protected void SetupStack(
IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer, // IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
out AgentCircuitManager acm) // out AgentCircuitManager acm)
{ // {
IConfigSource configSource = new IniConfigSource(); // IConfigSource configSource = new IniConfigSource();
ClientStackUserSettings userSettings = new ClientStackUserSettings(); // ClientStackUserSettings userSettings = new ClientStackUserSettings();
testLLUDPServer = new TestLLUDPServer(); // testLLUDPServer = new TestLLUDPServer();
acm = new AgentCircuitManager(); // acm = new AgentCircuitManager();
//
uint port = 666; // uint port = 666;
testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm); // testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings); // testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
testLLUDPServer.LocalScene = scene; // testLLUDPServer.LocalScene = scene;
} // }
} }
} }

View File

@ -29,105 +29,113 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using Nini.Config;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenSim.Framework;
namespace OpenSim.Region.ClientStack.LindenUDP.Tests namespace OpenSim.Region.ClientStack.LindenUDP.Tests
{ {
/// <summary> /// <summary>
/// This class enables synchronous testing of the LLUDPServer by allowing us to load our own data into the end /// This class enables regression testing of the LLUDPServer by allowing us to intercept outgoing data.
/// receive event
/// </summary> /// </summary>
public class TestLLUDPServer : LLUDPServer public class TestLLUDPServer : LLUDPServer
{ {
/// <summary> public List<Packet> PacketsSent { get; private set; }
/// The chunks of data to pass to the LLUDPServer when it calls EndReceive
/// </summary>
protected Queue<ChunkSenderTuple> m_chunksToLoad = new Queue<ChunkSenderTuple>();
protected override void BeginReceive() public TestLLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
: base(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager)
{ {
if (m_chunksToLoad.Count > 0 && m_chunksToLoad.Peek().BeginReceiveException) PacketsSent = new List<Packet>();
{
ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
reusedEpSender = tuple.Sender;
throw new SocketException();
}
} }
protected override bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender) public override void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack)
{ {
numBytes = 0; PacketsSent.Add(ack);
//m_log.Debug("Queue size " + m_chunksToLoad.Count);
if (m_chunksToLoad.Count <= 0)
return false;
ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
RecvBuffer = tuple.Data;
numBytes = tuple.Data.Length;
epSender = tuple.Sender;
return true;
} }
public override void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) public override void SendPacket(
LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
{ {
// Don't do anything just yet PacketsSent.Add(packet);
} }
/// <summary> //// /// <summary>
/// Signal that this chunk should throw an exception on Socket.BeginReceive() //// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
/// </summary> //// /// </summary>
/// <param name="epSender"></param> //// protected Queue<ChunkSenderTuple> m_chunksToLoad = new Queue<ChunkSenderTuple>();
public void LoadReceiveWithBeginException(EndPoint epSender) //
{ //// protected override void BeginReceive()
ChunkSenderTuple tuple = new ChunkSenderTuple(epSender); //// {
tuple.BeginReceiveException = true; //// if (m_chunksToLoad.Count > 0 && m_chunksToLoad.Peek().BeginReceiveException)
m_chunksToLoad.Enqueue(tuple); //// {
} //// ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
//// reusedEpSender = tuple.Sender;
/// <summary> //// throw new SocketException();
/// Load some data to be received by the LLUDPServer on the next receive call //// }
/// </summary> //// }
/// <param name="data"></param> //
/// <param name="epSender"></param> //// protected override bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender)
public void LoadReceive(byte[] data, EndPoint epSender) //// {
{ //// numBytes = 0;
m_chunksToLoad.Enqueue(new ChunkSenderTuple(data, epSender)); ////
} //// //m_log.Debug("Queue size " + m_chunksToLoad.Count);
////
/// <summary> //// if (m_chunksToLoad.Count <= 0)
/// Load a packet to be received by the LLUDPServer on the next receive call //// return false;
/// </summary> ////
/// <param name="packet"></param> //// ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
public void LoadReceive(Packet packet, EndPoint epSender) //// RecvBuffer = tuple.Data;
{ //// numBytes = tuple.Data.Length;
LoadReceive(packet.ToBytes(), epSender); //// epSender = tuple.Sender;
} ////
//// return true;
/// <summary> //// }
/// Calls the protected asynchronous result method. This fires out all data chunks currently queued for send //
/// </summary> //// public override void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
/// <param name="result"></param> //// {
public void ReceiveData(IAsyncResult result) //// // Don't do anything just yet
{ //// }
while (m_chunksToLoad.Count > 0) //
OnReceivedData(result); // /// <summary>
} // /// Signal that this chunk should throw an exception on Socket.BeginReceive()
// /// </summary>
/// <summary> // /// <param name="epSender"></param>
/// Has a circuit with the given code been established? // public void LoadReceiveWithBeginException(EndPoint epSender)
/// </summary> // {
/// <param name="circuitCode"></param> // ChunkSenderTuple tuple = new ChunkSenderTuple(epSender);
/// <returns></returns> // tuple.BeginReceiveException = true;
public bool HasCircuit(uint circuitCode) // m_chunksToLoad.Enqueue(tuple);
{ // }
lock (clientCircuits_reverse) //
{ // /// <summary>
return clientCircuits_reverse.ContainsKey(circuitCode); // /// Load some data to be received by the LLUDPServer on the next receive call
} // /// </summary>
} // /// <param name="data"></param>
// /// <param name="epSender"></param>
// public void LoadReceive(byte[] data, EndPoint epSender)
// {
// m_chunksToLoad.Enqueue(new ChunkSenderTuple(data, epSender));
// }
//
// /// <summary>
// /// Load a packet to be received by the LLUDPServer on the next receive call
// /// </summary>
// /// <param name="packet"></param>
// public void LoadReceive(Packet packet, EndPoint epSender)
// {
// LoadReceive(packet.ToBytes(), epSender);
// }
//
// /// <summary>
// /// Calls the protected asynchronous result method. This fires out all data chunks currently queued for send
// /// </summary>
// /// <param name="result"></param>
// public void ReceiveData(IAsyncResult result)
// {
// // Doesn't work the same way anymore
//// while (m_chunksToLoad.Count > 0)
//// OnReceivedData(result);
// }
} }
/// <summary> /// <summary>

View File

@ -118,12 +118,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Returns a list of all of the packets with a TickCount older than /// Returns a list of all of the packets with a TickCount older than
/// the specified timeout /// the specified timeout
/// </summary> /// </summary>
/// <remarks>
/// This function is not thread safe, and cannot be called
/// multiple times concurrently
/// </remarks>
/// <param name="timeoutMS">Number of ticks (milliseconds) before a /// <param name="timeoutMS">Number of ticks (milliseconds) before a
/// packet is considered expired</param> /// packet is considered expired
/// <returns>A list of all expired packets according to the given /// </param>
/// expiration timeout</returns> /// <returns>
/// <remarks>This function is not thread safe, and cannot be called /// A list of all expired packets according to the given
/// multiple times concurrently</remarks> /// expiration timeout
/// </returns>
public List<OutgoingPacket> GetExpiredPackets(int timeoutMS) public List<OutgoingPacket> GetExpiredPackets(int timeoutMS)
{ {
ProcessQueues(); ProcessQueues();
@ -159,6 +164,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
//if (expiredPackets != null)
// m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Found {0} expired packets on timeout of {1}", expiredPackets.Count, timeoutMS);
return expiredPackets; return expiredPackets;
} }
@ -174,6 +182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PendingAck pendingAcknowledgement; PendingAck pendingAcknowledgement;
while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement)) while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
{ {
//m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber);
OutgoingPacket ackedPacket; OutgoingPacket ackedPacket;
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket)) if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
{ {
@ -196,6 +205,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ackedPacket.Client.UpdateRoundTrip(rtt); ackedPacket.Client.UpdateRoundTrip(rtt);
} }
} }
else
{
//m_log.WarnFormat("[UNACKED PACKET COLLECTION]: Could not find packet with sequence number {0} to ack", pendingAcknowledgement.SequenceNumber);
}
} }
} }

View File

@ -103,6 +103,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
// If it's cached, return the cached results // If it's cached, return the cached results
if (m_decodedCache.TryGetValue(assetID, out result)) if (m_decodedCache.TryGetValue(assetID, out result))
{ {
// m_log.DebugFormat(
// "[J2KDecoderModule]: Returning existing cached {0} layers j2k decode for {1}",
// result.Length, assetID);
callback(assetID, result); callback(assetID, result);
} }
else else
@ -129,18 +133,20 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
// Do Decode! // Do Decode!
if (decode) if (decode)
DoJ2KDecode(assetID, j2kData); Decode(assetID, j2kData);
} }
} }
/// <summary> public bool Decode(UUID assetID, byte[] j2kData)
/// Provides a synchronous decode so that caller can be assured that this executes before the next line
/// </summary>
/// <param name="assetID"></param>
/// <param name="j2kData"></param>
public void Decode(UUID assetID, byte[] j2kData)
{ {
DoJ2KDecode(assetID, j2kData); OpenJPEG.J2KLayerInfo[] layers;
int components;
return Decode(assetID, j2kData, out layers, out components);
}
public bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components)
{
return DoJ2KDecode(assetID, j2kData, out layers, out components);
} }
#endregion IJ2KDecoder #endregion IJ2KDecoder
@ -150,11 +156,21 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
/// </summary> /// </summary>
/// <param name="assetID">UUID of Asset</param> /// <param name="assetID">UUID of Asset</param>
/// <param name="j2kData">JPEG2000 data</param> /// <param name="j2kData">JPEG2000 data</param>
private void DoJ2KDecode(UUID assetID, byte[] j2kData) /// <param name="layers">layer data</param>
/// <param name="components">number of components</param>
/// <returns>true if decode was successful. false otherwise.</returns>
private bool DoJ2KDecode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components)
{ {
// m_log.DebugFormat(
// "[J2KDecoderModule]: Doing J2K decoding of {0} bytes for asset {1}", j2kData.Length, assetID);
bool decodedSuccessfully = true;
//int DecodeTime = 0; //int DecodeTime = 0;
//DecodeTime = Environment.TickCount; //DecodeTime = Environment.TickCount;
OpenJPEG.J2KLayerInfo[] layers;
// We don't get this from CSJ2K. Is it relevant?
components = 0;
if (!TryLoadCacheForAsset(assetID, out layers)) if (!TryLoadCacheForAsset(assetID, out layers))
{ {
@ -189,14 +205,15 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
catch (Exception ex) catch (Exception ex)
{ {
m_log.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " + assetID + ": " + ex.Message); m_log.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " + assetID + ": " + ex.Message);
decodedSuccessfully = false;
} }
} }
else else
{ {
int components;
if (!OpenJPEG.DecodeLayerBoundaries(j2kData, out layers, out components)) if (!OpenJPEG.DecodeLayerBoundaries(j2kData, out layers, out components))
{ {
m_log.Warn("[J2KDecoderModule]: OpenJPEG failed to decode texture " + assetID); m_log.Warn("[J2KDecoderModule]: OpenJPEG failed to decode texture " + assetID);
decodedSuccessfully = false;
} }
} }
@ -205,6 +222,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults"); m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults");
// Layer decoding completely failed. Guess at sane defaults for the layer boundaries // Layer decoding completely failed. Guess at sane defaults for the layer boundaries
layers = CreateDefaultLayers(j2kData.Length); layers = CreateDefaultLayers(j2kData.Length);
decodedSuccessfully = false;
} }
// Cache Decoded layers // Cache Decoded layers
@ -224,6 +242,8 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
m_notifyList.Remove(assetID); m_notifyList.Remove(assetID);
} }
} }
return decodedSuccessfully;
} }
private OpenJPEG.J2KLayerInfo[] CreateDefaultLayers(int j2kLength) private OpenJPEG.J2KLayerInfo[] CreateDefaultLayers(int j2kLength)

View File

@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
AssetBase asset = AssetHelpers.CreateAsset(); AssetBase asset = AssetHelpers.CreateNotecardAsset();
asset.ID = TestHelpers.ParseTail(0x1).ToString(); asset.ID = TestHelpers.ParseTail(0x1).ToString();
// Check we don't get anything before the asset is put in the cache // Check we don't get anything before the asset is put in the cache
@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
AssetBase asset = AssetHelpers.CreateAsset(); AssetBase asset = AssetHelpers.CreateNotecardAsset();
asset.ID = TestHelpers.ParseTail(0x2).ToString(); asset.ID = TestHelpers.ParseTail(0x2).ToString();
m_cache.Store(asset); m_cache.Store(asset);
@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
AssetBase asset = AssetHelpers.CreateAsset(); AssetBase asset = AssetHelpers.CreateNotecardAsset();
asset.ID = TestHelpers.ParseTail(0x2).ToString(); asset.ID = TestHelpers.ParseTail(0x2).ToString();
m_cache.Store(asset); m_cache.Store(asset);

View File

@ -615,7 +615,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.AttachedAvatar = UUID.Zero; so.AttachedAvatar = UUID.Zero;
rootPart.SetParentLocalId(0); rootPart.SetParentLocalId(0);
so.ClearPartAttachmentData(); so.ClearPartAttachmentData();
rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim); rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive);
so.HasGroupChanged = true; so.HasGroupChanged = true;
rootPart.Rezzed = DateTime.Now; rootPart.Rezzed = DateTime.Now;
rootPart.RemFlag(PrimFlags.TemporaryOnRez); rootPart.RemFlag(PrimFlags.TemporaryOnRez);
@ -764,10 +764,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.AttachedAvatar = avatar.UUID; so.AttachedAvatar = avatar.UUID;
if (so.RootPart.PhysActor != null) if (so.RootPart.PhysActor != null)
{ so.RootPart.RemoveFromPhysics();
m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
so.RootPart.PhysActor = null;
}
so.AbsolutePosition = attachOffset; so.AbsolutePosition = attachOffset;
so.RootPart.AttachedPos = attachOffset; so.RootPart.AttachedPos = attachOffset;

View File

@ -115,22 +115,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
#endregion #endregion
/// <summary>
/// Check for the existence of the baked texture assets.
/// </summary>
/// <param name="client"></param>
public bool ValidateBakedTextureCache(IClientAPI client) public bool ValidateBakedTextureCache(IClientAPI client)
{
return ValidateBakedTextureCache(client, true);
}
/// <summary>
/// Check for the existence of the baked texture assets. Request a rebake
/// unless checkonly is true.
/// </summary>
/// <param name="client"></param>
/// <param name="checkonly"></param>
private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly)
{ {
ScenePresence sp = m_scene.GetScenePresence(client.AgentId); ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp == null) if (sp == null)
@ -164,17 +149,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
defonly = false; // found a non-default texture reference defonly = false; // found a non-default texture reference
if (!CheckBakedTextureAsset(client, face.TextureID, idx)) if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
{
// the asset didn't exist if we are only checking, then we found a bad
// one and we're done otherwise, ask for a rebake
if (checkonly)
return false; return false;
m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID);
client.SendRebakeAvatarTextures(face.TextureID);
}
} }
m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", client.AgentId); m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", client.AgentId);
@ -183,6 +159,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
return (defonly ? false : true); return (defonly ? false : true);
} }
public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
{
int texturesRebaked = 0;
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
{
int idx = AvatarAppearance.BAKE_INDICES[i];
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
// if there is no texture entry, skip it
if (face == null)
continue;
// m_log.DebugFormat(
// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
// face.TextureID, idx, client.Name, client.AgentId);
// if the texture is one of the "defaults" then skip it
// this should probably be more intelligent (skirt texture doesnt matter
// if the avatar isnt wearing a skirt) but if any of the main baked
// textures is default then the rest should be as well
if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
continue;
if (missingTexturesOnly)
{
if (m_scene.AssetService.Get(face.TextureID.ToString()) != null)
continue;
else
m_log.DebugFormat(
"[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
face.TextureID, idx, sp.Name);
}
else
{
m_log.DebugFormat(
"[AVFACTORY]: Requesting rebake of {0} ({1}) for {2}.",
face.TextureID, idx, sp.Name);
}
texturesRebaked++;
sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
}
return texturesRebaked;
}
/// <summary> /// <summary>
/// Set appearance data (texture asset IDs and slider settings) received from the client /// Set appearance data (texture asset IDs and slider settings) received from the client
/// </summary> /// </summary>
@ -230,14 +253,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
{ {
changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", client.AgentId); if (!ValidateBakedTextureCache(sp.ControllingClient))
Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client, false); }); RequestRebake(sp, true);
// This appears to be set only in the final stage of the appearance // This appears to be set only in the final stage of the appearance
// update transaction. In theory, we should be able to do an immediate // update transaction. In theory, we should be able to do an immediate
// appearance send and save here. // appearance send and save here.
} }
// save only if there were changes, send no matter what (doesn't hurt to send twice) // save only if there were changes, send no matter what (doesn't hurt to send twice)
if (changed) if (changed)
QueueAppearanceSave(client.AgentId); QueueAppearanceSave(client.AgentId);
@ -385,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// </summary> /// </summary>
public void QueueAppearanceSend(UUID agentid) public void QueueAppearanceSend(UUID agentid)
{ {
// m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); // m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second // 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
@ -444,10 +467,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue); Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue);
foreach (KeyValuePair<UUID, long> kvp in sends) foreach (KeyValuePair<UUID, long> kvp in sends)
{ {
if (kvp.Value < now) // We have to load the key and value into local parameters to avoid a race condition if we loop
// around and load kvp with a different value before FireAndForget has launched its thread.
UUID avatarID = kvp.Key;
long sendTime = kvp.Value;
// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
if (sendTime < now)
{ {
Util.FireAndForget(delegate(object o) { SendAppearance(kvp.Key); }); Util.FireAndForget(o => SendAppearance(avatarID));
m_sendqueue.Remove(kvp.Key); m_sendqueue.Remove(avatarID);
} }
} }
} }
@ -457,17 +487,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue); Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue);
foreach (KeyValuePair<UUID, long> kvp in saves) foreach (KeyValuePair<UUID, long> kvp in saves)
{ {
if (kvp.Value < now) // We have to load the key and value into local parameters to avoid a race condition if we loop
// around and load kvp with a different value before FireAndForget has launched its thread.
UUID avatarID = kvp.Key;
long sendTime = kvp.Value;
if (sendTime < now)
{ {
Util.FireAndForget(delegate(object o) { SaveAppearance(kvp.Key); }); Util.FireAndForget(o => SaveAppearance(avatarID));
m_savequeue.Remove(kvp.Key); m_savequeue.Remove(avatarID);
}
} }
} }
// We must lock both queues here so that QueueAppearanceSave() or *Send() don't m_updateTimer.Start() on
// another thread inbetween the first count calls and m_updateTimer.Stop() on this thread.
lock (m_sendqueue)
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0) if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
m_updateTimer.Stop(); m_updateTimer.Stop();
} }
}
#endregion #endregion
@ -535,6 +573,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
public bool SendAppearance(UUID agentId) public bool SendAppearance(UUID agentId)
{ {
// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
ScenePresence sp = m_scene.GetScenePresence(agentId); ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null) if (sp == null)
{ {

View File

@ -279,12 +279,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
HashSet<UUID> receiverIDs = new HashSet<UUID>(); HashSet<UUID> receiverIDs = new HashSet<UUID>();
((Scene)c.Scene).ForEachScenePresence( ((Scene)c.Scene).ForEachRootScenePresence(
delegate(ScenePresence presence) delegate(ScenePresence presence)
{ {
// ignore chat from child agents
if (presence.IsChildAgent) return;
IClientAPI client = presence.ControllingClient; IClientAPI client = presence.ControllingClient;
// don't forward SayOwner chat from objects to // don't forward SayOwner chat from objects to

View File

@ -98,9 +98,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
public void SendGeneralAlert(string message) public void SendGeneralAlert(string message)
{ {
m_scene.ForEachScenePresence(delegate(ScenePresence presence) m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
{ {
if (!presence.IsChildAgent)
presence.ControllingClient.SendAlertMessage(message); presence.ControllingClient.SendAlertMessage(message);
}); });
} }
@ -163,9 +162,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
public void SendNotificationToUsersInRegion( public void SendNotificationToUsersInRegion(
UUID fromAvatarID, string fromAvatarName, string message) UUID fromAvatarID, string fromAvatarName, string message)
{ {
m_scene.ForEachScenePresence(delegate(ScenePresence presence) m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
{ {
if (!presence.IsChildAgent)
presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message); presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message);
}); });
} }
@ -201,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
} }
else else
{ {
OpenSim.Framework.Console.MainConsole.Instance.Output( MainConsole.Instance.Output(
"Usage: alert <message> | alert-user <first> <last> <message>"); "Usage: alert <message> | alert-user <first> <last> <message>");
return; return;
} }

View File

@ -36,6 +36,7 @@ using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.Communications; using OpenSim.Framework.Communications;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
@ -78,10 +79,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected IFriendsService m_FriendsService = null; protected IFriendsService m_FriendsService = null;
protected FriendsSimConnector m_FriendsSimConnector; protected FriendsSimConnector m_FriendsSimConnector;
protected Dictionary<UUID, UserFriendData> m_Friends = /// <summary>
new Dictionary<UUID, UserFriendData>(); /// Cache friends lists for users.
/// </summary>
/// <remarks>
/// This is a complex and error-prone thing to do. At the moment, we assume that the efficiency gained in
/// permissions checks outweighs the disadvantages of that complexity.
/// </remarks>
protected Dictionary<UUID, UserFriendData> m_Friends = new Dictionary<UUID, UserFriendData>();
protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>(); /// <summary>
/// Maintain a record of viewers that need to be sent notifications for friends that are online. This only
/// needs to be done on login. Subsequent online/offline friend changes are sent by a different mechanism.
/// </summary>
protected HashSet<UUID> m_NeedsListOfOnlineFriends = new HashSet<UUID>();
protected IPresenceService PresenceService protected IPresenceService PresenceService
{ {
@ -164,6 +175,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// Instantiate the request handler // Instantiate the request handler
IHttpServer server = MainServer.GetHttpServer((uint)mPort); IHttpServer server = MainServer.GetHttpServer((uint)mPort);
if (server != null)
server.AddStreamHandler(new FriendsRequestHandler(this)); server.AddStreamHandler(new FriendsRequestHandler(this));
} }
@ -186,6 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{ {
if (!m_Enabled) if (!m_Enabled)
return; return;
m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
m_Scenes.Add(scene); m_Scenes.Add(scene);
@ -238,16 +252,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
client.OnInstantMessage += OnInstantMessage; client.OnInstantMessage += OnInstantMessage;
client.OnApproveFriendRequest += OnApproveFriendRequest; client.OnApproveFriendRequest += OnApproveFriendRequest;
client.OnDenyFriendRequest += OnDenyFriendRequest; client.OnDenyFriendRequest += OnDenyFriendRequest;
client.OnTerminateFriendship += OnTerminateFriendship; client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID);
client.OnGrantUserRights += OnGrantUserRights; client.OnGrantUserRights += OnGrantUserRights;
Util.FireAndForget(delegate { FetchFriendslist(client); }); // Do not do this asynchronously. If we do, then subsequent code can outrace CacheFriends() and
// return misleading results from the still empty friends cache.
// If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls
// to GetFriends() will wait until CacheFriends() completes. Locks are insufficient.
CacheFriends(client);
} }
/// Fetch the friends list or increment the refcount for the existing /// <summary>
/// friends list /// Cache the friends list or increment the refcount for the existing friends list.
/// </summary>
/// <param name="client">
/// </param>
/// <returns>
/// Returns true if the list was fetched, false if it wasn't /// Returns true if the list was fetched, false if it wasn't
protected virtual bool FetchFriendslist(IClientAPI client) /// </returns>
protected virtual bool CacheFriends(IClientAPI client)
{ {
UUID agentID = client.AgentId; UUID agentID = client.AgentId;
lock (m_Friends) lock (m_Friends)
@ -294,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private void OnMakeRootAgent(ScenePresence sp) private void OnMakeRootAgent(ScenePresence sp)
{ {
RefetchFriends(sp.ControllingClient); RecacheFriends(sp.ControllingClient);
} }
private void OnClientLogin(IClientAPI client) private void OnClientLogin(IClientAPI client)
@ -306,8 +329,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
StatusChange(agentID, true); StatusChange(agentID, true);
// Register that we need to send the list of online friends to this user // Register that we need to send the list of online friends to this user
lock (m_NeedsListOfFriends) lock (m_NeedsListOfOnlineFriends)
m_NeedsListOfFriends.Add(agentID); m_NeedsListOfOnlineFriends.Add(agentID);
} }
public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
@ -315,9 +338,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
UUID agentID = client.AgentId; UUID agentID = client.AgentId;
// Check if the online friends list is needed // Check if the online friends list is needed
lock (m_NeedsListOfFriends) lock (m_NeedsListOfOnlineFriends)
{ {
if (!m_NeedsListOfFriends.Remove(agentID)) if (!m_NeedsListOfOnlineFriends.Remove(agentID))
return false; return false;
} }
@ -325,7 +348,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
List<UUID> online = GetOnlineFriends(agentID); List<UUID> online = GetOnlineFriends(agentID);
if (online.Count > 0) if (online.Count > 0)
{ {
m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); m_log.DebugFormat(
"[FRIENDS MODULE]: User {0} in region {1} has {2} friends online",
client.Name, client.Scene.RegionInfo.RegionName, online.Count);
client.SendAgentOnline(online.ToArray()); client.SendAgentOnline(online.ToArray());
} }
@ -575,19 +601,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders) private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
{ {
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
StoreFriendships(agentID, friendID); AddFriendship(client, friendID);
}
public void AddFriendship(IClientAPI client, UUID friendID)
{
StoreFriendships(client.AgentId, friendID);
// Update the local cache // Update the local cache
RefetchFriends(client); RecacheFriends(client);
// //
// Notify the friend // Notify the friend
// //
// Try Local // Try Local
if (LocalFriendshipApproved(agentID, client.Name, friendID)) if (LocalFriendshipApproved(client.AgentId, client.Name, friendID))
{ {
client.SendAgentOnline(new UUID[] { friendID }); client.SendAgentOnline(new UUID[] { friendID });
return; return;
@ -601,7 +632,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (friendSession != null) if (friendSession != null)
{ {
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); m_FriendsSimConnector.FriendshipApproved(region, client.AgentId, client.Name, friendID);
client.SendAgentOnline(new UUID[] { friendID }); client.SendAgentOnline(new UUID[] { friendID });
} }
} }
@ -636,13 +667,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
} }
} }
private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) public void RemoveFriendship(IClientAPI client, UUID exfriendID)
{ {
if (!DeleteFriendship(agentID, exfriendID)) if (!DeleteFriendship(client.AgentId, exfriendID))
client.SendAlertMessage("Unable to terminate friendship on this sim."); client.SendAlertMessage("Unable to terminate friendship on this sim.");
// Update local cache // Update local cache
RefetchFriends(client); RecacheFriends(client);
client.SendTerminateFriend(exfriendID); client.SendTerminateFriend(exfriendID);
@ -661,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (friendSession != null) if (friendSession != null)
{ {
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID);
} }
} }
} }
@ -756,7 +787,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
friendClient.SendInstantMessage(im); friendClient.SendInstantMessage(im);
// Update the local cache // Update the local cache
RefetchFriends(friendClient); RecacheFriends(friendClient);
// we're done // we're done
return true; return true;
@ -789,7 +820,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// the friend in this sim as root agent // the friend in this sim as root agent
friendClient.SendTerminateFriend(exfriendID); friendClient.SendTerminateFriend(exfriendID);
// update local cache // update local cache
RefetchFriends(friendClient); RecacheFriends(friendClient);
// we're done // we're done
return true; return true;
} }
@ -806,16 +837,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (onlineBitChanged) if (onlineBitChanged)
{ {
if ((rights & (int)FriendRights.CanSeeOnline) == 1) if ((rights & (int)FriendRights.CanSeeOnline) == 1)
friendClient.SendAgentOnline(new UUID[] { new UUID(userID) }); friendClient.SendAgentOnline(new UUID[] { userID });
else else
friendClient.SendAgentOffline(new UUID[] { new UUID(userID) }); friendClient.SendAgentOffline(new UUID[] { userID });
} }
else else
{ {
bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0;
if (canEditObjectsChanged) if (canEditObjectsChanged)
friendClient.SendChangeUserRights(userID, friendID, rights); friendClient.SendChangeUserRights(userID, friendID, rights);
} }
// Update local cache // Update local cache
@ -868,7 +898,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
} }
/// <summary> /// <summary>
/// Update loca cache only /// Update local cache only
/// </summary> /// </summary>
/// <param name="userID"></param> /// <param name="userID"></param>
/// <param name="friendID"></param> /// <param name="friendID"></param>
@ -889,7 +919,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return FriendsService.GetFriends(client.AgentId); return FriendsService.GetFriends(client.AgentId);
} }
private void RefetchFriends(IClientAPI client) private void RecacheFriends(IClientAPI client)
{ {
UUID agentID = client.AgentId; UUID agentID = client.AgentId;
lock (m_Friends) lock (m_Friends)

View File

@ -30,7 +30,6 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using Nwc.XmlRpc; using Nwc.XmlRpc;
@ -84,9 +83,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
#endregion #endregion
protected override bool FetchFriendslist(IClientAPI client) protected override bool CacheFriends(IClientAPI client)
{ {
if (base.FetchFriendslist(client)) if (base.CacheFriends(client))
{ {
UUID agentID = client.AgentId; UUID agentID = client.AgentId;
// we do this only for the root agent // we do this only for the root agent

View File

@ -0,0 +1,118 @@
/*
* 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 Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Avatar.Friends;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
{
[TestFixture]
public class FriendsModuleTests
{
private FriendsModule m_fm;
private TestScene m_scene;
[SetUp]
public void Init()
{
IConfigSource config = new IniConfigSource();
config.AddConfig("Modules");
// Not strictly necessary since FriendsModule assumes it is the default (!)
config.Configs["Modules"].Set("FriendsModule", "FriendsModule");
config.AddConfig("Friends");
config.Configs["Friends"].Set("Connector", "OpenSim.Services.FriendsService.dll");
config.AddConfig("FriendsService");
config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
m_scene = SceneHelpers.SetupScene();
m_fm = new FriendsModule();
SceneHelpers.SetupSceneModules(m_scene, config, m_fm);
}
[Test]
public void TestNoFriends()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0));
}
[Test]
public void TestAddFriendshipWhileOnline()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1);
UUID user2Id = TestHelpers.ParseTail(0x2);
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id);
// This fiendship is two-way but without a connector, only the first user will receive the online
// notification.
m_fm.AddFriendship(sp.ControllingClient, user2Id);
Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1));
}
[Test]
public void TestRemoveFriendshipWhileOnline()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID user1Id = TestHelpers.ParseTail(0x1);
UUID user2Id = TestHelpers.ParseTail(0x2);
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, user1Id);
SceneHelpers.AddScenePresence(m_scene, user2Id);
m_fm.AddFriendship(sp.ControllingClient, user2Id);
m_fm.RemoveFriendship(sp.ControllingClient, user2Id);
TestClient user1Client = sp.ControllingClient as TestClient;
Assert.That(user1Client.ReceivedFriendshipTerminations.Count, Is.EqualTo(1));
Assert.That(user1Client.ReceivedFriendshipTerminations[0], Is.EqualTo(user2Id));
}
}
}

View File

@ -140,10 +140,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
// This is a bit crude. It seems the client will be null before it actually stops the thread // This is a bit crude. It seems the client will be null before it actually stops the thread
// The thread will kill itself eventually :/ // The thread will kill itself eventually :/
// Is there another way to make sure *all* clients get this 'inter region' message? // Is there another way to make sure *all* clients get this 'inter region' message?
m_scene.ForEachScenePresence( m_scene.ForEachRootScenePresence(
delegate(ScenePresence p) delegate(ScenePresence p)
{ {
if (p.UUID != godID && !p.IsChildAgent) if (p.UUID != godID)
{ {
// Possibly this should really be p.Close() though that method doesn't send a close // Possibly this should really be p.Close() though that method doesn't send a close
// to the client // to the client

View File

@ -36,6 +36,7 @@ using Nwc.XmlRpc;
using Mono.Addins; using Mono.Addins;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using GridRegion = OpenSim.Services.Interfaces.GridRegion; using GridRegion = OpenSim.Services.Interfaces.GridRegion;

View File

@ -34,6 +34,7 @@ using Nini.Config;
using Nwc.XmlRpc; using Nwc.XmlRpc;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using GridRegion = OpenSim.Services.Interfaces.GridRegion; using GridRegion = OpenSim.Services.Interfaces.GridRegion;

View File

@ -275,19 +275,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
{ {
if (m_TransferModule != null) if (m_TransferModule != null)
m_TransferModule.SendInstantMessage(im, delegate(bool success) { m_TransferModule.SendInstantMessage(im, delegate(bool success) {
// Send BulkUpdateInventory
IInventoryService invService = scene.InventoryService;
UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId); // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
folder = invService.GetFolder(folder); // and is apparently supposed to fix bulk inventory updates after accepting items. But
// instead it appears to cause two copies of an accepted folder for the receiving user in
// at least some cases. Folder/item update is already done when the offer is made (see code above)
ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID)); // // Send BulkUpdateInventory
// IInventoryService invService = scene.InventoryService;
// If the user has left the scene by the time the message comes back then we can't send // UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
// them the update. //
if (fromUser != null) // InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
fromUser.ControllingClient.SendBulkUpdateInventory(folder); // folder = invService.GetFolder(folder);
//
// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
//
// // If the user has left the scene by the time the message comes back then we can't send
// // them the update.
// if (fromUser != null)
// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
}); });
} }
} }

View File

@ -29,12 +29,14 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Text;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using Mono.Addins; using Mono.Addins;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using Caps=OpenSim.Framework.Capabilities.Caps; using Caps=OpenSim.Framework.Capabilities.Caps;
@ -46,6 +48,8 @@ namespace OpenSim.Region.CoreModules.Framework
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private string m_showCapsCommandFormat = " {0,-38} {1,-60}\n";
protected Scene m_scene; protected Scene m_scene;
/// <summary> /// <summary>
@ -67,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework
m_scene.RegisterModuleInterface<ICapabilitiesModule>(this); m_scene.RegisterModuleInterface<ICapabilitiesModule>(this);
MainConsole.Instance.Commands.AddCommand("Capabilities", false, "show caps", MainConsole.Instance.Commands.AddCommand("Capabilities", false, "show caps",
"show caps", "show caps",
"Shows all registered capabilities", CapabilitiesCommand); "Shows all registered capabilities", HandleShowCapsCommand);
} }
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
@ -226,21 +230,23 @@ namespace OpenSim.Region.CoreModules.Framework
} }
} }
private void CapabilitiesCommand(string module, string[] cmdparams) private void HandleShowCapsCommand(string module, string[] cmdparams)
{ {
System.Text.StringBuilder caps = new System.Text.StringBuilder(); StringBuilder caps = new StringBuilder();
caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects)
{ {
caps.AppendFormat("** User {0}:\n", kvp.Key); caps.AppendFormat("** User {0}:\n", kvp.Key);
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.CapsDetails.GetEnumerator(); kvp2.MoveNext(); )
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); )
{ {
Uri uri = new Uri(kvp2.Value.ToString()); Uri uri = new Uri(kvp2.Value.ToString());
caps.AppendFormat(" {0} = {1}\n", kvp2.Key, uri.PathAndQuery); caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
} }
foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers)
caps.AppendFormat(" {0} = {1}\n", kvp3.Key, kvp3.Value); caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
} }
MainConsole.Instance.Output(caps.ToString()); MainConsole.Instance.Output(caps.ToString());

View File

@ -547,12 +547,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
return null; return null;
userID = remoteClient.AgentId; userID = remoteClient.AgentId;
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}",
// action, remoteClient.Name, userID);
} }
else else
{ {
// All returns / deletes go to the object owner // All returns / deletes go to the object owner
// //
userID = so.RootPart.OwnerID; userID = so.RootPart.OwnerID;
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}",
// action, userID);
} }
if (userID == UUID.Zero) // Can't proceed if (userID == UUID.Zero) // Can't proceed
@ -638,11 +646,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
} }
// Override and put into where it came from, if it came // Override and put into where it came from, if it came
// from anywhere in inventory // from anywhere in inventory and the owner is taking it back.
// //
if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
{ {
if (so.RootPart.FromFolderID != UUID.Zero) if (so.RootPart.FromFolderID != UUID.Zero && userID == remoteClient.AgentId)
{ {
InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID);
folder = m_Scene.InventoryService.GetFolder(f); folder = m_Scene.InventoryService.GetFolder(f);

View File

@ -29,8 +29,31 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
{ {
interface IMonitor interface IMonitor
{ {
double GetValue(); /// <summary>
/// Name of the monitor.
/// </summary>
/// <remarks>
/// This is the name used in XML.
/// </remarks>
/// <returns></returns>
string GetName(); string GetName();
string GetFriendlyValue(); // Convert to readable numbers
/// <summary>
/// Value of this monitor
/// </summary>
/// <returns></returns>
double GetValue();
/// <summary>
/// Human-readable name of the monitor
/// </summary>
/// <returns></returns>
string GetFriendlyName();
/// <summary>
/// Human readable value.
/// </summary>
/// <returns></returns>
string GetFriendlyValue();
} }
} }

View File

@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
@ -32,6 +33,7 @@ using log4net;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts; using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts;
using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
@ -41,16 +43,50 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
{ {
public class MonitorModule : IRegionModule public class MonitorModule : IRegionModule
{ {
/// <summary>
/// Is this module enabled?
/// </summary>
public bool Enabled { get; private set; }
private Scene m_scene; private Scene m_scene;
private readonly List<IMonitor> m_monitors = new List<IMonitor>(); private readonly List<IMonitor> m_monitors = new List<IMonitor>();
private readonly List<IAlert> m_alerts = new List<IAlert>(); private readonly List<IAlert> m_alerts = new List<IAlert>();
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#region Implementation of IRegionModule
public MonitorModule()
{
Enabled = true;
}
public void Initialise(Scene scene, IConfigSource source)
{
IConfig cnfg = source.Configs["Monitoring"];
if (cnfg != null)
Enabled = cnfg.GetBoolean("Enabled", true);
if (!Enabled)
return;
m_scene = scene;
m_scene.AddCommand(this, "monitor report",
"monitor report",
"Returns a variety of statistics about the current region and/or simulator",
DebugMonitors);
MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID, StatsPage);
MainServer.Instance.AddHTTPHandler(
"/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage);
}
public void DebugMonitors(string module, string[] args) public void DebugMonitors(string module, string[] args)
{ {
foreach (IMonitor monitor in m_monitors) foreach (IMonitor monitor in m_monitors)
{ {
m_log.Info("[MonitorModule] " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetName() + " = " + monitor.GetFriendlyValue()); m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue());
} }
} }
@ -62,20 +98,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
} }
} }
#region Implementation of IRegionModule
public void Initialise(Scene scene, IConfigSource source)
{
m_scene = scene;
m_scene.AddCommand(this, "monitor report",
"monitor report",
"Returns a variety of statistics about the current region and/or simulator",
DebugMonitors);
MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID + "/", StatsPage);
}
public Hashtable StatsPage(Hashtable request) public Hashtable StatsPage(Hashtable request)
{ {
// If request was for a specific monitor // If request was for a specific monitor
@ -114,11 +136,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
string xml = "<data>"; string xml = "<data>";
foreach (IMonitor monitor in m_monitors) foreach (IMonitor monitor in m_monitors)
{ {
string elemName = monitor.ToString(); string elemName = monitor.GetName();
if (elemName.StartsWith(monitor.GetType().Namespace)) xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1); // m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
xml += "<" + elemName + ">" + monitor.GetValue() + "</" + elemName + ">";
} }
xml += "</data>"; xml += "</data>";
@ -133,6 +153,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public void PostInitialise() public void PostInitialise()
{ {
if (!Enabled)
return;
m_monitors.Add(new AgentCountMonitor(m_scene)); m_monitors.Add(new AgentCountMonitor(m_scene));
m_monitors.Add(new ChildAgentCountMonitor(m_scene)); m_monitors.Add(new ChildAgentCountMonitor(m_scene));
m_monitors.Add(new GCMemoryMonitor()); m_monitors.Add(new GCMemoryMonitor());
@ -146,6 +169,158 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m_monitors.Add(new LandFrameMonitor(m_scene)); m_monitors.Add(new LandFrameMonitor(m_scene));
m_monitors.Add(new LastFrameTimeMonitor(m_scene)); m_monitors.Add(new LastFrameTimeMonitor(m_scene));
m_monitors.Add(
new GenericMonitor(
m_scene,
"TimeDilationMonitor",
"Time Dilation",
m => m.Scene.StatsReporter.LastReportedSimStats[0],
m => m.GetValue().ToString()));
m_monitors.Add(
new GenericMonitor(
m_scene,
"SimFPSMonitor",
"Sim FPS",
m => m.Scene.StatsReporter.LastReportedSimStats[1],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"PhysicsFPSMonitor",
"Physics FPS",
m => m.Scene.StatsReporter.LastReportedSimStats[2],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"AgentUpdatesPerSecondMonitor",
"Agent Updates",
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(
new GenericMonitor(
m_scene,
"ActiveObjectCountMonitor",
"Active Objects",
m => m.Scene.StatsReporter.LastReportedSimStats[7],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"ActiveScriptsMonitor",
"Active Scripts",
m => m.Scene.StatsReporter.LastReportedSimStats[19],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"ScriptEventsPerSecondMonitor",
"Script Events",
m => m.Scene.StatsReporter.LastReportedSimStats[20],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"InPacketsPerSecondMonitor",
"In Packets",
m => m.Scene.StatsReporter.LastReportedSimStats[13],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"OutPacketsPerSecondMonitor",
"Out Packets",
m => m.Scene.StatsReporter.LastReportedSimStats[14],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"UnackedBytesMonitor",
"Unacked Bytes",
m => m.Scene.StatsReporter.LastReportedSimStats[15],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"PendingDownloadsMonitor",
"Pending Downloads",
m => m.Scene.StatsReporter.LastReportedSimStats[17],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"PendingUploadsMonitor",
"Pending Uploads",
m => m.Scene.StatsReporter.LastReportedSimStats[18],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"TotalFrameTimeMonitor",
"Total Frame Time",
m => m.Scene.StatsReporter.LastReportedSimStats[8],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"NetFrameTimeMonitor",
"Net Frame Time",
m => m.Scene.StatsReporter.LastReportedSimStats[9],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"PhysicsFrameTimeMonitor",
"Physics Frame Time",
m => m.Scene.StatsReporter.LastReportedSimStats[10],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"SimulationFrameTimeMonitor",
"Simulation Frame Time",
m => m.Scene.StatsReporter.LastReportedSimStats[12],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"AgentFrameTimeMonitor",
"Agent Frame Time",
m => m.Scene.StatsReporter.LastReportedSimStats[16],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"ImagesFrameTimeMonitor",
"Images Frame Time",
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_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
foreach (IAlert alert in m_alerts) foreach (IAlert alert in m_alerts)
@ -161,7 +336,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public void Close() public void Close()
{ {
} }
public string Name public string Name

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "AgentCountMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.SceneGraph.GetRootAgentCount(); return m_scene.SceneGraph.GetRootAgentCount();
} }
public string GetName() public string GetFriendlyName()
{ {
return "Root Agent Count"; return "Root Agent Count";
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "ChildAgentCountMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.SceneGraph.GetChildAgentCount(); return m_scene.SceneGraph.GetChildAgentCount();
} }
public string GetName() public string GetFriendlyName()
{ {
return "Child Agent Count"; return "Child Agent Count";
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "EventFrameMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.MonitorEventTime; return m_scene.MonitorEventTime;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Total Event Frame Time"; return "Total Event Frame Time";
} }

View File

@ -33,12 +33,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
{ {
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "GCMemoryMonitor";
}
public double GetValue() public double GetValue()
{ {
return GC.GetTotalMemory(false); return GC.GetTotalMemory(false);
} }
public string GetName() public string GetFriendlyName()
{ {
return "GC Reported Memory"; return "GC Reported Memory";
} }

View File

@ -26,43 +26,55 @@
*/ */
using System; using System;
using System.Diagnostics;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Examples.SimpleModule namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
{ {
public class CpuCounterObject : SceneObjectGroup class GenericMonitor : IMonitor
{ {
protected override bool InSceneBackup public Scene Scene { get; private set; }
public string Name { get; private set; }
public string FriendlyName { get; private set; }
private readonly Func<GenericMonitor, double> m_getValueAction;
private readonly Func<GenericMonitor, string> m_getFriendlyValueAction;
public GenericMonitor(
Scene scene,
string name,
string friendlyName,
Func<GenericMonitor, double> getValueAction,
Func<GenericMonitor, string> getFriendlyValueAction)
{ {
get Scene = scene;
{ Name = name;
return false; FriendlyName = name;
} m_getFriendlyValueAction = getFriendlyValueAction;
m_getValueAction = getValueAction;
} }
private PerformanceCounter m_counter; public double GetValue()
public CpuCounterObject(UUID ownerID, Vector3 pos)
: base(ownerID, pos, PrimitiveBaseShape.Default)
{ {
String objectName = "Processor"; return m_getValueAction(this);
String counterName = "% Processor Time";
String instanceName = "_Total";
m_counter = new PerformanceCounter(objectName, counterName, instanceName);
} }
public override void UpdateMovement() public string GetName()
{ {
float cpu = m_counter.NextValue()/40f; return Name;
Vector3 size = new Vector3(cpu, cpu, cpu); }
RootPart.Resize(size); public string GetFriendlyName()
{
return FriendlyName;
}
base.UpdateMovement(); public string GetFriendlyValue()
{
return m_getFriendlyValueAction(this);
} }
} }
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "LandFrameMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.MonitorLandTime; return m_scene.MonitorLandTime;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Land Frame Time"; return "Land Frame Time";
} }

View File

@ -41,12 +41,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "LastFrameTimeMonitor";
}
public double GetValue() public double GetValue()
{ {
return Environment.TickCount - m_scene.MonitorLastFrameTick; return Environment.TickCount - m_scene.MonitorLastFrameTick;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Last Completed Frame At"; return "Last Completed Frame At";
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "ObjectCountMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.SceneGraph.GetTotalObjectsCount(); return m_scene.SceneGraph.GetTotalObjectsCount();
} }
public string GetName() public string GetFriendlyName()
{ {
return "Total Objects Count"; return "Total Objects Count";
} }

View File

@ -33,12 +33,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
{ {
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "PWSMemoryMonitor";
}
public double GetValue() public double GetValue()
{ {
return System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64; return System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Private Working Set Memory"; return "Private Working Set Memory";
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "PhysicsFrameMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.MonitorPhysicsSyncTime + m_scene.MonitorPhysicsUpdateTime; return m_scene.MonitorPhysicsSyncTime + m_scene.MonitorPhysicsUpdateTime;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Total Physics Frame Time"; return "Total Physics Frame Time";
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "PhysicsUpdateFrameMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.MonitorPhysicsUpdateTime; return m_scene.MonitorPhysicsUpdateTime;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Physics Update Frame Time"; return "Physics Update Frame Time";
} }

View File

@ -32,12 +32,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
{ {
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "ThreadCountMonitor";
}
public double GetValue() public double GetValue()
{ {
return System.Diagnostics.Process.GetCurrentProcess().Threads.Count; return System.Diagnostics.Process.GetCurrentProcess().Threads.Count;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Total Threads"; return "Total Threads";
} }

View File

@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
#region Implementation of IMonitor #region Implementation of IMonitor
public string GetName()
{
return "TotalFrameMonitor";
}
public double GetValue() public double GetValue()
{ {
return m_scene.MonitorFrameTime; return m_scene.MonitorFrameTime;
} }
public string GetName() public string GetFriendlyName()
{ {
return "Total Frame Time"; return "Total Frame Time";
} }

View File

@ -37,6 +37,7 @@ using Nwc.XmlRpc;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications; using OpenSim.Framework.Communications;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;

View File

@ -40,6 +40,7 @@ using OpenMetaverse;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Capabilities; using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using Caps=OpenSim.Framework.Capabilities.Caps; using Caps=OpenSim.Framework.Capabilities.Caps;

View File

@ -396,9 +396,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{ {
result = OpenJPEG.EncodeFromImage(joint, true); result = OpenJPEG.EncodeFromImage(joint, true);
} }
catch (Exception) catch (Exception e)
{ {
m_log.Error("[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); m_log.ErrorFormat(
"[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
e.Message, e.StackTrace);
} }
return result; return result;

View File

@ -34,6 +34,7 @@ using log4net;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
@ -135,6 +136,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
{ {
IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
foreach (IScriptModule scriptModule in scriptModules)
{
scriptModule.OnScriptRemoved += ScriptRemoved;
scriptModule.OnObjectRemoved += ObjectRemoved;
}
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
@ -165,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
urlData.urlcode = urlcode; urlData.urlcode = urlcode;
urlData.requests = new Dictionary<UUID, RequestData>(); urlData.requests = new Dictionary<UUID, RequestData>();
m_UrlMap[url] = urlData; m_UrlMap[url] = urlData;
string uri = "/lslhttp/" + urlcode.ToString() + "/"; string uri = "/lslhttp/" + urlcode.ToString() + "/";
@ -280,6 +286,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public void ScriptRemoved(UUID itemID) public void ScriptRemoved(UUID itemID)
{ {
// m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID);
lock (m_UrlMap) lock (m_UrlMap)
{ {
List<string> removeURLs = new List<string>(); List<string> removeURLs = new List<string>();

View File

@ -338,10 +338,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{ {
imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
} }
catch (Exception) catch (Exception e)
{ {
m_log.Error( m_log.ErrorFormat(
"[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
e.Message, e.StackTrace);
} }
m_textureManager.ReturnData(id, imageJ2000); m_textureManager.ReturnData(id, imageJ2000);

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Server.Base; using OpenSim.Server.Base;
@ -59,9 +60,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory
{ {
m_log.Info("[INVENTORY IN CONNECTOR]: Inventory Service In Connector enabled"); m_log.Info("[INVENTORY IN CONNECTOR]: Inventory Service In Connector enabled");
} }
} }
} }
public void PostInitialise() public void PostInitialise()

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;

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