Проблема с OpenSSL
От: i3F  
Дата: 10.12.13 10:35
Оценка:
Есть программа, использует WinInet, нормально общается с сервером в интернете по HTTPS.
Чтобы иметь больший контроль над сокетами хочется отказаться от WinInet, создавать и настраивать сокеты вручную, поддержку HTTPS реализовать, например, с помощью OpenSSL.
Тут обнаруживается проблема: через примерно 40-50 секунд после установления соединения вызов SSL_read возвращает 0,
при этом
SSL_get_error() = 5 (SSL_ERROR_SYSCALL)
ERR_get_error() = 0
WSAGetLastError() = 0
GetLastError() = 0
errno = 0


Судя по обсуждениям в интеренете причиной может быть закрытие соединения сервером.
Пока не догадываюсь, как искать причину такого поведения сервера.
Напоминаю, что WinInet-версия приложения работает без таких проблем, так что ошибка скорее всего наведена клиентским приложением.

Сокеты создаю обычной командой
WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0 );
Каких-то особенных опций сокету не выставляю.

В HTTP-запросах "Connection: Keep-Alive" указываю (хоть для HTTP 1.1 это не принципиально).
Приложение отправляет запрос на сервер и получает ответ не реже 1 раза в секунду.
Вообще, формы НТТР-запросов подсмотрел фидлером у WinInet-версии программы и использую их в OpenSSL-версии.
Только cookie из запросов выбросил, но уверен на 99,9% что дело не в них.

Возможно дело в неправильном использовании OpenSSL?
Работаю с ним впервые.
Какие могут быть идеи, в чем может быть проблема или как её искать?

Основной поток вызывает
SSL_load_error_strings();
SSL_library_init();
SSL_CTX *sslContext = SSL_CTX_new( SSLv23_client_method() );


Далее основной поток создаёт 2 соединения
SOCKET socket[ 2 ];
SSL* sslHandle[ 2 ];
for ( int i = 0; i < 2; ++i ) {
    socket[ i ] = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0 );
    connect( socket[ i ], &saddr, sizeof( saddr ) );
    sslHandle[ i ] = SSL_new( sslContext );
    SSL_set_fd( sslHandle[ i ], socket[ i ] );
    SSL_connect( sslHandle[ i ] );
}


Эти 2 соединения будут использоваться паралельно и независимо друг от друга.
Например, как если бы они были установлены разными браузерами или даже установлены с разных компьютеров.

После чего основной поток использует первое соединение
SSL_write( sslHandle[0], ... )
SSL_read( sslHandle[0], ... )


Второй поток использует второе соединение
SSL_write( sslHandle[1], ... )
SSL_read( sslHandle[1], ... )


Оба потока успешно выполняют положенную работу:
SSL_write возвращает управление мгновенно (видимо, копирует данные в локальные буферы),
SSL_read (вызванный сразу после выхода из SSL_write) возвращает управление через несколько сотен миллисекунд, когда приходит ответ из сети.

Через 40-50 секунд всё ломается.
SSL_write возвращает правильное число записанных байт.
После чего SSL_read немедленно возвращает 0.
SSL_get_error() возвращает SSL_ERROR_SYSCALL.

Использую
VC++ 2010
Win32 OpenSSL v1.0.1e

Приложение линкуется статически с библиотеками
...\OpenSSL-Win32\lib\VC\static\libeay32MT.lib
...\OpenSSL-Win32\lib\VC\static\ssleay32MT.lib

Как думаете, в чем может быть проблема или как искать причину сбоя?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.