Example #1
0
/* accept a socket and read data as much as you can */
static TDS_THREAD_PROC_DECLARE(fake_thread_proc, arg)
{
	TDS_SYS_SOCKET s = ptr2int(arg), sock;
	socklen_t len;
	char buf[128];
	struct sockaddr_in sin;
	struct pollfd fd;

	memset(&sin, 0, sizeof(sin));
	len = sizeof(sin);

	fd.fd = s;
	fd.events = POLLIN;
	fd.revents = 0;
	if (poll(&fd, 1, 30000) <= 0) {
		perror("poll");
		exit(1);
	}

	if (TDS_IS_SOCKET_INVALID(sock = tds_accept(s, (struct sockaddr *) &sin, &len))) {
		perror("accept");
		exit(1);
	}
	tds_mutex_lock(&mtx);
	fake_sock = sock;
	tds_mutex_unlock(&mtx);
	CLOSESOCKET(s);

	for (;;) {
		int len;

		fd.fd = sock;
		fd.events = POLLIN;
		fd.revents = 0;
		if (poll(&fd, 1, 30000) <= 0) {
			perror("poll");
			exit(1);
		}

		/* just read and discard */
		len = READSOCKET(sock, buf, sizeof(buf));
		if (len == 0)
			break;
		if (len < 0 && sock_errno != TDSSOCK_EINPROGRESS)
			break;
	}
	return NULL;
}
Example #2
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;
}
Example #3
0
int
tds_socketpair(int domain, int type, int protocol, int sv[2])
{
	struct sockaddr_in sa, sa2;
	SOCKLEN_T addrlen;
	TDS_SYS_SOCKET s;

	if (!sv)
		return -1;

	/* create a listener */
	s = socket(AF_INET, type, 0);
	if (TDS_IS_SOCKET_INVALID(s))
		return -1;

	sv[1] = INVALID_SOCKET;

	sv[0] = socket(AF_INET, type, 0);
	if (TDS_IS_SOCKET_INVALID(sv[0]))
		goto Cleanup;

	/* bind to a random port */
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	sa.sin_port = 0;
	if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0)
		goto Cleanup;
	if (listen(s, 1) < 0)
		goto Cleanup;

	/* connect to kernel choosen port */
	addrlen = sizeof(sa);
	if (tds_getsockname(s, (struct sockaddr*) &sa, &addrlen) < 0)
		goto Cleanup;
	if (connect(sv[0], (struct sockaddr*) &sa, sizeof(sa)) < 0)
		goto Cleanup;
	addrlen = sizeof(sa2);
	sv[1] = tds_accept(s, (struct sockaddr*) &sa2, &addrlen);
	if (TDS_IS_SOCKET_INVALID(sv[1]))
		goto Cleanup;

	/* check proper connection */
	addrlen = sizeof(sa);
	if (tds_getsockname(sv[0], (struct sockaddr*) &sa, &addrlen) < 0)
		goto Cleanup;
	addrlen = sizeof(sa2);
	if (tds_getpeername(sv[1], (struct sockaddr*) &sa2, &addrlen) < 0)
		goto Cleanup;
	if (sa.sin_family != sa2.sin_family || sa.sin_port != sa2.sin_port
	    || sa.sin_addr.s_addr != sa2.sin_addr.s_addr)
		goto Cleanup;

	CLOSESOCKET(s);
	return 0;

Cleanup:
	CLOSESOCKET(s);
	CLOSESOCKET(sv[0]);
	CLOSESOCKET(sv[1]);
	return -1;
}
Example #4
0
static TDS_THREAD_PROC_DECLARE(fake_thread_proc, arg)
{
	TDS_SYS_SOCKET s = ptr2int(arg), server_sock;
	socklen_t sock_len;
	int len;
	char buf[128];
	struct sockaddr_in sin;
	fd_set fds_read, fds_write, fds_error;
	TDS_SYS_SOCKET max_fd = 0;

	memset(&sin, 0, sizeof(sin));
	sock_len = sizeof(sin);
	alarm(30);
	fprintf(stderr, "waiting connect...\n");
	if ((fake_sock = tds_accept(s, (struct sockaddr *) &sin, &sock_len)) < 0) {
		perror("accept");
		exit(1);
	}
	CLOSESOCKET(s);

	if (TDS_IS_SOCKET_INVALID(server_sock = socket(remote_addr.sa.sa_family, SOCK_STREAM, 0))) {
		perror("socket");
		exit(1);
	}

	fprintf(stderr, "connecting to server...\n");
	if (remote_addr.sa.sa_family == AF_INET) {
		fprintf(stderr, "connecting to %x:%d\n", remote_addr.sin.sin_addr.s_addr, ntohs(remote_addr.sin.sin_port));
	}
	if (connect(server_sock, &remote_addr.sa, remote_addr_len)) {
		perror("connect");
		exit(1);
	}
	alarm(0);

	if (fake_sock > max_fd) max_fd = fake_sock;
	if (server_sock > max_fd) max_fd = server_sock;

	for (;;) {
		int res;

		FD_ZERO(&fds_read);
		FD_SET(fake_sock, &fds_read);
		FD_SET(server_sock, &fds_read);

		FD_ZERO(&fds_write);

		FD_ZERO(&fds_error);
		FD_SET(fake_sock, &fds_error);
		FD_SET(server_sock, &fds_error);

		alarm(30);
		res = select(max_fd + 1, &fds_read, &fds_write, &fds_error, NULL);
		alarm(0);
		if (res < 0) {
			if (sock_errno == TDSSOCK_EINTR)
				continue;
			perror("select");
			exit(1);
		}

		if (FD_ISSET(fake_sock, &fds_error) || FD_ISSET(server_sock, &fds_error)) {
			fprintf(stderr, "error in select\n");
			exit(1);
		}

		/* just read and forward */
		if (FD_ISSET(fake_sock, &fds_read)) {
			if (flow != sending) {
				tds_mutex_lock(&mtx);
				++round_trips;
				tds_mutex_unlock(&mtx);
			}
			flow = sending;

			len = READSOCKET(fake_sock, buf, sizeof(buf));
			if (len == 0) {
				fprintf(stderr, "client connection closed\n");
				break;
			}
			if (len < 0 && sock_errno != TDSSOCK_EINPROGRESS) {
				fprintf(stderr, "read client error %d\n", sock_errno);
				break;
			}
			count_insert(buf, len);
			write_all(server_sock, buf, len);
		}

		if (FD_ISSET(server_sock, &fds_read)) {
			if (flow != receiving) {
				tds_mutex_lock(&mtx);
				++round_trips;
				tds_mutex_unlock(&mtx);
			}
			flow = receiving;

			len = READSOCKET(server_sock, buf, sizeof(buf));
			if (len == 0) {
				fprintf(stderr, "server connection closed\n");
				break;
			}
			if (len < 0 && sock_errno != TDSSOCK_EINPROGRESS) {
				fprintf(stderr, "read server error %d\n", sock_errno);
				break;
			}
			write_all(fake_sock, buf, len);
		}
	}
	CLOSESOCKET(fake_sock);
	CLOSESOCKET(server_sock);
	return NULL;
}