socket.c 57.6 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * Copyright (C) 1998  Internet Software Consortium.
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
Bob Halley's avatar
Bob Halley committed
17
18

#include <config.h>
19
20
21
22
23
24

#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
Michael Graff's avatar
Michael Graff committed
25
#include <fcntl.h>
26
27
28
29
30

#include <sys/types.h>
#include <sys/socket.h>

#include <isc/assertions.h>
31
#include <isc/error.h>
32
33
34
35
36
#include <isc/thread.h>
#include <isc/mutex.h>
#include <isc/condition.h>
#include <isc/socket.h>

Bob Halley's avatar
Bob Halley committed
37
38
#include "util.h"

39
40
41
42
#ifndef _WIN32
#define WINAPI /* we're not windows */
#endif

43
44
45
46
#define ISC_TASK_SEND(a, b) do { \
	INSIST(isc_task_send(a, b) == ISC_R_SUCCESS); \
} while (0);

Michael Graff's avatar
Michael Graff committed
47
#define SOFT_ERROR(e)	((e) == EAGAIN || (e) == EWOULDBLOCK || (e) == EINTR)
48

Michael Graff's avatar
Michael Graff committed
49
#if 1
50
51
52
53
#define ISC_SOCKET_DEBUG
#endif

#if defined(ISC_SOCKET_DEBUG)
Michael Graff's avatar
Michael Graff committed
54
55
56
57
58
59
60
#define TRACE_WATCHER	0x0001
#define TRACE_LISTEN	0x0002
#define TRACE_CONNECT	0x0004
#define TRACE_RECV	0x0008
#define TRACE_SEND    	0x0010
#define TRACE_MANAGER	0x0020

61
int trace_level = 0xffffffff;
Michael Graff's avatar
Michael Graff committed
62
63
64
#define XTRACE(l, a)	if (l & trace_level) printf a
#define XENTER(l, a)	if (l & trace_level) printf("ENTER %s\n", (a))
#define XEXIT(l, a)	if (l & trace_level) printf("EXIT %s\n", (a))
65
#else
Michael Graff's avatar
Michael Graff committed
66
67
68
#define XTRACE(l, a)
#define XENTER(l, a)
#define XEXIT(l, a)
69
70
71
#endif

/*
Michael Graff's avatar
Michael Graff committed
72
73
 * internal event used to send readable/writable events to our internal
 * functions.
74
 */
Michael Graff's avatar
Michael Graff committed
75
typedef struct rwintev {
Bob Halley's avatar
Bob Halley committed
76
77
78
	isc_event_t			common;	   /* Sender is the socket. */
	isc_task_t *			task;	   /* task to send these to */
	isc_socketevent_t *		done_ev;   /* the done event to post */
Michael Graff's avatar
Michael Graff committed
79
	isc_boolean_t			partial;   /* partial i/o ok */
Michael Graff's avatar
Michael Graff committed
80
	isc_boolean_t			canceled;  /* I/O was canceled */
Michael Graff's avatar
Michael Graff committed
81
	isc_boolean_t			posted;	   /* event posted to task */
Michael Graff's avatar
Michael Graff committed
82
	LINK(struct rwintev)		link;	   /* next event */
Bob Halley's avatar
Bob Halley committed
83
} rwintev_t;
Michael Graff's avatar
Michael Graff committed
84
85

typedef struct ncintev {
Bob Halley's avatar
Bob Halley committed
86
87
88
	isc_event_t			common;	   /* Sender is the socket */
	isc_task_t *			task;	   /* task to send these to */
	isc_socket_newconnev_t *	done_ev;   /* the done event */
Michael Graff's avatar
Michael Graff committed
89
	isc_boolean_t			canceled;  /* accept was canceled */
Michael Graff's avatar
Michael Graff committed
90
	isc_boolean_t			posted;	   /* event posted to task */
Michael Graff's avatar
Michael Graff committed
91
	LINK(struct ncintev)		link;	   /* next event */
Bob Halley's avatar
Bob Halley committed
92
} ncintev_t;
Michael Graff's avatar
Michael Graff committed
93
94

typedef struct cnintev {
Bob Halley's avatar
Bob Halley committed
95
96
97
	isc_event_t			common;	   /* Sender is the socket */
	isc_task_t *			task;	   /* task to send these to */
	isc_socket_connev_t *		done_ev;   /* the done event */
Michael Graff's avatar
Michael Graff committed
98
	isc_boolean_t			canceled;  /* connect was canceled */
Michael Graff's avatar
Michael Graff committed
99
	isc_boolean_t			posted;	   /* event posted to task */
Bob Halley's avatar
Bob Halley committed
100
} cnintev_t;
Michael Graff's avatar
Michael Graff committed
101
102
103

#define SOCKET_MAGIC		0x494f696fU	/* IOio */
#define VALID_SOCKET(t)		((t) != NULL && (t)->magic == SOCKET_MAGIC)
Michael Graff's avatar
Michael Graff committed
104

105
106
107
struct isc_socket {
	/* Not locked. */
	unsigned int			magic;
Bob Halley's avatar
Bob Halley committed
108
	isc_socketmgr_t *		manager;
109
	isc_mutex_t			lock;
Michael Graff's avatar
Michael Graff committed
110
111
	isc_sockettype_t		type;

112
113
114
	/* Locked by socket lock. */
	unsigned int			references;
	int				fd;
115
116
	isc_result_t			recv_result;
	isc_result_t			send_result;
Bob Halley's avatar
Bob Halley committed
117
118
119
120
	LIST(rwintev_t)			recv_list;
	LIST(rwintev_t)			send_list;
	LIST(ncintev_t)			accept_list;
	cnintev_t *			connect_ev;
Michael Graff's avatar
Michael Graff committed
121
122
	isc_boolean_t			pending_recv;
	isc_boolean_t			pending_send;
Michael Graff's avatar
Michael Graff committed
123
	isc_boolean_t			pending_accept;
Michael Graff's avatar
Michael Graff committed
124
	isc_boolean_t			listener;  /* is a listener socket */
Michael Graff's avatar
Michael Graff committed
125
	isc_boolean_t			connected;
Michael Graff's avatar
Michael Graff committed
126
	isc_boolean_t			connecting; /* connect pending */
Bob Halley's avatar
Bob Halley committed
127
128
129
130
	rwintev_t *			riev; /* allocated recv intev */
	rwintev_t *			wiev; /* allocated send intev */
	cnintev_t *			ciev; /* allocated accept intev */
	isc_sockaddr_t			address;  /* remote address */
Michael Graff's avatar
Michael Graff committed
131
	int				addrlength; /* remote addrlen */
132
133
134
135
136
137
138
139
};

#define SOCKET_MANAGER_MAGIC		0x494f6d67U	/* IOmg */
#define VALID_MANAGER(m)		((m) != NULL && \
					 (m)->magic == SOCKET_MANAGER_MAGIC)
struct isc_socketmgr {
	/* Not locked. */
	unsigned int			magic;
Bob Halley's avatar
Bob Halley committed
140
	isc_memctx_t *			mctx;
141
142
	isc_mutex_t			lock;
	/* Locked by manager lock. */
Michael Graff's avatar
Michael Graff committed
143
	unsigned int			nsockets;  /* sockets managed */
Michael Graff's avatar
Michael Graff committed
144
	isc_thread_t			watcher;
Michael Graff's avatar
Michael Graff committed
145
	fd_set				read_fds;
146
	fd_set				write_fds;
Bob Halley's avatar
Bob Halley committed
147
	isc_socket_t *			fds[FD_SETSIZE];
Michael Graff's avatar
Michael Graff committed
148
	int				fdstate[FD_SETSIZE];
149
	int				maxfd;
Michael Graff's avatar
Michael Graff committed
150
	int				pipe_fds[2];
151
152
};

Michael Graff's avatar
Michael Graff committed
153
154
155
156
#define CLOSED		0	/* this one must be zero */
#define MANAGED		1
#define CLOSE_PENDING	2

Bob Halley's avatar
Bob Halley committed
157
158
159
160
161
162
163
164
165
static void send_recvdone_event(isc_socket_t *, rwintev_t **,
				isc_socketevent_t **, isc_result_t);
static void send_senddone_event(isc_socket_t *, rwintev_t **,
				isc_socketevent_t **, isc_result_t);
static void done_event_destroy(isc_event_t *);
static void free_socket(isc_socket_t **);
static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
				    isc_socket_t **);
static void destroy(isc_socket_t **);
166
167
168
169
static void internal_accept(isc_task_t *, isc_event_t *);
static void internal_connect(isc_task_t *, isc_event_t *);
static void internal_recv(isc_task_t *, isc_event_t *);
static void internal_send(isc_task_t *, isc_event_t *);
Michael Graff's avatar
Michael Graff committed
170
171
172
173

#define SELECT_POKE_SHUTDOWN		(-1)
#define SELECT_POKE_NOTHING		(-2)
#define SELECT_POKE_RESCAN		(-3) /* XXX implement */
174
175

/*
Michael Graff's avatar
Michael Graff committed
176
177
178
 * Poke the select loop when there is something for us to do.
 * We assume that if a write completes here, it will be inserted into the
 * queue fully.  That is, we will not get partial writes.
179
180
 */
static void
Bob Halley's avatar
Bob Halley committed
181
select_poke(isc_socketmgr_t *mgr, int msg)
182
{
Michael Graff's avatar
Michael Graff committed
183
184
	int cc;

Michael Graff's avatar
Michael Graff committed
185
	cc = write(mgr->pipe_fds[1], &msg, sizeof(int));
Michael Graff's avatar
Michael Graff committed
186
187
188
189
	if (cc < 0) /* XXX need to handle EAGAIN, EINTR here */
		FATAL_ERROR(__FILE__, __LINE__,
			    "write() failed during watcher poke: %s",
			    strerror(errno));
190
191
192
193
194
}

/*
 * read a message on the internal fd.
 */
Michael Graff's avatar
Michael Graff committed
195
static int
Bob Halley's avatar
Bob Halley committed
196
select_readmsg(isc_socketmgr_t *mgr)
197
{
Michael Graff's avatar
Michael Graff committed
198
	int msg;
Michael Graff's avatar
Michael Graff committed
199
200
	int cc;

Michael Graff's avatar
Michael Graff committed
201
	cc = read(mgr->pipe_fds[0], &msg, sizeof(int));
Michael Graff's avatar
Michael Graff committed
202
	if (cc < 0) {
Michael Graff's avatar
Michael Graff committed
203
		if (SOFT_ERROR(errno))
Michael Graff's avatar
Michael Graff committed
204
			return (SELECT_POKE_NOTHING);
Michael Graff's avatar
Michael Graff committed
205

Michael Graff's avatar
Michael Graff committed
206
207
208
209
		FATAL_ERROR(__FILE__, __LINE__,
			    "read() failed during watcher poke: %s",
			    strerror(errno));

Michael Graff's avatar
Michael Graff committed
210
		return (SELECT_POKE_NOTHING);
Michael Graff's avatar
Michael Graff committed
211
	}
212

Michael Graff's avatar
Michael Graff committed
213
	return (msg);
214
215
216
}

/*
Michael Graff's avatar
Michael Graff committed
217
 * Make a fd non-blocking
218
 */
Michael Graff's avatar
Michael Graff committed
219
220
static isc_result_t
make_nonblock(int fd)
221
{
Michael Graff's avatar
Michael Graff committed
222
223
	int ret;
	int flags;
224

Michael Graff's avatar
Michael Graff committed
225
226
227
	flags = fcntl(fd, F_GETFL, 0);
	flags |= O_NONBLOCK;
	ret = fcntl(fd, F_SETFL, flags);
228

Michael Graff's avatar
Michael Graff committed
229
230
231
232
	if (ret == -1) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "fcntl(%d, F_SETFL, %d): %s",
				 fd, flags, strerror(errno));
Michael Graff's avatar
Michael Graff committed
233

Michael Graff's avatar
Michael Graff committed
234
		return (ISC_R_UNEXPECTED);
