private void disconnect(EpollHandler handler) { var os = new Overspan(50); // detach the handler var socketHandle = handler.OnDetach(); // unsubscribe from Epoll events Remove(socketHandle, 0); // close the socket if (Syscall.close(socketHandle) < 0) { Log.Error($"Call to close(socked) failed: {Stdlib.GetLastError()}"); } Log.Epoll("[{0}] socked disconnected, closed", socketHandle); os.Check("disconnect()"); }
public void PollOnce(EpollEvent[] events, int timeoutMode = -1) { if (timeoutMode < 0) { Log.Epoll("Listener waiting for signals"); } var count = Syscall.epoll_wait(epfd, events, events.Length, timeoutMode); if (count < 0) { Log.Error($"Call to epoll_wait() failed with code {count}: {Stdlib.GetLastError()}"); return; } if (count > 0) { Log.Epoll("+" + count); } for (var i = 0; i < count; i++) { var ev = events[i]; Log.Epoll("Epoll[{0}] got {1} for {2}", i, ev.events, ev.u32); // find the handler var socket = (int)ev.u32; var handler = server.GetHandler(socket); if (((int)ev.events & disconnectMask) > 0) { disconnect(handler); } else if (ev.events.HasFlag(EpollEvents.EPOLLIN)) { if (socket == listenerSocket) { OnReadReady(); Update(socket, GetEvents()); } else { var os = new Overspan(50); var ret = handler.OnReadReady(); os.Check("OnReadReady()"); if (ret < 0) { disconnect(handler); } else { Update(socket, handler.GetEvents()); } } } else if (ev.events.HasFlag(EpollEvents.EPOLLOUT)) { var os = new Overspan(50); var ret = handler.OnWriteReady(); os.Check("OnWriteReady()"); if (ret < 0) { disconnect(handler); } else { Update(socket, handler.GetEvents()); } } } }
// called either from OnAttach or on EPOLLIN public int OnReadReady() { Log.Epoll("[{0}] OnReadReady()", socketHandle); if (state != EState.Reading) { Log.Error("OnReadReady() in state " + state); } if (socketHandle < 0) { Log.Error("Error: OnReadReady on detached socket"); return(0); } var read = Syscall.read(socketHandle, IntPtr.Add(bufferPtr, totalRead), (ulong)(Buffer.Length - totalRead)); Log.Epoll("[{0}] read() returned {1}", socketHandle, read); if (read < 0) { var errno = Stdlib.GetLastError(); if (errno == Errno.EAGAIN || errno == Errno.EWOULDBLOCK || errno == 0) { return(0); // continue in the Reading state } Log.Error("[{0}] read() socket error {1}", socketHandle, errno); return(-1); // waiting for the socket to be detached/closed } if (read == 0) { Log.Epoll("[{0}] peer closed connection", socketHandle); return(-1); } if (totalRead == 0 && processingStarted.Ticks == 0) { processingStarted = Stats.Watch.Elapsed; } totalRead += (int)read; if (RequestLength == 0) { ParseRequestHeader(totalRead); } if (RequestLength == 0 || RequestLength > 0 && totalRead < RequestLength) { return((int)read); // continue in the Reading state } // done! //Console.Write('<'); Log.Epoll("[{0}] Read completed, size={1}", socketHandle, RequestLength); if (RequestLength > MaxRequestSize) { MaxRequestSize = RequestLength; } // process the request setProcessing(); Log.Epoll("[{0}] Send to processing, query_id={1}", socketHandle, QueryId); var os = new Overspan(20); server.ProcessContext(this); os.Check(ContextType); return(0); }