//------------------------------------------------------------------------------------------------------------------------ private void _YPServer_OnNewChannel(Server Server, YPChannel.Channel Channel) { var id = new LANDiscoverer.RemoteEndpointID() { IPAddress = Channel.RemoteIdentifier, ID = 0, }; lock (RemoteNodes) { //get or create entry for remote node var remInfo = RemoteNodes.TryGetOrDefault(id); if (remInfo == null) { //create entry for remote node remInfo = new RemoteNode(Node, TimeSpan.FromMinutes(5), this) { RemoteEndpointID = id, DiscoveryMessage = null, RemoteNodeKey = default(NodeKey), }; //add to discovered remote nodes RemoteNodes.ForceAdd(id, remInfo); } //hookevents hookNewRemoteNodeEvents(remInfo); //setup channel remInfo.SetupChannel(Channel); } }
private void _channelConnected(ButtonConnectionChannel channel) { var bdAddr = channel.BdAddr; DebugEx.TraceLog(channel.ToString() + " connected"); ButtonChannels.ForceAdd(bdAddr, channel); }
//------------------------------------------------------------------------------------------------------------------------ void HandleNewConnection(Socket newsocket) { try { #region check reconnection throttle try { //setup socket newsocket.ReceiveTimeout = -1; newsocket.SendTimeout = 60 * 1000; #if NETFX var re = newsocket.RemoteEndPoint.GetIPAddress().ToStringInvariant(); #elif UNIVERSAL var re = newsocket.Information.RemoteAddress.ToStringInvariant(); #endif //filtering if (OnNewSocketConnectionFilter != null && OnNewSocketConnectionFilter(this, re) == false) { #if NETFX try { newsocket.Close(); } catch { } #endif try { newsocket.Dispose(); } catch { } DebugEx.TraceWarning("Connection from " + re + " closed from filter"); return; } if (IsReconnectionThrottleEnabled && re != "127.0.0.1" && re != "localhost") //no reconnection throttle for localhost connections { var rbe = reconnectThrottleBookKeeper.TryGetOrDefault(re); if (rbe == null) { rbe = new ReconnectionBookkeepEntry() { ConnectionTimestamp = DateTime.Now + TimeSpan.FromMilliseconds(100), Connections = 1, }; reconnectThrottleBookKeeper.ForceAdd(re, rbe); } else { if (++rbe.Connections > ReconnectionThrottleAfterConnectionCount) { var elapsed = DateTime.Now - rbe.ConnectionTimestamp; if (elapsed < ReconnectionThrottleTimeout) { #if NETFX try { newsocket.Close(); } catch { } #endif try { newsocket.Dispose(); } catch { } DebugEx.TraceWarning("Connection from " + re + " closed due to reconnection throttle (" + elapsed.Seconds + " sec)"); return; } } } } } catch (Exception ex) { DebugEx.TraceWarning(ex, "YPServer Reconnection throttle exception"); } //cleanup old entries reconnectThrottleBookKeeper.RemoveWhere(e => DateTime.Now - e.Value.ConnectionTimestamp > ReconnectionThrottleTimeout); #endregion //start task new connection Task.Run(() => { ServerChannel channel = null; string channelKey = null; Thread.Sleep(MathTools.GetRandomNumber(1, 100)); try { //check #if NETFX if (!newsocket.Connected) { DebugEx.TraceWarning("YPServer newsocket not connected?"); try { newsocket.Close(); } catch { } return; } #endif //create channel var con = ChannelConstructor; channel = con == null ? new ServerChannel(this, Protocols, SupportedChannelSerializationModes, PreferredChannelSerializationModes, newsocket) : con(Protocols, newsocket); if (channel == null) { DebugEx.Assert("Could not create channel"); #if NETFX try { newsocket.Close(); } catch { } #endif try { newsocket.Dispose(); } catch { } return; } //add to set lock (_Channels) { //generate unique key while (IssuedKeys.ContainsKey(channelKey = MathTools.GenerateRandomAlphaNumericString(64))) { ; } //set on channel channel._ChannelKey = channelKey; //add to lookups _Channels.Add(channel); IssuedKeys.Add(channelKey, channel); } //start task timeout monitor bool setupFinished = false; Task.Run(() => { try { //wait Thread.Sleep(30000); //check if (!setupFinished) { DebugEx.TraceLog($"ServerChannel setup timeout ({channel})"); try { channel.Close("ServerChannel setup timeout"); } catch { } #if NETFX try { newsocket?.Close(); } catch { } #endif try { newsocket?.Dispose(); } catch { } //remove from lookups lock (_Channels) { if (channel != null) { _Channels.Remove(channel); } if (channelKey != null) { IssuedKeys.Remove(channelKey); } } return; } } catch (Exception ex) { DebugEx.Assert(ex, $"Unhandled exception ({channel})"); #if NETFX try { newsocket?.Close(); } catch { } #endif try { newsocket?.Dispose(); } catch { } //remove from lookups lock (_Channels) { if (channel != null) { _Channels.Remove(channel); } if (channelKey != null) { IssuedKeys.Remove(channelKey); } } return; } }); //set serializer channel.MsgPack = MsgPackSerializer; //setup channel socket if (channel.SetupServerSocket() == false) { #if NETFX try { newsocket?.Close(); } catch { } #endif try { newsocket?.Dispose(); } catch { } //remove from lookups lock (_Channels) { if (channel != null) { _Channels.Remove(channel); } if (channelKey != null) { IssuedKeys.Remove(channelKey); } } return; } //mark setup finish setupFinished = true; //call event OnNewChannel?.Invoke(this, channel); //start heartbeat channel.Start(); } catch (Exception ex) { DebugEx.Assert(ex, "YPServer: Failed setting up new connection for " + channel); #if NETFX try { newsocket.Close(); } catch { } #endif try { newsocket.Dispose(); } catch { } //remove from lookups lock (_Channels) { if (channel != null) { _Channels.Remove(channel); } if (channelKey != null) { IssuedKeys.Remove(channelKey); } } return; } }); } catch (Exception ex) { DebugEx.Assert(ex, "YPChannel server setup new connection error"); } }