void unixfd::newfd (svccb *sbp) { assert (paios_out); rexcb_newfd_arg *argp = sbp->Xtmpl getarg<rexcb_newfd_arg> (); int s[2]; if(socketpair(AF_UNIX, SOCK_STREAM, 0, s)) { warn << "error creating socketpair"; sbp->replyref (false); return; } make_async (s[1]); make_async (s[0]); close_on_exec (s[1]); close_on_exec (s[0]); paios_out->sendfd (s[1]); vNew refcounted<unixfd> (pch, argp->newfd, s[0]); sbp->replyref (true); }
/* 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); }
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; }
void tcp_manager::doRPC_tcp_connect_cb (RPC_delay_args *args, int fd) { hostinfo *hi = lookup_host (args->l->address ()); if (fd < 0) { warn << "locationtable: connect failed: " << strerror (errno) << "\n"; (args->cb) (RPC_CANTSEND); args->l->set_alive (false); remove_host (hi); delete args; } else { struct linger li; li.l_onoff = 1; li.l_linger = 0; setsockopt (fd, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof (li)); tcp_nodelay (fd); make_async(fd); hi->fd = fd; hi->xp = axprt_stream::alloc (fd); assert (hi->xp); send_RPC (args); while (hi->connect_waiters.size ()) send_RPC (hi->connect_waiters.pop_front ()); } }
proxy::proxy (int fd1, int fd2) { con[0].fd = fd1; con[1].fd = fd2; for (int i = 0; i < 2; i++) { make_async (con[i].fd); tcp_nodelay (con[i].fd); setcb (i); } }
void identptr (int fd, callback<void, str, ptr<hostent>, int>::ref cb) { struct sockaddr_in la, ra; socklen_t len; len = sizeof (la); bzero (&la, sizeof (la)); bzero (&ra, sizeof (ra)); errno = 0; if (getsockname (fd, (struct sockaddr *) &la, &len) < 0 || la.sin_family != AF_INET || getpeername (fd, (struct sockaddr *) &ra, &len) < 0 || ra.sin_family != AF_INET || len != sizeof (la)) { warn ("ident: getsockname/getpeername: %s\n", strerror (errno)); (*cb) ("*disconnected*", NULL, ARERR_CANTSEND); return; } u_int lp = ntohs (la.sin_port); la.sin_port = htons (0); u_int rp = ntohs (ra.sin_port); ra.sin_port = htons (AUTH_PORT); int ifd = socket (AF_INET, SOCK_STREAM, 0); if (ifd >= 0) { close_on_exec (ifd); make_async (ifd); if (connect (ifd, (sockaddr *) &ra, sizeof (ra)) < 0 && errno != EINPROGRESS) { close (ifd); ifd = -1; } } identstat *is = New identstat; is->err = 0; is->cb = cb; is->host = inet_ntoa (ra.sin_addr); if (ifd >= 0) { is->ncb = 2; close_on_exec (ifd); is->a = aios::alloc (ifd); is->a << rp << ", " << lp << "\r\n"; is->a->settimeout (15); is->a->readline (wrap (is, &identstat::identcb)); } else is->ncb = 1; dns_hostbyaddr (ra.sin_addr, wrap (is, &identstat::dnscb)); }
ptr<aclnt> dhblock_srv::get_maint_aclnt (str msock) { int fd = unixsocket_connect (msock); if (fd < 0) fatal ("get_maint_aclnt: Error connecting to %s: %m\n", msock.cstr ()); make_async (fd); ptr<aclnt> c = aclnt::alloc (axprt_unix::alloc (fd, 1024*1025), maint_program_1); return c; }
mtd_thread_arg_t * mtdispatch_t::launch_init (int i, int fdout, int *closeit) { int fds[2]; if (pipe (fds) < 0) fatal << "mtdispatch::launch: cannot open pipe\n"; make_async ((shmem->arr[i].fdout = fds[1])); mtd_thread_arg_t *arg = New mtd_thread_arg_t (i, fds[0], fdout, &shmem->arr[i], this); *closeit = fds[0]; return arg; }
static PyObject * Core_make_async (PyObject *self, PyObject *args) { int fd = 0; if (!PyArg_ParseTuple (args, "i", &fd)) return NULL; make_async (fd); Py_INCREF (Py_None); return Py_None; }
void sfs_unixserv (str sock, cbi cb, mode_t mode) { /* We set the permissions of the socket because on some OS's this * gives an extra measure of protection. However, the real * protection comes from the fact that sfssockdir is not world * readable or executable. */ mode_t m = runinplace ? umask (0) : umask (~(mode & 0777)); int lfd = unixsocket (sock); if (lfd < 0 && errno == EADDRINUSE) { /* XXX - This is a slightly race-prone way of cleaning up after a * server bails without unlinking the socket. If we can't connect * to the socket, it's dead and should be unlinked and rebound. * Two daemons's could do this simultaneously, however. */ int fd = unixsocket_connect (sock); if (fd < 0) { unlink (sock); lfd = unixsocket (sock); } else { close (fd); errno = EADDRINUSE; } } if (lfd < 0) fatal ("%s: %m\n", sock.cstr ()); sockets.push_back (sock); umask (m); listen (lfd, 5); make_async (lfd); fdcb (lfd, selread, wrap (accept_cb, lfd, cb)); #if 0 /* A nice idea that unfortunately doesn't work... */ struct stat sb1, sb2; if (stat (sock, &sb1) < 0 || fstat (lfd, &sb2) < 0) fatal ("%s: %m\n", sock); if (sb1.st_ino != sb2.st_ino || sb1.st_dev != sb2.st_dev) fatal ("%s: changed while binding\n", sock); #endif }
bool resolver::tcpinit () { tcpsock = NULL; int fd = socket (addr->sa_family, SOCK_STREAM, 0); if (fd < 0) { warn ("resolver::tcpsock: socket: %m\n"); return false; } make_async (fd); close_on_exec (fd); if (connect (fd, addr, addrlen) < 0 && errno != EINPROGRESS) { close (fd); return false; } tcpsock = New refcounted<dnssock_tcp> (fd, wrap (this, &resolver::pktready, true)); return true; }
void axprt_dgram::poll () { assert (cb); make_sync (fd); socklen_t ss = socksize; bzero (sabuf, ss); ssize_t ps = recvfrom (fd, pktbuf, pktsize, 0, sabuf, &ss); make_async (fd); if (ps < 0) { if (errno != EAGAIN && connected) (*cb) (NULL, -1, NULL); return; } (*cb) (pktbuf, ps, sabuf); }
bool resolver::udpinit () { udpsock = NULL; int fd = socket (addr->sa_family, SOCK_DGRAM, 0); if (fd < 0) { warn ("resolver::udpsock: socket: %m\n"); return false; } make_async (fd); close_on_exec (fd); if (connect (fd, addr, addrlen) < 0) { warn ("resolver::udpsock: connect: %m\n"); close (fd); return false; } udpsock = New refcounted<dnssock_udp> (fd, wrap (this, &resolver::pktready, false)); return true; }
// Listen for connections void net::tcp_listen(int port, cbsb cb) { int ret; int tmp_socket; // Init socket bound to port tmp_socket = inetsocket(SOCK_STREAM, port); check_ret(tmp_socket, "inetsocket()"); // Make fd asynchronous make_async(tmp_socket); // Listen for a connection ret = listen(tmp_socket, LISTEN_BACKLOG); check_ret(ret, "listen()"); // Schedule event to accept incoming connection fdcb(tmp_socket, selread, wrap(this, &net::tcp_accept, tmp_socket, cb)); }
int chanfd::newfd (int rfd, bool _enablercb) { size_t i; for (i = 0; i < fdi.size (); i++) if (fdi[i].fd == -1 && fdi[i].closed && !fdi[i].rsize) break; if (i == fdi.size ()) fdi.push_back (); fdi[i].reset (); fdi[i].fd = rfd; fdi[i].isunixsocket = isunixsocket (rfd); if (_enablercb) enablercb (i); make_async (fdi[i].fd); return i; }
void mtdispatch_t::init () { init_rpc_stats (); int fds[2]; if (num == 0) { warn << "Cannot start program with 0 threads; exiting...\n"; exit (3); } if (pipe (fds) < 0) fatal << "mtdispatch::init: cannot open pipe\n"; fdin = fds[0]; make_async (fdin); fdcb (fdin, selread, wrap (this, &mtdispatch_t::chld_msg)); for (u_int i = 0; i < num; i++) { launch (i, fds[1]); } //close (fds[1]); }
axprt_dgram::axprt_dgram (int f, bool c, size_t ss, size_t ps) : axprt (false, c, c ? 0 : ss), pktsize (ps), fd (f), cb (NULL) { make_async (fd); close_on_exec (fd); #ifdef SO_RCVBUF int n = 0; socklen_t sn = sizeof (n); if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &n, &sn) >= 0 && pktsize > implicit_cast<size_t> (n)) { n = pktsize; if (setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof (n)) < 0) warn ("SO_RCVBUF -> %d bytes: %m\n", n); } #endif /* SO_RCVBUF */ if (c) sabuf = NULL; else sabuf = (sockaddr *) xmalloc (socksize); pktbuf = (char *) xmalloc (pktsize); }
// Make a new TCP connection (this blocks) void net::tcp_connect(str host, int port) { int ret; int flag; struct sockaddr_in sin; // Get socket fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); check_ret(fd_, "socket()"); // Disable Nagle buffering algorithm tcp_nodelay(fd_); // Zero structure memset(&sin, 0, sizeof(sin)); // Set to IPV4 sin.sin_family = AF_INET; // Convert address ret = inet_pton(AF_INET, host.cstr(), &sin.sin_addr.s_addr); check_ret(ret, "inet_pton()"); // Set port sin.sin_port = htons(port); // Establish connection to the server ret = connect(fd_, (struct sockaddr*) &sin, sizeof(sin)); check_ret(ret, "connect()"); // Make fd asynchronous make_async(fd_); // We are done }
listener (int f) : fd (f) { make_async (fd); close_on_exec (fd); listen (fd, 5); fdcb (fd, selread, wrap (newserv, fd)); }
noise_from_fd::noise_from_fd (datasink *dst, int fd, cbv cb, size_t maxbytes) : dst (dst), fd (fd), bytes (maxbytes), cb (cb) { make_async (fd); fdcb (fd, selread, wrap (this, &noise_from_fd::doread)); }