Giter VIP home page Giter VIP logo

zig-network's Introduction

Zig Network Abstraction

Small network abstraction layer around TCP & UDP.

Features

  • Implements the minimal API surface for basic networking
  • Makes cross-platform abstractions
  • Supports blocking and non-blocking I/O via select/poll
  • UDP multicast support

Usage

Use with the package manager

build.zig.zon:

.{
    .name = "appname",
    .version = "0.0.0",
    .dependencies = .{
        .network = .{
            .url = "https://github.com/MasterQ32/zig-network/archive/<COMMIT_HASH_HERE>.tar.gz",
            .hash = "HASH_GOES_HERE",
        },
    },
}

(To aquire the hash, please remove the line containing .hash, the compiler will then tell you which line to put back)

build.zig:

exe.addModule("network", b.dependency("network", .{}).module("network"));

Usage example

const network = @import("network");

test "Connect to an echo server" {
    try network.init();
    defer network.deinit();

    const sock = try network.connectToHost(std.heap.page_allocator, "tcpbin.com", 4242, .tcp);
    defer sock.close();

    const msg = "Hi from socket!\n";
    try sock.writer().writeAll(msg);

    var buf: [128]u8 = undefined;
    std.debug.print("Echo: {}", .{buf[0..try sock.reader().readAll(buf[0..msg.len])]});
}

See async.zig for a more complete example on how to use asynchronous I/O to make a small TCP server.

Run examples

Build all examples:

$ zig build examples

Build a specific example:

$ zig build sync-examples

To test an example, eg. echo:

$ ./zig-out/bin/echo 3000

in another terminal

$ nc localhost 3000
hello
hello
how are you
how are you

Notes

On Windows receive and send function calls are asynchronous and cooperate with the standard library event loop when io_mode = .evented is set in the root file of your program.
Other calls (connect, listen, accept etc) are blocking.

zig-network's People

Contributors

360tetsu360 avatar a-day-old-bagel avatar alexnask avatar beyley avatar bingcicle avatar data-man avatar deecellar avatar ducdetronquito avatar g-w1 avatar gonzooo avatar iridescentrose avatar joachimschmidt557 avatar kassane avatar kprotty avatar luukdegram avatar magurotuna avatar masterq32 avatar mochalins avatar nektro avatar paoda avatar pwnfooj716 avatar rageoholic avatar robinka avatar rofrol avatar silbinarywolf avatar star-tek-mb avatar twystd avatar vesim987 avatar zerozshadow avatar zigster64 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zig-network's Issues

add sources to the notes

nice articles on portable sockets I found:

introduction to raw sockets and portable sockets basics.

Other implementations

Not sure, if relevant: microsoft/WSL#4240

Also: This seems to be an open problem on stack overflow.

From what I have been reading, only AF_INET and AF_INET6 are widely portable due to their necessity/generality.
Otherwise, (anonymous) pipes are used.
Though, curiously I found a (more recent) benchmark that shows (anonymous) pipes to be slower than unix domain sockets.

Code path issue when compiling for Linux while linking libc

When linking in libc I've noticed that compiling for Linux will result in a compilation error:

