protected override void OnMonitorReceive(IPAddress address, Guid guid, ushort channel, byte[] data) { Message.Base msg = ReceiveMonitorCommand(data); if (msg.IsType <Message.Negotiation.Channel.UDP>()) { Message.Negotiation.Channel.UDP response = (Message.Negotiation.Channel.UDP)msg; ServerChannel channel_parameters = channels[response.channel]; Message.Negotiation.Parameters param = new Message.Negotiation.Parameters { guid = response.guid, channel = response.channel, type = channel_parameters.type, heartbeat = channel_parameters.parameters.Heartbeat, autoReconnect = !channel_parameters.parameters.disableAutoReconnect }; Connection.Tcp monitor; if (monitors.TryGetValue(param.guid, out monitor)) { UdpConnectionParams udp_param = SendUdpParams(monitor, param); ConnectUdp(udp_param, response); } else { Debug.LogErrorFormat("No monitor channel with guid '{0}' to send UDP negotiation for channel {1}", param.guid, param.channel); } } }
protected void NegotiateChannels(Connection.Tcp connection) { Message.Base msg; if (connection.Receive(out msg)) { if (msg.IsType <Message.Negotiation.Start>()) { connection.Parameters.guid = Guid.NewGuid(); SaveMonitor(connection); // Send a new Guid for these connections and the number of associated channels Message.Negotiation.New n = new Message.Negotiation.New { guid = connection.Parameters.guid, nbChannels = (ushort)Math.Min(channels != null ? channels.Count : 0, ushort.MaxValue) }; connection.Send(n); if (n.nbChannels <= 0) { Drop(connection, "No channels configured."); } for (ushort i = 0; i < n.nbChannels; i++) { ServerChannel channel = channels[i]; Message.Negotiation.Parameters param = new Message.Negotiation.Parameters { guid = n.guid, channel = i, type = channel.type, heartbeat = channel.parameters.Heartbeat, autoReconnect = !channel.parameters.disableAutoReconnect }; connection.Send(param); } } else if (msg.IsType <Message.Negotiation.Channel.TCP>()) { Message.Negotiation.Channel.TCP tcp = (Message.Negotiation.Channel.TCP)msg; connection.SetConfig(tcp.guid, tcp.channel, channels[tcp.channel].parameters.Heartbeat); SaveChannel(connection); } else { Drop(connection, "Unsupported negotiation command '{0}'.", msg.GetType()); } } else { Drop(connection, "Expected to receive some negotiation command."); } }
protected void AcceptClient(IAsyncResult async_result) { try { if (state == State.RUNNING && listener != null && listener.Server != null && listener.Server.IsBound) { Message.Negotiation.Parameters param = new Message.Negotiation.Parameters { guid = Guid.Empty, channel = ushort.MaxValue, heartbeat = negotiation.parameters.Heartbeat, autoReconnect = !negotiation.parameters.disableAutoReconnect }; // Get the new connection Connection.Tcp connection = new Connection.Tcp(this, param, DisconnectionHandler, listener.EndAcceptTcpClient(async_result)); lock (initializedConnections) { initializedConnections.Add(connection); } connection.initialization = Task.Run(() => Connected(connection)); } } catch (ObjectDisposedException) { // Can happen rarely because the atomicity between IsBound and EndAcceptTcpClient is not verified. Therefore the // listener can be disposed in this time frame. In this case, we have nothing to do. Just exit to close cleanly the listener. } catch (Exception exception) { Debug.LogErrorFormat("{0}: {1}\n{2}", exception.GetType(), exception.Message, exception.StackTrace); } }
protected void ConnectUdp(Connection.Tcp connection, Message.Negotiation.Parameters param) { UdpConnectionParams udp_params = SendUdpParams(connection, param); lock (pendingUdpConnection) { pendingUdpConnection.Add(udp_params); } }
protected void ConnectTcp(Message.Negotiation.Parameters param) { // Create a new TCP client Connection.Tcp connection = new Connection.Tcp(this, param, DisconnectionHandler, new TcpClient()); if (param.guid != Guid.Empty) { lock (initializedConnections) { initializedConnections.Add(connection); } } // Start asynchronous connection to server connection.initialization = Task.Run(() => connection.client.BeginConnect(hostname, port, Connected, connection)); }
protected void NegotiateChannels(Connection.Tcp connection) { // Check if we must negotiate other channel or just open the current one if (connection.Remote == Guid.Empty) { connection.Send(new Message.Negotiation.Start()); Message.Base msg; if (connection.Receive(out msg) && msg.IsType <Message.Negotiation.New>()) { Message.Negotiation.New n = (Message.Negotiation.New)msg; connection.Parameters.guid = n.guid; ushort nb_channels = n.nbChannels; if (nb_channels > 0) { List <Message.Negotiation.Parameters> parameters = new List <Message.Negotiation.Parameters>(nb_channels); for (ushort i = 0; i < nb_channels; i++) { if (connection.Receive(out msg) && msg.IsType <Message.Negotiation.Parameters>()) { Message.Negotiation.Parameters param = (Message.Negotiation.Parameters)msg; parameters.Add(param); } else { Drop(connection, "Expected to receive channel parameterts for channel {0}.", i); } } SaveMonitor(connection); foreach (Message.Negotiation.Parameters param in parameters) { if (!Ready(param.guid, param.channel)) { switch (param.type) { case Channel.Type.TCP: ConnectTcp(param); break; case Channel.Type.UDP: ConnectUdp(connection, param); break; } } } state = State.RUNNING; } else { Drop(connection, "No channels configured."); } } else { Drop(connection, "Expected to receive the new connection negotiation parameters."); } } else { Message.Negotiation.Channel.TCP tcp = new Message.Negotiation.Channel.TCP { guid = connection.Remote, channel = connection.Channel }; connection.Send(tcp); SaveChannel(connection); } }