/** * @param e Edge to close * @param cm message to send to other node * This method is used if we want to use a particular CloseMessage * If not, we can use the method with the same name with one fewer * parameters */ public void GracefullyClose(Edge e, string message) { /** * Close any connection on this edge, and * put the edge into the list of unconnected edges */ _connection_table.Disconnect(e); ListDictionary close_info = new ListDictionary(); string reason = message; if (reason != String.Empty) { close_info["reason"] = reason; } ProtocolLog.WriteIf(ProtocolLog.EdgeClose, String.Format( "GracefulCLose - " + e + ": " + reason)); var results = new BCon.Channel(1); EventHandler close_eh = delegate(object o, EventArgs args) { e.Close(); }; results.CloseEvent += close_eh; try { _rpc.Invoke(e, results, "sys:link.Close", close_info); } catch { Close(e); } }
/* * Start sending packets */ public void Run() { byte[] buf = new byte[UInt16.MaxValue]; Random ran_obj = new Random(); for (int counter = 0; counter < count; counter++) { try { int size = ran_obj.Next(4, Int16.MaxValue); ran_obj.NextBytes(buf); NumberSerializer.WriteInt(counter, buf, 0); MemBlock cp = MemBlock.Copy(buf, 0, Math.Max(4, counter)); lock (_sync) { _sent_blocks[cp] = counter; } _e.Send(cp); Thread.Sleep(10); Console.WriteLine("Sending Packet #: " + counter); } catch (Exception x) { Console.WriteLine("send: {0} caused exception: {1}", counter, x); break; } } //Let all the responses get back Thread.Sleep(5000); Check(); _e.Close(); }
protected void Close(Edge e) { try { //This can throw an exception if the _packet_queue is closed EnqueueAction(new EdgeCloseAction(e)); } catch { e.Close(); } }
public override bool Close() { if (Interlocked.Exchange(ref _weclosed, 1) == 1) { return(false); } base.Close(); _edge.Close(); return(true); }
public void CreationCallback(bool success, Edge e, Exception x) { if (!success && _edge != null) { _edge.Close(); } if (System.Threading.Interlocked.Exchange(ref _called, 1) == 1) { return; } ExternalECB(success, e, x); }
/*** Gracefully close this connection, if it is not already disconnected. * Idempotent (calling it twice is the same as once). * @return the old state, new state pair. */ public Pair <ConnectionState, ConnectionState> Close(RpcManager rpc, string reason) { var old_new = Abort(); if (old_new.First.Disconnected != true) { //Now try to tell the other node: var close_info = new ListDictionary(); if (reason != String.Empty) { close_info["reason"] = reason; } Edge e = old_new.Second.Edge; var results = new Channel(1); //Either the RPC call times out, or we get a response. results.CloseEvent += delegate(object o, EventArgs args) { e.Close(); }; try { rpc.Invoke(e, results, "sys:link.Close", close_info); } catch { e.Close(); } } return(old_new); }
/** * This Handler should be connected to incoming EdgeEvent * events. If it is not, it cannot hear the new edges. * * When a new edge is created, we make sure we can hear * the packets from it. Also, we make sure we can hear * the CloseEvent. * * @param edge the new Edge */ protected void EdgeHandler(object edge, EventArgs args) { Edge e = (Edge)edge; try { _connection_table.AddUnconnected(e); e.Subscribe(this, e); } catch (TableClosedException) { /* * Close this edge immediately, before any packets * have a chance to be received. We are shutting down, * and it is best that we stop getting new packets */ e.Close(); } }
/** Watch this incoming Edge */ protected void HandleEdge(object newedge, System.EventArgs args) { Edge e = (Edge)newedge; try { e.CloseEvent += this.HandleEdgeClose; e.Subscribe(this, null); lock ( _sync ) { _edges.Add(e); } } catch (Exception x) { //Didn't work out, make sure the edges is closed Console.WriteLine("Closing ({0}) due to: {1}", e, x); e.Close(); } }
///<summary>When a SecurityAssociation changes amongst inactive, active, ///or closed this gets notified.</summary> protected void AnnounceSA(SecurityAssociation sa, SecurityAssociation.States state) { Edge e = sa.Sender as Edge; // if e is an edge, let's see if he's creating a SE // or maybe it isn't our edge! if (e == null) { return; } else if (e.TAType != this.TAType) { return; } if (state == SecurityAssociation.States.Active) { SecurityAssociation stored_sa = null; if (!RemoveFromDictionary(e, out stored_sa)) { // May have already been here return; } else if (stored_sa != null && stored_sa != sa) { throw new Exception("Cannot have the same edge used in multiple SAs"); } SecureEdge se = new SecureEdge(e, sa); sa.Subscribe(se, null); try { Finalize(se); } catch { se.Close(); } } else if (state == SecurityAssociation.States.Closed) { e.Close(); } }
///<summary>When a SecurityAssociation changes amongst inactive, active, ///or closed this gets notified.</summary> protected void AnnounceSA(object o, EventArgs ea) { SecurityAssociation sa = o as SecurityAssociation; if (sa == null) { throw new Exception("Needs to be a SecurityAssociation"); } Edge e = sa.Sender as Edge; // if e is an edge, let's see if he's creating a SE // or maybe it isn't our edge! if (e == null) { return; } else if (e.TAType != this.TAType) { return; } if (sa.Active) { SecureEdge se = new SecureEdge(e, sa); sa.Subscribe(se, null); try { Finalize(se); } catch { se.Close(); } } else { e.Close(); } }
public void Start() { EdgeToClose.Close(); }
/** * There are only four ways we can get here: * * 1) We got some exception in Start and never made the first request * 2) There was some problem in LinkCloseHandler * 3) We either got a response or had a problem in StatusCloseHandler * 4) The Edge closed, and the CloseHandler was called. * * The only possibility for a race is between the CloseHandler and * the others. * * When this state machine reaches an end point, it calls this method, * which fires the FinishEvent */ protected void Finish(Result res) { /* * No matter what, we are done here: */ if (ProtocolLog.LinkDebug.Enabled) { string message; Exception x; if (_x.TryGet(out x)) { message = String.Format( "LPS: {0} finished: {2}, with exception: {1}", _node.Address, x, res); } else { message = String.Format("LPS: {0} finished: {1}", _node.Address, res); } ProtocolLog.Write(ProtocolLog.LinkDebug, message); } int already_finished = Interlocked.Exchange(ref _is_finished, 1); if (already_finished == 1) { //We already got here. //This is a barrier. Only one Finish call will make //it past this point. Only two could happen in a race: //Edge closing or some other failure/success. return; } //We don't care about close event's anymore _e.CloseEvent -= this.CloseHandler; //Set the result: _result = res; try { //Check to see if we need to close the edge if (_con.IsSet == false) { /* * We didn't get a complete connection, * but we may have heard some response. If so * close the edge gracefully. */ if (LinkMessageReply != null) { //Let's be nice: _node.GracefullyClose(_e, "From LPS, did not complete a connection."); } else { /* * We never heard from the other side, so we will assume that further * packets will only waste bandwidth */ _e.Close(); } if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: {0} got no connection", _node.Address)); } } else { if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: {0} got connection: {1}", _node.Address, _con.Value)); } } //This could throw an exception, but make sure we unlock if it does. FireFinished(); } finally { /** * We have to make sure the lock is eventually released: */ this.Unlock(); } }
public override bool Close() { _e.Close(); return(base.Close()); }
/** * This informs all the ConnectionOverlord objects * to not respond to loss of edges, then to issue * close messages to all the edges * */ protected void Leave() { if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "In StructuredNode.Leave: {0}", this.Address)); } #if !BRUNET_SIMULATOR _iphandler.Stop(); #endif StopConnectionOverlords(); //Stop notifying neighbors of disconnection, we are the one leaving _connection_table.DisconnectionEvent -= this.UpdateNeighborStatus; //Gracefully close all the edges: _connection_table.Close(); //This makes sure we can't add any new connections. ArrayList edges_to_close = new ArrayList(); foreach (Edge e in _connection_table.GetUnconnectedEdges()) { edges_to_close.Add(e); } //There is no way unconnected edges could have become Connections, //so we should put the connections in last. foreach (Connection c in _connection_table) { edges_to_close.Add(c.State.Edge); } //edges_to_close has all the connections and unconnected edges. IList copy = edges_to_close.ToArray(); //Make sure multiple readers and writers won't have problems: edges_to_close = ArrayList.Synchronized(edges_to_close); EventHandler ch = delegate(object o, EventArgs a) { if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "{1} Handling Close of: {0}", o, this.Address)); } edges_to_close.Remove(o); if (edges_to_close.Count == 0) { if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "Node({0}) Stopping all EdgeListeners", Address)); } StopAllEdgeListeners(); } }; if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "{0} About to gracefully close all edges", this.Address)); } //Use just one of these for all the calls: IDictionary carg = new ListDictionary(); carg["reason"] = "disconnecting"; for (int i = 0; i < copy.Count; i++) { Edge e = (Edge)copy[i]; if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "{0} Closing: [{1} of {2}]: {3}", this.Address, i, copy.Count, e)); } try { e.CloseEvent += ch; Channel res_q = new Channel(1); DateTime start_time = DateTime.UtcNow; res_q.CloseEvent += delegate(object o, EventArgs arg) { if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "Close on edge: {0} took: {1}", e, (DateTime.UtcNow - start_time))); } e.Close(); }; try { _rpc.Invoke(e, res_q, "sys:link.Close", carg); } catch (EdgeException) { /* * It is not strange for the other side to have potentially * closed, or some other error be in progress which is why * we might have been shutting down in the first place * No need to print a message */ e.Close(); } catch (Exception x) { if (ProtocolLog.Exceptions.Enabled) { ProtocolLog.Write(ProtocolLog.Exceptions, String.Format( "sys:link.Close({0}) threw: {1}", e, x)); } e.Close(); } } catch { ch(e, null); } } if (copy.Count == 0) { //There were no edges, go ahead an Stop if (ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "Node({0}) Stopping all EdgeListeners", Address)); } StopAllEdgeListeners(); } }
protected void RequestClose(Edge e) { EventHandler eh = EdgeCloseRequestEvent; if( eh == null ) { //We have to close the edge: e.Close(); } else { try { eh(this, new EdgeCloseRequestArgs(e)); } catch(Exception x) { Console.Error.WriteLine("ERROR: closing: {0} -- {1}", e, x); e.Close(); } } }
protected void Close(Edge e) { try { //This can throw an exception if the _packet_queue is closed EnqueueAction(new Edge.CloseAction(e)); } catch { e.Close(); } }
/** * Check all the edges in the ConnectionTable and see if any of them * need to be pinged or closed. * This method is connected to the heartbeat event. */ virtual protected void CheckEdgesCallback(object node, EventArgs args) { DateTime now = DateTime.UtcNow; //_connection_timeout = ComputeDynamicTimeout(); _connection_timeout = MAX_CONNECTION_TIMEOUT; /* * If we haven't heard from any of these people in this time, * we ping them, and if we don't get a response, we close them */ foreach (Connection c in _connection_table) { Edge e = c.Edge; TimeSpan since_last_in = now - e.LastInPacketDateTime; if ((1 == _send_pings) && (since_last_in > _connection_timeout)) { object ping_arg = String.Empty; DateTime start = DateTime.UtcNow; EventHandler on_close = delegate(object q, EventArgs cargs) { BCon.Channel qu = (BCon.Channel)q; if (qu.Count == 0) { /* we never got a response! */ if (!e.IsClosed) { //We are going to close it after waiting: ProtocolLog.WriteIf(ProtocolLog.NodeLog, String.Format( "On an edge timeout({1}), closing connection: {0}", c, DateTime.UtcNow - start)); //Make sure it is indeed closed. e.Close(); } else { //The edge was closed somewhere else, so it //didn't timeout. } } else { //We got a response, let's make sure it's not an exception: bool close = false; try { RpcResult r = (RpcResult)qu.Dequeue(); object o = r.Result; //This will throw an exception if there was a problem if (!o.Equals(ping_arg)) { //Something is wrong with the other node: ProtocolLog.WriteIf(ProtocolLog.NodeLog, String.Format( "Ping({0}) != {1} on {2}", ping_arg, o, c)); close = true; } } catch (Exception x) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, String.Format( "Ping on {0}: resulted in: {1}", c, x)); close = true; } if (close) { e.Close(); } } }; BCon.Channel tmp_queue = new BCon.Channel(1); tmp_queue.CloseEvent += on_close; //Do the ping try { _rpc.Invoke(e, tmp_queue, "sys:link.Ping", ping_arg); } catch (EdgeClosedException) { //Just ignore closed edges, clearly we can't ping them } catch (EdgeException x) { if (!x.IsTransient) { //Go ahead and close the Edge e.Close(); } } } } foreach (Edge e in _connection_table.GetUnconnectedEdges()) { if (now - e.LastInPacketDateTime > _unconnected_timeout) { if (ProtocolLog.Connections.Enabled) { ProtocolLog.Write(ProtocolLog.Connections, String.Format( "Closed an unconnected edge: {0}", e)); } e.Close(); } } }
/** Handle incoming data on an Edge */ public void HandleData(MemBlock data, ISender retpath, object state) { MemBlock rest_of_data; PType p; if (state == null) { p = PType.Parse(data, out rest_of_data); } else { //a demux has already happened: p = (PType)state; rest_of_data = data; } if (PType.Protocol.Pathing.Equals(p)) { /* * We use a special PType to denote this transaction so * we don't confuse it with other RepRep communication */ _rrm.HandleData(rest_of_data, retpath, null); } else if (PType.Protocol.Rpc.Equals(p)) { /* * Send this to the RpcHandler */ Rpc.HandleData(rest_of_data, retpath, null); } else { /* * This is some other data * It is either: * 1) Time to announce an already created edge. * 2) Assume this is a "default path" edge creation, to be backwards * compatible */ Edge e = null; PathEdge pe = null; try { e = (Edge)retpath; PathEdgeListener pel = null; lock ( _sync ) { if (_unannounced.TryGetValue(e, out pe)) { // _unannounced.Remove(e); pel = _pel_map[pe.LocalPath]; } } if (pe == null) { /* * This must be a "default path" incoming connection */ pel = _pel_map[Root]; pe = new PathEdge(e, Root, Root); } pel.SendPathEdgeEvent(pe); pe.Subscribe(); pe.ReceivedPacketEvent(data); } catch (Exception x) { if (pe != null) { //This closes both edges: pe.Close(); } else if (e != null) { Console.WriteLine("Closing ({0}) due to: {1}", e, x); e.Close(); } } } }