public TestResult StartTest() { Debug.Assert(m_protocol==ProtocolType.Tcp || m_protocol==ProtocolType.Udp); m_poller = new SocketPoller(); m_testResult = new TestResult(); m_testResult.Protocol = m_protocol; // 소켓 준비 m_requester = Function.CreateSocket(m_protocol, null, m_protocol == ProtocolType.Tcp); m_testResult.PrivateAddress_1 = (IPEndPoint)m_requester.LocalEndPoint; if (m_protocol == ProtocolType.Udp) { // UDP는 하나의 소켓으로 모두 처리한다. m_poller.Start(m_requester); } else { Function.CreateListenr(m_testResult.PrivateAddress_1, m_poller, true); } // 테스트 수행 try { // Step 1. Filtering Behavior Test if (Step1()) return m_testResult; Debug.Assert(m_testResult.Exist_NAT); Debug.Assert(m_testResult.FilteringBehavior != TestResult.Behavior.None); // Step 2. Mapping Behavior Test (1) : APDM인지 여부를 테스트. if (m_testResult.PublicAddress_2 == null) { if (Step2()) return m_testResult; } // Step 3. Mapping Behavior Test (2) : EIM인지 ADM인지 여부를 테스트. if (m_testResult.MappingBehavior == TestResult.Behavior.None) { Debug.Assert(m_testResult.PublicAddress_1.Equals(m_testResult.PublicAddress_2)); if (Step3()) return m_testResult; } Debug.Assert(m_testResult.MappingBehavior != TestResult.Behavior.None); // Step 4. Hairpin Test Step4(); // 완료 m_testResult.Complete = true; return m_testResult; } finally { m_poller.Stop(); } }
public void Start() { Socket tcpSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Socket udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); tcpSock.Bind(m_tcp); udpSock.Bind(m_udp); m_poller = new SocketPoller(); m_poller.Start_Acceptor(tcpSock); m_poller.Start(udpSock); m_run = true; m_thread = new Thread((object a_data) => { while (m_run) { Message msg; Socket sock; IPEndPoint sender; bool isTimeout = ! m_poller.WaitForMessage(Config.Server_Poll_Timeout_Ms, out msg, out sock, out sender); if (isTimeout) continue; string protocolName; if (sock.ProtocolType == ProtocolType.Tcp) { protocolName = "[TCP] "; } else { Debug.Assert(sock.Equals(udpSock)); protocolName = "[UDP] "; } bool isHeartbeatMessage = msg.m_contextID == 0; IPEndPoint dst; if (msg.AddressIsEmpty() || isHeartbeatMessage) { // Client로부터 직접 요청을 받은 경우 dst = sender; msg.m_address = sender.Address.ToString(); msg.m_port = sender.Port; } else { // Client의 요청을 MainServer로부터 전달받은 경우 dst = new IPEndPoint(IPAddress.Parse(msg.m_address), msg.m_port); msg.m_address = dst.Address.ToString(); msg.m_port = dst.Port; } ++msg.m_contextSeq; msg.m_senderType = Message.SenderType.SubServer; if (isHeartbeatMessage) { // Heartbeat 메시지인 경우 if (sock.ProtocolType == ProtocolType.Udp) m_poller.SendTo(sock, dst, msg, false); else m_poller.Send(sock, msg, false); } else { // Request 메시지인 경우 string ctxstr = " " + Message.ContextString(msg); Config.OnEventDelegate(protocolName + "Requested from " + sender.ToString() + ctxstr); Config.OnEventDelegate(protocolName + "Response to " + dst.ToString() + ctxstr); if (sock.ProtocolType == ProtocolType.Udp) m_poller.SendTo(sock, dst, msg, false); else { Socket newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (m_poller.ConnectAndSend(newSocket, dst, msg) == false) Config.OnEventDelegate(protocolName + "Failed Response" + ctxstr); m_poller.Close(sock); } } } }); m_thread.Start(); }