/* * 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; }
/** * 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"); } }
/* * 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; }
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; }
/* * 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 */ }
/* * 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; }
/* * 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); }