From 86e7fb6a574c0f71169cf6025278319c55b9529d Mon Sep 17 00:00:00 2001 From: Kitteh Date: Wed, 2 Jun 2021 12:03:55 +0100 Subject: [PATCH] aaaaa --- src/client.zig | 57 ++++++++++++++++++++++++++++++++++++++ src/main.zig | 12 ++++++-- src/qtshit/qvariant.zig | 58 +++++++++++++++++++++++++++++++++++++-- src/qtshit/read.zig | 1 - src/qtshit/test.zig | 4 +-- src/qtshit/write.zig | 61 +++++++++++++++++++++++++++++++++++++++-- 6 files changed, 183 insertions(+), 10 deletions(-) create mode 100644 src/client.zig diff --git a/src/client.zig b/src/client.zig new file mode 100644 index 0000000..15fd755 --- /dev/null +++ b/src/client.zig @@ -0,0 +1,57 @@ +const std = @import("std"); +const read = @import("./qtshit/read.zig"); +const write = @import("./qtshit/write.zig"); +const qvar = @import("./qtshit/qvariant.zig"); + +pub const Client = struct { + allocator: *std.mem.Allocator, + stream: *std.net.Stream, + + pub fn handshake(s: *Client) !void { + const magic = 0x42b33f00; + + try write.add_int(s.stream.writer(), magic); + try write.add_int(s.stream.writer(), 2); + try write.add_int(s.stream.writer(), 1 << 31); + var resp = try read.get_int(s.stream.reader()); + if ((resp & 0xff) != 1) { + @panic("No support 4 legacy protocol."); + } + + if (((resp >> 24) & 1) != 0) { + @panic("No support 4 ssl protocol."); + } + + if (((resp >> 24) & 2) != 0) { + @panic("No support 4 compression."); + } + std.debug.print("handshake Success!\n", .{}); + } + pub fn quassel_init_packet(s: *Client) !void { + var map = std.StringHashMap(qvar.QVariant).init(s.allocator); + try map.put("UseSSL", .{ .byte = 0 }); + try map.put("UseCompression", .{ .byte = 0 }); + try map.put("ProtocolVersion", .{ .int = 10 }); + try map.put("MsgType", .{ .string = "ClientInit" }); + try map.put("ClientVersion", .{ .string = "0.1 (quasselclient)" }); + try map.put("ClientDate", .{ .string = "0" }); + + try write.add_qvariantmap(s.stream.writer(), map); + } + pub fn quassel_login(s: *Client) !void { + var map = std.StringHashMap(qvar.QVariant).init(s.allocator); + + try map.put("MsgType", .{ .string = "ClientLogin" }); + try map.put("User", .{ .string = "z" }); + try map.put("Password", .{ .string = "password" }); + + try write.add_qvariantmap(s.stream.writer(), map); + } +}; + +pub fn initClient(allocator: *std.mem.Allocator, stream: *std.net.Stream) Client { + return Client{ + .allocator = allocator, + .stream = stream, + }; +} diff --git a/src/main.zig b/src/main.zig index 2602eb0..90509d0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3,7 +3,15 @@ const std = @import("std"); const read = @import("./qtshit/read.zig"); const write = @import("./qtshit/write.zig"); +const initClient = @import("./client.zig").initClient; + pub fn main() !void { - const stdout = std.io.getStdOut().writer(); - try stdout.print("Hello, {s}!\n", .{"world"}); + const allocator = std.heap.page_allocator; + var sock = try std.net.tcpConnectToHost(allocator, "127.0.0.1", 64242); + + var client = initClient(allocator, &sock); + try client.handshake(); + try client.quassel_init_packet(); + try client.quassel_login(); + } diff --git a/src/qtshit/qvariant.zig b/src/qtshit/qvariant.zig index d1952aa..78c897c 100644 --- a/src/qtshit/qvariant.zig +++ b/src/qtshit/qvariant.zig @@ -1,11 +1,11 @@ const std = @import("std"); -pub const QVariant = union { +pub const QVariant = union(enum) { int: u32, short: u16, byte: u8, bytearray: std.ArrayList(u8), - string: []u8, + string: []const u8, stringlist: std.ArrayList([]const u8), empty: bool, }; @@ -15,8 +15,60 @@ pub const QVariantTypes = enum(u32) { // IDK why there is 2??? int_1 = 2, int_2 = 3, + qmap = 8, string = 10, stringlist = 11, bytearray = 12, short = 133, -}; \ No newline at end of file +}; + +pub fn qvariant_type_id(variant: QVariant) !u32 { + switch (variant) { + .byte => { + return @enumToInt(QVariantTypes.byte); + }, + .int_1, .int_2 => { + return @enumToInt(QVariantTypes.int_1); + }, + .qmap => { + return @enumToInt(QVariantTypes.qmap); + }, + .string => { + return @enumToInt(QVariantTypes.string); + }, + .stringlist => { + return @enumToInt(QVariantTypes.stringlist); + }, + .bytearray => { + return @enumToInt(QVariantTypes.bytearray); + }, + .short => { + return @enumToInt(QVariantTypes.short); + }, + else => { + return 0; + }, + } +} + +pub fn qvariant_size(variant: QVariant) !u32 { + var size: u32 = 0; + + switch (variant) { + .int => { + size += 4; + }, + .byte => { + size += 1; + }, + .string => |*str| { + size += @intCast(u32, str.len); + // Null Terminator + size += 1; + }, + else => { + size += 0; + }, + } + return size; +} diff --git a/src/qtshit/read.zig b/src/qtshit/read.zig index bf06115..bfee870 100644 --- a/src/qtshit/read.zig +++ b/src/qtshit/read.zig @@ -17,7 +17,6 @@ pub fn get_bytearray(reader: anytype, allocator: *std.mem.Allocator) !std.ArrayL var byteList = std.ArrayList(u8).init(allocator); var length = try get_int(reader); - var index: usize = 0; while (true) { if (index == length) return byteList; diff --git a/src/qtshit/test.zig b/src/qtshit/test.zig index fd7c611..37a57d0 100644 --- a/src/qtshit/test.zig +++ b/src/qtshit/test.zig @@ -108,7 +108,7 @@ test "read/write byte variant" { var byteList = std.ArrayList(u8).init(global_allocator); defer byteList.deinit(); - try write.add_qvariant(byteList.writer(), @enumToInt(qvar.QVariantTypes.byte)); + try write.add_qvariant_with_id(byteList.writer(), @enumToInt(qvar.QVariantTypes.byte)); try write.add_byte(byteList.writer(), 'a'); var fBS = std.io.fixedBufferStream(byteList.items); @@ -121,7 +121,7 @@ test "read/write int variant" { var byteList = std.ArrayList(u8).init(global_allocator); defer byteList.deinit(); - try write.add_qvariant(byteList.writer(), @enumToInt(qvar.QVariantTypes.int_2)); + try write.add_qvariant_with_id(byteList.writer(), @enumToInt(qvar.QVariantTypes.int_2)); try write.add_int(byteList.writer(), 1312); var fBS = std.io.fixedBufferStream(byteList.items); diff --git a/src/qtshit/write.zig b/src/qtshit/write.zig index fe4dc35..09ae0d0 100644 --- a/src/qtshit/write.zig +++ b/src/qtshit/write.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const qvar = @import("./qvariant.zig"); pub fn add_int(writer: anytype, number: u32) !void { try writer.writeIntBig(u32, number); @@ -29,9 +30,65 @@ pub fn add_stringlist(writer: anytype, strList: std.ArrayList([]const u8)) !void } } - // Call this and Then write your type -pub fn add_qvariant(writer: anytype, type_id: u32) !void { +pub fn add_qvariant_with_id(writer: anytype, type_id: u32) !void { try add_int(writer, type_id); try add_byte(writer, 0); } + +pub fn add_qvariant(writer: anytype, variant: qvar.QVariant) !void { + add_qvariant_with_id(writer, qvar.qvariant_type_id(variant)); + switch (variant) { + .byte => |*out| { + return add_byte(writer, out); + }, + .int_1, .int_2 => |*out| { + return add_int(writer, out); + }, + .qmap => |*out| { + return add_qvariantmap(writer, out); + }, + .string => |*out| { + return add_string(writer, out); + }, + .stringlist => |*out| { + return add_stringlist(writer, out); + }, + .bytearray => |*out| { + return add_bytearray(writer, out); + }, + .short => |*out| { + return add_short(writer, out); + }, + else => { + return 0; + }, + } +} + +pub fn add_qvariantmap(writer: anytype, map: std.StringHashMap(qvar.QVariant)) !void { + var size: u32 = 0; + + var iterator = map.iterator(); + + while (iterator.next()) |entry| { + size += try qvar.qvariant_size(.{ .string = entry.key }); + size += try qvar.qvariant_size(entry.value); + size += 4; + } + + try add_int(writer, size + 4 + 1 + 4); + try add_int(writer, 8); + try add_byte(writer, 1); + try add_int(writer, map.count()); + + while (iterator.next()) |entry| { + size += try qvar.qvariant_size(.{ .string = entry.key }); + size += try qvar.qvariant_size(entry.value); + size += 4; + } + + std.debug.print("Size {d} !\n", .{size}); + + return; +}