Skip to content

Instantly share code, notes, and snippets.

@gralin
Created April 25, 2016 19:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gralin/b5edfd908a41fc7268a7757698af1e66 to your computer and use it in GitHub Desktop.
Save gralin/b5edfd908a41fc7268a7757698af1e66 to your computer and use it in GitHub Desktop.
Gerrit proxy for IIS
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace GerritProxy
{
public class Proxy
{
private static readonly Regex EncodedPercent = new Regex("%(25)+");
private TcpListener _listener;
private static string _gerritAddress;
private static int _gerritPort;
public void Start(string gerritAddress, int gerritPort, int proxyPort)
{
_gerritAddress = gerritAddress;
_gerritPort = gerritPort;
Task.Run(() =>
{
_listener = new TcpListener(IPAddress.Loopback, proxyPort);
return Run();
});
}
private async Task Run()
{
_listener.Start();
while (_listener != null && _listener.Server.IsBound)
{
try
{
var client = await _listener.AcceptTcpClientAsync();
ProcessAsync(client);
}
catch
{
break;
}
}
}
public void Stop()
{
var listener = _listener;
_listener = null;
listener.Stop();
}
private static async void ProcessAsync(TcpClient client)
{
var gerrit = new TcpClient();
try
{
var clientStream = client.GetStream();
await gerrit.ConnectAsync(_gerritAddress, _gerritPort);
var gerritStream = gerrit.GetStream();
Task.WaitAny(
Forward(clientStream, gerritStream, DecodeEncodedUrlPercents),
Forward(gerritStream, clientStream));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
if (client.Connected)
client.Close();
if (gerrit.Connected)
gerrit.Close();
}
}
private static byte[] DecodeEncodedUrlPercents(byte[] bytes)
{
var lines = Encoding.ASCII.GetString(bytes, 0, bytes.Length).Split('\n');
for (var i = 0; i < lines.Length; i++)
{
if (lines[i].Length == 0)
continue;
if (!EncodedPercent.IsMatch(lines[i]))
break;
lines[i] = EncodedPercent.Replace(lines[i], "%");
return Encoding.ASCII.GetBytes(string.Join("\n", lines));
}
return bytes;
}
private static async Task Forward(Stream receiveFrom, Stream sendTo, Func<byte[], byte[]> alterData = null)
{
var buffer = new byte[4096];
while (true)
{
int dataLength;
try
{
dataLength = await receiveFrom.ReadAsync(buffer, 0, buffer.Length);
}
catch
{
break;
}
if (dataLength == 0)
break;
var data = buffer.Take(dataLength).ToArray();
if (alterData != null)
data = alterData(data);
await sendTo.WriteAsync(data, 0, data.Length);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment