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

📄 sslsocket.c

📁 spserver 是一个实现了半同步/半异步(Half-Sync/Half-Async)和领导者/追随者(Leader/Follower) 模式的服务器框架
💻 C
📖 第 1 页 / 共 2 页
字号:
	case SSL_ALERT:
		if (alertDescription == SSL_ALERT_CLOSE_NOTIFY) {
			*status = SSLSOCKET_CLOSE_NOTIFY;
			goto readZero;
		}
		syslog( LOG_WARNING, "SSL: Closing on client alert %d: %d\n",
			alertLevel, alertDescription);
		goto readError;
/*
	We have a partial record, we need to read more data off the socket.
	If we have a completely full conn->insock buffer, we'll need to grow it
	here so that we CAN read more data when called the next time.
*/
	case SSL_PARTIAL:
		if (cp->insock.start == cp->insock.buf && cp->insock.end == 
				(cp->insock.buf + cp->insock.size)) {
			if (cp->insock.size > SSL_MAX_BUF_SIZE) {
				goto readError;
			}
			cp->insock.size *= 2;
			cp->insock.start = cp->insock.buf = 
				(unsigned char *)realloc(cp->insock.buf, cp->insock.size);
			cp->insock.end = cp->insock.buf + (cp->insock.size / 2);
		}
		if (!performRead) {
			performRead = 1;
			free(cp->inbuf.buf);
			cp->inbuf.buf = NULL;
			goto readMore;
		} else {
			goto readZero;
		}
/*
	The out buffer is too small to fit the decoded or response
	data.  Increase the size of the buffer and call decode again
*/
	case SSL_FULL:
		cp->inbuf.size *= 2;
		if (cp->inbuf.buf != (unsigned char*)buf) {
			free(cp->inbuf.buf);
			cp->inbuf.buf = NULL;
		}
		cp->inbuf.start = cp->inbuf.end = cp->inbuf.buf = 
			(unsigned char *)malloc(cp->inbuf.size);
		goto decodeMore;
	}
/*
	We consolidated some of the returns here because we must ensure
	that conn->inbuf is cleared if pointing at caller's buffer, otherwise
	it will be freed later on.
*/
readZero:
	if (cp->inbuf.buf == (unsigned char*)buf) {
		cp->inbuf.buf = NULL;
	}
	return 0;
readError:
	if (cp->inbuf.buf == (unsigned char*)buf) {
		cp->inbuf.buf = NULL;
	}
	return -1;
}

/******************************************************************************/
/*
	Example sslWrite functionality.  Takes care of encoding the input buffer
	and sending it out on the connection.

	Return codes are as follows:

	-1 return code is an error.  If a socket level error, error code is
		contained in status.  If using a non-blocking socket
		implementation the caller should check for non-fatal errors such as
		WOULD_BLOCK before closing the connection.  A zero value
		in status indicates an error with this routine.

	A positive integer return value indicates the number of bytes succesfully
		written on the connection.  Should always match the len parameter.

	0 return code indicates the write must be called again with the same
		parameters.
*/
int sslWrite(sslConn_t *cp, char *buf, int len, int *status)
{
	int		rc;

	*status = 0;
/*
	Pack the buffered socket data (if any) so that start is at zero.
*/
	if (cp->outsock.buf < cp->outsock.start) {
		if (cp->outsock.start == cp->outsock.end) {
			cp->outsock.start = cp->outsock.end = cp->outsock.buf;
		} else {
			memmove(cp->outsock.buf, cp->outsock.start, cp->outsock.end - cp->outsock.start);
			cp->outsock.end -= (cp->outsock.start - cp->outsock.buf);
			cp->outsock.start = cp->outsock.buf;
		}
	}
/*
	If there is buffered output data, the caller must be trying to
	send the same amount of data as last time.  We don't support 
	sending additional data until the original buffered request has
	been completely sent.
*/
	if (cp->outBufferCount > 0 && len != cp->outBufferCount) {
		socketAssert(len != cp->outBufferCount);
		return -1;
	}
/*
	If we don't have buffered data, encode the caller's data
*/
	if (cp->outBufferCount == 0) {
retryEncode:
		rc = matrixSslEncode(cp->ssl, (unsigned char *)buf, len, &cp->outsock);
		switch (rc) {
		case SSL_ERROR:
			return -1;
		case SSL_FULL:
			if (cp->outsock.size > SSL_MAX_BUF_SIZE) {
				return -1;
			}
			cp->outsock.size *= 2;
			cp->outsock.buf = 
				(unsigned char *)realloc(cp->outsock.buf, cp->outsock.size);
			cp->outsock.end = cp->outsock.buf + (cp->outsock.end - cp->outsock.start);
			cp->outsock.start = cp->outsock.buf;
			goto retryEncode;
		}
	}
/*
	We've got data to send.
*/
	rc = send(cp->fd, (char *)cp->outsock.start, 
		(int)(cp->outsock.end - cp->outsock.start), MSG_NOSIGNAL);
	if (rc == SOCKET_ERROR) {
		*status = getSocketError();
		return -1;
	}
	cp->outsock.start += rc;
/*
	If we wrote it all return the length, otherwise remember the number of
	bytes passed in, and return 0 to be called again later.
*/
	if (cp->outsock.start == cp->outsock.end) {
		cp->outBufferCount = 0;
		return len;
	}
	cp->outBufferCount = len;
	return 0;
}

