Beispiel #1
0
void
net::do_write() 
{

  if (write_queue_.empty()) {
	  fdcb(fd_, selwrite, 0);
    return;
  }

  strbuf data = write_queue_.pop_front();
  
  uint32_t size = data.len();
  int res = write(fd_, (void*) &size, sizeof(uint32_t));

  if (res != sizeof(uint32_t))
    fatal << "write failed()";

  res = data.tosuio()->output(fd_);
  check_ret(res, "write()");

	// Schedule write again.
	if (data.tosuio()->resid()){
    //warn << "Scheduling write again\n";
	  fdcb(fd_, selwrite, wrap(this, &net::do_write_partial, data));
  	return;
  }
}
Beispiel #2
0
// This is called if only part of a message was previously read.
void
net::do_read_partial(cbsb cb, strbuf data, int remaining)
{
  int res;
  res = data.tosuio()->input(fd_, remaining);

  if (res != remaining) {
    if (res == 0 || errno == ECONNRESET) {
      warn << "Connection has been closed\n";
      fdcb(fd_, selread, 0);
      exit(0);
      //return;
    } else if (res < 0) {
      fatal << "input() failed\n";
    } else { // res is > and  < remaining
      // partial message received.
      fdcb(fd_, selread, wrap(this, &net::do_read_partial, cb, data, remaining - res));
      return; 
    }
  }

  fdcb(fd_, selread, wrap(this, &net::do_read, cb));
  // Call function
  (*cb)(data);  
}
Beispiel #3
0
// close connection
void
net::close_net()
{
  fdcb(fd_, selread, 0);
  fdcb(fd_, selwrite, 0);
  close(fd_);
}
Beispiel #4
0
void
chanfd::wcb (int fdn)
{
  if (fdi[fdn].wuio.resid ()) {
    assert (fdi[fdn].wuio.iovcnt () >= 1);
    if (fdi[fdn].fdsendq.empty ()) {
      if (fdi[fdn].wuio.output (fdi[fdn].fd) < 0) {
	fdi[fdn].seterr ();
	return;
      }
    }
    else {
      int n = writevfd (fdi[fdn].fd, fdi[fdn].wuio.iov (), 1,
			fdi[fdn].fdsendq.front ());
      if (n > 0) {
	::close (fdi[fdn].fdsendq.pop_front ());
	fdi[fdn].wuio.rembytes (n);
      }
      else {
	fdi[fdn].seterr ();
	return;
      }
    }
  }

  if (fdi[fdn].wuio.resid ())
    fdcb (fdi[fdn].fd, selwrite, (wrap (this, &chanfd::wcb, fdn)));
  else if (fdi[fdn].weof && fdi[fdn].reof)
    fdi[fdn].seterr ();
  else
    fdcb (fdi[fdn].fd, selwrite, NULL);
}
Beispiel #5
0
void
aios::input ()
{
  if (rlock)
    return;
  rlock = true;

  ref<aios> hold = mkref (this); // Don't let this be freed under us

  int n = ::readv (fd, const_cast<iovec *> (inb.iniov ()), inb.iniovcnt ());
  if (n > 0)
    inb.addbytes (n);
  else if (n < 0 && errno != EAGAIN) {
    fail (errno);
    rlock = false;
    return;
  }
  else if (!n && !(this->*infn) ()) {
    fail (0);
    rlock = false;
    return;
  }
  while ((this->*infn) ())
    ;
  if (fd >= 0) {
    if (rcb)
      fdcb (fd, selread, wrap (this, &aios::input));
    else
      fdcb (fd, selread, NULL);
    //timeoutbump ();
  }
  rlock = false;
}
Beispiel #6
0
static PyObject *
Core_fdcb (PyObject *self, PyObject *args)
{
  int fd = 0;
  int i_op = 0;
  PyObject *cb = NULL;

  if (!PyArg_ParseTuple (args, "ii|O", &fd, &i_op, &cb))
    return NULL;

  selop op = selop (i_op);

  if (op != selread && op != selwrite) {
    PyErr_SetString (PyExc_TypeError, "unknown select option");
    return NULL;
  }

  if (!cb) {
    fdcb (fd, op, NULL);
  } else {
    if (!PyCallable_Check (cb)) {
      PyErr_SetString (PyExc_TypeError, "callable object expected");
      return NULL;
    }
    ptr<pop_t> pop = pop_t::alloc (cb);
    make_async (fd);
    fdcb (fd, op, wrap (Core_cb, pop));
  }

  Py_INCREF (Py_None);
  return Py_None;
}
Beispiel #7
0
void
kbdinput::output (str s)
{
  suio_print (&outq, s);
  if (outq.resid ()) {
    fdcb (kbdfd, selread, NULL);
    fdcb (kbdfd, selwrite, wrap (this, &kbdinput::writecb));
  }
}
Beispiel #8
0
void
kbdinput::writecb ()
{
  if (outq.output (kbdfd) < 0)
    fatal ("keyboard (output): %m\n");
  if (!outq.resid ()) {
    fdcb (kbdfd, selwrite, NULL);
    fdcb (kbdfd, selread, wrap (this, &kbdinput::readcb));
  }
}
Beispiel #9
0
proxy::~proxy ()
{
    list<proxy, &proxy::llink>::remove (this);
    for (int i = 0; i < 2; i++) {
        fdcb (con[i].fd, selread, NULL);
        fdcb (con[i].fd, selwrite, NULL);
        close (con[i].fd);
        timecb_remove (con[i].tmo);
    }
}
Beispiel #10
0
aios::~aios ()
{
  if (fd >= 0) {
    if (debugname)
      warnx << debugname << " === EOF\n";
    fdcb (fd, selread, NULL);
    fdcb (fd, selwrite, NULL);
    ::close (fd);
  }
  if (timeoutcb)
    timecb_remove (timeoutcb);
}
Beispiel #11
0
 void reset () {
   if (fdreset)
     return;
   fdreset = true;
   if (tok)
     setorig ();
   if (outq.resid ())
     writecb ();
   if (kbdfd >= 0) {
     fdcb (kbdfd, selread, NULL);
     fdcb (kbdfd, selwrite, NULL);
   }
 }
Beispiel #12
0
void 
unixfd::rcb ()
{
  if (reof) {
    fdcb (localfd_in, selread, NULL);
    return;
  }

  char buf[16*1024];
  int fdrecved = -1;
  ssize_t n;
  if (unixsock)
    n = readfd (localfd_in, buf, sizeof (buf), &fdrecved);
  else
    n = read (localfd_in, buf, sizeof (buf));

  if (n < 0) {
    if (errno != EAGAIN)
      abort ();
    return;
  }

  if (!n) {
    readeof ();
    return;
  }
  else {
    rex_payload arg;
    arg.channel = channo;
    arg.fd = fd;
    arg.data.set (buf, n);

    if (fdrecved >= 0) {
      close_on_exec (fdrecved);
      rex_newfd_arg arg;
      arg.channel = channo;
      arg.fd = fd;
      ref<rex_newfd_res> resp (New refcounted<rex_newfd_res> (false));
      proxy->call (REX_NEWFD, &arg, resp,
		   wrap (mkref (this), &unixfd::newfdcb, fdrecved, resp));
    }

    ref<bool> pres (New refcounted<bool> (false));
    rsize += n;
    proxy->call (REX_DATA, &arg, pres,
		 wrap (mkref (this), &unixfd::datacb, n, pres));
  }

  if (rsize >= hiwat)
    fdcb (localfd_in, selread, NULL);
}
Beispiel #13
0
void
net::do_read(cbsb cb) 
{
	strbuf data;
  int size;
  int res;

  res = read(fd_, (void*) &size, sizeof(int));

  if (res != sizeof(int)) {
    if (res == 0 || errno == ECONNRESET) { 
      // Connection was closed. Disable reading.
      warn << "Connection has been closed\n";
      fdcb(fd_, selread, 0);
      exit(0);
      //return;
    } else if (errno == EAGAIN) { // Just ignore.
      return;
    } else {
      //TODO: Handle case where only a fraction of first 4 bytes is read.
      fatal << "read() failed. errno = " << errno << "\n";
    }
  }

  res = data.tosuio()->input(fd_, size);
 
  if (res != size) {
    if (res == 0 || errno == ECONNRESET) {
      warn << "Connection has been closed\n";
      fdcb(fd_, selread, 0);
      return;
    } else if (res < 0) {
      if (errno == EAGAIN) {
        //warn << "Reading partial message\n";
        fdcb(fd_, selread, wrap(this, &net::do_read_partial, cb, data, size));
        return;
      }

      fatal << "input() failed. errno: " << errno <<"\n";
    } else { // res is > and  < size
      // partial message received.
      //warn << "Reading partial message\n";
      fdcb(fd_, selread, wrap(this, &net::do_read_partial, cb, data, size - res));
      return; 
    }
  }

  // Call function
  (*cb)(data);  
}
Beispiel #14
0
void
proxy::setcb (int i)
{
    /* If we have data or an EOF to transmit, schedule a write callback. */
    if (con[i].wbuf.resid () || con[!i].eof && !con[i].closed) {
        fdcb (con[i].fd, selwrite, wrap (this, &proxy::wcb, i));
        if (!con[i].tmo)
            con[i].tmo = delaycb (120, wrap (this, &proxy::timeout, i));
    }

    /* If buffer falls beneath low-water mark, schedule a read callback. */
    if (!con[!i].eof && con[i].wbuf.resid () <= lowat)
        fdcb (con[!i].fd, selread, wrap (this, &proxy::rcb, !i));
}
Beispiel #15
0
void
chanfd::fdinfo::seterr ()
{
  if (fd >= 0) {
    while (!fdsendq.empty ())
      ::close (fdsendq.pop_front ());
    fdcb (fd, selread, NULL);
    fdcb (fd, selwrite, NULL);
    int savedfd = fd;
    fd = -1;
    wuio.clear ();
    ::close (savedfd);
  }
  reof = weof = true;
}
Beispiel #16
0
void
aios::setoutcb ()
{
  if (err && err != ETIMEDOUT) {
    fdcb (fd, selwrite, NULL);
    outb.tosuio ()->clear ();
  }
  else if (outb.tosuio ()->resid ()) {
    if (!timeoutcb)
      timeoutbump ();
    fdcb (fd, selwrite, wrap (this, &aios::output));
  }
  else
    fdcb (fd, selwrite, NULL);
}
Beispiel #17
0
void
proxy::wcb (int i)
{
    size_t bufsize = con[i].wbuf.resid ();
    if (bufsize && con[i].wbuf.output (con[i].fd) < 0 && errno != EAGAIN) {
        warn << "write-" << (i ? "client" : "server")
             << ": " << strerror (errno) << "\n";
        delete this;
        return;
    }
    if (con[i].wbuf.resid () < bufsize && con[i].tmo) {
        timecb_remove (con[i].tmo);
        con[i].tmo = NULL;
    }
    if (!con[i].wbuf.resid ()) {
        fdcb (con[i].fd, selwrite, NULL);
        if (con[!i].eof && !con[i].closed) {
            if (con[!i].closed) {
                delete this;
                return;
            }
            con[i].closed = true;
            shutdown (con[i].fd, 1);
        }
    }
    setcb (i);
}
Beispiel #18
0
/* unixfd specific arguments:

   localfd_in:	local file descriptor for input (or everything for non-tty)

   localfd_out: local file descriptor for output (only used for tty support)
     Set localfd_out = -1 (or omit the argument entirely) if you're not
     working with a remote tty; then the localfd_in is connected directly
     to the remote FD for both reads and writes (except it it's RO or WO).

   noclose: Unixfd will not use close or shutdown calls on the local
     file descriptor (localfd_in); useful for terminal descriptors,
     which must hang around so that raw mode can be disabled, etc.

   shutrdonexit: When the remote module exits, we shutdown the read
     direction of the local file descriptor (_in).  This isn't always
     done since not all file descriptors managed on the REX channel
     are necessarily connected to the remote module.
*/
unixfd::unixfd (rexchannel *pch, int fd, int localfd_in, int localfd_out,
		bool noclose, bool shutrdonexit, cbv closecb)
  : rexfd::rexfd (pch, fd),
    localfd_in (localfd_in), localfd_out (localfd_out), rsize (0),
    unixsock (isunixsocket (localfd_in)), weof (false), reof (false),
    shutrdonexit (shutrdonexit), closecb (closecb)
{
  if (noclose) {
    int duplocalfd = dup (localfd_in);
    if (duplocalfd < 0)
      warn ("failed to duplicate fd for noclose behavior (%m)\n");
    else
      unixfd::localfd_in = duplocalfd;
  }

  make_async (this->localfd_in);
  if (!is_fd_wronly (this->localfd_in))
    fdcb (this->localfd_in, selread, wrap (this, &unixfd::rcb));
    
  /* for tty support we split the input/output to two local FDs */
  if (localfd_out >= 0)
    paios_out = aios::alloc (this->localfd_out);
  else
    paios_out = aios::alloc (this->localfd_in);
}
Beispiel #19
0
void
proxy::rcb (int i)
{
    if (con[!i].wbuf.resid () >= hiwat) {
        fdcb (con[i].fd, selread, NULL);
        return;
    }
    int n = con[!i].wbuf.input (con[i].fd);
    if (n == 0 || n < 0 && errno != EAGAIN) {
        if (n < 0)
            warn << "read: " << strerror (errno) << "\n";
        con[i].eof = true;
        fdcb (con[i].fd, selread, NULL);
    }
    setcb (!i);
}
Beispiel #20
0
axprt_dgram::~axprt_dgram ()
{
  fdcb (fd, selread, NULL);
  close (fd);
  xfree (sabuf);
  xfree (pktbuf);
}
void
dnssock_tcp::wcb (bool selected)
{
  if (selected)
    write_ok = true;
  if (!write_ok)
    return;
  int n = tcpstate.output (fd);
  if (n < 0) {
    fdcb (fd, selwrite, NULL);
    (*cb) (NULL, -1);
  }
  else if (n > 0)
    fdcb (fd, selwrite, NULL);
  else
    fdcb (fd, selwrite, wrap (this, &dnssock_tcp::wcb, true));
}
Beispiel #22
0
void
aios::abort ()
{
  if (fd < 0)
    return;
  if (debugname)
    warnx << debugname << " === EOF\n";
  rcb = NULL;
  fdcb (fd, selread, NULL);
  fdcb (fd, selwrite, NULL);
  ::close (fd);
  fd = -1;
  eof = true;
  weof = true;
  err = EBADF;
  outb.tosuio ()->clear ();
}
Beispiel #23
0
static void
err_wcb ()
{
  int n;
  int cnt;

  if (!erruio->resid () || _err_output != _err_output_async) {
    fdcb (errfd, selwrite, NULL);
    return;
  }

  /* Try to write whole lines at a time. */
  for (cnt = min (erruio->iovcnt (), (size_t) UIO_MAXIOV);
       cnt > 0 && (erruio->iov ()[cnt-1].iov_len == 0
		   || *((char *) erruio->iov ()[cnt-1].iov_base
			+ erruio->iov ()[cnt-1].iov_len - 1) != '\n');
       cnt--)
    ;
  if (!cnt) {
    if (erruio->iovcnt () < UIO_MAXIOV) {
      /* Wait for a carriage return */
      fdcb (errfd, selwrite, NULL);
      return;
    }
    else
      cnt = -1;
  }

  /* Write asynchronously, but keep stderr synchronous in case of
   * emergency (e.g. maybe assert wants to fprintf to stderr). */
  if (globaldestruction)
    n = erruio->output (errfd, cnt);
  else {
    _make_async (errfd);
    n = erruio->output (errfd, cnt);
    make_sync (errfd);
  }

  if (n < 0)
    err_reset ();

  if (erruio->resid () && !globaldestruction)
    fdcb (errfd, selwrite, wrap (err_wcb)); 
  else
    fdcb (errfd, selwrite, NULL);
}
Beispiel #24
0
  void
  fdtab_t::close (fd_t *obj, int del)
  {
    FLUMEDBG4(FDS, CHATTER, "[%" PRIx64 "] close (%s); unreg: %d\n", 
	     getflmpid ().value (), obj->desc (), obj->_dereg);
    assert (_tab[obj->_fd]);

    if (obj->_dereg) {
      fdcb (obj->_fd, selread, NULL);
      fdcb (obj->_fd, selwrite, NULL);
    }

    ::close (obj->_fd);
    remove (obj);
    if (del)
      delete obj;
  }
Beispiel #25
0
// Asynchronous write
void 
net::a_write(str data) 
{
  write_queue_.push_back(data);
   
  if (write_queue_.size() == 1)
    fdcb(fd_, selwrite, wrap(this, &net::do_write));

}
Beispiel #26
0
 void turn_off ()
 {
   if (selread_on && fd >= 0) {
     fdcb (fd, selread, NULL);
     selread_on = false;
     success = true;
   } else {
     success = false;
   }
 }
Beispiel #27
0
void
aios::fail (int e)
{
  ref<aios> hold = mkref (this); // Don't let this be freed under us

  eof = true;
  if (e)
    err = e;

  if (fd >= 0) {
    fdcb (fd, selread, NULL);
    if (rcb)
      mkrcb (NULL);

    if (fd >= 0 && err && err != ETIMEDOUT) {
      fdcb (fd, selwrite, NULL);
      outb.tosuio ()->clear ();
    }
  }
}
Beispiel #28
0
void
merkle_disk_server::client_listen (int fd)
{
    if (listen (fd, 5) < 0) {
        fatal ("Error from listen: %m\n");
        close (fd);
    } else {
        fdcb (fd, selread,
              wrap (this, &merkle_disk_server::client_accept_socket, fd));
    }
}
Beispiel #29
0
stalesrv::~stalesrv ()
{
  if (nf->sotype == SOCK_STREAM) {
    fdcb (nf->fd, selread, NULL);
    close (nf->fd);
  }
  while (srvelm *s = srvs.first) {
    srvs.remove (s);
    delete s;
  }
}
Beispiel #30
0
// This is only invoked if only a fraction of the message was sent.
void
net::do_write_partial(strbuf data)
{
  int res = data.tosuio()->output(fd_);
  check_ret(res, "write()");

  // Schedule partial write again.
  if (data.tosuio()->resid())
    return;
  
  // Go back to normal write.
  fdcb(fd_, selwrite, wrap(this, &net::do_write));
}