Exemple #1
0
/* 
 * pool_process_members
 * check the fd_set for members returning data to the client, lookup the 
 * client holding this member and forward the results.
 */
int
pool_process_members(TDS_POOL * pool, fd_set * fds)
{
	TDS_POOL_MEMBER *pmbr;
	TDS_POOL_USER *puser;
	TDSSOCKET *tds;
	int i, age, ret;
	int cnt = 0;
	time_t time_now;

	for (i = 0; i < pool->num_members; i++) {
		pmbr = &pool->members[i];

		tds = pmbr->tds;
		if (!tds) {
			assert(pmbr->state == TDS_IDLE);
			continue;	/* dead connection */
		}

		time_now = time(NULL);
		if (FD_ISSET(tds_get_s(tds), fds)) {
			pmbr->last_used_tm = time_now;
			cnt++;
			if (pool_packet_read(tds))
				continue;

			if (tds->in_len == 0) {
				fprintf(stderr, "Uh oh! member %d disconnected\n", i);
				/* mark as dead */
				pool_free_member(pmbr);
			} else if (tds->in_len < 0) {
				fprintf(stderr, "Uh oh! member %d disconnected\n", i);
				perror("read");
				pool_free_member(pmbr);
			} else {
				tdsdump_dump_buf(TDS_DBG_NETWORK, "Got packet from server:", tds->in_buf, tds->in_len);
				/* fprintf(stderr, "read %d bytes from member %d\n", tds->in_len, i); */
				puser = pmbr->current_user;
				if (puser) {
					tdsdump_log(TDS_DBG_INFO1, "writing it sock %d\n", tds_get_s(puser->tds));
					/* cf. net.c for better technique.  */
					/* FIXME handle partial write, stop read on member */
					ret = pool_write_all(tds_get_s(puser->tds), tds->in_buf, tds->in_len);
					if (ret < 0) { /* couldn't write, ditch the user */
						fprintf(stdout, "member %d received error while writing\n",i);
						pool_free_member(pmbr);
					}
				}
			}
		}
		age = time_now - pmbr->last_used_tm;
		if (age > pool->max_member_age && i >= pool->min_open_conn && !pmbr->current_user) {
			fprintf(stderr, "member %d is %d seconds old...closing\n", i, age);
			pool_free_member(pmbr);
		}
	}
	return cnt;
}
Exemple #2
0
/**
 * Handle async login
 */
void
pool_user_finish_login(TDS_POOL * pool, TDS_POOL_USER * puser)
{
	END_LOGIN_EVENT *ev = (END_LOGIN_EVENT *) calloc(1, sizeof(*ev));
	if (!ev) {
		pool_free_member(pool, puser->assigned_member);
		return;
	}

	ev->pool  = pool;
	ev->puser = puser;

	if (tds_thread_create_detached(end_login_proc, ev) != 0) {
		pool_free_member(pool, puser->assigned_member);
		free(ev);
		fprintf(stderr, "error creating thread\n");
	}
}
Exemple #3
0
/*
 * if a dead connection on the client side left this member in a questionable
 * state, let's bring in a correct one
 * We are not sure what the client did so we must try to clean as much as
 * possible.
 * Use pool_free_member if the state is really broken.
 */
void
pool_reset_member(TDS_POOL_MEMBER * pmbr)
{
	// FIXME not wait for server !!! asyncronous
	TDSSOCKET *tds = pmbr->tds;

	if (pmbr->current_user) {
		pmbr->current_user->assigned_member = NULL;
		pool_free_user(pmbr->current_user);
		pmbr->current_user = NULL;
	}

	/* cancel whatever pending */
	tds->state = TDS_IDLE;
	tds_init_write_buf(tds);
	tds->out_flag = TDS_CANCEL;
	tds_flush_packet(tds);
	tds->state = TDS_PENDING;

	if (tds_read_packet(tds) < 0) {
		pool_free_member(pmbr);
		return;
	}

	if (IS_TDS71_PLUS(tds->conn)) {
		/* this 0x9 final reset the state from mssql 2000 */
		tds_init_write_buf(tds);
		tds->out_flag = TDS_QUERY;
		tds_write_packet(tds, 0x9);
		tds->state = TDS_PENDING;

		if (tds_read_packet(tds) < 0) {
			pool_free_member(pmbr);
			return;
		}
	}

	pmbr->state = TDS_IDLE;
}
Exemple #4
0
static void
end_login_execute(TDS_POOL_EVENT *base_event)
{
	END_LOGIN_EVENT *ev = (END_LOGIN_EVENT *) base_event;
	TDS_POOL *pool = ev->pool;
	TDS_POOL_USER *puser = ev->puser;
	TDS_POOL_MEMBER *pmbr = puser->assigned_member;

	if (!ev->success) {
		pool_free_member(pool, pmbr);
		return;
	}

	puser->sock.poll_recv = true;
	puser->sock.poll_send = false;
	pmbr->sock.poll_recv = true;
	pmbr->sock.poll_send = false;
}
Exemple #5
0
/* 
 * pool_process_users
 * check the fd_set for user input, allocate a pool member to it, and forward
 * the query to that member.
 */
