Compare commits
359 Commits
master
...
0.7.2-post
Author | SHA1 | Date |
---|---|---|
Justin Clark-Casey (justincc) | a315aee803 | |
Justin Clark-Casey (justincc) | 0c931e3657 | |
Justin Clark-Casey (justincc) | 9f4d772d6a | |
Justin Clark-Casey (justincc) | d6cf029860 | |
Justin Clark-Casey (justincc) | 083587eb32 | |
Justin Clark-Casey (justincc) | 8c8e3ad3ff | |
Justin Clark-Casey (justincc) | 91d5495e26 | |
Justin Clark-Casey (justincc) | 2030377d2c | |
Justin Clark-Casey (justincc) | 31a0f75aff | |
Justin Clark-Casey (justincc) | c1d84ffc6c | |
Justin Clark-Casey (justincc) | 6c72381732 | |
Justin Clark-Casey (justincc) | 8c271802ac | |
Justin Clark-Casey (justincc) | 20a76fd224 | |
Justin Clark-Casey (justincc) | 4473f00e63 | |
Justin Clark-Casey (justincc) | 0b5210dd6a | |
Justin Clark-Casey (justincc) | 34d4bde585 | |
Justin Clark-Casey (justincc) | 4c20c2045c | |
Justin Clark-Casey (justincc) | d9a8f5f16d | |
Justin Clark-Casey (justincc) | 79c2081741 | |
Justin Clark-Casey (justincc) | eb49c356e2 | |
Justin Clark-Casey (justincc) | 717942e81b | |
Justin Clark-Casey (justincc) | 6d47c394b2 | |
Justin Clark-Casey (justincc) | 8305c5d369 | |
Justin Clark-Casey (justincc) | 9e5f5f3d80 | |
Justin Clark-Casey (justincc) | 0a277a64a7 | |
Justin Clark-Casey (justincc) | 7dd0b7ea2f | |
Justin Clark-Casey (justincc) | cd666a3d2c | |
Justin Clark-Casey (justincc) | 681502473e | |
Justin Clark-Casey (justincc) | 0ffe293692 | |
Justin Clark-Casey (justincc) | 356e8516f0 | |
Justin Clark-Casey (justincc) | 71b11f557d | |
Justin Clark-Casey (justincc) | 26be9ed08e | |
Justin Clark-Casey (justincc) | f43d63240d | |
Justin Clark-Casey (justincc) | 5c982c98aa | |
Justin Clark-Casey (justincc) | 63f0ec9aeb | |
Justin Clark-Casey (justincc) | e90cfc17ca | |
Justin Clark-Casey (justincc) | 16d5ce16b6 | |
Justin Clark-Casey (justincc) | ab4c4a362f | |
Justin Clark-Casey (justincc) | b5971db76c | |
Justin Clark-Casey (justincc) | 0c39c9e84d | |
Justin Clark-Casey (justincc) | 0b49773ab3 | |
Justin Clark-Casey (justincc) | 820a39621e | |
Justin Clark-Casey (justincc) | 7a0f4cf8e1 | |
Justin Clark-Casey (justincc) | 2853b78f16 | |
Justin Clark-Casey (justincc) | a3ada745bd | |
Justin Clark-Casey (justincc) | ff0f90bc35 | |
Justin Clark-Casey (justincc) | 7b564b8b35 | |
Justin Clark-Casey (justincc) | 19a818017d | |
Justin Clark-Casey (justincc) | 7bc03a54e5 | |
Justin Clark-Casey (justincc) | aef6a9571c | |
Justin Clark-Casey (justincc) | 0a3b2f904e | |
Justin Clark-Casey (justincc) | 023023a5fc | |
Justin Clark-Casey (justincc) | eebcea22ba | |
Justin Clark-Casey (justincc) | 9474bdb6df | |
Justin Clark-Casey (justincc) | 4d28bac9bb | |
Justin Clark-Casey (justincc) | de746cd987 | |
Justin Clark-Casey (justincc) | 0ef16f9f5b | |
Justin Clark-Casey (justincc) | de0a45d9a3 | |
Justin Clark-Casey (justincc) | a2071e5b13 | |
Justin Clark-Casey (justincc) | 1b3ae566e8 | |
Mic Bowman | 674baa39ed | |
Justin Clark-Casey (justincc) | 1cf57c83e1 | |
Justin Clark-Casey (justincc) | e98e580900 | |
Justin Clark-Casey (justincc) | 292ab783e4 | |
Justin Clark-Casey (justincc) | 0563530bf8 | |
Justin Clark-Casey (justincc) | 2135b89c07 | |
Dan Lake | 2b19a112d9 | |
Justin Clark-Casey (justincc) | cd78f50632 | |
Justin Clark-Casey (justincc) | b300db9e0a | |
Justin Clark-Casey (justincc) | 4370f0e181 | |
Justin Clark-Casey (justincc) | 48ea503c33 | |
nebadon | 546eb88112 | |
Justin Clark-Casey (justincc) | 52710b48ac | |
Justin Clark-Casey (justincc) | cc5e28c1c1 | |
Justin Clark-Casey (justincc) | 67a2d6d855 | |
Justin Clark-Casey (justincc) | 7d426debd3 | |
Justin Clark-Casey (justincc) | 4de98ca4c8 | |
Justin Clark-Casey (justincc) | deb50cd410 | |
Justin Clark-Casey (justincc) | b3cfc5b76e | |
Justin Clark-Casey (justincc) | 27644bcce6 | |
Justin Clark-Casey (justincc) | 903da8acbd | |
Justin Clark-Casey (justincc) | cfdccdd71c | |
Justin Clark-Casey (justincc) | 93e65fb9d5 | |
Justin Clark-Casey (justincc) | af117fe4d4 | |
Justin Clark-Casey (justincc) | 986f6b39ca | |
Justin Clark-Casey (justincc) | 7a8dd539fd | |
Justin Clark-Casey (justincc) | 382cda662f | |
Justin Clark-Casey (justincc) | ede9aea45f | |
Justin Clark-Casey (justincc) | 52b8518fc2 | |
Justin Clark-Casey (justincc) | c3d16955a7 | |
Justin Clark-Casey (justincc) | 61df0da7f9 | |
Justin Clark-Casey (justincc) | f8b0427086 | |
Justin Clark-Casey (justincc) | 5b0d0ef1e9 | |
Justin Clark-Casey (justincc) | 7ca688f5c5 | |
Justin Clark-Casey (justincc) | 9dc1000c27 | |
Justin Clark-Casey (justincc) | 638afca5aa | |
Justin Clark-Casey (justincc) | 7e415e3f85 | |
Justin Clark-Casey (justincc) | 8c4e58995d | |
Justin Clark-Casey (justincc) | d26ded4788 | |
Justin Clark-Casey (justincc) | 5268334c61 | |
Justin Clark-Casey (justincc) | 6ba4cbc259 | |
Melanie | ac445463e9 | |
Justin Clark-Casey (justincc) | 1e83800d32 | |
Justin Clark-Casey (justincc) | 3d94984eee | |
Justin Clark-Casey (justincc) | fd8734b22c | |
Justin Clark-Casey (justincc) | 9b229efdc5 | |
Justin Clark-Casey (justincc) | 81daedcfe3 | |
Michelle Argus | b819771919 | |
Justin Clark-Casey (justincc) | 2f536f92c0 | |
Justin Clark-Casey (justincc) | 0b4774c50c | |
Justin Clark-Casey (justincc) | 139b0d03b6 | |
Justin Clark-Casey (justincc) | c13916d392 | |
Justin Clark-Casey (justincc) | 3ebb56734d | |
Justin Clark-Casey (justincc) | 235147c857 | |
Justin Clark-Casey (justincc) | ddb74bc68d | |
Justin Clark-Casey (justincc) | cd132966df | |
Justin Clark-Casey (justincc) | 5d4fee6eb9 | |
Justin Clark-Casey (justincc) | cc80377325 | |
Justin Clark-Casey (justincc) | 7dce33ce69 | |
Justin Clark-Casey (justincc) | 0dd45f6ca4 | |
Justin Clark-Casey (justincc) | ac3d88804f | |
Justin Clark-Casey (justincc) | f1698552f9 | |
Justin Clark-Casey (justincc) | dfeb424afd | |
Justin Clark-Casey (justincc) | 2380980975 | |
Justin Clark-Casey (justincc) | 52ec854c42 | |
Justin Clark-Casey (justincc) | 4dbfcc26a2 | |
Justin Clark-Casey (justincc) | a262d2492f | |
Justin Clark-Casey (justincc) | e5b7e2fd40 | |
Justin Clark-Casey (justincc) | 7505f23f80 | |
Justin Clark-Casey (justincc) | 7562e63ae6 | |
Justin Clark-Casey (justincc) | 7987a6da95 | |
Justin Clark-Casey (justincc) | fcd60c6b74 | |
Justin Clark-Casey (justincc) | 1e88bf78f1 | |
Justin Clark-Casey (justincc) | a819890137 | |
Justin Clark-Casey (justincc) | 5c85a98f6a | |
Justin Clark-Casey (justincc) | e58daf052d | |
Justin Clark-Casey (justincc) | 0a0e285919 | |
Justin Clark-Casey (justincc) | c693bd51a0 | |
Justin Clark-Casey (justincc) | 808ace0696 | |
Justin Clark-Casey (justincc) | 9730a862db | |
Justin Clark-Casey (justincc) | 754d6036ea | |
Justin Clark-Casey (justincc) | 476d893630 | |
Justin Clark-Casey (justincc) | 0a6374d37a | |
Justin Clark-Casey (justincc) | 0337f2e2a0 | |
Justin Clark-Casey (justincc) | 7be35d5a9a | |
Justin Clark-Casey (justincc) | 8ab2d42143 | |
Justin Clark-Casey (justincc) | dc8ce9ec5d | |
Justin Clark-Casey (justincc) | 7171913400 | |
Justin Clark-Casey (justincc) | 0cf5c0837b | |
Justin Clark-Casey (justincc) | 1edfe05c16 | |
Justin Clark-Casey (justincc) | bba4577d88 | |
Justin Clark-Casey (justincc) | 5c305494ae | |
Justin Clark-Casey (justincc) | 4b2b0d4a05 | |
Justin Clark-Casey (justincc) | 61848ebe0d | |
Justin Clark-Casey (justincc) | f48431345b | |
Justin Clark-Casey (justincc) | 9c4597a00f | |
Justin Clark-Casey (justincc) | b528150d16 | |
Justin Clark-Casey (justincc) | 4a99619bc0 | |
Justin Clark-Casey (justincc) | 5bd27b7b22 | |
Justin Clark-Casey (justincc) | 8ea97cc608 | |
Justin Clark-Casey (justincc) | 1850b778e2 | |
Justin Clark-Casey (justincc) | 5cd33f5e21 | |
Justin Clark-Casey (justincc) | cd3d5379d6 | |
Justin Clark-Casey (justincc) | 58021b5300 | |
Justin Clark-Casey (justincc) | 3b141e5eee | |
Justin Clark-Casey (justincc) | 08bc6622dd | |
Justin Clark-Casey (justincc) | c253539c04 | |
Justin Clark-Casey (justincc) | f3b45be9c0 | |
Justin Clark-Casey (justincc) | 59c19110e4 | |
Justin Clark-Casey (justincc) | 7c03fba3fc | |
Justin Clark-Casey (justincc) | 2593a446ac | |
Justin Clark-Casey (justincc) | 011c1279f5 | |
Justin Clark-Casey (justincc) | 25133cbdf6 | |
Justin Clark-Casey (justincc) | 06ed824711 | |
Justin Clark-Casey (justincc) | 63aa448608 | |
justincc | 4afb773399 | |
Justin Clark-Casey (justincc) | dafe65ad81 | |
Justin Clark-Casey (justincc) | b107a8ec2a | |
Justin Clark-Casey (justincc) | e31d7fe424 | |
justincc | cc9888f28b | |
Justin Clark-Casey (justincc) | fef3baf107 | |
Justin Clark-Casey (justincc) | 123322569d | |
Justin Clark-Casey (justincc) | 8c0d8e72aa | |
Justin Clark-Casey (justincc) | 1e69845869 | |
Justin Clark-Casey (justincc) | 1bc0d0fac6 | |
Justin Clark-Casey (justincc) | f7b5d17aa2 | |
Justin Clark-Casey (justincc) | 85170f5d5d | |
Justin Clark-Casey (justincc) | 66863fdd34 | |
Justin Clark-Casey (justincc) | 6b0553ed7c | |
Justin Clark-Casey (justincc) | 57cffcd1ec | |
Justin Clark-Casey (justincc) | 78739067d1 | |
Justin Clark-Casey (justincc) | 310c2403b0 | |
Justin Clark-Casey (justincc) | a88381ba82 | |
Justin Clark-Casey (justincc) | 1fa0c2f9b0 | |
Justin Clark-Casey (justincc) | 1069390b3e | |
Justin Clark-Casey (justincc) | 3068cc3618 | |
Justin Clark-Casey (justincc) | b5a69833f8 | |
Justin Clark-Casey (justincc) | 8b5bacc78b | |
Justin Clark-Casey (justincc) | 8f7f03e7fd | |
Justin Clark-Casey (justincc) | 80bea38c07 | |
Justin Clark-Casey (justincc) | 9742491a63 | |
Justin Clark-Casey (justincc) | acad65a832 | |
Justin Clark-Casey (justincc) | b527901556 | |
Justin Clark-Casey (justincc) | 3c9654d5d6 | |
Justin Clark-Casey (justincc) | 4be42b3f75 | |
Justin Clark-Casey (justincc) | 6a994f8c9c | |
Justin Clark-Casey (justincc) | f9e6e32ce2 | |
Melanie | 6bbf4fdc0f | |
Dan Lake | 10aee2f0ec | |
Dan Lake | 0ed6149463 | |
Justin Clark-Casey (justincc) | a64be59c3b | |
Justin Clark-Casey (justincc) | b720454950 | |
Justin Clark-Casey (justincc) | dd3dc5cd91 | |
Justin Clark-Casey (justincc) | 9cd94ac6ec | |
Justin Clark-Casey (justincc) | 2cc49d7d9a | |
Justin Clark-Casey (justincc) | 69e11af475 | |
Dan Lake | aa6915f1ba | |
Dan Lake | b36ff0fd24 | |
Justin Clark-Casey (justincc) | a16c9206b4 | |
Justin Clark-Casey (justincc) | b5b2541d1a | |
Justin Clark-Casey (justincc) | 1baadac59a | |
Justin Clark-Casey (justincc) | 88ef35cb23 | |
Justin Clark-Casey (justincc) | 05dff4987b | |
Justin Clark-Casey (justincc) | e1e0f20c7f | |
Justin Clark-Casey (justincc) | 70d559d1af | |
Justin Clark-Casey (justincc) | 6c92b48143 | |
Justin Clark-Casey (justincc) | 127626edd8 | |
Justin Clark-Casey (justincc) | aba26c098d | |
Justin Clark-Casey (justincc) | 9f19405490 | |
Justin Clark-Casey (justincc) | 871f1d0ae7 | |
Justin Clark-Casey (justincc) | 057b78bfbe | |
Justin Clark-Casey (justincc) | d4fc07aae1 | |
Justin Clark-Casey (justincc) | 750e8ec3da | |
Justin Clark-Casey (justincc) | 15142093ad | |
Justin Clark-Casey (justincc) | f050f0fc0b | |
Justin Clark-Casey (justincc) | a3c79b399e | |
Justin Clark-Casey (justincc) | 424735efee | |
Justin Clark-Casey (justincc) | d5dfbc3844 | |
Justin Clark-Casey (justincc) | c3127d1323 | |
Justin Clark-Casey (justincc) | 03c98c3b8f | |
Justin Clark-Casey (justincc) | 24e02afeac | |
Justin Clark-Casey (justincc) | 8d5606e09b | |
Justin Clark-Casey (justincc) | bd3d119a03 | |
Justin Clark-Casey (justincc) | cf2405385d | |
Justin Clark-Casey (justincc) | a6eba09dac | |
Justin Clark-Casey (justincc) | b2ca7c0927 | |
Justin Clark-Casey (justincc) | dd6c236253 | |
Justin Clark-Casey (justincc) | b2ff680cca | |
Justin Clark-Casey (justincc) | 23a9a7daa7 | |
Justin Clark-Casey (justincc) | 19fde57fca | |
Justin Clark-Casey (justincc) | a556930456 | |
Justin Clark-Casey (justincc) | 1a008b237b | |
Justin Clark-Casey (justincc) | d6456b9ea8 | |
Justin Clark-Casey (justincc) | 5980d57b7a | |
Justin Clark-Casey (justincc) | 7c409eff53 | |
Justin Clark-Casey (justincc) | 614ea5a48a | |
Justin Clark-Casey (justincc) | 8905f34e18 | |
Justin Clark-Casey (justincc) | 380f2a1719 | |
Justin Clark-Casey (justincc) | 1c66e08964 | |
Justin Clark-Casey (justincc) | af564291f2 | |
Justin Clark-Casey (justincc) | 250eed5141 | |
Justin Clark-Casey (justincc) | a2c9b3d83d | |
Justin Clark-Casey (justincc) | 3a047b2bdb | |
Justin Clark-Casey (justincc) | f8deca7f2d | |
Justin Clark-Casey (justincc) | 63a6bc93e4 | |
Justin Clark-Casey (justincc) | 50c340ef35 | |
Justin Clark-Casey (justincc) | 41e7e613a2 | |
Justin Clark-Casey (justincc) | 4d1ab38068 | |
Justin Clark-Casey (justincc) | 47c412ca1e | |
Justin Clark-Casey (justincc) | acb0a5b6c1 | |
Justin Clark-Casey (justincc) | 1b8716a99a | |
Justin Clark-Casey (justincc) | 9edbb4f77a | |
Justin Clark-Casey (justincc) | 753f11273f | |
Justin Clark-Casey (justincc) | 435aefe1bf | |
Justin Clark-Casey (justincc) | e5286b7b7c | |
Justin Clark-Casey (justincc) | aa4637db47 | |
Justin Clark-Casey (justincc) | 73c201449f | |
Justin Clark-Casey (justincc) | 36be226dc8 | |
Justin Clark-Casey (justincc) | ea5d1d0ff0 | |
Justin Clark-Casey (justincc) | 299cc2d12d | |
Justin Clark-Casey (justincc) | 4ecd3fbff1 | |
Justin Clark-Casey (justincc) | 1b32d5c6a4 | |
Justin Clark-Casey (justincc) | c404760731 | |
Justin Clark-Casey (justincc) | 7d4e224620 | |
Justin Clark-Casey (justincc) | 986ded5a72 | |
Justin Clark-Casey (justincc) | 8340bd7e20 | |
Justin Clark-Casey (justincc) | 9d59fc0587 | |
Justin Clark-Casey (justincc) | 22e1298e97 | |
Justin Clark-Casey (justincc) | 1a29ddf328 | |
Justin Clark-Casey (justincc) | 8a2c3a0267 | |
Justin Clark-Casey (justincc) | ea65d4f5ce | |
Justin Clark-Casey (justincc) | eb65f5072d | |
Justin Clark-Casey (justincc) | aad13a4c76 | |
Justin Clark-Casey (justincc) | 233127c696 | |
Justin Clark-Casey (justincc) | b7fcd6871e | |
Justin Clark-Casey (justincc) | c06cd3b2b9 | |
Justin Clark-Casey (justincc) | 31ac7571f4 | |
Justin Clark-Casey (justincc) | 2a7a5c4c90 | |
Justin Clark-Casey (justincc) | d8ad649957 | |
Justin Clark-Casey (justincc) | a1f232af2b | |
Justin Clark-Casey (justincc) | 14bddb6af9 | |
Justin Clark-Casey (justincc) | f93635fe85 | |
Justin Clark-Casey (justincc) | 3a635507cc | |
Justin Clark-Casey (justincc) | 0506ccb51a | |
Justin Clark-Casey (justincc) | 4bce90d0ab | |
Justin Clark-Casey (justincc) | 4d93ab06c9 | |
Justin Clark-Casey (justincc) | e2c807a0d0 | |
Justin Clark-Casey (justincc) | 23a9a98d5d | |
Justin Clark-Casey (justincc) | 32ba06a55c | |
Justin Clark-Casey (justincc) | 64c42a729a | |
Justin Clark-Casey (justincc) | b342fb9c0a | |
Justin Clark-Casey (justincc) | 3f70f54fa6 | |
Justin Clark-Casey (justincc) | c4ce7b8162 | |
Justin Clark-Casey (justincc) | 4c9226be7b | |
Diva Canto | 58f2c9e224 | |
Diva Canto | 8ba0cc470a | |
Justin Clark-Casey (justincc) | 2a654974c9 | |
Diva Canto | b72753dc81 | |
Justin Clark-Casey (justincc) | 2ecfa29eb6 | |
Justin Clark-Casey (justincc) | 3678b8f1f7 | |
Justin Clark-Casey (justincc) | 29a62abc6d | |
Justin Clark-Casey (justincc) | 31ef2f9a2e | |
Justin Clark-Casey (justincc) | 21e3f8e53a | |
Justin Clark-Casey (justincc) | 579aa9c6a0 | |
BlueWall | 8b374daae9 | |
Justin Clark-Casey (justincc) | 31d1b3310d | |
Pixel Tomsen | d1711519a0 | |
BlueWall | 71fa970990 | |
Justin Clark-Casey (justincc) | 6fa4f88d39 | |
Justin Clark-Casey (justincc) | 9ff3d9221b | |
Justin Clark-Casey (justincc) | 3920e56dd4 | |
Justin Clark-Casey (justincc) | 6700f1edd9 | |
Justin Clark-Casey (justincc) | e6d1182dec | |
Justin Clark-Casey (justincc) | a3316f1eac | |
Pixel Tomsen | 5f281716a9 | |
Pixel Tomsen | f90c3d0633 | |
Justin Clark-Casey (justincc) | 633d4f3e6e | |
Justin Clark-Casey (justincc) | 43bbdbe760 | |
Justin Clark-Casey (justincc) | 494e5867a3 | |
Justin Clark-Casey (justincc) | 270f0d5ae3 | |
Dan Lake | d079ee9ef1 | |
Justin Clark-Casey (justincc) | cd46bf6fad | |
Justin Clark-Casey (justincc) | bb419044ef | |
Justin Clark-Casey (justincc) | 549fdc8b11 | |
Justin Clark-Casey (justincc) | 550d1fea96 | |
Justin Clark-Casey (justincc) | 94f49e859b | |
Snoopy Pfeffer | c2586b0ea9 | |
Justin Clark-Casey (justincc) | 2905288545 | |
Justin Clark-Casey (justincc) | 353170589b | |
Justin Clark-Casey (justincc) | ee78c4d2a8 | |
Justin Clark-Casey (justincc) | 084df4b7ef | |
Justin Clark-Casey (justincc) | 53ffc7ff8c | |
Justin Clark-Casey (justincc) | d8d048cfa1 | |
Justin Clark-Casey (justincc) | a4e1d29e3c | |
Justin Clark-Casey (justincc) | 8c4dd6b330 | |
Justin Clark-Casey (justincc) | f1612997a6 | |
Justin Clark-Casey (justincc) | c574c80011 | |
Justin Clark-Casey (justincc) | 9f76bc4fff | |
Justin Clark-Casey (justincc) | 79f3de6ba8 |
|
@ -8,6 +8,7 @@
|
|||
<target name="distbin">
|
||||
<copy file="bin/OpenSim.ini.example" tofile="bin/OpenSim.ini"/>
|
||||
<copy file="bin/config-include/StandaloneCommon.ini.example" tofile="bin/config-include/StandaloneCommon.ini"/>
|
||||
<copy file="bin/config-include/FlotsamCache.ini.example" tofile="bin/config-include/FlotsamCache.ini"/>
|
||||
<delete dir="${distbindir}"/>
|
||||
<copy todir="${distbindir}">
|
||||
<fileset>
|
||||
|
@ -111,12 +112,15 @@
|
|||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.serialization.tests)==0}" />
|
||||
|
||||
<!--
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindencaps.tests">
|
||||
<arg value="./bin/OpenSim.Region.ClientStack.LindenCaps.Tests.dll" />
|
||||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindencaps.tests)==0}" />
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests">
|
||||
<arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" />
|
||||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
|
||||
-->
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.scriptengine.tests">
|
||||
<arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" />
|
||||
|
@ -297,12 +301,15 @@
|
|||
<arg value="-xml=test-results/OpenSim.Framework.Servers.Tests.dll-Results.xml" />
|
||||
</exec>
|
||||
|
||||
<!--
|
||||
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindencaps.tests">
|
||||
<arg value="./bin/OpenSim.Region.ClientStack.LindenCaps.Tests.dll" />
|
||||
<arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenCaps.Tests.dll-Results.xml" />
|
||||
</exec>
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests">
|
||||
<arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" />
|
||||
<arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenUDP.Tests.dll-Results.xml" />
|
||||
</exec>
|
||||
-->
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.scriptengine.tests">
|
||||
<arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" />
|
||||
|
@ -332,7 +339,7 @@
|
|||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />
|
||||
<!-- <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" /> -->
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -51,11 +51,10 @@ namespace OpenSim.Framework.Capabilities
|
|||
/// supplied BaseHttpServer.
|
||||
/// </summary>
|
||||
/// <param name="httpListener">base HTTP server</param>
|
||||
/// <param name="httpListenerHostname">host name of the HTTP
|
||||
/// server</param>
|
||||
/// <param name="httpListenerHostname">host name of the HTTP server</param>
|
||||
/// <param name="httpListenerPort">HTTP port</param>
|
||||
public CapsHandlers(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort)
|
||||
: this (httpListener,httpListenerHostname,httpListenerPort, false)
|
||||
: this(httpListener,httpListenerHostname,httpListenerPort, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -88,44 +87,52 @@ namespace OpenSim.Framework.Capabilities
|
|||
/// handler to be removed</param>
|
||||
public void Remove(string capsName)
|
||||
{
|
||||
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
|
||||
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
|
||||
m_capsHandlers.Remove(capsName);
|
||||
lock (m_capsHandlers)
|
||||
{
|
||||
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
|
||||
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
|
||||
m_capsHandlers.Remove(capsName);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsCap(string cap)
|
||||
{
|
||||
return m_capsHandlers.ContainsKey(cap);
|
||||
lock (m_capsHandlers)
|
||||
return m_capsHandlers.ContainsKey(cap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The indexer allows us to treat the CapsHandlers object
|
||||
/// in an intuitive dictionary like way.
|
||||
/// </summary>
|
||||
/// <Remarks>
|
||||
/// <remarks>
|
||||
/// The indexer will throw an exception when you try to
|
||||
/// retrieve a cap handler for a cap that is not contained in
|
||||
/// CapsHandlers.
|
||||
/// </Remarks>
|
||||
/// </remarks>
|
||||
public IRequestHandler this[string idx]
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_capsHandlers[idx];
|
||||
lock (m_capsHandlers)
|
||||
return m_capsHandlers[idx];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (m_capsHandlers.ContainsKey(idx))
|
||||
lock (m_capsHandlers)
|
||||
{
|
||||
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path);
|
||||
m_capsHandlers.Remove(idx);
|
||||
if (m_capsHandlers.ContainsKey(idx))
|
||||
{
|
||||
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path);
|
||||
m_capsHandlers.Remove(idx);
|
||||
}
|
||||
|
||||
if (null == value) return;
|
||||
|
||||
m_capsHandlers[idx] = value;
|
||||
m_httpListener.AddStreamHandler(value);
|
||||
}
|
||||
|
||||
if (null == value) return;
|
||||
|
||||
m_capsHandlers[idx] = value;
|
||||
m_httpListener.AddStreamHandler(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,9 +144,12 @@ namespace OpenSim.Framework.Capabilities
|
|||
{
|
||||
get
|
||||
{
|
||||
string[] __keys = new string[m_capsHandlers.Keys.Count];
|
||||
m_capsHandlers.Keys.CopyTo(__keys, 0);
|
||||
return __keys;
|
||||
lock (m_capsHandlers)
|
||||
{
|
||||
string[] __keys = new string[m_capsHandlers.Keys.Count];
|
||||
m_capsHandlers.Keys.CopyTo(__keys, 0);
|
||||
return __keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,25 +157,29 @@ namespace OpenSim.Framework.Capabilities
|
|||
/// Return an LLSD-serializable Hashtable describing the
|
||||
/// capabilities and their handler details.
|
||||
/// </summary>
|
||||
public Hashtable CapsDetails
|
||||
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
||||
public Hashtable GetCapsDetails(bool excludeSeed)
|
||||
{
|
||||
get
|
||||
{
|
||||
Hashtable caps = new Hashtable();
|
||||
string protocol = "http://";
|
||||
|
||||
if (m_useSSL)
|
||||
protocol = "https://";
|
||||
Hashtable caps = new Hashtable();
|
||||
string protocol = "http://";
|
||||
|
||||
if (m_useSSL)
|
||||
protocol = "https://";
|
||||
|
||||
string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString();
|
||||
string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString();
|
||||
|
||||
lock (m_capsHandlers)
|
||||
{
|
||||
foreach (string capsName in m_capsHandlers.Keys)
|
||||
{
|
||||
// skip SEED cap
|
||||
if ("SEED" == capsName) continue;
|
||||
if (excludeSeed && "SEED" == capsName)
|
||||
continue;
|
||||
|
||||
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
|
||||
}
|
||||
return caps;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -111,6 +111,10 @@ namespace OpenSim.Capabilities.Handlers
|
|||
m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
|
||||
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
|
||||
|
||||
httpResponse.Send();
|
||||
return null;
|
||||
}
|
||||
|
@ -210,7 +214,7 @@ namespace OpenSim.Capabilities.Handlers
|
|||
private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format)
|
||||
{
|
||||
string range = request.Headers.GetOne("Range");
|
||||
//m_log.DebugFormat("[GETTEXTURE]: Range {0}", range);
|
||||
|
||||
if (!String.IsNullOrEmpty(range)) // JP2's only
|
||||
{
|
||||
// Range request
|
||||
|
@ -222,23 +226,27 @@ namespace OpenSim.Capabilities.Handlers
|
|||
if (start >= texture.Data.Length)
|
||||
{
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = Utils.Clamp(end, 0, texture.Data.Length - 1);
|
||||
start = Utils.Clamp(start, 0, end);
|
||||
int len = end - start + 1;
|
||||
|
||||
end = Utils.Clamp(end, 0, texture.Data.Length - 1);
|
||||
start = Utils.Clamp(start, 0, end);
|
||||
int len = end - start + 1;
|
||||
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
|
||||
|
||||
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
|
||||
|
||||
if (len < texture.Data.Length)
|
||||
// Always return PartialContent, even if the range covered the entire data length
|
||||
// We were accidentally sending back 404 before in this situation
|
||||
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
|
||||
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
|
||||
|
||||
response.ContentLength = len;
|
||||
response.ContentType = texture.Metadata.ContentType;
|
||||
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
|
||||
|
||||
response.Body.Write(texture.Data, start, len);
|
||||
response.ContentLength = len;
|
||||
response.ContentType = texture.Metadata.ContentType;
|
||||
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
|
||||
|
||||
response.Body.Write(texture.Data, start, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -257,6 +265,10 @@ namespace OpenSim.Capabilities.Handlers
|
|||
response.ContentType = "image/" + format;
|
||||
response.Body.Write(texture.Data, 0, texture.Data.Length);
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
|
||||
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
|
||||
}
|
||||
|
||||
private bool TryParseRange(string header, out int start, out int end)
|
||||
|
@ -275,7 +287,6 @@ namespace OpenSim.Capabilities.Handlers
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
private byte[] ConvertTextureData(AssetBase texture, string format)
|
||||
{
|
||||
m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
|
||||
|
@ -350,7 +361,5 @@ namespace OpenSim.Capabilities.Handlers
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||
|
||||
namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class UploadBakedTextureHandler
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Caps m_HostCapsObj;
|
||||
private IAssetService m_assetService;
|
||||
private bool m_persistBakedTextures;
|
||||
|
||||
public UploadBakedTextureHandler(Caps caps, IAssetService assetService, bool persistBakedTextures)
|
||||
{
|
||||
m_HostCapsObj = caps;
|
||||
m_assetService = assetService;
|
||||
m_persistBakedTextures = persistBakedTextures;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a request from the client for a Uri to upload a baked texture.
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="param"></param>
|
||||
/// <param name="httpRequest"></param>
|
||||
/// <param name="httpResponse"></param>
|
||||
/// <returns>The upload response if the request is successful, null otherwise.</returns>
|
||||
public string UploadBakedTexture(
|
||||
string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
|
||||
{
|
||||
try
|
||||
{
|
||||
string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
|
||||
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
|
||||
|
||||
BakedTextureUploader uploader =
|
||||
new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener);
|
||||
uploader.OnUpLoad += BakedTextureUploaded;
|
||||
|
||||
m_HostCapsObj.HttpListener.AddStreamHandler(
|
||||
new BinaryStreamHandler("POST", capsBase + uploaderPath,
|
||||
uploader.uploaderCaps));
|
||||
|
||||
string protocol = "http://";
|
||||
|
||||
if (m_HostCapsObj.SSLCaps)
|
||||
protocol = "https://";
|
||||
|
||||
string uploaderURL = protocol + m_HostCapsObj.HostName + ":" +
|
||||
m_HostCapsObj.Port.ToString() + capsBase + uploaderPath;
|
||||
|
||||
LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
|
||||
uploadResponse.uploader = uploaderURL;
|
||||
uploadResponse.state = "upload";
|
||||
|
||||
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[UPLOAD BAKED TEXTURE HANDLER]: " + e.ToString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a baked texture has been successfully uploaded by a client.
|
||||
/// </summary>
|
||||
/// <param name="assetID"></param>
|
||||
/// <param name="data"></param>
|
||||
private void BakedTextureUploaded(UUID assetID, byte[] data)
|
||||
{
|
||||
// m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString());
|
||||
|
||||
AssetBase asset;
|
||||
asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
|
||||
asset.Data = data;
|
||||
asset.Temporary = true;
|
||||
asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
|
||||
m_assetService.Store(asset);
|
||||
}
|
||||
}
|
||||
|
||||
class BakedTextureUploader
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public event Action<UUID, byte[]> OnUpLoad;
|
||||
|
||||
private string uploaderPath = String.Empty;
|
||||
private UUID newAssetID;
|
||||
private IHttpServer httpListener;
|
||||
|
||||
public BakedTextureUploader(string path, IHttpServer httpServer)
|
||||
{
|
||||
newAssetID = UUID.Random();
|
||||
uploaderPath = path;
|
||||
httpListener = httpServer;
|
||||
// m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle raw uploaded baked texture data.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="param"></param>
|
||||
/// <returns></returns>
|
||||
public string uploaderCaps(byte[] data, string path, string param)
|
||||
{
|
||||
Action<UUID, byte[]> handlerUpLoad = OnUpLoad;
|
||||
|
||||
// Don't do this asynchronously, otherwise it's possible for the client to send set appearance information
|
||||
// on another thread which might send out avatar updates before the asset has been put into the asset
|
||||
// service.
|
||||
if (handlerUpLoad != null)
|
||||
handlerUpLoad(newAssetID, data);
|
||||
|
||||
string res = String.Empty;
|
||||
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
|
||||
uploadComplete.new_asset = newAssetID.ToString();
|
||||
uploadComplete.new_inventory_item = UUID.Zero;
|
||||
uploadComplete.state = "complete";
|
||||
|
||||
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
|
||||
|
||||
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||
|
||||
// m_log.DebugFormat("[BAKED TEXTURE UPLOADER]: baked texture upload completed for {0}", newAssetID);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -208,7 +208,86 @@ namespace OpenSim.Capabilities.Handlers
|
|||
containingFolder.Owner = agentID;
|
||||
containingFolder = m_InventoryService.GetFolder(containingFolder);
|
||||
if (containingFolder != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
|
||||
// containingFolder.Name, containingFolder.ID, agentID);
|
||||
|
||||
version = containingFolder.Version;
|
||||
//
|
||||
// if (fetchItems)
|
||||
// {
|
||||
// List<InventoryItemBase> linkedItemsToAdd = new List<InventoryItemBase>();
|
||||
//
|
||||
// foreach (InventoryItemBase item in contents.Items)
|
||||
// {
|
||||
// if (item.AssetType == (int)AssetType.Link)
|
||||
// {
|
||||
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||
//
|
||||
// // Take care of genuinely broken links where the target doesn't exist
|
||||
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// // rather than having to keep track of every folder requested in the recursion.
|
||||
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||
// linkedItemsToAdd.Insert(0, linkedItem);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
|
||||
// linkedItem.Name, folderID, agentID);
|
||||
//
|
||||
// contents.Items.Add(linkedItem);
|
||||
// }
|
||||
//
|
||||
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
|
||||
// // will be broken in the viewer.
|
||||
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
|
||||
// foreach (InventoryItemBase item in contents.Items)
|
||||
// {
|
||||
// if (item.AssetType == (int)AssetType.Link)
|
||||
// {
|
||||
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||
//
|
||||
// // Take care of genuinely broken links where the target doesn't exist
|
||||
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// // rather than having to keep track of every folder requested in the recursion.
|
||||
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||
// {
|
||||
// // We don't need to send the folder if source and destination of the link are in the same
|
||||
// // folder.
|
||||
// if (linkedItem.Folder != containingFolder.ID)
|
||||
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
|
||||
// linkedItemFolderId, folderID, agentID);
|
||||
//
|
||||
// int dummyVersion;
|
||||
// InventoryCollection linkedCollection
|
||||
// = Fetch(
|
||||
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
|
||||
//
|
||||
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
|
||||
// linkedFolder.Owner = agentID;
|
||||
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
|
||||
//
|
||||
//// contents.Folders.AddRange(linkedCollection.Folders);
|
||||
//
|
||||
// contents.Folders.Add(linkedFolder);
|
||||
// contents.Items.AddRange(linkedCollection.Items);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@ using System.IO;
|
|||
using System.Xml;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenMetaverse;
|
||||
|
||||
|
|
|
@ -37,10 +37,30 @@ namespace OpenSim.Data
|
|||
public UUID RegionID;
|
||||
public UUID ScopeID;
|
||||
public string RegionName;
|
||||
|
||||
/// <summary>
|
||||
/// The position in meters of this region.
|
||||
/// </summary>
|
||||
public int posX;
|
||||
|
||||
/// <summary>
|
||||
/// The position in meters of this region.
|
||||
/// </summary>
|
||||
public int posY;
|
||||
|
||||
public int sizeX;
|
||||
public int sizeY;
|
||||
|
||||
/// <summary>
|
||||
/// Return the x-coordinate of this region.
|
||||
/// </summary>
|
||||
public int coordX { get { return posX / (int)Constants.RegionSize; } }
|
||||
|
||||
/// <summary>
|
||||
/// Return the y-coordinate of this region.
|
||||
/// </summary>
|
||||
public int coordY { get { return posY / (int)Constants.RegionSize; } }
|
||||
|
||||
public Dictionary<string, object> Data;
|
||||
}
|
||||
|
||||
|
|
|
@ -794,7 +794,8 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid", dbcon))
|
||||
// System folders can never be deleted. Period.
|
||||
using (MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid and type=-1", dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?uuid", folderID.ToString());
|
||||
|
||||
|
|
|
@ -56,13 +56,21 @@ namespace OpenSim.Data.Null
|
|||
/// <returns></returns>
|
||||
public FriendsData[] GetFriends(string userID)
|
||||
{
|
||||
List<FriendsData> lst = m_Data.FindAll(delegate (FriendsData fdata)
|
||||
List<FriendsData> lst = m_Data.FindAll(fdata =>
|
||||
{
|
||||
return fdata.PrincipalID == userID.ToString();
|
||||
});
|
||||
|
||||
if (lst != null)
|
||||
{
|
||||
lst.ForEach(f =>
|
||||
{
|
||||
FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID);
|
||||
if (f2 != null) { f.Data["TheirFlags"] = f2.Data["Flags"]; }
|
||||
});
|
||||
|
||||
return lst.ToArray();
|
||||
}
|
||||
|
||||
return new FriendsData[0];
|
||||
}
|
||||
|
|
|
@ -311,7 +311,7 @@ namespace OpenSim.Framework
|
|||
if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map))
|
||||
{
|
||||
Appearance.Unpack((OSDMap)args["packed_appearance"]);
|
||||
m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance");
|
||||
// m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -335,7 +335,7 @@ namespace OpenSim.Framework
|
|||
|
||||
public virtual OSDMap Pack()
|
||||
{
|
||||
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
|
||||
// m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
|
||||
|
||||
OSDMap args = new OSDMap();
|
||||
args["message_type"] = OSD.FromString("AgentData");
|
||||
|
|
|
@ -31,19 +31,10 @@ namespace OpenSim.Framework
|
|||
{
|
||||
public string PhysicsEngine { get; set; }
|
||||
public string MeshEngineName { get; set; }
|
||||
public bool See_into_region_from_neighbor { get; set; }
|
||||
public string StorageDll { get; set; }
|
||||
public string ClientstackDll { get; set; }
|
||||
public bool PhysicalPrim { get; set; }
|
||||
public string LibrariesXMLFile { get; set; }
|
||||
|
||||
public const uint DefaultAssetServerHttpPort = 8003;
|
||||
public const uint DefaultRegionHttpPort = 9000;
|
||||
public const uint DefaultUserServerHttpPort = 8002;
|
||||
public const bool DefaultUserServerHttpSSL = false;
|
||||
public const uint DefaultMessageServerHttpPort = 8006;
|
||||
public const bool DefaultMessageServerHttpSSL = false;
|
||||
public const uint DefaultGridServerHttpPort = 8003;
|
||||
public const uint DefaultInventoryServerHttpPort = 8003;
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ using System.Reflection;
|
|||
using System.Xml;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework.Console;
|
||||
//using OpenSim.Framework.Console;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
|
|
|
@ -33,12 +33,11 @@ using System.Reflection;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Framework.Console
|
||||
{
|
||||
public delegate void CommandDelegate(string module, string[] cmd);
|
||||
|
||||
public class Commands
|
||||
public class Commands : ICommands
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates a command that can be invoked from the console
|
||||
|
@ -564,14 +563,16 @@ namespace OpenSim.Framework.Console
|
|||
/// <summary>
|
||||
/// A console that processes commands internally
|
||||
/// </summary>
|
||||
public class CommandConsole : ConsoleBase
|
||||
public class CommandConsole : ConsoleBase, ICommandConsole
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public Commands Commands = new Commands();
|
||||
public ICommands Commands { get; private set; }
|
||||
|
||||
public CommandConsole(string defaultPrompt) : base(defaultPrompt)
|
||||
{
|
||||
Commands = new Commands();
|
||||
|
||||
Commands.AddCommand("console", false, "help", "help [<command>]",
|
||||
"Get general command list or more detailed help on a specific command", Help);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace OpenSim.Framework.Console
|
|||
|
||||
protected string prompt = "# ";
|
||||
|
||||
public object ConsoleScene = null;
|
||||
public object ConsoleScene { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default prompt text.
|
||||
|
|
|
@ -703,6 +703,12 @@ namespace OpenSim.Framework
|
|||
|
||||
UUID AgentId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it
|
||||
/// is connected).
|
||||
/// </summary>
|
||||
ISceneAgent SceneAgent { get; }
|
||||
|
||||
UUID SessionId { get; }
|
||||
|
||||
UUID SecureSessionId { get; }
|
||||
|
@ -1007,11 +1013,11 @@ namespace OpenSim.Framework
|
|||
event MuteListEntryRemove OnRemoveMuteListEntry;
|
||||
event GodlikeMessage onGodlikeMessage;
|
||||
event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the debug level at which packet output should be printed to console.
|
||||
/// </summary>
|
||||
void SetDebugPacketLevel(int newDebug);
|
||||
int DebugPacketLevel { get; set; }
|
||||
|
||||
void InPacket(object NewPack);
|
||||
void ProcessInPacket(Packet NewPack);
|
||||
|
@ -1096,7 +1102,14 @@ namespace OpenSim.Framework
|
|||
void SetChildAgentThrottle(byte[] throttle);
|
||||
|
||||
void SendAvatarDataImmediate(ISceneEntity avatar);
|
||||
void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
|
||||
|
||||
/// <summary>
|
||||
/// Send a positional, velocity, etc. update to the viewer for a given entity.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="updateFlags"></param>
|
||||
void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
|
||||
|
||||
void ReprioritizeUpdates();
|
||||
void FlushPrimUpdates();
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public delegate void CommandDelegate(string module, string[] cmd);
|
||||
|
||||
public interface ICommands
|
||||
{
|
||||
void FromXml(XmlElement root, CommandDelegate fn);
|
||||
|
||||
/// <summary>
|
||||
/// Get help for the given help string
|
||||
/// </summary>
|
||||
/// <param name="helpParts">Parsed parts of the help string. If empty then general help is returned.</param>
|
||||
/// <returns></returns>
|
||||
List<string> GetHelp(string[] cmd);
|
||||
|
||||
/// <summary>
|
||||
/// Add a command to those which can be invoked from the console.
|
||||
/// </summary>
|
||||
/// <param name="module"></param>
|
||||
/// <param name="command"></param>
|
||||
/// <param name="help"></param>
|
||||
/// <param name="longhelp"></param>
|
||||
/// <param name="fn"></param>
|
||||
void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn);
|
||||
|
||||
/// <summary>
|
||||
/// Add a command to those which can be invoked from the console.
|
||||
/// </summary>
|
||||
/// <param name="module"></param>
|
||||
/// <param name="command"></param>
|
||||
/// <param name="help"></param>
|
||||
/// <param name="longhelp"></param>
|
||||
/// <param name="descriptivehelp"></param>
|
||||
/// <param name="fn"></param>
|
||||
void AddCommand(string module, bool shared, string command,
|
||||
string help, string longhelp, string descriptivehelp,
|
||||
CommandDelegate fn);
|
||||
|
||||
string[] FindNextOption(string[] cmd, bool term);
|
||||
|
||||
string[] Resolve(string[] cmd);
|
||||
|
||||
XmlElement GetXml(XmlDocument doc);
|
||||
}
|
||||
|
||||
public interface ICommandConsole : IConsole
|
||||
{
|
||||
ICommands Commands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Display a command prompt on the console and wait for user input
|
||||
/// </summary>
|
||||
void Prompt();
|
||||
|
||||
void RunCommand(string cmd);
|
||||
|
||||
string ReadLine(string p, bool isCommand, bool e);
|
||||
}
|
||||
}
|
|
@ -25,27 +25,29 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenSim.Region.Examples.SimpleModule
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class FileSystemObject : SceneObjectGroup
|
||||
public interface IConsole
|
||||
{
|
||||
public FileSystemObject(FileInfo fileInfo, Vector3 pos)
|
||||
: base(UUID.Zero, pos, PrimitiveBaseShape.Default)
|
||||
{
|
||||
Text = fileInfo.Name;
|
||||
}
|
||||
object ConsoleScene { get; }
|
||||
|
||||
protected override bool InSceneBackup
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void Output(string text, string level);
|
||||
void Output(string text);
|
||||
void OutputFormat(string format, params object[] components);
|
||||
|
||||
string CmdPrompt(string p);
|
||||
string CmdPrompt(string p, string def);
|
||||
string CmdPrompt(string p, List<char> excludedCharacters);
|
||||
string CmdPrompt(string p, string def, List<char> excludedCharacters);
|
||||
|
||||
// Displays a command prompt and returns a default value, user may only enter 1 of 2 options
|
||||
string CmdPrompt(string prompt, string defaultresponse, List<string> options);
|
||||
|
||||
// Displays a prompt and waits for the user to enter a string, then returns that string
|
||||
// (Done with no echo and suitable for passwords)
|
||||
string PasswdPrompt(string p);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,22 +26,19 @@
|
|||
*/
|
||||
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework.Console;
|
||||
//using OpenSim.Framework.Console;
|
||||
using Nini.Config;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public delegate void restart(RegionInfo thisRegion);
|
||||
|
||||
//public delegate void regionup (RegionInfo thisRegion);
|
||||
|
||||
public enum RegionStatus : int
|
||||
{
|
||||
Down = 0,
|
||||
Up = 1,
|
||||
Crashed = 2,
|
||||
Starting = 3,
|
||||
SlaveScene = 4
|
||||
};
|
||||
|
||||
/// <value>
|
||||
|
@ -71,12 +68,14 @@ namespace OpenSim.Framework
|
|||
event restart OnRestart;
|
||||
|
||||
/// <summary>
|
||||
/// Register the new client with the scene. The client starts off as a child agent - the later agent crossing
|
||||
/// will promote it to a root agent.
|
||||
/// Add a new client and create a presence for it. All clients except initial login clients will starts off as a child agent
|
||||
/// - the later agent crossing will promote it to a root agent.
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="type">The type of agent to add.</param>
|
||||
void AddNewClient(IClientAPI client, PresenceType type);
|
||||
/// <returns>
|
||||
/// The scene agent if the new client was added or if an agent that already existed.</returns>
|
||||
ISceneAgent AddNewClient(IClientAPI client, PresenceType type);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the given client from the scene.
|
||||
|
@ -90,28 +89,31 @@ namespace OpenSim.Framework
|
|||
|
||||
string GetSimulatorVersion();
|
||||
|
||||
/// <summary>
|
||||
/// Is the agent denoted by the given agentID a child presence in this scene?
|
||||
/// </summary>
|
||||
///
|
||||
/// Used by ClientView when a 'kick everyone' or 'estate message' occurs
|
||||
///
|
||||
/// <param name="avatarID">AvatarID to lookup</param>
|
||||
/// <returns>true if the presence is a child agent, false if the presence is a root exception</returns>
|
||||
/// <exception cref="System.NullReferenceException">
|
||||
/// Thrown if the agent does not exist.
|
||||
/// </exception>
|
||||
bool PresenceChildStatus(UUID agentId);
|
||||
|
||||
bool TryGetScenePresence(UUID agentID, out object scenePresence);
|
||||
|
||||
T RequestModuleInterface<T>();
|
||||
T[] RequestModuleInterfaces<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Register an interface to a region module. This allows module methods to be called directly as
|
||||
/// well as via events. If there is already a module registered for this interface, it is not replaced
|
||||
/// (is this the best behaviour?)
|
||||
/// </summary>
|
||||
/// <param name="mod"></param>
|
||||
void RegisterModuleInterface<M>(M mod);
|
||||
|
||||
void StackModuleInterface<M>(M mod);
|
||||
|
||||
void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback);
|
||||
/// <summary>
|
||||
/// For the given interface, retrieve the region module which implements it.
|
||||
/// </summary>
|
||||
/// <returns>null if there is no registered module implementing that interface</returns>
|
||||
T RequestModuleInterface<T>();
|
||||
|
||||
/// <summary>
|
||||
/// For the given interface, retrieve an array of region modules that implement it.
|
||||
/// </summary>
|
||||
/// <returns>an empty array if there are no registered modules implementing that interface</returns>
|
||||
T[] RequestModuleInterfaces<T>();
|
||||
|
||||
// void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback);
|
||||
|
||||
ISceneObject DeserializeObject(string representation);
|
||||
|
||||
|
|
|
@ -25,44 +25,51 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
using System;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public delegate void ExpectUserDelegate(AgentCircuitData agent);
|
||||
|
||||
|
||||
public delegate void UpdateNeighbours(List<RegionInfo> neighbours);
|
||||
|
||||
public delegate void AgentCrossing(UUID agentID, Vector3 position, bool isFlying);
|
||||
|
||||
public delegate void PrimCrossing(UUID primID, Vector3 position, bool isPhysical);
|
||||
|
||||
public delegate void AcknowledgeAgentCross(UUID agentID);
|
||||
|
||||
public delegate void AcknowledgePrimCross(UUID PrimID);
|
||||
|
||||
public delegate bool CloseAgentConnection(UUID agentID);
|
||||
|
||||
public delegate bool ChildAgentUpdate(ChildAgentDataUpdate cAgentData);
|
||||
|
||||
public delegate void LogOffUser(UUID agentID, UUID regionSecret, string message);
|
||||
|
||||
public delegate LandData GetLandData(uint x, uint y);
|
||||
|
||||
public interface IRegionCommsListener
|
||||
/// <summary>
|
||||
/// An agent in the scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Interface is a work in progress. Please feel free to add other required properties and methods.
|
||||
/// </remarks>
|
||||
public interface ISceneAgent : ISceneEntity
|
||||
{
|
||||
event ExpectUserDelegate OnExpectUser;
|
||||
event GenericCall2 OnExpectChildAgent;
|
||||
event AgentCrossing OnAvatarCrossingIntoRegion;
|
||||
event PrimCrossing OnPrimCrossingIntoRegion;
|
||||
event AcknowledgeAgentCross OnAcknowledgeAgentCrossed;
|
||||
event AcknowledgePrimCross OnAcknowledgePrimCrossed;
|
||||
event UpdateNeighbours OnNeighboursUpdate;
|
||||
event CloseAgentConnection OnCloseAgentConnection;
|
||||
event ChildAgentUpdate OnChildAgentUpdate;
|
||||
event LogOffUser OnLogOffUser;
|
||||
event GetLandData OnGetLandData;
|
||||
/// <value>
|
||||
/// The client controlling this presence
|
||||
/// </value>
|
||||
IClientAPI ControllingClient { get; }
|
||||
|
||||
/// <summary>
|
||||
/// What type of presence is this? User, NPC, etc.
|
||||
/// </summary>
|
||||
PresenceType PresenceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, then the agent has no avatar in the scene.
|
||||
/// The agent exists to relay data from a region that neighbours the current position of the user's avatar.
|
||||
/// Occasionally data is relayed, such as which a user clicks an item in a neighbouring region.
|
||||
/// </summary>
|
||||
bool IsChildAgent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Avatar appearance data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
// Because appearance setting is in a module, we actually need
|
||||
// to give it access to our appearance directly, otherwise we
|
||||
// get a synchronization issue.
|
||||
/// </remarks>
|
||||
AvatarAppearance Appearance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Send initial scene data to the client controlling this agent
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This includes scene object data and the appearance data of other avatars.
|
||||
/// </remarks>
|
||||
void SendInitialDataToMe();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ namespace OpenSim.Framework
|
|||
string Name { get; set; }
|
||||
UUID UUID { get; }
|
||||
uint LocalId { get; }
|
||||
|
||||
Vector3 AbsolutePosition { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,12 @@ namespace OpenSim.Framework
|
|||
public interface ISceneObject
|
||||
{
|
||||
UUID UUID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The owner of this object.
|
||||
/// </summary>
|
||||
UUID OwnerID { get; set; }
|
||||
|
||||
ISceneObject CloneForNewScene();
|
||||
string ToXml2();
|
||||
string ExtraToXmlString();
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OpenSim.Framework.Console
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class MainConsole
|
||||
{
|
||||
private static CommandConsole instance;
|
||||
private static ICommandConsole instance;
|
||||
|
||||
public static CommandConsole Instance
|
||||
public static ICommandConsole Instance
|
||||
{
|
||||
get { return instance; }
|
||||
set { instance = value; }
|
|
@ -32,19 +32,9 @@ namespace OpenSim.Framework
|
|||
{
|
||||
public class NetworkServersInfo
|
||||
{
|
||||
public string AssetSendKey = String.Empty;
|
||||
public string AssetURL = "http://127.0.0.1:" + ConfigSettings.DefaultAssetServerHttpPort.ToString() + "/";
|
||||
|
||||
public string GridRecvKey = String.Empty;
|
||||
public string GridSendKey = String.Empty;
|
||||
public string GridURL = String.Empty;
|
||||
public uint HttpListenerPort = ConfigSettings.DefaultRegionHttpPort;
|
||||
public string InventoryURL = String.Empty;
|
||||
public bool secureInventoryServer = false;
|
||||
public bool isSandbox;
|
||||
public string UserRecvKey = String.Empty;
|
||||
public string UserSendKey = String.Empty;
|
||||
public string UserURL = String.Empty;
|
||||
public bool HttpUsesSSL = false;
|
||||
public string HttpSSLCN = "";
|
||||
public uint httpSSLPort = 9001;
|
||||
|
@ -55,8 +45,6 @@ namespace OpenSim.Framework
|
|||
public string cert_path = String.Empty;
|
||||
public string cert_pass = String.Empty;
|
||||
|
||||
public string MessagingURL = String.Empty;
|
||||
|
||||
public NetworkServersInfo()
|
||||
{
|
||||
}
|
||||
|
@ -65,33 +53,14 @@ namespace OpenSim.Framework
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
public void loadFromConfiguration(IConfigSource config)
|
||||
{
|
||||
|
||||
HttpListenerPort =
|
||||
(uint) config.Configs["Network"].GetInt("http_listener_port", (int) ConfigSettings.DefaultRegionHttpPort);
|
||||
httpSSLPort =
|
||||
(uint)config.Configs["Network"].GetInt("http_listener_sslport", ((int)ConfigSettings.DefaultRegionHttpPort+1));
|
||||
HttpUsesSSL = config.Configs["Network"].GetBoolean("http_listener_ssl", false);
|
||||
HttpSSLCN = config.Configs["Network"].GetString("http_listener_cn", "localhost");
|
||||
GridURL =
|
||||
config.Configs["Network"].GetString("grid_server_url",
|
||||
"http://127.0.0.1:" + ConfigSettings.DefaultGridServerHttpPort.ToString());
|
||||
GridSendKey = config.Configs["Network"].GetString("grid_send_key", "null");
|
||||
GridRecvKey = config.Configs["Network"].GetString("grid_recv_key", "null");
|
||||
UserURL =
|
||||
config.Configs["Network"].GetString("user_server_url",
|
||||
"http://127.0.0.1:" + ConfigSettings.DefaultUserServerHttpPort.ToString());
|
||||
UserSendKey = config.Configs["Network"].GetString("user_send_key", "null");
|
||||
UserRecvKey = config.Configs["Network"].GetString("user_recv_key", "null");
|
||||
AssetURL = config.Configs["Network"].GetString("asset_server_url", AssetURL);
|
||||
InventoryURL = config.Configs["Network"].GetString("inventory_server_url",
|
||||
"http://127.0.0.1:" +
|
||||
ConfigSettings.DefaultInventoryServerHttpPort.ToString());
|
||||
secureInventoryServer = config.Configs["Network"].GetBoolean("secure_inventory_server", true);
|
||||
|
||||
MessagingURL = config.Configs["Network"].GetString("messaging_server_url", string.Empty);
|
||||
|
||||
// "Out of band management https"
|
||||
ssl_listener = config.Configs["Network"].GetBoolean("https_listener",false);
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Sandbox mode region comms listener. There is one of these per region
|
||||
/// </summary>
|
||||
public class RegionCommsListener : IRegionCommsListener
|
||||
{
|
||||
public string debugRegionName = String.Empty;
|
||||
private AcknowledgeAgentCross handlerAcknowledgeAgentCrossed = null; // OnAcknowledgeAgentCrossed;
|
||||
private AcknowledgePrimCross handlerAcknowledgePrimCrossed = null; // OnAcknowledgePrimCrossed;
|
||||
private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
|
||||
private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
|
||||
private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
|
||||
private GenericCall2 handlerExpectChildAgent = null; // OnExpectChildAgent;
|
||||
private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser
|
||||
private UpdateNeighbours handlerNeighboursUpdate = null; // OnNeighboursUpdate;
|
||||
// private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
|
||||
private LogOffUser handlerLogOffUser = null;
|
||||
private GetLandData handlerGetLandData = null;
|
||||
|
||||
#region IRegionCommsListener Members
|
||||
|
||||
public event ExpectUserDelegate OnExpectUser;
|
||||
public event GenericCall2 OnExpectChildAgent;
|
||||
public event AgentCrossing OnAvatarCrossingIntoRegion;
|
||||
public event PrimCrossing OnPrimCrossingIntoRegion;
|
||||
public event UpdateNeighbours OnNeighboursUpdate;
|
||||
public event AcknowledgeAgentCross OnAcknowledgeAgentCrossed;
|
||||
public event AcknowledgePrimCross OnAcknowledgePrimCrossed;
|
||||
public event CloseAgentConnection OnCloseAgentConnection;
|
||||
public event ChildAgentUpdate OnChildAgentUpdate;
|
||||
public event LogOffUser OnLogOffUser;
|
||||
public event GetLandData OnGetLandData;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="agent"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool TriggerExpectUser(AgentCircuitData agent)
|
||||
{
|
||||
handlerExpectUser = OnExpectUser;
|
||||
if (handlerExpectUser != null)
|
||||
{
|
||||
handlerExpectUser(agent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// From User Server
|
||||
public virtual void TriggerLogOffUser(UUID agentID, UUID RegionSecret, string message)
|
||||
{
|
||||
handlerLogOffUser = OnLogOffUser;
|
||||
if (handlerLogOffUser != null)
|
||||
{
|
||||
handlerLogOffUser(agentID, RegionSecret, message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public virtual bool TriggerChildAgentUpdate(ChildAgentDataUpdate cAgentData)
|
||||
{
|
||||
handlerChildAgentUpdate = OnChildAgentUpdate;
|
||||
if (handlerChildAgentUpdate != null)
|
||||
{
|
||||
handlerChildAgentUpdate(cAgentData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TriggerExpectAvatarCrossing(UUID agentID, Vector3 position, bool isFlying)
|
||||
{
|
||||
handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
|
||||
if (handlerAvatarCrossingIntoRegion != null)
|
||||
{
|
||||
handlerAvatarCrossingIntoRegion(agentID, position, isFlying);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TriggerAcknowledgeAgentCrossed(UUID agentID)
|
||||
{
|
||||
handlerAcknowledgeAgentCrossed = OnAcknowledgeAgentCrossed;
|
||||
if (handlerAcknowledgeAgentCrossed != null)
|
||||
{
|
||||
handlerAcknowledgeAgentCrossed(agentID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TriggerAcknowledgePrimCrossed(UUID primID)
|
||||
{
|
||||
handlerAcknowledgePrimCrossed = OnAcknowledgePrimCrossed;
|
||||
if (handlerAcknowledgePrimCrossed != null)
|
||||
{
|
||||
handlerAcknowledgePrimCrossed(primID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TriggerCloseAgentConnection(UUID agentID)
|
||||
{
|
||||
handlerCloseAgentConnection = OnCloseAgentConnection;
|
||||
if (handlerCloseAgentConnection != null)
|
||||
{
|
||||
handlerCloseAgentConnection(agentID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Doesnt take any args??</remarks>
|
||||
/// <returns></returns>
|
||||
public virtual bool TriggerExpectChildAgent()
|
||||
{
|
||||
handlerExpectChildAgent = OnExpectChildAgent;
|
||||
if (handlerExpectChildAgent != null)
|
||||
{
|
||||
handlerExpectChildAgent();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>Added to avoid a unused compiler warning on OnNeighboursUpdate, TODO: Check me</remarks>
|
||||
/// <param name="neighbours"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool TriggerOnNeighboursUpdate(List<RegionInfo> neighbours)
|
||||
{
|
||||
handlerNeighboursUpdate = OnNeighboursUpdate;
|
||||
if (handlerNeighboursUpdate != null)
|
||||
{
|
||||
handlerNeighboursUpdate(neighbours);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TriggerTellRegionToCloseChildConnection(UUID agentID)
|
||||
{
|
||||
handlerCloseAgentConnection = OnCloseAgentConnection;
|
||||
if (handlerCloseAgentConnection != null)
|
||||
return handlerCloseAgentConnection(agentID);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public LandData TriggerGetLandData(uint x, uint y)
|
||||
{
|
||||
handlerGetLandData = OnGetLandData;
|
||||
if (handlerGetLandData != null)
|
||||
return handlerGetLandData(x, y);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ using log4net;
|
|||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework.Console;
|
||||
//using OpenSim.Framework.Console;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
|
|
|
@ -192,6 +192,15 @@ namespace OpenSim.Framework.Servers
|
|||
m_console.Commands.AddCommand("base", false, "show version",
|
||||
"show version",
|
||||
"Show server version", HandleShow);
|
||||
|
||||
m_console.Commands.AddCommand("base", false, "threads abort",
|
||||
"threads abort <thread-id>",
|
||||
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
|
||||
|
||||
m_console.Commands.AddCommand("base", false, "threads show",
|
||||
"threads show",
|
||||
"Show thread status. Synonym for \"show threads\"",
|
||||
(string module, string[] args) => Notice(GetThreadsReport()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,17 +243,28 @@ namespace OpenSim.Framework.Servers
|
|||
/// </summary>
|
||||
protected string GetThreadsReport()
|
||||
{
|
||||
// This should be a constant field.
|
||||
string reportFormat = "{0,6} {1,35} {2,16} {3,10} {4,30}";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreads();
|
||||
|
||||
sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
|
||||
|
||||
int timeNow = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "PRIORITY", "STATE");
|
||||
sb.Append(Environment.NewLine);
|
||||
|
||||
foreach (Watchdog.ThreadWatchdogInfo twi in threads)
|
||||
{
|
||||
Thread t = twi.Thread;
|
||||
|
||||
sb.Append(
|
||||
"ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", TimeRunning: "
|
||||
+ "Pri: " + t.Priority + ", State: " + t.ThreadState);
|
||||
sb.AppendFormat(
|
||||
reportFormat,
|
||||
//t.ManagedThreadId, t.Name, string.Format("{0} ms", timeNow - twi.LastTick), t.Priority, t.ThreadState);
|
||||
t.ManagedThreadId, t.Name, timeNow - twi.LastTick, t.Priority, t.ThreadState);
|
||||
|
||||
sb.Append(Environment.NewLine);
|
||||
}
|
||||
|
||||
|
@ -395,6 +415,27 @@ namespace OpenSim.Framework.Servers
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void HandleThreadsAbort(string module, string[] cmd)
|
||||
{
|
||||
if (cmd.Length != 3)
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: threads abort <thread-id>");
|
||||
return;
|
||||
}
|
||||
|
||||
int threadId;
|
||||
if (!int.TryParse(cmd[2], out threadId))
|
||||
{
|
||||
MainConsole.Instance.Output("ERROR: Thread id must be an integer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Watchdog.AbortThread(threadId))
|
||||
MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
|
||||
else
|
||||
MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
|
||||
}
|
||||
|
||||
protected void ShowInfo()
|
||||
{
|
||||
|
|
|
@ -79,6 +79,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
|
||||
private PollServiceRequestManager m_PollServiceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Control the printing of certain debug messages.
|
||||
/// </summary>
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
public uint SSLPort
|
||||
{
|
||||
get { return m_sslport; }
|
||||
|
@ -442,17 +447,18 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
string path = request.RawUrl;
|
||||
string handlerKey = GetHandlerKey(request.HttpMethod, path);
|
||||
|
||||
//m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
|
||||
|
||||
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
||||
{
|
||||
//m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler");
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found stream handler for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
// Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
|
||||
byte[] buffer = null;
|
||||
|
||||
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
|
||||
|
||||
|
||||
if (requestHandler is IStreamedRequestHandler)
|
||||
{
|
||||
IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
|
||||
|
@ -480,7 +486,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
string[] querystringkeys = request.QueryString.AllKeys;
|
||||
string[] rHeaders = request.Headers.AllKeys;
|
||||
|
||||
|
||||
foreach (string queryname in querystringkeys)
|
||||
{
|
||||
keysvals.Add(queryname, request.QueryString[queryname]);
|
||||
|
@ -556,6 +561,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
{
|
||||
m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -566,7 +572,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
if (strAccept.Contains("application/llsd+xml") ||
|
||||
strAccept.Contains("application/llsd+json"))
|
||||
{
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: Found an application/llsd+xml accept header");
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found application/llsd+xml accept header handler for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleLLSDRequests(request, response);
|
||||
return;
|
||||
}
|
||||
|
@ -577,15 +587,24 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
{
|
||||
case null:
|
||||
case "text/html":
|
||||
// m_log.DebugFormat(
|
||||
// "[BASE HTTP SERVER]: Found a text/html content type for request {0}", request.RawUrl);
|
||||
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleHTTPRequest(request, response);
|
||||
return;
|
||||
|
||||
case "application/llsd+xml":
|
||||
case "application/xml+llsd":
|
||||
case "application/llsd+json":
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: found a application/llsd+xml content type");
|
||||
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleLLSDRequests(request, response);
|
||||
return;
|
||||
|
||||
|
@ -602,7 +621,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
|
||||
if (DoWeHaveALLSDHandler(request.RawUrl))
|
||||
{
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: Found LLSD Handler");
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleLLSDRequests(request, response);
|
||||
return;
|
||||
}
|
||||
|
@ -610,12 +633,20 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
|
||||
if (DoWeHaveAHTTPHandler(request.RawUrl))
|
||||
{
|
||||
// m_log.DebugFormat("[BASE HTTP SERVER]: Found HTTP Handler for request {0}", request.RawUrl);
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleHTTPRequest(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: Generic XMLRPC");
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
// generic login request.
|
||||
HandleXmlRpcRequests(request, response);
|
||||
|
||||
|
@ -872,7 +903,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
byte[] buf = Encoding.UTF8.GetBytes("Not found");
|
||||
response.KeepAlive = false;
|
||||
|
||||
m_log.ErrorFormat("[BASE HTTP SERVER]: Handler not found for http request {0}", request.RawUrl);
|
||||
m_log.ErrorFormat(
|
||||
"[BASE HTTP SERVER]: Handler not found for http request {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buf.Length;
|
||||
|
@ -978,7 +1011,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
|
||||
if (llsdRequest != null)// && m_defaultLlsdHandler != null)
|
||||
{
|
||||
|
||||
LLSDMethod llsdhandler = null;
|
||||
|
||||
if (TryGetLLSDHandler(request.RawUrl, out llsdhandler) && !LegacyLLSDLoginLibOMV)
|
||||
|
@ -1002,13 +1034,14 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
llsdResponse = GenerateNoLLSDHandlerResponse();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
llsdResponse = GenerateNoLLSDHandlerResponse();
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
if (llsdResponse.ToString() == "shutdown404!")
|
||||
{
|
||||
response.ContentType = "text/plain";
|
||||
|
@ -1814,12 +1847,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
public void RemovePollServiceHTTPHandler(string httpMethod, string path)
|
||||
{
|
||||
lock (m_pollHandlers)
|
||||
{
|
||||
if (m_pollHandlers.ContainsKey(httpMethod))
|
||||
{
|
||||
m_pollHandlers.Remove(httpMethod);
|
||||
}
|
||||
}
|
||||
m_pollHandlers.Remove(path);
|
||||
|
||||
RemoveHTTPHandler(httpMethod, path);
|
||||
}
|
||||
|
@ -1843,12 +1871,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
public void RemoveXmlRPCHandler(string method)
|
||||
{
|
||||
lock (m_rpcHandlers)
|
||||
{
|
||||
if (m_rpcHandlers.ContainsKey(method))
|
||||
{
|
||||
m_rpcHandlers.Remove(method);
|
||||
}
|
||||
}
|
||||
m_rpcHandlers.Remove(method);
|
||||
}
|
||||
|
||||
public bool RemoveLLSDHandler(string path, LLSDMethod handler)
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
/// <summary>
|
||||
/// Add a handler for an HTTP request.
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// This handler can actually be invoked either as
|
||||
///
|
||||
/// http://<hostname>:<port>/?method=<methodName>
|
||||
|
@ -70,7 +70,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
/// In addition, the handler invoked by the HTTP server for any request is the one when best matches the request
|
||||
/// URI. So if a handler for "/myapp/" is registered and a request for "/myapp/page" is received, then
|
||||
/// the "/myapp/" handler is invoked if no "/myapp/page" handler exists.
|
||||
///
|
||||
/// </remarks>
|
||||
/// <param name="methodName"></param>
|
||||
/// <param name="handler"></param>
|
||||
/// <returns>
|
||||
|
|
|
@ -28,12 +28,17 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using HttpServer;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public class PollServiceRequestManager
|
||||
{
|
||||
// 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 uint m_WorkerThreadCount = 0;
|
||||
|
@ -42,8 +47,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
private Thread m_watcherThread;
|
||||
private bool m_running = true;
|
||||
|
||||
|
||||
|
||||
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
|
||||
{
|
||||
m_server = pSrv;
|
||||
|
@ -52,22 +55,27 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
|
||||
|
||||
//startup worker threads
|
||||
for (uint i=0;i<m_WorkerThreadCount;i++)
|
||||
for (uint i = 0; i < m_WorkerThreadCount; i++)
|
||||
{
|
||||
m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, pTimeout);
|
||||
m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent;
|
||||
|
||||
m_workerThreads[i] = new Thread(m_PollServiceWorkerThreads[i].ThreadStart);
|
||||
m_workerThreads[i].Name = String.Format("PollServiceWorkerThread{0}",i);
|
||||
//Can't add to thread Tracker here Referencing OpenSim.Framework creates circular reference
|
||||
m_workerThreads[i].Start();
|
||||
|
||||
|
||||
m_workerThreads[i]
|
||||
= Watchdog.StartThread(
|
||||
m_PollServiceWorkerThreads[i].ThreadStart,
|
||||
String.Format("PollServiceWorkerThread{0}", i),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
int.MaxValue);
|
||||
}
|
||||
|
||||
//start watcher threads
|
||||
m_watcherThread = new Thread(ThreadStart);
|
||||
m_watcherThread.Name = "PollServiceWatcherThread";
|
||||
m_watcherThread.Start();
|
||||
m_watcherThread
|
||||
= Watchdog.StartThread(
|
||||
this.ThreadStart,
|
||||
"PollServiceWatcherThread",
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
1000 * 60 * 10);
|
||||
}
|
||||
|
||||
internal void ReQueueEvent(PollServiceHttpRequest req)
|
||||
|
@ -82,10 +90,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
m_requests.Enqueue(req);
|
||||
}
|
||||
|
||||
public void ThreadStart(object o)
|
||||
public void ThreadStart()
|
||||
{
|
||||
while (m_running)
|
||||
{
|
||||
Watchdog.UpdateThread();
|
||||
ProcessQueuedRequests();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
@ -98,12 +107,15 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
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++)
|
||||
{
|
||||
//Loop over number of requests each thread handles.
|
||||
for (int i=0;i<reqperthread && m_requests.Count > 0;i++)
|
||||
for (int i = 0; i < reqperthread && m_requests.Count > 0; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -121,14 +133,14 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
~PollServiceRequestManager()
|
||||
{
|
||||
foreach (object o in m_requests)
|
||||
{
|
||||
PollServiceHttpRequest req = (PollServiceHttpRequest) o;
|
||||
m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id), new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
|
||||
m_server.DoHTTPGruntWork(
|
||||
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
|
||||
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
|
||||
}
|
||||
|
||||
m_requests.Clear();
|
||||
|
@ -140,4 +152,4 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
m_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
m_timeout = pTimeout;
|
||||
}
|
||||
|
||||
public void ThreadStart(object o)
|
||||
public void ThreadStart()
|
||||
{
|
||||
Run();
|
||||
}
|
||||
|
@ -69,6 +69,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
while (m_running)
|
||||
{
|
||||
PollServiceHttpRequest req = m_request.Dequeue();
|
||||
|
||||
Watchdog.UpdateThread();
|
||||
|
||||
try
|
||||
{
|
||||
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
|
||||
|
|
|
@ -31,7 +31,7 @@ using System.Net;
|
|||
using log4net;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
namespace OpenSim.Framework.Servers
|
||||
{
|
||||
public class MainServer
|
||||
{
|
|
@ -30,7 +30,7 @@ namespace OpenSim
|
|||
public class VersionInfo
|
||||
{
|
||||
private const string VERSION_NUMBER = "0.7.2";
|
||||
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
|
||||
private const Flavour VERSION_FLAVOUR = Flavour.Post_Fixes;
|
||||
|
||||
public enum Flavour
|
||||
{
|
||||
|
|
|
@ -146,9 +146,9 @@ namespace OpenSim.Framework.Tests
|
|||
Assert.IsFalse(Util.isUUID("FOOBAR67-89ab-Cdef-0123-456789AbCdEf"),
|
||||
"UUIDs with non-hex characters are recognized as correct UUIDs.");
|
||||
Assert.IsFalse(Util.isUUID("01234567"),
|
||||
"Too short UUIDs are regognized as correct UUIDs.");
|
||||
"Too short UUIDs are recognized as correct UUIDs.");
|
||||
Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123-456789AbCdEf0"),
|
||||
"Too long UUIDs are regognized as correct UUIDs.");
|
||||
"Too long UUIDs are recognized as correct UUIDs.");
|
||||
Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123+456789AbCdEf"),
|
||||
"UUIDs with wrong format are recognized as correct UUIDs.");
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ using System.Threading;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using Nwc.XmlRpc;
|
||||
// using BclExtras;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using Amib.Threading;
|
||||
|
@ -59,10 +58,12 @@ namespace OpenSim.Framework
|
|||
/// <remarks>
|
||||
/// None is used to execute the method in the same thread that made the call. It should only be used by regression
|
||||
/// test code that relies on predictable event ordering.
|
||||
/// RegressionTest is used by regression tests. It fires the call synchronously and does not catch any exceptions.
|
||||
/// </remarks>
|
||||
public enum FireAndForgetMethod
|
||||
{
|
||||
None,
|
||||
RegressionTest,
|
||||
UnsafeQueueUserWorkItem,
|
||||
QueueUserWorkItem,
|
||||
BeginInvoke,
|
||||
|
@ -91,8 +92,10 @@ namespace OpenSim.Framework
|
|||
private static readonly DateTime unixEpoch =
|
||||
DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
|
||||
|
||||
public static readonly Regex UUIDPattern
|
||||
= new Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
|
||||
private static readonly string rawUUIDPattern
|
||||
= "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
|
||||
public static readonly Regex PermissiveUUIDPattern = new Regex(rawUUIDPattern);
|
||||
public static readonly Regex UUIDPattern = new Regex(string.Format("^{0}$", rawUUIDPattern));
|
||||
|
||||
public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
|
||||
public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
|
||||
|
@ -1543,27 +1546,38 @@ namespace OpenSim.Framework
|
|||
|
||||
public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
|
||||
{
|
||||
// When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture
|
||||
// so that we don't encounter problems where, for instance, data is saved with a culture that uses commas
|
||||
// for decimals places but is read by a culture that treats commas as number seperators.
|
||||
WaitCallback realCallback = delegate(object o)
|
||||
{
|
||||
Culture.SetCurrentCulture();
|
||||
WaitCallback realCallback;
|
||||
|
||||
try
|
||||
if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
|
||||
{
|
||||
// If we're running regression tests, then we want any exceptions to rise up to the test code.
|
||||
realCallback = o => { Culture.SetCurrentCulture(); callback(o); };
|
||||
}
|
||||
else
|
||||
{
|
||||
// When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture
|
||||
// so that we don't encounter problems where, for instance, data is saved with a culture that uses commas
|
||||
// for decimals places but is read by a culture that treats commas as number seperators.
|
||||
realCallback = o =>
|
||||
{
|
||||
callback(o);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[UTIL]: Continuing after async_call_method thread terminated with exception {0}{1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
};
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
try
|
||||
{
|
||||
callback(o);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[UTIL]: Continuing after async_call_method thread terminated with exception {0}{1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
switch (FireAndForgetMethod)
|
||||
{
|
||||
case FireAndForgetMethod.RegressionTest:
|
||||
case FireAndForgetMethod.None:
|
||||
realCallback.Invoke(obj);
|
||||
break;
|
||||
|
@ -1650,13 +1664,14 @@ namespace OpenSim.Framework
|
|||
/// </summary>
|
||||
public static void PrintCallStack()
|
||||
{
|
||||
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||
StackTrace stackTrace = new StackTrace(true); // get call stack
|
||||
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||
|
||||
// write call stack method names
|
||||
foreach (StackFrame stackFrame in stackFrames)
|
||||
{
|
||||
m_log.Debug(stackFrame.GetMethod().DeclaringType + "." + stackFrame.GetMethod().Name); // write method name
|
||||
MethodBase mb = stackFrame.GetMethod();
|
||||
m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,19 +40,41 @@ namespace OpenSim.Framework
|
|||
{
|
||||
/// <summary>Timer interval in milliseconds for the watchdog timer</summary>
|
||||
const double WATCHDOG_INTERVAL_MS = 2500.0d;
|
||||
|
||||
/// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary>
|
||||
const int WATCHDOG_TIMEOUT_MS = 5000;
|
||||
|
||||
[System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
|
||||
public class ThreadWatchdogInfo
|
||||
{
|
||||
public Thread Thread;
|
||||
public int LastTick;
|
||||
public Thread Thread { get; private set; }
|
||||
|
||||
public ThreadWatchdogInfo(Thread thread)
|
||||
/// <summary>
|
||||
/// Approximate tick when this thread was started.
|
||||
/// </summary>
|
||||
public int StartTick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Last time this heartbeat update was invoked
|
||||
/// </summary>
|
||||
public int LastTick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of milliseconds before we notify that the thread is having a problem.
|
||||
/// </summary>
|
||||
public int Timeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this thread considered timed out?
|
||||
/// </summary>
|
||||
public bool IsTimedOut { get; set; }
|
||||
|
||||
public ThreadWatchdogInfo(Thread thread, int timeout)
|
||||
{
|
||||
Thread = thread;
|
||||
LastTick = Environment.TickCount & Int32.MaxValue;
|
||||
Timeout = timeout;
|
||||
StartTick = Environment.TickCount & Int32.MaxValue;
|
||||
LastTick = StartTick;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +104,7 @@ namespace OpenSim.Framework
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a new thread that is tracked by the watchdog timer
|
||||
/// Start a new thread that is tracked by the watchdog timer.
|
||||
/// </summary>
|
||||
/// <param name="start">The method that will be executed in a new thread</param>
|
||||
/// <param name="name">A name to give to the new thread</param>
|
||||
|
@ -91,11 +113,37 @@ namespace OpenSim.Framework
|
|||
/// thread, otherwise false</param>
|
||||
/// <returns>The newly created Thread object</returns>
|
||||
public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground)
|
||||
{
|
||||
return StartThread(start, name, priority, isBackground, WATCHDOG_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a new thread that is tracked by the watchdog timer
|
||||
/// </summary>
|
||||
/// <param name="start">The method that will be executed in a new thread</param>
|
||||
/// <param name="name">A name to give to the new thread</param>
|
||||
/// <param name="priority">Priority to run the thread at</param>
|
||||
/// <param name="isBackground">True to run this thread as a background
|
||||
/// thread, otherwise false</param>
|
||||
/// <param name="timeout">
|
||||
/// Number of milliseconds to wait until we issue a warning about timeout.
|
||||
/// </para>
|
||||
/// <returns>The newly created Thread object</returns>
|
||||
public static Thread StartThread(
|
||||
ThreadStart start, string name, ThreadPriority priority, bool isBackground, int timeout)
|
||||
{
|
||||
Thread thread = new Thread(start);
|
||||
thread.Name = name;
|
||||
thread.Priority = priority;
|
||||
thread.IsBackground = isBackground;
|
||||
|
||||
ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout);
|
||||
|
||||
m_log.Debug("[WATCHDOG]: Started tracking thread \"" + twi.Thread.Name + "\" (ID " + twi.Thread.ManagedThreadId + ")");
|
||||
|
||||
lock (m_threads)
|
||||
m_threads.Add(twi.Thread.ManagedThreadId, twi);
|
||||
|
||||
thread.Start();
|
||||
|
||||
return thread;
|
||||
|
@ -112,27 +160,40 @@ namespace OpenSim.Framework
|
|||
/// <summary>
|
||||
/// Stops watchdog tracking on the current thread
|
||||
/// </summary>
|
||||
/// <returns>True if the thread was removed from the list of tracked
|
||||
/// threads, otherwise false</returns>
|
||||
/// <returns>
|
||||
/// True if the thread was removed from the list of tracked
|
||||
/// threads, otherwise false
|
||||
/// </returns>
|
||||
public static bool RemoveThread()
|
||||
{
|
||||
return RemoveThread(Thread.CurrentThread.ManagedThreadId);
|
||||
}
|
||||
|
||||
private static void AddThread(ThreadWatchdogInfo threadInfo)
|
||||
{
|
||||
m_log.Debug("[WATCHDOG]: Started tracking thread \"" + threadInfo.Thread.Name + "\" (ID " + threadInfo.Thread.ManagedThreadId + ")");
|
||||
|
||||
lock (m_threads)
|
||||
m_threads.Add(threadInfo.Thread.ManagedThreadId, threadInfo);
|
||||
}
|
||||
|
||||
private static bool RemoveThread(int threadID)
|
||||
{
|
||||
lock (m_threads)
|
||||
return m_threads.Remove(threadID);
|
||||
}
|
||||
|
||||
public static bool AbortThread(int threadID)
|
||||
{
|
||||
lock (m_threads)
|
||||
{
|
||||
if (m_threads.ContainsKey(threadID))
|
||||
{
|
||||
ThreadWatchdogInfo twi = m_threads[threadID];
|
||||
twi.Thread.Abort();
|
||||
RemoveThread(threadID);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateThread(int threadID)
|
||||
{
|
||||
ThreadWatchdogInfo threadInfo;
|
||||
|
@ -144,9 +205,14 @@ namespace OpenSim.Framework
|
|||
try
|
||||
{
|
||||
if (m_threads.TryGetValue(threadID, out threadInfo))
|
||||
{
|
||||
threadInfo.LastTick = Environment.TickCount & Int32.MaxValue;
|
||||
threadInfo.IsTimedOut = false;
|
||||
}
|
||||
else
|
||||
AddThread(new ThreadWatchdogInfo(Thread.CurrentThread));
|
||||
{
|
||||
m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
@ -157,7 +223,8 @@ namespace OpenSim.Framework
|
|||
/// <returns></returns>
|
||||
public static ThreadWatchdogInfo[] GetThreads()
|
||||
{
|
||||
return m_threads.Values.ToArray();
|
||||
lock (m_threads)
|
||||
return m_threads.Values.ToArray();
|
||||
}
|
||||
|
||||
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
|
@ -174,10 +241,16 @@ namespace OpenSim.Framework
|
|||
|
||||
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
|
||||
{
|
||||
if (threadInfo.Thread.ThreadState == ThreadState.Stopped || now - threadInfo.LastTick >= WATCHDOG_TIMEOUT_MS)
|
||||
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
|
||||
{
|
||||
timedOut = threadInfo;
|
||||
m_threads.Remove(threadInfo.Thread.ManagedThreadId);
|
||||
RemoveThread(threadInfo.Thread.ManagedThreadId);
|
||||
break;
|
||||
}
|
||||
else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout)
|
||||
{
|
||||
threadInfo.IsTimedOut = true;
|
||||
timedOut = threadInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -190,4 +263,4 @@ namespace OpenSim.Framework
|
|||
m_watchdogTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,9 +39,7 @@ using System.Text;
|
|||
using System.Web;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
using log4net;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
|
@ -65,35 +63,35 @@ namespace OpenSim.Framework
|
|||
// a "long" call for warning & debugging purposes
|
||||
public const int LongCallTime = 500;
|
||||
|
||||
/// <summary>
|
||||
/// Send LLSD to an HTTP client in application/llsd+json form
|
||||
/// </summary>
|
||||
/// <param name="response">HTTP response to send the data in</param>
|
||||
/// <param name="body">LLSD to send to the client</param>
|
||||
public static void SendJSONResponse(OSHttpResponse response, OSDMap body)
|
||||
{
|
||||
byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body));
|
||||
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
response.ContentLength = responseData.Length;
|
||||
response.ContentType = "application/llsd+json";
|
||||
response.Body.Write(responseData, 0, responseData.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send LLSD to an HTTP client in application/llsd+xml form
|
||||
/// </summary>
|
||||
/// <param name="response">HTTP response to send the data in</param>
|
||||
/// <param name="body">LLSD to send to the client</param>
|
||||
public static void SendXMLResponse(OSHttpResponse response, OSDMap body)
|
||||
{
|
||||
byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body);
|
||||
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
response.ContentLength = responseData.Length;
|
||||
response.ContentType = "application/llsd+xml";
|
||||
response.Body.Write(responseData, 0, responseData.Length);
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Send LLSD to an HTTP client in application/llsd+json form
|
||||
// /// </summary>
|
||||
// /// <param name="response">HTTP response to send the data in</param>
|
||||
// /// <param name="body">LLSD to send to the client</param>
|
||||
// public static void SendJSONResponse(OSHttpResponse response, OSDMap body)
|
||||
// {
|
||||
// byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body));
|
||||
//
|
||||
// response.ContentEncoding = Encoding.UTF8;
|
||||
// response.ContentLength = responseData.Length;
|
||||
// response.ContentType = "application/llsd+json";
|
||||
// response.Body.Write(responseData, 0, responseData.Length);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Send LLSD to an HTTP client in application/llsd+xml form
|
||||
// /// </summary>
|
||||
// /// <param name="response">HTTP response to send the data in</param>
|
||||
// /// <param name="body">LLSD to send to the client</param>
|
||||
// public static void SendXMLResponse(OSHttpResponse response, OSDMap body)
|
||||
// {
|
||||
// byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body);
|
||||
//
|
||||
// response.ContentEncoding = Encoding.UTF8;
|
||||
// response.ContentLength = responseData.Length;
|
||||
// response.ContentType = "application/llsd+xml";
|
||||
// response.Body.Write(responseData, 0, responseData.Length);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Make a GET or GET-like request to a web service that returns LLSD
|
||||
|
@ -296,10 +294,10 @@ namespace OpenSim.Framework
|
|||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch
|
||||
{
|
||||
// don't need to treat this as an error... we're just guessing anyway
|
||||
m_log.DebugFormat("[WEB UTIL] couldn't decode <{0}>: {1}",response,e.Message);
|
||||
// m_log.DebugFormat("[WEB UTIL] couldn't decode <{0}>: {1}",response,e.Message);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -362,10 +362,6 @@ namespace OpenSim
|
|||
{
|
||||
m_configSettings.PhysicsEngine = startupConfig.GetString("physics");
|
||||
m_configSettings.MeshEngineName = startupConfig.GetString("meshing");
|
||||
m_configSettings.PhysicalPrim = startupConfig.GetBoolean("physical_prim", true);
|
||||
|
||||
m_configSettings.See_into_region_from_neighbor = startupConfig.GetBoolean("see_into_this_sim_from_neighbor", true);
|
||||
|
||||
m_configSettings.StorageDll = startupConfig.GetString("storage_plugin");
|
||||
|
||||
m_configSettings.ClientstackDll
|
||||
|
|
|
@ -37,6 +37,7 @@ using Nini.Config;
|
|||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Statistics;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
@ -210,28 +211,33 @@ namespace OpenSim
|
|||
/// </summary>
|
||||
private void RegisterConsoleCommands()
|
||||
{
|
||||
m_console.Commands.AddCommand("region", false, "clear assets",
|
||||
"clear assets",
|
||||
"Clear the asset cache", HandleClearAssets);
|
||||
|
||||
m_console.Commands.AddCommand("region", false, "force update",
|
||||
"force update",
|
||||
"Force the update of all objects on clients",
|
||||
HandleForceUpdate);
|
||||
|
||||
m_console.Commands.AddCommand("region", false, "debug packet",
|
||||
"debug packet <level>",
|
||||
"debug packet <level> [<avatar-first-name> <avatar-last-name>]",
|
||||
"Turn on packet debugging",
|
||||
"If level > 255 then all incoming and outgoing packets are logged.\n"
|
||||
+ "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
|
||||
+ "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
|
||||
+ "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
|
||||
+ "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
|
||||
+ "If level <= 0 then no packets are logged.",
|
||||
+ "If level <= 0 then no packets are logged.\n"
|
||||
+ "If an avatar name is given then only packets from that avatar are logged",
|
||||
Debug);
|
||||
|
||||
m_console.Commands.AddCommand("region", false, "debug http",
|
||||
"debug http <level>",
|
||||
"Turn on inbound http request debugging for everything except the event queue (see debug eq).",
|
||||
"If level >= 2 then the handler used to service the request is logged.\n"
|
||||
+ "If level >= 1 then incoming HTTP requests are logged.\n"
|
||||
+ "If level <= 0 then no extra http logging is done.\n",
|
||||
Debug);
|
||||
|
||||
m_console.Commands.AddCommand("region", false, "debug scene",
|
||||
"debug scene <cripting> <collisions> <physics>",
|
||||
"debug scene <scripting> <collisions> <physics>",
|
||||
"Turn on scene debugging", Debug);
|
||||
|
||||
m_console.Commands.AddCommand("region", false, "change region",
|
||||
|
@ -325,7 +331,7 @@ namespace OpenSim
|
|||
|
||||
m_console.Commands.AddCommand("region", false, "backup",
|
||||
"backup",
|
||||
"Persist objects to the database now", RunCommand);
|
||||
"Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand);
|
||||
|
||||
m_console.Commands.AddCommand("region", false, "create region",
|
||||
"create region [\"region name\"] <region_file.ini>",
|
||||
|
@ -509,11 +515,6 @@ namespace OpenSim
|
|||
}
|
||||
}
|
||||
|
||||
private void HandleClearAssets(string module, string[] args)
|
||||
{
|
||||
MainConsole.Instance.Output("Not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force resending of all updates to all clients in active region(s)
|
||||
/// </summary>
|
||||
|
@ -781,6 +782,7 @@ namespace OpenSim
|
|||
break;
|
||||
|
||||
case "backup":
|
||||
MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
|
||||
m_sceneManager.BackupCurrentScene();
|
||||
break;
|
||||
|
||||
|
@ -791,7 +793,7 @@ namespace OpenSim
|
|||
if (m_sceneManager.TryGetScene(regRemoveName, out removeScene))
|
||||
RemoveRegion(removeScene, false);
|
||||
else
|
||||
MainConsole.Instance.Output("no region with that name");
|
||||
MainConsole.Instance.Output("No region with that name");
|
||||
break;
|
||||
|
||||
case "delete-region":
|
||||
|
@ -854,22 +856,42 @@ namespace OpenSim
|
|||
switch (args[1])
|
||||
{
|
||||
case "packet":
|
||||
string name = null;
|
||||
if (args.Length == 5)
|
||||
name = string.Format("{0} {1}", args[3], args[4]);
|
||||
|
||||
if (args.Length > 2)
|
||||
{
|
||||
int newDebug;
|
||||
if (int.TryParse(args[2], out newDebug))
|
||||
{
|
||||
m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug);
|
||||
m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
|
||||
// We provide user information elsewhere if any clients had their debug level set.
|
||||
// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("packet debug should be 0..255");
|
||||
MainConsole.Instance.Output("Usage: debug packet 0..255");
|
||||
}
|
||||
MainConsole.Instance.Output(String.Format("New packet debug: {0}", newDebug));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "http":
|
||||
if (args.Length == 3)
|
||||
{
|
||||
int newDebug;
|
||||
if (int.TryParse(args[2], out newDebug))
|
||||
{
|
||||
MainServer.Instance.DebugLevel = newDebug;
|
||||
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output("Usage: debug http 0..2");
|
||||
break;
|
||||
|
||||
case "scene":
|
||||
if (args.Length == 5)
|
||||
{
|
||||
|
@ -892,13 +914,13 @@ namespace OpenSim
|
|||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("debug scene <scripting> <collisions> <physics> (where inside <> is true/false)");
|
||||
MainConsole.Instance.Output("Usage: debug scene <scripting> <collisions> <physics> (where inside <> is true/false)");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
MainConsole.Instance.Output("Unknown debug");
|
||||
MainConsole.Instance.Output("Unknown debug command");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ using OpenSim.Region.Framework;
|
|||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Services.UserAccountService;
|
||||
|
@ -462,9 +462,18 @@ namespace OpenSim
|
|||
string password = MainConsole.Instance.PasswdPrompt("Password");
|
||||
string email = MainConsole.Instance.CmdPrompt("Email", "");
|
||||
|
||||
string rawPrincipalId = MainConsole.Instance.CmdPrompt("User ID", UUID.Random().ToString());
|
||||
|
||||
UUID principalId = UUID.Zero;
|
||||
if (!UUID.TryParse(rawPrincipalId, out principalId))
|
||||
{
|
||||
m_log.ErrorFormat("[OPENSIM]: ID {0} is not a valid UUID", rawPrincipalId);
|
||||
return;
|
||||
}
|
||||
|
||||
account
|
||||
= ((UserAccountService)scene.UserAccountService).CreateUser(
|
||||
regionInfo.ScopeID, first, last, password, email);
|
||||
regionInfo.ScopeID, principalId, first, last, password, email);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
@ -650,8 +659,8 @@ namespace OpenSim
|
|||
|
||||
return new Scene(
|
||||
regionInfo, circuitManager, sceneGridService,
|
||||
simDataService, estateDataService, m_moduleLoader, false, m_configSettings.PhysicalPrim,
|
||||
m_configSettings.See_into_region_from_neighbor, m_config.Source, m_version);
|
||||
simDataService, estateDataService, m_moduleLoader, false,
|
||||
m_config.Source, m_version);
|
||||
}
|
||||
|
||||
protected void ShutdownClientServer(RegionInfo whichRegion)
|
||||
|
@ -719,7 +728,7 @@ namespace OpenSim
|
|||
|
||||
public string Path
|
||||
{
|
||||
get { return "/simstatus/"; }
|
||||
get { return "/simstatus"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,7 +766,7 @@ namespace OpenSim
|
|||
public string Path
|
||||
{
|
||||
// This is for the OpenSimulator instance and is the osSecret hashed
|
||||
get { return "/" + osXStatsURI + "/"; }
|
||||
get { return "/" + osXStatsURI; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -798,7 +807,7 @@ namespace OpenSim
|
|||
public string Path
|
||||
{
|
||||
// This is for the OpenSimulator instance and is the user provided URI
|
||||
get { return "/" + osUXStatsURI + "/"; }
|
||||
get { return "/" + osUXStatsURI; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
|
||||
byte[] data, string inventoryType, string assetType);
|
||||
|
||||
public delegate void UploadedBakedTexture(UUID assetID, byte[] data);
|
||||
|
||||
public delegate UUID UpdateItem(UUID itemID, byte[] data);
|
||||
|
||||
public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
|
||||
|
@ -97,7 +95,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
private static readonly string m_notecardTaskUpdatePath = "0005/";
|
||||
// private static readonly string m_fetchInventoryPath = "0006/";
|
||||
// private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
|
||||
private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule.
|
||||
|
||||
|
||||
// These are callbacks which will be setup by the scene so that we can update scene data when we
|
||||
|
@ -165,8 +162,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory);
|
||||
m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
|
||||
m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
|
||||
m_HostCapsObj.RegisterHandler("UploadBakedTexture", new RestStreamHandler("POST", capsBase + m_uploadBakedTexturePath, UploadBakedTexture));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -239,7 +234,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
Hashtable caps = m_HostCapsObj.CapsHandlers.CapsDetails;
|
||||
Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true);
|
||||
|
||||
// Add the external too
|
||||
foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
|
||||
caps[kvp.Key] = kvp.Value;
|
||||
|
@ -330,74 +326,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a request from the client for a Uri to upload a baked texture.
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="param"></param>
|
||||
/// <param name="httpRequest"></param>
|
||||
/// <param name="httpResponse"></param>
|
||||
/// <returns>The upload response if the request is successful, null otherwise.</returns>
|
||||
public string UploadBakedTexture(string request, string path,
|
||||
string param, OSHttpRequest httpRequest,
|
||||
OSHttpResponse httpResponse)
|
||||
{
|
||||
try
|
||||
{
|
||||
// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName);
|
||||
|
||||
string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
|
||||
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
|
||||
|
||||
BakedTextureUploader uploader =
|
||||
new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener);
|
||||
uploader.OnUpLoad += BakedTextureUploaded;
|
||||
|
||||
m_HostCapsObj.HttpListener.AddStreamHandler(
|
||||
new BinaryStreamHandler("POST", capsBase + uploaderPath,
|
||||
uploader.uploaderCaps));
|
||||
|
||||
string protocol = "http://";
|
||||
|
||||
if (m_HostCapsObj.SSLCaps)
|
||||
protocol = "https://";
|
||||
|
||||
string uploaderURL = protocol + m_HostCapsObj.HostName + ":" +
|
||||
m_HostCapsObj.Port.ToString() + capsBase + uploaderPath;
|
||||
|
||||
LLSDAssetUploadResponse uploadResponse =
|
||||
new LLSDAssetUploadResponse();
|
||||
uploadResponse.uploader = uploaderURL;
|
||||
uploadResponse.state = "upload";
|
||||
|
||||
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[CAPS]: " + e.ToString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a baked texture has been successfully uploaded by a client.
|
||||
/// </summary>
|
||||
/// <param name="assetID"></param>
|
||||
/// <param name="data"></param>
|
||||
public void BakedTextureUploaded(UUID assetID, byte[] data)
|
||||
{
|
||||
// m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString());
|
||||
|
||||
AssetBase asset;
|
||||
asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
|
||||
asset.Data = data;
|
||||
asset.Temporary = true;
|
||||
asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
|
||||
m_assetService.Store(asset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when new asset data for an agent inventory item update has been uploaded.
|
||||
/// </summary>
|
||||
|
@ -1067,6 +995,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
// XXX Maybe this should be some meaningful error packet
|
||||
return null;
|
||||
}
|
||||
|
||||
///Left this in and commented in case there are unforseen issues
|
||||
//private void SaveAssetToFile(string filename, byte[] data)
|
||||
//{
|
||||
|
@ -1090,53 +1019,4 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public class BakedTextureUploader
|
||||
{
|
||||
public event UploadedBakedTexture OnUpLoad;
|
||||
private UploadedBakedTexture handlerUpLoad = null;
|
||||
|
||||
private string uploaderPath = String.Empty;
|
||||
private UUID newAssetID;
|
||||
private IHttpServer httpListener;
|
||||
|
||||
public BakedTextureUploader(string path, IHttpServer httpServer)
|
||||
{
|
||||
newAssetID = UUID.Random();
|
||||
uploaderPath = path;
|
||||
httpListener = httpServer;
|
||||
// m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle raw uploaded baked texture data.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="param"></param>
|
||||
/// <returns></returns>
|
||||
public string uploaderCaps(byte[] data, string path, string param)
|
||||
{
|
||||
handlerUpLoad = OnUpLoad;
|
||||
if (handlerUpLoad != null)
|
||||
{
|
||||
Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); });
|
||||
}
|
||||
|
||||
string res = String.Empty;
|
||||
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
|
||||
uploadComplete.new_asset = newAssetID.ToString();
|
||||
uploadComplete.new_inventory_item = UUID.Zero;
|
||||
uploadComplete.state = "complete";
|
||||
|
||||
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
|
||||
|
||||
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||
|
||||
// m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -39,6 +39,7 @@ using OpenMetaverse.Messages.Linden;
|
|||
using OpenMetaverse.Packets;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
@ -58,9 +59,15 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
public class EventQueueGetModule : IEventQueue, IRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
protected Scene m_scene = null;
|
||||
|
||||
/// <value>
|
||||
/// Debug level.
|
||||
/// </value>
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
protected Scene m_scene;
|
||||
private IConfigSource m_gConfig;
|
||||
bool enabledYN = false;
|
||||
bool enabledYN;
|
||||
|
||||
private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
|
||||
|
||||
|
@ -97,12 +104,21 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
scene.EventManager.OnClientClosed += ClientClosed;
|
||||
scene.EventManager.OnMakeChildAgent += MakeChildAgent;
|
||||
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"event queue",
|
||||
false,
|
||||
"debug eq",
|
||||
"debug eq [0|1]",
|
||||
"Turn on event queue debugging",
|
||||
"debug eq 1 will turn on event queue debugging. This will log all outgoing event queue messages to clients.\n"
|
||||
+ "debug eq 0 will turn off event queue debugging.",
|
||||
HandleDebugEq);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gConfig = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p)
|
||||
|
@ -129,6 +145,22 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
}
|
||||
#endregion
|
||||
|
||||
protected void HandleDebugEq(string module, string[] args)
|
||||
{
|
||||
int debugLevel;
|
||||
|
||||
if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Usage: debug eq [0|1]");
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLevel = debugLevel;
|
||||
MainConsole.Instance.OutputFormat(
|
||||
"Set event queue debug level to {0} in {1}", DebugLevel, m_scene.RegionInfo.RegionName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Always returns a valid queue
|
||||
/// </summary>
|
||||
|
@ -179,9 +211,10 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
{
|
||||
Queue<OSD> queue = GetQueue(avatarID);
|
||||
if (queue != null)
|
||||
queue.Enqueue(ev);
|
||||
lock (queue)
|
||||
queue.Enqueue(ev);
|
||||
}
|
||||
catch(NullReferenceException e)
|
||||
catch (NullReferenceException e)
|
||||
{
|
||||
m_log.Error("[EVENTQUEUE] Caught exception: " + e);
|
||||
return false;
|
||||
|
@ -204,7 +237,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
private void ClientClosed(UUID AgentID, Scene scene)
|
||||
{
|
||||
//m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
|
||||
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
|
||||
|
||||
int count = 0;
|
||||
while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
|
||||
|
@ -216,11 +249,13 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
{
|
||||
queues.Remove(AgentID);
|
||||
}
|
||||
|
||||
List<UUID> removeitems = new List<UUID>();
|
||||
lock (m_AvatarQueueUUIDMapping)
|
||||
{
|
||||
foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
|
||||
{
|
||||
// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
|
||||
if (ky == AgentID)
|
||||
{
|
||||
removeitems.Add(ky);
|
||||
|
@ -229,11 +264,13 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
foreach (UUID ky in removeitems)
|
||||
{
|
||||
UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
|
||||
m_AvatarQueueUUIDMapping.Remove(ky);
|
||||
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
|
||||
}
|
||||
|
||||
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + eventQueueGetUuid.ToString() + "/");
|
||||
}
|
||||
}
|
||||
|
||||
UUID searchval = UUID.Zero;
|
||||
|
||||
removeitems.Clear();
|
||||
|
@ -252,7 +289,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
foreach (UUID ky in removeitems)
|
||||
m_QueueUUIDAvatarMapping.Remove(ky);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,7 +356,9 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
// This will persist this beyond the expiry of the caps handlers
|
||||
MainServer.Instance.AddPollServiceHTTPHandler(
|
||||
capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
|
||||
capsBase + EventQueueGetUUID.ToString() + "/",
|
||||
EventQueuePoll,
|
||||
new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
|
||||
|
||||
Random rnd = new Random(Environment.TickCount);
|
||||
lock (m_ids)
|
||||
|
@ -338,12 +376,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
Queue<OSD> queue = GetQueue(agentID);
|
||||
if (queue != null)
|
||||
lock (queue)
|
||||
{
|
||||
if (queue.Count > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return queue.Count > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -358,8 +392,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
element = queue.Dequeue(); // 15s timeout
|
||||
}
|
||||
|
||||
|
||||
|
||||
int thisID = 0;
|
||||
lock (m_ids)
|
||||
thisID = m_ids[pAgentId];
|
||||
|
@ -373,12 +405,31 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
}
|
||||
else
|
||||
{
|
||||
if (DebugLevel > 0 && element is OSDMap)
|
||||
{
|
||||
OSDMap ev = (OSDMap)element;
|
||||
m_log.DebugFormat(
|
||||
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
|
||||
ev["message"], m_scene.GetScenePresence(pAgentId).Name);
|
||||
}
|
||||
|
||||
array.Add(element);
|
||||
|
||||
lock (queue)
|
||||
{
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
array.Add(queue.Dequeue());
|
||||
element = queue.Dequeue();
|
||||
|
||||
if (DebugLevel > 0 && element is OSDMap)
|
||||
{
|
||||
OSDMap ev = (OSDMap)element;
|
||||
m_log.DebugFormat(
|
||||
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
|
||||
ev["message"], m_scene.GetScenePresence(pAgentId).Name);
|
||||
}
|
||||
|
||||
array.Add(element);
|
||||
thisID++;
|
||||
}
|
||||
}
|
||||
|
@ -431,7 +482,10 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
// }
|
||||
|
||||
Queue<OSD> queue = TryGetQueue(agentID);
|
||||
OSD element = queue.Dequeue(); // 15s timeout
|
||||
OSD element;
|
||||
|
||||
lock (queue)
|
||||
element = queue.Dequeue(); // 15s timeout
|
||||
|
||||
Hashtable responsedata = new Hashtable();
|
||||
|
||||
|
@ -470,10 +524,32 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
else
|
||||
{
|
||||
array.Add(element);
|
||||
while (queue.Count > 0)
|
||||
|
||||
if (element is OSDMap)
|
||||
{
|
||||
array.Add(queue.Dequeue());
|
||||
thisID++;
|
||||
OSDMap ev = (OSDMap)element;
|
||||
m_log.DebugFormat(
|
||||
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
|
||||
ev["message"], m_scene.GetScenePresence(agentID).Name);
|
||||
}
|
||||
|
||||
lock (queue)
|
||||
{
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
element = queue.Dequeue();
|
||||
|
||||
if (element is OSDMap)
|
||||
{
|
||||
OSDMap ev = (OSDMap)element;
|
||||
m_log.DebugFormat(
|
||||
"[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
|
||||
ev["message"], m_scene.GetScenePresence(agentID).Name);
|
||||
}
|
||||
|
||||
array.Add(element);
|
||||
thisID++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,7 +566,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
responsedata["content_type"] = "application/xml";
|
||||
responsedata["keepalive"] = false;
|
||||
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
|
||||
//m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
|
||||
|
||||
m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
|
||||
|
||||
return responsedata;
|
||||
}
|
||||
|
@ -520,6 +597,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
AvatarID = m_QueueUUIDAvatarMapping[capUUID];
|
||||
}
|
||||
}
|
||||
|
||||
if (AvatarID != UUID.Zero)
|
||||
{
|
||||
return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
|
||||
|
@ -712,6 +790,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
OSD item = EventQueueHelper.GroupMembership(groupUpdate);
|
||||
Enqueue(item, avatarID);
|
||||
}
|
||||
|
||||
public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
|
||||
{
|
||||
OSD item = EventQueueHelper.PlacesQuery(groupUpdate);
|
||||
|
|
|
@ -25,48 +25,55 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using log4net.Config;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.ClientStack.Linden;
|
||||
using OpenSim.Region.CoreModules.Framework;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
{
|
||||
public class TestLLPacketServer : LLPacketServer
|
||||
namespace OpenSim.Region.ClientStack.Linden.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class EventQueueTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Record counts of packets received
|
||||
/// </summary>
|
||||
protected Dictionary<PacketType, int> m_packetsReceived = new Dictionary<PacketType, int>();
|
||||
|
||||
public TestLLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings)
|
||||
: base(networkHandler, userSettings)
|
||||
{}
|
||||
|
||||
public override void InPacket(uint circuitCode, Packet packet)
|
||||
private TestScene m_scene;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
base.InPacket(circuitCode, packet);
|
||||
|
||||
if (m_packetsReceived.ContainsKey(packet.Type))
|
||||
m_packetsReceived[packet.Type]++;
|
||||
else
|
||||
m_packetsReceived[packet.Type] = 1;
|
||||
MainServer.Instance = new BaseHttpServer(9999, false, 9998, "");
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Startup");
|
||||
config.Configs["Startup"].Set("EventQueue", "true");
|
||||
|
||||
CapabilitiesModule capsModule = new CapabilitiesModule();
|
||||
EventQueueGetModule eqgModule = new EventQueueGetModule();
|
||||
|
||||
m_scene = SceneHelpers.SetupScene();
|
||||
SceneHelpers.SetupSceneModules(m_scene, config, capsModule, eqgModule);
|
||||
}
|
||||
|
||||
public int GetTotalPacketsReceived()
|
||||
|
||||
[Test]
|
||||
public void AddForClient()
|
||||
{
|
||||
int totalCount = 0;
|
||||
|
||||
foreach (int count in m_packetsReceived.Values)
|
||||
totalCount += count;
|
||||
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
public int GetPacketsReceivedFor(PacketType packetType)
|
||||
{
|
||||
if (m_packetsReceived.ContainsKey(packetType))
|
||||
return m_packetsReceived[packetType];
|
||||
else
|
||||
return 0;
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
|
||||
|
||||
// TODO: Add more assertions for the other aspects of event queues
|
||||
Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using Mono.Addins;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||
using OpenSim.Capabilities.Handlers;
|
||||
|
||||
namespace OpenSim.Region.ClientStack.Linden
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class UploadBakedTextureModule : INonSharedRegionModule
|
||||
{
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// For historical reasons this is fixed, but there
|
||||
/// </summary>
|
||||
private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule.
|
||||
|
||||
private Scene m_scene;
|
||||
private bool m_persistBakedTextures;
|
||||
|
||||
public void Initialise(IConfigSource source)
|
||||
{
|
||||
IConfig sconfig = source.Configs["Startup"];
|
||||
if (sconfig != null)
|
||||
m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
|
||||
}
|
||||
|
||||
public void AddRegion(Scene s)
|
||||
{
|
||||
m_scene = s;
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene s)
|
||||
{
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene s)
|
||||
{
|
||||
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
public void Close() { }
|
||||
|
||||
public string Name { get { return "UploadBakedTextureModule"; } }
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void RegisterCaps(UUID agentID, Caps caps)
|
||||
{
|
||||
caps.RegisterHandler(
|
||||
"UploadBakedTexture",
|
||||
new RestStreamHandler(
|
||||
"POST",
|
||||
"/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
|
||||
new UploadBakedTextureHandler(
|
||||
caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,6 +45,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private const int IMAGE_PACKET_SIZE = 1000;
|
||||
private const int FIRST_PACKET_SIZE = 600;
|
||||
|
||||
/// <summary>
|
||||
/// If we've requested an asset but not received it in this ticks timeframe, then allow a duplicate
|
||||
/// request from the client to trigger a fresh asset request.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There are 10,000 ticks in a millisecond
|
||||
/// </remarks>
|
||||
private const int ASSET_REQUEST_TIMEOUT = 100000000;
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public uint LastSequence;
|
||||
|
@ -56,9 +65,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
public IAssetService AssetService;
|
||||
public UUID AgentID;
|
||||
public IInventoryAccessModule InventoryAccessModule;
|
||||
public OpenJPEG.J2KLayerInfo[] Layers;
|
||||
public bool IsDecoded;
|
||||
public bool HasAsset;
|
||||
private OpenJPEG.J2KLayerInfo[] m_layers;
|
||||
|
||||
/// <summary>
|
||||
/// Has this request decoded the asset data?
|
||||
/// </summary>
|
||||
public bool IsDecoded { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has this request received the required asset data?
|
||||
/// </summary>
|
||||
public bool HasAsset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time in milliseconds at which the asset was requested.
|
||||
/// </summary>
|
||||
public long AssetRequestTime { get; private set; }
|
||||
|
||||
public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle;
|
||||
|
||||
private uint m_currentPacket;
|
||||
|
@ -82,7 +105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="packetsToSend">Maximum number of packets to send during this call</param>
|
||||
/// <param name="packetsSent">Number of packets sent during this call</param>
|
||||
/// <returns>True if the transfer completes at the current discard level, otherwise false</returns>
|
||||
public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent)
|
||||
public bool SendPackets(IClientAPI client, int packetsToSend, out int packetsSent)
|
||||
{
|
||||
packetsSent = 0;
|
||||
|
||||
|
@ -102,7 +125,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
m_currentPacket = 2;
|
||||
}
|
||||
|
||||
|
||||
while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket)
|
||||
{
|
||||
sendMore = SendPacket(client);
|
||||
|
@ -114,17 +137,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
return (m_currentPacket > m_stopPacket);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is where we decide what we need to update
|
||||
/// and assign the real discardLevel and packetNumber
|
||||
/// assuming of course that the connected client might be bonkers
|
||||
/// </summary>
|
||||
public void RunUpdate()
|
||||
{
|
||||
//This is where we decide what we need to update
|
||||
//and assign the real discardLevel and packetNumber
|
||||
//assuming of course that the connected client might be bonkers
|
||||
|
||||
if (!HasAsset)
|
||||
{
|
||||
if (!m_assetRequested)
|
||||
if (!m_assetRequested || DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[J2KIMAGE]: Requesting asset {0} from request in packet {1}, already requested? {2}, due to timeout? {3}",
|
||||
// TextureID, LastSequence, m_assetRequested, DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT);
|
||||
|
||||
m_assetRequested = true;
|
||||
AssetRequestTime = DateTime.UtcNow.Ticks;
|
||||
|
||||
AssetService.Get(TextureID.ToString(), this, AssetReceived);
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +167,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
//Request decode
|
||||
m_decodeRequested = true;
|
||||
|
||||
// m_log.DebugFormat("[J2KIMAGE]: Requesting decode of asset {0}", TextureID);
|
||||
|
||||
// Do we have a jpeg decoder?
|
||||
if (J2KDecoder != null)
|
||||
{
|
||||
|
@ -149,7 +182,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// Send it off to the jpeg decoder
|
||||
J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -170,14 +202,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if (DiscardLevel >= 0 || m_stopPacket == 0)
|
||||
{
|
||||
// This shouldn't happen, but if it does, we really can't proceed
|
||||
if (Layers == null)
|
||||
if (m_layers == null)
|
||||
{
|
||||
m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing Layers. Canceling texture transfer");
|
||||
m_currentPacket = m_stopPacket;
|
||||
return;
|
||||
}
|
||||
|
||||
int maxDiscardLevel = Math.Max(0, Layers.Length - 1);
|
||||
int maxDiscardLevel = Math.Max(0, m_layers.Length - 1);
|
||||
|
||||
// Treat initial texture downloads with a DiscardLevel of -1 a request for the highest DiscardLevel
|
||||
if (DiscardLevel < 0 && m_stopPacket == 0)
|
||||
|
@ -187,9 +219,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
DiscardLevel = (sbyte)Math.Min(DiscardLevel, maxDiscardLevel);
|
||||
|
||||
//Calculate the m_stopPacket
|
||||
if (Layers.Length > 0)
|
||||
if (m_layers.Length > 0)
|
||||
{
|
||||
m_stopPacket = (uint)GetPacketForBytePosition(Layers[(Layers.Length - 1) - DiscardLevel].End);
|
||||
m_stopPacket = (uint)GetPacketForBytePosition(m_layers[(m_layers.Length - 1) - DiscardLevel].End);
|
||||
//I don't know why, but the viewer seems to expect the final packet if the file
|
||||
//is just one packet bigger.
|
||||
if (TexturePacketCount() == m_stopPacket + 1)
|
||||
|
@ -208,7 +240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
private bool SendFirstPacket(LLClientView client)
|
||||
private bool SendFirstPacket(IClientAPI client)
|
||||
{
|
||||
if (client == null)
|
||||
return false;
|
||||
|
@ -243,7 +275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
return false;
|
||||
}
|
||||
|
||||
private bool SendPacket(LLClientView client)
|
||||
private bool SendPacket(IClientAPI client)
|
||||
{
|
||||
if (client == null)
|
||||
return false;
|
||||
|
@ -328,20 +360,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
if (m_currentPacket == 0)
|
||||
return 0;
|
||||
|
||||
if (m_currentPacket == 1)
|
||||
return FIRST_PACKET_SIZE;
|
||||
|
||||
int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE;
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
result = FIRST_PACKET_SIZE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers)
|
||||
{
|
||||
Layers = layers;
|
||||
m_layers = layers;
|
||||
IsDecoded = true;
|
||||
RunUpdate();
|
||||
}
|
||||
|
@ -372,9 +405,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
private void AssetReceived(string id, Object sender, AssetBase asset)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[J2KIMAGE]: Received asset {0} ({1} bytes)", id, asset != null ? asset.Data.Length.ToString() : "n/a");
|
||||
|
||||
UUID assetID = UUID.Zero;
|
||||
if (asset != null)
|
||||
{
|
||||
assetID = asset.FullID;
|
||||
}
|
||||
else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule))
|
||||
{
|
||||
// Unfortunately we need this here, there's no other way.
|
||||
|
@ -392,7 +430,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
|
||||
AssetDataCallback(assetID, asset);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <value>
|
||||
/// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
|
||||
/// </value>
|
||||
protected int m_debugPacketLevel = 0;
|
||||
public int DebugPacketLevel { get; set; }
|
||||
|
||||
#region Events
|
||||
|
||||
|
@ -303,6 +303,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
|
||||
|
||||
/// <summary>
|
||||
/// Handles UDP texture download.
|
||||
/// </summary>
|
||||
public LLImageManager ImageManager { get; private set; }
|
||||
|
||||
private readonly LLUDPServer m_udpServer;
|
||||
private readonly LLUDPClient m_udpClient;
|
||||
private readonly UUID m_sessionId;
|
||||
|
@ -347,7 +352,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
|
||||
protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
|
||||
protected Scene m_scene;
|
||||
protected LLImageManager m_imageManager;
|
||||
protected string m_firstName;
|
||||
protected string m_lastName;
|
||||
protected Thread m_clientThread;
|
||||
|
@ -379,6 +383,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
set { m_startpos = value; }
|
||||
}
|
||||
public UUID AgentId { get { return m_agentId; } }
|
||||
public ISceneAgent SceneAgent { get; private set; }
|
||||
public UUID ActiveGroupId { get { return m_activeGroupID; } }
|
||||
public string ActiveGroupName { get { return m_activeGroupName; } }
|
||||
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
|
||||
|
@ -455,7 +460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
m_assetService = m_scene.RequestModuleInterface<IAssetService>();
|
||||
m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
|
||||
m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
|
||||
ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
|
||||
m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
|
||||
m_agentId = agentId;
|
||||
m_sessionId = sessionId;
|
||||
|
@ -477,11 +482,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
RegisterLocalPacketHandlers();
|
||||
}
|
||||
|
||||
public void SetDebugPacketLevel(int newDebug)
|
||||
{
|
||||
m_debugPacketLevel = newDebug;
|
||||
}
|
||||
|
||||
#region Client Methods
|
||||
|
||||
/// <summary>
|
||||
|
@ -500,8 +500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
IsActive = false;
|
||||
|
||||
// Shutdown the image manager
|
||||
if (m_imageManager != null)
|
||||
m_imageManager.Close();
|
||||
ImageManager.Close();
|
||||
|
||||
// Fire the callback for this connection closing
|
||||
if (OnConnectionClosed != null)
|
||||
|
@ -513,6 +512,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
// Remove ourselves from the scene
|
||||
m_scene.RemoveClient(AgentId, true);
|
||||
SceneAgent = null;
|
||||
|
||||
// We can't reach into other scenes and close the connection
|
||||
// We need to do this over grid communications
|
||||
|
@ -528,7 +528,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
public void Kick(string message)
|
||||
{
|
||||
if (!ChildAgentStatus())
|
||||
if (!SceneAgent.IsChildAgent)
|
||||
{
|
||||
KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
|
||||
kupack.UserInfo.AgentID = AgentId;
|
||||
|
@ -577,8 +577,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <summary>
|
||||
/// Add a handler for the given packet type.
|
||||
/// </summary>
|
||||
/// <remarks>The packet is handled on its own thread. If packets must be handled in the order in which thye
|
||||
/// are received then please us ethe synchronous version of this method.</remarks>
|
||||
/// <remarks>
|
||||
/// The packet is handled on its own thread. If packets must be handled in the order in which they
|
||||
/// are received then please use the synchronous version of this method.
|
||||
/// </remarks>
|
||||
/// <param name="packetType"></param>
|
||||
/// <param name="handler"></param>
|
||||
/// <returns>true if the handler was added. This is currently always the case.</returns>
|
||||
|
@ -692,7 +694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
public virtual void Start()
|
||||
{
|
||||
m_scene.AddNewClient(this, PresenceType.User);
|
||||
SceneAgent = m_scene.AddNewClient(this, PresenceType.User);
|
||||
|
||||
RefreshGroupMembership();
|
||||
}
|
||||
|
@ -1963,8 +1965,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
SendBulkUpdateInventoryItem((InventoryItemBase)node);
|
||||
else if (node is InventoryFolderBase)
|
||||
SendBulkUpdateInventoryFolder((InventoryFolderBase)node);
|
||||
else if (node != null)
|
||||
m_log.ErrorFormat("[CLIENT]: {0} sent unknown inventory node named {1}", Name, node.Name);
|
||||
else
|
||||
m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name);
|
||||
m_log.ErrorFormat("[CLIENT]: {0} sent null inventory node", Name);
|
||||
}
|
||||
|
||||
protected void SendBulkUpdateInventoryItem(InventoryItemBase item)
|
||||
|
@ -2444,7 +2448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="Message"></param>
|
||||
public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
|
||||
{
|
||||
if (!ChildAgentStatus())
|
||||
if (!SceneAgent.IsChildAgent)
|
||||
SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3()));
|
||||
|
||||
//SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
|
||||
|
@ -3592,7 +3596,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// Generate one of the object update packets based on PrimUpdateFlags
|
||||
/// and broadcast the packet to clients
|
||||
/// </summary>
|
||||
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
|
||||
public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
|
||||
{
|
||||
//double priority = m_prioritizer.GetUpdatePriority(this, entity);
|
||||
uint priority = m_prioritizer.GetUpdatePriority(this, entity);
|
||||
|
@ -3625,7 +3629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// </summary>
|
||||
private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
|
||||
{
|
||||
// m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
|
||||
// m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber);
|
||||
|
||||
// Remove the update packet from the list of packets waiting for acknowledgement
|
||||
// because we are requeuing the list of updates. They will be resent in new packets
|
||||
|
@ -3931,15 +3935,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
|
||||
if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
|
||||
{
|
||||
ProcessTextureRequests();
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessTextureRequests()
|
||||
{
|
||||
if (m_imageManager != null)
|
||||
m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
|
||||
ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
|
||||
}
|
||||
|
||||
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
|
||||
|
@ -4744,6 +4740,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
position = presence.OffsetPosition;
|
||||
velocity = presence.Velocity;
|
||||
acceleration = Vector3.Zero;
|
||||
|
||||
// Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
|
||||
// in that direction, even though we don't model this on the server. Implementing this in the future
|
||||
// may improve movement smoothness.
|
||||
// acceleration = new Vector3(1, 0, 0);
|
||||
|
||||
angularVelocity = Vector3.Zero;
|
||||
rotation = presence.Rotation;
|
||||
|
||||
|
@ -4854,8 +4856,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
data.CollisionPlane.ToBytes(objectData, 0);
|
||||
data.OffsetPosition.ToBytes(objectData, 16);
|
||||
//data.Velocity.ToBytes(objectData, 28);
|
||||
//data.Acceleration.ToBytes(objectData, 40);
|
||||
// data.Velocity.ToBytes(objectData, 28);
|
||||
// data.Acceleration.ToBytes(objectData, 40);
|
||||
data.Rotation.ToBytes(objectData, 52);
|
||||
//data.AngularVelocity.ToBytes(objectData, 64);
|
||||
|
||||
|
@ -4880,8 +4882,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
|
||||
update.Text = Utils.EmptyBytes;
|
||||
update.TextColor = new byte[4];
|
||||
|
||||
// Don't send texture anim for avatars - this has no meaning for them.
|
||||
update.TextureAnim = Utils.EmptyBytes;
|
||||
update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
|
||||
|
||||
// Don't send texture entry for avatars here - this is accomplished via the AvatarAppearance packet
|
||||
update.TextureEntry = Utils.EmptyBytes;
|
||||
// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
|
||||
|
||||
update.UpdateFlags = (uint)(
|
||||
PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
|
||||
PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
|
||||
|
@ -5044,14 +5052,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
|
||||
/// </summary>
|
||||
public bool ChildAgentStatus()
|
||||
{
|
||||
return m_scene.PresenceChildStatus(AgentId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
@ -7465,12 +7465,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if ((ImageType)block.Type == ImageType.Baked)
|
||||
args.Priority *= 2.0f;
|
||||
|
||||
// in the end, we null this, so we have to check if it's null
|
||||
if (m_imageManager != null)
|
||||
{
|
||||
m_imageManager.EnqueueReq(args);
|
||||
}
|
||||
ImageManager.EnqueueReq(args);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -10328,6 +10325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack)
|
||||
{
|
||||
GroupRoleMembersRequestPacket groupRoleMembersRequest =
|
||||
|
@ -11588,29 +11586,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// provide your own method.</param>
|
||||
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
|
||||
{
|
||||
if (m_debugPacketLevel > 0)
|
||||
if (DebugPacketLevel > 0)
|
||||
{
|
||||
bool logPacket = true;
|
||||
|
||||
if (m_debugPacketLevel <= 255
|
||||
if (DebugPacketLevel <= 255
|
||||
&& (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage))
|
||||
logPacket = false;
|
||||
|
||||
if (m_debugPacketLevel <= 200
|
||||
if (DebugPacketLevel <= 200
|
||||
&& (packet.Type == PacketType.ImagePacket
|
||||
|| packet.Type == PacketType.ImageData
|
||||
|| packet.Type == PacketType.LayerData
|
||||
|| packet.Type == PacketType.CoarseLocationUpdate))
|
||||
logPacket = false;
|
||||
|
||||
if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
|
||||
if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
|
||||
logPacket = false;
|
||||
|
||||
if (m_debugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
|
||||
if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
|
||||
logPacket = false;
|
||||
|
||||
if (logPacket)
|
||||
m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
|
||||
m_log.DebugFormat(
|
||||
"[CLIENT]: PACKET OUT to {0} ({1}) in {2} - {3}",
|
||||
Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type);
|
||||
}
|
||||
|
||||
m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
|
||||
|
@ -11651,21 +11651,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="Pack">OpenMetaverse.packet</param>
|
||||
public void ProcessInPacket(Packet packet)
|
||||
{
|
||||
if (m_debugPacketLevel > 0)
|
||||
if (DebugPacketLevel > 0)
|
||||
{
|
||||
bool outputPacket = true;
|
||||
bool logPacket = true;
|
||||
|
||||
if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
|
||||
outputPacket = false;
|
||||
if (DebugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
|
||||
logPacket = false;
|
||||
|
||||
if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
|
||||
outputPacket = false;
|
||||
if (DebugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
|
||||
logPacket = false;
|
||||
|
||||
if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
|
||||
outputPacket = false;
|
||||
if (DebugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
|
||||
logPacket = false;
|
||||
|
||||
if (outputPacket)
|
||||
m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
|
||||
if (logPacket)
|
||||
m_log.DebugFormat(
|
||||
"[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}",
|
||||
Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type);
|
||||
}
|
||||
|
||||
if (!ProcessPacketMethod(packet))
|
||||
|
|
|
@ -39,6 +39,9 @@ using log4net;
|
|||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles UDP texture requests.
|
||||
/// </summary>
|
||||
public class LLImageManager
|
||||
{
|
||||
private sealed class J2KImageComparer : IComparer<J2KImage>
|
||||
|
@ -52,18 +55,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private bool m_shuttingdown;
|
||||
private AssetBase m_missingImage;
|
||||
private LLClientView m_client; //Client we're assigned to
|
||||
private IAssetService m_assetCache; //Asset Cache
|
||||
private IJ2KDecoder m_j2kDecodeModule; //Our J2K module
|
||||
private IAssetService m_assetCache;
|
||||
private IJ2KDecoder m_j2kDecodeModule;
|
||||
|
||||
/// <summary>
|
||||
/// Priority queue for determining which image to send first.
|
||||
/// </summary>
|
||||
private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer());
|
||||
|
||||
/// <summary>
|
||||
/// Used to control thread access to the priority queue.
|
||||
/// </summary>
|
||||
private object m_syncRoot = new object();
|
||||
|
||||
public LLClientView Client { get { return m_client; } }
|
||||
/// <summary>
|
||||
/// Client served by this image manager
|
||||
/// </summary>
|
||||
public IClientAPI Client { get; private set; }
|
||||
|
||||
public AssetBase MissingImage { get { return m_missingImage; } }
|
||||
|
||||
public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule)
|
||||
public LLImageManager(IClientAPI client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule)
|
||||
{
|
||||
m_client = client;
|
||||
Client = client;
|
||||
m_assetCache = pAssetCache;
|
||||
|
||||
if (pAssetCache != null)
|
||||
|
@ -81,7 +95,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="newRequest"></param>
|
||||
public void EnqueueReq(TextureRequestArgs newRequest)
|
||||
{
|
||||
//Make sure we're not shutting down..
|
||||
if (!m_shuttingdown)
|
||||
{
|
||||
J2KImage imgrequest;
|
||||
|
@ -96,19 +109,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
//m_log.Debug("[TEX]: (CAN) ID=" + newRequest.RequestedAssetID);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
lock (m_syncRoot)
|
||||
m_priorityQueue.Delete(imgrequest.PriorityQueueHandle);
|
||||
m_priorityQueue.Delete(imgrequest.PriorityQueueHandle);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
else
|
||||
{
|
||||
//m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}",
|
||||
// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
|
||||
// m_log.DebugFormat(
|
||||
// "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}",
|
||||
// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name);
|
||||
|
||||
//Check the packet sequence to make sure this isn't older than
|
||||
// m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}",
|
||||
// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
|
||||
|
||||
//Check the packet sequence to make sure this isn't older than
|
||||
//one we've already received
|
||||
if (newRequest.requestSequence > imgrequest.LastSequence)
|
||||
{
|
||||
|
@ -123,11 +140,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
//Update the requested priority
|
||||
imgrequest.Priority = newRequest.Priority;
|
||||
|
||||
UpdateImageInQueue(imgrequest);
|
||||
|
||||
//Run an update
|
||||
imgrequest.RunUpdate();
|
||||
|
||||
// J2KImage imgrequest2 = new J2KImage(this);
|
||||
// imgrequest2.J2KDecoder = m_j2kDecodeModule;
|
||||
// imgrequest2.AssetService = m_assetCache;
|
||||
// imgrequest2.AgentID = m_client.AgentId;
|
||||
// imgrequest2.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>();
|
||||
// imgrequest2.DiscardLevel = newRequest.DiscardLevel;
|
||||
// imgrequest2.StartPacket = Math.Max(1, newRequest.PacketNumber);
|
||||
// imgrequest2.Priority = newRequest.Priority;
|
||||
// imgrequest2.TextureID = newRequest.RequestedAssetID;
|
||||
// imgrequest2.Priority = newRequest.Priority;
|
||||
//
|
||||
// //Add this download to the priority queue
|
||||
// AddImageToQueue(imgrequest2);
|
||||
//
|
||||
// imgrequest2.RunUpdate();
|
||||
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[LL IMAGE MANAGER]: Ignoring duplicate of existing request for {0} (sequence {1}) from {2} as its request sequence {3} is not greater",
|
||||
// newRequest.RequestedAssetID, imgrequest.LastSequence, m_client.Name, newRequest.requestSequence);
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -139,14 +179,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
else
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[LL IMAGE MANAGER]: Received request for {0}, start packet {1} from {2}",
|
||||
// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name);
|
||||
|
||||
//m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}",
|
||||
// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
|
||||
|
||||
imgrequest = new J2KImage(this);
|
||||
imgrequest.J2KDecoder = m_j2kDecodeModule;
|
||||
imgrequest.AssetService = m_assetCache;
|
||||
imgrequest.AgentID = m_client.AgentId;
|
||||
imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>();
|
||||
imgrequest.AgentID = Client.AgentId;
|
||||
imgrequest.InventoryAccessModule = Client.Scene.RequestModuleInterface<IInventoryAccessModule>();
|
||||
imgrequest.DiscardLevel = newRequest.DiscardLevel;
|
||||
imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber);
|
||||
imgrequest.Priority = newRequest.Priority;
|
||||
|
@ -156,7 +200,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
//Add this download to the priority queue
|
||||
AddImageToQueue(imgrequest);
|
||||
|
||||
//Run an update
|
||||
imgrequest.RunUpdate();
|
||||
}
|
||||
}
|
||||
|
@ -173,12 +216,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
// If null was returned, the texture priority queue is currently empty
|
||||
if (image == null)
|
||||
return false;
|
||||
break;
|
||||
|
||||
if (image.IsDecoded)
|
||||
{
|
||||
int sent;
|
||||
bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent);
|
||||
bool imageDone = image.SendPackets(Client, packetsToSend - packetsSent, out sent);
|
||||
packetsSent += sent;
|
||||
|
||||
// If the send is complete, destroy any knowledge of this transfer
|
||||
|
@ -191,10 +234,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// written. Undecoded textures should not be going into the priority
|
||||
// queue, because a high priority undecoded texture will clog up the
|
||||
// pipeline for a client
|
||||
return true;
|
||||
// m_log.DebugFormat(
|
||||
// "[LL IMAGE MANAGER]: Exiting image queue processing early on encountering undecoded image {0}",
|
||||
// image.TextureID);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if (packetsSent != 0)
|
||||
// m_log.DebugFormat("[LL IMAGE MANAGER]: Processed {0} packets from image queue", packetsSent);
|
||||
|
||||
return m_priorityQueue.Count > 0;
|
||||
}
|
||||
|
||||
|
@ -206,9 +256,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_shuttingdown = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the image queue.
|
||||
/// </summary>
|
||||
/// <returns>The number of requests cleared.</returns>
|
||||
public int ClearImageQueue()
|
||||
{
|
||||
int requestsDeleted;
|
||||
|
||||
lock (m_priorityQueue)
|
||||
{
|
||||
requestsDeleted = m_priorityQueue.Count;
|
||||
|
||||
// Surprisingly, there doesn't seem to be a clear method at this time.
|
||||
while (!m_priorityQueue.IsEmpty)
|
||||
m_priorityQueue.DeleteMax();
|
||||
}
|
||||
|
||||
return requestsDeleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array containing all the images in the queue.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public J2KImage[] GetImages()
|
||||
{
|
||||
lock (m_priorityQueue)
|
||||
return m_priorityQueue.ToArray();
|
||||
}
|
||||
|
||||
#region Priority Queue Helpers
|
||||
|
||||
J2KImage GetHighestPriorityImage()
|
||||
private J2KImage GetHighestPriorityImage()
|
||||
{
|
||||
J2KImage image = null;
|
||||
|
||||
|
@ -216,34 +296,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
if (m_priorityQueue.Count > 0)
|
||||
{
|
||||
try { image = m_priorityQueue.FindMax(); }
|
||||
try
|
||||
{
|
||||
image = m_priorityQueue.FindMax();
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
void AddImageToQueue(J2KImage image)
|
||||
private void AddImageToQueue(J2KImage image)
|
||||
{
|
||||
image.PriorityQueueHandle = null;
|
||||
|
||||
lock (m_syncRoot)
|
||||
try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); }
|
||||
{
|
||||
try
|
||||
{
|
||||
m_priorityQueue.Add(ref image.PriorityQueueHandle, image);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveImageFromQueue(J2KImage image)
|
||||
{
|
||||
lock (m_syncRoot)
|
||||
try { m_priorityQueue.Delete(image.PriorityQueueHandle); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
void UpdateImageInQueue(J2KImage image)
|
||||
private void RemoveImageFromQueue(J2KImage image)
|
||||
{
|
||||
lock (m_syncRoot)
|
||||
{
|
||||
try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); }
|
||||
try
|
||||
{
|
||||
m_priorityQueue.Delete(image.PriorityQueueHandle);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateImageInQueue(J2KImage image)
|
||||
{
|
||||
lock (m_syncRoot)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_priorityQueue.Replace(image.PriorityQueueHandle, image);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
image.PriorityQueueHandle = null;
|
||||
|
@ -254,4 +350,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
#endregion Priority Queue Helpers
|
||||
}
|
||||
}
|
||||
}
|
|
@ -169,7 +169,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="circuitCode">Circuit code for this connection</param>
|
||||
/// <param name="agentID">AgentID for the connected agent</param>
|
||||
/// <param name="remoteEndPoint">Remote endpoint for this connection</param>
|
||||
public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
|
||||
/// <param name="defaultRTO">
|
||||
/// Default retransmission timeout for unacked packets. The RTO will never drop
|
||||
/// beyond this number.
|
||||
/// </param>
|
||||
/// <param name="maxRTO">
|
||||
/// The maximum retransmission timeout for unacked packets. The RTO will never exceed this number.
|
||||
/// </param>
|
||||
public LLUDPClient(
|
||||
LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID,
|
||||
IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
|
||||
{
|
||||
AgentID = agentID;
|
||||
RemoteEndPoint = remoteEndPoint;
|
||||
|
@ -197,7 +206,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
|
||||
}
|
||||
|
||||
// Default the retransmission timeout to three seconds
|
||||
// Default the retransmission timeout to one second
|
||||
RTO = m_defaultRTO;
|
||||
|
||||
// Initialize this to a sane value to prevent early disconnects
|
||||
|
@ -262,9 +271,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <summary>
|
||||
/// Return statistics information about client packet queues.
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// FIXME: This should really be done in a more sensible manner rather than sending back a formatted string.
|
||||
///
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public string GetStats()
|
||||
{
|
||||
|
@ -583,8 +592,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
RTO = rto;
|
||||
|
||||
//m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
|
||||
// RTTVAR + " based on new RTT of " + r + "ms");
|
||||
//if (RTO != rto)
|
||||
// m_log.Debug("[LLUDPCLIENT]: Setting RTO to " + RTO + "ms from " + rto + "ms with an RTTVAR of " +
|
||||
//RTTVAR + " based on new RTT of " + r + "ms");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -606,8 +616,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// Does an early check to see if this queue empty callback is already
|
||||
/// running, then asynchronously firing the event
|
||||
/// </summary>
|
||||
/// <param name="throttleIndex">Throttle category to fire the callback
|
||||
/// for</param>
|
||||
/// <param name="categories">Throttle categories to fire the callback for</param>
|
||||
private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
|
||||
{
|
||||
if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
|
||||
|
@ -694,4 +703,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -324,7 +324,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="packet"></param>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="allowSplitting"></param>
|
||||
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
|
||||
/// <param name="method">
|
||||
/// The method to call if the packet is not acked by the client. If null, then a standard
|
||||
/// resend of the packet is done.
|
||||
/// </param>
|
||||
public virtual void SendPacket(
|
||||
LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
|
||||
{
|
||||
// CoarseLocationUpdate packets cannot be split in an automated way
|
||||
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
|
||||
|
@ -357,8 +362,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="udpClient"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="category"></param>
|
||||
public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
|
||||
/// <param name="category"></param>
|
||||
/// <param name="method">
|
||||
/// The method to call if the packet is not acked by the client. If null, then a standard
|
||||
/// resend of the packet is done.
|
||||
/// </param>
|
||||
public void SendPacketData(
|
||||
LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
|
||||
{
|
||||
int dataLength = data.Length;
|
||||
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
|
||||
|
@ -482,6 +492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
|
||||
{
|
||||
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
|
||||
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
|
||||
|
||||
RemoveClient(udpClient);
|
||||
return;
|
||||
|
@ -601,11 +612,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
|
||||
}
|
||||
|
||||
protected override void PacketReceived(UDPPacketBuffer buffer)
|
||||
public override void PacketReceived(UDPPacketBuffer buffer)
|
||||
{
|
||||
// Debugging/Profiling
|
||||
//try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
|
||||
//catch (Exception) { }
|
||||
// m_log.DebugFormat(
|
||||
// "[LLUDPSERVER]: Packet received from {0} in {1}", buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||
|
||||
LLUDPClient udpClient = null;
|
||||
Packet packet = null;
|
||||
|
@ -615,7 +628,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
#region Decoding
|
||||
|
||||
if (buffer.DataLength < 7)
|
||||
{
|
||||
// m_log.WarnFormat(
|
||||
// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
|
||||
// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||
|
||||
return; // Drop undersizd packet
|
||||
}
|
||||
|
||||
int headerLen = 7;
|
||||
if (buffer.Data[6] == 0xFF)
|
||||
|
@ -627,7 +646,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
|
||||
if (buffer.DataLength < headerLen)
|
||||
{
|
||||
// m_log.WarnFormat(
|
||||
// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
|
||||
// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||
|
||||
return; // Malformed header
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -640,6 +665,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
// m_log.WarnFormat(
|
||||
// "[LLUDPSERVER]: Dropping short packet received from {0} in {1}",
|
||||
// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||
|
||||
return; // Drop short packet
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -877,23 +906,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// DateTime startTime = DateTime.Now;
|
||||
object[] array = (object[])o;
|
||||
UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
|
||||
UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1];
|
||||
UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
|
||||
|
||||
m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint);
|
||||
|
||||
IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
|
||||
|
||||
// Begin the process of adding the client to the simulator
|
||||
AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
|
||||
|
||||
// Send ack
|
||||
SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
|
||||
AuthenticateResponse sessionInfo;
|
||||
if (IsClientAuthorized(uccp, out sessionInfo))
|
||||
{
|
||||
// Begin the process of adding the client to the simulator
|
||||
IClientAPI client
|
||||
= AddClient(
|
||||
uccp.CircuitCode.Code,
|
||||
uccp.CircuitCode.ID,
|
||||
uccp.CircuitCode.SessionID,
|
||||
remoteEndPoint,
|
||||
sessionInfo);
|
||||
|
||||
// Send ack straight away to let the viewer know that the connection is active.
|
||||
// The client will be null if it already exists (e.g. if on a region crossing the client sends a use
|
||||
// circuit code to the existing child agent. This is not particularly obvious.
|
||||
SendAckImmediate(remoteEndPoint, uccp.Header.Sequence);
|
||||
|
||||
// We only want to send initial data to new clients, not ones which are being converted from child to root.
|
||||
if (client != null)
|
||||
client.SceneAgent.SendInitialDataToMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't create clients for unauthorized requesters.
|
||||
m_log.WarnFormat(
|
||||
"[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
|
||||
uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint);
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
|
||||
// buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send an ack immediately to the given endpoint.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// FIXME: Might be possible to use SendPacketData() like everything else, but this will require refactoring so
|
||||
/// that we can obtain the UDPClient easily at this point.
|
||||
/// </remarks>
|
||||
/// <param name="remoteEndpoint"></param>
|
||||
/// <param name="sequenceNumber"></param>
|
||||
private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
|
||||
{
|
||||
PacketAckPacket ack = new PacketAckPacket();
|
||||
|
@ -902,6 +963,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
ack.Packets[0] = new PacketAckPacket.PacketsBlock();
|
||||
ack.Packets[0].ID = sequenceNumber;
|
||||
|
||||
SendAckImmediate(remoteEndpoint, ack);
|
||||
}
|
||||
|
||||
public virtual void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack)
|
||||
{
|
||||
byte[] packetData = ack.ToBytes();
|
||||
int length = packetData.Length;
|
||||
|
||||
|
@ -923,63 +989,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
return sessionInfo.Authorised;
|
||||
}
|
||||
|
||||
private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint)
|
||||
/// <summary>
|
||||
/// Add a client.
|
||||
/// </summary>
|
||||
/// <param name="circuitCode"></param>
|
||||
/// <param name="agentID"></param>
|
||||
/// <param name="sessionID"></param>
|
||||
/// <param name="remoteEndPoint"></param>
|
||||
/// <param name="sessionInfo"></param>
|
||||
/// <returns>The client if it was added. Null if the client already existed.</returns>
|
||||
protected virtual IClientAPI AddClient(
|
||||
uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
|
||||
{
|
||||
UUID agentID = useCircuitCode.CircuitCode.ID;
|
||||
UUID sessionID = useCircuitCode.CircuitCode.SessionID;
|
||||
uint circuitCode = useCircuitCode.CircuitCode.Code;
|
||||
IClientAPI client = null;
|
||||
|
||||
if (m_scene.RegionStatus != RegionStatus.SlaveScene)
|
||||
{
|
||||
AuthenticateResponse sessionInfo;
|
||||
if (IsClientAuthorized(useCircuitCode, out sessionInfo))
|
||||
{
|
||||
AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't create circuits for unauthorized clients
|
||||
m_log.WarnFormat(
|
||||
"[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
|
||||
useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slave regions don't accept new clients
|
||||
m_log.Debug("[LLUDPSERVER]: Slave region " + m_scene.RegionInfo.RegionName + " ignoring UseCircuitCode packet");
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
|
||||
{
|
||||
// In priciple there shouldn't be more than one thread here, ever.
|
||||
// But in case that happens, we need to synchronize this piece of code
|
||||
// because it's too important
|
||||
lock (this)
|
||||
{
|
||||
IClientAPI existingClient;
|
||||
|
||||
if (!m_scene.TryGetClient(agentID, out existingClient))
|
||||
if (!m_scene.TryGetClient(agentID, out client))
|
||||
{
|
||||
// Create the LLUDPClient
|
||||
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
|
||||
// Create the LLClientView
|
||||
LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
|
||||
|
||||
client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
|
||||
client.OnLogout += LogoutHandler;
|
||||
|
||||
client.DisableFacelights = m_disableFacelights;
|
||||
((LLClientView)client).DisableFacelights = m_disableFacelights;
|
||||
|
||||
// Start the IClientAPI
|
||||
client.Start();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
|
||||
existingClient.AgentId, remoteEndPoint, circuitCode);
|
||||
}
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
private void RemoveClient(LLUDPClient udpClient)
|
||||
|
@ -1108,7 +1150,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Watchdog.RemoveThread();
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace OpenMetaverse
|
|||
/// This method is called when an incoming packet is received
|
||||
/// </summary>
|
||||
/// <param name="buffer">Incoming packet buffer</param>
|
||||
protected abstract void PacketReceived(UDPPacketBuffer buffer);
|
||||
public abstract void PacketReceived(UDPPacketBuffer buffer);
|
||||
|
||||
/// <summary>UDP port to bind to in server mode</summary>
|
||||
protected int m_udpPort;
|
||||
|
|
|
@ -25,14 +25,15 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using log4net.Config;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.SyntaxHelpers;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
|
@ -44,89 +45,92 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
|||
[TestFixture]
|
||||
public class BasicCircuitTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Init()
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureInit()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlConfigurator.Configure();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// I don't care, just leave log4net off
|
||||
}
|
||||
// Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
|
||||
Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a client for testing
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="testLLUDPServer"></param>
|
||||
/// <param name="testPacketServer"></param>
|
||||
/// <param name="acm">Agent circuit manager used in setting up the stack</param>
|
||||
protected void SetupStack(
|
||||
IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
|
||||
out AgentCircuitManager acm)
|
||||
{
|
||||
IConfigSource configSource = new IniConfigSource();
|
||||
ClientStackUserSettings userSettings = new ClientStackUserSettings();
|
||||
testLLUDPServer = new TestLLUDPServer();
|
||||
acm = new AgentCircuitManager();
|
||||
|
||||
uint port = 666;
|
||||
testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
|
||||
testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
|
||||
testLLUDPServer.LocalScene = scene;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set up a client for tests which aren't concerned with this process itself and where only one client is being
|
||||
/// tested
|
||||
/// </summary>
|
||||
/// <param name="circuitCode"></param>
|
||||
/// <param name="epSender"></param>
|
||||
/// <param name="testLLUDPServer"></param>
|
||||
/// <param name="acm"></param>
|
||||
protected void AddClient(
|
||||
uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
|
||||
{
|
||||
UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
|
||||
UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
|
||||
|
||||
AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set up a client for tests which aren't concerned with this process itself
|
||||
/// </summary>
|
||||
/// <param name="circuitCode"></param>
|
||||
/// <param name="epSender"></param>
|
||||
/// <param name="agentId"></param>
|
||||
/// <param name="sessionId"></param>
|
||||
/// <param name="testLLUDPServer"></param>
|
||||
/// <param name="acm"></param>
|
||||
protected void AddClient(
|
||||
uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
|
||||
TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
|
||||
{
|
||||
AgentCircuitData acd = new AgentCircuitData();
|
||||
acd.AgentID = agentId;
|
||||
acd.SessionID = sessionId;
|
||||
|
||||
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
|
||||
|
||||
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
= new UseCircuitCodePacket.CircuitCodeBlock();
|
||||
uccpCcBlock.Code = circuitCode;
|
||||
uccpCcBlock.ID = agentId;
|
||||
uccpCcBlock.SessionID = sessionId;
|
||||
uccp.CircuitCode = uccpCcBlock;
|
||||
|
||||
acm.AddNewCircuit(circuitCode, acd);
|
||||
|
||||
testLLUDPServer.LoadReceive(uccp, epSender);
|
||||
testLLUDPServer.ReceiveData(null);
|
||||
[TestFixtureTearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
// We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
|
||||
// threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
|
||||
// tests really shouldn't).
|
||||
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Add a client for testing
|
||||
// /// </summary>
|
||||
// /// <param name="scene"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="testPacketServer"></param>
|
||||
// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
|
||||
// protected void SetupStack(
|
||||
// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
|
||||
// out AgentCircuitManager acm)
|
||||
// {
|
||||
// IConfigSource configSource = new IniConfigSource();
|
||||
// ClientStackUserSettings userSettings = new ClientStackUserSettings();
|
||||
// testLLUDPServer = new TestLLUDPServer();
|
||||
// acm = new AgentCircuitManager();
|
||||
//
|
||||
// uint port = 666;
|
||||
// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
|
||||
// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
|
||||
// testLLUDPServer.LocalScene = scene;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
|
||||
// /// tested
|
||||
// /// </summary>
|
||||
// /// <param name="circuitCode"></param>
|
||||
// /// <param name="epSender"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="acm"></param>
|
||||
// protected void AddClient(
|
||||
// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
|
||||
// {
|
||||
// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
|
||||
// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
|
||||
//
|
||||
// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Set up a client for tests which aren't concerned with this process itself
|
||||
// /// </summary>
|
||||
// /// <param name="circuitCode"></param>
|
||||
// /// <param name="epSender"></param>
|
||||
// /// <param name="agentId"></param>
|
||||
// /// <param name="sessionId"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="acm"></param>
|
||||
// protected void AddClient(
|
||||
// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
|
||||
// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
|
||||
// {
|
||||
// AgentCircuitData acd = new AgentCircuitData();
|
||||
// acd.AgentID = agentId;
|
||||
// acd.SessionID = sessionId;
|
||||
//
|
||||
// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
|
||||
//
|
||||
// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
// = new UseCircuitCodePacket.CircuitCodeBlock();
|
||||
// uccpCcBlock.Code = circuitCode;
|
||||
// uccpCcBlock.ID = agentId;
|
||||
// uccpCcBlock.SessionID = sessionId;
|
||||
// uccp.CircuitCode = uccpCcBlock;
|
||||
//
|
||||
// acm.AddNewCircuit(circuitCode, acd);
|
||||
//
|
||||
// testLLUDPServer.LoadReceive(uccp, epSender);
|
||||
// testLLUDPServer.ReceiveData(null);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Build an object name packet for test purposes
|
||||
|
@ -148,152 +152,167 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
|||
/// <summary>
|
||||
/// Test adding a client to the stack
|
||||
/// </summary>
|
||||
[Test, LongRunning]
|
||||
[Test]
|
||||
public void TestAddClient()
|
||||
{
|
||||
TestHelper.InMethod();
|
||||
TestHelpers.InMethod();
|
||||
// XmlConfigurator.Configure();
|
||||
|
||||
TestScene scene = SceneHelpers.SetupScene();
|
||||
uint myCircuitCode = 123456;
|
||||
UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
|
||||
UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
|
||||
|
||||
TestLLUDPServer testLLUDPServer;
|
||||
TestLLPacketServer testLLPacketServer;
|
||||
AgentCircuitManager acm;
|
||||
SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
|
||||
AgentCircuitData acd = new AgentCircuitData();
|
||||
acd.AgentID = myAgentUuid;
|
||||
acd.SessionID = mySessionUuid;
|
||||
|
||||
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
|
||||
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
|
||||
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
|
||||
|
||||
uint port = 0;
|
||||
AgentCircuitManager acm = scene.AuthenticateHandler;
|
||||
|
||||
TestLLUDPServer llUdpServer
|
||||
= new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
|
||||
llUdpServer.AddScene(scene);
|
||||
|
||||
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
|
||||
|
||||
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
|
||||
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
= new UseCircuitCodePacket.CircuitCodeBlock();
|
||||
uccpCcBlock.Code = myCircuitCode;
|
||||
uccpCcBlock.ID = myAgentUuid;
|
||||
uccpCcBlock.SessionID = mySessionUuid;
|
||||
uccp.CircuitCode = uccpCcBlock;
|
||||
|
||||
EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
|
||||
|
||||
testLLUDPServer.LoadReceive(uccp, testEp);
|
||||
testLLUDPServer.ReceiveData(null);
|
||||
|
||||
// Circuit shouildn't exist since the circuit manager doesn't know about this circuit for authentication yet
|
||||
Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode));
|
||||
|
||||
|
||||
byte[] uccpBytes = uccp.ToBytes();
|
||||
UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
|
||||
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
|
||||
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
|
||||
|
||||
llUdpServer.PacketReceived(upb);
|
||||
|
||||
// Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
|
||||
Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null);
|
||||
|
||||
AgentCircuitData acd = new AgentCircuitData();
|
||||
acd.AgentID = myAgentUuid;
|
||||
acd.SessionID = mySessionUuid;
|
||||
|
||||
acm.AddNewCircuit(myCircuitCode, acd);
|
||||
|
||||
testLLUDPServer.LoadReceive(uccp, testEp);
|
||||
testLLUDPServer.ReceiveData(null);
|
||||
|
||||
|
||||
llUdpServer.PacketReceived(upb);
|
||||
|
||||
// Should succeed now
|
||||
Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode));
|
||||
Assert.IsFalse(testLLUDPServer.HasCircuit(101));
|
||||
ScenePresence sp = scene.GetScenePresence(myAgentUuid);
|
||||
Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
|
||||
|
||||
Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1));
|
||||
|
||||
Packet packet = llUdpServer.PacketsSent[0];
|
||||
Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
|
||||
|
||||
PacketAckPacket ackPacket = packet as PacketAckPacket;
|
||||
Assert.That(ackPacket.Packets.Length, Is.EqualTo(1));
|
||||
Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test removing a client from the stack
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveClient()
|
||||
{
|
||||
TestHelper.InMethod();
|
||||
|
||||
uint myCircuitCode = 123457;
|
||||
|
||||
TestLLUDPServer testLLUDPServer;
|
||||
TestLLPacketServer testLLPacketServer;
|
||||
AgentCircuitManager acm;
|
||||
SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
AddClient(myCircuitCode, new IPEndPoint(IPAddress.Loopback, 1000), testLLUDPServer, acm);
|
||||
|
||||
testLLUDPServer.RemoveClientCircuit(myCircuitCode);
|
||||
Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode));
|
||||
|
||||
// Check that removing a non-existant circuit doesn't have any bad effects
|
||||
testLLUDPServer.RemoveClientCircuit(101);
|
||||
Assert.IsFalse(testLLUDPServer.HasCircuit(101));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure that the client stack reacts okay to malformed packets
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMalformedPacketSend()
|
||||
{
|
||||
TestHelper.InMethod();
|
||||
|
||||
uint myCircuitCode = 123458;
|
||||
EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 1001);
|
||||
MockScene scene = new MockScene();
|
||||
|
||||
TestLLUDPServer testLLUDPServer;
|
||||
TestLLPacketServer testLLPacketServer;
|
||||
AgentCircuitManager acm;
|
||||
SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
AddClient(myCircuitCode, testEp, testLLUDPServer, acm);
|
||||
|
||||
byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 };
|
||||
|
||||
// Send two garbled 'packets' in succession
|
||||
testLLUDPServer.LoadReceive(data, testEp);
|
||||
testLLUDPServer.LoadReceive(data, testEp);
|
||||
testLLUDPServer.ReceiveData(null);
|
||||
|
||||
// Check that we are still here
|
||||
Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode));
|
||||
Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(0));
|
||||
|
||||
// Check that sending a valid packet to same circuit still succeeds
|
||||
Assert.That(scene.ObjectNameCallsReceived, Is.EqualTo(0));
|
||||
|
||||
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "helloooo"), testEp);
|
||||
testLLUDPServer.ReceiveData(null);
|
||||
|
||||
Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(1));
|
||||
Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that the stack continues to work even if some client has caused a
|
||||
/// SocketException on Socket.BeginReceive()
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestExceptionOnBeginReceive()
|
||||
{
|
||||
TestHelper.InMethod();
|
||||
|
||||
MockScene scene = new MockScene();
|
||||
|
||||
uint circuitCodeA = 130000;
|
||||
EndPoint epA = new IPEndPoint(IPAddress.Loopback, 1300);
|
||||
UUID agentIdA = UUID.Parse("00000000-0000-0000-0000-000000001300");
|
||||
UUID sessionIdA = UUID.Parse("00000000-0000-0000-0000-000000002300");
|
||||
|
||||
uint circuitCodeB = 130001;
|
||||
EndPoint epB = new IPEndPoint(IPAddress.Loopback, 1301);
|
||||
UUID agentIdB = UUID.Parse("00000000-0000-0000-0000-000000001301");
|
||||
UUID sessionIdB = UUID.Parse("00000000-0000-0000-0000-000000002301");
|
||||
|
||||
TestLLUDPServer testLLUDPServer;
|
||||
TestLLPacketServer testLLPacketServer;
|
||||
AgentCircuitManager acm;
|
||||
SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
AddClient(circuitCodeA, epA, agentIdA, sessionIdA, testLLUDPServer, acm);
|
||||
AddClient(circuitCodeB, epB, agentIdB, sessionIdB, testLLUDPServer, acm);
|
||||
|
||||
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet1"), epA);
|
||||
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet2"), epB);
|
||||
testLLUDPServer.LoadReceiveWithBeginException(epA);
|
||||
testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(2, "packet3"), epB);
|
||||
testLLUDPServer.ReceiveData(null);
|
||||
|
||||
Assert.IsFalse(testLLUDPServer.HasCircuit(circuitCodeA));
|
||||
|
||||
Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(3));
|
||||
Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(3));
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Test removing a client from the stack
|
||||
// /// </summary>
|
||||
// [Test]
|
||||
// public void TestRemoveClient()
|
||||
// {
|
||||
// TestHelper.InMethod();
|
||||
//
|
||||
// uint myCircuitCode = 123457;
|
||||
//
|
||||
// TestLLUDPServer testLLUDPServer;
|
||||
// TestLLPacketServer testLLPacketServer;
|
||||
// AgentCircuitManager acm;
|
||||
// SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
// AddClient(myCircuitCode, new IPEndPoint(IPAddress.Loopback, 1000), testLLUDPServer, acm);
|
||||
//
|
||||
// testLLUDPServer.RemoveClientCircuit(myCircuitCode);
|
||||
// Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode));
|
||||
//
|
||||
// // Check that removing a non-existant circuit doesn't have any bad effects
|
||||
// testLLUDPServer.RemoveClientCircuit(101);
|
||||
// Assert.IsFalse(testLLUDPServer.HasCircuit(101));
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Make sure that the client stack reacts okay to malformed packets
|
||||
// /// </summary>
|
||||
// [Test]
|
||||
// public void TestMalformedPacketSend()
|
||||
// {
|
||||
// TestHelper.InMethod();
|
||||
//
|
||||
// uint myCircuitCode = 123458;
|
||||
// EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 1001);
|
||||
// MockScene scene = new MockScene();
|
||||
//
|
||||
// TestLLUDPServer testLLUDPServer;
|
||||
// TestLLPacketServer testLLPacketServer;
|
||||
// AgentCircuitManager acm;
|
||||
// SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
// AddClient(myCircuitCode, testEp, testLLUDPServer, acm);
|
||||
//
|
||||
// byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 };
|
||||
//
|
||||
// // Send two garbled 'packets' in succession
|
||||
// testLLUDPServer.LoadReceive(data, testEp);
|
||||
// testLLUDPServer.LoadReceive(data, testEp);
|
||||
// testLLUDPServer.ReceiveData(null);
|
||||
//
|
||||
// // Check that we are still here
|
||||
// Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode));
|
||||
// Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(0));
|
||||
//
|
||||
// // Check that sending a valid packet to same circuit still succeeds
|
||||
// Assert.That(scene.ObjectNameCallsReceived, Is.EqualTo(0));
|
||||
//
|
||||
// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "helloooo"), testEp);
|
||||
// testLLUDPServer.ReceiveData(null);
|
||||
//
|
||||
// Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(1));
|
||||
// Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(1));
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Test that the stack continues to work even if some client has caused a
|
||||
// /// SocketException on Socket.BeginReceive()
|
||||
// /// </summary>
|
||||
// [Test]
|
||||
// public void TestExceptionOnBeginReceive()
|
||||
// {
|
||||
// TestHelper.InMethod();
|
||||
//
|
||||
// MockScene scene = new MockScene();
|
||||
//
|
||||
// uint circuitCodeA = 130000;
|
||||
// EndPoint epA = new IPEndPoint(IPAddress.Loopback, 1300);
|
||||
// UUID agentIdA = UUID.Parse("00000000-0000-0000-0000-000000001300");
|
||||
// UUID sessionIdA = UUID.Parse("00000000-0000-0000-0000-000000002300");
|
||||
//
|
||||
// uint circuitCodeB = 130001;
|
||||
// EndPoint epB = new IPEndPoint(IPAddress.Loopback, 1301);
|
||||
// UUID agentIdB = UUID.Parse("00000000-0000-0000-0000-000000001301");
|
||||
// UUID sessionIdB = UUID.Parse("00000000-0000-0000-0000-000000002301");
|
||||
//
|
||||
// TestLLUDPServer testLLUDPServer;
|
||||
// TestLLPacketServer testLLPacketServer;
|
||||
// AgentCircuitManager acm;
|
||||
// SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
// AddClient(circuitCodeA, epA, agentIdA, sessionIdA, testLLUDPServer, acm);
|
||||
// AddClient(circuitCodeB, epB, agentIdB, sessionIdB, testLLUDPServer, acm);
|
||||
//
|
||||
// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet1"), epA);
|
||||
// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet2"), epB);
|
||||
// testLLUDPServer.LoadReceiveWithBeginException(epA);
|
||||
// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(2, "packet3"), epB);
|
||||
// testLLUDPServer.ReceiveData(null);
|
||||
//
|
||||
// Assert.IsFalse(testLLUDPServer.HasCircuit(circuitCodeA));
|
||||
//
|
||||
// Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(3));
|
||||
// Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(3));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using log4net.Config;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.CoreModules.Agent.TextureSender;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class LLImageManagerTests
|
||||
{
|
||||
private AssetBase m_testImageAsset;
|
||||
private Scene scene;
|
||||
private LLImageManager llim;
|
||||
private TestClient tc;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureInit()
|
||||
{
|
||||
using (
|
||||
Stream resource
|
||||
= GetType().Assembly.GetManifestResourceStream(
|
||||
"OpenSim.Region.ClientStack.LindenUDP.Tests.Resources.4-tile2.jp2"))
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(resource))
|
||||
{
|
||||
m_testImageAsset
|
||||
= new AssetBase(
|
||||
TestHelpers.ParseTail(0x1),
|
||||
"Test Image",
|
||||
(sbyte)AssetType.Texture,
|
||||
TestHelpers.ParseTail(0x2).ToString());
|
||||
|
||||
m_testImageAsset.Data = br.ReadBytes(99999999);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
UUID userId = TestHelpers.ParseTail(0x3);
|
||||
|
||||
J2KDecoderModule j2kdm = new J2KDecoderModule();
|
||||
|
||||
scene = SceneHelpers.SetupScene();
|
||||
SceneHelpers.SetupSceneModules(scene, j2kdm);
|
||||
|
||||
tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene);
|
||||
llim = new LLImageManager(tc, scene.AssetService, j2kdm);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSendImage()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// XmlConfigurator.Configure();
|
||||
|
||||
scene.AssetService.Store(m_testImageAsset);
|
||||
|
||||
TextureRequestArgs args = new TextureRequestArgs();
|
||||
args.RequestedAssetID = m_testImageAsset.FullID;
|
||||
args.DiscardLevel = 0;
|
||||
args.PacketNumber = 1;
|
||||
args.Priority = 5;
|
||||
args.requestSequence = 1;
|
||||
|
||||
llim.EnqueueReq(args);
|
||||
llim.ProcessImageQueue(20);
|
||||
|
||||
Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDiscardImage()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// XmlConfigurator.Configure();
|
||||
|
||||
scene.AssetService.Store(m_testImageAsset);
|
||||
|
||||
TextureRequestArgs args = new TextureRequestArgs();
|
||||
args.RequestedAssetID = m_testImageAsset.FullID;
|
||||
args.DiscardLevel = 0;
|
||||
args.PacketNumber = 1;
|
||||
args.Priority = 5;
|
||||
args.requestSequence = 1;
|
||||
llim.EnqueueReq(args);
|
||||
|
||||
// Now create a discard request
|
||||
TextureRequestArgs discardArgs = new TextureRequestArgs();
|
||||
discardArgs.RequestedAssetID = m_testImageAsset.FullID;
|
||||
discardArgs.DiscardLevel = -1;
|
||||
discardArgs.PacketNumber = 1;
|
||||
discardArgs.Priority = 0;
|
||||
discardArgs.requestSequence = 2;
|
||||
llim.EnqueueReq(discardArgs);
|
||||
|
||||
llim.ProcessImageQueue(20);
|
||||
|
||||
Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMissingImage()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// XmlConfigurator.Configure();
|
||||
|
||||
TextureRequestArgs args = new TextureRequestArgs();
|
||||
args.RequestedAssetID = m_testImageAsset.FullID;
|
||||
args.DiscardLevel = 0;
|
||||
args.PacketNumber = 1;
|
||||
args.Priority = 5;
|
||||
args.requestSequence = 1;
|
||||
|
||||
llim.EnqueueReq(args);
|
||||
llim.ProcessImageQueue(20);
|
||||
|
||||
Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0));
|
||||
Assert.That(tc.SentImageNotInDatabasePackets.Count, Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System.Net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
@ -52,14 +53,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
|||
public override void Update() {}
|
||||
public override void LoadWorldMap() {}
|
||||
|
||||
public override void AddNewClient(IClientAPI client)
|
||||
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
|
||||
{
|
||||
client.OnObjectName += RecordObjectNameCall;
|
||||
|
||||
// FIXME
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void RemoveClient(UUID agentID) {}
|
||||
public override void CloseAllAgents(uint circuitcode) {}
|
||||
public override void RemoveClient(UUID agentID, bool someReason) {}
|
||||
// public override void CloseAllAgents(uint circuitcode) {}
|
||||
public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; }
|
||||
public override void OtherRegionUp(GridRegion otherRegion) { }
|
||||
|
||||
public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; }
|
||||
|
||||
/// <summary>
|
||||
/// Doesn't really matter what the call is - we're using this to test that a packet has actually been received
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.SyntaxHelpers;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenSim.Framework;
|
||||
|
@ -42,65 +41,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
|||
[TestFixture]
|
||||
public class PacketHandlerTests
|
||||
{
|
||||
[Test]
|
||||
/// <summary>
|
||||
/// More a placeholder, really
|
||||
/// </summary>
|
||||
public void InPacketTest()
|
||||
{
|
||||
TestHelper.InMethod();
|
||||
|
||||
AgentCircuitData agent = new AgentCircuitData();
|
||||
agent.AgentID = UUID.Random();
|
||||
agent.firstname = "testfirstname";
|
||||
agent.lastname = "testlastname";
|
||||
agent.SessionID = UUID.Zero;
|
||||
agent.SecureSessionID = UUID.Zero;
|
||||
agent.circuitcode = 123;
|
||||
agent.BaseFolder = UUID.Zero;
|
||||
agent.InventoryFolder = UUID.Zero;
|
||||
agent.startpos = Vector3.Zero;
|
||||
agent.CapsPath = "http://wibble.com";
|
||||
|
||||
TestLLUDPServer testLLUDPServer;
|
||||
TestLLPacketServer testLLPacketServer;
|
||||
AgentCircuitManager acm;
|
||||
IScene scene = new MockScene();
|
||||
SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
|
||||
TestClient testClient = new TestClient(agent, scene);
|
||||
|
||||
LLPacketHandler packetHandler
|
||||
= new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings());
|
||||
|
||||
packetHandler.InPacket(new AgentAnimationPacket());
|
||||
LLQueItem receivedPacket = packetHandler.PacketQueue.Dequeue();
|
||||
|
||||
Assert.That(receivedPacket, Is.Not.Null);
|
||||
Assert.That(receivedPacket.Incoming, Is.True);
|
||||
Assert.That(receivedPacket.Packet, Is.TypeOf(typeof(AgentAnimationPacket)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a client for testing
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="testLLUDPServer"></param>
|
||||
/// <param name="testPacketServer"></param>
|
||||
/// <param name="acm">Agent circuit manager used in setting up the stack</param>
|
||||
protected void SetupStack(
|
||||
IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
|
||||
out AgentCircuitManager acm)
|
||||
{
|
||||
IConfigSource configSource = new IniConfigSource();
|
||||
ClientStackUserSettings userSettings = new ClientStackUserSettings();
|
||||
testLLUDPServer = new TestLLUDPServer();
|
||||
acm = new AgentCircuitManager();
|
||||
|
||||
uint port = 666;
|
||||
testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
|
||||
testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
|
||||
testLLUDPServer.LocalScene = scene;
|
||||
}
|
||||
// [Test]
|
||||
// /// <summary>
|
||||
// /// More a placeholder, really
|
||||
// /// </summary>
|
||||
// public void InPacketTest()
|
||||
// {
|
||||
// TestHelper.InMethod();
|
||||
//
|
||||
// AgentCircuitData agent = new AgentCircuitData();
|
||||
// agent.AgentID = UUID.Random();
|
||||
// agent.firstname = "testfirstname";
|
||||
// agent.lastname = "testlastname";
|
||||
// agent.SessionID = UUID.Zero;
|
||||
// agent.SecureSessionID = UUID.Zero;
|
||||
// agent.circuitcode = 123;
|
||||
// agent.BaseFolder = UUID.Zero;
|
||||
// agent.InventoryFolder = UUID.Zero;
|
||||
// agent.startpos = Vector3.Zero;
|
||||
// agent.CapsPath = "http://wibble.com";
|
||||
//
|
||||
// TestLLUDPServer testLLUDPServer;
|
||||
// TestLLPacketServer testLLPacketServer;
|
||||
// AgentCircuitManager acm;
|
||||
// IScene scene = new MockScene();
|
||||
// SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
|
||||
//
|
||||
// TestClient testClient = new TestClient(agent, scene);
|
||||
//
|
||||
// LLPacketHandler packetHandler
|
||||
// = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings());
|
||||
//
|
||||
// packetHandler.InPacket(new AgentAnimationPacket());
|
||||
// LLQueItem receivedPacket = packetHandler.PacketQueue.Dequeue();
|
||||
//
|
||||
// Assert.That(receivedPacket, Is.Not.Null);
|
||||
// Assert.That(receivedPacket.Incoming, Is.True);
|
||||
// Assert.That(receivedPacket.Packet, Is.TypeOf(typeof(AgentAnimationPacket)));
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Add a client for testing
|
||||
// /// </summary>
|
||||
// /// <param name="scene"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="testPacketServer"></param>
|
||||
// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
|
||||
// protected void SetupStack(
|
||||
// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
|
||||
// out AgentCircuitManager acm)
|
||||
// {
|
||||
// IConfigSource configSource = new IniConfigSource();
|
||||
// ClientStackUserSettings userSettings = new ClientStackUserSettings();
|
||||
// testLLUDPServer = new TestLLUDPServer();
|
||||
// acm = new AgentCircuitManager();
|
||||
//
|
||||
// uint port = 666;
|
||||
// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
|
||||
// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
|
||||
// testLLUDPServer.LocalScene = scene;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -29,105 +29,113 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// This class enables synchronous testing of the LLUDPServer by allowing us to load our own data into the end
|
||||
/// receive event
|
||||
/// This class enables regression testing of the LLUDPServer by allowing us to intercept outgoing data.
|
||||
/// </summary>
|
||||
public class TestLLUDPServer : LLUDPServer
|
||||
{
|
||||
/// <summary>
|
||||
/// The chunks of data to pass to the LLUDPServer when it calls EndReceive
|
||||
/// </summary>
|
||||
protected Queue<ChunkSenderTuple> m_chunksToLoad = new Queue<ChunkSenderTuple>();
|
||||
|
||||
protected override void BeginReceive()
|
||||
{
|
||||
if (m_chunksToLoad.Count > 0 && m_chunksToLoad.Peek().BeginReceiveException)
|
||||
{
|
||||
ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
|
||||
reusedEpSender = tuple.Sender;
|
||||
throw new SocketException();
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender)
|
||||
{
|
||||
numBytes = 0;
|
||||
public List<Packet> PacketsSent { get; private set; }
|
||||
|
||||
//m_log.Debug("Queue size " + m_chunksToLoad.Count);
|
||||
|
||||
if (m_chunksToLoad.Count <= 0)
|
||||
return false;
|
||||
|
||||
ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
|
||||
RecvBuffer = tuple.Data;
|
||||
numBytes = tuple.Data.Length;
|
||||
epSender = tuple.Sender;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
|
||||
public TestLLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
|
||||
: base(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager)
|
||||
{
|
||||
// Don't do anything just yet
|
||||
PacketsSent = new List<Packet>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signal that this chunk should throw an exception on Socket.BeginReceive()
|
||||
/// </summary>
|
||||
/// <param name="epSender"></param>
|
||||
public void LoadReceiveWithBeginException(EndPoint epSender)
|
||||
|
||||
public override void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack)
|
||||
{
|
||||
ChunkSenderTuple tuple = new ChunkSenderTuple(epSender);
|
||||
tuple.BeginReceiveException = true;
|
||||
m_chunksToLoad.Enqueue(tuple);
|
||||
PacketsSent.Add(ack);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load some data to be received by the LLUDPServer on the next receive call
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="epSender"></param>
|
||||
public void LoadReceive(byte[] data, EndPoint epSender)
|
||||
|
||||
public override void SendPacket(
|
||||
LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
|
||||
{
|
||||
m_chunksToLoad.Enqueue(new ChunkSenderTuple(data, epSender));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a packet to be received by the LLUDPServer on the next receive call
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
public void LoadReceive(Packet packet, EndPoint epSender)
|
||||
{
|
||||
LoadReceive(packet.ToBytes(), epSender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls the protected asynchronous result method. This fires out all data chunks currently queued for send
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
public void ReceiveData(IAsyncResult result)
|
||||
{
|
||||
while (m_chunksToLoad.Count > 0)
|
||||
OnReceivedData(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Has a circuit with the given code been established?
|
||||
/// </summary>
|
||||
/// <param name="circuitCode"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasCircuit(uint circuitCode)
|
||||
{
|
||||
lock (clientCircuits_reverse)
|
||||
{
|
||||
return clientCircuits_reverse.ContainsKey(circuitCode);
|
||||
}
|
||||
PacketsSent.Add(packet);
|
||||
}
|
||||
|
||||
//// /// <summary>
|
||||
//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
|
||||
//// /// </summary>
|
||||
//// protected Queue<ChunkSenderTuple> m_chunksToLoad = new Queue<ChunkSenderTuple>();
|
||||
//
|
||||
//// protected override void BeginReceive()
|
||||
//// {
|
||||
//// if (m_chunksToLoad.Count > 0 && m_chunksToLoad.Peek().BeginReceiveException)
|
||||
//// {
|
||||
//// ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
|
||||
//// reusedEpSender = tuple.Sender;
|
||||
//// throw new SocketException();
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
//// protected override bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender)
|
||||
//// {
|
||||
//// numBytes = 0;
|
||||
////
|
||||
//// //m_log.Debug("Queue size " + m_chunksToLoad.Count);
|
||||
////
|
||||
//// if (m_chunksToLoad.Count <= 0)
|
||||
//// return false;
|
||||
////
|
||||
//// ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
|
||||
//// RecvBuffer = tuple.Data;
|
||||
//// numBytes = tuple.Data.Length;
|
||||
//// epSender = tuple.Sender;
|
||||
////
|
||||
//// return true;
|
||||
//// }
|
||||
//
|
||||
//// public override void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
|
||||
//// {
|
||||
//// // Don't do anything just yet
|
||||
//// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Signal that this chunk should throw an exception on Socket.BeginReceive()
|
||||
// /// </summary>
|
||||
// /// <param name="epSender"></param>
|
||||
// public void LoadReceiveWithBeginException(EndPoint epSender)
|
||||
// {
|
||||
// ChunkSenderTuple tuple = new ChunkSenderTuple(epSender);
|
||||
// tuple.BeginReceiveException = true;
|
||||
// m_chunksToLoad.Enqueue(tuple);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Load some data to be received by the LLUDPServer on the next receive call
|
||||
// /// </summary>
|
||||
// /// <param name="data"></param>
|
||||
// /// <param name="epSender"></param>
|
||||
// public void LoadReceive(byte[] data, EndPoint epSender)
|
||||
// {
|
||||
// m_chunksToLoad.Enqueue(new ChunkSenderTuple(data, epSender));
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Load a packet to be received by the LLUDPServer on the next receive call
|
||||
// /// </summary>
|
||||
// /// <param name="packet"></param>
|
||||
// public void LoadReceive(Packet packet, EndPoint epSender)
|
||||
// {
|
||||
// LoadReceive(packet.ToBytes(), epSender);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Calls the protected asynchronous result method. This fires out all data chunks currently queued for send
|
||||
// /// </summary>
|
||||
// /// <param name="result"></param>
|
||||
// public void ReceiveData(IAsyncResult result)
|
||||
// {
|
||||
// // Doesn't work the same way anymore
|
||||
//// while (m_chunksToLoad.Count > 0)
|
||||
//// OnReceivedData(result);
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -118,12 +118,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// Returns a list of all of the packets with a TickCount older than
|
||||
/// the specified timeout
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function is not thread safe, and cannot be called
|
||||
/// multiple times concurrently
|
||||
/// </remarks>
|
||||
/// <param name="timeoutMS">Number of ticks (milliseconds) before a
|
||||
/// packet is considered expired</param>
|
||||
/// <returns>A list of all expired packets according to the given
|
||||
/// expiration timeout</returns>
|
||||
/// <remarks>This function is not thread safe, and cannot be called
|
||||
/// multiple times concurrently</remarks>
|
||||
/// packet is considered expired
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A list of all expired packets according to the given
|
||||
/// expiration timeout
|
||||
/// </returns>
|
||||
public List<OutgoingPacket> GetExpiredPackets(int timeoutMS)
|
||||
{
|
||||
ProcessQueues();
|
||||
|
@ -159,6 +164,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
//if (expiredPackets != null)
|
||||
// m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Found {0} expired packets on timeout of {1}", expiredPackets.Count, timeoutMS);
|
||||
|
||||
return expiredPackets;
|
||||
}
|
||||
|
||||
|
@ -174,6 +182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
PendingAck pendingAcknowledgement;
|
||||
while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
|
||||
{
|
||||
//m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber);
|
||||
OutgoingPacket ackedPacket;
|
||||
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
|
||||
{
|
||||
|
@ -196,6 +205,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
ackedPacket.Client.UpdateRoundTrip(rtt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//m_log.WarnFormat("[UNACKED PACKET COLLECTION]: Could not find packet with sequence number {0} to ack", pendingAcknowledgement.SequenceNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,4 +229,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -103,6 +103,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
|||
// If it's cached, return the cached results
|
||||
if (m_decodedCache.TryGetValue(assetID, out result))
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[J2KDecoderModule]: Returning existing cached {0} layers j2k decode for {1}",
|
||||
// result.Length, assetID);
|
||||
|
||||
callback(assetID, result);
|
||||
}
|
||||
else
|
||||
|
@ -129,18 +133,20 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
|||
|
||||
// Do Decode!
|
||||
if (decode)
|
||||
DoJ2KDecode(assetID, j2kData);
|
||||
Decode(assetID, j2kData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a synchronous decode so that caller can be assured that this executes before the next line
|
||||
/// </summary>
|
||||
/// <param name="assetID"></param>
|
||||
/// <param name="j2kData"></param>
|
||||
public void Decode(UUID assetID, byte[] j2kData)
|
||||
public bool Decode(UUID assetID, byte[] j2kData)
|
||||
{
|
||||
DoJ2KDecode(assetID, j2kData);
|
||||
OpenJPEG.J2KLayerInfo[] layers;
|
||||
int components;
|
||||
return Decode(assetID, j2kData, out layers, out components);
|
||||
}
|
||||
|
||||
public bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components)
|
||||
{
|
||||
return DoJ2KDecode(assetID, j2kData, out layers, out components);
|
||||
}
|
||||
|
||||
#endregion IJ2KDecoder
|
||||
|
@ -150,11 +156,21 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
|||
/// </summary>
|
||||
/// <param name="assetID">UUID of Asset</param>
|
||||
/// <param name="j2kData">JPEG2000 data</param>
|
||||
private void DoJ2KDecode(UUID assetID, byte[] j2kData)
|
||||
/// <param name="layers">layer data</param>
|
||||
/// <param name="components">number of components</param>
|
||||
/// <returns>true if decode was successful. false otherwise.</returns>
|
||||
private bool DoJ2KDecode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[J2KDecoderModule]: Doing J2K decoding of {0} bytes for asset {1}", j2kData.Length, assetID);
|
||||
|
||||
bool decodedSuccessfully = true;
|
||||
|
||||
//int DecodeTime = 0;
|
||||
//DecodeTime = Environment.TickCount;
|
||||
OpenJPEG.J2KLayerInfo[] layers;
|
||||
|
||||
// We don't get this from CSJ2K. Is it relevant?
|
||||
components = 0;
|
||||
|
||||
if (!TryLoadCacheForAsset(assetID, out layers))
|
||||
{
|
||||
|
@ -189,14 +205,15 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
|||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " + assetID + ": " + ex.Message);
|
||||
decodedSuccessfully = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int components;
|
||||
if (!OpenJPEG.DecodeLayerBoundaries(j2kData, out layers, out components))
|
||||
{
|
||||
m_log.Warn("[J2KDecoderModule]: OpenJPEG failed to decode texture " + assetID);
|
||||
decodedSuccessfully = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,6 +222,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
|||
m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults");
|
||||
// Layer decoding completely failed. Guess at sane defaults for the layer boundaries
|
||||
layers = CreateDefaultLayers(j2kData.Length);
|
||||
decodedSuccessfully = false;
|
||||
}
|
||||
|
||||
// Cache Decoded layers
|
||||
|
@ -224,6 +242,8 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
|||
m_notifyList.Remove(assetID);
|
||||
}
|
||||
}
|
||||
|
||||
return decodedSuccessfully;
|
||||
}
|
||||
|
||||
private OpenJPEG.J2KLayerInfo[] CreateDefaultLayers(int j2kLength)
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
|
|||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
AssetBase asset = AssetHelpers.CreateAsset();
|
||||
AssetBase asset = AssetHelpers.CreateNotecardAsset();
|
||||
asset.ID = TestHelpers.ParseTail(0x1).ToString();
|
||||
|
||||
// Check we don't get anything before the asset is put in the cache
|
||||
|
@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
|
|||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
AssetBase asset = AssetHelpers.CreateAsset();
|
||||
AssetBase asset = AssetHelpers.CreateNotecardAsset();
|
||||
asset.ID = TestHelpers.ParseTail(0x2).ToString();
|
||||
|
||||
m_cache.Store(asset);
|
||||
|
@ -112,8 +112,8 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
|
|||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
AssetBase asset = AssetHelpers.CreateAsset();
|
||||
|
||||
AssetBase asset = AssetHelpers.CreateNotecardAsset();
|
||||
asset.ID = TestHelpers.ParseTail(0x2).ToString();
|
||||
|
||||
m_cache.Store(asset);
|
||||
|
|
|
@ -615,7 +615,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
so.AttachedAvatar = UUID.Zero;
|
||||
rootPart.SetParentLocalId(0);
|
||||
so.ClearPartAttachmentData();
|
||||
rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
|
||||
rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive);
|
||||
so.HasGroupChanged = true;
|
||||
rootPart.Rezzed = DateTime.Now;
|
||||
rootPart.RemFlag(PrimFlags.TemporaryOnRez);
|
||||
|
@ -764,10 +764,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
so.AttachedAvatar = avatar.UUID;
|
||||
|
||||
if (so.RootPart.PhysActor != null)
|
||||
{
|
||||
m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
|
||||
so.RootPart.PhysActor = null;
|
||||
}
|
||||
so.RootPart.RemoveFromPhysics();
|
||||
|
||||
so.AbsolutePosition = attachOffset;
|
||||
so.RootPart.AttachedPos = attachOffset;
|
||||
|
@ -891,4 +888,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,22 +115,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Check for the existence of the baked texture assets.
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
public bool ValidateBakedTextureCache(IClientAPI client)
|
||||
{
|
||||
return ValidateBakedTextureCache(client, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for the existence of the baked texture assets. Request a rebake
|
||||
/// unless checkonly is true.
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="checkonly"></param>
|
||||
private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly)
|
||||
{
|
||||
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
|
||||
if (sp == null)
|
||||
|
@ -164,17 +149,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
|
||||
defonly = false; // found a non-default texture reference
|
||||
|
||||
if (!CheckBakedTextureAsset(client, face.TextureID, idx))
|
||||
{
|
||||
// the asset didn't exist if we are only checking, then we found a bad
|
||||
// one and we're done otherwise, ask for a rebake
|
||||
if (checkonly)
|
||||
return false;
|
||||
|
||||
m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID);
|
||||
|
||||
client.SendRebakeAvatarTextures(face.TextureID);
|
||||
}
|
||||
if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", client.AgentId);
|
||||
|
@ -183,6 +159,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
return (defonly ? false : true);
|
||||
}
|
||||
|
||||
public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
|
||||
{
|
||||
int texturesRebaked = 0;
|
||||
|
||||
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
||||
{
|
||||
int idx = AvatarAppearance.BAKE_INDICES[i];
|
||||
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
|
||||
|
||||
// if there is no texture entry, skip it
|
||||
if (face == null)
|
||||
continue;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
|
||||
// face.TextureID, idx, client.Name, client.AgentId);
|
||||
|
||||
// if the texture is one of the "defaults" then skip it
|
||||
// this should probably be more intelligent (skirt texture doesnt matter
|
||||
// if the avatar isnt wearing a skirt) but if any of the main baked
|
||||
// textures is default then the rest should be as well
|
||||
if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||
continue;
|
||||
|
||||
if (missingTexturesOnly)
|
||||
{
|
||||
if (m_scene.AssetService.Get(face.TextureID.ToString()) != null)
|
||||
continue;
|
||||
else
|
||||
m_log.DebugFormat(
|
||||
"[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
|
||||
face.TextureID, idx, sp.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[AVFACTORY]: Requesting rebake of {0} ({1}) for {2}.",
|
||||
face.TextureID, idx, sp.Name);
|
||||
}
|
||||
|
||||
texturesRebaked++;
|
||||
sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
|
||||
}
|
||||
|
||||
return texturesRebaked;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set appearance data (texture asset IDs and slider settings) received from the client
|
||||
/// </summary>
|
||||
|
@ -230,14 +253,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
{
|
||||
changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
|
||||
|
||||
m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", client.AgentId);
|
||||
Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client, false); });
|
||||
if (!ValidateBakedTextureCache(sp.ControllingClient))
|
||||
RequestRebake(sp, true);
|
||||
|
||||
// This appears to be set only in the final stage of the appearance
|
||||
// update transaction. In theory, we should be able to do an immediate
|
||||
// appearance send and save here.
|
||||
|
||||
}
|
||||
|
||||
// save only if there were changes, send no matter what (doesn't hurt to send twice)
|
||||
if (changed)
|
||||
QueueAppearanceSave(client.AgentId);
|
||||
|
@ -385,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
/// </summary>
|
||||
public void QueueAppearanceSend(UUID agentid)
|
||||
{
|
||||
// m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
|
||||
// m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
|
||||
|
||||
// 10000 ticks per millisecond, 1000 milliseconds per second
|
||||
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
|
||||
|
@ -444,10 +467,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue);
|
||||
foreach (KeyValuePair<UUID, long> kvp in sends)
|
||||
{
|
||||
if (kvp.Value < now)
|
||||
// We have to load the key and value into local parameters to avoid a race condition if we loop
|
||||
// around and load kvp with a different value before FireAndForget has launched its thread.
|
||||
UUID avatarID = kvp.Key;
|
||||
long sendTime = kvp.Value;
|
||||
|
||||
// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
|
||||
|
||||
if (sendTime < now)
|
||||
{
|
||||
Util.FireAndForget(delegate(object o) { SendAppearance(kvp.Key); });
|
||||
m_sendqueue.Remove(kvp.Key);
|
||||
Util.FireAndForget(o => SendAppearance(avatarID));
|
||||
m_sendqueue.Remove(avatarID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -457,16 +487,24 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue);
|
||||
foreach (KeyValuePair<UUID, long> kvp in saves)
|
||||
{
|
||||
if (kvp.Value < now)
|
||||
// We have to load the key and value into local parameters to avoid a race condition if we loop
|
||||
// around and load kvp with a different value before FireAndForget has launched its thread.
|
||||
UUID avatarID = kvp.Key;
|
||||
long sendTime = kvp.Value;
|
||||
|
||||
if (sendTime < now)
|
||||
{
|
||||
Util.FireAndForget(delegate(object o) { SaveAppearance(kvp.Key); });
|
||||
m_savequeue.Remove(kvp.Key);
|
||||
Util.FireAndForget(o => SaveAppearance(avatarID));
|
||||
m_savequeue.Remove(avatarID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
|
||||
m_updateTimer.Stop();
|
||||
// We must lock both queues here so that QueueAppearanceSave() or *Send() don't m_updateTimer.Start() on
|
||||
// another thread inbetween the first count calls and m_updateTimer.Stop() on this thread.
|
||||
lock (m_sendqueue)
|
||||
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
|
||||
m_updateTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -535,6 +573,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
|
||||
public bool SendAppearance(UUID agentId)
|
||||
{
|
||||
// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
|
||||
|
||||
ScenePresence sp = m_scene.GetScenePresence(agentId);
|
||||
if (sp == null)
|
||||
{
|
||||
|
|
|
@ -279,12 +279,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
|
|||
|
||||
HashSet<UUID> receiverIDs = new HashSet<UUID>();
|
||||
|
||||
((Scene)c.Scene).ForEachScenePresence(
|
||||
((Scene)c.Scene).ForEachRootScenePresence(
|
||||
delegate(ScenePresence presence)
|
||||
{
|
||||
// ignore chat from child agents
|
||||
if (presence.IsChildAgent) return;
|
||||
|
||||
{
|
||||
IClientAPI client = presence.ControllingClient;
|
||||
|
||||
// don't forward SayOwner chat from objects to
|
||||
|
|
|
@ -98,10 +98,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
|
|||
|
||||
public void SendGeneralAlert(string message)
|
||||
{
|
||||
m_scene.ForEachScenePresence(delegate(ScenePresence presence)
|
||||
m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
|
||||
{
|
||||
if (!presence.IsChildAgent)
|
||||
presence.ControllingClient.SendAlertMessage(message);
|
||||
presence.ControllingClient.SendAlertMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -163,10 +162,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
|
|||
public void SendNotificationToUsersInRegion(
|
||||
UUID fromAvatarID, string fromAvatarName, string message)
|
||||
{
|
||||
m_scene.ForEachScenePresence(delegate(ScenePresence presence)
|
||||
m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
|
||||
{
|
||||
if (!presence.IsChildAgent)
|
||||
presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message);
|
||||
presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -201,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
|
|||
}
|
||||
else
|
||||
{
|
||||
OpenSim.Framework.Console.MainConsole.Instance.Output(
|
||||
MainConsole.Instance.Output(
|
||||
"Usage: alert <message> | alert-user <first> <last> <message>");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ using OpenMetaverse;
|
|||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Framework.Communications;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
@ -78,10 +79,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
protected IFriendsService m_FriendsService = null;
|
||||
protected FriendsSimConnector m_FriendsSimConnector;
|
||||
|
||||
protected Dictionary<UUID, UserFriendData> m_Friends =
|
||||
new Dictionary<UUID, UserFriendData>();
|
||||
/// <summary>
|
||||
/// Cache friends lists for users.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a complex and error-prone thing to do. At the moment, we assume that the efficiency gained in
|
||||
/// permissions checks outweighs the disadvantages of that complexity.
|
||||
/// </remarks>
|
||||
protected Dictionary<UUID, UserFriendData> m_Friends = new Dictionary<UUID, UserFriendData>();
|
||||
|
||||
protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>();
|
||||
/// <summary>
|
||||
/// Maintain a record of viewers that need to be sent notifications for friends that are online. This only
|
||||
/// needs to be done on login. Subsequent online/offline friend changes are sent by a different mechanism.
|
||||
/// </summary>
|
||||
protected HashSet<UUID> m_NeedsListOfOnlineFriends = new HashSet<UUID>();
|
||||
|
||||
protected IPresenceService PresenceService
|
||||
{
|
||||
|
@ -164,7 +175,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
|
||||
// Instantiate the request handler
|
||||
IHttpServer server = MainServer.GetHttpServer((uint)mPort);
|
||||
server.AddStreamHandler(new FriendsRequestHandler(this));
|
||||
|
||||
if (server != null)
|
||||
server.AddStreamHandler(new FriendsRequestHandler(this));
|
||||
}
|
||||
|
||||
if (m_FriendsService == null)
|
||||
|
@ -186,6 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
|
||||
|
||||
m_Scenes.Add(scene);
|
||||
|
@ -238,16 +252,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
client.OnInstantMessage += OnInstantMessage;
|
||||
client.OnApproveFriendRequest += OnApproveFriendRequest;
|
||||
client.OnDenyFriendRequest += OnDenyFriendRequest;
|
||||
client.OnTerminateFriendship += OnTerminateFriendship;
|
||||
client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID);
|
||||
client.OnGrantUserRights += OnGrantUserRights;
|
||||
|
||||
Util.FireAndForget(delegate { FetchFriendslist(client); });
|
||||
// Do not do this asynchronously. If we do, then subsequent code can outrace CacheFriends() and
|
||||
// return misleading results from the still empty friends cache.
|
||||
// If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls
|
||||
// to GetFriends() will wait until CacheFriends() completes. Locks are insufficient.
|
||||
CacheFriends(client);
|
||||
}
|
||||
|
||||
/// Fetch the friends list or increment the refcount for the existing
|
||||
/// friends list
|
||||
/// <summary>
|
||||
/// Cache the friends list or increment the refcount for the existing friends list.
|
||||
/// </summary>
|
||||
/// <param name="client">
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Returns true if the list was fetched, false if it wasn't
|
||||
protected virtual bool FetchFriendslist(IClientAPI client)
|
||||
/// </returns>
|
||||
protected virtual bool CacheFriends(IClientAPI client)
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
lock (m_Friends)
|
||||
|
@ -294,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
|
||||
private void OnMakeRootAgent(ScenePresence sp)
|
||||
{
|
||||
RefetchFriends(sp.ControllingClient);
|
||||
RecacheFriends(sp.ControllingClient);
|
||||
}
|
||||
|
||||
private void OnClientLogin(IClientAPI client)
|
||||
|
@ -306,8 +329,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
StatusChange(agentID, true);
|
||||
|
||||
// Register that we need to send the list of online friends to this user
|
||||
lock (m_NeedsListOfFriends)
|
||||
m_NeedsListOfFriends.Add(agentID);
|
||||
lock (m_NeedsListOfOnlineFriends)
|
||||
m_NeedsListOfOnlineFriends.Add(agentID);
|
||||
}
|
||||
|
||||
public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
|
||||
|
@ -315,9 +338,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
UUID agentID = client.AgentId;
|
||||
|
||||
// Check if the online friends list is needed
|
||||
lock (m_NeedsListOfFriends)
|
||||
lock (m_NeedsListOfOnlineFriends)
|
||||
{
|
||||
if (!m_NeedsListOfFriends.Remove(agentID))
|
||||
if (!m_NeedsListOfOnlineFriends.Remove(agentID))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -325,7 +348,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
List<UUID> online = GetOnlineFriends(agentID);
|
||||
if (online.Count > 0)
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
|
||||
m_log.DebugFormat(
|
||||
"[FRIENDS MODULE]: User {0} in region {1} has {2} friends online",
|
||||
client.Name, client.Scene.RegionInfo.RegionName, online.Count);
|
||||
|
||||
client.SendAgentOnline(online.ToArray());
|
||||
}
|
||||
|
||||
|
@ -575,19 +601,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
|
||||
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
||||
{
|
||||
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
|
||||
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
|
||||
|
||||
StoreFriendships(agentID, friendID);
|
||||
AddFriendship(client, friendID);
|
||||
}
|
||||
|
||||
public void AddFriendship(IClientAPI client, UUID friendID)
|
||||
{
|
||||
StoreFriendships(client.AgentId, friendID);
|
||||
|
||||
// Update the local cache
|
||||
RefetchFriends(client);
|
||||
RecacheFriends(client);
|
||||
|
||||
//
|
||||
// Notify the friend
|
||||
//
|
||||
|
||||
// Try Local
|
||||
if (LocalFriendshipApproved(agentID, client.Name, friendID))
|
||||
if (LocalFriendshipApproved(client.AgentId, client.Name, friendID))
|
||||
{
|
||||
client.SendAgentOnline(new UUID[] { friendID });
|
||||
return;
|
||||
|
@ -601,7 +632,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
if (friendSession != null)
|
||||
{
|
||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||
m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID);
|
||||
m_FriendsSimConnector.FriendshipApproved(region, client.AgentId, client.Name, friendID);
|
||||
client.SendAgentOnline(new UUID[] { friendID });
|
||||
}
|
||||
}
|
||||
|
@ -635,14 +666,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
|
||||
|
||||
public void RemoveFriendship(IClientAPI client, UUID exfriendID)
|
||||
{
|
||||
if (!DeleteFriendship(agentID, exfriendID))
|
||||
if (!DeleteFriendship(client.AgentId, exfriendID))
|
||||
client.SendAlertMessage("Unable to terminate friendship on this sim.");
|
||||
|
||||
// Update local cache
|
||||
RefetchFriends(client);
|
||||
RecacheFriends(client);
|
||||
|
||||
client.SendTerminateFriend(exfriendID);
|
||||
|
||||
|
@ -661,9 +692,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
if (friendSession != null)
|
||||
{
|
||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||
m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID);
|
||||
m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
|
||||
|
@ -756,7 +787,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
friendClient.SendInstantMessage(im);
|
||||
|
||||
// Update the local cache
|
||||
RefetchFriends(friendClient);
|
||||
RecacheFriends(friendClient);
|
||||
|
||||
// we're done
|
||||
return true;
|
||||
|
@ -789,7 +820,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
// the friend in this sim as root agent
|
||||
friendClient.SendTerminateFriend(exfriendID);
|
||||
// update local cache
|
||||
RefetchFriends(friendClient);
|
||||
RecacheFriends(friendClient);
|
||||
// we're done
|
||||
return true;
|
||||
}
|
||||
|
@ -806,16 +837,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
if (onlineBitChanged)
|
||||
{
|
||||
if ((rights & (int)FriendRights.CanSeeOnline) == 1)
|
||||
friendClient.SendAgentOnline(new UUID[] { new UUID(userID) });
|
||||
friendClient.SendAgentOnline(new UUID[] { userID });
|
||||
else
|
||||
friendClient.SendAgentOffline(new UUID[] { new UUID(userID) });
|
||||
friendClient.SendAgentOffline(new UUID[] { userID });
|
||||
}
|
||||
else
|
||||
{
|
||||
bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0;
|
||||
if (canEditObjectsChanged)
|
||||
friendClient.SendChangeUserRights(userID, friendID, rights);
|
||||
|
||||
}
|
||||
|
||||
// Update local cache
|
||||
|
@ -868,7 +898,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update loca cache only
|
||||
/// Update local cache only
|
||||
/// </summary>
|
||||
/// <param name="userID"></param>
|
||||
/// <param name="friendID"></param>
|
||||
|
@ -889,7 +919,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
return FriendsService.GetFriends(client.AgentId);
|
||||
}
|
||||
|
||||
private void RefetchFriends(IClientAPI client)
|
||||
private void RecacheFriends(IClientAPI client)
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
lock (m_Friends)
|
||||
|
|
|
@ -30,7 +30,6 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using Nwc.XmlRpc;
|
||||
|
@ -84,9 +83,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
|
||||
#endregion
|
||||
|
||||
protected override bool FetchFriendslist(IClientAPI client)
|
||||
protected override bool CacheFriends(IClientAPI client)
|
||||
{
|
||||
if (base.FetchFriendslist(client))
|
||||
if (base.CacheFriends(client))
|
||||
{
|
||||
UUID agentID = client.AgentId;
|
||||
// we do this only for the root agent
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.CoreModules.Avatar.Friends;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class FriendsModuleTests
|
||||
{
|
||||
private FriendsModule m_fm;
|
||||
private TestScene m_scene;
|
||||
|
||||
[SetUp]
|
||||
public void Init()
|
||||
{
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
// Not strictly necessary since FriendsModule assumes it is the default (!)
|
||||
config.Configs["Modules"].Set("FriendsModule", "FriendsModule");
|
||||
config.AddConfig("Friends");
|
||||
config.Configs["Friends"].Set("Connector", "OpenSim.Services.FriendsService.dll");
|
||||
config.AddConfig("FriendsService");
|
||||
config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
|
||||
|
||||
m_scene = SceneHelpers.SetupScene();
|
||||
m_fm = new FriendsModule();
|
||||
SceneHelpers.SetupSceneModules(m_scene, config, m_fm);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoFriends()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
UUID userId = TestHelpers.ParseTail(0x1);
|
||||
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||
|
||||
Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0));
|
||||
Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddFriendshipWhileOnline()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
UUID userId = TestHelpers.ParseTail(0x1);
|
||||
UUID user2Id = TestHelpers.ParseTail(0x2);
|
||||
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||
ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id);
|
||||
|
||||
// This fiendship is two-way but without a connector, only the first user will receive the online
|
||||
// notification.
|
||||
m_fm.AddFriendship(sp.ControllingClient, user2Id);
|
||||
|
||||
Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0));
|
||||
Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRemoveFriendshipWhileOnline()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
UUID user1Id = TestHelpers.ParseTail(0x1);
|
||||
UUID user2Id = TestHelpers.ParseTail(0x2);
|
||||
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, user1Id);
|
||||
SceneHelpers.AddScenePresence(m_scene, user2Id);
|
||||
|
||||
m_fm.AddFriendship(sp.ControllingClient, user2Id);
|
||||
m_fm.RemoveFriendship(sp.ControllingClient, user2Id);
|
||||
|
||||
TestClient user1Client = sp.ControllingClient as TestClient;
|
||||
Assert.That(user1Client.ReceivedFriendshipTerminations.Count, Is.EqualTo(1));
|
||||
Assert.That(user1Client.ReceivedFriendshipTerminations[0], Is.EqualTo(user2Id));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -140,10 +140,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
|
|||
// This is a bit crude. It seems the client will be null before it actually stops the thread
|
||||
// The thread will kill itself eventually :/
|
||||
// Is there another way to make sure *all* clients get this 'inter region' message?
|
||||
m_scene.ForEachScenePresence(
|
||||
m_scene.ForEachRootScenePresence(
|
||||
delegate(ScenePresence p)
|
||||
{
|
||||
if (p.UUID != godID && !p.IsChildAgent)
|
||||
if (p.UUID != godID)
|
||||
{
|
||||
// Possibly this should really be p.Close() though that method doesn't send a close
|
||||
// to the client
|
||||
|
|
|
@ -36,6 +36,7 @@ using Nwc.XmlRpc;
|
|||
using Mono.Addins;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
|
|
@ -34,6 +34,7 @@ using Nini.Config;
|
|||
using Nwc.XmlRpc;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
|
|
@ -275,19 +275,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
|
|||
{
|
||||
if (m_TransferModule != null)
|
||||
m_TransferModule.SendInstantMessage(im, delegate(bool success) {
|
||||
// Send BulkUpdateInventory
|
||||
IInventoryService invService = scene.InventoryService;
|
||||
UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
|
||||
|
||||
InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
|
||||
folder = invService.GetFolder(folder);
|
||||
// justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
|
||||
// and is apparently supposed to fix bulk inventory updates after accepting items. But
|
||||
// instead it appears to cause two copies of an accepted folder for the receiving user in
|
||||
// at least some cases. Folder/item update is already done when the offer is made (see code above)
|
||||
|
||||
ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
|
||||
|
||||
// If the user has left the scene by the time the message comes back then we can't send
|
||||
// them the update.
|
||||
if (fromUser != null)
|
||||
fromUser.ControllingClient.SendBulkUpdateInventory(folder);
|
||||
// // Send BulkUpdateInventory
|
||||
// IInventoryService invService = scene.InventoryService;
|
||||
// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
|
||||
//
|
||||
// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
|
||||
// folder = invService.GetFolder(folder);
|
||||
//
|
||||
// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
|
||||
//
|
||||
// // If the user has left the scene by the time the message comes back then we can't send
|
||||
// // them the update.
|
||||
// if (fromUser != null)
|
||||
// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,12 +29,14 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using Mono.Addins;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using Caps=OpenSim.Framework.Capabilities.Caps;
|
||||
|
@ -45,6 +47,8 @@ namespace OpenSim.Region.CoreModules.Framework
|
|||
public class CapabilitiesModule : INonSharedRegionModule, ICapabilitiesModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_showCapsCommandFormat = " {0,-38} {1,-60}\n";
|
||||
|
||||
protected Scene m_scene;
|
||||
|
||||
|
@ -67,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework
|
|||
m_scene.RegisterModuleInterface<ICapabilitiesModule>(this);
|
||||
MainConsole.Instance.Commands.AddCommand("Capabilities", false, "show caps",
|
||||
"show caps",
|
||||
"Shows all registered capabilities", CapabilitiesCommand);
|
||||
"Shows all registered capabilities", HandleShowCapsCommand);
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
|
@ -226,21 +230,23 @@ namespace OpenSim.Region.CoreModules.Framework
|
|||
}
|
||||
}
|
||||
|
||||
private void CapabilitiesCommand(string module, string[] cmdparams)
|
||||
private void HandleShowCapsCommand(string module, string[] cmdparams)
|
||||
{
|
||||
System.Text.StringBuilder caps = new System.Text.StringBuilder();
|
||||
StringBuilder caps = new StringBuilder();
|
||||
caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
|
||||
|
||||
foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects)
|
||||
{
|
||||
caps.AppendFormat("** User {0}:\n", kvp.Key);
|
||||
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.CapsDetails.GetEnumerator(); kvp2.MoveNext(); )
|
||||
|
||||
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); )
|
||||
{
|
||||
Uri uri = new Uri(kvp2.Value.ToString());
|
||||
caps.AppendFormat(" {0} = {1}\n", kvp2.Key, uri.PathAndQuery);
|
||||
caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers)
|
||||
caps.AppendFormat(" {0} = {1}\n", kvp3.Key, kvp3.Value);
|
||||
caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(caps.ToString());
|
||||
|
|
|
@ -547,12 +547,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
return null;
|
||||
|
||||
userID = remoteClient.AgentId;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}",
|
||||
// action, remoteClient.Name, userID);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All returns / deletes go to the object owner
|
||||
//
|
||||
userID = so.RootPart.OwnerID;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}",
|
||||
// action, userID);
|
||||
}
|
||||
|
||||
if (userID == UUID.Zero) // Can't proceed
|
||||
|
@ -638,11 +646,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
}
|
||||
|
||||
// Override and put into where it came from, if it came
|
||||
// from anywhere in inventory
|
||||
// from anywhere in inventory and the owner is taking it back.
|
||||
//
|
||||
if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
|
||||
{
|
||||
if (so.RootPart.FromFolderID != UUID.Zero)
|
||||
if (so.RootPart.FromFolderID != UUID.Zero && userID == remoteClient.AgentId)
|
||||
{
|
||||
InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID);
|
||||
folder = m_Scene.InventoryService.GetFolder(f);
|
||||
|
|
|
@ -29,8 +29,31 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
{
|
||||
interface IMonitor
|
||||
{
|
||||
double GetValue();
|
||||
/// <summary>
|
||||
/// Name of the monitor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the name used in XML.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
string GetName();
|
||||
string GetFriendlyValue(); // Convert to readable numbers
|
||||
|
||||
/// <summary>
|
||||
/// Value of this monitor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
double GetValue();
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable name of the monitor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetFriendlyName();
|
||||
|
||||
/// <summary>
|
||||
/// Human readable value.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetFriendlyValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
@ -32,6 +33,7 @@ using log4net;
|
|||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts;
|
||||
using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
@ -41,16 +43,50 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
{
|
||||
public class MonitorModule : IRegionModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Is this module enabled?
|
||||
/// </summary>
|
||||
public bool Enabled { get; private set; }
|
||||
|
||||
private Scene m_scene;
|
||||
private readonly List<IMonitor> m_monitors = new List<IMonitor>();
|
||||
private readonly List<IAlert> m_alerts = new List<IAlert>();
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
#region Implementation of IRegionModule
|
||||
|
||||
public MonitorModule()
|
||||
{
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource source)
|
||||
{
|
||||
IConfig cnfg = source.Configs["Monitoring"];
|
||||
|
||||
if (cnfg != null)
|
||||
Enabled = cnfg.GetBoolean("Enabled", true);
|
||||
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
m_scene = scene;
|
||||
|
||||
m_scene.AddCommand(this, "monitor report",
|
||||
"monitor report",
|
||||
"Returns a variety of statistics about the current region and/or simulator",
|
||||
DebugMonitors);
|
||||
|
||||
MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID, StatsPage);
|
||||
MainServer.Instance.AddHTTPHandler(
|
||||
"/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage);
|
||||
}
|
||||
|
||||
public void DebugMonitors(string module, string[] args)
|
||||
{
|
||||
foreach (IMonitor monitor in m_monitors)
|
||||
{
|
||||
m_log.Info("[MonitorModule] " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetName() + " = " + monitor.GetFriendlyValue());
|
||||
m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,20 +98,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
}
|
||||
}
|
||||
|
||||
#region Implementation of IRegionModule
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource source)
|
||||
{
|
||||
m_scene = scene;
|
||||
|
||||
m_scene.AddCommand(this, "monitor report",
|
||||
"monitor report",
|
||||
"Returns a variety of statistics about the current region and/or simulator",
|
||||
DebugMonitors);
|
||||
|
||||
MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID + "/", StatsPage);
|
||||
}
|
||||
|
||||
public Hashtable StatsPage(Hashtable request)
|
||||
{
|
||||
// If request was for a specific monitor
|
||||
|
@ -114,11 +136,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
string xml = "<data>";
|
||||
foreach (IMonitor monitor in m_monitors)
|
||||
{
|
||||
string elemName = monitor.ToString();
|
||||
if (elemName.StartsWith(monitor.GetType().Namespace))
|
||||
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
|
||||
|
||||
xml += "<" + elemName + ">" + monitor.GetValue() + "</" + elemName + ">";
|
||||
string elemName = monitor.GetName();
|
||||
xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
|
||||
// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
|
||||
}
|
||||
xml += "</data>";
|
||||
|
||||
|
@ -133,6 +153,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
|
||||
public void PostInitialise()
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
m_monitors.Add(new AgentCountMonitor(m_scene));
|
||||
m_monitors.Add(new ChildAgentCountMonitor(m_scene));
|
||||
m_monitors.Add(new GCMemoryMonitor());
|
||||
|
@ -145,6 +168,158 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
m_monitors.Add(new EventFrameMonitor(m_scene));
|
||||
m_monitors.Add(new LandFrameMonitor(m_scene));
|
||||
m_monitors.Add(new LastFrameTimeMonitor(m_scene));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"TimeDilationMonitor",
|
||||
"Time Dilation",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[0],
|
||||
m => m.GetValue().ToString()));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"SimFPSMonitor",
|
||||
"Sim FPS",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[1],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PhysicsFPSMonitor",
|
||||
"Physics FPS",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[2],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"AgentUpdatesPerSecondMonitor",
|
||||
"Agent Updates",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[3],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ObjectUpdatesPerSecondMonitor",
|
||||
"Object Updates",
|
||||
m => m.Scene.StatsReporter.LastReportedObjectUpdates,
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ActiveObjectCountMonitor",
|
||||
"Active Objects",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[7],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ActiveScriptsMonitor",
|
||||
"Active Scripts",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[19],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ScriptEventsPerSecondMonitor",
|
||||
"Script Events",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[20],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"InPacketsPerSecondMonitor",
|
||||
"In Packets",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[13],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"OutPacketsPerSecondMonitor",
|
||||
"Out Packets",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[14],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"UnackedBytesMonitor",
|
||||
"Unacked Bytes",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[15],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PendingDownloadsMonitor",
|
||||
"Pending Downloads",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[17],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PendingUploadsMonitor",
|
||||
"Pending Uploads",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[18],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"TotalFrameTimeMonitor",
|
||||
"Total Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[8],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"NetFrameTimeMonitor",
|
||||
"Net Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[9],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PhysicsFrameTimeMonitor",
|
||||
"Physics Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[10],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"SimulationFrameTimeMonitor",
|
||||
"Simulation Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[12],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"AgentFrameTimeMonitor",
|
||||
"Agent Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[16],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ImagesFrameTimeMonitor",
|
||||
"Images Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[11],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
|
||||
|
||||
|
@ -161,7 +336,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
|||
|
||||
public void Close()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public string Name
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "AgentCountMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.SceneGraph.GetRootAgentCount();
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Root Agent Count";
|
||||
}
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "ChildAgentCountMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.SceneGraph.GetChildAgentCount();
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Child Agent Count";
|
||||
}
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "EventFrameMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.MonitorEventTime;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Total Event Frame Time";
|
||||
}
|
||||
|
|
|
@ -33,12 +33,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
{
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "GCMemoryMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return GC.GetTotalMemory(false);
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "GC Reported Memory";
|
||||
}
|
||||
|
|
|
@ -26,43 +26,55 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
namespace OpenSim.Region.Examples.SimpleModule
|
||||
namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
||||
{
|
||||
public class CpuCounterObject : SceneObjectGroup
|
||||
class GenericMonitor : IMonitor
|
||||
{
|
||||
protected override bool InSceneBackup
|
||||
public Scene Scene { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public string FriendlyName { get; private set; }
|
||||
|
||||
private readonly Func<GenericMonitor, double> m_getValueAction;
|
||||
private readonly Func<GenericMonitor, string> m_getFriendlyValueAction;
|
||||
|
||||
public GenericMonitor(
|
||||
Scene scene,
|
||||
string name,
|
||||
string friendlyName,
|
||||
Func<GenericMonitor, double> getValueAction,
|
||||
Func<GenericMonitor, string> getFriendlyValueAction)
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Scene = scene;
|
||||
Name = name;
|
||||
FriendlyName = name;
|
||||
m_getFriendlyValueAction = getFriendlyValueAction;
|
||||
m_getValueAction = getValueAction;
|
||||
}
|
||||
|
||||
private PerformanceCounter m_counter;
|
||||
|
||||
public CpuCounterObject(UUID ownerID, Vector3 pos)
|
||||
: base(ownerID, pos, PrimitiveBaseShape.Default)
|
||||
public double GetValue()
|
||||
{
|
||||
String objectName = "Processor";
|
||||
String counterName = "% Processor Time";
|
||||
String instanceName = "_Total";
|
||||
|
||||
m_counter = new PerformanceCounter(objectName, counterName, instanceName);
|
||||
return m_getValueAction(this);
|
||||
}
|
||||
|
||||
public override void UpdateMovement()
|
||||
public string GetName()
|
||||
{
|
||||
float cpu = m_counter.NextValue()/40f;
|
||||
Vector3 size = new Vector3(cpu, cpu, cpu);
|
||||
return Name;
|
||||
}
|
||||
|
||||
RootPart.Resize(size);
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return FriendlyName;
|
||||
}
|
||||
|
||||
base.UpdateMovement();
|
||||
public string GetFriendlyValue()
|
||||
{
|
||||
return m_getFriendlyValueAction(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "LandFrameMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.MonitorLandTime;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Land Frame Time";
|
||||
}
|
||||
|
|
|
@ -41,12 +41,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "LastFrameTimeMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return Environment.TickCount - m_scene.MonitorLastFrameTick;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Last Completed Frame At";
|
||||
}
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "ObjectCountMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.SceneGraph.GetTotalObjectsCount();
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Total Objects Count";
|
||||
}
|
||||
|
|
|
@ -33,12 +33,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
{
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "PWSMemoryMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Private Working Set Memory";
|
||||
}
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "PhysicsFrameMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.MonitorPhysicsSyncTime + m_scene.MonitorPhysicsUpdateTime;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Total Physics Frame Time";
|
||||
}
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "PhysicsUpdateFrameMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.MonitorPhysicsUpdateTime;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Physics Update Frame Time";
|
||||
}
|
||||
|
|
|
@ -32,12 +32,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
{
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "ThreadCountMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return System.Diagnostics.Process.GetCurrentProcess().Threads.Count;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Total Threads";
|
||||
}
|
||||
|
|
|
@ -40,12 +40,17 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring.Monitors
|
|||
|
||||
#region Implementation of IMonitor
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return "TotalFrameMonitor";
|
||||
}
|
||||
|
||||
public double GetValue()
|
||||
{
|
||||
return m_scene.MonitorFrameTime;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return "Total Frame Time";
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ using Nwc.XmlRpc;
|
|||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Communications;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ using OpenMetaverse;
|
|||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using Caps=OpenSim.Framework.Capabilities.Caps;
|
||||
|
|
|
@ -396,9 +396,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
|||
{
|
||||
result = OpenJPEG.EncodeFromImage(joint, true);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
|
||||
m_log.ErrorFormat(
|
||||
"[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -34,6 +34,7 @@ using log4net;
|
|||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
@ -135,6 +136,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
|||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
|
||||
foreach (IScriptModule scriptModule in scriptModules)
|
||||
{
|
||||
scriptModule.OnScriptRemoved += ScriptRemoved;
|
||||
scriptModule.OnObjectRemoved += ObjectRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
|
@ -164,7 +171,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
|||
urlData.url = url;
|
||||
urlData.urlcode = urlcode;
|
||||
urlData.requests = new Dictionary<UUID, RequestData>();
|
||||
|
||||
|
||||
m_UrlMap[url] = urlData;
|
||||
|
||||
|
@ -280,6 +286,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
|||
|
||||
public void ScriptRemoved(UUID itemID)
|
||||
{
|
||||
// m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID);
|
||||
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
List<string> removeURLs = new List<string>();
|
||||
|
|
|
@ -338,10 +338,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
|||
{
|
||||
imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(
|
||||
"[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
|
||||
m_log.ErrorFormat(
|
||||
"[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
m_textureManager.ReturnData(id, imageJ2000);
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Server.Base;
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Server.Base;
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Server.Base;
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Server.Base;
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Server.Base;
|
||||
|
@ -59,9 +60,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory
|
|||
{
|
||||
m_log.Info("[INVENTORY IN CONNECTOR]: Inventory Service In Connector enabled");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Server.Base;
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Collections.Generic;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Server.Base;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue