NeoMutt  2019-12-07-168-gc45f47
Teaching an old dog new tricks
DOXYGEN
socket.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <errno.h>
33 #include <string.h>
34 #include <time.h>
35 #include "mutt/lib.h"
36 #include "socket.h"
37 #include "conn_globals.h"
38 #include "connaccount.h"
39 #include "connection.h"
40 #include "protos.h"
41 #include "ssl.h"
42 #include "tunnel.h"
43 
49 static int socket_preconnect(void)
50 {
51  if (!C_Preconnect)
52  return 0;
53 
54  mutt_debug(LL_DEBUG2, "Executing preconnect: %s\n", C_Preconnect);
55  const int rc = mutt_system(C_Preconnect);
56  mutt_debug(LL_DEBUG2, "Preconnect result: %d\n", rc);
57  if (rc != 0)
58  {
59  const int save_errno = errno;
60  mutt_perror(_("Preconnect command failed"));
61 
62  return save_errno;
63  }
64 
65  return 0;
66 }
67 
74 int mutt_socket_open(struct Connection *conn)
75 {
76  int rc;
77 
78  if (socket_preconnect())
79  return -1;
80 
81  rc = conn->conn_open(conn);
82 
83  mutt_debug(LL_DEBUG2, "Connected to %s:%d on fd=%d\n", conn->account.host,
84  conn->account.port, conn->fd);
85 
86  return rc;
87 }
88 
95 int mutt_socket_close(struct Connection *conn)
96 {
97  if (!conn)
98  return 0;
99 
100  int rc = -1;
101 
102  if (conn->fd < 0)
103  mutt_debug(LL_DEBUG1, "Attempt to close closed connection\n");
104  else
105  rc = conn->conn_close(conn);
106 
107  conn->fd = -1;
108  conn->ssf = 0;
109  conn->bufpos = 0;
110  conn->available = 0;
111 
112  return rc;
113 }
114 
123 int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
124 {
125  return conn->conn_read(conn, buf, len);
126 }
127 
136 int mutt_socket_write(struct Connection *conn, const char *buf, size_t len)
137 {
138  return conn->conn_write(conn, buf, len);
139 }
140 
150 int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
151 {
152  int sent = 0;
153 
154  mutt_debug(dbg, "%d> %s", conn->fd, buf);
155 
156  if (conn->fd < 0)
157  {
158  mutt_debug(LL_DEBUG1, "attempt to write to closed connection\n");
159  return -1;
160  }
161 
162  while (sent < len)
163  {
164  const int rc = conn->conn_write(conn, buf + sent, len - sent);
165  if (rc < 0)
166  {
167  mutt_debug(LL_DEBUG1, "error writing (%s), closing socket\n", strerror(errno));
168  mutt_socket_close(conn);
169 
170  return -1;
171  }
172 
173  if (rc < len - sent)
174  mutt_debug(LL_DEBUG3, "short write (%d of %d bytes)\n", rc, len - sent);
175 
176  sent += rc;
177  }
178 
179  return sent;
180 }
181 
190 int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
191 {
192  if (conn->bufpos < conn->available)
193  return conn->available - conn->bufpos;
194 
195  if (conn->conn_poll)
196  return conn->conn_poll(conn, wait_secs);
197 
198  return -1;
199 }
200 
208 int mutt_socket_readchar(struct Connection *conn, char *c)
209 {
210  if (conn->bufpos >= conn->available)
211  {
212  if (conn->fd >= 0)
213  conn->available = conn->conn_read(conn, conn->inbuf, sizeof(conn->inbuf));
214  else
215  {
216  mutt_debug(LL_DEBUG1, "attempt to read from closed connection\n");
217  return -1;
218  }
219  conn->bufpos = 0;
220  if (conn->available == 0)
221  {
222  mutt_error(_("Connection to %s closed"), conn->account.host);
223  }
224  if (conn->available <= 0)
225  {
226  mutt_socket_close(conn);
227  return -1;
228  }
229  }
230  *c = conn->inbuf[conn->bufpos];
231  conn->bufpos++;
232  return 1;
233 }
234 
244 int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
245 {
246  char ch;
247  int i;
248 
249  for (i = 0; i < buflen - 1; i++)
250  {
251  if (mutt_socket_readchar(conn, &ch) != 1)
252  {
253  buf[i] = '\0';
254  return -1;
255  }
256 
257  if (ch == '\n')
258  break;
259  buf[i] = ch;
260  }
261 
262  /* strip \r from \r\n termination */
263  if (i && (buf[i - 1] == '\r'))
264  i--;
265  buf[i] = '\0';
266 
267  mutt_debug(dbg, "%d< %s\n", conn->fd, buf);
268 
269  /* number of bytes read, not strlen */
270  return i + 1;
271 }
272 
279 {
280  struct Connection *conn = mutt_mem_calloc(1, sizeof(struct Connection));
281  conn->fd = -1;
282 
283  if (type == MUTT_CONNECTION_TUNNEL)
284  {
286  }
287  else if (type == MUTT_CONNECTION_SSL)
288  {
289  int ret = mutt_ssl_socket_setup(conn);
290 
291  if (ret < 0)
292  FREE(&conn);
293  }
294  else
295  {
296  conn->conn_read = raw_socket_read;
298  conn->conn_open = raw_socket_open;
300  conn->conn_poll = raw_socket_poll;
301  }
302 
303  return conn;
304 }
Tunnelled connection.
Definition: socket.h:36
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define mutt_perror(...)
Definition: logging.h:85
struct ConnAccount account
Definition: connection.h:36
unsigned int ssf
security strength factor, in bits
Definition: connection.h:37
int(* conn_open)(struct Connection *conn)
Open a socket Connection.
Definition: connection.h:53
int(* conn_read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection.
Definition: connection.h:62
An open network connection (socket)
struct Connection * mutt_socket_new(enum ConnectionType type)
allocate and initialise a new connection
Definition: socket.c:278
An open network connection (socket)
Definition: connection.h:34
#define _(a)
Definition: message.h:28
const char * C_Preconnect
Config: (socket) External command to run prior to opening a socket.
Definition: conn_globals.c:49
int mutt_ssl_socket_setup(struct Connection *conn)
Set up SSL socket mulitplexor.
Definition: ssl.c:1485
int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
Write data to a socket.
Definition: socket.c:150
Support for network tunnelling.
int mutt_socket_readchar(struct Connection *conn, char *c)
simple read buffering to speed things up
Definition: socket.c:208
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:74
char host[128]
Definition: connaccount.h:63
char inbuf[1024]
Definition: connection.h:39
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:190
Log at debug level 2.
Definition: logging.h:41
int(* conn_poll)(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block.
Definition: connection.h:80
unsigned short port
Definition: connaccount.h:64
Prototypes for many functions.
SSL/TLS-encrypted connection.
Definition: socket.h:37
int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a socket - Implements Connection::conn_write()
Definition: conn_raw.c:300
int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
read from a Connection
Definition: socket.c:123
int available
Definition: connection.h:43
static int socket_preconnect(void)
Execute a command before opening a socket.
Definition: socket.c:49
int(* conn_close)(struct Connection *conn)
Close a socket Connection.
Definition: connection.h:87
int raw_socket_close(struct Connection *conn)
Close a socket - Implements Connection::conn_close()
Definition: conn_raw.c:369
int raw_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block - Implements Connection::conn_poll()
Definition: conn_raw.c:330
int(* conn_write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection.
Definition: connection.h:71
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:95
int raw_socket_read(struct Connection *conn, char *buf, size_t count)
Read data from a socket - Implements Connection::conn_read()
Definition: conn_raw.c:270
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
int mutt_socket_write(struct Connection *conn, const char *buf, size_t len)
write to a Connection
Definition: socket.c:136
int raw_socket_open(struct Connection *conn)
Open a socket - Implements Connection::conn_open()
Definition: conn_raw.c:122
#define FREE(x)
Definition: memory.h:40
Handling of OpenSSL encryption.
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:244
int bufpos
Definition: connection.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Connection Credentials.
Convenience wrapper for the library headers.
Low-level socket handling.
ConnectionType
Type of connection.
Definition: socket.h:33
void mutt_tunnel_socket_setup(struct Connection *conn)
sets up tunnel connection functions
Definition: tunnel.c:234
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:52
Log at debug level 3.
Definition: logging.h:42
Connection Global Variables.