Michael Graff's avatar
Michael Graff committed
235
236
	}

Michael Graff's avatar
Michael Graff committed
237
	return (ISC_R_SUCCESS);
238
239
}

240
#ifdef ISC_SOCKET_DEBUG
Michael Graff's avatar
Michael Graff committed
241
static void
Bob Halley's avatar
Bob Halley committed
242
socket_dump(isc_socket_t *sock)
Michael Graff's avatar
Michael Graff committed
243
{
Bob Halley's avatar
Bob Halley committed
244
245
	rwintev_t *	rwiev;
	ncintev_t *	aiev;
Michael Graff's avatar
Michael Graff committed
246
247
248
249
250
251
252

	printf("--------\nDump of socket %p\n", sock);
	printf("fd: %d, references %u\n", sock->fd, sock->references);

	printf("recv queue:\n");
	rwiev = HEAD(sock->recv_list);
	while (rwiev != NULL) {
Bob Halley's avatar
Bob Halley committed
253
254
		printf("\tintev %p, done_ev %p, task %p, "
		       "canceled %d, posted %d",
Michael Graff's avatar
Michael Graff committed
255
256
257
258
259
260
261
262
		       rwiev, rwiev->done_ev, rwiev->task, rwiev->canceled,
		       rwiev->posted);
		rwiev = NEXT(rwiev, link);
	}

	printf("send queue:\n");
	rwiev = HEAD(sock->send_list);
	while (rwiev != NULL) {
Bob Halley's avatar
Bob Halley committed
263
264
		printf("\tintev %p, done_ev %p, task %p, "
		       "canceled %d, posted %d",
Michael Graff's avatar
Michael Graff committed
265
266
267
268
269
270
271
272
		       rwiev, rwiev->done_ev, rwiev->task, rwiev->canceled,
		       rwiev->posted);
		rwiev = NEXT(rwiev, link);
	}

	printf("accept queue:\n");
	aiev = HEAD(sock->accept_list);
	while (aiev != NULL) {
Bob Halley's avatar
Bob Halley committed
273
274
		printf("\tintev %p, done_ev %p, task %p, "
		       "canceled %d, posted %d\n",
Michael Graff's avatar
Michael Graff committed
275
276
277
278
279
280
281
		       aiev, aiev->done_ev, aiev->task, aiev->canceled,
		       aiev->posted);
		aiev = NEXT(aiev, link);
	}

	printf("--------\n");
}
282
#endif
Michael Graff's avatar
Michael Graff committed
283

284
/*
Michael Graff's avatar
Michael Graff committed
285
 * Handle freeing a done event when needed.
286
 */
Michael Graff's avatar
Michael Graff committed
287
static void
Bob Halley's avatar
Bob Halley committed
288
done_event_destroy(isc_event_t *ev)
289
{
Bob Halley's avatar
Bob Halley committed
290
	isc_socket_t *sock = ev->sender;
Michael Graff's avatar
Michael Graff committed
291
	isc_boolean_t kill_socket = ISC_FALSE;
292
293
294
295
296
297

	/*
	 * detach from the socket.  We would have already detached from the
	 * task when we actually queue this event up.
	 */
	LOCK(&sock->lock);
Michael Graff's avatar
Michael Graff committed
298
		
299
300
	REQUIRE(sock->references > 0);
	sock->references--;
Michael Graff's avatar
Michael Graff committed
301
302
	XTRACE(TRACE_MANAGER, ("done_event_destroy: sock %p, ref cnt == %d\n",
			       sock, sock->references));
303

Michael Graff's avatar
Michael Graff committed
304
305
	if (sock->references == 0)
		kill_socket = ISC_TRUE;
306
	UNLOCK(&sock->lock);
Michael Graff's avatar
Michael Graff committed
307
308
309
	
	if (kill_socket)
		destroy(&sock);
310
311
}

312
313
314
315
316
317
/*
 * Kill.
 *
 * Caller must ensure locking.
 */
static void
Bob Halley's avatar
Bob Halley committed
318
destroy(isc_socket_t **sockp)
319
{
Bob Halley's avatar
Bob Halley committed
320
321
	isc_socket_t *sock = *sockp;
	isc_socketmgr_t *manager = sock->manager;
322

Michael Graff's avatar
Michael Graff committed
323
324
	XTRACE(TRACE_MANAGER,
	       ("destroy sockp = %p, sock = %p\n", sockp, sock));
Michael Graff's avatar
Michael Graff committed
325

326
327
328
	LOCK(&manager->lock);

	/*
Michael Graff's avatar
Michael Graff committed
329
	 * Noone has this socket open, so the watcher doesn't have to be
Michael Graff's avatar
Michael Graff committed
330
	 * poked, and the socket doesn't have to be locked.
331
	 */
Michael Graff's avatar
Michael Graff committed
332
	manager->fds[sock->fd] = NULL;
Michael Graff's avatar
Michael Graff committed
333
334
	manager->fdstate[sock->fd] = CLOSE_PENDING;
	select_poke(sock->manager, sock->fd);
Michael Graff's avatar
Michael Graff committed
335
	manager->nsockets--;
Michael Graff's avatar
Michael Graff committed
336
	XTRACE(TRACE_MANAGER, ("nsockets == %d\n", manager->nsockets));
337

338
339
340
341
	/*
	 * XXX should reset manager->maxfd here
	 */

342
343
	UNLOCK(&manager->lock);

Michael Graff's avatar
Michael Graff committed
344
	free_socket(sockp);
Michael Graff's avatar
Michael Graff committed
345
346
347
}

static isc_result_t
Bob Halley's avatar
Bob Halley committed
348
349
allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
		isc_socket_t **socketp)
Michael Graff's avatar
Michael Graff committed
350
{
Bob Halley's avatar
Bob Halley committed
351
	isc_socket_t *sock;
Michael Graff's avatar
Michael Graff committed
352
353
354
355

	sock = isc_mem_get(manager->mctx, sizeof *sock);

	if (sock == NULL)
356
		return (ISC_R_NOMEMORY);
Michael Graff's avatar
Michael Graff committed
357
358

	sock->magic = SOCKET_MAGIC;
Michael Graff's avatar
Michael Graff committed
359
	sock->references = 0;
Michael Graff's avatar
Michael Graff committed
360
361
362

	sock->manager = manager;
	sock->type = type;
363
	sock->fd = -1;
Michael Graff's avatar
Michael Graff committed
364
365
366
367

	/*
	 * set up list of readers and writers to be initially empty
	 */
Michael Graff's avatar
Michael Graff committed
368
369
370
371
372
	INIT_LIST(sock->recv_list);
	INIT_LIST(sock->send_list);
	INIT_LIST(sock->accept_list);
	sock->pending_recv = ISC_FALSE;
	sock->pending_send = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
373
	sock->pending_accept = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
374
375
	sock->listener = ISC_FALSE;
	sock->connecting = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
376
	sock->connected = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
377

378
379
380
	sock->recv_result = ISC_R_SUCCESS;
	sock->send_result = ISC_R_SUCCESS;

Michael Graff's avatar
Michael Graff committed
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
	/*
	 * initialize the lock
	 */
	if (isc_mutex_init(&sock->lock) != ISC_R_SUCCESS) {
		sock->magic = 0;
		isc_mem_put(manager->mctx, sock, sizeof *sock);
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_mutex_init() failed");
		return (ISC_R_UNEXPECTED);
	}

	*socketp = sock;

	return (ISC_R_SUCCESS);
}

/*
 * This event requires that the various lists be empty, that the reference
 * count be 1, and that the magic number is valid.  The other socket bits,
 * like the lock, must be initialized as well.  The fd associated must be
 * marked as closed, by setting it to -1 on close, or this routine will
 * also close the socket.
 */
static void
Bob Halley's avatar
Bob Halley committed
405
free_socket(isc_socket_t **socketp)
Michael Graff's avatar
Michael Graff committed
406
{
Bob Halley's avatar
Bob Halley committed
407
	isc_socket_t *sock = *socketp;
Michael Graff's avatar
Michael Graff committed
408

Michael Graff's avatar
Michael Graff committed
409
	REQUIRE(sock->references == 0);
Michael Graff's avatar
Michael Graff committed
410
	REQUIRE(VALID_SOCKET(sock));
Michael Graff's avatar
Michael Graff committed
411
	REQUIRE(!sock->connecting);
Michael Graff's avatar
Michael Graff committed
412
413
	REQUIRE(!sock->pending_recv);
	REQUIRE(!sock->pending_send);
Michael Graff's avatar
Michael Graff committed
414
	REQUIRE(!sock->pending_accept);
Michael Graff's avatar
Michael Graff committed
415
416
417
	REQUIRE(EMPTY(sock->recv_list));
	REQUIRE(EMPTY(sock->send_list));
	REQUIRE(EMPTY(sock->accept_list));
Michael Graff's avatar
Michael Graff committed
418

419
	sock->magic = 0;
Michael Graff's avatar
Michael Graff committed
420
421
422
423

	(void)isc_mutex_destroy(&sock->lock);

	isc_mem_put(sock->manager->mctx, sock, sizeof *sock);
Michael Graff's avatar
Michael Graff committed
424
425

	*socketp = NULL;
426
427
428
429
430
431
432
433
434
435
}

/*
 * Create a new 'type' socket managed by 'manager'.  The sockets
 * parameters are specified by 'expires' and 'interval'.  Events
 * will be posted to 'task' and when dispatched 'action' will be
 * called with 'arg' as the arg value.  The new socket is returned
 * in 'socketp'.
 */
isc_result_t
Bob Halley's avatar
Bob Halley committed
436
437
isc_socket_create(isc_socketmgr_t *manager, isc_sockettype_t type,
		  isc_socket_t **socketp)
438
{
Bob Halley's avatar
Bob Halley committed
439
	isc_socket_t *sock = NULL;
Michael Graff's avatar
Michael Graff committed
440
	isc_result_t ret;
441
442
443
444

	REQUIRE(VALID_MANAGER(manager));
	REQUIRE(socketp != NULL && *socketp == NULL);

Michael Graff's avatar
Michael Graff committed
445
	XENTER(TRACE_MANAGER, "isc_socket_create");
Michael Graff's avatar
Michael Graff committed
446
447
448
449
	
	ret = allocate_socket(manager, type, &sock);
	if (ret != ISC_R_SUCCESS)
		return (ret);
450
451
452
453
454
455
456
457
458
459

	switch (type) {
	case isc_socket_udp:
		sock->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
		break;
	case isc_socket_tcp:
		sock->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
		break;
	}
	if (sock->fd < 0) {
Michael Graff's avatar
Michael Graff committed
460
		free_socket(&sock);
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

		switch (errno) {
		case EMFILE:
		case ENFILE:
		case ENOBUFS:
			return (ISC_R_NORESOURCES);
			break;
		default:
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "socket() failed: %s",
					 strerror(errno));
			return (ISC_R_UNEXPECTED);
			break;
		}
	}

Michael Graff's avatar
Michael Graff committed
477
	if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
Michael Graff's avatar
Michael Graff committed
478
		free_socket(&sock);
Michael Graff's avatar
Michael Graff committed
479
480
481
		return (ISC_R_UNEXPECTED);
	}

482
483
484
	sock->references = 1;
	*socketp = sock;

485
486
487
488
489
490
491
	LOCK(&manager->lock);

	/*
	 * Note we don't have to lock the socket like we normally would because
	 * there are no external references to it yet.
	 */

Michael Graff's avatar
Michael Graff committed
492
	manager->fds[sock->fd] = sock;
Michael Graff's avatar
Michael Graff committed
493
	manager->fdstate[sock->fd] = MANAGED;
Michael Graff's avatar
Michael Graff committed
494
	manager->nsockets++;
Michael Graff's avatar
Michael Graff committed
495
	XTRACE(TRACE_MANAGER, ("nsockets == %d\n", manager->nsockets));
496
497
	if (manager->maxfd < sock->fd)
		manager->maxfd = sock->fd;
