示例#1
0
/*  
    Populate a packet with file data. Return the number of bytes read or a negative error code. Will not return with
    a short read.
 */
static ssize readFileData(HttpQueue *q, HttpPacket *packet, MprOff pos, ssize size)
{
    HttpConn    *conn;
    HttpTx      *tx;
    ssize       nbytes;

    conn = q->conn;
    tx = conn->tx;

    if (packet->content == 0 && (packet->content = mprCreateBuf(size, -1)) == 0) {
        return MPR_ERR_MEMORY;
    }
    assert(size <= mprGetBufSpace(packet->content));    
    if (pos >= 0) {
        mprSeekFile(tx->file, SEEK_SET, pos);
    }
    if ((nbytes = mprReadFile(tx->file, mprGetBufStart(packet->content), size)) != size) {
        /*  
            As we may have sent some data already to the client, the only thing we can do is abort and hope the client 
            notices the short data.
         */
        httpError(conn, HTTP_CODE_SERVICE_UNAVAILABLE, "Cannot read file %s", tx->filename);
        return MPR_ERR_CANT_READ;
    }
    mprAdjustBufEnd(packet->content, nbytes);
    packet->esize -= nbytes;
    assert(packet->esize == 0);
    return nbytes;
}
示例#2
0
文件: ejsFile.c 项目: coordcn/ejs
/*  
    Index into a file and extract a byte. This is random access reading.
 */
static EjsNumber *getFileProperty(Ejs *ejs, EjsFile *fp, int slotNum)
{
    MprOff  offset;
    int     c;

    if (!(fp->mode & EJS_FILE_OPEN)) {
        ejsThrowIOError(ejs, "File is not open");
        return 0;
    }
#if KEEP
    if (fp->mode & EJS_FILE_READ) {
        if (slotNum >= fp->info.size) {
            ejsThrowOutOfBoundsError(ejs, "Bad file index");
            return 0;
        }
    }
    if (slotNum < 0) {
        ejsThrowOutOfBoundsError(ejs, "Bad file index");
        return 0;
    }
#endif

#if ME_CC_MMU && FUTURE
    //  must check against mapped size here.
    c = fp->mapped[slotNum];
#else
    offset = mprSeekFile(fp->file, SEEK_CUR, 0);
    if (offset != slotNum) {
        if (mprSeekFile(fp->file, SEEK_SET, slotNum) != slotNum) {
            ejsThrowIOError(ejs, "Cannot seek to file offset");
            return 0;
        }
    }
    c = mprPeekFileChar(fp->file);
    if (c < 0) {
        ejsThrowIOError(ejs, "Cannot read file");
        return 0;
    }
#endif
    return ejsCreateNumber(ejs, c);
}
示例#3
0
文件: output.c 项目: WeiY/appweb-4
/*
    Event callback. Invoked for incoming web socket messages and other events of interest.
    We're interested in the WRITABLE event.
 */
static void output_callback(HttpConn *conn, int event, int arg)
{
    Output      *output;
    ssize       len, wrote;
    int         flags, type;
    char        buf[MPR_BUFSIZE];

    /*
        Get a writable event when the socket can absorb more data
     */
    if (event == HTTP_EVENT_WRITABLE) {
        output = getData();
        do {
            if ((len = mprReadFile(output->file, buf, sizeof(buf))) > 0) {

                /*
                    Set the HTTP_MORE flag on every write except the last. This means each write is sent as
                    a separate frame. The first frame has the type of WS_MSG_TEXT, all others must be 
                    continuation frames.
                 */
                flags = HTTP_NON_BLOCK;
                if ((output->written + len) < output->info.size) {
                    flags |= HTTP_MORE;
                }
                type = output->written == 0 ? WS_MSG_TEXT : WS_MSG_CONT;
                /*
                    Send the next chunk as a WebSockets frame using a non-blocking write. 
                    This may return having written only a portion of the requested data.
                 */
                if ((wrote = httpSendBlock(conn, type, buf, len, flags)) < 0) {
                    httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot send message of %d bytes", len);
                    return;
                }
                output->written += wrote;
                if (wrote < len) {
                    /* Reposition if the send returned having written less than requested */
                    mprSeekFile(output->file, SEEK_CUR, wrote - len);
                    break;
                }
            } else {
                httpSendClose(conn, WS_STATUS_OK, "OK");
                break;
            }
        } while (len > 0);

    } else if (event == HTTP_EVENT_APP_CLOSE) {
        mprLog(0, "output.c: close event. Status status %d, orderly closed %d, reason %s", arg,
        httpWebSocketOrderlyClosed(conn), httpGetWebSocketCloseReason(conn));

    } else if (event == HTTP_EVENT_ERROR) {
        mprLog(0, "output.c: error event");
    }
}
示例#4
0
文件: ejsFile.c 项目: coordcn/ejs
/*  
    Seek to a new location in the file and set the File marker to a new read/write position.
    function set position(value: Number): void
 */
