Introduction
Introduction Statistics Contact Development Disclaimer Help
https.c - frontends - front-ends for some sites (experiment)
Log
Files
Refs
README
LICENSE
---
https.c (4485B)
---
1 #include <sys/socket.h>
2 #include <sys/types.h>
3
4 #include <ctype.h>
5 #include <errno.h>
6 #include <netdb.h>
7 #include <stdarg.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <unistd.h>
14
15 #include <tls.h>
16
17 #define READ_BUF_SIZ 16384 /* read buffer in bytes */
18 #define MAX_RESPONSETIMEOUT 10 /* timeout in seconds */
19 #define MAX_RESPONSESIZ 4194304 /* max download size in bytes */
20
21 static void
22 die(const char *fmt, ...)
23 {
24 va_list ap;
25
26 va_start(ap, fmt);
27 vfprintf(stderr, fmt, ap);
28 va_end(ap);
29
30 exit(1);
31 }
32
33 /* TODO: use die or rename die to fatal */
34 void
35 fatal(const char *s)
36 {
37 fputs(s, stderr);
38 exit(1);
39 }
40
41 char *
42 readtls(struct tls *t)
43 {
44 char *buf;
45 size_t len = 0, size = 0;
46 ssize_t r;
47
48 /* always allocate an empty buffer */
49 if (!(buf = calloc(1, size + 1)))
50 die("calloc: %s\n", strerror(errno));
51
52 while (1) {
53 if (len + READ_BUF_SIZ + 1 > size) {
54 /* allocate size: common case is small textfiles…
55 size += READ_BUF_SIZ;
56 if (!(buf = realloc(buf, size + 1)))
57 die("realloc: %s\n", strerror(errno));
58 }
59 r = tls_read(t, &buf[len], READ_BUF_SIZ);
60 if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) {
61 continue;
62 } else if (r <= 0) {
63 break;
64 }
65 len += r;
66 buf[len] = '\0';
67 if (len > MAX_RESPONSESIZ)
68 die("response is too big: > %zu bytes\n", MAX_RE…
69 }
70 if (r == -1)
71 die("tls_read: %s\n", tls_error(t));
72
73 return buf;
74 }
75
76 int
77 edial(const char *host, const char *port)
78 {
79 struct addrinfo hints, *res, *res0;
80 int error, save_errno, s;
81 const char *cause = NULL;
82 struct timeval timeout;
83
84 memset(&hints, 0, sizeof(hints));
85 hints.ai_family = AF_UNSPEC;
86 hints.ai_socktype = SOCK_STREAM;
87 hints.ai_flags = AI_NUMERICSERV; /* numeric port only */
88 if ((error = getaddrinfo(host, port, &hints, &res0)))
89 die("%s: %s: %s:%s\n", __func__, gai_strerror(error), ho…
90 s = -1;
91 for (res = res0; res; res = res->ai_next) {
92 s = socket(res->ai_family, res->ai_socktype,
93 res->ai_protocol);
94 if (s == -1) {
95 cause = "socket";
96 continue;
97 }
98
99 timeout.tv_sec = MAX_RESPONSETIMEOUT;
100 timeout.tv_usec = 0;
101 if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, siz…
102 die("%s: setsockopt: %s\n", __func__, strerror(e…
103
104 timeout.tv_sec = MAX_RESPONSETIMEOUT;
105 timeout.tv_usec = 0;
106 if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, siz…
107 die("%s: setsockopt: %s\n", __func__, strerror(e…
108
109 if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
110 cause = "connect";
111 save_errno = errno;
112 close(s);
113 errno = save_errno;
114 s = -1;
115 continue;
116 }
117 break;
118 }
119 if (s == -1)
120 die("%s: %s: %s:%s\n", __func__, cause, host, port);
121 freeaddrinfo(res0);
122
123 return s;
124 }
125
126 char *
127 request(const char *host, const char *path, const char *headers)
128 {
129 struct tls *t;
130 char request[4096];
131 char *data;
132 size_t len;
133 ssize_t w;
134 int fd;
135
136 /* use HTTP/1.0, don't use HTTP/1.1 using ugly chunked-encoding …
137 snprintf(request, sizeof(request),
138 "GET %s HTTP/1.0\r\n"
139 "Host: %s\r\n"
140 "Accept-Language: en-US,en;q=0.5\r\n"
141 "Connection: close\r\n"
142 "%s"
143 "\r\n", path, host, headers);
144
145 if (tls_init() == -1)
146 die("tls_init\n");
147
148 if (!(t = tls_client()))
149 die("tls_client: %s\n", tls_error(t));
150
151 fd = edial(host, "443");
152
153 if (tls_connect_socket(t, fd, host) == -1)
154 die("tls_connect: %s\n", tls_error(t));
155
156 data = request;
157 len = strlen(data);
158 while (len > 0) {
159 w = tls_write(t, data, len);
160 if (w == TLS_WANT_POLLIN || w == TLS_WANT_POLLOUT)
161 continue;
162 else if (w == -1)
163 die("tls_write: %s\n", tls_error(t));
164 data += w;
165 len -= w;
166 }
167
168 data = readtls(t);
169
170 tls_close(t);
171 tls_free(t);
172
173 return data;
174 }
175
176 /* DEBUG */
177 char *
178 readfile(const char *file)
179 {
180 FILE *fp;
181 char *buf;
182 size_t n, len = 0, size = 0;
183
184 fp = fopen(file, "rb");
185 if (!fp)
186 die("fopen");
187 buf = calloc(1, size + 1); /* always allocate an empty buffer */
188 if (!buf)
189 die("calloc");
190 while (!feof(fp)) {
191 if (len + READ_BUF_SIZ + 1 > size) {
192 /* allocate size: common case is small textfiles…
193 size += READ_BUF_SIZ;
194 if (!(buf = realloc(buf, size + 1))) {
195 fprintf(stderr, "realloc: %s\n", strerro…
196 exit(1);
197 }
198 }
199 if (!(n = fread(&buf[len], 1, READ_BUF_SIZ, fp)))
200 break;
201 len += n;
202 buf[len] = '\0';
203 if (n != READ_BUF_SIZ)
204 break;
205 }
206 if (ferror(fp)) {
207 fprintf(stderr, "fread: file: %s: %s\n", file, strerror(…
208 exit(1);
209 }
210 fclose(fp);
211
212 return buf;
213 }
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.