protected void HandleWrites(SocketState ss) { ArrayList socks = ss.WriteSocks; for (int i = 0; i < socks.Count; i++) { Socket s = (Socket)socks[i]; CreationState cs = ss.TakeCreationState(s); if (cs != null) { cs.HandleWritability(s); } else { //Let's try to flush the buffer: try { ss.FlushSocket(s); } catch { /* * We should close this edge */ TcpEdge tcpe = ss.GetEdge(s); TEL.RequestClose(tcpe); //Go ahead and forget about this socket. CloseAction ca = new CloseAction(tcpe, null); ca.Start(ss); } } } }
/** * Called when the socket is writable */ public void HandleWritability(Socket s) { try { if (s.Connected) { TcpEdgeListener.SetSocketOpts(s); TcpEdge e = new TcpEdge(TEL, false, s); Result.Value = e; //Handle closes in the select thread: CloseAction ca = new CloseAction(e, TEL.ActionQueue); e.CloseEvent += ca.CloseHandler; //Set the edge TEL.ActionQueue.Enqueue(this); } else { //This did not work out, close the socket and release the resources: HandleError(s); } } catch (Exception) { //This did not work out, close the socket and release the resources: //Console.WriteLine("Exception: {0}", x); HandleError(s); } }
public override void Start(SocketState ss) { /* * Note, we are the only thread running actions from the queue, * so, no change to ss can happen concurrently with this logic */ ArrayList close_actions = new ArrayList(); foreach (Socket s in ss.AllSockets) { TcpEdge e = ss.GetEdge(s); TEL.RequestClose(e); /* * We can't just call ca.Start(ss) because that * would change ss.AllSockets */ close_actions.Add(new CloseAction(e, null)); } foreach (CloseAction ca in close_actions) { ca.Start(ss); } //Close the main socket: ss.ListenSock.Close(); }
/* * Update the SocketState.TAA and check to see if any Edges need * to be closed. */ public override void Start(SocketState ss) { ss.TAA = TAA; ArrayList bad_edges = new ArrayList(); foreach (Socket s in ss.AllSockets) { TcpEdge e = ss.GetEdge(s); if (e != null) { if (TAA.Authorize(e.RemoteTA) == TAAuthorizer.Decision.Deny) { //We can't close now, that would invalidate the AllSockets //iterator bad_edges.Add(e); } } } foreach (TcpEdge e in bad_edges) { EL.RequestClose(e); CloseAction ca = new CloseAction(e, null); ca.Start(ss); } }
/** * Implements the SocketStateAction interface. This is called to trigger the ECB * in the SelectThread so we don't have to worry about multiple threads * accessing variables. */ public override void Start(SocketState ss) { object result = Result.Value; if (result != null) { TcpEdge new_edge = result as TcpEdge; if (new_edge != null) { //Tell the world about the new Edge: ss.AddEdge(new_edge); ECB(true, new_edge, null); } else { ECB(false, null, (Exception)result); } } else { //Try to make a new start: if (IPAddressQueue.Count <= 0) { ECB(false, null, new EdgeException("No more IP Addresses")); } else { Socket s = null; try { s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); s.Blocking = false; ss.AddCreationState(s, this); IPAddress ipaddr = (IPAddress)IPAddressQueue.Dequeue(); IPEndPoint end = new IPEndPoint(ipaddr, Port); //This is a hack because of a bug in MS.Net and Mono: //https://bugzilla.novell.com/show_bug.cgi?id=349449 //http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=332142 s.Bind(new IPEndPoint(IPAddress.Any, 0)); s.Connect(end); } catch (SocketException sx) { if (sx.SocketErrorCode != SocketError.WouldBlock) { if (s != null) { ss.TakeCreationState(s); } ECB(false, null, new EdgeException(false, "Could not Connect", sx)); } /* else Ignore the non-blocking socket error */ } } } }
public void AddEdge(TcpEdge e) { Socket s = e.Socket; AllSockets.Add(s); ReceiveState rs = new ReceiveState(e, BA); _sock_to_rs[s] = rs; Interlocked.Increment(ref TEL._count); }
public void RemoveEdge(TcpEdge e) { Socket s = e.Socket; if (false == _sock_to_rs.Contains(s)) { return; } // Go ahead and remove from the map. ... this needs to be done because // Socket's dynamic HashCode, a bug in an older version of Mono Hashtable new_s_to_rs = new Hashtable(_sock_to_rs.Count); foreach (DictionaryEntry de in _sock_to_rs) { ReceiveState trs = (ReceiveState)de.Value; if (e != trs.Edge) { new_s_to_rs.Add(de.Key, trs); } } _sock_to_rs = new_s_to_rs; AllSockets.Remove(s); _socks_to_send.Remove(s); Interlocked.Decrement(ref TEL._count); //We shouldn't be sending at the same time: lock ( e ) { //We need to shutdown the socket: try { //Don't let more reading or writing: s.Shutdown(SocketShutdown.Both); } catch { } finally { //This can't throw an exception s.Close(); } } }
public void HandleEdgeSend(Edge from, ICopyable p) { TcpEdge sender = (TcpEdge)from; try { bool flushed = true; lock ( sender ) { //Try to fill up the buffer: sender.WriteToBuffer(p); //Okay, we loaded the whole packet into the TcpEdge's buffer //now it is time to try to flush the buffer: flushed = sender.Flush(); } if (!flushed) { /* * We should remember to try again when the socket is * writable */ ActionQueue.Enqueue(new SendWaitAction(sender.Socket)); } } catch (EdgeException ex) { if (false == ex.IsTransient) { //Go ahead and forget about this socket. RequestClose(from); ActionQueue.Enqueue(new CloseAction(sender, null)); } //Rethrow the exception throw; } catch (Exception x) { //Assume any other error is transient: throw new EdgeException(true, String.Format("Could not send on: {0}", from), x); } }
protected void HandleReads(SocketState ss) { ArrayList readsocks = ss.ReadSocks; Socket listen_sock = ss.ListenSock; for (int i = 0; i < readsocks.Count; i++) { Socket s = (Socket)readsocks[i]; //See if this is a new socket if (s == listen_sock) { TcpEdge e = null; Socket new_s = null; try { new_s = listen_sock.Accept(); IPEndPoint rep = (IPEndPoint)new_s.RemoteEndPoint; new_s.LingerState = new LingerOption(true, 0); TransportAddress rta = TransportAddressFactory.CreateInstance(TransportAddress.TAType.Tcp, rep); if (ss.TAA.Authorize(rta) == TAAuthorizer.Decision.Deny) { //No thank you Dr. Evil Console.Error.WriteLine("Denying: {0}", rta); new_s.Close(); } else { //This edge looks clean TcpEdgeListener.SetSocketOpts(s); e = new TcpEdge(TEL, true, new_s); ss.AddEdge(e); //Handle closes in the select thread: CloseAction ca = new CloseAction(e, TEL.ActionQueue); e.CloseEvent += ca.CloseHandler; TEL.SendEdgeEvent(e); } } catch (Exception) { //Looks like this Accept has failed. Do nothing //Console.Error.WriteLine("New incoming edge ({0}) failed: {1}", new_s, sx); //Make sure the edge is closed if (e != null) { TEL.RequestClose(e); //Go ahead and forget about this socket. CloseAction ca = new CloseAction(e, null); ca.Start(ss); } else if (new_s != null) { //This should not be able to throw an exception: new_s.Close(); } } } else { ReceiveState rs = ss.GetReceiveState(s); if (rs != null && !rs.Receive()) { TEL.RequestClose(rs.Edge); //Go ahead and forget about this socket. CloseAction ca = new CloseAction(rs.Edge, null); ca.Start(ss); } } } }
public CloseAction(TcpEdge e, LockFreeQueue <SocketStateAction> q) { _e = e; _queue = q; }
public void RemoveEdge(TcpEdge e) { Socket s = e.Socket; if( false == _sock_to_rs.Contains(s) ) { return; } // Go ahead and remove from the map. ... this needs to be done because // Socket's dynamic HashCode, a bug in an older version of Mono Hashtable new_s_to_rs = new Hashtable( _sock_to_rs.Count ); foreach(DictionaryEntry de in _sock_to_rs) { ReceiveState trs = (ReceiveState)de.Value; if( e != trs.Edge ) { new_s_to_rs.Add( de.Key, trs ); } } _sock_to_rs = new_s_to_rs; AllSockets.Remove(s); _socks_to_send.Remove(s); Interlocked.Decrement(ref TEL._count); //We shouldn't be sending at the same time: lock( e ) { //We need to shutdown the socket: try { //Don't let more reading or writing: s.Shutdown(SocketShutdown.Both); } catch { } finally { //This can't throw an exception s.Close(); } } }
public ReceiveState(TcpEdge e, BufferAllocator ba) { Edge = e; _s = e.Socket; _ba = ba; }
protected void HandleReads(SocketState ss) { ArrayList readsocks = ss.ReadSocks; Socket listen_sock = ss.ListenSock; for(int i = 0; i < readsocks.Count; i++) { Socket s = (Socket)readsocks[i]; //See if this is a new socket if( s == listen_sock ) { TcpEdge e = null; Socket new_s = null; try { new_s = listen_sock.Accept(); IPEndPoint rep = (IPEndPoint)new_s.RemoteEndPoint; new_s.LingerState = new LingerOption (true, 0); TransportAddress rta = TransportAddressFactory.CreateInstance(TransportAddress.TAType.Tcp, rep); if( ss.TAA.Authorize(rta) == TAAuthorizer.Decision.Deny ) { //No thank you Dr. Evil Console.Error.WriteLine("Denying: {0}", rta); new_s.Close(); } else { //This edge looks clean TcpEdgeListener.SetSocketOpts(s); e = new TcpEdge(TEL, true, new_s); ss.AddEdge(e); //Handle closes in the select thread: CloseAction ca = new CloseAction(e, TEL.ActionQueue); e.CloseEvent += ca.CloseHandler; TEL.SendEdgeEvent(e); } } catch(Exception) { //Looks like this Accept has failed. Do nothing //Console.Error.WriteLine("New incoming edge ({0}) failed: {1}", new_s, sx); //Make sure the edge is closed if( e != null ) { TEL.RequestClose(e); //Go ahead and forget about this socket. CloseAction ca = new CloseAction(e, null); ca.Start(ss); } else if( new_s != null) { //This should not be able to throw an exception: new_s.Close(); } } } else { ReceiveState rs = ss.GetReceiveState(s); if( rs != null && !rs.Receive() ) { TEL.RequestClose(rs.Edge); //Go ahead and forget about this socket. CloseAction ca = new CloseAction(rs.Edge, null); ca.Start(ss); } } } }
/** * Called when the socket is writable */ public void HandleWritability(Socket s) { try { if( s.Connected ) { TcpEdgeListener.SetSocketOpts(s); TcpEdge e = new TcpEdge(TEL, false, s); Result.Value = e; //Handle closes in the select thread: CloseAction ca = new CloseAction(e, TEL.ActionQueue); e.CloseEvent += ca.CloseHandler; //Set the edge TEL.ActionQueue.Enqueue(this); } else { //This did not work out, close the socket and release the resources: HandleError(s); } } catch(Exception) { //This did not work out, close the socket and release the resources: //Console.WriteLine("Exception: {0}", x); HandleError(s); } }
public CloseAction(TcpEdge e, LockFreeQueue<SocketStateAction> q) { _e = e; _queue = q; }