Example #1
0
NPT_Result
NPT_StreamToStreamCopy(NPT_InputStream&  from,
                       NPT_OutputStream& to,
                       NPT_Position      offset /* = 0 */,
                       NPT_Size          size   /* = 0, 0 means the entire stream */)
{
    // seek into the input if required
    if (offset) {
        NPT_CHECK(from.Seek(offset));
    }

    // allocate a buffer for the transfer
    NPT_Size bytes_transfered = 0;
    NPT_Byte* buffer = new NPT_Byte[NPT_STREAM_COPY_BUFFER_SIZE];
    NPT_Result result = NPT_SUCCESS;
    if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY;

    // copy until an error occurs or the end of stream is reached
    for (;;) {
        // read some data
        NPT_Size   bytes_to_read = NPT_STREAM_COPY_BUFFER_SIZE;
        NPT_Size   bytes_read = 0;
        if (size) {
            // a max size was specified
            if (bytes_to_read > size-bytes_transfered) {
                bytes_to_read = size-bytes_transfered;
            }
        }
        result = from.Read(buffer, bytes_to_read, &bytes_read);
        if (NPT_FAILED(result)) {
            if (result == NPT_ERROR_EOS) result = NPT_SUCCESS;
            break;
        }
        if (bytes_read == 0) continue;

        // write the data
        result = to.WriteFully(buffer, bytes_read);
        if (NPT_FAILED(result)) break;

        // update the counts
        if (size) {
            bytes_transfered += bytes_read;
            if (bytes_transfered >= size) break;
        }
    }

    // free the buffer and return
    delete[] buffer;
    return result;
}
Example #2
0
/*----------------------------------------------------------------------
|   PLT_HttpServerSocketTask::SendResponseBody
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpServerSocketTask::SendResponseBody(NPT_HttpResponse* response,
                                           NPT_OutputStream& output_stream)
{
    NPT_HttpEntity* entity = response->GetEntity();
    if (!entity) return NPT_SUCCESS;

    NPT_InputStreamReference body_stream;
    entity->GetInputStream(body_stream);
    if (body_stream.IsNull()) return NPT_SUCCESS;

    // check for chunked transfer encoding
    NPT_OutputStream* dest = &output_stream;
    if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
        dest = new NPT_HttpChunkedOutputStream(output_stream);
    }

    // send body
    NPT_LOG_FINE_1("sending body stream, %lld bytes", entity->GetContentLength());
    NPT_LargeSize bytes_written = 0;
    NPT_Result result = NPT_StreamToStreamCopy(*body_stream, *dest, 0, entity->GetContentLength(), &bytes_written); /* passing 0 if content length is unknown will read until nothing is left */
    if (NPT_FAILED(result)) {
        NPT_LOG_FINE_3("body stream only partially sent, %lld bytes (%d:%s)",
                       bytes_written,
                       result,
                       NPT_ResultText(result));
    }

    // flush to write out any buffered data left in chunked output if used
    dest->Flush();

    // cleanup (this will send zero size chunk followed by CRLF)
    if (dest != &output_stream) delete dest;

    return result;
}
 NPT_Result SendResponseBody(const NPT_HttpRequestContext& /*context*/,
                             NPT_HttpResponse&             /*response*/,
                             NPT_OutputStream&             output) {
     output.WriteString("<html><body>\r\n");
     for (unsigned int i=0; i<30; i++) {
         output.WriteString("Line ");
         output.WriteString(NPT_String::FromInteger(i).GetChars());
         output.WriteString("\r\n");
         output.Flush();
         NPT_System::Sleep(NPT_TimeInterval(0.2f));
     }
     output.WriteString("</body></html>\r\n");
     return NPT_SUCCESS;
 }
