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>")); } }
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); }
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())); }
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()); }
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); } } }
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)); }
public override Task HandleRequestAsyncImpl(HttpConnection p) { p.setContentTypeTextPlain(); return(p.EndResponseAsync(p.RawRequest)); }