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

Comparing trunk/WinXPFAQPoll/IMAPHandler.cpp (file contents):
Revision 104 by douglas, 2003-03-31T20:18:26-08:00 vs.
Revision 123 by douglas, 2003-04-02T18:10:51-08:00

# Line 1 | Line 1
1 < /* ============================================================================
2 < * Douglas Thrift's Web Contact License
3 < *
4 < * Copyright (C) 2002, Douglas Thrift. All Rights Reserved.
5 < *
6 < * Redistribution and use in source and binary forms, with or without
7 < * modification, are permitted provided that the following conditions are met:
8 < *
9 < * 1. Redistributions of source code must retain the above copyright notice,
10 < *    this list of conditions and the following disclaimer.
11 < *
12 < * 2. Redistributions in binary form must reproduce the above copyright notice,
13 < *    this list of conditions and the following disclaimer in the documentation
14 < *    and/or other materials provided with the distribution.
15 < *
16 < * 3. The end-user documentation included with the redistribution, if any, must
17 < *    include the following acknowledgment:
18 < *
19 < *       "This product includes software developed by Douglas Thrift
20 < *       (http://computers.douglasthrift.net/webcontact.html)."
21 < *
22 < *    Alternately, this acknowledgment may appear in the software itself, if
23 < *    and wherever such third-party acknowledgments normally appear.
24 < *
25 < * 4. The names "Douglas Thrift" and "Douglas Thrift's Web Contact" must not be
26 < *    used to endorse or promote products derived from this software without
27 < *    specific prior written permission. For written permission, please visit
28 < *    http://www.douglasthrift.net/contact.html for contact information.
29 < *
30 < * 5. Products derived from this software may not be called "Douglas Thrift's
31 < *    Web Contact", nor may "Douglas Thrift's Web Contact" appear in their
32 < *    name, without prior written permission.
33 < *
34 < * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 < * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 < * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37 < * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
38 < * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 < * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
40 < * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41 < * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42 < * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
43 < * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 < * ============================================================================
45 < */
46 < // Windows XP FAQ Poll
1 > // IMAP Handler
2   //
3   // Douglas Thrift
4   //
# Line 51 | Line 6
6  
7   #include "IMAPHandler.h"
8  
9 + IMAPHandler::IMAPHandler(const string& server, bool tls)
10 + {
11 +        letter = 'a';
12 +        number = 0;
13 +
14 +        this->tls = tls;
15 +        buffer = new char[BUFSIZ + 1];
16 +
17   #ifdef _WIN32
18 < #define PATH_SEPARATOR "\\"
19 < #define ENV_SEPARATOR ';'
20 < #else
21 < #define PATH_SEPARATOR "/"
22 < #define ENV_SEPARATOR ':'
23 < #endif
18 >        if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
19 >        {
20 >                error(program + ": WSAStartup");
21 >                exit(1);
22 >        }
23 > #endif // _WIN32
24  
25 < IMAPHandler::IMAPHandler(const string& host, unsigned port)
26 < {
27 <        setJarPath();
25 >        if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
26 >        {
27 >                error(program + ": Socket");
28 >                exit(1);
29 >        }
30 >        
31 >        sockaddr_in address;
32 >        hostent* host;
33  
34 <        options[0].optionString = jarPath;
67 <        memset(&vm_args, 0, sizeof (vm_args));
68 <        vm_args.version = JNI_VERSION_1_2;
69 <        vm_args.nOptions = 1;
70 <        vm_args.options = options;
34 >        address.sin_family = AF_INET;
35  
36 <        status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
36 >        if ((host = gethostbyname(server.c_str())) == NULL)
37 >        {
38 >                error(program + ": Host: " + server, true);
39 >                exit(1);
40 >        }
41 >
42 >        address.sin_addr = *((in_addr*)*host->h_addr_list);
43 >        address.sin_port = htons(tls ? 993 : 143);
44 >
45 >        if (connect(sock, (sockaddr*)&address, sizeof(sockaddr_in)) ==
46 >                SOCKET_ERROR)
47 >        {
48 >                error(program + ": Connect");
49 >                exit(1);
50 >        }
51  
52 <        if (status != JNI_ERR)
52 >        if (tls)
53          {
54 <                cls = env->FindClass("IMAPHandler");
54 >                SSL_load_error_strings();
55 >                SSL_library_init();
56  
57 <                if (cls != 0)
57 >                char* seed = new char[BUFSIZ + 1];
58 >                time_t moment = time(NULL);
59 >                sprintf(seed, "froofy%sfoofoo", ctime(&moment));
60 >
61 >                RAND_add(seed, strlen(seed), 0.007456);
62 >
63 >                delete [] seed;
64 >
65 >                ctx = SSL_CTX_new(TLSv1_client_method());
66 >                if (ctx == NULL)
67                  {
68 <                        mid = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;IZ)V");
68 >                        cerr << program << ": SSL CTX New: " <<
69 >                                ERR_reason_error_string(ERR_get_error()) << "\n";
70 >                        exit(1);
71 >                }
72  
73 <                        if (mid != 0)
83 <                        {
84 <                                jstring hostJ = env->NewStringUTF(host.c_str());
85 <                                jint portJ = port;
86 < #ifdef _DEBUG
87 <                                jboolean debugJ = debug;
88 < #else
89 <                                jboolean debugJ = false;
90 < #endif
73 >                ssl = SSL_new(ctx);
74  
75 <                                obj = env->NewObject(cls, mid, hostJ, portJ, debugJ);
76 <                        }
75 >                if (SSL_set_fd(ssl, sock) == 0)
76 >                {
77 >                        cerr << program << ": SSL Set FD: " <<
78 >                                ERR_reason_error_string(ERR_get_error()) << "\n";
79 >                        exit(1);
80 >                }
81 >
82 >                if (int code = SSL_connect(ssl) <= 0)
83 >                {
84 >                        error(program + ": SSL Connect", code);
85 >                        exit(1);
86                  }
87          }
88 +
89 +        getline();
90   }
91  
92   IMAPHandler::~IMAPHandler()
93   {
94 <        if (status != JNI_ERR)
94 >        if (tls)
95          {
96 <                jvm->DestroyJavaVM();
96 >                SSL_shutdown(ssl);
97 >                SSL_free(ssl);
98 >                SSL_CTX_free(ctx);
99          }
100 +
101 +        closesocket(sock);
102 +        
103 +        delete [] buffer;
104 +
105 + #ifdef _WIN32
106 +        WSACleanup();
107 + #endif // _WIN32
108   }
109  
110 < bool IMAPHandler::successful()
110 > string IMAPHandler::starttls()
111   {
112 <        bool answer;
112 >        string answer = imap("STARTTLS");
113  
114 <        if (cls != 0)
114 >        if (success)
115          {
116 <                mid = env->GetMethodID(cls, "successful", "()Z");
116 >                tls = true;
117 >
118 >                SSL_load_error_strings();
119 >                SSL_library_init();
120 >
121 >                char* seed = new char[BUFSIZ + 1];
122 >                time_t moment = time(NULL);
123 >                sprintf(seed, "froofy%sfoofoo", ctime(&moment));
124 >
125 >                RAND_add(seed, strlen(seed), 0.007456);
126  
127 <                if (mid != 0)
127 >                delete [] seed;
128 >
129 >                ctx = SSL_CTX_new(TLSv1_client_method());
130 >                if (ctx == NULL)
131                  {
132 <                        jboolean answerJ = env->CallBooleanMethod(obj, mid);
132 >                        cerr << program << ": SSL CTX New: " <<
133 >                                ERR_reason_error_string(ERR_get_error()) << "\n";
134 >                        exit(1);
135 >                }
136  
137 <                        answer = answerJ != 0;
137 >                ssl = SSL_new(ctx);
138 >
139 >                if (SSL_set_fd(ssl, sock) == 0)
140 >                {
141 >                        cerr << program << ": SSL Set FD: " <<
142 >                                ERR_reason_error_string(ERR_get_error()) << "\n";
143 >                        exit(1);
144 >                }
145 >
146 >                if (int code = SSL_connect(ssl) <= 0)
147 >                {
148 >                        error(program + ": SSL Connect", code);
149 >                        exit(1);
150                  }
151          }
152  
153          return answer;
154   }
155  
156 < void IMAPHandler::setJarPath()
156 > string IMAPHandler::command()
157   {
158 <        const string jarFile = "IMAPHandler.jar";
159 <        string jarFilePath = jarFile;
158 >        char buffer[4];
159 >        sprintf(buffer, "%03u", number++);
160  
161 <        ifstream fin(jarFilePath.c_str());
162 <        if (!fin.is_open())
161 >        string sequence = letter + string(buffer);
162 >
163 >        if (number > 999)
164          {
165 <                unsigned end = program.rfind(PATH_SEPARATOR);
166 <                if (end != string::npos)
167 <                {
136 <                        string path = program.substr(0, end);
165 >                letter++;
166 >                number = 0;
167 >        }
168  
169 <                        jarFilePath = path + PATH_SEPARATOR + jarFile;
169 >        if (letter > 'z')
170 >        {
171 >                letter = 'a';
172 >        }
173  
174 <                        fin.open(jarFilePath.c_str());
175 <                        if (!fin.is_open())
176 <                        {
177 <                                cerr << program << ": Could not find required file: "
178 <                                        << jarFile << "\n";
179 <                                exit(1);
180 <                        }
181 <                        else
182 <                        {
183 <                                fin.close();
184 <                        }
174 >        return sequence;
175 > }
176 >
177 > string IMAPHandler::imap(const string& imap)
178 > {
179 >        string result;
180 >
181 >        string sequence = command();
182 >        putline(sequence + " " + imap);
183 >
184 >        while (true)
185 >        {
186 >                string input = getline();
187 >
188 >                if (input.find(sequence + " OK") == 0)
189 >                {
190 >                        success = true;
191 >                        break;
192 >                }
193 >                else if (input.find(sequence + " NO") == 0 || input.find(sequence +
194 >                        " BAD") == 0)
195 >                {
196 >                        success = false;
197 >                        break;
198                  }
199                  else
200                  {
201 <                        string envPath = getenv("PATH");
202 <
203 <                        if (debug) cerr << "envPath = " << envPath << "\n";
157 <
158 <                        unsigned begin = 0;
159 <                        do
160 <                        {
161 <                                unsigned end = envPath.find(ENV_SEPARATOR, begin);
162 <                                string path = envPath.substr(begin, end);
201 >                        result += input + "\n";
202 >                }
203 >        }
204  
205 <                                if (debug) cerr << "path = " << path << "\n";
205 >        return result;
206 > }
207  
208 <                                jarFilePath = path + PATH_SEPARATOR + jarFile;
208 > string IMAPHandler::imap(const string& imap, const string& args)
209 > {
210 >        string result;
211  
212 <                                fin.open(jarFilePath.c_str());
213 <                                if (fin.is_open())
170 <                                {
171 <                                        fin.close();
172 <                                        break;
173 <                                }
212 >        string sequence = command();
213 >        putline(sequence + " " + imap + " " + args);
214  
215 <                                begin = end != string::npos ? end + 1 : string::npos;
216 <                        }
217 <                        while (begin < envPath.length());
215 >        while (true)
216 >        {
217 >                string input = getline();
218  
219 <                        if (begin == string::npos)
220 <                        {
221 <                                cerr << program << ": Could not find required file: "
222 <                                        << jarFile << "\n";
223 <                                exit(1);
224 <                        }
219 >                if (input.find(sequence + " OK") == 0)
220 >                {
221 >                        success = true;
222 >                        break;
223 >                }
224 >                else if (input.find(sequence + " NO") == 0 || input.find(sequence +
225 >                        " BAD") == 0)
226 >                {
227 >                        success = false;
228 >                        break;
229 >                }
230 >                else
231 >                {
232 >                        result += input + "\n";
233                  }
234          }
187        else
188        {
189                fin.close();
190        }
191
192        string jarPath = "-Djava.class.path=" + jarFilePath;
235  
236 <        this->jarPath = new char[jarPath.length()];
195 <        strcpy(this->jarPath, jarPath.c_str());
236 >        return result;
237   }
238  
239 < string IMAPHandler::imap(char* imap)
239 > string IMAPHandler::imap(const string& imap, const string& args, const string&
240 >        message)
241   {
242          string result;
243  
244 <        if (cls != 0)
244 >        string sequence = command();
245 >        putline(sequence + " " + imap + " " + args);
246 >        putline(message);
247 >
248 >        while (true)
249          {
250 <                mid = env->GetMethodID(cls, imap, "()Ljava/lang/String;");
250 >                string input = getline();
251  
252 <                if (mid != 0)
252 >                if (input.find(sequence + " OK") == 0)
253                  {
254 <                        jstring resultJ = (jstring)env->CallObjectMethod(obj, mid);
255 <
256 <                        const char* resultC = env->GetStringUTFChars(resultJ, 0);
257 <                        result = resultC;
258 <                        env->ReleaseStringUTFChars(resultJ, resultC);
254 >                        success = true;
255 >                        break;
256 >                }
257 >                else if (input.find(sequence + " NO") == 0 || input.find(sequence +
258 >                        " BAD") == 0)
259 >                {
260 >                        success = false;
261 >                        break;
262 >                }
263 >                else
264 >                {
265 >                        result += input + "\n";
266                  }
267          }
268  
269          return result;
270   }
271  
272 < string IMAPHandler::imap(char* imap, const string& args)
272 > void IMAPHandler::putline(const string line)
273   {
274 <        string result;
274 >        if (debug) cerr << line << "\n";
275 >
276 >        istringstream lines(line);
277  
278 <        if (cls != 0)
278 >        while (lines.good())
279          {
280 <                mid = env->GetMethodID(cls, imap,
226 <                        "(Ljava/lang/String;)Ljava/lang/String;");
280 >                string line;
281  
282 <                if (mid != 0)
282 >                std::getline(lines, line);
283 >                sprintf(buffer, "%s\r\n", line.c_str());
284 >
285 >                if (tls)
286 >                {
287 >                        if (int code = SSL_write(ssl, buffer, strlen(buffer)) <= 0)
288 >                        {
289 >                                error(program + ": SSL Write", code);
290 >                                exit(1);
291 >                        }
292 >                }
293 >                else
294                  {
295 <                        jstring argsJ = env->NewStringUTF(args.c_str());
295 >                        if (send(sock, buffer, strlen(buffer), 0) == SOCKET_ERROR)
296 >                        {
297 >                                error(program + ": Send");
298 >                                exit(1);
299 >                        }
300 >                }
301  
302 <                        jstring resultJ = (jstring)env->CallObjectMethod(obj, mid, argsJ);
302 >                lines.peek();
303 >        }
304 > }
305 >
306 > string IMAPHandler::getline()
307 > {
308 >        string line;
309 >        char byte;
310  
311 <                        const char* resultC = env->GetStringUTFChars(resultJ, 0);
312 <                        result = resultC;
313 <                        env->ReleaseStringUTFChars(resultJ, resultC);
311 >        do
312 >        {
313 >                if (tls)
314 >                {
315 >                        if (int code = SSL_read(ssl, &byte, 1) <= 0)
316 >                        {
317 >                                error(program + ": SSL Read", code);
318 >                                exit(1);
319 >                        }
320 >                }
321 >                else
322 >                {
323 >                        if (recv(sock, &byte, 1, 0) == SOCKET_ERROR)
324 >                        {
325 >                                error(program + ": Recv");
326 >                                exit(1);
327 >                        }
328 >                }
329 >
330 >                if (byte != '\r' && byte != '\n')
331 >                {
332 >                        line += byte;
333                  }
334          }
335 +        while (byte != '\n');
336  
337 <        return result;
337 >        if (debug) cerr << line << "\n";
338 >
339 >        return line;
340   }
341  
342 < string IMAPHandler::imap(char* imap, const string& args, const string& message)
342 > void IMAPHandler::error(const string& prefix, bool host)
343   {
344 <        string result;
344 > #ifdef _WIN32
345 >        string error;
346  
347 <        if (cls != 0)
347 >        switch (WSAGetLastError())
348          {
349 <                mid = env->GetMethodID(cls, imap,
350 <                        "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
349 >        case WSAEACCES:
350 >                error = "Permission denied.";
351 >                break;
352 >        case WSAEADDRINUSE:
353 >                error = "Address already in use.";
354 >                break;
355 >        case WSAEADDRNOTAVAIL:
356 >                error = "Cannot assign requested address.";
357 >                break;
358 >        case WSAEAFNOSUPPORT:
359 >                error = "Address family not supported by protocol family.";
360 >                break;
361 >        case WSAEALREADY:
362 >                error = "Operation already in progress.";
363 >                break;
364 >        case WSAECONNABORTED:
365 >                error = "Software caused connection abort.";
366 >                break;
367 >        case WSAECONNREFUSED:
368 >                error = "Connection refused.";
369 >                break;
370 >        case WSAECONNRESET:
371 >                error = "Connection reset by peer.";
372 >                break;
373 >        case WSAEDESTADDRREQ:
374 >                error = "Destination address required.";
375 >                break;
376 >        case WSAEFAULT:
377 >                error = "Bad address.";
378 >                break;
379 >        case WSAEHOSTDOWN:
380 >                error = "Host is down.";
381 >                break;
382 >        case WSAEHOSTUNREACH:
383 >                error = "No route to host.";
384 >                break;
385 >        case WSAEINPROGRESS:
386 >                error = "Operation now in progress.";
387 >                break;
388 >        case WSAEINTR:
389 >                error = "Interrupted function call.";
390 >                break;
391 >        case WSAEINVAL:
392 >                error = "Invalid argument.";
393 >                break;
394 >        case WSAEISCONN:
395 >                error = "Socket is already connected.";
396 >                break;
397 >        case WSAEMFILE:
398 >                error = "Too many open files.";
399 >                break;
400 >        case WSAEMSGSIZE:
401 >                error = "Message too long.";
402 >                break;
403 >        case WSAENETDOWN:
404 >                error = "Network is down.";
405 >                break;
406 >        case WSAENETRESET:
407 >                error = "Network dropped connection on reset.";
408 >                break;
409 >        case WSAENETUNREACH:
410 >                error = "Network is unreachable.";
411 >                break;
412 >        case WSAENOBUFS:
413 >                error = "No buffer space available.";
414 >                break;
415 >        case WSAENOPROTOOPT:
416 >                error = "Bad protocol option.";
417 >                break;
418 >        case WSAENOTCONN:
419 >                error = "Socket is not connected.";
420 >                break;
421 >        case WSAENOTSOCK:
422 >                error = "Socket operation on non-socket.";
423 >                break;
424 >        case WSAEOPNOTSUPP:
425 >                error = "Operation not supported.";
426 >                break;
427 >        case WSAEPFNOSUPPORT:
428 >                error = "Protocol family not supported.";
429 >                break;
430 >        case WSAEPROCLIM:
431 >                error = "Too many processes.";
432 >                break;
433 >        case WSAEPROTONOSUPPORT:
434 >                error = "Protocol not supported.";
435 >                break;
436 >        case WSAEPROTOTYPE:
437 >                error = "Protocol wrong type for socket.";
438 >                break;
439 >        case WSAESHUTDOWN:
440 >                error = "Cannot send after socket shutdown.";
441 >                break;
442 >        case WSAESOCKTNOSUPPORT:
443 >                error = "Socket type not supported.";
444 >                break;
445 >        case WSAETIMEDOUT:
446 >                error = "Connection timed out.";
447 >                break;
448 >        case WSATYPE_NOT_FOUND:
449 >                error = "Class type not found.";
450 >                break;
451 >        case WSAEWOULDBLOCK:
452 >                error = "Resource temporarily unavailable.";
453 >                break;
454 >        case WSAHOST_NOT_FOUND:
455 >                error = "Host not found.";
456 >                break;
457 >        case WSA_INVALID_HANDLE:
458 >                error = "Specified event object handle is invalid.";
459 >                break;
460 >        case WSA_INVALID_PARAMETER:
461 >                error = "One or more parameters are invalid.";
462 >                break;
463 > //      case WSAINVALIDPROCTABLE:
464 > //              error = "Invalid procedure table from service provider.";
465 > //              break;
466 > //      case WSAINVALIDPROVIDER:
467 > //              error = "Invalid service provider version number.";
468 > //              break;
469 >        case WSA_IO_INCOMPLETE:
470 >                error = "Overlapped I/O event object not in signaled state.";
471 >                break;
472 >        case WSA_IO_PENDING:
473 >                error = "Overlapped operations will complete later.";
474 >                break;
475 >        case WSA_NOT_ENOUGH_MEMORY:
476 >                error = "Insufficient memory available.";
477 >                break;
478 >        case WSANOTINITIALISED:
479 >                error = "Successful WSAStartup not yet performed.";
480 >                break;
481 >        case WSANO_DATA:
482 >                error = "Valid name, no data record of requested type.";
483 >                break;
484 >        case WSANO_RECOVERY:
485 >                error = "This is a non-recoverable error.";
486 >                break;
487 > //      case WSAPROVIDERFAILEDINIT:
488 > //              error = "Unable to initialize a service provider.";
489 > //              break;
490 >        case WSASYSCALLFAILURE:
491 >                error = "System call failure.";
492 >                break;
493 >        case WSASYSNOTREADY:
494 >                error = "Network subsystem is unavailable.";
495 >                break;
496 >        case WSATRY_AGAIN:
497 >                error = "Non-authoritative host not found.";
498 >                break;
499 >        case WSAVERNOTSUPPORTED:
500 >                error = "WINSOCK.DLL version out of range.";
501 >                break;
502 >        case WSAEDISCON:
503 >                error = "Graceful shutdown in progress.";
504 >                break;
505 >        case WSA_OPERATION_ABORTED:
506 >                error = "Overlapped operation aborted.";
507 >                break;
508 >        default:
509 >                error = "Unknown error.";
510 >                break;
511 >        }
512  
513 <                if (mid != 0)
514 <                {
515 <                        jstring argsJ = env->NewStringUTF(args.c_str());
516 <                        jstring messageJ = env->NewStringUTF(message.c_str());
513 >        cerr << prefix << ": " << error << "\n";
514 > #else
515 >        if (host)
516 >        {
517 >                herror(prefix.c_str());
518 >        }
519 >        else
520 >        {
521 >                perror(prefix.c_str());
522 >        }
523 > #endif // _WIN32
524 > }
525  
526 <                        jstring resultJ = (jstring)env->CallObjectMethod(obj, mid, argsJ,
527 <                                messageJ);
526 > void IMAPHandler::error(const string& prefix, int code)
527 > {
528 >        string error;
529  
530 <                        const char* resultC = env->GetStringUTFChars(resultJ, 0);
531 <                        result = resultC;
532 <                        env->ReleaseStringUTFChars(resultJ, resultC);
530 >        switch (SSL_get_error(ssl, code))
531 >        {
532 >        case SSL_ERROR_NONE:
533 >                error = "The TLS/SSL I/O operation completed.";
534 >                break;
535 >        case SSL_ERROR_ZERO_RETURN:
536 >                error = "The TLS/SSL connection has been closed.";
537 >                break;
538 >        case SSL_ERROR_WANT_READ:
539 >        case SSL_ERROR_WANT_WRITE:
540 >        case SSL_ERROR_WANT_CONNECT:
541 > //      case SSL_ERROR_WANT_ACCEPT:
542 >        case SSL_ERROR_WANT_X509_LOOKUP:
543 >                error = "The operation did not complete.";
544 >                break;
545 >        case SSL_ERROR_SYSCALL:
546 >                if (int err = ERR_get_error() != 0)
547 >                {
548 >                        error = ERR_reason_error_string(err);
549                  }
550 +                else
551 +                {
552 +                        switch (code)
553 +                        {
554 +                        case 0:
555 +                                error = "An EOF was observed that violates the protocol.";
556 +                                break;
557 +                        case -1:
558 +                                this->error(prefix);
559 +                                return;
560 +                        default:
561 +                                error = "Unknown error.";
562 +                                break;
563 +                        }
564 +                }
565 +                break;
566 +        case SSL_ERROR_SSL:
567 +                error = ERR_reason_error_string(ERR_get_error());
568 +                break;
569 +        default:
570 +                error = "Unknown error.";
571 +                break;
572          }
573  
574 <        return result;
574 >        cerr << prefix << ": " << error << "\n";
575   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines