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