diff options
Diffstat (limited to 'tools/mass test client/ClientManager.cs')
-rw-r--r-- | tools/mass test client/ClientManager.cs | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/tools/mass test client/ClientManager.cs b/tools/mass test client/ClientManager.cs new file mode 100644 index 0000000..a6e784c --- /dev/null +++ b/tools/mass test client/ClientManager.cs | |||
@@ -0,0 +1,323 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Reflection; | ||
4 | using System.Xml; | ||
5 | using System.Threading; | ||
6 | using libsecondlife; | ||
7 | using libsecondlife.Packets; | ||
8 | using libsecondlife.AssetSystem; | ||
9 | |||
10 | namespace libsecondlife.TestClient | ||
11 | { | ||
12 | public class LoginDetails | ||
13 | { | ||
14 | public string FirstName; | ||
15 | public string LastName; | ||
16 | public string Password; | ||
17 | public string StartLocation; | ||
18 | public string MasterName; | ||
19 | public LLUUID MasterKey; | ||
20 | public string LoginURI; | ||
21 | } | ||
22 | |||
23 | public class StartPosition | ||
24 | { | ||
25 | public string sim; | ||
26 | public int x; | ||
27 | public int y; | ||
28 | public int z; | ||
29 | |||
30 | public StartPosition() | ||
31 | { | ||
32 | this.sim = null; | ||
33 | this.x = 0; | ||
34 | this.y = 0; | ||
35 | this.z = 0; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | public class ClientManager | ||
40 | { | ||
41 | public Dictionary<LLUUID, SecondLife> Clients = new Dictionary<LLUUID, SecondLife>(); | ||
42 | public Dictionary<Simulator, Dictionary<uint, Primitive>> SimPrims = new Dictionary<Simulator, Dictionary<uint, Primitive>>(); | ||
43 | |||
44 | public bool Running = true; | ||
45 | |||
46 | string contactPerson = String.Empty; | ||
47 | private LLUUID resolvedMasterKey = LLUUID.Zero; | ||
48 | private ManualResetEvent keyResolution = new ManualResetEvent(false); | ||
49 | |||
50 | /// <summary> | ||
51 | /// | ||
52 | /// </summary> | ||
53 | /// <param name="accounts"></param> | ||
54 | public ClientManager(List<LoginDetails> accounts, string c) | ||
55 | { | ||
56 | this.contactPerson = c; | ||
57 | foreach (LoginDetails account in accounts) | ||
58 | Login(account); | ||
59 | } | ||
60 | |||
61 | public ClientManager(List<LoginDetails> accounts, string c, string s) | ||
62 | { | ||
63 | this.contactPerson = c; | ||
64 | char sep = '/'; | ||
65 | string[] startbits = s.Split(sep); | ||
66 | |||
67 | foreach (LoginDetails account in accounts) | ||
68 | { | ||
69 | account.StartLocation = NetworkManager.StartLocation(startbits[0], Int32.Parse(startbits[1]), | ||
70 | Int32.Parse(startbits[2]), Int32.Parse(startbits[3])); | ||
71 | Login(account); | ||
72 | } | ||
73 | } | ||
74 | /// <summary> | ||
75 | /// | ||
76 | /// </summary> | ||
77 | /// <param name="account"></param> | ||
78 | /// <returns></returns> | ||
79 | public TestClient Login(LoginDetails account) | ||
80 | { | ||
81 | |||
82 | // Check if this client is already logged in | ||
83 | foreach (TestClient c in Clients.Values) | ||
84 | { | ||
85 | if (c.Self.FirstName == account.FirstName && c.Self.LastName == account.LastName) | ||
86 | { | ||
87 | Logout(c); | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | TestClient client = new TestClient(this); | ||
93 | |||
94 | // Optimize the throttle | ||
95 | client.Throttle.Wind = 0; | ||
96 | client.Throttle.Cloud = 0; | ||
97 | client.Throttle.Land = 1000000; | ||
98 | client.Throttle.Task = 1000000; | ||
99 | |||
100 | client.SimPrims = SimPrims; | ||
101 | client.MasterName = account.MasterName; | ||
102 | client.MasterKey = account.MasterKey; | ||
103 | |||
104 | libsecondlife.NetworkManager.LoginParams loginParams = new NetworkManager.LoginParams(); | ||
105 | loginParams.FirstName = account.FirstName; | ||
106 | loginParams.LastName = account.LastName; | ||
107 | loginParams.Password = account.Password; | ||
108 | loginParams.UserAgent = "MassTestClient"; | ||
109 | loginParams.Start = account.StartLocation; | ||
110 | loginParams.Author = contactPerson; | ||
111 | loginParams.URI = account.LoginURI; | ||
112 | |||
113 | |||
114 | if (!client.Network.Login(loginParams)) | ||
115 | { | ||
116 | Console.WriteLine("Failed to login " + account.FirstName + " " + account.LastName + ": " + | ||
117 | client.Network.LoginMessage); | ||
118 | } | ||
119 | |||
120 | |||
121 | if (client.Network.Connected) | ||
122 | { | ||
123 | if (account.MasterKey == LLUUID.Zero && !String.IsNullOrEmpty(account.MasterName)) | ||
124 | { | ||
125 | Console.WriteLine("Resolving {0}'s UUID", account.MasterName); | ||
126 | // Find master's key from name | ||
127 | DirectoryManager.DirPeopleReplyCallback callback = new DirectoryManager.DirPeopleReplyCallback(KeyResolvHandler); | ||
128 | client.Directory.OnDirPeopleReply += callback; | ||
129 | client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, account.MasterName, 0); | ||
130 | if (keyResolution.WaitOne(TimeSpan.FromMinutes(1), false)) | ||
131 | { | ||
132 | account.MasterKey = resolvedMasterKey; | ||
133 | Console.WriteLine("\"{0}\" resolved to {1}", account.MasterName, account.MasterKey); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | Console.WriteLine("Unable to obtain UUID for \"{0}\". No master will be used. Try specifying a key with --masterkey.", account.MasterName); | ||
138 | } | ||
139 | client.Directory.OnDirPeopleReply -= callback; | ||
140 | keyResolution.Reset(); | ||
141 | } | ||
142 | |||
143 | client.MasterKey = account.MasterKey; | ||
144 | |||
145 | Clients[client.Network.AgentID] = client; | ||
146 | |||
147 | Console.WriteLine("Logged in " + client.ToString()); | ||
148 | } | ||
149 | |||
150 | return client; | ||
151 | } | ||
152 | |||
153 | private void KeyResolvHandler(LLUUID queryid, List<DirectoryManager.AgentSearchData> matches) | ||
154 | { | ||
155 | LLUUID master = matches[0].AgentID; | ||
156 | if (matches.Count > 1) | ||
157 | { | ||
158 | Console.WriteLine("Possible masters:"); | ||
159 | for (int i = 0; i < matches.Count; ++i) | ||
160 | { | ||
161 | Console.WriteLine("{0}: {1}", i, matches[i].FirstName + " " + matches[i].LastName); | ||
162 | } | ||
163 | Console.Write("Ambiguous master, choose one:"); | ||
164 | string read = Console.ReadLine(); | ||
165 | while (read != null) | ||
166 | { | ||
167 | int choice = 0; | ||
168 | if (int.TryParse(read, out choice)) | ||
169 | { | ||
170 | master = matches[choice].AgentID; | ||
171 | break; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | Console.WriteLine("Responce misunderstood."); | ||
176 | Console.Write("Type the corresponding number:"); | ||
177 | } | ||
178 | read = Console.ReadLine(); | ||
179 | } | ||
180 | } | ||
181 | resolvedMasterKey = master; | ||
182 | keyResolution.Set(); | ||
183 | } | ||
184 | |||
185 | /// <summary> | ||
186 | /// | ||
187 | /// </summary> | ||
188 | /// <param name="args"></param> | ||
189 | /// <returns></returns> | ||
190 | public TestClient Login(string[] args) | ||
191 | { | ||
192 | LoginDetails account = new LoginDetails(); | ||
193 | account.FirstName = args[0]; | ||
194 | account.LastName = args[1]; | ||
195 | account.Password = args[2]; | ||
196 | |||
197 | if (args.Length == 4) | ||
198 | { | ||
199 | account.StartLocation = NetworkManager.StartLocation(args[3], 128, 128, 40); | ||
200 | } | ||
201 | |||
202 | return Login(account); | ||
203 | } | ||
204 | |||
205 | /// <summary> | ||
206 | /// | ||
207 | /// </summary> | ||
208 | public void Run(List<string> massTestCommands) | ||
209 | { | ||
210 | Console.WriteLine("Type quit to exit. Type help for a command list."); | ||
211 | |||
212 | if (massTestCommands.Count == 0) | ||
213 | { | ||
214 | while (Running) | ||
215 | { | ||
216 | PrintPrompt(); | ||
217 | string input = Console.ReadLine(); | ||
218 | DoCommandAll(input, null, null); | ||
219 | } | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | int currentCommand = 0; | ||
224 | while (Running) | ||
225 | { | ||
226 | DoCommandAll(massTestCommands[currentCommand], null, null); | ||
227 | currentCommand++; | ||
228 | if (massTestCommands.Count >= currentCommand) | ||
229 | { | ||
230 | currentCommand = 0; | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | |||
235 | foreach (SecondLife client in Clients.Values) | ||
236 | { | ||
237 | if (client.Network.Connected) | ||
238 | client.Network.Logout(); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | private void PrintPrompt() | ||
243 | { | ||
244 | int online = 0; | ||
245 | |||
246 | foreach (SecondLife client in Clients.Values) | ||
247 | { | ||
248 | if (client.Network.Connected) online++; | ||
249 | } | ||
250 | |||
251 | Console.Write(online + " avatars online> "); | ||
252 | } | ||
253 | |||
254 | /// <summary> | ||
255 | /// | ||
256 | /// </summary> | ||
257 | /// <param name="cmd"></param> | ||
258 | /// <param name="fromAgentID"></param> | ||
259 | /// <param name="imSessionID"></param> | ||
260 | public void DoCommandAll(string cmd, LLUUID fromAgentID, LLUUID imSessionID) | ||
261 | { | ||
262 | string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' }); | ||
263 | string firstToken = tokens[0].ToLower(); | ||
264 | |||
265 | if (tokens.Length == 0) | ||
266 | return; | ||
267 | |||
268 | if (firstToken == "login") | ||
269 | { | ||
270 | // Special login case: Only call it once, and allow it with | ||
271 | // no logged in avatars | ||
272 | string[] args = new string[tokens.Length - 1]; | ||
273 | Array.Copy(tokens, 1, args, 0, args.Length); | ||
274 | Login(args); | ||
275 | } | ||
276 | else if (firstToken == "quit") | ||
277 | { | ||
278 | Quit(); | ||
279 | Console.WriteLine("All clients logged out and program finished running."); | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | // make a copy of the clients list so that it can be iterated without fear of being changed during iteration | ||
284 | Dictionary<LLUUID, SecondLife> clientsCopy = new Dictionary<LLUUID, SecondLife>(Clients); | ||
285 | |||
286 | foreach (TestClient client in clientsCopy.Values) | ||
287 | client.DoCommand(cmd, fromAgentID, imSessionID); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /// <summary> | ||
292 | /// | ||
293 | /// </summary> | ||
294 | /// <param name="client"></param> | ||
295 | public void Logout(TestClient client) | ||
296 | { | ||
297 | Clients.Remove(client.Network.AgentID); | ||
298 | client.Network.Logout(); | ||
299 | } | ||
300 | |||
301 | /// <summary> | ||
302 | /// | ||
303 | /// </summary> | ||
304 | public void LogoutAll() | ||
305 | { | ||
306 | // make a copy of the clients list so that it can be iterated without fear of being changed during iteration | ||
307 | Dictionary<LLUUID, SecondLife> clientsCopy = new Dictionary<LLUUID, SecondLife>(Clients); | ||
308 | |||
309 | foreach (TestClient client in clientsCopy.Values) | ||
310 | Logout(client); | ||
311 | } | ||
312 | |||
313 | /// <summary> | ||
314 | /// | ||
315 | /// </summary> | ||
316 | public void Quit() | ||
317 | { | ||
318 | LogoutAll(); | ||
319 | Running = false; | ||
320 | // TODO: It would be really nice if we could figure out a way to abort the ReadLine here in so that Run() will exit. | ||
321 | } | ||
322 | } | ||
323 | } | ||