ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/HttpConnector/HttpConnector.cpp
Revision: 353
Committed: 2004-06-03T17:29:49-07:00 (21 years ago) by Douglas Thrift
Original Path: trunk/HttpConnector/HttpConnector.cpp
File size: 9640 byte(s)
Log Message:
Meep!

File Contents

# User Rev Content
1 douglas 57 /*
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 Douglas Thrift 353 if (size == 0) break;
178     else if (byte != '\r' && byte != '\n')
179 douglas 57 {
180     line += byte;
181     }
182     }
183     while (byte != '\n');
184    
185 Douglas Thrift 353 cout << line << (size == 1 ? "\n" : "") << flush;
186 douglas 57
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     }