emulate.c

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

C
627
字号
PRInt32 ssl_EmulateSendFile(PRFileDesc *sd, PRSendFileData *sfd,                    PRTransmitFileFlags flags, PRIntervalTime timeout){    char *       buf = NULL;    const void * buffer;    PRInt32      rv;    PRInt32      count = 0;    PRInt32      rlen;    PRInt32      buflen;    PRInt32      sendbytes;    PRInt32      readbytes;#define _SENDFILE_BUFSIZE   (16 * 1024)    buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE);    if (buf == NULL) {        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);        return -1;    }    /*     * send header, first     */    buflen = sfd->hlen;    buffer = sfd->header;    while (buflen) {        rv =  PR_Send(sd, buffer, buflen, 0, timeout);        if (rv < 0) {            /* PR_Send() has invoked PR_SetError(). */            rv = -1;            goto done;        } else {            count += rv;            buffer = (const void*) ((const char*)buffer + rv);            buflen -= rv;        }    }    /*     * send file, next     */    if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) {        rv = -1;        goto done;    }    sendbytes = sfd->file_nbytes;    if (sendbytes == 0) {        /* send entire file */        while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) {            while (rlen) {                char *bufptr = buf;                rv =  PR_Send(sd, bufptr, rlen, 0, timeout);                if (rv < 0) {                    /* PR_Send() has invoked PR_SetError(). */                    rv = -1;                    goto done;                } else {                    count += rv;                    bufptr = ((char*)bufptr + rv);                    rlen -= rv;                }            }        }        if (rlen < 0) {            /* PR_Read() has invoked PR_SetError(). */            rv = -1;            goto done;        }    } else {        readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);        while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) {            while (rlen) {                char *bufptr = buf;                rv =  PR_Send(sd, bufptr, rlen, 0, timeout);                if (rv < 0) {                    /* PR_Send() has invoked PR_SetError(). */                    rv = -1;                    goto done;                } else {                    count += rv;                    sendbytes -= rv;                    bufptr = ((char*)bufptr + rv);                    rlen -= rv;                }            }	    readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);        }        if (rlen < 0) {            /* PR_Read() has invoked PR_SetError(). */            rv = -1;            goto done;        } else if (sendbytes != 0) {            /*             * there are fewer bytes in file to send than specified             */	    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);            rv = -1;            goto done;        }    }    /*     * send trailer, last     */    buflen = sfd->tlen;    buffer = sfd->trailer;    while (buflen) {        rv =  PR_Send(sd, buffer, buflen, 0, timeout);        if (rv < 0) {            /* PR_Send() has invoked PR_SetError(). */            rv = -1;            goto done;        } else {            count += rv;            buffer = (const void*) ((const char*)buffer + rv);            buflen -= rv;        }    }    rv = count;done:    if (buf)        PR_DELETE(buf);    if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))	PR_Close(sd);    return rv;}#else /* UNIX and NT handled below *//* * _PR_UnixSendFile * *    Send file sfd->fd across socket sd. If header/trailer are specified *    they 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 * */#define SENDFILE_MMAP_CHUNK    (256 * 1024)PRInt32 ssl_EmulateSendFile(PRFileDesc *sd, PRSendFileData *sfd,                    PRTransmitFileFlags flags, PRIntervalTime timeout){    void *            addr;    PRFileMap *       mapHandle  	= NULL;    PRInt32           count 		= 0;    PRInt32           file_bytes;    PRInt32           index 		= 0;    PRInt32           len;    PRInt32           rv;    PRUint32          addr_offset;    PRUint32          file_mmap_offset;    PRUint32          mmap_len;    PRUint32          pagesize;    struct PRFileInfo info;    struct PRIOVec    iov[3];    /* Get file size */    if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) {	count = -1;	goto done;    }    if (sfd->file_nbytes && 		(info.size < (sfd->file_offset + sfd->file_nbytes))) {        /*         * there are fewer bytes in file to send than specified         */	PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);        count = -1;        goto done;    }    if (sfd->file_nbytes)        file_bytes = sfd->file_nbytes;    else        file_bytes = info.size - sfd->file_offset;#if defined(WIN32)    {        SYSTEM_INFO sysinfo;        GetSystemInfo(&sysinfo);        pagesize = sysinfo.dwAllocationGranularity;    }#else    pagesize = PR_GetPageSize();#endif    /*     * If the file is large, mmap and send the file in chunks so as     * to not consume too much virtual address space     */    if (!sfd->file_offset || !(sfd->file_offset & (pagesize - 1))) {        /*         * case 1: page-aligned file offset         */        mmap_len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);        len      = mmap_len;        file_mmap_offset = sfd->file_offset;        addr_offset = 0;    } else {        /*         * case 2: non page-aligned file offset         */        /* find previous page boundary */        file_mmap_offset = (sfd->file_offset & ~(pagesize - 1));        /* number of initial bytes to skip in mmap'd segment */        addr_offset = sfd->file_offset - file_mmap_offset;        PR_ASSERT(addr_offset > 0);        mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK);        len      = mmap_len - addr_offset;    }    /*     * Map in (part of) file. Take care of zero-length files.     */    if (len > 0) {	mapHandle = PR_CreateFileMap(sfd->fd, info.size, PR_PROT_READONLY);	if (!mapHandle) {	    count = -1;	    goto done;	}	addr = PR_MemMap(mapHandle, file_mmap_offset, mmap_len);        if (!addr) {            count = -1;            goto done;        }    }    /*     * send headers, first, followed by the file     */    if (sfd->hlen) {        iov[index].iov_base = (char *) sfd->header;        iov[index].iov_len  = sfd->hlen;        index++;    }    if (len) {        iov[index].iov_base = (char*)addr + addr_offset;        iov[index].iov_len  = len;        index++;    }    if ((file_bytes == len) && (sfd->tlen)) {        /*         * all file data is mapped in; send the trailer too         */        iov[index].iov_base = (char *) sfd->trailer;        iov[index].iov_len  = sfd->tlen;        index++;    }    rv = PR_Writev(sd, iov, index, timeout);    if (len)        PR_MemUnmap(addr, mmap_len);    if (rv < 0) {        count = -1;        goto done;    }    PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0));    file_bytes -= len;    count      += rv;    if (!file_bytes)    /* header, file and trailer are sent */	goto done;    /*     * send remaining bytes of the file, if any     */    len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);    while (len > 0) {	/*	 * Map in (part of) file	 */	file_mmap_offset = sfd->file_offset + count - sfd->hlen;	PR_ASSERT((file_mmap_offset % pagesize) == 0);	addr = PR_MemMap(mapHandle, file_mmap_offset, len);        if (!addr) {            count = -1;            goto done;        }	rv = PR_Send(sd, addr, len, 0, timeout);	PR_MemUnmap(addr, len);	if (rv < 0) {	    count = -1;	    goto done;	}	PR_ASSERT(rv == len);	file_bytes -= rv;	count      += rv;	len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);    }    PR_ASSERT(0 == file_bytes);    if (sfd->tlen) {        rv =  PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);        if (rv >= 0) {            PR_ASSERT(rv == sfd->tlen);            count += rv;        } else            count = -1;    }done:    if (mapHandle)    	PR_CloseFileMap(mapHandle);    if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))	PR_Close(sd);    return count;}#endif /* UNIX and NT */

⌨️ 快捷键说明

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