mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -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() });
|
||||
}
|
||||
}
|
||||
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.harfbuzz_pkg);
|
||||
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 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
|
||||
|
||||
const Socket = struct {
|
||||
const c = @cImport({@cInclude("cross_platform_udp_socket.h");});
|
||||
socketID: u31,
|
||||
const os = std.os;
|
||||
socketID: os.socket_t,
|
||||
|
||||
fn checkError(comptime msg: []const u8, comptime T: type, result: T) !std.meta.Int(.unsigned, @bitSizeOf(T) - 1) {
|
||||
if(result == -1) {
|
||||
std.log.warn(msg, .{c.getError()});
|
||||
return error.SocketError;
|
||||
fn startup() void {
|
||||
if(builtin.os.tag == .windows) {
|
||||
_ = os.windows.WSAStartup(2, 2) catch |err| { // TODO: Return the error (this triggers a false depency loop error right now).
|
||||
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 {
|
||||
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 {
|
||||
_ = 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 {
|
||||
_ = 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 {
|
||||
var length = try checkError("Receive failed: {}", isize, c.receiveFrom(self.socketID, buffer.ptr, buffer.len, timeout, &resultAddress.ip, &resultAddress.port));
|
||||
fn receive(self: Socket, buffer: []u8, timeout: i32, resultAddress: *Address) ![]u8 {
|
||||
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;
|
||||
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];
|
||||
}
|
||||
|
||||
fn resolveIP(ip: [:0]const u8) u32 {
|
||||
const result: u32 = c.resolveIP(ip.ptr);
|
||||
if(result == 0xffffffff) {
|
||||
std.log.warn("Could not resolve address: {s} error: {}", .{ip, c.getError()});
|
||||
}
|
||||
return result;
|
||||
fn resolveIP(addr: []const u8) !u32 {
|
||||
const list = try std.net.getAddressList(main.threadAllocator, addr, settings.defaultPort);
|
||||
defer list.deinit();
|
||||
return list.addrs[0].in.sa.addr;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init() void {
|
||||
Socket.c.startup();
|
||||
Socket.startup();
|
||||
inline for(@typeInfo(@TypeOf(Protocols)).Struct.fields) |field| {
|
||||
if(field.type == type) {
|
||||
const id = @field(Protocols, field.name).id;
|
||||
@ -239,9 +259,14 @@ const STUN = struct {
|
||||
random.fill(data[8..]); // Fill the transaction ID.
|
||||
|
||||
var splitter = std.mem.split(u8, server, ":");
|
||||
var nullTerminatedIP = main.threadAllocator.dupeZ(u8, splitter.first()) catch continue;
|
||||
defer main.threadAllocator.free(nullTerminatedIP);
|
||||
var serverAddress = Address{.ip=Socket.resolveIP(nullTerminatedIP), .port=std.fmt.parseUnsigned(u16, splitter.rest(), 10) catch 3478};
|
||||
const ip = splitter.first();
|
||||
var serverAddress = Address {
|
||||
.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| {
|
||||
std.log.warn("Encountered error: {s} while connecting to STUN server: {s}", .{@errorName(err), server});
|
||||
continue;
|
||||
@ -270,7 +295,7 @@ const STUN = struct {
|
||||
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 {
|
||||
@ -330,7 +355,7 @@ pub const ConnectionManager = struct {
|
||||
thread: std.Thread = undefined,
|
||||
threadId: std.Thread.Id = 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),
|
||||
|
||||
connections: std.ArrayList(*Connection) = undefined,
|
||||
@ -1248,9 +1273,8 @@ pub const Connection = struct {
|
||||
std.ArrayList(u32).init(result.allocator),
|
||||
};
|
||||
var splitter = std.mem.split(u8, ipPort, ":");
|
||||
var nullTerminatedIP = try main.threadAllocator.dupeZ(u8, splitter.first());
|
||||
defer main.threadAllocator.free(nullTerminatedIP);
|
||||
result.remoteAddress.ip = Socket.resolveIP(nullTerminatedIP);
|
||||
const ip = splitter.first();
|
||||
result.remoteAddress.ip = try Socket.resolveIP(ip);
|
||||
var port = splitter.rest();
|
||||
if(port.len != 0 and port[0] == '?') {
|
||||
result.remoteAddress.isSymmetricNAT = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user