io.c 45.3 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
/* io.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen's avatar
J.H.M. Dassen committed
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Niels Möller's avatar
Niels Möller committed
22
23
 */

24
#include "io.h"
25
26

#include "format.h"
27
28
29
#include "werror.h"
#include "xalloc.h"

Niels Möller's avatar
Niels Möller committed
30
31
32
#include <assert.h>
#include <string.h>

33
#if HAVE_UNISTD_H
Niels Möller's avatar
Niels Möller committed
34
#include <unistd.h>
35
#endif
36
37

#ifdef HAVE_POLL
38
39
40
41
42
# if HAVE_POLL_H
#  include <poll.h>
# elif HAVE_SYS_POLL_H
#  include <sys/poll.h>
# endif
43
#else
44
# include "jpoll.h"
45
46
#endif

47
48
49
50
51
52
53
/* Workaround for some version of FreeBSD. */
#ifdef POLLRDNORM
# define MY_POLLIN (POLLIN | POLLRDNORM)
#else /* !POLLRDNORM */
# define MY_POLLIN POLLIN
#endif /* !POLLRDNORM */

Niels Möller's avatar
Niels Möller committed
54
55
56
57
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
58
#include <sys/un.h>
Niels Möller's avatar
Niels Möller committed
59
#include <arpa/inet.h>
60
#include <signal.h>
61
62
#include <sys/stat.h>

Niels Möller's avatar
Niels Möller committed
63

64
#define GABA_DEFINE
65
#include "io.h.x"
66
#undef GABA_DEFINE
67
68
69

#include "io.c.x"

70
71
72
73
74
75
76
/* Calls trigged by a signal handler. */
/* GABA:
   (class
     (name lsh_signal_handler)
     (super resource)
     (vars
       (next object lsh_signal_handler)
Niels Möller's avatar
Added    
Niels Möller committed
77
       (flag . "volatile sig_atomic_t *")
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
       (action object lsh_callback)))
*/

/* Scheduled calls. FIXME: For now, no scheduling in time. */
/* GABA:
   (class
     (name lsh_callout)
     (super resource)
     (vars
       (next object lsh_callout)
       (action object lsh_callback)))
       ;; (when . time_t)
*/

/* GABA:
   (class
     (name io_backend)
95
     (super resource)
96
97
98
99
100
101
102
103
104
105
106
107
108
109
     (vars
       ; Linked list of fds. 
       (files object lsh_fd)

       ; Stack of closed files
       ;; (closed object lsh_fd)

       ; Flags
       (signals object lsh_signal_handler)
       
       ; Callouts
       (callouts object lsh_callout)))
*/

Niels Möller's avatar
Niels Möller committed
110
111
112

/* Backend loop */

Niels Möller's avatar
Niels Möller committed
113
114
115
116
117
/* If there's nothing to do for this amount of time (ms), do
 * spontaneous gc. */

#define IDLE_TIME 100

