io.c 48.4 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
#include <oop.h>

49
50
51
52
53
54
55
/* 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
56
57
58
59
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
60
#include <sys/un.h>
Niels Möller's avatar
Niels Möller committed
61
#include <arpa/inet.h>
62
#include <signal.h>
63
64
#include <sys/stat.h>

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

66
#define GABA_DEFINE
67
#include "io.h.x"
68
#undef GABA_DEFINE
69
70
71

#include "io.c.x"

72
73
/* Glue to liboop */

74
/* Because of signal handlers, there can be only one oop object. */
75
76
static oop_source_sys *global_oop_sys = NULL;
static oop_source *source = NULL;
77

78
79
void
io_init(void)
80
{
81
82
83
84
85
86
87
88
89
90
91
92
93
  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");

  assert(!global_oop_sys);
  global_oop_sys = oop_sys_new();
  if (!global_oop_sys)
94
    fatal("Failed to initialize liboop.\n");
95
96

  source = oop_sys_source(global_oop_sys);
97
98
}

99
void
100
io_final(void)
101
{
102
103
  gc_final();
  
104
  /* There mustn't be any outstanding callbacks left. */
105
106
107
108
109
110
111
112
113
114
115
116
117
  oop_sys_delete(global_oop_sys);
  global_oop_sys = NULL;
  source = NULL;
}

void
io_run(void)
{
  oop_sys_run(global_oop_sys);

  /* FIXME: Check for OOP_ERROR */
  
  trace("io_run: Exiting\n");
118
119
120
}


121
/* OOP Callbacks */
122
static void *
123
lsh_oop_signal_callback(oop_source *s UNUSED, int sig, void *data)
124
125
126
{
  CAST(lsh_signal_handler, self, (struct lsh_object *) data);

127
  trace("lsh_oop_signal_callback: Signal %i, handler: %t\n",
128
	sig, self->action);
129
  
130
131
  assert(sig == self->signum);
  
132
  LSH_CALLBACK(self->action);
133

134
  return OOP_CONTINUE;
135
136
137
}

static void
138
lsh_oop_register_signal(struct lsh_signal_handler *handler)
139
{
140
141
142
  trace("lsh_oop_register_signal: signal: %i, handler: %t\n",
	handler->signum, handler);
  
143
  if (handler->super.alive)
144
    source->on_signal(source, handler->signum, lsh_oop_signal_callback, handler);
145
146
}

147
static void
148
lsh_oop_cancel_signal(struct lsh_signal_handler *handler)
149
{
150
151
  trace("lsh_oop_cancel_signal: signal: %i, handler: %t\n",
	handler->signum, handler);
152

153
154
  if (handler->super.alive)
    source->cancel_signal(source, handler->signum, lsh_oop_signal_callback, handler);
155
}
156
157

static void *
158
lsh_oop_fd_read_callback(oop_source *s UNUSED, int fileno, oop_event event, void *data)
159
160
161
162
{
  CAST(lsh_fd, fd, (struct lsh_object *) data);

  assert(fileno == fd->fd);
163
164
  assert(event == OOP_READ);
  assert(fd->super.alive);
165

166
  trace("lsh_oop_fd_read_callback: fd %i: %z\n",
167
168
169
	fd->fd, fd->label);

  FD_READ(fd);
170

171
  return OOP_CONTINUE;
172
173
}

174
175
void
lsh_oop_register_read_fd(struct lsh_fd *fd)
176
{
177
178
179
  trace("lsh_oop_register_read_fd: fd: %i, %z\n",
	fd->fd, fd->label);
  
180
  if (fd->super.alive && !fd->want_read)
181
182
183
184
185
186
    {
      assert(fd->read);
      
      source->on_fd(source, fd->fd, OOP_READ, lsh_oop_fd_read_callback, fd);
      fd->want_read = 1;
    }
187
188
}

189
190
191
void
lsh_oop_cancel_read_fd(struct lsh_fd *fd)
{
192
193
194
  trace("lsh_oop_cancel_read_fd: fd: %i, %z\n",
	fd->fd, fd->label);
  
195
196
197
198
199
200
  if (fd->super.alive)
    {
      source->cancel_fd(source, fd->fd, OOP_READ);
      fd->want_read = 0;
    }
}
201
202

static void *
203
lsh_oop_fd_write_callback(oop_source *s UNUSED, int fileno, oop_event event, void *data)
204
{
205
  CAST(lsh_fd, fd, (struct lsh_object *) data);
206

207
  assert(fileno == fd->fd);
208
  assert(event == OOP_WRITE);
209
210
  assert(fd->super.alive);
  
211
  trace("lsh_oop_fd_write_callback: fd %i: %z\n",
212
	fd->fd, fd->label);
213

214
  FD_WRITE(fd);
215

216
  return OOP_CONTINUE;
217
218
}

219
220
void
lsh_oop_register_write_fd(struct lsh_fd *fd)
221
{
222
223
224
  trace("lsh_oop_register_write_fd: fd: %i, %z\n",
	fd->fd, fd->label);
  
225
  if (fd->super.alive && !fd->want_write)
226
227
228
229
230
231
232
    {
      assert(fd->write);
      
      source->on_fd(source, fd->fd, OOP_WRITE, lsh_oop_fd_write_callback, fd);
      fd->want_write = 1;
    }
}
233

234
235
void
lsh_oop_cancel_write_fd(struct lsh_fd *fd)
236
{
237
238
239
  trace("lsh_oop_cancel_write_fd: fd: %i, %z\n",
	fd->fd, fd->label);

240
241
242
243
244
  if (fd->super.alive)
    {
      source->cancel_fd(source, fd->fd, OOP_WRITE);
      fd->want_write = 0;
    }
245
246
247
}


248
249
250
251
252
253
/* Calls trigged by a signal handler. */
/* GABA:
   (class
     (name lsh_signal_handler)
     (super resource)
     (vars
254
       (signum . int)
255
256
257
258
259
260
261
262
263
264
265
266
267
268
       (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)
*/

269
270
/* FIXME: With liboop, we should not need this object, we'd only need
 * a resource_list owned by the gc. */
271
/* ;; GABA:
272
273
   (class
     (name io_backend)
274
     (super resource)
275
276
277
278
     (vars
       ; Linked list of fds. 
       (files object lsh_fd)

279
       ; Signal handlers
280
281
282
283
284
285
       (signals object lsh_signal_handler)
       
       ; Callouts
       (callouts object lsh_callout)))
*/

Niels Möller's avatar
Niels Möller committed
286
287
288

/* Backend loop */

Niels Möller's avatar
Niels Möller committed
289
290
291
292
293
/* If there's nothing to do for this amount of time (ms), do
 * spontaneous gc. */

#define IDLE_TIME 100

294
#if 0
Niels Möller's avatar
Niels Möller committed
295
296
297
298
int io_iter(struct io_backend *b)
{
  unsigned long nfds; /* FIXME: Should be nfds_t if that type is defined */
  struct pollfd *fds;
299
300
  struct lsh_fd **active_fds;
  
301
  /* FIXME: Real scheduling of callouts not implemented */
Niels Möller's avatar
Niels Möller committed
302
  /* int timeout; */
Niels Möller's avatar
Niels Möller committed
303
304
  int res;

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  /* 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;
	    }
	}
    }
  
326
327
328
329
330
  /* 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)
    {
331
      struct lsh_callout *p;
332
      
333
334
335
336
337
338
339
      for (p = b->callouts, b->callouts = NULL;
	   p; p = p->next)
	if (p->super.alive)
	  {
	    LSH_CALLBACK(p->action);
	    p->super.alive = 0;
	  }
340
    }
341
342

  /* Prepare fds. */
Niels Möller's avatar
Niels Möller committed
343
  {
344
345
346
    struct lsh_fd *fd;

    for (fd = b->files; fd; fd = fd->next)
347
348
349
350
      /* NOTE: The prepare callback is allowed to close files. */
      if (fd->super.alive && fd->prepare)
	FD_PREPARE(fd);
  }
351

352
353
354
355
356
357
358
359
  /* This phase unlinks any closed fd:s, and also counts how many
   * fd:s there are. */
  {
    struct lsh_fd *fd;
    struct lsh_fd **fd_p;
    nfds = 0;
    
    for(fd_p = &b->files; (fd = *fd_p); )
360
      {
361
362
363
364
365
	if (!fd->super.alive)
	  /* Unlink this fd */
	  *fd_p = fd->next;
	    
	else
Niels Möller's avatar
Niels Möller committed
366
	  {
367
368
	    if (fd->want_read || fd->want_write)
	      nfds++;
369

370
371
	    fd_p = &fd->next;
	  }
372
      }
Niels Möller's avatar
Niels Möller committed
373
  }
374
    
Niels Möller's avatar
Niels Möller committed
375
376
377
378
379
380
  if (!nfds)
    /* Nothing more to do.
     *
     * NOTE: There might be some callouts left, but we won't wait for them. */
    return 0;

381
382
383
  fds = alloca(sizeof(struct pollfd) * nfds);
  active_fds = alloca(sizeof(struct lsh_fd *) *nfds);
  
Niels Möller's avatar
Niels Möller committed
384
385
386
  /* Fill out fds-array */
  {
    struct lsh_fd *fd;
387
    unsigned long i;
Niels Möller's avatar
Niels Möller committed
388
389
    int all_events = 0;
    
390
    for (fd = b->files, i = 0; fd; fd = fd->next)
Niels Möller's avatar
Niels Möller committed
391
      {
392
393
	assert(fd->super.alive);
	
394
395
	if (fd->want_read || fd->want_write)
	  {
396
397
	    assert(i < nfds);

398
	    active_fds[i] = fd;
Niels Möller's avatar
Niels Möller committed
399

400
401
402
403
	    fds[i].fd = fd->fd;
	    fds[i].events = 0;
	    
	    if (fd->want_read)
404
	      fds[i].events |= MY_POLLIN;
Niels Möller's avatar
Niels Möller committed
405

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

409
410
411
	    all_events |= fds[i].events;
	    i++;
	  }
Niels Möller's avatar
Niels Möller committed
412
413
      }
    assert(i == nfds);
414
    assert(all_events);
Niels Möller's avatar
Niels Möller committed
415
416
  }

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

Niels Möller's avatar
Niels Möller committed
419
420
  if (!res)
    {
421
      gc_maybe(&b->super.super, 0);
Niels Möller's avatar
Niels Möller committed
422
423
      res = poll(fds, nfds, -1);
    }
424
  else
425
    gc_maybe(&b->super.super, 1);
Niels Möller's avatar
Niels Möller committed
426
  
Niels Möller's avatar
Niels Möller committed
427
428
429
430
431
432
433
434
435
436
437
438
  if (!res)
    {
      /* Callouts are not implemented */
      fatal("Unexpected timeout\n");
    }
  if (res < 0)
    switch(errno)
      {
      case EAGAIN:
      case EINTR:
	return 1;
      default:
439
	fatal("io_iter: poll failed: %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
440
441
442
443
      }
  
  {
    /* Do io. Note that the callback functions may add new fds to the
444
445
     * 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
446

447
    /* struct lsh_fd *fd; */
448
    unsigned long i;
Niels Möller's avatar
Niels Möller committed
449
    
450
    for(i=0; i<nfds; i++)
Niels Möller's avatar
Niels Möller committed
451
      {
452
	struct lsh_fd *fd = active_fds[i];
Niels Möller's avatar
Niels Möller committed
453
	assert(i<nfds);
454
455

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

461
462
	/* On systems without poll, we use jpoll.c to emulate some
	 * of poll, but we lack POLLNVAL, POLLPRI and POLLHUP. */
463
#ifdef POLLNVAL
464
465
466
467
468
	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);
469
	    close_fd(fd);
470
471
	    continue;
	  }
472
#endif /* POLLNVAL */
473

474
#ifdef POLLHUP
475
	/* NOTE: The behaviour of poll at EOF varies quite a lot
476
477
478
	 * between systems.
	 *
	 * According to Solaris' man page, POLLHUP is mutually
479
480
481
	 * exclusive with POLLOUT, but orthogonal to POLLIN.
	 *
	 * However, on my system (sparc-linux) POLLHUP is set when we
482
483
	 * get EOF on an fd we are reading.
	 *
484
485
	 * I.e. on some systems, EOF is indicated by poll setting
	 * POLLIN and read returning 0 (in particular, this happens
486
	 * if the poll-by-select-code in jpoll.c is used), while on
487
	 * other systems, poll sets POLLHUP and subsequent read
488
489
	 * calls will return -1, not 0.
	 *
490
491
492
493
	 * 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.
	 *
494
	 * We set the hanged_up flag before calling FD_READ, which
495
	 * tells the io_callback that it should avoid calling read. */
496

497
498
	if (fds[i].revents & POLLHUP)
	  {
499
500
	    if (fd->want_write)
	      /* Will raise an i/o error */
501
	      FD_WRITE(fd);
502
	    else if (fd->want_read)
503
	      {
504
505
506
507
508
509
510
		if (!fd->super.alive)
		  continue;

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

511
512
		FD_READ(fd);
	      }
513
	    else
514
515
	      {
		werror("io.c: poll said POLLHUP on an inactive fd.\n");
516
		close_fd(fd);
517
	      }
518
519
	    continue;
	  }
520
#endif /* POLLHUP */
521

Niels Möller's avatar
Niels Möller committed
522
523
524
525
526
527
528
529
530
531
532
533
534
#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 */
	
535
#ifdef POLLPRI
536
537
538
	if (fds[i].revents & POLLPRI)
	  {
	    werror("io.c: Peer is trying to send Out of Band data. Hanging up.\n");
539
540

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

542
	    close_fd(fd); 
543
544
545

	    continue;
	  }
546
#endif /* POLLPRI */
Niels Möller's avatar
Niels Möller committed
547
	if (fds[i].revents & POLLOUT)
548
	  FD_WRITE(fd);
Niels Möller's avatar
Niels Möller committed
549

550
	if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
551
552
	  continue;

553
	if (fds[i].revents & MY_POLLIN)
554
	  FD_READ(fd);
Niels Möller's avatar
Niels Möller committed
555
556
557
558
559
560
      }
    assert(i == nfds);
  }

  return 1;
}
561
562
#endif

