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

📄 socket.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
字号:
/*------------------------------------------------------------------------- * * socket.c *	  Microsoft Windows Win32 Socket Functions * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.10 2005/10/25 15:15:16 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#undef socket#undef accept#undef connect#undef select#undef recv#undef send/* * Blocking socket functions implemented so they listen on both * the socket and the signal event, required for signal handling. *//* * Convert the last socket error code into errno */static voidTranslateSocketError(void){	switch (WSAGetLastError())	{		case WSANOTINITIALISED:		case WSAENETDOWN:		case WSAEINPROGRESS:		case WSAEINVAL:		case WSAESOCKTNOSUPPORT:		case WSAEFAULT:		case WSAEINVALIDPROVIDER:		case WSAEINVALIDPROCTABLE:		case WSAEMSGSIZE:			errno = EINVAL;			break;		case WSAEAFNOSUPPORT:			errno = EAFNOSUPPORT;			break;		case WSAEMFILE:			errno = EMFILE;			break;		case WSAENOBUFS:			errno = ENOBUFS;			break;		case WSAEPROTONOSUPPORT:		case WSAEPROTOTYPE:			errno = EPROTONOSUPPORT;			break;		case WSAECONNREFUSED:			errno = ECONNREFUSED;			break;		case WSAEINTR:			errno = EINTR;			break;		case WSAENOTSOCK:			errno = EBADFD;			break;		case WSAEOPNOTSUPP:			errno = EOPNOTSUPP;			break;		case WSAEWOULDBLOCK:			errno = EWOULDBLOCK;			break;		case WSAEACCES:			errno = EACCES;			break;		case WSAENOTCONN:		case WSAENETRESET:		case WSAECONNRESET:		case WSAESHUTDOWN:		case WSAECONNABORTED:		case WSAEDISCON:			errno = ECONNREFUSED;		/* ENOTCONN? */			break;		default:			ereport(NOTICE,					(errmsg_internal("Unknown win32 socket error code: %i", WSAGetLastError())));			errno = EINVAL;	}}static intpgwin32_poll_signals(void){	if (UNBLOCKED_SIGNAL_QUEUE())	{		pgwin32_dispatch_queued_signals();		errno = EINTR;		return 1;	}	return 0;}intpgwin32_waitforsinglesocket(SOCKET s, int what){	static HANDLE waitevent = INVALID_HANDLE_VALUE;	HANDLE		events[2];	int			r;	if (waitevent == INVALID_HANDLE_VALUE)	{		waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);		if (waitevent == INVALID_HANDLE_VALUE)			ereport(ERROR,					(errmsg_internal("Failed to create socket waiting event: %i", (int) GetLastError())));	}	else if (!ResetEvent(waitevent))		ereport(ERROR,				(errmsg_internal("Failed to reset socket waiting event: %i", (int) GetLastError())));	if (WSAEventSelect(s, waitevent, what) == SOCKET_ERROR)	{		TranslateSocketError();		return 0;	}	events[0] = pgwin32_signal_event;	events[1] = waitevent;	r = WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE);	if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)	{		pgwin32_dispatch_queued_signals();		errno = EINTR;		return 0;	}	if (r == WAIT_OBJECT_0 + 1)		return 1;	ereport(ERROR,			(errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));	return 0;}/* * Create a socket, setting it to overlapped and non-blocking */SOCKETpgwin32_socket(int af, int type, int protocol){	SOCKET		s;	unsigned long on = 1;	s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);	if (s == INVALID_SOCKET)	{		TranslateSocketError();		return INVALID_SOCKET;	}	if (ioctlsocket(s, FIONBIO, &on))	{		TranslateSocketError();		return INVALID_SOCKET;	}	errno = 0;	return s;}SOCKETpgwin32_accept(SOCKET s, struct sockaddr * addr, int *addrlen){	SOCKET		rs;	/*	 * Poll for signals, but don't return with EINTR, since we don't handle	 * that in pqcomm.c	 */	pgwin32_poll_signals();	rs = WSAAccept(s, addr, addrlen, NULL, 0);	if (rs == INVALID_SOCKET)	{		TranslateSocketError();		return INVALID_SOCKET;	}	return rs;}/* No signal delivery during connect. */intpgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen){	int			r;	r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL);	if (r == 0)		return 0;	if (WSAGetLastError() != WSAEWOULDBLOCK)	{		TranslateSocketError();		return -1;	}	while (pgwin32_waitforsinglesocket(s, FD_CONNECT) == 0)	{		/* Loop endlessly as long as we are just delivering signals */	}	return 0;}intpgwin32_recv(SOCKET s, char *buf, int len, int f){	WSABUF		wbuf;	int			r;	DWORD		b;	DWORD		flags = f;	if (pgwin32_poll_signals())		return -1;	wbuf.len = len;	wbuf.buf = buf;	r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);	if (r != SOCKET_ERROR && b > 0)		/* Read succeeded right away */		return b;	if (r == SOCKET_ERROR &&		WSAGetLastError() != WSAEWOULDBLOCK)	{		TranslateSocketError();		return -1;	}	/* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */	if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT) == 0)		return -1;	r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);	if (r == SOCKET_ERROR)	{		TranslateSocketError();		return -1;	}	return b;}intpgwin32_send(SOCKET s, char *buf, int len, int flags){	WSABUF		wbuf;	int			r;	DWORD		b;	if (pgwin32_poll_signals())		return -1;	wbuf.len = len;	wbuf.buf = buf;	r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);	if (r != SOCKET_ERROR && b > 0)		/* Write succeeded right away */		return b;	if (r == SOCKET_ERROR &&		WSAGetLastError() != WSAEWOULDBLOCK)	{		TranslateSocketError();		return -1;	}	/* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */	if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE) == 0)		return -1;	r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);	if (r == SOCKET_ERROR)	{		TranslateSocketError();		return -1;	}	return b;}/* * Wait for activity on one or more sockets. * While waiting, allow signals to run * * NOTE! Currently does not implement exceptfds check, * since it is not used in postgresql! */intpgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout){	WSAEVENT	events[FD_SETSIZE * 2]; /* worst case is readfds totally										 * different from writefds, so										 * 2*FD_SETSIZE sockets */	SOCKET		sockets[FD_SETSIZE * 2];	int			numevents = 0;	int			i;	int			r;	DWORD		timeoutval = WSA_INFINITE;	FD_SET		outreadfds;	FD_SET		outwritefds;	int			nummatches = 0;	Assert(exceptfds == NULL);	if (pgwin32_poll_signals())		return -1;	FD_ZERO(&outreadfds);	FD_ZERO(&outwritefds);	/*	 * Write FDs are different in the way that it is only flagged by	 * WSASelectEvent() if we have tried to write to them first. So try an	 * empty write	 */	if (writefds)	{		for (i = 0; i < writefds->fd_count; i++)		{			char		c;			WSABUF		buf;			DWORD		sent;			buf.buf = &c;			buf.len = 0;			r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);			if (r == 0)			/* Completed - means things are fine! */				FD_SET(writefds->fd_array[i], &outwritefds);			else			{					/* Not completed */				if (WSAGetLastError() != WSAEWOULDBLOCK)					/*					 * Not completed, and not just "would block", so an error					 * occured					 */					FD_SET(writefds->fd_array[i], &outwritefds);			}		}		if (outwritefds.fd_count > 0)		{			memcpy(writefds, &outwritefds, sizeof(fd_set));			if (readfds)				FD_ZERO(readfds);			return outwritefds.fd_count;		}	}	/* Now set up for an actual select */	if (timeout != NULL)	{		/* timeoutval is in milliseconds */		timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;	}	if (readfds != NULL)	{		for (i = 0; i < readfds->fd_count; i++)		{			events[numevents] = WSACreateEvent();			sockets[numevents] = readfds->fd_array[i];			numevents++;		}	}	if (writefds != NULL)	{		for (i = 0; i < writefds->fd_count; i++)		{			if (!readfds ||				!FD_ISSET(writefds->fd_array[i], readfds))			{				/* If the socket is not in the read list */				events[numevents] = WSACreateEvent();				sockets[numevents] = writefds->fd_array[i];				numevents++;			}		}	}	for (i = 0; i < numevents; i++)	{		int			flags = 0;		if (readfds && FD_ISSET(sockets[i], readfds))			flags |= FD_READ | FD_ACCEPT | FD_CLOSE;		if (writefds && FD_ISSET(sockets[i], writefds))			flags |= FD_WRITE | FD_CLOSE;		if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR)		{			TranslateSocketError();			for (i = 0; i < numevents; i++)				WSACloseEvent(events[i]);			return -1;		}	}	events[numevents] = pgwin32_signal_event;	r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);	if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))	{		/*		 * We scan all events, even those not signalled, in case more than one		 * event has been tagged but Wait.. can only return one.		 */		WSANETWORKEVENTS resEvents;		for (i = 0; i < numevents; i++)		{			ZeroMemory(&resEvents, sizeof(resEvents));			if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR)				ereport(FATAL,						(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));			/* Read activity? */			if (readfds && FD_ISSET(sockets[i], readfds))			{				if ((resEvents.lNetworkEvents & FD_READ) ||					(resEvents.lNetworkEvents & FD_ACCEPT) ||					(resEvents.lNetworkEvents & FD_CLOSE))				{					FD_SET(sockets[i], &outreadfds);					nummatches++;				}			}			/* Write activity? */			if (writefds && FD_ISSET(sockets[i], writefds))			{				if ((resEvents.lNetworkEvents & FD_WRITE) ||					(resEvents.lNetworkEvents & FD_CLOSE))				{					FD_SET(sockets[i], &outwritefds);					nummatches++;				}			}		}	}	/* Clean up all handles */	for (i = 0; i < numevents; i++)	{		WSAEventSelect(sockets[i], events[i], 0);		WSACloseEvent(events[i]);	}	if (r == WSA_WAIT_TIMEOUT)	{		if (readfds)			FD_ZERO(readfds);		if (writefds)			FD_ZERO(writefds);		return 0;	}	if (r == WAIT_OBJECT_0 + numevents)	{		pgwin32_dispatch_queued_signals();		errno = EINTR;		if (readfds)			FD_ZERO(readfds);		if (writefds)			FD_ZERO(writefds);		return -1;	}	/* Overwrite socket sets with our resulting values */	if (readfds)		memcpy(readfds, &outreadfds, sizeof(fd_set));	if (writefds)		memcpy(writefds, &outwritefds, sizeof(fd_set));	return nummatches;}/* * Return win32 error string, since strerror can't * handle winsock codes */static char wserrbuf[256];const char *pgwin32_socket_strerror(int err){	static HANDLE handleDLL = INVALID_HANDLE_VALUE;	if (handleDLL == INVALID_HANDLE_VALUE)	{		handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);		if (handleDLL == NULL)			ereport(FATAL,					(errmsg_internal("Failed to load netmsg.dll: %i", (int) GetLastError())));	}	ZeroMemory(&wserrbuf, sizeof(wserrbuf));	if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,					  handleDLL,					  err,					  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),					  wserrbuf,					  sizeof(wserrbuf) - 1,					  NULL) == 0)	{		/* Failed to get id */		sprintf(wserrbuf, "Unknown winsock error %i", err);	}	return wserrbuf;}

⌨️ 快捷键说明

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