LCOV - code coverage report
Current view: top level - lib - client.c (source / functions) Hit Total Coverage
Test: smtpd.info Lines: 33 56 58.9 %
Date: 2015-11-25 19:06:20 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* This file is part of the cmail project (http://cmail.rocks/)
       2             :  * (c) 2015 Fabian "cbdev" Stumpf
       3             :  * License: Simplified BSD (2-Clause)
       4             :  * For further information, consult LICENSE.txt
       5             :  */
       6             : 
       7         350 : ssize_t client_send_raw(LOGGER log, CONNECTION* client, char* data, ssize_t bytes){
       8         350 :         ssize_t bytes_sent = 0, bytes_written = 0, bytes_left;
       9             : 
      10             :         //early bail saves some syscalls
      11         350 :         if(bytes == 0){
      12           0 :                 return 0;
      13             :         }
      14             : 
      15         350 :         if(bytes < 0){
      16           0 :                 bytes=strlen(data);
      17             :         }
      18             : 
      19         350 :         logprintf(log, LOG_DEBUG, "Sending %d raw bytes\n", bytes);
      20             : 
      21             :         do{
      22         350 :                 bytes_left = bytes - bytes_sent;
      23         350 :                 if(bytes_left > MAX_SEND_CHUNK){
      24           0 :                         bytes_left = MAX_SEND_CHUNK;
      25             :                 }
      26             :                 #ifndef CMAIL_NO_TLS
      27         350 :                 switch(client->tls_mode){
      28             :                         case TLS_NONE:
      29         240 :                                 bytes_written = send(client->fd, data + bytes_sent, bytes_left, 0);
      30         240 :                                 break;
      31             :                         case TLS_NEGOTIATE:
      32           0 :                                 logprintf(log, LOG_WARNING, "Not sending data while negotiation is in progress\n");
      33           0 :                                 return bytes_sent;
      34             :                         case TLS_ONLY:
      35         110 :                                 bytes_written = gnutls_record_send(client->tls_session, data + bytes_sent, bytes_left);
      36         110 :                                 break;
      37             :                 }
      38             :                 #else
      39             :                 bytes_written = send(client->fd, data + bytes_sent, bytes_left, 0);
      40             :                 #endif
      41             : 
      42         350 :                 if(bytes_written + bytes_sent < bytes){
      43           0 :                         logprintf(log, LOG_DEBUG, "Partial write (%d for %d/%d)\n", bytes_written, bytes_sent, bytes);
      44             :                 }
      45             : 
      46         350 :                 if(bytes_written < 0){
      47             :                         #ifndef CMAIL_NO_TLS
      48           0 :                         if(client->tls_mode == TLS_NONE){
      49             :                         #endif
      50           0 :                         if(errno != EAGAIN){
      51           0 :                                 logprintf(log, LOG_ERROR, "Write failed: %s\n", strerror(errno));
      52           0 :                                 break;
      53             :                         }
      54             :                         #ifndef CMAIL_NO_TLS
      55             :                         }
      56             :                         else{
      57           0 :                                 if(bytes_written != GNUTLS_E_INTERRUPTED && bytes_written != GNUTLS_E_AGAIN){
      58           0 :                                         logprintf(log, LOG_ERROR, "TLS Write failed: %s\n", gnutls_strerror(bytes_written));
      59           0 :                                         break;
      60             :                                 }
      61             :                         }
      62             :                         #endif
      63             :                 }
      64             :                 else{
      65         350 :                         bytes_sent += bytes_written;
      66             :                 }
      67             :         }
      68         350 :         while(bytes_sent < bytes);
      69             : 
      70         350 :         logprintf(log, LOG_ALL_IO, "<< %.*s", bytes, data);
      71         350 :         logprintf(log, LOG_DEBUG, "Sent %d bytes of %d\n", bytes_sent, bytes);
      72             : 
      73         350 :         return bytes_sent;
      74             : }
      75             : 
      76         350 : int client_send(LOGGER log, CONNECTION* client, char* fmt, ...){
      77             :         va_list args, copy;
      78         350 :         ssize_t bytes = 0;
      79             :         char static_send_buffer[STATIC_SEND_BUFFER_LENGTH + 1];
      80         350 :         char* dynamic_send_buffer = NULL;
      81         350 :         char* send_buffer = static_send_buffer;
      82             : 
      83         350 :         va_start(args, fmt);
      84         350 :         va_copy(copy, args);
      85             :         //check if the buffer was long enough, if not, allocate a new one
      86         350 :         bytes = vsnprintf(send_buffer, STATIC_SEND_BUFFER_LENGTH, fmt, args);
      87         350 :         va_end(args);
      88             : 
      89         350 :         if(bytes >= STATIC_SEND_BUFFER_LENGTH){
      90           0 :                 dynamic_send_buffer = calloc(bytes + 2, sizeof(char));
      91           0 :                 if(!dynamic_send_buffer){
      92           0 :                         logprintf(log, LOG_ERROR, "Failed to allocate dynamic send buffer\n");
      93           0 :                         va_end(copy);
      94           0 :                         return -1;
      95             :                 }
      96           0 :                 send_buffer = dynamic_send_buffer;
      97           0 :                 bytes = vsnprintf(send_buffer, bytes + 1, fmt, copy);
      98             :         }
      99         350 :         va_end(copy);
     100             : 
     101         350 :         if(bytes < 0){
     102           0 :                 logprintf(log, LOG_ERROR, "Failed to render client output data string\n");
     103           0 :                 return -1;
     104             :         }
     105             : 
     106         350 :         bytes = client_send_raw(log, client, send_buffer, bytes);
     107             : 
     108         350 :         if(dynamic_send_buffer){
     109           0 :                 free(dynamic_send_buffer);
     110             :         }
     111             : 
     112         350 :         return bytes;
     113             : }

Generated by: LCOV version 1.11