using System; using System.Collections.Generic; using System.IO.Pipes; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using cloud.insecurity.http; using log4net; namespace cloud.insecurity.docker.ipam { internal class Ipam { private static log4net.ILog Log { get { return log4net.LogManager.GetLogger(typeof(Ipam)); } } internal static void Main(string[] args) { Task UnixSocketProxy; log4net.Config.XmlConfigurator.Configure(); var tasks = new Task[] { HttpServer.Server.Start(new string[] { @"http://127.0.0.1:65467/", }), ProxyRequestsFromUnixSocket() }; Console.CancelKeyPress += (sender, eventArgs) => { Console.WriteLine("shutting down, waiting for unfinished tasks.."); HttpServer.Server.Stop(); tasks.ToList().ForEach(t => t.Wait()); Environment.Exit(0); }; cKey: switch (Console.ReadKey()) { default: goto cKey; } } private static async Task ProxyRequestsFromUnixSocket() { var listeningPort = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); var endPoint = new UnixDomainSocketEndPoint(@"/run/cloud.insecurity.docker/ipam.sock"); listeningPort.Bind(endPoint); listeningPort.Listen(0); ManualResetEvent AcceptFinished = new ManualResetEvent(false); while (HttpServer.Server.Running) { listeningPort.BeginAccept(ConnectionAccepted, new Tuple(listeningPort, AcceptFinished)); AcceptFinished.WaitOne(); } return Task.CompletedTask; } private static void ConnectionAccepted(IAsyncResult ar) { ManualResetEvent ReceiveFinished = new ManualResetEvent(false); var socket = (ar.AsyncState as Tuple)?.Item1; var finished = (ar.AsyncState as Tuple)?.Item2; var ProxySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ProxySocket.Connect(new IPEndPoint(0x7f000001, 0xffbb)); var buffer = new List>(); bool ReceivedFromClient = false; recv: while (!Encoding.UTF8.GetString(buffer.SelectMany(bytes => bytes) .ToArray()) .EndsWith("\r\n\r\n")) { (ReceivedFromClient ? ProxySocket : socket)?.BeginReceive(buffer, SocketFlags.None, result => { (result.AsyncState as ManualResetEvent)?.Set(); }, ReceiveFinished); ReceiveFinished.WaitOne(); } if (ReceivedFromClient) { socket?.Send(buffer); finished?.Set(); } else { ProxySocket.Send(buffer); buffer = new List>(); ReceivedFromClient = true; goto recv; } } } }