static EjsObj *setFilePosition(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv)
{
    MprOff      pos;

    assert(argc == 1 && ejsIs(ejs, argv[0], Number));
    pos = ejsGetInt(ejs, argv[0]);

    if (fp->file == 0) {
        ejsThrowStateError(ejs, "File not opened");
        return 0;
    }
    pos = ejsGetInt(ejs, argv[0]);
    if (mprSeekFile(fp->file, SEEK_SET, pos) != pos) {
        ejsThrowIOError(ejs, "Cannot seek to %Ld", pos);
    }
    return 0;
}
示例#5
0
/*
    The incoming callback is invoked to receive body data 
 */
static void incomingFile(HttpQueue *q, HttpPacket *packet)
{
    HttpConn    *conn;
    HttpTx      *tx;
    HttpRx      *rx;
    HttpRange   *range;
    MprBuf      *buf;
    MprFile     *file;
    ssize       len;

    conn = q->conn;
    tx = conn->tx;
    rx = conn->rx;
    file = (MprFile*) q->queueData;
    
    if (file == 0) {
        /*  Not a PUT so just ignore the incoming data.  */
        return;
    }
    if (httpGetPacketLength(packet) == 0) {
        /* End of input */
        if (file) {
            mprCloseFile(file);
        }
        q->queueData = 0;
        if (!tx->etag) {
            /* Set the etag for caching in the client */
            mprGetPathInfo(tx->filename, &tx->fileInfo);
            tx->etag = sfmt("\"%llx-%llx-%llx\"", tx->fileInfo.inode, tx->fileInfo.size, tx->fileInfo.mtime);
        }
        return;
    }
    buf = packet->content;
    len = mprGetBufLength(buf);
    assert(len > 0);

    range = rx->inputRange;
    if (range && mprSeekFile(file, SEEK_SET, range->start) != range->start) {
        httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot seek to range start to %lld", range->start);

    } else if (mprWriteFile(file, mprGetBufStart(buf), len) != len) {
        httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot PUT to %s", tx->filename);
    }
}
示例#6
0
/*  
    This is called to setup for a HTTP PUT request. It is called before receiving the post data via incomingFileData
 */
static void handlePutRequest(HttpQueue *q)
{
    HttpConn    *conn;
    HttpTx      *tx;
    MprFile     *file;
    char        *path;

    assure(q->pair->queueData == 0);

    conn = q->conn;
    tx = conn->tx;
    assure(tx->filename);
    assure(tx->fileInfo.checked);

    path = tx->filename;
    if (tx->outputRanges) {
        /*  
            Open an existing file with fall-back to create
         */
        if ((file = mprOpenFile(path, O_BINARY | O_WRONLY, 0644)) == 0) {
            if ((file = mprOpenFile(path, O_CREAT | O_TRUNC | O_BINARY | O_WRONLY, 0644)) == 0) {
                httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create the put URI");
                return;
            }
        } else {
            mprSeekFile(file, SEEK_SET, 0);
        }
    } else {
        if ((file = mprOpenFile(path, O_CREAT | O_TRUNC | O_BINARY | O_WRONLY, 0644)) == 0) {
            httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create the put URI");
            return;
        }
    }
    if (!tx->fileInfo.isReg) {
        httpSetHeader(conn, "Location", conn->rx->uri);
    }
    httpSetStatus(conn, tx->fileInfo.isReg ? HTTP_CODE_NO_CONTENT : HTTP_CODE_CREATED);
    q->pair->queueData = (void*) file;
}