static void pool_socket_init(TDS_POOL * pool) { struct sockaddr_in sin; TDS_SYS_SOCKET s, event_pair[2]; int socktrue = 1; /* FIXME -- read the interfaces file and bind accordingly */ sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(pool->port); sin.sin_family = AF_INET; if (TDS_IS_SOCKET_INVALID(s = socket(AF_INET, SOCK_STREAM, 0))) { perror("socket"); exit(1); } tds_socket_set_nonblocking(s); /* don't keep addr in use from [email protected] */ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &socktrue, sizeof(socktrue)); fprintf(stderr, "Listening on port %d\n", pool->port); if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("bind"); exit(1); } listen(s, 5); pool->listen_fd = s; if (socketpair(AF_UNIX, SOCK_STREAM, 0, event_pair) < 0) { perror("socketpair"); exit(1); } tds_socket_set_nonblocking(event_pair[0]); tds_socket_set_nonblocking(event_pair[1]); pool->event_fd = event_pair[1]; pool->wakeup_fd = event_pair[0]; }
/* * pool_user_create * accepts a client connection and adds it to the users list and returns it */ TDS_POOL_USER * pool_user_create(TDS_POOL * pool, TDS_SYS_SOCKET s) { TDS_POOL_USER *puser; TDS_SYS_SOCKET fd; TDSSOCKET *tds; LOGIN_EVENT *ev; tdsdump_log(TDS_DBG_NETWORK, "accepting connection\n"); if (TDS_IS_SOCKET_INVALID(fd = tds_accept(s, NULL, NULL))) { char *errstr = sock_strerror(errno); tdsdump_log(TDS_DBG_ERROR, "error calling assert :%s\n", errstr); sock_strerror_free(errstr); return NULL; } if (tds_socket_set_nonblocking(fd) != 0) { CLOSESOCKET(fd); return NULL; } puser = pool_user_find_new(pool); if (!puser) { CLOSESOCKET(fd); return NULL; } tds = tds_alloc_socket(pool->ctx, BLOCKSIZ); if (!tds) { CLOSESOCKET(fd); return NULL; } ev = (LOGIN_EVENT *) calloc(1, sizeof(*ev)); if (!ev || TDS_FAILED(tds_iconv_open(tds->conn, "UTF-8", 0))) { free(ev); tds_free_socket(tds); CLOSESOCKET(fd); return NULL; } /* FIX ME - little endian emulation should be config file driven */ tds->conn->emul_little_endian = 1; tds_set_s(tds, fd); tds->state = TDS_IDLE; tds->out_flag = TDS_LOGIN; puser->sock.tds = tds; puser->user_state = TDS_SRV_QUERY; puser->sock.poll_recv = false; puser->sock.poll_send = false; /* launch login asyncronously */ ev->puser = puser; ev->pool = pool; if (tds_thread_create_detached(login_proc, ev) != 0) { pool_free_user(pool, puser); fprintf(stderr, "error creating thread\n"); return NULL; } return puser; }
static TDSERRNO tds_connect_socket(TDSSOCKET *tds, struct addrinfo *addr, unsigned int port, int timeout, int *p_oserr) { SOCKLEN_T optlen; TDSCONNECTION *conn = tds->conn; char ipaddr[128]; int retval, len; tds_addrinfo_set_port(addr, port); tds_addrinfo2str(addr, ipaddr, sizeof(ipaddr)); if (TDS_IS_SOCKET_INVALID(conn->s)) return TDSECONN; *p_oserr = 0; tdsdump_log(TDS_DBG_INFO1, "Connecting to %s port %d (TDS version %d.%d)\n", ipaddr, port, TDS_MAJOR(conn), TDS_MINOR(conn)); #ifdef DOS32X /* the other connection doesn't work on WATTCP32 */ if (connect(conn->s, addr->ai_addr, addr->ai_addrlen) < 0) { *p_oserr = sock_errno; tdsdump_log(TDS_DBG_ERROR, "tds_open_socket(): %s:%d", ipaddr, port); return TDSECONN; } #else if (!timeout) { /* A timeout of zero means wait forever; 90,000 seconds will feel like forever. */ timeout = 90000; } if ((*p_oserr = tds_socket_set_nonblocking(conn->s)) != 0) { tds_connection_close(conn); return TDSEUSCT; /* close enough: "Unable to set communications timer" */ } retval = connect(conn->s, addr->ai_addr, addr->ai_addrlen); if (retval == 0) { tdsdump_log(TDS_DBG_INFO2, "connection established\n"); } else { int err = *p_oserr = sock_errno; char *errstr = sock_strerror(err); tdsdump_log(TDS_DBG_ERROR, "tds_open_socket: connect(2) returned \"%s\"\n", errstr); sock_strerror_free(errstr); #if DEBUGGING_CONNECTING_PROBLEM if (err != ECONNREFUSED && err != ENETUNREACH && err != TDSSOCK_EINPROGRESS) { tdsdump_dump_buf(TDS_DBG_ERROR, "Contents of sockaddr_in", addr->ai_addr, addr->ai_addrlen); tdsdump_log(TDS_DBG_ERROR, " sockaddr_in:\t" "%s = %x\n" "\t\t\t%s = %x\n" "\t\t\t%s = %s\n" , "sin_family", addr->ai_family , "port", port , "address", ipaddr ); } #endif if (err != TDSSOCK_EINPROGRESS) return TDSECONN; *p_oserr = TDSSOCK_ETIMEDOUT; if (tds_select(tds, TDSSELWRITE|TDSSELERR, timeout) == 0) return TDSECONN; } #endif /* not DOS32X */ /* check socket error */ optlen = sizeof(len); len = 0; if (tds_getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (char *) &len, &optlen) != 0) { char *errstr = sock_strerror(*p_oserr = sock_errno); tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) failed: %s\n", errstr); sock_strerror_free(errstr); return TDSECONN; } if (len != 0) { char *errstr = sock_strerror(*p_oserr = len); tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) reported: %s\n", errstr); sock_strerror_free(errstr); return TDSECONN; } return TDSEOK; }