/* Called when we receive a connection on the listening socket. */ static void accept_bittorrent_peer_connection(void *____) { struct sockaddr_in addr; int peer_sock; int addrlen = sizeof(addr); struct bittorrent_peer_connection *peer; struct read_buffer *buffer; peer_sock = accept(bittorrent_socket, (struct sockaddr *) &addr, &addrlen); if (peer_sock < 0) return; if (set_nonblocking_fd(peer_sock) < 0) { close(peer_sock); return; } peer = init_bittorrent_peer_connection(peer_sock); if (!peer) { close(peer_sock); return; } peer->remote.initiater = 1; /* Just return. Failure is handled by alloc_read_buffer(). */ buffer = alloc_read_buffer(peer->socket); if (!buffer) return; read_from_socket(peer->socket, buffer, connection_state(S_TRANS), read_bittorrent_peer_handshake); add_to_list(bittorrent_peer_connections, peer); }
void http_get_header(struct connection *c) { struct read_buffer *rb; set_timeout(c); if (!(rb = alloc_read_buffer(c))) return; rb->close = 1; read_from_socket(c, c->sock1, rb, http_got_header); }
void finger_sent_request(struct connection *c) { struct read_buffer *rb; set_timeout(c); if (!(rb = alloc_read_buffer(c))) return; rb->close = 1; read_from_socket(c, c->sock1, rb, finger_get_response); }
static void read_response_from_socket(struct socket *socket) { struct read_buffer *rb = alloc_read_buffer(socket); if (rb) read_from_socket(socket, rb, connection_state(S_SENT), socket->read_done); }
static void ftp_get_banner(struct connection *c) { struct read_buffer *rb; set_timeout(c); setcstate(c, S_SENT); if (!(rb = alloc_read_buffer(c))) return; read_from_socket(c, c->sock1, rb, ftp_got_banner); }
static void ftp_logged(struct connection *c) { struct read_buffer *rb; if (!(rb = alloc_read_buffer(c))) return; if (!ftp_options.fast_ftp) { ftp_got_user_info(c, rb); return; } read_from_socket(c, c->sock1, rb, ftp_got_info); }
static void get_request(struct connection *conn) { struct read_buffer *rb = alloc_read_buffer(conn->socket); if (!rb) return; memcpy(rb->data, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n", 45); rb->length = 45; rb->freespace -= 45; conn->unrestartable = 1; conn->socket->state = SOCKET_END_ONCLOSE; read_from_socket(conn->socket, rb, connection_state(S_SENT), http_got_header); }
static void read_from_stdin(struct connection *conn) { struct read_buffer *rb = alloc_read_buffer(conn->socket); if (!rb) return; memcpy(rb->data, "HTTP/1.0 200 OK\r\n\r\n", 19); rb->length = 19; rb->freespace -= 19; conn->unrestartable = 1; conn->socket->state = SOCKET_END_ONCLOSE; read_from_socket(conn->socket, rb, connection_state(S_SENT), check_if_closed); }
void smb_protocol_handler(struct connection *conn) { int smb_pipe[2] = { -1, -1 }; int header_pipe[2] = { -1, -1 }; pid_t cpid; if (c_pipe(smb_pipe) || c_pipe(header_pipe)) { int s_errno = errno; if (smb_pipe[0] >= 0) close(smb_pipe[0]); if (smb_pipe[1] >= 0) close(smb_pipe[1]); if (header_pipe[0] >= 0) close(header_pipe[0]); if (header_pipe[1] >= 0) close(header_pipe[1]); abort_connection(conn, connection_state_for_errno(s_errno)); return; } conn->from = 0; conn->unrestartable = 1; find_auth(conn->uri); /* remember username and password */ cpid = fork(); if (cpid == -1) { int s_errno = errno; close(smb_pipe[0]); close(smb_pipe[1]); close(header_pipe[0]); close(header_pipe[1]); retry_connection(conn, connection_state_for_errno(s_errno)); return; } if (!cpid) { dup2(open("/dev/null", O_RDONLY), 0); close(1); close(2); data_out = fdopen(smb_pipe[1], "w"); header_out = fdopen(header_pipe[1], "w"); if (!data_out || !header_out) exit(1); close(smb_pipe[0]); close(header_pipe[0]); /* There may be outgoing data in stdio buffers * inherited from the parent process. The parent * process is going to write this data, so the child * process must not do that. Closing the file * descriptors ensures this. * * FIXME: If something opens more files and gets the * same file descriptors and does not close them * before exit(), then stdio may attempt to write the * buffers to the wrong files. This might happen for * example if libsmbclient calls syslog(). */ close_all_fds_but_two(smb_pipe[1], header_pipe[1]); do_smb(conn); } else { struct read_buffer *buf2; conn->data_socket->fd = smb_pipe[0]; conn->socket->fd = header_pipe[0]; set_nonblocking_fd(conn->data_socket->fd); set_nonblocking_fd(conn->socket->fd); close(smb_pipe[1]); close(header_pipe[1]); buf2 = alloc_read_buffer(conn->socket); if (!buf2) { close_socket(conn->data_socket); close_socket(conn->socket); abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } read_from_socket(conn->socket, buf2, connection_state(S_CONN), smb_got_header); } }
static void smb_got_header(struct socket *socket, struct read_buffer *rb) { struct connection *conn = socket->conn; struct read_buffer *buf; int error = 0; conn->cached = get_cache_entry(conn->uri); if (!conn->cached) { /* Even though these are pipes rather than real * sockets, call close_socket instead of close, to * ensure that abort_connection won't try to close the * file descriptors again. (Could we skip the calls * and assume abort_connection will do them?) */ close_socket(socket); close_socket(conn->data_socket); abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } socket->state = SOCKET_END_ONCLOSE; if (rb->length > 0) { unsigned char *ctype = memacpy(rb->data, rb->length); if (ctype && *ctype) { if (!strcmp(ctype, "text/x-error")) { error = 1; mem_free(ctype); } else { if (ctype[0] >= '0' && ctype[0] <= '9') { #ifdef HAVE_ATOLL conn->est_length = (off_t)atoll(ctype); #else conn->est_length = (off_t)atol(ctype); #endif mem_free(ctype); /* avoid error */ if (!conn->est_length) { abort_connection(conn, connection_state(S_OK)); return; } } else mem_free_set(&conn->cached->content_type, ctype); } } else { mem_free_if(ctype); } } buf = alloc_read_buffer(conn->data_socket); if (!buf) { close_socket(socket); close_socket(conn->data_socket); abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } if (error) { mem_free_set(&conn->cached->content_type, stracpy("text/html")); read_from_socket(conn->data_socket, buf, connection_state(S_CONN), smb_got_error); } else { read_from_socket(conn->data_socket, buf, connection_state(S_CONN), smb_got_data); } }
static void ftp_retr_1(struct connection *c) { struct read_buffer *rb; if (!(rb = alloc_read_buffer(c))) return; read_from_socket(c, c->sock1, rb, ftp_retr_file); }
static void ftp_sent_passwd(struct connection *c) { struct read_buffer *rb; if (!(rb = alloc_read_buffer(c))) return; read_from_socket(c, c->sock1, rb, ftp_pass_info); }