ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/Search/HttpHandler.cpp
(Generate patch)

Comparing trunk/Search/HttpHandler.cpp (file contents):
Revision 7 by douglas, 2002-12-04T22:05:30-08:00 vs.
Revision 209 by douglas, 2003-07-18T00:26:41-07:00

# Line 1 | Line 1
1   /* ============================================================================
2   * Douglas Thrift's Search Engine License
3   *
4 < * Copyright (C) 2002, Douglas Thrift. All Rights Reserved.
4 > * Copyright (C) 2002-2003, Douglas Thrift. All Rights Reserved.
5   * Redistribution and use in source and binary forms, with or without
6   * modification, are permitted provided that the following conditions are met:
7   *
# Line 46 | Line 46
46   //
47   // Douglas Thrift
48   //
49 < // HttpHandler.cpp
49 > // $Id: HttpHandler.cpp,v 1.21 2003/07/18 07:26:41 douglas Exp $
50  
51   #include "HttpHandler.h"
52  
53 < #ifdef _WIN32
54 < #define PATH_SEPARATOR "\\"
55 < #define ENV_SEPARATOR ';'
56 < #else
57 < #define PATH_SEPARATOR "/"
58 < #define ENV_SEPARATOR ':'
53 > // Lovely C Sockets!
54 > #ifndef _WIN32
55 > // BSD Sockets
56 > #include <unistd.h>
57 > #include <sys/types.h>
58 > #include <sys/socket.h>
59 > #include <netinet/in.h>
60 > #include <netdb.h>
61 >
62 > #define INVALID_SOCKET -1
63 > #define SOCKET_ERROR -1
64 >
65 > inline int closesocket(SOCKET s) { return close(s); }
66   #endif
67  
68   HttpHandler::HttpHandler()
69   {
70 <        string arguments = "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/Strin"
64 <                + string("g;Ljava/lang/String;)Ljava/lang/String;");
65 <
66 <        begin = 0;
70 >        buffer = new char[BUFSIZ + 1];
71  
72 < //      setJarPath();
72 > #ifdef _WIN32
73 >        if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
74 >        {
75 >                error(program + ": WSAStartup");
76 >                exit(1);
77 >        }
78 > #endif // _WIN32
79  
80 < //      options[0].optionString = jarPath;
81 < //      memset(&vm_args, 0, sizeof (vm_args));
82 < //      vm_args.version = JNI_VERSION_1_4;
83 < //      vm_args.nOptions = 1;
84 < //      vm_args.options = options;
85 <
76 < //      status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
77 <
78 < //      if (status != JNI_ERR)
79 < //      {
80 < //              cls = env->FindClass("HttpConnector");
81 <
82 < //              if (cls != 0)
83 < //              {
84 < //                      mid = env->GetStaticMethodID(cls, "connect", arguments.c_str());
85 < //              }
86 < //      }
80 >        binary = false;
81 >        length = 0;
82 >        chunked = false;
83 > #ifdef _OpenSSL_
84 >        tls = false;
85 > #endif
86   }
87  
88   HttpHandler::~HttpHandler()
89   {
90 < //      if (status != JNI_ERR)
92 < //      {
93 < //              jvm->DestroyJavaVM();
94 < //      }
90 >        delete [] buffer;
91  
92 < //      delete [] jarPath;
92 > #ifdef _WIN32
93 >        WSACleanup();
94 > #endif // _WIN32
95   }
96  
97 < bool HttpHandler::connect(URL& url)
97 > bool HttpHandler::handle(URL &url, const string referer, bool head)
98   {
99          bool answer = false;
100  
101 < //      if (status != JNI_ERR)
102 < //      {
103 < //              if (cls != 0)
104 < //              {
105 < //                      if (mid != 0)
106 < //                      {
107 < //                              jstring addressJ = env->NewStringUTF(url.getAddress().c_str());
108 < //                              jint portJ = url.getPort();
111 < //                              jstring pathJ = env->NewStringUTF(url.getPath().c_str());
112 < //                              jstring programNameJ = env->NewStringUTF(programName.c_str());
113 < //                              jstring programVersionJ =
114 < //                                      env->NewStringUTF(programVersion.c_str());
115 <
116 < //                              jstring pageJ = (jstring)env->CallStaticObjectMethod(cls, mid,
117 < //                                      addressJ, portJ, pathJ, programNameJ, programVersionJ);
118 <
119 < //                              const char* pageC = env->GetStringUTFChars(pageJ, 0);
120 < //                              page = pageC;
121 < //                              env->ReleaseStringUTFChars(pageJ, pageC);
122 <
123 < //                              if (page != "unknown host\n" && page != "io exception\n" &&
124 < //                                      page != "bad headers\n") answer = true;
125 < //                      }
126 < //              }
127 < //      }
101 >        if ((http = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
102 >        {
103 >                error(program + ": Socket");
104 >                exit(1);
105 >        }
106 >
107 >        sockaddr_in address;
108 >        hostent* host;
109  
110 <        return answer;
130 < }
110 >        address.sin_family = AF_INET;
111  
112 < HttpHandler& HttpHandler::getline(string& line, char endline)
113 < {
114 <        int end = page.find(endline, begin);
115 <        int newline = page.find('\n', begin);
112 >        if ((host = gethostbyname(url.getAddress().c_str())) == NULL)
113 >        {
114 >                error(program + ": Host: " + url.getAddress(), true);
115 >                return answer;
116 >        }
117  
118 <        if (newline < end || end == string::npos)
118 >        address.sin_addr = *((in_addr*)*host->h_addr_list);
119 >        address.sin_port = htons(url.getPort());
120 >
121 >        if (connect(http, (sockaddr*)&address, sizeof(sockaddr_in)) ==
122 >                SOCKET_ERROR)
123          {
124 <                end = newline;
124 >                error(program + ": Connect");
125 >                return answer;
126          }
127  
128 <        line = page.substr(begin, end - begin);
128 > #ifdef _OpenSSL_
129 >        if (url.getTls())
130 >        {
131 >                tls = true;
132 >
133 >                if (!starttls()) return answer;
134 >        }
135 > #endif
136  
137 <        if (end == string::npos)
137 >        if (head)
138          {
139 <                begin = end;
139 >                putline("HEAD " + url.getPath() + " HTTP/1.1");
140          }
141          else
142          {
143 <                begin = end + 1;
143 >                putline("GET " + url.getPath() + " HTTP/1.1");
144          }
145  
146 <        return *this;
147 < }
146 >        putline("Accept: text/html; text/plain");
147 > #ifndef _OpenSSL_
148 >        putline("User-Agent: " + agent(true) + ' ' + platform());
149  
150 < bool HttpHandler::good()
151 < {
152 <        bool answer = true;
150 >        if (url.getPort() == 80)
151 > #else
152 >        putline("User-Agent: " + agent(true) + ' ' + platform() + ' '
153 >                + openssl(true));
154 >
155 >        if (url.getPort() == 80 && tls || url.getPort() == 443 && tls)
156 > #endif
157 >        {
158 >                putline("Host: " + url.getAddress());
159 >        }
160 >        else
161 >        {
162 >                ostringstream port;
163 >
164 >                port << url.getPort();
165 >
166 >                putline("Host: " + url.getAddress() + ':' + port.str());
167 >        }
168 >
169 >        if (referer != "")
170 >        {
171 >                putline("Referer: " + referer);
172 >        }
173 >
174 >        putline("Connection: close");
175 >        putline();
176 >
177 >        code response;
178 >        string line;
179 >
180 >        do
181 >        {
182 >                line = getline();
183 >
184 >                if (line.find("HTTP/") != 0)
185 >                {
186 >                        return answer;
187 >                }
188 >
189 >                unsigned dot = line.find('.');
190 >                unsigned space = line.find(' ');
191 >
192 >                unsigned major = strtoul(line.substr(5, dot - 5).c_str(), 0, 10);
193 >                unsigned minor = strtoul(line.substr(dot + 1, space - dot - 1).c_str(),
194 >                        0, 10);
195 >
196 >                if (major > 1)
197 >                {
198 >                        cerr << program << ": Potentially Incompatible Server: HTTP/" <<
199 >                                major << "." << minor << "\n";
200 >
201 >                        return answer;
202 >                }
203 >
204 >                response = code(strtoul(line.substr(space + 1).c_str(), 0, 10));
205 >
206 >                if (response < ok) do line = getline(); while (line != "");
207 >        }
208 >        while (response < ok);
209  
210 <        if (begin >= page.length())
210 >        do
211          {
212 <                answer = false;
212 >                line = getline();
213 >
214 >                if (line != "")
215 >                {
216 >                        unsigned colon = line.find(':');
217 >
218 >                        string field = line.substr(0, colon);
219 >                        string value = line.substr(colon + 1);
220 >
221 >                        while (isspace(value[0])) value.erase(0, 1);
222 >
223 >                        if (field == "Content-Type")
224 >                        {
225 >                                type = value;
226 >                        }
227 >                        else if (field == "Content-Length")
228 >                        {
229 >                                length = strtoul(value.c_str(), 0, 10);
230 >                        }
231 >                        else if (field == "Location")
232 >                        {
233 >                                location = value;
234 >                        }
235 >                        else if (field == "Transfer-Encoding")
236 >                        {
237 >                                chunked = value == "chunked";
238 >                        }
239 >                }
240          }
241 <        else if (begin == string::npos)
241 >        while (line != "");
242 >
243 >        switch (response)
244          {
245 <                answer = false;
245 >        case ok:
246 >                if (debug) cerr << "response = " << response << "\n";
247 >                answer = true;
248 >                break;
249 >        case choices:
250 >        case moved:
251 >        case found:
252 >                if (debug) cerr << "response = " << response << "\n"
253 >                        << "location = " << location << "\n";
254 >                location = getLink(location, url);
255 >                break;
256 >        case notfound:
257 >        case internal:
258 >                if (debug) cerr << "response = " << response << "\n";
259 >                break;
260 >        default:
261 >                if (debug) cerr << "response = " << response << "\n";
262 >                if (response <= 299)
263 >                {
264 >                        answer = true;
265 >                }
266 >                else if (response <= 399)
267 >                {
268 >                        location = getLink(location, url);
269 >                }
270 >                break;
271          }
272  
273 +        if (!head && answer) populate();
274 +
275          return answer;
276   }
277  
278   void HttpHandler::clear()
279   {
280 <        begin = 0;
281 <        page = "";
280 >        if (tls)
281 >        {
282 >                SSL_shutdown(ssl);
283 >                SSL_free(ssl);
284 >                SSL_CTX_free(ctx);
285 >        }
286 >
287 >        closesocket(http);
288 >
289 >        type = "";
290 >        length = 0;
291 >        location = "";
292 >        page.clear();
293 >        page.str("");
294 >        chunked = false;
295 > #ifdef _OpenSSL_
296 >        tls = false;
297 > #endif
298   }
299  
300 < /*void HttpHandler::setJarPath()
300 > void HttpHandler::populate()
301   {
302 <        const string jarFile = "HttpConnector.jar";
181 <        string jarFilePath = jarFile;
182 <
183 <        ifstream fin(jarFilePath.c_str());
184 <        if (!fin.is_open())
302 >        if (!chunked)
303          {
304 <                unsigned end = program.rfind(PATH_SEPARATOR);
305 <                if (end != string::npos)
304 >                unsigned left = length;
305 >
306 >                while (left > 0)
307                  {
308 <                        string path = program.substr(0, end);
308 >                        memset(buffer, 0, BUFSIZ + 1);
309  
310 <                        jarFilePath = path + PATH_SEPARATOR + jarFile;
310 >                        unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
311 >                        long received;
312  
313 <                        fin.open(jarFilePath.c_str());
194 <                        if (!fin.is_open())
313 >                        while (true)
314                          {
315 <                                cerr << program << ": Could not find required file: "
316 <                                        << jarFile << "\n";
317 <                                exit(1);
318 <                        }
319 <                        else
320 <                        {
321 <                                fin.close();
315 > #ifndef _OpenSSL_
316 >                                if ((received = recv(http, buffer, bytes, 0)) == SOCKET_ERROR)
317 >                                {
318 >                                        error(program + ": Recv");
319 >                                        exit(1);
320 >                                }
321 > #else
322 >                                if ((received = !tls ? recv(http, buffer, bytes, 0) :
323 >                                        SSL_read(ssl, buffer, bytes)) <= 0)
324 >                                {
325 >                                        !tls ? error(program + ": Recv") : error(program +
326 >                                                ": SSL Read", int(received));
327 >                                }
328 > #endif
329 >                                else if (received != bytes)
330 >                                {
331 >                                        left -= received;
332 >                                        page << buffer;
333 >
334 >                                        memset(buffer, 0, BUFSIZ + 1);
335 >
336 >                                        bytes -= received;
337 >                                }
338 >                                else
339 >                                {
340 >                                        break;
341 >                                }
342                          }
343 +
344 +                        page << buffer;
345 +                        left -= bytes;
346                  }
347 <                else
347 >        }
348 >        else
349 >        {
350 >                unsigned chunk;
351 >
352 >                do
353                  {
354 <                        string envPath = getenv("PATH");
354 >                        chunk = strtoul(getline().c_str(), 0, 16);
355  
356 <                        if (debug) cerr << "envPath = " << envPath << "\n";
356 >                        unsigned left = chunk;
357  
358 <                        unsigned begin = 0;
212 <                        do
358 >                        while (left > 0)
359                          {
360 <                                unsigned end = envPath.find(ENV_SEPARATOR, begin);
215 <                                string path = envPath.substr(begin, end);
360 >                                memset(buffer, 0, BUFSIZ + 1);
361  
362 <                                if (debug) cerr << "path = " << path << "\n";
362 >                                unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
363 >                                long received;
364  
365 <                                jarFilePath = path + PATH_SEPARATOR + jarFile;
220 <
221 <                                fin.open(jarFilePath.c_str());
222 <                                if (fin.is_open())
365 >                                while (true)
366                                  {
367 <                                        fin.close();
368 <                                        break;
367 > #ifndef _OpenSSL_
368 >                                        if ((received = recv(http, buffer, bytes, 0)) ==
369 >                                                SOCKET_ERROR)
370 >                                        {
371 >                                                error(program + ": Recv");
372 >                                                exit(1);
373 >                                        }
374 > #else
375 >                                        if ((received = !tls ? recv(http, buffer, bytes, 0) :
376 >                                                SSL_read(ssl, buffer, bytes)) <= 0)
377 >                                        {
378 >                                                !tls ? error(program + ": Recv") : error(program +
379 >                                                        ": SSL Read", int(received));
380 >                                                exit(1);
381 >                                        }
382 > #endif
383 >                                        else if (received != bytes)
384 >                                        {
385 >                                                left -= received;
386 >                                                page << buffer;
387 >
388 >                                                memset(buffer, 0, BUFSIZ + 1);
389 >
390 >                                                bytes -= received;
391 >                                        }
392 >                                        else
393 >                                        {
394 >                                                break;
395 >                                        }
396                                  }
397  
398 <                                begin = end != string::npos ? end + 1 : string::npos;
398 >                                page << buffer;
399 >                                left -= bytes;
400                          }
230                        while (begin < envPath.length());
401  
402 <                        if (begin == string::npos)
402 >                        getline();
403 >                        length += chunk;
404 >                }
405 >                while (chunk > 0);
406 >        }
407 >
408 >        if (!binary)
409 >        {
410 >                string page = this->page.str();
411 >
412 >                for (unsigned index = 0; index < page.length(); index++)
413 >                {
414 >                        if (page[index] == '\r' && (index + 1 < page.length()) ? page[index +
415 >                                1] == '\n' : false)
416 >                        {
417 >                                page.erase(index, 1);
418 >                        }
419 >                        else if (page[index] == '\r')
420                          {
421 <                                cerr << program << ": Could not find required file: "
235 <                                        << jarFile << "\n";
236 <                                exit(1);
421 >                                page[index] = '\n';
422                          }
423                  }
424 +
425 +                this->page.str(page);
426 +        }
427 + }
428 +
429 + void HttpHandler::putline(const string line)
430 + {
431 +        sprintf(buffer, "%s\r\n", line.c_str());
432 +
433 + #ifndef _OpenSSL_
434 +        if (send(http, buffer, strlen(buffer), 0) == SOCKET_ERROR)
435 +        {
436 +                error(program + ": Send");
437 +                exit(1);
438 +        }
439 + #else
440 +        if (!tls)
441 +        {
442 +                if (send(http, buffer, strlen(buffer), 0) == SOCKET_ERROR)
443 +                {
444 +                        error(program + ": Send");
445 +                        exit(1);
446 +                }
447          }
448          else
449          {
450 <                fin.close();
450 >                int number;
451 >
452 >                if ((number = SSL_write(ssl, buffer, strlen(buffer))) <= 0)
453 >                {
454 >                        error(program + ": SSL Write", number);
455 >                        exit(1);
456 >                }
457          }
458 + #endif
459 + }
460 +
461 + string HttpHandler::getline()
462 + {
463 +        string line;
464 +        char byte;
465  
466 <        string jarPath = "-Djava.class.path=" + jarFilePath;
466 >        do
467 >        {
468 > #ifndef _OpenSSL_
469 >                if (recv(http, &byte, 1, 0) == SOCKET_ERROR)
470 >                {
471 >                        error(program + ": Recv");
472 >                }
473 > #else
474 >                if (!tls)
475 >                {
476 >                        if (recv(http, &byte, 1, 0) == SOCKET_ERROR)
477 >                        {
478 >                                error(program + ": Recv");
479 >                        }
480 >                }
481 >                else
482 >                {
483 >                        int number;
484  
485 < //      this->jarPath = new char[jarPath.length()];
486 < //      strcpy(this->jarPath, jarPath.c_str());
487 < }*/
485 >                        if ((number = SSL_read(ssl, &byte, 1)) <= 0)
486 >                        {
487 >                                error(program + ": SSL Read", number);
488 >                        }
489 >                }
490 > #endif
491 >
492 >                if (byte != '\r' && byte != '\n')
493 >                {
494 >                        line += byte;
495 >                }
496 >        }
497 >        while (byte != '\n');
498 >
499 >        return line;
500 > }
501 >
502 > void HttpHandler::error(const string& prefix, bool host)
503 > {
504 > #ifdef _WIN32
505 >        string error;
506 >
507 >        switch (WSAGetLastError())
508 >        {
509 >        case WSAEACCES:
510 >                error = "Permission denied";
511 >                break;
512 >        case WSAEADDRINUSE:
513 >                error = "Address already in use";
514 >                break;
515 >        case WSAEADDRNOTAVAIL:
516 >                error = "Cannot assign requested address";
517 >                break;
518 >        case WSAEAFNOSUPPORT:
519 >                error = "Address family not supported by protocol family";
520 >                break;
521 >        case WSAEALREADY:
522 >                error = "Operation already in progress";
523 >                break;
524 >        case WSAECONNABORTED:
525 >                error = "Software caused connection abort";
526 >                break;
527 >        case WSAECONNREFUSED:
528 >                error = "Connection refused";
529 >                break;
530 >        case WSAECONNRESET:
531 >                error = "Connection reset by peer";
532 >                break;
533 >        case WSAEDESTADDRREQ:
534 >                error = "Destination address required";
535 >                break;
536 >        case WSAEFAULT:
537 >                error = "Bad address";
538 >                break;
539 >        case WSAEHOSTDOWN:
540 >                error = "Host is down";
541 >                break;
542 >        case WSAEHOSTUNREACH:
543 >                error = "No route to host";
544 >                break;
545 >        case WSAEINPROGRESS:
546 >                error = "Operation now in progress";
547 >                break;
548 >        case WSAEINTR:
549 >                error = "Interrupted function call";
550 >                break;
551 >        case WSAEINVAL:
552 >                error = "Invalid argument";
553 >                break;
554 >        case WSAEISCONN:
555 >                error = "Socket is already connected";
556 >                break;
557 >        case WSAEMFILE:
558 >                error = "Too many open files";
559 >                break;
560 >        case WSAEMSGSIZE:
561 >                error = "Message too long";
562 >                break;
563 >        case WSAENETDOWN:
564 >                error = "Network is down";
565 >                break;
566 >        case WSAENETRESET:
567 >                error = "Network dropped connection on reset";
568 >                break;
569 >        case WSAENETUNREACH:
570 >                error = "Network is unreachable";
571 >                break;
572 >        case WSAENOBUFS:
573 >                error = "No buffer space available";
574 >                break;
575 >        case WSAENOPROTOOPT:
576 >                error = "Bad protocol option";
577 >                break;
578 >        case WSAENOTCONN:
579 >                error = "Socket is not connected";
580 >                break;
581 >        case WSAENOTSOCK:
582 >                error = "Socket operation on non-socket";
583 >                break;
584 >        case WSAEOPNOTSUPP:
585 >                error = "Operation not supported";
586 >                break;
587 >        case WSAEPFNOSUPPORT:
588 >                error = "Protocol family not supported";
589 >                break;
590 >        case WSAEPROCLIM:
591 >                error = "Too many processes";
592 >                break;
593 >        case WSAEPROTONOSUPPORT:
594 >                error = "Protocol not supported";
595 >                break;
596 >        case WSAEPROTOTYPE:
597 >                error = "Protocol wrong type for socket";
598 >                break;
599 >        case WSAESHUTDOWN:
600 >                error = "Cannot send after socket shutdown";
601 >                break;
602 >        case WSAESOCKTNOSUPPORT:
603 >                error = "Socket type not supported";
604 >                break;
605 >        case WSAETIMEDOUT:
606 >                error = "Connection timed out";
607 >                break;
608 >        case WSATYPE_NOT_FOUND:
609 >                error = "Class type not found";
610 >                break;
611 >        case WSAEWOULDBLOCK:
612 >                error = "Resource temporarily unavailable";
613 >                break;
614 >        case WSAHOST_NOT_FOUND:
615 >                error = "Host not found";
616 >                break;
617 >        case WSA_INVALID_HANDLE:
618 >                error = "Specified event object handle is invalid";
619 >                break;
620 >        case WSA_INVALID_PARAMETER:
621 >                error = "One or more parameters are invalid";
622 >                break;
623 > //      case WSAINVALIDPROCTABLE:
624 > //              error = "Invalid procedure table from service provider";
625 > //              break;
626 > //      case WSAINVALIDPROVIDER:
627 > //              error = "Invalid service provider version number";
628 > //              break;
629 >        case WSA_IO_INCOMPLETE:
630 >                error = "Overlapped I/O event object not in signaled state";
631 >                break;
632 >        case WSA_IO_PENDING:
633 >                error = "Overlapped operations will complete later";
634 >                break;
635 >        case WSA_NOT_ENOUGH_MEMORY:
636 >                error = "Insufficient memory available";
637 >                break;
638 >        case WSANOTINITIALISED:
639 >                error = "Successful WSAStartup not yet performed";
640 >                break;
641 >        case WSANO_DATA:
642 >                error = "Valid name, no data record of requested type";
643 >                break;
644 >        case WSANO_RECOVERY:
645 >                error = "This is a non-recoverable error";
646 >                break;
647 > //      case WSAPROVIDERFAILEDINIT:
648 > //              error = "Unable to initialize a service provider";
649 > //              break;
650 >        case WSASYSCALLFAILURE:
651 >                error = "System call failure";
652 >                break;
653 >        case WSASYSNOTREADY:
654 >                error = "Network subsystem is unavailable";
655 >                break;
656 >        case WSATRY_AGAIN:
657 >                error = "Non-authoritative host not found";
658 >                break;
659 >        case WSAVERNOTSUPPORTED:
660 >                error = "WINSOCK.DLL version out of range";
661 >                break;
662 >        case WSAEDISCON:
663 >                error = "Graceful shutdown in progress";
664 >                break;
665 >        case WSA_OPERATION_ABORTED:
666 >                error = "Overlapped operation aborted";
667 >                break;
668 >        default:
669 >                error = "Unknown error";
670 >                break;
671 >        }
672 >
673 >        cerr << prefix << ": " << error << "\n";
674 > #else
675 >        if (host)
676 >        {
677 >                string error;
678 >
679 >                switch (h_errno)
680 >                {
681 >                case HOST_NOT_FOUND:
682 >                        error = "Unknown host";
683 >                        break;
684 >                case TRY_AGAIN:
685 >                        error = "Host name lookup failure";
686 >                        break;
687 >                case NO_RECOVERY:
688 >                        error = "Unknown server error";
689 >                        break;
690 >                case NO_DATA:
691 >                        error = "No address associated with name";
692 >                        break;
693 >                default:
694 >                        error = "Unknown error";
695 >                        break;
696 >                }
697 >
698 >                cerr << prefix << ": " << error << "\n";
699 >        }
700 >        else
701 >        {
702 >                perror(prefix.c_str());
703 >        }
704 > #endif // _WIN32
705 > }
706 >
707 > #ifdef _OpenSSL_
708 > void HttpHandler::error(const string& prefix, int number)
709 > {
710 >        string error;
711 >
712 >        switch (SSL_get_error(ssl, number))
713 >        {
714 >        case SSL_ERROR_NONE:
715 >                error = "The TLS/SSL I/O operation completed";
716 >                break;
717 >        case SSL_ERROR_ZERO_RETURN:
718 >                error = "The TLS/SSL connection has been closed";
719 >                break;
720 >        case SSL_ERROR_WANT_READ:
721 >        case SSL_ERROR_WANT_WRITE:
722 >        case SSL_ERROR_WANT_CONNECT:
723 > //      case SSL_ERROR_WANT_ACCEPT:
724 >        case SSL_ERROR_WANT_X509_LOOKUP:
725 >                error = "The operation did not complete";
726 >                break;
727 >        case SSL_ERROR_SYSCALL:
728 >                if (int err = ERR_get_error() != 0)
729 >                {
730 >                        error = ERR_reason_error_string(err);
731 >                }
732 >                else
733 >                {
734 >                        switch (number)
735 >                        {
736 >                        case 0:
737 >                                error = "An EOF was observed that violates the protocol";
738 >                                break;
739 >                        case -1:
740 >                                this->error(prefix);
741 >                                return;
742 >                        default:
743 >                                error = "Unknown error";
744 >                                break;
745 >                        }
746 >                }
747 >                break;
748 >        case SSL_ERROR_SSL:
749 >                error = ERR_reason_error_string(ERR_get_error());
750 >                break;
751 >        default:
752 >                error = "Unknown error";
753 >                break;
754 >        }
755 >
756 >        cerr << prefix << ": " << error << "\n";
757 > }
758 >
759 > bool HttpHandler::starttls()
760 > {
761 >        SSL_load_error_strings();
762 >        SSL_library_init();
763 >
764 >        //
765 >
766 >        return true;
767 > }
768 > #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines