Qsmtp  0.30dev
Macros | Functions | Variables
netio.c File Reference

functions for network I/O More...

#include <netio.h>
#include <log.h>
#include <ssl_timeoutio.h>
#include <tls.h>
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>

Macros

#define _GNU_SOURCE   /* to get POLLRDHUP if possible */
 
#define POLL_IN_OR_ERROR   POLLIN
 
#define DEBUG_IN(l)   {}
 
#define DEBUG_OUT(s, l)   {}
 

Functions

static void get_from_inbuffer (char *dest, const size_t len, const size_t droplen)
 
static size_t readinput (char *buffer, const size_t len, const int fatal)
 
static const char * find_eol (const char *buffer, const size_t buflen, int *valid)
 
static void loop_long (int has_cr)
 
int net_read (const int fatal)
 read one line from the network More...
 
int netnwrite (const char *s, const size_t l)
 
int net_writen (const char *const *s)
 
int net_write_multiline (const char *const *s)
 
size_t net_readbin (size_t num, char *buf)
 
size_t net_readline (size_t num, char *buf)
 
int data_pending (void)
 check if there is data ready to be read without blocking More...
 

Variables

static char lineinbuf [1002]
 
struct string linein
 
static char lineinn [sizeof(lineinbuf)]
 
static size_t linenlen
 
time_t timeout
 

Detailed Description

functions for network I/O

Function Documentation

int data_pending ( void  )

check if there is data ready to be read without blocking

Returns
if there is data available
Return values
0if no data
1if data
<0error code

This will return -ECONNRESET if the connection has been closed by the remote end.

static const char* find_eol ( const char *  buffer,
const size_t  buflen,
int *  valid 
)
static

detect the end of the first line in the given buffer

Parameters
bufferinput buffer to check
buflenamount of data in buffer
valida flag is stored here if the line is valid
Returns
the first character after the line end
Return values
NULLbuffer does neither contain CR nor LF

If the buffer begins with a sequence of characters that contains a stray CR or LF a pointer one character behind this is returned and valid is set to 0. If the buffer begins with a valid line ending in CRLF a pointer behind the LF is returned. If neither CR nor LF is found NULL is returned.

static void get_from_inbuffer ( char *  dest,
const size_t  len,
const size_t  droplen 
)
static

read the first characters of lineinn

Parameters
destdestination buffer or NULL to simply drop the data
lencharacters to copy
droplenadditional characters to drop (usually 2 to drop CRLF)

Move the rest of the buffer content forward (if any).

static void loop_long ( int  has_cr)
static

read input until a line with a valid length is in buffer

Parameters
has_crif the previous buffer ended with CR

This function will set errno to the proper error code before returning.

int net_read ( const int  fatal)

read one line from the network

Parameters
fatalif connection errors should lead to program termination
Return values
0on success
-1on error (errno is set)

does not return on timeout, program will be cancelled

size_t net_readbin ( size_t  num,
char *  buf 
)

read a given number of bytes from network as binary data (i.e. without any mangling)

Parameters
numnumber of bytes to read
bufbuffer to store data (must have enough space for (num + 1) bytes)
Returns
number of bytes read
Return values
-1on error
size_t net_readline ( size_t  num,
char *  buf 
)

read up to a given number of bytes from network but stop at the first CRLF

Parameters
numnumber of bytes to read, must be < 1002 so everything behind the CRLF can be copied back to lineinn
bufbuffer to store data (must have enough space)
Returns
number of bytes read
Return values
-1on error

The trailing CRLF sequence is kept in the buffer. This function will return an error if it detects a bare CR or LF in the middle of the input data, but it cannot detect if the CR goes in one call and LF in the next, so it will allow the output to be just LF or to end in CR.

int net_write_multiline ( const char *const *  s)

write multiple lines to the network

Parameters
sarray of strings to send
Return values
0on success
-1on error (errno is set)

This combines all given strings into one buffer and send them out to the network. This allows the underlying network stack to use the least sensible number of packets, reducing network latency. If memory allocation fails for the intermediate buffer the lines may be send in smaller chunks, which is less efficient but is no other loss in functionality.

Does not return on timeout, program will be cancelled.

If one part or multiple consecutive parts covers a whole SMTP line this line must conform to the SMTP line length limit (512 bytes).

int net_writen ( const char *const *  s)

write one line to the network, fold if needed

Parameters
sarray of strings to send
Return values
0on success
-1on error (errno is set)

does not return on timeout, program will be cancelled

Warning
s[0] must be short enough to fit completely into the buffer
s[0] must contain the whole status code as well as the following space (' ') or hyphen ('-')
every s[] must not have a sequence longer then 506 characters without a space (' ') in them
int netnwrite ( const char *  s,
const size_t  l 
)

write one line to the network

Parameters
sline to be written (nothing else it written so it should contain CRLF)
llength of s
Return values
0on success
-1on error (errno is set)

does not return on timeout, program will be cancelled

static size_t readinput ( char *  buffer,
const size_t  len,
const int  fatal 
)
static

read characters from (network) input

Parameters
bufferbuffer to put the data in
lenmaximum length of data to read (one char less is read, the last one is set to '\0')
fatalif connection errors should lead to program termination
Returns
number of bytes read
Return values
-1on error (errno is set)

Variable Documentation

struct string linein
Initial value:
= {
.s = lineinbuf
}
static char lineinbuf[1002]
Definition: netio.c:25
char lineinbuf[1002]
static

buffer for the line to read: max 1000 chars including CRLF, leading extra '.', closing '\0'

char lineinn[sizeof(lineinbuf)]
static

if more than one line was in linein the rest is stored here

size_t linenlen
static

length of the lineinn

time_t timeout

how long to wait for data