private void TryApplyPerChannelEncryption(Channel x) { if (PerChannelEncryption.IsNullOrEmpty() == false) { NaiveProtocol.ApplyEncryption(x.DataFilter, PerChannelEncryptionKey, PerChannelEncryption); } }
private async Task <WebSocketServer> HandleWebsocket(HttpConnection p, byte[] realKey, string encType) { var ws = new WebSocketServer(p); ws.AddToManaged(timeout / 2, timeout); NaiveProtocol.ApplyEncryption(ws, realKey, encType); // check encryption parameters before http response if ((await ws.HandleRequestAsync(false)).IsConnected == false) { throw new Exception("websocket handshake failed."); } return(ws); }
public async Task HandleRequestAsync(HttpConnection p, Settings settings, string token) { try { if (token == null) { throw new ArgumentNullException(nameof(token)); } NaiveProtocol.Request req; try { var bytes = Convert.FromBase64String(token); if (settings.realKey != null) { bytes = NaiveProtocol.EncryptOrDecryptBytes(false, settings.realKey, bytes); } req = NaiveProtocol.Request.Parse(bytes); } catch (Exception e) { Logger.exception(e, Logging.Level.Warning, "parsing token"); return; } try { p.Handled = true; var r = await GetMsgStream(p, settings, req); if (r == null) { return; } var msgStream = r.Item1; var imux = r.Item2; try { await HandleNaiveProtocol(msgStream, settings, req); } finally { if (imux != null) { lock (imuxSessions) imuxSessions.Remove(imux.SessionId); imux.WhenEnd.SetResult(null); } } } catch (Exception e) { Logger.exception(e, Logging.Level.Error, "NaiveMHandler From: " + p.myStream + " Url: " + p.Url); } } finally { if (p.ConnectionState == HttpConnection.States.Processing) { p.Handled = false; } } }
private void addPath(string path, PathSettings settings) { if (settings.imux_max < 0) { settings.imux_max = imux_max; } if (settings.network != null) { settings.networks = settings.networks ?? new Dictionary <string, AdapterRef>(); settings.networks.Add("default", settings.network); } settings.realKey = NaiveProtocol.GetRealKeyFromString(settings.key ?? this.key, 32); httpServer.Router.AddAsyncRoute(path, (p) => { var m = Regex.Match(p.Url_qstr, settings.format); if (m.Success == false) { return(NaiveUtils.CompletedTask); } var token = m.Groups["token"].Value; token = HttpUtil.UrlDecode(token); return(this.HandleRequestAsync(p, settings, token)); }); }
private async Task <Tuple <IMsgStream, ImuxSession> > GetMsgStream(HttpConnection p, Settings settings, NaiveProtocol.Request req) { var realKey = settings.realKey; const string XumPrefix = "chs2:"; bool isImux = req.additionalString.StartsWith(XumPrefix); ImuxSession imux = null; string encryptType = ""; if (req.extraStrings.Length > 0) { encryptType = req.extraStrings[0]; } if (!isImux && req.additionalString != "channels") { Logger.warning($"{p.remoteEP}: protocol not supported"); return(null); } IMsgStream msgStream = null; if (isImux) { var arr = NaiveUtils.DeserializeArray(req.additionalString.Substring(XumPrefix.Length)); var sessionId = arr[0]; int wsCount = Int32.Parse(arr[1]), wssoCount = 0, httpCount = 0; var connId = Int32.Parse(arr[2]); if (arr.Count > 3) { wssoCount = Int32.Parse(arr[3]); httpCount = Int32.Parse(arr[4]); } var connCount = wsCount + wssoCount + httpCount; int imuxMax = settings.imux_max; if (imuxMax < 0) { imuxMax = 16; } if (connCount > imuxMax) { Logger.warning($"{p.remoteEP}: IMUX count requesting ({connCount}) > imux_max ({imuxMax})"); return(null); } IMsgStream wsOrHttp; if (connId < connCount - httpCount) { wsOrHttp = await HandleWebsocket(p, realKey, encryptType); } else { p.setStatusCode("200 OK"); p.setHeader(HttpHeaders.KEY_Transfer_Encoding, HttpHeaders.VALUE_Transfer_Encoding_chunked); await p.EndResponseAsync(); var baseStream = MyStream.FromStream(p.SwitchProtocol()); var msf = new HttpChunkedEncodingMsgStream(baseStream); NaiveProtocol.ApplyEncryption(msf, realKey, encryptType); wsOrHttp = msf; } lock (imuxSessions) { if (imuxSessions.TryGetValue(sessionId, out imux) == false) { imux = new ImuxSession(sessionId, connCount) { WsCount = wsCount, WssoCount = wssoCount, HttpCount = httpCount }; imuxSessions.Add(sessionId, imux); NaiveUtils.SetTimeout(10 * 1000, () => { if (imux.ConnectedCount != imux.Count) { Logger.warning($"IMUX (id={imux.SessionId}, count={imux.ConnectedCount}/{imux.Count}) timed out"); imux.WhenEnd.SetResult(null); } }); } if (imux.HandleConnection(wsOrHttp, connId)) { // all connections are connected to the imux session, return the msg stream. msgStream = imux.MuxStream; } } if (msgStream == null) { // wait for the end of the imux session, prevent it from being disconncected. await imux.WhenEnd.Task; return(null); } } else { msgStream = await HandleWebsocket(p, realKey, encryptType); } return(Tuple.Create(msgStream, imux)); }