NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
socket.c File Reference

Low-level socket handling. More...

#include "config.h"
#include <errno.h>
#include <string.h>
#include <time.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "socket.h"
#include "connaccount.h"
#include "connection.h"
#include "protos.h"
#include "ssl.h"
+ Include dependency graph for socket.c:

Go to the source code of this file.

Functions

static int socket_preconnect (void)
 Execute a command before opening a socket. More...
 
int mutt_socket_open (struct Connection *conn)
 Simple wrapper. More...
 
int mutt_socket_close (struct Connection *conn)
 Close a socket. More...
 
int mutt_socket_read (struct Connection *conn, char *buf, size_t len)
 read from a Connection More...
 
int mutt_socket_write (struct Connection *conn, const char *buf, size_t len)
 write to a Connection More...
 
int mutt_socket_write_d (struct Connection *conn, const char *buf, int len, int dbg)
 Write data to a socket. More...
 
int mutt_socket_poll (struct Connection *conn, time_t wait_secs)
 Checks whether reads would block. More...
 
int mutt_socket_readchar (struct Connection *conn, char *c)
 simple read buffering to speed things up More...
 
int mutt_socket_readln_d (char *buf, size_t buflen, struct Connection *conn, int dbg)
 Read a line from a socket. More...
 
struct Connectionmutt_socket_new (enum ConnectionType type)
 allocate and initialise a new connection More...
 
void mutt_socket_empty (struct Connection *conn)
 Clear out any queued data. More...
 

Detailed Description

Low-level socket handling.

Authors
  • Michael R. Elkins
  • Brendan Cully
  • Tommi Komulainen

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file socket.c.

Function Documentation

◆ socket_preconnect()

static int socket_preconnect ( void  )
static

Execute a command before opening a socket.

Return values
0Success
>0An errno, e.g. EPERM

Definition at line 50 of file socket.c.

51 {
52  const char *const c_preconnect = cs_subset_string(NeoMutt->sub, "preconnect");
53  if (!c_preconnect)
54  return 0;
55 
56  mutt_debug(LL_DEBUG2, "Executing preconnect: %s\n", c_preconnect);
57  const int rc = mutt_system(c_preconnect);
58  mutt_debug(LL_DEBUG2, "Preconnect result: %d\n", rc);
59  if (rc != 0)
60  {
61  const int save_errno = errno;
62  mutt_perror(_("Preconnect command failed"));
63 
64  return save_errno;
65  }
66 
67  return 0;
68 }
#define _(a)
Definition: message.h:28
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
Log at debug level 2.
Definition: logging.h:41
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_socket_open()

int mutt_socket_open ( struct Connection conn)

Simple wrapper.

Parameters
connConnection to a server
Return values
0Success
-1Error

Definition at line 76 of file socket.c.

