⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 user.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
字号:
/* TDSPool - Connection pooling for TDS based databases * Copyright (C) 2001, 2002, 2003, 2004, 2005  Brian Bruns * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#if HAVE_CONFIG_H#include <config.h>#endif /* HAVE_CONFIG_H */#include <stdarg.h>#include <stdio.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#if HAVE_STRING_H#include <string.h>#endif /* HAVE_STRING_H */#if HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#if HAVE_SYS_TYPES_H#include <sys/types.h>#endif /* HAVE_SYS_TYPES_H */#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif /* HAVE_SYS_SOCKET_H */#include "pool.h"#include "tdssrv.h"#include "tdsstring.h"TDS_RCSID(var, "$Id: user.c,v 1.32 2008/01/07 14:07:21 freddy77 Exp $");static TDS_POOL_USER *pool_user_find_new(TDS_POOL * pool);static int pool_user_login(TDS_POOL * pool, TDS_POOL_USER * puser);static void pool_user_read(TDS_POOL * pool, TDS_POOL_USER * puser);extern int waiters;voidpool_user_init(TDS_POOL * pool){	/* allocate room for pool users */	pool->users = (TDS_POOL_USER *)		calloc(MAX_POOL_USERS, sizeof(TDS_POOL_USER));}static TDS_POOL_USER *pool_user_find_new(TDS_POOL * pool){	TDS_POOL_USER *puser;	int i;	/* first check for dead users to reuse */	for (i=0; i<pool->max_users; i++) {		puser = (TDS_POOL_USER *) & pool->users[i];		if (!puser->tds)			return puser;	}	/* did we exhaust the number of concurrent users? */	if (pool->max_users >= MAX_POOL_USERS) {		fprintf(stderr, "Max concurrent users exceeded, increase in pool.h\n");		return NULL;	}	/* else take one off the top of the pool->users */	puser = (TDS_POOL_USER *) & pool->users[pool->max_users];	pool->max_users++;	return puser;}/* * 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, struct sockaddr_in *sin){	TDS_POOL_USER *puser;	TDS_SYS_SOCKET fd;	socklen_t len;	TDSSOCKET *tds;	puser = pool_user_find_new(pool);	if (!puser)		return NULL;	fprintf(stderr, "accepting connection\n");	len = sizeof(*sin);	if (TDS_IS_SOCKET_INVALID(fd = accept(s, (struct sockaddr *) sin, &len))) {		perror("accept");		return NULL;	}	tds = tds_alloc_socket(NULL, BLOCKSIZ);	if (!tds) {		CLOSESOCKET(fd);		return NULL;	}	tds_set_parent(tds, NULL);	/* FIX ME - little endian emulation should be config file driven */	tds->emul_little_endian = 1;	tds->in_buf = (unsigned char *) calloc(1, BLOCKSIZ);	tds->s = fd;	if (!tds->in_buf) {		tds_free_socket(tds);		return NULL;	}	tds->in_buf_max = BLOCKSIZ;	tds->out_flag = TDS_LOGIN;	puser->tds = tds;	puser->user_state = TDS_SRV_LOGIN;	return puser;}/*  * pool_free_user * close out a disconnected user. */voidpool_free_user(TDS_POOL_USER * puser){	/* make sure to decrement the waiters list if he is waiting */	if (puser->user_state == TDS_SRV_WAIT)		waiters--;	tds_free_socket(puser->tds);	memset(puser, 0, sizeof(TDS_POOL_USER));}/*  * pool_process_users * check the fd_set for user input, allocate a pool member to it, and forward * the query to that member. */intpool_process_users(TDS_POOL * pool, fd_set * fds){	TDS_POOL_USER *puser;	int i;	int cnt = 0;	for (i = 0; i < pool->max_users; i++) {		puser = (TDS_POOL_USER *) & pool->users[i];		if (!puser->tds)			continue;	/* dead connection */		if (FD_ISSET(puser->tds->s, fds)) {			cnt++;			switch (puser->user_state) {			case TDS_SRV_LOGIN:				if (pool_user_login(pool, puser)) {					/* login failed...free socket */					pool_free_user(puser);				}				/* otherwise we have a good login */				break;			case TDS_SRV_IDLE:				pool_user_read(pool, puser);				break;			case TDS_SRV_QUERY:				/* what is this? a cancel perhaps */				pool_user_read(pool, puser);				break;			/* just to avoid a warning */			default:				break;			}	/* switch */		}		/* if */	}			/* for */	return cnt;}/* * pool_user_login * Reads clients login packet and forges a login acknowledgement sequence  */static intpool_user_login(TDS_POOL * pool, TDS_POOL_USER * puser){	TDSSOCKET *tds;	TDSLOGIN *login = tds_alloc_login();	/* FIXME */	char msg[256];	tds = puser->tds;	tds_read_login(tds, login);	dump_login(login);	if (!strcmp(tds_dstr_cstr(&login->user_name), pool->user) && !strcmp(tds_dstr_cstr(&login->password), pool->password)) {		tds->out_flag = TDS_REPLY;		tds_env_change(tds, 1, "master", pool->database);		sprintf(msg, "Changed database context to '%s'.", pool->database);		tds_send_msg(tds, 5701, 2, 10, msg, "JDBC", "ZZZZZ", 1);		if (!login->suppress_language) {			tds_env_change(tds, 2, NULL, "us_english");			tds_send_msg(tds, 5703, 1, 10, "Changed language setting to 'us_english'.", "JDBC", "ZZZZZ", 1);		}		tds_env_change(tds, 4, NULL, "512");		tds_send_login_ack(tds, "sql server");		/* tds_send_capabilities_token(tds); */		tds_send_done_token(tds, 0, 1);		puser->user_state = TDS_SRV_IDLE;		/* send it! */		tds_flush_packet(tds);		tds_free_login(login);		return 0;	} else {		tds_free_login(login);		/* send nack before exiting */		return 1;	}}/* * pool_user_read * checks the packet type of data coming from the client and allocates a  * pool member if necessary. */static voidpool_user_read(TDS_POOL * pool, TDS_POOL_USER * puser){	TDSSOCKET *tds;	TDS_POOL_MEMBER *pmbr;	tds = puser->tds;	/* FIXME read entire packet !!! */	tds->in_len = read(tds->s, tds->in_buf, tds->in_buf_max);	if (tds->in_len == 0) {		fprintf(stderr, "user disconnected\n");		pool_free_user(puser);		return;	} else if (tds->in_len == -1) {		perror("read");		fprintf(stderr, "cleaning up user\n");		if (puser->assigned_member) {			fprintf(stderr, "user has assigned member, freeing\n");			pmbr = puser->assigned_member;			pool_deassign_member(pmbr);			pool_reset_member(pmbr);		}		pool_free_user(puser);	} else {		dump_buf(tds->in_buf, tds->in_len);		/* language packet or TDS5 language packet */		if (tds->in_buf[0] == 0x01 || tds->in_buf[0] == 0x0F) {			pool_user_query(pool, puser);		} else if (tds->in_buf[0] == 0x06) {			/* cancel */		} else {			fprintf(stderr, "Unrecognized packet type, closing user\n");			pool_free_user(puser);		}	}	/* fprintf(stderr,"read %d bytes from conn %d\n",len,i); */}voidpool_user_query(TDS_POOL * pool, TDS_POOL_USER * puser){	TDS_POOL_MEMBER *pmbr;	int ret;		puser->user_state = TDS_SRV_QUERY;	pmbr = pool_find_idle_member(pool);	if (!pmbr) {		/* 		 * put into wait state 		 * check when member is deallocated		 */		fprintf(stderr, "Not enough free members...placing user in WAIT\n");		puser->user_state = TDS_SRV_WAIT;		waiters++;	} else {		pmbr->state = TDS_QUERYING;		pool_assign_member(pmbr, puser);#ifdef MSG_NOSIGNAL			/* cf. net.c for better technique.  */		ret = send(pmbr->tds->s, puser->tds->in_buf, puser->tds->in_len, MSG_NOSIGNAL);#else		/* write(pmbr->tds->s, puser->tds->in_buf, puser->tds->in_len); */		ret = send(pmbr->tds->s, puser->tds->in_buf, puser->tds->in_len, 0);#endif		/* write failed, cleanup member */		if (ret==-1) {			pool_free_member(pmbr);		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -