Advertisement
tyler569

irc.zig

Apr 8th, 2019
387
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.82 KB | None | 0 0
  1. const std = @import("std");
  2. const net = @cImport(@cInclude("netinet/in.h"));
  3. const socket = @cImport(@cInclude("sys/socket.h"));
  4. const cio = @cImport(@cInclude("stdio.h"));
  5. const netdb = @cImport(@cInclude("netdb.h"));
  6.  
  7. const assert = std.debug.assert;
  8. const warn = std.debug.warn;
  9.  
  10. const irc_port = 6667;
  11. const addr = c"irc.esper.net";
  12. const channel = "#openredstone";
  13.  
  14. const nick = "tbot_zig";
  15. const real = nick;
  16. const user = nick;
  17.  
  18. const recv_buf_len = 1024;
  19. var recv_buf: [recv_buf_len]u8 = undefined;
  20.  
  21. fn strchr(str: []const u8, char: u8) ?usize {
  22. for (str) |c, i| {
  23. if (c == char) {
  24. return i;
  25. }
  26. }
  27. return null;
  28. }
  29.  
  30. test "strings contain characters" {
  31. assert(strchr("foobar", 'f').? == 0);
  32. assert(strchr("foobar", 'o').? == 1);
  33. assert(strchr("foobar", 'b').? == 3);
  34. assert(strchr("foobar", 'a').? == 4);
  35. assert(strchr("foobar", 'x') == null);
  36. }
  37.  
  38. fn streq(s: []const u8, t: []const u8) bool {
  39. if (s.len != t.len) {
  40. return false;
  41. }
  42.  
  43. var i: usize = 0;
  44. while (i < s.len) : (i += 1) {
  45. if (s[i] != t[i]) {
  46. return false;
  47. }
  48. }
  49.  
  50. return true;
  51. }
  52.  
  53. test "strings are equal to each other" {
  54. assert(streq("foo bar", "foo bar"));
  55. assert(streq("", ""));
  56. assert(!streq("foo", "foobar"));
  57. assert(!streq("foo", "bar"));
  58. }
  59.  
  60. fn strstr(str: []const u8, s: []const u8) ?usize {
  61. if (s.len == 0) {
  62. return 0;
  63. }
  64. outer: for (str) |c, i| {
  65. if (i + s.len > str.len) {
  66. break;
  67. }
  68. for (s) |sc, si| {
  69. if (sc != str[i + si]) {
  70. continue :outer;
  71. }
  72. }
  73. return i;
  74. }
  75. return null;
  76. }
  77.  
  78. test "strings contain other strings" {
  79. assert(strstr("foobar", "foo").? == 0);
  80. assert(strstr("foobar", "bar").? == 3);
  81. assert(strstr("foobar", "foox") == null);
  82. assert(strstr("foobar", "xfoo") == null);
  83. }
  84.  
  85. fn parse_nick(line: []const u8) ?[]const u8 {
  86. if (line[0] == ':') {
  87. var spce = strchr(line, ' ') orelse return null;
  88. var excl = strchr(line, '!') orelse return null;
  89.  
  90. if (spce < excl) {
  91. return null;
  92. }
  93.  
  94. var nick_end: usize = excl;
  95. return line[1..nick_end];
  96. }
  97. return null;
  98. }
  99.  
  100. test "parse nickname" {
  101. const line = ":tyler!testtesttest foo bar :trail\r\n";
  102. assert(streq(parse_nick(line).?, "tyler"));
  103.  
  104. const line2 = "foo bar :trail\r\n";
  105. assert(parse_nick(line2) == null);
  106. }
  107.  
  108. fn parse_command(line: []const u8) ?[]const u8 {
  109. var cmd_start: usize = 0;
  110. var cmd_end: usize = 0;
  111.  
  112. if (line[0] == ':') {
  113. cmd_start = strchr(line, ' ') orelse unreachable;
  114. cmd_start += 1;
  115. cmd_end = strchr(line[cmd_start..], ' ') orelse strchr(line[cmd_start..], '\r') orelse unreachable;
  116. cmd_end += cmd_start;
  117. } else {
  118. cmd_end = strchr(line, ' ') orelse strchr(line, '\r') orelse unreachable;
  119. }
  120. return line[cmd_start..cmd_end];
  121. }
  122.  
  123. test "parse command" {
  124. const line = ":tyler!testtesttest foo bar :trail\r\n";
  125. assert(streq(parse_command(line).?, "foo"));
  126.  
  127. const line2 = "foo bar :trail\r\n";
  128. assert(streq(parse_command(line2).?, "foo"));
  129. }
  130.  
  131. const CError = error.CError;
  132.  
  133. fn perror(msg: []const u8) anyerror {
  134. cio.perror(msg.ptr);
  135. return error.CError;
  136. }
  137.  
  138. fn irc_send(sock: i32, value: []const u8) void {
  139. // for loop on var args kills compiler
  140. // for (args) |arg| {
  141. // warn("{}", arg);
  142. // socket.send(sock, arg, arg.len, 0);
  143. // }
  144. // var i: usize = 0;
  145. // while (i < args.len) : (i += 1) {
  146. // warn("{}", args[i]);
  147. // _ = socket.send(sock, args[i], args[i].len, 0);
  148. // }
  149. // inline for (args) |arg| {
  150. // warn("{}", arg);
  151. // socket.send(sock, arg, arg.len, 0);
  152. // }
  153. warn("<< {}\n", value);
  154. _ = socket.send(sock, value.ptr, value.len, 0);
  155. _ = socket.send(sock, c"\r\n", 2, 0);
  156. }
  157.  
  158. pub fn main() !void {
  159. var stdout = try std.io.getStdOut();
  160.  
  161. try stdout.write("Test\n");
  162.  
  163. const buf_index: usize = 0;
  164.  
  165. const host: ?*netdb.hostent = @ptrCast(?*netdb.hostent, netdb.gethostbyname(addr)) orelse return perror("getaddr");
  166. const sock: i32 = socket.socket(socket.AF_INET, @enumToInt(socket.SOCK_STREAM), 0);
  167. if (sock == -1) {
  168. return perror("sock");
  169. }
  170.  
  171. var remote = net.sockaddr_in{
  172. .sin_family = socket.AF_INET,
  173. .sin_port = net.htons(irc_port),
  174. .sin_addr = undefined,
  175. .sin_zero = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },
  176. };
  177.  
  178. // @ptrCast(*net.in_addr, @alignCast(4, host.?.h_addr_list.?[0].?)).*,
  179.  
  180. @memcpy(@ptrCast([*]u8, &remote.sin_addr), host.?.h_addr_list[0], @sizeOf(@typeOf(remote.sin_addr)));
  181.  
  182. var conn_result = socket.connect(sock, @ptrCast([*]const socket.sockaddr, &remote), @sizeOf(@typeOf(remote)));
  183. if (conn_result == -1) {
  184. return perror("connect");
  185. }
  186.  
  187. irc_send(sock, "USER " ++ nick ++ " 0 * :" ++ nick);
  188. irc_send(sock, "NICK " ++ nick);
  189. irc_send(sock, "JOIN " ++ channel);
  190.  
  191. var buffer_index: usize = 0;
  192.  
  193. while (true) {
  194. // main loop
  195. var len: isize = 0;
  196. warn("buffer_index: {}\n", buffer_index);
  197. len = socket.recv(sock, @ptrCast(?*c_void, &recv_buf[buffer_index]), recv_buf_len - buffer_index, 0);
  198.  
  199. // is there a better way to do this?
  200. var buf_view: []u8 = undefined;
  201. buf_view.ptr = @ptrCast([*]u8, &recv_buf);
  202. buf_view.len = @intCast(usize, len) + buffer_index;
  203.  
  204. var one_line_end = strchr(recv_buf, '\n');
  205.  
  206. while (one_line_end != null) {
  207. warn("buf view at {} - {}\n", @ptrToInt(buf_view.ptr) - @ptrToInt(&recv_buf), @ptrToInt(buf_view.ptr) - @ptrToInt(&recv_buf) + buf_view.len);
  208. warn("buf_view len: {}\n", buf_view.len);
  209. warn("recv_buf: {x}\n", recv_buf);
  210. warn("buf_view: {x}\n", buf_view);
  211. warn("one_line_end: {}\n", one_line_end.?);
  212. var line = buf_view[0 .. one_line_end.? - 1];
  213. warn(">> {}\n", line);
  214.  
  215. var line_nick = parse_nick(line);
  216. var line_command = parse_command(line);
  217. warn(" nick: {}\n", line_nick);
  218. warn(" command: {}\n", line_command);
  219.  
  220. if (streq(line_command.?, "PING")) {
  221. line[1] = 'O'; // @fragile
  222. irc_send(sock, line);
  223. }
  224.  
  225. if (streq(line_command.?, "MODE")) {
  226. irc_send(sock, "PRIVMSG NickServ :IDENTIFY orepassword");
  227. irc_send(sock, "JOIN #openredstone");
  228. }
  229.  
  230. if (strstr(line, "~test")) |_| {
  231. irc_send(sock, "PRIVMSG #openredstone :ayy test");
  232. }
  233.  
  234. // var zero_used: usize = 0;
  235. // while (buf_view[zero_used] != '\n') : (zero_used += 1) {
  236. // buf_view[zero_used] = 0;
  237. // }
  238. // buf_view[zero_used] = 0;
  239.  
  240. buf_view = buf_view[one_line_end.? + 1 ..];
  241. one_line_end = strchr(buf_view, '\n');
  242. }
  243. // warn("recv_buf: 0x{x}\n", @ptrToInt(&recv_buf));
  244. // warn("buf_view: 0x{x}\n", @ptrToInt(buf_view.ptr));
  245. // warn("moving {}\n", recv_buf_len - (@ptrToInt(buf_view.ptr) - @ptrToInt(&recv_buf)));
  246. // @memset(
  247. // @ptrCast([*]u8, &recv_buf) + buf_view.len,
  248. // 0,
  249. // recv_buf_len - buf_view.len
  250. // );
  251. if (buf_view.len != 0) {
  252. @memcpy(&recv_buf, buf_view.ptr, buf_view.len);
  253. // var i: usize = buf_view.len;
  254. // while (i<recv_buf_len) : (i += 1) {
  255. // recv_buf[i] = 0;
  256. // }
  257. buffer_index = buf_view.len;
  258. } else {
  259. buffer_index = 0;
  260. }
  261. }
  262. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement