Created
April 25, 2016 19:34
-
-
Save gralin/b5edfd908a41fc7268a7757698af1e66 to your computer and use it in GitHub Desktop.
Gerrit proxy for IIS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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