static TcpMapServerWorker AddStartServer(TcpMapServer server) { var conn = new TcpMapServerWorker() { Server = server }; lock (_servers) _servers.Add(conn); conn.StartWork(); return(conn); }
static public void ReAddServer(TcpMapServer server) { string jsonfilepath = Path.Combine(DataFolder, "TcpMapServer_" + server.Id + ".json"); File.WriteAllText(jsonfilepath, JsonSerializer.Serialize(server)); TcpMapServerWorker serverWorker = null; lock (_clients) { serverWorker = _servers.Where(v => v.Server.Id == server.Id).FirstOrDefault(); if (serverWorker != null) { _servers.Remove(serverWorker); } } if (serverWorker != null) { serverWorker.Stop(); } AddStartServer(server); }
async Task WorkAsync(CommandMessage connmsg) { if (connmsg.Name == "SessionConnect") { _is_client = false; _is_session = true; } byte[] clientKeyIV; _worker = TcpMapService.FindServerWorkerByKey(connmsg.Args[0], int.Parse(connmsg.Args[1])); string failedreason = null; if (_worker == null) { failedreason = "NotFound"; } else if (!_worker.Server.IsValidated) { failedreason = "NotValidated"; } else if (_worker.Server.IsDisabled) { failedreason = "NotEnabled"; } if (_worker == null || !string.IsNullOrEmpty(failedreason)) { var failedmsg = new CommandMessage("ConnectFailed", failedreason); await _socket.SendAsync(failedmsg.Pack(), SocketFlags.None); return; } bool supportEncrypt = _worker.Server.UseEncrypt; if (connmsg.Args[4] == "0") { supportEncrypt = false; } try { _worker.Server.License.DescriptSourceKey(Convert.FromBase64String(connmsg.Args[2]), Convert.FromBase64String(connmsg.Args[3]), out clientKeyIV); } catch (Exception x) { _worker.OnError(x); var failedmsg = new CommandMessage("ConnectFailed", "InvalidSecureKey"); await _socket.SendAsync(failedmsg.Pack(), SocketFlags.None); return; } var successMsg = new CommandMessage("ConnectOK", "ConnectOK", supportEncrypt ? "1" : "0"); await _socket.SendAsync(successMsg.Pack(), SocketFlags.None); if (supportEncrypt) { _worker.Server.License.OverrideStream(_socket.CreateStream(), clientKeyIV, out _sread, out _swrite); } else { _sread = _swrite = _socket.CreateStream(); } if (_is_session) { this.SessionId = connmsg.Args[5]; if (SessionId == null) { _cts_wait_upgrade = new CancellationTokenSource(); } } _worker.AddClientOrSession(this); try { if (_is_client) { _ = _swrite.WriteAsync(new CommandMessage("SetOption", "ClientEndPoint", _socket.RemoteEndPoint.ToString()).Pack()); while (true) { var msg = await CommandMessage.ReadFromStreamAsync(_sread); //process it... if (msg == null) { //TcpMapService.LogMessage("no message ? Connected:" + _socket.Connected); throw new SocketException(995); } //_worker.LogMessage("TcpMapServerClient get msg " + msg); switch (msg.Name) { case "SetOption": string optvalue = msg.Args[1]; switch (msg.Args[0]) { case "RouterClientPort": this.OptionRouterClientPort = int.Parse(optvalue); break; default: _worker.LogMessage("Error:Ignore option " + msg); break; } break; case "StartSessionResult": case "CloseSessionResult": case "CreateUDPNatResult": long reqid = long.Parse(msg.Args[0]); if (reqmap.TryGetValue(reqid, out var ritem)) { ritem.Response = msg; ritem.cts.Cancel(); } else { _worker.LogMessage("Request Expired : " + msg); } break; case "_ping_": this._lastPingTime = DateTime.Now; await _swrite.WriteAsync(new CommandMessage("_ping_result_").Pack()); break; case "_ping_result_": break; default: _worker.LogMessage("Error: 5 Ignore message " + msg); break; } } } else if (_is_session) { if (SessionId == null) { _worker.LogMessage($"Warning:ServerClient*{_scid} Wait for Upgrade To Session "); while (SessionId == null) { if (await _cts_wait_upgrade.Token.WaitForSignalSettedAsync(28000)) //check the presession closed or not every 28 seconds { if (SessionId != null) { break; //OK, session attached. } throw new SocketException(995); //_cts_wait_upgrade Cancelled , by SessionId is not seted } //if (!_socket.Connected) //NEVER useful.. //{ // _worker.LogMessage("Warning:presession exit."); // throw new SocketException(995); //} if (!_socket.Poll(0, SelectMode.SelectRead)) //WORKS.. { continue; } if (_socket.Available == 0) { _worker.LogMessage("Warning:presession exit!"); throw new SocketException(995); } //_worker.LogMessage("Warning:presession send message before upgrade ?"+_socket.Available); if (!_cts_wait_upgrade.IsCancellationRequested) { //TODO:not locked/sync, not so safe it the presession is upgrading var msg = await CommandMessage.ReadFromSocketAsync(_socket); if (msg.Name == "_ping_") { byte[] resp = new CommandMessage("_ping_result_").Pack(); await _socket.SendAsync(resp, SocketFlags.None); } else { _worker.LogMessage("Warning:presession unexpected msg : " + msg); } } } _worker.LogMessage($"Warning:ServerClient*{_scid} SessionId:" + SessionId); } int waitMapTimes = 0; TryGetMap: if (_attachedSession != null) { _worker.LogMessage($"ServerClient*{_scid} use attached Session : {SessionId} *{waitMapTimes}"); await _attachedSession.UseThisSocketAsync(_sread, _swrite); } else if (_worker.sessionMap.TryGetValue(SessionId, out var session)) { _worker.LogMessage($"ServerClient*{_scid} session server ok : {SessionId} *{waitMapTimes}"); await session.UseThisSocketAsync(_sread, _swrite); } else { if (waitMapTimes < 5) { waitMapTimes++; await Task.Delay(10); //wait sessionMap be added.. goto TryGetMap; } _worker.LogMessage($"Warning:ServerClient*{_scid} session not found : {SessionId}"); throw new Exception($"ServerClient*{_scid} session not found : {SessionId}"); } } else { throw new InvalidOperationException(); } } catch (SocketException) { //no log } catch (Exception x) { _worker.OnError(x); } finally { _worker.RemoveClientOrSession(this); } _worker.LogMessage($"ServerClient*{_scid} WorkAsync END " + SessionId); }
public TcpMapServerConnector(TcpMapServerWorker sworker) { _worker = sworker; }