Commit 69ad872f 69ad872fb22c0f05fe2ca06610dfc69711a97c08 by Sergey Poznyakoff

Accept up to two arguments: hostname to connect to and URL of the page to get.

1 parent b16da1bd
...@@ -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)
......