//------------------------------------------------------------------------------------------------------------------------ public override void OnTransportConnected(string msg) { base.OnTransportConnected(msg); _CloudConnected = true; // Send the connection timestamp TaskEx.RunSafe(() => { // Send the report 10Second after connection to avoid the timing issue with active port key // TODO: Fix this case !!!! Thread.Sleep(10000); if (Ports?.ContainsKey("connectionTimestamp") ?? false) { SetPortState(new List <TupleS <string, string> >() { new TupleS <string, string>(Ports["connectionTimestamp"].PortKey, DateTime.UtcNow.ToStringInvariant()), new TupleS <string, string>(Ports["isTransportConnected"].PortKey, "True"), }); } }); }
//------------------------------------------------------------------------------------------------------------------------ public void SendVBMToBrothers(List <VirtualBlockEvent> events) { try { //split into packets-per brother var brotherPackets = new Dictionary <NodeKey, List <VirtualBlockEvent> >(); foreach (var ev in events) { var bk = (BlockKey)ev.BlockKey; var nk = bk.GraphKey.NodeKey; if (BrotherNodes.ContainsKey(nk)) { //get (or create) packet list var packets = brotherPackets.TryGetOrDefault(nk); if (packets == null) { brotherPackets.Add(nk, packets = new List <VirtualBlockEvent>()); } //add packet for brother node packets.Add(ev); } } //send to brothers and consume foreach (var bpkv in brotherPackets) { //get brother var brother = BrotherNodes.TryGetOrDefault(bpkv.Key); if (brother != null && brother.IsConnected) { var msgReq = new VirtualBlockEventMsg() { BlockEvents = bpkv.Value.ToArray(), }; var rsp = brother.SendRequest <GenericRsp>(msgReq, Timeout: TimeSpan.FromSeconds(3)); if (rsp != null && rsp.IsSuccess) { //consume events from original set msgReq.BlockEvents.ForEach(e => events.Remove(e)); } } } } catch (Exception ex) { DebugEx.Assert(ex, "Unhandled exception in SendVBMToBrothers"); } }
/// <summary> /// Get resource based on given descriptor /// </summary> /// <param name="descriptor"></param> /// <returns></returns> public static byte[] GetResource(BinaryResourceDescriptor descriptor) { byte[] resource = null; try { if (FetchHandlers.ContainsKey(descriptor.LocationType)) { resource = FetchHandlers[descriptor.LocationType](descriptor); } else { DebugEx.TraceError("No handler for resource descriptor of type: " + descriptor.LocationType.ToString()); } } catch (Exception ex) { DebugEx.Assert(ex, "Error getting resource from specified resource descriptor"); } return(resource); }
private void GotButton(Bdaddr bdAddr) { DebugEx.TraceLog("Got Button"); var thing = flicThings.TryGetOrDefault(bdAddr); if (thing == null) { thing = ThingTools.FlicThing.CreateThing(bdAddr.ToString().Replace(":", ""), bdAddr.ToString()); thing = AddThing(thing); flicThings.Add(bdAddr, thing); } DebugEx.TraceLog("===========>Add Button Thing Completed"); var channel = ButtonChannels.TryGetOrDefault(bdAddr); if (channel == null) { DebugEx.TraceLog("===========>New Channel is created"); channel = new ButtonConnectionChannel(bdAddr); channel.CreateConnectionChannelResponse += (sender1, eventArgs) => { if (eventArgs.Error == CreateConnectionChannelError.NoError) { _channelConnected((ButtonConnectionChannel)sender1); } else { DebugEx.TraceError(((ButtonConnectionChannel)sender1).BdAddr.ToString() + " could not be connected"); } }; channel.Removed += (sender1, eventArgs) => { _channelDisconnected((ButtonConnectionChannel)sender1); }; channel.ConnectionStatusChanged += (sender1, eventArgs) => { var chan = (ButtonConnectionChannel)sender1; if (eventArgs.ConnectionStatus == ConnectionStatus.Disconnected) { _channelDisconnected(chan); } }; channel.ButtonSingleOrDoubleClickOrHold += (sender1, eventArgs) => { var chan = (ButtonConnectionChannel)sender1; var thisThing = flicThings.TryGetOrDefault(chan.BdAddr); if (thisThing == null) { return; } DebugEx.TraceLog(eventArgs.ClickType + " for " + thisThing.Name + " (key:" + thisThing.ThingKey + ")"); switch (eventArgs.ClickType) { case ClickType.ButtonSingleClick: SetPortState(PortKey.BuildFromArbitraryString(thisThing.ThingKey, ThingTools.FlicThing.SingleClick), "True"); break; case ClickType.ButtonDoubleClick: SetPortState(PortKey.BuildFromArbitraryString(thisThing.ThingKey, ThingTools.FlicThing.DoubleClick), "True"); break; case ClickType.ButtonHold: SetPortState(PortKey.BuildFromArbitraryString(thisThing.ThingKey, ThingTools.FlicThing.LongClick), "True"); break; default: break; } if (!ButtonChannels.ContainsKey(chan.BdAddr)) { _channelConnected(chan); } }; //try to add channel _flicClient.AddConnectionChannel(channel); DebugEx.TraceLog("===========>Add Connection Channel Completed"); foreach (var navctx in NavigationContext.Values) { DebugEx.TraceLog("===========>navctx.CurrentPage.Title: " + navctx.CurrentPage.Title); if (navctx.CurrentPage.Title == "Flic Pairing") { DebugEx.TraceLog("=====>here I am <======"); navctx.GoBack(); navctx.UpdateCurrentPage(createDiscoverPage()); } } } }
//------------------------------------------------------------------------------------------------------------------------ public GenericRsp HandleGraphDeploymentReq(GraphDeploymentReq req, bool SupressSave) { lock (locker) { var res = new GenericRsp(); try { //get graphkey var graphkey = (GraphKey)req.GraphKey; if (graphkey.IsInvalid) { res.IsSuccess = false; res.Message = "Invalid GraphKey"; return(res); } if (graphkey.NodeId != this.Node.NodeKey.NodeID) { res.IsSuccess = false; res.Message = "Invalid NodeID in GraphKey"; return(res); } //collect sets var sets = Node.BeginActiveThingsUpdate(); //deploy or undeploy? if (req.IsDeployed) { //deserialize graph descriptor GraphDescriptor graphDescriptor; try { graphDescriptor = GraphBuilder.GetGraphDescriptorFromJson(req.GraphDescriptor, false); } catch (Exception ex) { DebugEx.Assert(ex, "Could not deserialize graph descriptor"); res.IsSuccess = false; res.Message = "Could not deserialize graph descriptor"; return(res); } graphDescriptor.GraphKey = graphkey; //Build Graph Graph graph; try { graph = BuildGraph(graphDescriptor); } catch (Exception ex) { DebugEx.Assert(ex, "Could not build graph from graph descriptor (unhandled exception)"); res.IsSuccess = false; res.Message = "Could not build graph from graph descriptor (unhandled exception)"; return(res); } if (graph == null) { DebugEx.Assert("Could not build graph from graph descriptor"); res.IsSuccess = false; res.Message = "Could not build graph from graph descriptor"; return(res); } //set key graph.GraphKey = graphkey; //do i already have it? if (Graphs.ContainsKey(graphkey)) { //invalidate graph _GraphManager.InvalidateGraph(graphkey); //remove information Graphs.Remove(graphkey); } //try deploy graph try { Exception exception; var depres = graph.OnDeploy(true, null, out exception); if (!depres) { res.IsSuccess = false; res.Message = "Graph OnDeploy() failed. Message : " + (exception?.Message ?? "null"); return(res); } } catch (Exception ex) { DebugEx.Assert(ex, "Graph OnDeploy() failed"); res.IsSuccess = false; res.Message = "Graph OnDeploy() failed. Message : " + ex.Message; return(res); } //add to lookup var gi = new GraphInfo() { GraphKey = graphkey, GraphDescriptor = graphDescriptor, GraphDescriptorString = req.GraphDescriptor, Graph = graph, }; Graphs.Add(graphkey, gi); //save! if (IsInitialized && !SupressSave) { Save(); } //associate block keys foreach (var thingblock in graph.Blocks.OfType <BaseThings>()) { //Add to Thing2Block set { //find block key set var set = ThingKey2BlockKey.TryGetOrDefault(thingblock.ThingKey); if (set == null) { set = new HashSetTS <BlockKey>(); ThingKey2BlockKey.Add(thingblock.ThingKey, set); } //add to loockup set set.Add(thingblock.BlockKey); } //Add only for thingIn if (thingblock.IsThingIn) { //find block key set var set = ThingKey2ThingInBlockKey.TryGetOrDefault(thingblock.ThingKey); if (set == null) { set = new HashSetTS <BlockKey>(); ThingKey2ThingInBlockKey.Add(thingblock.ThingKey, set); } //add to loockup set set.Add(thingblock.BlockKey); } } //Handle Deploy res.IsSuccess = true; res.Message = "Graph Deployed Successfully"; } else { //Handle UnDeploy if (Graphs.ContainsKey(graphkey) == false) { res.IsSuccess = true; res.Message = "Graph Undeployed Successfully (was not deployed)"; } else { //get graph var gi = Graphs[graphkey]; var graph = gi.Graph; //inform graph Exception exception; try { if (graph.OnUndeploy(null, out exception) == false) { DebugEx.Assert(exception, "Graph OnUndeploy failed"); } } catch (Exception ex) { DebugEx.Assert(ex, "Graph OnUndeploy failed"); } //invalidate graph _GraphManager.InvalidateGraph(graphkey); //remove information Graphs.Remove(graphkey); //save! if (IsInitialized && !SupressSave) { Save(); } //disassociate block keys if (graph != null) { foreach (var thingblock in gi.Graph.Blocks.OfType <BaseThings>()) { //remove from thing2block { var set = ThingKey2BlockKey.TryGetOrDefault(thingblock.ThingKey); if (set != null) { set.Remove(thingblock.BlockKey); } } //remove from thignIn2block if (thingblock.IsThingIn) { var set = ThingKey2ThingInBlockKey.TryGetOrDefault(thingblock.ThingKey); if (set != null) { set.Remove(thingblock.BlockKey); } } } } //done res.IsSuccess = true; res.Message = "Graph Undeployed Successfully"; } } //finish update Node.EndActiveThingsUpdate(sets); } catch (Exception ex) { res.IsSuccess = false; res.Message = "Unhandled exception in GraphDeploymentReq(). Message=" + ex.Message; } finally { //begin activation state snapshot var sets = Node.BeginActiveThingsUpdate(); //update active ports/things var activeThings = ThingKey2BlockKey.Where(kv => kv.Value.Count > 0) .Select(kv => Node.Things.TryGetOrDefaultReadOnly(kv.Key)) .WhereNotNull().ToHashSetTS(); var activeThingKeys = activeThings.Select(t => (ThingKey)t.ThingKey).ToHashSetTS(); var activePorts = activeThings.SelectMany(t => t.Ports).ToHashSetTS(); var activePortsKeys = activePorts.Select(p => (PortKey)p.PortKey).ToHashSetTS(); //update sets Interlocked.Exchange(ref _ActiveThings, activeThings); Interlocked.Exchange(ref _ActivePorts, activePorts); Interlocked.Exchange(ref _ActiveThingKeys, activeThingKeys); Interlocked.Exchange(ref _ActivePortKeys, activePortsKeys); //trigger node thing activation update Node.EndActiveThingsUpdate(sets); } //return result msg return(res); } }
//------------------------------------------------------------------------------------------------------------------------ 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"); } }