NeoMutt  2022-04-29-323-g5fcc6c
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 <stdbool.h>
34#include <string.h>
35#include <time.h>
36#include "private.h"
37#include "mutt/lib.h"
38#include "config/lib.h"
39#include "core/lib.h"
40#include "socket.h"
41#include "connaccount.h"
42#include "connection.h"
43#include "protos.h"
44#include "ssl.h"
45
51static int socket_preconnect(void)
52{
53 const char *const c_preconnect = cs_subset_string(NeoMutt->sub, "preconnect");
54 if (!c_preconnect)
55 return 0;
56
57 mutt_debug(LL_DEBUG2, "Executing preconnect: %s\n", c_preconnect);
58 const int rc = mutt_system(c_preconnect);
59 mutt_debug(LL_DEBUG2, "Preconnect result: %d\n", rc);
60 if (rc != 0)
61 {
62 const int save_errno = errno;
63 mutt_perror(_("Preconnect command failed"));
64
65 return save_errno;
66 }
67
68 return 0;
69}
70
78{
79 int rc;
80
82 return -1;
83
84 rc = conn->open(conn);
85
86 if (rc >= 0)
87 {
88 mutt_debug(LL_DEBUG2, "Connected to %s:%d on fd=%d\n", conn->account.host,
89 conn->account.port, conn->fd);
90 }
91
92 return rc;
93}
94
102{
103 if (!conn)
104 return 0;
105
106 int rc = -1;
107
108 if (conn->fd < 0)
109 mutt_debug(LL_DEBUG1, "Attempt to close closed connection\n");
110 else
111 rc = conn->close(conn);
112
113 conn->fd = -1;
114 conn->ssf = 0;
115 conn->bufpos = 0;
116 conn->available = 0;
117
118 return rc;
119}
120
129int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
130{
131 return conn->read(conn, buf, len);
132}
133
142int mutt_socket_write(struct Connection *conn, const char *buf, size_t len)
143{
144 return conn->write(conn, buf, len);
145}
146
156int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
157{
158 int sent = 0;
159
160 mutt_debug(dbg, "%d> %s", conn->fd, buf);
161
162 if (conn->fd < 0)
163 {
164 mutt_debug(LL_DEBUG1, "attempt to write to closed connection\n");
165 return -1;
166 }
167
168 while (sent < len)
169 {
170 const int rc = conn->write(conn, buf + sent, len - sent);
171 if (rc < 0)
172 {
173 mutt_debug(LL_DEBUG1, "error writing (%s), closing socket\n", strerror(errno));
174 mutt_socket_close(conn);
175
176 return -1;
177 }
178
179 if (rc < len - sent)
180 mutt_debug(LL_DEBUG3, "short write (%d of %d bytes)\n", rc, len - sent);
181
182 sent += rc;
183 }
184
185 return sent;
186}
187
196int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
197{
198 if (conn->bufpos < conn->available)
199 return conn->available - conn->bufpos;
200
201 if (conn->poll)
202 return conn->poll(conn, wait_secs);
203
204 return -1;
205}
206
214int mutt_socket_readchar(struct Connection *conn, char *c)
215{
216 if (conn->bufpos >= conn->available)
217 {
218 if (conn->fd >= 0)
219 conn->available = conn->read(conn, conn->inbuf, sizeof(conn->inbuf));
220 else
221 {
222 mutt_debug(LL_DEBUG1, "attempt to read from closed connection\n");
223 return -1;
224 }
225 conn->bufpos = 0;
226 if (conn->available == 0)
227 {
228 mutt_error(_("Connection to %s closed"), conn->account.host);
229 }
230 if (conn->available <= 0)
231 {
232 mutt_socket_close(conn);
233 return -1;
234 }
235 }
236 *c = conn->inbuf[conn->bufpos];
237 conn->bufpos++;
238 return 1;
239}
240
250int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
251{
252 char ch;
253 int i;
254
255 for (i = 0; i < buflen - 1; i++)
256 {
257 if (mutt_socket_readchar(conn, &ch) != 1)
258 {
259 buf[i] = '\0';
260 return -1;
261 }
262
263 if (ch == '\n')
264 break;
265 buf[i] = ch;
266 }
267
268 /* strip \r from \r\n termination */
269 if (i && (buf[i - 1] == '\r'))
270 i--;
271 buf[i] = '\0';
272
273 mutt_debug(dbg, "%d< %s\n", conn->fd, buf);
274
275 /* number of bytes read, not strlen */
276 return i + 1;
277}
278
285{
286 struct Connection *conn = mutt_mem_calloc(1, sizeof(struct Connection));
287 conn->fd = -1;
288
289 if (type == MUTT_CONNECTION_TUNNEL)
290 {
292 }
293 else if (type == MUTT_CONNECTION_SSL)
294 {
295 int rc = mutt_ssl_socket_setup(conn);
296 if (rc < 0)
297 FREE(&conn);
298 }
299 else
300 {
301 conn->read = raw_socket_read;
302 conn->write = raw_socket_write;
303 conn->open = raw_socket_open;
304 conn->close = raw_socket_close;
305 conn->poll = raw_socket_poll;
306 }
307
308 return conn;
309}
310
318{
319 if (!conn)
320 return;
321
322 char buf[1024] = { 0 };
323 int bytes;
324
325 while ((bytes = mutt_socket_poll(conn, 0)) > 0)
326 {
327 mutt_socket_read(conn, buf, MIN(bytes, sizeof(buf)));
328 }
329}
330
339int mutt_socket_buffer_readln_d(struct Buffer *buf, struct Connection *conn, int dbg)
340{
341 char ch;
342 bool has_cr = false;
343
345
346 while (true)
347 {
348 if (mutt_socket_readchar(conn, &ch) != 1)
349 return -1;
350
351 if (ch == '\n')
352 break;
353
354 if (has_cr)
355 {
356 mutt_buffer_addch(buf, '\r');
357 has_cr = false;
358 }
359
360 if (ch == '\r')
361 has_cr = true;
362 else
363 mutt_buffer_addch(buf, ch);
364 }
365
366 mutt_debug(dbg, "%d< %s\n", conn->fd, mutt_buffer_string(buf));
367 return 0;
368}
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Convenience wrapper for the config headers.
void mutt_tunnel_socket_setup(struct Connection *conn)
Sets up tunnel connection functions.
Definition: tunnel.c:233
Connection Credentials.
An open network connection (socket)
Convenience wrapper for the core headers.
int mutt_ssl_socket_setup(struct Connection *conn)
Set up SSL socket mulitplexor.
Definition: gnutls.c:1123
int raw_socket_close(struct Connection *conn)
Close a socket - Implements Connection::close() -.
Definition: raw.c:362
int raw_socket_open(struct Connection *conn)
Open a socket - Implements Connection::open() -.
Definition: raw.c:117
int raw_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block - Implements Connection::poll() -.
Definition: raw.c:324
int raw_socket_read(struct Connection *conn, char *buf, size_t len)
Read data from a socket - Implements Connection::read() -.
Definition: raw.c:264
int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a socket - Implements Connection::write() -.
Definition: raw.c:294
#define mutt_error(...)
Definition: logging.h:87
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
#define MIN(a, b)
Definition: memory.h:31
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
Prototypes for many functions.
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
GUI display the mailboxes in a side panel.
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:101
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:196
int mutt_socket_buffer_readln_d(struct Buffer *buf, struct Connection *conn, int dbg)
Read a line from a socket into a Buffer.
Definition: socket.c:339
int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
Write data to a socket.
Definition: socket.c:156
struct Connection * mutt_socket_new(enum ConnectionType type)
Allocate and initialise a new connection.
Definition: socket.c:284
int mutt_socket_readchar(struct Connection *conn, char *c)
Simple read buffering to speed things up.
Definition: socket.c:214
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:317
int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
Read from a Connection.
Definition: socket.c:129
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:77
static int socket_preconnect(void)
Execute a command before opening a socket.
Definition: socket.c:51
int mutt_socket_write(struct Connection *conn, const char *buf, size_t len)
Write to a Connection.
Definition: socket.c:142
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:250
Low-level socket handling.
ConnectionType
Type of connection.
Definition: socket.h:36
@ MUTT_CONNECTION_SSL
SSL/TLS-encrypted connection.
Definition: socket.h:39
@ MUTT_CONNECTION_TUNNEL
Tunnelled connection.
Definition: socket.h:38
Handling of SSL encryption.
String manipulation buffer.
Definition: buffer.h:34
char host[128]
Server to login to.
Definition: connaccount.h:54
unsigned short port
Port to connect to.
Definition: connaccount.h:58
char inbuf[1024]
Buffer for incoming traffic.
Definition: connection.h:52
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:106
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:93
unsigned int ssf
Security strength factor, in bits (see notes)
Definition: connection.h:51
int bufpos
Current position in the buffer.
Definition: connection.h:53
int(* close)(struct Connection *conn)
Definition: connection.h:117
int available
Amount of data waiting to be read.
Definition: connection.h:55
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
int(* open)(struct Connection *conn)
Definition: connection.h:67
int fd
Socket file descriptor.
Definition: connection.h:54
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:80
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39