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

📄 net.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			tdsdump_log(TDS_DBG_ERROR, "tds_ctx->int_handler returned %d\n", timeout_action);#endif			switch (timeout_action) {			case TDS_INT_CONTINUE:		/* keep waiting */				continue;			case TDS_INT_CANCEL:		/* abort the current command batch */							/* FIXME tell tds_goodread() not to call tdserror() */				return 0;			default:				tdsdump_log(TDS_DBG_NETWORK, 					"tds_select: invalid interupt handler return code: %d\n", timeout_action);				exit(EXIT_FAILURE);				break;			}		}		/* 		 * We can reach here if no interrupt handler was installed and we either timed out or got EINTR. 		 * We cannot be polling, so we are about to drop out of the loop. 		 */		assert(poll_seconds == timeout_seconds);	}		return 0;}/** * Loops until we have received buflen characters * return -1 on failure * This function does not close the socket.  Maybe it should.   */static inttds_goodread(TDSSOCKET * tds, unsigned char *buf, int buflen, unsigned char unfinished){	int rc, got = 0;	if (buf == NULL || buflen < 1 || tds == NULL)		return 0;	for (;;) {		int len;		if (IS_TDSDEAD(tds))			return -1;		if ((len = tds_select(tds, TDSSELREAD, tds->query_timeout)) > 0) {#ifndef MSG_NOSIGNAL			len = READSOCKET(tds->s, buf + got, buflen);#else			len = recv(tds->s, buf + got, buflen, MSG_NOSIGNAL);#endif			if (len < 0 && sock_errno == EAGAIN)				continue;			/* detect connection close */			if (len <= 0) {				tdserror(tds->tds_ctx, tds, len == 0 ? TDSESEOF : TDSEREAD, sock_errno);				tds_close_socket(tds);				return -1;			}		} else if (len < 0) {			if (sock_errno == EAGAIN) /* shouldn't happen, but OK */				continue;			tdserror(tds->tds_ctx, tds, TDSEREAD, sock_errno);			tds_close_socket(tds);			return -1;		} else { /* timeout */			switch (rc = tdserror(tds->tds_ctx, tds, TDSETIME, sock_errno)) {			case TDS_INT_CONTINUE:				continue;			case TDS_INT_TIMEOUT:				tds_send_cancel(tds);				continue; /* fixme: or return? */			default:			case TDS_INT_CANCEL:				tds_close_socket(tds);				return -1;			}			assert(0); /* not reached */		}		got += len;		buflen -= len;		/* doing test here reduce number of syscalls required */		if (buflen <= 0)			break;		if (unfinished && got)			break;	}	return got;}static intgoodread(TDSSOCKET * tds, unsigned char *buf, int buflen){#ifdef HAVE_GNUTLS	if (tds->tls_session)		return gnutls_record_recv(tds->tls_session, buf, buflen);#elif defined(HAVE_OPENSSL)	if (tds->tls_session)		return SSL_read((SSL*) tds->tls_session, buf, buflen);#endif	return tds_goodread(tds, buf, buflen, 0);}/** * Read in one 'packet' from the server.  This is a wrapped outer packet of * the protocol (they bundle result packets into chunks and wrap them at * what appears to be 512 bytes regardless of how that breaks internal packet * up.   (tetherow\@nol.org) * @return bytes read or -1 on failure */inttds_read_packet(TDSSOCKET * tds){	unsigned char header[8];	int len, have;	if (IS_TDSDEAD(tds)) {		tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD");		return -1;	}	/*	 * Read in the packet header.  We use this to figure out our packet length. 	 * Cast to int are needed because some compiler seem to convert	 * len to unsigned (as FreeBSD 4.5 one)	 */	if ((len = goodread(tds, header, sizeof(header))) < (int) sizeof(header)) {		/* GW ADDED */		if (len < 0) {			/* not needed because goodread() already called:  tdserror(tds->tds_ctx, tds, TDSEREAD, 0); */			tds_close_socket(tds);			tds->in_len = 0;			tds->in_pos = 0;			return -1;		}		/* GW ADDED */		/*		 * Not sure if this is the best way to do the error		 * handling here but this is the way it is currently		 * being done.		 */		tds->in_len = 0;		tds->in_pos = 0;		tds->last_packet = 1;		if (tds->state != TDS_IDLE && len == 0) {			tds_close_socket(tds);		}		return -1;	}	tdsdump_dump_buf(TDS_DBG_NETWORK, "Received header", header, sizeof(header));#if 0	/*	 * Note:	 * this was done by Gregg, I don't think its the real solution (it breaks	 * under 5.0, but I haven't gotten a result big enough to test this yet. 	 */	if (IS_TDS42(tds)) {		if (header[0] != 0x04 && header[0] != 0x0f) {			tdsdump_log(TDS_DBG_ERROR, "Invalid packet header %d\n", header[0]);			/*			 * Not sure if this is the best way to do the error 			 * handling here but this is the way it is currently 			 * being done.			 */			tds->in_len = 0;			tds->in_pos = 0;			tds->last_packet = 1;			return (-1);		}	}#endif	/* Convert our packet length from network to host byte order */	len = ((((unsigned int) header[2]) << 8) | header[3]) - 8;	/*	 * If this packet size is the largest we have gotten allocate space for it	 */	if (len > tds->in_buf_max) {		unsigned char *p;		if (!tds->in_buf) {			p = (unsigned char *) malloc(len);		} else {			p = (unsigned char *) realloc(tds->in_buf, len);		}		if (!p) {			tds_close_socket(tds);			return -1;		}		tds->in_buf = p;		/* Set the new maximum packet size */		tds->in_buf_max = len;	}	/* Clean out the in_buf so we don't use old stuff by mistake */	memset(tds->in_buf, 0, tds->in_buf_max);	/* Now get exactly how many bytes the server told us to get */	have = 0;	while (have < len) {		int nbytes = goodread(tds, tds->in_buf + have, len - have);		if (nbytes < 1) {			/*			 * Not sure if this is the best way to do the error			 * handling here but this is the way it is currently			 * being done.			 */			/* no need to call tdserror(), because goodread() already did */			tds->in_len = 0;			tds->in_pos = 0;			tds->last_packet = 1;			tds_close_socket(tds);			return -1;		}		have += nbytes;	}	/* Set the last packet flag */	tds->last_packet = (header[1] != 0);	/* set the received packet type flag */	tds->in_flag = header[0];	/* Set the length and pos (not sure what pos is used for now */	tds->in_len = have;	tds->in_pos = 0;	tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", tds->in_buf, tds->in_len);	return (tds->in_len);}/** * \param tds the famous socket * \param p pointer to buffer * \param len bytes in buffer * \param last 1 if this is the last packet, else 0 * \return len on success, <0 on failure */static inttds_goodwrite(TDSSOCKET * tds, const unsigned char *p, int len, unsigned char last){	int remaining = len;	int nput, rc, err=0;	/* Fix of SIGSEGV when FD_SET() called with negative fd (Sergey A. Cherukhin, 23/09/2005) */	if (TDS_IS_SOCKET_INVALID(tds->s))		return -1;	while (remaining > 0) {		if ((rc = tds_select(tds, TDSSELWRITE, tds->query_timeout)) > 0) {#ifdef USE_MSGMORE			nput = send(tds->s, p, remaining, last ? MSG_NOSIGNAL : MSG_NOSIGNAL|MSG_MORE);			/* In case the kernel does not support MSG_MORE, try again without it */			if (nput < 0 && errno == EINVAL && !last)				nput = send(tds->s, p, remaining, MSG_NOSIGNAL);#elif !defined(MSG_NOSIGNAL)			nput = WRITESOCKET(tds->s, p, remaining);#else			nput = send(tds->s, p, remaining, MSG_NOSIGNAL);#endif			if (nput < 0 && sock_errno == EAGAIN)				continue;			/* detect connection close */			if (nput <= 0) {				tdserror(tds->tds_ctx, tds, nput == 0 ? TDSESEOF : TDSEWRIT, sock_errno);				tds_close_socket(tds);				return -1;			}		} else if (rc < 0) {			if (sock_errno == EAGAIN) /* shouldn't happen, but OK, retry */				continue;			tdsdump_log(TDS_DBG_NETWORK, "TDS: Write failed in tds_write_packet\nError: %d (%s)\n", err, strerror(err));			tdserror(tds->tds_ctx, tds, TDSEWRIT, sock_errno);			tds_close_socket(tds);			return -1;		} else { /* timeout */			tdsdump_log(TDS_DBG_NETWORK, "tds_goodwrite(): timed out, asking client\n");			switch (rc = tdserror(tds->tds_ctx, tds, TDSETIME, sock_errno)) {			case TDS_INT_CONTINUE:				continue;			case TDS_INT_TIMEOUT:				/* FIXME we are not able to send a packet and we want to send a packet ?? */				tds_send_cancel(tds);				continue; /* fixme: or return? */			default:			case TDS_INT_CANCEL:				tds_close_socket(tds);				return -1;			}			assert(0); /* not reached */		}		p += nput;		remaining -= nput;	}#ifdef USE_CORK	/* force packet flush */	if (last) {		int opt;		opt = 0;		setsockopt(tds->s, SOL_TCP, TCP_CORK, (const void *) &opt, sizeof(opt));		opt = 1;		setsockopt(tds->s, SOL_TCP, TCP_CORK, (const void *) &opt, sizeof(opt));	}#endif	return len;}inttds_write_packet(TDSSOCKET * tds, unsigned char final){	int sent;	unsigned int left = 0;#if !defined(WIN32) && !defined(MSG_NOSIGNAL) && !defined(DOS32X)	void (*oldsig) (int);#endif#if TDS_ADDITIONAL_SPACE != 0	if (tds->out_pos > tds->env.block_size) {		left = tds->out_pos - tds->env.block_size;		tds->out_pos = tds->env.block_size;	}#endif	tds->out_buf[0] = tds->out_flag;	tds->out_buf[1] = final;	tds->out_buf[2] = (tds->out_pos) / 256u;	tds->out_buf[3] = (tds->out_pos) % 256u;	if (IS_TDS7_PLUS(tds) && !tds->connection)		tds->out_buf[6] = 0x01;	tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", tds->out_buf, tds->out_pos);#if !defined(WIN32) && !defined(MSG_NOSIGNAL) && !defined(DOS32X)	oldsig = signal(SIGPIPE, SIG_IGN);	if (oldsig == SIG_ERR) {		tdsdump_log(TDS_DBG_WARN, "TDS: Warning: Couldn't set SIGPIPE signal to be ignored\n");	}#endif#ifdef HAVE_GNUTLS	if (tds->tls_session)		sent = gnutls_record_send(tds->tls_session, tds->out_buf, tds->out_pos);	else#elif defined(HAVE_OPENSSL)	if (tds->tls_session)		sent = SSL_write((SSL*) tds->tls_session, tds->out_buf, tds->out_pos);	else#endif		sent = tds_goodwrite(tds, tds->out_buf, tds->out_pos, final);#if !defined(WIN32) && !defined(MSG_NOSIGNAL) && !defined(DOS32X)	if (signal(SIGPIPE, oldsig) == SIG_ERR) {		tdsdump_log(TDS_DBG_WARN, "TDS: Warning: Couldn't reset SIGPIPE signal to previous value\n");	}#endif#if TDS_ADDITIONAL_SPACE != 0	memcpy(tds->out_buf + 8, tds->out_buf + tds->env.block_size, left);#endif	tds->out_pos = left + 8;	/* GW added in check for write() returning <0 and SIGPIPE checking */	return sent <= 0 ? TDS_FAIL : TDS_SUCCEED;}/** * Get port of given instance * @return port number or 0 if error */inttds7_get_instance_port(const char *ip_addr, const char *instance){	int num_try;	struct sockaddr_in sin;	ioctl_nonblocking_t ioctl_nonblocking;#if USE_POLL	struct pollfd fd;#else	struct timeval selecttimeout;	fd_set fds;#endif	int retval;	TDS_SYS_SOCKET s;	char msg[1024];	size_t msg_len;	int port = 0;	tdsdump_log(TDS_DBG_ERROR, "tds7_get_instance_port(%s, %s)\n", ip_addr, instance);	sin.sin_addr.s_addr = inet_addr(ip_addr);	if (sin.sin_addr.s_addr == INADDR_NONE) {		tdsdump_log(TDS_DBG_ERROR, "inet_addr() failed, IP = %s\n", ip_addr);		return 0;	}	sin.sin_family = AF_INET;	sin.sin_port = htons(1434);	/* create an UDP socket */	if (TDS_IS_SOCKET_INVALID(s = socket(AF_INET, SOCK_DGRAM, 0))) {		tdsdump_log(TDS_DBG_ERROR, "socket creation error: %s\n", strerror(sock_errno));		return 0;	}#if !USE_POLL#if !defined(WIN32) && defined(FD_SETSIZE)	if (s >= FD_SETSIZE) {		sock_errno = EINVAL;		return 0;	}#endif#endif	/*	 * on cluster environment is possible that reply packet came from	 * different IP so do not filter by ip with connect	 */	ioctl_nonblocking = 1;	if (IOCTLSOCKET(s, FIONBIO, &ioctl_nonblocking) < 0) {		CLOSESOCKET(s);		return 0;	}	/* 	 * Request the instance's port from the server.  	 * There is no easy way to detect if port is closed so we always try to	 * get a reply from server 16 times. 	 */	for (num_try = 0; num_try < 16; ++num_try) {

⌨️ 快捷键说明

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