/* Read data bytes from a file. If offset is < 0, then append to the write position. function read(buffer: ByteArray, offset: Number = 0, count: Number = -1): Number */ static EjsNumber *readFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsByteArray *buffer; MprPath info; ssize offset, count, totalRead; assert(1 <= argc && argc <= 3); buffer = (EjsByteArray*) argv[0]; offset = (argc >= 2) ? ejsGetInt(ejs, argv[1]): 0; count = (argc >= 3) ? ejsGetInt(ejs, argv[2]): -1; if (fp->file == 0) { ejsThrowStateError(ejs, "File not open"); return 0; } if (!(fp->mode & EJS_FILE_READ)) { ejsThrowStateError(ejs, "File not opened for reading"); return 0; } if (offset >= buffer->size) { ejsThrowOutOfBoundsError(ejs, "Bad read offset value"); return 0; } if (offset < 0) { offset = buffer->writePosition; } else if (offset == 0) { ejsSetByteArrayPositions(ejs, buffer, 0, 0); } if (count < 0) { // TODO OPT could this be cached in fp->info if (mprGetPathInfo(fp->path, &info) == 0) { count = (int) info.size; count -= (int) mprGetFilePosition(fp->file); } else { count = ME_MAX_BUFFER; } assert(count >= 0); } totalRead = readData(ejs, fp, buffer, offset, count); if (totalRead < 0) { return 0; } else if (totalRead == 0) { return ESV(zero); } ejsSetByteArrayPositions(ejs, buffer, -1, offset + totalRead); return ejsCreateNumber(ejs, (MprNumber) totalRead); }
/* function read(buffer: ByteArray, offset: Number = 0, count: Number = -1): Number Returns a count of bytes read. Non-blocking if a callback is defined. Otherwise, blocks. Offset: -1 then read to the buffer write position, >= 0 then read to that offset count: -1 then read as much as the buffer will hold. If buffer is growable, read all content. If not growable, read the buffer size. If count >= 0, then read that number of bytes. */ static EjsNumber *http_read(Ejs *ejs, EjsHttp *hp, int argc, EjsObj **argv) { EjsByteArray *buffer; HttpConn *conn; MprOff contentLength; ssize offset, count; conn = hp->conn; buffer = (EjsByteArray*) argv[0]; offset = (argc >= 2) ? ejsGetInt(ejs, argv[1]) : 0; count = (argc >= 3) ? ejsGetInt(ejs, argv[2]): -1; if (!waitForResponseHeaders(hp)) { return 0; } contentLength = httpGetContentLength(conn); if (conn->state >= HTTP_STATE_PARSED && contentLength == hp->readCount) { /* End of input */ return ESV(null); } if (offset < 0) { offset = buffer->writePosition; } else if (offset < buffer->size) { ejsSetByteArrayPositions(ejs, buffer, offset, offset); } else { ejsThrowOutOfBoundsError(ejs, "Bad read offset value"); return 0; } if (count < 0 && !buffer->resizable) { count = buffer->size - offset; } if ((count = readHttpData(ejs, hp, count)) < 0) { assert(ejs->exception); return 0; } else if (count == 0 && conn->state > HTTP_STATE_CONTENT) { return ESV(null); } hp->readCount += count; if (ejsCopyToByteArray(ejs, buffer, offset, (char*) mprGetBufStart(hp->responseContent), count) != count) { ejsThrowMemoryError(ejs); } ejsSetByteArrayPositions(ejs, buffer, -1, buffer->writePosition + count); mprAdjustBufStart(hp->responseContent, count); mprResetBufIfEmpty(hp->responseContent); return ejsCreateNumber(ejs, (MprNumber) count); }
/* Read data bytes from a file function readBytes(count: Number = -1): ByteArray */ static EjsObj *readFileBytes(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsByteArray *result; MprPath info; ssize count, totalRead; if (argc == 0) { count = -1; } else if (argc != 1) { count = 0; ejsThrowArgError(ejs, "Bad args"); return 0; } else { assert(argc == 1 && ejsIs(ejs, argv[0], Number)); count = ejsGetInt(ejs, argv[0]); } if (fp->file == 0) { ejsThrowStateError(ejs, "File not open"); return 0; } if (!(fp->mode & EJS_FILE_READ)) { ejsThrowStateError(ejs, "File not opened for reading"); return 0; } if (count < 0) { // TODO OPT could this be cached in fp->info if (mprGetPathInfo(fp->path, &info) == 0) { count = (int) info.size; count -= (int) mprGetFilePosition(fp->file); } else { count = ME_MAX_BUFFER; } assert(count >= 0); } result = ejsCreateByteArray(ejs, count); if (result == 0) { ejsThrowMemoryError(ejs); return 0; } totalRead = readData(ejs, fp, result, 0, count); if (totalRead < 0) { ejsThrowIOError(ejs, "Cannot read from file: %s", fp->path); return 0; } else if (totalRead == 0) { return ESV(null); } ejsSetByteArrayPositions(ejs, result, 0, totalRead); return (EjsObj*) result; }
/* Connection callback */ static void webSocketNotify(HttpConn *conn, int event, int arg) { Ejs *ejs; EjsWebSocket *ws; EjsByteArray *ba; EjsAny *data; HttpPacket *packet; MprBuf *content; ssize len; if ((ws = httpGetConnContext(conn)) == 0) { return; } ejs = ws->ejs; if (!ejs->service) { /* Shutting down */ return; } switch (event) { case HTTP_EVENT_STATE: if (arg == HTTP_STATE_CONTENT) { ws->protocol = (char*) httpGetHeader(conn, "Sec-WebSocket-Protocol"); mprTrace(3, "Web socket protocol %s", ws->protocol); onWebSocketEvent(ws, HTTP_EVENT_APP_OPEN, 0, 0); } break; case HTTP_EVENT_READABLE: packet = httpGetPacket(conn->readq); content = packet->content; if (packet->type == WS_MSG_TEXT) { data = ejsCreateStringFromBytes(ejs, mprGetBufStart(content), mprGetBufLength(content)); } else { len = httpGetPacketLength(packet); assert(len > 0); if ((ba = ejsCreateByteArray(ejs, len)) == 0) { return; } memcpy(ba->value, mprGetBufStart(content), len); ejsSetByteArrayPositions(ejs, ba, -1, len); data = ba; } onWebSocketEvent(ws, event, data, packet); break; case HTTP_EVENT_ERROR: if (!ws->error && !ws->closed) { ws->error = 1; onWebSocketEvent(ws, event, 0, 0); ws->closed = 1; onWebSocketEvent(ws, HTTP_EVENT_APP_CLOSE, 0, 0); } break; case HTTP_EVENT_APP_CLOSE: if (!ws->closed) { ws->closed = 1; onWebSocketEvent(ws, event, 0, 0); } break; } }