diff options
author | Justin Clarke Casey | 2008-10-24 21:22:54 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2008-10-24 21:22:54 +0000 |
commit | 3340a579e72f1248bb092a705db068027e46ef75 (patch) | |
tree | de14319e2adc598dff0fd7557fc4f9d807ac55a2 | |
parent | un-double-flipped some double-flipped normals in circular path prim end caps (diff) | |
download | opensim-SC_OLD-3340a579e72f1248bb092a705db068027e46ef75.zip opensim-SC_OLD-3340a579e72f1248bb092a705db068027e46ef75.tar.gz opensim-SC_OLD-3340a579e72f1248bb092a705db068027e46ef75.tar.bz2 opensim-SC_OLD-3340a579e72f1248bb092a705db068027e46ef75.tar.xz |
* Stop creating a circuit if the client fails authentication (i.e. the region server wasn't told that it was coming)
* This moves authentication from the client thread (where failure was difficult to detect) to the particular thread handling that packet
* I've kept the authentication outside of the crucial clientCircuits lock (though any delay here is probably swamped by the other delays associated with login)
* Also added more to the unit test to ensure this doesn't regress
Diffstat (limited to '')
5 files changed, 110 insertions, 69 deletions
diff --git a/OpenSim/Framework/AgentCircuitManager.cs b/OpenSim/Framework/AgentCircuitManager.cs index a73e86d..5fd7219 100644 --- a/OpenSim/Framework/AgentCircuitManager.cs +++ b/OpenSim/Framework/AgentCircuitManager.cs | |||
@@ -63,6 +63,7 @@ namespace OpenSim.Framework | |||
63 | user.LoginInfo.Last = validcircuit.lastname; | 63 | user.LoginInfo.Last = validcircuit.lastname; |
64 | user.LoginInfo.InventoryFolder = validcircuit.InventoryFolder; | 64 | user.LoginInfo.InventoryFolder = validcircuit.InventoryFolder; |
65 | user.LoginInfo.BaseFolder = validcircuit.BaseFolder; | 65 | user.LoginInfo.BaseFolder = validcircuit.BaseFolder; |
66 | user.LoginInfo.StartPos = validcircuit.startpos; | ||
66 | } | 67 | } |
67 | else | 68 | else |
68 | { | 69 | { |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index fc76086..b517c13 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -105,7 +105,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
105 | protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); | 105 | protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); |
106 | 106 | ||
107 | protected IScene m_scene; | 107 | protected IScene m_scene; |
108 | protected AgentCircuitManager m_authenticateSessionsHandler; | ||
109 | 108 | ||
110 | protected LLPacketServer m_networkServer; | 109 | protected LLPacketServer m_networkServer; |
111 | 110 | ||
@@ -409,7 +408,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
409 | /// <param name="proxyEP"></param> | 408 | /// <param name="proxyEP"></param> |
410 | public LLClientView( | 409 | public LLClientView( |
411 | EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, | 410 | EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, |
412 | AgentCircuitManager authenSessions, UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP, | 411 | AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP, |
413 | ClientStackUserSettings userSettings) | 412 | ClientStackUserSettings userSettings) |
414 | { | 413 | { |
415 | m_moneyBalance = 1000; | 414 | m_moneyBalance = 1000; |
@@ -422,17 +421,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
422 | m_assetCache = assetCache; | 421 | m_assetCache = assetCache; |
423 | 422 | ||
424 | m_networkServer = packServer; | 423 | m_networkServer = packServer; |
425 | // m_inventoryCache = inventoryCache; | ||
426 | m_authenticateSessionsHandler = authenSessions; | ||
427 | 424 | ||
428 | m_agentId = agentId; | 425 | m_agentId = agentId; |
429 | m_sessionId = sessionId; | 426 | m_sessionId = sessionId; |
430 | m_circuitCode = circuitCode; | 427 | m_circuitCode = circuitCode; |
431 | 428 | ||
432 | m_userEndPoint = remoteEP; | 429 | m_userEndPoint = remoteEP; |
433 | m_proxyEndPoint = proxyEP; | 430 | m_proxyEndPoint = proxyEP; |
431 | |||
432 | m_firstName = sessionInfo.LoginInfo.First; | ||
433 | m_lastName = sessionInfo.LoginInfo.Last; | ||
434 | m_startpos = sessionInfo.LoginInfo.StartPos; | ||
434 | 435 | ||
435 | m_startpos = m_authenticateSessionsHandler.GetPosition(circuitCode); | 436 | if (sessionInfo.LoginInfo.SecureSession != UUID.Zero) |
437 | { | ||
438 | m_secureSessionId = sessionInfo.LoginInfo.SecureSession; | ||
439 | } | ||
436 | 440 | ||
437 | // While working on this, the BlockingQueue had me fooled for a bit. | 441 | // While working on this, the BlockingQueue had me fooled for a bit. |
438 | // The Blocking queue causes the thread to stop until there's something | 442 | // The Blocking queue causes the thread to stop until there's something |
@@ -444,7 +448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
444 | 448 | ||
445 | RegisterLocalPacketHandlers(); | 449 | RegisterLocalPacketHandlers(); |
446 | 450 | ||
447 | m_clientThread = new Thread(new ThreadStart(AuthUser)); | 451 | m_clientThread = new Thread(new ThreadStart(Start)); |
448 | m_clientThread.Name = "ClientThread"; | 452 | m_clientThread.Name = "ClientThread"; |
449 | m_clientThread.IsBackground = true; | 453 | m_clientThread.IsBackground = true; |
450 | m_clientThread.Start(); | 454 | m_clientThread.Start(); |
@@ -759,9 +763,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
759 | } | 763 | } |
760 | 764 | ||
761 | /// <summary> | 765 | /// <summary> |
762 | /// Authorize an incoming user session. This method lies at the base of the entire client thread. | 766 | /// Start a user session. This method lies at the base of the entire client thread. |
763 | /// </summary> | 767 | /// </summary> |
764 | protected virtual void AuthUser() | 768 | protected virtual void Start() |
765 | { | 769 | { |
766 | //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) | 770 | //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) |
767 | //otherwise it will override this and use the system default | 771 | //otherwise it will override this and use the system default |
@@ -769,37 +773,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
769 | 773 | ||
770 | try | 774 | try |
771 | { | 775 | { |
772 | // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(m_cirpack.m_circuitCode.m_sessionId, m_cirpack.m_circuitCode.ID, m_cirpack.m_circuitCode.Code); | 776 | // This sets up all the timers |
773 | AuthenticateResponse sessionInfo = | 777 | InitNewClient(); |
774 | m_authenticateSessionsHandler.AuthenticateSession(m_sessionId, m_agentId, m_circuitCode); | 778 | ClientLoop(); |
775 | |||
776 | if (!sessionInfo.Authorised) | ||
777 | { | ||
778 | //session/circuit not authorised | ||
779 | m_log.WarnFormat( | ||
780 | "[CLIENT]: New user request denied to avatar {0} connecting with circuit code {1} from {2}", | ||
781 | m_agentId, m_circuitCode, m_userEndPoint); | ||
782 | |||
783 | m_PacketHandler.Stop(); | ||
784 | m_clientThread.Abort(); | ||
785 | } | ||
786 | else | ||
787 | { | ||
788 | m_log.Info("[CLIENT]: Got authenticated connection from " + m_userEndPoint.ToString()); | ||
789 | //session is authorised | ||
790 | m_firstName = sessionInfo.LoginInfo.First; | ||
791 | m_lastName = sessionInfo.LoginInfo.Last; | ||
792 | |||
793 | if (sessionInfo.LoginInfo.SecureSession != UUID.Zero) | ||
794 | { | ||
795 | m_secureSessionId = sessionInfo.LoginInfo.SecureSession; | ||
796 | } | ||
797 | |||
798 | // This sets up all the timers | ||
799 | InitNewClient(); | ||
800 | |||
801 | ClientLoop(); | ||
802 | } | ||
803 | } | 779 | } |
804 | catch (System.Exception e) | 780 | catch (System.Exception e) |
805 | { | 781 | { |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs index 5d3dba0..e3a02bc 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | using System.Net; | 28 | using System.Net; |
29 | using System.Net.Sockets; | 29 | using System.Net.Sockets; |
30 | using System.Reflection; | ||
31 | using log4net; | ||
30 | using OpenMetaverse; | 32 | using OpenMetaverse; |
31 | using OpenMetaverse.Packets; | 33 | using OpenMetaverse.Packets; |
32 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
@@ -36,8 +38,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
36 | { | 38 | { |
37 | public class LLPacketServer | 39 | public class LLPacketServer |
38 | { | 40 | { |
39 | //private static readonly log4net.ILog m_log | 41 | private static readonly log4net.ILog m_log |
40 | // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 42 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
41 | 43 | ||
42 | protected readonly ILLClientStackNetworkHandler m_networkHandler; | 44 | protected readonly ILLClientStackNetworkHandler m_networkHandler; |
43 | protected IScene m_scene; | 45 | protected IScene m_scene; |
@@ -87,49 +89,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
87 | /// <returns></returns> | 89 | /// <returns></returns> |
88 | protected virtual IClientAPI CreateNewCircuit(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, | 90 | protected virtual IClientAPI CreateNewCircuit(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, |
89 | ClientManager clientManager, IScene scene, AssetCache assetCache, | 91 | ClientManager clientManager, IScene scene, AssetCache assetCache, |
90 | LLPacketServer packServer, AgentCircuitManager authenSessions, | 92 | LLPacketServer packServer, AuthenticateResponse sessionInfo, |
91 | UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP) | 93 | UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP) |
92 | { | 94 | { |
93 | return | 95 | return |
94 | new LLClientView( | 96 | new LLClientView( |
95 | remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode, proxyEP, | 97 | remoteEP, scene, assetCache, packServer, sessionInfo, agentId, sessionId, circuitCode, proxyEP, |
96 | m_userSettings); | 98 | m_userSettings); |
97 | } | 99 | } |
98 | 100 | ||
99 | /// <summary> | 101 | /// <summary> |
102 | /// Check whether a given client is authorized to connect | ||
103 | /// </summary> | ||
104 | /// <param name="useCircuit"></param> | ||
105 | /// <param name="circuitManager"></param> | ||
106 | /// <returns></returns> | ||
107 | public virtual bool IsClientAuthorized( | ||
108 | UseCircuitCodePacket useCircuit, AgentCircuitManager circuitManager, out AuthenticateResponse sessionInfo) | ||
109 | { | ||
110 | UUID agentId = useCircuit.CircuitCode.ID; | ||
111 | UUID sessionId = useCircuit.CircuitCode.SessionID; | ||
112 | uint circuitCode = useCircuit.CircuitCode.Code; | ||
113 | |||
114 | sessionInfo = circuitManager.AuthenticateSession(sessionId, agentId, circuitCode); | ||
115 | |||
116 | if (!sessionInfo.Authorised) | ||
117 | return false; | ||
118 | |||
119 | return true; | ||
120 | } | ||
121 | |||
122 | /// <summary> | ||
100 | /// Add a new client circuit | 123 | /// Add a new client circuit |
101 | /// </summary> | 124 | /// </summary> |
102 | /// <param name="epSender"></param> | 125 | /// <param name="epSender"></param> |
103 | /// <param name="useCircuit"></param> | 126 | /// <param name="useCircuit"></param> |
104 | /// <param name="assetCache"></param> | 127 | /// <param name="assetCache"></param> |
105 | /// <param name="circuitManager"></param> | 128 | /// <param name="sessionInfo"></param> |
106 | /// <param name="proxyEP"></param> | 129 | /// <param name="proxyEP"></param> |
107 | /// <returns> | 130 | /// <returns> |
108 | /// true if a new circuit was created, false if a circuit with the given circuit code already existed | 131 | /// true if a new circuit was created, false if a circuit with the given circuit code already existed |
109 | /// </returns> | 132 | /// </returns> |
110 | public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache, | 133 | public virtual bool AddNewClient( |
111 | AgentCircuitManager circuitManager, EndPoint proxyEP) | 134 | EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache, |
135 | AuthenticateResponse sessionInfo, EndPoint proxyEP) | ||
112 | { | 136 | { |
113 | IClientAPI newuser; | 137 | IClientAPI newuser; |
114 | 138 | uint circuitCode = useCircuit.CircuitCode.Code; | |
115 | if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser)) | 139 | |
140 | if (m_scene.ClientManager.TryGetClient(circuitCode, out newuser)) | ||
116 | { | 141 | { |
142 | // The circuit is already known to the scene. This not actually a problem since this will currently | ||
143 | // occur if a client is crossing borders (hence upgrading its circuit). However, we shouldn't | ||
144 | // really by trying to add a new client if this is the case. | ||
117 | return false; | 145 | return false; |
118 | } | 146 | } |
119 | else | 147 | |
120 | { | 148 | UUID agentId = useCircuit.CircuitCode.ID; |
121 | newuser = CreateNewCircuit(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this, | 149 | UUID sessionId = useCircuit.CircuitCode.SessionID; |
122 | circuitManager, useCircuit.CircuitCode.ID, | 150 | |
123 | useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code, proxyEP); | 151 | newuser |
152 | = CreateNewCircuit( | ||
153 | epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this, sessionInfo, | ||
154 | agentId, sessionId, circuitCode, proxyEP); | ||
124 | 155 | ||
125 | m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser); | 156 | m_scene.ClientManager.Add(circuitCode, newuser); |
126 | 157 | ||
127 | newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; | 158 | newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; |
128 | newuser.OnLogout += LogoutHandler; | 159 | newuser.OnLogout += LogoutHandler; |
129 | newuser.OnConnectionClosed += CloseClient; | 160 | newuser.OnConnectionClosed += CloseClient; |
130 | 161 | ||
131 | return true; | 162 | return true; |
132 | } | ||
133 | } | 163 | } |
134 | 164 | ||
135 | public void LogoutHandler(IClientAPI client) | 165 | public void LogoutHandler(IClientAPI client) |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 2e9af74..40b4a42 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -385,11 +385,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
385 | //Slave regions don't accept new clients | 385 | //Slave regions don't accept new clients |
386 | if (m_localScene.Region_Status != RegionStatus.SlaveScene) | 386 | if (m_localScene.Region_Status != RegionStatus.SlaveScene) |
387 | { | 387 | { |
388 | AuthenticateResponse sessionInfo; | ||
388 | bool isNewCircuit = false; | 389 | bool isNewCircuit = false; |
389 | 390 | ||
391 | if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo)) | ||
392 | { | ||
393 | m_log.WarnFormat( | ||
394 | "[CLIENT]: New user request denied to avatar {0} connecting with unauthorized circuit code {1} from {2}", | ||
395 | useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, epSender); | ||
396 | |||
397 | return; | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | m_log.Info("[CLIENT]: Got authenticated connection from " + epSender); | ||
402 | } | ||
403 | |||
390 | lock (clientCircuits) | 404 | lock (clientCircuits) |
391 | { | 405 | { |
392 | if (!clientCircuits.ContainsKey(epSender)) | 406 | if (!clientCircuits.ContainsKey(epSender)) |
393 | { | 407 | { |
394 | m_log.DebugFormat( | 408 | m_log.DebugFormat( |
395 | "[CLIENT]: Adding new circuit for agent {0}, circuit code {1}", | 409 | "[CLIENT]: Adding new circuit for agent {0}, circuit code {1}", |
@@ -409,8 +423,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
409 | { | 423 | { |
410 | proxyCircuits[useCircuit.CircuitCode.Code] = epProxy; | 424 | proxyCircuits[useCircuit.CircuitCode.Code] = epProxy; |
411 | } | 425 | } |
412 | 426 | ||
413 | m_packetServer.AddNewClient(epSender, useCircuit, m_assetCache, m_circuitManager, epProxy); | 427 | m_packetServer.AddNewClient(epSender, useCircuit, m_assetCache, sessionInfo, epProxy); |
414 | } | 428 | } |
415 | } | 429 | } |
416 | 430 | ||
@@ -533,6 +547,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
533 | useCircuit.CircuitCode.Code = circuit.circuitcode; | 547 | useCircuit.CircuitCode.Code = circuit.circuitcode; |
534 | useCircuit.CircuitCode.ID = circuit.AgentID; | 548 | useCircuit.CircuitCode.ID = circuit.AgentID; |
535 | useCircuit.CircuitCode.SessionID = circuit.SessionID; | 549 | useCircuit.CircuitCode.SessionID = circuit.SessionID; |
550 | |||
551 | AuthenticateResponse sessionInfo; | ||
552 | |||
553 | if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo)) | ||
554 | { | ||
555 | m_log.WarnFormat( | ||
556 | "[CLIENT]: Restore request denied to avatar {0} connecting with unauthorized circuit code {1}", | ||
557 | useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code); | ||
558 | |||
559 | return; | ||
560 | } | ||
536 | 561 | ||
537 | lock (clientCircuits) | 562 | lock (clientCircuits) |
538 | { | 563 | { |
@@ -562,7 +587,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
562 | } | 587 | } |
563 | } | 588 | } |
564 | 589 | ||
565 | m_packetServer.AddNewClient(userEP, useCircuit, m_assetCache, m_circuitManager, proxyEP); | 590 | m_packetServer.AddNewClient(userEP, useCircuit, m_assetCache, sessionInfo, proxyEP); |
566 | } | 591 | } |
567 | } | 592 | } |
568 | } | 593 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/LindenUDP/Tests/BasicCircuitTests.cs index c90aecf..819e4e8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/Tests/BasicCircuitTests.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System.Net; | 28 | using System.Net; |
29 | //using System.Threading; | ||
29 | using log4net; | 30 | using log4net; |
30 | using NUnit.Framework; | 31 | using NUnit.Framework; |
31 | using OpenMetaverse; | 32 | using OpenMetaverse; |
@@ -69,8 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
69 | AgentCircuitManager acm = new AgentCircuitManager(); | 70 | AgentCircuitManager acm = new AgentCircuitManager(); |
70 | AgentCircuitData acd = new AgentCircuitData(); | 71 | AgentCircuitData acd = new AgentCircuitData(); |
71 | acd.AgentID = myAgentUuid; | 72 | acd.AgentID = myAgentUuid; |
72 | acd.SessionID = mySessionUuid; | 73 | acd.SessionID = mySessionUuid; |
73 | acm.AddNewCircuit(myCircuitCode, acd); | ||
74 | 74 | ||
75 | uint port = 666; | 75 | uint port = 666; |
76 | testLLUDPServer.Initialise(null, ref port, 0, false, userSettings, null, acm); | 76 | testLLUDPServer.Initialise(null, ref port, 0, false, userSettings, null, acm); |
@@ -89,10 +89,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
89 | EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); | 89 | EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); |
90 | 90 | ||
91 | testLLUDPServer.LoadReceive(uccp, testEp); | 91 | testLLUDPServer.LoadReceive(uccp, testEp); |
92 | testLLUDPServer.ReceiveData(null); | 92 | testLLUDPServer.ReceiveData(null); |
93 | 93 | ||
94 | Assert.IsFalse(testLLUDPServer.HasCircuit(101)); | 94 | // Circuit shouildn't exist since the circuit manager doesn't know about this circuit for authentication yet |
95 | Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode)); | ||
96 | |||
97 | acm.AddNewCircuit(myCircuitCode, acd); | ||
98 | |||
99 | testLLUDPServer.LoadReceive(uccp, testEp); | ||
100 | testLLUDPServer.ReceiveData(null); | ||
101 | |||
102 | // Should succeed now | ||
95 | Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode)); | 103 | Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode)); |
104 | Assert.IsFalse(testLLUDPServer.HasCircuit(101)); | ||
96 | } | 105 | } |
97 | } | 106 | } |
98 | } | 107 | } |