-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathmulti.zig
More file actions
87 lines (72 loc) · 3.02 KB
/
Copy pathmulti.zig
File metadata and controls
87 lines (72 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
const std = @import("std");
const println = @import("util.zig").println;
const mem = std.mem;
const Allocator = mem.Allocator;
const curl = @import("curl");
const Easy = curl.Easy;
const Multi = curl.Multi;
const c = curl.libcurl;
const checkCode = curl.checkCode;
const Writer = std.Io.Writer;
fn newEasy(writer: *Writer, url: [:0]const u8) !Easy {
var easy = try Easy.init(.{});
try easy.setUrl(url);
try easy.setWriter(writer);
// CURLOPT_PRIVATE allows us to store a pointer to the ctx in the easy handle
// so we can retrieve it later in the callback.
try easy.setPrivate(writer);
return easy;
}
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer if (gpa.deinit() != .ok) @panic("leak");
const allocator = gpa.allocator();
var multi = try Multi.init();
defer multi.deinit() catch |e| {
std.debug.print("multi handle deinit failed, err:{any}\n", .{e});
if (multi.diagnostics.getMessage()) |msg| {
std.debug.print("Diagnostics: {s}\n", .{msg});
}
};
var wtr1 = std.Io.Writer.Allocating.init(allocator);
defer wtr1.deinit();
var wtr2 = std.Io.Writer.Allocating.init(allocator);
defer wtr2.deinit();
var easy1 = try newEasy(&wtr1.writer, "http://edgebin.liujiacai.net/headers");
defer easy1.deinit();
var easy2 = try newEasy(&wtr2.writer, "http://edgebin.liujiacai.net/ip");
defer easy2.deinit();
try multi.addHandle(&easy1);
try multi.addHandle(&easy2);
var keep_running = true;
while (keep_running) {
const still_running = try multi.perform();
keep_running = still_running > 0;
std.debug.print("{d} pending requests...\n", .{still_running});
const num_fds = try multi.poll(null, 300);
std.debug.print("{d} requests had activity...\n", .{num_fds});
const info = multi.readInfo() catch |e| switch (e) {
// no new data to read on this iteration
error.InfoReadExhausted => continue,
};
// If we have `info` then one of the requests completed
const easy_handle = info.msg.easy_handle.?;
defer {
multi.removeHandle(easy_handle) catch |e| {
std.debug.print("{any}", .{e});
};
c.curl_easy_cleanup(easy_handle);
}
// check that the request was successful
try checkCode(info.msg.data.result, &multi.diagnostics);
// Read the HTTP status code
var status_code: c_long = 0;
try checkCode(c.curl_easy_getinfo(easy_handle, c.CURLINFO_RESPONSE_CODE, &status_code), &multi.diagnostics);
std.debug.print("Response Code: {any}\n", .{status_code});
// Get the private data (buffer) associated with this handle
var private_data: ?*anyopaque = null;
try checkCode(c.curl_easy_getinfo(easy_handle, c.CURLINFO_PRIVATE, &private_data), &multi.diagnostics);
const writer: *Writer = @ptrCast(@alignCast(private_data.?));
std.debug.print("Response body: {s}\n", .{writer.buffered()});
}
}