All Projects → lithdew → snow

lithdew / snow

Licence: MIT license
A small, fast, cross-platform, async Zig networking framework built on top of lithdew/pike.

Programming Languages

Zig
133 projects

Projects that are alternatives of or similar to snow

overload
📡 Overload DoS Tool (Layer 7)
Stars: ✭ 167 (+456.67%)
Mutual labels:  tcp
p2p
Simple implementation of a p2p network in Go
Stars: ✭ 12 (-60%)
Mutual labels:  tcp
gosynflood
Demonstrates a synflood DDOS attack with raw sockets (for Ubuntu and Debian-like distros)
Stars: ✭ 88 (+193.33%)
Mutual labels:  tcp
funboost
pip install funboost,python全功能分布式函数调度框架,。支持python所有类型的并发模式和全球一切知名消息队列中间件,python函数加速器,框架包罗万象,一统编程思维,兼容50% python编程业务场景,适用范围广。只需要一行代码即可分布式执行python一切函数。旧名字是function_scheduling_distributed_framework
Stars: ✭ 351 (+1070%)
Mutual labels:  tcp
AndroidNetMonitor
This project aims to collect and analyze traffic information of Android.(采集手机发送和接收的报文简要信息,并且根据socket记录每个报文对应哪个手机app)
Stars: ✭ 25 (-16.67%)
Mutual labels:  tcp
dperf
dperf is a DPDK based 100Gbps network performance and load testing software.
Stars: ✭ 1,320 (+4300%)
Mutual labels:  tcp
NLog
Flexible logging for C# and Unity
Stars: ✭ 158 (+426.67%)
Mutual labels:  tcp
protocol
Easy protocol definitions in Rust
Stars: ✭ 151 (+403.33%)
Mutual labels:  tcp
XAsyncSockets
XAsyncSockets is an efficient Python/MicroPython library of managed asynchronous sockets.
Stars: ✭ 28 (-6.67%)
Mutual labels:  tcp
gnb udp over tcp
gnb_udp_over_tcp 是一个为GNB开发的通过tcp链路中转UDP分组转发的服务
Stars: ✭ 32 (+6.67%)
Mutual labels:  tcp
mqtt
The fully compliant, embeddable high-performance Go MQTT v5 server for IoT, smarthome, and pubsub
Stars: ✭ 356 (+1086.67%)
Mutual labels:  tcp
NakovForwardServer
TCP port forwarding software, written in Java: forwards a local TCP port (e.g. 127.0.0.1:1521) to external port (e.g. 0.0.0.0:1522)
Stars: ✭ 41 (+36.67%)
Mutual labels:  tcp
condor
A minimal library for building scalable TCP servers in Erlang
Stars: ✭ 75 (+150%)
Mutual labels:  tcp
ChatServerTCP
保密型聊天软件服务器 /Private Chat Server
Stars: ✭ 14 (-53.33%)
Mutual labels:  tcp
GenericProtocol
⚡️ A fast TCP event based buffered server/client protocol for transferring data over the (inter)net in .NET 🌐
Stars: ✭ 38 (+26.67%)
Mutual labels:  tcp
network exporter
ICMP & MTR & TCP Port & HTTP Get - Network Prometheus exporter
Stars: ✭ 162 (+440%)
Mutual labels:  tcp
mongoose
Embedded Web Server
Stars: ✭ 8,968 (+29793.33%)
Mutual labels:  tcp
tcp server client
A thin and simple C++ TCP client server
Stars: ✭ 124 (+313.33%)
Mutual labels:  tcp
Swiddler
TCP/UDP debugging tool.
Stars: ✭ 56 (+86.67%)
Mutual labels:  tcp
fourinarow-app
An online version of the popular game four in a row, written in Flutter + Dart on the client and Rust on the server side.
Stars: ✭ 23 (-23.33%)
Mutual labels:  tcp

snow

A small, fast, cross-platform, async Zig networking framework built on top of lithdew/pike.

It automatically handles:

  1. buffering/framing data coming in and out of a socket,
  2. managing the lifecycle of incoming / outgoing connections, and
  3. representing a singular Client / Server as a bounded adaptive pool of outgoing / incoming connections.

It also allows you to specify:

  1. how messages are framed (\n suffixed to each message, message length prefixed to each message, etc.),
  2. a sequence of steps to be performed before successfully establishing a connection (a handshake protocol), and
  3. an upper bound to the maximum number of connections a Client / Server may pool in total.

Usage

In your build.zig:

const std = @import("std");

