This is a high-performance, event notification library for Nim. It provides a low-level event loop and timer wheel, as well as higher-level abstractions for building TCP/UDP, HTTP and WebSocket servers.
The library is designed to be minimal and efficient, with a focus on low-latency event handling and minimal overhead, providing a solid foundation for building high-performance networked applications in Nim.
Features
Core Event Loop (loop.nim)
- Single-threaded non-blocking reactor
- I/O multiplexing via kqueue (macOS/BSD), epoll (Linux), IOCP (Windows), poll (fallback), or the opt-in Linux io_uring backend (io/)
- 4-level hierarchical timer wheel — O(1) insert/fire/cancel
- One-shot and repeating interval timers
- Deferred callbacks (executed before each I/O poll iteration)
- Idle handlers (executed when no I/O events are pending)
- Pointer-based fd watcher dispatch — zero hash-table lookups on the hot path
- Generation-counter stale event detection
- Dead watcher sweep with zombie/retired list for in-flight event safety
- Thread-safe stop() via eventfd (Linux) or self-pipe (macOS/BSD)
- Buffer pool for shared read buffers
- Adaptive event capacity scaling (min 64, max 4096)
TCP Networking (net/tcp.nim)
- Non-blocking TCP server with connection pooling
- Non-blocking TCP client with async connect (DNS resolved on the loop)
- Edge-triggered I/O events
- Write buffering with automatic corking (TCP_CORK / TCP_NOPUSH)
- Scatter-gather writes via writev
- Zero-copy file send via sendfile (Linux sendfile, macOS sendfile, POSIX fallback)
- Graceful shutdown with close-after-drain (closeAfterDrain)
- Unix domain socket support (macOS/BSD/Linux)
- SO_LINGER{0} for fast shutdown
- Per-connection read buffer pooling
Async DNS (net/dns.nim)
- In-loop DNS resolver (RFC 1035) — no blocking getaddrinfo, no worker threads
- Reads /etc/hosts and /etc/resolv.conf (system resolver config)
- A + AAAA queries with A-fallback; retries with timeout/attempts
- TTL-based result cache + negative caching
- resolveAddrAsync for users; connect uses it automatically
- Numeric IP literals resolve inline (zero DNS I/O)
OS Signals (signal.nim)
- In-process SignalRelay pub/sub bus (listen / listenOnce / unlisten)
- watchOsSignal/watchOsSignals deliver real OS signals through the loop
- OsSignal enum: SIGHUP, SIGINT, SIGQUIT, SIGUSR1/2, SIGPIPE, SIGALRM, SIGTERM, SIGURG, SIGCHLD, SIGIO
- Platform-native delivery: signalfd (Linux), self-pipe (macOS/BSD/POSIX), SetConsoleCtrlHandler Ctrl+C (Windows) — no global signal handlers
- Graceful shutdown on SIGINT/SIGTERM without blocking the loop
Stream I/O (stream.nim)
- IoStream wraps an arbitrary non-blocking fd and drives it from the loop
- Pipes, subprocess stdout, UDS and socketpair IPC; newStreamPair creates a full-duplex channel
- Connection-style write path: direct write drained until EAGAIN, remainder buffered and flushed on Write events; 32 MiB queued-write cap
- pause/resume read backpressure (a paused reader blocks the pipe writer)
- close is the single terminal transition and fires onClose exactly once; closeAfterWrite flushes then delivers EOF to the peer
- POSIX only (Windows IOCP is sockets-only); regular files work on kqueue but epoll rejects them
UDP Networking (net/udp.nim)
- Non-blocking UDP server (bind) and client (connect)
- recvfrom / sendto for connectionless communication
- Connected UDP sockets for peer-scoped send/recv
HTTP/1.1 Parser (proto/http.nim)
- Incremental, zero-copy parser — materialize strings lazily from byte offsets
- O(1) method dispatch via first-byte switch
- Pipelined request support
- Streaming body handling via callback
- Chunked transfer encoding
- Body streaming to file
- Multipart form data support
HTTP Server (proto/httpserver.nim)
- Implement your-own-router — lower-level callback-based design
- OnRequestCallback* = proc(req: HttpRequest, res: HttpResponse) {.gcsafe.}
- Higher-level frameworks implement routing on top of this callback
- Streaming response body
- Static file serving with MIME type detection
- Conditional requests (If-Modified-Since, If-None-Match)
- Range requests with 206 Partial Content
- Directory listing
- CORS headers
- Streaming multipart upload handling
- Pipelined request-response processing
WebSocket (proto/ws.nim)
- RFC 6455 compliant
- Standalone WebSocket server mode
- HTTP upgrade from HttpServer routes
- Text, binary, ping/pong, and close frames
- Per-message deflate extension
- Masked frame handling
Multi-threaded HTTP Server (proto/multithread.nim)
- SO_REUSEPORT kernel-level connection distribution
- One event loop + listen socket per worker thread
- Zero cross-thread communication — no single-threaded acceptor bottleneck
- Graceful shutdown via shutdown pipe
SIMD-Accelerated Scanning (proto/simdscan.nim)
- SSE2-accelerated CRLF detection
- Scalar fallback for non-x86 architectures
Platform Abstraction (platform/)
- kqueue — macOS/BSD (high-performance, edge-triggered)
- epoll — Linux (with eventfd wake)
- iocp — Windows (I/O Completion Ports)
- poll — POSIX fallback
- io/ — Linux io_uring backend (submission-based, opt-in). Enabled with nimble --features:io_uring <cmd>, requires "powpow[io_uring]", or nim c -d:powpowIoUring. The same public API, driven by IORING_OP_ACCEPT/RECV/SEND/CONNECT/SEND_ZC/SPLICE/... completions instead of readiness events; the generic fd-watcher API is emulated with one-shot IORING_OP_POLL_ADD. Ships the full io_uring API binding (io/uring.nim), IORING_REGISTER_PROBE feature detection, zero-copy SEND_ZC and SPLICE file sends, and registered buffers (IORING_REGISTER_BUFFERS). Requires Linux >= 5.6.
Networking Common (net/common.nim)
- Platform-agnostic socket API and address resolution (IPv4 + IPv6)
- Socket options: non-blocking, SO_REUSEADDR, SO_REUSEPORT, TCP_NODELAY
- sendfile zero-copy file transmission
- Cross-platform error handling (EAGAIN, EINPROGRESS, etc.)
- Auto-initialization (WSAStartup on Windows, SIGPIPE ignore on POSIX)
Exports
-
ObserverCallback, FdCallback, EventType, TimerId, TimerCallback, ==, Callback, iouEnabled, TlsState, PlatformEvent, poll, Platform, TimerId, ==, modify, iouEnabled, ObserverCallback, add, wake, FdCallback, ensureCapacity, EventType, TimerCallback, Callback, init, remove, TlsState, Loop, postToLoop, deferCall, pauseTimer, unregister, poll, unregisterFd, addInterval, TimerId, ==, modify, poll, ObserverCallback, FdWatcher, remove, EventType, close, cancelObserver, TimerCallback, Callback, register, init, resumeTimer, wake, TlsState, releaseBuf, PlatformEvent, newLoop, removeIdle, run, Platform, close, iouEnabled, timerCount, addIdle, monoMs, addCleanup, Observer, add, cancelTimer, runOnce, FdCallback, ensureCapacity, modify, acquireBuf, observe, stop, isRunning, addTimer, addIdle, sockInProgress, ObserverCallback, DtlsMaxChunk, FdCallback, close, timerCount, bindUdp, observe, sendv, monoMs, SEEK_END, TxtCallback, DnsResolver, shutdown, remove, setTcpNoDelay, MaxConnPoolSize, sockWritev, OnUdpData, closeFile, close, close, sockaddrFromIp, addTimer, poll, maxBufPoolSize, sendFile, DtlsConfig, TlsState, IoStream, pauseTimer, Platform, write, readFile, sockRecv, driveHandshake, connectUdp, sendTo, lastSocketError, O_BINARY, O_RDONLY, closeDns, unregisterFd, DtlsMtuDefault, sessionCount, close, wrapTls, OnAccept, Observer, DnsCacheEntry, send, ConnState, listenUnix, send, unregister, TimerId, IoStreamState, addCleanup, sockWouldBlock, newClientTlsContext, connectUnix, injectFd, removeIdle, close, setReuseAddr, sendTo, SslError, newServerTlsContext, tlsRead, run, getClientSockAddr, newTcpServer, postToLoop, isTlsActive, flushWriteBuffer, MxCallback, TimerCallback, sendFileActive, FdWatcher, acquireBuf, MaxIoStreamWriteBuffer, cancelObserver, newDtlsServer, resumeTimer, closeAfterDrain, closeAndRelease, sockShutdown, cancelSendFile, DtlsSweepIntervalDefaultMs, addInterval, tlsFree, DefaultSendFileChunk, SEEK_CUR, sendTo, maxWriteBufferSize, newServerDtlsContext, Callback, DtlsError, OnError, SendFileChunkSize, newStreamPair, resume, releaseBuf, OnData, openStream, listen, openFileRead, connectDtls, DtlsSession, sockSend, resolveAddr, EventType, getSockLen, continueSendFile, DtlsMaxSessionsDefault, connectHe, isRunning, close, setReusePort, close, close, UNIX_PATH_MAX, ==, MaxBufPoolSize, TxtRecord, write, DtlsRole, DtlsSessionState, deferCall, send, newConnection, setTcpCork, resolveMxAsync, ensureCapacity, setNonBlocking, OnClose, init, SslContext, initNet, runOnce, isIpAddress, UdpSocket, sendFileChunk, Connection, Loop, configureDns, peerAddrStr, wake, sockInterrupted, resolveTxtAsync, iouEnabled, add, send, DnsCallback, connect, sendTo, DtlsContext, register, poll, setDnsServers, modify, seekFile, setIpv6Only, pause, newLoop, DtlsServer, maxConnPoolSize, resolveAddrBothAsync, closeAfterWrite, tlsWrite, ResolvedIp, getClientIp, formatIp, defaultDtlsConfig, resolveAddrAsync, getFileSize, sendTo, TlsRole, resolveAddrAll, TcpServer, SEEK_SET, DefaultBufSize, MxRecord, DnsQuery, send, newClientDtlsContext, NetError, DtlsHandshakeTimeoutDefaultMs, DtlsIdleTimeoutDefaultMs, sockClose, send, PlatformEvent, cancelTimer, modify, stop, close, close, peekPath, delete, resetForNext, DefaultMaxFrameSize, DefaultKeepAliveMs, hasTrailers, getMultipart, getQuery, upgradeToWs, withinRoot, isComplete, newHttpClient, closeAll, send, put, HttpRequest, get, onMessage, PooledConn, getConnectionClose, patch, connectWs, reset, getConnectionClose, WsErrorCb, writeFrameMasked, options, sendPong, getBodyStream, WsError, readChunkInto, removeSession, ParsePhase, drainChunk, parseWsFrames, phase, getConn, close, WsServer, post, serveFile, post, getTrailer, WsMessageCb, HttpClientBase, newHttpServer, peekMethod, websocketUpgrade, MaxHeaderSize, MultiThreadHttpServer, HttpClientResponse, sendHandshakeRequest, get, listenUnix, HttpResponse, getMethod, WsFrameKind, WsCloseCb, peekAll, readChunkString, put, RateLimiter, MaxWsPoolSize, setError, DefaultMaxIdlePerHost, newWsServer, put, header, get, head, getTrailer, sendPing, request, getUrl, sendFile, populatePools, error, HttpClient, writeFrame, getPath, request, tryAdvance, allow, headerBytes, delete, getLoop, getRequest, OnRequestCallback, HttpParser, addConnection, newWsServer, DefaultChunkSize, sendHandshake, getHeaders, AsyncHttpClient, MaxRequestLine, getConnectionClose, newHttpServer, put, MaxHeaders, patch, options, newWsConnection, get, listen, markSent, send, sendError, listen, options, getContentLength, isChunked, head, getTrailers, getProtocol, parseWsUrl, listen, getStatusText, ConnHttp, getContentLength, getTrailers, patch, getContentLength, wsPoolAdd, idleConnections, request, computeAcceptKey, idleConnections, streamToFile, request, newRateLimiter, options, WsOpenCb, DefaultMaxResponseBody, getClientIp, DefaultBodyBuf, handshakeCount, WindowLimit, onClose, PoolKey, start, finalizeCloseDelimited, headersDone, status, sendBinary, getRemainingData, getBodyString, close, idleConnectionsFor, hasTrailers, resolveReal, HttpError, post, getFileExt, feed, getHeaders, peekChunk, setKeepAliveTimeout, ensureTcpServer, head, HttpServer, isOk, DefaultMaxIdleTotal, delete, push, head, getStatusText, removeFromPool, start, isError, reset, getBody, MaxStreamBodySize, MinStreamBodySize, start, WsConnection, newHttpConnPool, close, getClientIp, getBody, isEstablished, getBodyView, delete, getLoop, HttpBodyCallback, post, patch, close, BodyStream, close, check, sendMessage, DefaultIdleTimeoutMs, newMultiRateLimiter, onOpen, stop, getBody, pop, newHttpServer, streamFile, getStatusCode, getHttpMinor, writeDisposition, bodyView, onError, wsPoolPop, parseRange, readChunk, sendText, HttpConnPool, getBodyString, getHeaders, peekContentType, newHttpParser, sendMessage, serveStatic, feed, closeWs, getStatusCode, newAsyncHttpClient, buildHandshakeResponse, emit, ListenerHandle, watchOsSignals, watchOsSignal, listen, signalNumber, newOsSignalRelay, listen, OsSignal, SIG_BLOCK, unlisten, newSignalRelay, listenOnce, listenOnce, close, FileSystemEvent, FileWatcherCb, newFileWatcher, FileWatcher, HeartbeatMs, TimerId, ==, shutdownThreadPool, iouEnabled, ThreadPoolError, closeThreadPool, getLoop, ObserverCallback, submitWork, newThreadPool, EventType, TimerCallback, Callback, ThreadPool, FdCallback, TlsState, sendMessage, pauseTimer, onClose, computeAcceptKey, SslContext, onClose, addInterval, ==, modify, WsOpenCb, WsReconnectPolicy, sendMessage, handshakeCount, onMessage, onError, FdWatcher, WsClient, Loop, removeIdle, sendBinary, WsErrorCb, TimerCallback, sendPong, close, WsRetryCb, TlsState, releaseBuf, getProtocol, WsGiveUpCb, upgradeToWs, runOnce, parseWsFrames, close, connect, WsServer, SslError, timerCount, deferCall, WsMessageCb, addIdle, modify, run, websocketUpgrade, add, cancelTimer, sendHandshakeRequest, run, WsCloseCb, observe, reset, session, isRunning, addTimer, start, poll, init, WsConnection, writeFrameMasked, onOpen, postToLoop, close, unregister, poll, unregisterFd, newWsServer, TimerId, isEstablished, attemptCount, connect, onRetry, sendPing, onOpen, onMessage, DefaultMaxFrameSize, ObserverCallback, DefaultWsReconnectPolicy, onGiveUp, remove, writeFrame, EventType, close, sendMessage, FdCallback, Callback, register, resumeTimer, wake, isConnected, cancelObserver, WsFrameKind, PlatformEvent, wrapTls, newLoop, connectWs, TlsRole, sendHandshake, newWsServer, Platform, setTlsContext, sendMessage, onError, iouEnabled, newWsConnection, monoMs, addCleanup, sendText, newServerTlsContext, Observer, ensureCapacity, acquireBuf, listen, WsError, newClientTlsContext, stop, closeWs, isTlsActive, newWsClient, parseWsUrl, buildHandshakeResponse