DTLSv1_Listen () OpenSSL приостанавливает программу во время выполнения

Я пытаюсь протестировать с OpenSSL DTLS, создавая программу, которая создает сокет клиента и сервера для отображения строк между сокетами; Однако, когда я пытаюсь протестировать функцию DTLSv1_Listen (), моя программа останавливается, даже когда я не пытаюсь подключиться или отправить данные между сокетами. примечание: я использую пост 1.0.2 OpenSSL, который после DTLSv1_Listen () был переписан.

Вот мой полный специфичный для C ++ winsock код:

#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
//#include <openssl/applink.c>
#include <string>
#pragma comment(lib, "Ws2_32.lib")struct DTLSStuff { //struct to contain DTLS object instances
SSL_CTX *ctx;
SSL *ssl;
BIO *bio;
};

void DTLSErr() { //DTLS error reporting
ERR_print_errors_fp(stderr);
exit(1);
}

int newSocket(sockaddr_in addr) { //creates a socket and returns the file descriptor //TODO expand for multi-platform
WSADATA wsaData;
int fd;
int iResult;

iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);                                                     //Initialize Winsock
if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); exit(1); }

fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("Unable to create socket"); exit(1); }    //create socket
printf("New Socket: %i\n", fd);
if (bind(fd, (struct sockaddr *)&addr, sizeof(sockaddr)) < 0) { printf("bind failed with error %u\n", WSAGetLastError());   exit(1); }

return fd;                                                                                          //file descriptor
}

void InitCTX(SSL_CTX *ctx, bool IsClient) { //Takes a ctx object and initializes it for DTLS communication
if (IsClient) {
if(SSL_CTX_use_certificate_chain_file(ctx, "client-cert.pem") < 0) { printf("Failed loading client cert");}
if(SSL_CTX_use_PrivateKey_file(ctx, "client-key.pem", SSL_FILETYPE_PEM) < 0) { printf("Failed loading client key"); }
}
else {
if (SSL_CTX_use_certificate_chain_file(ctx, "server-cert.pem") < 0) { printf("Failed loading client cert"); }
if (SSL_CTX_use_PrivateKey_file(ctx, "server-key.pem", SSL_FILETYPE_PEM) < 0) { printf("Failed loading client key"); }
}
//SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cert);    //omitted for testing
//SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie);     //omitted for testing
//SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie);         //omitted for testing
SSL_CTX_set_read_ahead(ctx, 1);
}

int main() { //creates client and server sockets and DTLS objects. TODO: have client complete handshake with server socket and send a message and have the server echo it back to client socket
BIO_ADDR *faux_addr = BIO_ADDR_new(); // for DTLSv1_listen(), since we are this is both client and server (meaning client address is known) it is only used to satisfy parameters.
ERR_load_BIO_strings();
SSL_load_error_strings();
SSL_library_init();

//Set up addresses
sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(25501);
client_addr.sin_addr.s_addr = INADDR_ANY;
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(25500);
server_addr.sin_addr.s_addr = INADDR_ANY;

//*********CLIENT
DTLSStuff ClientInf;
ClientInf.ctx = SSL_CTX_new(DTLSv1_client_method());
InitCTX(ClientInf.ctx,true);
int ClientFD = newSocket(client_addr);
ClientInf.bio = BIO_new_dgram(ClientFD, BIO_NOCLOSE);
ClientInf.ssl = SSL_new(ClientInf.ctx);
//SSL_set_options(ClientInf.ssl, SSL_OP_COOKIE_EXCHANGE); //omitted for testing
SSL_set_bio(ClientInf.ssl, ClientInf.bio, ClientInf.bio);

//*********SERVER
DTLSStuff ServerInf;
ServerInf.ctx = SSL_CTX_new(DTLSv1_server_method());
InitCTX(ServerInf.ctx,false);
int ServerFD = newSocket(server_addr);
ServerInf.bio = BIO_new_dgram(ServerFD, BIO_NOCLOSE);
ServerInf.ssl = SSL_new(ServerInf.ctx);
//SSL_set_options(ServerInf.ssl, SSL_OP_COOKIE_EXCHANGE); //omitted for testing
SSL_set_bio(ServerInf.ssl, ServerInf.bio, ServerInf.bio);

printf("Listen attempt...\n");
int ret = DTLSv1_listen(ServerInf.ssl, faux_addr);
if (ret < 0) { DTLSErr(); }
printf("this print should occur, but it never does");
exit(1);
}

Я ожидаю, что результаты будут следующими:

NewSocket: 356
NewSocket: 360
Listen attempt...
this print should occur but it never does

Однако при запуске программы она никогда не печатает последнюю строку. Кажется, что программа отвечает, поскольку я могу отменить исполняемый файл с помощью ctrl + c, поэтому я предполагаю, что он не завис или не завис, но кроме этого я в растерянности. Насколько я понимаю, метод должен возвращать 0, если ничего не происходит,> 1, если он услышал clienthello, и <0, если произошла ошибка.

Кроме того, несколько связанный с этим вопрос: поскольку DTLSv1_Listen () требует BIO_ADDR для хранения адреса входящих запросов, означает ли это, что отдельным программам клиента и сервера потребуются 2 сокета, если они хотят иметь возможность и отправлять, и прослушивать? Обычно клиентам и серверам UDP нужен только один сокет, но я не могу придумать, как сохранить это с помощью DTLS OpenSSL.

Я благодарю вас за ваше время.

0

Решение

Я не вижу нигде в вашем коде, где вы устанавливаете сокет как неблокирующий. В режиме блокировки по умолчанию при попытке чтения из сокета ваша программа будет приостановлена, пока не поступят данные. Если вы не хотите этого, убедитесь, что вы установили соответствующую опцию (я не программист Windows, но ioctlsocket, похоже, выполняет свою работу: https://msdn.microsoft.com/en-us/library/windows/desktop/ms738573(v=vs.85).aspx)

Означает ли это, что отдельным программам клиента и сервера потребуются 2 сокета, если они хотят иметь возможность отправлять и прослушивать

При использовании DTLSv1_listen () вы используете сокет в неподключенном состоянии, поэтому вы можете получать UDP-пакеты от нескольких клиентов. DTLS основан на соединении, поэтому, как только DTLSv1_listen () вернется успешно, вы должны создать «подключенный» сокет к адресу клиента. Таким образом, у вас есть один сокет для прослушивания новых соединений и один сокет для клиента, связывающегося с вашим сервером.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]