Accept up to two arguments: hostname to connect to and URL of the page to get.
Showing
1 changed file
with
116 additions
and
46 deletions
... | @@ -28,77 +28,147 @@ | ... | @@ -28,77 +28,147 @@ |
28 | 28 | ||
29 | #include <mailutils/mailutils.h> | 29 | #include <mailutils/mailutils.h> |
30 | 30 | ||
31 | const char *wbuf = "GET / HTTP/1.0\r\n\r\n"; | 31 | char wbuf[1024]; |
32 | char rbuf[1024]; | 32 | char rbuf[1024]; |
33 | 33 | ||
34 | size_t io_timeout = 3; | ||
35 | size_t io_attempts = 3; | ||
36 | |||
34 | int | 37 | int |
35 | main (void) | 38 | http_stream_wait (stream_t stream, int flags, size_t *attempt) |
39 | { | ||
40 | int rc; | ||
41 | int oflags = flags; | ||
42 | struct timeval tv; | ||
43 | |||
44 | while (*attempt < io_attempts) | ||
45 | { | ||
46 | tv.tv_sec = io_timeout; | ||
47 | tv.tv_usec = 0; | ||
48 | rc = stream_wait (stream, &oflags, &tv); | ||
49 | switch (rc) { | ||
50 | case 0: | ||
51 | if (flags & oflags) | ||
52 | return 0; | ||
53 | /* FALLTHROUGH */ | ||
54 | case EAGAIN: | ||
55 | case EINPROGRESS: | ||
56 | ++*attempt; | ||
57 | continue; | ||
58 | |||
59 | default: | ||
60 | return rc; | ||
61 | } | ||
62 | } | ||
63 | return ETIMEDOUT; | ||
64 | } | ||
65 | |||
66 | int | ||
67 | main (int argc, char **argv) | ||
36 | { | 68 | { |
37 | int ret, off = 0; | 69 | int ret, off = 0; |
38 | stream_t stream; | 70 | stream_t stream; |
39 | size_t nb; | 71 | size_t nb, size; |
72 | size_t attempt; | ||
73 | char *url = "www.gnu.org"; | ||
74 | |||
75 | if (argc > 3) | ||
76 | { | ||
77 | fprintf (stderr, "usage: %s [hostname [url]]\n", argv[0]); | ||
78 | exit (1); | ||
79 | } | ||
40 | 80 | ||
41 | ret = tcp_stream_create (&stream, "www.gnu.org", 80, MU_STREAM_NONBLOCK); | 81 | if (argc > 1) |
82 | url = argv[1]; | ||
83 | |||
84 | snprintf (wbuf, sizeof wbuf, "GET %s HTTP/1.0\r\n\r\n", | ||
85 | argc == 3 ? argv[2] : "/"); | ||
86 | |||
87 | ret = tcp_stream_create (&stream, url, 80, MU_STREAM_NONBLOCK); | ||
42 | if (ret != 0) | 88 | if (ret != 0) |
43 | { | 89 | { |
44 | mu_error ("tcp_stream_create: %s", mu_strerror (ret)); | 90 | mu_error ("tcp_stream_create: %s", mu_strerror (ret)); |
45 | exit (EXIT_FAILURE); | 91 | exit (EXIT_FAILURE); |
46 | } | 92 | } |
47 | 93 | ||
48 | connect_again: | 94 | for (attempt = 0; (ret = stream_open (stream)); ) |
49 | ret = stream_open (stream); | ||
50 | if (ret != 0) | ||
51 | { | 95 | { |
52 | if (ret == EAGAIN) | 96 | if ((ret == EAGAIN || ret == EINPROGRESS) && attempt < io_attempts) |
53 | { | 97 | { |
54 | int wflags = MU_STREAM_READY_WR; | 98 | ret = http_stream_wait(stream, MU_STREAM_READY_WR, &attempt); |
55 | stream_wait (stream, &wflags, NULL); | 99 | if (ret == 0) |
56 | goto connect_again; | 100 | continue; |
57 | } | 101 | } |
58 | mu_error ("stream_open: %s", mu_strerror (ret)); | 102 | mu_error ("stream_open: %s", mu_strerror (ret)); |
59 | exit (EXIT_FAILURE); | 103 | exit (EXIT_FAILURE); |
60 | } | 104 | } |
61 | 105 | ||
62 | write_again: | 106 | for (attempt = 0, size = strlen (wbuf); size > 0; ) |
63 | ret = stream_write (stream, wbuf + off, strlen (wbuf), 0, &nb); | ||
64 | if (ret != 0) | ||
65 | { | 107 | { |
66 | if (ret == EAGAIN) | 108 | ret = stream_write (stream, wbuf + off, strlen (wbuf), 0, &nb); |
109 | if (ret == 0) | ||
110 | { | ||
111 | if (nb == 0) | ||
112 | { | ||
113 | mu_error("stream_write: wrote 0 bytes"); | ||
114 | exit (EXIT_FAILURE); | ||
115 | } | ||
116 | off += nb; | ||
117 | size -= nb; | ||
118 | } | ||
119 | else if (ret == EAGAIN) | ||
67 | { | 120 | { |
68 | int wflags = MU_STREAM_READY_WR; | 121 | if (attempt < io_attempts) |
69 | stream_wait (stream, &wflags, NULL); | 122 | { |
70 | off += nb; | 123 | ret = http_stream_wait (stream, MU_STREAM_READY_WR, &attempt); |
71 | goto write_again; | 124 | if (ret) |
72 | } | 125 | { |
73 | mu_error ("stream_write: %s", mu_strerror (ret)); | 126 | mu_error ("http_wait failed: %s", mu_strerror (ret)); |
74 | exit (EXIT_FAILURE); | 127 | return -1; |
128 | } | ||
129 | continue; | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | mu_error ("stream_write timed out"); | ||
134 | exit (EXIT_FAILURE); | ||
135 | } | ||
136 | } | ||
137 | else | ||
138 | { | ||
139 | mu_error ("stream_write: %s", mu_strerror (ret)); | ||
140 | exit (EXIT_FAILURE); | ||
141 | } | ||
75 | } | 142 | } |
76 | 143 | ||
77 | if (nb != strlen (wbuf)) | 144 | attempt = 0; |
78 | { | 145 | for (;;) |
79 | mu_error ("stream_write: %s", "nb != wbuf length"); | ||
80 | exit (EXIT_FAILURE); | ||
81 | } | ||
82 | |||
83 | do | ||
84 | { | 146 | { |
85 | ret = stream_read (stream, rbuf, sizeof (rbuf), 0, &nb); | 147 | ret = stream_read (stream, rbuf, sizeof (rbuf), 0, &nb); |
86 | if (ret != 0) | 148 | if (ret == 0) |
87 | { | 149 | { |
88 | if (ret == EAGAIN) | 150 | if (nb == 0) |
89 | { | 151 | break; |
90 | int wflags = MU_STREAM_READY_RD; | 152 | write (1, rbuf, nb); |
91 | stream_wait (stream, &wflags, NULL); | 153 | } |
92 | } | 154 | else if (ret == EAGAIN) |
93 | else | 155 | { |
94 | { | 156 | if (attempt < io_attempts) |
95 | mu_error ("stream_read: %s", mu_strerror (ret)); | 157 | { |
96 | exit (EXIT_FAILURE); | 158 | ret = http_stream_wait (stream, MU_STREAM_READY_RD, &attempt); |
97 | } | 159 | if (ret) |
98 | } | 160 | { |
99 | write (1, rbuf, nb); | 161 | mu_error ("http_stream_wait failed: %s", mu_strerror (ret)); |
162 | exit (EXIT_FAILURE); | ||
163 | } | ||
164 | } | ||
165 | else | ||
166 | { | ||
167 | mu_error ("stream_read: %s", mu_strerror (ret)); | ||
168 | exit (EXIT_FAILURE); | ||
169 | } | ||
170 | } | ||
100 | } | 171 | } |
101 | while (nb || ret == EAGAIN); | ||
102 | 172 | ||
103 | ret = stream_close (stream); | 173 | ret = stream_close (stream); |
104 | if (ret != 0) | 174 | if (ret != 0) | ... | ... |
-
Please register or sign in to post a comment