498
499
500

	UNLOCK(&manager->lock);

Michael Graff's avatar
Michael Graff committed
501
	XEXIT(TRACE_MANAGER, "isc_socket_create");
502

Michael Graff's avatar
Michael Graff committed
503
	return (ISC_R_SUCCESS);
504
505
506
507
508
509
}

/*
 * Attach to a socket.  Caller must explicitly detach when it is done.
 */
void
Bob Halley's avatar
Bob Halley committed
510
isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp)
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
{
	REQUIRE(VALID_SOCKET(sock));
	REQUIRE(socketp != NULL && *socketp == NULL);

	LOCK(&sock->lock);
	sock->references++;
	UNLOCK(&sock->lock);
	
	*socketp = sock;
}

/*
 * Dereference a socket.  If this is the last reference to it, clean things
 * up by destroying the socket.
 */
void 
Bob Halley's avatar
Bob Halley committed
527
isc_socket_detach(isc_socket_t **socketp)
528
{
Bob Halley's avatar
Bob Halley committed
529
	isc_socket_t *sock;
Michael Graff's avatar
Michael Graff committed
530
	isc_boolean_t kill_socket = ISC_FALSE;
531
532
533
534
535

	REQUIRE(socketp != NULL);
	sock = *socketp;
	REQUIRE(VALID_SOCKET(sock));

Michael Graff's avatar
Michael Graff committed
536
	XENTER(TRACE_MANAGER, "isc_socket_detach");
537
538
539
540
541

	LOCK(&sock->lock);
	REQUIRE(sock->references > 0);
	sock->references--;
	if (sock->references == 0)
Michael Graff's avatar
Michael Graff committed
542
		kill_socket = ISC_TRUE;
543
544
	UNLOCK(&sock->lock);
	
Michael Graff's avatar
Michael Graff committed
545
546
	if (kill_socket)
		destroy(&sock);
547

Michael Graff's avatar
Michael Graff committed
548
	XEXIT(TRACE_MANAGER, "isc_socket_detach");
549
550
551
552

	*socketp = NULL;
}

Michael Graff's avatar
Michael Graff committed
553
554
555
556
557
558
559
560
561
/*
 * I/O is possible on a given socket.  Schedule an event to this task that
 * will call an internal function to do the I/O.  This will charge the
 * task with the I/O operation and let our select loop handler get back
 * to doing something real as fast as possible.
 *
 * The socket and manager must be locked before calling this function.
 */
static void
Bob Halley's avatar
Bob Halley committed
562
dispatch_read(isc_socket_t *sock)
Michael Graff's avatar
Michael Graff committed
563
{
Bob Halley's avatar
Bob Halley committed
564
565
	rwintev_t *iev;
	isc_event_t *ev;
Michael Graff's avatar
Michael Graff committed
566

Michael Graff's avatar
Michael Graff committed
567
	iev = HEAD(sock->recv_list);
Bob Halley's avatar
Bob Halley committed
568
	ev = (isc_event_t *)iev;
Michael Graff's avatar
Michael Graff committed
569

Michael Graff's avatar
Michael Graff committed
570
	INSIST(!sock->pending_recv);
Michael Graff's avatar
Michael Graff committed
571

Michael Graff's avatar
Michael Graff committed
572
	sock->pending_recv = ISC_TRUE;
Michael Graff's avatar
Michael Graff committed
573

Michael Graff's avatar
Michael Graff committed
574
575
	XTRACE(TRACE_WATCHER, ("dispatch_read:  posted event %p to task %p\n",
			       ev, iev->task));
576

Michael Graff's avatar
Michael Graff committed
577
578
	iev->posted = ISC_TRUE;

579
	ISC_TASK_SEND(iev->task, &ev);
Michael Graff's avatar
Michael Graff committed
580
581
}

582
static void
Bob Halley's avatar
Bob Halley committed
583
dispatch_write(isc_socket_t *sock)
Michael Graff's avatar
Michael Graff committed
584
{
Bob Halley's avatar
Bob Halley committed
585
586
	rwintev_t *iev;
	isc_event_t *ev;
Michael Graff's avatar
Michael Graff committed
587

Michael Graff's avatar
Michael Graff committed
588
	iev = HEAD(sock->send_list);
Bob Halley's avatar
Bob Halley committed
589
	ev = (isc_event_t *)iev;
Michael Graff's avatar
Michael Graff committed
590

Michael Graff's avatar
Michael Graff committed
591
592
	INSIST(!sock->pending_send);
	sock->pending_send = ISC_TRUE;
Michael Graff's avatar
Michael Graff committed
593

Michael Graff's avatar
Michael Graff committed
594
595
	iev->posted = ISC_TRUE;

596
	ISC_TASK_SEND(iev->task, &ev);
Michael Graff's avatar
Michael Graff committed
597
598
}

599
static void
Bob Halley's avatar
Bob Halley committed
600
dispatch_listen(isc_socket_t *sock)
601
{
Bob Halley's avatar
Bob Halley committed
602
603
	ncintev_t *iev;
	isc_event_t *ev;
604

Michael Graff's avatar
Michael Graff committed
605
	iev = HEAD(sock->accept_list);
Bob Halley's avatar
Bob Halley committed
606
	ev = (isc_event_t *)iev;
607

Michael Graff's avatar
Michael Graff committed
608
	INSIST(!sock->pending_accept);
609

Michael Graff's avatar
Michael Graff committed
610
611
612
	sock->pending_accept = ISC_TRUE;

	iev->posted = ISC_TRUE;
613

614
	ISC_TASK_SEND(iev->task, &ev);
615
616
}

Michael Graff's avatar
Michael Graff committed
617
static void
Bob Halley's avatar
Bob Halley committed
618
dispatch_connect(isc_socket_t *sock)
Michael Graff's avatar
Michael Graff committed
619
{
Bob Halley's avatar
Bob Halley committed
620
	cnintev_t *iev;
Michael Graff's avatar
Michael Graff committed
621
622
623
624
625

	INSIST(sock->connecting);

	iev = sock->connect_ev;

Michael Graff's avatar
Michael Graff committed
626
627
	iev->posted = ISC_TRUE;

Bob Halley's avatar
Bob Halley committed
628
	ISC_TASK_SEND(iev->task, (isc_event_t **)&iev);
Michael Graff's avatar
Michael Graff committed
629
630
}

