ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/HttpConnector/HttpConnector.cpp
Revision: 368
Committed: 2008-08-23T02:44:00-07:00 (16 years, 9 months ago) by douglas
File size: 9640 byte(s)
Log Message:
Rearranged everything else.

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 (size == 0) break;
178 else if (byte != '\r' && byte != '\n')
179 {
180 line += byte;
181 }
182 }
183 while (byte != '\n');
184
185 cout << line << (size == 1 ? "\n" : "") << flush;
186
187 line.erase();
188 }
189
190 #ifdef _WIN32
191 closesocket(sock);
192 WSACleanup();
193 #else
194 close(sock);
195 #endif
196
197 return 0;
198 }
199
200 void error(const string prefix, bool host)
201 {
202 #ifdef _WIN32
203 string error;
204
205 switch (WSAGetLastError())
206 {
207 case WSAEACCES:
208 error = "Permission denied.";
209 break;
210 case WSAEADDRINUSE:
211 error = "Address already in use.";
212 break;
213 case WSAEADDRNOTAVAIL:
214 error = "Cannot assign requested address.";
215 break;
216 case WSAEAFNOSUPPORT:
217 error = "Address family not supported by protocol family.";
218 break;
219 case WSAEALREADY:
220 error = "Operation already in progress.";
221 break;
222 case WSAECONNABORTED:
223 error = "Software caused connection abort.";
224 break;
225 case WSAECONNREFUSED:
226 error = "Connection refused.";
227 break;
228 case WSAECONNRESET:
229 error = "Connection reset by peer.";
230 break;
231 case WSAEDESTADDRREQ:
232 error = "Destination address required.";
233 break;
234 case WSAEFAULT:
235 error = "Bad address.";
236 break;
237 case WSAEHOSTDOWN:
238 error = "Host is down.";
239 break;
240 case WSAEHOSTUNREACH:
241 error = "No route to host.";
242 break;
243 case WSAEINPROGRESS:
244 error = "Operation now in progress.";
245 break;
246 case WSAEINTR:
247 error = "Interrupted function call.";
248 break;
249 case WSAEINVAL:
250 error = "Invalid argument.";
251 break;
252 case WSAEISCONN:
253 error = "Socket is already connected.";
254 break;
255 case WSAEMFILE:
256 error = "Too many open files.";
257 break;
258 case WSAEMSGSIZE:
259 error = "Message too long.";
260 break;
261 case WSAENETDOWN:
262 error = "Network is down.";
263 break;
264 case WSAENETRESET:
265 error = "Network dropped connection on reset.";
266 break;
267 case WSAENETUNREACH:
268 error = "Network is unreachable.";
269 break;
270 case WSAENOBUFS:
271 error = "No buffer space available.";
272 break;
273 case WSAENOPROTOOPT:
274 error = "Bad protocol option.";
275 break;
276 case WSAENOTCONN:
277 error = "Socket is not connected.";
278 break;
279 case WSAENOTSOCK:
280 error = "Socket operation on non-socket.";
281 break;
282 case WSAEOPNOTSUPP:
283 error = "Operation not supported.";
284 break;
285 case WSAEPFNOSUPPORT:
286 error = "Protocol family not supported.";
287 break;
288 case WSAEPROCLIM:
289 error = "Too many processes.";
290 break;
291 case WSAEPROTONOSUPPORT:
292 error = "Protocol not supported.";
293 break;
294 case WSAEPROTOTYPE:
295 error = "Protocol wrong type for socket.";
296 break;
297 case WSAESHUTDOWN:
298 error = "Cannot send after socket shutdown.";
299 break;
300 case WSAESOCKTNOSUPPORT:
301 error = "Socket type not supported.";
302 break;
303 case WSAETIMEDOUT:
304 error = "Connection timed out.";
305 break;
306 case WSATYPE_NOT_FOUND:
307 error = "Class type not found.";
308 break;
309 case WSAEWOULDBLOCK:
310 error = "Resource temporarily unavailable.";
311 break;
312 case WSAHOST_NOT_FOUND:
313 error = "Host not found.";
314 break;
315 case WSA_INVALID_HANDLE:
316 error = "Specified event object handle is invalid.";
317 break;
318 case WSA_INVALID_PARAMETER:
319 error = "One or more parameters are invalid.";
320 break;
321 // case WSAINVALIDPROCTABLE:
322 // error = "Invalid procedure table from service provider.";
323 // break;
324 // case WSAINVALIDPROVIDER:
325 // error = "Invalid service provider version number.";
326 // break;
327 case WSA_IO_INCOMPLETE:
328 error = "Overlapped I/O event object not in signaled state.";
329 break;
330 case WSA_IO_PENDING:
331 error = "Overlapped operations will complete later.";
332 break;
333 case WSA_NOT_ENOUGH_MEMORY:
334 error = "Insufficient memory available.";
335 break;
336 case WSANOTINITIALISED:
337 error = "Successful WSAStartup not yet performed.";
338 break;
339 case WSANO_DATA:
340 error = "Valid name, no data record of requested type.";
341 break;
342 case WSANO_RECOVERY:
343 error = "This is a non-recoverable error.";
344 break;
345 // case WSAPROVIDERFAILEDINIT:
346 // error = "Unable to initialize a service provider.";
347 // break;
348 case WSASYSCALLFAILURE:
349 error = "System call failure.";
350 break;
351 case WSASYSNOTREADY:
352 error = "Network subsystem is unavailable.";
353 break;
354 case WSATRY_AGAIN:
355 error = "Non-authoritative host not found.";
356 break;
357 case WSAVERNOTSUPPORTED:
358 error = "WINSOCK.DLL version out of range.";
359 break;
360 case WSAEDISCON:
361 error = "Graceful shutdown in progress.";
362 break;
363 case WSA_OPERATION_ABORTED:
364 error = "Overlapped operation aborted.";
365 break;
366 default:
367 error = "Unknown error.";
368 break;
369 }
370
371 cerr << prefix << ": " << error << "\n";
372 #else
373 if (host)
374 {
375 herror(prefix.c_str());
376 }
377 else
378 {
379 perror(prefix.c_str());
380 }
381 #endif
382 }
383
384 void death()
385 {
386 #ifdef _WIN32
387 WSACleanup();
388 #endif
389 exit(1);
390 }
391
392 string platform()
393 {
394 string os;
395 string version;
396 string architecture;
397 string marketing;
398
399 #ifdef _WIN32
400 OSVERSIONINFO* computer = new OSVERSIONINFO;
401 computer->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
402 GetVersionEx(computer);
403
404 os = computer->dwPlatformId == VER_PLATFORM_WIN32_NT ? "Windows NT" :
405 "Windows";
406 unsigned major = computer->dwMajorVersion;
407 unsigned minor = computer->dwMinorVersion;
408
409 delete computer;
410
411 SYSTEM_INFO* system = new SYSTEM_INFO;
412 GetSystemInfo(system);
413
414 switch (system->wProcessorArchitecture)
415 {
416 case PROCESSOR_ARCHITECTURE_INTEL:
417 architecture = "ix86";
418 break;
419 case PROCESSOR_ARCHITECTURE_MIPS:
420 architecture = "mips";
421 break;
422 case PROCESSOR_ARCHITECTURE_ALPHA:
423 architecture = "alpha";
424 break;
425 case PROCESSOR_ARCHITECTURE_PPC:
426 architecture = "ppc";
427 break;
428 case PROCESSOR_ARCHITECTURE_IA64:
429 architecture = "ia64";
430 break;
431 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
432 architecture = "ix86_on_win64";
433 break;
434 case PROCESSOR_ARCHITECTURE_AMD64:
435 architecture = "amd64";
436 break;
437 default:
438 architecture = "unknown";
439 break;
440 }
441
442 char* cversion = new char[1024];
443 sprintf(cversion, "%u.%u", major, minor);
444 version = cversion;
445
446 delete [] cversion;
447
448 if (major == 4 && minor <= 3 && os != "Windows NT")
449 {
450 marketing = " [Windows 95]";
451 }
452 else if (major == 4 && minor == 10 && os != "Windows NT")
453 {
454 marketing = " [Windows 98]";
455 }
456 else if (major == 5 && minor == 0 && os == "Windows NT")
457 {
458 marketing = " [Windows 2000]";
459 }
460 else if (major == 4 && minor == 90 && os != "Windows NT")
461 {
462 marketing = " [Windows ME]";
463 }
464 else if (major == 5 && minor == 1 && os == "Windows NT")
465 {
466 marketing = " [Windows XP]";
467 }
468 else if (major == 5 && minor == 2 && os == "Windows NT")
469 {
470 marketing = " [Windows .NET Server]";
471 }
472 #else // _WIN32
473 struct utsname* computer = new struct utsname;
474 uname(computer);
475
476 os = computer->sysname;
477 version = computer->release;
478 architecture = computer->machine;
479
480 delete computer;
481 #endif // _WIN32
482 return os + " " + version + marketing + " " + architecture;
483 }