/******************************************************************************/
/*
	Send a close alert
*/
void sslWriteClosureAlert(sslConn_t *cp)
{
	if (cp != NULL) {
		cp->outsock.start = cp->outsock.end = cp->outsock.buf;
			matrixSslEncodeClosureAlert(cp->ssl, &cp->outsock);
		setSocketNonblock(cp->fd);
		send(cp->fd, cp->outsock.start,
			(int)(cp->outsock.end - cp->outsock.start), MSG_NOSIGNAL);
	}
}

/******************************************************************************/
/*
	Server initiated rehandshake.  Builds and sends the HELLO_REQUEST message
*/
void sslRehandshake(sslConn_t *cp)
{
	matrixSslEncodeHelloRequest(cp->ssl, &cp->outsock);
	psSocketWrite(cp->fd, &cp->outsock);
	cp->outsock.start = cp->outsock.end = cp->outsock.buf;
}

/******************************************************************************/
/*
	Close a seesion that was opened with sslAccept or sslConnect and
	free the insock and outsock buffers
*/
void sslFreeConnection(sslConn_t **cpp)
{
	sslConn_t	*conn;

	conn = *cpp;
	matrixSslDeleteSession(conn->ssl);
	conn->ssl = NULL;
	if (conn->insock.buf) {
		free(conn->insock.buf);
		conn->insock.buf = NULL;
	}
	if (conn->outsock.buf) {
		free(conn->outsock.buf);
		conn->outsock.buf = NULL;
	}
	if (conn->inbuf.buf) {
		free(conn->inbuf.buf);
		conn->inbuf.buf = NULL;
	}
	free(conn);
	*cpp = NULL;
}

/******************************************************************************/
/*
	free the insock and outsock buffers
*/
void sslFreeConnectionBuffers(sslConn_t **cpp)
{
	sslConn_t	*conn;

	conn = *cpp;
	if (conn->insock.buf) {
		free(conn->insock.buf);
		conn->insock.buf = NULL;
	}
	if (conn->outsock.buf) {
		free(conn->outsock.buf);
		conn->outsock.buf = NULL;
	}
	if (conn->inbuf.buf) {
		free(conn->inbuf.buf);
		conn->inbuf.buf = NULL;
	}
}

/******************************************************************************/
/*
	Set the socket to non blocking mode and perform a few extra tricks
	to make sure the socket closes down cross platform
*/
void socketShutdown(SOCKET sock)
{
	char	buf[32];

	if (sock != INVALID_SOCKET) {
		setSocketNonblock(sock);
		if (shutdown(sock, 1) >= 0) {
			while (recv(sock, buf, sizeof(buf), 0) > 0);
		}
		closesocket(sock);
	}
}

/******************************************************************************/
/*
	Perform a blocking write of data to a socket
*/
int psSocketWrite(SOCKET sock, sslBuf_t *out)
{
	unsigned char	*s;
	int				bytes;

	s = out->start;
	while (out->start < out->end) {
		bytes = send(sock, out->start, (int)(out->end - out->start), MSG_NOSIGNAL);
		if (bytes == SOCKET_ERROR) {
			return -1;
		}
		out->start += bytes;
	}
	return (int)(out->start - s);
}

int psSocketRead(SOCKET sock, sslBuf_t **out, int *status)
{
	sslBuf_t	*local;
	char		*c;
	int			bytes;

	local = *out;
	c = local->start;

	bytes = recv(sock, c, (int)((local->buf + local->size) - local->end), MSG_NOSIGNAL);
	if (bytes == SOCKET_ERROR) {
		*status = getSocketError();
		return -1;
	}
	if (bytes == 0) {
		*status = SSLSOCKET_EOF;
		return 0;
	}
	local->end += bytes;
	return bytes;
}

/******************************************************************************/
/*
	Turn on socket blocking mode (and set CLOEXEC on LINUX for kicks).
*/
void setSocketBlock(SOCKET sock)
{
#if _WIN32
	int		block = 0;
	ioctlsocket(sock, FIONBIO, &block);
#elif LINUX
	fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) & ~O_NONBLOCK);
	fcntl(sock, F_SETFD, FD_CLOEXEC);
#endif
}

/******************************************************************************/
/*
	Turn off socket blocking mode.
*/
void setSocketNonblock(SOCKET sock)
{
#if _WIN32
	int		block = 1;
	ioctlsocket(sock, FIONBIO, &block);
#elif LINUX
	fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
#endif
}

/******************************************************************************/
/*
	Disable the Nagle algorithm for less latency in RPC
	http://www.faqs.org/rfcs/rfc896.html
	http://www.w3.org/Protocols/HTTP/Performance/Nagle/
*/
void setSocketNodelay(SOCKET sock)
{
#if _WIN32
	BOOL	tmp = TRUE;
#else
	int		tmp = 1;
#endif /* WIN32 */
	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp));
}

/******************************************************************************/
/*
	Set a breakpoint in this function to catch asserts.
	This function is called whenever an assert is triggered.  Useful because
	VisualStudio often won't show the right line of code if DebugBreak() is 
	called directly, and abort() may not be desireable on LINUX.
*/
void breakpoint()
{
	static int preventInline = 0;

	if( preventInline ) {
	}
#if _WIN32
	DebugBreak();
#elif LINUX
	abort();
#endif
}


/******************************************************************************/
/*
 	Parse an ASCII command line string.  Assumes a NULL terminated space 
 	separated list of command line arguments.  Uses this info to create an argv
 	array.
 
 	Notes:
 		handles double quotes
 		args gets hacked up!  can't pass in static string!
 		not thread safe, so should be called b4 any thread creation
 		we currently hardcode argv[0] cause none of our apps need it
 */

#if WINCE || VXWORKS

void parseCmdLineArgs(char *args, int *pargc, char ***pargv)
{
	char			**argv;
	char			*ptr;
	int				size, i;

/*
 *	Figure out the number of elements in our argv array.  
 *	We know we need an argv array of at least 3, since we have the
 *	program name, an argument, and a NULL in the array.
 */
	for (size = 3, ptr = args; ptr && *ptr != '\0'; ptr++) {
		if (isspace(*ptr)) {
			size++;
			while (isspace(*ptr)) {
				ptr++;
			}
			if (*ptr == '\0') {
				break;
			}
		}
	}
/*
 *	This is called from main, so don't use psMalloc here or
 *	all the stats will be wrong.
 */
	argv = (char**) malloc(size * sizeof(char*));
	*pargv = argv;

	for (i = 1, ptr = args; ptr && *ptr != '\0'; i++) {
		while (isspace(*ptr)) {
			ptr++;
		}
		if (*ptr == '\0')  {
			break;
		}
/*
 *		Handle double quoted arguments.  Treat everything within
 *		the double quote as one arg.
 */
		if (*ptr == '"') {
			ptr++;
			argv[i] = ptr;
			while ((*ptr != '\0') && (*ptr != '"')) {
				ptr++;
			}
		} else {
			argv[i] = ptr;
			while (*ptr != '\0' && !isspace(*ptr)) {
				ptr++;
			}
		}
		if (*ptr != '\0') {
			*ptr = '\0';
			ptr++;
		}
	}
	argv[i] = NULL;
	*pargc = i ;

	argv[0] = "PeerSec";
	for (ptr = argv[0]; *ptr; ptr++) {
		if (*ptr == '\\') {
			*ptr = '/';
		}
	}
}
#endif /* WINCE || VXWORKS */

#ifdef WINCE

/******************************************************************************/
/*
 	The following functions implement a unixlike time() function for WINCE.

	NOTE: this code is copied from the os layer in win.c to expose it for use
	in example applications.
 */

static FILETIME YearToFileTime(WORD wYear)
{	
	SYSTEMTIME sbase;
	FILETIME fbase;

	sbase.wYear         = wYear;
	sbase.wMonth        = 1;
	sbase.wDayOfWeek    = 1; //assumed
	sbase.wDay          = 1;
	sbase.wHour         = 0;
	sbase.wMinute       = 0;
	sbase.wSecond       = 0;
	sbase.wMilliseconds = 0;

	SystemTimeToFileTime( &sbase, &fbase );

	return fbase;
}

time_t time() {

	__int64 time1, time2, iTimeDiff;
	FILETIME fileTime1, fileTime2;
	SYSTEMTIME  sysTime;

/*
	Get 1970's filetime.
*/
	fileTime1 = YearToFileTime(1970);

/*
	Get the current filetime time.
*/
	GetSystemTime(&sysTime);
	SystemTimeToFileTime(&sysTime, &fileTime2);


/* 
	Stuff the 2 FILETIMEs into their own __int64s.
*/	
	time1 = fileTime1.dwHighDateTime;
	time1 <<= 32;				
	time1 |= fileTime1.dwLowDateTime;

	time2 = fileTime2.dwHighDateTime;
	time2 <<= 32;				
	time2 |= fileTime2.dwLowDateTime;

/*
	Get the difference of the two64-bit ints.

	This is he number of 100-nanosecond intervals since Jan. 1970.  So
	we divide by 10000 to get seconds.
 */
	iTimeDiff = (time2 - time1) / 10000000;
	return (int)iTimeDiff;
}
#endif /* WINCE */

/******************************************************************************/





⌨️ 快捷键说明

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