bool new_pipe(int fd[2], bool r_nonblocking, bool w_nonblocking) { if( ::pipe(fd) == -1 ) return false; bool ret = false; do { if( r_nonblocking && make_nonblocking(fd[0])==-1 ) break; if( w_nonblocking && make_nonblocking(fd[1])==-1 ) break; ret = true; }while(0); if(!ret) { ::close(fd[0]); ::close(fd[1]); } return ret; }
static error_code try_port (RELAYLIB_INFO* rli, u_short port, char *if_name, char *relay_ip) { struct hostent *he; struct sockaddr_in local; rli->m_listensock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (rli->m_listensock == SOCKET_ERROR) { debug_printf ("try_port(%d) failed socket() call\n", port); return SR_ERROR_SOCK_BASE; } make_nonblocking(rli->m_listensock); if ('\0' == *relay_ip) { if (read_interface(if_name,&local.sin_addr.s_addr) != 0) local.sin_addr.s_addr = htonl(INADDR_ANY); } else { he = gethostbyname(relay_ip); memcpy(&local.sin_addr, he->h_addr_list[0], he->h_length); } local.sin_family = AF_INET; local.sin_port = htons(port); #ifndef WIN32 { // Prevent port error when restarting quickly after a previous exit int opt = 1; setsockopt(rli->m_listensock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); } #endif if (bind(rli->m_listensock, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR) { debug_printf ("try_port(%d) failed bind() call\n", port); closesocket(rli->m_listensock); rli->m_listensock = SOCKET_ERROR; return SR_ERROR_CANT_BIND_ON_PORT; } if (listen(rli->m_listensock, 1) == SOCKET_ERROR) { debug_printf ("try_port(%d) failed listen() call\n", port); closesocket(rli->m_listensock); rli->m_listensock = SOCKET_ERROR; return SR_ERROR_SOCK_BASE; } debug_printf ("try_port(%d) succeeded\n", port); return SR_SUCCESS; }
bool make_info_slave(void) { int socks[2]; pid_t child; int n; if (info_slave_state != INFO_SLAVE_DOWN) { if (info_slave_pid > 0) kill_info_slave(); info_slave_state = INFO_SLAVE_DOWN; } if (startup_attempts == 0) time(&startup_window); startup_attempts += 1; if (startup_attempts > MAX_ATTEMPTS) { time_t now; time(&now); if (difftime(now, startup_window) <= 60.0) { /* Too many failed attempts to start info_slave in 1 minute */ do_rawlog(LT_ERR, "Disabling info_slave due to too many errors."); info_slave_halted = true; return false; } else { /* Reset counter */ startup_window = now; startup_attempts = 0; } } #ifndef AF_LOCAL /* Use Posix.1g names. */ #define AF_LOCAL AF_UNIX #endif #ifdef HAVE_SOCKETPAIR if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, socks) < 0) { penn_perror("creating slave datagram socketpair"); return false; } if (socks[0] >= maxd) maxd = socks[0] + 1; if (socks[1] >= maxd) maxd = socks[1] + 1; #endif child = fork(); if (child < 0) { penn_perror("forking info slave"); #ifdef HAVE_SOCKETPAIR closesocket(socks[0]); closesocket(socks[1]); #endif return false; } else if (child > 0) { info_slave_state = INFO_SLAVE_READY; info_slave_pid = child; #ifdef HAVE_SOCKETPAIR info_slave = socks[0]; closesocket(socks[1]); do_rawlog(LT_ERR, "Spawning info slave, communicating using socketpair, pid %d.", child); #endif make_nonblocking(info_slave); } else { int errfd = fileno(stderr); int dupfd; /* Close unneeded fds and sockets: Everything but stderr and the socket used to talk to the mush */ for (n = 0; n < maxd; n++) { if (n == errfd) continue; #ifdef HAVE_SOCKETPAIR if (n == socks[1]) continue; #endif close(n); } /* Reuse stdin and stdout for talking to the slave */ dupfd = dup2(socks[1], 0); if (dupfd < 0) { penn_perror("dup2() of stdin in info_slave"); exit(1); } dupfd = dup2(socks[1], 1); if (dupfd < 0) { penn_perror("dup2() of stdout in info_slave"); exit(1); } close(socks[1]); execl("./info_slave", "info_slave", "for", MUDNAME, (char *) NULL); penn_perror("execing info slave"); exit(1); } if (info_slave >= maxd) maxd = info_slave + 1; lower_priority_by(info_slave_pid, 4); for (n = 0; n < maxd; n++) if (FD_ISSET(n, &info_pending)) query_info_slave(n); return true; }
void run(void) { int listener; struct fd_state *state[FD_SETSIZE]; struct sockaddr_in sin; int i, maxfd; fd_set readset, writeset, exset; sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; sin.sin_port = htons(8081); for (i = 0; i < FD_SETSIZE; ++i) state[i] = NULL; listener = socket(AF_INET, SOCK_STREAM, 0); make_nonblocking(listener); if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0) { perror("bind"); return; } if (listen(listener, 16)<0) { perror("listen"); return; } FD_ZERO(&readset); FD_ZERO(&writeset); FD_ZERO(&exset); while (1) { maxfd = listener; FD_ZERO(&readset); FD_ZERO(&writeset); FD_ZERO(&exset); FD_SET(listener, &readset); for (i=0; i < FD_SETSIZE; ++i) { if (state[i]) { if (i > maxfd) maxfd = i; FD_SET(i, &readset); if (state[i]->writing) { FD_SET(i, &writeset); } } } if (select(maxfd+1, &readset, &writeset, &exset, NULL) < 0) { perror("select"); return; } if (FD_ISSET(listener, &readset)) { struct sockaddr_storage ss; socklen_t slen = sizeof(ss); int fd = accept(listener, (struct sockaddr*)&ss, &slen); if (fd < 0) { perror("accept"); } else if (fd > FD_SETSIZE) { close(fd); } else { make_nonblocking(fd); state[fd] = alloc_fd_state(); char send_buf[1024] = "Connected"; send(fd, send_buf, 1024, 0); assert(state[fd]);/*XXX*/ } } for (i=0; i < maxfd+1; ++i) { int r = 0; if (i == listener) continue; if (FD_ISSET(i, &readset)) { r = do_read(i, state[i]); } if (r == 0 && FD_ISSET(i, &writeset)) { r = do_write(i, state[i]); } if (r) { free_fd_state(state[i]); state[i] = NULL; close(i); } } } }
/* Copies data from stdin to PTY and from PTY to stdout until no more data can be read or written. */ static void relay (int pty, int dead_child_fd) { struct pipe { int in, out; char buf[BUFSIZ]; size_t size, ofs; bool active; }; struct pipe pipes[2]; /* Make PTY, stdin, and stdout non-blocking. */ make_nonblocking (pty, true); make_nonblocking (STDIN_FILENO, true); make_nonblocking (STDOUT_FILENO, true); /* Configure noncanonical mode on PTY and stdin to avoid waiting for end-of-line. We want to minimize context switching on PTY (for efficiency) and minimize latency on stdin to avoid a laggy user experience. */ make_noncanon (pty, 16, 1); make_noncanon (STDIN_FILENO, 1, 0); memset (pipes, 0, sizeof pipes); pipes[0].in = STDIN_FILENO; pipes[0].out = pty; pipes[1].in = pty; pipes[1].out = STDOUT_FILENO; while (pipes[0].in != -1 || pipes[1].in != -1) { fd_set read_fds, write_fds; int retval; int i; FD_ZERO (&read_fds); FD_ZERO (&write_fds); for (i = 0; i < 2; i++) { struct pipe *p = &pipes[i]; /* Don't do anything with the stdin->pty pipe until we have some data for the pty->stdout pipe. If we get too eager, Bochs will throw away our input. */ if (i == 0 && !pipes[1].active) continue; if (p->in != -1 && p->size + p->ofs < sizeof p->buf) FD_SET (p->in, &read_fds); if (p->out != -1 && p->size > 0) FD_SET (p->out, &write_fds); } FD_SET (dead_child_fd, &read_fds); do { retval = select (FD_SETSIZE, &read_fds, &write_fds, NULL, NULL); } while (retval < 0 && errno == EINTR); if (retval < 0) fail_io ("select"); if (FD_ISSET (dead_child_fd, &read_fds)) { /* Child died. Do final relaying. */ struct pipe *p = &pipes[1]; if (p->out == -1) return; make_nonblocking (STDOUT_FILENO, false); for (;;) { ssize_t n; /* Write buffer. */ while (p->size > 0) { n = write (p->out, p->buf + p->ofs, p->size); if (n < 0) fail_io ("write"); else if (n == 0) fail_io ("zero-length write"); p->ofs += n; p->size -= n; } p->ofs = 0; p->size = n = read (p->in, p->buf, sizeof p->buf); if (n <= 0) return; } } for (i = 0; i < 2; i++) { struct pipe *p = &pipes[i]; if (p->in != -1 && FD_ISSET (p->in, &read_fds)) { ssize_t n = read (p->in, p->buf + p->ofs + p->size, sizeof p->buf - p->ofs - p->size); if (n > 0) { p->active = true; p->size += n; if (p->size == BUFSIZ && p->ofs != 0) { memmove (p->buf, p->buf + p->ofs, p->size); p->ofs = 0; } } else if (!handle_error (n, &p->in, p->in == pty, "read")) return; } if (p->out != -1 && FD_ISSET (p->out, &write_fds)) { ssize_t n = write (p->out, p->buf + p->ofs, p->size); if (n > 0) { p->ofs += n; p->size -= n; if (p->size == 0) p->ofs = 0; } else if (!handle_error (n, &p->out, p->out == pty, "write")) return; } } } }
const char * get_username(long a, int prt, int myprt) { int fd, len, result; struct sockaddr_in addr; char *ptr, *ptr2; static char buf[1024]; int lasterr; int timeout = IDENTD_TIMEOUT; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("resolver ident socket"); return(0); } make_nonblocking(fd); len = sizeof(addr); addr.sin_family = AF_INET; addr.sin_addr.s_addr = a; addr.sin_port = htons((short)113); do { result = connect(fd, (struct sockaddr *) &addr, len); lasterr = errno; if (result < 0) { if (!timeout--) break; sleep(1); } } while (result < 0 && lasterr == EINPROGRESS); if (result < 0 && lasterr != EISCONN) { goto bad; } sprintf(buf, "%d,%d\n", prt, myprt); do { result = write(fd ,buf, strlen(buf)); lasterr = errno; if (result < 0) { if (!timeout--) break; sleep(1); } } while (result < 0 && lasterr == EAGAIN); if (result < 0) goto bad; do { result = read(fd, buf, sizeof(buf)); lasterr = errno; if (result < 0) { if (!timeout--) break; sleep(1); } } while (result < 0 && lasterr == EAGAIN); if (result < 0) goto bad; ptr = index(buf, ':'); if (!ptr) goto bad; ptr++; if (*ptr) ptr++; if(strncmp(ptr, "USERID", 6)) goto bad; ptr = index(ptr, ':'); if (!ptr) goto bad; ptr = index(ptr + 1, ':'); if (!ptr) goto bad; ptr++; /* if (*ptr) ptr++; */ close(fd); if ((ptr2 = index(ptr, '\r'))) *ptr2 = '\0'; if (!*ptr) return(0); return ptr; bad: close(fd); return(0); }
int main() { int l_socket_fd = -1; int c_socket_fd = -1; fd_set fds; l_socket_fd = android_get_control_socket(SOCKET_NAME); if (l_socket_fd < 0 ){ ALOGE("Unable to open inputdevinfo_socket (%s)\n", strerror(errno)); return -1; } if (make_nonblocking (l_socket_fd)) { ALOGE("Unable to modify inputdevinfo_socket flags. (%s)\n", strerror(errno)); } if (listen (l_socket_fd, 0) < 0) { ALOGE("Unable to open inputdevinfo_socket (%s)\n", strerror(errno)); return -1; } while(1){ FD_ZERO(&fds); FD_SET(l_socket_fd, &fds); if (c_socket_fd >= 0 ) { // && fcntl(c_socket_fd, F_GETFD) >= 0 ? FD_SET(c_socket_fd, &fds); } int retval = select(get_max(c_socket_fd, l_socket_fd) + 1, &fds, NULL, NULL, NULL); if(retval <= 0){ ALOGI("Error\n"); // Should I check for EBADR? break; } if(FD_ISSET(l_socket_fd, &fds)) { ALOGI("Connection attempt\n"); if(c_socket_fd < 0) { c_socket_fd = accept(l_socket_fd, NULL, NULL); } if (make_nonblocking (c_socket_fd)) { ALOGE("Unable to modify socket flags. (%s)\n", strerror(errno)); } } if(c_socket_fd >= 0 && FD_ISSET(c_socket_fd, &fds)){ int unread_bytes_count; if (ioctl(c_socket_fd, FIONREAD, &unread_bytes_count)){ ALOGE("Attempt to check if client socket is closed resulted in error.\n"); } else if(unread_bytes_count == 0) { //TODO: Check return code? close(c_socket_fd); c_socket_fd = -1; } else { process_cmds(c_socket_fd, MAX_COMMAND_LENGTH); close(c_socket_fd); c_socket_fd = -1; } } } return 0; }
int main(int argc, char *argv[]) { //======= insert unit test // test(); //======= if (argc < 2) { fprintf(stderr,"ERROR, no port provided\n"); exit(1); } int portno = atoi(argv[1]); struct sigaction sa; // for signal SIGCHLD /****** Kill Zombie Processes ******/ sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } /*********************************/ struct sockaddr_in myaddr; /* our address */ struct sockaddr_in remaddr; /* remote address */ int fd; /* our socket */ /* create a UDP socket */ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("cannot create socket\n"); return 0; } /* bind the socket to any valid IP address and a specific port */ memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(portno); if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { perror("bind failed"); return 0; } make_nonblocking(fd); if (argc == 5) { //set window size... maybe validate? WINDOW_SIZE = atoi(argv[2]); LOSS_PROBABILITY = atof(argv[3]); CORRUPTION_PROBABILITY = atof(argv[4]); Server server(portno, fd, myaddr, remaddr, WINDOW_SIZE, LOSS_PROBABILITY, CORRUPTION_PROBABILITY); server.startListening(); } else { Server server(portno, fd, myaddr, remaddr); server.startListening(); } }
void thread_accept (void* arg) { int ret; int newsock; BOOL good; struct sockaddr_in client; socklen_t iAddrSize = sizeof(client); RELAY_LIST* newhostsock; int icy_metadata; char* client_http_header; RIP_MANAGER_INFO* rmi = (RIP_MANAGER_INFO*) arg; RELAYLIB_INFO* rli = &rmi->relaylib_info; STREAM_PREFS* prefs = rmi->prefs; int have_metadata; if (rmi->http_info.meta_interval == NO_META_INTERVAL) { have_metadata = 0; } else { have_metadata = 1; } debug_printf("thread_accept:start\n"); while (rli->m_running) { fd_set fds; struct timeval tv; // this event will keep use from accepting while we // have a connection active // when a connection gets dropped, or when streamripper shuts down // this event will get signaled debug_printf("thread_accept:waiting on m_sem_not_connected\n"); threadlib_waitfor_sem (&rli->m_sem_not_connected); if (!rli->m_running) { debug_printf("thread_accept:exit (no longer m_running)\n"); break; } // Poll once per second, instead of blocking forever in // accept(), so that we can regain control if relaylib_stop() // called FD_ZERO (&fds); while (rli->m_listensock != SOCKET_ERROR && rli->m_running) { FD_SET (rli->m_listensock, &fds); tv.tv_sec = 1; tv.tv_usec = 0; debug_printf("thread_accept:calling select()\n"); ret = select (rli->m_listensock + 1, &fds, NULL, NULL, &tv); debug_printf("thread_accept:select() returned %d\n", ret); if (ret == 1) { unsigned long num_connected; /* If connections are full, do nothing. Note that m_max_connections is 0 for infinite connections allowed. */ threadlib_waitfor_sem (&rmi->relay_list_sem); num_connected = rmi->relay_list_len; threadlib_signal_sem (&rmi->relay_list_sem); if (prefs->max_connections > 0 && num_connected >= (unsigned long) prefs->max_connections) { continue; } /* Check for connections */ debug_printf ("Calling accept()\n"); newsock = accept (rli->m_listensock, (struct sockaddr *)&client, &iAddrSize); if (newsock != SOCKET_ERROR) { // Got successful accept debug_printf ("Relay: Client %d new from %s:%hu\n", newsock, inet_ntoa(client.sin_addr), ntohs(client.sin_port)); // Socket is new and its buffer had better have // room to hold the entire HTTP header! good = FALSE; if (header_receive (newsock, &icy_metadata) == 0 && rmi->cbuf2.buf != NULL) { int header_len; make_nonblocking (newsock); client_http_header = client_relay_header_generate (rmi, icy_metadata); header_len = strlen (client_http_header); ret = send (newsock, client_http_header, strlen(client_http_header), 0); debug_printf ("Relay: Sent response header to client %d (%d)\n", ret, header_len); client_relay_header_release (client_http_header); if (ret == header_len) { newhostsock = malloc (sizeof(RELAY_LIST)); if (newhostsock != NULL) { // Add new client to list (headfirst) threadlib_waitfor_sem (&rmi->relay_list_sem); newhostsock->m_is_new = 1; newhostsock->m_sock = newsock; newhostsock->m_next = rmi->relay_list; if (have_metadata) { newhostsock->m_icy_metadata = icy_metadata; } else { newhostsock->m_icy_metadata = 0; } rmi->relay_list = newhostsock; rmi->relay_list_len++; threadlib_signal_sem (&rmi->relay_list_sem); good = TRUE; } } } if (!good) { closesocket (newsock); debug_printf ("Relay: Client %d disconnected (Unable to receive HTTP header) or cbuf2.buf is NULL\n", newsock); //if (rmi->cbuf2.buf == NULL) { // debug_printf ("In fact, cbuf2.buf is NULL\n"); //} } } } else if (ret == SOCKET_ERROR) { /* Something went wrong with select */ break; } } threadlib_signal_sem (&rli->m_sem_not_connected); /* loop back up to select */ } rli->m_running_accept = FALSE; rli->m_running = FALSE; }
static int forward(pid_t pid, int *sigchld_fd, int stdin_pipe[2], int stdout_pipe[2], int stderr_pipe[2], void *socket) { int rc = -1; if (close(stdin_pipe[0]) == -1) TRACE_ERRNO("close(%i) failed", stdin_pipe[0]); stdin_pipe[0] = -1; if (close(stdout_pipe[1]) == -1) TRACE_ERRNO("close(%i) failed", stdout_pipe[1]); stdout_pipe[1] = -1; if (close(stderr_pipe[1]) == -1) TRACE_ERRNO("close(%i) failed", stderr_pipe[1]); stderr_pipe[1] = -1; zmq_msg_t stdin_msg; size_t stdin_msg_pos = 0; zmq_msg_t stdout_msg; int stdout_msg_valid = 0; zmq_msg_t stderr_msg; int stderr_msg_valid = 0; if (make_nonblocking(stdin_pipe[1]) == -1) goto _out; if (make_nonblocking(stdout_pipe[0]) == -1) goto _out; if (make_nonblocking(stderr_pipe[0]) == -1) goto _out; TRACE("made nonblocking: %i, %i, %i", stdin_pipe[1], stdout_pipe[0], stderr_pipe[0]); while (1) { zmq_pollitem_t items[5]; zmq_pollitem_t *item = items; zmq_pollitem_t *stdin_item = NULL; if (stdin_pipe[1] != -1 && stdin_msg_pos) { stdin_item = item++; stdin_item->socket = NULL; stdin_item->fd = stdin_pipe[1]; stdin_item->events = ZMQ_POLLOUT | ZMQ_POLLERR; } zmq_pollitem_t *stdout_item = NULL; if (stdout_pipe[0] != -1 && !stdout_msg_valid) { stdout_item = item++; stdout_item->socket = NULL; stdout_item->fd = stdout_pipe[0]; stdout_item->events = ZMQ_POLLIN | ZMQ_POLLERR; } zmq_pollitem_t *stderr_item = NULL; if (stderr_pipe[0] != -1 && !stderr_msg_valid) { stderr_item = item++; stderr_item->socket = NULL; stderr_item->fd = stderr_pipe[0]; stderr_item->events = ZMQ_POLLIN | ZMQ_POLLERR; } zmq_pollitem_t *socket_item = NULL; short socket_events = ((stdout_msg_valid || stderr_msg_valid) ? ZMQ_POLLOUT : 0) | ((stdin_pipe[1] == -1 || stdin_msg_pos) ? 0 : ZMQ_POLLIN); if (socket_events) { socket_item = item++; socket_item->socket = socket; socket_item->fd = -1; socket_item->events = socket_events; } zmq_pollitem_t *sigchld_item = NULL; if (*sigchld_fd != -1) { sigchld_item = item++; sigchld_item->socket = NULL; sigchld_item->fd = *sigchld_fd; sigchld_item->events = ZMQ_POLLIN | ZMQ_POLLERR; } if (item == items) { TRACE("nothing to poll, exiting"); break; } TRACE("polling:%s%s%s%s%s", stdin_item ? " stdin" : "", stdout_item ? " stdout" : "", stderr_item ? " stderr" : "", socket_item ? " socket" : "", sigchld_item ? " sigchld" : ""); while (1) { if (zmq_poll(items, item - items, -1) == -1) { if (errno == EINTR) continue; TRACE_ERRNO("zmq_poll() failed"); goto _out; } break; } if (stdin_item && (stdin_item->revents & (ZMQ_POLLOUT | ZMQ_POLLERR))) if (fd_write(&stdin_pipe[1], &stdin_msg, &stdin_msg_pos) == -1) goto _out; if (socket_item && (socket_item->revents & ZMQ_POLLOUT)) { if (socket_write(socket, &stdout_msg, &stdout_msg_valid) == -1) goto _out; if (socket_write(socket, &stderr_msg, &stderr_msg_valid) == -1) goto _out; } if (stdout_item && (stdout_item->revents & (ZMQ_POLLIN | ZMQ_POLLERR))) if (on_fd_readable(&stdout_pipe[0], socket, &stdout_msg, &stdout_msg_valid, msg_type_stdout) == -1) goto _out; if (stderr_item && (stderr_item->revents & (ZMQ_POLLIN | ZMQ_POLLERR))) if (on_fd_readable(&stderr_pipe[0], socket, &stderr_msg, &stderr_msg_valid, msg_type_stderr) == -1) goto _out; if (socket_item && (socket_item->revents & ZMQ_POLLIN)) if (on_socket_readable(socket, &stdin_pipe[1], &stdin_msg, &stdin_msg_pos) == -1) goto _out; if (sigchld_item && (sigchld_item->revents & (ZMQ_POLLIN | ZMQ_POLLERR))) if (on_sigchld(sigchld_fd, pid, &stdin_pipe[1]) == -1) goto _out; } rc = 0; _out: if (stdin_msg_pos && zmq_msg_close(&stdin_msg) == -1) TRACE_ERRNO("zmq_msg_close() failed"); if (stdout_msg_valid && zmq_msg_close(&stdout_msg) == -1) TRACE_ERRNO("zmq_msg_close() failed"); if (stderr_msg_valid && zmq_msg_close(&stderr_msg) == -1) TRACE_ERRNO("zmq_msg_close() failed"); return rc; }