src/sock_gnutls.c
changeset 12 4147fae232d9
parent 10 9fe218576d13
child 14 3a70e5901f17
equal deleted inserted replaced
11:14e79683c48c 12:4147fae232d9
     6 
     6 
     7 // XXX: errors
     7 // XXX: errors
     8 static err_t sock_gnutls_read (struct sock_stream *base_sock, void *buf, size_t *len)
     8 static err_t sock_gnutls_read (struct sock_stream *base_sock, void *buf, size_t *len)
     9 {
     9 {
    10     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
    10     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
       
    11     struct error_info *err = SOCK_GNUTLS_ERR(sock);
    11     int ret;
    12     int ret;
    12     
    13     
    13     // just map to gnutls_record_recv
    14     // read gnutls record
    14     if ((ret = gnutls_record_recv(sock->session, buf, *len)) < 0)
    15     ret = gnutls_record_recv(sock->session, buf, *len);
    15         RETURN_SET_ERROR_ERRNO(SOCK_GNUTLS_ERR(sock), ERR_GNUTLS_RECORD_RECV);
    16     
    16     
    17     // errors
    17     // updated length
    18     if (ret < 0 && ret != GNUTLS_E_AGAIN)
    18     *len = ret;
    19         RETURN_SET_ERROR_EXTRA(err, ERR_GNUTLS_RECORD_RECV, ret);
       
    20     
       
    21     else if (ret == 0)
       
    22         return SET_ERROR(err, ERR_READ_EOF);
       
    23 
       
    24 
       
    25     // eagain?
       
    26     if (ret == 0) {
       
    27         *len = 0;
       
    28 
       
    29     } else {
       
    30         // updated length
       
    31         *len = ret;
       
    32 
       
    33     }
    19 
    34 
    20     return SUCCESS;
    35     return SUCCESS;
    21 }
    36 }
    22 
    37 
    23 static err_t sock_gnutls_write (struct sock_stream *base_sock, const void *buf, size_t *len)
    38 static err_t sock_gnutls_write (struct sock_stream *base_sock, const void *buf, size_t *len)
    24 {
    39 {
    25     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
    40     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
       
    41     struct error_info *err = SOCK_GNUTLS_ERR(sock);
    26     int ret;
    42     int ret;
    27     
    43  
    28     // just map to gnutls_record_send
    44     // read gnutls record
    29     if ((ret = gnutls_record_send(sock->session, buf, *len)) < 0)
    45     ret = gnutls_record_send(sock->session, buf, *len);
    30         RETURN_SET_ERROR_ERRNO(SOCK_GNUTLS_ERR(sock), ERR_GNUTLS_RECORD_SEND);
    46     
    31     
    47     // errors
    32     // updated length
    48     if (ret < 0 && ret != GNUTLS_E_AGAIN)
    33     *len = ret;
    49         RETURN_SET_ERROR_EXTRA(err, ERR_GNUTLS_RECORD_RECV, ret);
    34 
    50     
    35     return SUCCESS;
    51     else if (ret == 0)
       
    52         return SET_ERROR(err, ERR_READ_EOF);
       
    53 
       
    54 
       
    55     // eagain?
       
    56     if (ret == 0) {
       
    57         *len = 0;
       
    58 
       
    59     } else {
       
    60         // updated length
       
    61         *len = ret;
       
    62     }
       
    63 
       
    64     return SUCCESS;
       
    65 }
       
    66 
       
    67 static void sock_gnutls_event_handler (int fd, short what, void *arg)
       
    68 {
       
    69     struct sock_gnutls *sock = arg;
       
    70     
       
    71     // gnutls might be able to proceed now, so ask user to try what didn't work before now, using the mask given to
       
    72     // event_enable().
       
    73     sock_stream_invoke_callbacks(SOCK_GNUTLS_BASE(sock), sock->ev_mask);
    36 }
    74 }
    37 
    75 
    38 static err_t sock_gnutls_event_init (struct sock_stream *base_sock)
    76 static err_t sock_gnutls_event_init (struct sock_stream *base_sock)
    39 {
    77 {
    40     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
    78     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
    41     
    79 
       
    80     err_t err;
       
    81 
       
    82     // set nonblocking
       
    83     if ((err = sock_tcp_set_nonblock(SOCK_GNUTLS_TCP(sock), 1)))
       
    84         return err;
       
    85 
       
    86     // add ourselves as the event handler
       
    87     if ((err = sock_tcp_init_ev(SOCK_GNUTLS_TCP(sock), &sock_gnutls_event_handler, sock)))
       
    88         return err;
       
    89 
       
    90     // ok
    42     return SUCCESS;
    91     return SUCCESS;
    43 }
    92 }
    44 
    93 
    45 static err_t sock_gnutls_event_enable (struct sock_stream *base_sock, short mask)
    94 static err_t sock_gnutls_event_enable (struct sock_stream *base_sock, short mask)
    46 {
    95 {
    47     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
    96     struct sock_gnutls *sock = SOCK_FROM_BASE(base_sock, struct sock_gnutls);
    48     
    97     int ret;
       
    98     
       
    99     // store the ev_mask. We don't care about it here, because we assume that event_enable is only called once read or
       
   100     // write, respectively, return zero. This is really the only case we can handle with gnutls.
       
   101     sock->ev_mask = mask;
       
   102 
       
   103     // gnutls_record_get_direction tells us what I/O operation gnutls would have required for the last
       
   104     // operation, so we can use that to determine what events to register
       
   105     switch ((ret = gnutls_record_get_direction(sock->session))) {
       
   106         case 0: 
       
   107             // read more data
       
   108             sock_tcp_add_event(SOCK_GNUTLS_TCP(sock), EV_READ); 
       
   109             break;
       
   110         
       
   111         case 1:
       
   112             // write buffer full
       
   113             sock_tcp_add_event(SOCK_GNUTLS_TCP(sock), EV_WRITE);
       
   114             break;
       
   115         
       
   116         default:
       
   117             // random error
       
   118             RETURN_SET_ERROR_EXTRA(SOCK_GNUTLS_ERR(sock), ERR_GNUTLS_RECORD_GET_DIRECTION, ret);
       
   119     }
       
   120     
       
   121     // ok... wait
    49     return SUCCESS;
   122     return SUCCESS;
    50 }
   123 }
    51 
   124 
    52 /*
   125 /*
    53  * Our sock_stream_Type
   126  * Our sock_stream_Type