2013-04-06 18 views
6

libcurl ma timeout options takie jak:Jak ustawić limit czasu połączenia i limitu czasu pracy w OpenSSL

CURLOPT_CONNECTTIMEOUT - maximum time in seconds that you allow the connection to the server to take. 
CURLOPT_TIMEOUT - maximum time in seconds that you allow the libcurl transfer operation to take. 

Chciałbym wdrożyć podobny mechanizm limitu czasu w OpenSSL.

Jakie zmiany byłyby wymagane w poniższym kodzie, aby wartość limitu czasu została zastosowana do BIO_do_connect(), BIO_write() i BIO_read()?

Łączę się z serwerem i wysyłam/odbieram dane do/z serwera za pomocą BIO_write()/BIO_read(), które zapewnia OpenSSL. Mój kod jest oparty na następującym przykładowym kodzie dostępnym pod numerem here.

int main() 
{ 
    BIO * bio; 
    SSL * ssl; 
    SSL_CTX * ctx; 

    int p; 

    char * request = "GET/HTTP/1.1\x0D\x0AHost: www.verisign.com\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A"; 
    char r[1024]; 

    /* Set up the library */ 

    ERR_load_BIO_strings(); 
    SSL_load_error_strings(); 
    OpenSSL_add_all_algorithms(); 

    /* Set up the SSL context */ 

    ctx = SSL_CTX_new(SSLv23_client_method()); 

    /* Load the trust store */ 

    if(! SSL_CTX_load_verify_locations(ctx, "TrustStore.pem", NULL)) 
    { 
     fprintf(stderr, "Error loading trust store\n"); 
     ERR_print_errors_fp(stderr); 
     SSL_CTX_free(ctx); 
     return 0; 
    } 

    /* Setup the connection */ 

    bio = BIO_new_ssl_connect(ctx); 

    /* Set the SSL_MODE_AUTO_RETRY flag */ 

    BIO_get_ssl(bio, & ssl); 
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 

    /* Create and setup the connection */ 

    BIO_set_conn_hostname(bio, "www.verisign.com:https"); 

    if(BIO_do_connect(bio) <= 0) 
    { 
     fprintf(stderr, "Error attempting to connect\n"); 
     ERR_print_errors_fp(stderr); 
     BIO_free_all(bio); 
     SSL_CTX_free(ctx); 
     return 0; 
    } 

    /* Check the certificate */ 

    if(SSL_get_verify_result(ssl) != X509_V_OK) 
    { 
     fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl)); 
     BIO_free_all(bio); 
     SSL_CTX_free(ctx); 
     return 0; 
    } 

    /* Send the request */ 

    BIO_write(bio, request, strlen(request)); 

    /* Read in the response */ 

    for(;;) 
    { 
     p = BIO_read(bio, r, 1023); 
     if(p <= 0) break; 
     r[p] = 0; 
     printf("%s", r); 
    } 

    /* Close the connection and free the context */ 

    BIO_free_all(bio); 
    SSL_CTX_free(ctx); 
    return 0; 
} 

Jestem cross-kompilacji dla ARM na Ubuntu (Eclipse z CodeSourcery Lite).

+0

pokrewne: [otwiera blok ssl_connect na zawsze - jak ustawić limit czasu?] (Http://stackoverflow.com/questions/11835203/openssl-ssl-connect-blocks-forever-how-to-set-timeout) – jfs

Odpowiedz

5

skończyło się robić coś jak poniżej (Pseudokod):

int nRet; 
int fdSocket; 
fd_set connectionfds; 
struct timeval timeout; 

BIO_set_nbio(pBio, 1); 

nRet = BIO_do_connect(pBio); 

if ((nRet <= 0) && !BIO_should_retry(pBio)) 
    // failed to establish connection. 

if (BIO_get_fd(pBio, &fdSocket) < 0) 
    // failed to get fd. 

if (nRet <= 0) 
{ 
    FD_ZERO(&connectionfds); 
    FD_SET(fdSocket, &connectionfds); 

    timeout.tv_usec = 0; 
    timeout.tv_sec = 10; 

    nRet = select(fdSocket + 1, NULL, &connectionfds, NULL, &timeout); 
    if (nRet == 0) 
     // timeout has occurred. 
} 

można użyć tego samego podejścia do BIO_read() też.

Może Ci się przydać this link.

+0

Zachowaj ostrożność, używając tego z 'BIO_read'. [Dokumentacja] (https://www.openssl.org/docs/manmaster/crypto/BIO_read.html) stwierdza, że ​​'BIO_read' może powodować wiele wywołań do' odczytania', potencjalnie blokując poza określony czas. –

+0

Czy możesz zamieścić swój aktualny kod lub link do niego? – am3

-1

Spójrz na SSL_CTX_set_timeout() funkcji, która robi podobny do CURLOPT_TIMEOUT zmiennej libCurl za:

Od http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html:

SSL_CTX_set_timeout() ustawia timeout dla nowo utworzonych sesji dla CTX do t. Wartość limitu czasu t musi być podana w sekundach.

W twoim przypadku można dodać następującą linię po utworzeniu obiektu ctx:

SSL_CTX_set_timeout (ctx, 60); 

Nadzieję, że to pomaga!

+0

@ Wizzard - nie jestem pewien, czy tego właśnie szukałem. Dziękuję za odpowiedź. – jpen

+1

Wierzę, że 'SSL_CTX_set_timeout' i' SSL_SESSION_set_timeout' są czasem oczekiwania na buforowanie sesji i wznawianie; i nie jest przekroczeniem limitu czasu dla 'select'. – jww

2

Aby się połączyć, @jpen podał najlepszą odpowiedź. Musisz zaznaczyć BIO jako nieblokujący i użyć select do określenia, czy jest on połączony i/lub przekroczony czas.

Czyta się trochę inaczej. Ponieważ OpenSSL może buforować odszyfrowane dane (w zależności od używanego pakietu algorytmów TLS), select może przestać działać, gdy próbujesz odczytać - nawet jeśli dane rzeczywiście są dostępne. Odpowiednim sposobem obsługi limitów czasu odczytu jest sprawdzenie najpierw: SSL_pending lub BIO_pending. Jeśli oczekująca funkcja zwraca zero, użyj opcji select, aby ustawić limit czasu. Jeśli oczekująca funkcja zwróci wartość większą od zera, po prostu zadzwoń pod numer SSL_read lub BIO_read lub dowolną inną funkcję odczytu.

Powiązane problemy