const Builder = std.build.Builder;

const pkgs = struct {
    const pike = std.build.Pkg{
        .name = "pike",
        .path = "pike/pike.zig",
    };

    const snow = std.build.Pkg{
        .name = "snow",
        .path = "snow/snow.zig",
        .dependencies = &[_]std.build.Pkg{
            pike,
        }
    };
};

pub fn build(b: *Builder) void {
    // Given a build step...
    step.addPackage(pkgs.pike);
    step.addPackage(pkgs.snow);
}

Protocol

Applications written with snow provide a Protocol implementation which specifies how message are encoded / decoded into frames.

Helpers (io.Reader / io.Writer) are provided to assist developers in specifying how frame encoding / decoding is to be performed.

Given a Protocol implementation, a Client / Server may be instantiated.

Here is an example of a Protocol that frames messages based on an End-of-Line character ('\n') suffixed at the end of each message:

const std = @import("std");
const snow = @import("snow");

const mem = std.mem;

const Protocol = struct {
    const Self = @This();

    // This gets called right before a connection is marked to be successfully established!
    //
    // Unlike the rest of the callbacks below, 'socket' is a raw 'pike.Socket'. Feel free to
    // read / write as much data as you wish, or to return an error to prevent a connection
    // from being marked as being successfully established.
    //
    // Rather than 'void', snow.Options.context_type may be set and returned from 'handshake'
    // to bootstrap a connection with additional fields and methods under 'socket.context'.
    pub fn handshake(self: *Self, comptime side: snow.Side, socket: anytype) !void {
        return {};
    }

    // This gets called before a connection is closed!
    pub fn close(self: *Self, comptime side: snow.Side, socket: anytype) void {
        return {};
    }

    // This gets called when a connection's resources is ready to be de-allocated!
    //
    // A slice of remaining items in the socket's write queue is passed to purge() to be
    // optionally deallocated.
    pub fn purge(self: *Self, comptime side: snow.Side, socket: anytype, items: []const []const u8) void {
        return {};
    }

    // This gets called when data is ready to be read from a connection!
    pub fn read(self: *Self, comptime side: snow.Side, socket: anytype, reader: anytype) !void {
        while (true) {
            const line = try reader.readLine();
            defer reader.shift(line.len);

            // Do something with the frame here!
        }
    }

    // This gets called when data is queued and ready to be encoded and written to
    // a connection!
    //
    // Rather than '[]const u8', custom message types may be set to be queuable to the
    // connections write queue by setting snow.Options.message_type.
    pub fn write(self: *Self, comptime side: snow.Side, socket: anytype, writer: anytype, items: [][]const u8) !void {
        for (items) |message| {
            if (mem.indexOfScalar(u8, message, '\n') != null) {
                return error.UnexpectedDelimiter;
            }

            const frame = try writer.peek(message.len + 1);
            mem.copy(u8, frame[0..message.len], message);
            frame[message.len..][0] = '\n';
        }

        try writer.flush();
    }
};

Client

A Client comprises of a bounded adaptive pool of outgoing connections that are to be connected to a single IPv4/IPv6 endpoint.

When writing a message to an endpoint with a Client, a connection is initially grabbed from the pool. The message is then queued to be written to the connection's underlying socket.

A policy is specified for selecting which connection to grab from a Client's pool. The policy goes as follows:

There exists a configurable maximum number of connections that may belong to a Client's pool (defaulting to 16). If all existing connections in a Client's pool contain queued messages that have yet to be flushed and written, a new connection is created and registered to the pool up to a maximum number of connections.

If the pool's maximum number of connections limit is reached, the connection in the pool with the smallest number of queued messages is returned. Otherwise, a new connection is created and registered to the pool and returned.

Server

A Server comprises of a bounded adaptive pool of incoming connections accepted from a single bounded IPv4/IPv6 endpoint. There exists a configurable maximum number of connections that may belong to a Server's pool (defaulting to 128).

Should an incoming connection be established and the pool underlying a Server appears to be full, the connection will be declined and de-initialized.

Socket

All sockets comprise of two coroutines: a reader coroutine, and a writer coroutine. The reader and writer coroutine are responsible for framing and buffering messages received from / written to a single socket instance, and for executing logic specified under a Protocol implementation.

An interesting detail to note is that the writer coroutine is entirely lock-free.

Performance

snow was written with performance in mind: zero heap allocations occur in all hot paths. Heap allocations only ever occur when establishing a new incoming / outgoing connection.

All other underlying components are stack-allocated and recycled as much as possible.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].