Здравствуйте, коллеги!
Пишу сетевой сервер с шифрованием TLS (однопоточный через poll). Большей частью получаются, но наткнулся на очень неприятную вещь: Если клиент, внезапно, некорректно рвет соединение, то сервер крашится.
Т.е. при вызове SSL_read или SSL_write все крашится.
Долгие «экскременты» показали интересную штуку: если я насильственно выбиваю клиента во время работы, то на сервер приходит пакет нулевой длинны.
Это я отлавливаю просто читая из сокета через recv с установленным флагом MSG_PEEK, т.е. считать из буфера, но не удалять данные.
recv считывает 0 байт, что является закрытием соединения, а вот SSL_read натакаясь на пакет нулевой длинны крашит программу.
Разумеется, можно сделать обертку типа:
int ssl_recv(SSL * ssl, char * data, int data_size){
int s = SSL_get_fd(ssl);
if(recv(s, data, data_size, MSG_PEEK)){
return SSL_read(ssl, data, data_size);
}
return -111;
}
При получении -111 от ssl_recv закрывать соединение на стороне сервера.
Но способ мне кажется несколько кривоватым.
Это же каждый раз, по большому счету, делать целых 2 ресива!
Есть способ узнать количество данных в сетевом буфере без его считывания?
Или, возможно, есть более прямой способ уберечь сервер от крашей при некорректном вылете клиента?
PS
if(SSL_get_state() == TLS_ST_OK){
retrurn SSL_read(ssl, data, data_size);
}
Не подходит. Этот SSL_get_state() радостно рапортует TLS_ST_OK даже при вылете клиента.