NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
socket.c
Go to the documentation of this file.
1
30#include "config.h"
31#include <errno.h>
32#include <stdbool.h>
33#include <string.h>
34#include <time.h>
35#include "private.h"
36#include "mutt/lib.h"
37#include "config/lib.h"
38#include "core/lib.h"
39#include "socket.h"
40#include "connaccount.h"
41#include "connection.h"
42#include "protos.h"
43#include "ssl.h"
44
50static int socket_preconnect(void)
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}
69
77{
78 int rc;
79
81 return -1;
82
83 rc = conn->open(conn);
84
85 if (rc >= 0)
86 {
87 mutt_debug(LL_DEBUG2, "Connected to %s:%d on fd=%d\n", conn->account.host,
88 conn->account.port, conn->fd);
89 }
90
91 return rc;
92}
93
101{
102 if (!conn)
103 return 0;
104
105 int rc = -1;
106
107 if (conn->fd < 0)
108 mutt_debug(LL_DEBUG1, "Attempt to close closed connection\n");
109 else
110 rc = conn->close(conn);
111
112 conn->fd = -1;
113 conn->ssf = 0;
114 conn->bufpos = 0;
115 conn->available = 0;
116
117 return rc;
118}
119
128int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
129{
130 return conn->read(conn, buf, len);
131}
132
142int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
143{
144 int sent = 0;
145
146 mutt_debug(dbg, "%d> %s", conn->fd, buf);
147
148 if (conn->fd < 0)
149 {
150 mutt_debug(LL_DEBUG1, "attempt to write to closed connection\n");
151 return -1;
152 }
153
154 while (sent < len)
155 {
156 const int rc = conn->write(conn, buf + sent, len - sent);
157 if (rc < 0)
158 {
159 mutt_debug(LL_DEBUG1, "error writing (%s), closing socket\n", strerror(errno));
160 mutt_socket_close(conn);
161
162 return -1;
163 }
164
165 if (rc < len - sent)
166 mutt_debug(LL_DEBUG3, "short write (%d of %d bytes)\n", rc, len - sent);
167
168 sent += rc;
169 }
170
171 return sent;
172}
173
182int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
183{
184 if (conn->bufpos < conn->available)
185 return conn->available - conn->bufpos;
186
187 if (conn->poll)
188 return conn->poll(conn, wait_secs);
189
190 return -1;
191}
192
200int mutt_socket_readchar(struct Connection *conn, char *c)
201{
202 if (conn->bufpos >= conn->available)
203 {
204 if (conn->fd >= 0)
205 {
206 conn->available = conn->read(conn, conn->inbuf, sizeof(conn->inbuf));
207 }
208 else
209 {
210 mutt_debug(LL_DEBUG1, "attempt to read from closed connection\n");
211 return -1;
212 }
213 conn->bufpos = 0;
214 if (conn->available == 0)
215 {
216 mutt_error(_("Connection to %s closed"), conn->account.host);
217 }
218 if (conn->available <= 0)
219 {
220 mutt_socket_close(conn);
221 return -1;
222 }
223 }
224 *c = conn->inbuf[conn->bufpos];
225 conn->bufpos++;
226 return 1;
227}
228
238int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
239{
240 char ch;
241 int i;
242
243 for (i = 0; i < buflen - 1; i++)
244 {
245 if (mutt_socket_readchar(conn, &ch) != 1)
246 {
247 buf[i] = '\0';
248 return -1;
249 }
250
251 if (ch == '\n')
252 break;
253 buf[i] = ch;
254 }
255
256 /* strip \r from \r\n termination */
257 if (i && (buf[i - 1] == '\r'))
258 i--;
259 buf[i] = '\0';
260
261 mutt_debug(dbg, "%d< %s\n", conn->fd, buf);
262
263 /* number of bytes read, not strlen */
264 return i + 1;
265}
266
273{
274 struct Connection *conn = mutt_mem_calloc(1, sizeof(struct Connection));
275 conn->fd = -1;
276
277 if (type == MUTT_CONNECTION_TUNNEL)
278 {
280 }
281 else if (type == MUTT_CONNECTION_SSL)
282 {
283 int rc = mutt_ssl_socket_setup(conn);
284 if (rc < 0)
285 FREE(&conn);
286 }
287 else
288 {
289 conn->read = raw_socket_read;
290 conn->write = raw_socket_write;
291 conn->open = raw_socket_open;
292 conn->close = raw_socket_close;
293 conn->poll = raw_socket_poll;
294 }
295
296 return conn;
297}
298
307{
308 if (!conn)
309 return;
310
311 char buf[1024] = { 0 };
312 int bytes;
313
314 while ((bytes = mutt_socket_poll(conn, 0)) > 0)
315 {
316 mutt_socket_read(conn, buf, MIN(bytes, sizeof(buf)));
317 }
318}
319
328int mutt_socket_buffer_readln_d(struct Buffer *buf, struct Connection *conn, int dbg)
329{
330 char ch;
331 bool has_cr = false;
332
333 buf_reset(buf);
334
335 while (true)
336 {
337 if (mutt_socket_readchar(conn, &ch) != 1)
338 return -1;
339
340 if (ch == '\n')
341 break;
342
343 if (has_cr)
344 {
345 buf_addch(buf, '\r');
346 has_cr = false;
347 }
348
349 if (ch == '\r')
350 has_cr = true;
351 else
352 buf_addch(buf, ch);
353 }
354
355 mutt_debug(dbg, "%d< %s\n", conn->fd, buf_string(buf));
356 return 0;
357}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:75
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
Convenience wrapper for the config headers.
void mutt_tunnel_socket_setup(struct Connection *conn)
Sets up tunnel connection functions.
Definition: tunnel.c:242
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:1129
int raw_socket_close(struct Connection *conn)
Close a socket - Implements Connection::close() -.
Definition: raw.c:391
int raw_socket_open(struct Connection *conn)
Open a socket - Implements Connection::open() -.
Definition: raw.c:146
int raw_socket_poll(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
Definition: raw.c:353
int raw_socket_read(struct Connection *conn, char *buf, size_t len)
Read data from a socket - Implements Connection::read() -.
Definition: raw.c:293
int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a socket - Implements Connection::write() -.
Definition: raw.c:323
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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:45
#define MIN(a, b)
Definition: memory.h:32
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:100
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:182
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:328
int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
Write data to a socket.
Definition: socket.c:142
struct Connection * mutt_socket_new(enum ConnectionType type)
Allocate and initialise a new connection.
Definition: socket.c:272
int mutt_socket_readchar(struct Connection *conn, char *c)
Simple read buffering to speed things up.
Definition: socket.c:200
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:306
int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
Read from a Connection.
Definition: socket.c:128
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:76
static int socket_preconnect(void)
Execute a command before opening a socket.
Definition: socket.c:50
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:238
Low-level socket handling.
ConnectionType
Type of connection.
Definition: socket.h:35
@ MUTT_CONNECTION_SSL
SSL/TLS-encrypted connection.
Definition: socket.h:38
@ MUTT_CONNECTION_TUNNEL
Tunnelled connection.
Definition: socket.h:37
Handling of SSL encryption.
String manipulation buffer.
Definition: buffer.h:36
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:51
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:105
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:92
unsigned int ssf
Security strength factor, in bits (see notes)
Definition: connection.h:50
int bufpos
Current position in the buffer.
Definition: connection.h:52
int(* close)(struct Connection *conn)
Definition: connection.h:116
int available
Amount of data waiting to be read.
Definition: connection.h:54
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:49
int(* open)(struct Connection *conn)
Definition: connection.h:66
int fd
Socket file descriptor.
Definition: connection.h:53
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:79
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45