mirror of
https://github.com/ziglang/zig.git
synced 2025-12-07 14:53:08 +00:00
Only allow SOCK_STREAM (std.x.net.tcp.Client) sockets to have wrappers for std.io.Reader and std.io.Writer provided, instead of Socket's in general.
118 lines
4.7 KiB
Zig
118 lines
4.7 KiB
Zig
// SPDX-License-Identifier: MIT
|
|
// Copyright (c) 2015-2021 Zig Contributors
|
|
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
|
|
// The MIT license requires this copyright notice to be included in all copies
|
|
// and substantial portions of the software.
|
|
|
|
const std = @import("../../std.zig");
|
|
const net = @import("net.zig");
|
|
|
|
const os = std.os;
|
|
const fmt = std.fmt;
|
|
const mem = std.mem;
|
|
const time = std.time;
|
|
const builtin = std.builtin;
|
|
|
|
/// Import in a `Socket` abstraction depending on the platform we are compiling against.
|
|
pub usingnamespace switch (builtin.os.tag) {
|
|
.windows => @import("socket_windows.zig"),
|
|
else => @import("socket_posix.zig"),
|
|
};
|
|
|
|
/// A common subset of shared structs across cross-platform abstractions over socket syscalls.
|
|
pub fn Mixin(comptime Self: type) type {
|
|
return struct {
|
|
/// A socket-address pair.
|
|
pub const Connection = struct {
|
|
socket: Self,
|
|
address: Self.Address,
|
|
|
|
/// Enclose a socket and address into a socket-address pair.
|
|
pub fn from(socket: Self, address: Self.Address) Self.Connection {
|
|
return .{ .socket = socket, .address = address };
|
|
}
|
|
};
|
|
|
|
/// A generic socket address abstraction. It is safe to directly access and modify
|
|
/// the fields of a `Self.Address`.
|
|
pub const Address = union(enum) {
|
|
ipv4: net.IPv4.Address,
|
|
ipv6: net.IPv6.Address,
|
|
|
|
/// Instantiate a new address with a IPv4 host and port.
|
|
pub fn initIPv4(host: net.IPv4, port: u16) Self.Address {
|
|
return .{ .ipv4 = .{ .host = host, .port = port } };
|
|
}
|
|
|
|
/// Instantiate a new address with a IPv6 host and port.
|
|
pub fn initIPv6(host: net.IPv6, port: u16) Self.Address {
|
|
return .{ .ipv6 = .{ .host = host, .port = port } };
|
|
}
|
|
|
|
/// Parses a `sockaddr` into a generic socket address.
|
|
pub fn fromNative(address: *align(4) const os.sockaddr) Self.Address {
|
|
switch (address.family) {
|
|
os.AF_INET => {
|
|
const info = @ptrCast(*const os.sockaddr_in, address);
|
|
const host = net.IPv4{ .octets = @bitCast([4]u8, info.addr) };
|
|
const port = mem.bigToNative(u16, info.port);
|
|
return Self.Address.initIPv4(host, port);
|
|
},
|
|
os.AF_INET6 => {
|
|
const info = @ptrCast(*const os.sockaddr_in6, address);
|
|
const host = net.IPv6{ .octets = info.addr, .scope_id = info.scope_id };
|
|
const port = mem.bigToNative(u16, info.port);
|
|
return Self.Address.initIPv6(host, port);
|
|
},
|
|
else => unreachable,
|
|
}
|
|
}
|
|
|
|
/// Encodes a generic socket address into an extern union that may be reliably
|
|
/// casted into a `sockaddr` which may be passed into socket syscalls.
|
|
pub fn toNative(self: Self.Address) extern union {
|
|
ipv4: os.sockaddr_in,
|
|
ipv6: os.sockaddr_in6,
|
|
} {
|
|
return switch (self) {
|
|
.ipv4 => |address| .{
|
|
.ipv4 = .{
|
|
.addr = @bitCast(u32, address.host.octets),
|
|
.port = mem.nativeToBig(u16, address.port),
|
|
},
|
|
},
|
|
.ipv6 => |address| .{
|
|
.ipv6 = .{
|
|
.addr = address.host.octets,
|
|
.port = mem.nativeToBig(u16, address.port),
|
|
.scope_id = address.host.scope_id,
|
|
.flowinfo = 0,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
/// Returns the number of bytes that make up the `sockaddr` equivalent to the address.
|
|
pub fn getNativeSize(self: Self.Address) u32 {
|
|
return switch (self) {
|
|
.ipv4 => @sizeOf(os.sockaddr_in),
|
|
.ipv6 => @sizeOf(os.sockaddr_in6),
|
|
};
|
|
}
|
|
|
|
/// Implements the `std.fmt.format` API.
|
|
pub fn format(
|
|
self: Self.Address,
|
|
comptime layout: []const u8,
|
|
opts: fmt.FormatOptions,
|
|
writer: anytype,
|
|
) !void {
|
|
switch (self) {
|
|
.ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
|
|
.ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
|
|
}
|
|
}
|
|
};
|
|
};
|
|
}
|