예제 #1
0
 public override Task HandleRequestAsyncImpl(HttpConnection p)
 {
     if (p.Url_path == "/" && p.Method == "GET")
     {
         var con = p.GetTag("connection") as InConnectionTcp;
         return(ClientList(p, con));
     }
     else
     {
         p.setStatusCode("404 Not Found");
         return(p.EndResponseAsync("<h1>Client not found</h1>"));
     }
 }
예제 #2
0
 public override Task HandleRequestAsyncImpl(HttpConnection p)
 {
     if (page_path.IsOrContains(p.Url_path))
     {
         if (WebSocketServer.IsWebSocketRequest(p))
         {
             return(ws(p));
         }
         p.Handled = true;
         p.setStatusCode("200 OK");
         if (page_file != null && File.Exists(page_file))
         {
             return(writePageFile(p));
         }
         else
         {
             return(p.EndResponseAsync(webconHtml));
         }
     }
     return(NaiveUtils.CompletedTask);
 }
예제 #3
0
        private Task SimpleList(HttpConnection pp, string path, string infoText)
        {
            var sb = new StringBuilder(128);
            int dirs = 0, files = 0;

            foreach (var dir in Directory.EnumerateDirectories(path))
            {
                sb.Append("[dir]\t").Append(Path.GetFileName(dir)).Append("/\r\n");
                dirs++;
            }
            foreach (var file in Directory.EnumerateFiles(path))
            {
                sb.Append("[file]\t").Append(Path.GetFileName(file)).Append("\r\n");
                files++;
            }
            if (sb.Length > 0)
            {
                sb.Append("\r\n");
            }
            sb.Append("[stat]\t").Append(dirs).Append(" dir(s), ").Append(files).Append(" file(s)\r\n");
            if (infoText != null)
            {
                sb.Append("[info]\t").Append(infoText).Append("\r\n");
            }
            else if (pp.Url_qstr == "help")
            {
                sb.Append("[help]\tcurl [-F <OPTION>]... <DIR_URL>\r\n" +
                          "\tOptions:\r\n" +
                          "\tfile=@FILE_TO_UPLOAD  mkdir=DIR_NAME  cp=\"(FROM...) TO\"\r\n" +
                          "\tmv=\"(FROM...) TO\"  rm=\"(FILE|DIR)...\"  netdl=\"URL [FILENAME]\"\r\n" +
                          "\ttextFileName=NEW_TEXT_FILE_NAME  textContent=NEW_TEXT_FILE_CONTENT\r\n");
            }
            else if (allow_create || allow_edit)
            {
                sb.Append("[tip]\tGET with ?help\r\n");
            }
            pp.setContentTypeTextPlain();
            return(pp.EndResponseAsync(sb.ToString()));
        }
예제 #4
0
        public async Task ClientList(HttpConnection p, InConnectionTcp con)
        {
            p.setStatusCode("200 OK");
            var sb = new StringBuilder(512);

            sb.AppendLine("<html><head><meta name='viewport' content='width=device-width, initial-scale=1'></head>")
            .AppendLine($"<body style='margin: 0 auto; max-width: 100ch; padding: 8px;'>" +
                        $"<h1 style='text-align: center'>NNetwork '{domain}'</h1>");
            sb.AppendLine("<h2>Connected Clients</h2><pre style='overflow: auto;'>");
            var curTime = WebSocket.CurrentTime;

            foreach (var item in clients)
            {
                sb.Append(item.Ip.ToString());
                foreach (var name in item.tags)
                {
                    sb.Append('\t').Append(name);
                }
                sb.Append("\tCreateTime: ").Append(item.CreateTime - curTime).AppendLine();
            }
            sb.AppendLine()
            .AppendLine("</pre><h2>Request Info</h2><pre style='overflow: auto;'>")
            .AppendLine($"Url: {p.Url}")
            .AppendLine($"Host: {p.Host}")
            .AppendLine($"BaseStream: {p.myStream}")
            .AppendLine($"EndPoint: {p.epPair}")
            .AppendLine($"Server Time: {DateTime.Now}");
            if (con != null)
            {
                sb.AppendLine($"Dest: {con.Dest}");
            }
            sb.AppendLine()
            .AppendLine("RawRequest:")
            .Append(HttpUtil.HtmlEncode(p.RawRequest))
            .AppendLine("</pre></body></html>");
            await p.EndResponseAsync(sb.ToString());
        }
