Пример #1
0
 private void TryApplyPerChannelEncryption(Channel x)
 {
     if (PerChannelEncryption.IsNullOrEmpty() == false)
     {
         NaiveProtocol.ApplyEncryption(x.DataFilter, PerChannelEncryptionKey, PerChannelEncryption);
     }
 }
Пример #2
0
        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);
        }
Пример #3
0
        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;
                }
            }
        }
Пример #4
0
 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));
     });
 }
Пример #5
0
        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));
        }