Я создал сервер и клиента, и они общаются в безопасном канале TLSv1.3, OpenSSL 3.0.0. Они должны иметь возможность отправлять и получать, но в этом тесте сервер только получает, а клиент только периодически отправляет данные приложения.
После успешного установления связи клиенты select()
сигнализируют о наличии данных, доступных для чтения. Когда я пытаюсь, SSL_read()
не возвращается. Я проверил сетевой трафик в wireshark и отладил библиотеку OpenSSL, чтобы выяснить, что 2 SESSION_TICKET отправляются после рукопожатия сервером клиенту, и это сообщение SSL_read()
не обрабатывается. Просто для любопытства я отправил сообщение с сервером сразу после рукопожатия, чтобы посмотреть, как клиент реагирует на него. Удивительно, но клиент вышел из заблокированного состояния, и после этого связь работала нормально.
Из-за наблюдаемого поведения мое единственное предположение состоит в том, что я пытаюсь прочитать данные, предназначенные для OpenSSL, которые, вероятно, обрабатываются его конечным автоматом, когда я вызываю SSL_read()
. Когда библиотека вызывает read()
, на самом деле данные приложения недоступны, поэтому она блокирует поток.
Функцию-член, которую я использую для чтения байтов "count", можно увидеть ниже.
int EventHandler::readByte(CommBuffer &buffer, ssize_t count, struct timeval &tmout){
fd_set rfds;
int retSelect, retRead;
int readByte=0;
int endRead=0;
int readSize=count;
buffer.setBufferSize(count+1);
do{
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
retSelect=select(fd+1,&rfds,NULL,NULL,&tmout);
if(retSelect>0){
if (encryptionOn) {
retRead = SSL_read(ssl, (const_cast<char*>(&buffer.get()[readByte])), readSize); // Thread blocks here.
} else {
retRead = read(fd, (const_cast<char*>(&buffer.get()[readByte])), readSize);
}
if( retRead > 0 ){
readByte+=retRead;
allReadBytes+=retRead;
buffer.setDataSize(readByte);
if(readByte>=count) endRead=1;
readSize=count-readByte;
}
else{
if( retRead == -1 && errno == EINTR ){
continue;
}
if(fd>=0){
close(fd);
}
fd=CLOSED_FD;
return (CLOSED_FD);
}
}
else if(retSelect==0){
// handle timeout error
return(TIMEOUT_FD);
}
else{
return(retSelect);
}
}while(endRead!=1);
return(readByte);
}
Обратите внимание, что эта функция прекрасно работает без шифрования. (read()
вместо SSL_read()
)
- Что я делаю не так?
- Как читать данные?
- Как бы вы изменили эту функцию?