Move socket/stream operations and handling to SocketManager.zig.
This commit is contained in:
parent
82e3e8491c
commit
6c09d63c3d
99
src/SocketManager.zig
Normal file
99
src/SocketManager.zig
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const QVariant = @import("./qtshit/types/QVariant.zig").QVariant;
|
||||||
|
const read = @import("./qtshit/read.zig");
|
||||||
|
const write = @import("./qtshit/write.zig");
|
||||||
|
const range = @import("./qtshit/utils/RangeIter.zig").range;
|
||||||
|
const tls = @import("./deps/iguanaTLS/src/main.zig");
|
||||||
|
|
||||||
|
pub const SocketManager = struct {
|
||||||
|
allocator: *std.mem.Allocator,
|
||||||
|
baseStream: *std.net.Stream,
|
||||||
|
|
||||||
|
pub var tlsAllowed = !true;
|
||||||
|
pub var tlsConnected = !true;
|
||||||
|
|
||||||
|
pub const TLSStream = tls.Client(std.net.Stream.Reader, std.net.Stream.Writer, tls.ciphersuites.all, false);
|
||||||
|
pub var tlsClient: TLSStream = undefined;
|
||||||
|
|
||||||
|
pub fn deinit(s: *SocketManager) void {}
|
||||||
|
|
||||||
|
pub fn setTLSAllowed(s: *SocketManager, value: bool) void {
|
||||||
|
tlsAllowed = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initTLS(s: *SocketManager) !void {
|
||||||
|
if (!tlsConnected and tlsAllowed) {
|
||||||
|
var randBuf: [32]u8 = undefined;
|
||||||
|
try std.os.getrandom(&randBuf);
|
||||||
|
var rng = std.rand.DefaultCsprng.init(randBuf);
|
||||||
|
|
||||||
|
var rand = blk: {
|
||||||
|
var seed: [std.rand.DefaultCsprng.secret_seed_length]u8 = undefined;
|
||||||
|
try std.os.getrandom(&seed);
|
||||||
|
break :blk &std.rand.DefaultCsprng.init(seed).random;
|
||||||
|
};
|
||||||
|
|
||||||
|
tlsClient = try tls.client_connect(.{
|
||||||
|
.rand = rand,
|
||||||
|
.temp_allocator = s.allocator,
|
||||||
|
.reader = s.baseStream.reader(),
|
||||||
|
.writer = s.baseStream.writer(),
|
||||||
|
.cert_verifier = .none,
|
||||||
|
.ciphersuites = tls.ciphersuites.all,
|
||||||
|
}, "quassel.owo.monster");
|
||||||
|
tlsConnected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _writeFrame(s: *SocketManager, writer: anytype, data: std.ArrayList(u8)) !void {
|
||||||
|
try write.writeUInt(writer, @intCast(u32, data.items.len));
|
||||||
|
try writer.writeAll(data.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeFrame(s: *SocketManager, data: std.ArrayList(u8)) !void {
|
||||||
|
try s.initTLS();
|
||||||
|
if (tlsConnected) {
|
||||||
|
var writer = tlsClient.writer();
|
||||||
|
try s._writeFrame(writer, data);
|
||||||
|
} else {
|
||||||
|
var writer = s.baseStream.writer();
|
||||||
|
try s._writeFrame(writer, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _readFrame(s: *SocketManager, reader: anytype) !std.ArrayList(u8) {
|
||||||
|
var size = try read.readUInt(reader);
|
||||||
|
var data = std.ArrayList(u8).init(s.allocator);
|
||||||
|
var iter = range(u32, 0, size);
|
||||||
|
while (iter.next()) |i| {
|
||||||
|
const byte = try reader.readByte();
|
||||||
|
try data.append(byte);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readFrame(s: *SocketManager) !QVariant {
|
||||||
|
try s.initTLS();
|
||||||
|
var data: std.ArrayList(u8) = undefined;
|
||||||
|
defer data.deinit();
|
||||||
|
|
||||||
|
if (tlsConnected) {
|
||||||
|
var reader = tlsClient.reader();
|
||||||
|
data = try s._readFrame(reader);
|
||||||
|
} else {
|
||||||
|
var reader = s.baseStream.reader();
|
||||||
|
data = try s._readFrame(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fBS = std.io.fixedBufferStream(data.items);
|
||||||
|
return try read.readQVariant(fBS.reader(), s.allocator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn initSocketManager(allocator: *std.mem.Allocator, stream: *std.net.Stream) SocketManager {
|
||||||
|
return SocketManager{
|
||||||
|
.allocator = allocator,
|
||||||
|
.baseStream = stream,
|
||||||
|
};
|
||||||
|
}
|
121
src/client.zig
121
src/client.zig
|
@ -1,18 +1,17 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const BufferManager = @import("./BufferManager.zig");
|
const BufferManager = @import("./BufferManager.zig");
|
||||||
|
const SocketManager = @import("./SocketManager.zig");
|
||||||
|
|
||||||
|
|
||||||
const read = @import("./qtshit/read.zig");
|
const read = @import("./qtshit/read.zig");
|
||||||
const write = @import("./qtshit/write.zig");
|
const write = @import("./qtshit/write.zig");
|
||||||
const range = @import("./qtshit/utils/RangeIter.zig").range;
|
const QVariant = @import("./qtshit/types/QVariant.zig").QVariant;
|
||||||
const QVariantType = @import("./qtshit/types/QVariant.zig").QVariant;
|
|
||||||
const prettyPrintQVariant = @import("./qtshit/utils/prettyPrintQVariant.zig").prettyPrintQVariant;
|
const prettyPrintQVariant = @import("./qtshit/utils/prettyPrintQVariant.zig").prettyPrintQVariant;
|
||||||
const freeQVariant = @import("./qtshit/utils/free/freeQVariant.zig").freeQVariant;
|
const freeQVariant = @import("./qtshit/utils/free/freeQVariant.zig").freeQVariant;
|
||||||
const QVariantMapToQVariantList = @import("./qtshit/utils/QVariantMapToQVariantList.zig").QVariantMapToQVariantList;
|
const QVariantMapToQVariantList = @import("./qtshit/utils/QVariantMapToQVariantList.zig").QVariantMapToQVariantList;
|
||||||
const UserType = @import("./qtshit/types/UserType.zig");
|
const UserType = @import("./qtshit/types/UserType.zig");
|
||||||
|
|
||||||
const tls = @import("./deps/iguanaTLS/src/main.zig");
|
|
||||||
|
|
||||||
fn dumpDebug(name: []const u8, list: std.ArrayList(u8)) !void {
|
fn dumpDebug(name: []const u8, list: std.ArrayList(u8)) !void {
|
||||||
std.debug.print("dumpDebug list len {d}\n", .{list.items.len});
|
std.debug.print("dumpDebug list len {d}\n", .{list.items.len});
|
||||||
|
|
||||||
|
@ -28,105 +27,28 @@ fn dumpDebug(name: []const u8, list: std.ArrayList(u8)) !void {
|
||||||
pub const Client = struct {
|
pub const Client = struct {
|
||||||
allocator: *std.mem.Allocator,
|
allocator: *std.mem.Allocator,
|
||||||
stream: *std.net.Stream,
|
stream: *std.net.Stream,
|
||||||
|
socketManager: SocketManager.SocketManager,
|
||||||
bufferManager: BufferManager.BufferManager,
|
bufferManager: BufferManager.BufferManager,
|
||||||
|
|
||||||
pub var tlsAllowed = !true;
|
|
||||||
pub var tlsConnected = !true;
|
|
||||||
|
|
||||||
pub const TLSStream = tls.Client(std.net.Stream.Reader, std.net.Stream.Writer, tls.ciphersuites.all, false);
|
|
||||||
pub var tlsClient: TLSStream = undefined;
|
|
||||||
|
|
||||||
pub fn deinit(s: *Client) void {
|
pub fn deinit(s: *Client) void {
|
||||||
s.bufferManager.deinit();
|
s.bufferManager.deinit();
|
||||||
}
|
s.socketManager.deinit();
|
||||||
|
|
||||||
|
|
||||||
pub fn initTLS(s: *Client) !void {
|
|
||||||
if (!tlsConnected and tlsAllowed) {
|
|
||||||
var randBuf: [32]u8 = undefined;
|
|
||||||
try std.os.getrandom(&randBuf);
|
|
||||||
var rng = std.rand.DefaultCsprng.init(randBuf);
|
|
||||||
|
|
||||||
var rand = blk: {
|
|
||||||
var seed: [std.rand.DefaultCsprng.secret_seed_length]u8 = undefined;
|
|
||||||
try std.os.getrandom(&seed);
|
|
||||||
break :blk &std.rand.DefaultCsprng.init(seed).random;
|
|
||||||
};
|
|
||||||
|
|
||||||
tlsClient = try tls.client_connect(.{
|
|
||||||
.rand = rand,
|
|
||||||
.temp_allocator = s.allocator,
|
|
||||||
.reader = s.stream.reader(),
|
|
||||||
.writer = s.stream.writer(),
|
|
||||||
.cert_verifier = .none,
|
|
||||||
.ciphersuites = tls.ciphersuites.all,
|
|
||||||
}, "quassel.owo.monster");
|
|
||||||
tlsConnected = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _writeFrame(s: *Client, writer: anytype, data: std.ArrayList(u8)) !void {
|
|
||||||
try write.writeUInt(writer, @intCast(u32, data.items.len));
|
|
||||||
try writer.writeAll(data.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeFrame(s: *Client, data: std.ArrayList(u8)) !void {
|
|
||||||
try s.initTLS();
|
|
||||||
if (tlsConnected) {
|
|
||||||
var writer = tlsClient.writer();
|
|
||||||
try s._writeFrame(writer, data);
|
|
||||||
} else {
|
|
||||||
var writer = s.stream.writer();
|
|
||||||
try s._writeFrame(writer, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _readFrame(s: *Client, reader: anytype) !std.ArrayList(u8) {
|
|
||||||
var size = try read.readUInt(reader);
|
|
||||||
var data = std.ArrayList(u8).init(s.allocator);
|
|
||||||
var iter = range(u32, 0, size);
|
|
||||||
while (iter.next()) |i| {
|
|
||||||
const byte = try reader.readByte();
|
|
||||||
try data.append(byte);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn readFrame(s: *Client) !QVariantType {
|
|
||||||
try s.initTLS();
|
|
||||||
var data: std.ArrayList(u8) = undefined;
|
|
||||||
defer data.deinit();
|
|
||||||
|
|
||||||
if (tlsConnected) {
|
|
||||||
var reader = tlsClient.reader();
|
|
||||||
data = try s._readFrame(reader);
|
|
||||||
} else {
|
|
||||||
var reader = s.stream.reader();
|
|
||||||
data = try s._readFrame(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
var fBS = std.io.fixedBufferStream(data.items);
|
|
||||||
return try read.readQVariant(fBS.reader(), s.allocator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handshake(s: *Client) !void {
|
pub fn handshake(s: *Client) !void {
|
||||||
//const magic = 0x42b33f00;
|
try s.socketManager.baseStream.writer().writeAll(&[_]u8{ 0x42, 0xb3, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00 });
|
||||||
|
var flags = try read.readByte(s.socketManager.baseStream.reader());
|
||||||
//try write.writeUInt(s.stream.writer(), magic);
|
var extra = try read.readShort(s.socketManager.baseStream.reader());
|
||||||
//try write.writeUInt(s.stream.writer(), 0x80000002);
|
var version = try read.readSignedByte(s.socketManager.baseStream.reader());
|
||||||
try s.stream.writer().writeAll(&[_]u8{ 0x42, 0xb3, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00 });
|
|
||||||
|
|
||||||
var flags = try read.readByte(s.stream.reader());
|
|
||||||
var extra = try read.readShort(s.stream.reader());
|
|
||||||
var version = try read.readSignedByte(s.stream.reader());
|
|
||||||
|
|
||||||
std.debug.print("Handshake: flags={d} extra={d} version={d} \n", .{ flags, extra, version });
|
std.debug.print("Handshake: flags={d} extra={d} version={d} \n", .{ flags, extra, version });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quassel_init_packet(s: *Client) !void {
|
pub fn quassel_init_packet(s: *Client) !void {
|
||||||
var data = std.ArrayList(u8).init(s.allocator);
|
var data = std.ArrayList(u8).init(s.allocator);
|
||||||
defer data.deinit();
|
defer data.deinit();
|
||||||
|
|
||||||
var map = std.StringHashMap(QVariantType).init(s.allocator);
|
var map = std.StringHashMap(QVariant).init(s.allocator);
|
||||||
defer map.deinit();
|
defer map.deinit();
|
||||||
|
|
||||||
try map.put("MsgType", .{ .String = "ClientInit" });
|
try map.put("MsgType", .{ .String = "ClientInit" });
|
||||||
|
@ -151,18 +73,18 @@ pub const Client = struct {
|
||||||
.QVariantMap = map,
|
.QVariantMap = map,
|
||||||
});
|
});
|
||||||
|
|
||||||
try s.writeFrame(data);
|
try s.socketManager.writeFrame(data);
|
||||||
|
|
||||||
var variant = try s.readFrame();
|
var variant = try s.socketManager.readFrame();
|
||||||
defer freeQVariant(variant, s.allocator);
|
defer freeQVariant(variant, s.allocator);
|
||||||
tlsAllowed = variant.QVariantMap.get("SupportSsl").?.Byte == 1;
|
s.socketManager.setTLSAllowed(variant.QVariantMap.get("SupportSsl").?.Byte == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quassel_login(s: *Client, username: []const u8, password: []const u8) !void {
|
pub fn quassel_login(s: *Client, username: []const u8, password: []const u8) !void {
|
||||||
var data = std.ArrayList(u8).init(s.allocator);
|
var data = std.ArrayList(u8).init(s.allocator);
|
||||||
defer data.deinit();
|
defer data.deinit();
|
||||||
|
|
||||||
var map = std.StringHashMap(QVariantType).init(s.allocator);
|
var map = std.StringHashMap(QVariant).init(s.allocator);
|
||||||
defer map.deinit();
|
defer map.deinit();
|
||||||
|
|
||||||
try map.put("MsgType", .{ .String = "ClientLogin" });
|
try map.put("MsgType", .{ .String = "ClientLogin" });
|
||||||
|
@ -173,9 +95,9 @@ pub const Client = struct {
|
||||||
.QVariantMap = map,
|
.QVariantMap = map,
|
||||||
});
|
});
|
||||||
|
|
||||||
try s.writeFrame(data);
|
try s.socketManager.writeFrame(data);
|
||||||
|
|
||||||
var loginResponse = try s.readFrame();
|
var loginResponse = try s.socketManager.readFrame();
|
||||||
defer freeQVariant(loginResponse, s.allocator);
|
defer freeQVariant(loginResponse, s.allocator);
|
||||||
|
|
||||||
var loginResponseMap = loginResponse.QVariantMap;
|
var loginResponseMap = loginResponse.QVariantMap;
|
||||||
|
@ -186,14 +108,14 @@ pub const Client = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_session_init_packet(s: *Client, sessionState: std.StringHashMap(QVariantType)) !void {
|
fn handle_session_init_packet(s: *Client, sessionState: std.StringHashMap(QVariant)) !void {
|
||||||
for (sessionState.get("BufferInfos").?.QVariantList) |qvar| {
|
for (sessionState.get("BufferInfos").?.QVariantList) |qvar| {
|
||||||
try s.bufferManager.addBufferInfo(qvar.UserType.BufferInfo);
|
try s.bufferManager.addBufferInfo(qvar.UserType.BufferInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_quassel_packet(s: *Client) !void {
|
pub fn read_quassel_packet(s: *Client) !void {
|
||||||
var variant = try s.readFrame();
|
var variant = try s.socketManager.readFrame();
|
||||||
defer freeQVariant(variant, s.allocator);
|
defer freeQVariant(variant, s.allocator);
|
||||||
|
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
|
@ -216,7 +138,7 @@ pub const Client = struct {
|
||||||
var data = std.ArrayList(u8).init(s.allocator);
|
var data = std.ArrayList(u8).init(s.allocator);
|
||||||
defer data.deinit();
|
defer data.deinit();
|
||||||
|
|
||||||
var listItems = std.ArrayList(QVariantType).init(s.allocator);
|
var listItems = std.ArrayList(QVariant).init(s.allocator);
|
||||||
defer listItems.deinit();
|
defer listItems.deinit();
|
||||||
|
|
||||||
try listItems.append(.{ .Int = 2 });
|
try listItems.append(.{ .Int = 2 });
|
||||||
|
@ -228,7 +150,7 @@ pub const Client = struct {
|
||||||
.QVariantList = listItems.items,
|
.QVariantList = listItems.items,
|
||||||
});
|
});
|
||||||
|
|
||||||
try s.writeFrame(data);
|
try s.socketManager.writeFrame(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -237,5 +159,6 @@ pub fn initClient(allocator: *std.mem.Allocator, stream: *std.net.Stream) Client
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.stream = stream,
|
.stream = stream,
|
||||||
.bufferManager = BufferManager.initBufferManager(allocator),
|
.bufferManager = BufferManager.initBufferManager(allocator),
|
||||||
|
.socketManager = SocketManager.initSocketManager(allocator, stream)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue