emulate.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 627 行 · 第 1/2 页

C
627
字号
/* * Functions that emulate PR_AcceptRead and PR_TransmitFile for SSL sockets. * Each Layered NSPR protocol (like SSL) must unfortunately contain its  * own implementation of these functions.  This code was taken from NSPR. * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. * * $Id: emulate.c,v 1.2 2000/05/18 01:32:53 nelsonb%netscape.com Exp $ */#include "nspr.h"#if defined( XP_UNIX )#include <fcntl.h>#endif#if defined(WIN32)#include <windef.h>#include <winbase.h>#endif#include <string.h>#define AMASK 7	/* mask for alignment of PRNetAddr *//* * _PR_EmulateAcceptRead * *  Accept an incoming connection on sd, set *nd to point to the *  newly accepted socket, read 'amount' bytes from the accepted *  socket. * *  buf is a buffer of length = amount + (2 * sizeof(PRNetAddr)) + 32 *  *raddr points to the PRNetAddr of the accepted connection upon *  return * *  return number of bytes read or -1 on error * */PRInt32 ssl_EmulateAcceptRead(	PRFileDesc *   sd, 			PRFileDesc **  nd,			PRNetAddr **   raddr, 			void *         buf, 			PRInt32        amount, 			PRIntervalTime timeout){    PRFileDesc *   newsockfd;    PRInt32        rv;    PRNetAddr      remote;    if (!(newsockfd = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT))) {	return -1;    }    rv = PR_Recv(newsockfd, buf, amount, 0, timeout);    if (rv >= 0) {	ptrdiff_t pNetAddr = (((ptrdiff_t)buf) + amount + AMASK) & ~AMASK;	*nd = newsockfd;	*raddr = (PRNetAddr *)pNetAddr;	memcpy((void *)pNetAddr, &remote, sizeof(PRNetAddr));	return rv;    }    PR_Close(newsockfd);    return -1;}#if !defined( XP_UNIX ) && !defined( WIN32 )/* * _PR_EmulateTransmitFile * *  Send file fd across socket sd. If headers is non-NULL, 'hlen' *  bytes of headers is sent before sending the file. * *  PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * *  return number of bytes sent or -1 on error * */#define _TRANSMITFILE_BUFSIZE	(16 * 1024)PRInt32 ssl_EmulateTransmitFile(    PRFileDesc *        sd, 			    PRFileDesc *        fd,			    const void *        headers, 			    PRInt32             hlen, 			    PRTransmitFileFlags flags,			    PRIntervalTime      timeout){    char *  buf 	= NULL;    PRInt32 count 	= 0;    PRInt32 rlen;    PRInt32 rv;    buf = PR_MALLOC(_TRANSMITFILE_BUFSIZE);    if (buf == NULL) {	PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);	return -1;    }    /*     * send headers, first     */    while (hlen) {	rv =  PR_Send(sd, headers, hlen, 0, timeout);	if (rv < 0) {	    /* PR_Send() has invoked PR_SetError(). */	    rv = -1;	    goto done;	} 	count += rv;	headers = (const void*) ((const char*)headers + rv);	hlen -= rv;    }    /*     * send file, next     */    while ((rlen = PR_Read(fd, buf, _TRANSMITFILE_BUFSIZE)) > 0) {	while (rlen) {	    char *bufptr = buf;	    rv =  PR_Send(sd, bufptr, rlen,0,PR_INTERVAL_NO_TIMEOUT);	    if (rv < 0) {		/* PR_Send() has invoked PR_SetError(). */		rv = -1;		goto done;	    } 	    count += rv;	    bufptr = ((char*)bufptr + rv);	    rlen -= rv;	}    }    if (rlen == 0) {	/*	 * end-of-file	 */	if (flags & PR_TRANSMITFILE_CLOSE_SOCKET)	    PR_Close(sd);	rv = count;    } else {	PR_ASSERT(rlen < 0);	/* PR_Read() has invoked PR_SetError(). */	rv = -1;    }done:    if (buf)	PR_DELETE(buf);    return rv;}#else#define TRANSMITFILE_MMAP_CHUNK (256 * 1024)/* * _PR_UnixTransmitFile * *  Send file fd across socket sd. If headers is non-NULL, 'hlen' *  bytes of headers is sent before sending the file. * *  PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * *  return number of bytes sent or -1 on error * */PRInt32 ssl_EmulateTransmitFile(    PRFileDesc *        sd, 			    PRFileDesc *        fd,			    const void *        headers, 			    PRInt32             hlen, 			    PRTransmitFileFlags flags,			    PRIntervalTime      timeout){    void *            addr;    PRFileMap *       mapHandle = NULL;    PRInt32           count     = 0;    PRInt32           index     = 0;    PRInt32           len	= 0;    PRInt32           rv;    struct PRFileInfo info;    struct PRIOVec    iov[2];    /* Get file size */    if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info)) {	count = -1;	goto done;    }    if (hlen) {	iov[index].iov_base = (char *) headers;	iov[index].iov_len  = hlen;	index++;    }    if (info.size > 0) {	mapHandle = PR_CreateFileMap(fd, info.size, PR_PROT_READONLY);	if (mapHandle == NULL) {	    count = -1;	    goto done;	}	/*	 * If the file is large, mmap and send the file in chunks so as	 * to not consume too much virtual address space	 */	len = PR_MIN(info.size , TRANSMITFILE_MMAP_CHUNK );	/*	 * Map in (part of) file. Take care of zero-length files.	 */	if (len) {	    addr = PR_MemMap(mapHandle, 0, len);	    if (addr == NULL) {		count = -1;		goto done;	    }	}	iov[index].iov_base = (char*)addr;	iov[index].iov_len = len;	index++;    }    if (!index)    	goto done;    rv = PR_Writev(sd, iov, index, timeout);    if (len) {	PR_MemUnmap(addr, len);    }    if (rv >= 0) {	PR_ASSERT(rv == hlen + len);	info.size -= len;	count     += rv;    } else {	count = -1;	goto done;    }    /*     * send remaining bytes of the file, if any     */    len = PR_MIN(info.size , TRANSMITFILE_MMAP_CHUNK );    while (len > 0) {	/*	 * Map in (part of) file	 */	PR_ASSERT((count - hlen) % TRANSMITFILE_MMAP_CHUNK == 0);	addr = PR_MemMap(mapHandle, count - hlen, len);	if (addr == NULL) {	    count = -1;	    goto done;	}	rv =  PR_Send(sd, addr, len, 0, timeout);	PR_MemUnmap(addr, len);	if (rv >= 0) {	    PR_ASSERT(rv == len);	    info.size -= rv;	    count     += rv;	    len = PR_MIN(info.size , TRANSMITFILE_MMAP_CHUNK );	} else {	    count = -1;	    goto done;	}    }done:    if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))	PR_Close(sd);    if (mapHandle != NULL)    	PR_CloseFileMap(mapHandle);    return count;}#endif  /* XP_UNIX */#if !defined( XP_UNIX ) && !defined( WIN32 )/* * _PR_EmulateSendFile * *  Send file sfd->fd across socket sd. The header and trailer buffers *  specified in the 'sfd' argument are sent before and after the file, *  respectively. * *  PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * *  return number of bytes sent or -1 on error * */

⌨️ 快捷键说明

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