예제 #5
0
파일: WebRelay.cs 프로젝트: smeoow/Naive
        public override async Task HandleRequestAsyncImpl(HttpConnection p)
        {
            if (!WebSocketServer.IsWebSocketRequest(p))
            {
                if (p.Url_path == client_js_path)
                {
                    p.Handled = true;
                    p.setStatusCode("200 OK");
                    p.setHeader(HttpHeaders.KEY_Content_Type, "text/javascript");
                    await p.EndResponseAsync(JsClient);

                    return;
                }
                if (p.Url_path == demo_chatroom_path)
                {
                    p.Handled = true;
                    p.setStatusCode("200 OK");
                    await p.EndResponseAsync(DemoChatRoom);

                    return;
                }
            }
            if (p.ParsedQstr["pass"] != pass)
            {
                return;
            }

            var cli = new Client(p);

            if ((await cli.HandleRequestAsync(false)).IsConnected == false)
            {
                return;
            }
            cli.Id = p.ParsedQstr["id"];
            var cliToken = p.ParsedQstr["idtoken"];
            var reuseId  = false;

            if (cli.Id != null)
            {
                lock (rooms) {
                    foreach (var item in idTokens)
                    {
                        if (item.Id == cli.Id)
                        {
                            // TODO: If hit, remove and re-add to the queue.
                            if (item.Token != cliToken)
                            {
                                break;
                            }
                            if (clients.TryGetValue(cli.Id, out var oldCli))
                            {
                                try {
                                    oldCli.SendStringAsync("kick-sameid").Forget();
                                } catch (Exception) { }
                                oldCli.Close();
                                RemoveClient(oldCli);
                            }
                            reuseId = true;
                            break;
                        }
                    }
                }
            }
            if (!reuseId)
            {
                cli.Id   = Guid.NewGuid().ToString("d");
                cliToken = Guid.NewGuid().ToString("d");
            }
            lock (rooms) {
                clients.Add(cli.Id, cli);
                if (!reuseId)
                {
                    if (idTokens.Count >= 50)
                    {
                        idTokens.Dequeue();
                    }
                    idTokens.Enqueue(new AuthItem {
                        Id = cli.Id, Token = cliToken
                    });
                }
            }
AUTHOK:

            try {
                await cli.SendStringAsync("hello " + cli.Id + " " + cliToken);

                while (true)
                {
                    var str = await cli.RecvString();

                    var span      = (Span)str;
                    var firstLine = span.CutSelf('\n');
                    var cmd       = firstLine.CutSelf(' ');
                    if (cmd == "room")
                    {
                        var verb   = firstLine.CutSelf(' ');
                        var rtoken = firstLine.CutSelf(' ').ToString();
                        if (!CheckClientId(cli, ref firstLine))
                        {
                            goto FAIL;
                        }
                        lock (rooms) { // Use such a big lock to ensure message order.
                            rooms.TryGetValue(rtoken, out var room);
                            if (verb == "join")
                            {
                                if (cli.Joined.Contains(room))
                                {
                                    goto FAIL;
                                }
                                if (room == null)
                                {
                                    rooms.Add(rtoken, room = new Room()
                                    {
                                        Token = rtoken, Parent = this
                                    });
                                }
                                if (room.Clients.Contains(cli) == false)
                                {
                                    room.Clients.Add(cli);
                                }
                                cli.Joined.Add(room);
                                room.Broadcast(str, cli);

                                var sb = new StringBuilder();
                                sb.Append("ok room state ").Append(room.Token).Append("\n");
                                foreach (var item in room.States)
                                {
                                    sb.Append(item.Key).Append(':').Append(item.Value).Append('\n');
                                }
                                cli.SendStringAsync(sb.ToString()).Forget();
                            }
                            else
                            {
                                if (room == null)
                                {
                                    goto FAIL;
                                }
                                if (cli.Joined.Contains(room) == false)
                                {
                                    goto FAIL;
                                }
                                if (verb == "msg")
                                {
                                    room.Broadcast(str, cli);
                                    cli.SendStringAsync("ok").Forget();
                                }
                                else if (verb == "state")
                                {
                                    while (span.len > 0)
                                    {
                                        var line  = span.CutSelf('\n');
                                        var key   = line.CutSelf(':').ToString();
                                        var value = line.ToString();
                                        if (value.Length == 0)
                                        {
                                            room.States.Remove(key);
                                        }
                                        else
                                        {
                                            room.States[key] = value;
                                        }
                                    }
                                    room.Broadcast(str, cli);
                                    cli.SendStringAsync("ok").Forget();
                                }
                                else if (verb == "list")
                                {
                                    var sb = new StringBuilder("ok list\n");
                                    foreach (var c in room.Clients)
                                    {
                                        sb.Append(c.Id).Append(' ').Append(c.Tag).Append('\n');
                                    }
                                    cli.SendStringAsync(sb.ToString()).Forget();
                                }
                                else if (verb == "leave")
                                {
                                    room.Clients.Remove(cli);
                                    if (room.Clients.Count == 0)
                                    {
                                        rooms.Remove(room.Token);
                                    }
                                    else
                                    {
                                        room.Broadcast(str, cli);
                                    }
                                    cli.SendStringAsync("ok").Forget();
                                }
                                else
                                {
                                    goto FAIL;
                                }
                            }
                        }
                    }
                    else if (cmd == "ping")
                    {
                        await cli.SendStringAsync("ok pong");
                    }
                    else if (cmd == "tag")
                    {
                        var verb = firstLine.CutSelf(' ');
                        if (verb == "set")
                        {
                            var tag = firstLine.CutSelf(' ');
                            cli.Tag = tag.ToString();
                            goto OK;
                        }
                        else
                        {
                            goto FAIL;
                        }
                    }
                    continue;
OK:
                    await cli.SendStringAsync("ok");

                    continue;
FAIL:
                    await cli.SendStringAsync("fail");

                    continue;
                }
            } catch (Exception e) {
                Logger.exception(e, Logging.Level.Warning);
            } finally {
                lock (rooms) {
                    RemoveClient(cli);
                }
            }
        }
예제 #6
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));
        }
예제 #7
0
파일: WebAdapters.cs 프로젝트: smeoow/Naive
 public override Task HandleRequestAsyncImpl(HttpConnection p)
 {
     p.setContentTypeTextPlain();
     return(p.EndResponseAsync(p.RawRequest));
 }