Example #4
0
/*----------------------------------------------------------------------
|   PLT_HttpServerSocketTask::SendResponseHeaders
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpServerSocketTask::SendResponseHeaders(NPT_HttpResponse* response,
                                              NPT_OutputStream& output_stream,
                                              bool&             keep_alive)
{
    // add any headers that may be missing
    NPT_HttpHeaders& headers = response->GetHeaders();

    // get the request entity to set additional headers
    NPT_InputStreamReference body_stream;
    NPT_HttpEntity* entity = response->GetEntity();
    if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
        // set the content length if known
        if (entity->ContentLengthIsKnown()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH,
                              NPT_String::FromIntegerU(entity->GetContentLength()));
        }

        // content type
        NPT_String content_type = entity->GetContentType();
        if (!content_type.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
        }

        // content encoding
        NPT_String content_encoding = entity->GetContentEncoding();
        if (!content_encoding.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
        }
        
        // transfer encoding
        const NPT_String& transfer_encoding = entity->GetTransferEncoding();
        if (!transfer_encoding.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING, transfer_encoding);
        }
        
    } else if (!headers.GetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH)) {
        // force content length to 0 if there is no message body
		// (necessary for 1.1 or 1.0 with keep-alive connections)
        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
    }

    const NPT_String* content_length  = headers.GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH);
    const NPT_String* transfer_encoding  = headers.GetHeaderValue(NPT_HTTP_HEADER_TRANSFER_ENCODING);
    const NPT_String* connection_header  = headers.GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
    if (keep_alive) {
        if (connection_header && connection_header->Compare("close") == 0) {
            keep_alive = false;
        } else {
            // the request says client supports keep-alive
            // but override if response has content-length header or
            // transfer chunked encoding
            keep_alive = content_length ||
                (transfer_encoding && transfer_encoding->Compare(NPT_HTTP_TRANSFER_ENCODING_CHUNKED) == 0);
        }
    }

    // only write keep-alive header for 1.1 if it's close
    NPT_String protocol = response->GetProtocol();
    if (protocol.Compare(NPT_HTTP_PROTOCOL_1_0, true) == 0 || !keep_alive) {
        headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, keep_alive?"keep-alive":"close", true);
    }
    headers.SetHeader(NPT_HTTP_HEADER_SERVER, PLT_HTTP_DEFAULT_SERVER, false); // set but don't replace

    PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINE, "PLT_HttpServerSocketTask::Write", response);

    // create a memory stream to buffer the headers
    NPT_MemoryStream header_stream;
    response->Emit(header_stream);

    // send the headers
    NPT_CHECK_WARNING(output_stream.WriteFully(header_stream.GetData(), header_stream.GetDataSize()));

    return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
|   NPT_Log::FormatRecordToStream
+---------------------------------------------------------------------*/
void
NPT_Log::FormatRecordToStream(const NPT_LogRecord& record,
                              NPT_OutputStream&    stream,
                              bool                 use_colors,
                              NPT_Flags            format_filter)
{
    const char* level_name = GetLogLevelName(record.m_Level);
    NPT_String  level_string;

    /* format and emit the record */
    if (level_name[0] == '\0') {
        level_string = NPT_String::FromInteger(record.m_Level);
        level_name = level_string;
    }
    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_SOURCE) == 0) {
        unsigned int start = 0;
        /* remove source file path if requested */
        if (format_filter & NPT_LOG_FORMAT_FILTER_NO_SOURCEPATH) {
            for (start = NPT_StringLength(record.m_SourceFile);
                 start;
                 --start) {
                if (record.m_SourceFile[start-1] == '\\' ||
                    record.m_SourceFile[start-1] == '/') {
                    break;
                }
            }
        }
        stream.WriteString(record.m_SourceFile + start);
        stream.Write("(", 1, NULL);
        stream.WriteString(NPT_String::FromIntegerU(record.m_SourceLine));
        stream.Write("): ", 3, NULL);
    }
    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_LOGGER_NAME) == 0) {
        stream.Write("[", 1, NULL);
        stream.WriteString(record.m_LoggerName);
        stream.Write("] ", 2, NULL);
    }
    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_TIMESTAMP) == 0) {
        NPT_String ts = NPT_DateTime(record.m_TimeStamp, true).ToString(NPT_DateTime::FORMAT_W3C, 
                                                                        NPT_DateTime::FLAG_EMIT_FRACTION | 
                                                                        NPT_DateTime::FLAG_EXTENDED_PRECISION);
        stream.WriteString(ts.GetChars());
        stream.Write(" ", 1);
    }
    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_FUNCTION_NAME) == 0) {
        stream.WriteFully("[",1);
        if (record.m_SourceFunction) {
            stream.WriteString(record.m_SourceFunction);
        }
        stream.WriteFully("] ",2);
    }
    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_THREAD_ID) == 0) {
        stream.Write("(", 1, NULL);
        stream.WriteString(NPT_String::FromIntegerU(record.m_ThreadId));
        stream.Write(") ", 2, NULL);
    }
    const char* ansi_color = NULL;
    if (use_colors) {
        ansi_color = GetLogLevelAnsiColor(record.m_Level);
        if (ansi_color) {
            stream.Write("\033[", 2, NULL);
            stream.WriteString(ansi_color);
            stream.Write(";1m", 3, NULL);
        }
    }
    stream.WriteString(level_name);
    if (use_colors && ansi_color) {
        stream.Write("\033[0m", 4, NULL);
    }
    stream.Write(": ", 2, NULL);
    stream.WriteString(record.m_Message);
    stream.Write("\r\n", 2, NULL);
}