Exemple #1
0
    public static async void WsTraceRoute(HttpListenerContext ctx)
    {
        WebSocketContext wsc;
        WebSocket        ws;

        try {
            wsc = await ctx.AcceptWebSocketAsync(null);

            ws = wsc.WebSocket;
        } catch (WebSocketException ex) {
            ctx.Response.Close();
            Logging.Err(ex);
            return;
        }

        string sessionId = ctx.Request.Cookies["sessionid"]?.Value ?? null;

        if (sessionId is null)
        {
            ctx.Response.Close();
            return;
        }

        object send_lock = new object();

        try {
            while (ws.State == WebSocketState.Open)
            {
                byte[] buff = new byte[2048];
                WebSocketReceiveResult receiveResult = await ws.ReceiveAsync(new ArraySegment <byte>(buff), CancellationToken.None);

                if (!Session.CheckAccess(sessionId))   //check session
                {
                    ctx.Response.Close();
                    return;
                }

                if (receiveResult.MessageType == WebSocketMessageType.Close)
                {
                    await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);

                    break;
                }

                string hostname = Encoding.Default.GetString(buff, 0, receiveResult.Count);
                hostname = hostname.Trim();
                if (hostname.Length == 0)
                {
                    await ws.SendAsync(Strings.INV, WebSocketMessageType.Text, true, CancellationToken.None);

                    continue;
                }

                const short timeout = 2000; //2s
                const short ttl     = 30;

                List <string> list = new List <string>();

                new Thread(async() => {
                    List <IPAddress> ipList = new List <IPAddress>();
                    string lastAddress      = "";

                    using (System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping())
                        for (short i = 1; i < ttl; i++)
                        {
                            if (ws.State != WebSocketState.Open)
                            {
                                break;
                            }
                            string result = $"{hostname}{(char)127}";

                            try {
                                PingReply reply = p.Send(hostname, timeout, TRACE_ROUTE_BUFFER, new PingOptions(i, true));
                                if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired)
                                {
                                    if (lastAddress == reply.Address.ToString())
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        lastAddress = reply.Address.ToString();
                                    }

                                    result += $"{reply.Address}{(char)127}{reply.RoundtripTime}";
                                    ipList.Add(reply.Address);
                                }
                                else if (reply.Status == IPStatus.TimedOut)
                                {
                                    result += "Timed Out";
                                }

                                else
                                {
                                    break;
                                }
                            } catch (Exception ex) {
                                Logging.Err(ex);
                                break;
                            }

                            lock (send_lock) //once send per socket
                                ws.SendAsync(new ArraySegment <byte>(Encoding.UTF8.GetBytes(result), 0, result.Length), WebSocketMessageType.Text, true, CancellationToken.None);
                        }

                    List <Task <string> > tasks = new List <Task <string> >();
                    for (int j = 0; j < ipList.Count; j++)
                    {
                        tasks.Add(Dns.DnsLookupAsync(ipList[j]));
                    }
                    string[] hostnameArray = await Task.WhenAll(tasks);

                    string hostnames = $"[hostnames]{(char)127}{hostname}{(char)127}";
                    for (int i = 0; i < hostnameArray.Length; i++)
                    {
                        if (hostnameArray[i].Length > 0 && hostnameArray[i] != ipList[i].ToString())
                        {
                            hostnames += $"{ipList[i]}{(char)127}{hostnameArray[i]}{(char)127}";
                        }
                    }
                    if (hostnames.EndsWith(((char)127).ToString()))
                    {
                        hostnames = hostnames.Substring(0, hostnames.Length - 1);
                    }

                    lock (send_lock) {
                        ws.SendAsync(new ArraySegment <byte>(Encoding.UTF8.GetBytes(hostnames), 0, hostnames.Length), WebSocketMessageType.Text, true, CancellationToken.None);

                        string over = "over" + ((char)127).ToString() + hostname;
                        ws.SendAsync(new ArraySegment <byte>(Encoding.UTF8.GetBytes(over), 0, over.Length), WebSocketMessageType.Text, true, CancellationToken.None);
                    }
                }).Start();
            }
        } catch (Exception ex) {
            Logging.Err(ex);
        }
    }