Compare commits

...

698 Commits

Author SHA1 Message Date
Diva Canto
5939529036 Minor typo in log message 2013-07-14 14:29:10 -07:00
Diva Canto
c8dcb8474d Let's go easy on authenticating ChildAgentUpdates, otherwise this will be chaotic while ppl are using different versions of opensim. Warning only, but no enforcement. 2013-07-14 10:26:05 -07:00
Diva Canto
98f59ffed5 Fix broken tests -- the test setup was wrong... sigh. 2013-07-14 09:22:55 -07:00
Diva Canto
c61ff917ef Authenticate ChildAgentUpdate too. 2013-07-14 09:21:28 -07:00
Diva Canto
f3b3e21dea Change the auth token to be the user's sessionid. 2013-07-14 07:28:40 -07:00
Diva Canto
fcb0349d56 And this fixes the other failing tests. Justin, the thread pool is not being initialized in the tests! 2013-07-13 23:01:41 -07:00
Diva Canto
e4f741f006 This should fix the failing test. 2013-07-13 22:52:51 -07:00
Diva Canto
a2ee887c6d Deleted a line too many 2013-07-13 22:32:52 -07:00
Diva Canto
b4f1b9acf6 Guard against unauthorized agent deletes. 2013-07-13 21:28:46 -07:00
Diva Canto
931eb892d9 Deleted GET agent all around. Not used. 2013-07-13 17:56:42 -07:00
Diva Canto
4d93870fe5 Gatekeeper: stop bogus agents earlier, here at the Gatekeeper. No need to bother the sim. 2013-07-13 17:52:05 -07:00
Diva Canto
5a1d6727e1 Some more debug to see how many threads are available. 2013-07-13 11:39:17 -07:00
Diva Canto
bc405a6a34 That didn't fix the problem.
Revert "Trying to reduce CPU usage on logins and TPs: trying radical elimination of all FireAndForgets throughout CompleteMovement. There were 4."

This reverts commit 6825377380.
2013-07-13 11:30:37 -07:00
Diva Canto
6825377380 Trying to reduce CPU usage on logins and TPs: trying radical elimination of all FireAndForgets throughout CompleteMovement. There were 4. 2013-07-13 11:11:18 -07:00
Diva Canto
3a26e366d2 This commit effectively reverses the previous one, but it's just to log that we found the root of the rez delay: the priority scheme BestAvatarResponsiveness, which is currently the default, was the culprit. Changing it to FrontBack made the region rez be a lot more natural.
BestAvatarResponsiveness introduces the region rez delay in cases where the region is full of avatars with lots of attachments, which is the case in CC load tests. In that case, the inworld prims are sent only after all avatar attachments are sent. Not recommended for regions with heavy avatar traffic!
2013-07-13 10:35:41 -07:00
Diva Canto
ff4ad60207 Same issue as previous commit. 2013-07-13 10:05:11 -07:00
Diva Canto
ccee2959f7 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-13 09:53:05 -07:00
Diva Canto
a412b1d682 Moved SendInitialDataToMe to earlier in CompleteMovement. Moved TriggerOnMakeRootAgent to the end of CompleteMovement.
Justin, if you read this, there's a long story here. Some time ago you placed SendInitialDataToMe at the very beginning of client creation (in LLUDPServer). That is problematic, as we discovered relatively recently: on TPs, as soon as the client starts getting data from child agents, it starts requesting resources back *from the simulator where its root agent is*. We found this to be the problem behind meshes missing on HG TPs (because the viewer was requesting the meshes of the receiving sim from the departing grid). But this affects much more than meshes and HG TPs. It may also explain cloud avatars after a local TP: baked textures are only stored in the simulator, so if a child agent receives a UUID of a baked texture in the destination sim and requests that texture from the departing sim where the root agent is, it will fail to get that texture.
Bottom line: we need to delay sending the new simulator data to the viewer until we are absolutely sure that the viewer knows that its main agent is in a new sim. Hence, moving it to CompleteMovement.
Now I am trying to tune the initial rez delay that we all experience in the CC. I think that when I fixed the issue described above, I may have moved SendInitialDataToMe to much later than it should be, so now I'm moving to earlier in CompleteMovement.
2013-07-13 09:46:58 -07:00
Diva Canto
cd64a70c79 Added UploadBakedTexture/UploadBakedTextureServerConnector, so that this can eventually be served by a robust instance. NOT FINISHED YET. 2013-07-13 08:31:03 -07:00
Justin Clark-Casey (justincc)
d06c85ea77 Reinsert PhysicsActor variable back into SOP.SubscribeForCollisionEvents() in order to avoid a race condition.
A separate PhysicsActor variable is used in case some other thread removes the PhysicsActor whilst this code is executing.
If this is now impossible please revert - just adding this now whilst I remember.
Also makes method comment into proper method doc.
2013-07-13 00:29:07 +01:00
Justin Clark-Casey (justincc)
b4cb644a05 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-13 00:03:23 +01:00
Justin Clark-Casey (justincc)
3d118fb580 In co-op termination, extend EventWaitHandle to give this an indefinite lifetime in order to avoid a later RemotingException if scripts are being loaded into their own domains.
This is necessary because XEngineScriptBase now retains a reference to an EventWaitHandle when co-op termination is active.
Aims to address http://opensimulator.org/mantis/view.php?id=6634
2013-07-13 00:02:54 +01:00
Robert Adams
fa02f28dbf Add ToOSDMap() overrides to the Stat subclass CounterStat.
Add a GetStatsAsOSDMap method to StatsManager which allows the filtered
fetching of stats for eventual returning over the internets.
2013-07-12 14:04:14 -07:00
Diva Canto
3d700bb42c Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-12 12:54:29 -07:00
Diva Canto
29f6ae199e Changed UploadBakedTextureModule so that it uses the same pattern as the others, in preparation for experiments to direct baked texture uploads to a robust instance. No functional or configuration changes -- should work exactly as before. 2013-07-12 12:53:58 -07:00
Robert Adams
65239b059f Enhance NullEstateData to remember stored estate values and return
them next time asked. This keeps any estate settings from being reset
when the estate dialog is opened in a region with null estate storage.
2013-07-11 20:55:32 -07:00
Robert Adams
1909ee70f8 Centralize duplicated code in SceneObjectPart for subscribing to
collision events. Improve logic for knowing when to add processing
routine to physics actor.
2013-07-11 16:57:07 -07:00
Diva Canto
83d1680057 Added a few more thingies to the asset client test to poke the threadpool. 2013-07-11 16:43:43 -07:00
Justin Clark-Casey (justincc)
ba8f9c9d0a Try naming the materials handlers again, this time registering the POST as RenderMaterials
This was probably the mistake.
The other handlers are named RenderMaterials as well but this actully has no affect apart from on stats, due to a (counterintuitive) disconnect between the registration name and the name  of the request handler.
Will be tested very soon and reverted if this still does not work.
2013-07-11 23:51:10 +01:00
Justin Clark-Casey (justincc)
7c2e4786ce minor: remove some regression test logging switches accidentally left uncommented. 2013-07-11 23:19:55 +01:00
Justin Clark-Casey (justincc)
e15a15688b minor: Take out unnecessary clumsy sleep at the end of regression Test404Response().
This wasn't actually necessary in the end but was accidentally left in.
2013-07-11 23:11:35 +01:00
Justin Clark-Casey (justincc)
f57f49eede Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-11 23:05:10 +01:00
Justin Clark-Casey (justincc)
44e9849ed1 Fix regression where llHTTPRequests which did not get an OK response returned 499 and the exception message in the http_response event rather than the actual response code and body.
This was a regression since commit 831e4c3 (Thu Apr 4 00:36:15 2013)
This commit also adds a regression test for this case, though this currently only works with Mono
This aims to address http://opensimulator.org/mantis/view.php?id=6704
2013-07-11 23:02:30 +01:00
Diva Canto
ee51a9f9c9 Added property to make for more flexible testing. 2013-07-11 14:23:37 -07:00
Diva Canto
51d106cff8 Added a test for the asset service 2013-07-11 14:21:57 -07:00
Diva Canto
c4f1ec1fd6 Changed the UserProfileModule so that it's less greedy in terms of thread usage. 2013-07-11 10:21:20 -07:00
Diva Canto
ea371a6f54 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-11 09:48:15 -07:00
Diva Canto
604967b31e Switched UUIDNameRequest and RegionHandleRequest to Sync, because now they are also non-blocking handlers. 2013-07-11 09:47:46 -07:00
Diva Canto
3b48b6a792 Switched TransferRequest (UDP packet handler) to sync. The permissions checks may block, so they get a FireAndForget. Everything else is non-blocking. 2013-07-11 09:44:48 -07:00
dahlia
0120e858b7 remove names from Capability handlers (added by justincc in commit 013710168b) as they seem to disable the use of multiple access methods for a single Capability in MaterialsDemoModule 2013-07-10 22:30:41 -07:00
Diva Canto
9173130fde Switched RegionHandshakeReply to Sync, because it's not doing anything blocking. 2013-07-10 20:48:13 -07:00
Diva Canto
fe5da43d15 EXPERIMENTAL: make RequestImage (UDP packet handler) sync instead of async. This _shouldn't_ screw things up, given that all this does is to dump the request in a queue. 2013-07-10 19:29:14 -07:00
Diva Canto
bdaeb02863 show client stats: Fixed the requests/min. Also changed the spelling of the command, not without the dash. 2013-07-10 17:14:20 -07:00
Diva Canto
864a86983e Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-10 16:10:04 -07:00
Diva Canto
1b265b213b Added show client-stats [first last] command to expose what viewers are requesting. 2013-07-10 16:09:45 -07:00
Robert Adams
59d19f038a Remove a null reference exception in SimianPresenceServiceConnector that
occurs when GetGridUserInfo cannot find the requested user info.
2013-07-10 08:55:54 -07:00
Robert Adams
38e6da5522 Comment out old inbound UDP throttling hack. This would cause the UDP
reception thread to sleep for 30ms if the number of available user worker
threads got low. It doesn't look like any of the UDP packet types are
marked async so this check is 1) unnecessary and 2) really crazy since
it stops up the reception thread under heavy load without any indication.
2013-07-09 18:34:24 -07:00
Robert Adams
bb6fb65392 Revert "minor: remove some mono compiler warnings in UserProfileModule"
Revert until we understand why all the calls to GetUserProfileServerURI were also
commented out.

This reverts commit 5f58b9b552.
2013-07-09 18:24:39 -07:00
Justin Clark-Casey (justincc)
cec8e6d0f7 If a sensor is in an attachment, avoid throwing an exception if the attachee is removed from the scene before we try to retrieve them. 2013-07-09 23:52:47 +01:00
Justin Clark-Casey (justincc)
095066b1ce Handle UUIDNameRequest UDP packet processing async instead of within the main inbound UDP processing loop, to avoid any chance that this is delaying the main udp in loop.
The potential impact of this should be lower now that these requests are being placed on a queue.
2013-07-09 23:39:29 +01:00
Diva Canto
d0dfb744b2 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-09 14:13:51 -07:00
Diva Canto
67e500383e Put guards on a bunch of exception-inducing code, as seen in logs from load test. 2013-07-09 14:12:52 -07:00
Robert Adams
2c761cef19 BulletSim: add parameter to optionally disable vehicle linear deflection.
Add parameter to not apply vehicle linear deflection Z forces if
vehicle is not colliding. This defaults to 'true' so vehicles will fall
even if there is some linear deflection to apply.
2013-07-09 09:37:42 -07:00
dahlia
065f8f56a2 remove some cruft and trigger a rebuild 2013-07-08 19:18:01 -07:00
dahlia
33eea62606 remove an invalid null UUID check which caused a warning 2013-07-08 17:12:39 -07:00
Robert Adams
fad4241e4e BulletSim: make all the different angularVerticalAttraction algorithms
selectable from configuration paramters.
Changed default algorithm to "1" from previous default as it seems to
handle Y axis correction a little better.
Add config file independent enablement of vehicle angular forces to
make debugging easier (independent testing of forces).
2013-07-08 16:24:31 -07:00
Justin Clark-Casey (justincc)
76b2b20f7e minor: remove mono compiler warnings from HGSuitcaseInventoryService 2013-07-09 00:06:22 +01:00
Justin Clark-Casey (justincc)
5f58b9b552 minor: remove some mono compiler warnings in UserProfileModule 2013-07-09 00:04:46 +01:00
Justin Clark-Casey (justincc)
83da14008f minor: remove some mono compiler warnings in new groups code 2013-07-08 23:57:05 +01:00
Justin Clark-Casey (justincc)
af9b17c545 minor: remove mono compiler warnings related to keyframe code 2013-07-08 23:52:40 +01:00
Justin Clark-Casey (justincc)
2025dd25f6 Add missing file BaseOutputStreamHandler.cs from recent commit e19defd 2013-07-08 23:50:40 +01:00
Justin Clark-Casey (justincc)
047ef9c2a5 minor: remove some mono compiler warnings in OdePlugin 2013-07-08 23:36:57 +01:00
Justin Clark-Casey (justincc)
eccec4f8f6 minor: remove now unused migration-hack bool from DAMap 2013-07-08 23:32:19 +01:00
Justin Clark-Casey (justincc)
8be59829d1 minor: Add back commented out logging message in Caps.RegisterHandler() that I accidentally removed. 2013-07-08 22:41:24 +01:00
Justin Clark-Casey (justincc)
013710168b For stat purposes, add names to capability request handlers where these were not set 2013-07-08 22:39:07 +01:00
Justin Clark-Casey (justincc)
dc54581700 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-08 22:19:37 +01:00
Diva Canto
b2d4b8b1da BaseHttpServer: if the handler sets the content length, don't override it. This happens in HEAD handlers. 2013-07-08 14:12:11 -07:00
Justin Clark-Casey (justincc)
c3db595944 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-08 22:07:27 +01:00
Justin Clark-Casey (justincc)
e19defde36 Add "show caps stats by user" and "show caps stats by cap" console commands to print various counts of capability invocation by user and by cap
This currently prints caps requests received and handled, so that overload of received compared to handled or deadlock can be detected.
This involves making BaseStreamHandler and BaseOutputStream record the ints, which means inheritors should subclass ProcessRequest() instead of Handle()
However, existing inheriting classes overriding Handle() will still work, albeit without stats recording.
"show caps" becomes "show caps list" to disambiguate between show caps commands
2013-07-08 22:03:07 +01:00
Justin Clark-Casey (justincc)
a38c2abae4 Make dictionary read/write locking consistent in CapabilitiesModule, rename two dictionary fields to standard m_ format 2013-07-08 18:07:04 +01:00
Diva Canto
c66a9a08e4 Placed a throttle on UserManagementModule for name lookups. Singularity apparently is flooding the sims with name requests. 2013-07-08 08:41:18 -07:00
Diva Canto
1e72e1b258 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-07 20:44:23 -07:00
Diva Canto
bbb9af363d Print out caller IP when unusual requests are received. 2013-07-07 20:43:42 -07:00
Vegaslon
bbc40fab62 BulletSim: Different Implementation of Angular Deflection for vehicles, Activates it again and fixes problem with fighting with vertical attractor removing wobble of forward axis. Comments on testing welcome, May require adjustments of this force or other forces after this commit, exact tweaking to come after testing on other hardware.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-07-07 06:18:50 -07:00
Robert Adams
6026759406 BulletSim: fix jumping up and down of linksets when center-of-mass
was enabled. Didn't effect the physical position but the viewer saw
the linkset jumping between its simulator center and its physical
center.
2013-07-07 05:47:41 -07:00
Robert Adams
70d24a654b BulletSim: rename position and orientation variables to remove the
inconsistant use of Raw* and _* conventions.
2013-07-07 05:46:24 -07:00
Diva Canto
1286677352 Try to normalize the creatorData of scene object parts with the trailing '/'. What a nightmare this '/' is! 2013-07-06 18:37:54 -07:00
Diva Canto
803e5498b0 A little more debug 2013-07-06 18:27:03 -07:00
Diva Canto
71e26555bd Revert "WARNING: BRUTE FORCE DEBUG AGAIN. AVOID USING THIS COMMIT"
This reverts commit 9b75d75724.
2013-07-06 18:16:27 -07:00
Diva Canto
391633c072 Some more fixes on strange behaviors of Unknown User, esp. related to large messy inventories and esp. related to kokua 2013-07-06 18:02:17 -07:00
Diva Canto
1dd3a0bc57 MORE DEBUG. DON"T USE THIS. 2013-07-06 17:29:19 -07:00
Diva Canto
9b75d75724 WARNING: BRUTE FORCE DEBUG AGAIN. AVOID USING THIS COMMIT 2013-07-06 16:51:14 -07:00
Diva Canto
93fd5e4036 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-06 15:18:29 -07:00
Diva Canto
b29a09ab8e Simina activity detector was too eager. Disabled it in case simian is not being used. 2013-07-06 15:17:55 -07:00
Robert Adams
d838f15d97 Add implementations for llSetVelocity and llSetAngularVelocity. 2013-07-06 09:53:30 -07:00
Robert Adams
a65cec3986 BulletSim: implementation of linkset center-of-mass.
Default off, for the moment, until more testing.
Add separate thread and center-of-mass flags to OpenSimDefaults.ini.
Clean up comments in OpenSimDefaults.ini.
2013-07-06 08:25:15 -07:00
Robert Adams
97698ae311 BulletSim: More tweaking on center-of-mass. Almost there. Changes have no effect if LinksetOffsetCenterOfMass=false (the default). 2013-07-06 08:25:15 -07:00
Robert Adams
03268d85c4 BulletSim: comments and non-functional changes working toward the center-of-gravity implementation. 2013-07-06 08:25:14 -07:00
Robert Adams
5f97c6f8f0 BulletSim: non-functional updates. Comments and formatting.
Update TODO list.
2013-07-06 08:25:13 -07:00
Diva Canto
c358d5d168 Changed a few bits in Inventory/Archiver/InventoryArchiveReadRequest.cs to be less dependent on a Scene. 2013-07-05 20:17:10 -07:00
Justin Clark-Casey (justincc)
2f6ee8aee2 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-06 00:55:35 +01:00
Justin Clark-Casey (justincc)
98de67d573 Fix mono warning in LLImageManagerTests 2013-07-06 00:55:14 +01:00
justincc
ccceb6d6d2 Fix windows build break fromrecent dd1f95 for real this time - put new dll reference in the wrong place 2013-07-06 00:52:54 +01:00
Justin Clark-Casey (justincc)
55ac8c83c7 Get InventoryWorkerThreads to update watchdog on processing requests 2013-07-06 00:34:22 +01:00
Justin Clark-Casey (justincc)
a44ad01492 Fix build break from recent commit dd15f95 on windows 2013-07-06 00:32:11 +01:00
Justin Clark-Casey (justincc)
67407024a2 Update thread watchdog on GridServiceRequestThread periodically and turn off alarming
Unfortunately, alarm can spuriously go off if the thread blocks for a long time on an empty queue.
2013-07-06 00:29:19 +01:00
Justin Clark-Casey (justincc)
5dbdd5f8b4 refactor: Make stats and sim status simpler by extending BaseStreamHandler like other handlers instead of implementing the IStreamedRequestHandler interface directly 2013-07-06 00:12:48 +01:00
Justin Clark-Casey (justincc)
dd15f95499 Add very basic regression test TestChildAgentSingleRegionCapabilities() which checks for addition and removal of capabilities on add/remove of child agent 2013-07-05 20:06:27 +01:00
Diva Canto
ca26583e6b Delete some verbose debug messages 2013-07-04 15:17:06 -07:00
Diva Canto
c4506cf4f3 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-04 14:51:55 -07:00
Diva Canto
8265a88c4a Throttle the viewer's requests for region handles. Apparently Kokua is requesting this for all landmarks in inventory. Not sure why. But this seems to be the root cause of the login freeze mentioned before. This commit adds a blocking queue / process thread pattern. 2013-07-04 14:51:18 -07:00
BlueWall
f2f33b7577 Some consistency fixes for the ini to stop parser breakage 2013-07-04 17:45:17 -04:00
Diva Canto
d80936bbbb Guard against completely unknown user UUIDs. 2013-07-04 14:07:25 -07:00
Diva Canto
da3aa44138 Debug the RegionHandle handler (same issue) 2013-07-04 13:27:53 -07:00
Diva Canto
33ddb6c246 Revert "WARNING: BRUTE FORCE DEBUG. AVOID USING THIS COMMIT."
This reverts commit c95a23863a.
2013-07-04 13:25:58 -07:00
Diva Canto
c95a23863a WARNING: BRUTE FORCE DEBUG. AVOID USING THIS COMMIT. 2013-07-04 13:13:52 -07:00
Diva Canto
38a04ff993 Revert "Same freeze issue, now checking if it's in estate"
This reverts commit ca380ec039.
2013-07-04 13:00:06 -07:00
Diva Canto
d997c49e47 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-04 12:45:34 -07:00
Diva Canto
ca380ec039 Same freeze issue, now checking if it's in estate 2013-07-04 12:41:45 -07:00
Justin Clark-Casey (justincc)
93ee515d9d Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-04 20:41:02 +01:00
Justin Clark-Casey (justincc)
fdafc2a16c With diva's permission, temporarily reinsert Unknown UserUMMAU3 to make sure that GUN7 failure has largely disappeared.
Unknown UserUMMAU3 insertion should definitely be removed down the line.
However, I would like a little more time to check the GUN* reduction first, since removing UMMAU3 will make these failures appear as GUN7 instead.
Also bumps GUN6 -> GUN7 and UMMAU2 -> UMMAU3
2013-07-04 20:39:16 +01:00
Diva Canto
bf214122cd More debug, same issue 2013-07-04 11:53:22 -07:00
Diva Canto
15d0bc0900 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-04 11:37:00 -07:00
Diva Canto
ec9ffbb89a More debug, same issue 2013-07-04 11:36:10 -07:00
Justin Clark-Casey (justincc)
c61becc62b Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-04 19:33:12 +01:00
Diva Canto
0cc0a2485c More debug related to the previous commit 2013-07-04 11:18:05 -07:00
Diva Canto
ae42c93f9a Now trying to find a cause of freeze at login related to friends status notifications. 2013-07-04 10:59:21 -07:00
Diva Canto
98a2fa8e35 HG Friends: this was commented some commits ago, but it shouldn't have been. 2013-07-04 10:23:20 -07:00
Diva Canto
068a3afad9 HG Friends: migration #3 is failing on some installations of MySql. Setting the table to InnoDB seems to fix the problem. 2013-07-04 09:51:31 -07:00
Justin Clark-Casey (justincc)
16f40c1a15 Add --default option to "debug lludp packet" command to allow packet logging to be performed immediately from client start 2013-07-04 17:29:53 +01:00
Diva Canto
5eb78aad96 Revert "HG Friends: debug an issue where the friends data stored in the DB is incomplete."
This reverts commit 27cdfb7b84.
2013-07-04 09:17:01 -07:00
Diva Canto
80f4a008eb Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-04 08:48:19 -07:00
Diva Canto
27cdfb7b84 HG Friends: debug an issue where the friends data stored in the DB is incomplete. 2013-07-04 08:47:45 -07:00
Justin Clark-Casey (justincc)
25889b2d7e change "debug packet" command to "debug lludp packet" to conform with other "debug lludp" options
also moves the implementing code into LLUDPServer.cs along with other debug commands from OpenSim.cs
gets all debug lludp commands to only activate for the set scene if not root
2013-07-04 00:02:53 +01:00
Diva Canto
119f84fe11 Squoosh one last opportunity for Unknown Users to creep in. 2013-07-02 17:03:04 -07:00
Diva Canto
06dba1fa62 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-07-02 16:47:17 -07:00
Diva Canto
4d24bf75fd Deleted debug messages. Fixed a null ref exception on the POST handler of GridUserServerPostHandler.cs 2013-07-02 16:46:35 -07:00
Justin Clark-Casey (justincc)
d01b8e163d minor: Correct typo of "Descrition" to "Description" in "show object *" console commands
Thanks to Ai Austin for pointing this out.
2013-07-03 00:27:22 +01:00
Diva Canto
316e8f9239 Fix SQL statement 2013-07-02 16:10:09 -07:00
Diva Canto
9725b829d5 Do the same for SQLite and MSSQL 2013-07-02 15:48:30 -07:00
Diva Canto
2c05caec7f Really make it call the method with the query interface 2013-07-02 15:47:02 -07:00
Diva Canto
626940ceb8 More debug messages 2013-07-02 15:39:10 -07:00
Diva Canto
e984bfb4c6 This should have a strong effect on the Unknown User issue mantis #6625 2013-07-02 14:31:39 -07:00
Diva Canto
ccca005969 HG: close a loophole by which if something was wrong with the ServiceURLs it resulted in never ending asset requests 2013-07-02 13:29:44 -07:00
Justin Clark-Casey (justincc)
635704b7ef Update debug unknown user name UserUMMTGUN3 to UserUMMTGUN4 and UserUMMAU -> UserUMMAU2 to track any new occurences.
This is to see the impact that Diva's fixes related to this issue (last one is currently commit c7383688)
You will need to clear your viewer cache for this to have any effect
Relates to http://opensimulator.org/mantis/view.php?id=6625
2013-07-01 23:54:04 +01:00
Robert Adams
8eb86c9ec9 BulletSim: add the reset of the last commit for flush log file problems.
Fix small typo in one log message.
2013-06-30 19:22:43 -07:00
Robert Adams
c24c99f4ba BulletSim: fix an occasional crash with flushing log files. 2013-06-30 19:08:15 -07:00
Robert Adams
9d5ae75950 BulletSim: remove the handle to the vehicle actor and cause routines
that need it to look it up.
2013-06-30 17:07:51 -07:00
Robert Adams
425d2a2a97 BulletSim: set linkset type to be prim specific rather than a simulator
wide default. This allows individual prims to differ in the
underlying linkset implementation.
2013-06-30 17:07:50 -07:00
Robert Adams
23516717e4 BulletSim: a better version of llMoveToTarget that doesn't go crazy.
There is still some overshoot but mostly fixes Mantis 6693.
Fix bug where moveToTarget was active for non-physical objects
and while selected.
Fix bug where move target was not getting changed if the script
changed the target during a move.
2013-06-30 17:07:49 -07:00
Robert Adams
2f4a729d40 BulletSim: add inTaintTime parameter to collision cache clear function. 2013-06-30 17:07:48 -07:00
Diva Canto
e377abcc35 Groups V2: charge for group creation only after the group has been successfully created 2013-06-30 08:39:35 -07:00
Diva Canto
c738368846 Revert "More debug mantis #6625"
This reverts commit 20f2cf8769.
2013-06-30 07:25:46 -07:00
Diva Canto
1e97972f78 Revert "One more debug mantis #6625"
This reverts commit 8fa5d12fcb.

Conflicts:
	OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
2013-06-30 07:25:13 -07:00
Diva Canto
d7775d1e11 Revert "A little more debug for the Unknown User problem mantis #6625"
This reverts commit ff47cf77ab.
2013-06-30 07:22:27 -07:00
Diva Canto
1fc873d09f Same fix to LocalInventoryServiceConnector.cs 2013-06-30 07:21:22 -07:00
Diva Canto
74e7fac13f More on mantis #6625 2013-06-29 22:32:26 -07:00
Diva Canto
20f2cf8769 More debug mantis #6625 2013-06-29 21:54:10 -07:00
Diva Canto
c462e0a51c Fixed previous debug message 2013-06-29 21:30:07 -07:00
Diva Canto
8fa5d12fcb One more debug mantis #6625 2013-06-29 21:26:58 -07:00
Diva Canto
0c97021565 More debug for mantis #6625. It looks like the home friends list is being fetched on HG TPs. 2013-06-29 21:05:45 -07:00
Diva Canto
ff47cf77ab A little more debug for the Unknown User problem mantis #6625 2013-06-29 19:15:25 -07:00
Diva Canto
00093a305d Changed HG status notifications timeout down to 15secs from the default 100. 2013-06-29 18:35:23 -07:00
Justin Clark-Casey (justincc)
3a634c56e3 Remove hack to migrate previous experimental-level os materials data.
This didn't seem to be working anyway and it's better not to have such hacks in the code for experimental stuff.
2013-06-29 00:23:41 +01:00
Justin Clark-Casey (justincc)
371085546d Add materials store null check into UuidGatherer code. 2013-06-28 23:57:41 +01:00
Justin Clark-Casey (justincc)
eed15703ed Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-28 23:35:44 +01:00
Justin Clark-Casey (justincc)
4406f07a84 Add IMG_BLOOM1.jp2 to standard asset set, which is used in stars.
This makes stars appear more realistically rather than as massive chunks due to the missing IMG_BLOOM1 asset from the viewer.
Thanks to YoshikoFazuku for supplying the star asset which I then uploaded via a viewer and extracted as JPEG2000.
Thanks also to Ai Austin for helping this process along.
See http://opensimulator.org/mantis/view.php?id=6691 for more details.
2013-06-28 23:34:16 +01:00
dahlia
4cb4c9fb25 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-28 14:03:46 -07:00
dahlia
cbb5122729 add some locking to materials storage dictionary 2013-06-28 14:00:28 -07:00
Justin Clark-Casey (justincc)
e26e8b8829 Remove "Asset deletion not supported by database" message from "delete asset" robust/standalone console command since it actually was implemented and performed.
Improve other associated messages.
2013-06-28 19:19:38 +01:00
Justin Clark-Casey (justincc)
dc0455e217 In XAssetService, on a delete asset request also delete the asset in any chained service.
This eliminates the async migration since it causes a race condition with the "delete asset" console command
2013-06-28 19:11:44 +01:00
Justin Clark-Casey (justincc)
f6ce87c96d Reinsert code for gathering uuids reference by materials back directly into UuidGatherer for now.
This cannot be triggered as an event from Scene.EventManager since some invocations of UuidGatherer (e.g. IAR saving) use scene objects which are not in scenes.
There needs to be some way for modules to register for events which are not connected with a particular scene.
2013-06-28 18:50:33 +01:00
dahlia
529633d970 add method docs for DAMap.GetStore() and DAMap.SetStore() 2013-06-27 18:44:27 -07:00
dahlia
d47fc48b32 and yet another check for null returned from DynAttrs.GetStore() 2013-06-27 18:01:17 -07:00
dahlia
c1b8f83dd4 test for null return from DynAttrs.GetStore() 2013-06-27 17:53:15 -07:00
Justin Clark-Casey (justincc)
149487ea0f refactor: Move code for gathering textures referenced by materials into MaterialsDemoModule from UuidGatherer
This code is now triggered via EventManager.OnGatherUuids which modules can subscribe to.
2013-06-27 23:42:35 +01:00
Justin Clark-Casey (justincc)
f7d09b898a Make the concept of namespaces explicit in dynamic attributes
This is in order to reduce the likelihood of naming clashes, make it easier to filter in/out attributes, ensure uniformity, etc.
All dynattrs in the opensim distro itself or likely future ones should be in the "OpenSim" namespace.
This does alter the underlying dynattrs data structure.  All data in previous structures may not be available, though old structures should not cause errors.
This is done without notice since this feature has been explicitly labelled as experimental, subject to change and has not been in a release.
However, existing materials data is being preserved by moving it to the "Materials" store in the "OpenSim" namespace.
2013-06-27 23:14:28 +01:00
Justin Clark-Casey (justincc)
f78d2ef166 Update temporary "Unknown UserUMMTGUN2" name to "Unknown UserUMMTGUN3" to see if Diva's recent HG updates (post 6c7e33f) fix this issue.
This string is returned if a UserManagementModule.TryGetUserNames() cannot find a server-side name binding or a user account for a given UUID.
This is only called when the viewer requests a binding via the UDP UUIDNameRequest message
2013-06-25 00:46:15 +01:00
Justin Clark-Casey (justincc)
ce9b1320d2 Improve situation where editing just the root prim of an attachment causes other prims to be set to very far off positions on reattach.
Functionally the same as the patch by tglion in http://opensimulator.org/mantis/view.php?id=5334
However, not yet perfect - after editing just root prim on reattach the position is still wrong, though other prims are not set to far off positions.
2013-06-25 00:41:46 +01:00
Justin Clark-Casey (justincc)
4b00203fa5 Tidy up SOG.UpdateRootPosition() to eliminate unnecessary copying of Vector3 structs 2013-06-25 00:15:55 +01:00
Melanie
936700bda3 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-06-23 01:49:45 +01:00
Melanie
4bf1afe300 Fix prim locking to behave like SL 2013-06-23 01:34:35 +01:00
Diva Canto
edb11a7eca Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-22 08:29:54 -07:00
Diva Canto
6c7e33fe47 Change IsLocalRegion from using region handle to using regionID. This was affecting UpdateAgent and CloseAgent in cases where the foreign region is on the same coordinates as *some* local region. 2013-06-22 08:29:06 -07:00
Diva Canto
ca3ce6da73 HG: avoid call on localhost between sim and UAS for standalone. 2013-06-22 08:26:59 -07:00
Diva Canto
4778d67005 Finally moved HG agent transfers to use agent fatpacks. 2013-06-21 20:52:46 -07:00
Robert Adams
74539659f6 BulletSim: move new linear deflection code to own routine.
Remove VehicleForwardVelocity changed storage since the value
will be modified as movement is processed.
2013-06-21 10:46:21 -07:00
Vegaslon
a5de4f692b BulletSim: Implementation of Linear Deflection, it is a partial help for the vehicle tuning diffrence between Opensim and Second life.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-06-20 19:02:15 -07:00
Robert Adams
bbeff4b8ca BulletSim: rework velocity updating when not colliding and not flying
to prevent infinite jumps. Now jumps last only AvatarJumpFrames long
(default 4) which is about as high as in SL.
TODO: jumping should only depend on standing (collision with feet)
rather than collision anywhere on the avatar.
2013-06-20 09:55:40 -07:00
Justin Clark-Casey (justincc)
a33b6eed6d minor: remove mono compiler warnings in WebsocketServerHandler.cs 2013-06-20 00:54:19 +01:00
Justin Clark-Casey (justincc)
085a87060a Change "ObjectMemory" stat to "HeapMemory" to align with other stat names. Also round this and ProcessMemory to three decimal places in common with other memory stats.
I believe leaving out such minor info makes stats easier to read
2013-06-20 00:52:39 +01:00
Justin Clark-Casey (justincc)
05790ba1cf Allow more than one stat category to be specified in "show stats"
e.g. "show stats httpserver.9000 server.network"
2013-06-20 00:45:56 +01:00
Justin Clark-Casey (justincc)
5b1a9f84fd minor: Change "memory churn" terminology in statistics to "heap allocation rate" since this is more generally meaningful 2013-06-20 00:32:12 +01:00
Justin Clark-Casey (justincc)
d97333255d Fix minor bug where the check whether to display SmartThreadPool stats was accidentally != null rather than == FireAndForgetMethod.SmartThreadPool
Due to another check this had no practical effect
2013-06-20 00:22:44 +01:00
Justin Clark-Casey (justincc)
3370e19205 minor: fix mono compiler warning in FetchInventory2Handler 2013-06-20 00:17:20 +01:00
Justin Clark-Casey (justincc)
086fd70a5f Make it possible to specify display of stats in a particular 'container' by separating category and container with a period.
e.g. "show stats server.network"
I failed to realize this had already been implemented without the period in the show stats command (as the command help had not been updated).
However, I would prefer the . approach as it will allow specifying multiple stats, easier wildcarding, etc.
This commit also prevents any stat from having a period in its short name.
2013-06-20 00:00:39 +01:00
Justin Clark-Casey (justincc)
84af1cab9b Display existing statistic of how many http requests a server is making as server.network.HTTPRequestsMade in "show stats all" 2013-06-19 20:48:12 +01:00
Talun
8a86e29579 Mantis 6608: Math error in parcel dimensions/borders seen with land show command
This patch changes the land show console command to return numbers in the
range 4 to 256 for the "to" coordinates instead of 0 to 252

Also trailing spaces removed from some lines.
2013-06-19 00:26:23 +01:00
Justin Clark-Casey (justincc)
1a72f62d7b minor: remove mono compiler warning in OfflineIMService 2013-06-18 23:52:15 +01:00
Kevin Cozens
3fe5e9057f Prevent an exception if no offline messages were retrieved. 2013-06-18 23:15:38 +01:00
Justin Clark-Casey (justincc)
dda44e31e3 minor: tidy up spacing if display a unit for additional stat information 2013-06-18 23:10:50 +01:00
Justin Clark-Casey (justincc)
9501a583cb Make number of inbound http requests handled available as a httpserver.<port>.IncomingHTTPRequestsProcessed stat 2013-06-18 23:07:18 +01:00
Justin Clark-Casey (justincc)
768e8e363b Fix issue where stat samples were accidentally static, so that any additional stat with sampling would produce wrong results 2013-06-18 22:49:49 +01:00
Justin Clark-Casey (justincc)
0767523834 Fix other places when saving scripts or notecards in prim inventories where messages should be transient without an OK button 2013-06-18 21:21:59 +01:00
Justin Clark-Casey (justincc)
a1e32b8437 If SmartThreadPool is active, display statistical information about it in "show stats server"
Also puts these and previous builtin threadpool stats in the "threadpool" stat container rather than "processor"
2013-06-18 00:10:21 +01:00
Justin Clark-Casey (justincc)
b7c9dee033 refactor: Move existing code to generate report information on the threadpool to the ServerBase rather than being in Util 2013-06-17 23:57:10 +01:00
Justin Clark-Casey (justincc)
c0a00cd7fd Fix bug where no threadpool data would be displayed in the "show threads" command if threadpool type was QueueUserWorkItem (Unsafe worked as expected) 2013-06-17 23:34:09 +01:00
Justin Clark-Casey (justincc)
713a14a6b5 minor: remove mono compiler warnings in WebFetchInvDescModule 2013-06-17 23:23:56 +01:00
Justin Clark-Casey (justincc)
b9dac1f8df Fix test failure in BasicCircuitTests from previous commit 0d2fd0d9 2013-06-17 23:17:55 +01:00
Justin Clark-Casey (justincc)
865d46ae1e Drop server level stats to debug instead of info.
This was the original intention with these stats, as I didn't believe they would be useful to ordinary users if everything is working as it should.
Please amend if this is an issue.
Just for now, levels actually have no impact on what is displayed via the "show stats" command.
2013-06-17 22:57:47 +01:00
Justin Clark-Casey (justincc)
2c9bb0f973 Add server stats for available builtin threadpool and iocp workers 2013-06-17 22:55:25 +01:00
Justin Clark-Casey (justincc)
0d2fd0d914 Make general server stats available on the robust console as well as the simulator console
This means the "show stats" command is now active on the robust console.
2013-06-17 22:39:00 +01:00
dahlia
694c4bcbb6 correct method doc for llRot2Axis() 2013-06-14 20:00:20 -07:00
Justin Clark-Casey (justincc)
e6cb7b4764 Lock m_classifiedCache and m_classifiedInterest dictionary reads in UserProfileModule since in the presence of writes these are not thread-safe operations.
Simplified locking to m_classifiedCache only since r/w of both dictionaries always occurs together
2013-06-15 00:52:57 +01:00
Justin Clark-Casey (justincc)
42b0c68eab Correct build break in previous commit 9c530d7 2013-06-15 00:46:55 +01:00
Justin Clark-Casey (justincc)
9c530d725f refactor: In UserProfileModule, change classifiedCache and classifiedInterest to m_classifiedCache and m_classifiedInterest
This is the coding standard name style for private fields.
2013-06-15 00:41:02 +01:00
Justin Clark-Casey (justincc)
ecfc6a3f4a Add the standard OpenSimulator copyright notice to the top of InventoryCache.cs 2013-06-15 00:36:16 +01:00
Justin Clark-Casey (justincc)
720806b661 Adjust the locking on InventoryCache. Locking for r/w of the ExpiringCache isn't needed since it's thread safe but r/w of contained dictionaries isn't thread-safe 2013-06-15 00:34:45 +01:00
Justin Clark-Casey (justincc)
da3724a904 minor: remove mono compiler warnings from LSL_Api, properly format method doc for llRot2Axis() 2013-06-15 00:11:36 +01:00
Talun
f074739e33 Mantis 6280: llSetContentType(). An implementation.
An implimentation of llSetContentType including all of the new
constants added since the mantis was raised.
2013-06-15 00:06:03 +01:00
Talun
fc89bde044 Mantis 6108: ossetprimitiveparams temporary/phantom problem
Corrected to ensure that the target prim is updated by
osSetPrimitiveParams when setting PRIM_TEMP_ON_REZ and/or PRIM_PHANTOM
instead of the prim that the script is in.
2013-06-15 00:00:00 +01:00
Justin Clark-Casey (justincc)
db9d9d83eb Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-14 23:58:16 +01:00
Justin Clark-Casey (justincc)
d412c1b0eb Don't try to abort worker threads in WebFetchInvDescModule if module was not enabled.
This also moves the abort to RemoveRegion() rather than a destructor.
2013-06-14 23:53:20 +01:00
BlueWall
d7f3d7efd2 Merge branch 'master' of /home/opensim/src/opensim 2013-06-13 09:27:13 -04:00
BlueWall
b2c8d5eec7 Add Option: ClassifiedFee
Add option to set minimum fee for publishing classifieds. Many viewers have a
  hard coded minimum of 50, which makes publishing classifieds fail where grids
  have no economy. This allows the grid to set the minimum fee to a suitable
  value for their operation.

  The option is located in the [LoginService] section and defaults to 0. The
  value is sent as "classified_fee" in the login response.
2013-06-13 09:18:27 -04:00
Diva Canto
b271217084 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-12 17:48:48 -07:00
Diva Canto
7c00ccb548 DataSnapshot: changed those annoying messages to Debug instead of Info. 2013-06-12 17:48:20 -07:00
Justin Clark-Casey (justincc)
6b8e94864a Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-13 00:33:53 +01:00
Justin Clark-Casey (justincc)
7759b05dcb Make XInventoryServicesConnector properly handle a RESULT = false return for methods where this contains failure rather than throwing an exception.
Result = False is generated for methods such as GetFolderForType() when the other end wants to signal a failure of the operation in methods such as GetFolderForType()
2013-06-13 00:31:32 +01:00
teravus
3357300362 * This fixes having to select and deselect prim to get keyframemotion to start running when pulled from data storage. 2013-06-12 18:13:00 -05:00
Justin Clark-Casey (justincc)
824a4b4808 After calls to GetSuitcaseXFolder() in HGSuitcaseInventoryService, consistently check for null return and log warning rather than throw exception.
This was being done already in some places.
If an exception is thrown it is now an error rather than debug
2013-06-12 23:47:47 +01:00
Justin Clark-Casey (justincc)
ef5be42c86 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-12 23:32:51 +01:00
Justin Clark-Casey (justincc)
47b6e78790 Implement logging of first 80 characters (debug level 5) or full body data (debug level 6) on outgoing requests, depending on debug level
This is set via "debug http out <level>"
This matches the existing debug level behaviours for logging incoming http data
2013-06-12 21:34:20 +01:00
BlueWall
7a17c3720b Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-11 21:47:39 -04:00
BlueWall
9fec0faade Revert "Add option to set minimum fee for classified ads"
This reverts commit 90097de6c3.
2013-06-11 21:46:40 -04:00
Robert Adams
3cb65f0d31 BulletSim: when meshing or asset fetching fails, include position
and region with the offending object's name in the error message.
2013-06-11 17:58:08 -07:00
BlueWall
9f8a8f3719 Merge working repo 2013-06-11 20:38:54 -04:00
BlueWall
90097de6c3 Add option to set minimum fee for classified ads
Upcoming phoenix-firestorm (4.4.1) adds a configurable option for setting
  the minimum price for publishing a classified ad.

  http://hg.phoenixviewer.com/phoenix-firestorm-lgpl/rev/43415d69b048
2013-06-11 20:35:25 -04:00
Robert Adams
7556a0f699 Add TriggerScenePresenceUpdated events when an animation is added
or removed. Shouldn't impact anyone as only DSG seems to use
OnScenePresenceUpdated event.
Some minor format changes to AnimationSet's ToString().
2013-06-11 17:18:12 -07:00
Justin Clark-Casey (justincc)
135e10ba09 Uncomment Mic's code and split to create new regression TestAddTemporaryAsset() and TestAddTemporaryLocalAsset() 2013-06-11 23:55:45 +01:00
Diva Canto
d8da83b4ff Removed the lock entirely 2013-06-11 15:50:12 -07:00
Diva Canto
a0fed03e10 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-11 15:36:52 -07:00
Diva Canto
b33db917f5 Really bad idea to lock m_UserCache for so long in UserManagementModule. Added a special lock object instead, if we really want to avoid concurrent executions of that code. 2013-06-11 15:36:27 -07:00
Melanie
26b66c730e Put the "script saved" and "notecard saved" messages back into the bottom
right corner.
2013-06-11 21:03:16 +01:00
teravus
d47a18fd09 * Adds KeyFrameMotion storage support to SQLite, just a note, seems that there's still something wrong with keyframed motion starting when the sim starts up, you have to 'select' and 'deselect' the prim again to get it to appear to move. Not sure what this is but maybe melanie_t can comment on this.
* Has a prim table migration..     that might take a while, hold on to your hats.
* Fixes a null-ref when shutting down while keyframed motion is active.
2013-06-11 08:56:20 -05:00
dahlia
ed950e6c74 Adjust output of llRot2Axis and llRot2Angle to match domains SL(tm) uses. Addresses Mantis #0006671 2013-06-11 00:29:40 -07:00
dahlia
ba84074468 LSL_Rotation.Normalize() now returns 0,0,0,1 for x,y,z,s when normalization fails 2013-06-10 17:54:14 -07:00
dahlia
9d9b9d4938 llRot2Angle now checks absolute value of s rotation component before normalizing 2013-06-10 17:11:49 -07:00
dahlia
b242ead6df llRot2Axis now checks absolute value of s rotation component before normalizing. Also removed some excessive division and cleaned up a bit 2013-06-10 17:10:04 -07:00
teravus
1c7fbb86c2 Check For NaN and Infinity in llRot2Axis/Angle Fixes mantis #6669 2013-06-10 18:47:08 -05:00
dahlia
a949556c4e add a Normalize() method for LSL_Rotation 2013-06-10 16:42:49 -07:00
Justin Clark-Casey (justincc)
7af97f88b7 Add port numbers to poll service thread names so that we can tell which belong to which HttpServer 2013-06-10 23:39:17 +01:00
Justin Clark-Casey (justincc)
32d1e50565 Reinstate explicit starting and stopping of PollServiceRequestManager added in 3eee991 but removed in 7c0bfca
Do not rely on destructors to stop things.
These fire at unpredictable times and cause problems such as http://opensimulator.org/mantis/view.php?id=6503
and most probably http://opensimulator.org/mantis/view.php?id=6668
2013-06-10 23:30:35 +01:00
Mic Bowman
a2f1cd87f8 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-10 15:15:38 -07:00
Mic Bowman
82e3b9a6e0 Fix test for adding temporary assets. Code for non-local temporary assets
is there but commented out.
2013-06-10 15:14:55 -07:00
Robert Adams
795acaa6aa BulletSim: add failure flag for meshing failure vs asset fetch failure
so error messages make more sense.
Change some BulletSim status log messages from WARN to INFO.
Update TODO list.
2013-06-10 14:12:45 -07:00
Mic Bowman
57141e34bf Remove Temporary from use to shortcut asset stores. The Local property
differentiates between local & grid storage. The Temporary property just
says that which service handles the it, the asset can be safely removed
in the future.
2013-06-10 13:26:19 -07:00
Talun
7de0912a97 Mantis 5346: llAxisAngle2Rot() should normalize before computing
Corrected to agree with
http://wiki.secondlife.com/wiki/Llaxisangle2rot#Deep_Notes
to normalise the vector before computing the quaternion

Signed-off-by: dahlia <dahlia@nomail>
2013-06-10 04:13:34 -07:00
Diva Canto
e741e5ebce More on mantis #6666 -- Groups V2 remote connector. 2013-06-09 20:20:37 -07:00
Diva Canto
4e2e69bd25 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-08 11:01:20 -07:00
Diva Canto
d00770d56b Groups V2 -- fix mantis #6666 2013-06-08 11:00:22 -07:00
BlueWall
75e4af9d39 Catch exception triggered by incoming avatars using legacy profiles 2013-06-08 11:00:05 -04:00
BlueWall
34d40e46a5 Merge branch 'profiles'
message to explain why this merge is necessary,
2013-06-07 20:17:45 -04:00
BlueWall
1cb1245d84 SQLite support for UserProfiles 2013-06-07 20:14:39 -04:00
BlueWall
1387224821 Ensure selected module is the only active one 2013-06-07 20:09:10 -04:00
Diva Canto
6aa54a8e16 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-07 16:01:07 -07:00
Diva Canto
07cc16ff9c Put the configuration back in FetchInventoryDesc2 cap. 2013-06-07 16:00:32 -07:00
Melanie
3a722ef81b Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-06-07 23:59:02 +01:00
Melanie
75631e0267 Supply proper type information for the various types of requests 2013-06-07 23:55:03 +01:00
Melanie
7c0bfca7a0 Adding Avination's PollService to round out the HTTP inventory changes 2013-06-07 23:43:45 +01:00
Justin Clark-Casey (justincc)
454499ff60 minor: Comment out debug logging (at warn level) about number of objects force selected and turn down to debug level 2013-06-07 23:38:23 +01:00
Justin Clark-Casey (justincc)
346eda27cc minor: add dr0berts to contributors list 2013-06-07 19:26:09 +01:00
Justin Clark-Casey (justincc)
f2a4d9b99c Fix regression where multiple close agents could be sent to the wrong neighbour region on root agent close.
This was introduced in git master d214e2d0 (Thu May 16 17:12:02 2013)
Caught out by the fact that value types used in iterators act like references and this was dispatched asynchronously.
Should address http://opensimulator.org/mantis/view.php?id=6658
2013-06-07 19:13:24 +01:00
Justin Clark-Casey (justincc)
a74e65200c Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-07 19:12:55 +01:00
Donnie Roberts
045c26f626 In LocalFriendshipTerminated, send the original client's agentId to the friend being removed instead of the friend's own id. 2013-06-07 18:43:00 +01:00
Diva Canto
664c6191ed Mantis #6620 (removed debug message) 2013-06-07 08:37:18 -07:00
Melanie
ac9c37f31b Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-06-06 23:49:34 +01:00
Melanie
06012f8675 Fix keyframe motion copyright 2013-06-06 23:49:02 +01:00
Diva Canto
25fa647a74 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-05 20:20:22 -07:00
Diva Canto
2ebf70d719 Strengthen some assumptions. 2013-06-05 20:19:59 -07:00
Melanie
a3210d1cf8 Database persistence for keyframes. Contains a Migration. 2013-06-06 03:17:38 +01:00
Melanie
81ad9255b5 Hook up Keyframe motion to almost everything. Failing to cross a sim border
may yield unexpected results in some cases. No database persistence yet,
2013-06-06 03:03:05 +01:00
Melanie
e1d98c9e4c Committing Avination's Keyframe module. This is not hooked up yet and will do nothing. More commits to follow. 2013-06-06 02:25:19 +01:00
BlueWall
26cd59cd6f Merge branch 'master' of /home/opensim/var/repo/opensim 2013-06-05 18:55:42 -04:00
Melanie
e53b62304f Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-06-05 23:44:26 +01:00
Melanie
a7dbafb0e3 Port Avination's inventory send throttling 2013-06-05 23:42:50 +01:00
BlueWall
e449950030 Prevent processing for Npc 2013-06-05 18:42:15 -04:00
BlueWall
cd64da8746 Cleanup 2013-06-05 18:41:55 -04:00
Justin Clark-Casey (justincc)
47ffa12078 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-06-05 22:26:42 +01:00
Justin Clark-Casey (justincc)
f41fc4eb25 Avoid a deadlock where a script can attempt to take a ScriptInstance.m_Scripts lock then a lock on SP.m_attachments whilst SP.MakeRootAgent() attempts to take in the opposite order.
This is because scripts (at least on XEngine) start unsuspended - deceptively the ResumeScripts() calls in various places in the code are actually completely redundant (and useless).
The solution chosen here is to use a copy of the SP attachments and not have the list locked whilst creating the scripts when an avatar enters the region.
This looks to address http://opensimulator.org/mantis/view.php?id=6557
2013-06-05 22:20:48 +01:00
BlueWall
10572b78f8 Remove a couple of orphaned lines 2013-06-05 15:10:53 -04:00
BlueWall
b4f472c4fa Make locking more uniform 2013-06-05 15:08:25 -04:00
Robert Adams
b5d0ac4c42 BulletSim: default PhysicsTimeStep to same as the simulator's
heartbeat timestep when running the physics engine on a separate
thread. This reduces the occurance of heartbeats that happen when
there is no physics step which is seen as vehicle jerkyness.
2013-06-05 07:12:14 -07:00
Robert Adams
0c971d148c BulletSim: fix corner case when rebuilding a compound linkset while
a mesh/hull while a mesh or hull is being rebuilt when its asset
is fetched. This fixes a 'pure virtual function' crash when changing
physical state of complex linksets that include many meshes.
2013-06-05 07:09:43 -07:00
Diva Canto
43d804b998 New HttpServer_OpenSim.dll with increased limits on number of connections, requests, etc. 2013-06-04 12:27:22 -07:00
Robert Adams
07058b044b BulletSim: experimental movement of physics execution off of heartbeat
thread. Off by default until more testing.

Setting "[BulletSim]UseSeparatePhysicsThread=true" causes the physics
engine to be called on its own thread and the heartbeat thread only
handles the reporting of property updates and collisions. Physics frame
rate is about right but physics execution time goes to zero as accounted
by the heartbeat loop.
2013-06-01 14:52:44 -07:00
BlueWall
d7fa9f671e Adding standard OpenSim header to source files 2013-05-31 22:03:27 -04:00
BlueWall
ba2f13db63 Adding back the BasicProfileModule 2013-05-31 21:19:15 -04:00
Justin Clark-Casey (justincc)
217c7d1140 Remove unnecessary m_scenes and m_scene from AsyncCommandManager.
These were private and the sole point of use (to know when to load config for the first time) can be done by looking at script engines instead.
2013-05-31 23:00:10 +01:00
Justin Clark-Casey (justincc)
921ad8704e Lock areas of AsyncCommandManager where multiple threads could try to access/update the same static structures simultaneously.
This is possible where there is more than one scene (multiple copies of the same script engine) and/or more than one script engine being used.
These operations are not thread safe and could be leading to the exceptions/problems seen in http://opensimulator.org/mantis/view.php?id=6651
This also prevents a small race condition where more than one AsyncLSLCmdHandlerThread could be started.
2013-05-31 22:50:15 +01:00
Justin Clark-Casey (justincc)
00c1586ff8 refactor: Remove unused AsyncCommandManager.PleaseShutdown 2013-05-31 18:12:36 +01:00
BlueWall
bf03523323 Fill in fields with default values on profile creation 2013-05-31 10:40:47 -04:00
BlueWall
5b3a443125 Trigger Jenkins build 2013-05-30 22:52:17 -04:00
Robert Adams
924a5df25f Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-30 19:20:36 -07:00
BlueWall
e85c70223a Merge branch 'work' contains UserProfiles with Robust service and updates region module using JsonRpc messaging. Requres no databse changes (but backup existing data before use). 2013-05-30 22:16:42 -04:00
Robert Adams
4d32ca19bf Trigger OnScenePresenceUpdated when the avatar's animations change. 2013-05-30 19:16:36 -07:00
Robert Adams
48a175eff7 Add methods to Animation and AnimationSet for easier manipulation and
display of groups of animations (Equal(), ToString(), FromOSDArray(), ...).
No functional change to animations.
2013-05-30 19:16:34 -07:00
Robert Adams
439f11cc3c Add region heartbeat start event to complement heartbeat end event.
This allows object modification before the usual heartbeat operation.
2013-05-30 19:16:31 -07:00
Robert Adams
3aa2fb9928 BulletSim: remove unuseful BulletSim parameters from OpenSimDefaults.ini and
replace with things someone might actually want to tune (avatar height, ...).
2013-05-30 19:16:29 -07:00
Justin Clark-Casey (justincc)
46335b103e If an exception occurs in the AsyncCommandManager loop, spit it out to log rather than silently swallowing it.
This might help diagnose the cause of http://opensimulator.org/mantis/view.php?id=6651 where sometimes scripts fail to start on region start.
2013-05-30 23:51:35 +01:00
BlueWall
328883700a UserProfiles
UserProfiles for Robust and Standalone. Includes service and connectors for Robust and standalone opensim plus matching region module.
2013-05-30 17:59:18 -04:00
Justin Clark-Casey (justincc)
6b88a665d3 minor: fix warnings in GodsModule that were due to duplicate using statements 2013-05-30 22:43:52 +01:00
Justin Clark-Casey (justincc)
12a3b85561 Fix passing of voice distance attenuation to the Vivox voice server.
Because of a typo, this wasn't being done at all - now the 'default' value as described in OpenSimDefaults.ini of 10m is passed (vivox_channel_clamping_distance)
Thanks to Ai Austin for spotting this.
2013-05-30 22:20:02 +01:00
Justin Clark-Casey (justincc)
8f9a726465 If on a sit request we sit the avatar on a different prim in a linkset for some reason (e.g. because it has a sit target), then send the actual sit prim UUID to the viewer rather than the requested one.
This purports to fix the issue described in http://opensimulator.org/mantis/view.php?id=6653 where the camera can end up following the requested sit prim rather than the actual.
The original spot was by Vegaslon, this commit just goes about it in a slightly different way
This commit also makes m_requestedSitTargetUUID to be the actual UUID, which is consistent with m_requestedSitTargetID which was already doing this.
However, this adjustment has no practical effect since we only currently need to know that there's any requested sit UUID at all, not which one it is.
2013-05-30 19:27:20 +01:00
Justin Clark-Casey (justincc)
cc7aa88b26 Try caching the user name for a new agent earlier on in the process of establishing a connection, to see if this helps with "Unknown UserUMMTGUN" issues.
The UMMTGUN form of Unknown User seems to appear because a viewer sometimes sends a UUIDNameRequest UDP request that fails to find a binding.
However, in theory the incoming agent should have made that binding before any such request is triggered.
So moving this binding to an earlier point in the process to see if this makes a difference.
Unknown user name is also updated to UserUMMTGUN2 - if you see the old name then you need to clear your viewer cache.
This relates to http://opensimulator.org/mantis/view.php?id=6625
2013-05-29 23:08:54 +01:00
Justin Clark-Casey (justincc)
f9ee9efb97 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-29 22:40:51 +01:00
Justin Clark-Casey (justincc)
4898f18f89 Add HG regression TestCachedUserNameForNewAgent() 2013-05-29 21:28:38 +01:00
Diva Canto
233b9ec4d7 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-28 20:59:54 -07:00
Diva Canto
7e1c7f54c7 First change in Vivox for ages! -- added a lock to serialize calls to vivox servers. This may ameliorate things when lots of avies arrive in a sim at about the same time. Turns out that there are 4 http requests per avie to Vivox. 2013-05-28 20:59:25 -07:00
Robert Adams
ae0d6ab28a BulletSim: don't zero motion when changing vehicle type.
Some vehicle scripts change type on the fly as an easy way of setting
all the parameters (like a plane changing to a car when on the ground).
2013-05-28 09:19:08 -07:00
Robert Adams
7c3a46ccea BulletSim: default using mesh asset hulls to 'true'. This means that,
if the mesh asset specifies physics hulls, BulletSim will fetch and
use same rather than approximating the hulls. If physics hulls are not
specified, the representation will fall back to the regular physics mesh.
2013-05-27 14:38:59 -07:00
Robert Adams
0c35d28933 BulletSim: enable GImpact shape for prims with cuts. Include DLLs and SOs
which recompute GImpact shape bounding box after creation as Bullet
doesn't do that itself (something it does for nearly every other shape).

Now, physical prims without cuts become single mesh convex meshes. Physical
prims with cuts become GImpact meshes. Meshes become a set of convex
hulls approximated from the mesh unless the hulls are specified in the
mesh asset data. The use of GImpact shapes should make some mechanical
physics more stable.
2013-05-26 17:35:12 -07:00
Melanie
533bbf033d Update the money framework to allow sending the new style linden "serverside is now viewerside" messages regarding currency
This will require all money modules to be refactored!
2013-05-25 02:08:54 +01:00
Robert Adams
1821372634 Meshmerizer: remember to add the copied hull verts to the list of hulls. 2013-05-24 16:32:19 -07:00
Robert Adams
5f1f5ea5ab BulletSim: add VehicleInertiaFactor to allow modifying inertia.
Another parameter for vehicle operation tuning.
Default to <1,1,1> which means nothing is different under normal use.
2013-05-24 16:24:16 -07:00
Robert Adams
4979940def BulletSim: properly set mesh hash key in use tracking structure.
Shouldn't see any functional difference.
2013-05-24 16:23:10 -07:00
Robert Adams
81a6c39781 Meshmerizer: add INI parameter to enable DEBUG mesh detail logging.
Default to off.
To turn mesh parsing DEBUG detail logging on, add
    [Mesh]
        LogMeshDetail=true
to the INI file.
2013-05-24 16:20:26 -07:00
Mic Bowman
a087dbed7f One more appearance change: drop sending the SendAppearance packet
to avatar when it becomes root. This packet shows up in the viewer
logs as an error and appears to cause problems for completing the
texture rebake process for v1 viewers in some cases.
2013-05-24 13:26:07 -07:00
Mic Bowman
bb0ea25090 Protect one more update of the baked texture hashes. 2013-05-24 13:25:25 -07:00
Mic Bowman
681fbda4b6 This is an experimental patch that adds support for comparing texture
hashes for the purpose of accurately responding to AgentTextureCached
packets. There is a change to IClientAPI to report the wearbles hashes
that come in through the SetAppearance packet. Added storage of the
texture hashes in the appearance. While these are added to the
Pack/Unpack (with support for missing values) routines (which means
Simian will store them properly), they are not currently persisted in
Robust.
2013-05-24 13:18:16 -07:00
dahlia
440905ad14 change a hull debugging message to Debug instead of Info 2013-05-24 10:31:14 -07:00
dahlia
21a3a81c7a Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-24 01:54:28 -07:00
dahlia
0cdea5c2f3 correct some errors in decoding of mesh asset convex decomposition data 2013-05-24 01:53:37 -07:00
Justin Clark-Casey (justincc)
eb2bd9d203 minor: Remove unnecessary duplication of AbsolutePosition Vector3 in SOG.Copy()
As a struct, Vector3 has already been cloned by MemberwiseClone()
2013-05-24 00:46:58 +01:00
Justin Clark-Casey (justincc)
02fe05f346 Fix issue where llSetPayPrice on either one of a clone prim in the same OpenSimulator session would change the prices on both prims.
This is because the PayPrice array refernence was being memberwise cloned and not the array itself.
Addresses http://opensimulator.org/mantis/view.php?id=6639
2013-05-24 00:41:47 +01:00
Justin Clark-Casey (justincc)
e597a7d94e Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-23 23:53:44 +01:00
Justin Clark-Casey (justincc)
9b56f99326 Fix bug where a cloned object would report the wrong llGetNumberOfPrims() when avatars had been sitting on the original and a different avatar sat on the copy within the same opensim session.
This was because the sitting avatars list was being cloned rather than reset.
Addresses http://opensimulator.org/mantis/view.php?id=6649
2013-05-23 23:52:07 +01:00
dahlia
d90d8e9999 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-23 15:48:47 -07:00
dahlia
c5549d2730 add decoder for bounding convex hull 2013-05-23 15:47:47 -07:00
Justin Clark-Casey (justincc)
0d5566e879 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-23 23:07:46 +01:00
Justin Clark-Casey (justincc)
28548ab347 Fix bug where both ordinary UserManagementModule and HGUserManagementModules were being added to scenes if no UserManagementModule was specified.
Without explicit config non-hg UMM is used - this is in common with other HG modules.
This was causing a non-HG module to unpredictably use the UMM or HGUMM, though lack of bug reports suggest either UMM was always used or it didn't matter in this case.
2013-05-23 23:05:56 +01:00
Robert Adams
0e002e3693 Add DEBUG level logging in Meshmerizer for mesh parsing. There is
a compile time variable to turn this logging off if it is too spammy.
2013-05-23 14:41:05 -07:00
Robert Adams
29b3b44fab BulletSim: add locking around Meshmerizer use to eliminate possible race
condition when extracting the convex hulls.
2013-05-23 14:40:16 -07:00
Robert Adams
5efce21abc BulletSim: correct errors caused by misspelled INI parameter spec.
Add debugging messages for hull asset use.
2013-05-22 21:57:07 -07:00
Robert Adams
f490522082 BulletSim: specify directory for OpenSim.Region.Physics.Meshing
DLL file in prebuild.xml since that file ends up in bin/Physics
directory.
2013-05-22 21:09:37 -07:00
Robert Adams
ffc9b3dda7 BulletSim: add code to experimentally use asset hull data.
Default to 'off' as it needs debugging.
2013-05-22 21:01:00 -07:00
Robert Adams
61cdf9390d BulletSim: fix problem with walking up stairs that are oriented
in certain directions. The problem was really that the avatar capsule
orientation was being set incorrectly.
2013-05-22 16:06:06 -07:00
Justin Clark-Casey (justincc)
7d38f4940c Implement llSetSoundQueueing().
This is controlled by the viewer, not the server.
So as per http://wiki.secondlife.com/wiki/LlSetSoundQueueing, only two sounds can be queued per prim.
You probably need to use llPreloadSound() for best results
2013-05-22 20:01:57 +01:00
Robert Adams
6596a1de80 Revert "BulletSim: add code to experimentally use asset hull data."
This reverts commit 2fd8819a04.

Remove this code until I can figure out why the references that are
clearly in prebuild.xml doesn't work for the
'using OpenSim.Region.Physics.Meshing' in BSShape.cs.
2013-05-21 22:16:18 -07:00
Robert Adams
10097f13aa BulletSim: update DLLs and SOs with version containing gImpact code. 2013-05-21 21:40:26 -07:00
Robert Adams
2fd8819a04 BulletSim: add code to experimentally use asset hull data.
Default to 'off' as it needs debugging.
2013-05-21 21:32:30 -07:00
Robert Adams
9de3979f5b BulletSim: add gImpact shape type. Add logic to use gImpact shape
for prims that have cuts or holes. Default logic to 'off' as it
needs debugging.
2013-05-21 15:32:10 -07:00
Robert Adams
ece7b33a96 Merge branch 'master' of git://opensimulator.org/git/opensim 2013-05-21 15:31:13 -07:00
Justin Clark-Casey (justincc)
06ab168897 To further help with tracking down the apperance of too much "Unknown User" in chatlogs, etc. temporarily change each instance of this in OpenSimulator so we can identify where it's coming from
For instance, the "Unknown User" in Util.ParseUniversalUserIdenitifer becaomes "Unknown UserUPUUI (class initials + method initials)
This is to help with http://opensimulator.org/mantis/view.php?id=6625
2013-05-21 22:26:15 +01:00
Justin Clark-Casey (justincc)
ba6a6b2d40 Fix compile failure from recent git master 434c3cf 2013-05-21 18:18:16 +01:00
Justin Clark-Casey (justincc)
434c3cf83b Make "show name" command display HomeURL like "show names" 2013-05-21 18:15:22 +01:00
Justin Clark-Casey (justincc)
5c8d38d6cf minor: Change "show names" command to use consistent console display table 2013-05-21 18:11:07 +01:00
Justin Clark-Casey (justincc)
6edecd5d94 Add "show name" console command to make it possible to show a single binding of a UUID to a name. 2013-05-21 18:00:41 +01:00
Justin Clark-Casey (justincc)
c47de9878d Log when "Unknown User" is sent to a user because the UMM had no binding for that UUID and when a binding replaces a previous "Unknown User" entry.
This is a temporary measure to hunt down issues where some but not all users see others as "Unknown user" in text chat, etc.
http://opensimulator.org/mantis/view.php?id=6625
2013-05-21 17:45:15 +01:00
Justin Clark-Casey (justincc)
6ae426c96b Lock m_UserCache whilst iterating over it in UserManagementModule.GetUserData() to avoid concurrency exceptions 2013-05-21 17:25:06 +01:00
Diva Canto
10e4fb2ce2 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-20 09:26:15 -07:00
Diva Canto
26904cc5a1 Add comment 2013-05-20 09:25:50 -07:00
dahlia
e65d1e459e fix error in hull point indexing 2013-05-18 13:11:22 -07:00
dahlia
477bee6468 remove duplicate hull scaling 2013-05-18 11:15:05 -07:00
dahlia
fa8f5bafb2 add prototype code to decode convex hulls from mesh assets. Please do not use yet; the interface will be defined in a later commit. 2013-05-18 01:23:09 -07:00
Robert Adams
214bae1479 BulletSim: fix BulletSim crashing if there is no [BulletSim] section
in any INI file. Update TODO list.
2013-05-17 21:19:38 -07:00
Justin Clark-Casey (justincc)
ec818a506b minor: remove long commented out scene cache clearing code in EntityTransferModule.CrossAgentToNewRegionAsync() 2013-05-16 18:26:22 +01:00
Justin Clark-Casey (justincc)
61f4ab6674 minor: Remove completely unused IClientAPI.RequestClientInfo() call from EntityTransferModule.CrossAgentToNewRegionAsync() 2013-05-16 18:25:04 +01:00
Justin Clark-Casey (justincc)
3bc8cf65a4 Where this is not already happening, trigger asychoronous calls to CloseChildAgent() above the LocalSimulationConnector level.
This is so that other callers (such as SceneCommunicationService.SendCloseChildAgentConnections() can perform all closes asynchronously without pointlessly firing another thread for local closes).
No functional change apart from elimination of unnecessary chaining of new threads.
2013-05-16 17:30:30 +01:00
Justin Clark-Casey (justincc)
d214e2d0c4 On closing child agents, send separate asynchronous requests to each neighbour rather than sending all closes concurrently on a separate thread.
This is to reduce race conditions where neighbours may be responding erratically, thus mixing up create and close agent requests in time.
This mirrors OpenSimulator behaviour on enabling child agents where each region is contacted separately.
2013-05-16 17:12:02 +01:00
Justin Clark-Casey (justincc)
bd31821792 On logout, send close child agent requests to neighbours asynchronously, so user is not prevented from relogging if many neighbours are present but not responsive.
The symptom here is that previous user connections are still present but are labelled active == false
2013-05-16 16:37:21 +01:00
dahlia
46eb8465a0 fall back to using a display mesh for physics proxy if no physics_mesh entry was wound in a mesh asset 2013-05-15 17:12:17 -07:00
Latif Khalifa
71a5cc2041 Updated libopenmetaverse to a5ad7f200e9bd2e91604ba921d1db3768108686b 2013-05-16 00:07:55 +02:00
Latif Khalifa
12289c4fd1 Removed obsolete libopenmetaverse file 2013-05-16 00:02:28 +02:00
Justin Clark-Casey (justincc)
a4290cdbb3 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-15 22:06:01 +01:00
Justin Clark-Casey (justincc)
177a53fbcf Fix issue where osMakeNotecard() would fail if given a list containing vectors or quaternions.
http://opensimulator.org/mantis/view.php?id=6640
2013-05-15 22:04:38 +01:00
Robert Adams
23ebae1828 Eliminate race condition where SimStatsReporter starts reporting
stats before the region is completely initialized.
2013-05-14 13:40:07 -07:00
Justin Clark-Casey (justincc)
df2a0fec5f Comment out log message about looking for asset data in remove asset service for now, in order to reduce log levels in a test region with many hg origin avatars 2013-05-14 20:11:58 +01:00
Justin Clark-Casey (justincc)
ce979552fd Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-14 19:45:35 +01:00
Justin Clark-Casey (justincc)
e9847a4dbd Comment out some debugging item permission messages since these are highly noisy on the console.
Please re-enable when required
2013-05-14 19:44:41 +01:00
Diva Canto
f8bb90d963 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-14 09:07:20 -07:00
Diva Canto
91091c3e54 Second take at HGTP-mesh bug: delay sending the initial data only for agents that are coming via TP (root agents) 2013-05-14 09:06:58 -07:00
Robert Adams
03fddb301b Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-14 08:49:41 -07:00
Vegaslon
b135f1d58a BulletSim: Fix for mantis 6487, also minor adjustment to fix flying while you are running.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-05-14 08:48:40 -07:00
Diva Canto
645da54f25 Revert "HGTP-mesh bug: the mesh download requests were going to the departing sims for a little while. This was also true for local TPs. BUt for local TPs the assets are on the same server, so it doesn't matter. For HGTPs, it matters. This potential fix moves sending the initial data to later, after the client has completed the movement into the region. Fingers crossed that it doesn't mess other things up!"
This reverts commit f32a21d967.
2013-05-14 08:47:18 -07:00
Diva Canto
66c328f51b Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-14 08:12:23 -07:00
Diva Canto
f32a21d967 HGTP-mesh bug: the mesh download requests were going to the departing sims for a little while. This was also true for local TPs. BUt for local TPs the assets are on the same server, so it doesn't matter. For HGTPs, it matters. This potential fix moves sending the initial data to later, after the client has completed the movement into the region. Fingers crossed that it doesn't mess other things up! 2013-05-14 08:12:01 -07:00
Robert Adams
c86e828dbf BulletSim: add a lock to try and catch a native shape creation/destruction
race condition.
2013-05-13 13:30:44 -07:00
Robert Adams
15360cbb6b BulletSim: add adjustment for avatar capsule height scaling. Makes
avatar standing on ground view better and enables tuning.
2013-05-13 13:30:42 -07:00
Robert Adams
45f37e11ad BulletSim: use heightmap terrain when using BulletXNA.
Output messages on features disabled when using BulletXNA.
2013-05-13 13:30:40 -07:00
Diva Canto
4194d935ec Fixed mantis #6609 -- LoadPlugin error messages on Robust. 2013-05-13 13:07:39 -07:00
Diva Canto
af1fa95875 Groups: Improve error handling on remote connector. 2013-05-13 11:36:17 -07:00
Diva Canto
25fea82049 Fixes mantis #6636 -- Groups 2013-05-13 07:29:17 -07:00
Diva Canto
a4431381fa Finalize the logic for SetHome. See comments in Land/LandManagementModule.cs about who has permission to set home where. 2013-05-11 07:58:14 -07:00
Diva Canto
ab4d530462 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-11 07:15:31 -07:00
Diva Canto
48f8b884c3 Handle SetHome properly 2013-05-11 07:15:09 -07:00
Melanie
55c9bc15e5 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-05-11 01:29:30 +01:00
Melanie
81d8deb1a8 Send up the part missing from the Avination Estate commit.
Warning - contains a small migration.
2013-05-11 01:27:37 +01:00
Robert Adams
a42bb799cc BulletSim: fix CPU loop that occurs when any 'degenerate' sculptie
is in a region. This fixes the high CPU usage for regions with nothing
else going on.
2013-05-10 14:48:52 -07:00
Diva Canto
a1031772eb Delete debug message 2013-05-10 08:09:26 -07:00
Justin Clark-Casey (justincc)
ff0332730d Implement delete key for local console 2013-05-09 23:11:37 +01:00
Justin Clark-Casey (justincc)
292a6037ad minor: Remove unnecessary code that was generating warning in TestXInventoryDataPlugin 2013-05-09 22:48:10 +01:00
Justin Clark-Casey (justincc)
0e6ad94829 minor: Remove mono compiler warning in RemoteAdminPlugin 2013-05-09 22:44:45 +01:00
Justin Clark-Casey (justincc)
9978f36d9f Don't send BulkUpdateInventory at the end up of UpdateInventoryItemAsset().
This is causing editing of worn clothes to fail frequently, possibly due to a race condition with a transaction.
This looks to address http://opensimulator.org/mantis/view.php?id=6600
2013-05-09 22:43:16 +01:00
Justin Clark-Casey (justincc)
b4a6f2195d Only send one kill object to the deleter when they derez an object rather than two.
Extend regression test to check this.
2013-05-09 18:53:34 +01:00
Justin Clark-Casey (justincc)
3290cd09d3 remove pointless region handle paramter from IClientAPI.SendKillObject() 2013-05-09 18:12:17 +01:00
Justin Clark-Casey (justincc)
2cb2f1d7e3 Fix issue where objects removed via llDie() would not disappear for users looking in from neighbouring sims.
This was because this particular code path (unlike user delete) only sent kills to root presences, for no apparent good reason.
Added regression test for this case.
This fixes http://opensimulator.org/mantis/view.php?id=6627
2013-05-09 18:02:19 +01:00
Justin Clark-Casey (justincc)
2b0b9f3e6c Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-09 18:01:49 +01:00
Justin Clark-Casey (justincc)
641c636790 minor: Simplify test setup in SceneObjectDeRezTests since permissions module doesn't need different configuration anymore 2013-05-09 16:43:16 +01:00
BlueWall
182ea00cb3 Application support:
Adding some viwer supported url settings for destination guide and avatar picker apps. URL for the destinations should be: "secondlife:///app/teleport/slurl"
2013-05-09 10:50:18 -04:00
Melanie
543d1fe70b Guard the scene list when estates are updated 2013-05-08 21:14:52 +01:00
Mic Bowman
33aaa40bee Adds an event and a method so that handling of the CachedTexture
packet can be pulled out of LLClientView and moved to
AvatarFactory. The first pass at reusing textures (turned off by
default) is included. When reusing textures, if the baked textures
from a previous login are still in the asset service (which generally
means that they are in the simulator's cache) then the avatar will not
need to rebake. This is both a performance improvement (specifically
that an avatars baked textures do not need to be sent to other users
who have the old textures cached) and a resource improvement (don't
have to deal with duplicate bakes in the asset service cache).
2013-05-08 13:13:51 -07:00
Diva Canto
601aa91163 Delete "" entry for AvatarPicker cap. 2013-05-07 19:16:42 -07:00
Diva Canto
6f5222e863 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-07 18:02:25 -07:00
Diva Canto
e92c05ebbd Added AvatarPickerSearch capability handler. 2013-05-07 18:01:48 -07:00
Vegaslon
ac6dcd35fb Bulletsim: and the rotational friction.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-05-07 07:14:10 -07:00
Vegaslon
f247ae1a75 BulletSim: Another way to create vehicle framed friction.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-05-07 07:14:06 -07:00
Robert Adams
ddd97cb78e BulletSim: normalize quaternian rotations when building compound linksets.
Attempt to fix vehicles being twisted off the ground when they go physical.
2013-05-06 18:06:34 -07:00
Robert Adams
84118c5735 BulletSim: properly free references to simple convex hull shapes. Didn't
loose memory since shapes are shared but did mess up usage accounting.
2013-05-06 18:05:37 -07:00
Melanie
1c6b8293d7 Step 3: Commit the Avination XEstate estate comms handler
This adds estate-wide Teleport Home and Teleport All User Home as well
2013-05-07 00:52:40 +01:00
Melanie
5d5edde429 Step 2: commit the IEstateModuleInterface changes needed 2013-05-07 00:37:45 +01:00
Melanie
4c83b5e719 Step one of estate settings sharing - port the Avination Estate module (complete module) as changes are too extensive to apply manually 2013-05-07 00:31:11 +01:00
Robert Adams
93e1986d69 BulletSim: apply linear and angular friction in vehicle coordinates
and not world coordinates.
2013-05-06 16:48:01 -07:00
Robert Adams
045aaa838a BulletSim: remove friction calcuation from BSMotor and move linear and
angular friction computation into linear and angular movement code.
The friction wasn't being applied properly. This will make it so vehicles
don't drift as much and the drift is tunable by changing the friction
timescales.
2013-05-06 13:32:26 -07:00
Robert Adams
bf31896983 BulletSim: simplify parameter specification by reducing the number of
specifications required for simple properties with defaults.
2013-05-06 13:32:24 -07:00
Robert Adams
f9fb1484aa BulletSim: extend BSActorLockAxis to allow locking linear movement in
addition to angular movement. Not enabled by anything yet.
2013-05-06 13:32:22 -07:00
Diva Canto
90f03ccd42 Added new method to Remote Admin for reloading the estate settings. This is meant to be called when some other program has changed the data on the backend. 2013-05-06 11:47:55 -07:00
Diva Canto
a81ddf3d70 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-06 09:18:17 -07:00
Diva Canto
ad00466483 Minor reordering of operations on NewUserConnection. The agent circuit needs to be added earlier for some of the checks to work correctly. 2013-05-06 09:17:54 -07:00
Robert Adams
1ffa69f691 Merge branch 'master' into bulletsim4 2013-05-03 14:25:52 -07:00
Robert Adams
5d25bb3084 BulletSim: zero vehicle motion when changing vehicle type.
Rebuild compound linkset of any child in the linkset changes shape.
Comments and better detailed logging messages.
2013-05-03 14:23:53 -07:00
Justin Clark-Casey (justincc)
5d93c99e8c Fix possible race condition with local region cache if a region was added after startup. 2013-05-03 18:56:58 +01:00
Justin Clark-Casey (justincc)
7ca42d5711 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-03 18:51:29 +01:00
Justin Clark-Casey (justincc)
304c5d4a8b On startup, start scenes after we're set up all local scenes, rather than starting scenes before others have been created.
This aims to avoid a race condition where scenes could look to inform neighbours that they were up before those neighbours had been created.
http://opensimulator.org/mantis/view.php?id=6618
2013-05-03 18:48:50 +01:00
Robert Adams
4042c82a72 BulletSim: prims with no cuts created with single convex hull shape.
Parameter added to enable/disable this feature.
2013-05-02 12:27:30 -07:00
Robert Adams
d9c3947824 BulletSim: Rebuild physical body if physical shape changes for mesh and hull.
Properly rebuilds collision caches.
Release asset data fetched when building mesh or hulls.
2013-05-02 10:06:12 -07:00
Robert Adams
a9480aed85 Merge branch 'master' into bulletsim4 2013-05-02 07:02:28 -07:00
BlueWall
4cb73192a7 Make default config directory "." 2013-05-01 23:01:33 -04:00
Robert Adams
ed46b42fea BulletSim: fix crash when mesh asset wasn't available when meshing
the first time.
Debugging added for mesh/hull asset fetch.
2013-05-01 17:16:46 -07:00
Robert Adams
0378baed35 BulletSim: rework LinksetCompound to work with new BSShape system.
Not all working yet.
2013-05-01 17:15:54 -07:00
BlueWall
04f76af22c Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-01 18:52:15 -04:00
BlueWall
e3d9d5566a Fix inventory issue
Fix issue where objects rezzed from Trash or Lost And Found then be placed back in the respective folder when taking the object or a copy back into inventory.
2013-05-01 18:51:43 -04:00
Justin Clark-Casey (justincc)
386d67ec61 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-05-01 23:02:06 +01:00
Justin Clark-Casey (justincc)
854dcd1abd Fix SmartThreadPool line endings in recent update from dos to unix 2013-05-01 23:00:46 +01:00
Melanie
c6d50cd431 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-05-01 21:37:17 +01:00
Melanie
b26276c8c4 Fix the long standing bug of items being delivered to lost and found or trash when takig copy.
This bug was recently aggravated through the perms changes required for the
export permission.
2013-05-01 21:35:50 +01:00
Robert Adams
fca4e4ec7c Merge branch 'master' into bulletsim4 2013-05-01 12:08:12 -07:00
Justin Clark-Casey (justincc)
81a90e30c6 Add in-code exaplanation for the change in cancellation signalling in STP 2.2.3. Remove left in Console.WriteLine accidentally inserted in recent 206fb306 2013-05-01 19:29:46 +01:00
Justin Clark-Casey (justincc)
8d3250cee4 Add information about creating a PID file for robust to the Robust.ini and Robust.HG.ini example files 2013-05-01 19:15:05 +01:00
Justin Clark-Casey (justincc)
206fb306a7 Update SmartThreadPool to latest version 2.2.3 with a major and minor change.
SmartThreadPool code comes from http://www.codeproject.com/Articles/7933/Smart-Thread-Pool
This version implements thread abort (via WorkItem.Cancel(true)), threadpool naming, max thread stack, etc. so we no longer need to manually patch those.
However, two changes have been made to stock 2.2.3.
Major change: WorkItem.Cancel(bool abortExecution) in our version does not succeed if the work item was in progress and thread abort was not specified.
This is to match previous behaviour where we handle co-operative termination via another mechanism rather than checking WorkItem.IsCanceled.
Minor change: Did not add STP's StopWatch implementation as this is only used WinCE and Silverlight and causes a build clash with System.Diagnostics.StopWatch
The reason for updating is to see if this improves http://opensimulator.org/mantis/view.php?id=6557 and http://opensimulator.org/mantis/view.php?id=6586
2013-05-01 19:01:43 +01:00
Melanie
ac135c649c Fix CAPS to work like they should - do not send caps to the viewer if they're not in the requested caps list.
The previous wrong behavior caused the debug setting "UseHTTPInventory" to fail
on all viewers when turned off. UDB inventory would not be correctly used in
that case.
2013-04-30 23:50:23 +01:00
Robert Adams
46ae84cfba BulletSim: fix error messages created while an avatar has no initial
collisions. Usually happens when logging in an avatar that had been
previously flying. Uninitialized variable.
2013-04-30 13:10:15 -07:00
Robert Adams
7cdb07b386 BulletSim: improvements to LinksetCompound and PrimDisplaced. Not all working yet. 2013-04-30 11:42:11 -07:00
Robert Adams
d322625f90 BulletSim: Add non-static BSShape.GetReference for getting another reference
to an existing shape instance.
BSShapeNative rebuilds shape for all references.
BSShapeCompound returns another reference copy if the compound shape
already exists (for linksets).
2013-04-29 17:30:54 -07:00
Robert Adams
15a3f80e2e BulletSim: LinksetCompound work to disable collision for root and
child prims so compound shape can do all collisions.
Don't try to build a compound linkset for non-physical linksets.
Remove and replace root body when compound shape is added so collision
cache is rebuilt.
2013-04-29 17:30:38 -07:00
Justin Clark-Casey (justincc)
3ce198165c minor: remove some mono compiler warnings in ServicesServerBase 2013-04-29 22:21:57 +01:00
Justin Clark-Casey (justincc)
537b243360 minor: Eliminate warning in LLimageManagerTests by properly calling through to OpenSimTestCase.SetUp() 2013-04-29 22:18:11 +01:00
Justin Clark-Casey (justincc)
67789201c3 Add TestRejectGivenFolder() and TestAcceptGivenFolder() regression tests 2013-04-29 22:14:13 +01:00
Justin Clark-Casey (justincc)
0beccf23c0 Add regression test for inventory item give, reject and subsequent trash folder purge by receiver.
This commit also actually adds the InventoryTransferModuleTests file which I previously forgot
2013-04-29 21:11:44 +01:00
Justin Clark-Casey (justincc)
a7cbb9edc9 Add regression test for offer, accept and subsequent receiver delete of an item offered via instant message. 2013-04-29 20:50:49 +01:00
Justin Clark-Casey (justincc)
12054aaa9f Fix bug where an agent that declined an inventory offer and subsequently emptied their trash would make the item invalid in the giver's inventory
This was because the original item/folder ID was sent in the session slot of the offer IM rather than the copy.
2013-04-29 17:14:44 +01:00
Robert Adams
92ee288d66 BulletSim: remove trailing white space to make git happier. No functional changes. 2013-04-29 07:54:50 -07:00
Robert Adams
ad1787770e BulletSim: rename variable 'PhysicsScene' to be either 'PhysScene' or 'm_physicsScene' to match coding conventions and reduce confusion. 2013-04-29 07:38:55 -07:00
Robert Adams
21ec434688 BulletSim: first cut at new linksetCompound shape building. 2013-04-29 07:38:51 -07:00
Robert Adams
f2d408829b BulletSim: fix crash when creating new hull. 2013-04-29 07:38:47 -07:00
Robert Adams
2da8e60b6d BulletSim: code for creating the avatar capsule shape. 2013-04-29 07:38:44 -07:00
Robert Adams
e5582939fd BulletSim: massive refactor of shape classes. Removed shape specific code from BSShapeCollection. Using BSShape* classes to hold references to shape. Simplified shape dependency callbacks. Remove 'PreferredShape' methods and have each class specify shape type. Disable compound shape linkset for a later commit that will simplify linkset implementation. 2013-04-29 07:38:40 -07:00
Robert Adams
890cb6a293 BulletSim: complete BSShape classes. 2013-04-29 07:38:35 -07:00
Melanie
3ff7391495 Some more pieces of Avination's ban system - if an avatar isn't allowed on any
parcel in the sim, keep them out entirely.
2013-04-29 00:55:34 +01:00
Diva Canto
a517e597f5 Fix wrong sql statement in offline im. 2013-04-28 09:03:09 -07:00
Diva Canto
a49c5291dc Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-04-27 21:24:07 -07:00
Diva Canto
222f530411 Added an interface to an external ban service. With this commit, the interface is used only in Hypergrided worlds (Gatekeeper), although in those, it applies to both local and foreign users. The Ban service itself is not in core; it is to be provided externally. 2013-04-27 21:23:29 -07:00
Diva Canto
90a6891a7d Better error reporting 2013-04-27 10:34:23 -07:00
Diva Canto
f675d465b2 Make method virtual 2013-04-27 10:34:13 -07:00
Melanie
12599c34e2 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-04-27 17:57:22 +01:00
Melanie
cbb3bb62da Unbreak the sample money module 2013-04-27 17:56:39 +01:00
Melanie
ef08ab68a7 Small oversight in EconomyDataRequest - this would have affected everyone NOT using a money module. 2013-04-27 17:42:54 +01:00
Diva Canto
2262b13048 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-04-25 17:02:32 -07:00
Diva Canto
0e162511cf Groups: make some methods protected. 2013-04-25 17:01:57 -07:00
Melanie
03c9d8ae4f Change EconomyDataRequest signature to use an IClientAPI rather than UUID. This is needed because recent LL viewer codebases call this earlier in login when the client is not yet established in the sim and can't be found by UUID.
Sending the reply requires having the IClientAPI.
2013-04-25 21:35:18 +01:00
Melanie
5d0a8ff391 Change copyright notice on DynamicMenuModule to proper BSD 2013-04-25 20:48:12 +01:00
Diva Canto
3bc8017464 Recover a lost "virtual". Downstream projects need this. 2013-04-25 09:23:15 -07:00
dahlia
c10405330d UUIDGatherer now includes UUIDs which reference texture assets used as materials 2013-04-24 20:43:15 -07:00
Diva Canto
0e22021c65 Make the kicked user's avie truly disappear when it's god-kicked. 2013-04-24 19:00:41 -07:00
Melanie
ec4f981f1d Adding the dynamic menu module which allows registering new menu options in compliant viewers 2013-04-25 01:52:34 +01:00
Melanie
5cd77a460c Commit Avination's God Kick feature. 2013-04-25 00:51:57 +01:00
Melanie
6f3c905744 Add Avination's support for parcel eject and freeze 2013-04-25 00:24:48 +01:00
Robert Adams
1593d795ea BulletSim: version of libBulletSim.so for 32 bit systems that doesn't
crash on startup. Doesn't yet solve the new glibcxx dependencies.
2013-04-24 15:01:11 -07:00
Diva Canto
1868680848 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-04-24 12:46:23 -07:00
Diva Canto
70081a40a4 Bug fix: compare tolower. This should fix the issue where HG visitors currently in the region were not being found by the avatar picker window. 2013-04-24 12:45:19 -07:00
Robert Adams
c22a2ab7d2 BulletSim: partial addition of BSShape class code preparing for
different physical mesh representations (simplified convex meshes)
and avatar mesh.
2013-04-24 08:05:42 -07:00
Robert Adams
e324f6f3f0 BulletSim: update DLLs and SOs to they have no dependencies on newer
glibc (2.14) since that is not yet in some Linux distributions.
Add unmanaged API calls and code for creating single convex hull shapes.
2013-04-24 08:03:45 -07:00
Robert Adams
522ab85045 BulletSim: improve avatar stair walking up. Add more parameters to control force
of both position change and up force that move avatars over barrier.
Default parameters are for steps up to 0.5m in height.
2013-04-23 18:31:12 -07:00
dahlia
ed22014646 revert CSJ2K.dll to version in use prior to commit d4fa2c69ed 2013-04-23 15:01:20 -07:00
Justin Clark-Casey (justincc)
115e0aaf83 Fix issue in ConciergeModule where UpdateBroker was sending malformed XML if any number of avatars other than 1 was in the region.
I don't know how well the rest of ConiergeModule works since I've practically never looked at this code.
Addresses http://opensimulator.org/mantis/view.php?id=6605
2013-04-23 21:55:51 +01:00
Robert Adams
e1ac683154 BulletSim: fix crash when deleting llVolumeDetect enabled objects. Bullet's check for an object being linked into the world does not work for Bullet's ghost objects so BulletSim was deleting the object while it was still linked into the physical world structures. 2013-04-22 16:50:06 -07:00
Melanie
293a024c14 Allow callers to set the invoice parameter for GenericMessage 2013-04-22 22:39:08 +01:00
Diva Canto
6ddc39a676 Clean up unused config and config comments. 2013-04-21 16:56:18 -07:00
dahlia
46e4ecadc8 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-04-21 00:21:42 -07:00
dahlia
69f07fdb34 Materials persistence via SceneObjectPart.dynAttrs. This appears to work across region restarts and taking objects into inventory, but probably will not work across archiving via OAR or IAR as materials texture assets may not be adequately referenced to trigger archiving. 2013-04-20 23:39:07 -07:00
BlueWall
855c88a9c0 Fix spelling 2013-04-20 11:57:11 -04:00
BlueWall
f40abc493a Small fix to prebuild xml for building with mono tools 2013-04-20 11:54:05 -04:00
dahlia
233f761779 handle PUT verb for RenderMaterials Cap 2013-04-20 02:08:22 -07:00
dahlia
258804cc04 RenderMaterials POST Cap now return material entries when invoked with an OSDArray of MaterialIDs 2013-04-19 22:19:57 -07:00
dahlia
9ae24cac2f Materials-capable viewers send ImageUpdate packets when updating materials that are normally sent via RenderMaterials CAP. This can cause a race condition for updating TextureEntry fields. Therefore filter any TextureEntry updates so they only update if something actually changed. 2013-04-19 00:35:06 -07:00
dahlia
06829c4082 remove default parameter value that apparently mono cant handle 2013-04-18 01:29:50 -07:00
dahlia
d5419f0a46 Initial experimental support for materials-capable viewers. This is in a very early stage and this module is disabled by default and should only be used by developers for testing as this module could cause data corruption and/or viewer crashes. No materials are persisted yet. 2013-04-18 01:03:19 -07:00
dahlia
7c839f176f amend previous commit, a line was left out 2013-04-17 23:14:28 -07:00
dahlia
53122fad40 Thanks lkalif for a fix to SendRegionHandshake() which fixes a potential crash with Server-side baking enabled viewers 2013-04-17 23:10:02 -07:00
dahlia
ce043c5141 Allow changes to TextureEntry to propagate to viewers when MaterialID changes 2013-04-17 22:41:12 -07:00
dahlia
d4fa2c69ed update libomv to git master which adds support for MaterialID in TextureEntry 2013-04-17 21:31:18 -07:00
Justin Clark-Casey (justincc)
c5de9840b0 refactor: Remove IClientNetworkServer.NetworkStop() in favour of existing Stop().
This was an undocumented interface which I think was for long defunct region load balancing experiments.
Also adds method doc for some IClientNetworkServer methods.
2013-04-16 21:58:24 +01:00
Robert Adams
5f2cbfc0fd BulletSim: fixing problems with llMoveToTarget. Not all fixed yet. 2013-04-09 18:00:29 -07:00
Robert Adams
b53713cdda BulletSim: some formatting changes. 2013-04-09 18:00:27 -07:00
Vegaslon
9cc41d5118 Another algorithm for AngularVerticalAttraction. This one Takes into account all rotations before it and makes the corrections more close to the time that sl does.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-04-09 18:00:25 -07:00
Robert Adams
59135c9a31 BulletSim: add Bullet HACD library invocation. Turned off by default as not
totally debugged. Updated DLLs and SOs with more debugged HACD library code.
2013-04-09 18:00:23 -07:00
Robert Adams
17fd075f39 BulletSim: fix problem where large sets of mega-regions weren't registering
all the terrain with the base region.
2013-04-09 18:00:20 -07:00
Justin Clark-Casey (justincc)
148e46563f minor: fix mono compiler warning in ScriptsHttpRequests.cs 2013-04-10 00:07:58 +01:00
Justin Clark-Casey (justincc)
29e28f4b84 minor: remove mono compiler warnings in InventoryAccessModule 2013-04-10 00:05:03 +01:00
Justin Clark-Casey (justincc)
e20b0d5695 minor: Make exceptions thrown by MySQLAssetData more consistent. 2013-04-10 00:03:37 +01:00
Justin Clark-Casey (justincc)
06068444e2 Comment out rez perms logging I accidentally left in at 7f07023 (Sat Apr 6 02:34:51 2013) 2013-04-09 23:21:13 +01:00
Justin Clark-Casey (justincc)
659c741ff5 Add more notes to async_call_method relating to UnsafeQueueUserWorkItem
UnsafeQueueUserWorkItem is so called because it allows the calling code to escalate its security privileges.
However, since we must already trust this code anyway in OpenSimulator this is not an issue.
2013-04-09 23:15:01 +01:00
Justin Clark-Casey (justincc)
8690a08881 minor: Log an exception if we aren't able to delete a script state file rather than simply ignoring it.
This should never normally happen but if it does then it can be valuable diagonstic information.
2013-04-09 23:02:11 +01:00
Justin Clark-Casey (justincc)
aab2b032aa Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-04-09 22:45:00 +01:00
Justin Clark-Casey (justincc)
8e04c752fc If OpenSimulator is writing a PID file and finds the file already present on startup, logging an error since this is commonly due to an unclean shutdown.
Unclean shutdown can cause constantly moving objects to disappear if an OAR has just been loaded and they have not reached persistence time threshold, among other problems.
2013-04-09 22:38:47 +01:00
Robert Adams
4d2203ff52 BulletSim: Add dylib for BulletSim and add he who figured out building BulletSim
on a Mac to the CONTRIBUTORS file.
2013-04-08 09:15:20 -07:00
Jon Cundill
f68b963596 fixed bullet config for osx
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-04-08 09:09:30 -07:00
Robert Adams
99f39836a1 BulletSim: moving comments around. No functional change. 2013-04-08 06:27:45 -07:00
Robert Adams
a7a1b8b7e9 BulletSim: clean up actor code so routines use the same coding pattern.
Fix a few enabling problems.
2013-04-08 06:27:44 -07:00
Robert Adams
fe16dc09da BulletSim: complete movement of physical object action code out of the
physical object and into actors for setForce, setTorque, hover, lock
axis and avatar move.
2013-04-08 06:27:43 -07:00
Mic Bowman
c7cd077e55 Optimize the number of Simian calls to get the initial presence
information for the friends list. This is a pretty big performance
improvement on login. Note that you must upgrade simian to incorporate
the corresponding GetSessions call.
2013-04-07 17:31:44 -07:00
Justin Clark-Casey (justincc)
7f070236f7 Fix taking (and rezzing) of coalesced objects in the non-root subregions of megaregions.
This fixes the combined bounding box location for regions bigger than 256x256.
It also fixes the position on taking coalesced objects in the non-root regions, where position checks are properly done on rez instead.
It also fixes the megaregion land channel to return null if the land does not exist, which should probably also be done for the ordinary land channels rather than returning a dummy region.
Inspiration from Garmin's commit in http://opensimulator.org/mantis/view.php?id=6595.  Thanks!
2013-04-06 02:34:51 +01:00
Justin Clark-Casey (justincc)
0f008d5f7d When rezzing a coalesced object, check adjust position of all components. 2013-04-06 01:44:06 +01:00
teravus
d2367968e4 * In between the fog, a moment of clarity. This fixes mantis 6570 2013-04-04 19:10:23 -04:00
Justin Clark-Casey (justincc)
f064075a85 Fix XmlRpcAdmin admin_exists_user call so that it actually returns the last user login time rather than serializing the DateTime directly which generates a set of unexpected fields.
lastlogin return is in unix timestamp format.
2013-04-04 01:06:57 +01:00
Justin Clark-Casey (justincc)
f281a994e8 refactor: Simplify ScriptsHttpRequests.GetNextCompletedRequest to more simply iterate through pending requests without unnecessary checks. 2013-04-04 00:49:07 +01:00
Justin Clark-Casey (justincc)
831e4c3850 Fix bug where outstanding llHTTPRequests for scripts were not being aborted when they were deleted.
This was because AsyncCommandManager was handing an item ID to IHttpRequestModule.StopHttpRequest() rather than the expected request ID.
This commit also makes the http request asynchronous using BeginGetResponse() rather than doing this by launching a new thread
so that we can more safely abort it via HttpWebRequest.Abort() rather than aborting the thread itself.
This also renames StopHttpRequest() to StopHttpRequestsForScript() since any outstanding requests are now aborted and/or removed.
2013-04-04 00:36:15 +01:00
Justin Clark-Casey (justincc)
94d44142e3 minor: Stop falsely logging that a teleport was being aborted on client logout even when no teleport was active. 2013-04-03 00:48:36 +01:00
Justin Clark-Casey (justincc)
7bf1986e91 Fix minor race condition in SOP.SitTargetOrientationLL where inconsistent values could be returned if the sit orientation was changed whilst the property was being fetched. 2013-04-03 00:24:33 +01:00
Justin Clark-Casey (justincc)
97f0c9da84 Use consistent GroupPosition value Make SOP.UpdateGroupPosition() rather than one that could change whilst the method is being executed. 2013-04-03 00:23:20 +01:00
Justin Clark-Casey (justincc)
c0319daa40 fix minor race condition in SOP.SitTargetPositionLL where inconsistency could occur if the sit target position changed whilst the property was fetched 2013-04-03 00:09:28 +01:00
Justin Clark-Casey (justincc)
3332af4060 minor: Make SOP.UpdateOffset() more consistent by checking against the same old OffsetPosition rather than one which may vary if it simultaneously changes. 2013-04-03 00:01:06 +01:00
Justin Clark-Casey (justincc)
a3c723ee30 Fix minor race condition where SOP.GetGeometricCenter() and GetCenterOfMass() could return results which were never the case if these values were changed whilst the method was running
No need to create new Vector3s since these are structs.
2013-04-02 23:48:55 +01:00
Robert Adams
68c8633ba1 BulletSim: create axis lock constraint with proper orientation and
enable axis lock functionality.
2013-04-02 06:40:12 -07:00
Robert Adams
17aef1c883 BulletSim: update unmanaged API for HACD parameter passing. Bullet HACD
mesh to hull conversion calls in place but code not working. Update
BulletSim DLLs and SOs for new API and HACD code.
2013-04-01 18:03:11 -07:00
Robert Adams
ebc1209fc9 BulletSim: rearrange mega-region terrain code to make the thread flow
a little clearer.
2013-04-01 18:03:09 -07:00
Justin Clark-Casey (justincc)
2bfe60e2fb Use Output instead of OutputFormat in appropriate places of XEngine status reporting. 2013-04-02 01:28:16 +01:00
Justin Clark-Casey (justincc)
69bc37acd6 minor: Remove unnecessary call to GetAttachments() in AttachmentsModule.UpdateUserInventoryWithAttachment() 2013-04-02 01:00:55 +01:00
Justin Clark-Casey (justincc)
0dce496499 Fix what appears to be a bug in HGUserManagementModule where it enables on the base.Name rather than its own Name. 2013-04-02 00:55:00 +01:00
Justin Clark-Casey (justincc)
600087ab49 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-04-02 00:46:53 +01:00
Justin Clark-Casey (justincc)
4153cfbf14 Change recent MSSQL migrations to drop COLUMN from ALTER TABLE which is either not syntactical or unnecessary.
May fix http://opensimulator.org/mantis/view.php?id=6593
2013-04-02 00:45:29 +01:00
Robert Adams
84eb25da23 BulletSim: stop an avatar from moving if standing on a stationary
object. This will stop avatars from sliding down steep terrains
or objects while still allowing an avatar to be moved if standing
on a moving object.
2013-03-31 22:19:44 -07:00
Robert Adams
933ac60746 BulletSim: not quite functional axis lock code. 2013-03-31 22:19:43 -07:00
Robert Adams
7d50015a74 BulletSim: start the renaming of local variables to m_ form to match the OpenSim coding conventions. 2013-03-31 22:19:42 -07:00
Robert Adams
75b8cf428e BulletSim: fix line endings in BSActor* 2013-03-31 22:19:42 -07:00
Robert Adams
747ece59d2 BulletSim: convert BSDynamic to a BSActor and change BSPrim to set
up the vehicle actor.
2013-03-31 22:19:41 -07:00
Robert Adams
2c581cae2a BulletSim: Add physical 'actors' that operate on the physical object.
Add first 'actor' for locked axis.
2013-03-31 22:19:41 -07:00
Melanie
9b83e53b28 Export permission, part two. Setting export perms for textures and clothing works. Setting perms for prims also works but they don't propagate correctly yet.
NOT FOR PRODUCTIN USE. Your database will need to be updated before you can use this!
2013-03-31 21:59:44 +01:00
Justin Clark-Casey (justincc)
9fee431cc8 In the flotasm asset cache, if we get a request for a file that we're actively writing, simply return null instead of first logging an exception. 2013-03-30 01:21:16 +00:00
Justin Clark-Casey (justincc)
f8785b5f47 refactor: rename ETM.InformClientToInitateTeleportToLocationDelegate to InformClientToInitiateTeleportToLocationDelegate to correct spelling and bring into line with other ETM Initiate methods 2013-03-30 00:29:52 +00:00
Justin Clark-Casey (justincc)
76629289f0 refactor: move the append magic number processing for attachments back up into RezSingleAttachmentFromInventory from RezSingleAttachmentFromInventoryInternal() done in commit 023faa2 2013-03-29 23:59:21 +00:00
Kevin Cozens
cbc9ae898c Added missing functionality (mainly custom headers) to llHTTPRequest. 2013-03-29 23:32:11 +00:00
Justin Clark-Casey (justincc)
023faa227e Check viewer 2/3 attachment calls against avatar appearance attachment data rather than actually attached objects
By checking against the grid's Avatar data, we can ignore viewer side attachments but still initiate these calls simulator-side.
Initiating simulator-side is always necessary for version 1 viewers.
This is a further commit to resolve http://opensimulator.org/mantis/view.php?id=6581
2013-03-29 23:10:28 +00:00
Justin Clark-Casey (justincc)
23ae4c0a4d Fix bug where CHANGED_REGION and/or CHANGED_TELEPORT weren't firing for scripts in attachments.
This was because the script resumption in AttachmentsModule was firing the attach event instead.
Had to reinstate the code in 285bd3a do we can resume the scripts there instead, though the bug existed before its removal.
This is to resolve http://opensimulator.org/mantis/view.php?id=6578
2013-03-29 02:21:38 +00:00
Justin Clark-Casey (justincc)
e89bcf4f77 Revert "Try eliminating the pause before auto-reteleporting for a megaregion now that we're telepoting in a different way."
Unfortunately fails on Nebadon's system right now.  Needs investigation.  May put in a temproary option for experimentation soon.

This reverts commit d87ddf50fc.
2013-03-29 01:34:31 +00:00
Justin Clark-Casey (justincc)
4dfffa1df3 Add Location (relative), Rotation (Relative) and Rotation (World) to "show part" and other related console commands 2013-03-29 01:31:37 +00:00
Justin Clark-Casey (justincc)
d87ddf50fc Try eliminating the pause before auto-reteleporting for a megaregion now that we're telepoting in a different way.
On my own system, I can now eliminate the pause entirely and the reteleport happens whilst the teleport screen is still up.
Trying this change to see if this is true for other people.
2013-03-29 01:16:29 +00:00
Justin Clark-Casey (justincc)
285bd3abc8 Eliminate code which tries to restart attachment scripts in ScenePresence.MakeRootAgent(), since this is already done in AttachmentsModule 2013-03-29 00:49:55 +00:00
Justin Clark-Casey (justincc)
c92654fb43 Stop attempts to update/add existing attachments in user inventory when teleporting between regions.
This appears to resolve issues on teleport where attachments disappear or become labelled as invalid within user inventory.
2013-03-28 23:57:35 +00:00
Justin Clark-Casey (justincc)
2b142f2f9e Add "debug attachments" console command to allow highly verbose attachment logging to be switched on and off.
Default is off.
2013-03-28 23:09:35 +00:00
Justin Clark-Casey (justincc)
feffc8081d minor: remove some mono compiler warnings from EntityTransferModule 2013-03-28 22:56:30 +00:00
Justin Clark-Casey (justincc)
03e421bf3d minor: comment out unused Scene.AgentCrossing() to reduce code complexity 2013-03-28 22:55:13 +00:00
Justin Clark-Casey (justincc)
4ad9b27530 If the viewer has already rezzed any attachments itself, then ignore the simulator-side rez attachments call.
This is a further effort to reduce v3 viewer race conditions where this call may clash with the viewer signalling attachment wearing from its current outfit folder.
2013-03-28 22:51:59 +00:00
Justin Clark-Casey (justincc)
3b377f16b2 Fix regression tests by making a new NPC always trigger simulator side attachment code when created.
Regression from previous commit c2093ccc.  Failed because NPCs don't set the ViaLogin flag
2013-03-28 22:44:59 +00:00
Justin Clark-Casey (justincc)
e97567e227 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-28 22:35:24 +00:00
Justin Clark-Casey (justincc)
c2093ccce1 Move the simulator-side RezAttachments call on login to SP.MakeRootAgent with the other attachments code, using TeleportFlags.ViaLogin check to fire if necessary.
This is to simplify the code (no tricky 'wasChild' signalling required)
and to reduce the risk of a thread clash between simulator-side attaching (necessary for v1 viewers)
and the viewer-side attaching the v3 viewers perform.
2013-03-28 22:07:58 +00:00
Robert Adams
6a9630d2bd BulletSim: fix race condition when creating very large mega-regions.
The symptom was exceptions while creating physical terrain.
Reduce default terrain mesh magnification to 2 from 3 because the
higher resolution uses a lot of memory and doesn't solve the terrain
smoothness for vehicles.
Added comments here and there and improved some debugging log messages.
2013-03-28 10:59:18 -07:00
Robert Adams
3f9b274180 BulletSim: tweaks to terrain boundry computation. No functional changes. 2013-03-28 10:59:16 -07:00
Justin Clark-Casey (justincc)
9ca54d00d8 Add back a log message when we attempt a megaregion auto-reteleport 2013-03-28 02:29:34 +00:00
Justin Clark-Casey (justincc)
afd0d6af07 minor: Only try to deregister stats in EntityTransferModule.RemoveRegion() if module was enabled. 2013-03-28 02:23:09 +00:00
Justin Clark-Casey (justincc)
d9c049fd9f Fix a bug in HGEntityTransferModule to call base.RemoveRegion() when a region is removed rather than base.AddRegion() 2013-03-28 02:20:43 +00:00
Justin Clark-Casey (justincc)
b05ed4ffa6 Instead of going via GodLikeRequestTeleport, auto-teleport the agent directly in a megaregion, in the same manner at the "teleport user" console command.
This is to bypass an issue with the HGLureModule which stops the auto-teleport from happening.
2013-03-28 02:17:32 +00:00
Justin Clark-Casey (justincc)
506d5e41bf On the North and East sides of a megaregion, only consider regions within 256m to be neighbours rather than regions up to 512 distant.
This looks like an off-by-one bug since the view distance was already only 256 on the west and south sides.
This reduces the number of child agents being logged into regions neighbouring a megaregion.
2013-03-28 01:54:11 +00:00
Justin Clark-Casey (justincc)
617637c788 minor: Fix usage error message for "debug eq" console command 2013-03-28 01:41:41 +00:00
Justin Clark-Casey (justincc)
b5b01e5bb5 Make HGLureModule track god like lures as well as normal lures, to see if this fixes issues where second megaregion auto-teleport hangs on black teleport screen when HG is active. 2013-03-28 01:37:52 +00:00
Justin Clark-Casey (justincc)
876d0d310f Add "show eq" console command to show numbers of messages in agent event queues.
For debugging purposes.
2013-03-28 01:36:34 +00:00
Justin Clark-Casey (justincc)
f32027f3b5 Remove some Console.WriteLines accidentally left in last commit cfb20f09 2013-03-28 01:08:47 +00:00
Justin Clark-Casey (justincc)
cfb20f09a9 refactor: combine the checks for megaregion view range into a single place. 2013-03-28 00:57:43 +00:00
Justin Clark-Casey (justincc)
dd7d7683c9 Fix problem with megaregions where teleporting into a different region which already had a child agent would stop the eq working for the agent in the new region.
This was because the calculation as to whether a new agent was needed in the receiving region did not take megaregions into account,
unlike the original calculation when the user first teleported into the region.
This meant that on teleport, entity transfer would create a new CAP but this would be ignored by the viewer and receiving region, meaning that the EQ could no longer be used.
This would prevent subsequent teleport, amongst other things.
Currently, regions up to 512m from a megaregion are considered neighbours.
2013-03-28 00:12:48 +00:00
Justin Clark-Casey (justincc)
da5dbaf1d0 Add admin_get_agents xmlrpc method.
This allows one to retrieve information about agents from a particular region (name, id, position, etc.)
Similar to output from "show users"
See http://opensimulator.org/wiki/Remoteadmin:admin_get_agents for more details
2013-03-26 23:02:13 +00:00
Justin Clark-Casey (justincc)
3072f257f5 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-26 23:00:51 +00:00
Robert Adams
abde0d4efb BulletSim: prevent asset fetching loop when the fetched asset fails to mesh.
Check for the case where the fetched mesh asset fails meshing (degenerate
triangles or no physical mesh). In this case, the asset is marked 'failed'
and BulletSim doesn't keep trying to fetch over-and-over trying to get a
good asset.
2013-03-26 15:02:10 -07:00
Justin Clark-Casey (justincc)
13170ca627 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-26 20:32:22 +00:00
Justin Clark-Casey (justincc)
3f0f313a76 Make llGetLinkPrimitiveParams() and llGetPrimitiveParams() work for avatars in a linkset.
llGetPrimitiveParams() works through PRIM_LINK_TARGET
Setting via llSetLinkPrimitiveParams(), etc. not yet implemented
2013-03-26 20:25:58 +00:00
Melanie
e82fab34d7 Implement a pref to turn on the simulator ExportSupported feature entry.
This tells the viewer to enable the UI for export permissions.
WARNING: If your inventory store contains invalid flags data, this will result
in items becoming exportable! Don't turn this on in production until it's complete!
2013-03-26 19:00:30 +00:00
Melanie
5f4c4df227 Phase 1 of implementing a transfer permission. Overwrite libOMV's PermissionMask
with our own and add export permissions as well as a new definition for "All" as meaning "all conventional permissions" rather than "all possible permissions"
2013-03-26 03:40:06 +00:00
Robert Adams
285dc554ec BulletSim: new algorithm for vertical attraction which uses quaternion
arithmetic to compute the shortest path between the current tilt
and vertical.
2013-03-25 15:40:46 -07:00
Robert Adams
c96a6f1de6 BulletSim: small tweaks and formatting in the parameter fetching code. 2013-03-25 15:40:44 -07:00
Robert Adams
953090fd62 BulletSim: fix possible race condition where an prim's asset can be requested quicker than the asset fetcher returns and thus falsely reporting that an asset was not fetched and defaulting the assset to a bounding box. 2013-03-25 15:40:43 -07:00
Robert Adams
f783b9169f BulletSim: parameterize C# HACD hull creation. Add feature of reducing max hull count for simple (non-cut prims) meshes. 2013-03-25 15:40:41 -07:00
Justin Clark-Casey (justincc)
128c72a234 Start recording inter-region teleport attempts, aborts, cancels and failures in statistics for monitoring/debugging purposes
These are recorded as 'entitytransfer' stats as seen by the "show stats entitytransfer" console command.
2013-03-25 21:53:27 +00:00
Justin Clark-Casey (justincc)
01636ca900 Fix teleporting into the non-SW 256x256 corner of a megaregion, though currently with a 10 second delay before auto-reteleport to the correct location.
This now does a check for border crossing (required to trigger the teleport) immediately in SP.MakeRootAgent().
If left any later, it looks like the physics scene changes the position and stops the cross happening.
If done any earlier, nothing happens because the cross-code currently requires a PhysicsActor to be in place, thuogh it's probably not necessary for this case.
2013-03-23 00:47:59 +00:00
Justin Clark-Casey (justincc)
93206ef0fa Add "show borders" command to show the borders of a region.
This is relevant to mega-regions where the borders are very different to a regular region.
Also adds some method doc and other code comments.
2013-03-23 00:45:21 +00:00
Justin Clark-Casey (justincc)
c4d9a23f26 Following on from 476a7d3e (which wasn't enough), make chat across regions on different simulators work.
Also resolves an issue of multiple chatting if the originating simulators had more than one region and they were neighbours
2013-03-22 01:43:18 +00:00
Justin Clark-Casey (justincc)
1f17ef6d3c Take out a testing sleep I accidentally left in the teleport code from last commit 7471bc7 2013-03-22 01:06:56 +00:00
Justin Clark-Casey (justincc)
7471bc7775 At strategic points in the teleport process, if the client has simultaneously logged out then do not continue.
This aims to reduce any side effects if the process tries to complete after the client has logged back in (e.g. it was delayed due to a slow destination region response).
This introduces a new Aborting entity transfer state which signals that the teleport should be stopped but no compensating actions performed.
2013-03-22 01:00:13 +00:00
Justin Clark-Casey (justincc)
476a7d3eee Implement chat across region borders since we can tell if avatars in neighbouring regions are in range. 2013-03-22 00:03:10 +00:00
Justin Clark-Casey (justincc)
e23a0dcc5d minor: On teleport, signal a child agent before we send the viewer TeleportFinish in order to avoid a theoretical race condition when teleporting to a neighbour.
If we do this after TeleportFinish, then it's possible for a neighbour destination to request the source to create a child agent whilst its still treated as root.
This closes the original presence which we don't really want to do.
This is probably okay (albeit with warnings on the console) but afaics there's no reason not to move the child agent signal.
2013-03-21 23:37:23 +00:00
Justin Clark-Casey (justincc)
46c833810c On a teleport, lock m_agentsInTransit whilst we grab the value to check for completion just to be sure we're not using a thread cached version. 2013-03-21 00:46:08 +00:00
Justin Clark-Casey (justincc)
4de530af45 minor: disable logging on regression TestCrossOnSameSimulator() that I accidentally left on a few commits ago. 2013-03-20 23:13:12 +00:00
Justin Clark-Casey (justincc)
b1cd1d917e minor: don't bother with the pause before rezzing attachments if we are running regression tests (fire and forget calls launched on the same thread).
Also adds code comments as to why this pause exists.
2013-03-20 23:12:13 +00:00
Justin Clark-Casey (justincc)
16af5b87f8 Add file missing from last commit 36651be 2013-03-20 23:08:35 +00:00
Justin Clark-Casey (justincc)
36651bed71 On the later forms of teleport failure, tell the user if this was because viewer couldn't/didn't connect with destination or if destination didn't signal teleport completion.
Also adds regression test for the case where the viewer couldn't connect with the destination region.
Also refactoring of regression test support code associated with entity transfer in order to make this test possible and the code less obscure.
2013-03-20 23:01:16 +00:00
Justin Clark-Casey (justincc)
8de933ab07 Insert a short delay on the simulator side rezzing of attachments in order to fix viewer 3 issues if its own rezzing actions on login collide with the simulator side actions.
This resolves issues (at least in my tests with LL 3.3.4) where this can make attachments invisible until one zooms in on the avatar.
This doesn't affect version 1 viewers since this delay is shorter than the login delay.
This doesn't increase the login time since this part of the process was already being performed asynchronously.
This may be a temporary solution.
2013-03-20 02:09:25 +00:00
Justin Clark-Casey (justincc)
c0ff5635ba Fix "show attachments" command probably broken in commit addab12 (Wed Jan 2 21:38:00 2013)
This break was not connected with the recent attachment code changes.
2013-03-20 02:00:56 +00:00
Justin Clark-Casey (justincc)
3cb1c23554 Force a viewer object update for attachments at the end of the final Scene.CompleteMovement() in order to make all multi-attachments appear on the destination region.
For some reason, sending updates before this will not have this effect.
This may be something related to some viewers (e.g. LL 3.3.4) or something OpenSimulator isn't getting quite right.
2013-03-20 01:46:50 +00:00
Justin Clark-Casey (justincc)
9151b9d233 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-20 01:36:28 +00:00
Robert Adams
90b9121e66 BulletSim: change 'degenerate mesh' message from Error to Debug because there
seem to be lots of sculpties with this problem while the condition really doesn't
change region operation.
2013-03-19 17:15:24 -07:00
Justin Clark-Casey (justincc)
3648164219 Prevent multiple instances of the same item ID being appended to an AvatarAppearance
It looks like this was happening when AttachmentsModule.RezAttachments was doing a secondary set of each attachment to update with the asset ID (initially they only have the inventory ID).
However, with multi-attach this was appending a second copy of the same attachment rather than updating the data that was already there.
This commit requires both simulator and service to be updated.
2013-03-19 21:49:29 +00:00
Robert Adams
c2e4f8aed5 For the moment, disable the output of the 'scene' statistics in SimExtraStatsCollector
and thus for the command 'show stats' because it is ugly and most of the information
is already output in the formatted printout that appears before.
2013-03-19 12:37:44 -07:00
Robert Adams
1dd2d432f1 For those people collecting and comparing logfiles from servers scattered
around the world, change LogWriter to use DateTime.UtcNow rather than
DateTime.Now.
2013-03-19 11:40:10 -07:00
Robert Adams
8360223fed BulletSim: code to generate a higher resolution terrain mesh. Parameter
TerrainMeshMagnification controls number of vertices generated per
heightmap point. Default is 3.
2013-03-19 00:00:03 -07:00
Robert Adams
8510f57ad4 BulletSim: add terrain contact processing threshold parameter. Initialize contact processing threshold for static object as well as mesh terrain. 2013-03-19 00:00:02 -07:00
Justin Clark-Casey (justincc)
397379cd3f Process default attachment point in AttachObjectInternal before we check whether a worn object needs to displace an existing attachment on the same point if we are not using multi-attach. 2013-03-19 00:39:58 +00:00
Melanie
55ab6f015a Fix tests for multiattach 2013-03-18 23:48:03 +00:00
Melanie
5e1f651e21 Merge branch 'master' into newmultiattach
Conflicts:
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
2013-03-18 23:31:27 +00:00
Melanie
0635d9d174 Merge commit 'ccd6f443e1092cb410f565e921f7cf4dd8cd2dac' into newmultiattach
Conflicts:
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
2013-03-18 23:21:01 +00:00
Melanie
e4a70b9f9a Limit each attachment point to 5 items as per spec 2013-03-18 22:56:26 +00:00
Melanie
d07943c262 Multiattach, part 2 2013-03-18 22:56:17 +00:00
Melanie
fcecfc81bb Multiattach, part 1
Conflicts:

	OpenSim/Framework/AvatarAppearance.cs
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
	OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
	OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
2013-03-18 22:56:03 +00:00
Justin Clark-Casey (justincc)
3611d33b00 Improve rejection of any attempt to reattach an object that is already attached.
This also adds/extends regression tests for wearing attachments directly for the scene and attempting to reattach/rewear already attached objects.
2013-03-18 22:04:27 +00:00
Justin Clark-Casey (justincc)
a7a9a8a614 Fix recent regression where an item worn to an attachment point that was already occupied did not remove the previous attachment (current behaviour)
Regression was commit ccd6f4 (Tue Mar 5 23:47:36 2013)
Added regression test for this case.
2013-03-18 20:48:50 +00:00
Melanie
46a81b3527 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2013-03-17 23:07:12 +00:00
Robert Adams
464201b41d BulletSim: add INI parameter for angular banking timescale fudge parameter. 2013-03-16 15:34:07 -07:00
Vegaslon
fc84ebb819 BulletSim: Working Implementation of Angular Banking for Vehicles (Not SL Grade, Other features when implemented should slow it down for now be Strong with Vertical Angular attraction setting and conservative with Angular Velocity on X axis)
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-03-16 15:13:40 -07:00
teravus
6e1b3f9951 *Yet another HTTPServer update code changes in OpenSim Libs. * This fixes a connection close issue by getting rid of the socket references * This adds a connection timeout checker to shutdown poor or evil connections and combats DOS attempts that just connect and make no complete requests and just wait. It also actually implements KeepAlive... instead of just understanding the connection header in the request... you can test by connecting and requesting a keepalive header and sending another request on the same connection. The new timeout checker closes expired keepalive sessions, just make sure you send the request within 70 seconds of connecting or the timeout checker will timeout the connection. 2013-03-16 03:14:11 -04:00
Justin Clark-Casey (justincc)
03075359b5 Finally remove the 'REST' ApplicationPlugins code which has been non-functional and largely commented out for many years. 2013-03-15 23:48:40 +00:00
Melanie
7e5d553781 Make the LSL memory functions virtual so script engines can override them if they have different memory management. 2013-03-15 23:46:49 +00:00
Justin Clark-Casey (justincc)
35843e8ec8 Change the table and field names of XAssetService mysql db tables to be capitalized like Avatars, Friends, etc.
Also fixes access time being set on assets rather than XAssetsMeta
This is to try and be somewhat consistent with other service tables that are mainly in this style.
No migration is supplied, since nobody should be using this service yet except on a test basis.
2013-03-15 23:42:16 +00:00
Justin Clark-Casey (justincc)
e9f3cd1a60 Implement access time updates on assets for XAssetService.
This only happens if access time is older than 30 days currently, in order to reduce database updates.
The idea is to give some idea of assets which haven't been accessed for a very, very long time.
These might conceivably be deleteable, though this will be a risk due to caching at other points in the chain.
This is actually currently much less useable on the xasset service since access time is on metadata rather than the data itself.
And many metadata entries may point to the same data.  Probably need to address this.
2013-03-15 23:17:54 +00:00
Justin Clark-Casey (justincc)
45dee383db refactor: Reuse Get() method in AssetService to eliminate some copy/paste in other Get methods 2013-03-15 22:42:34 +00:00
Justin Clark-Casey (justincc)
bd0c1d9b6a Migrate assets from chained asset service to xassetservice as they are requested.
This shrinks the asset database over time as duplicate assets are fetched.
2013-03-15 22:33:39 +00:00
Justin Clark-Casey (justincc)
d05af4bdad Fix bug in AssetService where requesting data only for an asset would throw an exception if the asset did not exist. 2013-03-15 22:14:34 +00:00
Justin Clark-Casey (justincc)
7fb458b055 minor: log an error rather than info if a connector fails to load. 2013-03-15 22:08:11 +00:00
Justin Clark-Casey (justincc)
3a7d9f740e minor: Make logged message in ServerUtils more consistent. 2013-03-15 22:05:18 +00:00
Justin Clark-Casey (justincc)
8cc3adb585 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-15 21:57:25 +00:00
Justin Clark-Casey (justincc)
924d6e892a Make it possible to chain another asset service underneath the de-duplicating XAssetService.
This makes it possible to use the dedupliicating service without needing to migrate all the existing asset data beforehand.
Currently controlled by a ChainedServiceModule setting in [AssetService] (e.g. ChainedServiceModule = "OpenSim.Services.AssetService.dll:AssetService")
Not yet ready for use.
2013-03-15 21:53:39 +00:00
Robert Adams
032b645e80 Add Vegaslon to CONTRIBUTORS.txt 2013-03-15 14:07:28 -07:00
Vegaslon
78b25094dc BulletSim: Tweak vertical angular attraction to remove double VehicleOrientation application fixing the problem with the vertical attractor pushing vehicles nose first into ground when tilted on side.
Signed-off-by: Robert Adams <Robert.Adams@intel.com>
2013-03-15 14:05:38 -07:00
Robert Adams
c10c43d6f6 Fix server statistics always reporting zero for total network bytes in/out.
Clean up some parameter code in Statistics.Binary.
2013-03-15 13:59:34 -07:00
Justin Clark-Casey (justincc)
d3e76730bd Add example code to DOExampleModule to pull data from that previously saved by DAExampleModule when instantiating a dynamc object. 2013-03-15 00:49:35 +00:00
Justin Clark-Casey (justincc)
cb74186888 Add ParentGroup.HasGroupChanged = true setting to DAExampleModule as this is necessary to get attributes to save (though this probably happens anyway due to the prim move) 2013-03-15 00:27:06 +00:00
Justin Clark-Casey (justincc)
e25ba116a3 refactor: make llGetLinkName() and llGetLinkKey() use a common GetLinkEntity() method 2013-03-15 00:06:42 +00:00
Justin Clark-Casey (justincc)
081271e1d7 minor: remove mono compiler warnings in LSL_Api.cs 2013-03-14 23:44:16 +00:00
Justin Clark-Casey (justincc)
12900ea84e Log same environment information to Robust log as is already done for simulator logs, for debug purposes 2013-03-14 23:39:15 +00:00
Justin Clark-Casey (justincc)
2fbc08d7dd refactor: minor cleanup in osGetAvatarList() 2013-03-14 23:19:18 +00:00
Justin Clark-Casey (justincc)
0ea0f8aa83 Fix bug in osCauseHealing() if called with an avatar ID for an avatar that is not in the scene. 2013-03-14 23:16:39 +00:00
Justin Clark-Casey (justincc)
56b333f301 minor: Use more compact libomv primitive constructors in osNpcGetPos() and osNpcGetRot() 2013-03-14 23:12:58 +00:00
Justin Clark-Casey (justincc)
55204ccde6 Fix minor race conditions in OSSL_Api functions where a parcel could be misidentified for moving prims. 2013-03-14 23:09:59 +00:00
Justin Clark-Casey (justincc)
f8dab4f93f refactor: Use LSL_Vector(Vector3) constructor in llCastRay() 2013-03-14 23:06:54 +00:00
Justin Clark-Casey (justincc)
ca99f418d8 refactor: Use ILandChannel.GetLandObject(Vector3) in LSL_Api rather than having to continually take intermediate Vector3s to avoid race conditions 2013-03-14 23:05:21 +00:00
Justin Clark-Casey (justincc)
c1115e4c2e Add ILandChannel.GetLandObject(Vector3 position) as this is a very common input to GetLandObject()
This conforms to the existing ILandChannel.ParcelsNearPoint() method
2013-03-14 22:56:26 +00:00
Justin Clark-Casey (justincc)
c09f4ff483 Fix minor race condition in llGetCameraRot() where inconsistent information could be returned for a rotating camera 2013-03-14 22:49:08 +00:00
Justin Clark-Casey (justincc)
114fd042de Fix minor race condition in llGetCameraPos() where an inconsistent post could be returned for a moving camera 2013-03-14 22:46:27 +00:00
Justin Clark-Casey (justincc)
d4b109b4c4 Fix minor race condition in llParcelMediaCommandList() where a parcel could be misidentified for a moving prim 2013-03-14 22:45:00 +00:00
Justin Clark-Casey (justincc)
2a81eb8d45 Fix minor race conditions in LSL_Api.GetPrimParams() for PRIM_POSITION, PRIM_SIZE and PRIM_ROT_LOCAL
This function is used by all the various ll*Params() and os*Params() functions
2013-03-14 22:42:11 +00:00
Justin Clark-Casey (justincc)
b23009e480 Fix minor race condition in llGetGeometricCenter() if this was changing whilst the function was called. 2013-03-14 22:35:41 +00:00
Justin Clark-Casey (justincc)
a6f8638174 refactor: use LSL_Rotation(Quaternion) constructor in lLGetRootRotation() 2013-03-14 22:34:48 +00:00
Justin Clark-Casey (justincc)
dd6f1fc637 Fix minor race condition in llGetRootPosition() where inconsistent results could be returned for moving prims 2013-03-14 22:33:44 +00:00
Justin Clark-Casey (justincc)
e7603f98b7 Fix minor race conditions in detecting current parcel for llAddToLandPassList(), llSetParcelMusicURL() and llGetParcelMusicURL() for moving prims 2013-03-14 22:31:07 +00:00
Justin Clark-Casey (justincc)
e6eb914675 refactor: use LSL_Vector(Vector3) constructor in llGroundNormal() 2013-03-14 22:29:09 +00:00
Justin Clark-Casey (justincc)
f8c24b2a61 minor: Reuse ground LSL_Vector in llGroundSlope() rather than creating a new one. 2013-03-14 22:26:37 +00:00
Justin Clark-Casey (justincc)
3c9bea1e3f Fix minor race conditions in llTeleportAgent(), llTeleportAgentGlobalCoords(), llEjectFromLand() and llOverMyLand() where the wrong parcel could be identified for very fast moving avatars. 2013-03-14 22:22:10 +00:00
Justin Clark-Casey (justincc)
7b85279dba refactor: Use LSL_Vector(Vector3) constructor in llGetCenterOfMass() 2013-03-14 22:14:32 +00:00
Justin Clark-Casey (justincc)
ff6a16b46e Fix a minor race condition in llInstantMessage() where slightly wrong origin co-ordinates could be given for a fast moving prim 2013-03-14 22:09:05 +00:00
Justin Clark-Casey (justincc)
895aa7346f Fix minor race condition in llGetOmega() where inconsistent results could be returned (accidentally stated that commit 1774c631 was this fix).
Commit 1774c631 was actually a fix for a similar minor race condition in llGetAccel()
2013-03-14 22:07:07 +00:00
Justin Clark-Casey (justincc)
1774c631cb Fix minor race condition in llGetOmega() where a call whilst a prim was changing angular velocity could return inconsistent results 2013-03-14 22:04:11 +00:00
Justin Clark-Casey (justincc)
04e806036f refactor: Use LSL_Vector(Vector3) constructor in llGetVel() 2013-03-14 22:02:43 +00:00
Justin Clark-Casey (justincc)
ffbbe29229 refactor: Use LSL_Vector(Vector3) constructor in llGetTorque() 2013-03-14 22:01:24 +00:00
Justin Clark-Casey (justincc)
c3e081a5ca Fix minor race condition in llGetLocalRot() where inconsistent results could be returned if the prim was rotating during the call 2013-03-14 22:00:04 +00:00
Justin Clark-Casey (justincc)
f840728273 refactor: use cleaner LSL_Rotation quaternion constructor in LSL_Api.GetPartRot() 2013-03-14 21:57:43 +00:00
Justin Clark-Casey (justincc)
ad9bd3fe93 Fix sensors, llGetRootRotation(), llGet*Param() and other functions to use the world rotation if the avatar to which they are attached is sitting 2013-03-14 21:46:29 +00:00
Justin Clark-Casey (justincc)
e9c394fb4e Make llGetObjectDetails() return the correct world rotation for a sitting avatar
This addresses http://opensimulator.org/mantis/view.php?id=6567
This creates a ScenePresence.GetWorldRotation() with the same semantics as SOP.GetWorldRotation()
SP.Rotation can't be used since it's relative to the sat upon prim if the avatar is sitting.
2013-03-14 21:23:48 +00:00
teravus
9fad90a914 Merge branch 'master' of ssh://opensim/var/git/opensim 2013-03-14 00:58:00 -04:00
teravus
42c533c589 * Updates HttpServer again to re-add the code that closes the stream and connection when It's done sending. Be on the lookout for an old linux/mono bug where the client doesn't get the last bit of the stream before it is disconnected!. Code on opensim-libs. All tests pass.. HttpServer's internal tests pass.. but just a bad feeling. More people should test :) 2013-03-14 00:57:42 -04:00
Justin Clark-Casey (justincc)
43220afda2 Improve DAExampleModule to show current necessary locking to avoid race conditions with a serialization thread. 2013-03-13 23:42:14 +00:00
Justin Clark-Casey (justincc)
48d41ef307 Remove unnecessary instation of DOMap() in SOP from commit 5c53660 since this is being done lazily 2013-03-13 23:25:56 +00:00
Justin Clark-Casey (justincc)
39a0928052 minor: Remove some mono compiler warnings in OpenSim.Framework.dll 2013-03-13 23:17:27 +00:00
Justin Clark-Casey (justincc)
5c53660a7f Add prototype dynamic objects map for scene object parts
This allows region modules to add dynamic objects to SOPs rather than having to continually push and pull OSD dynamic attributes.
This is to explore the original MOAP use case for dynamic attributes where it could be very awkward and possibly time-consuming to keep reconstructing MediaEntrys from stored DynamicAttributes.
This commit adds a DOExampleModule to demonstrate/evolve this code.
Dynamic objects involve no storage or persistence changes - the 'backing store' for any data that does need to be saved will remain the DAMap.
DOExampleModule in this commit only attaches a fresh dynamic object.  Actually constructing this from stored dynamic attributes and handling persistence is left for later.
These changes should affect no existing functionality, though it may or may not reveal necessary changes in DAMap down the road.
2013-03-13 22:59:06 +00:00
Justin Clark-Casey (justincc)
b7216f4daf minor: save some commented out log lines which will be useful again in future debugging of VectorRenderModule 2013-03-13 00:46:17 +00:00
Justin Clark-Casey (justincc)
f8a4d95bdd minor: Remove mono compiler warning in LLClientView 2013-03-13 00:22:07 +00:00
Justin Clark-Casey (justincc)
0d25be3f81 Make C# scripts return correct error line and column numbers instead of failing because they have no linemap.
Adapted fix from http://opensimulator.org/mantis/view.php?id=6571
Thanks Nickel Briand
2013-03-13 00:19:37 +00:00
Justin Clark-Casey (justincc)
fb1211ad5e Add DisableInterRegionTeleportCancellation option in [EntityTransfer] section of OpenSim.ini. False by default.
This option allows the simulator to specify that the cancel button on inter-region teleports should never appear.
This exists because sometimes cancellation will result in a stuck avatar requiring relog.
It may be hard to prevent this due to the protocol design (the LL grid has the same issue)
In small controlled grids where teleport failure is practically impossible it can be better to disable teleport cancellation entirely.
2013-03-12 23:01:27 +00:00
Justin Clark-Casey (justincc)
c43d4b5572 Improve teleport cancellation in some circumstances, though cancelling teleports is still not recommended.
Previously, hitting the cancel button on a teleport would cancel on the client side but the request was ignored on the server side.
Cancel would still work if the teleport failed in the early stages (e.g. because the destination never replied to early CreateAgent and UpdateAgent messages).
But if the teleport still completed after a delay here or later on, the viewer would become confused (usual symptom appears to be avatar being unable to move/reteleport).
This commit makes OpenSimulator obey cancellations which are received before it sends the TeleportFinish event queue message and does proper cleanup.
But cancellations received after this (which can happen even though the cancel button is removed as this messages comes on a different thread) can still result in a frozen avatar.
This looks extremely difficult and impossible to fix.
I can replicate the same problem on the Linden Lab grid by hitting cancel immediately after a teleport starts (a teleport which would otherwise quickly succeed).
2013-03-12 22:16:09 +00:00
Justin Clark-Casey (justincc)
0c6268fe56 minor: remove mono compiler warning in SceneObjectUndoRedoTests 2013-03-11 23:15:13 +00:00
Justin Clark-Casey (justincc)
be686f80a3 minor: Remove mono compiler warnings from LSL_ApiHttpTests 2013-03-11 23:01:07 +00:00
Justin Clark-Casey (justincc)
e898a5fec5 minor: Remove mono compiler warnings in EventQueueTests 2013-03-11 22:42:27 +00:00
Robert Adams
13f3bcae94 Update comment about setting physics=BulletSimN as the C# Bullet
version has been wrapped into one BulletSim and the physics engine
selection is now done as specified in OpenSimDefaults.ini.
2013-03-10 22:24:34 -07:00
Robert Adams
1120bcf123 BulletSim: remove the ability for avatars to fly off the edge of
regions when there are no region neighbors.
Add some terrain location processing routines to support above.
2013-03-09 14:15:14 -08:00
teravus
5097437e11 * Apparently, sometimes texture entries come in from the wire with no default texture defined.. so apply better fallback protection against that. The net result is clients will have their selected textures set when they would have previously had an ignored exception. 2013-03-08 19:32:47 -05:00
teravus
33dab49d22 * Just another one of those new packet blocks causing a null ref. Defaulting to zero length array..... 2013-03-07 19:19:36 -05:00
Diva Canto
2f1aa87eb5 One more comment inconsistency fixed. 2013-03-07 08:02:48 -08:00
Diva Canto
fdebee25db Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-07 06:41:03 -08:00
Diva Canto
2b0056eaca Fixed inconsistency in comments. Thanks Ai Austin. 2013-03-07 06:40:39 -08:00
Justin Clark-Casey (justincc)
6706e189d5 minor: remove some completely unused string local vars added recently in commit 984faf2 2013-03-06 23:11:32 +00:00
Justin Clark-Casey (justincc)
2fe938d11d Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2013-03-06 23:07:04 +00:00
Justin Clark-Casey (justincc)
5751ecde52 Add code for testing event queue messages recevied on region cross.
This is currently disabled pending an improvement in the test code to properly add avatars when an event queue module is present.
2013-03-06 23:06:00 +00:00
Justin Clark-Casey (justincc)
8960418e7d Add regression test for presence crossing between regions on the same simulator.
Unlike a much earlier commented out version of this test, this is done in synchronous mode.
2013-03-06 21:37:53 +00:00
419 changed files with 50373 additions and 39773 deletions

View File

@@ -58,7 +58,7 @@ where we are today.
= Additional OpenSim Contributors =
These folks have contributed code patches to OpenSim to help make it
These folks have contributed code patches or content to OpenSimulator to help make it
what it is today.
* aduffy70
@@ -75,11 +75,12 @@ what it is today.
* controlbreak
* coyled
* Daedius
* Dong Jun Lan (IBM)
* DoranZemlja
* daTwitch
* devalnor-#708
* dmiles (Daxtron Labs)
* Dong Jun Lan (IBM)
* DoranZemlja
* dr0b3rts
* dslake (Intel)
* FredoChaplin
* Garmin Kawaguichi
@@ -101,6 +102,7 @@ what it is today.
* jhurliman
* John R Sohn (XenReborn)
* jonc
* Jon Cundill
* Junta Kohime
* Kayne
* Kevin Cozens
@@ -155,11 +157,13 @@ what it is today.
* tglion
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
* tyre
* Vegaslon <vegaslon@gmail.com>
* VikingErik
* Vytek
* webmage (IBM)
* Xantor
* Y. Nitta
* YoshikoFazuku
* YZh
* Zackary Geers aka Kunnis Basiat
* Zha Ewry
@@ -212,5 +216,3 @@ In addition, we would like to thank:
* The Mono Project
* The NANT Developers
* Microsoft (.NET, MSSQL-Adapters)
*x

View File

@@ -347,7 +347,7 @@ namespace OpenSim.Groups
{
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog);
//m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog);
// Group invitations
if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
{
@@ -485,7 +485,7 @@ namespace OpenSim.Groups
return;
//// 16 bytes are the UUID. Maybe.
UUID folderID = new UUID(im.binaryBucket, 0);
// UUID folderID = new UUID(im.binaryBucket, 0);
UUID noticeID = new UUID(im.imSessionID);
GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteClient.AgentId.ToString(), noticeID);
@@ -766,14 +766,17 @@ namespace OpenSim.Groups
remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group.");
return UUID.Zero;
}
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation");
}
string reason = string.Empty;
UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment,
allowPublish, maturePublish, remoteClient.AgentId, out reason);
if (groupID != UUID.Zero)
{
if (money != null)
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly");
// Update the founder with new group information.

View File

@@ -186,7 +186,6 @@ namespace OpenSim.Groups
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{
m_log.DebugFormat("[Groups]: Creating group {0}", name);
reason = string.Empty;
if (m_UserManagement.IsLocalGridUser(RequestingAgentID))
return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
@@ -544,7 +543,6 @@ namespace OpenSim.Groups
List<string> urls = new List<string>();
foreach (GroupMembersData m in members)
{
UUID userID = UUID.Zero;
if (!m_UserManagement.IsLocalGridUser(m.AgentID))
{
string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI");
@@ -685,6 +683,9 @@ namespace OpenSim.Groups
{
serviceLocation = string.Empty;
name = string.Empty;
if (groupID.Equals(UUID.Zero))
return true;
ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty);
if (group == null)
{

View File

@@ -47,7 +47,6 @@ namespace OpenSim.Groups
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HGGroupsService m_GroupsService;
private string m_HomeURI = string.Empty;
private string m_ConfigName = "Groups";
// Called by Robust shell
@@ -113,7 +112,7 @@ namespace OpenSim.Groups
m_GroupsService = service;
}
public override byte[] Handle(string path, Stream requestData,
protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
StreamReader sr = new StreamReader(requestData);
@@ -209,7 +208,6 @@ namespace OpenSim.Groups
UUID groupID = new UUID(request["GroupID"].ToString());
string agentID = request["AgentID"].ToString();
string token = request["AccessToken"].ToString();
string reason = string.Empty;
m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token);
}

View File

@@ -75,7 +75,7 @@ namespace OpenSim.Groups
m_GroupsService = service;
}
public override byte[] Handle(string path, Stream requestData,
protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
StreamReader sr = new StreamReader(requestData);
@@ -170,11 +170,16 @@ namespace OpenSim.Groups
}
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
if (grec == null)
NullResult(result, "Internal Error");
if (grec.GroupID != UUID.Zero)
{
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
if (grec == null)
NullResult(result, "Internal Error");
else
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
}
else
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
NullResult(result, reason);
}
string xmlString = ServerUtils.BuildXmlResponse(result);
@@ -264,7 +269,6 @@ namespace OpenSim.Groups
UUID groupID = new UUID(request["GroupID"].ToString());
string agentID = request["AgentID"].ToString();
string requestingAgentID = request["RequestingAgentID"].ToString();
string reason = string.Empty;
m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID);
}
@@ -495,7 +499,6 @@ namespace OpenSim.Groups
else
{
string op = request["OP"].ToString();
string reason = string.Empty;
bool success = false;
if (op == "ADD")
@@ -563,7 +566,6 @@ namespace OpenSim.Groups
else
{
string op = request["OP"].ToString();
string reason = string.Empty;
if (op == "GROUP")
{
@@ -626,7 +628,6 @@ namespace OpenSim.Groups
else
{
string op = request["OP"].ToString();
string reason = string.Empty;
if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID"))
{

View File

@@ -209,13 +209,10 @@ namespace OpenSim.Groups
public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d)
{
GroupMembershipData activeGroup = d();
if (activeGroup != null)
{
string cacheKey = "active-" + AgentID.ToString();
lock (m_Cache)
if (m_Cache.Contains(cacheKey))
m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
}
string cacheKey = "active-" + AgentID.ToString();
lock (m_Cache)
if (m_Cache.Contains(cacheKey))
m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
}
public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d)

View File

@@ -130,6 +130,13 @@ namespace OpenSim.Groups
{
reason = string.Empty;
// Check if the group already exists
if (m_Database.RetrieveGroup(name) != null)
{
reason = "A group with that name already exists";
return UUID.Zero;
}
// Create the group
GroupData data = new GroupData();
data.GroupID = UUID.Random();
@@ -723,12 +730,12 @@ namespace OpenSim.Groups
#region Actions without permission checks
private void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
{
_AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, string.Empty);
}
public void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
protected void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
{
// 1. Delete membership
m_Database.DeleteMember(GroupID, AgentID);
@@ -780,7 +787,7 @@ namespace OpenSim.Groups
}
private bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
protected bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
{
RoleData data = m_Database.RetrieveRole(groupID, roleID);
@@ -810,12 +817,12 @@ namespace OpenSim.Groups
return m_Database.StoreRole(data);
}
private void _RemoveGroupRole(UUID groupID, UUID roleID)
protected void _RemoveGroupRole(UUID groupID, UUID roleID)
{
m_Database.DeleteRole(groupID, roleID);
}
private void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
protected void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
{
RoleMembershipData data = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
if (data != null)
@@ -840,7 +847,7 @@ namespace OpenSim.Groups
}
private List<GroupRolesData> _GetGroupRoles(UUID groupID)
protected List<GroupRolesData> _GetGroupRoles(UUID groupID)
{
List<GroupRolesData> roles = new List<GroupRolesData>();
@@ -865,7 +872,7 @@ namespace OpenSim.Groups
return roles;
}
private List<ExtendedGroupRoleMembersData> _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
protected List<ExtendedGroupRoleMembersData> _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
{
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();

View File

@@ -75,7 +75,7 @@ namespace OpenSim.OfflineIM
m_OfflineIMService = service;
}
public override byte[] Handle(string path, Stream requestData,
protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
StreamReader sr = new StreamReader(requestData);

View File

@@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
{
public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int MAX_IM = 25;
private XmlSerializer m_serializer;

View File

@@ -115,6 +115,8 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
Environment.Exit(1);
}
List<IScene> createdScenes = new List<IScene>();
for (int i = 0; i < regionsToLoad.Length; i++)
{
IScene scene;
@@ -123,17 +125,22 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
")");
bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]);
m_openSim.CreateRegion(regionsToLoad[i], true, out scene);
createdScenes.Add(scene);
if (changed)
regionsToLoad[i].EstateSettings.Save();
if (scene != null)
regionsToLoad[i].EstateSettings.Save();
}
foreach (IScene scene in createdScenes)
{
scene.Start();
m_newRegionCreatedHandler = OnNewRegionCreated;
if (m_newRegionCreatedHandler != null)
{
m_newRegionCreatedHandler = OnNewRegionCreated;
if (m_newRegionCreatedHandler != null)
{
m_newRegionCreatedHandler(scene);
}
m_newRegionCreatedHandler(scene);
}
}
}

View File

@@ -50,6 +50,7 @@ using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using PermissionMask = OpenSim.Framework.PermissionMask;
namespace OpenSim.ApplicationPlugins.RemoteController
{
@@ -136,6 +137,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
// Agent management
availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
// User management
@@ -155,6 +157,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
availableMethods["admin_acl_add"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListAdd);
availableMethods["admin_acl_remove"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListRemove);
availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList);
availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload);
// Either enable full remote functionality or just selected features
string enabledMethods = m_config.GetString("enabled_methods", "all");
@@ -698,6 +701,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
IScene newScene;
m_application.CreateRegion(region, out newScene);
newScene.Start();
// If an access specification was provided, use it.
// Otherwise accept the default.
@@ -1092,7 +1096,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
GridUserInfo userInfo = m_application.SceneManager.CurrentOrFirstScene.GridUserService.GetGridUserInfo(account.PrincipalID.ToString());
if (userInfo != null)
responseData["lastlogin"] = userInfo.Login;
responseData["lastlogin"] = Util.ToUnixTime(userInfo.Login);
else
responseData["lastlogin"] = 0;
@@ -1759,6 +1763,87 @@ namespace OpenSim.ApplicationPlugins.RemoteController
m_log.Info("[RADMIN]: Access List List Request complete");
}
private void XmlRpcEstateReload(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Received Estate Reload Request");
Hashtable responseData = (Hashtable)response.Value;
// Hashtable requestData = (Hashtable)request.Params[0];
m_application.SceneManager.ForEachScene(s =>
s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false)
);
responseData["success"] = true;
m_log.Info("[RADMIN]: Estate Reload Request complete");
}
private void XmlRpcGetAgentsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
Hashtable responseData = (Hashtable)response.Value;
Hashtable requestData = (Hashtable)request.Params[0];
bool includeChildren = false;
if (requestData.Contains("include_children"))
bool.TryParse((string)requestData["include_children"], out includeChildren);
Scene scene;
GetSceneFromRegionParams(requestData, responseData, out scene);
ArrayList xmlRpcRegions = new ArrayList();
responseData["regions"] = xmlRpcRegions;
Hashtable xmlRpcRegion = new Hashtable();
xmlRpcRegions.Add(xmlRpcRegion);
xmlRpcRegion["name"] = scene.Name;
xmlRpcRegion["id"] = scene.RegionInfo.RegionID.ToString();
List<ScenePresence> agents = scene.GetScenePresences();
ArrayList xmlrpcAgents = new ArrayList();
foreach (ScenePresence agent in agents)
{
if (agent.IsChildAgent && !includeChildren)
continue;
Hashtable xmlRpcAgent = new Hashtable();
xmlRpcAgent.Add("name", agent.Name);
xmlRpcAgent.Add("id", agent.UUID.ToString());
xmlRpcAgent.Add("type", agent.PresenceType.ToString());
xmlRpcAgent.Add("current_parcel_id", agent.currentParcelUUID.ToString());
Vector3 pos = agent.AbsolutePosition;
xmlRpcAgent.Add("pos_x", pos.X.ToString());
xmlRpcAgent.Add("pos_y", pos.Y.ToString());
xmlRpcAgent.Add("pos_z", pos.Z.ToString());
Vector3 lookAt = agent.Lookat;
xmlRpcAgent.Add("lookat_x", lookAt.X.ToString());
xmlRpcAgent.Add("lookat_y", lookAt.Y.ToString());
xmlRpcAgent.Add("lookat_z", lookAt.Z.ToString());
Vector3 vel = agent.Velocity;
xmlRpcAgent.Add("vel_x", vel.X.ToString());
xmlRpcAgent.Add("vel_y", vel.Y.ToString());
xmlRpcAgent.Add("vel_z", vel.Z.ToString());
xmlRpcAgent.Add("is_flying", agent.Flying.ToString());
xmlRpcAgent.Add("is_sat_on_ground", agent.SitGround.ToString());
xmlRpcAgent.Add("is_sat_on_object", agent.IsSatOnObject.ToString());
xmlrpcAgents.Add(xmlRpcAgent);
}
m_log.DebugFormat(
"[REMOTE ADMIN]: XmlRpcGetAgents found {0} agents in {1}", xmlrpcAgents.Count, scene.Name);
xmlRpcRegion["agents"] = xmlrpcAgents;
responseData["success"] = true;
}
private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
Hashtable responseData = (Hashtable)response.Value;

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
<Addin id="OpenSim.ApplicationPlugins.Rest.Inventory" version="0.1">
<Runtime>
<Import assembly="OpenSim.ApplicationPlugins.Rest.Inventory.dll"/>
</Runtime>
<Dependencies>
<Addin id="OpenSim" version="0.5" />
</Dependencies>
<Extension path = "/OpenSim/Startup">
<Plugin id="RestInventory" type="OpenSim.ApplicationPlugins.Rest.Inventory.RestHandler" />
</Extension>
</Addin>

View File

@@ -1,551 +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 System.Reflection;
using System.Text;
using log4net;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Services.Interfaces;
using IAvatarService = OpenSim.Services.Interfaces.IAvatarService;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
public class Rest
{
internal static readonly ILog Log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
internal static bool DEBUG = Log.IsDebugEnabled;
/// <summary>
/// Supported authentication schemes
/// </summary>
public const string AS_BASIC = "Basic"; // simple user/password verification
public const string AS_DIGEST = "Digest"; // password safe authentication
/// Supported Digest algorithms
public const string Digest_MD5 = "MD5"; // assumed default if omitted
public const string Digest_MD5Sess = "MD5-sess"; // session-span - not good for REST?
public const string Qop_Auth = "auth"; // authentication only
public const string Qop_Int = "auth-int"; // TODO
/// <summary>
/// These values have a single value for the whole
/// domain and lifetime of the plugin handler. We
/// make them static for ease of reference within
/// the assembly. These are initialized by the
/// RestHandler class during start-up.
/// </summary>
internal static IRestHandler Plugin = null;
internal static OpenSimBase main = null;
internal static string Prefix = null;
internal static IConfig Config = null;
internal static string GodKey = null;
internal static bool Authenticate = true;
internal static bool Secure = true;
internal static bool ExtendedEscape = true;
internal static bool DumpAsset = false;
internal static bool Fill = true;
internal static bool FlushEnabled = true;
internal static string Realm = "OpenSim REST";
internal static string Scheme = AS_BASIC;
internal static int DumpLineSize = 32; // Should be a multiple of 16 or (possibly) 4
/// <summary>
/// These are all dependent upon the Comms manager
/// being initialized. So they have to be properties
/// because the comms manager is now a module and is
/// not guaranteed to be there when the rest handler
/// initializes.
/// </summary>
internal static IInventoryService InventoryServices
{
get { return main.SceneManager.CurrentOrFirstScene.InventoryService; }
}
internal static IUserAccountService UserServices
{
get { return main.SceneManager.CurrentOrFirstScene.UserAccountService; }
}
internal static IAuthenticationService AuthServices
{
get { return main.SceneManager.CurrentOrFirstScene.AuthenticationService; }
}
internal static IAvatarService AvatarServices
{
get { return main.SceneManager.CurrentOrFirstScene.AvatarService; }
}
internal static IAssetService AssetServices
{
get { return main.SceneManager.CurrentOrFirstScene.AssetService; }
}
/// <summary>
/// HTTP requires that status information be generated for PUT
/// and POST opertaions. This is in support of that. The
/// operation verb gets substituted into the first string,
/// and the completion code is inserted into the tail. The
/// strings are put here to encourage consistency.
/// </summary>
internal static string statusHead = "<html><body><title>{0} status</title><break>";
internal static string statusTail = "</body></html>";
internal static Dictionary<int,string> HttpStatusDesc;
static Rest()
{
HttpStatusDesc = new Dictionary<int,string>();
if (HttpStatusCodeArray.Length != HttpStatusDescArray.Length)
{
Log.ErrorFormat("{0} HTTP Status Code and Description arrays do not match");
throw new Exception("HTTP Status array discrepancy");
}
// Repackage the data into something more tractable. The sparse
// nature of HTTP return codes makes an array a bad choice.
for (int i=0; i<HttpStatusCodeArray.Length; i++)
{
HttpStatusDesc.Add(HttpStatusCodeArray[i], HttpStatusDescArray[i]);
}
}
internal static int CreationDate
{
get { return (int) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; }
}
internal static string MsgId
{
get { return Plugin.MsgId; }
}
internal static string RequestId
{
get { return Plugin.RequestId; }
}
internal static Encoding Encoding = Util.UTF8;
/// <summary>
/// Version control for REST implementation. This
/// refers to the overall infrastructure represented
/// by the following classes
/// RequestData
/// RequestInventoryPlugin
/// Rest
/// It does no describe implementation classes such as
/// RestInventoryServices, which may morph much more
/// often. Such classes ARE dependent upon this however
/// and should check it in their Initialize method.
/// </summary>
public static readonly float Version = 1.0F;
public const string Name = "REST 1.0";
/// <summary>
/// Currently defined HTTP methods.
/// Only GET and HEAD are required to be
/// supported by all servers. See Respond
/// to see how these are handled.
/// </summary>
// REST AGENT 1.0 interpretations
public const string GET = "get"; // information retrieval - server state unchanged
public const string HEAD = "head"; // same as get except only the headers are returned.
public const string POST = "post"; // Replace the URI designated resource with the entity.
public const string PUT = "put"; // Add the entity to the context represented by the URI
public const string DELETE = "delete"; // Remove the URI designated resource from the server.
public const string OPTIONS = "options"; //
public const string TRACE = "trace"; //
public const string CONNECT = "connect"; //
// Define this in one place...
public const string UrlPathSeparator = "/";
public const string UrlMethodSeparator = ":";
// Redirection qualifications
public const bool PERMANENT = false;
public const bool TEMPORARY = true;
// Constant arrays used by String.Split
public static readonly char C_SPACE = ' ';
public static readonly char C_SLASH = '/';
public static readonly char C_PATHSEP = '/';
public static readonly char C_COLON = ':';
public static readonly char C_PLUS = '+';
public static readonly char C_PERIOD = '.';
public static readonly char C_COMMA = ',';
public static readonly char C_DQUOTE = '"';
public static readonly string CS_SPACE = " ";
public static readonly string CS_SLASH = "/";
public static readonly string CS_PATHSEP = "/";
public static readonly string CS_COLON = ":";
public static readonly string CS_PLUS = "+";
public static readonly string CS_PERIOD = ".";
public static readonly string CS_COMMA = ",";
public static readonly string CS_DQUOTE = "\"";
public static readonly char[] CA_SPACE = { C_SPACE };
public static readonly char[] CA_SLASH = { C_SLASH };
public static readonly char[] CA_PATHSEP = { C_PATHSEP };
public static readonly char[] CA_COLON = { C_COLON };
public static readonly char[] CA_PERIOD = { C_PERIOD };
public static readonly char[] CA_PLUS = { C_PLUS };
public static readonly char[] CA_COMMA = { C_COMMA };
public static readonly char[] CA_DQUOTE = { C_DQUOTE };
// HTTP Code Values (in value order)
public const int HttpStatusCodeContinue = 100;
public const int HttpStatusCodeSwitchingProtocols = 101;
public const int HttpStatusCodeOK = 200;
public const int HttpStatusCodeCreated = 201;
public const int HttpStatusCodeAccepted = 202;
public const int HttpStatusCodeNonAuthoritative = 203;
public const int HttpStatusCodeNoContent = 204;
public const int HttpStatusCodeResetContent = 205;
public const int HttpStatusCodePartialContent = 206;
public const int HttpStatusCodeMultipleChoices = 300;
public const int HttpStatusCodePermanentRedirect = 301;
public const int HttpStatusCodeFound = 302;
public const int HttpStatusCodeSeeOther = 303;
public const int HttpStatusCodeNotModified = 304;
public const int HttpStatusCodeUseProxy = 305;
public const int HttpStatusCodeReserved306 = 306;
public const int HttpStatusCodeTemporaryRedirect = 307;
public const int HttpStatusCodeBadRequest = 400;
public const int HttpStatusCodeNotAuthorized = 401;
public const int HttpStatusCodePaymentRequired = 402;
public const int HttpStatusCodeForbidden = 403;
public const int HttpStatusCodeNotFound = 404;
public const int HttpStatusCodeMethodNotAllowed = 405;
public const int HttpStatusCodeNotAcceptable = 406;
public const int HttpStatusCodeProxyAuthenticate = 407;
public const int HttpStatusCodeTimeOut = 408;
public const int HttpStatusCodeConflict = 409;
public const int HttpStatusCodeGone = 410;
public const int HttpStatusCodeLengthRequired = 411;
public const int HttpStatusCodePreconditionFailed = 412;
public const int HttpStatusCodeEntityTooLarge = 413;
public const int HttpStatusCodeUriTooLarge = 414;
public const int HttpStatusCodeUnsupportedMedia = 415;
public const int HttpStatusCodeRangeNotSatsified = 416;
public const int HttpStatusCodeExpectationFailed = 417;
public const int HttpStatusCodeServerError = 500;
public const int HttpStatusCodeNotImplemented = 501;
public const int HttpStatusCodeBadGateway = 502;
public const int HttpStatusCodeServiceUnavailable = 503;
public const int HttpStatusCodeGatewayTimeout = 504;
public const int HttpStatusCodeHttpVersionError = 505;
public static readonly int[] HttpStatusCodeArray = {
HttpStatusCodeContinue,
HttpStatusCodeSwitchingProtocols,
HttpStatusCodeOK,
HttpStatusCodeCreated,
HttpStatusCodeAccepted,
HttpStatusCodeNonAuthoritative,
HttpStatusCodeNoContent,
HttpStatusCodeResetContent,
HttpStatusCodePartialContent,
HttpStatusCodeMultipleChoices,
HttpStatusCodePermanentRedirect,
HttpStatusCodeFound,
HttpStatusCodeSeeOther,
HttpStatusCodeNotModified,
HttpStatusCodeUseProxy,
HttpStatusCodeReserved306,
HttpStatusCodeTemporaryRedirect,
HttpStatusCodeBadRequest,
HttpStatusCodeNotAuthorized,
HttpStatusCodePaymentRequired,
HttpStatusCodeForbidden,
HttpStatusCodeNotFound,
HttpStatusCodeMethodNotAllowed,
HttpStatusCodeNotAcceptable,
HttpStatusCodeProxyAuthenticate,
HttpStatusCodeTimeOut,
HttpStatusCodeConflict,
HttpStatusCodeGone,
HttpStatusCodeLengthRequired,
HttpStatusCodePreconditionFailed,
HttpStatusCodeEntityTooLarge,
HttpStatusCodeUriTooLarge,
HttpStatusCodeUnsupportedMedia,
HttpStatusCodeRangeNotSatsified,
HttpStatusCodeExpectationFailed,
HttpStatusCodeServerError,
HttpStatusCodeNotImplemented,
HttpStatusCodeBadGateway,
HttpStatusCodeServiceUnavailable,
HttpStatusCodeGatewayTimeout,
HttpStatusCodeHttpVersionError
};
// HTTP Status Descriptions (in status code order)
// This array must be kept strictly consistent with respect
// to the status code array above.
public static readonly string[] HttpStatusDescArray = {
"Continue Request",
"Switching Protocols",
"OK",
"CREATED",
"ACCEPTED",
"NON-AUTHORITATIVE INFORMATION",
"NO CONTENT",
"RESET CONTENT",
"PARTIAL CONTENT",
"MULTIPLE CHOICES",
"PERMANENT REDIRECT",
"FOUND",
"SEE OTHER",
"NOT MODIFIED",
"USE PROXY",
"RESERVED CODE 306",
"TEMPORARY REDIRECT",
"BAD REQUEST",
"NOT AUTHORIZED",
"PAYMENT REQUIRED",
"FORBIDDEN",
"NOT FOUND",
"METHOD NOT ALLOWED",
"NOT ACCEPTABLE",
"PROXY AUTHENTICATION REQUIRED",
"TIMEOUT",
"CONFLICT",
"GONE",
"LENGTH REQUIRED",
"PRECONDITION FAILED",
"ENTITY TOO LARGE",
"URI TOO LARGE",
"UNSUPPORTED MEDIA",
"RANGE NOT SATISFIED",
"EXPECTATION FAILED",
"SERVER ERROR",
"NOT IMPLEMENTED",
"BAD GATEWAY",
"SERVICE UNAVAILABLE",
"GATEWAY TIMEOUT",
"HTTP VERSION NOT SUPPORTED"
};
// HTTP Headers
public const string HttpHeaderAccept = "Accept";
public const string HttpHeaderAcceptCharset = "Accept-Charset";
public const string HttpHeaderAcceptEncoding = "Accept-Encoding";
public const string HttpHeaderAcceptLanguage = "Accept-Language";
public const string HttpHeaderAcceptRanges = "Accept-Ranges";
public const string HttpHeaderAge = "Age";
public const string HttpHeaderAllow = "Allow";
public const string HttpHeaderAuthorization = "Authorization";
public const string HttpHeaderCacheControl = "Cache-Control";
public const string HttpHeaderConnection = "Connection";
public const string HttpHeaderContentEncoding = "Content-Encoding";
public const string HttpHeaderContentLanguage = "Content-Language";
public const string HttpHeaderContentLength = "Content-Length";
public const string HttpHeaderContentLocation = "Content-Location";
public const string HttpHeaderContentMD5 = "Content-MD5";
public const string HttpHeaderContentRange = "Content-Range";
public const string HttpHeaderContentType = "Content-Type";
public const string HttpHeaderDate = "Date";
public const string HttpHeaderETag = "ETag";
public const string HttpHeaderExpect = "Expect";
public const string HttpHeaderExpires = "Expires";
public const string HttpHeaderFrom = "From";
public const string HttpHeaderHost = "Host";
public const string HttpHeaderIfMatch = "If-Match";
public const string HttpHeaderIfModifiedSince = "If-Modified-Since";
public const string HttpHeaderIfNoneMatch = "If-None-Match";
public const string HttpHeaderIfRange = "If-Range";
public const string HttpHeaderIfUnmodifiedSince = "If-Unmodified-Since";
public const string HttpHeaderLastModified = "Last-Modified";
public const string HttpHeaderLocation = "Location";
public const string HttpHeaderMaxForwards = "Max-Forwards";
public const string HttpHeaderPragma = "Pragma";
public const string HttpHeaderProxyAuthenticate = "Proxy-Authenticate";
public const string HttpHeaderProxyAuthorization = "Proxy-Authorization";
public const string HttpHeaderRange = "Range";
public const string HttpHeaderReferer = "Referer";
public const string HttpHeaderRetryAfter = "Retry-After";
public const string HttpHeaderServer = "Server";
public const string HttpHeaderTE = "TE";
public const string HttpHeaderTrailer = "Trailer";
public const string HttpHeaderTransferEncoding = "Transfer-Encoding";
public const string HttpHeaderUpgrade = "Upgrade";
public const string HttpHeaderUserAgent = "User-Agent";
public const string HttpHeaderVary = "Vary";
public const string HttpHeaderVia = "Via";
public const string HttpHeaderWarning = "Warning";
public const string HttpHeaderWWWAuthenticate = "WWW-Authenticate";
/// Utility routines
public static string StringToBase64(string str)
{
try
{
byte[] encData_byte = new byte[str.Length];
encData_byte = Util.UTF8.GetBytes(str);
return Convert.ToBase64String(encData_byte);
}
catch
{
return String.Empty;
}
}
public static string Base64ToString(string str)
{
try
{
return Util.Base64ToString(str);
}
catch
{
return String.Empty;
}
}
private const string hvals = "0123456789abcdef";
public static int Hex2Int(string hex)
{
int val = 0;
int sum = 0;
string tmp = null;
if (hex != null)
{
tmp = hex.ToLower();
for (int i = 0; i < tmp.Length; i++)
{
val = hvals.IndexOf(tmp[i]);
if (val == -1)
break;
sum *= 16;
sum += val;
}
}
return sum;
}
// Nonce management
public static string NonceGenerator()
{
return StringToBase64(CreationDate + Guid.NewGuid().ToString());
}
// Dump the specified data stream
public static void Dump(byte[] data)
{
char[] buffer = new char[DumpLineSize];
int cc = 0;
for (int i = 0; i < data.Length; i++)
{
if (i % DumpLineSize == 0) Console.Write("\n{0}: ",i.ToString("d8"));
if (i % 4 == 0) Console.Write(" ");
Console.Write("{0}",data[i].ToString("x2"));
if (data[i] < 127 && data[i] > 31)
buffer[i % DumpLineSize] = (char) data[i];
else
buffer[i % DumpLineSize] = '.';
cc++;
if (i != 0 && (i + 1) % DumpLineSize == 0)
{
Console.Write(" |"+(new String(buffer))+"|");
cc = 0;
}
}
// Finish off any incomplete line
if (cc != 0)
{
for (int i = cc ; i < DumpLineSize; i++)
{
if (i % 4 == 0) Console.Write(" ");
Console.Write(" ");
buffer[i % DumpLineSize] = ' ';
}
Console.WriteLine(" |"+(new String(buffer))+"|");
}
else
{
Console.Write("\n");
}
}
}
// Local exception type
public class RestException : Exception
{
internal int statusCode;
internal string statusDesc;
internal string httpmethod;
internal string httppath;
public RestException(string msg) : base(msg)
{
}
}
}

View File

@@ -1,860 +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;
using System.Collections.Generic;
using System.Xml;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
public class RestAppearanceServices : IRest
{
// private static readonly int PARM_USERID = 0;
// private static readonly int PARM_PATH = 1;
// private bool enabled = false;
private string qPrefix = "appearance";
/// <summary>
/// The constructor makes sure that the service prefix is absolute
/// and the registers the service handler and the allocator.
/// </summary>
public RestAppearanceServices()
{
Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId);
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
// If a relative path was specified for the handler's domain,
// add the standard prefix to make it absolute, e.g. /admin
if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
{
Rest.Log.InfoFormat("{0} Domain is relative, adding absolute prefix", MsgId);
qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
Rest.Log.InfoFormat("{0} Domain is now <{1}>", MsgId, qPrefix);
}
// Register interface using the absolute URI.
Rest.Plugin.AddPathHandler(DoAppearance,qPrefix,Allocate);
// Activate if everything went OK
// enabled = true;
Rest.Log.InfoFormat("{0} User appearance services initialization complete", MsgId);
}
/// <summary>
/// Post-construction, pre-enabled initialization opportunity
/// Not currently exploited.
/// </summary>
public void Initialize()
{
}
/// <summary>
/// Called by the plug-in to halt service processing. Local processing is
/// disabled.
/// </summary>
public void Close()
{
// enabled = false;
Rest.Log.InfoFormat("{0} User appearance services closing down", MsgId);
}
/// <summary>
/// This property is declared locally because it is used a lot and
/// brevity is nice.
/// </summary>
internal string MsgId
{
get { return Rest.MsgId; }
}
#region Interface
/// <summary>
/// The plugin (RestHandler) calls this method to allocate the request
/// state carrier for a new request. It is destroyed when the request
/// completes. All request-instance specific state is kept here. This
/// is registered when this service provider is registered.
/// </summary>
/// <param name=request>Inbound HTTP request information</param>
/// <param name=response>Outbound HTTP request information</param>
/// <param name=qPrefix>REST service domain prefix</param>
/// <returns>A RequestData instance suitable for this service</returns>
private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
{
return (RequestData) new AppearanceRequestData(request, response, prefix);
}
/// <summary>
/// This method is registered with the handler when this service provider
/// is initialized. It is called whenever the plug-in identifies this service
/// provider as the best match for a given request.
/// It handles all aspects of inventory REST processing, i.e. /admin/inventory
/// </summary>
/// <param name=hdata>A consolidated HTTP request work area</param>
private void DoAppearance(RequestData hdata)
{
// !!! REFACTORIMG PROBLEM. This needs rewriting for 0.7
//AppearanceRequestData rdata = (AppearanceRequestData) hdata;
//Rest.Log.DebugFormat("{0} DoAppearance ENTRY", MsgId);
//// If we're disabled, do nothing.
//if (!enabled)
//{
// return;
//}
//// Now that we know this is a serious attempt to
//// access inventory data, we should find out who
//// is asking, and make sure they are authorized
//// to do so. We need to validate the caller's
//// identity before revealing anything about the
//// status quo. Authenticate throws an exception
//// via Fail if no identity information is present.
////
//// With the present HTTP server we can't use the
//// builtin authentication mechanisms because they
//// would be enforced for all in-bound requests.
//// Instead we look at the headers ourselves and
//// handle authentication directly.
//try
//{
// if (!rdata.IsAuthenticated)
// {
// rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName));
// }
//}
//catch (RestException e)
//{
// if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
// {
// Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
// Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
// }
// else
// {
// Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
// Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
// }
// throw (e);
//}
//Rest.Log.DebugFormat("{0} Authenticated {1}", MsgId, rdata.userName);
//// We can only get here if we are authorized
////
//// The requestor may have specified an UUID or
//// a conjoined FirstName LastName string. We'll
//// try both. If we fail with the first, UUID,
//// attempt, we try the other. As an example, the
//// URI for a valid inventory request might be:
////
//// http://<host>:<port>/admin/inventory/Arthur Dent
////
//// Indicating that this is an inventory request for
//// an avatar named Arthur Dent. This is ALL that is
//// required to designate a GET for an entire
//// inventory.
////
//// Do we have at least a user agent name?
//if (rdata.Parameters.Length < 1)
//{
// Rest.Log.WarnFormat("{0} Appearance: No user agent identifier specified", MsgId);
// rdata.Fail(Rest.HttpStatusCodeBadRequest, "no user identity specified");
//}
//// The first parameter MUST be the agent identification, either an UUID
//// or a space-separated First-name Last-Name specification. We check for
//// an UUID first, if anyone names their character using a valid UUID
//// that identifies another existing avatar will cause this a problem...
//try
//{
// rdata.uuid = new UUID(rdata.Parameters[PARM_USERID]);
// Rest.Log.DebugFormat("{0} UUID supplied", MsgId);
// rdata.userProfile = Rest.UserServices.GetUserProfile(rdata.uuid);
//}
//catch
//{
// string[] names = rdata.Parameters[PARM_USERID].Split(Rest.CA_SPACE);
// if (names.Length == 2)
// {
// Rest.Log.DebugFormat("{0} Agent Name supplied [2]", MsgId);
// rdata.userProfile = Rest.UserServices.GetUserProfile(names[0],names[1]);
// }
// else
// {
// Rest.Log.WarnFormat("{0} A Valid UUID or both first and last names must be specified", MsgId);
// rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid user identity");
// }
//}
//// If the user profile is null then either the server is broken, or the
//// user is not known. We always assume the latter case.
//if (rdata.userProfile != null)
//{
// Rest.Log.DebugFormat("{0} User profile obtained for agent {1} {2}",
// MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
//}
//else
//{
// Rest.Log.WarnFormat("{0} No user profile for {1}", MsgId, rdata.path);
// rdata.Fail(Rest.HttpStatusCodeNotFound, "unrecognized user identity");
//}
//// If we get to here, then we have effectively validated the user's
//switch (rdata.method)
//{
// case Rest.HEAD : // Do the processing, set the status code, suppress entity
// DoGet(rdata);
// rdata.buffer = null;
// break;
// case Rest.GET : // Do the processing, set the status code, return entity
// DoGet(rdata);
// break;
// case Rest.PUT : // Update named element
// DoUpdate(rdata);
// break;
// case Rest.POST : // Add new information to identified context.
// DoExtend(rdata);
// break;
// case Rest.DELETE : // Delete information
// DoDelete(rdata);
// break;
// default :
// Rest.Log.WarnFormat("{0} Method {1} not supported for {2}",
// MsgId, rdata.method, rdata.path);
// rdata.Fail(Rest.HttpStatusCodeMethodNotAllowed,
// String.Format("{0} not supported", rdata.method));
// break;
//}
}
#endregion Interface
#region method-specific processing
/// <summary>
/// This method implements GET processing for user's appearance.
/// </summary>
/// <param name=rdata>HTTP service request work area</param>
// private void DoGet(AppearanceRequestData rdata)
// {
// AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID);
//
// if (adata == null)
// {
// rdata.Fail(Rest.HttpStatusCodeNoContent,
// String.Format("appearance data not found for user {0} {1}",
// rdata.userProfile.FirstName, rdata.userProfile.SurName));
// }
// rdata.userAppearance = adata.ToAvatarAppearance(rdata.userProfile.ID);
//
// rdata.initXmlWriter();
//
// FormatUserAppearance(rdata);
//
// // Indicate a successful request
//
// rdata.Complete();
//
// // Send the response to the user. The body will be implicitly
// // constructed from the result of the XML writer.
//
// rdata.Respond(String.Format("Appearance {0} Normal completion", rdata.method));
// }
/// <summary>
/// POST adds NEW information to the user profile database.
/// This effectively resets the appearance before applying those
/// characteristics supplied in the request.
/// </summary>
// private void DoExtend(AppearanceRequestData rdata)
// {
//
// bool created = false;
// bool modified = false;
// string newnode = String.Empty;
//
// Rest.Log.DebugFormat("{0} POST ENTRY", MsgId);
//
// //AvatarAppearance old = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID);
//
// rdata.userAppearance = new AvatarAppearance();
//
// // Although the following behavior is admitted by HTTP I am becoming
// // increasingly doubtful that it is appropriate for REST. If I attempt to
// // add a new record, and it already exists, then it seems to me that the
// // attempt should fail, rather than update the existing record.
// AvatarData adata = null;
// if (GetUserAppearance(rdata))
// {
// modified = rdata.userAppearance != null;
// created = !modified;
// adata = new AvatarData(rdata.userAppearance);
// Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata);
// // Rest.UserServices.UpdateUserProfile(rdata.userProfile);
// }
// else
// {
// created = true;
// adata = new AvatarData(rdata.userAppearance);
// Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata);
// // Rest.UserServices.UpdateUserProfile(rdata.userProfile);
// }
//
// if (created)
// {
// newnode = String.Format("{0} {1}", rdata.userProfile.FirstName,
// rdata.userProfile.SurName);
// // Must include a location header with a URI that identifies the new resource.
//
// rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}{3}{4}",
// rdata.hostname,rdata.port,rdata.path,Rest.UrlPathSeparator, newnode));
// rdata.Complete(Rest.HttpStatusCodeCreated);
//
// }
// else
// {
// if (modified)
// {
// rdata.Complete(Rest.HttpStatusCodeOK);
// }
// else
// {
// rdata.Complete(Rest.HttpStatusCodeNoContent);
// }
// }
//
// rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method));
//
// }
/// <summary>
/// This updates the user's appearance. not all aspects need to be provided,
/// only those supplied will be changed.
/// </summary>
// private void DoUpdate(AppearanceRequestData rdata)
// {
//
// // REFACTORING PROBLEM This was commented out. It doesn't work for 0.7
//
// //bool created = false;
// //bool modified = false;
//
//
// //rdata.userAppearance = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID);
//
// //// If the user exists then this is considered a modification regardless
// //// of what may, or may not be, specified in the payload.
//
// //if (rdata.userAppearance != null)
// //{
// // modified = true;
// // Rest.AvatarServices.UpdateUserAppearance(rdata.userProfile.ID, rdata.userAppearance);
// // Rest.UserServices.UpdateUserProfile(rdata.userProfile);
// //}
//
// //if (created)
// //{
// // rdata.Complete(Rest.HttpStatusCodeCreated);
// //}
// //else
// //{
// // if (modified)
// // {
// // rdata.Complete(Rest.HttpStatusCodeOK);
// // }
// // else
// // {
// // rdata.Complete(Rest.HttpStatusCodeNoContent);
// // }
// //}
//
// rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method));
//
// }
/// <summary>
/// Delete the specified user's appearance. This actually performs a reset
/// to the default avatar appearance, if the info is already there.
/// Existing ownership is preserved. All prior updates are lost and can not
/// be recovered.
/// </summary>
// private void DoDelete(AppearanceRequestData rdata)
// {
// AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID);
//
// if (adata != null)
// {
// AvatarAppearance old = adata.ToAvatarAppearance(rdata.userProfile.ID);
// rdata.userAppearance = new AvatarAppearance();
// rdata.userAppearance.Owner = old.Owner;
// adata = new AvatarData(rdata.userAppearance);
//
// Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata);
//
// rdata.Complete();
// }
// else
// {
//
// rdata.Complete(Rest.HttpStatusCodeNoContent);
// }
//
// rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method));
// }
#endregion method-specific processing
private bool GetUserAppearance(AppearanceRequestData rdata)
{
XmlReader xml;
bool indata = false;
rdata.initXmlReader();
xml = rdata.reader;
while (xml.Read())
{
switch (xml.NodeType)
{
case XmlNodeType.Element :
switch (xml.Name)
{
case "Appearance" :
if (xml.MoveToAttribute("Height"))
{
rdata.userAppearance.AvatarHeight = (float) Convert.ToDouble(xml.Value);
indata = true;
}
// if (xml.MoveToAttribute("Owner"))
// {
// rdata.userAppearance.Owner = (UUID)xml.Value;
// indata = true;
// }
if (xml.MoveToAttribute("Serial"))
{
rdata.userAppearance.Serial = Convert.ToInt32(xml.Value);
indata = true;
}
break;
/*
case "Body" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.BodyItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.BodyAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Skin" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.SkinItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.SkinAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Hair" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.HairItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.HairAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Eyes" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.EyesItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.EyesAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Shirt" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.ShirtItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.ShirtAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Pants" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.PantsItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.PantsAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Shoes" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.ShoesItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.ShoesAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Socks" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.SocksItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.SocksAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Jacket" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.JacketItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.JacketAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Gloves" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.GlovesItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.GlovesAsset = (UUID)xml.Value;
indata = true;
}
break;
case "UnderShirt" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.UnderShirtItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.UnderShirtAsset = (UUID)xml.Value;
indata = true;
}
break;
case "UnderPants" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.UnderPantsItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.UnderPantsAsset = (UUID)xml.Value;
indata = true;
}
break;
case "Skirt" :
if (xml.MoveToAttribute("Item"))
{
rdata.userAppearance.SkirtItem = (UUID)xml.Value;
indata = true;
}
if (xml.MoveToAttribute("Asset"))
{
rdata.userAppearance.SkirtAsset = (UUID)xml.Value;
indata = true;
}
break;
*/
case "Attachment" :
{
int ap;
UUID asset;
UUID item;
if (xml.MoveToAttribute("AtPoint"))
{
ap = Convert.ToInt32(xml.Value);
if (xml.MoveToAttribute("Asset"))
{
asset = new UUID(xml.Value);
if (xml.MoveToAttribute("Asset"))
{
item = new UUID(xml.Value);
rdata.userAppearance.SetAttachment(ap, item, asset);
indata = true;
}
}
}
}
break;
case "Texture" :
if (xml.MoveToAttribute("Default"))
{
rdata.userAppearance.Texture = new Primitive.TextureEntry(new UUID(xml.Value));
indata = true;
}
break;
case "Face" :
{
uint index;
if (xml.MoveToAttribute("Index"))
{
index = Convert.ToUInt32(xml.Value);
if (xml.MoveToAttribute("Id"))
{
rdata.userAppearance.Texture.CreateFace(index).TextureID = new UUID(xml.Value);
indata = true;
}
}
}
break;
case "VisualParameters" :
{
xml.ReadContentAsBase64(rdata.userAppearance.VisualParams,
0, rdata.userAppearance.VisualParams.Length);
indata = true;
}
break;
}
break;
}
}
return indata;
}
private void FormatPart(AppearanceRequestData rdata, string part, UUID item, UUID asset)
{
if (item != UUID.Zero || asset != UUID.Zero)
{
rdata.writer.WriteStartElement(part);
if (item != UUID.Zero)
{
rdata.writer.WriteAttributeString("Item",item.ToString());
}
if (asset != UUID.Zero)
{
rdata.writer.WriteAttributeString("Asset",asset.ToString());
}
rdata.writer.WriteEndElement();
}
}
private void FormatUserAppearance(AppearanceRequestData rdata)
{
Rest.Log.DebugFormat("{0} FormatUserAppearance", MsgId);
if (rdata.userAppearance != null)
{
Rest.Log.DebugFormat("{0} FormatUserAppearance: appearance object exists", MsgId);
rdata.writer.WriteStartElement("Appearance");
rdata.writer.WriteAttributeString("Height", rdata.userAppearance.AvatarHeight.ToString());
// if (rdata.userAppearance.Owner != UUID.Zero)
// rdata.writer.WriteAttributeString("Owner", rdata.userAppearance.Owner.ToString());
rdata.writer.WriteAttributeString("Serial", rdata.userAppearance.Serial.ToString());
/*
FormatPart(rdata, "Body", rdata.userAppearance.BodyItem, rdata.userAppearance.BodyAsset);
FormatPart(rdata, "Skin", rdata.userAppearance.SkinItem, rdata.userAppearance.SkinAsset);
FormatPart(rdata, "Hair", rdata.userAppearance.HairItem, rdata.userAppearance.HairAsset);
FormatPart(rdata, "Eyes", rdata.userAppearance.EyesItem, rdata.userAppearance.EyesAsset);
FormatPart(rdata, "Shirt", rdata.userAppearance.ShirtItem, rdata.userAppearance.ShirtAsset);
FormatPart(rdata, "Pants", rdata.userAppearance.PantsItem, rdata.userAppearance.PantsAsset);
FormatPart(rdata, "Skirt", rdata.userAppearance.SkirtItem, rdata.userAppearance.SkirtAsset);
FormatPart(rdata, "Shoes", rdata.userAppearance.ShoesItem, rdata.userAppearance.ShoesAsset);
FormatPart(rdata, "Socks", rdata.userAppearance.SocksItem, rdata.userAppearance.SocksAsset);
FormatPart(rdata, "Jacket", rdata.userAppearance.JacketItem, rdata.userAppearance.JacketAsset);
FormatPart(rdata, "Gloves", rdata.userAppearance.GlovesItem, rdata.userAppearance.GlovesAsset);
FormatPart(rdata, "UnderShirt", rdata.userAppearance.UnderShirtItem, rdata.userAppearance.UnderShirtAsset);
FormatPart(rdata, "UnderPants", rdata.userAppearance.UnderPantsItem, rdata.userAppearance.UnderPantsAsset);
*/
Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId);
rdata.writer.WriteStartElement("Attachments");
List<AvatarAttachment> attachments = rdata.userAppearance.GetAttachments();
foreach (AvatarAttachment attach in attachments)
{
rdata.writer.WriteStartElement("Attachment");
rdata.writer.WriteAttributeString("AtPoint", attach.AttachPoint.ToString());
rdata.writer.WriteAttributeString("Item", attach.ItemID.ToString());
rdata.writer.WriteAttributeString("Asset", attach.AssetID.ToString());
rdata.writer.WriteEndElement();
}
rdata.writer.WriteEndElement();
Primitive.TextureEntry texture = rdata.userAppearance.Texture;
if (texture != null && (texture.DefaultTexture != null || texture.FaceTextures != null))
{
Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting textures", MsgId);
rdata.writer.WriteStartElement("Texture");
if (texture.DefaultTexture != null)
{
Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting default texture", MsgId);
rdata.writer.WriteAttributeString("Default",
texture.DefaultTexture.TextureID.ToString());
}
if (texture.FaceTextures != null)
{
Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting face textures", MsgId);
for (int i=0; i<texture.FaceTextures.Length;i++)
{
if (texture.FaceTextures[i] != null)
{
rdata.writer.WriteStartElement("Face");
rdata.writer.WriteAttributeString("Index", i.ToString());
rdata.writer.WriteAttributeString("Id",
texture.FaceTextures[i].TextureID.ToString());
rdata.writer.WriteEndElement();
}
}
}
rdata.writer.WriteEndElement();
}
Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting visual parameters", MsgId);
rdata.writer.WriteStartElement("VisualParameters");
rdata.writer.WriteBase64(rdata.userAppearance.VisualParams,0,
rdata.userAppearance.VisualParams.Length);
rdata.writer.WriteEndElement();
rdata.writer.WriteFullEndElement();
}
Rest.Log.DebugFormat("{0} FormatUserAppearance: completed", MsgId);
return;
}
#region appearance RequestData extension
internal class AppearanceRequestData : RequestData
{
/// <summary>
/// These are the inventory specific request/response state
/// extensions.
/// </summary>
internal UUID uuid = UUID.Zero;
internal UserProfileData userProfile = null;
internal AvatarAppearance userAppearance = null;
internal AppearanceRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
: base(request, response, prefix)
{
}
}
#endregion Appearance RequestData extension
}
}

View File

@@ -1,383 +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.Xml;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
public class RestAssetServices : IRest
{
private bool enabled = false;
private string qPrefix = "assets";
// A simple constructor is used to handle any once-only
// initialization of working classes.
public RestAssetServices()
{
Rest.Log.InfoFormat("{0} Asset services initializing", MsgId);
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
// If the handler specifies a relative path for its domain
// then we must add the standard absolute prefix, e.g. /admin
if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
{
Rest.Log.InfoFormat("{0} Prefixing domain name ({1})", MsgId, qPrefix);
qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
Rest.Log.InfoFormat("{0} Fully qualified domain name is <{1}>", MsgId, qPrefix);
}
// Register interface using the fully-qualified prefix
Rest.Plugin.AddPathHandler(DoAsset, qPrefix, Allocate);
// Activate if all went OK
enabled = true;
Rest.Log.InfoFormat("{0} Asset services initialization complete", MsgId);
}
// Post-construction, pre-enabled initialization opportunity
// Not currently exploited.
public void Initialize()
{
}
// Called by the plug-in to halt REST processing. Local processing is
// disabled, and control blocks until all current processing has
// completed. No new processing will be started
public void Close()
{
enabled = false;
Rest.Log.InfoFormat("{0} Asset services ({1}) closing down", MsgId, qPrefix);
}
// Properties
internal string MsgId
{
get { return Rest.MsgId; }
}
#region Interface
private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
{
return (RequestData) new AssetRequestData(request, response, prefix);
}
// Asset Handler
private void DoAsset(RequestData rparm)
{
if (!enabled) return;
AssetRequestData rdata = (AssetRequestData) rparm;
Rest.Log.DebugFormat("{0} REST Asset handler ({1}) ENTRY", MsgId, qPrefix);
// Now that we know this is a serious attempt to
// access inventory data, we should find out who
// is asking, and make sure they are authorized
// to do so. We need to validate the caller's
// identity before revealing anything about the
// status quo. Authenticate throws an exception
// via Fail if no identity information is present.
//
// With the present HTTP server we can't use the
// builtin authentication mechanisms because they
// would be enforced for all in-bound requests.
// Instead we look at the headers ourselves and
// handle authentication directly.
try
{
if (!rdata.IsAuthenticated)
{
rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated"));
}
}
catch (RestException e)
{
if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
{
Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
rdata.request.Headers.Get("Authorization"));
}
else
{
Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
rdata.request.Headers.Get("Authorization"));
}
throw (e);
}
// Remove the prefix and what's left are the parameters. If we don't have
// the parameters we need, fail the request. Parameters do NOT include
// any supplied query values.
if (rdata.Parameters.Length > 0)
{
switch (rdata.method)
{
case "get" :
DoGet(rdata);
break;
case "put" :
DoPut(rdata);
break;
case "post" :
DoPost(rdata);
break;
case "delete" :
default :
Rest.Log.WarnFormat("{0} Asset: Method not supported: {1}",
MsgId, rdata.method);
rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method));
break;
}
}
else
{
Rest.Log.WarnFormat("{0} Asset: No agent information provided", MsgId);
rdata.Fail(Rest.HttpStatusCodeBadRequest, "no agent information provided");
}
Rest.Log.DebugFormat("{0} REST Asset handler EXIT", MsgId);
}
#endregion Interface
/// <summary>
/// The only parameter we recognize is a UUID.If an asset with this identification is
/// found, it's content, base-64 encoded, is returned to the client.
/// </summary>
private void DoGet(AssetRequestData rdata)
{
Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length == 1)
{
UUID uuid = new UUID(rdata.Parameters[0]);
AssetBase asset = Rest.AssetServices.Get(uuid.ToString());
if (asset != null)
{
Rest.Log.DebugFormat("{0} Asset located <{1}>", MsgId, rdata.Parameters[0]);
rdata.initXmlWriter();
rdata.writer.WriteStartElement(String.Empty,"Asset",String.Empty);
rdata.writer.WriteAttributeString("id", asset.ID);
rdata.writer.WriteAttributeString("name", asset.Name);
rdata.writer.WriteAttributeString("desc", asset.Description);
rdata.writer.WriteAttributeString("type", asset.Type.ToString());
rdata.writer.WriteAttributeString("local", asset.Local.ToString());
rdata.writer.WriteAttributeString("temporary", asset.Temporary.ToString());
rdata.writer.WriteBase64(asset.Data,0,asset.Data.Length);
rdata.writer.WriteFullEndElement();
}
else
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
}
}
rdata.Complete();
rdata.Respond(String.Format("Asset <{0}> : Normal completion", rdata.method));
}
/// <summary>
/// UPDATE existing item, if it exists. URI identifies the item in question.
/// The only parameter we recognize is a UUID. The enclosed asset data (base-64 encoded)
/// is decoded and stored in the database, identified by the supplied UUID.
/// </summary>
private void DoPut(AssetRequestData rdata)
{
bool modified = false;
bool created = false;
AssetBase asset = null;
Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length == 1)
{
rdata.initXmlReader();
XmlReader xml = rdata.reader;
if (!xml.ReadToFollowing("Asset"))
{
Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
}
UUID uuid = new UUID(rdata.Parameters[0]);
asset = Rest.AssetServices.Get(uuid.ToString());
modified = (asset != null);
created = !modified;
asset = new AssetBase(uuid, xml.GetAttribute("name"), SByte.Parse(xml.GetAttribute("type")), UUID.Zero.ToString());
asset.Description = xml.GetAttribute("desc");
asset.Local = Int32.Parse(xml.GetAttribute("local")) != 0;
asset.Temporary = Int32.Parse(xml.GetAttribute("temporary")) != 0;
asset.Data = Convert.FromBase64String(xml.ReadElementContentAsString("Asset", ""));
if (asset.ID != rdata.Parameters[0])
{
Rest.Log.WarnFormat("{0} URI and payload disagree on UUID U:{1} vs P:{2}",
MsgId, rdata.Parameters[0], asset.ID);
}
Rest.AssetServices.Store(asset);
}
else
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
}
if (created)
{
rdata.appendStatus(String.Format("<p> Created asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
rdata.Complete(Rest.HttpStatusCodeCreated);
}
else
{
if (modified)
{
rdata.appendStatus(String.Format("<p> Modified asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
rdata.Complete(Rest.HttpStatusCodeOK);
}
else
{
rdata.Complete(Rest.HttpStatusCodeNoContent);
}
}
rdata.Respond(String.Format("Asset {0} : Normal completion", rdata.method));
}
/// <summary>
/// CREATE new item, replace if it exists. URI identifies the context for the item in question.
/// No parameters are required for POST, just thepayload.
/// </summary>
private void DoPost(AssetRequestData rdata)
{
bool modified = false;
bool created = false;
Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length != 0)
{
Rest.Log.WarnFormat("{0} Parameters ignored <{1}>", MsgId, rdata.path);
Rest.Log.InfoFormat("{0} POST of an asset has no parameters", MsgId, rdata.path);
}
rdata.initXmlReader();
XmlReader xml = rdata.reader;
if (!xml.ReadToFollowing("Asset"))
{
Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
}
UUID uuid = new UUID(xml.GetAttribute("id"));
AssetBase asset = Rest.AssetServices.Get(uuid.ToString());
modified = (asset != null);
created = !modified;
asset = new AssetBase(uuid, xml.GetAttribute("name"), SByte.Parse(xml.GetAttribute("type")), UUID.Zero.ToString());
asset.Description = xml.GetAttribute("desc");
asset.Local = Int32.Parse(xml.GetAttribute("local")) != 0;
asset.Temporary = Int32.Parse(xml.GetAttribute("temporary")) != 0;
asset.Data = Convert.FromBase64String(xml.ReadElementContentAsString("Asset", ""));
Rest.AssetServices.Store(asset);
if (created)
{
rdata.appendStatus(String.Format("<p> Created asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
rdata.Complete(Rest.HttpStatusCodeCreated);
}
else
{
if (modified)
{
rdata.appendStatus(String.Format("<p> Modified asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
rdata.Complete(Rest.HttpStatusCodeOK);
}
else
{
rdata.Complete(Rest.HttpStatusCodeNoContent);
}
}
rdata.Respond(String.Format("Asset {0} : Normal completion", rdata.method));
}
/// <summary>
/// Asset processing has no special data area requirements.
/// </summary>
internal class AssetRequestData : RequestData
{
internal AssetRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
: base(request, response, prefix)
{
}
}
}
}

View File

@@ -1,448 +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.Xml;
using System.IO;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
public class RestFileServices : IRest
{
private bool enabled = false;
private string qPrefix = "files";
// A simple constructor is used to handle any once-only
// initialization of working classes.
public RestFileServices()
{
Rest.Log.InfoFormat("{0} File services initializing", MsgId);
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
// If the handler specifies a relative path for its domain
// then we must add the standard absolute prefix, e.g. /admin
if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
{
Rest.Log.InfoFormat("{0} Prefixing domain name ({1})", MsgId, qPrefix);
qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
Rest.Log.InfoFormat("{0} Fully qualified domain name is <{1}>", MsgId, qPrefix);
}
// Register interface using the fully-qualified prefix
Rest.Plugin.AddPathHandler(DoFile, qPrefix, Allocate);
// Activate if all went OK
enabled = true;
Rest.Log.InfoFormat("{0} File services initialization complete", MsgId);
}
// Post-construction, pre-enabled initialization opportunity
// Not currently exploited.
public void Initialize()
{
}
// Called by the plug-in to halt REST processing. Local processing is
// disabled, and control blocks until all current processing has
// completed. No new processing will be started
public void Close()
{
enabled = false;
Rest.Log.InfoFormat("{0} File services ({1}) closing down", MsgId, qPrefix);
}
// Properties
internal string MsgId
{
get { return Rest.MsgId; }
}
#region Interface
private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
{
return (RequestData) new FileRequestData(request, response, prefix);
}
// Asset Handler
private void DoFile(RequestData rparm)
{
if (!enabled) return;
FileRequestData rdata = (FileRequestData) rparm;
Rest.Log.DebugFormat("{0} REST File handler ({1}) ENTRY", MsgId, qPrefix);
// Now that we know this is a serious attempt to
// access file data, we should find out who
// is asking, and make sure they are authorized
// to do so. We need to validate the caller's
// identity before revealing anything about the
// status quo. Authenticate throws an exception
// via Fail if no identity information is present.
//
// With the present HTTP server we can't use the
// builtin authentication mechanisms because they
// would be enforced for all in-bound requests.
// Instead we look at the headers ourselves and
// handle authentication directly.
try
{
if (!rdata.IsAuthenticated)
{
rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated"));
}
}
catch (RestException e)
{
if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
{
Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
rdata.request.Headers.Get("Authorization"));
}
else
{
Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
rdata.request.Headers.Get("Authorization"));
}
throw (e);
}
// Remove the prefix and what's left are the parameters. If we don't have
// the parameters we need, fail the request. Parameters do NOT include
// any supplied query values.
if (rdata.Parameters.Length > 0)
{
switch (rdata.method)
{
case "get" :
DoGet(rdata);
break;
case "put" :
DoPut(rdata);
break;
case "post" :
DoPost(rdata);
break;
case "delete" :
DoDelete(rdata);
break;
default :
Rest.Log.WarnFormat("{0} File: Method not supported: {1}",
MsgId, rdata.method);
rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method));
break;
}
}
else
{
Rest.Log.WarnFormat("{0} File: No agent information provided", MsgId);
rdata.Fail(Rest.HttpStatusCodeBadRequest, "no agent information provided");
}
Rest.Log.DebugFormat("{0} REST File handler EXIT", MsgId);
}
#endregion Interface
/// <summary>
/// The only parameter we recognize is a UUID.If an asset with this identification is
/// found, it's content, base-64 encoded, is returned to the client.
/// </summary>
private void DoGet(FileRequestData rdata)
{
string path = String.Empty;
Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length > 1)
{
try
{
path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
if (File.Exists(path))
{
Rest.Log.DebugFormat("{0} File located <{1}>", MsgId, path);
Byte[] data = File.ReadAllBytes(path);
rdata.initXmlWriter();
rdata.writer.WriteStartElement(String.Empty,"File",String.Empty);
rdata.writer.WriteAttributeString("name", path);
rdata.writer.WriteBase64(data,0,data.Length);
rdata.writer.WriteFullEndElement();
}
else
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, path);
rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0}", path));
}
}
catch (Exception e)
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, e.Message);
rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0} {1}",
path, e.Message));
}
}
rdata.Complete();
rdata.Respond(String.Format("File <{0}> : Normal completion", rdata.method));
}
/// <summary>
/// UPDATE existing item, if it exists. URI identifies the item in question.
/// The only parameter we recognize is a UUID. The enclosed asset data (base-64 encoded)
/// is decoded and stored in the database, identified by the supplied UUID.
/// </summary>
private void DoPut(FileRequestData rdata)
{
bool modified = false;
bool created = false;
string path = String.Empty;
Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length > 1)
{
try
{
path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
bool maymod = File.Exists(path);
rdata.initXmlReader();
XmlReader xml = rdata.reader;
if (!xml.ReadToFollowing("File"))
{
Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
}
Byte[] data = Convert.FromBase64String(xml.ReadElementContentAsString("File", ""));
File.WriteAllBytes(path,data);
modified = maymod;
created = ! maymod;
}
catch (Exception e)
{
Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,
e.Message);
}
}
else
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
}
if (created)
{
rdata.appendStatus(String.Format("<p> Created file {0} <p>", path));
rdata.Complete(Rest.HttpStatusCodeCreated);
}
else
{
if (modified)
{
rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path));
rdata.Complete(Rest.HttpStatusCodeOK);
}
else
{
rdata.Complete(Rest.HttpStatusCodeNoContent);
}
}
rdata.Respond(String.Format("File {0} : Normal completion", rdata.method));
}
/// <summary>
/// CREATE new item, replace if it exists. URI identifies the context for the item in question.
/// No parameters are required for POST, just thepayload.
/// </summary>
private void DoPost(FileRequestData rdata)
{
bool modified = false;
bool created = false;
string path = String.Empty;
Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length > 1)
{
try
{
path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
bool maymod = File.Exists(path);
rdata.initXmlReader();
XmlReader xml = rdata.reader;
if (!xml.ReadToFollowing("File"))
{
Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
}
Byte[] data = Convert.FromBase64String(xml.ReadElementContentAsString("File", ""));
File.WriteAllBytes(path,data);
modified = maymod;
created = ! maymod;
}
catch (Exception e)
{
Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,
e.Message);
}
}
else
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
}
if (created)
{
rdata.appendStatus(String.Format("<p> Created file {0} <p>", path));
rdata.Complete(Rest.HttpStatusCodeCreated);
}
else
{
if (modified)
{
rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path));
rdata.Complete(Rest.HttpStatusCodeOK);
}
else
{
rdata.Complete(Rest.HttpStatusCodeNoContent);
}
}
rdata.Respond(String.Format("File {0} : Normal completion", rdata.method));
}
/// <summary>
/// CREATE new item, replace if it exists. URI identifies the context for the item in question.
/// No parameters are required for POST, just thepayload.
/// </summary>
private void DoDelete(FileRequestData rdata)
{
bool modified = false;
bool created = false;
string path = String.Empty;
Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
if (rdata.Parameters.Length > 1)
{
try
{
path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
if (File.Exists(path))
{
File.Delete(path);
}
}
catch (Exception e)
{
Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,
e.Message);
rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0} {1}",
path, e.Message));
}
}
else
{
Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
}
if (created)
{
rdata.appendStatus(String.Format("<p> Created file {0} <p>", path));
rdata.Complete(Rest.HttpStatusCodeCreated);
}
else
{
if (modified)
{
rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path));
rdata.Complete(Rest.HttpStatusCodeOK);
}
else
{
rdata.Complete(Rest.HttpStatusCodeNoContent);
}
}
rdata.Respond(String.Format("File {0} : Normal completion", rdata.method));
}
/// <summary>
/// File processing has no special data area requirements.
/// </summary>
internal class FileRequestData : RequestData
{
internal FileRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
: base(request, response, prefix)
{
}
}
}
}

View File

@@ -1,662 +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 System.Reflection;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
/// <remarks>
/// The class signature reveals the roles that RestHandler plays.
///
/// [1] It is a sub-class of RestPlugin. It inherits and extends
/// the functionality of this class, constraining it to the
/// specific needs of this REST implementation. This relates
/// to the plug-in mechanism supported by OpenSim, the specifics
/// of which are mostly hidden by RestPlugin.
/// [2] IRestHandler describes the interface that this class
/// exports to service implementations. This is the services
/// management interface.
/// [3] IHttpAgentHandler describes the interface that is exported
/// to the BaseHttpServer in support of this particular HTTP
/// processing model. This is the request interface of the
/// handler.
/// </remarks>
public class RestHandler : RestPlugin, IRestHandler, IHttpAgentHandler
{
// Handler tables: both stream and REST are supported. The path handlers and their
// respective allocators are stored in separate tables.
internal Dictionary<string,RestMethodHandler> pathHandlers = new Dictionary<string,RestMethodHandler>();
internal Dictionary<string,RestMethodAllocator> pathAllocators = new Dictionary<string,RestMethodAllocator>();
internal Dictionary<string,RestStreamHandler> streamHandlers = new Dictionary<string,RestStreamHandler>();
#region local static state
private static bool handlersLoaded = false;
private static List<Type> classes = new List<Type>();
private static List<IRest> handlers = new List<IRest>();
private static Type[] parms = new Type[0];
private static Object[] args = new Object[0];
/// <summary>
/// This static initializer scans the ASSEMBLY for classes that
/// export the IRest interface and builds a list of them. These
/// are later activated by the handler. To add a new handler it
/// is only necessary to create a new services class that implements
/// the IRest interface, and recompile the handler. This gives
/// all of the build-time flexibility of a modular approach
/// while not introducing yet-another module loader. Note that
/// multiple assembles can still be built, each with its own set
/// of handlers. Examples of services classes are RestInventoryServices
/// and RestSkeleton.
/// </summary>
static RestHandler()
{
Module[] mods = Assembly.GetExecutingAssembly().GetModules();
foreach (Module m in mods)
{
Type[] types = m.GetTypes();
foreach (Type t in types)
{
try
{
if (t.GetInterface("IRest") != null)
{
classes.Add(t);
}
}
catch (Exception)
{
Rest.Log.WarnFormat("[STATIC-HANDLER]: #0 Error scanning {1}", t);
Rest.Log.InfoFormat("[STATIC-HANDLER]: #0 {1} is not included", t);
}
}
}
}
#endregion local static state
#region local instance state
/// <summary>
/// This routine loads all of the handlers discovered during
/// instance initialization.
/// A table of all loaded and successfully constructed handlers
/// is built, and this table is then used by the constructor to
/// initialize each of the handlers in turn.
/// NOTE: The loading process does not automatically imply that
/// the handler has registered any kind of an interface, that
/// may be (optionally) done by the handler either during
/// construction, or during initialization.
///
/// I was not able to make this code work within a constructor
/// so it is isolated within this method.
/// </summary>
private void LoadHandlers()
{
lock (handlers)
{
if (!handlersLoaded)
{
ConstructorInfo ci;
Object ht;
foreach (Type t in classes)
{
try
{
ci = t.GetConstructor(parms);
ht = ci.Invoke(args);
handlers.Add((IRest)ht);
}
catch (Exception e)
{
Rest.Log.WarnFormat("{0} Unable to load {1} : {2}", MsgId, t, e.Message);
}
}
handlersLoaded = true;
}
}
}
#endregion local instance state
#region overriding properties
// These properties override definitions
// in the base class.
// Name is used to differentiate the message header.
public override string Name
{
get { return "HANDLER"; }
}
// Used to partition the .ini configuration space.
public override string ConfigName
{
get { return "RestHandler"; }
}
// We have to rename these because we want
// to be able to share the values with other
// classes in our assembly and the base
// names are protected.
public string MsgId
{
get { return base.MsgID; }
}
public string RequestId
{
get { return base.RequestID; }
}
#endregion overriding properties
#region overriding methods
/// <summary>
/// This method is called by OpenSimMain immediately after loading the
/// plugin and after basic server setup, but before running any server commands.
/// </summary>
/// <remarks>
/// Note that entries MUST be added to the active configuration files before
/// the plugin can be enabled.
/// </remarks>
public override void Initialise(OpenSimBase openSim)
{
try
{
// This plugin will only be enabled if the broader
// REST plugin mechanism is enabled.
//Rest.Log.InfoFormat("{0} Plugin is initializing", MsgId);
base.Initialise(openSim);
// IsEnabled is implemented by the base class and
// reflects an overall RestPlugin status
if (!IsEnabled)
{
//Rest.Log.WarnFormat("{0} Plugins are disabled", MsgId);
return;
}
Rest.Log.InfoFormat("{0} Rest <{1}> plugin will be enabled", MsgId, Name);
Rest.Log.InfoFormat("{0} Configuration parameters read from <{1}>", MsgId, ConfigName);
// These are stored in static variables to make
// them easy to reach from anywhere in the assembly.
Rest.main = openSim;
if (Rest.main == null)
throw new Exception("OpenSim base pointer is null");
Rest.Plugin = this;
Rest.Config = Config;
Rest.Prefix = Prefix;
Rest.GodKey = GodKey;
Rest.Authenticate = Rest.Config.GetBoolean("authenticate", Rest.Authenticate);
Rest.Scheme = Rest.Config.GetString("auth-scheme", Rest.Scheme);
Rest.Secure = Rest.Config.GetBoolean("secured", Rest.Secure);
Rest.ExtendedEscape = Rest.Config.GetBoolean("extended-escape", Rest.ExtendedEscape);
Rest.Realm = Rest.Config.GetString("realm", Rest.Realm);
Rest.DumpAsset = Rest.Config.GetBoolean("dump-asset", Rest.DumpAsset);
Rest.Fill = Rest.Config.GetBoolean("path-fill", Rest.Fill);
Rest.DumpLineSize = Rest.Config.GetInt("dump-line-size", Rest.DumpLineSize);
Rest.FlushEnabled = Rest.Config.GetBoolean("flush-on-error", Rest.FlushEnabled);
// Note: Odd spacing is required in the following strings
Rest.Log.InfoFormat("{0} Authentication is {1}required", MsgId,
(Rest.Authenticate ? "" : "not "));
Rest.Log.InfoFormat("{0} Security is {1}enabled", MsgId,
(Rest.Secure ? "" : "not "));
Rest.Log.InfoFormat("{0} Extended URI escape processing is {1}enabled", MsgId,
(Rest.ExtendedEscape ? "" : "not "));
Rest.Log.InfoFormat("{0} Dumping of asset data is {1}enabled", MsgId,
(Rest.DumpAsset ? "" : "not "));
// The supplied prefix MUST be absolute
if (Rest.Prefix.Substring(0,1) != Rest.UrlPathSeparator)
{
Rest.Log.WarnFormat("{0} Prefix <{1}> is not absolute and must be", MsgId, Rest.Prefix);
Rest.Log.InfoFormat("{0} Prefix changed to </{1}>", MsgId, Rest.Prefix);
Rest.Prefix = String.Format("{0}{1}", Rest.UrlPathSeparator, Rest.Prefix);
}
// If data dumping is requested, report on the chosen line
// length.
if (Rest.DumpAsset)
{
Rest.Log.InfoFormat("{0} Dump {1} bytes per line", MsgId, Rest.DumpLineSize);
}
// Load all of the handlers present in the
// assembly
// In principle, as we're an application plug-in,
// most of what needs to be done could be done using
// static resources, however the Open Sim plug-in
// model makes this an instance, so that's what we
// need to be.
// There is only one Communications manager per
// server, and by inference, only one each of the
// user, asset, and inventory servers. So we can cache
// those using a static initializer.
// We move all of this processing off to another
// services class to minimize overlap between function
// and infrastructure.
LoadHandlers();
// The intention of a post construction initializer
// is to allow for setup that is dependent upon other
// activities outside of the agency.
foreach (IRest handler in handlers)
{
try
{
handler.Initialize();
}
catch (Exception e)
{
Rest.Log.ErrorFormat("{0} initialization error: {1}", MsgId, e.Message);
}
}
// Now that everything is setup we can proceed to
// add THIS agent to the HTTP server's handler list
// FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
// have to be handled through the AddHttpHandler interface.
// if (!AddAgentHandler(Rest.Name,this))
// {
// Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId);
// foreach (IRest handler in handlers)
// {
// handler.Close();
// }
// }
}
catch (Exception e)
{
Rest.Log.ErrorFormat("{0} Plugin initialization has failed: {1}", MsgId, e.Message);
}
}
/// <summary>
/// In the interests of efficiency, and because we cannot determine whether
/// or not this instance will actually be harvested, we clobber the only
/// anchoring reference to the working state for this plug-in. What the
/// call to close does is irrelevant to this class beyond knowing that it
/// can nullify the reference when it returns.
/// To make sure everything is copacetic we make sure the primary interface
/// is disabled by deleting the handler from the HTTP server tables.
/// </summary>
public override void Close()
{
Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId);
// FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
// have to be handled through the AddHttpHandler interface.
// try
// {
// RemoveAgentHandler(Rest.Name, this);
// }
// catch (KeyNotFoundException){}
foreach (IRest handler in handlers)
{
handler.Close();
}
}
#endregion overriding methods
#region interface methods
/// <summary>
/// This method is called by the HTTP server to match an incoming
/// request. It scans all of the strings registered by the
/// underlying handlers and looks for the best match. It returns
/// true if a match is found.
/// The matching process could be made arbitrarily complex.
/// Note: The match is case-insensitive.
/// </summary>
public bool Match(OSHttpRequest request, OSHttpResponse response)
{
string path = request.RawUrl.ToLower();
// Rest.Log.DebugFormat("{0} Match ENTRY", MsgId);
try
{
foreach (string key in pathHandlers.Keys)
{
// Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key);
// Note that Match will not necessarily find the handler that will
// actually be used - it does no test for the "closest" fit. It
// simply reflects that at least one possible handler exists.
if (path.StartsWith(key))
{
// Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
// This apparently odd evaluation is needed to prevent a match
// on anything other than a URI token boundary. Otherwise we
// may match on URL's that were not intended for this handler.
return (path.Length == key.Length ||
path.Substring(key.Length, 1) == Rest.UrlPathSeparator);
}
}
path = String.Format("{0}{1}{2}", request.HttpMethod, Rest.UrlMethodSeparator, path);
foreach (string key in streamHandlers.Keys)
{
// Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key);
// Note that Match will not necessarily find the handler that will
// actually be used - it does no test for the "closest" fit. It
// simply reflects that at least one possible handler exists.
if (path.StartsWith(key))
{
// Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
// This apparently odd evaluation is needed to prevent a match
// on anything other than a URI token boundary. Otherwise we
// may match on URL's that were not intended for this handler.
return (path.Length == key.Length ||
path.Substring(key.Length, 1) == Rest.UrlPathSeparator);
}
}
}
catch (Exception e)
{
Rest.Log.ErrorFormat("{0} matching exception for path <{1}> : {2}", MsgId, path, e.Message);
}
return false;
}
/// <summary>
/// This is called by the HTTP server once the handler has indicated
/// that it is able to handle the request.
/// Preconditions:
/// [1] request != null and is a valid request object
/// [2] response != null and is a valid response object
/// Behavior is undefined if preconditions are not satisfied.
/// </summary>
public bool Handle(OSHttpRequest request, OSHttpResponse response)
{
bool handled;
base.MsgID = base.RequestID;
// Debug only
if (Rest.DEBUG)
{
Rest.Log.DebugFormat("{0} ENTRY", MsgId);
Rest.Log.DebugFormat("{0} Agent: {1}", MsgId, request.UserAgent);
Rest.Log.DebugFormat("{0} Method: {1}", MsgId, request.HttpMethod);
for (int i = 0; i < request.Headers.Count; i++)
{
Rest.Log.DebugFormat("{0} Header [{1}] : <{2}> = <{3}>",
MsgId, i, request.Headers.GetKey(i), request.Headers.Get(i));
}
Rest.Log.DebugFormat("{0} URI: {1}", MsgId, request.RawUrl);
}
// If a path handler worked we're done, otherwise try any
// available stream handlers too.
try
{
handled = (FindPathHandler(request, response) ||
FindStreamHandler(request, response));
}
catch (Exception e)
{
// A raw exception indicates that something we weren't expecting has
// happened. This should always reflect a shortcoming in the plugin,
// or a failure to satisfy the preconditions. It should not reflect
// an error in the request itself. Under such circumstances the state
// of the request cannot be determined and we are obliged to mark it
// as 'handled'.
Rest.Log.ErrorFormat("{0} Plugin error: {1}", MsgId, e.Message);
handled = true;
}
Rest.Log.DebugFormat("{0} EXIT", MsgId);
return handled;
}
#endregion interface methods
/// <summary>
/// If there is a stream handler registered that can handle the
/// request, then fine. If the request is not matched, do
/// nothing.
/// Note: The selection is case-insensitive
/// </summary>
private bool FindStreamHandler(OSHttpRequest request, OSHttpResponse response)
{
RequestData rdata = new RequestData(request, response, String.Empty);
string bestMatch = String.Empty;
string path = String.Format("{0}:{1}", rdata.method, rdata.path).ToLower();
Rest.Log.DebugFormat("{0} Checking for stream handler for <{1}>", MsgId, path);
if (!IsEnabled)
{
return false;
}
foreach (string pattern in streamHandlers.Keys)
{
if (path.StartsWith(pattern))
{
if (pattern.Length > bestMatch.Length)
{
bestMatch = pattern;
}
}
}
// Handle using the best match available
if (bestMatch.Length > 0)
{
Rest.Log.DebugFormat("{0} Stream-based handler matched with <{1}>", MsgId, bestMatch);
RestStreamHandler handler = streamHandlers[bestMatch];
rdata.buffer = handler.Handle(rdata.path, rdata.request.InputStream, rdata.request, rdata.response);
rdata.AddHeader(rdata.response.ContentType,handler.ContentType);
rdata.Respond("FindStreamHandler Completion");
}
return rdata.handled;
}
/// <summary>
/// Add a stream handler for the designated HTTP method and path prefix.
/// If the handler is not enabled, the request is ignored. If the path
/// does not start with the REST prefix, it is added. If method-qualified
/// path has not already been registered, the method is added to the active
/// handler table.
/// </summary>
public void AddStreamHandler(string httpMethod, string path, RestMethod method)
{
if (!IsEnabled)
{
return;
}
if (!path.StartsWith(Rest.Prefix))
{
path = String.Format("{0}{1}", Rest.Prefix, path);
}
path = String.Format("{0}{1}{2}", httpMethod, Rest.UrlMethodSeparator, path);
// Conditionally add to the list
if (!streamHandlers.ContainsKey(path))
{
streamHandlers.Add(path, new RestStreamHandler(httpMethod, path, method));
Rest.Log.DebugFormat("{0} Added handler for {1}", MsgId, path);
}
else
{
Rest.Log.WarnFormat("{0} Ignoring duplicate handler for {1}", MsgId, path);
}
}
/// <summary>
/// Given the supplied request/response, if the handler is enabled, the inbound
/// information is used to match an entry in the active path handler tables, using
/// the method-qualified path information. If a match is found, then the handler is
/// invoked. The result is the boolean result of the handler, or false if no
/// handler was located. The boolean indicates whether or not the request has been
/// handled, not whether or not the request was successful - that information is in
/// the response.
/// Note: The selection process is case-insensitive
/// </summary>
internal bool FindPathHandler(OSHttpRequest request, OSHttpResponse response)
{
RequestData rdata = null;
string bestMatch = null;
if (!IsEnabled)
{
return false;
}
// Conditionally add to the list
Rest.Log.DebugFormat("{0} Checking for path handler for <{1}>", MsgId, request.RawUrl);
foreach (string pattern in pathHandlers.Keys)
{
if (request.RawUrl.ToLower().StartsWith(pattern))
{
if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
{
bestMatch = pattern;
}
}
}
if (!String.IsNullOrEmpty(bestMatch))
{
rdata = pathAllocators[bestMatch](request, response, bestMatch);
Rest.Log.DebugFormat("{0} Path based REST handler matched with <{1}>", MsgId, bestMatch);
try
{
pathHandlers[bestMatch](rdata);
}
// A plugin generated error indicates a request-related error
// that has been handled by the plugin.
catch (RestException r)
{
Rest.Log.WarnFormat("{0} Request failed: {1}", MsgId, r.Message);
}
}
return (rdata == null) ? false : rdata.handled;
}
/// <summary>
/// A method handler and a request allocator are stored using the designated
/// path as a key. If an entry already exists, it is replaced by the new one.
/// </summary>
public void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ra)
{
if (!IsEnabled)
{
return;
}
if (pathHandlers.ContainsKey(path))
{
Rest.Log.DebugFormat("{0} Replacing handler for <${1}>", MsgId, path);
pathHandlers.Remove(path);
}
if (pathAllocators.ContainsKey(path))
{
Rest.Log.DebugFormat("{0} Replacing allocator for <${1}>", MsgId, path);
pathAllocators.Remove(path);
}
Rest.Log.DebugFormat("{0} Adding path handler for {1}", MsgId, path);
pathHandlers.Add(path, mh);
pathAllocators.Add(path, ra);
}
}
}

View File

@@ -1,246 +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 System.Reflection;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
public class RestTestServices : IRest
{
private bool enabled = false;
private string qPrefix = "test";
// A simple constructor is used to handle any once-only
// initialization of working classes.
public RestTestServices()
{
Rest.Log.InfoFormat("{0} Test services initializing", MsgId);
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
// If a relative path was specified, make it absolute by adding
// the standard prefix, e.g. /admin
if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
{
Rest.Log.InfoFormat("{0} Domain is relative, adding absolute prefix", MsgId);
qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
Rest.Log.InfoFormat("{0} Domain is now <{1}>", MsgId, qPrefix);
}
// Load test cases
loadTests();
foreach (ITest test in tests)
{
test.Initialize();
}
// Register interface
Rest.Plugin.AddPathHandler(DoTests,qPrefix,Allocate);
// Activate
enabled = true;
Rest.Log.InfoFormat("{0} Test services initialization complete", MsgId);
}
// Post-construction, pre-enabled initialization opportunity
// Not currently exploited.
public void Initialize()
{
}
// Called by the plug-in to halt REST processing. Local processing is
// disabled, and control blocks until all current processing has
// completed. No new processing will be started
public void Close()
{
enabled = false;
foreach (ITest test in tests)
{
test.Close();
}
Rest.Log.InfoFormat("{0} Test services closing down", MsgId);
}
// Properties
internal string MsgId
{
get { return Rest.MsgId; }
}
#region Interface
private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
{
return new RequestData(request, response, prefix);
}
// Inventory Handler
private void DoTests(RequestData rdata)
{
if (!enabled)
return;
// Now that we know this is a serious attempt to
// access inventory data, we should find out who
// is asking, and make sure they are authorized
// to do so. We need to validate the caller's
// identity before revealing anything about the
// status quo. Authenticate throws an exception
// via Fail if no identity information is present.
//
// With the present HTTP server we can't use the
// builtin authentication mechanisms because they
// would be enforced for all in-bound requests.
// Instead we look at the headers ourselves and
// handle authentication directly.
try
{
if (!rdata.IsAuthenticated)
{
rdata.Fail(Rest.HttpStatusCodeNotAuthorized,
String.Format("user \"{0}\" could not be authenticated", rdata.userName));
}
}
catch (RestException e)
{
if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
{
Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
}
else
{
Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
}
throw (e);
}
// Check that a test was specified
if (rdata.Parameters.Length < 1)
{
Rest.Log.DebugFormat("{0} Insufficient parameters", MsgId);
rdata.Fail(Rest.HttpStatusCodeBadRequest, "not enough parameters");
}
// Select the test
foreach (ITest test in tests)
{
if (!rdata.handled)
test.Execute(rdata);
}
}
#endregion Interface
private static bool testsLoaded = false;
private static List<Type> classes = new List<Type>();
private static List<ITest> tests = new List<ITest>();
private static Type[] parms = new Type[0];
private static Object[] args = new Object[0];
static RestTestServices()
{
Module[] mods = Assembly.GetExecutingAssembly().GetModules();
foreach (Module m in mods)
{
Type[] types = m.GetTypes();
foreach (Type t in types)
{
try
{
if (t.GetInterface("ITest") != null)
{
classes.Add(t);
}
}
catch (Exception e)
{
Rest.Log.WarnFormat("[STATIC-TEST] Unable to include test {0} : {1}", t, e.Message);
}
}
}
}
/// <summary>
/// This routine loads all of the handlers discovered during
/// instance initialization. Each handler is responsible for
/// registering itself with this handler.
/// I was not able to make this code work in a constructor.
/// </summary>
private void loadTests()
{
lock (tests)
{
if (!testsLoaded)
{
ConstructorInfo ci;
Object ht;
foreach (Type t in classes)
{
try
{
if (t.GetInterface("ITest") != null)
{
ci = t.GetConstructor(parms);
ht = ci.Invoke(args);
tests.Add((ITest)ht);
Rest.Log.InfoFormat("{0} Test {1} added", MsgId, t);
}
}
catch (Exception e)
{
Rest.Log.WarnFormat("{0} Unable to load test {1} : {2}", MsgId, t, e.Message);
}
}
testsLoaded = true;
}
}
}
}
}

View File

@@ -1,46 +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.
*
*/
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
/// <summary>
/// This interface represents the boundary between the general purpose
/// REST plugin handling, and the functionally specific handlers. The
/// handler knows only to initialzie and terminate all such handlers
/// that it finds.
/// </summary>
internal interface ITest
{
void Initialize();
void Execute(RequestData rdata);
void Close();
}
}

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 OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
{
public class Remote : ITest
{
private static readonly int PARM_TESTID = 0;
private static readonly int PARM_COMMAND = 1;
private static readonly int PARM_MOVE_AVATAR = 2;
private static readonly int PARM_MOVE_X = 3;
private static readonly int PARM_MOVE_Y = 4;
private static readonly int PARM_MOVE_Z = 5;
private bool enabled = false;
// No constructor code is required.
public Remote()
{
Rest.Log.InfoFormat("{0} Remote services constructor", MsgId);
}
// Post-construction, pre-enabled initialization opportunity
// Not currently exploited.
public void Initialize()
{
enabled = true;
Rest.Log.InfoFormat("{0} Remote services initialized", MsgId);
}
// Called by the plug-in to halt REST processing. Local processing is
// disabled, and control blocks until all current processing has
// completed. No new processing will be started
public void Close()
{
enabled = false;
Rest.Log.InfoFormat("{0} Remote services closing down", MsgId);
}
// Properties
internal string MsgId
{
get { return Rest.MsgId; }
}
// Remote Handler
// Key information of interest here is the Parameters array, each
// entry represents an element of the URI, with element zero being
// the
public void Execute(RequestData rdata)
{
if (!enabled) return;
// If we can't relate to what's there, leave it for others.
if (rdata.Parameters.Length == 0 || rdata.Parameters[PARM_TESTID] != "remote")
return;
Rest.Log.DebugFormat("{0} REST Remote handler ENTRY", MsgId);
// Remove the prefix and what's left are the parameters. If we don't have
// the parameters we need, fail the request. Parameters do NOT include
// any supplied query values.
if (rdata.Parameters.Length > 1)
{
switch (rdata.Parameters[PARM_COMMAND].ToLower())
{
case "move" :
DoMove(rdata);
break;
default :
DoHelp(rdata);
break;
}
}
else
{
DoHelp(rdata);
}
}
private void DoHelp(RequestData rdata)
{
rdata.body = Help;
rdata.Complete();
rdata.Respond("Help");
}
private void DoMove(RequestData rdata)
{
if (rdata.Parameters.Length < 6)
{
Rest.Log.WarnFormat("{0} Move: No movement information provided", MsgId);
rdata.Fail(Rest.HttpStatusCodeBadRequest, "no movement information provided");
}
else
{
string[] names = rdata.Parameters[PARM_MOVE_AVATAR].Split(Rest.CA_SPACE);
ScenePresence presence = null;
Scene scene = null;
if (names.Length != 2)
{
rdata.Fail(Rest.HttpStatusCodeBadRequest,
String.Format("invalid avatar name: <{0}>",rdata.Parameters[PARM_MOVE_AVATAR]));
}
Rest.Log.WarnFormat("{0} '{1}' command received for {2} {3}",
MsgId, rdata.Parameters[0], names[0], names[1]);
// The first parameter should be an avatar name, look for the
// avatar in the known regions first.
Rest.main.SceneManager.ForEachScene(delegate(Scene s)
{
s.ForEachRootScenePresence(delegate(ScenePresence sp)
{
if (sp.Firstname == names[0] && sp.Lastname == names[1])
{
scene = s;
presence = sp;
}
});
});
if (presence != null)
{
Rest.Log.DebugFormat("{0} Move : Avatar {1} located in region {2}",
MsgId, rdata.Parameters[PARM_MOVE_AVATAR], scene.RegionInfo.RegionName);
try
{
float x = Convert.ToSingle(rdata.Parameters[PARM_MOVE_X]);
float y = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Y]);
float z = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Z]);
Vector3 vector = new Vector3(x, y, z);
presence.MoveToTarget(vector, false, false);
}
catch (Exception e)
{
rdata.Fail(Rest.HttpStatusCodeBadRequest,
String.Format("invalid parameters: {0}", e.Message));
}
}
else
{
rdata.Fail(Rest.HttpStatusCodeBadRequest,
String.Format("avatar {0} not present", rdata.Parameters[PARM_MOVE_AVATAR]));
}
rdata.Complete();
rdata.Respond("OK");
}
}
private static readonly string Help =
"<html>"
+ "<head><title>Remote Command Usage</title></head>"
+ "<body>"
+ "<p>Supported commands are:</p>"
+ "<dl>"
+ "<dt>move/avatar-name/x/y/z</dt>"
+ "<dd>moves the specified avatar to another location</dd>"
+ "</dl>"
+ "</body>"
+ "</html>"
;
}
}

View File

@@ -1,228 +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.IO;
using System.Xml.Serialization;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.ApplicationPlugins.Rest.Regions
{
public partial class RestRegionPlugin : RestPlugin
{
#region GET methods
public string GetHandler(string request, string path, string param,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// foreach (string h in httpRequest.Headers.AllKeys)
// foreach (string v in httpRequest.Headers.GetValues(h))
// m_log.DebugFormat("{0} IsGod: {1} -> {2}", MsgID, h, v);
MsgID = RequestID;
m_log.DebugFormat("{0} GET path {1} param {2}", MsgID, path, param);
try
{
// param empty: regions list
if (String.IsNullOrEmpty(param)) return GetHandlerRegions(httpResponse);
// param not empty: specific region
return GetHandlerRegion(httpResponse, param);
}
catch (Exception e)
{
return Failure(httpResponse, OSHttpStatusCode.ServerErrorInternalError, "GET", e);
}
}
public string GetHandlerRegions(IOSHttpResponse httpResponse)
{
RestXmlWriter rxw = new RestXmlWriter(new StringWriter());
rxw.WriteStartElement(String.Empty, "regions", String.Empty);
foreach (Scene s in App.SceneManager.Scenes)
{
rxw.WriteStartElement(String.Empty, "uuid", String.Empty);
rxw.WriteString(s.RegionInfo.RegionID.ToString());
rxw.WriteEndElement();
}
rxw.WriteEndElement();
return rxw.ToString();
}
protected string ShortRegionInfo(string key, string value)
{
RestXmlWriter rxw = new RestXmlWriter(new StringWriter());
if (String.IsNullOrEmpty(value) ||
String.IsNullOrEmpty(key)) return null;
rxw.WriteStartElement(String.Empty, "region", String.Empty);
rxw.WriteStartElement(String.Empty, key, String.Empty);
rxw.WriteString(value);
rxw.WriteEndDocument();
return rxw.ToString();
}
public string GetHandlerRegion(IOSHttpResponse httpResponse, string param)
{
// be resilient and don't get confused by a terminating '/'
param = param.TrimEnd(new char[]{'/'});
string[] comps = param.Split('/');
UUID regionID = (UUID)comps[0];
m_log.DebugFormat("{0} GET region UUID {1}", MsgID, regionID.ToString());
if (UUID.Zero == regionID) throw new Exception("missing region ID");
Scene scene = null;
App.SceneManager.TryGetScene(regionID, out scene);
if (null == scene) return Failure(httpResponse, OSHttpStatusCode.ClientErrorNotFound,
"GET", "cannot find region {0}", regionID.ToString());
RegionDetails details = new RegionDetails(scene.RegionInfo);
// m_log.DebugFormat("{0} GET comps {1}", MsgID, comps.Length);
// for (int i = 0; i < comps.Length; i++) m_log.DebugFormat("{0} GET comps[{1}] >{2}<", MsgID, i, comps[i]);
if (1 == comps.Length)
{
// complete region details requested
RestXmlWriter rxw = new RestXmlWriter(new StringWriter());
XmlSerializer xs = new XmlSerializer(typeof(RegionDetails));
xs.Serialize(rxw, details, _xmlNs);
return rxw.ToString();
}
if (2 == comps.Length)
{
string resp = ShortRegionInfo(comps[1], details[comps[1]]);
if (null != resp) return resp;
// m_log.DebugFormat("{0} GET comps advanced: >{1}<", MsgID, comps[1]);
// check for {terrain,stats,prims}
switch (comps[1].ToLower())
{
case "terrain":
return RegionTerrain(httpResponse, scene);
case "stats":
return RegionStats(httpResponse, scene);
case "prims":
return RegionPrims(httpResponse, scene, Vector3.Zero, Vector3.Zero);
}
}
if (3 == comps.Length)
{
switch (comps[1].ToLower())
{
case "prims":
string[] subregion = comps[2].Split(',');
if (subregion.Length == 6)
{
Vector3 min, max;
try
{
min = new Vector3((float)Double.Parse(subregion[0], Culture.NumberFormatInfo), (float)Double.Parse(subregion[1], Culture.NumberFormatInfo), (float)Double.Parse(subregion[2], Culture.NumberFormatInfo));
max = new Vector3((float)Double.Parse(subregion[3], Culture.NumberFormatInfo), (float)Double.Parse(subregion[4], Culture.NumberFormatInfo), (float)Double.Parse(subregion[5], Culture.NumberFormatInfo));
}
catch (Exception)
{
return Failure(httpResponse, OSHttpStatusCode.ClientErrorBadRequest,
"GET", "invalid subregion parameter");
}
return RegionPrims(httpResponse, scene, min, max);
}
else
{
return Failure(httpResponse, OSHttpStatusCode.ClientErrorBadRequest,
"GET", "invalid subregion parameter");
}
}
}
return Failure(httpResponse, OSHttpStatusCode.ClientErrorBadRequest,
"GET", "too many parameters {0}", param);
}
#endregion GET methods
protected string RegionTerrain(IOSHttpResponse httpResponse, Scene scene)
{
httpResponse.SendChunked = true;
httpResponse.ContentType = "text/xml";
return scene.Heightmap.SaveToXmlString();
//return Failure(httpResponse, OSHttpStatusCode.ServerErrorNotImplemented,
// "GET", "terrain not implemented");
}
protected string RegionStats(IOSHttpResponse httpResponse, Scene scene)
{
int users = scene.GetRootAgentCount();
int objects = scene.Entities.Count - users;
RestXmlWriter rxw = new RestXmlWriter(new StringWriter());
rxw.WriteStartElement(String.Empty, "region", String.Empty);
rxw.WriteStartElement(String.Empty, "stats", String.Empty);
rxw.WriteStartElement(String.Empty, "users", String.Empty);
rxw.WriteString(users.ToString());
rxw.WriteEndElement();
rxw.WriteStartElement(String.Empty, "objects", String.Empty);
rxw.WriteString(objects.ToString());
rxw.WriteEndElement();
rxw.WriteEndDocument();
return rxw.ToString();
}
protected string RegionPrims(IOSHttpResponse httpResponse, Scene scene, Vector3 min, Vector3 max)
{
httpResponse.SendChunked = true;
httpResponse.ContentType = "text/xml";
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
if (serialiser != null)
serialiser.SavePrimsToXml2(scene, new StreamWriter(httpResponse.OutputStream), min, max);
return "";
}
}
}

View File

@@ -1,136 +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.IO;
using System.Xml.Serialization;
using OpenMetaverse;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.ApplicationPlugins.Rest.Regions
{
public partial class RestRegionPlugin : RestPlugin
{
#region GET methods
public string GetRegionInfoHandler(string request, string path, string param,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// foreach (string h in httpRequest.Headers.AllKeys)
// foreach (string v in httpRequest.Headers.GetValues(h))
// m_log.DebugFormat("{0} IsGod: {1} -> {2}", MsgID, h, v);
MsgID = RequestID;
m_log.DebugFormat("{0} GET path {1} param {2}", MsgID, path, param);
try
{
// param empty: regions list
// if (String.IsNullOrEmpty(param))
return GetRegionInfoHandlerRegions(httpResponse);
// // param not empty: specific region
// return GetRegionInfoHandlerRegion(httpResponse, param);
}
catch (Exception e)
{
return Failure(httpResponse, OSHttpStatusCode.ServerErrorInternalError, "GET", e);
}
}
public string GetRegionInfoHandlerRegions(IOSHttpResponse httpResponse)
{
RestXmlWriter rxw = new RestXmlWriter(new StringWriter());
// regions info
rxw.WriteStartElement(String.Empty, "regions", String.Empty);
{
// regions info: number of regions
rxw.WriteStartAttribute(String.Empty, "number", String.Empty);
rxw.WriteValue(App.SceneManager.Scenes.Count);
rxw.WriteEndAttribute();
// regions info: max number of regions
rxw.WriteStartAttribute(String.Empty, "max", String.Empty);
if (App.ConfigSource.Source.Configs["RemoteAdmin"] != null)
{
rxw.WriteValue(App.ConfigSource.Source.Configs["RemoteAdmin"].GetInt("region_limit", -1));
}
else
{
rxw.WriteValue(-1);
}
rxw.WriteEndAttribute();
// regions info: region
foreach (Scene s in App.SceneManager.Scenes)
{
rxw.WriteStartElement(String.Empty, "region", String.Empty);
rxw.WriteStartAttribute(String.Empty, "uuid", String.Empty);
rxw.WriteString(s.RegionInfo.RegionID.ToString());
rxw.WriteEndAttribute();
rxw.WriteStartAttribute(String.Empty, "name", String.Empty);
rxw.WriteString(s.RegionInfo.RegionName);
rxw.WriteEndAttribute();
rxw.WriteStartAttribute(String.Empty, "x", String.Empty);
rxw.WriteValue(s.RegionInfo.RegionLocX);
rxw.WriteEndAttribute();
rxw.WriteStartAttribute(String.Empty, "y", String.Empty);
rxw.WriteValue(s.RegionInfo.RegionLocY);
rxw.WriteEndAttribute();
rxw.WriteStartAttribute(String.Empty, "external_hostname", String.Empty);
rxw.WriteString(s.RegionInfo.ExternalHostName);
rxw.WriteEndAttribute();
rxw.WriteStartAttribute(String.Empty, "ip", String.Empty);
rxw.WriteString(s.RegionInfo.InternalEndPoint.ToString());
rxw.WriteEndAttribute();
int users = s.GetRootAgentCount();
rxw.WriteStartAttribute(String.Empty, "avatars", String.Empty);
rxw.WriteValue(users);
rxw.WriteEndAttribute();
rxw.WriteStartAttribute(String.Empty, "objects", String.Empty);
rxw.WriteValue(s.Entities.Count - users);
rxw.WriteEndAttribute();
rxw.WriteEndElement();
}
}
return rxw.ToString();
}
#endregion GET methods
}
}

View File

@@ -1,122 +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.IO;
using OpenMetaverse;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.ApplicationPlugins.Rest.Regions
{
public partial class RestRegionPlugin : RestPlugin
{
#region POST methods
public string PostHandler(string request, string path, string param,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// foreach (string h in httpRequest.Headers.AllKeys)
// foreach (string v in httpRequest.Headers.GetValues(h))
// m_log.DebugFormat("{0} IsGod: {1} -> {2}", MsgID, h, v);
MsgID = RequestID;
m_log.DebugFormat("{0} POST path {1} param {2}", MsgID, path, param);
try
{
// param empty: new region post
if (!IsGod(httpRequest))
// XXX: this needs to be turned into a FailureUnauthorized(...)
return Failure(httpResponse, OSHttpStatusCode.ClientErrorUnauthorized,
"GET", "you are not god");
if (String.IsNullOrEmpty(param)) return CreateRegion(httpRequest, httpResponse);
// Parse region ID and other parameters
param = param.TrimEnd(new char[] {'/'});
string[] comps = param.Split('/');
UUID regionID = (UUID) comps[0];
m_log.DebugFormat("{0} POST region UUID {1}", MsgID, regionID.ToString());
if (UUID.Zero == regionID) throw new Exception("missing region ID");
Scene scene = null;
App.SceneManager.TryGetScene(regionID, out scene);
if (null == scene)
return Failure(httpResponse, OSHttpStatusCode.ClientErrorNotFound,
"POST", "cannot find region {0}", regionID.ToString());
if (2 == comps.Length)
{
// check for {prims}
switch (comps[1].ToLower())
{
case "prims":
return LoadPrims(request, httpRequest, httpResponse, scene);
}
}
return Failure(httpResponse, OSHttpStatusCode.ClientErrorNotFound,
"POST", "url {0} not supported", param);
}
catch (Exception e)
{
return Failure(httpResponse, OSHttpStatusCode.ServerErrorInternalError, "POST", e);
}
}
public string CreateRegion(IOSHttpRequest request, IOSHttpResponse response)
{
RestXmlWriter rxw = new RestXmlWriter(new StringWriter());
rxw.WriteStartElement(String.Empty, "regions", String.Empty);
foreach (Scene s in App.SceneManager.Scenes)
{
rxw.WriteStartElement(String.Empty, "uuid", String.Empty);
rxw.WriteString(s.RegionInfo.RegionID.ToString());
rxw.WriteEndElement();
}
rxw.WriteEndElement();
return rxw.ToString();
}
public string LoadPrims(string requestBody, IOSHttpRequest request, IOSHttpResponse response, Scene scene)
{
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
if (serialiser != null)
serialiser.LoadPrimsFromXml2(scene, new StringReader(requestBody), true);
return "";
}
#endregion POST methods
}
}

View File

@@ -1,98 +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.Xml.Serialization;
using OpenMetaverse;
using OpenSim.Framework;
namespace OpenSim.ApplicationPlugins.Rest.Regions
{
[XmlRoot(ElementName="region", IsNullable = false)]
public class RegionDetails
{
public string region_name;
public string region_id;
public uint region_x;
public uint region_y;
public string region_owner;
public string region_owner_id;
public uint region_http_port;
public uint region_port;
public string region_server_uri;
public string region_external_hostname;
public RegionDetails()
{
}
public RegionDetails(RegionInfo regInfo)
{
region_name = regInfo.RegionName;
region_id = regInfo.RegionID.ToString();
region_x = regInfo.RegionLocX;
region_y = regInfo.RegionLocY;
region_owner_id = regInfo.EstateSettings.EstateOwner.ToString();
region_http_port = regInfo.HttpPort;
region_server_uri = regInfo.ServerURI;
region_external_hostname = regInfo.ExternalHostName;
Uri uri = new Uri(region_server_uri);
region_port = (uint)uri.Port;
}
public string this[string idx]
{
get
{
switch (idx.ToLower())
{
case "name":
return region_name;
case "id":
return region_id;
case "location":
return String.Format("<x>{0}</x><y>{1}</y>", region_x, region_y);
case "owner":
return region_owner;
case "owner_id":
return region_owner_id;
case "http_port":
return region_http_port.ToString();
case "server_uri":
return region_server_uri;
case "external_hostname":
case "hostname":
return region_external_hostname;
default:
return null;
}
}
}
}
}

View File

@@ -1,11 +0,0 @@
<Addin id="OpenSim.ApplicationPlugins.Rest.Regions" version="0.1">
<Runtime>
<Import assembly="OpenSim.ApplicationPlugins.Rest.Regions.dll"/>
</Runtime>
<Dependencies>
<Addin id="OpenSim" version="0.5" />
</Dependencies>
<Extension path = "/OpenSim/Startup">
<Plugin id="RestRegions" type="OpenSim.ApplicationPlugins.Rest.Regions.RestRegionPlugin" />
</Extension>
</Addin>

View File

@@ -1,417 +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 System.IO;
using System.Reflection;
using System.Xml;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.ApplicationPlugins.Rest
{
public abstract class RestPlugin : IApplicationPlugin
{
#region properties
protected static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IConfig _config; // Configuration source: Rest Plugins
private IConfig _pluginConfig; // Configuration source: Plugin specific
private OpenSimBase _app; // The 'server'
private BaseHttpServer _httpd; // The server's RPC interface
private string _prefix; // URL prefix below
// which all REST URLs
// are living
// private StringWriter _sw = null;
// private RestXmlWriter _xw = null;
private string _godkey;
private int _reqk;
[ThreadStatic]
private static string _threadRequestID = String.Empty;
/// <summary>
/// Return an ever increasing request ID for logging
/// </summary>
protected string RequestID
{
get { return _reqk++.ToString(); }
set { _reqk = Convert.ToInt32(value); }
}
/// <summary>
/// Thread-constant message IDs for logging.
/// </summary>
protected string MsgID
{
get { return String.Format("[REST-{0}] #{1}", Name, _threadRequestID); }
set { _threadRequestID = value; }
}
/// <summary>
/// Returns true if Rest Plugins are enabled.
/// </summary>
public bool PluginsAreEnabled
{
get { return null != _config; }
}
/// <summary>
/// Returns true if specific Rest Plugin is enabled.
/// </summary>
public bool IsEnabled
{
get
{
return (null != _pluginConfig) && _pluginConfig.GetBoolean("enabled", false);
}
}
/// <summary>
/// OpenSimMain application
/// </summary>
public OpenSimBase App
{
get { return _app; }
}
/// <summary>
/// RPC server
/// </summary>
public BaseHttpServer HttpServer
{
get { return _httpd; }
}
/// <summary>
/// URL prefix to use for all REST handlers
/// </summary>
public string Prefix
{
get { return _prefix; }
}
/// <summary>
/// Access to GOD password string
/// </summary>
protected string GodKey
{
get { return _godkey; }
}
/// <summary>
/// Configuration of the plugin
/// </summary>
public IConfig Config
{
get { return _pluginConfig; }
}
/// <summary>
/// Name of the plugin
/// </summary>
public abstract string Name { get; }
/// <summary>
/// Return the config section name
/// </summary>
public abstract string ConfigName { get; }
// public XmlTextWriter XmlWriter
// {
// get
// {
// if (null == _xw)
// {
// _sw = new StringWriter();
// _xw = new RestXmlWriter(_sw);
// _xw.Formatting = Formatting.Indented;
// }
// return _xw;
// }
// }
// public string XmlWriterResult
// {
// get
// {
// _xw.Flush();
// _xw.Close();
// _xw = null;
// return _sw.ToString();
// }
// }
#endregion properties
#region methods
// TODO: required by IPlugin, but likely not at all right
private string m_version = "0.0";
public string Version
{
get { return m_version; }
}
public void Initialise()
{
m_log.Info("[RESTPLUGIN]: " + Name + " cannot be default-initialized!");
throw new PluginNotInitialisedException(Name);
}
/// <summary>
/// This method is called by OpenSimMain immediately after loading the
/// plugin and after basic server setup, but before running any server commands.
/// </summary>
/// <remarks>
/// Note that entries MUST be added to the active configuration files before
/// the plugin can be enabled.
/// </remarks>
public virtual void Initialise(OpenSimBase openSim)
{
RequestID = "0";
MsgID = RequestID;
try
{
if ((_config = openSim.ConfigSource.Source.Configs["RestPlugins"]) == null)
{
m_log.WarnFormat("{0} Rest Plugins not configured", MsgID);
return;
}
if (!_config.GetBoolean("enabled", false))
{
//m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID);
return;
}
_app = openSim;
_httpd = openSim.HttpServer;
// Retrieve GOD key value, if any.
_godkey = _config.GetString("god_key", String.Empty);
// Retrive prefix if any.
_prefix = _config.GetString("prefix", "/admin");
// Get plugin specific config
_pluginConfig = openSim.ConfigSource.Source.Configs[ConfigName];
m_log.InfoFormat("{0} Rest Plugins Enabled", MsgID);
}
catch (Exception e)
{
// we can safely ignore this, as it just means that
// the key lookup in Configs failed, which signals to
// us that noone is interested in our services...they
// don't know what they are missing out on...
// NOTE: Under the present OpenSimulator implementation it is
// not possible for the openSimulator pointer to be null. However
// were the implementation to be changed, this could
// result in a silent initialization failure. Harmless
// except for lack of function and lack of any
// diagnostic indication as to why. The same is true if
// the HTTP server reference is bad.
// We should at least issue a message...
m_log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message);
m_log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString());
}
}
public virtual void PostInitialise()
{
}
private List<RestStreamHandler> _handlers = new List<RestStreamHandler>();
private Dictionary<string, IHttpAgentHandler> _agents = new Dictionary<string, IHttpAgentHandler>();
/// <summary>
/// Add a REST stream handler to the underlying HTTP server.
/// </summary>
/// <param name="httpMethod">GET/PUT/POST/DELETE or
/// similar</param>
/// <param name="path">URL prefix</param>
/// <param name="method">RestMethod handler doing the actual work</param>
public virtual void AddRestStreamHandler(string httpMethod, string path, RestMethod method)
{
if (!IsEnabled) return;
if (!path.StartsWith(_prefix))
{
path = String.Format("{0}{1}", _prefix, path);
}
RestStreamHandler h = new RestStreamHandler(httpMethod, path, method);
_httpd.AddStreamHandler(h);
_handlers.Add(h);
m_log.DebugFormat("{0} Added REST handler {1} {2}", MsgID, httpMethod, path);
}
/// <summary>
/// Add a powerful Agent handler to the underlying HTTP
/// server.
/// </summary>
/// <param name="agentName">name of agent handler</param>
/// <param name="handler">agent handler method</param>
/// <returns>false when the plugin is disabled or the agent
/// handler could not be added. Any generated exceptions are
/// allowed to drop through to the caller, i.e. ArgumentException.
/// </returns>
public bool AddAgentHandler(string agentName, IHttpAgentHandler handler)
{
if (!IsEnabled) return false;
_agents.Add(agentName, handler);
// return _httpd.AddAgentHandler(agentName, handler);
return false;
}
/// <summary>
/// Remove a powerful Agent handler from the underlying HTTP
/// server.
/// </summary>
/// <param name="agentName">name of agent handler</param>
/// <param name="handler">agent handler method</param>
/// <returns>false when the plugin is disabled or the agent
/// handler could not be removed. Any generated exceptions are
/// allowed to drop through to the caller, i.e. KeyNotFound.
/// </returns>
public bool RemoveAgentHandler(string agentName, IHttpAgentHandler handler)
{
if (!IsEnabled) return false;
if (_agents[agentName] == handler)
{
_agents.Remove(agentName);
// return _httpd.RemoveAgentHandler(agentName, handler);
}
return false;
}
/// <summary>
/// Check whether the HTTP request came from god; that is, is
/// the god_key as configured in the config section supplied
/// via X-OpenSim-Godkey?
/// </summary>
/// <param name="request">HTTP request header</param>
/// <returns>true when the HTTP request came from god.</returns>
protected bool IsGod(IOSHttpRequest request)
{
string[] keys = request.Headers.GetValues("X-OpenSim-Godkey");
if (null == keys) return false;
// we take the last key supplied
return keys[keys.Length - 1] == _godkey;
}
/// <summary>
/// Checks wether the X-OpenSim-Password value provided in the
/// HTTP header is indeed the password on file for the avatar
/// specified by the UUID
/// </summary>
protected bool IsVerifiedUser(IOSHttpRequest request, UUID uuid)
{
// XXX under construction
return false;
}
/// <summary>
/// Clean up and remove all handlers that were added earlier.
/// </summary>
public virtual void Close()
{
foreach (RestStreamHandler h in _handlers)
{
_httpd.RemoveStreamHandler(h.HttpMethod, h.Path);
}
_handlers = null;
// foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
// {
// _httpd.RemoveAgentHandler(h.Key, h.Value);
// }
_agents = null;
}
public virtual void Dispose()
{
Close();
}
/// <summary>
/// Return a failure message.
/// </summary>
/// <param name="method">origin of the failure message</param>
/// <param name="message">failure message</param>
/// <remarks>This should probably set a return code as
/// well. (?)</remarks>
protected string Failure(IOSHttpResponse response, OSHttpStatusCode status,
string method, string format, params string[] msg)
{
string m = String.Format(format, msg);
response.StatusCode = (int) status;
response.StatusDescription = m;
m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, m);
return String.Format("<error>{0}</error>", m);
}
/// <summary>
/// Return a failure message.
/// </summary>
/// <param name="method">origin of the failure message</param>
/// <param name="e">exception causing the failure message</param>
/// <remarks>This should probably set a return code as
/// well. (?)</remarks>
public string Failure(IOSHttpResponse response, OSHttpStatusCode status,
string method, Exception e)
{
string m = String.Format("exception occurred: {0}", e.Message);
response.StatusCode = (int) status;
response.StatusDescription = m;
m_log.DebugFormat("{0} {1} failed: {2}", MsgID, method, e.ToString());
m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, e.Message);
return String.Format("<error>{0}</error>", e.Message);
}
#endregion methods
}
}

View File

@@ -1,276 +0,0 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation xml:lang="en">
Open Simulator Export/Import XML schema
August 2008
</xsd:documentation>
</xsd:annotation>
<!-- WARNING!!!
This is currently a draft, it does not reflect
what is exported, nor what will be understood
on import. It is included as a working document
and this comment will be removed at such time as
the schema corresponds to reality.
-->
<!--
REST-related information
Inventory data is always framed by an
inventory element. Consists of zero or
more elements representing either folders
or items within those folders. The inventory
element represents the "real" root folder.
-->
<xsd:element name="inventory" type="inventory_ct" />
<!--
The inventory complex type is just an arbitrary
sequence of folders and items. In reality it is
typically just folders. Both item and folder
have corresponding complex types. It is distinct
from folders insofar as it has no other defining
attributes.
-->
<xsd:complexType name="inventory_ct">
<xsd:element name="folder" type="folder_ct" maxOccurs="unbounded"/>
<xsd:element name="item" type="item_ct" maxOccurs="unbounded" />
</xsd:complexType>
<xsd:complexType name="folder_ct">
<xsd:attribute name="UUID" type="uuid_st" />
<xsd:attribute name="name" type="name_st" />
<xsd:attribute name="type" type="folder_type_st" />
<xsd:attribute name="description" type="xsd:string" /> <!-- added -->
<xsd:attribute name="version" type="unsignedShort" />
<xsd:attribute name="owner" type="uuid_st" />
<xsd:attribute name="creator" type="uuid_st" /> <!-- added -->
<xsd:attribute name="creationdate" type="date_st" /> <!-- added -->
<xsd:attribute name="parent" type="uuid_st" />
<xsd:element name="permissions" type="permissions_ct" maxOccurs="unbounded" /> <!-- added -->
<xsd:element name="folder" type="folder_ct" maxOccurs="unbounded" />
<xsd:element name="item" type="item_ct" maxOccurs="unbounded" />
</xsd:complexType>
<xsd:complexType name="item_ct">
<xsd:attribute name="UUID" type="uuid_st" />
<xsd:attribute name="name" type="name_st" />
<xsd:attribute name="type" type="inventory_type_st" />
<xsd:attribute name="description" type="xsd:string" />
<xsd:attribute name="version" type="unsignedShort" /> <!-- added -->
<xsd:attribute name="owner" type="uuid_st" />
<xsd:attribute name="creator" type="uuid_st" />
<xsd:attribute name="creationdate" type="date_st" />
<xsd:attribute name="folder" type="uuid_st" />
<xsd:attribute name="groupid" type="uuid_st" />
<xsd:attribute name="groupowned" type="xsd:boolean" />
<xsd:attribute name="saletype" type="sale_st" />
<xsd:attribute name="saleprice" type="xsd:decimal" />
<xsd:element name="permissions" type="permissions_ct" maxOccurs="unbounded" />
</xsd:complexType>
<xsd:complexType name="asset_ct">
<xsd:attribute name="UUID" type="uuid_st" />
<xsd:attribute name="name" type="name_st" />
<xsd:attribute name="type" type="asset_type_st" />
<xsd:attribute name="description" type="xsd:string" />
<xsd:attribute name="version" type="unsignedShort" /> <!-- added -->
<xsd:attribute name="owner" type="uuid_st" />
<xsd:attribute name="creator" type="uuid_st" />
<xsd:attribute name="creationdate" type="date_st" />
<xsd:attribute name="temporary" type="xsd:boolean" />
<xsd:attribute name="local" type="xsd:boolean" />
<xsd:attribute name="inline" type="xsd:boolean" />
</xsd:complexType>
<!-- Constrained Simple Data types -->
<!--
We need to specify name as a simple type because on
some platforms it is constrained by a certain length
limitation. For completeness we indicate that whitespace
should be preserved exactly as specified.
-->
<xsd:simpleType name="name_st">
<xsd:restriction base="xsd:string">
<whiteSpace value="preserve" />
<minLength value="0" />
<maxLength value="64" />
</xsd:restriction>
</xsd:simpleType>
<!--
Type information in the folder is meant to indicate
the preferred asset type for this folder. As such, that
currently corresponds to the type values allowed for
assets, however that is not mandated, so for
now at least I'll represent this as a distinct
enumeration.
This seems inappropriate; it seems like the folder's
content should reflect the InventoryType classifications
rather than the asset types.
-->
<xsd:simpleType name="folder_type_st">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Texture" />
<xsd:enumeration value="Sound" />
<xsd:enumeration value="CallingCard" />
<xsd:enumeration value="Landmark" />
<xsd:enumeration value="Script" />
<xsd:enumeration value="Clothing" />
<xsd:enumeration value="Object" />
<xsd:enumeration value="Notecard" />
<xsd:enumeration value="LSLText" />
<xsd:enumeration value="LSLByteCode" />
<xsd:enumeration value="TextureTGA" />
<xsd:enumeration value="BodyPart" />
<xsd:enumeration value="SoundWAV" />
<xsd:enumeration value="ImageTGA" />
<xsd:enumeration value="ImageJPEG" />
<xsd:enumeration value="Animation" />
<xsd:enumeration value="Gesture" />
<xsd:enumeration value="Simstate" />
<xsd:enumeration value="Unknown" />
<xsd:enumeration value="LostAndFoundFolder" />
<xsd:enumeration value="SnapshotFolder" />
<xsd:enumeration value="TrashFolder" />
<xsd:enumeration value="Folder" />
<xsd:enumeration value="RootFolder" />
</xsd:restriction>
</xsd:simpleType>
<!--
Inventory item type designates an asset class, rather
than a specific asset type. For example, "SnapShot"
might include a number of asset types such as JPEG,
TGA, etc.. This is not a consistent interpretation,
classifications such as LostAndFound are meta-types
relative to asset classes.
These types should be abstract and not be tied to a
specific platform. A world's import facility should be
responsible for mapping these to meaningful internal
representations.
These types were based on information in:
libsecondlife/InventoryManager.cs
-->
<xsd:simpleType name="inventory_type_st">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Texture" />
<xsd:enumeration value="Sound" />
<xsd:enumeration value="CallingCard" />
<xsd:enumeration value="Landmark" />
<xsd:enumeration value="Script" />
<xsd:enumeration value="Clothing" />
<xsd:enumeration value="Object" />
<xsd:enumeration value="Notecard" />
<xsd:enumeration value="LSL" />
<xsd:enumeration value="LSLBytecode" />
<xsd:enumeration value="TextureTGA" />
<xsd:enumeration value="BodyPart" />
<xsd:enumeration value="Snapshot" />
<xsd:enumeration value="Attachment" />
<xsd:enumeration value="Wearable" />
<xsd:enumeration value="Animation" />
<xsd:enumeration value="Gesture" />
<xsd:enumeration value="Folder" />
<xsd:enumeration value="Unknown" />
<xsd:enumeration value="LostAndFound" />
<xsd:enumeration value="Trash" />
<xsd:enumeration value="Root" />
</xsd:restriction>
</xsd:simpleType>
<!--
The asset types seem to be even more disarrayed than
the inventory types. It seems to be little more than
a reiteration of the inventory type information,
which adds little or nothing to the overall data
model.
Of course, given that these are drawn from the
libsecondlife definitions, we aren't at liberty to
simply redefine them in place. But the XML definitions
here could be made more useful.
These types were based on information in:
libsecondlife/AssetManager.cs
-->
<xsd:simpleType name="asset_type_st">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Texture" />
<xsd:enumeration value="Sound" />
<xsd:enumeration value="CallingCard" />
<xsd:enumeration value="Landmark" />
<xsd:enumeration value="Script" />
<xsd:enumeration value="Clothing" />
<xsd:enumeration value="Object" />
<xsd:enumeration value="Notecard" />
<xsd:enumeration value="LSLText" />
<xsd:enumeration value="LSLByteCode" />
<xsd:enumeration value="TextureTGA" />
<xsd:enumeration value="BodyPart" />
<xsd:enumeration value="SoundWAV" />
<xsd:enumeration value="ImageTGA" />
<xsd:enumeration value="ImageJPEG" />
<xsd:enumeration value="Animation" />
<xsd:enumeration value="Gesture" />
<xsd:enumeration value="Simstate" />
<xsd:enumeration value="Unknown" />
<xsd:enumeration value="LostAndFoundFolder" />
<xsd:enumeration value="SnapshotFolder" />
<xsd:enumeration value="TrashFolder" />
<xsd:enumeration value="Folder" />
<xsd:enumeration value="RootFolder" />
</xsd:restriction>
</xsd:simpleType>
<!-- This is describing the apparent form of a UUID. If
we ever want a more metaphysical definition we'll
need to add to it.
-->
<xsd:simpleType name="uuid_st">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
</xsd:restriction>
</xsd:simpleType>
<!-- This constrains the date representation. Currently
it is simply an integer representing the elapsed
?? since ??.
-->
<xsd:simpleType name="date_st">
<xsd:restriction base="xsd:positiveInteger">
</xsd:restriction>
</xsd:simpleType>
<!-- This constrains the representation of sale price.
Currently it is a simple decimal with no unit
specified.
Issues: interoperability.
-->
<xsd:simpleType name="sale_st">
<xsd:restriction base="xsd:decimal">
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -143,8 +143,8 @@ namespace OpenSim.Framework.Capabilities
/// <param name="handler"></param>
public void RegisterHandler(string capName, IRequestHandler handler)
{
m_capsHandlers[capName] = handler;
//m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
m_capsHandlers[capName] = handler;
}
/// <summary>

View File

@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Capabilities
/// </summary>
public class CapsHandlers
{
private Dictionary <string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
private IHttpServer m_httpListener;
private string m_httpListenerHostName;
private uint m_httpListenerPort;
@@ -158,7 +158,7 @@ namespace OpenSim.Framework.Capabilities
/// capabilities and their handler details.
/// </summary>
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
public Hashtable GetCapsDetails(bool excludeSeed)
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
{
Hashtable caps = new Hashtable();
string protocol = "http://";
@@ -175,11 +175,26 @@ namespace OpenSim.Framework.Capabilities
if (excludeSeed && "SEED" == capsName)
continue;
if (requestedCaps != null && !requestedCaps.Contains(capsName))
continue;
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
}
}
return caps;
}
/// <summary>
/// Returns a copy of the dictionary of all the HTTP cap handlers
/// </summary>
/// <returns>
/// The dictionary copy. The key is the capability name, the value is the HTTP handler.
/// </returns>
public Dictionary<string, IRequestHandler> GetCapsHandlers()
{
lock (m_capsHandlers)
return new Dictionary<string, IRequestHandler>(m_capsHandlers);
}
}
}

View File

@@ -0,0 +1,116 @@
/*
* 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.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Web;
using log4net;
using Nini.Config;
using OpenMetaverse;
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 AvatarPickerSearchHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IPeople m_PeopleService;
public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description)
: base("GET", path, name, description)
{
m_PeopleService = peopleService;
}
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string names = query.GetOne("names");
string psize = query.GetOne("page_size");
string pnumber = query.GetOne("page");
if (m_PeopleService == null)
return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse);
if (string.IsNullOrEmpty(names) || names.Length < 3)
return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse);
m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names);
int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize));
int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber));
// Full content request
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
//httpResponse.ContentLength = ??;
httpResponse.ContentType = "application/llsd+xml";
List<UserData> users = m_PeopleService.GetUserData(names, page_size, page_number);
LLSDAvatarPicker osdReply = new LLSDAvatarPicker();
osdReply.next_page_url = httpRequest.RawUrl;
foreach (UserData u in users)
osdReply.agents.Array.Add(ConvertUserData(u));
string reply = LLSDHelpers.SerialiseLLSDReply(osdReply);
return System.Text.Encoding.UTF8.GetBytes(reply);
}
private LLSDPerson ConvertUserData(UserData user)
{
LLSDPerson p = new LLSDPerson();
p.legacy_first_name = user.FirstName;
p.legacy_last_name = user.LastName;
p.display_name = user.FirstName + " " + user.LastName;
if (user.LastName.StartsWith("@"))
p.username = user.FirstName.ToLower() + user.LastName.ToLower();
else
p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
p.id = user.Id;
p.is_display_name_default = false;
return p;
}
private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse)
{
m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names);
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return System.Text.Encoding.UTF8.GetBytes(string.Empty);
}
}
}

View File

@@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
{
public class FetchInventory2Handler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_inventoryService;
@@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
return llsdItem;
}
}
}
}

View File

@@ -64,7 +64,7 @@ namespace OpenSim.Capabilities.Handlers
m_assetService = assService;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
@@ -189,6 +189,7 @@ namespace OpenSim.Capabilities.Handlers
newTexture.Flags = AssetFlags.Collectable;
newTexture.Temporary = true;
newTexture.Local = true;
m_assetService.Store(newTexture);
WriteTextureData(httpRequest, httpResponse, newTexture, format);
return true;

View File

@@ -0,0 +1,76 @@
/*
* 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 Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
using OpenMetaverse;
namespace OpenSim.Capabilities.Handlers
{
public class UploadBakedTextureServerConnector : ServiceConnector
{
private IAssetService m_AssetService;
private string m_ConfigName = "CapsService";
public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
if (configName != String.Empty)
m_ConfigName = configName;
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
string assetService = serverConfig.GetString("AssetService", String.Empty);
if (assetService == String.Empty)
throw new Exception("No AssetService in config file");
Object[] args = new Object[] { config };
m_AssetService =
ServerUtils.LoadPlugin<IAssetService>(assetService, args);
if (m_AssetService == null)
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
// NEED TO FIX THIS
OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, "");
server.AddStreamHandler(new RestStreamHandler(
"POST",
"/CAPS/UploadBakedTexture/",
new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture,
"UploadBakedTexture",
"Upload Baked Texture Capability"));
}
}
}

View File

@@ -25,35 +25,27 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenSim.Framework.Servers.HttpServer;
using OpenMetaverse;
namespace OpenSim.ApplicationPlugins.Rest.Inventory
namespace OpenSim.Framework.Capabilities
{
/// <remarks>
/// The handler delegates are not noteworthy. The allocator allows
/// a given handler to optionally subclass the base RequestData
/// structure to carry any locally required per-request state
/// needed.
/// </remarks>
public delegate void RestMethodHandler(RequestData rdata);
public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path);
/// <summary>
/// This interface exports the generic plugin-handling services
/// available to each loaded REST services module (IRest implementation)
/// </summary>
internal interface IRestHandler
[OSDMap]
public class LLSDAvatarPicker
{
string MsgId { get; }
string RequestId { get; }
void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ma);
void AddStreamHandler(string httpMethod, string path, RestMethod method);
public string next_page_url;
// an array of LLSDPerson
public OSDArray agents = new OSDArray();
}
}
[OSDMap]
public class LLSDPerson
{
public string username;
public string display_name;
//'display_name_next_update':d"1970-01-01T00:00:00Z"
public string legacy_first_name;
public string legacy_last_name;
public UUID id;
public bool is_display_name_default;
}
}

View File

@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Capabilities
m_method = method;
}
public override byte[] Handle(string path, Stream request,
protected override byte[] ProcessRequest(string path, Stream request,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
//Encoding encoding = Util.UTF8;

View File

@@ -50,6 +50,7 @@ namespace OpenSim.Data
public interface IGridUserData
{
GridUserData Get(string userID);
GridUserData[] GetAll(string query);
bool Store(GridUserData data);
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
namespace OpenSim.Data
{
public interface IProfilesData
{
OSDArray GetClassifiedRecords(UUID creatorId);
bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result);
bool DeleteClassifiedRecord(UUID recordId);
OSDArray GetAvatarPicks(UUID avatarId);
UserProfilePick GetPickInfo(UUID avatarId, UUID pickId);
bool UpdatePicksRecord(UserProfilePick pick);
bool DeletePicksRecord(UUID pickId);
bool GetAvatarNotes(ref UserProfileNotes note);
bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result);
bool GetAvatarProperties(ref UserProfileProperties props, ref string result);
bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
bool GetUserAppData(ref UserAppData props, ref string result);
bool SetUserAppData(UserAppData props, ref string result);
OSDArray GetUserImageAssets(UUID avatarId);
}
}

View File

@@ -50,7 +50,7 @@ namespace OpenSim.Data.MSSQL
{
}
public GridUserData Get(string userID)
public new GridUserData Get(string userID)
{
GridUserData[] ret = Get("UserID", userID);
@@ -60,5 +60,10 @@ namespace OpenSim.Data.MSSQL
return ret[0];
}
public GridUserData[] GetAll(string userID)
{
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
}
}
}

View File

@@ -2100,7 +2100,7 @@ VALUES
parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
if (prim.DynAttrs.Count > 0)
if (prim.DynAttrs.CountNamespaces > 0)
parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
else
parameters.Add(_Database.CreateParameter("DynAttrs", null));

View File

@@ -1153,7 +1153,7 @@ COMMIT
BEGIN TRANSACTION
ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
ALTER TABLE prims ADD DynAttrs TEXT;
COMMIT
@@ -1161,10 +1161,10 @@ COMMIT
BEGIN TRANSACTION
ALTER TABLE prims ADD COLUMN `PhysicsShapeType` tinyint(4) NOT NULL default '0';
ALTER TABLE prims ADD COLUMN `Density` double NOT NULL default '1000';
ALTER TABLE prims ADD COLUMN `GravityModifier` double NOT NULL default '1';
ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
ALTER TABLE prims ADD `PhysicsShapeType` tinyint(4) NOT NULL default '0';
ALTER TABLE prims ADD `Density` double NOT NULL default '1000';
ALTER TABLE prims ADD `GravityModifier` double NOT NULL default '1';
ALTER TABLE prims ADD `Friction` double NOT NULL default '0.6';
ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5';
COMMIT

View File

@@ -142,7 +142,8 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message);
m_log.Error(
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e);
}
}
}
@@ -209,8 +210,11 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}",
asset.FullID, asset.Name, e.Message);
m_log.Error(
string.Format(
"[ASSET DB]: MySQL failure creating asset {0} with name {1}. Exception ",
asset.FullID, asset.Name)
, e);
}
}
}
@@ -241,10 +245,11 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: " +
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
m_log.Error(
string.Format(
"[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
asset.FullID, asset.Name),
e);
}
}
}
@@ -284,8 +289,8 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
m_log.Error(
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
}
}
}
@@ -344,7 +349,11 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
m_log.Error(
string.Format(
"[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}. Exception ",
start, count),
e);
}
}
}

View File

@@ -46,7 +46,7 @@ namespace OpenSim.Data.MySQL
public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "GridUserStore") {}
public GridUserData Get(string userID)
public new GridUserData Get(string userID)
{
GridUserData[] ret = Get("UserID", userID);
@@ -56,6 +56,9 @@ namespace OpenSim.Data.MySQL
return ret[0];
}
public GridUserData[] GetAll(string userID)
{
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
}
}
}

View File

@@ -47,13 +47,10 @@ namespace OpenSim.Data.MySQL
public void DeleteOld()
{
uint now = (uint)Util.UnixTimeSinceEpoch();
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 WEEK", m_Realm);
ExecuteNonQuery(cmd);
}

View File

@@ -52,7 +52,7 @@ namespace OpenSim.Data.MySQL
private string m_connectionString;
private object m_dbLock = new object();
protected Assembly Assembly
protected virtual Assembly Assembly
{
get { return GetType().Assembly; }
}
@@ -173,9 +173,9 @@ namespace OpenSim.Data.MySQL
"ParticleSystem, ClickAction, Material, " +
"CollisionSound, CollisionSoundVolume, " +
"PassTouches, " +
"LinkNumber, MediaURL, DynAttrs, " +
"LinkNumber, MediaURL, KeyframeMotion, " +
"PhysicsShapeType, Density, GravityModifier, " +
"Friction, Restitution " +
"Friction, Restitution, DynAttrs " +
") values (" + "?UUID, " +
"?CreationDate, ?Name, ?Text, " +
"?Description, ?SitName, ?TouchName, " +
@@ -208,9 +208,9 @@ namespace OpenSim.Data.MySQL
"?ColorB, ?ColorA, ?ParticleSystem, " +
"?ClickAction, ?Material, ?CollisionSound, " +
"?CollisionSoundVolume, ?PassTouches, " +
"?LinkNumber, ?MediaURL, ?DynAttrs, " +
"?LinkNumber, ?MediaURL, ?KeyframeMotion, " +
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
"?Friction, ?Restitution)";
"?Friction, ?Restitution, ?DynAttrs)";
FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
@@ -455,7 +455,9 @@ namespace OpenSim.Data.MySQL
foreach (SceneObjectPart prim in prims.Values)
{
if (prim.ParentUUID == UUID.Zero)
{
objects[prim.UUID] = new SceneObjectGroup(prim);
}
}
// Add all of the children objects to the SOGs
@@ -1307,6 +1309,19 @@ namespace OpenSim.Data.MySQL
else
prim.DynAttrs = new DAMap();
if (!(row["KeyframeMotion"] is DBNull))
{
Byte[] data = (byte[])row["KeyframeMotion"];
if (data.Length > 0)
prim.KeyframeMotion = KeyframeMotion.FromData(null, data);
else
prim.KeyframeMotion = null;
}
else
{
prim.KeyframeMotion = null;
}
prim.PhysicsShapeType = (byte)Convert.ToInt32(row["PhysicsShapeType"].ToString());
prim.Density = (float)(double)row["Density"];
prim.GravityModifier = (float)(double)row["GravityModifier"];
@@ -1659,8 +1674,12 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
if (prim.KeyframeMotion != null)
cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize());
else
cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]);
if (prim.DynAttrs.Count > 0)
if (prim.DynAttrs.CountNamespaces > 0)
cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
else
cmd.Parameters.AddWithValue("DynAttrs", null);

File diff suppressed because it is too large Load Diff

View File

@@ -50,6 +50,11 @@ namespace OpenSim.Data.MySQL
get { return GetType().Assembly; }
}
/// <summary>
/// Number of days that must pass before we update the access time on an asset when it has been fetched.
/// </summary>
private const int DaysBetweenAccessTimeUpdates = 30;
private bool m_enableCompression = false;
private string m_connectionString;
private object m_dbLock = new object();
@@ -133,10 +138,10 @@ namespace OpenSim.Data.MySQL
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand(
"SELECT name, description, asset_type, local, temporary, asset_flags, creator_id, data FROM xassetsmeta JOIN xassetsdata ON xassetsmeta.hash = xassetsdata.hash WHERE id=?id",
"SELECT Name, Description, AccessTime, AssetType, Local, Temporary, AssetFlags, CreatorID, Data FROM XAssetsMeta JOIN XAssetsData ON XAssetsMeta.Hash = XAssetsData.Hash WHERE ID=?ID",
dbcon))
{
cmd.Parameters.AddWithValue("?id", assetID.ToString());
cmd.Parameters.AddWithValue("?ID", assetID.ToString());
try
{
@@ -144,18 +149,18 @@ namespace OpenSim.Data.MySQL
{
if (dbReader.Read())
{
asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["asset_type"], dbReader["creator_id"].ToString());
asset.Data = (byte[])dbReader["data"];
asset.Description = (string)dbReader["description"];
asset = new AssetBase(assetID, (string)dbReader["Name"], (sbyte)dbReader["AssetType"], dbReader["CreatorID"].ToString());
asset.Data = (byte[])dbReader["Data"];
asset.Description = (string)dbReader["Description"];
string local = dbReader["local"].ToString();
string local = dbReader["Local"].ToString();
if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
asset.Local = true;
else
asset.Local = false;
asset.Temporary = Convert.ToBoolean(dbReader["temporary"]);
asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["asset_flags"]);
asset.Temporary = Convert.ToBoolean(dbReader["Temporary"]);
asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
if (m_enableCompression)
{
@@ -171,12 +176,14 @@ namespace OpenSim.Data.MySQL
// asset.ID, asset.Name, asset.Data.Length, compressedLength);
}
}
UpdateAccessTime(asset.Metadata, (int)dbReader["AccessTime"]);
}
}
}
catch (Exception e)
{
m_log.Error("[MYSQL XASSET DATA]: MySql failure fetching asset " + assetID + ": " + e.Message);
m_log.Error(string.Format("[MYSQL XASSET DATA]: Failure fetching asset {0}", assetID), e);
}
}
}
@@ -192,6 +199,8 @@ namespace OpenSim.Data.MySQL
/// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
public void StoreAsset(AssetBase asset)
{
// m_log.DebugFormat("[XASSETS DB]: Storing asset {0} {1}", asset.Name, asset.ID);
lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
@@ -242,23 +251,23 @@ namespace OpenSim.Data.MySQL
{
using (MySqlCommand cmd =
new MySqlCommand(
"replace INTO xassetsmeta(id, hash, name, description, asset_type, local, temporary, create_time, access_time, asset_flags, creator_id)" +
"VALUES(?id, ?hash, ?name, ?description, ?asset_type, ?local, ?temporary, ?create_time, ?access_time, ?asset_flags, ?creator_id)",
"replace INTO XAssetsMeta(ID, Hash, Name, Description, AssetType, Local, Temporary, CreateTime, AccessTime, AssetFlags, CreatorID)" +
"VALUES(?ID, ?Hash, ?Name, ?Description, ?AssetType, ?Local, ?Temporary, ?CreateTime, ?AccessTime, ?AssetFlags, ?CreatorID)",
dbcon))
{
// create unix epoch time
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
cmd.Parameters.AddWithValue("?id", asset.ID);
cmd.Parameters.AddWithValue("?hash", hash);
cmd.Parameters.AddWithValue("?name", assetName);
cmd.Parameters.AddWithValue("?description", assetDescription);
cmd.Parameters.AddWithValue("?asset_type", asset.Type);
cmd.Parameters.AddWithValue("?local", asset.Local);
cmd.Parameters.AddWithValue("?temporary", asset.Temporary);
cmd.Parameters.AddWithValue("?create_time", now);
cmd.Parameters.AddWithValue("?access_time", now);
cmd.Parameters.AddWithValue("?creator_id", asset.Metadata.CreatorID);
cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags);
cmd.Parameters.AddWithValue("?ID", asset.ID);
cmd.Parameters.AddWithValue("?Hash", hash);
cmd.Parameters.AddWithValue("?Name", assetName);
cmd.Parameters.AddWithValue("?Description", assetDescription);
cmd.Parameters.AddWithValue("?AssetType", asset.Type);
cmd.Parameters.AddWithValue("?Local", asset.Local);
cmd.Parameters.AddWithValue("?Temporary", asset.Temporary);
cmd.Parameters.AddWithValue("?CreateTime", now);
cmd.Parameters.AddWithValue("?AccessTime", now);
cmd.Parameters.AddWithValue("?CreatorID", asset.Metadata.CreatorID);
cmd.Parameters.AddWithValue("?AssetFlags", (int)asset.Flags);
cmd.ExecuteNonQuery();
}
}
@@ -278,11 +287,11 @@ namespace OpenSim.Data.MySQL
{
using (MySqlCommand cmd =
new MySqlCommand(
"INSERT INTO xassetsdata(hash, data) VALUES(?hash, ?data)",
"INSERT INTO XAssetsData(Hash, Data) VALUES(?Hash, ?Data)",
dbcon))
{
cmd.Parameters.AddWithValue("?hash", hash);
cmd.Parameters.AddWithValue("?data", asset.Data);
cmd.Parameters.AddWithValue("?Hash", hash);
cmd.Parameters.AddWithValue("?Data", asset.Data);
cmd.ExecuteNonQuery();
}
}
@@ -303,41 +312,49 @@ namespace OpenSim.Data.MySQL
}
}
// private void UpdateAccessTime(AssetBase asset)
// {
// lock (m_dbLock)
// {
// using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
// {
// dbcon.Open();
// MySqlCommand cmd =
// new MySqlCommand("update assets set access_time=?access_time where id=?id",
// dbcon);
//
// // need to ensure we dispose
// try
// {
// using (cmd)
// {
// // create unix epoch time
// int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
// cmd.Parameters.AddWithValue("?id", asset.ID);
// cmd.Parameters.AddWithValue("?access_time", now);
// cmd.ExecuteNonQuery();
// cmd.Dispose();
// }
// }
// catch (Exception e)
// {
// m_log.ErrorFormat(
// "[ASSETS DB]: " +
// "MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
// + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
// }
// }
// }
//
// }
/// <summary>
/// Updates the access time of the asset if it was accessed above a given threshhold amount of time.
/// </summary>
/// <remarks>
/// This gives us some insight into assets which haven't ben accessed for a long period. This is only done
/// over the threshold time to avoid excessive database writes as assets are fetched.
/// </remarks>
/// <param name='asset'></param>
/// <param name='accessTime'></param>
private void UpdateAccessTime(AssetMetadata assetMetadata, int accessTime)
{
DateTime now = DateTime.UtcNow;
if ((now - Utils.UnixTimeToDateTime(accessTime)).TotalDays < DaysBetweenAccessTimeUpdates)
return;
lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd =
new MySqlCommand("update XAssetsMeta set AccessTime=?AccessTime where ID=?ID", dbcon);
try
{
using (cmd)
{
// create unix epoch time
cmd.Parameters.AddWithValue("?ID", assetMetadata.ID);
cmd.Parameters.AddWithValue("?AccessTime", (int)Utils.DateTimeToUnixTime(now));
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.ErrorFormat(
"[XASSET MYSQL DB]: Failure updating access_time for asset {0} with name {1}",
assetMetadata.ID, assetMetadata.Name);
}
}
}
}
/// <summary>
/// We assume we already have the m_dbLock.
@@ -353,9 +370,9 @@ namespace OpenSim.Data.MySQL
bool exists = false;
using (MySqlCommand cmd = new MySqlCommand("SELECT hash FROM xassetsdata WHERE hash=?hash", dbcon))
using (MySqlCommand cmd = new MySqlCommand("SELECT Hash FROM XAssetsData WHERE Hash=?Hash", dbcon))
{
cmd.Parameters.AddWithValue("?hash", hash);
cmd.Parameters.AddWithValue("?Hash", hash);
try
{
@@ -395,9 +412,9 @@ namespace OpenSim.Data.MySQL
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM xassetsmeta WHERE id=?id", dbcon))
using (MySqlCommand cmd = new MySqlCommand("SELECT ID FROM XAssetsMeta WHERE ID=?ID", dbcon))
{
cmd.Parameters.AddWithValue("?id", uuid.ToString());
cmd.Parameters.AddWithValue("?ID", uuid.ToString());
try
{
@@ -412,8 +429,7 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.ErrorFormat(
"[XASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
m_log.Error(string.Format("[XASSETS DB]: MySql failure fetching asset {0}", uuid), e);
}
}
}
@@ -422,6 +438,7 @@ namespace OpenSim.Data.MySQL
return assetExists;
}
/// <summary>
/// Returns a list of AssetMetadata objects. The list is a subset of
/// the entire data set offset by <paramref name="start" /> containing
@@ -439,7 +456,7 @@ namespace OpenSim.Data.MySQL
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = new MySqlCommand("SELECT name,description,asset_type,temporary,id,asset_flags,creator_id FROM xassetsmeta LIMIT ?start, ?count", dbcon);
MySqlCommand cmd = new MySqlCommand("SELECT Name, Description, AccessTime, AssetType, Temporary, ID, AssetFlags, CreatorID FROM XAssetsMeta LIMIT ?start, ?count", dbcon);
cmd.Parameters.AddWithValue("?start", start);
cmd.Parameters.AddWithValue("?count", count);
@@ -450,17 +467,19 @@ namespace OpenSim.Data.MySQL
while (dbReader.Read())
{
AssetMetadata metadata = new AssetMetadata();
metadata.Name = (string)dbReader["name"];
metadata.Description = (string)dbReader["description"];
metadata.Type = (sbyte)dbReader["asset_type"];
metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct.
metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["asset_flags"]);
metadata.FullID = DBGuid.FromDB(dbReader["id"]);
metadata.CreatorID = dbReader["creator_id"].ToString();
metadata.Name = (string)dbReader["Name"];
metadata.Description = (string)dbReader["Description"];
metadata.Type = (sbyte)dbReader["AssetType"];
metadata.Temporary = Convert.ToBoolean(dbReader["Temporary"]); // Not sure if this is correct.
metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
metadata.FullID = DBGuid.FromDB(dbReader["ID"]);
metadata.CreatorID = dbReader["CreatorID"].ToString();
// We'll ignore this for now - it appears unused!
// metadata.SHA1 = dbReader["hash"]);
UpdateAccessTime(metadata, (int)dbReader["AccessTime"]);
retList.Add(metadata);
}
}
@@ -485,9 +504,9 @@ namespace OpenSim.Data.MySQL
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("delete from xassetsmeta where id=?id", dbcon))
using (MySqlCommand cmd = new MySqlCommand("delete from XAssetsMeta where ID=?ID", dbcon))
{
cmd.Parameters.AddWithValue("?id", id);
cmd.Parameters.AddWithValue("?ID", id);
cmd.ExecuteNonQuery();
}

View File

@@ -77,5 +77,11 @@ BEGIN;
ALTER TABLE estate_settings AUTO_INCREMENT = 100;
COMMIT;
:VERSION 33 #---------------------
BEGIN;
ALTER TABLE estate_settings ADD COLUMN `AllowLandmark` tinyint(4) NOT NULL default '1';
ALTER TABLE estate_settings ADD COLUMN `AllowParcelChanges` tinyint(4) NOT NULL default '1';
ALTER TABLE estate_settings ADD COLUMN `AllowSetHome` tinyint(4) NOT NULL default '1';
COMMIT;

View File

@@ -9,7 +9,7 @@ CREATE TABLE `Friends` (
`Offered` VARCHAR(32) NOT NULL DEFAULT 0,
PRIMARY KEY(`PrincipalID`, `Friend`),
KEY(`PrincipalID`)
);
) ENGINE=InnoDB;
COMMIT;

View File

@@ -923,3 +923,10 @@ ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
COMMIT;
:VERSION 48 #---------------- Keyframes
BEGIN;
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
COMMIT;

View File

@@ -0,0 +1,83 @@
:VERSION 1 # -------------------------------
begin;
CREATE TABLE IF NOT EXISTS `classifieds` (
`classifieduuid` char(36) NOT NULL,
`creatoruuid` char(36) NOT NULL,
`creationdate` int(20) NOT NULL,
`expirationdate` int(20) NOT NULL,
`category` varchar(20) NOT NULL,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`parceluuid` char(36) NOT NULL,
`parentestate` int(11) NOT NULL,
`snapshotuuid` char(36) NOT NULL,
`simname` varchar(255) NOT NULL,
`posglobal` varchar(255) NOT NULL,
`parcelname` varchar(255) NOT NULL,
`classifiedflags` int(8) NOT NULL,
`priceforlisting` int(5) NOT NULL,
PRIMARY KEY (`classifieduuid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `usernotes` (
`useruuid` varchar(36) NOT NULL,
`targetuuid` varchar(36) NOT NULL,
`notes` text NOT NULL,
UNIQUE KEY `useruuid` (`useruuid`,`targetuuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `userpicks` (
`pickuuid` varchar(36) NOT NULL,
`creatoruuid` varchar(36) NOT NULL,
`toppick` enum('true','false') NOT NULL,
`parceluuid` varchar(36) NOT NULL,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`snapshotuuid` varchar(36) NOT NULL,
`user` varchar(255) NOT NULL,
`originalname` varchar(255) NOT NULL,
`simname` varchar(255) NOT NULL,
`posglobal` varchar(255) NOT NULL,
`sortorder` int(2) NOT NULL,
`enabled` enum('true','false') NOT NULL,
PRIMARY KEY (`pickuuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `userprofile` (
`useruuid` varchar(36) NOT NULL,
`profilePartner` varchar(36) NOT NULL,
`profileAllowPublish` binary(1) NOT NULL,
`profileMaturePublish` binary(1) NOT NULL,
`profileURL` varchar(255) NOT NULL,
`profileWantToMask` int(3) NOT NULL,
`profileWantToText` text NOT NULL,
`profileSkillsMask` int(3) NOT NULL,
`profileSkillsText` text NOT NULL,
`profileLanguages` text NOT NULL,
`profileImage` varchar(36) NOT NULL,
`profileAboutText` text NOT NULL,
`profileFirstImage` varchar(36) NOT NULL,
`profileFirstText` text NOT NULL,
PRIMARY KEY (`useruuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
commit;
:VERSION 2 # -------------------------------
begin;
CREATE TABLE IF NOT EXISTS `userdata` (
`UserId` char(36) NOT NULL,
`TagId` varchar(64) NOT NULL,
`DataKey` varchar(255),
`DataVal` varchar(255),
PRIMARY KEY (`UserId`,`TagId`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
commit;

View File

@@ -3,24 +3,24 @@
BEGIN;
CREATE TABLE `xassetsmeta` (
`id` char(36) NOT NULL,
`hash` binary(32) NOT NULL,
`name` varchar(64) NOT NULL,
`description` varchar(64) NOT NULL,
`asset_type` tinyint(4) NOT NULL,
`local` tinyint(1) NOT NULL,
`temporary` tinyint(1) NOT NULL,
`create_time` int(11) NOT NULL,
`access_time` int(11) NOT NULL,
`asset_flags` int(11) NOT NULL,
`creator_id` varchar(128) NOT NULL,
CREATE TABLE `XAssetsMeta` (
`ID` char(36) NOT NULL,
`Hash` binary(32) NOT NULL,
`Name` varchar(64) NOT NULL,
`Description` varchar(64) NOT NULL,
`AssetType` tinyint(4) NOT NULL,
`Local` tinyint(1) NOT NULL,
`Temporary` tinyint(1) NOT NULL,
`CreateTime` int(11) NOT NULL,
`AccessTime` int(11) NOT NULL,
`AssetFlags` int(11) NOT NULL,
`CreatorID` varchar(128) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Version 1';
CREATE TABLE `xassetsdata` (
`hash` binary(32) NOT NULL,
`data` longblob NOT NULL,
CREATE TABLE `XAssetsData` (
`Hash` binary(32) NOT NULL,
`Data` longblob NOT NULL,
PRIMARY KEY (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Version 1';

View File

@@ -42,6 +42,22 @@ namespace OpenSim.Data.Null
// private string m_connectionString;
private Dictionary<uint, EstateSettings> m_knownEstates = new Dictionary<uint, EstateSettings>();
private EstateSettings m_estate = null;
private EstateSettings GetEstate()
{
if (m_estate == null)
{
// This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
// The estate info is pretty empty so don't try banning anyone.
m_estate = new EstateSettings();
m_estate.EstateID = 1;
m_estate.OnSave += StoreEstateSettings;
}
return m_estate;
}
protected virtual Assembly Assembly
{
get { return GetType().Assembly; }
@@ -68,21 +84,18 @@ namespace OpenSim.Data.Null
public EstateSettings LoadEstateSettings(UUID regionID, bool create)
{
// This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
// The estate info is pretty empty so don't try banning anyone.
EstateSettings oneEstate = new EstateSettings();
oneEstate.EstateID = 1;
return oneEstate;
return GetEstate();
}
public void StoreEstateSettings(EstateSettings es)
{
m_estate = es;
return;
}
public EstateSettings LoadEstateSettings(int estateID)
{
return new EstateSettings();
return GetEstate();
}
public EstateSettings CreateNewEstate()
@@ -93,13 +106,14 @@ namespace OpenSim.Data.Null
public List<EstateSettings> LoadEstateSettingsAll()
{
List<EstateSettings> allEstateSettings = new List<EstateSettings>();
allEstateSettings.Add(new EstateSettings());
allEstateSettings.Add(GetEstate());
return allEstateSettings;
}
public List<int> GetEstatesAll()
{
List<int> result = new List<int>();
result.Add((int)GetEstate().EstateID);
return result;
}

View File

@@ -86,3 +86,12 @@ begin;
alter table estate_settings add column DenyMinors tinyint not null default 0;
commit;
:VERSION 9
begin;
alter table estate_settings add column AllowLandmark tinyint not null default '1';
alter table estate_settings add column AllowParcelChanges tinyint not null default '1';
alter table estate_settings add column AllowSetHome tinyint not null default '1';
commit;

View File

@@ -592,3 +592,11 @@ ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
COMMIT;
:VERSION 29 #---------------- Keyframes
BEGIN;
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
COMMIT;

View File

@@ -0,0 +1,90 @@
:VERSION 1 # -------------------------------
begin;
CREATE TABLE IF NOT EXISTS classifieds (
classifieduuid char(36) NOT NULL PRIMARY KEY,
creatoruuid char(36) NOT NULL,
creationdate int(20) NOT NULL,
expirationdate int(20) NOT NULL,
category varchar(20) NOT NULL,
name varchar(255) NOT NULL,
description text NOT NULL,
parceluuid char(36) NOT NULL,
parentestate int(11) NOT NULL,
snapshotuuid char(36) NOT NULL,
simname varchar(255) NOT NULL,
posglobal varchar(255) NOT NULL,
parcelname varchar(255) NOT NULL,
classifiedflags int(8) NOT NULL,
priceforlisting int(5) NOT NULL
);
commit;
begin;
CREATE TABLE IF NOT EXISTS usernotes (
useruuid varchar(36) NOT NULL,
targetuuid varchar(36) NOT NULL,
notes text NOT NULL,
UNIQUE (useruuid,targetuuid) ON CONFLICT REPLACE
);
commit;
begin;
CREATE TABLE IF NOT EXISTS userpicks (
pickuuid varchar(36) NOT NULL PRIMARY KEY,
creatoruuid varchar(36) NOT NULL,
toppick int NOT NULL,
parceluuid varchar(36) NOT NULL,
name varchar(255) NOT NULL,
description text NOT NULL,
snapshotuuid varchar(36) NOT NULL,
user varchar(255) NOT NULL,
originalname varchar(255) NOT NULL,
simname varchar(255) NOT NULL,
posglobal varchar(255) NOT NULL,
sortorder int(2) NOT NULL,
enabled int NOT NULL
);
commit;
begin;
CREATE TABLE IF NOT EXISTS userprofile (
useruuid varchar(36) NOT NULL PRIMARY KEY,
profilePartner varchar(36) NOT NULL,
profileAllowPublish binary(1) NOT NULL,
profileMaturePublish binary(1) NOT NULL,
profileURL varchar(255) NOT NULL,
profileWantToMask int(3) NOT NULL,
profileWantToText text NOT NULL,
profileSkillsMask int(3) NOT NULL,
profileSkillsText text NOT NULL,
profileLanguages text NOT NULL,
profileImage varchar(36) NOT NULL,
profileAboutText text NOT NULL,
profileFirstImage varchar(36) NOT NULL,
profileFirstText text NOT NULL
);
commit;
:VERSION 2 # -------------------------------
begin;
CREATE TABLE IF NOT EXISTS userdata (
UserId char(36) NOT NULL,
TagId varchar(64) NOT NULL,
DataKey varchar(255),
DataVal varchar(255),
PRIMARY KEY (UserId,TagId)
);
commit;

View File

@@ -56,6 +56,10 @@ namespace OpenSim.Data.SQLite
return ret[0];
}
public GridUserData[] GetAll(string userID)
{
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
}
}
}

View File

@@ -732,9 +732,12 @@ namespace OpenSim.Data.SQLite
}
SceneObjectGroup group = new SceneObjectGroup(prim);
createdObjects.Add(group.UUID, group);
retvals.Add(group);
LoadItems(prim);
}
}
catch (Exception e)
@@ -1241,6 +1244,7 @@ namespace OpenSim.Data.SQLite
createCol(prims, "Friction", typeof(Double));
createCol(prims, "Restitution", typeof(Double));
createCol(prims, "KeyframeMotion", typeof(Byte[]));
// Add in contraints
prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
@@ -1736,6 +1740,20 @@ namespace OpenSim.Data.SQLite
prim.Friction = Convert.ToSingle(row["Friction"]);
prim.Restitution = Convert.ToSingle(row["Restitution"]);
if (!(row["KeyframeMotion"] is DBNull))
{
Byte[] data = (byte[])row["KeyframeMotion"];
if (data.Length > 0)
prim.KeyframeMotion = KeyframeMotion.FromData(null, data);
else
prim.KeyframeMotion = null;
}
else
{
prim.KeyframeMotion = null;
}
return prim;
}
@@ -2158,7 +2176,7 @@ namespace OpenSim.Data.SQLite
row["MediaURL"] = prim.MediaUrl;
if (prim.DynAttrs.Count > 0)
if (prim.DynAttrs.CountNamespaces > 0)
row["DynAttrs"] = prim.DynAttrs.ToXml();
else
row["DynAttrs"] = null;
@@ -2168,6 +2186,13 @@ namespace OpenSim.Data.SQLite
row["GravityModifier"] = (double)prim.GravityModifier;
row["Friction"] = (double)prim.Friction;
row["Restitution"] = (double)prim.Restitution;
if (prim.KeyframeMotion != null)
row["KeyframeMotion"] = prim.KeyframeMotion.Serialize();
else
row["KeyframeMotion"] = new Byte[0];
}
/// <summary>

View File

@@ -0,0 +1,904 @@
/*
* 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.Data;
using System.Reflection;
using log4net;
#if CSharpSqlite
using Community.CsharpSqlite.Sqlite;
#else
using Mono.Data.Sqlite;
#endif
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Data.SQLite
{
public class SQLiteUserProfilesData: IProfilesData
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private SqliteConnection m_connection;
private string m_connectionString;
private FieldInfo[] m_Fields;
private Dictionary<string, FieldInfo> m_FieldMap =
new Dictionary<string, FieldInfo>();
protected virtual Assembly Assembly
{
get { return GetType().Assembly; }
}
public SQLiteUserProfilesData()
{
}
public SQLiteUserProfilesData(string connectionString)
{
Initialise(connectionString);
}
public void Initialise(string connectionString)
{
if (Util.IsWindows())
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
m_connectionString = connectionString;
m_log.Info("[PROFILES_DATA]: Sqlite - connecting: "+m_connectionString);
m_connection = new SqliteConnection(m_connectionString);
m_connection.Open();
Migration m = new Migration(m_connection, Assembly, "UserProfiles");
m.Update();
}
private string[] FieldList
{
get { return new List<string>(m_FieldMap.Keys).ToArray(); }
}
#region IProfilesData implementation
public OSDArray GetClassifiedRecords(UUID creatorId)
{
OSDArray data = new OSDArray();
string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = :Id";
IDataReader reader = null;
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", creatorId);
reader = cmd.ExecuteReader();
}
while (reader.Read())
{
OSDMap n = new OSDMap();
UUID Id = UUID.Zero;
string Name = null;
try
{
UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
Name = Convert.ToString(reader["name"]);
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": UserAccount exception {0}", e.Message);
}
n.Add("classifieduuid", OSD.FromUUID(Id));
n.Add("name", OSD.FromString(Name));
data.Add(n);
}
reader.Close();
return data;
}
public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
{
string query = string.Empty;
query += "INSERT OR REPLACE INTO classifieds (";
query += "`classifieduuid`,";
query += "`creatoruuid`,";
query += "`creationdate`,";
query += "`expirationdate`,";
query += "`category`,";
query += "`name`,";
query += "`description`,";
query += "`parceluuid`,";
query += "`parentestate`,";
query += "`snapshotuuid`,";
query += "`simname`,";
query += "`posglobal`,";
query += "`parcelname`,";
query += "`classifiedflags`,";
query += "`priceforlisting`) ";
query += "VALUES (";
query += ":ClassifiedId,";
query += ":CreatorId,";
query += ":CreatedDate,";
query += ":ExpirationDate,";
query += ":Category,";
query += ":Name,";
query += ":Description,";
query += ":ParcelId,";
query += ":ParentEstate,";
query += ":SnapshotId,";
query += ":SimName,";
query += ":GlobalPos,";
query += ":ParcelName,";
query += ":Flags,";
query += ":ListingPrice ) ";
if(string.IsNullOrEmpty(ad.ParcelName))
ad.ParcelName = "Unknown";
if(ad.ParcelId == null)
ad.ParcelId = UUID.Zero;
if(string.IsNullOrEmpty(ad.Description))
ad.Description = "No Description";
DateTime epoch = new DateTime(1970, 1, 1);
DateTime now = DateTime.Now;
TimeSpan epochnow = now - epoch;
TimeSpan duration;
DateTime expiration;
TimeSpan epochexp;
if(ad.Flags == 2)
{
duration = new TimeSpan(7,0,0,0);
expiration = now.Add(duration);
epochexp = expiration - epoch;
}
else
{
duration = new TimeSpan(365,0,0,0);
expiration = now.Add(duration);
epochexp = expiration - epoch;
}
ad.CreationDate = (int)epochnow.TotalSeconds;
ad.ExpirationDate = (int)epochexp.TotalSeconds;
try {
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":ClassifiedId", ad.ClassifiedId.ToString());
cmd.Parameters.AddWithValue(":CreatorId", ad.CreatorId.ToString());
cmd.Parameters.AddWithValue(":CreatedDate", ad.CreationDate.ToString());
cmd.Parameters.AddWithValue(":ExpirationDate", ad.ExpirationDate.ToString());
cmd.Parameters.AddWithValue(":Category", ad.Category.ToString());
cmd.Parameters.AddWithValue(":Name", ad.Name.ToString());
cmd.Parameters.AddWithValue(":Description", ad.Description.ToString());
cmd.Parameters.AddWithValue(":ParcelId", ad.ParcelId.ToString());
cmd.Parameters.AddWithValue(":ParentEstate", ad.ParentEstate.ToString());
cmd.Parameters.AddWithValue(":SnapshotId", ad.SnapshotId.ToString ());
cmd.Parameters.AddWithValue(":SimName", ad.SimName.ToString());
cmd.Parameters.AddWithValue(":GlobalPos", ad.GlobalPos.ToString());
cmd.Parameters.AddWithValue(":ParcelName", ad.ParcelName.ToString());
cmd.Parameters.AddWithValue(":Flags", ad.Flags.ToString());
cmd.Parameters.AddWithValue(":ListingPrice", ad.Price.ToString ());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": ClassifiedesUpdate exception {0}", e.Message);
result = e.Message;
return false;
}
return true;
}
public bool DeleteClassifiedRecord(UUID recordId)
{
string query = string.Empty;
query += "DELETE FROM classifieds WHERE ";
query += "classifieduuid = :ClasifiedId";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":ClassifiedId", recordId.ToString());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": DeleteClassifiedRecord exception {0}", e.Message);
return false;
}
return true;
}
public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
{
IDataReader reader = null;
string query = string.Empty;
query += "SELECT * FROM classifieds WHERE ";
query += "classifieduuid = :AdId";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":AdId", ad.ClassifiedId.ToString());
using (reader = cmd.ExecuteReader())
{
if(reader.Read ())
{
ad.CreatorId = new UUID(reader["creatoruuid"].ToString());
ad.ParcelId = new UUID(reader["parceluuid"].ToString ());
ad.SnapshotId = new UUID(reader["snapshotuuid"].ToString ());
ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
ad.Flags = (byte) Convert.ToUInt32(reader["classifiedflags"]);
ad.Category = Convert.ToInt32(reader["category"]);
ad.Price = Convert.ToInt16(reader["priceforlisting"]);
ad.Name = reader["name"].ToString();
ad.Description = reader["description"].ToString();
ad.SimName = reader["simname"].ToString();
ad.GlobalPos = reader["posglobal"].ToString();
ad.ParcelName = reader["parcelname"].ToString();
}
}
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": GetPickInfo exception {0}", e.Message);
}
return true;
}
public OSDArray GetAvatarPicks(UUID avatarId)
{
IDataReader reader = null;
string query = string.Empty;
query += "SELECT `pickuuid`,`name` FROM userpicks WHERE ";
query += "creatoruuid = :Id";
OSDArray data = new OSDArray();
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
using (reader = cmd.ExecuteReader())
{
while (reader.Read())
{
OSDMap record = new OSDMap();
record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
record.Add("name",OSD.FromString((string)reader["name"]));
data.Add(record);
}
}
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": GetAvatarPicks exception {0}", e.Message);
}
return data;
}
public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
{
IDataReader reader = null;
string query = string.Empty;
UserProfilePick pick = new UserProfilePick();
query += "SELECT * FROM userpicks WHERE ";
query += "creatoruuid = :CreatorId AND ";
query += "pickuuid = :PickId";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":CreatorId", avatarId.ToString());
cmd.Parameters.AddWithValue(":PickId", pickId.ToString());
using (reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string description = (string)reader["description"];
if (string.IsNullOrEmpty(description))
description = "No description given.";
UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
pick.GlobalPos = (string)reader["posglobal"];
bool.TryParse((string)reader["toppick"].ToString(), out pick.TopPick);
bool.TryParse((string)reader["enabled"].ToString(), out pick.Enabled);
pick.Name = (string)reader["name"];
pick.Desc = description;
pick.User = (string)reader["user"];
pick.OriginalName = (string)reader["originalname"];
pick.SimName = (string)reader["simname"];
pick.SortOrder = (int)reader["sortorder"];
}
}
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": GetPickInfo exception {0}", e.Message);
}
return pick;
}
public bool UpdatePicksRecord(UserProfilePick pick)
{
string query = string.Empty;
query += "INSERT OR REPLACE INTO userpicks (";
query += "pickuuid, ";
query += "creatoruuid, ";
query += "toppick, ";
query += "parceluuid, ";
query += "name, ";
query += "description, ";
query += "snapshotuuid, ";
query += "user, ";
query += "originalname, ";
query += "simname, ";
query += "posglobal, ";
query += "sortorder, ";
query += "enabled ) ";
query += "VALUES (";
query += ":PickId,";
query += ":CreatorId,";
query += ":TopPick,";
query += ":ParcelId,";
query += ":Name,";
query += ":Desc,";
query += ":SnapshotId,";
query += ":User,";
query += ":Original,";
query += ":SimName,";
query += ":GlobalPos,";
query += ":SortOrder,";
query += ":Enabled) ";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
int top_pick;
int.TryParse(pick.TopPick.ToString(), out top_pick);
int enabled;
int.TryParse(pick.Enabled.ToString(), out enabled);
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":PickId", pick.PickId.ToString());
cmd.Parameters.AddWithValue(":CreatorId", pick.CreatorId.ToString());
cmd.Parameters.AddWithValue(":TopPick", top_pick);
cmd.Parameters.AddWithValue(":ParcelId", pick.ParcelId.ToString());
cmd.Parameters.AddWithValue(":Name", pick.Name.ToString());
cmd.Parameters.AddWithValue(":Desc", pick.Desc.ToString());
cmd.Parameters.AddWithValue(":SnapshotId", pick.SnapshotId.ToString());
cmd.Parameters.AddWithValue(":User", pick.User.ToString());
cmd.Parameters.AddWithValue(":Original", pick.OriginalName.ToString());
cmd.Parameters.AddWithValue(":SimName",pick.SimName.ToString());
cmd.Parameters.AddWithValue(":GlobalPos", pick.GlobalPos);
cmd.Parameters.AddWithValue(":SortOrder", pick.SortOrder.ToString ());
cmd.Parameters.AddWithValue(":Enabled", enabled);
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": UpdateAvatarNotes exception {0}", e.Message);
return false;
}
return true;
}
public bool DeletePicksRecord(UUID pickId)
{
string query = string.Empty;
query += "DELETE FROM userpicks WHERE ";
query += "pickuuid = :PickId";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":PickId", pickId.ToString());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": DeleteUserPickRecord exception {0}", e.Message);
return false;
}
return true;
}
public bool GetAvatarNotes(ref UserProfileNotes notes)
{
IDataReader reader = null;
string query = string.Empty;
query += "SELECT `notes` FROM usernotes WHERE ";
query += "useruuid = :Id AND ";
query += "targetuuid = :TargetId";
OSDArray data = new OSDArray();
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", notes.UserId.ToString());
cmd.Parameters.AddWithValue(":TargetId", notes.TargetId.ToString());
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
while (reader.Read())
{
notes.Notes = OSD.FromString((string)reader["notes"]);
}
}
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": GetAvatarNotes exception {0}", e.Message);
}
return true;
}
public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
{
string query = string.Empty;
bool remove;
if(string.IsNullOrEmpty(note.Notes))
{
remove = true;
query += "DELETE FROM usernotes WHERE ";
query += "useruuid=:UserId AND ";
query += "targetuuid=:TargetId";
}
else
{
remove = false;
query += "INSERT OR REPLACE INTO usernotes VALUES ( ";
query += ":UserId,";
query += ":TargetId,";
query += ":Notes )";
}
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
if(!remove)
cmd.Parameters.AddWithValue(":Notes", note.Notes);
cmd.Parameters.AddWithValue(":TargetId", note.TargetId.ToString ());
cmd.Parameters.AddWithValue(":UserId", note.UserId.ToString());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": UpdateAvatarNotes exception {0}", e.Message);
return false;
}
return true;
}
public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
{
IDataReader reader = null;
string query = string.Empty;
query += "SELECT * FROM userprofile WHERE ";
query += "useruuid = :Id";
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", props.UserId.ToString());
try
{
reader = cmd.ExecuteReader();
}
catch(Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": GetAvatarProperties exception {0}", e.Message);
result = e.Message;
return false;
}
if(reader != null && reader.Read())
{
m_log.DebugFormat("[PROFILES_DATA]" +
": Getting data for {0}.", props.UserId);
props.WebUrl = (string)reader["profileURL"];
UUID.TryParse((string)reader["profileImage"], out props.ImageId);
props.AboutText = (string)reader["profileAboutText"];
UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
props.FirstLifeText = (string)reader["profileFirstText"];
UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
props.WantToMask = (int)reader["profileWantToMask"];
props.WantToText = (string)reader["profileWantToText"];
props.SkillsMask = (int)reader["profileSkillsMask"];
props.SkillsText = (string)reader["profileSkillsText"];
props.Language = (string)reader["profileLanguages"];
}
else
{
m_log.DebugFormat("[PROFILES_DATA]" +
": No data for {0}", props.UserId);
props.WebUrl = string.Empty;
props.ImageId = UUID.Zero;
props.AboutText = string.Empty;
props.FirstLifeImageId = UUID.Zero;
props.FirstLifeText = string.Empty;
props.PartnerId = UUID.Zero;
props.WantToMask = 0;
props.WantToText = string.Empty;
props.SkillsMask = 0;
props.SkillsText = string.Empty;
props.Language = string.Empty;
props.PublishProfile = false;
props.PublishMature = false;
query = "INSERT INTO userprofile (";
query += "useruuid, ";
query += "profilePartner, ";
query += "profileAllowPublish, ";
query += "profileMaturePublish, ";
query += "profileURL, ";
query += "profileWantToMask, ";
query += "profileWantToText, ";
query += "profileSkillsMask, ";
query += "profileSkillsText, ";
query += "profileLanguages, ";
query += "profileImage, ";
query += "profileAboutText, ";
query += "profileFirstImage, ";
query += "profileFirstText) VALUES (";
query += ":userId, ";
query += ":profilePartner, ";
query += ":profileAllowPublish, ";
query += ":profileMaturePublish, ";
query += ":profileURL, ";
query += ":profileWantToMask, ";
query += ":profileWantToText, ";
query += ":profileSkillsMask, ";
query += ":profileSkillsText, ";
query += ":profileLanguages, ";
query += ":profileImage, ";
query += ":profileAboutText, ";
query += ":profileFirstImage, ";
query += ":profileFirstText)";
using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
{
put.CommandText = query;
put.Parameters.AddWithValue(":userId", props.UserId.ToString());
put.Parameters.AddWithValue(":profilePartner", props.PartnerId.ToString());
put.Parameters.AddWithValue(":profileAllowPublish", props.PublishProfile);
put.Parameters.AddWithValue(":profileMaturePublish", props.PublishMature);
put.Parameters.AddWithValue(":profileURL", props.WebUrl);
put.Parameters.AddWithValue(":profileWantToMask", props.WantToMask);
put.Parameters.AddWithValue(":profileWantToText", props.WantToText);
put.Parameters.AddWithValue(":profileSkillsMask", props.SkillsMask);
put.Parameters.AddWithValue(":profileSkillsText", props.SkillsText);
put.Parameters.AddWithValue(":profileLanguages", props.Language);
put.Parameters.AddWithValue(":profileImage", props.ImageId.ToString());
put.Parameters.AddWithValue(":profileAboutText", props.AboutText);
put.Parameters.AddWithValue(":profileFirstImage", props.FirstLifeImageId.ToString());
put.Parameters.AddWithValue(":profileFirstText", props.FirstLifeText);
put.ExecuteNonQuery();
}
}
}
return true;
}
public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
{
string query = string.Empty;
query += "UPDATE userprofile SET ";
query += "profilePartner=:profilePartner, ";
query += "profileURL=:profileURL, ";
query += "profileImage=:image, ";
query += "profileAboutText=:abouttext,";
query += "profileFirstImage=:firstlifeimage,";
query += "profileFirstText=:firstlifetext ";
query += "WHERE useruuid=:uuid";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":profileURL", props.WebUrl);
cmd.Parameters.AddWithValue(":profilePartner", props.PartnerId.ToString());
cmd.Parameters.AddWithValue(":image", props.ImageId.ToString());
cmd.Parameters.AddWithValue(":abouttext", props.AboutText);
cmd.Parameters.AddWithValue(":firstlifeimage", props.FirstLifeImageId.ToString());
cmd.Parameters.AddWithValue(":firstlifetext", props.FirstLifeText);
cmd.Parameters.AddWithValue(":uuid", props.UserId.ToString());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": AgentPropertiesUpdate exception {0}", e.Message);
return false;
}
return true;
}
public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
{
string query = string.Empty;
query += "UPDATE userprofile SET ";
query += "profileWantToMask=:WantMask, ";
query += "profileWantToText=:WantText,";
query += "profileSkillsMask=:SkillsMask,";
query += "profileSkillsText=:SkillsText, ";
query += "profileLanguages=:Languages ";
query += "WHERE useruuid=:uuid";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":WantMask", up.WantToMask);
cmd.Parameters.AddWithValue(":WantText", up.WantToText);
cmd.Parameters.AddWithValue(":SkillsMask", up.SkillsMask);
cmd.Parameters.AddWithValue(":SkillsText", up.SkillsText);
cmd.Parameters.AddWithValue(":Languages", up.Language);
cmd.Parameters.AddWithValue(":uuid", up.UserId.ToString());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": AgentInterestsUpdate exception {0}", e.Message);
result = e.Message;
return false;
}
return true;
}
public bool GetUserAppData(ref UserAppData props, ref string result)
{
IDataReader reader = null;
string query = string.Empty;
query += "SELECT * FROM `userdata` WHERE ";
query += "UserId = :Id AND ";
query += "TagId = :TagId";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", props.UserId.ToString());
cmd.Parameters.AddWithValue (":TagId", props.TagId.ToString());
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if(reader.Read())
{
props.DataKey = (string)reader["DataKey"];
props.DataVal = (string)reader["DataVal"];
}
else
{
query += "INSERT INTO userdata VALUES ( ";
query += ":UserId,";
query += ":TagId,";
query += ":DataKey,";
query += ":DataVal) ";
using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
{
put.Parameters.AddWithValue(":Id", props.UserId.ToString());
put.Parameters.AddWithValue(":TagId", props.TagId.ToString());
put.Parameters.AddWithValue(":DataKey", props.DataKey.ToString());
put.Parameters.AddWithValue(":DataVal", props.DataVal.ToString());
put.ExecuteNonQuery();
}
}
}
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": Requst application data exception {0}", e.Message);
result = e.Message;
return false;
}
return true;
}
public bool SetUserAppData(UserAppData props, ref string result)
{
string query = string.Empty;
query += "UPDATE userdata SET ";
query += "TagId = :TagId, ";
query += "DataKey = :DataKey, ";
query += "DataVal = :DataVal WHERE ";
query += "UserId = :UserId AND ";
query += "TagId = :TagId";
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":UserId", props.UserId.ToString());
cmd.Parameters.AddWithValue(":TagId", props.TagId.ToString ());
cmd.Parameters.AddWithValue(":DataKey", props.DataKey.ToString ());
cmd.Parameters.AddWithValue(":DataVal", props.DataKey.ToString ());
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": SetUserData exception {0}", e.Message);
return false;
}
return true;
}
public OSDArray GetUserImageAssets(UUID avatarId)
{
IDataReader reader = null;
OSDArray data = new OSDArray();
string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = :Id";
// Get classified image assets
try
{
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
while(reader.Read())
{
data.Add(new OSDString((string)reader["snapshotuuid"].ToString()));
}
}
}
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if(reader.Read())
{
data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
}
}
}
query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = :Id";
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
{
cmd.CommandText = query;
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if(reader.Read())
{
data.Add(new OSDString((string)reader["profileImage"].ToString ()));
data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
}
}
}
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES_DATA]" +
": GetAvatarNotes exception {0}", e.Message);
}
return data;
}
#endregion
}
}

View File

@@ -120,5 +120,24 @@ namespace OpenSim.Framework
sequenceNum = args["seq_num"].AsInteger();
}
public override bool Equals(object obj)
{
Animation other = obj as Animation;
if (other != null)
{
return (other.AnimID.Equals(this.AnimID)
&& other.SequenceNum == this.SequenceNum
&& other.ObjectID.Equals(this.ObjectID) );
}
return base.Equals(obj);
}
public override string ToString()
{
return "AnimID=" + AnimID.ToString()
+ "/seq=" + SequenceNum.ToString()
+ "/objID=" + ObjectID.ToString();
}
}
}

View File

@@ -53,6 +53,7 @@ namespace OpenSim.Framework
protected AvatarWearable[] m_wearables;
protected Dictionary<int, List<AvatarAttachment>> m_attachments;
protected float m_avatarHeight = 0;
protected UUID[] m_texturehashes;
public virtual int Serial
{
@@ -98,6 +99,8 @@ namespace OpenSim.Framework
SetDefaultParams();
SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
ResetTextureHashes();
}
public AvatarAppearance(OSDMap map)
@@ -108,32 +111,6 @@ namespace OpenSim.Framework
SetHeight();
}
public AvatarAppearance(AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
// m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance");
m_serial = 0;
if (wearables != null)
m_wearables = wearables;
else
SetDefaultWearables();
if (textureEntry != null)
m_texture = textureEntry;
else
SetDefaultTexture();
if (visualParams != null)
m_visualparams = visualParams;
else
SetDefaultParams();
SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
}
public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true)
{
}
@@ -151,6 +128,8 @@ namespace OpenSim.Framework
SetHeight();
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
ResetTextureHashes();
return;
}
@@ -166,6 +145,10 @@ namespace OpenSim.Framework
SetWearable(i,appearance.Wearables[i]);
}
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
m_texturehashes[i] = new UUID(appearance.m_texturehashes[i]);
m_texture = null;
if (appearance.Texture != null)
{
@@ -200,6 +183,37 @@ namespace OpenSim.Framework
}
}
public void ResetTextureHashes()
{
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
m_texturehashes[i] = UUID.Zero;
}
public UUID GetTextureHash(int textureIndex)
{
return m_texturehashes[NormalizeBakedTextureIndex(textureIndex)];
}
public void SetTextureHash(int textureIndex, UUID textureHash)
{
m_texturehashes[NormalizeBakedTextureIndex(textureIndex)] = new UUID(textureHash);
}
/// <summary>
/// Normalizes the texture index to the actual bake index, this is done to
/// accommodate older viewers that send the BAKE_INDICES index rather than
/// the actual texture index
/// </summary>
private int NormalizeBakedTextureIndex(int textureIndex)
{
// Earlier viewer send the index into the baked index array, just trying to be careful here
if (textureIndex < BAKE_INDICES.Length)
return BAKE_INDICES[textureIndex];
return textureIndex;
}
public void ClearWearables()
{
m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
@@ -223,12 +237,7 @@ namespace OpenSim.Framework
m_serial = 0;
SetDefaultTexture();
//for (int i = 0; i < BAKE_INDICES.Length; i++)
// {
// int idx = BAKE_INDICES[i];
// m_texture.FaceTextures[idx].TextureID = UUID.Zero;
// }
ResetTextureHashes();
}
protected virtual void SetDefaultParams()
@@ -459,45 +468,59 @@ namespace OpenSim.Framework
if (attachpoint == 0)
return false;
if (item == UUID.Zero)
lock (m_attachments)
{
lock (m_attachments)
if (item == UUID.Zero)
{
if (m_attachments.ContainsKey(attachpoint))
{
m_attachments.Remove(attachpoint);
return true;
}
return false;
}
// When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
// the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
// later fail unless the attachment is detached and reattached.
//
// Therefore, we will carry on with the set if the existing attachment has no asset id.
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
if (existingAttachment != null)
{
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Found existing attachment for {0}, asset {1} at point {2}",
// existingAttachment.ItemID, existingAttachment.AssetID, existingAttachment.AttachPoint);
if (existingAttachment.AssetID != UUID.Zero && existingAttachment.AttachPoint == (attachpoint & 0x7F))
{
m_log.DebugFormat(
"[AVATAR APPEARANCE]: Ignoring attempt to attach an already attached item {0} at point {1}",
item, attachpoint);
return false;
}
else
{
// Remove it here so that the later append does not add a second attachment but we still update
// the assetID
DetachAttachment(existingAttachment.ItemID);
}
}
return false;
}
// When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
// the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
// later fail unless the attachment is detached and reattached.
//
// Therefore, we will carry on with the set if the existing attachment has no asset id.
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
if (existingAttachment != null
&& existingAttachment.AssetID != UUID.Zero
&& existingAttachment.AttachPoint == (attachpoint & 0x7F))
{
// m_log.DebugFormat("[AVATAR APPEARANCE] attempt to attach an already attached item {0}",item);
return false;
}
// check if this is an append or a replace, 0x80 marks it as an append
if ((attachpoint & 0x80) > 0)
{
// strip the append bit
int point = attachpoint & 0x7F;
AppendAttachment(new AvatarAttachment(point, item, asset));
}
else
{
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
// check if this is an append or a replace, 0x80 marks it as an append
if ((attachpoint & 0x80) > 0)
{
// strip the append bit
int point = attachpoint & 0x7F;
AppendAttachment(new AvatarAttachment(point, item, asset));
}
else
{
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
}
}
return true;
@@ -547,6 +570,10 @@ namespace OpenSim.Framework
int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
if (index >= 0)
{
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Detaching attachment {0}, index {1}, point {2}",
// m_attachments[kvp.Key][index].ItemID, index, m_attachments[kvp.Key][index].AttachPoint);
// Remove it from the list of attachments at that attach point
m_attachments[kvp.Key].RemoveAt(index);
@@ -580,6 +607,12 @@ namespace OpenSim.Framework
data["serial"] = OSD.FromInteger(m_serial);
data["height"] = OSD.FromReal(m_avatarHeight);
// Hashes
OSDArray hashes = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
hashes.Add(OSD.FromUUID(m_texturehashes[i]));
data["hashes"] = hashes;
// Wearables
OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
@@ -624,6 +657,25 @@ namespace OpenSim.Framework
try
{
// Hashes
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
if ((data != null) && (data["hashes"] != null) && (data["hashes"]).Type == OSDType.Array)
{
OSDArray hashes = (OSDArray)(data["hashes"]);
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
{
UUID hashID = UUID.Zero;
if (i < hashes.Count && hashes[i] != null)
hashID = hashes[i].AsUUID();
m_texturehashes[i] = hashID;
}
}
else
{
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
m_texturehashes[i] = UUID.Zero;
}
// Wearables
SetDefaultWearables();
if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)

View File

@@ -25,19 +25,22 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace OpenSim.ApplicationPlugins.Rest.Inventory
{
/// <summary>
/// This interface represents the boundary between the general purpose
/// REST plugin handling, and the functionally specific handlers. The
/// handler knows only to initialize and terminate all such handlers
/// that it finds. Implementing this interface identifies the class as
/// a REST handler implementation.
/// </summary>
using System;
using System.Text;
using OpenMetaverse;
internal interface IRest
namespace OpenSim.Framework
{
public class CachedTextureRequestArg
{
void Initialize();
void Close();
public int BakedTextureIndex;
public UUID WearableHashID;
}
public class CachedTextureResponseArg
{
public int BakedTextureIndex;
public UUID BakedTextureID;
public String HostName;
}
}

View File

@@ -171,9 +171,10 @@ namespace OpenSim.Framework
/// Soon to be decommissioned
/// </summary>
/// <param name="cAgent"></param>
public void CopyFrom(ChildAgentDataUpdate cAgent)
public void CopyFrom(ChildAgentDataUpdate cAgent, UUID sid)
{
AgentID = new UUID(cAgent.AgentID);
SessionID = sid;
// next: ???
Size = new Vector3();

View File

@@ -33,12 +33,13 @@ namespace OpenSim.Framework
{
public class ClientInfo
{
public AgentCircuitData agentcircuit;
public readonly DateTime StartedTime = DateTime.Now;
public AgentCircuitData agentcircuit = null;
public Dictionary<uint, byte[]> needAck;
public List<byte[]> out_packets;
public Dictionary<uint, uint> pendingAcks;
public List<byte[]> out_packets = new List<byte[]>();
public Dictionary<uint, uint> pendingAcks = new Dictionary<uint,uint>();
public EndPoint proxyEP;
public uint sequence;
@@ -53,5 +54,9 @@ namespace OpenSim.Framework
public int assetThrottle;
public int textureThrottle;
public int totalThrottle;
public Dictionary<string, int> SyncRequests = new Dictionary<string,int>();
public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>();
public Dictionary<string, int> GenericRequests = new Dictionary<string,int>();
}
}

View File

@@ -420,6 +420,21 @@ namespace OpenSim.Framework.Console
SetCursorLeft(0);
m_cursorYPosition = SetCursorTop(m_cursorYPosition);
if (m_echo)
System.Console.Write("{0}{1} ", prompt, m_commandLine);
else
System.Console.Write("{0}", prompt);
break;
case ConsoleKey.Delete:
if (m_cursorXPosition == m_commandLine.Length)
break;
m_commandLine.Remove(m_cursorXPosition, 1);
SetCursorLeft(0);
m_cursorYPosition = SetCursorTop(m_cursorYPosition);
if (m_echo)
System.Console.Write("{0}{1} ", prompt, m_commandLine);
else

View File

@@ -234,7 +234,7 @@ namespace OpenSim.Framework.Console
string uri = "/ReadResponses/" + sessionID.ToString() + "/";
m_Server.AddPollServiceHTTPHandler(
uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID));
uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
@@ -425,7 +425,7 @@ namespace OpenSim.Framework.Console
return false;
}
private Hashtable GetEvents(UUID RequestID, UUID sessionID, string request)
private Hashtable GetEvents(UUID RequestID, UUID sessionID)
{
ConsoleConnection c = null;

View File

@@ -29,10 +29,12 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using log4net;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
@@ -48,13 +50,20 @@ namespace OpenSim.Framework
/// within their data store. However, avoid storing large amounts of data because that
/// would slow down database access.
/// </remarks>
public class DAMap : IDictionary<string, OSDMap>, IXmlSerializable
public class DAMap : IXmlSerializable
{
private static readonly int MIN_STORE_NAME_LENGTH = 4;
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected OSDMap m_map;
public DAMap() { m_map = new OSDMap(); }
private static readonly int MIN_NAMESPACE_LENGTH = 4;
private OSDMap m_map = new OSDMap();
// WARNING: this is temporary for experimentation only, it will be removed!!!!
public OSDMap TopLevelMap
{
get { return m_map; }
set { m_map = value; }
}
public XmlSchema GetSchema() { return null; }
@@ -64,39 +73,34 @@ namespace OpenSim.Framework
map.ReadXml(rawXml);
return map;
}
public void ReadXml(XmlReader reader)
{
ReadXml(reader.ReadInnerXml());
}
public void ReadXml(string rawXml)
{
// System.Console.WriteLine("Trying to deserialize [{0}]", rawXml);
lock (this)
{
m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml);
}
// WARNING: this is temporary for experimentation only, it will be removed!!!!
public OSDMap TopLevelMap
{
get { return m_map; }
set { m_map = value; }
}
public void ReadXml(XmlReader reader)
{
ReadXml(reader.ReadInnerXml());
}
public string ToXml()
{
lock (this)
return OSDParser.SerializeLLSDXmlString(m_map);
SanitiseMap(this);
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteRaw(ToXml());
}
public string ToXml()
{
lock (this)
return OSDParser.SerializeLLSDXmlString(m_map);
}
public void CopyFrom(DAMap other)
{
// Deep copy
@@ -104,7 +108,7 @@ namespace OpenSim.Framework
string data = null;
lock (other)
{
if (other.Count > 0)
if (other.CountNamespaces > 0)
{
data = OSDParser.SerializeLLSDXmlString(other.m_map);
}
@@ -120,59 +124,132 @@ namespace OpenSim.Framework
}
/// <summary>
/// Returns the number of data stores.
/// Sanitise the map to remove any namespaces or stores that are not OSDMap.
/// </summary>
public int Count { get { lock (this) { return m_map.Count; } } }
public bool IsReadOnly { get { return false; } }
/// <summary>
/// Returns the names of the data stores.
/// </summary>
public ICollection<string> Keys { get { lock (this) { return m_map.Keys; } } }
/// <summary>
/// Returns all the data stores.
/// </summary>
public ICollection<OSDMap> Values
/// <param name='map'>
/// </param>
public static void SanitiseMap(DAMap daMap)
{
get
List<string> keysToRemove = null;
OSDMap namespacesMap = daMap.m_map;
foreach (string key in namespacesMap.Keys)
{
lock (this)
// Console.WriteLine("Processing ns {0}", key);
if (!(namespacesMap[key] is OSDMap))
{
List<OSDMap> stores = new List<OSDMap>(m_map.Count);
foreach (OSD llsd in m_map.Values)
stores.Add((OSDMap)llsd);
return stores;
if (keysToRemove == null)
keysToRemove = new List<string>();
keysToRemove.Add(key);
}
}
if (keysToRemove != null)
{
foreach (string key in keysToRemove)
{
// Console.WriteLine ("Removing bad ns {0}", key);
namespacesMap.Remove(key);
}
}
foreach (OSD nsOsd in namespacesMap.Values)
{
OSDMap nsOsdMap = (OSDMap)nsOsd;
keysToRemove = null;
foreach (string key in nsOsdMap.Keys)
{
if (!(nsOsdMap[key] is OSDMap))
{
if (keysToRemove == null)
keysToRemove = new List<string>();
keysToRemove.Add(key);
}
}
if (keysToRemove != null)
foreach (string key in keysToRemove)
nsOsdMap.Remove(key);
}
}
/// <summary>
/// Gets or sets one data store.
/// Get the number of namespaces
/// </summary>
/// <param name="key">Store name</param>
/// <returns></returns>
public OSDMap this[string key]
{
get
{
OSD llsd;
public int CountNamespaces { get { lock (this) { return m_map.Count; } } }
/// <summary>
/// Get the number of stores.
/// </summary>
public int CountStores
{
get
{
int count = 0;
lock (this)
{
if (m_map.TryGetValue(key, out llsd))
return (OSDMap)llsd;
else
return null;
foreach (OSD osdNamespace in m_map)
{
count += ((OSDMap)osdNamespace).Count;
}
}
}
set
return count;
}
}
/// <summary>
/// Retrieve a Dynamic Attribute store
/// </summary>
/// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
/// <param name="storeName">name of the store within the namespace</param>
/// <returns>an OSDMap representing the stored data, or null if not found</returns>
public OSDMap GetStore(string ns, string storeName)
{
OSD namespaceOsd;
lock (this)
{
ValidateKey(key);
lock (this)
m_map[key] = value;
if (m_map.TryGetValue(ns, out namespaceOsd))
{
OSD store;
if (((OSDMap)namespaceOsd).TryGetValue(storeName, out store))
return (OSDMap)store;
}
}
return null;
}
/// <summary>
/// Saves a Dynamic attribute store
/// </summary>
/// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
/// <param name="storeName">name of the store within the namespace</param>
/// <param name="store">an OSDMap representing the data to store</param>
public void SetStore(string ns, string storeName, OSDMap store)
{
ValidateNamespace(ns);
OSDMap nsMap;
lock (this)
{
if (!m_map.ContainsKey(ns))
{
nsMap = new OSDMap();
m_map[ns] = nsMap;
}
nsMap = (OSDMap)m_map[ns];
// m_log.DebugFormat("[DA MAP]: Setting store to {0}:{1}", ns, storeName);
nsMap[storeName] = store;
}
}
@@ -180,54 +257,46 @@ namespace OpenSim.Framework
/// Validate the key used for storing separate data stores.
/// </summary>
/// <param name='key'></param>
private static void ValidateKey(string key)
public static void ValidateNamespace(string ns)
{
if (key.Length < MIN_STORE_NAME_LENGTH)
throw new Exception("Minimum store name length is " + MIN_STORE_NAME_LENGTH);
if (ns.Length < MIN_NAMESPACE_LENGTH)
throw new Exception("Minimum namespace length is " + MIN_NAMESPACE_LENGTH);
}
public bool ContainsKey(string key)
public bool ContainsStore(string ns, string storeName)
{
lock (this)
return m_map.ContainsKey(key);
}
OSD namespaceOsd;
public void Add(string key, OSDMap store)
{
ValidateKey(key);
lock (this)
m_map.Add(key, store);
}
public void Add(KeyValuePair<string, OSDMap> kvp)
{
ValidateKey(kvp.Key);
lock (this)
m_map.Add(kvp.Key, kvp.Value);
}
public bool Remove(string key)
{
lock (this)
return m_map.Remove(key);
}
public bool TryGetValue(string key, out OSDMap store)
{
lock (this)
{
OSD llsd;
if (m_map.TryGetValue(key, out llsd))
if (m_map.TryGetValue(ns, out namespaceOsd))
{
store = (OSDMap)llsd;
return true;
}
else
{
store = null;
return false;
return ((OSDMap)namespaceOsd).ContainsKey(storeName);
}
}
return false;
}
public bool TryGetStore(string ns, string storeName, out OSDMap store)
{
OSD namespaceOsd;
lock (this)
{
if (m_map.TryGetValue(ns, out namespaceOsd))
{
OSD storeOsd;
bool result = ((OSDMap)namespaceOsd).TryGetValue(storeName, out storeOsd);
store = (OSDMap)storeOsd;
return result;
}
}
store = null;
return false;
}
public void Clear()
@@ -235,39 +304,25 @@ namespace OpenSim.Framework
lock (this)
m_map.Clear();
}
public bool Contains(KeyValuePair<string, OSDMap> kvp)
public bool RemoveStore(string ns, string storeName)
{
OSD namespaceOsd;
lock (this)
return m_map.ContainsKey(kvp.Key);
}
{
if (m_map.TryGetValue(ns, out namespaceOsd))
{
OSDMap namespaceOsdMap = (OSDMap)namespaceOsd;
namespaceOsdMap.Remove(storeName);
public void CopyTo(KeyValuePair<string, OSDMap>[] array, int index)
{
throw new NotImplementedException();
}
// Don't keep empty namespaces around
if (namespaceOsdMap.Count <= 0)
m_map.Remove(ns);
}
}
public bool Remove(KeyValuePair<string, OSDMap> kvp)
{
lock (this)
return m_map.Remove(kvp.Key);
}
public System.Collections.IDictionaryEnumerator GetEnumerator()
{
lock (this)
return m_map.GetEnumerator();
}
IEnumerator<KeyValuePair<string, OSDMap>> IEnumerable<KeyValuePair<string, OSDMap>>.GetEnumerator()
{
return null;
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (this)
return m_map.GetEnumerator();
}
return false;
}
}
}

View File

@@ -26,69 +26,73 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.ApplicationPlugins.Rest.Regions
namespace OpenSim.Framework
{
public partial class RestRegionPlugin : RestPlugin
/// <summary>
/// This class stores and retrieves dynamic objects.
/// </summary>
/// <remarks>
/// Experimental - DO NOT USE. Does not yet have namespace support.
/// </remarks>
public class DOMap
{
private static XmlSerializerNamespaces _xmlNs;
static RestRegionPlugin()
private IDictionary<string, object> m_map;
public void Add(string ns, string objName, object dynObj)
{
_xmlNs = new XmlSerializerNamespaces();
_xmlNs.Add(String.Empty, String.Empty);
DAMap.ValidateNamespace(ns);
lock (this)
{
if (m_map == null)
m_map = new Dictionary<string, object>();
m_map.Add(objName, dynObj);
}
}
#region overriding properties
public override string Name
public bool ContainsKey(string key)
{
get { return "REGION"; }
return Get(key) != null;
}
public override string ConfigName
{
get { return "RestRegionPlugin"; }
}
#endregion overriding properties
#region overriding methods
/// <summary>
/// This method is called by OpenSimMain immediately after loading the
/// plugin and after basic server setup, but before running any server commands.
/// Get a dynamic object
/// </summary>
/// <remarks>
/// Note that entries MUST be added to the active configuration files before
/// the plugin can be enabled.
/// Not providing an index method so that users can't casually overwrite each other's objects.
/// </remarks>
public override void Initialise(OpenSimBase openSim)
/// <param name='key'></param>
public object Get(string key)
{
try
lock (this)
{
base.Initialise(openSim);
if (!IsEnabled)
{
//m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID);
return;
}
m_log.InfoFormat("{0} REST region plugin enabled", MsgID);
// add REST method handlers
AddRestStreamHandler("GET", "/regions/", GetHandler);
AddRestStreamHandler("POST", "/regions/", PostHandler);
AddRestStreamHandler("GET", "/regioninfo/", GetRegionInfoHandler);
}
catch (Exception e)
{
m_log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message);
m_log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString());
if (m_map == null)
return null;
else
return m_map[key];
}
}
public override void Close()
public bool Remove(string key)
{
lock (this)
{
if (m_map == null)
return false;
else
return m_map.Remove(key);
}
}
#endregion overriding methods
}
}
}

View File

@@ -58,6 +58,30 @@ namespace OpenSim.Framework
set { m_EstateName = value; }
}
private bool m_AllowLandmark = true;
public bool AllowLandmark
{
get { return m_AllowLandmark; }
set { m_AllowLandmark = value; }
}
private bool m_AllowParcelChanges = true;
public bool AllowParcelChanges
{
get { return m_AllowParcelChanges; }
set { m_AllowParcelChanges = value; }
}
private bool m_AllowSetHome = true;
public bool AllowSetHome
{
get { return m_AllowSetHome; }
set { m_AllowSetHome = value; }
}
private uint m_ParentEstateID = 1;
public uint ParentEstateID
@@ -374,10 +398,18 @@ namespace OpenSim.Framework
return l_EstateAccess.Contains(user);
}
public void SetFromFlags(ulong regionFlags)
{
ResetHomeOnTeleport = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport) == (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport);
BlockDwell = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.BlockDwell) == (ulong)OpenMetaverse.RegionFlags.BlockDwell);
AllowLandmark = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowLandmark) == (ulong)OpenMetaverse.RegionFlags.AllowLandmark);
AllowParcelChanges = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges) == (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges);
AllowSetHome = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowSetHome) == (ulong)OpenMetaverse.RegionFlags.AllowSetHome);
}
public bool GroupAccess(UUID groupID)
{
return l_EstateGroups.Contains(groupID);
}
}
}

View File

@@ -64,7 +64,9 @@ namespace OpenSim.Framework
public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes);
public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams);
public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> cachedTextureData);
public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
@@ -313,7 +315,7 @@ namespace OpenSim.Framework
public delegate void ObjectPermissions(
IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set);
public delegate void EconomyDataRequest(UUID agentID);
public delegate void EconomyDataRequest(IClientAPI client);
public delegate void ObjectIncludeInSearch(IClientAPI remoteClient, bool IncludeInSearch, uint localID);
@@ -780,6 +782,7 @@ namespace OpenSim.Framework
event EstateChangeInfo OnEstateChangeInfo;
event EstateManageTelehub OnEstateManageTelehub;
// [Obsolete("LLClientView Specific.")]
event CachedTextureRequest OnCachedTextureRequest;
event SetAppearance OnSetAppearance;
// [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")]
event AvatarNowWearing OnAvatarNowWearing;
@@ -1087,14 +1090,15 @@ namespace OpenSim.Framework
/// <param name="textureEntry"></param>
void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry);
void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
void SendStartPingCheck(byte seq);
/// <summary>
/// Tell the client that an object has been deleted
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="localID"></param>
void SendKillObject(ulong regionHandle, List<uint> localID);
void SendKillObject(List<uint> localID);
void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
@@ -1116,8 +1120,8 @@ namespace OpenSim.Framework
void SendInstantMessage(GridInstantMessage im);
void SendGenericMessage(string method, List<string> message);
void SendGenericMessage(string method, List<byte[]> message);
void SendGenericMessage(string method, UUID invoice, List<string> message);
void SendGenericMessage(string method, UUID invoice, List<byte[]> message);
void SendLayerData(float[] map);
void SendLayerData(int px, int py, float[] map);
@@ -1155,7 +1159,8 @@ namespace OpenSim.Framework
void SendTeleportStart(uint flags);
void SendTeleportProgress(uint flags, string message);
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item);
void SendPayPrice(UUID objectID, int[] payPrice);
void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
@@ -1250,8 +1255,6 @@ namespace OpenSim.Framework
void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch,
string[] buttonlabels);
bool AddMoney(int debit);
/// <summary>
/// Update the client as to where the sun is currently located.
/// </summary>

View File

@@ -55,6 +55,13 @@ namespace OpenSim.Region.Framework.Interfaces
/// <returns>Land object at the point supplied</returns>
ILandObject GetLandObject(float x, float y);
/// <summary>
/// Get the parcel at the specified point
/// </summary>
/// <param name="position">Vector where x and y components are between 0 and 256. z component is ignored.</param>
/// <returns>Land object at the point supplied</returns>
ILandObject GetLandObject(Vector3 position);
/// <summary>
/// Get the parcels near the specified point
/// </summary>

View File

@@ -38,7 +38,8 @@ namespace OpenSim.Framework
int GetBalance(UUID agentID);
bool UploadCovered(UUID agentID, int amount);
bool AmountCovered(UUID agentID, int amount);
void ApplyCharge(UUID agentID, int amount, string text);
void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type);
void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData);
void ApplyUploadCharge(UUID agentID, int amount, string text);
int UploadCharge { get; }

View File

@@ -0,0 +1,47 @@
/*
* 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
{
public class UserData
{
public UUID Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string HomeURL { get; set; }
public Dictionary<string, object> ServerURLs { get; set; }
}
public interface IPeople
{
List<UserData> GetUserData(string query, int page_size, int page_number);
}
}

View File

@@ -136,5 +136,10 @@ namespace OpenSim.Framework
ISceneObject DeserializeObject(string representation);
bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
/// <summary>
/// Start the scene and associated scripts within it.
/// </summary>
void Start();
}
}
}

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -45,16 +45,16 @@ namespace OpenSim.Framework.Monitoring
sb.Append(Environment.NewLine);
sb.AppendFormat(
"Allocated to OpenSim objects: {0} MB\n",
"Heap allocated to OpenSim : {0} MB\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
sb.AppendFormat(
"OpenSim last object memory churn : {0} MB/s\n",
Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
"Last heap allocation rate : {0} MB/s\n",
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
sb.AppendFormat(
"OpenSim average object memory churn : {0} MB/s\n",
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
"Average heap allocation rate: {0} MB/s\n",
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
sb.AppendFormat(
"Process memory : {0} MB\n",

View File

@@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
private static bool m_enabled;
/// <summary>
/// Last memory churn in bytes per millisecond.
/// Average heap allocation rate in bytes per millisecond.
/// </summary>
public static double AverageMemoryChurn
public static double AverageHeapAllocationRate
{
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
}
/// <summary>
/// Average memory churn in bytes per millisecond.
/// Last heap allocation in bytes
/// </summary>
public static double LastMemoryChurn
public static double LastHeapAllocationRate
{
get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
}

View File

@@ -0,0 +1,349 @@
/*
* 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.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using log4net;
using Nini.Config;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
namespace OpenSim.Framework.Monitoring
{
public class ServerStatsCollector
{
private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly string LogHeader = "[SERVER STATS]";
public bool Enabled = false;
private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
public readonly string CategoryServer = "server";
public readonly string ContainerThreadpool = "threadpool";
public readonly string ContainerProcessor = "processor";
public readonly string ContainerMemory = "memory";
public readonly string ContainerNetwork = "network";
public readonly string ContainerProcess = "process";
public string NetworkInterfaceTypes = "Ethernet";
readonly int performanceCounterSampleInterval = 500;
// int lastperformanceCounterSampleTime = 0;
private class PerfCounterControl
{
public PerformanceCounter perfCounter;
public int lastFetch;
public string name;
public PerfCounterControl(PerformanceCounter pPc)
: this(pPc, String.Empty)
{
}
public PerfCounterControl(PerformanceCounter pPc, string pName)
{
perfCounter = pPc;
lastFetch = 0;
name = pName;
}
}
PerfCounterControl processorPercentPerfCounter = null;
// IRegionModuleBase.Initialize
public void Initialise(IConfigSource source)
{
IConfig cfg = source.Configs["Monitoring"];
if (cfg != null)
Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
if (Enabled)
{
NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
}
}
public void Start()
{
if (RegisteredStats.Count == 0)
RegisterServerStats();
}
public void Close()
{
if (RegisteredStats.Count > 0)
{
foreach (Stat stat in RegisteredStats.Values)
{
StatsManager.DeregisterStat(stat);
stat.Dispose();
}
RegisteredStats.Clear();
}
}
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
{
MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
}
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
{
string desc = pDesc;
if (desc == null)
desc = pName;
Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
StatsManager.RegisterStat(stat);
RegisteredStats.Add(pName, stat);
}
public void RegisterServerStats()
{
// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
PerformanceCounter tempPC;
Stat tempStat;
string tempName;
try
{
tempName = "CPUPercent";
tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
processorPercentPerfCounter = new PerfCounterControl(tempPC);
// A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
MakeStat("Threads", null, "threads", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
}
MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
s =>
{
int workerThreads, iocpThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
s.Value = workerThreads;
});
MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
s =>
{
int workerThreads, iocpThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
s.Value = iocpThreads;
});
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
{
MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
}
MakeStat(
"HTTPRequestsMade",
"Number of outbound HTTP requests made",
"requests",
ContainerNetwork,
s => s.Value = WebUtil.RequestNumber,
MeasuresOfInterest.AverageChangeOverTime);
try
{
List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface nic in nics)
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
string nicInterfaceType = nic.NetworkInterfaceType.ToString();
if (!okInterfaceTypes.Contains(nicInterfaceType))
{
m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
LogHeader, nic.Name, nicInterfaceType);
m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
LogHeader, NetworkInterfaceTypes);
continue;
}
if (nic.Supports(NetworkInterfaceComponent.IPv4))
{
IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
if (nicStats != null)
{
MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
}
}
// TODO: add IPv6 (it may actually happen someday)
}
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
}
MakeStat("ProcessMemory", null, "MB", ContainerMemory,
(s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
MakeStat("HeapMemory", null, "MB", ContainerMemory,
(s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
}
// Notes on performance counters:
// "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
// "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
// "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
private delegate double PerfCounterNextValue();
private void GetNextValue(Stat stat, PerfCounterControl perfControl)
{
GetNextValue(stat, perfControl, 1.0);
}
private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
{
if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
{
if (perfControl != null && perfControl.perfCounter != null)
{
try
{
// Kludge for factor to run double duty. If -1, subtract the value from one
if (factor == -1)
stat.Value = 1 - perfControl.perfCounter.NextValue();
else
stat.Value = perfControl.perfCounter.NextValue() / factor;
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
}
perfControl.lastFetch = Util.EnvironmentTickCount();
}
}
}
// Lookup the nic that goes with this stat and set the value by using a fetch action.
// Not sure about closure with delegates inside delegates.
private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
{
// Get the one nic that has the name of this stat
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
(network) => network.Name == stat.Description);
try
{
foreach (NetworkInterface nic in nics)
{
IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
if (intrStats != null)
{
double newVal = Math.Round(getter(intrStats) / factor, 3);
stat.Value = newVal;
}
break;
}
}
catch
{
// There are times interfaces go away so we just won't update the stat for this
m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
}
}
}
public class ServerStatsAggregator : Stat
{
public ServerStatsAggregator(
string shortName,
string name,
string description,
string unitName,
string category,
string container
)
: base(
shortName,
name,
description,
unitName,
category,
container,
StatType.Push,
MeasuresOfInterest.None,
null,
StatVerbosity.Info)
{
}
public override string ToConsoleString()
{
StringBuilder sb = new StringBuilder();
return sb.ToString();
}
public override OSDMap ToOSDMap()
{
OSDMap ret = new OSDMap();
return ret;
}
}
}

View File

@@ -359,8 +359,9 @@ Asset service request failures: {3}" + Environment.NewLine,
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
/* 20130319 RA: For the moment, disable the dump of 'scene' catagory as they are mostly output by
* the two formatted printouts above.
SortedDictionary<string, SortedDictionary<string, Stat>> sceneStats;
if (StatsManager.TryGetStats("scene", out sceneStats))
{
foreach (KeyValuePair<string, SortedDictionary<string, Stat>> kvp in sceneStats)
@@ -374,6 +375,7 @@ Asset service request failures: {3}" + Environment.NewLine,
}
}
}
*/
/*
sb.Append(Environment.NewLine);

View File

@@ -224,5 +224,26 @@ public class CounterStat : Stat
}
}
}
// CounterStat is a basic stat plus histograms
public override OSDMap ToOSDMap()
{
// Get the foundational instance
OSDMap map = base.ToOSDMap();
map["StatType"] = "CounterStat";
// If there are any histograms, add a new field that is an array of histograms as OSDMaps
if (m_histograms.Count > 0)
{
OSDArray histos = new OSDArray();
foreach (EventHistogram histo in m_histograms.Values)
{
histos.Add(histo.GetHistogramAsOSDMap());
}
map.Add("Histograms", histos);
}
return map;
}
}
}

View File

@@ -27,8 +27,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using log4net;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework.Monitoring
@@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
/// </summary>
public class Stat : IDisposable
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static readonly char[] DisallowedShortNameCharacters = { '.' };
/// <summary>
/// Category of this stat (e.g. cache, scene, etc).
/// </summary>
@@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
/// <remarks>
/// Will be null if no measures of interest require samples.
/// </remarks>
private static Queue<double> m_samples;
private Queue<double> m_samples;
/// <summary>
/// Maximum number of statistical samples.
@@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
throw new Exception(
string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
foreach (char c in DisallowedShortNameCharacters)
{
if (shortName.IndexOf(c) != -1)
throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
}
ShortName = shortName;
Name = name;
Description = description;
@@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
if (m_samples.Count >= m_maxSamples)
m_samples.Dequeue();
// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
m_samples.Enqueue(newValue);
}
}
@@ -228,6 +242,7 @@ namespace OpenSim.Framework.Monitoring
ret.Add("Description", OSD.FromString(Description));
ret.Add("UnitName", OSD.FromString(UnitName));
ret.Add("Value", OSD.FromReal(Value));
ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat
return ret;
}
@@ -242,6 +257,10 @@ namespace OpenSim.Framework.Monitoring
lock (m_samples)
{
// m_log.DebugFormat(
// "[STAT]: Samples for {0} are {1}",
// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
foreach (double s in m_samples)
{
if (lastSample != null)
@@ -253,7 +272,7 @@ namespace OpenSim.Framework.Monitoring
int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
}
}
}

View File

@@ -27,8 +27,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework.Monitoring
{
/// <summary>
@@ -54,13 +57,13 @@ namespace OpenSim.Framework.Monitoring
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
private static AssetStatsCollector assetStats;
private static UserStatsCollector userStats;
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
// private static AssetStatsCollector assetStats;
// private static UserStatsCollector userStats;
// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
public static AssetStatsCollector AssetStats { get { return assetStats; } }
public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
// public static AssetStatsCollector AssetStats { get { return assetStats; } }
// public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get; set; }
public static void RegisterConsoleCommands(ICommandConsole console)
{
@@ -68,12 +71,14 @@ namespace OpenSim.Framework.Monitoring
"General",
false,
"show stats",
"show stats [list|all|<category>]",
"show stats [list|all|(<category>[.<container>])+",
"Show statistical information for this server",
"If no final argument is specified then legacy statistics information is currently shown.\n"
+ "If list is specified then statistic categories are shown.\n"
+ "If all is specified then all registered statistics are shown.\n"
+ "If a category name is specified then only statistics from that category are shown.\n"
+ "'list' argument will show statistic categories.\n"
+ "'all' will show all statistics.\n"
+ "A <category> name will show statistics from that category.\n"
+ "A <category>.<container> name will show statistics from that category in that container.\n"
+ "More than one name can be given separated by spaces.\n"
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
HandleShowStatsCommand);
}
@@ -84,43 +89,47 @@ namespace OpenSim.Framework.Monitoring
if (cmd.Length > 2)
{
var categoryName = cmd[2];
var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
foreach (string name in cmd.Skip(2))
{
string[] components = name.Split('.');
if (categoryName == AllSubCommand)
{
foreach (var category in RegisteredStats.Values)
string categoryName = components[0];
string containerName = components.Length > 1 ? components[1] : null;
if (categoryName == AllSubCommand)
{
OutputCategoryStatsToConsole(con, category);
OutputAllStatsToConsole(con);
}
}
else if (categoryName == ListSubCommand)
{
con.Output("Statistic categories available are:");
foreach (string category in RegisteredStats.Keys)
con.OutputFormat(" {0}", category);
}
else
{
SortedDictionary<string, SortedDictionary<string, Stat>> category;
if (!RegisteredStats.TryGetValue(categoryName, out category))
else if (categoryName == ListSubCommand)
{
con.OutputFormat("No such category as {0}", categoryName);
con.Output("Statistic categories available are:");
foreach (string category in RegisteredStats.Keys)
con.OutputFormat(" {0}", category);
}
else
{
if (String.IsNullOrEmpty(containerName))
OutputCategoryStatsToConsole(con, category);
SortedDictionary<string, SortedDictionary<string, Stat>> category;
if (!RegisteredStats.TryGetValue(categoryName, out category))
{
con.OutputFormat("No such category as {0}", categoryName);
}
else
{
SortedDictionary<string, Stat> container;
if (category.TryGetValue(containerName, out container))
if (String.IsNullOrEmpty(containerName))
{
OutputContainerStatsToConsole(con, container);
OutputCategoryStatsToConsole(con, category);
}
else
{
con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
SortedDictionary<string, Stat> container;
if (category.TryGetValue(containerName, out container))
{
OutputContainerStatsToConsole(con, container);
}
else
{
con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
}
}
}
}
@@ -129,7 +138,18 @@ namespace OpenSim.Framework.Monitoring
else
{
// Legacy
con.Output(SimExtraStats.Report());
if (SimExtraStats != null)
con.Output(SimExtraStats.Report());
else
OutputAllStatsToConsole(con);
}
}
private static void OutputAllStatsToConsole(ICommandConsole con)
{
foreach (var category in RegisteredStats.Values)
{
OutputCategoryStatsToConsole(con, category);
}
}
@@ -150,27 +170,91 @@ namespace OpenSim.Framework.Monitoring
}
}
/// <summary>
/// Start collecting statistics related to assets.
/// Should only be called once.
/// </summary>
public static AssetStatsCollector StartCollectingAssetStats()
// Creates an OSDMap of the format:
// { categoryName: {
// containerName: {
// statName: {
// "Name": name,
// "ShortName": shortName,
// ...
// },
// statName: {
// "Name": name,
// "ShortName": shortName,
// ...
// },
// ...
// },
// containerName: {
// ...
// },
// ...
// },
// categoryName: {
// ...
// },
// ...
// }
// The passed in parameters will filter the categories, containers and stats returned. If any of the
// parameters are either EmptyOrNull or the AllSubCommand value, all of that type will be returned.
// Case matters.
public static OSDMap GetStatsAsOSDMap(string pCategoryName, string pContainerName, string pStatName)
{
assetStats = new AssetStatsCollector();
OSDMap map = new OSDMap();
return assetStats;
foreach (string catName in RegisteredStats.Keys)
{
// Do this category if null spec, "all" subcommand or category name matches passed parameter.
// Skip category if none of the above.
if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
continue;
OSDMap contMap = new OSDMap();
foreach (string contName in RegisteredStats[catName].Keys)
{
if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
continue;
OSDMap statMap = new OSDMap();
SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
foreach (string statName in theStats.Keys)
{
if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
continue;
statMap.Add(statName, theStats[statName].ToOSDMap());
}
contMap.Add(contName, statMap);
}
map.Add(catName, contMap);
}
return map;
}
/// <summary>
/// Start collecting statistics related to users.
/// Should only be called once.
/// </summary>
public static UserStatsCollector StartCollectingUserStats()
{
userStats = new UserStatsCollector();
return userStats;
}
// /// <summary>
// /// Start collecting statistics related to assets.
// /// Should only be called once.
// /// </summary>
// public static AssetStatsCollector StartCollectingAssetStats()
// {
// assetStats = new AssetStatsCollector();
//
// return assetStats;
// }
//
// /// <summary>
// /// Start collecting statistics related to users.
// /// Should only be called once.
// /// </summary>
// public static UserStatsCollector StartCollectingUserStats()
// {
// userStats = new UserStatsCollector();
//
// return userStats;
// }
/// <summary>
/// Registers a statistic.

View File

@@ -218,7 +218,7 @@ namespace OpenSim.Framework
Console.WriteLine ("Looking for updates...");
Repositories.UpdateAllRepositories (ps);
Console.WriteLine ("Available add-in updates:");
bool found = false;
AddinRepositoryEntry[] entries = Repositories.GetAvailableUpdates();
foreach (AddinRepositoryEntry entry in entries)
@@ -541,7 +541,7 @@ namespace OpenSim.Framework
{
list.AddRange(PluginRegistry.GetAddins());
}
catch(Exception e)
catch (Exception)
{
Addin[] x = xlist.ToArray(typeof(Addin)) as Addin[];
return x;

View File

@@ -86,25 +86,22 @@ namespace OpenSim.Framework.Servers
/// </summary>
protected virtual void StartupSpecific()
{
if (m_console == null)
return;
StatsManager.SimExtraStats = new SimExtraStatsCollector();
RegisterCommonCommands();
m_console.Commands.AddCommand("General", false, "quit",
"quit",
"Quit the application", HandleQuit);
RegisterCommonComponents(Config);
}
m_console.Commands.AddCommand("General", false, "shutdown",
"shutdown",
"Quit the application", HandleQuit);
protected override void ShutdownSpecific()
{
m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
RemovePIDFile();
base.ShutdownSpecific();
Environment.Exit(0);
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
/// </summary>
public virtual void ShutdownSpecific() {}
/// <summary>
/// Provides a list of help topics that are available. Overriding classes should append their topics to the
/// information returned when the base method is called.
@@ -133,17 +130,7 @@ namespace OpenSim.Framework.Servers
/// Performs initialisation of the scene, such as loading configuration from disk.
/// </summary>
public virtual void Startup()
{
m_log.Info("[STARTUP]: Beginning startup processing");
m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine);
// clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
// the clr version number doesn't match the project version number under Mono.
//m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine);
m_log.InfoFormat(
"[STARTUP]: Operating system version: {0}, .NET platform {1}, {2}-bit\n",
Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32");
{
StartupSpecific();
TimeSpan timeTaken = DateTime.Now - m_startuptime;
@@ -153,25 +140,8 @@ namespace OpenSim.Framework.Servers
timeTaken.Minutes, timeTaken.Seconds);
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
/// </summary>
public virtual void Shutdown()
public string osSecret
{
ShutdownSpecific();
m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
RemovePIDFile();
Environment.Exit(0);
}
private void HandleQuit(string module, string[] args)
{
Shutdown();
}
public string osSecret {
// Secret uuid for the simulator
get { return m_osSecret; }
}

View File

@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
/// <summary>
/// This is a pending websocket request before it got an sucessful upgrade response.
/// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
/// </remarks>
public int RequestNumber { get; private set; }
/// <summary>
/// Statistic for holding number of requests processed.
/// </summary>
private Stat m_requestsProcessedStat;
private volatile int NotSocketErrors = 0;
public volatile bool HTTPDRunning = false;
@@ -436,9 +440,8 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
{
OSHttpRequest req = new OSHttpRequest(context, request);
WebSocketRequestDelegate dWebSocketRequestDelegate = null;
lock (m_WebSocketHandlers)
@@ -453,9 +456,8 @@ namespace OpenSim.Framework.Servers.HttpServer
}
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
HandleRequest(req, resp);
resp.ReuseContext = true;
HandleRequest(req, resp);
// !!!HACK ALERT!!!
// There seems to be a bug in the underlying http code that makes subsequent requests
@@ -486,7 +488,9 @@ namespace OpenSim.Framework.Servers.HttpServer
{
try
{
SendHTML500(response);
byte[] buffer500 = SendHTML500(response);
response.Body.Write(buffer500,0,buffer500.Length);
response.Body.Close();
}
catch
{
@@ -684,7 +688,7 @@ namespace OpenSim.Framework.Servers.HttpServer
if (buffer != null)
{
if (!response.SendChunked)
if (!response.SendChunked && response.ContentLength64 <= 0)
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(buffer, 0, buffer.Length);
@@ -719,7 +723,15 @@ namespace OpenSim.Framework.Servers.HttpServer
catch (Exception e)
{
m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
SendHTML500(response);
try
{
byte[] buffer500 = SendHTML500(response);
response.Body.Write(buffer500, 0, buffer500.Length);
response.Body.Close();
}
catch
{
}
}
finally
{
@@ -1746,7 +1758,8 @@ namespace OpenSim.Framework.Servers.HttpServer
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
return buffer;
}
@@ -1813,6 +1826,21 @@ namespace OpenSim.Framework.Servers.HttpServer
// useful without inbound HTTP.
throw e;
}
m_requestsProcessedStat
= new Stat(
"HTTPRequestsServed",
"Number of inbound HTTP requests processed",
"",
"requests",
"httpserver",
Port.ToString(),
StatType.Pull,
MeasuresOfInterest.AverageChangeOverTime,
stat => stat.Value = RequestNumber,
StatVerbosity.Debug);
StatsManager.RegisterStat(m_requestsProcessedStat);
}
public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1843,6 +1871,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Stop()
{
HTTPDRunning = false;
StatsManager.DeregisterStat(m_requestsProcessedStat);
try
{
m_PollServiceManager.Stop();

View File

@@ -0,0 +1,60 @@
/*
* 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.IO;
namespace OpenSim.Framework.Servers.HttpServer
{
/// <summary>
/// Base handler for writing to an output stream
/// </summary>
/// <remarks>
/// Inheriting classes should override ProcessRequest() rather than Handle()
/// </remarks>
public abstract class BaseOutputStreamHandler : BaseRequestHandler, IRequestHandler
{
protected BaseOutputStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseOutputStreamHandler(string httpMethod, string path, string name, string description)
: base(httpMethod, path, name, description) {}
public virtual void Handle(
string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
RequestsReceived++;
ProcessRequest(path, request, response, httpRequest, httpResponse);
RequestsHandled++;
}
protected virtual void ProcessRequest(
string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
}
}
}

View File

@@ -31,6 +31,10 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public abstract class BaseRequestHandler
{
public int RequestsReceived { get; protected set; }
public int RequestsHandled { get; protected set; }
public virtual string ContentType
{
get { return "application/xml"; }

View File

@@ -29,14 +29,35 @@ using System.IO;
namespace OpenSim.Framework.Servers.HttpServer
{
/// <summary>
/// Base streamed request handler.
/// </summary>
/// <remarks>
/// Inheriting classes should override ProcessRequest() rather than Handle()
/// </remarks>
public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
{
public abstract byte[] Handle(string path, Stream request,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseStreamHandler(string httpMethod, string path, string name, string description)
: base(httpMethod, path, name, description) {}
public virtual byte[] Handle(
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
RequestsReceived++;
byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
RequestsHandled++;
return result;
}
protected virtual byte[] ProcessRequest(
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
return null;
}
}
}

View File

@@ -45,7 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_method = binaryMethod;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
byte[] data = ReadFully(request);
string param = GetParam(path);

View File

@@ -32,7 +32,6 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public interface IRequestHandler
{
/// <summary>
/// Name for this handler.
/// </summary>
@@ -59,6 +58,19 @@ namespace OpenSim.Framework.Servers.HttpServer
// Return path
string Path { get; }
/// <summary>
/// Number of requests received by this handler
/// </summary>
int RequestsReceived { get; }
/// <summary>
/// Number of requests handled.
/// </summary>
/// <remarks>
/// Should be equal to RequestsReceived unless requested are being handled slowly or there is deadlock.
/// </remarks>
int RequestsHandled { get; }
}
public interface IStreamedRequestHandler : IRequestHandler
@@ -69,7 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
public interface IStreamHandler : IRequestHandler
{
// Handle request stream, return byte array
void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse);
}

View File

@@ -34,7 +34,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate void RequestMethod(UUID requestID, Hashtable request);
public delegate bool HasEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request);
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
@@ -45,17 +45,28 @@ namespace OpenSim.Framework.Servers.HttpServer
public NoEventsMethod NoEvents;
public RequestMethod Request;
public UUID Id;
public int TimeOutms;
public EventType Type;
public enum EventType : int
{
Normal = 0,
LslHttp = 1,
Inventory = 2
}
public PollServiceEventArgs(
RequestMethod pRequest,
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
UUID pId)
UUID pId, int pTimeOutms)
{
Request = pRequest;
HasEvents = pHasEvents;
GetEvents = pGetEvents;
NoEvents = pNoEvents;
Id = pId;
TimeOutms = pTimeOutms;
Type = EventType.Normal;
}
}
}
}

View File

@@ -33,54 +33,60 @@ using log4net;
using HttpServer;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using Amib.Threading;
using System.IO;
using System.Text;
using System.Collections.Generic;
namespace OpenSim.Framework.Servers.HttpServer
{
public class PollServiceRequestManager
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly BaseHttpServer m_server;
private static Queue m_requests = Queue.Synchronized(new Queue());
private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
private static Queue<PollServiceHttpRequest> m_slowRequests = new Queue<PollServiceHttpRequest>();
private static Queue<PollServiceHttpRequest> m_retryRequests = new Queue<PollServiceHttpRequest>();
private uint m_WorkerThreadCount = 0;
private Thread[] m_workerThreads;
private PollServiceWorkerThread[] m_PollServiceWorkerThreads;
private volatile bool m_running = true;
private int m_pollTimeout;
private Thread m_retrysThread;
private bool m_running = true;
private int slowCount = 0;
private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
// private int m_timeout = 1000; // increase timeout 250; now use the event one
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
{
m_server = pSrv;
m_WorkerThreadCount = pWorkerThreadCount;
m_pollTimeout = pTimeout;
m_workerThreads = new Thread[m_WorkerThreadCount];
}
public void Start()
{
m_running = true;
m_workerThreads = new Thread[m_WorkerThreadCount];
m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
//startup worker threads
for (uint i = 0; i < m_WorkerThreadCount; i++)
{
m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, m_pollTimeout);
m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent;
m_workerThreads[i]
= Watchdog.StartThread(
m_PollServiceWorkerThreads[i].ThreadStart,
String.Format("PollServiceWorkerThread{0}", i),
PoolWorkerJob,
string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
ThreadPriority.Normal,
false,
true,
false,
null,
int.MaxValue);
}
Watchdog.StartThread(
this.ThreadStart,
"PollServiceWatcherThread",
m_retrysThread = Watchdog.StartThread(
this.CheckRetries,
string.Format("PollServiceWatcherThread:{0}", m_server.Port),
ThreadPriority.Normal,
false,
true,
@@ -88,78 +94,210 @@ namespace OpenSim.Framework.Servers.HttpServer
1000 * 60 * 10);
}
internal void ReQueueEvent(PollServiceHttpRequest req)
private void ReQueueEvent(PollServiceHttpRequest req)
{
// Do accounting stuff here
Enqueue(req);
if (m_running)
{
lock (m_retryRequests)
m_retryRequests.Enqueue(req);
}
}
public void Enqueue(PollServiceHttpRequest req)
{
lock (m_requests)
m_requests.Enqueue(req);
if (m_running)
{
if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.Normal)
{
m_requests.Enqueue(req);
}
else
{
lock (m_slowRequests)
m_slowRequests.Enqueue(req);
}
}
}
public void ThreadStart()
private void CheckRetries()
{
while (m_running)
{
Thread.Sleep(100); // let the world move .. back to faster rate
Watchdog.UpdateThread();
ProcessQueuedRequests();
Thread.Sleep(1000);
}
}
private void ProcessQueuedRequests()
{
lock (m_requests)
{
if (m_requests.Count == 0)
return;
// m_log.DebugFormat("[POLL SERVICE REQUEST MANAGER]: Processing {0} requests", m_requests.Count);
int reqperthread = (int) (m_requests.Count/m_WorkerThreadCount) + 1;
// For Each WorkerThread
for (int tc = 0; tc < m_WorkerThreadCount && m_requests.Count > 0; tc++)
lock (m_retryRequests)
{
//Loop over number of requests each thread handles.
for (int i = 0; i < reqperthread && m_requests.Count > 0; i++)
while (m_retryRequests.Count > 0 && m_running)
m_requests.Enqueue(m_retryRequests.Dequeue());
}
slowCount++;
if (slowCount >= 10)
{
slowCount = 0;
lock (m_slowRequests)
{
try
{
m_PollServiceWorkerThreads[tc].Enqueue((PollServiceHttpRequest)m_requests.Dequeue());
}
catch (InvalidOperationException)
{
// The queue is empty, we did our calculations wrong!
return;
}
while (m_slowRequests.Count > 0 && m_running)
m_requests.Enqueue(m_slowRequests.Dequeue());
}
}
}
}
public void Stop()
{
m_running = false;
// m_timeout = -10000; // cause all to expire
Thread.Sleep(1000); // let the world move
foreach (object o in m_requests)
foreach (Thread t in m_workerThreads)
Watchdog.AbortThread(t.ManagedThreadId);
try
{
PollServiceHttpRequest req = (PollServiceHttpRequest) o;
PollServiceWorkerThread.DoHTTPGruntWork(
m_server, req, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
foreach (PollServiceHttpRequest req in m_retryRequests)
{
DoHTTPGruntWork(m_server,req,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
}
catch
{
}
PollServiceHttpRequest wreq;
m_retryRequests.Clear();
lock (m_slowRequests)
{
while (m_slowRequests.Count > 0 && m_running)
m_requests.Enqueue(m_slowRequests.Dequeue());
}
while (m_requests.Count() > 0)
{
try
{
wreq = m_requests.Dequeue(0);
DoHTTPGruntWork(m_server,wreq,
wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id));
}
catch
{
}
}
m_requests.Clear();
}
foreach (Thread t in m_workerThreads)
// work threads
private void PoolWorkerJob()
{
while (m_running)
{
t.Abort();
PollServiceHttpRequest req = m_requests.Dequeue(5000);
Watchdog.UpdateThread();
if (req != null)
{
try
{
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
if (responsedata == null)
continue;
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal) // This is the event queue
{
try
{
DoHTTPGruntWork(m_server, req, responsedata);
}
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
{
// Ignore it, no need to reply
}
}
else
{
m_threadPool.QueueWorkItem(x =>
{
try
{
DoHTTPGruntWork(m_server, req, responsedata);
}
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
{
// Ignore it, no need to reply
}
return null;
}, null);
}
}
else
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
DoHTTPGruntWork(m_server, req,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
else
{
ReQueueEvent(req);
}
}
}
catch (Exception e)
{
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
}
}
}
}
// DoHTTPGruntWork changed, not sending response
// do the same work around as core
internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
{
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (Exception e)
{
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
}
}
}
}
}
}

View File

@@ -1,165 +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;
using System.Collections.Generic;
using System.IO;
using System.Text;
using HttpServer;
using OpenMetaverse;
using System.Reflection;
using log4net;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Framework.Servers.HttpServer
{
public delegate void ReQueuePollServiceItem(PollServiceHttpRequest req);
public class PollServiceWorkerThread
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
public event ReQueuePollServiceItem ReQueue;
private readonly BaseHttpServer m_server;
private BlockingQueue<PollServiceHttpRequest> m_request;
private bool m_running = true;
private int m_timeout = 250;
public PollServiceWorkerThread(BaseHttpServer pSrv, int pTimeout)
{
m_request = new BlockingQueue<PollServiceHttpRequest>();
m_server = pSrv;
m_timeout = pTimeout;
}
public void ThreadStart()
{
Run();
}
public void Run()
{
while (m_running)
{
PollServiceHttpRequest req = m_request.Dequeue();
Watchdog.UpdateThread();
try
{
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
StreamReader str;
try
{
str = new StreamReader(req.Request.Body);
}
catch (System.ArgumentException)
{
// Stream was not readable means a child agent
// was closed due to logout, leaving the
// Event Queue request orphaned.
continue;
}
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
DoHTTPGruntWork(m_server, req, responsedata);
}
else
{
if ((Environment.TickCount - req.RequestTime) > m_timeout)
{
DoHTTPGruntWork(
m_server,
req,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
}
else
{
ReQueuePollServiceItem reQueueItem = ReQueue;
if (reQueueItem != null)
reQueueItem(req);
}
}
}
catch (Exception e)
{
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
}
}
}
internal void Enqueue(PollServiceHttpRequest pPollServiceHttpRequest)
{
m_request.Enqueue(pPollServiceHttpRequest);
}
/// <summary>
/// FIXME: This should be part of BaseHttpServer
/// </summary>
internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
{
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (Exception e)
{
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
}
}
}
}
}

View File

@@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request);
public class RestDeserialiseHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler
public class RestDeserialiseHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
where TRequest : new()
{
private RestDeserialiseMethod<TRequest, TResponse> m_method;
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_method = method;
}
public void Handle(string path, Stream request, Stream responseStream,
protected override void ProcessRequest(string path, Stream request, Stream responseStream,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
TRequest deserial;

View File

@@ -183,7 +183,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate bool CheckIdentityMethod(string sid, string aid);
public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler
public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
where TRequest : new()
{
private static readonly ILog m_log
@@ -201,7 +201,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_method = method;
}
public void Handle(string path, Stream request, Stream responseStream,
protected override void ProcessRequest(string path, Stream request, Stream responseStream,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>);
@@ -237,7 +237,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate bool CheckTrustedSourceMethod(IPEndPoint peer);
public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler
public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
where TRequest : new()
{
private static readonly ILog m_log
@@ -260,7 +260,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_method = method;
}
public void Handle(string path, Stream request, Stream responseStream,
protected override void ProcessRequest(string path, Stream request, Stream responseStream,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
TRequest deserial = default(TRequest);
@@ -292,6 +292,5 @@ namespace OpenSim.Framework.Servers.HttpServer
serializer.Serialize(xmlWriter, response);
}
}
}
}
}
}

View File

@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_restMethod = restMethod;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
Encoding encoding = Encoding.UTF8;
StreamReader streamReader = new StreamReader(request, encoding);

View File

@@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// <summary>
/// This is a regular HTTP Request... This may be removed in the future.
/// </summary>
public event RegularHttpRequestDelegate OnRegularHttpRequest;
// public event RegularHttpRequestDelegate OnRegularHttpRequest;
/// <summary>
/// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@@ -304,15 +304,14 @@ namespace OpenSim.Framework.Servers.HttpServer
if (d != null)
d(this, new UpgradeCompletedEventArgs());
}
catch (IOException fail)
catch (IOException)
{
Close(string.Empty);
}
catch (ObjectDisposedException fail)
catch (ObjectDisposedException)
{
Close(string.Empty);
}
}
}
/// <summary>
@@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
_socketState.Header = pheader;
}
if (_socketState.FrameComplete)
{
ProcessFrame(_socketState);
@@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
_socketState.ExpectedBytes = 0;
}
}
}
else
@@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
_socketState.ReceivedBytes.Clear();
_socketState.ExpectedBytes = 0;
// do some processing
}
}
}
}
if (offset > 0)
@@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
{
// We can't read the stream anymore...
}
}
catch (IOException fail)
catch (IOException)
{
Close(string.Empty);
}
catch (ObjectDisposedException fail)
catch (ObjectDisposedException)
{
Close(string.Empty);
}

View File

@@ -121,12 +121,14 @@ namespace OpenSim.Framework.Servers
+ " level >= 2 then long warnings are logged when receiving bad input data.\n"
+ " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n"
+ " level >= 4 then the time taken to fulfill the request is logged.\n"
+ " level >= 5 then a sample from the beginning of the incoming data is logged.\n"
+ " level >= 6 then the entire incoming data is logged.\n"
+ " level >= 5 then a sample from the beginning of the data is logged.\n"
+ " level >= 6 then the entire data is logged.\n"
+ " no level is specified then the current level is returned.\n\n"
+ "If out or all and\n"
+ " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n"
+ " level >= 4 then the time taken to fulfill the request is logged.\n",
+ " level >= 4 then the time taken to fulfill the request is logged.\n"
+ " level >= 5 then a sample from the beginning of the data is logged.\n"
+ " level >= 6 then the entire data is logged.\n",
HandleDebugHttpCommand);
}

View File

@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
protected string m_pidFile = String.Empty;
protected ServerStatsCollector m_serverStatsCollector;
/// <summary>
/// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
/// </summary>
@@ -76,6 +78,11 @@ namespace OpenSim.Framework.Servers
protected void CreatePIDFile(string path)
{
if (File.Exists(path))
m_log.ErrorFormat(
"[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
path);
try
{
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
@@ -113,6 +120,26 @@ namespace OpenSim.Framework.Servers
}
}
/// <summary>
/// Log information about the circumstances in which we're running (OpenSimulator version number, CLR details,
/// etc.).
/// </summary>
public void LogEnvironmentInformation()
{
// FIXME: This should be done down in ServerBase but we need to sort out and refactor the log4net
// XmlConfigurator calls first accross servers.
m_log.InfoFormat("[SERVER BASE]: Starting in {0}", m_startupDirectory);
m_log.InfoFormat("[SERVER BASE]: OpenSimulator version: {0}", m_version);
// clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
// the clr version number doesn't match the project version number under Mono.
//m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine);
m_log.InfoFormat(
"[SERVER BASE]: Operating system version: {0}, .NET platform {1}, {2}-bit",
Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32");
}
public void RegisterCommonAppenders(IConfig startupConfig)
{
ILoggerRepository repository = LogManager.GetRepository();
@@ -234,6 +261,25 @@ namespace OpenSim.Framework.Servers
"force gc",
"Manually invoke runtime garbage collection. For debugging purposes",
HandleForceGc);
m_console.Commands.AddCommand(
"General", false, "quit",
"quit",
"Quit the application", (mod, args) => Shutdown());
m_console.Commands.AddCommand(
"General", false, "shutdown",
"shutdown",
"Quit the application", (mod, args) => Shutdown());
StatsManager.RegisterConsoleCommands(m_console);
}
public void RegisterCommonComponents(IConfigSource configSource)
{
m_serverStatsCollector = new ServerStatsCollector();
m_serverStatsCollector.Initialise(configSource);
m_serverStatsCollector.Start();
}
private void HandleForceGc(string module, string[] args)
@@ -621,7 +667,68 @@ namespace OpenSim.Framework.Servers
sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
sb.Append("Main threadpool (excluding script engine pools)\n");
sb.Append(Util.GetThreadPoolReport());
sb.Append(GetThreadPoolReport());
return sb.ToString();
}
/// <summary>
/// Get a thread pool report.
/// </summary>
/// <returns></returns>
public static string GetThreadPoolReport()
{
string threadPoolUsed = null;
int maxThreads = 0;
int minThreads = 0;
int allocatedThreads = 0;
int inUseThreads = 0;
int waitingCallbacks = 0;
int completionPortThreads = 0;
StringBuilder sb = new StringBuilder();
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
{
STPInfo stpi = Util.GetSmartThreadPoolInfo();
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
if (stpi != null)
{
threadPoolUsed = "SmartThreadPool";
maxThreads = stpi.MaxThreads;
minThreads = stpi.MinThreads;
inUseThreads = stpi.InUseThreads;
allocatedThreads = stpi.ActiveThreads;
waitingCallbacks = stpi.WaitingCallbacks;
}
}
else if (
Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
|| Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
{
threadPoolUsed = "BuiltInThreadPool";
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
inUseThreads = maxThreads - availableThreads;
allocatedThreads = -1;
waitingCallbacks = -1;
}
if (threadPoolUsed != null)
{
sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
sb.AppendFormat("Max threads : {0}\n", maxThreads);
sb.AppendFormat("Min threads : {0}\n", minThreads);
sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
sb.AppendFormat("In use threads : {0}\n", inUseThreads);
sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
}
else
{
sb.AppendFormat("Thread pool not used\n");
}
return sb.ToString();
}
@@ -673,5 +780,16 @@ namespace OpenSim.Framework.Servers
if (m_console != null)
m_console.OutputFormat(format, components);
}
public virtual void Shutdown()
{
m_serverStatsCollector.Close();
ShutdownSpecific();
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
/// </summary>
protected virtual void ShutdownSpecific() {}
}
}

View File

@@ -100,7 +100,7 @@ namespace OpenSim.Framework.Tests
cadu.AVHeight = Size1.Z;
AgentPosition position2 = new AgentPosition();
position2.CopyFrom(cadu);
position2.CopyFrom(cadu, position1.SessionID);
Assert.IsTrue(
position2.AgentID == position1.AgentID

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