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); }
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)); }