ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/HttpConnector/HttpConnector.cpp
Revision: 57
Committed: 2003-02-19T22:55:36-08:00 (22 years, 4 months ago) by douglas
File size: 9601 byte(s)
Log Message:
Initial revision

File Contents

# Content
1 /*
2 * HTTP Connector
3 *
4 * Douglas Thrift
5 *
6 * HttpConnector.cpp
7 */
8
9 #include <iostream>
10 #include <string>
11 #include <cstdlib>
12 #include <cstdio>
13 #include <cstring>
14
15 #ifndef _WIN32
16
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <netdb.h>
22 #include <sys/utsname.h>
23
24 #define INVALID_SOCKET -1
25 #define SOCKET_ERROR -1
26 typedef int SOCKET;
27
28 #else
29
30 #include <winsock2.h>
31 #include <windows.h>
32
33 #endif // _WIN32
34
35 using namespace std;
36
37 string program;
38
39 void error(const string prefix, bool host = false);
40 void death();
41 string platform();
42
43 int main(int argc, char* argv[])
44 {
45 SOCKET sock;
46 struct sockaddr_in address;
47 struct hostent* addressHost;
48 struct servent* addressServ;
49 string host = "localhost";
50 unsigned port = 80;
51 string serv = "http";
52 string path = "/";
53 bool get = true;
54
55 program = argv[0];
56
57 for (int index = 1; index < argc; index++)
58 {
59 string arg = argv[index];
60
61 switch (index)
62 {
63 case 1:
64 host = arg;
65 break;
66 case 2:
67 serv = arg;
68 break;
69 case 3:
70 path = arg;
71 break;
72 default:
73 get = (arg == "head") ? false : true;
74 break;
75 }
76 }
77
78 #ifdef _WIN32
79 WSADATA data;
80 if (WSAStartup(MAKEWORD(2, 0) != 0, &data))
81 {
82 error(program + ": WSAStartup()");
83 death();
84 }
85 #endif
86
87 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
88 {
89 error(program + ": Socket");
90 death();
91 }
92
93 address.sin_family = AF_INET;
94
95 if ((addressHost = gethostbyname(host.c_str())) == NULL)
96 {
97 error(program + ": Host: " + host, true);
98 death();
99 }
100
101 address.sin_addr = *((in_addr*)*addressHost->h_addr_list);
102
103 port = strtoul(serv.c_str(), 0, 0);
104
105 if (port == 0)
106 {
107 if ((addressServ = getservbyname(serv.c_str(), "tcp")) == NULL)
108 {
109 error(program + ": Service: " + serv);
110 death();
111 }
112
113 address.sin_port = addressServ->s_port;
114 port = ntohs(addressServ->s_port);
115 }
116 else
117 {
118 address.sin_port = htons(port);
119 }
120
121 if (connect(sock, (sockaddr*)&address, sizeof(sockaddr_in)) ==
122 SOCKET_ERROR)
123 {
124 error(program + ": Connect");
125 death();
126 }
127
128 char* buffer = new char[BUFSIZ + 1];
129
130 if (get)
131 {
132 sprintf(buffer, "GET %s HTTP/1.1\r\n", path.c_str());
133 send(sock, buffer, strlen(buffer), 0);
134 }
135 else
136 {
137 sprintf(buffer, "HEAD %s HTTP/1.1\r\n", path.c_str());
138 send(sock, buffer, strlen(buffer), 0);
139 }
140
141 sprintf(buffer, "Accept: text/html; text/plain\r\n");
142 send(sock, buffer, strlen(buffer), 0);
143
144 sprintf(buffer, "User-Agent: HttpConnector/1.1 (%s)\r\n",
145 platform().c_str());
146 send(sock, buffer, strlen(buffer), 0);
147
148 if (port == 80)
149 {
150 sprintf(buffer, "Host: %s\r\n", host.c_str());
151 send(sock, buffer, strlen(buffer), 0);
152 }
153 else
154 {
155 sprintf(buffer, "Host: %s:%u\r\n", host.c_str(), port);
156 send(sock, buffer, strlen(buffer), 0);
157 }
158 sprintf(buffer, "Connection: close\r\n");
159 send(sock, buffer, strlen(buffer), 0);
160 sprintf(buffer, "\r\n");
161 send(sock, buffer, strlen(buffer), 0);
162
163 delete [] buffer;
164
165 string line;
166
167 int size = 1;
168
169 while (size == 1)
170 {
171 char byte;
172
173 do
174 {
175 size = recv(sock, &byte, 1, 0);
176
177 if (byte != '\r' && byte != '\n')
178 {
179 line += byte;
180 }
181 }
182 while (byte != '\n');
183
184 cout << line << (size == 1 ? "\n" : "");
185
186 line.erase();
187 }
188
189 #ifdef _WIN32
190 closesocket(sock);
191 WSACleanup();
192 #else
193 close(sock);
194 #endif
195
196 return 0;
197 }
198
199 void error(const string prefix, bool host)
200 {
201 #ifdef _WIN32
202 string error;
203
204 switch (WSAGetLastError())
205 {
206 case WSAEACCES:
207 error = "Permission denied.";
208 break;
209 case WSAEADDRINUSE:
210 error = "Address already in use.";
211 break;
212 case WSAEADDRNOTAVAIL:
213 error = "Cannot assign requested address.";
214 break;
215 case WSAEAFNOSUPPORT:
216 error = "Address family not supported by protocol family.";
217 break;
218 case WSAEALREADY:
219 error = "Operation already in progress.";
220 break;
221 case WSAECONNABORTED:
222 error = "Software caused connection abort.";
223 break;
224 case WSAECONNREFUSED:
225 error = "Connection refused.";
226 break;
227 case WSAECONNRESET:
228 error = "Connection reset by peer.";
229 break;
230 case WSAEDESTADDRREQ:
231 error = "Destination address required.";
232 break;
233 case WSAEFAULT:
234 error = "Bad address.";
235 break;
236 case WSAEHOSTDOWN:
237 error = "Host is down.";
238 break;
239 case WSAEHOSTUNREACH:
240 error = "No route to host.";
241 break;
242 case WSAEINPROGRESS:
243 error = "Operation now in progress.";
244 break;
245 case WSAEINTR:
246 error = "Interrupted function call.";
247 break;
248 case WSAEINVAL:
249 error = "Invalid argument.";
250 break;
251 case WSAEISCONN:
252 error = "Socket is already connected.";
253 break;
254 case WSAEMFILE:
255 error = "Too many open files.";
256 break;
257 case WSAEMSGSIZE:
258 error = "Message too long.";
259 break;
260 case WSAENETDOWN:
261 error = "Network is down.";
262 break;
263 case WSAENETRESET:
264 error = "Network dropped connection on reset.";
265 break;
266 case WSAENETUNREACH:
267 error = "Network is unreachable.";
268 break;
269 case WSAENOBUFS:
270 error = "No buffer space available.";
271 break;
272 case WSAENOPROTOOPT:
273 error = "Bad protocol option.";
274 break;
275 case WSAENOTCONN:
276 error = "Socket is not connected.";
277 break;
278 case WSAENOTSOCK:
279 error = "Socket operation on non-socket.";
280 break;
281 case WSAEOPNOTSUPP:
282 error = "Operation not supported.";
283 break;
284 case WSAEPFNOSUPPORT:
285 error = "Protocol family not supported.";
286 break;
287 case WSAEPROCLIM:
288 error = "Too many processes.";
289 break;
290 case WSAEPROTONOSUPPORT:
291 error = "Protocol not supported.";
292 break;
293 case WSAEPROTOTYPE:
294 error = "Protocol wrong type for socket.";
295 break;
296 case WSAESHUTDOWN:
297 error = "Cannot send after socket shutdown.";
298 break;
299 case WSAESOCKTNOSUPPORT:
300 error = "Socket type not supported.";
301 break;
302 case WSAETIMEDOUT:
303 error = "Connection timed out.";
304 break;
305 case WSATYPE_NOT_FOUND:
306 error = "Class type not found.";
307 break;
308 case WSAEWOULDBLOCK:
309 error = "Resource temporarily unavailable.";
310 break;
311 case WSAHOST_NOT_FOUND:
312 error = "Host not found.";
313 break;
314 case WSA_INVALID_HANDLE:
315 error = "Specified event object handle is invalid.";
316 break;
317 case WSA_INVALID_PARAMETER:
318 error = "One or more parameters are invalid.";
319 break;
320 // case WSAINVALIDPROCTABLE:
321 // error = "Invalid procedure table from service provider.";
322 // break;
323 // case WSAINVALIDPROVIDER:
324 // error = "Invalid service provider version number.";
325 // break;
326 case WSA_IO_INCOMPLETE:
327 error = "Overlapped I/O event object not in signaled state.";
328 break;
329 case WSA_IO_PENDING:
330 error = "Overlapped operations will complete later.";
331 break;
332 case WSA_NOT_ENOUGH_MEMORY:
333 error = "Insufficient memory available.";
334 break;
335 case WSANOTINITIALISED:
336 error = "Successful WSAStartup not yet performed.";
337 break;
338 case WSANO_DATA:
339 error = "Valid name, no data record of requested type.";
340 break;
341 case WSANO_RECOVERY:
342 error = "This is a non-recoverable error.";
343 break;
344 // case WSAPROVIDERFAILEDINIT:
345 // error = "Unable to initialize a service provider.";
346 // break;
347 case WSASYSCALLFAILURE:
348 error = "System call failure.";
349 break;
350 case WSASYSNOTREADY:
351 error = "Network subsystem is unavailable.";
352 break;
353 case WSATRY_AGAIN:
354 error = "Non-authoritative host not found.";
355 break;
356 case WSAVERNOTSUPPORTED:
357 error = "WINSOCK.DLL version out of range.";
358 break;
359 case WSAEDISCON:
360 error = "Graceful shutdown in progress.";
361 break;
362 case WSA_OPERATION_ABORTED:
363 error = "Overlapped operation aborted.";
364 break;
365 default:
366 error = "Unknown error.";
367 break;
368 }
369
370 cerr << prefix << ": " << error << "\n";
371 #else
372 if (host)
373 {
374 herror(prefix.c_str());
375 }
376 else
377 {
378 perror(prefix.c_str());
379 }
380 #endif
381 }
382
383 void death()
384 {
385 #ifdef _WIN32
386 WSACleanup();
387 #endif
388 exit(1);
389 }
390
391 string platform()
392 {
393 string os;
394 string version;
395 string architecture;
396 string marketing;
397
398 #ifdef _WIN32
399 OSVERSIONINFO* computer = new OSVERSIONINFO;
400 computer->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
401 GetVersionEx(computer);
402
403 os = computer->dwPlatformId == VER_PLATFORM_WIN32_NT ? "Windows NT" :
404 "Windows";
405 unsigned major = computer->dwMajorVersion;
406 unsigned minor = computer->dwMinorVersion;
407
408 delete computer;
409
410 SYSTEM_INFO* system = new SYSTEM_INFO;
411 GetSystemInfo(system);
412
413 switch (system->wProcessorArchitecture)
414 {
415 case PROCESSOR_ARCHITECTURE_INTEL:
416 architecture = "ix86";
417 break;
418 case PROCESSOR_ARCHITECTURE_MIPS:
419 architecture = "mips";
420 break;
421 case PROCESSOR_ARCHITECTURE_ALPHA:
422 architecture = "alpha";
423 break;
424 case PROCESSOR_ARCHITECTURE_PPC:
425 architecture = "ppc";
426 break;
427 case PROCESSOR_ARCHITECTURE_IA64:
428 architecture = "ia64";
429 break;
430 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
431 architecture = "ix86_on_win64";
432 break;
433 case PROCESSOR_ARCHITECTURE_AMD64:
434 architecture = "amd64";
435 break;
436 default:
437 architecture = "unknown";
438 break;
439 }
440
441 char* cversion = new char[1024];
442 sprintf(cversion, "%u.%u", major, minor);
443 version = cversion;
444
445 delete [] cversion;
446
447 if (major == 4 && minor <= 3 && os != "Windows NT")
448 {
449 marketing = " [Windows 95]";
450 }
451 else if (major == 4 && minor == 10 && os != "Windows NT")
452 {
453 marketing = " [Windows 98]";
454 }
455 else if (major == 5 && minor == 0 && os == "Windows NT")
456 {
457 marketing = " [Windows 2000]";
458 }
459 else if (major == 4 && minor == 90 && os != "Windows NT")
460 {
461 marketing = " [Windows ME]";
462 }
463 else if (major == 5 && minor == 1 && os == "Windows NT")
464 {
465 marketing = " [Windows XP]";
466 }
467 else if (major == 5 && minor == 2 && os == "Windows NT")
468 {
469 marketing = " [Windows .NET Server]";
470 }
471 #else // _WIN32
472 struct utsname* computer = new struct utsname;
473 uname(computer);
474
475 os = computer->sysname;
476 version = computer->release;
477 architecture = computer->machine;
478
479 delete computer;
480 #endif // _WIN32
481 return os + " " + version + marketing + " " + architecture;
482 }