Michael Graff's avatar
Michael Graff committed
631
632
633
634
635
636
637
/*
 * Dequeue an item off the given socket's read queue, set the result code
 * in the done event to the one provided, and send it to the task it was
 * destined for.
 *
 * Caller must have the socket locked.
 */
Michael Graff's avatar
Michael Graff committed
638
static void
Bob Halley's avatar
Bob Halley committed
639
640
send_recvdone_event(isc_socket_t *sock, rwintev_t **iev,
		    isc_socketevent_t **dev, isc_result_t resultcode)
Michael Graff's avatar
Michael Graff committed
641
{
Michael Graff's avatar
Michael Graff committed
642
	REQUIRE(!EMPTY(sock->recv_list));
Michael Graff's avatar
Michael Graff committed
643
644
645
646
647
	REQUIRE(iev != NULL);
	REQUIRE(*iev != NULL);
	REQUIRE(dev != NULL);
	REQUIRE(*dev != NULL);

Michael Graff's avatar
Michael Graff committed
648
	DEQUEUE(sock->recv_list, *iev, link);
Michael Graff's avatar
Michael Graff committed
649
	(*dev)->result = resultcode;
Bob Halley's avatar
Bob Halley committed
650
	ISC_TASK_SEND((*iev)->task, (isc_event_t **)dev);
Michael Graff's avatar
Michael Graff committed
651
	(*iev)->done_ev = NULL;
Bob Halley's avatar
Bob Halley committed
652
	isc_event_free((isc_event_t **)iev);
Michael Graff's avatar
Michael Graff committed
653
}
654
static void
Bob Halley's avatar
Bob Halley committed
655
656
send_senddone_event(isc_socket_t *sock, rwintev_t **iev,
		    isc_socketevent_t **dev, isc_result_t resultcode)
657
{
Michael Graff's avatar
Michael Graff committed
658
	REQUIRE(!EMPTY(sock->send_list));
659
660
661
662
663
	REQUIRE(iev != NULL);
	REQUIRE(*iev != NULL);
	REQUIRE(dev != NULL);
	REQUIRE(*dev != NULL);

Michael Graff's avatar
Michael Graff committed
664
	DEQUEUE(sock->send_list, *iev, link);
665
	(*dev)->result = resultcode;
Bob Halley's avatar
Bob Halley committed
666
	ISC_TASK_SEND((*iev)->task, (isc_event_t **)dev);
667
	(*iev)->done_ev = NULL;
Bob Halley's avatar
Bob Halley committed
668
	isc_event_free((isc_event_t **)iev);
669
}
Michael Graff's avatar
Michael Graff committed
670

671
static void
Bob Halley's avatar
Bob Halley committed
672
673
send_ncdone_event(ncintev_t **iev,
		  isc_socket_newconnev_t **dev, isc_result_t resultcode)
674
675
676
677
678
679
680
{
	REQUIRE(iev != NULL);
	REQUIRE(*iev != NULL);
	REQUIRE(dev != NULL);
	REQUIRE(*dev != NULL);

	(*dev)->result = resultcode;
Bob Halley's avatar
Bob Halley committed
681
	ISC_TASK_SEND((*iev)->task, (isc_event_t **)dev);
Michael Graff's avatar
Michael Graff committed
682
	(*iev)->done_ev = NULL;
683

Bob Halley's avatar
Bob Halley committed
684
	isc_event_free((isc_event_t **)iev);
685
686
}

Michael Graff's avatar
Michael Graff committed
687
688
689
690
691
692
693
/*
 * Call accept() on a socket, to get the new file descriptor.  The listen
 * socket is used as a prototype to create a new isc_socket_t.  The new
 * socket is referenced twice (one for the task which is receiving this
 * message, and once for the message itself) so the task does not need to
 * attach to the socket again.  The task is not attached at all.
 */
