ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/sockets.c
Revision: 1171
Committed: Fri Aug 12 20:00:46 2011 UTC (12 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 72138 byte(s)
Log Message:
- Import ircservices-5.1.24. Don't ever think about modifying anything in this
  folder!
  Since Andrew Church has discontinued his services project in April 2011, the
  ircd-hybrid team has been given permissions to officially continue and
  maintain the already mentioned project.
  The name of this project will be changed for the reason being that the current
  name "IRC Services" is way too generic these days.

  Remember: Don't ever modify anything in here. This folder is kept for reference.

File Contents

# Content
1 /* Socket routines.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 /* Define this to trace function calls: */
11 /* #define TRACE_CALLS */
12
13 /* Define this to log warnings on exceeding buffer size: */
14 /* #define WARN_ON_BUFSIZE */
15
16 /* Define this to disable swritemap(). For IRC Services, we disable this
17 * to avoid depending on the presence of munmap(), since we don't use
18 * swritemap() anyway. */
19 #define DISABLE_SWRITEMAP
20
21 #include "services.h"
22 #include <fcntl.h>
23 #include <sys/socket.h>
24 #include <netdb.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27
28 #ifndef DISABLE_SWRITEMAP
29 # include <sys/mman.h> /* for munmap() */
30 #endif
31
32 /*************************************************************************/
33
34 /* For function call tracing: */
35
36 #ifdef TRACE_CALLS
37
38 static int trace_depth = -1;
39
40 #define ENTER(fmt,...) \
41 trace_depth++; \
42 log_debug(1, "sockets: TRACE: %*s%s(" fmt ")", \
43 trace_depth*2, "", __FUNCTION__ , ## __VA_ARGS__)
44 #define ENTER_WITH(retfmt,fmt,...) \
45 const char *__retfmt = (retfmt); \
46 ENTER(fmt , ## __VA_ARGS__)
47 #define RETURN do { \
48 log_debug(1, "sockets: TRACE: %*s%s() -> void", \
49 trace_depth*2, "", __FUNCTION__); \
50 trace_depth--; \
51 return; \
52 } while (0)
53 #define RETURN_WITH(val) do { \
54 typeof(val) __tmp = (val); \
55 if (debug) { \
56 char buf[64]; \
57 snprintf(buf, sizeof(buf), __retfmt, __tmp); \
58 log_debug(1, "sockets: TRACE: %*s%s() -> %s", \
59 trace_depth*2, "", __FUNCTION__, buf); \
60 } \
61 trace_depth--; \
62 return __tmp; \
63 } while (0)
64
65 #else /* !TRACE_CALLS */
66
67 #define ENTER(fmt,...) /* nothing */
68 #define ENTER_WITH(retfmt,fmt,...) /* nothing */
69 #define RETURN return
70 #define RETURN_WITH(val) return(val)
71
72 #endif /* TRACE_CALLS */
73
74 /*************************************************************************/
75
76 /* Socket data structure */
77
78 struct socket_ {
79 Socket *next, *prev;
80 int fd; /* Socket's file descriptor */
81 struct sockaddr_in remote; /* Remote address */
82 int flags; /* Status flags (SF_*) */
83
84 SocketCallback cb_connect; /* Connect callback */
85 SocketCallback cb_disconn; /* Disconnect callback */
86 SocketCallback cb_accept; /* Accept callback */
87 SocketCallback cb_read; /* Data-available callback */
88 SocketCallback cb_readline; /* Line-available callback */
89 SocketCallback cb_trigger; /* Write trigger callback */
90
91 int write_timeout; /* Write timeout, in seconds (0 = none) */
92 time_t last_write_time; /* Last time data was successfully sent */
93
94 /* Usage of pointers:
95 * - Xbuf is the buffer base pointer
96 * - Xptr is the address of the next character to store
97 * - Xend is the address of the next character to retrieve
98 * - Xtop is the address of the last byte of the buffer + 1
99 * Xend-Xptr (mod Xbufsize) gives the number of bytes in the buffer.
100 */
101 char *rbuf, *rptr, *rend, *rtop; /* Read buffer and pointers */
102 char *wbuf, *wptr, *wend, *wtop; /* Write buffer and pointers */
103
104 /* List of mapped memory areas to send, earliest first */
105 struct wmapinfo {
106 struct wmapinfo *next;
107 int32 wait; /* # of bytes to write from wbuf first */
108 const char *map; /* Start of mapped area, or trigger data */
109 int32 maplen; /* Length of mapped area (0 = write trigger) */
110 int32 pos; /* Current position */
111 } *writemap, *writemap_tail;
112
113 uint64 total_read; /* Total number of bytes read */
114 uint64 total_written; /* Total number of bytes written */
115 };
116
117 #define SF_SELFCREATED 0x0001 /* We created this socket ourselves */
118 #define SF_BLOCKING 0x0002 /* Writes are blocking */
119 #define SF_LISTENER 0x0004 /* Socket is a listener socket */
120 #define SF_CONNECTING 0x0008 /* Socket is busy connecting */
121 #define SF_CONNECTED 0x0010 /* Socket has connected */
122 #define SF_MUTE 0x0020 /* Socket is muted */
123 #define SF_UNMUTED 0x0040 /* Socket was just unmuted */
124 #define SF_CALLBACK 0x0080 /* Currently calling callbacks */
125 #define SF_WTRIGGER 0x0100 /* A write trigger has been reached */
126 #define SF_WARNED 0x0200 /* Warned about hitting buffer limit */
127 #define SF_DISCONNECT 0x0400 /* Disconnect when writebuf empty */
128 #define SF_DISCONN_REQ 0x0800 /* Disconnect has been requested */
129 #define SF_DISCONNECTING 0x1000 /* Socket is in the middle of disconnecting */
130 #define SF_BROKEN 0x2000 /* Connection was broken while in a callback */
131 #define SF_DELETEME 0x4000 /* Delete socket when convenient */
132
133 /* Used when calling do_disconn() due to SF_DISCONNECT */
134 #define DISCONN_RESUME_FLAG 0x100
135 #define DISCONN_LOCAL_RESUME (void *)((int)DISCONN_LOCAL|DISCONN_RESUME_FLAG)
136 #define DISCONN_REMOTE_RESUME (void *)((int)DISCONN_REMOTE|DISCONN_RESUME_FLAG)
137
138 /* Size of read/write buffers */
139 #define read_buffer_size(s) ((s)->rtop - (s)->rbuf)
140 #define write_buffer_size(s) ((s)->wtop - (s)->wbuf)
141
142 /* Does the socket still have more data that needs to be written? */
143 #define MORE_TO_WRITE(s) (write_buffer_len(s) > 0 || ((s)->writemap))
144
145 /*************************************************************************/
146
147 /* List of all sockets (even unopened ones) */
148 static Socket *allsockets = NULL;
149
150 /* Array of all opened sockets (indexed by FD), dynamically allocated */
151 static Socket **sockets = NULL;
152
153 /* Highest FD number in use plus 1; also length of sockets[] array */
154 static int max_fd;
155
156 /* Set of all connected socket FDs */
157 static fd_set sock_fds;
158
159 /* Set of all FDs that need data written (or are connecting) */
160 static fd_set write_fds;
161
162 /* Total memory used by socket buffers */
163 static uint32 total_bufsize;
164
165 /* Per-connection and total buffer size limits */
166 static uint32 bufsize_limit = 0, total_bufsize_limit = 0;
167
168 /* Global read timeout, in milliseconds */
169 static int read_timeout = -1;
170
171 /*************************************************************************/
172
173 /* Internal routine declarations (definitions at bottom of file) */
174
175 static int do_callback(Socket *s, SocketCallback cb, void *param);
176 static void do_accept(Socket *s);
177 static int fill_read_buffer(Socket *s);
178 static int flush_write_buffer(Socket *s);
179 static uint32 resize_how_much(const Socket *s, uint32 current_size, int *errp);
180 static int resize_rbuf(Socket *s, uint32 size);
181 static int resize_wbuf(Socket *s, uint32 size);
182 static int resize_buf(char **p_buf, char **p_ptr, char **p_end, char **p_top,
183 uint32 newsize);
184 static int reclaim_buffer_space_one(Socket *s);
185 static int reclaim_buffer_space(void);
186 static void next_wmap(Socket *s);
187 static int buffered_write(Socket *s, const char *buf, int len);
188 static int do_disconn(Socket *s, void *code);
189 static void sock_closefd(Socket *s);
190
191 /*************************************************************************/
192 /*************************** Global routines *****************************/
193 /*************************************************************************/
194
195 /* Set the per-connection and total buffer size limits (zero means no
196 * limit). Always successful; both values are silently rounded down to a
197 * multiple of SOCK_MIN_BUFSIZE (if a value is less than SOCK_MIN_BUFSIZE it
198 * is rounded up). Both values default to zero, i.e. unlimited.
199 */
200
201 void sock_set_buflimits(uint32 per_conn, uint32 total)
202 {
203 if (per_conn > 0) {
204 per_conn = per_conn / SOCK_MIN_BUFSIZE * SOCK_MIN_BUFSIZE;
205 if (!per_conn)
206 per_conn = SOCK_MIN_BUFSIZE;
207 }
208 if (total > 0) {
209 total = total / SOCK_MIN_BUFSIZE * SOCK_MIN_BUFSIZE;
210 if (!total)
211 total = SOCK_MIN_BUFSIZE;
212 }
213 bufsize_limit = per_conn;
214 total_bufsize_limit = total;
215 }
216
217 /*************************************************************************/
218
219 /* Set the global read timeout. A value of -1 (default) means no timeout. */
220
221 void sock_set_rto(int msec)
222 {
223 read_timeout = msec;
224 }
225
226 /*************************************************************************/
227
228 /* Create and return a new socket. Returns NULL if unsuccessful (i.e. no
229 * more space for buffers).
230 */
231
232 Socket *sock_new(void)
233 {
234 Socket *s;
235
236 ENTER_WITH("%p", "");
237 if (total_bufsize_limit) {
238 while (total_bufsize + SOCK_MIN_BUFSIZE*2 > total_bufsize_limit) {
239 if (!reclaim_buffer_space()) {
240 log("sockets: sock_new(): out of buffer space! current=%lu,"
241 " limit=%lu", (unsigned long)total_bufsize,
242 (unsigned long)total_bufsize_limit);
243 RETURN_WITH(NULL);
244 }
245 }
246 }
247
248 s = malloc(sizeof(*s));
249 if (!s) {
250 RETURN_WITH(NULL);
251 }
252 s->rbuf = malloc(SOCK_MIN_BUFSIZE);
253 if (!s->rbuf) {
254 int errno_save = errno;
255 free(s);
256 errno = errno_save;
257 RETURN_WITH(NULL);
258 }
259 s->wbuf = malloc(SOCK_MIN_BUFSIZE);
260 if (!s->wbuf) {
261 int errno_save = errno;
262 free(s->rbuf);
263 free(s);
264 errno = errno_save;
265 RETURN_WITH(NULL);
266 }
267
268 s->fd = -1;
269 memset(&s->remote, 0, sizeof(s->remote));
270 s->flags = 0;
271 s->cb_connect = NULL;
272 s->cb_disconn = NULL;
273 s->cb_accept = NULL;
274 s->cb_read = NULL;
275 s->cb_readline = NULL;
276 s->cb_trigger = NULL;
277 s->write_timeout = 0;
278 s->last_write_time = time(NULL);
279 s->rptr = s->rbuf;
280 s->rend = s->rbuf;
281 s->rtop = s->rbuf + SOCK_MIN_BUFSIZE;
282 s->wptr = s->wbuf;
283 s->wend = s->wbuf;
284 s->wtop = s->wbuf + SOCK_MIN_BUFSIZE;
285 s->writemap = NULL;
286 s->writemap_tail = NULL;
287 s->total_read = 0;
288 s->total_written = 0;
289 LIST_INSERT(s, allsockets);
290 total_bufsize += read_buffer_size(s) + write_buffer_size(s);
291 RETURN_WITH(s);
292 }
293
294 /*************************************************************************/
295
296 /* Free a socket, first disconnecting/closing it if necessary. */
297
298 void sock_free(Socket *s)
299 {
300 ENTER("%p", s);
301 if (!s) {
302 log("sockets: sock_free() with NULL socket!");
303 errno = EINVAL;
304 RETURN;
305 }
306 if (s->flags & (SF_CONNECTING | SF_CONNECTED)) {
307 s->flags |= SF_DELETEME;
308 do_disconn(s, DISCONN_LOCAL);
309 /* do_disconn() will call us again at the appropriate time */
310 RETURN;
311 } else if (s->flags & SF_LISTENER) {
312 close_listener(s);
313 }
314 LIST_REMOVE(s, allsockets);
315 total_bufsize -= read_buffer_size(s) + write_buffer_size(s);
316 free(s->rbuf);
317 free(s->wbuf);
318 free(s);
319 /* If this was the last socket, free the sockets[] array too */
320 if (!allsockets) {
321 free(sockets);
322 sockets = NULL;
323 }
324 RETURN;
325 }
326
327 /*************************************************************************/
328
329 /* Set a callback on a socket. */
330
331 void sock_setcb(Socket *s, SocketCallbackID which, SocketCallback func)
332 {
333 ENTER("%p,%d,%p", s, which, func);
334 if (!s) {
335 log("sockets: sock_setcb() with NULL socket!");
336 errno = EINVAL;
337 RETURN;
338 }
339 switch (which) {
340 case SCB_CONNECT: s->cb_connect = func; break;
341 case SCB_DISCONNECT: s->cb_disconn = func; break;
342 case SCB_ACCEPT: s->cb_accept = func; break;
343 case SCB_READ: s->cb_read = func; break;
344 case SCB_READLINE: s->cb_readline = func; break;
345 case SCB_TRIGGER: s->cb_trigger = func; break;
346 default:
347 log("sockets: sock_setcb(): invalid callback ID %d", which);
348 break;
349 }
350 RETURN;
351 }
352
353 /*************************************************************************/
354
355 /* Return whether the given socket is currently connected. */
356
357 int sock_isconn(const Socket *s)
358 {
359 ENTER_WITH("%d", "%p", s);
360 if (!s) {
361 log("sockets: sock_isconn() with NULL socket!");
362 errno = EINVAL;
363 RETURN_WITH(0);
364 }
365 RETURN_WITH(s->flags & SF_CONNECTED ? 1 : 0);
366 }
367
368 /*************************************************************************/
369
370 /* Retrieve address of remote end of socket. Functions the same way as
371 * getpeername() (initialize *lenptr to sizeof(sa), address returned in sa,
372 * non-truncated length of address returned in *lenptr). Returns -1 with
373 * errno == EINVAL if a NULL pointer is passed or the given socket is not
374 * connected.
375 */
376
377 int sock_remote(const Socket *s, struct sockaddr *sa, int *lenptr)
378 {
379 ENTER_WITH("%d", "%p,%p,%p", s, sa, lenptr);
380 if (!s || !sa || !lenptr || !(s->flags & SF_CONNECTED)) {
381 if (!s || !sa || !lenptr) {
382 log("sockets: sock_remote() with NULL %s!",
383 !s ? "socket" : !sa ? "sockaddr" : "lenptr");
384 }
385 errno = EINVAL;
386 RETURN_WITH(-1);
387 }
388 if (sizeof(s->remote) <= *lenptr)
389 memcpy(sa, &s->remote, sizeof(s->remote));
390 else
391 memcpy(sa, &s->remote, *lenptr);
392 *lenptr = sizeof(s->remote);
393 RETURN_WITH(0);
394 }
395
396 /*************************************************************************/
397
398 /* Set whether socket writes should block (blocking != 0) or not
399 * (blocking == 0).
400 */
401
402 void sock_set_blocking(Socket *s, int blocking)
403 {
404 ENTER("%p,%d", s, blocking);
405 if (!s) {
406 log("sockets: sock_set_blocking() with NULL socket!");
407 errno = EINVAL;
408 RETURN;
409 }
410 if (blocking)
411 s->flags |= SF_BLOCKING;
412 else
413 s->flags &= ~SF_BLOCKING;
414 RETURN;
415 }
416
417 /*************************************************************************/
418
419 /* Return whether socket writes are blocking (return value > 0) or not
420 * (return value == 0). Returns -1 if socket is invalid.
421 */
422
423 int sock_get_blocking(const Socket *s)
424 {
425 ENTER_WITH("%d", "%p", s);
426 if (!s) {
427 log("sockets: sock_get_blocking() with NULL socket!");
428 errno = EINVAL;
429 RETURN_WITH(-1);
430 }
431 RETURN_WITH(s->flags & SF_BLOCKING);
432 }
433
434 /*************************************************************************/
435
436 /* Set (or clear, if seconds==0) the write timeout for a socket. */
437
438 void sock_set_wto(Socket *s, int seconds)
439 {
440 ENTER("%p,%d", s, seconds);
441 if (!s || seconds < 0) {
442 log("sockets: sock_set_wto() with %s!",
443 !s ? "NULL socket" : "negative timeout");
444 errno = EINVAL;
445 RETURN;
446 }
447 s->write_timeout = seconds;
448 RETURN;
449 }
450
451 /*************************************************************************/
452
453 /* Mute a socket. When a socket is muted, no arriving data will be
454 * acknowledged (except to the extent that the operating system
455 * automatically acknowledges and buffers the data), and the read and
456 * accept callbacks will not be called. However, a socket in the
457 * process of conenction will still call the connect or disconnect
458 * callbacks when it completes or fails.
459 */
460
461 void sock_mute(Socket *s)
462 {
463 ENTER("%p", s);
464 if (!s) {
465 log("sockets: sock_mute() with NULL socket!");
466 RETURN;
467 }
468 if (!(s->flags & SF_MUTE)) {
469 if (s->fd >= 0)
470 FD_CLR(s->fd, &sock_fds);
471 s->flags |= SF_MUTE;
472 }
473 RETURN;
474 }
475
476 /*************************************************************************/
477
478 /* Unmute a socket. If any data is waiting, it will be acknowledged and
479 * the appropriate callback (read or accept) called during the next call to
480 * check_sockets().
481 */
482
483 void sock_unmute(Socket *s)
484 {
485 ENTER("%p", s);
486 if (!s) {
487 log("sockets: sock_unmute() with NULL socket!");
488 RETURN;
489 }
490 if (s->flags & SF_MUTE) {
491 if (s->fd >= 0)
492 FD_SET(s->fd, &sock_fds);
493 s->flags &= ~SF_MUTE;
494 s->flags |= SF_UNMUTED;
495 }
496 RETURN;
497 }
498
499 /*************************************************************************/
500
501 /* Return amount of data in read buffer. Assumes socket is valid. */
502
503 inline uint32 read_buffer_len(const Socket *s)
504 {
505 if (s->rend >= s->rptr)
506 return s->rend - s->rptr;
507 else
508 return (s->rend + read_buffer_size(s)) - s->rptr;
509 }
510
511
512 /*************************************************************************/
513
514 /* Return amount of data in write buffer. Assumes socket is valid. */
515
516 inline uint32 write_buffer_len(const Socket *s)
517 {
518 if (s->wend >= s->wptr)
519 return s->wend - s->wptr;
520 else
521 return (s->wend + write_buffer_size(s)) - s->wptr;
522 }
523
524 /*************************************************************************/
525
526 /* Return total number of bytes received and sent on this socket in
527 * *read_ret and *writekb_ret respectively. Sent data count does not
528 * include buffered but unsent data. Returns 0 on success, -1 on error
529 * (invalid socket).
530 */
531
532 int sock_rwstat(const Socket *s, uint64 *read_ret, uint64 *written_ret)
533 {
534 ENTER_WITH("%u", "%p,%p,%p", s, read_ret, written_ret);
535 if (!s) {
536 log("sockets: sock_rwstat() with NULL socket!");
537 errno = EINVAL;
538 RETURN_WITH(-1);
539 }
540 if (read_ret)
541 *read_ret = s->total_read;
542 if (written_ret)
543 *written_ret = s->total_written;
544 RETURN_WITH(0);
545 }
546
547 /*************************************************************************/
548
549 /* Return the larger of (1) the ratio of the given socket's total buffer
550 * size (read and write buffers combined) to bufsize_limit and (2) the
551 * ratio of the amount of memory used by all sockets' buffers to
552 * total_bufsize_limit, as a percentage rounded up to the next integer.
553 * Ratios (1) and (2) are zero if bufsize_limit or total_bufsize_limit,
554 * respectively, are set to zero (unlimited).
555 *
556 * If any of `socksize_ret', `totalsize_ret', `ratio1_ret', and
557 * `ratio2_ret' are non-NULL, they are set respectively to the given
558 * socket's total buffer size, the amount of memory used by all sockets'
559 * buffers, ratio (1) as a percentage, and ratio (2) as a percentage.
560 *
561 * If `s' is NULL, ratio (1) is set to zero, and *socksize_ret is not
562 * modified.
563 */
564
565 int sock_bufstat(const Socket *s, uint32 *socksize_ret,
566 uint32 *totalsize_ret, int *ratio1_ret, int *ratio2_ret)
567 {
568 int ratio1 = 0, ratio2 = 0;
569
570 ENTER_WITH("%d", "%p,%p,%p,%p,%p", s, socksize_ret, totalsize_ret,
571 ratio1_ret, ratio2_ret);
572 if (bufsize_limit && s) {
573 uint32 size = read_buffer_size(s) + write_buffer_size(s);
574 if (bufsize_limit <= 0x7FFFFFFF/100)
575 ratio1 = (size*100 + bufsize_limit-1) / bufsize_limit;
576 else
577 ratio1 = (size + bufsize_limit/100-1) / (bufsize_limit/100);
578 }
579 if (total_bufsize_limit) {
580 if (bufsize_limit <= 0x7FFFFFFF/100)
581 ratio2 = (total_bufsize*100 + total_bufsize_limit-1)
582 / total_bufsize_limit;
583 else
584 ratio2 = (total_bufsize + total_bufsize_limit/100-1)
585 / (total_bufsize_limit/100);
586 }
587 if (socksize_ret && s)
588 *socksize_ret = read_buffer_size(s) + write_buffer_size(s);
589 if (totalsize_ret)
590 *totalsize_ret = total_bufsize;
591 if (ratio1_ret)
592 *ratio1_ret = ratio1;
593 if (ratio2_ret)
594 *ratio2_ret = ratio2;
595 if (ratio1 > ratio2)
596 RETURN_WITH(ratio1);
597 else
598 RETURN_WITH(ratio2);
599 }
600
601 /*************************************************************************/
602 /*************************************************************************/
603
604 /* Check all sockets for activity, and call callbacks as necessary.
605 * Returns after activity has been detected on at least one socket.
606 */
607
608 void check_sockets(void)
609 {
610 fd_set rfds, wfds;
611 int i;
612 int32 res;
613 struct timeval tv;
614 time_t now = time(NULL);
615 Socket *s;
616
617 ENTER("");
618 rfds = sock_fds;
619 wfds = write_fds;
620 if (read_timeout < 0) {
621 tv.tv_sec = -1; // flag: use a NULL tv parameter to select()
622 tv.tv_usec = 0;
623 } else {
624 tv.tv_sec = read_timeout/1000;
625 tv.tv_usec = (read_timeout%1000) * 1000;
626 }
627 for (i = 0; i < max_fd; i++) {
628 s = sockets[i];
629 if (s && s->write_timeout && MORE_TO_WRITE(s)) {
630 int tleft = s->write_timeout - (now - s->last_write_time);
631 if (tleft < 0)
632 tleft = 0;
633 if (tv.tv_sec < 0 || tleft <= tv.tv_sec) {
634 tv.tv_sec = tleft;
635 tv.tv_usec = 0;
636 }
637 }
638 }
639 enable_signals();
640 do {
641 struct timeval thistv = tv;
642 res = select(max_fd, &rfds, &wfds, NULL, tv.tv_sec<0?NULL:&thistv);
643 } while (res < 0 && errno == EINTR);
644 disable_signals();
645 log_debug(3, "sockets: select returned %d", res);
646 if (res < 0) {
647 log_perror("sockets: select()");
648 RETURN;
649 }
650
651 for (i = 0; i < max_fd; i++) {
652 s = sockets[i];
653 if (!s)
654 continue;
655 if (s->fd != i) {
656 log("sockets: BUG: sockets[%d]->fd = %d (should be equal),"
657 " clearing socket from table", i, s->fd);
658 sockets[i] = NULL;
659 continue;
660 }
661
662 if (FD_ISSET(i, &wfds)) {
663 log_debug(3, "sockets: write ready on fd %d", i);
664 if (!s) {
665 log("sockets: BUG: got write-ready on fd %d but no socket"
666 " for it!", i);
667 continue;
668 } else if (s->flags & SF_CONNECTING) {
669 /* Connection established (or failed) */
670 int val;
671 socklen_t vallen;
672 vallen = sizeof(val);
673 log_debug(2, "sockets: connect on fd %d returned", i);
674 if (getsockopt(i, SOL_SOCKET, SO_ERROR, &val, &vallen) < 0) {
675 log_perror("sockets: getsockopt(SO_ERROR) for connect (%d"
676 " -> %s:%u)", i, inet_ntoa(s->remote.sin_addr),
677 htons(s->remote.sin_port));
678 do_disconn(s, DISCONN_CONNFAIL);
679 continue;
680 }
681 if (val != 0) {
682 errno = val;
683 log_perror("sockets: connect(%d -> %s:%u)", i,
684 inet_ntoa(s->remote.sin_addr),
685 htons(s->remote.sin_port));
686 do_disconn(s, DISCONN_CONNFAIL);
687 continue;
688 } else {
689 if (!do_callback(s, s->cb_connect, 0))
690 continue;
691 }
692 s->flags &= ~SF_CONNECTING;
693 s->flags |= SF_CONNECTED;
694 FD_CLR(i, &write_fds);
695 if (flush_write_buffer(s) < 0) /* we may have pending data */
696 continue; /* socket is not valid any more */
697 if (!(s->flags & SF_MUTE))
698 FD_SET(i, &sock_fds);
699 } else if (!(s->flags & SF_CONNECTED)) {
700 log("sockets: BUG: got write-ready on fd %d but socket not"
701 " connected!", i);
702 } else {
703 if (flush_write_buffer(s) < 0)
704 continue; /* socket is not valid any more */
705 }
706 } /* set in write fds */
707
708 while (s->flags & SF_WTRIGGER) {
709 /* Write trigger reached */
710 void *userdata = (void *)s->writemap->map;
711 next_wmap(s);
712 s->flags &= ~SF_WTRIGGER;
713 do_callback(s, s->cb_trigger, userdata);
714 }
715
716 if (FD_ISSET(i, &rfds) || (s && (s->flags & SF_UNMUTED))) {
717 log_debug(3, "sockets: %s on fd %d",
718 FD_ISSET(i,&rfds) ? "read ready" : "unmute", i);
719 if (!s) {
720 log("sockets: BUG: got data on fd %d but no socket for it!",i);
721 FD_CLR(i, &sock_fds);
722 continue;
723 }
724 if (s->flags & SF_MUTE) {
725 /* Socket was muted by a previous socket's callback */
726 log_debug(3, "sockets: socket %d has been muted", i);
727 continue;
728 }
729 s->flags &= ~SF_UNMUTED;
730 if (FD_ISSET(i, &rfds)) {
731 if (s->flags & SF_LISTENER) {
732 /* Connection arrived */
733 do_accept(s);
734 continue;
735 } else if (!(s->flags & SF_CONNECTED)) {
736 log("sockets: BUG: got data on fd %d but not connected!",
737 i);
738 FD_CLR(i, &sock_fds);
739 continue;
740 }
741 /* Normal read */
742 if (read_buffer_len(s) >= read_buffer_size(s)-1) {
743 /* Buffer is full, try to expand it */
744 int newsize = 0;
745 if (read_buffer_size(s) < SOCK_MIN_BUFSIZE)
746 newsize = SOCK_MIN_BUFSIZE;
747 else if (read_buffer_size(s)+SOCK_MIN_BUFSIZE<bufsize_limit)
748 newsize = read_buffer_size(s) + SOCK_MIN_BUFSIZE;
749 if (newsize > 0)
750 resize_rbuf(s, newsize);
751 }
752 res = fill_read_buffer(s);
753 if (res < 0) {
754 /* Connection was closed (or some other error occurred) */
755 if (res < 0)
756 log_perror_debug(1, "sockets: recv(%d)", i);
757 do_disconn(s, DISCONN_REMOTE);
758 continue;
759 } else if (res == 0) {
760 /* Read buffer is full (NOTE: this causes busy waiting
761 * until space is made available) */
762 }
763 } else {
764 res = read_buffer_len(s);
765 }
766 if (res > 0) {
767 uint32 left = read_buffer_len(s), newleft;
768 if (left == 0) {
769 log("sockets: BUG: 0 bytes avail after successful read!");
770 continue;
771 }
772 /* Call read callback(s) in a loop until no more data is
773 * left or neither callback takes any data, or the socket is
774 * disconnected */
775 newleft = left;
776 do {
777 if (!do_callback(s, s->cb_read, (void *)(long)newleft))
778 goto disconnected;
779 if (s->flags & SF_MUTE)
780 break;
781 newleft = read_buffer_len(s);
782 if (s->cb_readline) {
783 char *newline;
784 if (s->rend > s->rptr) {
785 newline = memchr(s->rptr, '\n', newleft);
786 } else {
787 newline = memchr(s->rptr, '\n', s->rtop - s->rptr);
788 if (!newline)
789 newline = memchr(s->rbuf, '\n',
790 s->rend - s->rbuf);
791 }
792 if (newline) {
793 if (!do_callback(s, s->cb_readline,
794 (void *)(long)newleft))
795 goto disconnected;
796 if (s->flags & SF_MUTE)
797 break;
798 newleft = read_buffer_len(s);
799 }
800 }
801 } while (newleft != left && (left = newleft) != 0);
802 reclaim_buffer_space_one(s);
803 }
804 } /* socket ready for reading or unmuted */
805
806 if (s->write_timeout
807 && MORE_TO_WRITE(s)
808 && s->last_write_time + s->write_timeout <= now
809 ) {
810 if (s->flags & SF_DISCONNECT)
811 do_disconn(s, DISCONN_LOCAL_RESUME);
812 else
813 do_disconn(s, DISCONN_REMOTE);
814 }
815
816 disconnected:
817 /* at least one statement is required after a label */ ;
818
819 } /* for all sockets */
820
821 RETURN;
822 } /* check_sockets() */
823
824 /*************************************************************************/
825 /*************************************************************************/
826
827 /* Initiate a connection to the given host and port. If an error occurs,
828 * returns -1, else returns 0. The connection is not necessarily complete
829 * even if 0 is returned, and may later fail; use the SCB_CONNECT and
830 * SCB_DISCONNECT callbacks. If this function fails due to inability to
831 * resolve a hostname, errno will be set to the negative of h_errno; pass
832 * the negative of this value to hstrerror() to get an appropriate error
833 * message.
834 *
835 * lhost/lport specify the local side of the connection. If they are not
836 * given (lhost==NULL, lport==0), then they are left to be set by the OS.
837 *
838 * If either host or lhost is not a valid IP address and the gethostbyname()
839 * function is available, this function may block while the hostname is
840 * being resolved.
841 *
842 * This function may be called from a socket's disconnect callback to
843 * establish a new connection using the same socket. It may not be called,
844 * however, if the socket is being freed with sock_free().
845 */
846
847 int conn(Socket *s, const char *host, int port, const char *lhost, int lport)
848 {
849 #if HAVE_GETHOSTBYNAME
850 struct hostent *hp;
851 #endif
852 uint8 *addr;
853 struct sockaddr_in sa, lsa;
854 int fd, i;
855
856 ENTER_WITH("%d", "%p,[%s],%d,[%s],%d", s, host?host:"(null)", port,
857 lhost?lhost:"(null)", lport);
858 if (!s || !host || port <= 0 || port > 65535) {
859 if (port <= 0 || port > 65535)
860 log("sockets: conn() with bad port number (%d)!", port);
861 else
862 log("sockets: conn() with NULL %s!", !s ? "socket" : "hostname");
863 errno = EINVAL;
864 RETURN_WITH(-1);
865 }
866 if (s->flags & SF_DELETEME) {
867 log("sockets: conn() called on a freeing socket (%p)", s);
868 errno = EPERM;
869 return -1;
870 }
871 memset(&lsa, 0, sizeof(lsa));
872 lsa.sin_family = AF_INET;
873 if (lhost) {
874 if ((addr = pack_ip(lhost)) != 0)
875 memcpy((char *)&lsa.sin_addr, addr, 4);
876 #if HAVE_GETHOSTBYNAME
877 else if ((hp = gethostbyname(lhost)) != NULL)
878 memcpy((char *)&lsa.sin_addr, hp->h_addr, hp->h_length);
879 #endif
880 else
881 lhost = NULL;
882 }
883 if (lport)
884 lsa.sin_port = htons(lport);
885
886 memset(&sa, 0, sizeof(sa));
887 if ((addr = pack_ip(host)) != 0) {
888 memcpy((char *)&sa.sin_addr, addr, 4);
889 sa.sin_family = AF_INET;
890 }
891 #if HAVE_GETHOSTBYNAME
892 else if ((hp = gethostbyname(host)) != NULL) {
893 memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
894 sa.sin_family = hp->h_addrtype;
895 } else {
896 errno = -h_errno;
897 RETURN_WITH(-1);
898 }
899 #else
900 else {
901 log("sockets: conn(): `%s' is not a valid IP address", host);
902 errno = EINVAL;
903 RETURN_WITH(-1);
904 }
905 #endif
906 sa.sin_port = htons((uint16)port);
907
908 if ((fd = socket(sa.sin_family, SOCK_STREAM, 0)) < 0)
909 RETURN_WITH(-1);
910
911 if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
912 int errno_save = errno;
913 close(fd);
914 errno = errno_save;
915 RETURN_WITH(-1);
916 }
917
918 if ((lhost || lport) && bind(fd,(struct sockaddr *)&lsa,sizeof(sa)) < 0) {
919 int errno_save = errno;
920 close(fd);
921 errno = errno_save;
922 RETURN_WITH(-1);
923 }
924
925 if ((i = connect(fd, (struct sockaddr *)&sa, sizeof(sa))) < 0
926 && errno != EINPROGRESS
927 ) {
928 int errno_save = errno;
929 close(fd);
930 errno = errno_save;
931 RETURN_WITH(-1);
932 }
933
934 if (max_fd < fd+1) {
935 int j;
936 void *new_sockets = realloc(sockets, (fd+1) * sizeof(*sockets));
937 if (!new_sockets) {
938 int errno_save = errno;
939 close(fd);
940 errno = errno_save;
941 RETURN_WITH(-1);
942 }
943 sockets = new_sockets;
944 for (j = max_fd; j < fd; j++)
945 sockets[j] = NULL;
946 max_fd = fd+1;
947 }
948 sockets[fd] = s;
949 s->remote = sa;
950 s->fd = fd;
951 s->flags &= ~(SF_CONNECTING | SF_CONNECTED);
952 if (i == 0) {
953 s->flags |= SF_CONNECTED;
954 if (!(s->flags & SF_MUTE))
955 FD_SET(fd, &sock_fds);
956 do_callback(s, s->cb_connect, 0);
957 } else {
958 s->flags |= SF_CONNECTING;
959 FD_SET(fd, &write_fds);
960 }
961 RETURN_WITH(0);
962 }
963
964 /*************************************************************************/
965
966 /* Disconnect a socket. Returns 0 on success, -1 on error (s == NULL or
967 * listener socket). Calling this routine on an already-disconnected
968 * socket returns success without doing anything. Note that the socket may
969 * not be disconnected immediately; callers who intend to reuse the socket
970 * MUST wait until the disconnect callback is called before doing so.
971 */
972
973 int disconn(Socket *s)
974 {
975 ENTER_WITH("%d", "%p", s);
976 if (!s) {
977 log("sockets: disconn() with NULL socket!");
978 errno = EINVAL;
979 RETURN_WITH(-1);
980 } else if (s->flags & SF_LISTENER) {
981 log("sockets: disconn() with listener socket!");
982 errno = EINVAL;
983 RETURN_WITH(-1);
984 }
985 RETURN_WITH(do_disconn(s, DISCONN_LOCAL));
986 }
987
988 /*************************************************************************/
989
990 /* Open a listener socket on the given host and port; returns 0 on success
991 * (the socket is set up and listening), -1 on error. If `host' has
992 * multiple addresses, only the first one is used; if `host' is NULL, all
993 * addresses are bound to. As with conn(), a negative errno value
994 * indicates a failure to resolve the hostname `host'. `backlog' is the
995 * backlog limit for incoming connections, and is passed directly to the
996 * listen() system call.
997 *
998 * Note that if the SCB_ACCEPT callback is not set, any connections to the
999 * socket will be dropped immediately.
1000 *
1001 * If host is not a valid IP address and the gethostbyname() function is
1002 * available, this function may block while the hostname is being resolved.
1003 */
1004
1005 int open_listener(Socket *s, const char *host, int port, int backlog)
1006 {
1007 #if HAVE_GETHOSTBYNAME
1008 struct hostent *hp;
1009 #endif
1010 uint8 *addr;
1011 struct sockaddr_in sa;
1012 int fd, i;
1013
1014 ENTER_WITH("%d", "%p,[%s],%d,%d", s, host?host:"(null)", port, backlog);
1015 if (!s || port <= 0 || port > 65535 || backlog < 1) {
1016 if (port <= 0 || port > 65535)
1017 log("sockets: open_listener() with bad port number (%d)!", port);
1018 else if (backlog < 1)
1019 log("sockets: open_listener() with bad backlog (%d)!", backlog);
1020 else
1021 log("sockets: open_listener() with NULL socket!");
1022 errno = EINVAL;
1023 RETURN_WITH(-1);
1024 }
1025 memset(&sa, 0, sizeof(sa));
1026 if (host) {
1027 if ((addr = pack_ip(host)) != 0) {
1028 memcpy((char *)&sa.sin_addr, addr, 4);
1029 sa.sin_family = AF_INET;
1030 }
1031 #if HAVE_GETHOSTBYNAME
1032 else if ((hp = gethostbyname(host)) != NULL) {
1033 memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
1034 sa.sin_family = hp->h_addrtype;
1035 } else {
1036 errno = -h_errno;
1037 RETURN_WITH(-1);
1038 }
1039 #else
1040 else {
1041 log("sockets: open_listener(): `%s' is not a valid IP address",
1042 host);
1043 errno = EINVAL;
1044 RETURN_WITH(-1);
1045 }
1046 #endif
1047 } else { /* !host */
1048 sa.sin_family = AF_INET;
1049 sa.sin_addr.s_addr = INADDR_ANY;
1050 }
1051 sa.sin_port = htons((uint16)port);
1052
1053 if ((fd = socket(sa.sin_family, SOCK_STREAM, 0)) < 0)
1054 RETURN_WITH(-1);
1055
1056 i = 1;
1057 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) {
1058 log_perror("sockets: open_listener(): setsockopt(%d, SO_REUSEADDR,"
1059 " 1) failed", fd);
1060 }
1061
1062 if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
1063 int errno_save = errno;
1064 close(fd);
1065 errno = errno_save;
1066 RETURN_WITH(-1);
1067 }
1068
1069 if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
1070 int errno_save = errno;
1071 close(fd);
1072 errno = errno_save;
1073 RETURN_WITH(-1);
1074 }
1075
1076 if (listen(fd, backlog) < 0) {
1077 int errno_save = errno;
1078 close(fd);
1079 errno = errno_save;
1080 RETURN_WITH(-1);
1081 }
1082
1083 if (max_fd < fd+1) {
1084 int j;
1085 void *new_sockets = realloc(sockets, (fd+1) * sizeof(*sockets));
1086 if (!new_sockets) {
1087 int errno_save = errno;
1088 close(fd);
1089 errno = errno_save;
1090 RETURN_WITH(-1);
1091 }
1092 sockets = new_sockets;
1093 for (j = max_fd; j < fd; j++)
1094 sockets[j] = NULL;
1095 max_fd = fd+1;
1096 }
1097 sockets[fd] = s;
1098 if (!(s->flags & SF_MUTE))
1099 FD_SET(fd, &sock_fds);
1100 s->fd = fd;
1101 s->flags |= SF_LISTENER;
1102
1103 /* Listener sockets don't need read/write buffers */
1104 free(s->rbuf);
1105 free(s->wbuf);
1106 s->rbuf = s->rptr = s->rend = s->rtop = NULL;
1107 s->wbuf = s->wptr = s->wend = s->wtop = NULL;
1108
1109 RETURN_WITH(0);
1110 }
1111
1112 /*************************************************************************/
1113
1114 /* Close a listener socket. */
1115
1116 int close_listener(Socket *s)
1117 {
1118 ENTER_WITH("%d", "%p", s);
1119 if (s == NULL || !(s->flags & SF_LISTENER)) {
1120 if (s)
1121 log("sockets: close_listener() with non-listener socket (%d)!",
1122 s->fd);
1123 else
1124 log("sockets: close_listener() with NULL socket!");
1125 errno = EINVAL;
1126 RETURN_WITH(-1);
1127 }
1128 sock_closefd(s);
1129 s->flags &= ~SF_LISTENER;
1130 RETURN_WITH(0);
1131 }
1132
1133 /*************************************************************************/
1134
1135 /* Read raw data from a socket, like read(). Returns number of bytes read,
1136 * or -1 on error. Only reads from the buffer (does not attempt to fetch
1137 * more data from the connection).
1138 */
1139
1140 int32 sread(Socket *s, char *buf, int32 len)
1141 {
1142 int32 nread = 0;
1143
1144 ENTER_WITH("%d", "%p,%p,%d", s, buf, len);
1145 if (!s || !buf || len <= 0) {
1146 log("sockets: sread() with %s!",
1147 !s ? "NULL socket" : !buf ? "NULL buffer" : "len <= 0");
1148 errno = EINVAL;
1149 RETURN_WITH(-1);
1150 }
1151 if (s->rend < s->rptr) {
1152 /* Buffer data wraps around */
1153 if (s->rptr + len <= s->rtop) {
1154 /* Only need to read from end of buffer */
1155 memcpy(buf, s->rptr, len);
1156 s->rptr += len;
1157 if (s->rptr >= s->rtop)
1158 s->rptr -= read_buffer_size(s);
1159 RETURN_WITH(len);
1160 } else {
1161 /* Need to read from both end and beginning */
1162 nread = s->rtop - s->rptr;
1163 memcpy(buf, s->rptr, nread);
1164 s->rptr = s->rbuf;
1165 len -= nread;
1166 /* Continue below */
1167 }
1168 }
1169 /* Read data from beginning of buffer */
1170 if (s->rptr < s->rend) {
1171 if (len > s->rend - s->rptr)
1172 len = s->rend - s->rptr;
1173 memcpy(buf+nread, s->rptr, len);
1174 s->rptr += len;
1175 nread += len;
1176 }
1177 /* Return number of bytes read */
1178 RETURN_WITH(nread);
1179 }
1180
1181 /*************************************************************************/
1182
1183 /* Write raw data to a socket, like write(). Returns number of bytes
1184 * written, or -1 on error.
1185 */
1186
1187 int32 swrite(Socket *s, const char *buf, int32 len)
1188 {
1189 ENTER_WITH("%d", "%p,%p,%d", s, buf, len);
1190 if (!s || !buf || len < 0) {
1191 log("sockets: swrite() with %s!",
1192 !s ? "NULL socket" : !buf ? "NULL buffer" : "len < 0");
1193 errno = EINVAL;
1194 RETURN_WITH(-1);
1195 }
1196 RETURN_WITH(buffered_write(s, buf, len));
1197 }
1198
1199 /*************************************************************************/
1200
1201 /* Write data from an mmap()ed area to a socket. The area will be
1202 * automatically unmapped when the write completes.
1203 */
1204
1205 int32 swritemap(Socket *s, const char *buf, int32 len)
1206 {
1207 #ifndef DISABLE_SWRITEMAP
1208 struct wmapinfo *info;
1209
1210 ENTER_WITH("%d", "%p,%p,%d", s, buf, len);
1211 if (!s || !buf || len < 0) {
1212 log("sockets: swritemap() with %s!",
1213 !s ? "NULL socket" : !buf ? "NULL buffer" : "len < 0");
1214 errno = EINVAL;
1215 RETURN_WITH(-1);
1216 }
1217 if (!len)
1218 RETURN_WITH(0);
1219 info = malloc(sizeof(*info));
1220 if (!info)
1221 RETURN_WITH(-1);
1222 info->next = NULL;
1223 info->wait = write_buffer_len(s);
1224 info->map = buf;
1225 info->maplen = len;
1226 info->pos = 0;
1227 if (s->writemap) {
1228 if (!s->writemap_tail) {
1229 log("sockets: BUG: socket %d: writemap non-NULL but writemap_tail"
1230 " NULL", s->fd);
1231 s->writemap_tail = s->writemap;
1232 while (s->writemap_tail->next)
1233 s->writemap_tail = s->writemap_tail->next;
1234 }
1235 s->writemap_tail->next = info;
1236 } else {
1237 if (s->writemap_tail) {
1238 log("sockets: BUG: socket %d: writemap NULL but writemap_tail"
1239 " non-NULL", s->fd);
1240 }
1241 s->writemap = info;
1242 }
1243 s->writemap_tail = info;
1244 flush_write_buffer(s); /* to ensure FD is set in write_fds if needed */
1245 RETURN_WITH(len);
1246 #else /* DISABLE_SWRITEMAP */
1247 errno = ENOSYS;
1248 RETURN_WITH(-1);
1249 #endif
1250 }
1251
1252 /*************************************************************************/
1253
1254 /* Add a write trigger to the socket. The `data' parameter will be passed
1255 * to the callback when the trigger is reached. Returns 0 on success, -1
1256 * on failure.
1257 */
1258
1259 int swrite_trigger(Socket *s, void *data)
1260 {
1261 struct wmapinfo *info;
1262
1263 ENTER_WITH("%d", "%p,%p", s, data);
1264 if (!s) {
1265 log("sockets: swrite_trigger() with NULL socket!");
1266 errno = EINVAL;
1267 RETURN_WITH(-1);
1268 }
1269 info = malloc(sizeof(*info));
1270 if (!info)
1271 RETURN_WITH(-1);
1272 info->next = NULL;
1273 info->wait = write_buffer_len(s);
1274 info->map = (const char *)data;
1275 info->maplen = 0;
1276 info->pos = 0;
1277 if (s->writemap) {
1278 if (!s->writemap_tail) {
1279 log("sockets: BUG: socket %d: writemap non-NULL but writemap_tail"
1280 " NULL", s->fd);
1281 s->writemap_tail = s->writemap;
1282 while (s->writemap_tail->next)
1283 s->writemap_tail = s->writemap_tail->next;
1284 }
1285 s->writemap_tail->next = info;
1286 } else {
1287 if (s->writemap_tail) {
1288 log("sockets: BUG: socket %d: writemap NULL but writemap_tail"
1289 " non-NULL", s->fd);
1290 }
1291 s->writemap = info;
1292 }
1293 s->writemap_tail = info;
1294 flush_write_buffer(s); /* to ensure FD is set in write_fds if needed */
1295 RETURN_WITH(0);
1296 }
1297
1298 /*************************************************************************/
1299 /*************************************************************************/
1300
1301 /* Read a character from a socket, like fgetc(). Returns EOF if no data
1302 * is available in the socket buffer. Assumes the socket is valid.
1303 */
1304
1305 int sgetc(Socket *s)
1306 {
1307 int c;
1308
1309 ENTER_WITH("%d", "%p", s);
1310 /* No paranoia check here, to save time */
1311 if (s->rptr == s->rend)
1312 RETURN_WITH(EOF);
1313 c = *s->rptr++;
1314 if (s->rptr >= s->rtop)
1315 s->rptr -= read_buffer_size(s);
1316 RETURN_WITH(c);
1317 }
1318
1319 /*************************************************************************/
1320
1321 /* Read a line from a socket, like fgets(). If not enough buffered data
1322 * is available to fill a complete line, or another error occurs, returns
1323 * NULL.
1324 */
1325
1326 char *sgets(char *buf, int32 len, Socket *s)
1327 {
1328 char *ptr = s->rptr, *eol;
1329 int32 to_top = s->rtop - ptr; /* used for efficiency */
1330
1331 ENTER_WITH("%p", "%p,%d,%p", buf, len, s);
1332 if (!s || !buf || len <= 0) {
1333 log("sockets: sgets[2]() with %s!",
1334 !s ? "NULL socket" : !buf ? "NULL buffer" : "len <= 0");
1335 RETURN_WITH(NULL);
1336 }
1337
1338 /* Find end of line */
1339 if (s->rend > s->rptr) {
1340 eol = memchr(s->rptr, '\n', s->rend - s->rptr);
1341 } else {
1342 eol = memchr(s->rptr, '\n', to_top);
1343 if (!eol)
1344 eol = memchr(s->rbuf, '\n', s->rend - s->rbuf);
1345 }
1346 if (!eol)
1347 RETURN_WITH(NULL);
1348 eol++; /* Point 1 byte after \n */
1349
1350 /* Set rptr now; old value is in ptr variable */
1351 s->rptr = eol;
1352 if (s->rptr >= s->rtop) /* >rtop is impossible, but just in case */
1353 s->rptr = s->rbuf;
1354
1355 /* Note: The greatest possible value for eol is s->rend, so as long as
1356 * we ensure that rend doesn't wrap around and reach rptr (i.e. always
1357 * leave at least 1 byte in the buffer unused), we can never have
1358 * eol == ptr here. */
1359
1360 /* Trim eol to <len bytes */
1361 if (eol > ptr) {
1362 if (eol-ptr >= len)
1363 eol = ptr + len-1;
1364 } else {
1365 if (to_top >= len-1) /* we don't mind eol == rtop */
1366 eol = ptr + len-1;
1367 else if (to_top + (eol - s->rbuf) >= len)
1368 eol = s->rbuf + (len-1 - to_top);
1369 }
1370
1371 /* Actually copy to buffer and return */
1372 if (eol > ptr) {
1373 memcpy(buf, ptr, eol-ptr);
1374 buf[eol-ptr] = 0;
1375 } else {
1376 memcpy(buf, ptr, to_top);
1377 memcpy(buf+to_top, s->rbuf, eol - s->rbuf);
1378 buf[to_top + (eol - s->rbuf)] = 0;
1379 }
1380 RETURN_WITH(buf);
1381 }
1382
1383 /*************************************************************************/
1384
1385 /* Reads a line of text from a socket, and strips newline and carriage
1386 * return characters from the end of the line.
1387 */
1388
1389 char *sgets2(char *buf, int32 len, Socket *s)
1390 {
1391 char *str;
1392
1393 ENTER_WITH("%p", "%p,%d,%p", buf, len, s);
1394 str = sgets(buf, len, s);
1395 if (!str)
1396 RETURN_WITH(str);
1397 str = buf + strlen(buf)-1;
1398 if (*str == '\n')
1399 *str-- = 0;
1400 if (*str == '\r')
1401 *str = 0;
1402 RETURN_WITH(buf);
1403 }
1404
1405 /*************************************************************************/
1406
1407 /* Write a string to a socket, like fputs(). Returns the number of bytes
1408 * written.
1409 */
1410
1411 int sputs(const char *str, Socket *s)
1412 {
1413 ENTER_WITH("%d", "[%s],%p", str?str:"(null)", s);
1414 if (!str || !s) {
1415 log("sockets: sputs() with %s!",
1416 !s ? "NULL socket" : "NULL string");
1417 errno = EINVAL;
1418 RETURN_WITH(-1);
1419 }
1420 RETURN_WITH(buffered_write(s, str, strlen(str)));
1421 }
1422
1423 /*************************************************************************/
1424
1425 /* Write to a socket a la [v]printf(). Returns the number of bytes written;
1426 * in no case will more than 65535 bytes be written (if the output would be
1427 * be longer than this, it will be truncated).
1428 */
1429
1430 int sockprintf(Socket *s, const char *fmt, ...)
1431 {
1432 va_list args;
1433 int ret;
1434
1435 ENTER_WITH("%d", "%p,[%s],...", s, fmt?fmt:"(null)");
1436 va_start(args, fmt);
1437 ret = vsockprintf(s, fmt, args);
1438 va_end(args);
1439 RETURN_WITH(ret);
1440 }
1441
1442 int vsockprintf(Socket *s, const char *fmt, va_list args)
1443 {
1444 char buf[65536];
1445
1446 ENTER_WITH("%d", "%p,[%s],%p", s, fmt?fmt:"(null)", args);
1447 if (!s || !fmt) {
1448 log("sockets: [v]sockprintf() with %s!",
1449 !s ? "NULL socket" : "NULL format string");
1450 errno = EINVAL;
1451 RETURN_WITH(-1);
1452 }
1453 RETURN_WITH(buffered_write(s, buf, vsnprintf(buf,sizeof(buf),fmt,args)));
1454 }
1455
1456 /*************************************************************************/
1457 /************************** Internal routines ****************************/
1458 /*************************************************************************/
1459
1460 /* Call a callback on the given socket. Handles setting and clearing
1461 * SF_CALLBACK, and checking for remote disconnects after the callback
1462 * completes. Returns 0 if the socket has been disconnected, 1 otherwise.
1463 * If 0 is returned, the socket should be considered no longer valid; if it
1464 * was an automatically-created socket, the socket itself will have been
1465 * freed.
1466 *
1467 * `s' or `cb' may be NULL, in which case this routine does nothing and
1468 * returns 1.
1469 */
1470
1471 static int do_callback(Socket *s, SocketCallback cb, void *param)
1472 {
1473 ENTER_WITH("%d", "%p,%p,%p", s, cb, param);
1474 if (s && cb) {
1475 /* Check whether the SF_CALLBACK flag was set; if it is, then this
1476 * is a nested callback, so don't clear the flag or disconnect the
1477 * socket afterwards. */
1478 int was_set = s->flags & SF_CALLBACK;
1479
1480 if (!was_set)
1481 s->flags |= SF_CALLBACK;
1482 log_debug(3, "sockets: callback(%d,%p,%p)", s->fd, cb, param);
1483 cb(s, param);
1484 log_debug(3, "sockets: ...cbret(%d,%p,%p)", s->fd, cb, param);
1485 if (!was_set) {
1486 s->flags &= ~SF_CALLBACK;
1487 if (s->flags & SF_BROKEN) {
1488 log_debug(3, "sockets: ...broken");
1489 do_disconn(s, DISCONN_REMOTE_RESUME);
1490 RETURN_WITH(0);
1491 }
1492 if (s->flags & SF_DELETEME) {
1493 log_debug(3, "sockets: ...deleteme");
1494 sock_free(s);
1495 RETURN_WITH(0);
1496 }
1497 if ((s->flags & SF_DISCONNECT) || s->fd < 0) {
1498 log_debug(3, "sockets: ...disconnect");
1499 RETURN_WITH(0);
1500 }
1501 log_debug(3, "sockets: ...normalret");
1502 } else { /* SF_CALLBACK was already set */
1503 log_debug(3, "sockets: ...nestedret");
1504 }
1505 }
1506 RETURN_WITH(1);
1507 }
1508
1509 /*************************************************************************/
1510
1511 /* Accept a connection on the given socket. Called from check_sockets(). */
1512
1513 static void do_accept(Socket *s)
1514 {
1515 int i;
1516 struct sockaddr_in sin;
1517 socklen_t sin_len = sizeof(sin);
1518 int newfd;
1519
1520 ENTER("%p", s);
1521 newfd = accept(s->fd, (struct sockaddr *)&sin, &sin_len);
1522 if (newfd < 0) {
1523 if (errno != ECONNRESET)
1524 log_perror("sockets: accept(%d)", s->fd);
1525 } else if (!s->cb_accept) {
1526 /* No accept callback, so just throw the connection away */
1527 close(newfd);
1528 } else if (fcntl(newfd, F_SETFL, O_NDELAY) < 0) {
1529 log_perror("sockets: fcntl(NDELAY) on accept(%d)", s->fd);
1530 close(newfd);
1531 } else {
1532 Socket *news = sock_new();
1533 if (!news) {
1534 log("sockets: accept(%d): Unable to create socket structure"
1535 " (out of buffer space?)", s->fd);
1536 } else {
1537 news->fd = newfd;
1538 news->flags |= SF_SELFCREATED | SF_CONNECTED;
1539 memcpy(&news->remote, &sin, sin_len);
1540 for (i = newfd; i < max_fd; i++);
1541 if (max_fd < newfd+1) {
1542 void *new_sockets =
1543 realloc(sockets, (newfd+1) * sizeof(*sockets));
1544 if (!new_sockets) {
1545 sock_free(news);
1546 close(newfd);
1547 RETURN;
1548 }
1549 sockets = new_sockets;
1550 for (i = max_fd; i < newfd; i++)
1551 sockets[i] = NULL;
1552 max_fd = newfd+1;
1553 }
1554 sockets[newfd] = news;
1555 if (!(news->flags & SF_MUTE))
1556 FD_SET(newfd, &sock_fds);
1557 do_callback(s, s->cb_accept, news);
1558 }
1559 }
1560 RETURN;
1561 }
1562
1563 /*************************************************************************/
1564
1565 /* Fill up the read buffer of a socket with any data that may have arrived.
1566 * Returns the number of bytes read (nonzero), or -1 on error; errno is set
1567 * by recv() calls but is otherwise preserved.
1568 */
1569
1570 static int fill_read_buffer(Socket *s)
1571 {
1572 int nread = 0;
1573 int errno_save = errno;
1574
1575 ENTER_WITH("%d", "%p", s);
1576 if (s->fd < 0) {
1577 errno = EBADF;
1578 RETURN_WITH(-1);
1579 }
1580 for (;;) {
1581 int maxread, res;
1582 if (read_buffer_len(s) >= read_buffer_size(s)-1) {
1583 /* Read buffer is full; try to expand the buffer. */
1584 int over;
1585 int32 more = resize_how_much(s, read_buffer_size(s), &over);
1586 if (more) {
1587 if (!resize_rbuf(s, read_buffer_size(s) + more)) {
1588 log("sockets: attempt to expand socket %d read buffer"
1589 " failed (out of memory?)", s->fd);
1590 errno_save = EAGAIN;
1591 if (nread == 0)
1592 nread = -1;
1593 break;
1594 }
1595 } else {
1596 #ifdef WARN_ON_BUFSIZE
1597 if (!(s->flags & SF_WARNED)) {
1598 log("sockets: socket %d exceeded %s buffer size limit"
1599 " (%d)", s->fd, over ? "per-connection" : "total",
1600 over ? bufsize_limit : total_bufsize_limit);
1601 s->flags |= SF_WARNED;
1602 }
1603 #endif
1604 errno_save = EAGAIN;
1605 if (nread == 0)
1606 nread = -1;
1607 break;
1608 }
1609 }
1610 if (s->rend < s->rptr) /* wrapped around? */
1611 maxread = (s->rptr-1) - s->rend;
1612 else if (s->rptr == s->rbuf)
1613 maxread = s->rtop - s->rend - 1;
1614 else
1615 maxread = s->rtop - s->rend;
1616 do {
1617 errno = 0;
1618 res = recv(s->fd, s->rend, maxread, 0);
1619 if (res <= 0 && errno == 0)
1620 errno = ECONNRESET; /* make a guess */
1621 } while (res <= 0 && errno == EINTR);
1622 errno_save = errno;
1623 log_debug(3, "sockets: fill_read_buffer wanted %d, got %d",
1624 maxread, nread);
1625 if (res <= 0) {
1626 if (nread == 0)
1627 nread = -1;
1628 break;
1629 }
1630 nread += res;
1631 s->total_read += res;
1632 s->rend += res;
1633 if (s->rend == s->rtop)
1634 s->rend = s->rbuf;
1635 }
1636 if (nread == 0) {
1637 nread = -1;
1638 errno = ENOBUFS;
1639 } else {
1640 errno = errno_save;
1641 }
1642 RETURN_WITH(nread);
1643 }
1644
1645 /*************************************************************************/
1646
1647 /* Try and write up to one chunk of data from the buffer to the socket.
1648 * Return -1 on error, -2 if a socket waiting for disconnection was closed,
1649 * or else how many bytes were written. (Note that a return value of zero
1650 * should not be considered an error.)
1651 */
1652
1653 static int flush_write_buffer(Socket *s)
1654 {
1655 int32 maxwrite, nwritten;
1656
1657 ENTER_WITH("%d", "%p", s);
1658 if (s->fd < 0) {
1659 errno = EBADF;
1660 RETURN_WITH(-1);
1661 }
1662 if (!sock_isconn(s)) /* not yet connected */
1663 RETURN_WITH(0);
1664 if (s->flags & SF_WTRIGGER) {
1665 /* Write trigger is still pending on this socket, don't do anything */
1666 nwritten = 0;
1667 goto check_result;
1668 }
1669 /* "while" instead of "if" to handle the case of:
1670 * s->writemap->wait == 0
1671 * s->writemap->pos == s->writemap->maplen (should be impossible here)
1672 * s->writemap->next->wait == 0
1673 */
1674 while (s->writemap && s->writemap->wait <= 0) {
1675 /* Write data from the map instead of the buffer */
1676 if (!s->writemap->maplen) {
1677 /* It's a trigger, stop here. We don't skip to the next wmap
1678 * yet in case we're called again before the trigger callback
1679 * is called. */
1680 s->flags |= SF_WTRIGGER;
1681 nwritten = 0; /* return value */
1682 goto check_result;
1683 }
1684 maxwrite = s->writemap->maplen - s->writemap->pos;
1685 if (maxwrite > 0) {
1686 nwritten = send(s->fd, s->writemap->map + s->writemap->pos,
1687 maxwrite, 0);
1688 log_debug(3, "sockets: flush_write_buffer/map wanted %d, got %d",
1689 maxwrite, nwritten);
1690 if (nwritten > 0) {
1691 s->writemap->pos += nwritten;
1692 if (s->writemap->pos >= s->writemap->maplen)
1693 next_wmap(s);
1694 }
1695 goto check_result;
1696 } else {
1697 next_wmap(s);
1698 }
1699 }
1700 nwritten = 0;
1701 if (s->wend != s->wptr) {
1702 if (s->wptr > s->wend) /* wrapped around? */
1703 maxwrite = s->wtop - s->wptr;
1704 else
1705 maxwrite = s->wend - s->wptr;
1706 if (s->writemap && maxwrite > s->writemap->wait) {
1707 maxwrite = s->writemap->wait;
1708 if (maxwrite <= 0) {
1709 /* paranoia: this is impossible from the while() above */
1710 log("sockets: BUG: flush_write_buffer(%d): writemap wait 0"
1711 " after while", s->fd);
1712 do_disconn(s, DISCONN_REMOTE);
1713 RETURN_WITH(-1);
1714 }
1715 }
1716 nwritten = send(s->fd, s->wptr, maxwrite, 0);
1717 log_debug(3, "sockets: flush_write_buffer wanted %d, got %d",
1718 maxwrite, nwritten);
1719 if (nwritten > 0) {
1720 struct wmapinfo *info;
1721 for (info = s->writemap; info; info = info->next) {
1722 info->wait -= nwritten;
1723 }
1724 s->wptr += nwritten;
1725 if (s->wptr >= s->wtop)
1726 s->wptr = s->wbuf;
1727 }
1728 check_result:
1729 if (nwritten < 0 && errno != EAGAIN && errno != EINTR) {
1730 int errno_save = errno;
1731 if (errno != ECONNRESET && errno != EPIPE)
1732 log_perror("sockets: flush_write_buffer(%d)", s->fd);
1733 do_disconn(s, DISCONN_REMOTE);
1734 errno = errno_save;
1735 RETURN_WITH(-1);
1736 }
1737 if (nwritten > 0) {
1738 s->last_write_time = time(NULL);
1739 s->flags &= ~SF_WARNED;
1740 s->total_written += nwritten;
1741 } else {
1742 nwritten = 0; /* return value */
1743 }
1744 }
1745 if ((s->flags & SF_CALLBACK) || MORE_TO_WRITE(s)) {
1746 FD_SET(s->fd, &write_fds);
1747 } else {
1748 FD_CLR(s->fd, &write_fds);
1749 if (s->flags & SF_DISCONNECT) {
1750 s->flags &= ~SF_DISCONNECT;
1751 do_disconn(s, DISCONN_LOCAL_RESUME);
1752 RETURN_WITH(-2);
1753 } else {
1754 reclaim_buffer_space_one(s);
1755 }
1756 }
1757 RETURN_WITH(nwritten);
1758 }
1759
1760 /*************************************************************************/
1761
1762 /* Return the amount by which a socket's read or write buffer should be
1763 * expanded. Return zero if the per-connection or total network buffer
1764 * size limits have been reached and the buffer cannot be expanded; in
1765 * this case, set *errp to 1 if the per-connection buffer size limit was
1766 * exceeded, 0 if the total buffer size limit was exceeded.
1767 */
1768
1769 static uint32 resize_how_much(const Socket *s, uint32 current_size, int *errp)
1770 {
1771 uint32 socktotal = read_buffer_size(s) + write_buffer_size(s);
1772 int32 more;
1773 int over = 0, over_total = 0;
1774
1775 /* Check current size against limits */
1776 if (bufsize_limit && socktotal >= bufsize_limit)
1777 over = 1;
1778 if (total_bufsize_limit && total_bufsize >= total_bufsize_limit)
1779 over_total = 1;
1780 if (over || over_total) {
1781 if (over)
1782 *errp = 1;
1783 else
1784 *errp = 0;
1785 return 0;
1786 }
1787
1788 /* Expand by 10%, rounded up to a multiple of SOCK_MIN_BUFSIZE */
1789 more = current_size / 10;
1790 more = (more+SOCK_MIN_BUFSIZE-1) / SOCK_MIN_BUFSIZE * SOCK_MIN_BUFSIZE;
1791
1792 /* Make sure new size doesn't exceed limits */
1793 if (bufsize_limit && socktotal + more >= bufsize_limit)
1794 more = bufsize_limit - socktotal;
1795 if (total_bufsize_limit && total_bufsize + more >= total_bufsize_limit)
1796 more = total_bufsize_limit - total_bufsize;
1797 if (more < 0) {
1798 more = 0;
1799 /* This shouldn't be possible; assume it's the total buffer size */
1800 *errp = 0;
1801 }
1802
1803 /* Return it */
1804 return more;
1805 }
1806
1807
1808 /* Resize a socket's read or write buffer. */
1809
1810 static int resize_rbuf(Socket *s, uint32 size)
1811 {
1812 ENTER("%p,%u", s, size);
1813 if (size <= read_buffer_len(s)) {
1814 log("sockets: BUG: resize_rbuf(%d): size (%d) <= rlen (%d)"
1815 " (cursize %ld)", s->fd, size, read_buffer_len(s),
1816 (long)(s->rtop - s->rbuf));
1817 RETURN_WITH(0);
1818 }
1819 RETURN_WITH(resize_buf(&s->rbuf, &s->rptr, &s->rend, &s->rtop, size));
1820 }
1821
1822
1823 static int resize_wbuf(Socket *s, uint32 size)
1824 {
1825 ENTER("%p,%u", s, size);
1826 if (size <= write_buffer_len(s)) {
1827 log("sockets: BUG: resize_wbuf(%d): size (%d) <= wlen (%d)"
1828 " (cursize %ld)", s->fd, size, write_buffer_len(s),
1829 (long)(s->wtop - s->wbuf));
1830 RETURN_WITH(0);
1831 }
1832 RETURN_WITH(resize_buf(&s->wbuf, &s->wptr, &s->wend, &s->wtop, size));
1833 }
1834
1835 /* Routine that does the actual resizing. Assumes that newsize >= current
1836 * size. Returns nonzero on success, zero on failure (out of memory). */
1837 static int resize_buf(char **p_buf, char **p_ptr, char **p_end, char **p_top,
1838 uint32 newsize)
1839 {
1840 uint32 size = *p_top - *p_buf;
1841 char *newbuf;
1842 uint32 len = 0;
1843
1844 ENTER_WITH("%d", "%p,%p,%p,%p,%u", p_buf, p_ptr, p_end, p_top, newsize);
1845 if (newsize <= size)
1846 RETURN_WITH(1);
1847 newbuf = malloc(newsize);
1848 if (!newbuf)
1849 RETURN_WITH(0);
1850 total_bufsize -= size;
1851 total_bufsize += newsize;
1852 /* Copy old data to new buffer, if any */
1853 if (*p_end < *p_ptr) {
1854 len = *p_top - *p_ptr;
1855 memcpy(newbuf, *p_ptr, len);
1856 *p_ptr = *p_buf;
1857 }
1858 if (*p_end > *p_ptr) {
1859 memcpy(newbuf+len, *p_ptr, *p_end - *p_ptr);
1860 len += *p_end - *p_ptr;
1861 }
1862 free(*p_buf);
1863 *p_buf = newbuf;
1864 *p_ptr = newbuf;
1865 *p_end = newbuf + len;
1866 *p_top = newbuf + newsize;
1867 RETURN_WITH(1);
1868 }
1869
1870 /*************************************************************************/
1871
1872 /* Try to reclaim unused buffer space. Return 1 if some buffer space was
1873 * freed, 0 if not.
1874 */
1875
1876 static int reclaim_buffer_space_one(Socket *s)
1877 {
1878 uint32 rlen = read_buffer_len(s), wlen = write_buffer_len(s);
1879 int retval = 0;
1880
1881 ENTER_WITH("%d", "%p", s);
1882 if (read_buffer_size(s) > SOCK_MIN_BUFSIZE
1883 && rlen < read_buffer_size(s) - SOCK_MIN_BUFSIZE
1884 ) {
1885 if (rlen < SOCK_MIN_BUFSIZE) {
1886 rlen = SOCK_MIN_BUFSIZE;
1887 } else {
1888 /* Round up to the next multiple of SOCK_MIN_BUFSIZE, leaving
1889 * at least one byte available */
1890 rlen += SOCK_MIN_BUFSIZE;
1891 rlen /= SOCK_MIN_BUFSIZE;
1892 rlen *= SOCK_MIN_BUFSIZE;
1893 }
1894 resize_rbuf(s, rlen);
1895 retval = 1;
1896 }
1897 if (write_buffer_size(s) > SOCK_MIN_BUFSIZE
1898 && wlen < write_buffer_size(s) - SOCK_MIN_BUFSIZE
1899 ) {
1900 if (wlen < SOCK_MIN_BUFSIZE) {
1901 wlen = SOCK_MIN_BUFSIZE;
1902 } else {
1903 wlen += SOCK_MIN_BUFSIZE;
1904 wlen /= SOCK_MIN_BUFSIZE;
1905 wlen *= SOCK_MIN_BUFSIZE;
1906 }
1907 resize_wbuf(s, wlen);
1908 retval = 1;
1909 }
1910 RETURN_WITH(retval);
1911 }
1912
1913
1914 static int reclaim_buffer_space(void)
1915 {
1916 Socket *s;
1917 int retval = 0;
1918
1919 ENTER_WITH("%d", "");
1920 LIST_FOREACH (s, allsockets) {
1921 retval |= reclaim_buffer_space_one(s);
1922 }
1923 RETURN_WITH(retval);
1924 }
1925
1926 /*************************************************************************/
1927
1928 /* Free the first map on the socket's writemap list. */
1929
1930 static void next_wmap(Socket *s)
1931 {
1932 struct wmapinfo *next;
1933
1934 ENTER("%p", s);
1935 if (!s || !s->writemap) {
1936 log("sockets: BUG: next_wmap() with NULL %s!",
1937 s ? "writemap" : "socket");
1938 RETURN;
1939 }
1940 if (s->writemap->map) {
1941 #ifdef DISABLE_SWRITEMAP
1942 log("sockets: BUG: DISABLE_SWRITEMAP but non-NULL map %p for socket"
1943 " %p", s->writemap->map, s);
1944 #else
1945 munmap((void *)s->writemap->map, s->writemap->maplen);
1946 #endif
1947 }
1948 next = s->writemap->next;
1949 free(s->writemap);
1950 if (next) {
1951 s->writemap = next;
1952 } else {
1953 s->writemap = s->writemap_tail = NULL;
1954 }
1955 RETURN;
1956 }
1957
1958 /*************************************************************************/
1959
1960 /* Write data to a socket with buffering. */
1961
1962 static int buffered_write(Socket *s, const char *buf, int len)
1963 {
1964 int nwritten, left = len;
1965 int errno_save = errno;
1966
1967 ENTER_WITH("%d", "%p,%p,%d", s, buf, len);
1968 if (s->fd < 0) {
1969 errno = EBADF;
1970 RETURN_WITH(-1);
1971 }
1972
1973 /* Reset the write timeout if the buffer is currently empty and we're
1974 * not busy writing a mapped buffer. */
1975 if (!MORE_TO_WRITE(s))
1976 s->last_write_time = time(NULL);
1977
1978 while (left > 0) {
1979
1980 /* Fill up to the current buffer size. */
1981 if (write_buffer_len(s) < write_buffer_size(s)-1) {
1982 int maxwrite;
1983 /* If buffer is empty, reset pointers to beginning for efficiency*/
1984 if (write_buffer_len(s) == 0)
1985 s->wptr = s->wend = s->wbuf;
1986 if (s->wptr == s->wbuf) {
1987 /* Buffer not wrapped */
1988 maxwrite = s->wtop - s->wend - 1;
1989 } else {
1990 /* Buffer is wrapped. If this write would reach to or past
1991 * the end of the buffer, write it first and reset the end
1992 * pointer to the beginning of the buffer. */
1993 if (s->wend+left >= s->wtop && s->wptr <= s->wend) {
1994 nwritten = s->wtop - s->wend;
1995 memcpy(s->wend, buf, nwritten);
1996 buf += nwritten;
1997 left -= nwritten;
1998 s->wend = s->wbuf;
1999 }
2000 /* Now we can copy a single chunk to wend. */
2001 if (s->wptr > s->wend)
2002 maxwrite = s->wptr - s->wend - 1;
2003 else
2004 maxwrite = left; /* guaranteed to fit from above code */
2005 }
2006 if (left > maxwrite)
2007 nwritten = maxwrite;
2008 else
2009 nwritten = left;
2010 if (nwritten) {
2011 memcpy(s->wend, buf, nwritten);
2012 buf += nwritten;
2013 left -= nwritten;
2014 s->wend += nwritten;
2015 }
2016 }
2017
2018 /* Now write to the socket as much as we can. */
2019 if (flush_write_buffer(s) < 0)
2020 RETURN_WITH(len - left); /* socket is not valid any more */
2021 errno_save = errno;
2022 if (write_buffer_len(s) >= write_buffer_size(s)-1) {
2023 /* Write failed on full buffer; try to expand the buffer. */
2024 int over;
2025 uint32 more = resize_how_much(s, write_buffer_size(s), &over);
2026 if (more) {
2027 if (!resize_wbuf(s, write_buffer_size(s) + more)) {
2028 /* It would be proper to block here, but if we ran out
2029 * of memory the program's probably about to abort
2030 * anyway, so just error out */
2031 log("sockets: attempt to expand socket %d read buffer"
2032 " failed (out of memory?)", s->fd);
2033 errno_save = EAGAIN;
2034 break;
2035 }
2036 } else {
2037 if ((s->flags & SF_BLOCKING) && !(s->flags & SF_WTRIGGER)) {
2038 fd_set fds;
2039 FD_ZERO(&fds);
2040 FD_SET(s->fd, &fds);
2041 if (select(s->fd+1, NULL, &fds, NULL, NULL) < 0) {
2042 log("sockets: waiting on blocking socket %d: %s",
2043 s->fd, strerror(errno));
2044 break;
2045 }
2046 continue; /* don't expand the buffer, since it's at max */
2047 } else {
2048 #ifdef WARN_ON_BUFSIZE
2049 if (!(s->flags & SF_WARNED)) {
2050 log("sockets: socket %d exceeded %s buffer size"
2051 " limit (%d)", s->fd,
2052 over ? "per-connection" : "total",
2053 over ? bufsize_limit : total_bufsize_limit);
2054 s->flags |= SF_WARNED;
2055 }
2056 #endif
2057 errno_save = EAGAIN;
2058 break;
2059 }
2060 }
2061 }
2062
2063 } /* while (left > 0) */
2064
2065 errno = errno_save;
2066 RETURN_WITH(len - left);
2067 }
2068
2069 /*************************************************************************/
2070
2071 /* Internal version of disconn(), used to pass a specific code to the
2072 * disconnect callback. If code == DISCONN_LOCAL, attempt to first write
2073 * out any data left in the write buffer, and delay disconnection if we
2074 * can't.
2075 */
2076
2077 static int do_disconn(Socket *s, void *code)
2078 {
2079 int errno_save = errno; /* for passing to the callback */
2080
2081 ENTER_WITH("%d", "%p,%p", s, code);
2082 if (s == NULL || (s->flags & SF_LISTENER)) {
2083 if (s)
2084 log("sockets: BUG: do_disconn(%d) with listener socket (%d)!",
2085 (int)(long)code, s->fd);
2086 else
2087 log("sockets: BUG: do_disconn(%d) with NULL socket!",
2088 (int)(long)code);
2089 errno = EINVAL;
2090 RETURN_WITH(-1);
2091 }
2092 if ((s->flags & SF_DISCONNECTING) && !((int)code & DISCONN_RESUME_FLAG))
2093 RETURN_WITH(0);
2094 if ((s->flags & SF_DISCONN_REQ) && code == DISCONN_LOCAL)
2095 RETURN_WITH(0);
2096 if (!(s->flags & (SF_CONNECTING | SF_CONNECTED)))
2097 RETURN_WITH(0);
2098 s->flags |= SF_DISCONN_REQ;
2099 FD_CLR(s->fd, &sock_fds);
2100 if (code == DISCONN_LOCAL && MORE_TO_WRITE(s)) {
2101 /* Write out any buffered data */
2102 if (flush_write_buffer(s) >= 0 && MORE_TO_WRITE(s)) {
2103 /* Some data is still buffered; request disconnect after it
2104 * goes out */
2105 s->flags |= SF_DISCONNECT;
2106 /* It's not technically disconnected yet, but it will (should)
2107 * succeed eventually */
2108 RETURN_WITH(0);
2109 }
2110 }
2111 s->flags |= SF_DISCONNECTING;
2112 if (code == DISCONN_REMOTE && (s->flags & SF_CALLBACK)) {
2113 /* Socket was closed while a callback was doing something; wait
2114 * until the callback finishes to actually close the socket */
2115 s->flags |= SF_BROKEN;
2116 RETURN_WITH(0);
2117 }
2118 shutdown(s->fd, 2);
2119 sock_closefd(s);
2120 while (s->writemap)
2121 next_wmap(s);
2122 s->writemap_tail = NULL;
2123 if (s->cb_disconn) {
2124 /* The disconnect callback doesn't need to check for disconnection,
2125 * so we just call it directly */
2126 errno = errno_save;
2127 s->cb_disconn(s, (void *)((int)code & ~DISCONN_RESUME_FLAG));
2128 }
2129 s->flags &= ~SF_DISCONNECTING;
2130 if (s->fd >= 0) {
2131 /* The socket was reconnected */
2132 return 0;
2133 }
2134 s->flags &= ~(SF_CONNECTING | SF_CONNECTED);
2135 if (s->flags & (SF_SELFCREATED | SF_DELETEME)) {
2136 if (s->flags & SF_CALLBACK)
2137 s->flags |= SF_DELETEME;
2138 else
2139 sock_free(s);
2140 } else {
2141 reclaim_buffer_space_one(s);
2142 }
2143 RETURN_WITH(0);
2144 }
2145
2146 /*************************************************************************/
2147
2148 /* Close a socket's file descriptor, and clear it from all associated
2149 * structures (s->fd, sockets[], sock_fds, write_fds).
2150 */
2151
2152 static void sock_closefd(Socket *s)
2153 {
2154 ENTER("%p", s);
2155 /* FIXME: apparently it's possible to come here twice for the same
2156 * connection; under what circumstances can that happen? */
2157 if (s->fd >= 0) {
2158 close(s->fd);
2159 FD_CLR(s->fd, &sock_fds);
2160 FD_CLR(s->fd, &write_fds);
2161 sockets[s->fd] = NULL;
2162 s->fd = -1;
2163 }
2164 RETURN;
2165 }
2166
2167 /*************************************************************************/
2168
2169 /*
2170 * Local variables:
2171 * c-file-style: "stroustrup"
2172 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
2173 * indent-tabs-mode: nil
2174 * End:
2175 *
2176 * vim: expandtab shiftwidth=4:
2177 */