NeoMutt  2024-03-23-23-gec7045
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
socket.c File Reference

Low-level socket handling. More...

#include "config.h"
#include <errno.h>
#include <stdbool.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.
 
int mutt_socket_open (struct Connection *conn)
 Simple wrapper.
 
int mutt_socket_close (struct Connection *conn)
 Close a socket.
 
int mutt_socket_read (struct Connection *conn, char *buf, size_t len)
 Read from a Connection.
 
int mutt_socket_write_d (struct Connection *conn, const char *buf, int len, int dbg)
 Write data to a socket.
 
int mutt_socket_poll (struct Connection *conn, time_t wait_secs)
 Checks whether reads would block.
 
int mutt_socket_readchar (struct Connection *conn, char *c)
 Simple read buffering to speed things up.
 
int mutt_socket_readln_d (char *buf, size_t buflen, struct Connection *conn, int dbg)
 Read a line from a socket.
 
struct Connectionmutt_socket_new (enum ConnectionType type)
 Allocate and initialise a new connection.
 
void mutt_socket_empty (struct Connection *conn)
 Clear out any queued data.
 
int mutt_socket_buffer_readln_d (struct Buffer *buf, struct Connection *conn, int dbg)
 Read a line from a socket into a Buffer.
 

Detailed Description

Low-level socket handling.

Authors
  • Damien Riegel
  • Richard Russon

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}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#define _(a)
Definition: message.h:28
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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
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}
static int socket_preconnect(void)
Execute a command before opening a socket.
Definition: socket.c:50
char host[128]
Server to login to.
Definition: connaccount.h:54
unsigned short port
Port to connect to.
Definition: connaccount.h:58
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
+ 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 100 of file socket.c.

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}
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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
+ 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 128 of file socket.c.

129{
130 return conn->read(conn, buf, len);
131}
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:79
+ Here is the caller graph for this function:

◆ 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 142 of file socket.c.

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}
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:100
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:92
+ 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 182 of file socket.c.

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}
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:105
+ 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 200 of file socket.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}
#define mutt_error(...)
Definition: logging2.h:92
char inbuf[1024]
Buffer for incoming traffic.
Definition: connection.h:51
+ 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 238 of file socket.c.

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}
int mutt_socket_readchar(struct Connection *conn, char *c)
Simple read buffering to speed things up.
Definition: socket.c:200
+ 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 272 of file socket.c.

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}
void mutt_tunnel_socket_setup(struct Connection *conn)
Sets up tunnel connection functions.
Definition: tunnel.c:241
int mutt_ssl_socket_setup(struct Connection *conn)
Set up SSL socket mulitplexor.
Definition: gnutls.c:1124
int raw_socket_close(struct Connection *conn)
Close a socket - Implements Connection::close() -.
Definition: raw.c:374
int raw_socket_open(struct Connection *conn)
Open a socket - Implements Connection::open() -.
Definition: raw.c:129
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:336
int raw_socket_read(struct Connection *conn, char *buf, size_t len)
Read data from a socket - Implements Connection::read() -.
Definition: raw.c:276
int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a socket - Implements Connection::write() -.
Definition: raw.c:306
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
@ MUTT_CONNECTION_SSL
SSL/TLS-encrypted connection.
Definition: socket.h:38
@ MUTT_CONNECTION_TUNNEL
Tunnelled connection.
Definition: socket.h:37
+ 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.

Parameters
connConnection to a server

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 306 of file socket.c.

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}
#define MIN(a, b)
Definition: memory.h:32
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:182
int mutt_socket_read(struct Connection *conn, char *buf, size_t len)
Read from a Connection.
Definition: socket.c:128
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_socket_buffer_readln_d()

int mutt_socket_buffer_readln_d ( struct Buffer buf,
struct Connection conn,
int  dbg 
)

Read a line from a socket into a Buffer.

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

Definition at line 328 of file socket.c.

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:93
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:258
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
+ Here is the call graph for this function: