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

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     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     }