Exemplo n.º 1
0
static void
write_all(TDS_SYS_SOCKET s, const void *buf, size_t len)
{
	int res, l;
	fd_set fds_write;

	for (; len > 0;) {
		FD_ZERO(&fds_write);
		FD_SET(s, &fds_write);

		res = select(s + 1, NULL, &fds_write, NULL, NULL);
		if (res <= 0) {
			if (errno == EINTR)
				continue;
			perror("select");
			exit(1);
		}

		l = WRITESOCKET(s, buf, len);
		if (l <= 0) {
			perror("write socket");
			exit(1);
		}
		buf = ((const char *) buf) + l;
		len -= l;
	}
}
Exemplo n.º 2
0
void
pool_event_add(TDS_POOL *pool, TDS_POOL_EVENT *ev, TDS_POOL_EXECUTE execute)
{
	tds_mutex_lock(&pool->events_mtx);
	ev->execute = execute;
	ev->next = pool->events;
	pool->events = ev;
	tds_mutex_unlock(&pool->events_mtx);
	WRITESOCKET(pool->event_fd, "x", 1);
}
Exemplo n.º 3
0
/*  write data to a nonblocking socket 
	Inputs:
		<fd> socket
		<buf> point to the data 
		<len> length of data
	Returns:
		< 0 on failure
		otherwise the number of bytes written
*/
int
tcp_nonblocking_write(int fd, char *buf, int len, void *dummy)
{
	int n;

	(void) dummy;

	n = WRITESOCKET (fd, buf, len);
	if (n == -1)
	{
		if (NET_ERRNO != EWOULDBLOCK && NET_ERRNO != ENOBUFS)
			return -1;
		n = 0;
	}
	return n;
}
Exemplo n.º 4
0
int
pool_write_all(TDS_SYS_SOCKET sock, const void *buf, size_t len)
{
	int ret;
	const unsigned char *p = (const unsigned char *) buf;

	while (len) {
		ret = WRITESOCKET(sock, p, len);
		/* write failed, cleanup member */
		if (ret <= 0) {
			return ret;
		}
		p   += ret;
		len -= ret;
	}
	return 1;
}
Exemplo n.º 5
0
int
pool_write(TDS_SYS_SOCKET sock, const void *buf, size_t len)
{
	int ret;
	const unsigned char *p = (const unsigned char *) buf;

	while (len) {
		ret = WRITESOCKET(sock, p, len);
		if (ret <= 0) {
			int err = errno;
			if (TDSSOCK_WOULDBLOCK(err) || err == EINTR)
				break;
			return -1;
		}
		p   += ret;
		len -= ret;
	}
	return p - (const unsigned char *) buf;
}
Exemplo n.º 6
0
/**
 * Write to an OS socket
 * @returns 0 if blocking, <0 error >0 bytes readed
 */
static int
tds_socket_write(TDSCONNECTION *conn, TDSSOCKET *tds, const unsigned char *buf, int buflen)
{
	int err, len;
	char *errstr;

#if ENABLE_EXTRA_CHECKS
	/* this simulate the fact that send can return less bytes */
	if (buflen >= 5) {
		static int cnt = 0;
		if (++cnt == 5) {
			cnt = 0;
			buflen -= 3;
		}
	}
#endif

#if defined(__APPLE__) && defined(SO_NOSIGPIPE)
	len = send(conn->s, buf, buflen, 0);
#else
	len = WRITESOCKET(conn->s, buf, buflen);
#endif
	if (len > 0)
		return len;

	err = sock_errno;
	if (0 == len || TDSSOCK_WOULDBLOCK(err))
		return 0;

	assert(len < 0);

	/* detect connection close */
	errstr = sock_strerror(err);
	tdsdump_log(TDS_DBG_NETWORK, "send(2) failed: %d (%s)\n", err, errstr);
	sock_strerror_free(errstr);
	tds_connection_close(conn);
	tdserror(conn->tds_ctx, tds, TDSEWRIT, err);
	return -1;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
static int
tds_goodwrite(TDSSOCKET * tds, const unsigned char *buffer, int len, unsigned char last)
{
    double start, now;
	const unsigned char *p = buffer;
	int rc;

	assert(tds && buffer);

	if (TDS_IS_SOCKET_INVALID(tds->s))
		return -1;

	while (p - buffer < len) {
        start = GetTimeMark();
        now = start;
		if ((rc = tds_select(tds, TDSSELWRITE, tds->query_timeout, start)) > 0) {
			int err;
			size_t remaining = len - (p - buffer);
#ifdef USE_MSGMORE
			ssize_t 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(__APPLE__) && defined(SO_NOSIGPIPE)
			ssize_t nput = send(tds->s, p, remaining, 0);
#else
			ssize_t nput = WRITESOCKET(tds->s, p, remaining);
#endif
			if (nput > 0) {
				p += nput;
				continue;
			}

			err = sock_errno;
            if (0 == nput || TDSSOCK_WOULDBLOCK(err) || err == TDSSOCK_EINTR)
				continue;

			assert(nput < 0);

			tdsdump_log(TDS_DBG_NETWORK, "send(2) failed: %d (%s)\n",
                        err, strerror(err));
            tds_report_error(tds->tds_ctx, tds, err, 20017,
                             "Write to SQL Server failed");
			tds_close_socket(tds);
			return -1;

		} else if (rc < 0) {
			int err = sock_errno;
			if (TDSSOCK_WOULDBLOCK(err)) /* shouldn't happen, but OK, retry */
				continue;
			tdsdump_log(TDS_DBG_NETWORK, "select(2) failed: %d (%s)\n",
                        err, strerror(err));
            tds_report_error(tds->tds_ctx, tds, err, 20005,
                             "select/send finished with error");
			tds_close_socket(tds);
			return -1;
		} else { /* timeout */
            now = GetTimeMark();
            if (tds->query_timeout  &&  (now - start) >= tds->query_timeout) {
                tds_client_msg(tds->tds_ctx, tds, 20002, 6, 0, 0,
                               "Writing to SQL server exceeded timeout");
                tds_close_socket(tds);
                return -1;
            }

			tdsdump_log(TDS_DBG_NETWORK, "tds_goodwrite(): timed out, asking client\n");
			switch (rc = tds_client_msg(tds->tds_ctx, tds, 20002, 6, 0, 0,
                                        "Writing to SQL server exceeded timeout")) {
			case TDS_INT_CONTINUE:
				continue;
			case TDS_INT_TIMEOUT:
				/* 
				 * "Cancel the operation ... but leave the dbproc in working condition." 
				 * We must try to send the cancel packet, else we have to abandon the dbproc.  
				 * If it can't be done, a harder error e.g. ECONNRESET will bubble up.  
				 */
				tds_send_cancel(tds);
				continue; 
			default:
			case TDS_INT_CANCEL:
				tds_close_socket(tds);
				return -1;
			}
			assert(0); /* not reached */
		}
		assert(0); /* not reached */
	}

#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;
}