77 {
78  int rc;
79 
80  if (socket_preconnect())
81  return -1;
82 
83  rc = conn->open(conn);
84 
85  mutt_debug(LL_DEBUG2, "Connected to %s:%d on fd=%d\n", conn->account.host,
86  conn->account.port, conn->fd);
87 
88  return rc;
89 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
int(* open)(struct Connection *conn)
Definition: connection.h:69
char host[128]
Server to login to.
Definition: connaccount.h:53
Log at debug level 2.
Definition: logging.h:41
unsigned short port
Port to connect to.
Definition: connaccount.h:57
int fd
Socket file descriptor.
Definition: connection.h:44
static int socket_preconnect(void)
Execute a command before opening a socket.
Definition: socket.c:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_socket_close()

int mutt_socket_close ( struct Connection conn)

Close a socket.

Parameters
connConnection to a server
Return values
0Success
-1Error

Definition at line 97 of file socket.c.

98 {
99  if (!conn)
100  return 0;
101 
102  int rc = -1;
103 
104  if (conn->fd < 0)
105  mutt_debug(LL_DEBUG1, "Attempt to close closed connection\n");
106  else
107  rc = conn->close(conn);
108 
109  conn->fd = -1;
110  conn->ssf = 0;
111  conn->bufpos = 0;
112  conn->available = 0;
113 
114  return rc;
115 }
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:41
int(* close)(struct Connection *conn)
Definition: connection.h:119
int fd
Socket file descriptor.
Definition: connection.h:44
int available
Amount of data waiting to be read.
Definition: connection.h:45
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
int bufpos
Current position in the buffer.
Definition: connection.h:43
+ Here is the caller graph for this function:

◆ mutt_socket_read()

int mutt_socket_read ( struct Connection conn,
char *  buf,
size_t  len 
)

read from a Connection

Parameters
connConnection a server
bufBuffer to store read data
lenlength of the buffer
Return values
>0Success, number of bytes read
-1Error, see errno

Definition at line 125 of file socket.c.

126 {
127  return conn->read(conn, buf, len);
128 }
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:82
const char * buf
Definition: sasl.c:67
+ Here is the caller graph for this function:

◆ mutt_socket_write()

int mutt_socket_write ( struct Connection conn,
const char *  buf,
size_t  len 
)

write to a Connection

Parameters
connConnection to a server
bufBuffer with data to write
lenLength of data to write
Return values
>0Number of bytes written
-1Error

Definition at line 138 of file socket.c.

139 {
140  return conn->write(conn, buf, len);
141 }
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:95
const char * buf
Definition: sasl.c:67

◆ mutt_socket_write_d()

int mutt_socket_write_d ( struct Connection conn,
const char *  buf,
int  len,
int  dbg 
)

Write data to a socket.

Parameters
connConnection to a server
bufBuffer with data to write
lenLength of data to write
dbgDebug level for logging
Return values
>0Number of bytes written
-1Error

Definition at line 152 of file socket.c.

153 {
154  int sent = 0;
155 
156  mutt_debug(dbg, "%d> %s", conn->fd, buf);
157 
158  if (conn->fd < 0)
159  {
160  mutt_debug(LL_DEBUG1, "attempt to write to closed connection\n");
161  return -1;
162  }
163 
164  while (sent < len)
165  {
166  const int rc = conn->write(conn, buf + sent, len - sent);
167  if (rc < 0)
168  {
169  mutt_debug(LL_DEBUG1, "error writing (%s), closing socket\n", strerror(errno));
170  mutt_socket_close(conn);
171 
172  return -1;
173  }
174 
175  if (rc < len - sent)
176  mutt_debug(LL_DEBUG3, "short write (%d of %d bytes)\n", rc, len - sent);
177 
178  sent += rc;
179  }
180 
181  return sent;
182 }
int fd
Socket file descriptor.
Definition: connection.h:44
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
Log at debug level 1.
Definition: logging.h:40
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:95
const char * buf
Definition: sasl.c:67
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:

◆ mutt_socket_poll()

int mutt_socket_poll ( struct Connection conn,
time_t  wait_secs 
)

Checks whether reads would block.

Parameters
connConnection to a server
wait_secsHow long to wait for a response
Return values
>0There is data to read
0Read would block
-1Connection doesn't support polling

Definition at line 192 of file socket.c.

193 {
194  if (conn->bufpos < conn->available)
195  return conn->available - conn->bufpos;
196 
197  if (conn->poll)
198  return conn->poll(conn, wait_secs);
199 
200  return -1;
201 }
int available
Amount of data waiting to be read.
Definition: connection.h:45
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:108
int bufpos
Current position in the buffer.
Definition: connection.h:43
+ Here is the caller graph for this function:

◆ mutt_socket_readchar()

int mutt_socket_readchar ( struct Connection conn,
char *  c 
)

simple read buffering to speed things up

Parameters
[in]connConnection to a server
[out]cCharacter that was read
Return values
1Success
-1Error

Definition at line 210 of file socket.c.

211 {
212  if (conn->bufpos >= conn->available)
213  {
214  if (conn->fd >= 0)
215  conn->available = conn->read(conn, conn->inbuf, sizeof(conn->inbuf));
216  else
217  {
218  mutt_debug(LL_DEBUG1, "attempt to read from closed connection\n");
219  return -1;
220  }
221  conn->bufpos = 0;
222  if (conn->available == 0)
223  {
224  mutt_error(_("Connection to %s closed"), conn->account.host);
225  }
226  if (conn->available <= 0)
227  {
228  mutt_socket_close(conn);
229  return -1;
230  }
231  }
232  *c = conn->inbuf[conn->bufpos];
233  conn->bufpos++;
234  return 1;
235 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
#define mutt_error(...)
Definition: logging.h:88
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:82
#define _(a)
Definition: message.h:28
char host[128]
Server to login to.
Definition: connaccount.h:53
char inbuf[1024]
Buffer for incoming traffic.
Definition: connection.h:42
int fd
Socket file descriptor.
Definition: connection.h:44
int available
Amount of data waiting to be read.
Definition: connection.h:45
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
Log at debug level 1.
Definition: logging.h:40
int bufpos
Current position in the buffer.
Definition: connection.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_socket_readln_d()

int mutt_socket_readln_d ( char *  buf,
size_t  buflen,
struct Connection conn,
int  dbg 
)

Read a line from a socket.

Parameters
bufBuffer to store the line
buflenLength of data to write
connConnection to a server
dbgDebug level for logging
Return values
>0Success, number of bytes read
-1Error

Definition at line 246 of file socket.c.

247 {
248  char ch;
249  int i;
250 
251  for (i = 0; i < buflen - 1; i++)
252  {
253  if (mutt_socket_readchar(conn, &ch) != 1)
254  {
255  buf[i] = '\0';
256  return -1;
257  }
258 
259  if (ch == '\n')
260  break;
261  buf[i] = ch;
262  }
263 
264  /* strip \r from \r\n termination */
265  if (i && (buf[i - 1] == '\r'))
266  i--;
267  buf[i] = '\0';
268 
269  mutt_debug(dbg, "%d< %s\n", conn->fd, buf);
270 
271  /* number of bytes read, not strlen */
272  return i + 1;
273 }
int mutt_socket_readchar(struct Connection *conn, char *c)
simple read buffering to speed things up
Definition: socket.c:210
int fd
Socket file descriptor.
Definition: connection.h:44
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
const char * buf
Definition: sasl.c:67
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_socket_new()

struct Connection* mutt_socket_new ( enum ConnectionType  type)

allocate and initialise a new connection

Parameters
typeType of the new Connection
Return values
ptrNew Connection

Definition at line 280 of file socket.c.

281 {
282  struct Connection *conn = mutt_mem_calloc(1, sizeof(struct Connection));
283  conn->fd = -1;
284 
285  if (type == MUTT_CONNECTION_TUNNEL)
286  {
288  }
289  else if (type == MUTT_CONNECTION_SSL)
290  {
291  int rc = mutt_ssl_socket_setup(conn);
292  if (rc < 0)
293  FREE(&conn);
294  }
295  else
296  {
297  conn->read = raw_socket_read;
298  conn->write = raw_socket_write;
299  conn->open = raw_socket_open;
300  conn->close = raw_socket_close;
301  conn->poll = raw_socket_poll;
302  }
303 
304  return conn;
305 }
Tunnelled connection.
Definition: socket.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:82
int(* open)(struct Connection *conn)
Definition: connection.h:69
int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a socket - Implements Connection::write() -.
Definition: raw.c:297
int(* close)(struct Connection *conn)
Definition: connection.h:119
SSL/TLS-encrypted connection.
Definition: socket.h:38
int fd
Socket file descriptor.
Definition: connection.h:44
int raw_socket_open(struct Connection *conn)
Open a socket - Implements Connection::open() -.
Definition: raw.c:120
void mutt_tunnel_socket_setup(struct Connection *conn)
sets up tunnel connection functions
Definition: tunnel.c:233
int raw_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block - Implements Connection::poll() -.
Definition: raw.c:327
int raw_socket_close(struct Connection *conn)
Close a socket - Implements Connection::close() -.
Definition: raw.c:365
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:108
int raw_socket_read(struct Connection *conn, char *buf, size_t len)
Read data from a socket - Implements Connection::read() -.
Definition: raw.c:267
int mutt_ssl_socket_setup(struct Connection *conn)
Set up SSL socket mulitplexor.
Definition: gnutls.c:1147
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:95
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_socket_empty()

void mutt_socket_empty ( struct Connection conn)

Clear out any queued data.

The internal buffer is emptied and any data that has already arrived at this machine (in kernel buffers) is read and dropped.

Definition at line 313 of file socket.c.

314 {
315  if (!conn)
316  return;
317 
318  char buf[1024];
319  int bytes;
320 
321  while ((bytes = mutt_socket_poll(conn, 0)) > 0)
322  {
323  mutt_socket_read(conn, buf, MIN(bytes, sizeof(buf)));
324  }
325 }
#define MIN(a, b)
Definition: memory.h:31
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:192
int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
read from a Connection
Definition: socket.c:125
+ Here is the call graph for this function:
+ Here is the caller graph for this function: