-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathHandler.ashx
130 lines (122 loc) · 3.86 KB
/
Handler.ashx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<%@ WebHandler Language="C#" Class="Handler" %>
using System;
using System.Net.WebSockets;
using System.Threading.Tasks;
using System.Threading;
using System.Web;
using System.Web.WebSockets;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
public class Handler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
var request = context.Request;
var response = context.Response;
if (!context.IsWebSocketRequest && !context.IsWebSocketRequestUpgrading)
{
response.StatusCode = 403;
return;
}
var addr = request.Headers.Get("X-Forwarded-Host");
if (addr == null)
{
response.StatusCode = 403;
return;
}
var parts = addr.Split(':');
if (parts.Length != 2)
{
response.StatusCode = 403;
return;
}
var host = parts[0];
var port = parts[1];
var client = new TcpClient();
try
{
client.Connect(host, int.Parse(port));
}
catch (Exception e)
{
response.StatusCode = 500;
response.Write(e.ToString());
return;
}
var key = MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(addr));
var p = new Proxy(client.Client, key);
context.AcceptWebSocketRequest(p.ProcessRequest);
}
private class Proxy
{
private Socket sock;
private byte[] key;
public Proxy(Socket sock, byte[] key)
{
this.sock = sock;
this.key = key;
}
private async Task ReadTask(WebSocket ws)
{
var buffer = new byte[1024];
var index = 0;
while (true)
{
try
{
var r = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None).ConfigureAwait(false);
for (int i = 0; i < r.Count; i++)
{
buffer[i] = (byte)(buffer[i] ^ key[index]);
index++;
if (index == key.Length)
{
index = 0;
}
}
await sock.SendAsync(new ArraySegment<byte>(buffer, 0, r.Count), SocketFlags.None).ConfigureAwait(false);
}
catch
{
break;
}
}
}
private async Task WriteTask(WebSocket ws)
{
var buffer = new byte[1024];
var index = 0;
while (true)
{
try
{
var count = await sock.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None).ConfigureAwait(false);
for (int i = 0; i < count; i++)
{
buffer[i] = (byte)(buffer[i] ^ key[index]);
index++;
if (index == key.Length)
{
index = 0;
}
}
await ws.SendAsync(new ArraySegment<byte>(buffer, 0, count), WebSocketMessageType.Binary, true, CancellationToken.None).ConfigureAwait(false);
}
catch
{
break;
}
}
}
public async Task ProcessRequest(AspNetWebSocketContext context)
{
var ws = context.WebSocket;
await Task.WhenAll(this.WriteTask(ws), this.ReadTask(ws));
}
}
}