mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-08 03:29:48 -04:00
Use the posix socket API wrapper of the zig standard library instead of messing with C code.
This commit is contained in:
parent
d9b81b91f8
commit
43da550385
@ -39,7 +39,7 @@ pub fn build(b: *std.build.Builder) !void {
|
|||||||
std.log.err("Unsupported target: {}\n", .{ target.getOsTag() });
|
std.log.err("Unsupported target: {}\n", .{ target.getOsTag() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exe.addCSourceFiles(&[_][]const u8{"lib/glad.c", "lib/stb_image.c", "lib/cross_platform_udp_socket.c"}, &[_][]const u8{"-g"});
|
exe.addCSourceFiles(&[_][]const u8{"lib/glad.c", "lib/stb_image.c"}, &[_][]const u8{"-g"});
|
||||||
exe.addPackage(freetype.pkg);
|
exe.addPackage(freetype.pkg);
|
||||||
exe.addPackage(freetype.harfbuzz_pkg);
|
exe.addPackage(freetype.harfbuzz_pkg);
|
||||||
freetype.link(b, exe, .{ .harfbuzz = .{} });
|
freetype.link(b, exe, .{ .harfbuzz = .{} });
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void startup();
|
|
||||||
|
|
||||||
int init(unsigned short localPort);
|
|
||||||
int deinit(int socketID);
|
|
||||||
int sendTo(int socketID, const char* data, uintptr_t size, uint32_t ip, uint16_t port);
|
|
||||||
intptr_t receiveFrom(int socketID, char* buffer, uintptr_t size, int timeout, uint32_t* resultIP, uint16_t* resultPort);
|
|
||||||
uint32_t resolveIP(const char* ip);
|
|
||||||
|
|
||||||
int getError();
|
|
@ -1,110 +0,0 @@
|
|||||||
#ifdef _WIN32
|
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0600
|
|
||||||
#endif
|
|
||||||
#include <winsock2.h>
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#else
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <cross_platform_udp_socket.h>
|
|
||||||
|
|
||||||
int checkError(int in) {
|
|
||||||
// TODO: Print the error here.
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startup() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
WSADATA d;
|
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &d)) {
|
|
||||||
fprintf(stderr, "Failed to initialize.\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int init(unsigned short localPort) {
|
|
||||||
int socketID = checkError(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
|
||||||
if(socketID == -1) return -1;
|
|
||||||
struct sockaddr_in bindingAddr;
|
|
||||||
bindingAddr.sin_family = AF_INET;
|
|
||||||
bindingAddr.sin_port = htons(localPort);
|
|
||||||
bindingAddr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
memset(&bindingAddr.sin_zero, 0, 8);
|
|
||||||
if(checkError(bind(socketID, (const struct sockaddr*)&bindingAddr, sizeof(bindingAddr))) == -1) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
closesocket(socketID);
|
|
||||||
#else
|
|
||||||
close(socketID);
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
return socketID;
|
|
||||||
}
|
|
||||||
|
|
||||||
int deinit(int socketID) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return checkError(closesocket(socketID));
|
|
||||||
#else
|
|
||||||
return checkError(close(socketID));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int sendTo(int socketID, const char* data, uintptr_t size, uint32_t ip, uint16_t port) {
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
addr.sin_addr.s_addr = ip;
|
|
||||||
memset(&addr.sin_zero, 0, 8);
|
|
||||||
return checkError(sendto(socketID, data, size, 0, (const struct sockaddr*)&addr, sizeof(addr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t receiveFrom(int socketID, char* buffer, uintptr_t size, int timeout, uint32_t* resultIP, uint16_t* resultPort) {
|
|
||||||
struct pollfd pfd = {.fd = socketID, .events = POLLIN};
|
|
||||||
#ifdef _WIN32
|
|
||||||
intptr_t result = checkError(WSAPoll(&pfd, 1, timeout));
|
|
||||||
#else
|
|
||||||
intptr_t result = checkError(poll(&pfd, 1, timeout));
|
|
||||||
#endif
|
|
||||||
if(result <= 0) return result;
|
|
||||||
struct sockaddr_in address;
|
|
||||||
uint32_t addrLen = sizeof(address);
|
|
||||||
result = checkError(recvfrom(socketID, buffer, size, 0, (struct sockaddr *)&address, &addrLen));
|
|
||||||
|
|
||||||
*resultIP = address.sin_addr.s_addr;
|
|
||||||
*resultPort = ntohs(address.sin_port);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
uint32_t resolveIP(const char* address) {
|
|
||||||
struct addrinfo hints;
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = AF_INET;
|
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
|
||||||
hints.ai_protocol = IPPROTO_UDP;
|
|
||||||
struct addrinfo* res;
|
|
||||||
int result = getaddrinfo(address, NULL, &hints, &res);
|
|
||||||
if(result != 0) {
|
|
||||||
errno = result;
|
|
||||||
return 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ip = ((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
|
|
||||||
freeaddrinfo(res);
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getError() {
|
|
||||||
return errno;
|
|
||||||
}
|
|
@ -1,3 +1,4 @@
|
|||||||
|
const builtin = @import("builtin");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
@ -22,46 +23,65 @@ const Vec3f = vec.Vec3f;
|
|||||||
//TODO: Might want to use SSL or something similar to encode the message
|
//TODO: Might want to use SSL or something similar to encode the message
|
||||||
|
|
||||||
const Socket = struct {
|
const Socket = struct {
|
||||||
const c = @cImport({@cInclude("cross_platform_udp_socket.h");});
|
const os = std.os;
|
||||||
socketID: u31,
|
socketID: os.socket_t,
|
||||||
|
|
||||||
fn checkError(comptime msg: []const u8, comptime T: type, result: T) !std.meta.Int(.unsigned, @bitSizeOf(T) - 1) {
|
fn startup() void {
|
||||||
if(result == -1) {
|
if(builtin.os.tag == .windows) {
|
||||||
std.log.warn(msg, .{c.getError()});
|
_ = os.windows.WSAStartup(2, 2) catch |err| { // TODO: Return the error (this triggers a false depency loop error right now).
|
||||||
return error.SocketError;
|
std.log.err("Error trying to startup WSA: {}", .{@errorName(err)});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return @intCast(std.meta.Int(.unsigned, @bitSizeOf(T) - 1), result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(localPort: u16) !Socket {
|
fn init(localPort: u16) !Socket {
|
||||||
return Socket{.socketID = try checkError("Socket creation failed with error: {}", c_int, c.init(localPort))};
|
var self = Socket {
|
||||||
|
.socketID = try os.socket(os.AF.INET, os.SOCK.DGRAM, os.IPPROTO.UDP),
|
||||||
|
};
|
||||||
|
errdefer self.deinit();
|
||||||
|
const bindingAddr = os.sockaddr.in {
|
||||||
|
.port = @byteSwap(localPort),
|
||||||
|
.addr = 0,
|
||||||
|
};
|
||||||
|
try os.bind(self.socketID, @ptrCast(*const os.sockaddr, &bindingAddr), @sizeOf(os.sockaddr.in));
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: Socket) void {
|
fn deinit(self: Socket) void {
|
||||||
_ = checkError("Error while closing socket: {}", c_int, c.deinit(self.socketID)) catch 0;
|
os.closeSocket(self.socketID);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(self: Socket, data: []const u8, destination: Address) !void {
|
fn send(self: Socket, data: []const u8, destination: Address) !void {
|
||||||
_ = try checkError("Error sending data: {}", isize, c.sendTo(self.socketID, data.ptr, data.len, destination.ip, destination.port));
|
const addr = os.sockaddr.in {
|
||||||
|
.port = @byteSwap(destination.port),
|
||||||
|
.addr = destination.ip,
|
||||||
|
};
|
||||||
|
std.debug.assert(data.len == try os.sendto(self.socketID, data, 0, @ptrCast(*const os.sockaddr, &addr), @sizeOf(os.sockaddr.in)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(self: Socket, buffer: []u8, timeout: c_int, resultAddress: *Address) ![]u8 {
|
fn receive(self: Socket, buffer: []u8, timeout: i32, resultAddress: *Address) ![]u8 {
|
||||||
var length = try checkError("Receive failed: {}", isize, c.receiveFrom(self.socketID, buffer.ptr, buffer.len, timeout, &resultAddress.ip, &resultAddress.port));
|
var pfd = [1]os.pollfd {
|
||||||
|
.{.fd = self.socketID, .events = os.POLL.IN, .revents = undefined},
|
||||||
|
};
|
||||||
|
var length = try os.poll(&pfd, timeout);
|
||||||
if(length == 0) return error.Timeout;
|
if(length == 0) return error.Timeout;
|
||||||
|
var addr: os.sockaddr.in = undefined;
|
||||||
|
var addrLen: os.socklen_t = @sizeOf(os.sockaddr.in);
|
||||||
|
length = try os.recvfrom(self.socketID, buffer, 0, @ptrCast(*os.sockaddr, &addr), &addrLen);
|
||||||
|
resultAddress.ip = addr.addr;
|
||||||
|
resultAddress.port = @byteSwap(addr.port);
|
||||||
return buffer[0..length];
|
return buffer[0..length];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveIP(ip: [:0]const u8) u32 {
|
fn resolveIP(addr: []const u8) !u32 {
|
||||||
const result: u32 = c.resolveIP(ip.ptr);
|
const list = try std.net.getAddressList(main.threadAllocator, addr, settings.defaultPort);
|
||||||
if(result == 0xffffffff) {
|
defer list.deinit();
|
||||||
std.log.warn("Could not resolve address: {s} error: {}", .{ip, c.getError()});
|
return list.addrs[0].in.sa.addr;
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init() void {
|
pub fn init() void {
|
||||||
Socket.c.startup();
|
Socket.startup();
|
||||||
inline for(@typeInfo(@TypeOf(Protocols)).Struct.fields) |field| {
|
inline for(@typeInfo(@TypeOf(Protocols)).Struct.fields) |field| {
|
||||||
if(field.type == type) {
|
if(field.type == type) {
|
||||||
const id = @field(Protocols, field.name).id;
|
const id = @field(Protocols, field.name).id;
|
||||||
@ -239,9 +259,14 @@ const STUN = struct {
|
|||||||
random.fill(data[8..]); // Fill the transaction ID.
|
random.fill(data[8..]); // Fill the transaction ID.
|
||||||
|
|
||||||
var splitter = std.mem.split(u8, server, ":");
|
var splitter = std.mem.split(u8, server, ":");
|
||||||
var nullTerminatedIP = main.threadAllocator.dupeZ(u8, splitter.first()) catch continue;
|
const ip = splitter.first();
|
||||||
defer main.threadAllocator.free(nullTerminatedIP);
|
var serverAddress = Address {
|
||||||
var serverAddress = Address{.ip=Socket.resolveIP(nullTerminatedIP), .port=std.fmt.parseUnsigned(u16, splitter.rest(), 10) catch 3478};
|
.ip=Socket.resolveIP(ip) catch |err| {
|
||||||
|
std.log.err("Cannot resolve stun server address: {s}, error: {s}", .{ip, @errorName(err)});
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
.port=std.fmt.parseUnsigned(u16, splitter.rest(), 10) catch 3478
|
||||||
|
};
|
||||||
if(connection.sendRequest(connection.allocator, &data, serverAddress, 500*1000000) catch |err| {
|
if(connection.sendRequest(connection.allocator, &data, serverAddress, 500*1000000) catch |err| {
|
||||||
std.log.warn("Encountered error: {s} while connecting to STUN server: {s}", .{@errorName(err), server});
|
std.log.warn("Encountered error: {s} while connecting to STUN server: {s}", .{@errorName(err), server});
|
||||||
continue;
|
continue;
|
||||||
@ -270,7 +295,7 @@ const STUN = struct {
|
|||||||
std.log.warn("Couldn't reach STUN server: {s}", .{server});
|
std.log.warn("Couldn't reach STUN server: {s}", .{server});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Address{.ip=Socket.resolveIP("127.0.0.1"), .port=settings.defaultPort}; // TODO: Return ip address in LAN.
|
return Address{.ip=Socket.resolveIP("127.0.0.1") catch unreachable, .port=settings.defaultPort}; // TODO: Return ip address in LAN.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn findIPPort(_data: []const u8) !Address {
|
fn findIPPort(_data: []const u8) !Address {
|
||||||
@ -330,7 +355,7 @@ pub const ConnectionManager = struct {
|
|||||||
thread: std.Thread = undefined,
|
thread: std.Thread = undefined,
|
||||||
threadId: std.Thread.Id = undefined,
|
threadId: std.Thread.Id = undefined,
|
||||||
externalAddress: Address = undefined,
|
externalAddress: Address = undefined,
|
||||||
online: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true),
|
online: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false),
|
||||||
running: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true),
|
running: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true),
|
||||||
|
|
||||||
connections: std.ArrayList(*Connection) = undefined,
|
connections: std.ArrayList(*Connection) = undefined,
|
||||||
@ -1248,9 +1273,8 @@ pub const Connection = struct {
|
|||||||
std.ArrayList(u32).init(result.allocator),
|
std.ArrayList(u32).init(result.allocator),
|
||||||
};
|
};
|
||||||
var splitter = std.mem.split(u8, ipPort, ":");
|
var splitter = std.mem.split(u8, ipPort, ":");
|
||||||
var nullTerminatedIP = try main.threadAllocator.dupeZ(u8, splitter.first());
|
const ip = splitter.first();
|
||||||
defer main.threadAllocator.free(nullTerminatedIP);
|
result.remoteAddress.ip = try Socket.resolveIP(ip);
|
||||||
result.remoteAddress.ip = Socket.resolveIP(nullTerminatedIP);
|
|
||||||
var port = splitter.rest();
|
var port = splitter.rest();
|
||||||
if(port.len != 0 and port[0] == '?') {
|
if(port.len != 0 and port[0] == '?') {
|
||||||
result.remoteAddress.isSymmetricNAT = true;
|
result.remoteAddress.isSymmetricNAT = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user