void Run() { do { // wait for a connection NPT_Socket* client = NULL; NPT_LOG_FINE_1("waiting for connection on port %d...", m_Port); NPT_Result result = m_Socket.WaitForNewClient(client, NPT_TIMEOUT_INFINITE); if (NPT_FAILED(result) || client == NULL) return; NPT_SocketInfo client_info; client->GetInfo(client_info); NPT_LOG_FINE_2("client connected (%s -> %s)", client_info.local_address.ToString().GetChars(), client_info.remote_address.ToString().GetChars()); // get the output stream NPT_OutputStreamReference output; client->GetOutputStream(output); // generate policy based on our current IP NPT_String policy = "<cross-domain-policy>"; policy += "<allow-access-from domain=\""+client_info.local_address.GetIpAddress().ToString()+"\" to-ports=\""+m_AuthorizedPorts+"\"/>"; policy += "<allow-access-from domain=\""+client_info.remote_address.GetIpAddress().ToString()+"\" to-ports=\""+m_AuthorizedPorts+"\"/>"; policy += "</cross-domain-policy>"; NPT_MemoryStream* mem_input = new NPT_MemoryStream(); mem_input->Write(policy.GetChars(), policy.GetLength()); NPT_InputStreamReference input(mem_input); NPT_StreamToStreamCopy(*input, *output); delete client; } while (!m_Aborted); }
/*---------------------------------------------------------------------- | PLT_HttpHelper::GetBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::GetBody(NPT_HttpMessage& message, NPT_String& body) { NPT_Result res; NPT_InputStreamReference stream; // get stream NPT_HttpEntity* entity = message.GetEntity(); if (!entity || NPT_FAILED(entity->GetInputStream(stream))) { return NPT_FAILURE; } // extract body NPT_StringOutputStream* output_stream = new NPT_StringOutputStream(&body); res = NPT_StreamToStreamCopy(*stream, *output_stream, 0, entity->GetContentLength()); delete output_stream; return res; }
/*---------------------------------------------------------------------- | PLT_Downloader::ProcessResponse +---------------------------------------------------------------------*/ NPT_Result PLT_Downloader::ProcessResponse(NPT_Result res, const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse* response) { NPT_COMPILER_UNUSED(request); NPT_COMPILER_UNUSED(context); if (NPT_FAILED(res)) { NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars()); m_State = PLT_DOWNLOADER_ERROR; return res; } m_State = PLT_DOWNLOADER_DOWNLOADING; NPT_HttpEntity* entity; NPT_InputStreamReference body; if (!response || !(entity = response->GetEntity()) || NPT_FAILED(entity->GetInputStream(body)) || body.IsNull()) { m_State = PLT_DOWNLOADER_ERROR; NPT_LOG_WARNING_2("No body %d for %s", res, m_URL.ToString().GetChars()); return NPT_FAILURE; } // Read body (no content length means until socket is closed) res = NPT_StreamToStreamCopy(*body.AsPointer(), *m_Output.AsPointer(), 0, entity->GetContentLength()); if (NPT_FAILED(res)) { NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars()); m_State = PLT_DOWNLOADER_ERROR; return res; } NPT_LOG_INFO_1("Finished downloading %s", m_URL.ToString().GetChars()); m_State = PLT_DOWNLOADER_SUCCESS; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_Zip::Deflate +---------------------------------------------------------------------*/ NPT_Result NPT_Zip::Deflate(NPT_File& in, NPT_File& out, int compression_level, Format format /* = ZLIB */) { // check parameters if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT || compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) { return NPT_ERROR_INVALID_PARAMETERS; } NPT_InputStreamReference input; NPT_CHECK(in.GetInputStream(input)); NPT_OutputStreamReference output; NPT_CHECK(out.GetOutputStream(output)); NPT_ZipDeflatingInputStream deflating_stream(input, compression_level, format); return NPT_StreamToStreamCopy(deflating_stream, *output.AsPointer()); }
/*---------------------------------------------------------------------- | PLT_Downloader::ProcessResponse +---------------------------------------------------------------------*/ NPT_Result PLT_Downloader::ProcessResponse(NPT_Result res, NPT_HttpRequest* request, const NPT_HttpRequestContext& context, NPT_HttpResponse* response) { NPT_COMPILER_UNUSED(request); NPT_COMPILER_UNUSED(context); if (NPT_FAILED(res)) { m_State = PLT_DOWNLOADER_ERROR; return res; } m_State = PLT_DOWNLOADER_DOWNLOADING; NPT_HttpEntity* entity; NPT_InputStreamReference body; if (!response || !(entity = response->GetEntity()) || NPT_FAILED(entity->GetInputStream(body)) || body.IsNull()) { m_State = PLT_DOWNLOADER_ERROR; return NPT_FAILURE; } // Read body (no content length means until socket is closed) res = NPT_StreamToStreamCopy(*body.AsPointer(), *m_Output.AsPointer(), 0, entity->GetContentLength()); if (NPT_FAILED(res)) { m_State = PLT_DOWNLOADER_ERROR; return res; } m_State = PLT_DOWNLOADER_SUCCESS; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | PLT_HttpClient::SendRequest +---------------------------------------------------------------------*/ NPT_Result PLT_HttpClient::SendRequest(NPT_OutputStreamReference& output_stream, NPT_HttpRequest& request, NPT_Timeout timeout) { NPT_COMPILER_UNUSED(timeout); // connect to the server NPT_LOG_FINE("Sending:"); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request); // add any headers that may be missing NPT_HttpHeaders& headers = request.GetHeaders(); //headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close"); if (!headers.GetHeader(NPT_HTTP_HEADER_USER_AGENT)) { headers.SetHeader(NPT_HTTP_HEADER_USER_AGENT, "Platinum/" PLT_PLATINUM_VERSION_STRING); } // set host only if not already set if (!headers.GetHeader(NPT_HTTP_HEADER_HOST)) { NPT_String host = request.GetUrl().GetHost(); if (request.GetUrl().GetPort() != NPT_HTTP_DEFAULT_PORT) { host += ":"; host += NPT_String::FromInteger(request.GetUrl().GetPort()); } headers.SetHeader(NPT_HTTP_HEADER_HOST, host); } // get the request entity to set additional headers NPT_InputStreamReference body_stream; NPT_HttpEntity* entity = request.GetEntity(); if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) { // content length headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, NPT_String::FromInteger(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); } } else { // force content length to 0 is there is no message body headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0"); } // create a memory stream to buffer the headers NPT_MemoryStream header_stream; // emit the request headers into the header buffer request.Emit(header_stream); // send the headers NPT_CHECK_SEVERE(output_stream->WriteFully(header_stream.GetData(), header_stream.GetDataSize())); // send request body if (!body_stream.IsNull() && entity->GetContentLength()) { NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(*body_stream.AsPointer(), *output_stream.AsPointer())); } // flush the output stream so that everything is sent to the server output_stream->Flush(); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServerSocketTask::Read +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServerSocketTask::Read(NPT_BufferedInputStreamReference& buffered_input_stream, NPT_HttpRequest*& request, NPT_HttpRequestContext* context) { NPT_SocketInfo info; GetInfo(info); // update context with socket info if needed if (context) { context->SetLocalAddress(info.local_address); context->SetRemoteAddress(info.remote_address); } // put back in buffered mode to be able to parse HTTP request properly buffered_input_stream->SetBufferSize(NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE); // parse request NPT_Result res = NPT_HttpRequest::Parse(*buffered_input_stream, &info.local_address, request); if (NPT_FAILED(res) || !request) { // only log if not timeout res = NPT_FAILED(res)?res:NPT_FAILURE; if (res != NPT_ERROR_TIMEOUT && res != NPT_ERROR_EOS) NPT_CHECK_WARNING(res); return res; } // update context with socket info again // to refresh the remote address in case it was a non connected udp socket GetInfo(info); if (context) { context->SetLocalAddress(info.local_address); context->SetRemoteAddress(info.remote_address); } // return right away if no body is expected if (request->GetMethod() == NPT_HTTP_METHOD_GET || request->GetMethod() == NPT_HTTP_METHOD_HEAD) { return NPT_SUCCESS; } // create an entity NPT_HttpEntity* request_entity = new NPT_HttpEntity(request->GetHeaders()); request->SetEntity(request_entity); NPT_MemoryStream* body_stream = new NPT_MemoryStream(); request_entity->SetInputStream((NPT_InputStreamReference)body_stream); // unbuffer the stream to read body fast buffered_input_stream->SetBufferSize(0); // check for chunked Transfer-Encoding if (request_entity->GetTransferEncoding() == "chunked") { NPT_CHECK_SEVERE(NPT_StreamToStreamCopy( *NPT_InputStreamReference(new NPT_HttpChunkedInputStream(buffered_input_stream)).AsPointer(), *body_stream)); request_entity->SetTransferEncoding(NULL); } else if (request_entity->GetContentLength()) { // a request with a body must always have a content length if not chunked NPT_CHECK_SEVERE(NPT_StreamToStreamCopy( *buffered_input_stream.AsPointer(), *body_stream, 0, request_entity->GetContentLength())); } else { request->SetEntity(NULL); } // rebuffer the stream buffered_input_stream->SetBufferSize(NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE); return NPT_SUCCESS; }