int setup_nonblocking_socket(void) { /* create socket */ int handle = socket(AF_INET, SOCK_STREAM, 0); if (handle == -1) return -1; /* set fd to non-blocking */ if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1) { int e = errno; close(handle); errno = e; return -1; } set_ka(handle); set_no_delay(handle); return handle; }
int connect_to(resolve_info *ri, char **message) { struct addrinfo *rp = ri -> alist[ri -> index]; int fd = socket(rp -> ai_family, rp -> ai_socktype, rp -> ai_protocol); if (fd == -1) { asprintf(message, "could not create socket: %s (%d)", strerror(errno), errno); ri -> index = (ri -> index + 1) % ri -> alist_n; return -1; } if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { asprintf(message, "fcnt(O_NONBLOCK) failed: %s (%d)", strerror(errno), errno); close(fd); ri -> index = (ri -> index + 1) % ri -> alist_n; return -1; } set_ka(fd); set_no_delay(fd); /* connect to peer */ if (connect(fd, rp -> ai_addr, rp -> ai_addrlen) == 0) return fd; if (errno == EINPROGRESS) { /* not yet made but might be fine*/ return fd; } asprintf(message, "connect failed: %s (%d)", strerror(errno), errno); close(fd); ri -> index = (ri -> index + 1) % ri -> alist_n; return -1; }
int create_socket(struct sockaddr *bind_to, struct addrinfo *ai, int recv_buffer_size, int tx_buffer_size, int max_mtu, char use_no_delay, int priority, int tos) { int fd = -1; /* create socket */ fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd == -1) { set_error(gettext("problem creating socket (%s)"), strerror(errno)); return RC_INVAL; } /* go through a specific interface? */ if (bind_to) { int set = 1; /* set reuse flags */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &set, sizeof set) == -1) { set_error(gettext("error setting sockopt to interface (%s)"), strerror(errno)); return RC_INVAL; } if (bind(fd, bind_to, sizeof *bind_to) == -1) { set_error(gettext("error binding to interface (%s)"), strerror(errno)); return RC_INVAL; } } if (max_mtu >= 0) { if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &max_mtu, sizeof max_mtu) == -1) { set_error(gettext("error setting MTU size (%s)"), strerror(errno)); return RC_INVAL; } } if (use_no_delay) { int rc = -1; if ((rc = set_no_delay(fd)) != 0) return rc; } if (tx_buffer_size > 0) { if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&tx_buffer_size, sizeof tx_buffer_size) == -1) { set_error(gettext("error setting transmit buffer size (%s)"), strerror(errno)); return RC_INVAL; } } if (recv_buffer_size > 0) { if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buffer_size, sizeof recv_buffer_size) == -1) { set_error(gettext("error setting receive buffer size (%s)"), strerror(errno)); return RC_INVAL; } } #ifdef linux if (priority >= 0) { if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (char *)&priority, sizeof priority) == -1) { set_error(gettext("error setting priority (%s)"), strerror(errno)); return RC_INVAL; } } #endif if (tos >= 0) { if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof tos) == -1) { set_error(gettext("failed to set TOS info")); return RC_INVAL; } } return fd; }
static struct conn_t *conn_new(struct sockaddr_in *raddr, struct sockaddr_in *laddr) { struct conn_t *c; int lsize, errnosave; struct sockaddr_in tmp; c = smalloc(sizeof(*c)); memset(c, 0, sizeof(*c)); c->state = CONN_NEW; INIT_LIST_HEAD(&c->reqs); if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { errnosave = errno; syslog(LOG_ERR, "socket: %s", strerror(errno)); free(c); errno = errnosave; return 0; } /* If this is not the first connection, do a non-blocking connect */ if (!list_empty(&clist)) set_non_block(c->fd); tmp = *laddr; /* use a temp here because * bindresvport writes it. */ if (laddr->sin_port || bindresvport(c->fd, &tmp) == -1) { syslog(LOG_ERR, "bindresvport: %s (ignoring)", strerror(errno)); /* If we specified a port or failed to bind to a reserved * port for some reason, try a normal bind. */ if (bind(c->fd, (struct sockaddr *) laddr, sizeof(*laddr)) == -1) { errnosave = errno; syslog(LOG_ERR, "bind(%s:%d): %s (ignoring)", inet_ntoa(laddr->sin_addr), ntohs(laddr->sin_port), strerror(errno)); close(c->fd); free(c); errno = errnosave; return 0; } } if (verbose) syslog(LOG_INFO, "Connecting to %s:%d...", inet_ntoa(raddr->sin_addr), ntohs(raddr->sin_port)); if (connect(c->fd, (struct sockaddr *) raddr, sizeof(*raddr)) == -1) { if (errno != EINPROGRESS) { errnosave = errno; syslog(LOG_ERR, "connect(%s:%d): %s", inet_ntoa(raddr->sin_addr), ntohs(raddr->sin_port), strerror(errno)); close(c->fd); free(c); errno = errnosave; return 0; } } /* Make note of our local address */ lsize = sizeof(c->laddr); getsockname(c->fd, (struct sockaddr *)&c->laddr, &lsize); c->raddr = *raddr; /* Prime output buffer with version information and cookie */ conn_send_version(c); set_keep_alive(c->fd); set_no_delay(c->fd); set_non_block(c->fd); /* Append to list of connections */ list_add_tail(&c->list, &clist); return c; }
void start() { set_no_delay(); do_read(); }