Niels Möller's avatar
Niels Möller committed
118
119
120
121
int io_iter(struct io_backend *b)
{
  unsigned long nfds; /* FIXME: Should be nfds_t if that type is defined */
  struct pollfd *fds;
122
123
  struct lsh_fd **active_fds;
  
124
  /* FIXME: Real scheduling of callouts not implemented */
Niels Möller's avatar
Niels Möller committed
125
  /* int timeout; */
Niels Möller's avatar
Niels Möller committed
126
127
  int res;

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  /* Check all flags */
  if (b->signals)
    {
      struct lsh_signal_handler *f;
      struct lsh_signal_handler **f_p;
      for (f_p = &b->signals; (f = *f_p); )
	{
	  if (!f->super.alive)
	    *f_p = f->next;
	  else
	    {
	      if (*f->flag)
		{
		  *f->flag = 0;
		  LSH_CALLBACK(f->action);
		}
	      f_p = &f->next;
	    }
	}
    }
  
149
150
151
152
153
  /* Invoke all callouts. Clear the list first; if any callout
   * installs another one, that will not be invoked until the next
   * iteration. */
  if (b->callouts)
    {
154
      struct lsh_callout *p;
155
      
156
157
158
159
160
161
162
      for (p = b->callouts, b->callouts = NULL;
	   p; p = p->next)
	if (p->super.alive)
	  {
	    LSH_CALLBACK(p->action);
	    p->super.alive = 0;
	  }
163
164
    }
      
Niels Möller's avatar
Niels Möller committed
165
  {
166
167
168
    struct lsh_fd *fd;
    int need_close;
    
169
    /* Prepare fd:s. This phase calls the prepare-methods, also closes
Niels Möller's avatar
Niels Möller committed
170
171
     * and unlinks any fd:s that should be closed, and also counts how
     * many fd:s there are. */
172
173

    for (fd = b->files; fd; fd = fd->next)
Niels Möller's avatar
Niels Möller committed
174
      {
175
	if (fd->super.alive && fd->prepare)
176
	  FD_PREPARE(fd);
177
178
179
180
181
182
183
      }
    
    /* Note that calling a close callback might cause other files to
     * be closed as well, so we need a double loop.
     *
     * FIXME: How can we improve this? We could keep a stack of closed
     * files, but that will require backpointers from the fd:s to the
184
     * backend (so that close_fd can find the top of the stack). */
185
186
187
188
189
190

    do
      {
	struct lsh_fd **fd_p;
	need_close = 0;
	nfds = 0;
Niels Möller's avatar
Niels Möller committed
191
	
192
	for(fd_p = &b->files; (fd = *fd_p); )
Niels Möller's avatar
Niels Möller committed
193
	  {
194
	    if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
195
	      {
196
197
198
199
200
201
202
203
204
205
		if (fd->fd < 0)
		  /* Unlink the file object, but don't close any
		   * underlying file. */
		  ;
		else
		  {
		    /* Used by write fd:s to make sure that writing to its
		     * buffer fails. */
		    if (fd->write_close)
		      FD_WRITE_CLOSE(fd);
Niels Möller's avatar
Niels Möller committed
206
		
207
208
		    if (fd->close_callback)
		      {
209
			LSH_CALLBACK(fd->close_callback);
210
211
			need_close = 1;
		      }
212
		    trace("io.c: Closing fd %i: %z\n", fd->fd, fd->label);
Niels Möller's avatar
Niels Möller committed
213
		
214
215
		    if (close(fd->fd) < 0)
		      {
216
			werror("io.c: close failed, (errno = %i): %z\n",
217
218
219
220
221
			       errno, STRERROR(errno));
			EXCEPTION_RAISE(fd->e,
					make_io_exception(EXC_IO_CLOSE, fd,
							  errno, NULL));
		      }
222
223
224
225
		  }
		/* Unlink this fd */
		*fd_p = fd->next;
		continue;
Niels Möller's avatar
Niels Möller committed
226
	      }
227

228
229
	    if (fd->want_read || fd->want_write)
	      nfds++;
230

231
232
233
	    fd_p = &fd->next;
	  }
      } while (need_close);
Niels Möller's avatar
Niels Möller committed
234
235
236
237
238
239
240
241
  }

  if (!nfds)
    /* Nothing more to do.
     *
     * NOTE: There might be some callouts left, but we won't wait for them. */
    return 0;

242
243
244
  fds = alloca(sizeof(struct pollfd) * nfds);
  active_fds = alloca(sizeof(struct lsh_fd *) *nfds);
  
Niels Möller's avatar
Niels Möller committed
245
246
247
  /* Fill out fds-array */
  {
    struct lsh_fd *fd;
248
    unsigned long i;
Niels Möller's avatar
Niels Möller committed
249
250
    int all_events = 0;
    
251
    for (fd = b->files, i = 0; fd; fd = fd->next)
Niels Möller's avatar
Niels Möller committed
252
      {
253
254
	assert(fd->super.alive);
	
255
256
	if (fd->want_read || fd->want_write)
	  {
257
258
	    assert(i < nfds);

259
	    active_fds[i] = fd;
Niels Möller's avatar
Niels Möller committed
260

261
262
263
264
	    fds[i].fd = fd->fd;
	    fds[i].events = 0;
	    
	    if (fd->want_read)
265
	      fds[i].events |= MY_POLLIN;
Niels Möller's avatar
Niels Möller committed
266

267
268
	    if (fd->want_write)
	      fds[i].events |= POLLOUT;
Niels Möller's avatar
Niels Möller committed
269

270
271
272
	    all_events |= fds[i].events;
	    i++;
	  }
Niels Möller's avatar
Niels Möller committed
273
274
      }
    assert(i == nfds);
275
    assert(all_events);
Niels Möller's avatar
Niels Möller committed
276
277
  }

Niels Möller's avatar
Niels Möller committed
278
  res = poll(fds, nfds, IDLE_TIME);
Niels Möller's avatar
Niels Möller committed
279

Niels Möller's avatar
Niels Möller committed
280
281
  if (!res)
    {
282
      gc_maybe(&b->super.super, 0);
Niels Möller's avatar
Niels Möller committed
283
284
      res = poll(fds, nfds, -1);
    }
285
  else
286
    gc_maybe(&b->super.super, 1);
Niels Möller's avatar
Niels Möller committed
287
  
Niels Möller's avatar
Niels Möller committed
288
289
290
291
292
293
294
295
296
297
298
299
  if (!res)
    {
      /* Callouts are not implemented */
      fatal("Unexpected timeout\n");
    }
  if (res < 0)
    switch(errno)
      {
      case EAGAIN:
      case EINTR:
	return 1;
      default:
300
	fatal("io_iter: poll failed: %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
301
302
303
304
      }
  
  {
    /* Do io. Note that the callback functions may add new fds to the
305
306
     * head of the list, or clear the alive flag on any fd. But this
     * is less of a problem now, as we use the active_fd array.*/
Niels Möller's avatar
Niels Möller committed
307

308
    /* struct lsh_fd *fd; */
309
    unsigned long i;
Niels Möller's avatar
Niels Möller committed
310
    
311
    for(i=0; i<nfds; i++)
Niels Möller's avatar
Niels Möller committed
312
      {
313
	struct lsh_fd *fd = active_fds[i];
Niels Möller's avatar
Niels Möller committed
314
	assert(i<nfds);
315
316

	debug("io.c: poll for fd %i: events = 0x%xi, revents = 0x%xi.\n",
317
 	      fds[i].fd, fds[i].events, fds[i].revents);
Niels Möller's avatar
Niels Möller committed
318
	
319
	if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
320
321
	  continue;

322
323
	/* On systems without poll, we use jpoll.c to emulate some
	 * of poll, but we lack POLLNVAL, POLLPRI and POLLHUP. */
324
#ifdef POLLNVAL
325
326
327
328
329
	if (fds[i].revents & POLLNVAL)
	  {
	    werror("io.c: poll request on fd %i, for events of type %xi\n"
		   "      return POLLNVAL, revents = %xi\n",
		   fds[i].fd, fds[i].events, fds[i].revents);
330
	    close_fd(fd);
331
332
	    continue;
	  }
333
#endif /* POLLNVAL */
334

335
#ifdef POLLHUP
336
	/* NOTE: The behaviour of poll at EOF varies quite a lot
337
338
339
	 * between systems.
	 *
	 * According to Solaris' man page, POLLHUP is mutually
340
341
342
	 * exclusive with POLLOUT, but orthogonal to POLLIN.
	 *
	 * However, on my system (sparc-linux) POLLHUP is set when we
343
344
	 * get EOF on an fd we are reading.
	 *
345
346
	 * I.e. on some systems, EOF is indicated by poll setting
	 * POLLIN and read returning 0 (in particular, this happens
347
	 * if the poll-by-select-code in jpoll.c is used), while on
348
	 * other systems, poll sets POLLHUP and subsequent read
349
350
	 * calls will return -1, not 0.
	 *
351
352
353
354
	 * But to complicate things some more, we can (also on Linux)
	 * get both POLLHUP and POLLIN set. In that case, we do an
	 * ordinary read.
	 *
355
	 * We set the hanged_up flag before calling FD_READ, which
356
	 * tells the io_callback that it should avoid calling read. */
357

358
359
	if (fds[i].revents & POLLHUP)
	  {
360
361
	    if (fd->want_write)
	      /* Will raise an i/o error */
362
	      FD_WRITE(fd);
363
	    else if (fd->want_read)
364
	      {
365
366
367
368
369
370
371
		if (!fd->super.alive)
		  continue;

		/* If reading is not possible, treat this as EOF. */ 
		if (!(fds[i].revents & MY_POLLIN))
		  fd->hanged_up = 1;

372
373
		FD_READ(fd);
	      }
374
	    else
375
376
	      {
		werror("io.c: poll said POLLHUP on an inactive fd.\n");
377
		close_fd(fd);
378
	      }
379
380
	    continue;
	  }
381
#endif /* POLLHUP */
382

Niels Möller's avatar
Niels Möller committed
383
384
385
386
387
388
389
390
391
392
393
394
395
#ifdef POLLERR
	if (fds[i].revents & POLLERR)
	  {
	    werror("io.c: POLLERR. Hanging up.\n");

	    /* FIXME: Should we raise any exception here? */

	    close_fd(fd); 

	    continue;
	  }
#endif /* POLLERR */
	
396
#ifdef POLLPRI
397
398
399
	if (fds[i].revents & POLLPRI)
	  {
	    werror("io.c: Peer is trying to send Out of Band data. Hanging up.\n");
400
401

	    /* FIXME: Should we raise any exception here? */
402

403
	    close_fd(fd); 
404
405
406

	    continue;
	  }
407
#endif /* POLLPRI */
Niels Möller's avatar
Niels Möller committed
408
	if (fds[i].revents & POLLOUT)
409
	  FD_WRITE(fd);
Niels Möller's avatar
Niels Möller committed
410

411
	if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
412
413
	  continue;

414
	if (fds[i].revents & MY_POLLIN)
415
	  FD_READ(fd);
Niels Möller's avatar
Niels Möller committed
416
417
418
419
420
421
      }
    assert(i == nfds);
  }

  return 1;
}
422
  
423
424
void
io_run(struct io_backend *b)
Niels Möller's avatar
Niels Möller committed
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
{
  struct sigaction pipe;
  memset(&pipe, 0, sizeof(pipe));

  pipe.sa_handler = SIG_IGN;
  sigemptyset(&pipe.sa_mask);
  pipe.sa_flags = 0;
  
  if (sigaction(SIGPIPE, &pipe, NULL) < 0)
    fatal("Failed to ignore SIGPIPE.\n");
  
  while(io_iter(b))
    ;
}

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
static void
do_kill_io_backend(struct resource *s)
{
  CAST(io_backend, backend, s);

  if (backend->super.alive)
    {
      struct lsh_fd *fd;
      struct lsh_signal_handler *signal;
  
      for (fd = backend->files, backend->files = NULL;
	   fd; fd = fd->next)
	{
	  close_fd(fd);
      
	  if (fd->fd < 0)
	    /* Unlink silently. */
	    ;
	  else
	    {
	      if (fd->write_close)
		FD_WRITE_CLOSE(fd);
	  
	      if (fd->close_callback)
		LSH_CALLBACK(fd->close_callback);
	  
	      if (close(fd->fd) < 0)
		{
		  werror("io.c: close failed, (errno = %i): %z\n",
			 errno, STRERROR(errno));
		  EXCEPTION_RAISE(fd->e,
				  make_io_exception(EXC_IO_CLOSE, fd,
						    errno, NULL));
		}
	    }
	}
      /* Check that no callback has opened new files. */
      assert(!backend->files);

      for (signal = backend->signals, backend->signals = NULL;
	   signal; signal = signal->next)
	signal->super.alive = 0;

      backend->super.alive = 0;
    }
}

487
488
struct io_backend *
make_io_backend(void)
Niels Möller's avatar
Niels Möller committed
489
{
490
491
  NEW(io_backend, b);

492
493
  resource_init(&b->super, do_kill_io_backend);
  
Niels Möller's avatar
Niels Möller committed
494
  b->files = NULL;
495
  b->signals = NULL;
496
  b->callouts = NULL;
497
498

  return b;
Niels Möller's avatar
Niels Möller committed
499
500
}

501
502
503
504
505
506
void
io_final(struct io_backend *b)
{
  KILL_RESOURCE(&b->super);
}

507
508
struct resource *
io_signal_handler(struct io_backend *b,
Niels Möller's avatar
Added    
Niels Möller committed
509
		  volatile sig_atomic_t *flag,
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
		  struct lsh_callback *action)
{
  NEW(lsh_signal_handler, handler);
  resource_init(&handler->super, NULL);

  handler->next = b->signals;
  handler->flag = flag;
  handler->action = action;

  b->signals = handler;
  
  return &handler->super;
}

/* Delays not implemented. */
struct resource *
io_callout(struct io_backend *b,
	   UINT32 delay UNUSED,
	   struct lsh_callback *action)
{
  NEW(lsh_callout, callout);
  resource_init(&callout->super, NULL);

  callout->next = b->callouts;
  callout->action = action;
  b->callouts = callout;

  return &callout->super;
}
Niels Möller's avatar
Niels Möller committed
539
540
541

/* Read-related callbacks */

542
543
544
static void
do_buffered_read(struct io_callback *s,
		 struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
545
546
547
{
  CAST(io_buffered_read, self, s);
  UINT8 *buffer = alloca(self->buffer_size);
548
549
550
  int res;

  assert(fd->want_read);   
551

552
  /* If hanged_up is set, pretend that read returned 0 */
553
  res = fd->hanged_up ? 0 : read(fd->fd, buffer, self->buffer_size);
Niels Möller's avatar
Niels Möller committed
554
555
556
557
558
559
560
561
562
563

  if (res < 0)
    switch(errno)
      {
      case EINTR:
	break;
      case EWOULDBLOCK:
	werror("io.c: read_callback: Unexpected EWOULDBLOCK\n");
	break;
      case EPIPE:
564
	/* Getting EPIPE from read seems strange, but appearantly
565
566
	 * it happens sometimes. */
	werror("Unexpected EPIPE.\n");
Niels Möller's avatar
Niels Möller committed
567
      default:
Niels Möller's avatar
Niels Möller committed
568
569
570
	EXCEPTION_RAISE(fd->e, 
			make_io_exception(EXC_IO_READ, fd,
					  errno, NULL));
571
572
573
	/* Close the fd, unless it has a write callback. */
	close_fd_read(fd);
	
Niels Möller's avatar
Niels Möller committed
574
575
576
577
578
579
	break;
      }
  else if (res > 0)
    {
      UINT32 left = res;
    
580
      while (fd->super.alive && fd->read && left)
Niels Möller's avatar
Niels Möller committed
581
582
	{
	  UINT32 done;
Niels Möller's avatar
Niels Möller committed
583

584
	  /* NOTE: What to do if want_read is false? To improve the
585
	   * connection_lock mechanism, it must be possible to
586
587
	   * temporarily stop reading, which means that fd->want_read
	   * has to be cleared.
588
589
590
591
592
593
594
595
596
597
598
	   *
	   * But when doing this, we have to keep the data that we
	   * have read, some of which is buffered here, on the stack,
	   * and the rest inside the read-handler.
	   *
	   * There are two alternatives: Save our buffer here, or
	   * continue looping, letting the read-handler process it
	   * into packets. In the latter case, the ssh_connection
	   * could keep a queue of waiting packets, but it would still
	   * have to clear the want_read flag, to prevent that queue
	   * from growing arbitrarily large.
599
	   *
600
	   * We now go with the second alternative. */
601

602
	  assert(self->handler);
Niels Möller's avatar
Niels Möller committed
603
604

	  /* NOTE: This call may replace self->handler */
Niels Möller's avatar
Niels Möller committed
605
	  done = READ_HANDLER(self->handler, left, buffer);
606
	  
Niels Möller's avatar
Niels Möller committed
607
608
	  buffer += done;
	  left -= done;
609

610
611
612
	  if (!fd->want_read)
	    debug("do_buffered_read: want_read = 0; handler needs a pause.\n");
	  
613
614
615
616
617
618
619
	  if (fd->want_read && !self->handler)
	    {
	      werror("do_buffered_read: Handler disappeared! Ignoring %i bytes\n",
		     left);
	      fd->want_read = 0;
	      return;
	    }
Niels Möller's avatar
Niels Möller committed
620
621
622
	}

      if (left)
623
	verbose("read_buffered: fd died, %i buffered bytes discarded\n",
Niels Möller's avatar
Niels Möller committed
624
625
626
		left);
    }
  else
627
628
629
630
631
632
633
    {
      /* We have read EOF. Pass available == 0 to the handler */
      assert(fd->super.alive);
      assert(fd->read);
      assert(fd->want_read);
      assert(self->handler);

Niels Möller's avatar
Niels Möller committed
634
635
      /* Close the fd, unless it has a write callback. */
      close_fd_read(fd);
636
      
637
638
639
      READ_HANDLER(self->handler, 0, NULL);
    }
	
Niels Möller's avatar
Niels Möller committed
640
641
}

642
struct io_callback *
Niels Möller's avatar
Niels Möller committed
643
644
645
646
647
make_buffered_read(UINT32 buffer_size,
		   struct read_handler *handler)
{
  NEW(io_buffered_read, self);

648
  self->super.f = do_buffered_read;
Niels Möller's avatar
Niels Möller committed
649
650
651
652
653
654
  self->buffer_size = buffer_size;
  self->handler = handler;

  return &self->super;
}

655
656
657
static void
do_consuming_read(struct io_callback *c,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
658
{
659
  CAST_SUBTYPE(io_consuming_read, self, c);
Niels Möller's avatar
Niels Möller committed
660
661
  UINT32 wanted = READ_QUERY(self);

662
663
664
  assert(fd->want_read);

  if (fd->hanged_up)
665
    {
666
      /* If hanged_up is set, pretend that read returned 0 */
Niels Möller's avatar
Niels Möller committed
667
      goto eof;
668
669
670
671
672
    }
  
  if (!wanted)
    {
      fd->want_read = 0;
673
    }
Niels Möller's avatar
Niels Möller committed
674
675
676
677
678
679
  else
    {
      struct lsh_string *s = lsh_string_alloc(wanted);
      int res = read(fd->fd, s->data, wanted);

      if (res < 0)
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
	{
	  switch(errno)
	    {
	    case EINTR:
	      break;
	    case EWOULDBLOCK:
	      werror("io.c: read_consume: Unexpected EWOULDBLOCK\n");
	      break;
	    case EPIPE:
	      /* FIXME: I don't understand why reading should return
	       * EPIPE, but it happens occasionally under linux. Perhaps
	       * we should treat it as EOF instead? */
	      werror("io.c: read_consume: Unexpected EPIPE.\n");
	    default:
	      EXCEPTION_RAISE(fd->e, 
			      make_io_exception(EXC_IO_READ,
						fd, errno, NULL));
	      break;
	    }
	  lsh_string_free(s);
	}
Niels Möller's avatar
Niels Möller committed
701
702
703
      else if (res > 0)
	{
	  s->length = res;
704
	  A_WRITE(self->consumer, s);
Niels Möller's avatar
Niels Möller committed
705
706
	}
      else
707
	{
708
	  lsh_string_free(s);
Niels Möller's avatar
Niels Möller committed
709
710
711
	eof:
	  /* Close the fd, unless it has a write callback. */
	  close_fd_read(fd);
712
713
	  A_WRITE(self->consumer, NULL);
	}
Niels Möller's avatar
Niels Möller committed
714
715
716
717
718
719
720
721
    }
}

/* NOTE: Doesn't initialize the query field. That should be done in
 * the subclass's constructor. */
void init_consuming_read(struct io_consuming_read *self,
			 struct abstract_write *consumer)
{
722
  self->super.f = do_consuming_read;
Niels Möller's avatar
Niels Möller committed
723
724
  self->consumer = consumer;
}
725

726

Niels Möller's avatar
Niels Möller committed
727
/* Write related callbacks */
728
729
730
static void
do_write_callback(struct io_callback *s UNUSED,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
731
{
732
  /* CAST(io_write_callback, self, s); */
Niels Möller's avatar
Niels Möller committed
733
734
735
  UINT32 size;
  int res;
  
736
737
  size = MIN(fd->write_buffer->end - fd->write_buffer->start,
	     fd->write_buffer->block_size);
Niels Möller's avatar
Niels Möller committed
738
739
740
  assert(size);
  
  res = write(fd->fd,
741
	      fd->write_buffer->buffer + fd->write_buffer->start,
Niels Möller's avatar
Niels Möller committed
742
743
744
745
746
747
748
749
750
751
	      size);
  if (!res)
    fatal("Closed?");
  if (res < 0)
    switch(errno)
      {
      case EINTR:
      case EAGAIN:
	break;
      case EPIPE:
752
	debug("io.c: Broken pipe.\n");
Niels Möller's avatar
Niels Möller committed
753
754
	
	/* Fall through */
Niels Möller's avatar
Niels Möller committed
755
      default:
756
	werror("io.c: write failed, %z\n", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
757
758
	EXCEPTION_RAISE(fd->e,
			make_io_exception(EXC_IO_WRITE, fd, errno, NULL));
759
	close_fd(fd);
Niels Möller's avatar
Niels Möller committed
760
761
762
763
	
	break;
      }
  else
764
    write_buffer_consume(fd->write_buffer, res);
Niels Möller's avatar
Niels Möller committed
765
}  
766

767
768
769
770
771
772
773
774
775
776
static struct io_callback io_write_callback =
{ STATIC_HEADER, do_write_callback };

static void
do_write_prepare(struct lsh_fd *fd)
{
  assert(fd->write_buffer);

  if (! (fd->want_write = write_buffer_pre_write(fd->write_buffer))
      && fd->write_buffer->closed)
777
    close_fd(fd);
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
}

static void
do_write_close(struct lsh_fd *fd)
{
  /* CAST(io_write_callback, self, s); */

  assert(fd->write_buffer);

  write_buffer_close(fd->write_buffer);
}

struct listen_value *
make_listen_value(struct lsh_fd *fd,
		  struct address_info *peer)
{
  NEW(listen_value, self);

  self->fd = fd;
  self->peer = peer;

  return self;
}

Niels Möller's avatar
Niels Möller committed
802
803
804

/* Listen callback */

805
806
807
808
809
810
811
812
813
814
/* GABA:
   (class
     (name io_listen_callback)
     (super io_callback)
     (vars
       (backend object io_backend)
       (c object command_continuation)
       (e object exception_handler)))
*/

Niels Möller's avatar
Niels Möller committed
815
static void
816
do_listen_callback(struct io_callback *s,
Niels Möller's avatar
Niels Möller committed
817
		   struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
818
{
819
  CAST(io_listen_callback, self, s);
820
821
822
823
824
825

#if WITH_IPV6
  struct sockaddr_storage peer;
#else
  struct sockaddr peer;
#endif
826
827

  socklen_t addr_len = sizeof(peer);
Niels Möller's avatar
Niels Möller committed
828
  int conn;
829

Niels Möller's avatar
Niels Möller committed
830
831
832
  conn = accept(fd->fd,
		(struct sockaddr *) &peer, &addr_len);
  if (conn < 0)
833
    {
834
      werror("io.c: accept failed, %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
835
      return;
836
    }
837
  trace("io.c: accept on fd %i\n", conn);
838
839
  COMMAND_RETURN(self->c,
		 make_listen_value(make_lsh_fd(self->backend,
840
					       conn, "accepted socket", self->e),
841
842
				   sockaddr2info(addr_len,
						 (struct sockaddr *) &peer)));
Niels Möller's avatar
Niels Möller committed
843
}
844

845
846
847
848
849
850
851
852
853
854
855
856
857
struct io_callback *
make_listen_callback(struct io_backend *backend,
		     struct command_continuation *c,
		     struct exception_handler *e)
{
  NEW(io_listen_callback, self);
  self->super.f = do_listen_callback;
  self->backend = backend;
  self->c = c;
  self->e = e;
  
  return &self->super;
}
Niels Möller's avatar
Niels Möller committed
858

Niels Möller's avatar
Niels Möller committed
859
860
/* Connect callback */

861
862
863
864
865
866
867
868
869
870
871
/* GABA:
   (class
     (name io_connect_callback)
     (super io_callback)
     (vars
       (c object command_continuation)))
*/

static void
do_connect_callback(struct io_callback *s,
		    struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
872
{
873
  CAST(io_connect_callback, self, s);
874
  int socket_error;
875
  socklen_t len = sizeof(socket_error);
876
  
877
  /* Check if the connection was successful */
878
879
  if ((getsockopt(fd->fd, SOL_SOCKET, SO_ERROR,
		  (char *) &socket_error, &len) < 0)
880
      || socket_error)
881
    {
882
      debug("io.c: connect_callback: Connect failed.\n");
Niels Möller's avatar
Niels Möller committed
883
      EXCEPTION_RAISE(fd->e,
884
		      make_io_exception(EXC_IO_CONNECT, fd, 0, "connect failed."));
885
      close_fd(fd);
886
887
    }
  else
Niels Möller's avatar
Niels Möller committed
888
    {
889
890
      fd->write = NULL;
      fd->want_write = 0;
891
      fd->label = "connected socket";
892
      COMMAND_RETURN(self->c, fd);
893
    }
894
895
896
897
898
899
900
901
902
903
904
}

static struct io_callback *
make_connect_callback(struct command_continuation *c)
{
  NEW(io_connect_callback, self);

  self->super.f = do_connect_callback;
  self->c = c;

  return &self->super;
905
906
}

907

Niels Möller's avatar
Niels Möller committed
908
/* This function is called if a connection this file somehow depends
909
910
911
912
913
914
915
916
 * on disappears. For instance, the connection may have spawned a
 * child process, and this file may be the stdin of that process. */

/* To kill a file, mark it for closing and the backend will do the work. */
static void do_kill_fd(struct resource *r)
{
  CAST_SUBTYPE(lsh_fd, fd, r);

Niels Möller's avatar
Niels Möller committed
917
918
  /* We use close_fd_nicely, so that any data in the write buffer is
   * flushed before the fd is closed. */
919
  if (r->alive)
920
    close_fd_nicely(fd);
921
922
}

923
924
925
926
927
928
929
930
931
932
/* Closes the file on i/o errors, and passes the exception on */

static void
do_exc_io_handler(struct exception_handler *self,
		  const struct exception *x)
{
  if (x->type & EXC_IO)
    {
      CAST_SUBTYPE(io_exception, e, x);

933
      if (e->fd)
934
	close_fd(e->fd);
935
936
937
938
939
    }
  EXCEPTION_RAISE(self->parent, x);
  return;
}

Niels Möller's avatar
Niels Möller committed
940
/* Initializes a file structure, and adds it to the backend's list. */
941
942
static void
init_file(struct io_backend *b, struct lsh_fd *f, int fd,
943
	  const char *label,
944
	  struct exception_handler *e)
Niels Möller's avatar
Niels Möller committed
945
{
946
947
  resource_init(&f->super, do_kill_fd);

Niels Möller's avatar
Niels Möller committed
948
  f->fd = fd;
949
950
  f->label = label;
  
951
  f->e = make_exception_handler(do_exc_io_handler, e, HANDLER_CONTEXT);
952
  
Niels Möller's avatar
Niels Möller committed
953
954
955
  f->close_callback = NULL;

  f->prepare = NULL;
956

957
958
  f->hanged_up = 0;
  
Niels Möller's avatar
Niels Möller committed
959
960
961
962
963
  f->want_read = 0;
  f->read = NULL;

  f->want_write = 0;
  f->write = NULL;
964
  f->write_close = NULL;
Niels Möller's avatar
Niels Möller committed
965
966
967
968

  f->next = b->files;
  b->files = f;
}
969

970
/* These functions are used by werror and friends */
Niels Möller's avatar
Niels Möller committed
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040

/* For fd:s in blocking mode. */
const struct exception *
write_raw(int fd, UINT32 length, const UINT8 *data)
{
  while(length)
    {
      int written = write(fd, data, length);

      if (written < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_WRITE,
				     NULL, errno, NULL);
	  }
      
      length -= written;
      data += written;
    }
  return NULL;
}

const struct exception *
write_raw_with_poll(int fd, UINT32 length, const UINT8 *data)
{
  while(length)
    {
      struct pollfd pfd;
      int res;
      int written;
      
      pfd.fd = fd;
      pfd.events = POLLOUT;

      res = poll(&pfd, 1, -1);

      if (res < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_WRITE,
				     NULL, errno, NULL);
	  }
      
      written = write(fd, data, length);

      if (written < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_WRITE,
				     NULL, errno, NULL);
	  }
      
      length -= written;
      data += written;
    }
  return NULL;
}

1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
/* For fd:s in blocking mode. */
const struct exception *
read_raw(int fd, UINT32 length, UINT8 *data)
{
  while(length)
    {
      int done = read(fd, data, length);

      if (done < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_READ,
				     NULL, errno, NULL);
	  }
      else if (done == 0)
	{
	  /* EOF. */
	  /* FIXME: Indicate the amount of data read, somehow. */
	  return make_io_exception(EXC_IO_BLOCKING_READ,
				   NULL, 0, NULL);
	}
	
      length -= done;
      data += done;
    }
  return NULL;
}
Niels Möller's avatar
Niels Möller committed
1072
1073
1074

/* Network utility functions */

1075
/* Converts a string port number or service name to a port number.
1076
1077
 * Returns the port number in _host_ byte order, or 0 if lookup
 * fails. */
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

int get_portno(const char *service, const char *protocol)
{
  if (service == NULL)
    return 0;
  else
    {
      char *end;
      long portno;

      portno = strtol(service, &end, 10);
      if (portno > 0
	  &&  portno <= 65535
	  &&  end != service
	  &&  *end == '\0')
	  return portno;
      else
	{
	  struct servent * serv;

	  serv = getservbyname(service, protocol);
1099
1100
	  if (!serv)
	    return 0;
1101
1102
1103
1104
1105
1106
	  return ntohs(serv->s_port);
	}
    }
}


1107
1108
1109
1110
1111
/* If def != 0, use that value as a fallback if the lookup fails. */
struct address_info *
make_address_info_c(const char *host,
		    const char *port,
		    int def)
1112
1113
{
  int portno = get_portno(port, "tcp");
1114
1115
1116
1117
1118
1119
  if (!portno)
    portno = def;

  if (!portno)
    return NULL;

1120
1121
1122
1123
1124
  else
    {
      NEW(address_info, info);
      
      info->port = portno;
1125
      info->ip = host ? ssh_format("%lz", host) : NULL;
1126
1127
1128
1129
      
      return info;
    }
}
1130

1131
1132
struct address_info *
make_address_info(struct lsh_string *host, UINT32 port)
1133
1134
1135
1136
1137
1138
1139
1140
{
  NEW(address_info, info);

  info->port = port; /* htons(port); */
  info->ip = host;
  return info;
}

1141
1142
1143
struct address_info *
sockaddr2info(size_t addr_len UNUSED,
	      struct sockaddr *addr)
1144
{
1145
  NEW(address_info, info);
1146
1147
1148
1149
1150
1151
1152
  
  switch(addr->sa_family)
    {
    case AF_INET:
      {
	struct sockaddr_in *in = (struct sockaddr_in *) addr;
	UINT32 ip = ntohl(in->sin_addr.s_addr);
1153
	info->port = ntohs(in->sin_port);
1154
1155
1156
1157
1158
	info->ip = ssh_format("%di.%di.%di.%di",
			      (ip >> 24) & 0xff,
			      (ip >> 16) & 0xff,
			      (ip >> 8) & 0xff,
			      ip & 0xff);
1159
1160
	return info;
      }
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
#if WITH_IPV6
    case AF_INET6:
      {
	struct sockaddr_in6 *in = (struct sockaddr_in6 *) addr;
	UINT8 *ip = in->sin6_addr.s6_addr;
	info->port = ntohs(in->sin6_port);
	info->ip = ssh_format("%xi:%xi:%xi:%xi:%xi:%xi:%xi:%xi",
			      (ip[0]  << 8) | ip[1],
			      (ip[2]  << 8) | ip[3],
			      (ip[4]  << 8) | ip[5],
			      (ip[6]  << 8) | ip[7],
			      (ip[8]  << 8) | ip[9],
			      (ip[10] << 8) | ip[11],
			      (ip[12] << 8) | ip[13],
			      (ip[14] << 8) | ip[15]);
	return info;
      }
1178
#endif
1179
1180
1181
1182
    case AF_UNIX:
      /* Silently return NULL. This happens when a gateway client
       * connects. */
      return NULL;
1183
    default:
1184
      werror("io.c: sockaddr2info: Unsupported address family.\n");
1185
      return NULL;
1186
1187
    }
}
1188

1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
#if HAVE_GETADDRINFO
static struct addrinfo *
choose_address(struct addrinfo *list,
	       const int *preference)
{
  int i;
  for (i = 0; preference[i]; i++)
    {
      struct addrinfo *p;
      for (p = list; p; p = p->ai_next)
	if (preference[i] == p->ai_family)
	  return p;
    }
  return NULL;
}
#endif /* HAVE_GETADDRINFO */

/* FIXME: Perhaps this function should be changed to return a list of
 * sockaddr:s? */
1208
1209
1210
struct sockaddr *
address_info2sockaddr(socklen_t *length,
		      struct address_info *a,
1211
1212
		      /* Preferred address families. Zero-terminated array. */
		      const int *preference,
1213
		      int lookup)
1214
{
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  char *host;

  if (a->ip)
    {
      host = alloca(a->ip->length + 1);
  
      memcpy(host, a->ip->data, a->ip->length);
      host[a->ip->length] = '\0';
    }
  else
    host = NULL;
1226

1227
/* Some systems have getaddrinfo, but still doesn't implement all of
1228
1229
1230
 * RFC 2553 */
#if defined(HAVE_GETADDRINFO) && \
    defined(HAVE_GAI_STRERROR) && defined(HAVE_AI_NUMERICHOST)
1231
1232
1233
  {
    struct addrinfo hints;
    struct addrinfo *list;
1234
    struct addrinfo *chosen;
1235
    struct sockaddr *res;
1236
1237
1238
1239
1240
1241
1242
    const int default_preference
#if WITH_IPV6
      [3] = { AF_INET6, AF_INET }
#else
      [2] = { AF_INET, 0 }
#endif      
      ;
1243
1244
1245
    int err;
    /* FIXME: It seems ugly to have to convert the port number to a
     * string. */
1246
    struct lsh_string *service = ssh_format("%di", a->port);
1247
1248
1249
1250
1251
1252
1253
1254
1255

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    if (!lookup)
      hints.ai_flags |= AI_NUMERICHOST;
    
1256
    err = getaddrinfo(host, lsh_get_cstring(service), &hints, &list);
1257
1258
1259
1260
    lsh_string_free(service);

    if (err)
      {
1261
	debug("address_info2sockaddr: getaddrinfo failed (err = %d): %z\n",
1262
1263
1264
1265
	      err, gai_strerror(err));
	return NULL;
      }

1266
1267
1268
1269
1270
1271
1272
1273
1274
    chosen = choose_address(list,
			    preference ? preference : default_preference);
    if (!chosen)
      {
	freeaddrinfo(list);
	return NULL;
      }
    
    *length = chosen->ai_addrlen;
1275
1276
    
    res = lsh_space_alloc(*length<