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); } }
void AddEstablishedConnection(SimConn conn) { var ready = new ClientConn(conn); if (_poll != null) { _poll.SetResult(ready); _poll = null; } else { _incoming.Enqueue(ready); } }
void AcceptNewConnection(SimPacket msg) { var conn = new SimConn(this, msg.Source, _proc, 0, msg.NextSeqNumber); _connections.Add(msg.Source, conn); _proc.Schedule(async() => { await conn.Write(null, SimFlag.Ack | SimFlag.Syn); var resp = await conn.Read(5.Sec()); if (resp.Flag != SimFlag.Ack) { Debug($"Non ACK packet: {msg.BodyString()}"); await conn.Write(null, SimFlag.Reset); _connections.Remove(msg.Source); return; } AddEstablishedConnection(conn); }); }
public ClientConn(SimConn conn) { _conn = conn; }