private HttpListener _httpListener;
private HttpTunnelClient(ushort listenPort, Uri serverUri, NetworkCredential credential, IPEndPoint remoteEndPoint = null, SocksProxyType? runType = null)
{
_httpListener = new HttpListener();
_httpListener.Prefixes.Add(string.Format("http://*:{0}/", listenPort));
_httpListener.Start();
_httpListener.BeginGetContext(this.GetContextCallback, null);
}
private void GetContextCallback(IAsyncResult ar)
{
if (_httpListener == null)
{
return;
}
_httpListener.BeginGetContext(this.GetContextCallback, null);
var context = _httpListener.EndGetContext(ar);
this.DirectHttp(context);
}
private void DirectHttp(HttpListenerContext context)
{
var Request = context.Request;
var Response = context.Response;
string destUri = Request.RawUrl;
try
{
var tunnel = this.CreateTunnel(ClientNull, TunnelCommand.HttpDirect);
tunnel.Headers[xHttpHandler.AgentDirect] = destUri;
tunnel.Headers[xHttpHandler.AgentCommand] = ((int)TunnelCommand.HttpDirect).ToString();
tunnel.Form.Remove(xHttpHandler.AgentCommand);
//tunnel.SetProxy(xHttpHandler.GoAgent);
using (var tResponse = tunnel.GetResponseWith(new HttpRequestWrapper(Request)))
{
Response.StatusCode = (int)tResponse.StatusCode;
Response.StatusDescription = tResponse.StatusDescription;
Response.KeepAlive = tResponse.Headers[HttpResponseHeader.Connection] != "close";
if (tResponse.ContentLength >= 0)
{
Response.ContentLength64 = tResponse.ContentLength;
}
Response.ContentType = tResponse.ContentType;
foreach (string header in HttpRequestWrapper.SystemHeaders)
{
tResponse.Headers.Remove(header);
}
Response.Headers.Add(tResponse.Headers);
var tStream = tResponse.GetResponseStream();
tStream.FixedCopyTo(Response.OutputStream);
}
this.OutWrite("{0} \"{1} {2}\" {3}\t{4}bytes.", Request.LocalEndPoint, Request.HttpMethod, destUri,
Response.StatusCode, Response.ContentLength64);
//如果写入未完成(异常等情况)就调用Close()则会抛“在写入所有字节之前不能关闭流”异常。
Response.Close();
}
catch (WebException ex)
{
TunnelExceptionHandler.Handle(ex, string.Format("DirectHttp{0}={1}", Request.HttpMethod, destUri));
}
catch (Exception ex)
{
TunnelExceptionHandler.Handle(ex, string.Format("DirectHttp{0}={1}", Request.HttpMethod, destUri));
}
}
private void Direct2GoAgent(HttpContext context, Uri destUri)
{
context.Server.ScriptTimeout = Timeout;
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
Request.Headers.Remove(HttpRequestHeader.Authorization.ToString());
Request.Headers.Remove(AgentSock);
Request.Headers.Remove(AgentDirect);
Request.Headers.Remove(AgentCommand);
var client = new HttpClient(destUri);
client.SetRequest(destUri);
client.SetProxy(GoAgent);
try
{
using (var cResponse = client.GetResponseWith(new System.Web.HttpRequestWrapper(Request)))
{
Response.StatusCode = (int)cResponse.StatusCode;
Response.StatusDescription = cResponse.StatusDescription;
Response.ContentType = cResponse.ContentType;
Response.Headers.Add(cResponse.Headers);
var cStream = cResponse.GetResponseStream();
cStream.FixedCopyTo(Response.OutputStream, (int)cResponse.ContentLength);
if (Response.IsClientConnected)
{
Response.Flush();
}
}
}
catch (WebException ex)
{
TunnelExceptionHandler.Handle(ex, string.Format("Direct2GoAgent={0}", destUri));
}
catch (Exception ex)
{
TunnelExceptionHandler.Handle(ex, string.Format("Direct2GoAgent={0}", destUri));
}
}