2014-06-12 17 views
7

Le funzioni socket come send e receive possono essere interrotte dai segnali. Per questo motivo è necessario un codice aggiuntivo, ad es. controllare errno == EINTR. Questo è descritto nelle pagine man corrispondenti.OpenSSL e segnali

Mi chiedo come funzioni quando vengono utilizzate le funzioni OpenSSL, ad es. SSL_write, SSL_read. Le loro pagine man non dicono nulla sui segnali. Ho anche provato a google per questo, ma senza fortuna. Sai se OpenSSL gestisce i segnali internamente o è necessario un codice aggiuntivo? Se sì, come verificare se la chiamata alla funzione è stata interrotta dal segnale?

Aggiornamento:

sguardi che OpenSSL non gestisce tentativi. Imposta solo il flag "dovrebbe riprovare" sull'oggetto BIO. Così ho bisogno di usare qualcosa di simile per rilevare se chiamata è stata interrotta ed è necessario tentativo:

int result = SSL_write(ssl, buff, length); 
if ((result < 0) && BIO_should_retry(SSL_get_wbio(ssl))) 
    // need to retry 

int result = SSL_read(ssl, buff, length); 
if ((result < 0) && BIO_should_retry(SSL_get_rbio(ssl))) 
    // need to retry 

risposta

3

Come essere un OpenSSL libray non può fare alcuna ipotesi su come i segnali vengono gestiti dal programma particolare usarlo. Quindi deve gestire il caso in cui una chiamata di sistema viene interrotta alla ricezione di un segnale.

Verificare se fosse opportuno riprovare un errore read() implementato in OpenSSL.

Utilizzare BIO_should_retry() se BIO_read() (o BIO_write()) non riuscito.

Per un esempio leggere qui: http://cvs.openssl.org/rlog?f=openssl/demos/bio/sconnect.c

relativo codice del attuazione segue:

static int sock_read(BIO *b, char *out, int outl) 
    { 
    int ret=0; 

    if (out != NULL) 
      { 
      clear_socket_error(); 
      ret=readsocket(b->num,out,outl); 
      BIO_clear_retry_flags(b); 
      if (ret <= 0) 
        { 
        if (BIO_sock_should_retry(ret)) 
          BIO_set_retry_read(b); 
        } 
      } 
    return(ret); 
    } 

Le funzioni di cui rilevanti sono qui:

(get_last_socket_error() rendimenti errno sulla maggior parte delle piattaforme IXish)

int BIO_sock_should_retry(int i) 
    { 
    int err; 

    if ((i == 0) || (i == -1)) 
      { 
      err=get_last_socket_error(); 

#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ 
      if ((i == -1) && (err == 0)) 
        return(1); 
#endif 

      return(BIO_sock_non_fatal_error(err)); 
      } 
    return(0); 
    } 


int BIO_sock_non_fatal_error(int err) 
     { 
     switch (err) 
       { 
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_NETWARE) 
# if defined(WSAEWOULDBLOCK) 
     case WSAEWOULDBLOCK: 
# endif 

# if 0 /* This appears to always be an error */ 
# if defined(WSAENOTCONN) 
     case WSAENOTCONN: 
# endif 
# endif 
#endif 

#ifdef EWOULDBLOCK 
# ifdef WSAEWOULDBLOCK 
# if WSAEWOULDBLOCK != EWOULDBLOCK 
     case EWOULDBLOCK: 
# endif 
# else 
     case EWOULDBLOCK: 
# endif 
#endif 

#if defined(ENOTCONN) 
     case ENOTCONN: 
#endif 

#ifdef EINTR 
     case EINTR: 
#endif 

#ifdef EAGAIN 
# if EWOULDBLOCK != EAGAIN 
     case EAGAIN: 
# endif 
#endif 

#ifdef EPROTO 
     case EPROTO: 
#endif 

#ifdef EINPROGRESS 
     case EINPROGRESS: 
#endif 

#ifdef EALREADY 
     case EALREADY: 
#endif 
       return(1); 
       /* break; */ 
     default: 
       break; 
       } 
     return(0); 
     } 

Per i dettagli vedere sock_read() da ispezionare qui: http://cvs.openssl.org/rlog?f=openssl/crypto/bio/bss_sock.c

(Le fonti citate insieme con l'indentazione utilizzato è dalla versione 1.0.1e.)