/// <summary> /// Try to establish a connection with the current tcpEndPoint. /// </summary> bool ConnectToTcpEndPoint() { if (tcpEndPoint != null) { stage = Stage.Connecting; try { lock (mConnecting) { mSocket = new Socket(tcpEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); mConnecting.Add(mSocket); } var result = mSocket.BeginConnect(tcpEndPoint, OnConnectResult, mSocket); var th = Tools.CreateThread(CancelConnect); th.Start(result); return(true); } catch (System.Exception ex) { AddError(ex); } } else { AddError("Unable to resolve the specified address"); } return(false); }
/// <summary> /// Stop port forwarding that was set up earlier. /// </summary> void Close(int port, bool tcp, OnPortRequest callback) { int id = (port << 8) | (tcp ? 1 : 0); if (port > 0 && mPorts.Remove(id) && mStatus == Status.Success) { ExtraParams xp = new ExtraParams(); xp.callback = callback; xp.port = port; xp.protocol = tcp ? ProtocolType.Tcp : ProtocolType.Udp; xp.action = "DeletePortMapping"; xp.request = "<NewRemoteHost></NewRemoteHost>\n" + "<NewExternalPort>" + port + "</NewExternalPort>\n" + "<NewProtocol>" + (tcp ? "TCP" : "UDP") + "</NewProtocol>\n"; if (callback != null) { xp.th = Tools.CreateThread(CloseRequest); lock (mThreads) { mThreads.Add(xp.th); xp.th.Start(xp); } } else { CloseRequest(xp); } } else if (callback != null) { callback(this, port, tcp ? ProtocolType.Tcp : ProtocolType.Udp, false); } }
/// <summary> /// Open up a port on the gateway. /// </summary> void Open(int port, bool tcp, OnPortRequest callback) { // IPv6 doesn't need port forwarding if (TcpProtocol.defaultListenerInterface.AddressFamily == AddressFamily.InterNetworkV6) { return; } if (port > 0) { int id = (port << 8) | (tcp ? 1 : 0); if (!mPorts.Contains(id) && mStatus != Status.Failure) { if (mStatus == Status.Inactive) { Start(); WaitForThreads(); } string addr = Tools.localAddress.ToString(); if (addr == "127.0.0.1") { return; } mPorts.Add(id); ExtraParams xp = new ExtraParams(); xp.callback = callback; xp.port = port; xp.protocol = tcp ? ProtocolType.Tcp : ProtocolType.Udp; xp.action = "AddPortMapping"; xp.request = "<NewRemoteHost></NewRemoteHost>\n" + "<NewExternalPort>" + port + "</NewExternalPort>\n" + "<NewProtocol>" + (tcp ? "TCP" : "UDP") + "</NewProtocol>\n" + "<NewInternalPort>" + port + "</NewInternalPort>\n" + "<NewInternalClient>" + addr + "</NewInternalClient>\n" + "<NewEnabled>1</NewEnabled>\n" + "<NewPortMappingDescription>" + name + "</NewPortMappingDescription>\n" + "<NewLeaseDuration>0</NewLeaseDuration>\n"; xp.th = Tools.CreateThread(OpenRequest); lock (mThreads) mThreads.Add(xp.th); xp.th.Start(xp); return; } } if (callback != null) { callback(this, port, tcp ? ProtocolType.Tcp : ProtocolType.Udp, false); } }
/// <summary> /// Send a server update. /// </summary> public override void SendUpdate(GameServer server) { if (!mShutdown) { mNextSend = 0; mGameServer = server; if (mThread == null) { mThread = Tools.CreateThread(ThreadFunction); mThread.Start(); } } }
/// <summary> /// Start UPnP and attempt to find the gateway. /// If you want to pause until the gateway is discovered, use WaitForThreads(). /// </summary> public void Start() { if (mStatus == Status.Inactive) { // IPv6 doesn't need port forwarding if (TcpProtocol.defaultListenerInterface.AddressFamily == AddressFamily.InterNetworkV6) { return; } mStatus = Status.Searching; mDiscover = Tools.CreateThread(ThreadDiscover); mDiscover.Start(mDiscover); } }
/// <summary> /// Start listening for incoming UDP packets on the specified listener port. /// </summary> public override bool Start(int listenPort) { Stop(); Tools.LoadList(banFilePath, mBan); #if FORCE_EN_US Tools.SetCurrentCultureToEnUS(); #endif mUdp = new UdpProtocol("Lobby Server"); if (!mUdp.Start(listenPort, UdpProtocol.defaultBroadcastInterface)) { return(false); } #if STANDALONE Tools.Print("Bans: " + mBan.Count); Tools.Print("UDP Lobby Server started on port " + listenPort + " using interface " + UdpProtocol.defaultNetworkInterface); #endif mThread = Tools.CreateThread(ThreadFunction); mThread.Start(); return(true); }
/// <summary> /// Start worker threads. /// </summary> void StartThreads() { if (mThreads != null) { return; } isShuttingDown = false; int maxThreads = System.Environment.ProcessorCount * threadsPerCore; if (maxThreads < 1) { maxThreads = 1; } if (maxThreads > 32) { maxThreads = 32; } mThreads = new Thread[maxThreads]; mLoad = new int[maxThreads]; // Create the threads for (int i = 0; i < maxThreads; ++i) { int threadID = i; mThreads[threadID] = Tools.CreateThread(delegate() { var active = new List <Entry>(); var sw = new Stopwatch(); WorkerThread.threadID = threadID + 1; for (;;) { bool handled = false; // Check without locking first as it's faster if (mPriority.Count > 0) { bool grab = true; // If this thread is not idling, check to see if others are if (active.size != 0) { for (int b = 0; b < maxThreads; ++b) { if (b != threadID && mLoad[b] == 0) { grab = false; break; } } } // No threads are idling -- grab the first queued item if (grab) { lock (mPriority) { if (mPriority.Count > 0) { handled = true; active.Add(mPriority.Dequeue()); mLoad[threadID] = active.size; } } } } if (!handled && mRegular.Count > 0) { bool grab = true; // If this thread is not idling, check to see if others are if (active.size != 0) { for (int b = 0; b < maxThreads; ++b) { if (b != threadID && mLoad[b] == 0) { grab = false; break; } } } // No threads are idling -- grab the first queued item if (grab) { lock (mRegular) { if (mRegular.Count > 0) { active.Add(mRegular.Dequeue()); mLoad[threadID] = active.size; } } } } // If we are working on something, run another update if (active.size > 0) { for (int b = active.size; b > 0;) { var ent = active[--b]; sw.Reset(); sw.Start(); try { if (ent.main != null) { ent.main(); ent.milliseconds += sw.ElapsedMilliseconds; active.RemoveAt(b); if (ent.finished != null || ent.finishedBool != null || ent.finishedEnum != null) { lock (mFinished) mFinished.Enqueue(ent); } else { lock (mUnused) mUnused.Add(ent); } mLoad[threadID] = active.size; } else if (ent.mainBool != null && ent.mainBool()) { ent.milliseconds += sw.ElapsedMilliseconds; active.RemoveAt(b); if (ent.finished != null || ent.finishedBool != null || ent.finishedEnum != null) { lock (mFinished) mFinished.Enqueue(ent); } else { lock (mUnused) mUnused.Add(ent); } mLoad[threadID] = active.size; } } catch (System.Exception ex) { UnityEngine.Debug.LogError(ex.Message + "\n" + ex.StackTrace); active.RemoveAt(b); } } } // Sleep for a short amount try { Thread.Sleep(1); } catch (System.Threading.ThreadInterruptedException) { return; } } }); } // Now that all threads have been created, start them all at once for (int i = 0; i < maxThreads; ++i) { mThreads[i].Start(); } }