563
#if 0
564
565
566
567
568
569
570
571
572
573
574
575
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)
576
577
	close_fd(fd);

578
579
580
      /* Check that no callback has opened new files. */
      assert(!backend->files);

581
      /* FIXME: Use a resource list instead? */
582
583
      for (signal = backend->signals, backend->signals = NULL;
	   signal; signal = signal->next)
584
585
	KILL_RESOURCE(&signal->super);
      
586
587
588
      backend->super.alive = 0;
    }
}
589
#endif
590

591
#if 0
592
593
struct io_backend *
make_io_backend(void)
Niels Möller's avatar
Niels Möller committed
594
{
595
596
  NEW(io_backend, b);

597
  io_init();
598
599
  init_resource(&b->super, do_kill_io_backend);
    
Niels Möller's avatar
Niels Möller committed
600
  b->files = NULL;
601
  b->signals = NULL;
602
  b->callouts = NULL;
603
604

  return b;
Niels Möller's avatar
Niels Möller committed
605
}
606
#endif
607

608
609
610
611
612
613
614
static void
do_kill_signal_handler(struct resource *s)
{
  CAST(lsh_signal_handler, self, s);

  if (self->super.alive)
    {
615
      lsh_oop_cancel_signal(self);
616
617
618
619
      self->super.alive = 0;
    }
}

620
struct resource *
621
io_signal_handler(int signum,
622
623
624
		  struct lsh_callback *action)
{
  NEW(lsh_signal_handler, handler);
625
626

  init_resource(&handler->super, do_kill_signal_handler);
627

628
  handler->signum = signum;
629
630
  handler->action = action;

631
  lsh_oop_register_signal(handler);
632
  gc_global(&handler->super);
633
634
635
636
637
638
  
  return &handler->super;
}

/* Delays not implemented. */
struct resource *
639
io_callout(UINT32 delay UNUSED,
640
641
	   struct lsh_callback *action)
{
642
643
  NEW(lsh_callout, self);
  init_resource(&self->super, NULL);
644

645
  self->action = action;
646

647
648
  gc_global(&self->super);
  return &self->super;
649
}
Niels Möller's avatar
Niels Möller committed
650
651
652

/* Read-related callbacks */

653
654
655
static void
do_buffered_read(struct io_callback *s,
		 struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
656
657
658
{
  CAST(io_buffered_read, self, s);
  UINT8 *buffer = alloca(self->buffer_size);
659
660
661
  int res;

  assert(fd->want_read);   
662

663
#if 0
664
  /* If hanged_up is set, pretend that read returned 0 */
665
  res = fd->hanged_up ? 0 : read(fd->fd, buffer, self->buffer_size);
666
#endif
Niels Möller's avatar
Niels Möller committed
667

668
  res = read(fd->fd, buffer, self->buffer_size);
669
  
Niels Möller's avatar
Niels Möller committed
670
671
672
673
674
675
676
677
678
  if (res < 0)
    switch(errno)
      {
      case EINTR:
	break;
      case EWOULDBLOCK:
	werror("io.c: read_callback: Unexpected EWOULDBLOCK\n");
	break;
      case EPIPE:
679
	/* Getting EPIPE from read seems strange, but appearantly
680
681
	 * it happens sometimes. */
	werror("Unexpected EPIPE.\n");
Niels Möller's avatar
Niels Möller committed
682
      default:
Niels Möller's avatar
Niels Möller committed
683
684
685
	EXCEPTION_RAISE(fd->e, 
			make_io_exception(EXC_IO_READ, fd,
					  errno, NULL));
686
687
688
	/* Close the fd, unless it has a write callback. */
	close_fd_read(fd);
	
Niels Möller's avatar
Niels Möller committed
689
690
691
692
693
694
	break;
      }
  else if (res > 0)
    {
      UINT32 left = res;
    
695
      while (fd->super.alive && fd->read && left)
Niels Möller's avatar
Niels Möller committed
696
697
	{
	  UINT32 done;
Niels Möller's avatar
Niels Möller committed
698

699
	  /* NOTE: What to do if want_read is false? To improve the
700
	   * connection_lock mechanism, it must be possible to
701
702
	   * temporarily stop reading, which means that fd->want_read
	   * has to be cleared.
703
704
705
706
707
708
709
710
711
712
713
	   *
	   * 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.
714
	   *
715
	   * We now go with the second alternative. */
716

717
	  assert(self->handler);
Niels Möller's avatar
Niels Möller committed
718
719

	  /* NOTE: This call may replace self->handler */
Niels Möller's avatar
Niels Möller committed
720
	  done = READ_HANDLER(self->handler, left, buffer);
721
	  
Niels Möller's avatar
Niels Möller committed
722
723
	  buffer += done;
	  left -= done;
724

725
726
727
	  if (!fd->want_read)
	    debug("do_buffered_read: want_read = 0; handler needs a pause.\n");
	  
728
729
730
731
	  if (fd->want_read && !self->handler)
	    {
	      werror("do_buffered_read: Handler disappeared! Ignoring %i bytes\n",
		     left);
732
	      lsh_oop_cancel_read_fd(fd);
733
734
	      return;
	    }
Niels Möller's avatar
Niels Möller committed
735
736
737
	}

      if (left)
738
	verbose("read_buffered: fd died, %i buffered bytes discarded\n",
Niels Möller's avatar
Niels Möller committed
739
740
741
		left);
    }
  else
742
743
744
745
746
747
748
    {
      /* 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
749
750
      /* Close the fd, unless it has a write callback. */
      close_fd_read(fd);
751
      
752
753
754
      READ_HANDLER(self->handler, 0, NULL);
    }
	
Niels Möller's avatar
Niels Möller committed
755
756
}

757
struct io_callback *
Niels Möller's avatar
Niels Möller committed
758
759
760
761
762
make_buffered_read(UINT32 buffer_size,
		   struct read_handler *handler)
{
  NEW(io_buffered_read, self);

763
  self->super.f = do_buffered_read;
Niels Möller's avatar
Niels Möller committed
764
765
766
767
768
769
  self->buffer_size = buffer_size;
  self->handler = handler;

  return &self->super;
}

770
771
772
static void
do_consuming_read(struct io_callback *c,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
773
{
774
  CAST_SUBTYPE(io_consuming_read, self, c);
Niels Möller's avatar
Niels Möller committed
775
776
  UINT32 wanted = READ_QUERY(self);

777
778
  assert(fd->want_read);

779
#if 0
780
  if (fd->hanged_up)
781
    {
782
      /* If hanged_up is set, pretend that read returned 0 */
Niels Möller's avatar
Niels Möller committed
783
      goto eof;
784
    }
785
#endif
786
787
788
  
  if (!wanted)
    {
789
      lsh_oop_cancel_read_fd(fd);
790
    }
Niels Möller's avatar
Niels Möller committed
791
792
793
794
795
796
  else
    {
      struct lsh_string *s = lsh_string_alloc(wanted);
      int res = read(fd->fd, s->data, wanted);

      if (res < 0)
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
	{
	  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
818
819
820
      else if (res > 0)
	{
	  s->length = res;
821
	  A_WRITE(self->consumer, s);
Niels Möller's avatar
Niels Möller committed
822
823
	}
      else
824
	{
825
	  lsh_string_free(s);
Niels Möller's avatar
Niels Möller committed
826
827
	eof:
	  /* Close the fd, unless it has a write callback. */
828
	  A_WRITE(self->consumer, NULL);
829
	  close_fd_read(fd);
830
	}
Niels Möller's avatar
Niels Möller committed
831
832
833
834
835
836
837
838
    }
}

/* 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)
{
839
  self->super.f = do_consuming_read;
Niels Möller's avatar
Niels Möller committed
840
841
  self->consumer = consumer;
}
842

843

Niels Möller's avatar
Niels Möller committed
844
/* Write related callbacks */
845
846
847
static void
do_write_callback(struct io_callback *s UNUSED,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
848
{
849
  /* CAST(io_write_callback, self, s); */
Niels Möller's avatar
Niels Möller committed
850
851
  UINT32 size;
  int res;
852

853
  /* FIXME: Delete this useless indirection. */
854
855
856
857
  FD_PREPARE(fd);

  if (! (fd->super.alive && fd->want_write))
    {
858
      lsh_oop_cancel_write_fd(fd);
859
860
      return;
    }
Niels Möller's avatar
Niels Möller committed
861
  
862
863
  size = MIN(fd->write_buffer->end - fd->write_buffer->start,
	     fd->write_buffer->block_size);
Niels Möller's avatar
Niels Möller committed
864
865
866
  assert(size);
  
  res = write(fd->fd,
867
	      fd->write_buffer->buffer + fd->write_buffer->start,
Niels Möller's avatar
Niels Möller committed
868
869
870
871
872
873
874
875
876
877
	      size);
  if (!res)
    fatal("Closed?");
  if (res < 0)
    switch(errno)
      {
      case EINTR:
      case EAGAIN:
	break;
      case EPIPE:
878
	debug("io.c: Broken pipe.\n");
Niels Möller's avatar
Niels Möller committed
879
880
	
	/* Fall through */
Niels Möller's avatar
Niels Möller committed
881
      default:
882
	werror("io.c: write failed, %z\n", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
883
884
	EXCEPTION_RAISE(fd->e,
			make_io_exception(EXC_IO_WRITE, fd, errno, NULL));
885
	close_fd(fd);
Niels Möller's avatar
Niels Möller committed
886
887
888
889
	
	break;
      }
  else
890
    write_buffer_consume(fd->write_buffer, res);
Niels Möller's avatar
Niels Möller committed
891
}  
892

893
894
895
896
897
898
899
900
901
902
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)
903
    close_fd(fd);
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
}

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
928
929
930

/* Listen callback */

931
932
933
934
935
936
937
938
939
/* GABA:
   (class
     (name io_listen_callback)
     (super io_callback)
     (vars
       (c object command_continuation)
       (e object exception_handler)))
*/

Niels Möller's avatar
Niels Möller committed
940
static void
941
do_listen_callback(struct io_callback *s,
Niels Möller's avatar
Niels Möller committed
942
		   struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
943
{
944
  CAST(io_listen_callback, self, s);
945
946
947
948
949
950

#if WITH_IPV6
  struct sockaddr_storage peer;
#else
  struct sockaddr peer;
#endif
951
952

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

Niels Möller's avatar
Niels Möller committed
955
956
957
  conn = accept(fd->fd,
		(struct sockaddr *) &peer, &addr_len);
  if (conn < 0)
958
    {
959
      werror("io.c: accept failed, %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
960
      return;
961
    }
962
  trace("io.c: accept on fd %i\n", conn);
963
  COMMAND_RETURN(self->c,
964
		 make_listen_value(make_lsh_fd(conn, "accepted socket", self->e),
965
966
				   sockaddr2info(addr_len,
						 (struct sockaddr *) &peer)));
Niels Möller's avatar
Niels Möller committed
967
}
968

969
struct io_callback *
970
make_listen_callback(struct command_continuation *c,
971
972
973
974
975
976
977
978
979
		     struct exception_handler *e)
{
  NEW(io_listen_callback, self);
  self->super.f = do_listen_callback;
  self->c = c;
  self->e = e;
  
  return &self->super;
}
Niels Möller's avatar
Niels Möller committed
980

Niels Möller's avatar
Niels Möller committed
981
982
/* Connect callback */

983
984
985
986
987
988
989
990
991
992
993
/* 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
994
{
995
  CAST(io_connect_callback, self, s);
996
  int socket_error;
997
  socklen_t len = sizeof(socket_error);
998
  
999
  /* Check if the connection was successful */
1000
1001
  if ((getsockopt(fd->fd, SOL_SOCKET, SO_ERROR,
		  (char *) &socket_error, &len) < 0)
1002
      || socket_error)
1003
    {
1004
      trace("io.c: connect_callback: Connect on fd %i failed.\n", fd->fd);
Niels Möller's avatar
Niels Möller committed
1005
      EXCEPTION_RAISE(fd->e,
1006
		      make_io_exception(EXC_IO_CONNECT, fd, 0, "connect failed."));
1007
      close_fd(fd);
1008
1009
    }
  else
Niels Möller's avatar
Niels Möller committed
1010
    {
1011
      trace("io.c: connect_callback: fd %i connected.\n", fd->fd);
1012
      fd->write = NULL;
1013
      lsh_oop_cancel_write_fd(fd);
1014
      fd->label = "connected socket";
1015
      COMMAND_RETURN(self->c, fd);
1016
    }
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
}

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;
1028
1029
}

1030

Niels Möller's avatar
Niels Möller committed
1031
/* This function is called if a connection this file somehow depends
1032
1033
1034
1035
1036
1037
1038
1039
 * 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
1040
1041
  /* We use close_fd_nicely, so that any data in the write buffer is
   * flushed before the fd is closed. */
1042
  if (r->alive)
1043
    close_fd_nicely(fd);
1044
1045
}

1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
/* 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);

1056
      if (e->fd)
1057
	close_fd(e->fd);
1058
1059
1060
1061
1062
    }
  EXCEPTION_RAISE(self->parent, x);
  return;
}

1063
#if 0
Niels Möller's avatar
Niels Möller committed
1064
/* Initializes a file structure, and adds it to the backend's list. */
Niels Möller's avatar