694
static void
Bob Halley's avatar
Bob Halley committed
695
internal_accept(isc_task_t *task, isc_event_t *ev)
Michael Graff's avatar
Michael Graff committed
696
{
Bob Halley's avatar
Bob Halley committed
697
698
699
700
	isc_socket_t *sock;
	isc_socketmgr_t *manager;
	isc_socket_newconnev_t *dev;
	ncintev_t *iev;
Michael Graff's avatar
Michael Graff committed
701
	struct sockaddr addr;
702
	u_int addrlen;
Michael Graff's avatar
Michael Graff committed
703
	int fd;
704
	isc_result_t result = ISC_R_SUCCESS;
Michael Graff's avatar
Michael Graff committed
705
706

	sock = ev->sender;
707
708
	REQUIRE(VALID_SOCKET(sock));

Bob Halley's avatar
Bob Halley committed
709
	iev = (ncintev_t *)ev;
710
711
	manager = sock->manager;
	REQUIRE(VALID_MANAGER(manager));
Michael Graff's avatar
Michael Graff committed
712
713

	LOCK(&sock->lock);
Michael Graff's avatar
Michael Graff committed
714
715
	XTRACE(TRACE_LISTEN,
	       ("internal_accept called, locked parent sock %p\n", sock));
Michael Graff's avatar
Michael Graff committed
716

Michael Graff's avatar
Michael Graff committed
717
	REQUIRE(sock->pending_accept);
Michael Graff's avatar
Michael Graff committed
718
	REQUIRE(sock->listener);
Michael Graff's avatar
Michael Graff committed
719
	REQUIRE(!EMPTY(sock->accept_list));
Michael Graff's avatar
Michael Graff committed
720
721
	REQUIRE(iev->task == task);

Michael Graff's avatar
Michael Graff committed
722
	sock->pending_accept = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
723

724
725
726
727
	/*
	 * Has this event been canceled?
	 */
	if (iev->canceled) {
Michael Graff's avatar
Michael Graff committed
728
		DEQUEUE(sock->accept_list, iev, link);
Bob Halley's avatar
Bob Halley committed
729
		isc_event_free((isc_event_t **)iev);
Michael Graff's avatar
Michael Graff committed
730
		if (!EMPTY(sock->accept_list))
731
732
733
734
			select_poke(sock->manager, sock->fd);

		UNLOCK(&sock->lock);

735
		return;
736
737
	}

Michael Graff's avatar
Michael Graff committed
738
739
	/*
	 * Try to accept the new connection.  If the accept fails with
Michael Graff's avatar
Michael Graff committed
740
	 * EAGAIN or EINTR, simply poke the watcher to watch this socket
Michael Graff's avatar
Michael Graff committed
741
742
	 * again.
	 */
743
	addrlen = sizeof(addr);
Michael Graff's avatar
Michael Graff committed
744
745
	fd = accept(sock->fd, &addr, &addrlen);
	if (fd < 0) {
Michael Graff's avatar
Michael Graff committed
746
		if (SOFT_ERROR(errno)) {
Michael Graff's avatar
Michael Graff committed
747
748
			select_poke(sock->manager, sock->fd);
			UNLOCK(&sock->lock);
749
			return;
Michael Graff's avatar
Michael Graff committed
750
751
752
753
		}

		/*
		 * If some other error, ignore it as well and hope
Michael Graff's avatar
Michael Graff committed
754
		 * for the best, but log it.
Michael Graff's avatar
Michael Graff committed
755
		 */
Michael Graff's avatar
Michael Graff committed
756
757
		XTRACE(TRACE_LISTEN, ("internal_accept: accept returned %s\n",
				      strerror(errno)));
758
759
760

		fd = -1;
		result = ISC_R_UNEXPECTED;
Michael Graff's avatar
Michael Graff committed
761
	}
762
763

	if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {
764
		close(fd);
765
766
767
768
769
		fd = -1;

		result = ISC_R_UNEXPECTED;

		free_socket(&dev->newsocket);
770
	}
Michael Graff's avatar
Michael Graff committed
771

Michael Graff's avatar
Michael Graff committed
772
773
774
775
776
	DEQUEUE(sock->accept_list, iev, link);

	if (!EMPTY(sock->accept_list))
		select_poke(sock->manager, sock->fd);

Michael Graff's avatar
Michael Graff committed
777
778
	UNLOCK(&sock->lock);

Michael Graff's avatar
Michael Graff committed
779
780
781
782
783
	/*
	 * The accept succeeded.  Pull off the done event and set the
	 * fd and other information in the socket descriptor here.  These
	 * were preallocated for us.
	 */
Michael Graff's avatar
Michael Graff committed
784
785
	dev = iev->done_ev;
	iev->done_ev = NULL;
Michael Graff's avatar
Michael Graff committed
786

787
	/*
788
	 * -1 means the new socket didn't happen.
789
	 */
790
791
	if (fd != -1) {
		dev->newsocket->fd = fd;
792

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
		/*
		 * Save away the remote address
		 */
		dev->newsocket->addrlength = addrlen;
		memcpy(&dev->newsocket->address, &addr, addrlen);
		dev->addrlength = addrlen;
		memcpy(&dev->address, &addr, addrlen);

		LOCK(&manager->lock);
		manager->fds[fd] = dev->newsocket;
		manager->fdstate[fd] = MANAGED;
		if (manager->maxfd < fd)
			manager->maxfd = fd;
		manager->nsockets++;
		UNLOCK(&manager->lock);

		XTRACE(TRACE_LISTEN, ("internal_accept: newsock %p, fd %d\n",
				      dev->newsocket, fd));
	}
Michael Graff's avatar
Michael Graff committed
812

813
	send_ncdone_event(&iev, &dev, result);
Michael Graff's avatar
Michael Graff committed
814
815
}