❯ zig build -Dtarget=native-linux
.\zig-network\network.zig:895:39: error: container 'std.c' has no member called 'getpeername'
    switch (std.os.errno(std.os.system.getpeername(sockfd, addr, addrlen))) {

I've made a repro repository here:

https://github.com/GoNZooo/link-libc-network-repro

Removing exe.linkLibC() in build.zig results in a successful compilation.

Note

This is with the following zig version info:

❯ zig version
0.6.0+083c0f1ce

Import of 'bind' overrides existing definition

Had that error while trying to add the library to my project. Line 1107 in network.zig.
The test cases in test-suite.zig also cause that error.

I am on windows 10, using zig 0.6.0+4b48fccad.

PS C:\Users\Guillaume\Programming\zig\repos\minecraft-server-test\zig-network> zig test .\testsuite.zig
.\network.zig:1107:5: error: import of 'bind' overrides existing definition
    usingnamespace std.os.windows;
    ^
.\network.zig:1443:5: note: previous definition here
    fn bind(sock: ws2_32.SOCKET, addr: *const std.os.sockaddr, namelen: std.os.socklen_t) std.os.BindError!void {
    ^
C:\zig\lib\zig\std\os\windows.zig:1160:5: note: imported definition here
pub fn bind(s: ws2_32.SOCKET, name: *const ws2_32.sockaddr, namelen: ws2_32.socklen_t) i32 {
    ^
.\network.zig:1107:5: error: import of 'listen' overrides existing definition
    usingnamespace std.os.windows;
    ^
.\network.zig:1352:5: note: previous definition here
    fn listen(sock: ws2_32.SOCKET, backlog: u32) ListenError!void {
    ^
C:\zig\lib\zig\std\os\windows.zig:1164:5: note: imported definition here
pub fn listen(s: ws2_32.SOCKET, backlog: u31) i32 {
    ^
.\network.zig:1107:5: error: import of 'getsockname' overrides existing definition
    usingnamespace std.os.windows;
    ^
.\network.zig:1409:5: note: previous definition here
    fn getsockname(sock: ws2_32.SOCKET, addr: *std.os.sockaddr, addrlen: *std.os.socklen_t) std.os.GetSockNameError!void {
    ^
C:\zig\lib\zig\std\os\windows.zig:1183:5: note: imported definition here
pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.socklen_t) i32 {
    ^
.\network.zig:1107:5: error: import of 'sendto' overrides existing definition
    usingnamespace std.os.windows;
    ^
.\network.zig:1192:5: note: previous definition here
    fn sendto(
    ^
C:\zig\lib\zig\std\os\windows.zig:1187:5: note: imported definition here
pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
    ^
.\network.zig:1107:5: error: import of 'recvfrom' overrides existing definition
    usingnamespace std.os.windows;
    ^
.\network.zig:1275:5: note: previous definition here
    fn recvfrom(
    ^
C:\zig\lib\zig\std\os\windows.zig:1197:5: note: imported definition here
pub fn recvfrom(s: ws2_32.SOCKET, buf: [*]u8, len: usize, flags: u32, from: ?*ws2_32.sockaddr, from_len: ?*ws2_32.socklen_t) i32 {
    ^
C:\zig\lib\zig\std\os\windows\bits.zig:920:28: note: referenced here
pub usingnamespace switch (builtin.arch) {
                           ^
C:\zig\lib\zig\std\os\windows\bits.zig:920:35: note: referenced here
pub usingnamespace switch (builtin.arch) {
                                  ^
.\network.zig:1460:23: note: referenced here
        hints: *const addrinfo,
                      ^
C:\zig\lib\zig\std\os\bits\windows.zig:175:23: note: referenced here
pub const socklen_t = ws2_32.socklen_t;
                      ^
C:\zig\lib\zig\std\os\bits\windows.zig:175:29: note: referenced here
pub const socklen_t = ws2_32.socklen_t;
                            ^
.\network.zig:1119:24: note: referenced here
        addrlen: std.os.socklen_t,
                       ^
C:\zig\lib\zig\std\os\bits\windows.zig:177:28: note: referenced here
pub const sockaddr = ws2_32.sockaddr;
                           ^
.\network.zig:1121:23: note: referenced here
        addr: ?*std.os.sockaddr,
                      ^
C:\zig\lib\zig\std\os\windows\ws2_32.zig:185:13: note: referenced here
    family: ADDRESS_FAMILY,
            ^
.\network.zig:1078:12: note: referenced here
} || std.os.UnexpectedError;
           ^
.\network.zig:1462:7: note: referenced here
    ) GetAddrInfoError!void {
      ^
.\network.zig:960:55: note: referenced here
        const getaddrinfo_fn = if (is_windows) windows.getaddrinfo else libc_getaddrinfo;
                                                      ^
.\network.zig:961:56: note: referenced here
        const freeaddrinfo_fn = if (is_windows) windows.funcs.freeaddrinfo else std.os.system.freeaddrinfo;
                                                       ^
.\network.zig:961:62: note: referenced here
        const freeaddrinfo_fn = if (is_windows) windows.funcs.freeaddrinfo else std.os.system.freeaddrinfo;
                                                             ^
.\network.zig:966:31: note: referenced here
        const name_c = try std.cstr.addNullByte(allocator, name);
                              ^
C:\zig\lib\zig\std\cstr.zig:9:13: note: referenced here
const mem = std.mem;
            ^
C:\zig\lib\zig\std\cstr.zig:41:32: note: referenced here
pub fn addNullByte(allocator: *mem.Allocator, slice: []const u8) ![:0]u8 {
                               ^
.\network.zig:966:36: note: referenced here
        const name_c = try std.cstr.addNullByte(allocator, name);
                                   ^
C:\zig\lib\zig\std\cstr.zig:42:33: note: referenced here
    const result = try allocator.alloc(u8, slice.len + 1);
                                ^
C:\zig\lib\zig\std\cstr.zig:43:8: note: referenced here
    mem.copy(u8, result, slice);
       ^
.\network.zig:969:31: note: referenced here
        const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});
                              ^
C:\zig\lib\zig\std\fmt.zig:9:13: note: referenced here
const mem = std.mem;
            ^
C:\zig\lib\zig\std\fmt.zig:1207:31: note: referenced here
pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![]u8 {
                              ^
.\network.zig:969:35: note: referenced here
        const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});
                                  ^
C:\zig\lib\zig\std\fmt.zig:1207:87: note: referenced here
pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![]u8 {
                                                                                      ^
.\network.zig:967:24: note: referenced here
        defer allocator.free(name_c);
                       ^
C:\zig\lib\zig\std\os\bits\windows.zig:187:29: note: referenced here
pub const AF_UNSPEC = ws2_32.AF_UNSPEC;
                            ^
.\network.zig:974:29: note: referenced here
            .family = std.os.AF_UNSPEC,
                            ^
C:\zig\lib\zig\std\os\bits\windows.zig:223:31: note: referenced here
pub const SOCK_STREAM = ws2_32.SOCK_STREAM;
                              ^
.\network.zig:975:31: note: referenced here
            .socktype = std.os.SOCK_STREAM,
                              ^
C:\zig\lib\zig\std\os\bits\windows.zig:241:31: note: referenced here
pub const IPPROTO_TCP = ws2_32.IPPROTO_TCP;
                              ^
.\network.zig:976:31: note: referenced here
            .protocol = std.os.IPPROTO_TCP,
                              ^
C:\zig\lib\zig\std\os\bits\windows.zig:189:27: note: referenced here
pub const AF_INET = ws2_32.AF_INET;
                          ^
.\network.zig:1004:23: note: referenced here
                std.os.AF_INET => block: {
                      ^
C:\zig\lib\zig\std\os\bits\windows.zig:212:28: note: referenced here
pub const AF_INET6 = ws2_32.AF_INET6;
                           ^
.\network.zig:1008:23: note: referenced here
                std.os.AF_INET6 => block: {
                      ^
.\network.zig:38:49: note: referenced here
        pub fn init(a: u8, b: u8, c: u8, d: u8) Self {
                                                ^
.\network.zig:1006:57: note: referenced here
                    break :block .{ .ipv4 = Address.IPv4.init(bytes[0], bytes[1], bytes[2], bytes[3]) };
                                                        ^
C:\zig\lib\zig\std\os\bits\windows.zig:179:32: note: referenced here
pub const sockaddr_in6 = ws2_32.sockaddr_in6;
                               ^
.\network.zig:1009:73: note: referenced here
                    const sockaddr_in6 = @ptrCast(*align(1) const std.os.sockaddr_in6, sockaddr);
                                                                        ^
C:\zig\lib\zig\std\os\windows\ws2_32.zig:211:11: note: referenced here
    port: USHORT,
          ^
.\network.zig:67:51: note: referenced here
        pub fn init(value: [16]u8, scope_id: u32) Self {
                                                  ^
.\network.zig:1010:57: note: referenced here
                    break :block .{ .ipv6 = Address.IPv6.init(sockaddr_in6.addr, sockaddr_in6.scope_id) };
                                                        ^
.\network.zig:1022:52: note: referenced here
                    result.canon_name = try std.mem.dupe(arena, u8, std.mem.spanZ(n));
                                                   ^
.\network.zig:1022:76: note: referenced here
                    result.canon_name = try std.mem.dupe(arena, u8, std.mem.spanZ(n));
                                                                           ^
C:\zig\lib\zig\std\mem.zig:614:28: note: referenced here
pub fn spanZ(ptr: anytype) Span(@TypeOf(ptr)) {
                           ^
C:\zig\lib\zig\std\mem.zig:550:26: note: referenced here
            return @Type(std.builtin.TypeInfo{ .Pointer = new_ptr_info });
                         ^
C:\zig\lib\zig\std\mem.zig:764:21: note: referenced here
    return allocator.dupe(T, m);
                    ^
C:\zig\lib\zig\std\mem\Allocator.zig:11:13: note: referenced here
const mem = std.mem;
            ^
C:\zig\lib\zig\std\mem\Allocator.zig:463:5: note: referenced here
    mem.copy(T, new_buf, m);
    ^
.\testsuite.zig:6:18: note: referenced here
    defer network.deinit();
                 ^
.\testsuite.zig:12:18: note: referenced here
        std.debug.print("{}\n", .{endpt});
                 ^
.\testsuite.zig:9:24: note: referenced here
    defer endpoint_list.deinit();
                       ^
.\network.zig:1161:58: error: expected type 'c_int', found 'u32'
        while (true) if (ws2_32.connect(sock, sock_addr, len) != 0) {
                                                         ^
.\network.zig:1161:58: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
        while (true) if (ws2_32.connect(sock, sock_addr, len) != 0) {

receiveFrom() error.WouldBlock

Hi, part way through first Zig project. I have some hardware that requires a broadcast. This is the code to send the request. I know the hardware is working as I have other implementations to test with.
`
const port: u32 = 1024;
try net.init();
defer net.deinit();

// Broadcast addr
const bcAddr = net.EndPoint{
    .address = net.Address{ .ipv4 = net.Address.IPv4.broadcast },
    .port = port,
};
// Bind addr
const bindAddr = net.EndPoint{
    .address = net.Address{ .ipv4 = net.Address.IPv4.any },
    .port = 10000,
};
// Create socket to broadcast to end point
var sock = try net.Socket.create(.ipv4, .udp);
try sock.setBroadcast(true);
try sock.setReadTimeout(1000000);
try sock.bind(bindAddr);
// Format discover packet
var data = std.mem.zeroes([MAX_MSG]u8);
data[0] = 0xEF;
data[1] = 0xFE;
data[2] = 0x02;
std.debug.print("Data: {any}\n", .{data});
// Send discover packet
var e = try sock.sendTo(bcAddr, data[0..MAX_MSG]);
std.debug.print("Send to resp: {}\n", .{e});
// Read response
try read_response(sock);

`
This works and says I sent 63 bytes. This is the read response code.

`
fn read_response(sock: net.Socket) !void {
var response: net.Socket.ReceiveFrom = undefined;
var count: u32 = 5;
var data = std.mem.zeroes([MAX_MSG]u8);
std.time.sleep(1000000000);
while (true) {
response = sock.receiveFrom(&data) catch |err| {
std.debug.print("Discover fail, retrying: {}\n", .{err});
const stderr = std.io.getStdErr();
_ = stderr;
count -= 1;
if (count <= 0) {
break;
} else {
std.time.sleep(1000000000);
continue;
}
};
}
std.debug.print("Discover resp: {any}, {any}\n", .{ response.numberOfBytes, response.sender });
std.debug.print("Discover data: {any}\n", .{data});
}

`
This just returns WouldBlock every attempt. The sleeps and retries make no difference. I read something about the zig event loop in another post so just tried 'async' which told me it wasn't implemented so I ran the whole discover on a thread but still made no difference, Not sure where to go from here.
Bob

macos : listen udp error

code is here https://github.com/eyun-tv/zig

when listen udp, failed
image

same code , when listen tcp, success
image

error code

+ zig build
+ exec ./zig-out/bin/zig
unexpected errno: 102
/usr/local/Cellar/zig/0.9.0/lib/zig/std/debug.zig:458:19: 0x10725d559 in std.debug.writeCurrentStackTrace (zig)
    while (it.next()) |return_address| {
                  ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/debug.zig:115:31: 0x10725ab26 in std.debug.dumpCurrentStackTrace (zig)
        writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| {
                              ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/os.zig:4985:40: 0x10725b1dd in std.os.unexpectedErrno (zig)
        std.debug.dumpCurrentStackTrace(null);
                                       ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/os.zig:3206:49: 0x10725be11 in std.os.listen (zig)
            else => |err| return unexpectedErrno(err),
                                                ^
/Users/z/rmw/zig/.zigmod/deps/git/[email protected]:MasterQ32/zig-network/network.zig:357:22: 0x107259ff5 in .network.Socket.listen (zig)
        try listen_fn(self.internal, 0);
                     ^
/Users/z/rmw/zig/src/main.zig:16:18: 0x107259c28 in main (zig)
    try sk.listen();
                 ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/start.zig:553:37: 0x10725e0a8 in std.start.callMain (zig)
            const result = root.main() catch |err| {
                                    ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/start.zig:495:12: 0x10725a507 in std.start.callMainWithArgs (zig)
    return @call(.{ .modifier = .always_inline }, callMain, .{});
           ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/start.zig:460:12: 0x10725a445 in std.start.main (zig)
    return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
           ^
???:?:?: 0x108dda4fd in ??? (???)
???:?:?: 0x0 in ??? (???)
error: Unexpected
/usr/local/Cellar/zig/0.9.0/lib/zig/std/os.zig:4987:5: 0x10725b1ec in std.os.unexpectedErrno (zig)
    return error.Unexpected;
    ^
/usr/local/Cellar/zig/0.9.0/lib/zig/std/os.zig:3206:27: 0x10725be1e in std.os.listen (zig)
            else => |err| return unexpectedErrno(err),
                          ^
/Users/z/rmw/zig/.zigmod/deps/git/[email protected]:MasterQ32/zig-network/network.zig:357:9: 0x10725a014 in .network.Socket.listen (zig)
        try listen_fn(self.internal, 0);
        ^
/Users/z/rmw/zig/src/main.zig:16:5: 0x107259c64 in main (zig)
    try sk.listen();

No method to shutdown socket

I have a race condition between two threads, one trying to close a socket and the other reading from it as shown in the code below, but the thread calling recieve needs to be able to yield an error if the socket is closed.

fn recieveLoop(context: *Context) !void {
    while (true) {
        var buffer: [@sizeOf(Input)]u8 = undefined;

        if ((try context.sock.receive(&buffer)) == buffer.len) {
            const held = context.mutex.acquire();
            defer held.release();

            context.input = Input.deserialize(&buffer);
        } else {
            return;
        }
    }
}

If I call close in the other thread then it hits the .WSAENOTSOCK => unreachable, case in recvfrom. Can a method be exposed to cleanly shutdown a socket so there is no race condition?

Windows specific crash bug where WSAECONNRESET can occur randomly with UDP sockets client/host

What's the issue?

I have both a server and client using UDP, both sending and receiving from each other.

When calling receive on a UDP socket where there's a random chance that it'll fail with an WSAECONNRESET error (currently not catchable as it's unreachable code).

A fix I know currently works:

  • Updating recvfrom error handling to catch WSAECONNRESET like so:
.WSAECONNRESET => error.ConnectionResetByPeer,
  • Catching that kind of error when calling sock.receive and ignoring it.

How various libraries avoid this issue:

Various other sources talking about this issue:

Provide a branch based on the latest Zig release

Hi @MasterQ32 !

When Zig 0.7 will be released, I plan to use zig-network in combination with h11 to try to build an HTTP client library.
Zig is young and move fast so I understand the value of compiling zig-network with Zig master branch.

As we get closer to Zig 1.0, would it be possible to provide a branch for zig-network that compile with the latest release of Zig ?

Maybe something like:

  • The master branch compile with the latest Zig release (0.7, 0.8, etc...), in order to provide stability to the users.
  • A develop branch compile with Zig master branch, in order to provide the latest language benefits but also feedbacks for the Zig compiler.

What do you think ?

Have a nice day 🌴

reallocAdvanced call uses old signature

The signature for reallocAdvanaced was changed here ziglang/zig@ceb0a63#diff-29d26e272ecc9cdcc97fd8c9ed45792cbbddd826ef399e9528490389f12d36e2L362

It is used here

fd_set.* = @ptrCast(*align(8) FdSet, (try allocator.reallocAdvanced(fd_set.*.memSlice(), 8, new_mem_size, .exact)).ptr);
and needs to be updated.

New to Zig so not sure how to do it myself yet :)

// This works I think?

fd_set.* = @ptrCast(*align(8) FdSet, (try allocator.reallocAdvanced(@alignCast(8, fd_set.*.memSlice()), new_mem_size, @returnAddress())).ptr);

The road to zig std

There are plans to upstream this library into the zig std library. This issue is here to create a concrete plan and track progress.

Some considerations:

  • Define a clear public API/error surface
    • Collapse unix/windows/… errors into well-defined zig-network errors
  • API must be event loop compatible
  • Changes in zig std to OS APIs (ziglang/zig#6600)
  • Support unix sockets? If yes, how to solve it on windows
  • Should we keep the address/port separation? OS's don't do it, but I find it unintuitive
    • How does this play with unix sockets? Address is a file name, not an IP + Port
    • The separation is required to implement happy eyeballs nicely
  • Optimize the polling API (make it allocation-free if possible)

Roadmap:

  • Clear up remaining questions
  • Clean up the API and provide abtractions
  • Create dedicated fork and start integration
  • Create PR and hope for the best

ping @alexnask @Luukdegram @kristoff-it

error.WouldBlock thrown

When running the async example, an error.WouldBlock is thrown by the accept() function.
It seems that this either means some issue with the event loop, or that accept also has a suspend in it?
I tried putting the accept() in the Client.handle() function and then it works, but with the current code this means a continuous stream of clients is created since it doesn't block.

How would one keep the accept blocking, but still make the rest of the code async?

zig-network git:(master) ./zig-cache/bin/async 
listening at 0.0.0.0:2501
Waiting for connection
error: WouldBlock
/usr/local/lib/zig/std/os.zig:3041:27: 0x256ade in std.os.accept (async)
                EAGAIN => return error.WouldBlock,
                          ^
/home/marijnfs/software/zig-network/network.zig:368:20: 0x2518bd in .network.Socket.accept (async)
        const fd = try accept4_fn(self.internal, addr_ptr, &addr_size, flags);
                   ^
/home/marijnfs/software/zig-network/examples/async.zig:26:21: 0x250db8 in main (async)
            .conn = try server.accept(),
                    ^

SO_BROADCAST setsockopt for UDP socket

Hi,

Any possibility of adding a setBroadcast function to enable/disable the SO_BROADCAST socket option (required for UDP sockets to send broadcast messages) ? The code looks something like this:

    /// Set SO_BROADCAST sockopt
    pub fn setBroadcast(self: *Self, enable: bool) !void {
        const val: u32 = if (enable)  1 else 0;
        if (is_windows) {
            try windows.setsockopt(self.internal, std.os.SOL.SOCKET, std.os.SO.BROADCAST, std.mem.asBytes(&val));
        } else {
            try std.os.setsockopt(self.internal, std.os.SOL.SOCKET, std.os.SO.BROADCAST, std.mem.asBytes(&val));
        }
    }

(I can do a pull request if you like but it seemed like such a small thing)

Darwin: connection-mode socket was connected already

Uses zig-macos-x86_64-0.11.0-dev.3950+a75531073 same source 7b5f76e (standalone project test)

edit: repo fork (CI test): https://github.com/kassane/zig-network/actions/runs/5568702251

Build ok. however when running:

thread 7538 panic: reached unreachable code
/Users/runner/hostedtoolcache/zig/master/x64/lib/std/os.zig:5985:24: 0x10d5fe61b in sendto (ntp-zig)
            .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified
                       ^
/Users/runner/.cache/zig/p/122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e/network.zig:520:46: 0x10d5ee39f in sendTo (ntp-zig)
            .ipv4 => |sockaddr| try sendto_fn(self.internal, data, flags, @ptrCast(&sockaddr), @sizeOf(@TypeOf(sockaddr))),
                                             ^
/Users/runner/.cache/zig/p/122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e/network.zig:469:35: 0x10d5d5859 in send (ntp-zig)
            return try self.sendTo(ep, data);
                                  ^
/Users/runner/hostedtoolcache/zig/master/x64/lib/std/io/writer.zig:17:27: 0x10d5ac956 in write (ntp-zig)
            return writeFn(self.context, bytes);
                          ^
/Users/runner/hostedtoolcache/zig/master/x64/lib/std/io/writer.zig:23:40: 0x10d5a8774 in writeAll (ntp-zig)
                index += try self.write(bytes[index..]);
                                       ^
/Users/runner/work/ntp-zig/ntp-zig/src/main.zig:14:31: 0x10d5a7f01 in main (ntp-zig)
    try sock.writer().writeAll(&request);
                              ^
/Users/runner/hostedtoolcache/zig/master/x64/lib/std/start.zig:608:37: 0x10d5a8fb2 in main (ntp-zig)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x115a8652d in ??? (???)
???:?:?: 0x0 in ??? (???)
run ntp-zig: error: the following command terminated unexpectedly:
/Users/runner/work/ntp-zig/ntp-zig/zig-cache/o/703913aea06a991a2c9b3f3ffe120bda/ntp-zig 
Build Summary: 1/3 steps succeeded; 1 failed (disable with --summary none)
run transitive failure
+- run ntp-zig failure
error: the following build command failed with exit code 1:
/Users/runner/work/ntp-zig/ntp-zig/zig-cache/o/b553499fe5c39aecb53f8ff1ef25817f/build /Users/runner/hostedtoolcache/zig/master/x64/zig /Users/runner/work/ntp-zig/ntp-zig /Users/runner/work/ntp-zig/ntp-zig/zig-cache /Users/runner/.cache/zig run -freference-trace -freference-trace

SocketSet.deinit frees memory with wrong alignment on Windows

On windows, the following step in deinit is problematic due to an alignment mismatch (1 instead of 8)

self.read_fd_set.deinit(self.allocator)

The cause is due to memSlice in allocator.free(self.memSlice()); not setting the alignment when casting pointer type.

List IP addresses

Would it be possible to add a function to get a list of local IP addresses?

Windows error: cast increases pointer alignment

I am running into a "cast increases pointer alignment" error on windows that I am unsure how to fix.

A minimal example:

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

pub fn main() !void {
    try network.init();
    defer network.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var socket = try network.Socket.create(.ipv4, .udp);
    defer socket.close();
    try socket.bind(.{
        .address = .{ .ipv4 = network.Address.IPv4.any },
        .port = 2501,
    });

    var socketset = try network.SocketSet.init(allocator);
    defer socketset.deinit();
    var event = network.SocketEvent{ .read = true, .write = false };
    try socketset.add(socket, event);

    const wait_msg = network.waitForSocketEvent(&socketset, 0) catch 0;
    _ = wait_msg;
}
C:\Users\UserName\AppData\Local\zig\p\122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e\network.zig:817:28: error: cast increases pointer alignment
                fd_set.* = @ptrCast((try allocator.reallocAdvanced(ptr, new_mem_size, @returnAddress())).ptr);
                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\UserName\AppData\Local\zig\p\122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e\network.zig:817:105: note: '[*]u8' has alignment '1'  
                fd_set.* = @ptrCast((try allocator.reallocAdvanced(ptr, new_mem_size, @returnAddress())).ptr);
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
C:\Users\UserName\AppData\Local\zig\p\122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e\network.zig:817:28: note: '*align(8) network.WindowsOSLogic.FdSet' has alignment '8'
C:\Users\UserName\AppData\Local\zig\p\122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e\network.zig:817:28: note: use @alignCast to assert pointer alignment
referenced by:
    getFdSet: C:\Users\UserName\AppData\Local\zig\p\122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e\network.zig:924:26
    waitForSocketEvent: C:\Users\UserName\AppData\Local\zig\p\122090e7cb4459c2224399a45c56f47462733b919aa547c96b8c14ee705bfa22976e\network.zig:973:46
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Using the latest version of zig-network (7b5f76e) with zig 0.11.0-dev.4315+f5239677e on Windows 10 Pro, 64 bit. #62 might be related.

Incorrect NOSIGPIPE mask on Darwin?

The current implementation of connect() appears to use a fixed constant (0x800) for all BSD family targets, but the stdlib has this constant defined for targets that support it in std.os.SO.NOSIGPIPE.

In particular, it looks like the constant differs on Darwin (0x1022 vs 0x800), so this might lead to problems.

const SO_NOSIGPIPE = 0x00000800;

Seems like you could change the constant to just use std.os.SO.NOSIGPIPE here?

How to use zig-network?

I'm going to use zig-network for prototyping web application. But I'm unfamiliar how zig projects depend on libraries and the README.md file doesn't talk about it.

@MasterQ32 could you show an example to add a dependency or I must copy the source and link it manually?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.