diff nspr/pr/src/io/priometh.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nspr/pr/src/io/priometh.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,596 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "primpl.h"
+
+#include <string.h>
+
+/*****************************************************************************/
+/************************** Invalid I/O method object ************************/
+/*****************************************************************************/
+PRIOMethods _pr_faulty_methods = {
+    (PRDescType)0,
+    (PRCloseFN)_PR_InvalidStatus,
+    (PRReadFN)_PR_InvalidInt,
+    (PRWriteFN)_PR_InvalidInt,
+    (PRAvailableFN)_PR_InvalidInt,
+    (PRAvailable64FN)_PR_InvalidInt64,
+    (PRFsyncFN)_PR_InvalidStatus,
+    (PRSeekFN)_PR_InvalidInt,
+    (PRSeek64FN)_PR_InvalidInt64,
+    (PRFileInfoFN)_PR_InvalidStatus,
+    (PRFileInfo64FN)_PR_InvalidStatus,
+    (PRWritevFN)_PR_InvalidInt,        
+    (PRConnectFN)_PR_InvalidStatus,        
+    (PRAcceptFN)_PR_InvalidDesc,        
+    (PRBindFN)_PR_InvalidStatus,        
+    (PRListenFN)_PR_InvalidStatus,        
+    (PRShutdownFN)_PR_InvalidStatus,    
+    (PRRecvFN)_PR_InvalidInt,        
+    (PRSendFN)_PR_InvalidInt,        
+    (PRRecvfromFN)_PR_InvalidInt,    
+    (PRSendtoFN)_PR_InvalidInt,        
+    (PRPollFN)_PR_InvalidInt16,
+    (PRAcceptreadFN)_PR_InvalidInt,   
+    (PRTransmitfileFN)_PR_InvalidInt, 
+    (PRGetsocknameFN)_PR_InvalidStatus,    
+    (PRGetpeernameFN)_PR_InvalidStatus,    
+    (PRReservedFN)_PR_InvalidInt,    
+    (PRReservedFN)_PR_InvalidInt,    
+    (PRGetsocketoptionFN)_PR_InvalidStatus,
+    (PRSetsocketoptionFN)_PR_InvalidStatus,
+    (PRSendfileFN)_PR_InvalidInt, 
+    (PRConnectcontinueFN)_PR_InvalidStatus,
+    (PRReservedFN)_PR_InvalidInt,
+    (PRReservedFN)_PR_InvalidInt,
+    (PRReservedFN)_PR_InvalidInt,
+    (PRReservedFN)_PR_InvalidInt
+};
+
+PRIntn _PR_InvalidInt(void)
+{
+    PR_ASSERT(!"I/O method is invalid");
+    PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+    return -1;
+}  /* _PR_InvalidInt */
+
+PRInt16 _PR_InvalidInt16(void)
+{
+    PR_ASSERT(!"I/O method is invalid");
+    PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+    return -1;
+}  /* _PR_InvalidInt */
+
+PRInt64 _PR_InvalidInt64(void)
+{
+    PRInt64 rv;
+    LL_I2L(rv, -1);
+    PR_ASSERT(!"I/O method is invalid");
+    PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+    return rv;
+}  /* _PR_InvalidInt */
+
+/*
+ * An invalid method that returns PRStatus
+ */
+
+PRStatus _PR_InvalidStatus(void)
+{
+    PR_ASSERT(!"I/O method is invalid");
+    PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+    return PR_FAILURE;
+}  /* _PR_InvalidDesc */
+
+/*
+ * An invalid method that returns a pointer
+ */
+
+PRFileDesc *_PR_InvalidDesc(void)
+{
+    PR_ASSERT(!"I/O method is invalid");
+    PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+    return NULL;
+}  /* _PR_InvalidDesc */
+
+PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file)
+{
+    return file->methods->file_type;
+}
+
+PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd)
+{
+    return (fd->methods->close)(fd);
+}
+
+PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+	return((fd->methods->read)(fd,buf,amount));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+	return((fd->methods->write)(fd,buf,amount));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
+{
+	return((fd->methods->seek)(fd, offset, whence));
+}
+
+PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
+{
+	return((fd->methods->seek64)(fd, offset, whence));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd)
+{
+	return((fd->methods->available)(fd));
+}
+
+PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd)
+{
+	return((fd->methods->available64)(fd));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info)
+{
+	return((fd->methods->fileInfo)(fd, info));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
+{
+	return((fd->methods->fileInfo64)(fd, info));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd)
+{
+	return((fd->methods->fsync)(fd));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Connect(
+    PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+	return((fd->methods->connect)(fd,addr,timeout));
+}
+
+PR_IMPLEMENT(PRStatus) PR_ConnectContinue(
+    PRFileDesc *fd, PRInt16 out_flags)
+{
+	return((fd->methods->connectcontinue)(fd,out_flags));
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr,
+PRIntervalTime timeout)
+{
+	return((fd->methods->accept)(fd,addr,timeout));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr)
+{
+	return((fd->methods->bind)(fd,addr));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
+{
+	return((fd->methods->shutdown)(fd,how));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog)
+{
+	return((fd->methods->listen)(fd,backlog));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+PRIntn flags, PRIntervalTime timeout)
+{
+	return((fd->methods->recv)(fd,buf,amount,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+PRIntn flags, PRIntervalTime timeout)
+{
+	return((fd->methods->send)(fd,buf,amount,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov,
+PRInt32 iov_size, PRIntervalTime timeout)
+{
+    if (iov_size > PR_MAX_IOVECTOR_SIZE)
+    {
+        PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+        return -1;
+    }
+	return((fd->methods->writev)(fd,iov,iov_size,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
+{
+	return((fd->methods->recvfrom)(fd,buf,amount,flags,addr,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_SendTo(
+    PRFileDesc *fd, const void *buf, PRInt32 amount,
+    PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+	return((fd->methods->sendto)(fd,buf,amount,flags,addr,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_TransmitFile(
+    PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen,
+    PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+	return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_AcceptRead(
+    PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+    void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+	return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
+{
+	return((fd->methods->getsockname)(fd,addr));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
+{
+	return((fd->methods->getpeername)(fd,addr));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetSocketOption(
+    PRFileDesc *fd, PRSocketOptionData *data)
+{
+	return((fd->methods->getsocketoption)(fd, data));
+}
+
+PR_IMPLEMENT(PRStatus) PR_SetSocketOption(
+    PRFileDesc *fd, const PRSocketOptionData *data)
+{
+	return((fd->methods->setsocketoption)(fd, data));
+}
+
+PR_IMPLEMENT(PRInt32) PR_SendFile(
+	PRFileDesc *sd, PRSendFileData *sfd,
+	PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+	return((sd->methods->sendfile)(sd,sfd,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead(
+    PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+    void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+    PRInt32 rv = -1;
+    PRNetAddr remote;
+    PRFileDesc *accepted = NULL;
+
+    /*
+    ** The timeout does not apply to the accept portion of the
+    ** operation - it waits indefinitely.
+    */
+    accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT);
+    if (NULL == accepted) return rv;
+
+    rv = PR_Recv(accepted, buf, amount, 0, timeout);
+    if (rv >= 0)
+    {
+        /* copy the new info out where caller can see it */
+#define AMASK ((PRPtrdiff)7)  /* mask for alignment of PRNetAddr */
+        PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK;
+        *raddr = (PRNetAddr*)(aligned & ~AMASK);
+        memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
+        *nd = accepted;
+        return rv;
+    }
+
+    PR_Close(accepted);
+    return rv;
+}
+
+/*
+ * PR_EmulateSendFile
+ *
+ *    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
+ *
+ */
+
+#if defined(XP_UNIX) || defined(WIN32)
+
+/*
+ * An implementation based on memory-mapped files
+ */
+
+#define SENDFILE_MMAP_CHUNK	(256 * 1024)
+
+PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
+    PRFileDesc *sd, PRSendFileData *sfd,
+    PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+    PRInt32 rv, count = 0;
+    PRInt32 len, file_bytes, index = 0;
+    PRFileInfo info;
+    PRIOVec iov[3];
+    PRFileMap *mapHandle = NULL;
+    void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */
+    PRUint32 file_mmap_offset, alignment;
+    PRInt64 zero64;
+    PROffset64 file_mmap_offset64;
+    PRUint32 addr_offset, mmap_len;
+
+    /* 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;
+
+    alignment = PR_GetMemMapAlignment();
+
+    /* number of initial bytes to skip in mmap'd segment */
+    addr_offset = sfd->file_offset % alignment;
+
+    /* find previous mmap alignment boundary */
+    file_mmap_offset = sfd->file_offset - addr_offset;
+
+    /*
+     * If the file is large, mmap and send the file in chunks so as
+     * to not consume too much virtual address space
+     */
+    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) {
+        LL_I2L(zero64, 0);
+        mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY);
+        if (!mapHandle) {
+            count = -1;
+            goto done;
+        }
+        LL_I2L(file_mmap_offset64, file_mmap_offset);
+        addr = PR_MemMap(mapHandle, file_mmap_offset64, 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 % alignment) == 0);
+
+        LL_I2L(file_mmap_offset64, file_mmap_offset);
+        addr = PR_MemMap(mapHandle, file_mmap_offset64, 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;
+}
+
+#else
+
+PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
+    PRFileDesc *sd, PRSendFileData *sfd,
+    PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+    PRInt32 rv, count = 0;
+    PRInt32 rlen;
+    const void * buffer;
+    PRInt32 buflen;
+    PRInt32 sendbytes, readbytes;
+    char *buf;
+
+#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;
+}
+
+#endif
+
+/* priometh.c */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)