public void Launch(Action <Exception> done) { if (_task != null && !_task.IsCompleted) { throw new InvalidOperationException($"Can't launch {Id} while previous instance is {_task.Status}"); } var procID = _machine.NextProcID(); var env = new SimProc(Id, _machine, procID, _factory); _task = _factory.StartNew(async() => { try { var engine = _launcher(env); try { await engine.Run(); } finally { await engine.Dispose(); } } catch (AggregateException ex) { done(ex.InnerException); return; } catch (Exception ex) { done(ex); return; } done(null); }).Unwrap(); _proc = env; }
public SimConn(SimSocket socket, SimEndpoint remoteAddress, SimProc proc, uint seq, uint ackNumber) { _socket = socket; RemoteAddress = remoteAddress; _proc = proc; _sequenceNumber = seq; _ackNumber = ackNumber; }
public void ReleaseResources() { if (_proc != null) { _proc.Dispose(); _proc = null; } _task = null; }
public async Task <IConn> Connect(SimProc process, SimEndpoint destination) { SimRoute route; if (!Cluster.TryGetRoute(Name, destination.Machine, out route)) { throw new IOException($"Route not found"); } // todo: allocate port // todo: allow Azure SNAT delay scenario var socketId = NextSocketID(); var source = new SimEndpoint(Name, socketId); var clientSocket = new SimSocket(process, source, Cluster); try { _sockets.Add(socketId, clientSocket); var conn = new SimConn(clientSocket, destination, process, 0, 0); clientSocket._connections.Add(destination, conn); // handshake await conn.Write(null, SimFlag.Syn); var response = await conn.Read(5.Sec()); if (response.Flag != (SimFlag.Ack | SimFlag.Syn)) { Debug(LogType.Warning, $"Bad handshake: {response.BodyString()}"); await conn.Write(null, SimFlag.Reset); clientSocket._connections.Remove(destination); throw new IOException($"Failed to connect (got {response.BodyString()})"); } await conn.Write(null, SimFlag.Ack); return(new ClientConn(conn)); } catch (IOException) { throw; } catch (Exception ex) { _sockets.Remove(socketId); clientSocket.Dispose(); throw new IOException($"Failed to connect: {ex.Message}", ex); } }
public async Task <ISocket> Bind(SimProc proc, ushort port, TimeSpan timeout) { // socket is bound to the owner var endpoint = new SimEndpoint(proc.Id.Machine, port); if (_sockets.ContainsKey(port)) { throw new IOException($"Address {endpoint} in use"); } var socket = new SimSocket(proc, endpoint, Cluster); _sockets.Add(port, socket); proc.RegisterSocket(socket); return(socket); }
public SimSocket(SimProc proc, SimEndpoint endpoint, SimCluster net) { _proc = proc; Endpoint = endpoint; _net = net; }