From 7fa61df9fe7a57a08c674afa45803307a5011ab0 Mon Sep 17 00:00:00 2001 From: Z Date: Sun, 13 Jun 2021 16:03:53 +0100 Subject: [PATCH] Work on add to NetworkManager --- src/NetworkManager.zig | 91 ++++++++++++++++ src/client.zig | 102 +++++++++++++++--- src/main.zig | 18 +++- src/qtshit/read/usertypes/readUserType.zig | 2 +- .../utils/QVariantListToQVariantMap.zig | 50 +++++++++ src/qtshit/utils/tests.zig | 1 + 6 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 src/NetworkManager.zig create mode 100644 src/qtshit/utils/QVariantListToQVariantMap.zig diff --git a/src/NetworkManager.zig b/src/NetworkManager.zig new file mode 100644 index 0000000..e09ab5b --- /dev/null +++ b/src/NetworkManager.zig @@ -0,0 +1,91 @@ +const std = @import("std"); +const log = std.log.scoped(.NetworkManager); +const QVariant = @import("./qtshit/types/QVariant.zig").QVariant; +const BufferInfo = @import("./qtshit/types/UserType.zig").BufferInfo; + +pub const NetworkInfo = struct { + networkID: i32, + + pub fn new(networkID: i32) NetworkInfo { + return .{ .networkID = networkID }; + } +}; + +pub const Network = struct { + allocator: *std.mem.Allocator, + myNick: []const u8, + buffers: std.AutoHashMap(i32, BufferInfo), + networkInfo: NetworkInfo, + + + pub fn new(allocator: *std.mem.Allocator, networkID: i32) Network { + return .{ + .allocator = allocator, + .networkInfo = NetworkInfo.new(networkID), + .myNick = "", + .buffers = std.AutoHashMap(i32, BufferInfo).init(allocator), + }; + } + + pub fn addBuffer(s: *Network, info: BufferInfo) !void { + try s.buffers.put(info.NetworkID, BufferInfo{ + .ID = info.ID, + .NetworkID = info.NetworkID, + .Type = info.Type, + .Name = try s.allocator.dupe(u8, info.Name), + }); + } + + pub fn handle_init_packet(s: *Network, data: std.StringHashMap(QVariant)) !void { + var itr = data.keyIterator(); + while (itr.next()) |key_ptr| { + log.info("nm: data key {s}", .{ + key_ptr.*, + }); + } + if (data.get("myNick")) |myNick| { + log.info("myNick {s}", .{myNick.String}); + s.myNick = try s.allocator.dupe(u8, myNick.String); + } + } + + pub fn deinit(s: *Network) void { + var buffersIter = s.buffers.iterator(); + while (buffersIter.next()) |bufInfo| { + s.allocator.free(bufInfo.value_ptr.*.Name); + } + s.buffers.deinit(); + s.allocator.free(s.myNick); + } +}; + +pub const NetworkManager = struct { + allocator: *std.mem.Allocator, + networks: std.AutoHashMap(i32, Network), + + pub fn deinit(s: *NetworkManager) void { + var iter = s.networks.iterator(); + while (iter.next()) |network| { + network.value_ptr.deinit(); + } + s.networks.deinit(); + } + + pub fn get(s: *NetworkManager, networkID: i32) !?Network { + return s.networks.get(networkID); + } + + pub fn add(s: *NetworkManager, networkID: i32) !void { + try s.networks.put( + networkID, + Network.new(s.allocator, networkID), + ); + } +}; + +pub fn initNetworkManager(allocator: *std.mem.Allocator) NetworkManager { + return NetworkManager{ + .allocator = allocator, + .networks = std.AutoHashMap(i32, Network).init(allocator), + }; +} diff --git a/src/client.zig b/src/client.zig index 1af43b6..96e51a7 100644 --- a/src/client.zig +++ b/src/client.zig @@ -1,7 +1,7 @@ const std = @import("std"); -const BufferManager = @import("./BufferManager.zig"); const SocketManager = @import("./SocketManager.zig"); +const NetworkManager = @import("./NetworkManager.zig"); const read = @import("./qtshit/read.zig"); const write = @import("./qtshit/write.zig"); @@ -11,6 +11,8 @@ const QDateTime = @import("./qtshit/types/QVariant.zig").QDateTime; const UserType = @import("./qtshit/types/UserType.zig"); const RequestType = @import("./types/RequestType.zig").RequestType; +const QVariantListToQVariantMap = @import("./qtshit/utils/QVariantListToQVariantMap.zig").QVariantListToQVariantMap; + const prettyPrintQVariant = @import("./qtshit/utils/prettyPrintQVariant.zig").prettyPrintQVariant; const freeQVariant = @import("./qtshit/utils/free/freeQVariant.zig").freeQVariant; @@ -30,11 +32,11 @@ pub const Client = struct { allocator: *std.mem.Allocator, stream: *std.net.Stream, socketManager: SocketManager.SocketManager, - bufferManager: BufferManager.BufferManager, + networkManager: NetworkManager.NetworkManager, pub fn deinit(s: *Client) void { - s.bufferManager.deinit(); s.socketManager.deinit(); + s.networkManager.deinit(); } pub fn handshake(s: *Client) !void { @@ -145,16 +147,87 @@ pub const Client = struct { try s.socketManager.writeFrame(data); } + fn send_init_request(s: *Client, className: []const u8, objectName: ?[]const u8) !void { + var data = std.ArrayList(u8).init(s.allocator); + defer data.deinit(); + + var listItems = std.ArrayList(QVariant).init(s.allocator); + defer listItems.deinit(); + + try listItems.append(.{ .Int = @enumToInt(RequestType.InitRequest) }); + try listItems.append(.{ .String = className }); + if (objectName) |objName| { + try listItems.append(.{ .String = objName }); + } else { + try listItems.append(.{ .String = "" }); + } + + try write.writeQVariant(data.writer(), s.allocator, .{ + .QVariantList = listItems.items, + }); + + try s.socketManager.writeFrame(data); + } + fn handle_session_init_packet(s: *Client, sessionState: std.StringHashMap(QVariant)) !void { + for (sessionState.get("NetworkIds").?.QVariantList) |qvar| { + var networkID = qvar.UserType.NetworkId; + try s.networkManager.add(networkID); + + var networkIDStr = try std.fmt.allocPrint( + s.allocator, + "{d}", + .{networkID}, + ); + defer s.allocator.free(networkIDStr); + + try s.send_init_request("Network", networkIDStr); + } for (sessionState.get("BufferInfos").?.QVariantList) |qvar| { - try s.bufferManager.addBufferInfo(qvar.UserType.BufferInfo); + var bufInfo = qvar.UserType.BufferInfo; + var network = try s.networkManager.get(bufInfo.NetworkID); + try network.?.addBuffer(bufInfo); + } + } + + pub fn handle_struct_init_data( + s: *Client, + className: []const u8, + id: i32, + data: std.StringHashMap(QVariant), + ) !void { + if (std.mem.eql(u8, className, "Network")) { + var network = try s.networkManager.get(id); + try network.?.handle_init_packet(data); + } + + // Do Things + //prettyPrintQVariant(.{ .QVariantMap = data }, 0); + } + + pub fn handle_struct(s: *Client, list: []QVariant) !void { + var reqType = @intToEnum(RequestType, list[0].Int); + switch (reqType) { + .InitData => { + var className = list[1].QByteArray; + var id = list[2].String; + var idInt = try std.fmt.parseInt(i32, id, 10); + var mapData = list[3].QVariantMap; + try s.handle_struct_init_data(className, idInt, mapData); + }, + .HeartBeat => { + try s.reply_to_heartbeat(list[1].QDateTime); + return; + }, + else => { + prettyPrintQVariant(.{ .QVariantList = list }, 0); + }, } } pub fn read_quassel_packet(s: *Client) !void { var variant = try s.socketManager.readFrame(); defer freeQVariant(variant, s.allocator); - switch (variant) { .QVariantMap => |map| { if (map.get("MsgType")) |msgType| { @@ -166,21 +239,22 @@ pub const Client = struct { } }, .QVariantList => |list| { - switch (@intToEnum(RequestType, list[0].Int)) { - .HeartBeat => { - try s.reply_to_heartbeat(list[1].QDateTime); - return; - }, - else => {}, - } + try s.handle_struct(list); + return; }, else => {}, } - std.debug.print("\n\n Unknown: Quassel Packet: \n", .{}); + prettyPrintQVariant(variant, 0); + std.debug.print("\n\n Unknown: Quassel Packet: \n", .{}); } }; pub fn initClient(allocator: *std.mem.Allocator, stream: *std.net.Stream) Client { - return Client{ .allocator = allocator, .stream = stream, .bufferManager = BufferManager.initBufferManager(allocator), .socketManager = SocketManager.initSocketManager(allocator, stream) }; + return Client{ + .allocator = allocator, + .stream = stream, + .socketManager = SocketManager.initSocketManager(allocator, stream), + .networkManager = NetworkManager.initNetworkManager(allocator), + }; } diff --git a/src/main.zig b/src/main.zig index 0d3b500..fcc1277 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,7 +4,7 @@ const DebugAllocator = @import("./debug_allocator.zig"); const write = @import("./qtshit/write.zig"); const initClient = @import("./client.zig").initClient; -pub const log_level: std.log.Level = .warn; +pub const log_level: std.log.Level = .info; pub fn realMain(allocator: *std.mem.Allocator) !void { var argIter = std.process.args(); @@ -32,11 +32,18 @@ pub fn realMain(allocator: *std.mem.Allocator) !void { try client.quassel_init_packet(); try client.quassel_login(username, password); + _ = try client.read_quassel_packet(); + + //var network = try client.networkManager.get(2); + //std.debug.print("\n\n {any} \n\n", .{network.?}); + //var bufferInfo = try client.bufferManager.getFirstByName("z_is_stimky"); //try client.send_message(bufferInfo.?, "uwu, owo, uwu"); + var i: i64 = 0; - while (true) { - std.time.sleep(100 * std.time.ns_per_ms); + while (i < 10) { + i = i + 1; + //std.time.sleep(100 * std.time.ns_per_ms); client.read_quassel_packet() catch |err| { if (err == error.DecodeError) { @@ -50,6 +57,9 @@ pub fn realMain(allocator: *std.mem.Allocator) !void { } }; } + + var network = try client.networkManager.get(1); + std.debug.print("network 1 is using nickname: {s} \n", .{network.?.myNick}); } pub fn main() !void { @@ -60,5 +70,5 @@ pub fn main() !void { const alloc = &gpalloc.allocator; - try realMain(alloc); + try realMain(std.heap.page_allocator); } diff --git a/src/qtshit/read/usertypes/readUserType.zig b/src/qtshit/read/usertypes/readUserType.zig index 8c4278b..ed8bc14 100644 --- a/src/qtshit/read/usertypes/readUserType.zig +++ b/src/qtshit/read/usertypes/readUserType.zig @@ -52,7 +52,7 @@ pub fn readUserType(reader: anytype, allocator: *std.mem.Allocator) !UserType { return UserType{ .NetworkInfo = try readQVariantMap(reader, allocator), }; - } else if (std.mem.eql(u8, userTypeName, "NetworkServer")) { + } else if (std.mem.eql(u8, userTypeName, "Network::Server")) { return UserType{ .NetworkServer = try readQVariantMap(reader, allocator), }; diff --git a/src/qtshit/utils/QVariantListToQVariantMap.zig b/src/qtshit/utils/QVariantListToQVariantMap.zig new file mode 100644 index 0000000..2184524 --- /dev/null +++ b/src/qtshit/utils/QVariantListToQVariantMap.zig @@ -0,0 +1,50 @@ +const std = @import("std"); +const QVariant = @import("../types/QVariant.zig").QVariant; +const range = @import("./RangeIter.zig").range; +const freeQVariantMap = @import("./free/freeQVariantMap.zig").freeQVariantMap; + +pub fn QVariantListToQVariantMap(varList: []QVariant, allocator: *std.mem.Allocator) !std.StringHashMap(QVariant) { + var varMap = std.StringHashMap(QVariant).init(allocator); + errdefer varMap.deinit(); + + if (varList.len % 2 != 0) { + return error.NotDivByTwo; + } + + var iter = range(u32, 0, @intCast(u32, @divExact(varList.len, 2))); + + while (iter.next()) |i| { + if (i % 2 == 1) continue; + try varMap.put( + varList[i].String, + varList[i + 1], + ); + } + return varMap; +} + +test "QVariantList -> QVariantMap" { + // These will get free'd by freeQVariantMap + var owoString = try std.testing.allocator.dupe(u8, "owo"); + + var varList = [_]QVariant{ + .{.String = owoString}, + .{.Int = 1337}, + }; + + var map = try QVariantListToQVariantMap(varList[0..], std.testing.allocator); + defer freeQVariantMap(map, std.testing.allocator); + + var owo = map.get("owo"); + try std.testing.expect(owo.?.Int == 1337); +} + + +test "QVariantList not div by 2" { + var varList = [_]QVariant{ + .{.String = "uwu"}, + }; + + var res = QVariantListToQVariantMap(varList[0..], std.testing.allocator); + try std.testing.expectError(error.NotDivByTwo, res); +} \ No newline at end of file diff --git a/src/qtshit/utils/tests.zig b/src/qtshit/utils/tests.zig index d183c55..b0b67cd 100644 --- a/src/qtshit/utils/tests.zig +++ b/src/qtshit/utils/tests.zig @@ -1,5 +1,6 @@ const unicode = @import("./unicode.zig"); const QVariantMapToQVariantList = @import("./QVariantMapToQVariantList.zig"); +const QVariantListToQVariantMap = @import("./QVariantListToQVariantMap.zig"); comptime { @import("std").testing.refAllDecls(@This());