816
static void
Bob Halley's avatar
Bob Halley committed
817
internal_recv(isc_task_t *task, isc_event_t *ev)
818
{
Bob Halley's avatar
Bob Halley committed
819
820
821
	rwintev_t *iev;
	isc_socketevent_t *dev;
	isc_socket_t *sock;
Michael Graff's avatar
Michael Graff committed
822
823
	int cc;
	size_t read_count;
824
825
	struct sockaddr addr;
	u_int addrlen;
Michael Graff's avatar
Michael Graff committed
826
827
828
829

	/*
	 * Find out what socket this is and lock it.
	 */
Bob Halley's avatar
Bob Halley committed
830
	sock = (isc_socket_t *)ev->sender;
Michael Graff's avatar
Michael Graff committed
831
832
	LOCK(&sock->lock);

Michael Graff's avatar
Michael Graff committed
833
834
	INSIST(sock->pending_recv == ISC_TRUE);
	sock->pending_recv = ISC_FALSE;
Michael Graff's avatar
Michael Graff committed
835

Michael Graff's avatar
Michael Graff committed
836
	XTRACE(TRACE_RECV,
Michael Graff's avatar
Michael Graff committed
837
	       ("internal_recv: sock %p, fd %d\n", sock, sock->fd));
838

Michael Graff's avatar
Michael Graff committed
839
840
841
842
	/*
	 * Pull the first entry off the list, and look at it.  If it is
	 * NULL, or not ours, something bad happened.
	 */
Michael Graff's avatar
Michael Graff committed
843
	iev = HEAD(sock->recv_list);
Michael Graff's avatar
Michael Graff committed
844
845
846
	INSIST(iev != NULL);
	INSIST(iev->task == task);

Michael Graff's avatar
Michael Graff committed
847
848
849
850
851
852
853
	/*
	 * Try to do as much I/O as possible on this socket.  There are no
	 * limits here, currently.  If some sort of quantum read count is
	 * desired before giving up control, make certain to process markers
	 * regardless of quantum.
	 */
	do {
Michael Graff's avatar
Michael Graff committed
854
		iev = HEAD(sock->recv_list);
Michael Graff's avatar
Michael Graff committed
855
856
		dev = iev->done_ev;

Michael Graff's avatar
Michael Graff committed
857
		/*
858
		 * check for canceled I/O
Michael Graff's avatar
Michael Graff committed
859
		 */
860
		if (iev->canceled) {
Michael Graff's avatar
Michael Graff committed
861
			DEQUEUE(sock->recv_list, iev, link);
Bob Halley's avatar
Bob Halley committed
862
			isc_event_free((isc_event_t **)&iev);
Michael Graff's avatar
Michael Graff committed
863
			goto next;
Michael Graff's avatar
Michael Graff committed
864
865
		}

Michael Graff's avatar
Michael Graff committed
866
867
868
869
870
		/*
		 * If this is a marker event, post its completion and
		 * continue the loop.
		 */
		if (dev->common.type == ISC_SOCKEVENT_RECVMARK) {
871
872
			send_recvdone_event(sock, &iev, &dev,
					    sock->recv_result);
Michael Graff's avatar
Michael Graff committed
873
			goto next;
Michael Graff's avatar
Michael Graff committed
874
875
		}

Michael Graff's avatar
Michael Graff committed
876
877
878
879
		/*
		 * It must be a read request.  Try to satisfy it as best
		 * we can.
		 */
Michael Graff's avatar
Michael Graff committed
880
		read_count = dev->region.length - dev->n;
Michael Graff's avatar
Michael Graff committed
881
		if (sock->type == isc_socket_udp) {
882
883
884
885
886
887
888
			addrlen = sizeof(addr);
			cc = recvfrom(sock->fd, dev->region.base + dev->n,
				      read_count, 0,
				      (struct sockaddr *)&addr,
				      &addrlen);
			memcpy(&dev->address, &addr, addrlen);
			dev->addrlength = addrlen;
Michael Graff's avatar
Michael Graff committed
889
890
891
892
		} else {
			cc = recv(sock->fd, dev->region.base + dev->n,
				  read_count, 0);
			memcpy(&dev->address, &sock->address,
893
			       (size_t)sock->addrlength);
Michael Graff's avatar
Michael Graff committed
894
			dev->addrlength = sock->addrlength;
895
		}			
896

Michael Graff's avatar
Michael Graff committed
897
		XTRACE(TRACE_RECV,
Michael Graff's avatar
Michael Graff committed
898
		       ("internal_recv:  read(%d) %d\n", sock->fd, cc));
Michael Graff's avatar
Michael Graff committed
899
900
901
902
903

		/*
		 * check for error or block condition
		 */
		if (cc < 0) {
Michael Graff's avatar
Michael Graff committed
904
			if (SOFT_ERROR(errno))
Michael Graff's avatar
Michael Graff committed
905
				goto poke;
Michael Graff's avatar
Michael Graff committed
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931

#define SOFT_OR_HARD(_system, _isc) \
	if (errno == _system) { \
		if (sock->connected) { \
			if (sock->type == isc_socket_tcp) \
				sock->recv_result = _isc; \
			send_recvdone_event(sock, &iev, &dev, _isc); \
		} \
		goto next; \
	}

			SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
			SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH);
			SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
#undef SOFT_OR_HARD

			/*
			 * This might not be a permanent error.
			 */
			if (errno == ENOBUFS) {
				send_recvdone_event(sock, &iev, &dev,
						    ISC_R_NORESOURCES);

				goto next;
			}

Michael Graff's avatar
Michael Graff committed
932
			UNEXPECTED_ERROR(__FILE__, __LINE__,
933
934
935
936
937
938
					 "internal read: %s", strerror(errno));

			sock->recv_result = ISC_R_UNEXPECTED;  /* XXX */
			send_recvdone_event(sock, &iev, &dev,
					    ISC_R_UNEXPECTED); /* XXX */

Michael Graff's avatar
Michael Graff committed
939
			goto next;
Michael Graff's avatar
Michael Graff committed
940
		}
Michael Graff's avatar
Michael Graff committed
941

Michael Graff's avatar
Michael Graff committed
942
943
944
		/*
		 * read of 0 means the remote end was closed.  Run through
		 * the event queue and dispatch all the events with an EOF
Michael Graff's avatar
Michael Graff committed
945
946
		 * result code.  This will set the EOF flag in markers as
		 * well, but that's really ok.
Michael Graff's avatar
Michael Graff committed
947
948
949
		 */
		if (cc == 0) {
			do {
950
951
				send_recvdone_event(sock, &iev, &dev,
						    ISC_R_EOF);
Michael Graff's avatar
Michael Graff committed
952
				iev = HEAD(sock->recv_list);
Michael Graff's avatar
Michael Graff committed
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
			} while (iev != NULL);

			goto poke;
		}

		/*
		 * if we read less than we expected, update counters,
		 * poke.
		 */
		if ((size_t)cc < read_count) {
			dev->n += cc;

			/*
			 * If partial reads are allowed, we return whatever
			 * was read with a success result, and continue
			 * the loop.
			 */
			if (iev->partial) {
971
972
				send_recvdone_event(sock, &iev, &dev,
						    ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
973
				goto next;
Michael Graff's avatar
Michael Graff committed
974
975
976
977
978
979
980
981
982
			}

			/*
			 * Partials not ok.  Exit the loop and notify the
			 * watcher to wait for more reads
			 */
			goto poke;
		}

983
		/*
Michael Graff's avatar
Michael Graff committed
984
985
		 * Exactly what we wanted to read.  We're done with this
		 * entry.  Post its completion event.
986
		 */
987
988
		if ((size_t)cc == read_count) {
			dev->n += read_count;
989
			send_recvdone_event(sock, &iev, &dev, ISC_R_SUCCESS);
990
		}
Michael Graff's avatar
Michael Graff committed
991

Michael Graff's avatar
Michael Graff committed
992
	next:
Michael Graff's avatar
Michael Graff committed
993
	} while (!EMPTY(sock->recv_list));
Michael Graff's avatar
Michael Graff committed
994
995

 poke:
Michael Graff's avatar
Michael Graff committed
996
	if (!EMPTY(sock->recv_list))
Michael Graff's avatar
Michael Graff committed
997
998
999
		select_poke(sock->manager, sock->fd);

	UNLOCK(&sock->lock);
1000
}