void
pool_process_users(TDS_POOL * pool, fd_set * rfds, fd_set * wfds)
{
	TDS_POOL_USER *puser, *next;

	for (next = dlist_user_first(&pool->users); (puser = next) != NULL; ) {

		next = dlist_user_next(&pool->users, puser);

		if (!puser->sock.tds)
			continue;	/* dead connection */

		if (puser->sock.poll_recv && FD_ISSET(tds_get_s(puser->sock.tds), rfds)) {
			assert(puser->user_state == TDS_SRV_QUERY);
			if (!pool_user_read(pool, puser))
				continue;
		}
		if (puser->sock.poll_send && FD_ISSET(tds_get_s(puser->sock.tds), wfds)) {
			if (!pool_write_data(&puser->assigned_member->sock, &puser->sock))
				pool_free_member(pool, puser->assigned_member);
		}
	}			/* for */
}
Exemple #6
0
/* 
 * pool_process_members
 * check the fd_set for members returning data to the client, lookup the 
 * client holding this member and forward the results.
 */
int
pool_process_members(TDS_POOL * pool, fd_set * fds)
{
	TDS_POOL_MEMBER *pmbr;
	TDS_POOL_USER *puser;
	TDSSOCKET *tds;
	int i, age, ret;
	int cnt = 0;
	unsigned char *buf;
	time_t time_now;

	for (i = 0; i < pool->num_members; i++) {
		pmbr = (TDS_POOL_MEMBER *) & pool->members[i];

		if (!pmbr->tds)
			break;	/* dead connection */

		tds = pmbr->tds;
		time_now = time(NULL);
		if (FD_ISSET(tds->s, fds)) {
			pmbr->last_used_tm = time_now;
			cnt++;
			/* tds->in_len = read(tds->s, tds->in_buf, BLOCKSIZ); */
			if (pool_packet_read(pmbr))
				continue;

			if (tds->in_len == 0) {
				fprintf(stderr, "Uh oh! member %d disconnected\n", i);
				/* mark as dead */
				pool_free_member(pmbr);
			} else if (tds->in_len == -1) {
				fprintf(stderr, "Uh oh! member %d disconnected\n", i);
				perror("read");
				pool_free_member(pmbr);
			} else {
				/* fprintf(stderr, "read %d bytes from member %d\n", tds->in_len, i); */
				if (pmbr->current_user) {
					puser = pmbr->current_user;
					buf = tds->in_buf;
					/* 
					 * check the netlib final packet flag
					 * instead of looking for done tokens.
					 * It's more efficient and generic to 
					 * all protocol versions. -- bsb 
					 * 2004-12-12 
					 */
					if (buf[1]) {
					/* if (pool_find_end_token(pmbr, buf + 8, tds->in_len - 8)) { */
						/* we are done...deallocate member */
						fprintf(stdout, "deassigning user from member %d\n",i);
						pool_deassign_member(pmbr);

						pmbr->state = TDS_IDLE;
						puser->user_state = TDS_SRV_IDLE;
					}
					/* cf. net.c for better technique.  */
					ret = WRITESOCKET(puser->tds->s, buf, tds->in_len);
					if (ret < 0) { /* couldn't write, ditch the user */
						fprintf(stdout, "member %d received error while writing\n",i);
						pool_free_user(pmbr->current_user);
						pool_deassign_member(pmbr);
						pool_reset_member(pmbr);
					}
				}
			}
		}
		age = time_now - pmbr->last_used_tm;
		if (age > pool->max_member_age && i >= pool->min_open_conn) {
			fprintf(stderr, "member %d is %d seconds old...closing\n", i, age);
			pool_free_member(pmbr);
		}
	}
	return cnt;
}
Exemple #7
0
/*
 * if a dead connection on the client side left this member in a questionable
 * state, let's clean it up.
 */
void
pool_reset_member(TDS_POOL_MEMBER * pmbr)
{
	pool_free_member(pmbr);
}