powpow

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