/*---------------------------------------------------------------------- | CMediaCrawler::ProcessFileRequest +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::ProcessFileRequest(NPT_HttpRequest& request, NPT_HttpResponse& response, NPT_SocketInfo& info) { NPT_COMPILER_UNUSED(info); NPT_LOG_FINE("CMediaCrawler::ProcessFileRequest Received Request:"); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request); if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) { response.SetStatus(500, "Internal Server Error"); return NPT_SUCCESS; } // add the user agent header, some stupid media servers like YME needs it if (!request.GetHeaders().GetHeader(NPT_HTTP_HEADER_USER_AGENT)) { request.GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT, "Platinum/" PLT_PLATINUM_VERSION_STRING); } // File requested NPT_HttpResponse* out_response = NULL; NPT_HttpUrlQuery query(request.GetUrl().GetQuery()); const char* url = query.GetField("url"); if (url) { // look for handler CStreamHandler* handler = NULL; NPT_ContainerFind(m_StreamHandlers, CStreamHandlerFinder(NULL, url), handler); if (handler && NPT_SUCCEEDED(handler->ProcessFileRequest(request, out_response)) && out_response) { // copy response code and reason response.SetStatus(out_response->GetStatusCode(), out_response->GetReasonPhrase()); // copy headers NPT_List<NPT_HttpHeader*>::Iterator headers = out_response->GetHeaders().GetHeaders().GetFirstItem(); while (headers) { response.GetHeaders().SetHeader((*headers)->GetName(), (*headers)->GetValue()); ++headers; } response.SetEntity(new NPT_HttpEntity(response.GetHeaders())); // update inputstream NPT_HttpEntity* out_entity; if ((out_entity = out_response->GetEntity()) != NULL) { NPT_InputStreamReference inputstream; out_entity->GetInputStream(inputstream); if (!inputstream.IsNull()) { // set the stream but do not update the content length response.GetEntity()->SetInputStream(inputstream, false); } } delete out_response; return NPT_SUCCESS; } } response.SetStatus(404, "File Not Found"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_ZipFile::GetInputStream +---------------------------------------------------------------------*/ NPT_Result NPT_ZipFile::GetInputStream(Entry& entry, NPT_InputStreamReference& zip_stream, NPT_InputStream*& file_stream) { // default return value file_stream = NULL; // we don't support encrypted files if (entry.m_Flags & NPT_ZIP_FILE_FLAG_ENCRYPTED) { return NPT_ERROR_NOT_SUPPORTED; } // check that we support the compression method #if NPT_CONFIG_ENABLE_ZIP if (entry.m_CompressionMethod != NPT_ZIP_FILE_COMPRESSION_METHOD_NONE && entry.m_CompressionMethod != NPT_ZIP_FILE_COMPRESSION_METHOD_DEFLATE) { return NPT_ERROR_NOT_SUPPORTED; } #else if (entry.m_CompressionMethod != NPT_ZIP_FILE_COMPRESSION_METHOD_NONE) { return NPT_ERROR_NOT_SUPPORTED; } #endif // seek to the start of the file entry NPT_Result result = zip_stream->Seek(entry.m_RelativeOffset); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("seek failed (%d)", result); return result; } // read the fixed part of the header unsigned char header[30]; result = zip_stream->ReadFully(header, 30); if (NPT_FAILED(result)) { NPT_LOG_WARNING_1("read failed (%d)", result); return result; } NPT_UInt16 file_name_length = NPT_BytesToInt16Le(&header[26]); NPT_UInt16 extra_field_length = NPT_BytesToInt16Le(&header[28]); unsigned int header_size = 30+file_name_length+extra_field_length; NPT_LargeSize zip_stream_size = 0; zip_stream->GetSize(zip_stream_size); if (entry.m_RelativeOffset+header_size+entry.m_CompressedSize > zip_stream_size) { // something's wrong here return NPT_ERROR_INVALID_FORMAT; } file_stream = new NPT_SubInputStream(zip_stream, entry.m_RelativeOffset+header_size, entry.m_CompressedSize); #if NPT_CONFIG_ENABLE_ZIP if (entry.m_CompressionMethod == NPT_ZIP_FILE_COMPRESSION_METHOD_DEFLATE) { NPT_InputStreamReference file_stream_ref(file_stream); file_stream = new NPT_ZipInflatingInputStream(file_stream_ref, true); } #endif return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServer::ServeFile +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServer::ServeFile(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response, NPT_String file_path) { NPT_InputStreamReference stream; NPT_File file(file_path); NPT_FileInfo file_info; // prevent hackers from accessing files outside of our root if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0) || NPT_FAILED(NPT_File::GetInfo(file_path, &file_info))) { return NPT_ERROR_NO_SUCH_ITEM; } // check for range requests const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE); // handle potential 304 only if range header not set NPT_DateTime date; NPT_TimeStamp timestamp; if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetIfModifiedSince((NPT_HttpMessage&)request, date)) && !range_spec) { date.ToTimeStamp(timestamp); NPT_LOG_INFO_5("File %s timestamps: request=%d (%s) vs file=%d (%s)", (const char*)request.GetUrl().GetPath(), (NPT_UInt32)timestamp.ToSeconds(), (const char*)date.ToString(), (NPT_UInt32)file_info.m_ModificationTime, (const char*)NPT_DateTime(file_info.m_ModificationTime).ToString()); if (timestamp >= file_info.m_ModificationTime) { // it's a match NPT_LOG_FINE_1("Returning 304 for %s", request.GetUrl().GetPath().GetChars()); response.SetStatus(304, "Not Modified", NPT_HTTP_PROTOCOL_1_1); return NPT_SUCCESS; } } // open file if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || NPT_FAILED(file.GetInputStream(stream)) || stream.IsNull()) { return NPT_ERROR_NO_SUCH_ITEM; } // set Last-Modified and Cache-Control headers if (file_info.m_ModificationTime) { NPT_DateTime last_modified = NPT_DateTime(file_info.m_ModificationTime); response.GetHeaders().SetHeader("Last-Modified", last_modified.ToString(NPT_DateTime::FORMAT_RFC_1123), true); response.GetHeaders().SetHeader("Cache-Control", "max-age=0,must-revalidate", true); //response.GetHeaders().SetHeader("Cache-Control", "max-age=1800", true); } PLT_HttpRequestContext tmp_context(request, context); return ServeStream(request, context, response, stream, PLT_MimeType::GetMimeType(file_path, &tmp_context)); }
/*---------------------------------------------------------------------- | NPT_File::Load +---------------------------------------------------------------------*/ NPT_Result NPT_File::Load(NPT_DataBuffer& buffer) { NPT_InputStreamReference input; // get the input stream for the file NPT_CHECK_FATAL(GetInputStream(input)); // read the stream return input->Load(buffer); }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnAlbumArtRequest +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnAlbumArtRequest(NPT_HttpResponse& response, NPT_String file_path) { NPT_LargeSize total_len; NPT_File file(file_path); NPT_InputStreamReference stream; // prevent hackers from accessing files outside of our root if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0)) { return NPT_FAILURE; } if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || NPT_FAILED(file.GetInputStream(stream)) || NPT_FAILED(stream->GetSize(total_len)) || (total_len == 0)) { goto filenotfound; } else { NPT_String extension = NPT_FilePath::FileExtension(file_path); if (extension.GetLength() == 0) { goto filenotfound; } PLT_MetadataHandler* metadataHandler = NULL; char* caData; int caDataLen; NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, PLT_MetadataHandlerFinder(extension), metadataHandler); if (NPT_FAILED(ret) || metadataHandler == NULL) { goto filenotfound; } // load the metadatahandler and read the cover art if (NPT_FAILED(metadataHandler->Load(*stream)) || NPT_FAILED(metadataHandler->GetCoverArtData(caData, caDataLen))) { goto filenotfound; } PLT_HttpHelper::SetContentType(response, "application/octet-stream"); PLT_HttpHelper::SetBody(response, caData, caDataLen); delete caData; return NPT_SUCCESS; } filenotfound: response.SetStatus(404, "File Not Found"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::IsBodyStreamSeekable +---------------------------------------------------------------------*/ bool PLT_HttpHelper::IsBodyStreamSeekable(NPT_HttpMessage* message) { NPT_HttpEntity* entity = message->GetEntity(); NPT_InputStreamReference stream; if (!entity || NPT_FAILED(entity->GetInputStream(stream))) return true; // try to get current position and seek there NPT_Position position; if (NPT_FAILED(stream->Tell(position)) || NPT_FAILED(stream->Seek(position))) { return false; } return true; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | ShowResponse +---------------------------------------------------------------------*/ static void ShowResponse(NPT_HttpResponse* response) { bool check_available = true;//true; // show entity NPT_HttpEntity* entity = response->GetEntity(); if (entity == NULL) return; NPT_Console::OutputF("ENTITY: length=%lld, type=%s, encoding=%s\n", entity->GetContentLength(), entity->GetContentType().GetChars(), entity->GetContentEncoding().GetChars()); NPT_DataBuffer buffer(65536); NPT_Result result; NPT_InputStreamReference input; entity->GetInputStream(input); NPT_TimeStamp start; NPT_System::GetCurrentTimeStamp(start); float total_read = 0.0f; for (;;) { NPT_Size bytes_read = 0; NPT_LargeSize available = 0; NPT_Size to_read = 65536; if (check_available) { input->GetAvailable(available); if ((NPT_Size)available < to_read) to_read = (NPT_Size)available; if (to_read == 0) { to_read = 1; NPT_TimeStamp sleep_time(0.01f); NPT_System::Sleep(sleep_time); } } result = input->Read(buffer.UseData(), to_read, &bytes_read); if (NPT_FAILED(result)) break; total_read += bytes_read; NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); NPT_TimeStamp duration = now-start; NPT_Console::OutputF("%6d avail, read %6d bytes, %6.3f KB/s\n", (int)available, bytes_read, (float)((total_read/1024.0)/(double)duration)); } }
/*---------------------------------------------------------------------- | DumpBody +---------------------------------------------------------------------*/ static NPT_Result ReadBody(PLT_Downloader& downloader, NPT_InputStreamReference& stream, NPT_Size& size) { NPT_LargeSize avail; char buffer[2048]; NPT_Result ret = NPT_ERROR_WOULD_BLOCK; /* reset output param first */ size = 0; /* we test for availability first to avoid getting stuck in Read forever in case blocking is true and the download is done writing to the stream */ NPT_CHECK(stream->GetAvailable(avail)); if (avail) { ret = stream->Read(buffer, 2048, &size); NPT_LOG_FINER_2("Read %d bytes (result = %d)\n", size, ret); return ret; } else { Plt_DowloaderState state = downloader.GetState(); switch (state) { case PLT_DOWNLOADER_ERROR: return NPT_FAILURE; case PLT_DOWNLOADER_SUCCESS: /* no more data expected */ return NPT_ERROR_EOS; default: NPT_System::Sleep(NPT_TimeInterval(0, 10000)); break; } } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | 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; }
void serveFile(AbortableTask *task, const NPT_String& filePath, const NPT_String& mimeType, const FrontEnd::RequestContext& reqCtx, const NPT_HttpRequest *req, NPT_HttpResponse& resp, HttpOutput *httpOutput) { NPT_File f(filePath); NPT_FileInfo fileInfo; if (NPT_FAILED(f.GetInfo(fileInfo)) || fileInfo.m_Type != NPT_FileInfo::FILE_TYPE_REGULAR || NPT_FAILED(f.Open(NPT_FILE_OPEN_MODE_READ))) { setStatusCode(resp, 404); httpOutput->writeResponseHeader(resp); return; } MediaStore::FileDetail detail; detail.m_mimeType = mimeType; detail.m_path = filePath; detail.m_modificationTime = fileInfo.m_ModificationTime; detail.m_size = fileInfo.m_Size; detail.m_type = MediaStore::FileDetail::PosixFile; NPT_InputStreamReference fileInput; f.GetInputStream(fileInput); AdvFileReader reader(fileInput.AsPointer()); serveStreamAdv(task, detail, &reader, reqCtx, req, resp, httpOutput, 1024 * 64); }
/*---------------------------------------------------------------------- | PLT_HttpHelper::GetBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::GetBody(const 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)) || stream.IsNull()) { 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_FileMediaServer::OnAlbumArtRequest +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnAlbumArtRequest(NPT_String filepath, NPT_HttpResponse& response) { NPT_Size total_len; NPT_File file(filepath); NPT_InputStreamReference stream; if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || NPT_FAILED(file.GetInputStream(stream)) || NPT_FAILED(stream->GetSize(total_len)) || (total_len == 0)) { goto filenotfound; } else { const char* extension = PLT_MediaItem::GetExtFromFilePath(filepath, m_DirDelimiter); if (extension == NULL) { goto filenotfound; } PLT_MetadataHandler* metadataHandler = NULL; char* caData; int caDataLen; NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, PLT_MetadataHandlerFinder(extension), metadataHandler); if (NPT_FAILED(ret) || metadataHandler == NULL) { goto filenotfound; } // load the metadatahandler and read the cover art if (NPT_FAILED(metadataHandler->Load(*stream)) || NPT_FAILED(metadataHandler->GetCoverArtData(caData, caDataLen))) { goto filenotfound; } PLT_HttpHelper::SetContentType(&response, "application/octet-stream"); PLT_HttpHelper::SetBody(&response, caData, caDataLen); delete caData; return NPT_SUCCESS; } filenotfound: response.SetStatus(404, "File Not Found"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | TcpServerLoop +---------------------------------------------------------------------*/ static void TcpServerLoop(int port) { NPT_TcpServerSocket listener; NPT_Result result = listener.Bind(NPT_SocketAddress(NPT_IpAddress::Any, port)); if (NPT_FAILED(result)) { NPT_Debug("ERROR: Bind() failed (%d)\n", result); } NPT_Socket* client; for (;;) { NPT_Debug("waiting for client on port %d\n", port); NPT_Result result = listener.WaitForNewClient(client); NPT_SocketInfo socket_info; client->GetInfo(socket_info); NPT_Debug("client connected from %s:%d\n", socket_info.remote_address.GetIpAddress().ToString().GetChars(), socket_info.remote_address.GetPort()); NPT_InputStreamReference input; client->GetInputStream(input); NPT_OutputStreamReference output; client->GetOutputStream(output); do { char buffer[1024]; NPT_Size bytes_read; result = input->Read(buffer, sizeof(buffer), &bytes_read); if (NPT_SUCCEEDED(result)) { NPT_Debug("read %ld bytes\n", bytes_read); output->Write(buffer, bytes_read); } } while (NPT_SUCCEEDED(result)); delete client; } }
/*---------------------------------------------------------------------- | NPT_HttpMessage::SetBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::SetBody(NPT_HttpMessage* message, NPT_InputStreamReference& stream, NPT_Size len) { if (len == 0) { NPT_CHECK_SEVERE(stream->GetAvailable(len)); } // get the entity NPT_HttpEntity* entity = message->GetEntity(); if (entity == NULL) { // no entity yet, create one message->SetEntity(entity = new NPT_HttpEntity()); } // set the entity body entity->SetInputStream(stream); entity->SetContentLength(len); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { // check command line if (argc < 2) { PrintUsageAndExit(); } // init endpoints EndPoint in_endpoint; in_endpoint.direction = ENDPOINT_DIRECTION_IN; EndPoint out_endpoint; out_endpoint.direction = ENDPOINT_DIRECTION_OUT; EndPoint* current_endpoint = &in_endpoint; // init other parameters unsigned int packet_size = PUMP_DEFAULT_PACKET_SIZE; // init options Options.verbose = false; Options.show_progress = false; // parse command line argv++; char* arg; while ((arg = *argv++)) { if (current_endpoint == NULL) { NPT_Debug("ERROR: unexpected argument (%s)\n", arg); exit(1); } if (!strcmp(arg, "--packet-size")) { packet_size = strtoul(*argv++, NULL, 10); continue; } else if (!strcmp(arg, "--verbose")) { Options.verbose = true; continue; } else if (!strcmp(arg, "--show-progress")) { Options.show_progress = true; continue; } else if (!strcmp(arg, "udp")) { if (argv[0] && argv[1]) { if (!strcmp(argv[0], "server")) { if (current_endpoint->direction == ENDPOINT_DIRECTION_OUT){ NPT_Debug("ERROR: cannot use 'udp server' as output\n"); exit(1); } current_endpoint->type = ENDPOINT_TYPE_UDP_SERVER; current_endpoint->info.udp_server.port = strtoul(argv[1], NULL, 10); argv += 2; } else if (!strcmp(argv[0], "client")) { if (current_endpoint->direction == ENDPOINT_DIRECTION_IN) { NPT_Debug("ERROR: cannot use 'udp client' as input\n"); exit(1); } if (argv[2]) { current_endpoint->type = ENDPOINT_TYPE_UDP_CLIENT; current_endpoint->info.udp_client.hostname = argv[1]; current_endpoint->info.udp_client.port = strtoul(argv[2], NULL, 10); argv += 3; } else { NPT_Debug("ERROR: missing argument for 'udp client'\n"); exit(1); } } } else { NPT_Debug("ERROR: missing argument for 'udp' endpoint\n"); exit(1); } } else if (!strcmp(arg, "multicast")) { if (argv[0] && argv[1]) { if (!strcmp(argv[0], "server")) { if (current_endpoint->direction == ENDPOINT_DIRECTION_OUT){ NPT_Debug("ERROR: cannot use 'multicast server' as output\n"); exit(1); } if (argv[2]) { current_endpoint->type = ENDPOINT_TYPE_MULTICAST_SERVER; current_endpoint->info.multicast_server.groupname = argv[1]; current_endpoint->info.multicast_server.port = strtoul(argv[2], NULL, 10); argv += 3; } else { NPT_Debug("ERROR: missing argument for 'multicast server'\n"); exit(1); } } else if (!strcmp(argv[0], "client")) { if (current_endpoint->direction == ENDPOINT_DIRECTION_IN) { NPT_Debug("ERROR: cannot use 'udp client' as input\n"); exit(1); } if (argv[2] && argv[3]) { current_endpoint->type = ENDPOINT_TYPE_MULTICAST_CLIENT; current_endpoint->info.multicast_client.groupname = argv[1]; current_endpoint->info.multicast_client.port = strtoul(argv[2], NULL, 10); current_endpoint->info.multicast_client.ttl = strtoul(argv[3], NULL, 10); argv += 4; } else { NPT_Debug("ERROR: missing argument for 'multicast client'\n"); exit(1); } } } else { NPT_Debug("ERROR: missing argument for 'multicast' endpoint\n"); exit(1); } } else if (!strcmp(arg, "tcp")) { if (argv[0] && argv[1]) { if (!strcmp(argv[0], "server")) { current_endpoint->type = ENDPOINT_TYPE_TCP_SERVER; current_endpoint->info.tcp_server.port = strtoul(argv[1], NULL, 10); argv += 2; } else if (!strcmp(argv[0], "client")) { if (argv[2]) { current_endpoint->type = ENDPOINT_TYPE_TCP_CLIENT; current_endpoint->info.tcp_client.hostname = argv[1]; current_endpoint->info.tcp_client.port = strtoul(argv[2], NULL, 10); argv += 3; } else { NPT_Debug("ERROR: missing argument for 'tcp client'\n"); exit(1); } } } else { NPT_Debug("ERROR: missing argument for 'tcp' endpoint\n"); exit(1); } } else if (!strcmp(arg, "file")) { if (argv[0]) { current_endpoint->type = ENDPOINT_TYPE_FILE; current_endpoint->info.file.name = *argv++; } else { NPT_Debug("ERROR: missing argument for 'file' endpoint\n"); exit(1); } } else if (!strcmp(arg, "serial")) { if (argv[0]) { current_endpoint->type = ENDPOINT_TYPE_SERIAL_PORT; current_endpoint->info.serial_port.name = *argv++; } else { NPT_Debug("ERROR: missing argument for 'serial' endpoint\n"); exit(1); } if (argv[0]) { long speed = 0; if (NPT_FAILED(NPT_ParseInteger(*argv++, speed))) { NPT_Debug("ERROR: invalid speed for 'serial' endpoint\n"); exit(1); } current_endpoint->info.serial_port.speed = (unsigned int)speed; } else { NPT_Debug("ERROR: missing argument for 'serial' endpoint\n"); exit(1); } } else { NPT_Debug("ERROR: invalid argument (%s)\n", arg); exit(1); } if (current_endpoint == &in_endpoint) { current_endpoint = &out_endpoint; } else { current_endpoint = NULL; } } if (current_endpoint) { NPT_Debug("ERROR: missing endpoint specification\n"); exit(1); } // data pump NPT_Result result; // allocate buffer unsigned char* buffer; buffer = (unsigned char*)malloc(packet_size); if (buffer == NULL) { NPT_Debug("ERROR: out of memory\n"); exit(1); } // get output stream NPT_OutputStreamReference out; result = GetEndPointStreams(&out_endpoint, NULL, &out); if (NPT_FAILED(result)) { NPT_Debug("ERROR: failed to get stream for output (%d)", result); exit(1); } unsigned long offset = 0; unsigned long total = 0; if (in_endpoint.type == ENDPOINT_TYPE_UDP_SERVER || in_endpoint.type == ENDPOINT_TYPE_MULTICAST_SERVER) { NPT_UdpSocket* udp_socket; result = GetEndPointUdpSocket(&in_endpoint, udp_socket); // packet loop NPT_DataBuffer packet(32768); NPT_SocketAddress address; do { result = udp_socket->Receive(packet, &address); if (NPT_SUCCEEDED(result)) { if (Options.verbose) { NPT_String ip = address.GetIpAddress().ToString(); NPT_Debug("Received %d bytes from %s\n", packet.GetDataSize(), ip.GetChars()); } result = out->Write(packet.GetData(), packet.GetDataSize(), NULL); offset += packet.GetDataSize(); total += packet.GetDataSize(); } } while (NPT_SUCCEEDED(result)); } else { // get the input stream NPT_InputStreamReference in; result = GetEndPointStreams(&in_endpoint, &in, NULL); if (NPT_FAILED(result)) { NPT_Debug("ERROR: failed to get stream for input (%d)\n", result); exit(1); } // stream loop do { NPT_Size bytes_read; NPT_Size bytes_written; // send result = in->Read(buffer, packet_size, &bytes_read); if (Options.show_progress) { NPT_Debug("[%d]\r", total); } if (NPT_SUCCEEDED(result) && bytes_read) { result = out->Write(buffer, bytes_read, &bytes_written); if (Options.show_progress) { NPT_Debug("[%d]\r", total); } offset += bytes_written; total += bytes_written; } else { printf("[%d] *******************\n", result); exit(1); } } while (NPT_SUCCEEDED(result)); } delete buffer; return 0; }
void serveFile2(AbortableTask *task, const NPT_String& filePath, const NPT_String& mimeType, const FrontEnd::RequestContext& reqCtx, const NPT_HttpRequest *req, NPT_HttpResponse& resp, HttpOutput *httpOutput) { #if 1 NPT_File f(filePath); NPT_FileInfo fileInfo; if (NPT_FAILED(f.GetInfo(fileInfo)) || fileInfo.m_Type != NPT_FileInfo::FILE_TYPE_REGULAR || NPT_FAILED(f.Open(NPT_FILE_OPEN_MODE_READ))) { setStatusCode(resp, 404); httpOutput->writeResponseHeader(resp); return; } NPT_InputStreamReference fileInput; f.GetInputStream(fileInput); serveStream(task, fileInput.AsPointer(), fileInfo.m_ModificationTime, mimeType, reqCtx, req, resp, httpOutput); #else bool isGetMethod = req->GetMethod().Compare("GET") == 0; bool isHeadMethod = req->GetMethod().Compare("HEAD") == 0; if (isGetMethod || isHeadMethod) { NPT_Result nr; NPT_File f(filePath); NPT_FileInfo fileInfo; if (NPT_FAILED(f.GetInfo(fileInfo)) || fileInfo.m_Type != NPT_FileInfo::FILE_TYPE_REGULAR || NPT_FAILED(f.Open(NPT_FILE_OPEN_MODE_READ))) { setStatusCode(resp, 404); httpOutput->writeResponseHeader(resp); return; } NPT_InputStreamReference fileInput; f.GetInputStream(fileInput); NPT_UInt64 offset, length; NPT_HttpHeader *hdrRange = req->GetHeaders().GetHeader("RANGE"); if (hdrRange) { if (!parseRangeHeader(hdrRange->GetValue(), fileInfo.m_Size, offset, length)) { setStatusCode(resp, 416); httpOutput->writeResponseHeader(resp); return; } setStatusCode(resp, 206); resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, NPT_String::Format("bytes %s-%s/%s", NPT_String::FromIntegerU(offset).GetChars(), NPT_String::FromIntegerU(offset + length - 1).GetChars(), NPT_String::FromIntegerU(fileInfo.m_Size).GetChars())); fileInput->Seek(offset); } else { offset = 0; length = fileInfo.m_Size; setStatusCode(resp, 200); } resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, mimeType); resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, NPT_String::FromIntegerU(length)); resp.GetHeaders().SetHeader("Last-Modified", NPT_DateTime(fileInfo.m_ModificationTime).ToString(NPT_DateTime::FORMAT_RFC_1123)); resp.GetHeaders().SetHeader("Accept-Ranges", "bytes"); resp.GetHeaders().SetHeader("EXT", ""); if (reqCtx.transferMode != FrontEnd::TM_None) { const char *transferMode = "Streaming"; switch (reqCtx.transferMode) { case FrontEnd::TM_Background: transferMode = "Background"; break; case FrontEnd::TM_Interactive: transferMode = "Interactive"; break; } resp.GetHeaders().SetHeader("transferMode.dlna.org", transferMode); } if (reqCtx.getcontentFeaturesReq) { NPT_String contentFeatures("DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"); resp.GetHeaders().SetHeader("contentFeatures.dlna.org", contentFeatures); } httpOutput->writeResponseHeader(resp); if (isGetMethod) { bool abortFlag = false; ServeFileAbortCallback abortCallback(&abortFlag); if (task->registerAbortCallback(&abortCallback)) { NPT_DataBuffer buffer(4096); NPT_UInt64 cbRemain = length; for (;;) { if (abortFlag) { break; } if (cbRemain == 0) { break; } NPT_Size cbRead; NPT_UInt64 cbToRead = cbRemain; if (cbToRead > buffer.GetBufferSize()) { cbToRead = buffer.GetBufferSize(); } nr = fileInput->Read(buffer.UseData(), buffer.GetBufferSize(), &cbRead); if (NPT_FAILED(nr)) { /*if (nr == NPT_ERROR_EOS) { } else { }*/ break; } if (abortFlag) { break; } if (cbRead > 0) { cbRemain -= cbRead; httpOutput->writeData(buffer.GetData(), cbRead); } } task->unregisterAbortCallback(&abortCallback); } } } else { setStatusCode(resp, 405); resp.GetHeaders().SetHeader("Allow", "GET, HEAD"); httpOutput->writeResponseHeader(resp); } #endif }
/*---------------------------------------------------------------------- | PLT_HttpServer::ServeStream +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServer::ServeStream(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response, NPT_InputStreamReference& body, const char* content_type) { if (body.IsNull()) return NPT_FAILURE; // set date NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); response.GetHeaders().SetHeader("Date", NPT_DateTime(now).ToString(NPT_DateTime::FORMAT_RFC_1123), true); // get entity NPT_HttpEntity* entity = response.GetEntity(); NPT_CHECK_POINTER_FATAL(entity); // set the content type entity->SetContentType(content_type); // check for range requests const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE); // setup entity body NPT_CHECK(NPT_HttpFileRequestHandler::SetupResponseBody(response, body, range_spec)); // set some default headers if (response.GetEntity()->GetTransferEncoding() != NPT_HTTP_TRANSFER_ENCODING_CHUNKED) { // set but don't replace Accept-Range header only if body is seekable NPT_Position offset; if (NPT_SUCCEEDED(body->Tell(offset)) && NPT_SUCCEEDED(body->Seek(offset))) { response.GetHeaders().SetHeader(NPT_HTTP_HEADER_ACCEPT_RANGES, "bytes", false); } } // set getcontentFeatures.dlna.org const NPT_String* value = request.GetHeaders().GetHeaderValue("getcontentFeatures.dlna.org"); if (value) { PLT_HttpRequestContext tmp_context(request, context); const char* dlna = PLT_ProtocolInfo::GetDlnaExtension(entity->GetContentType(), &tmp_context); if (dlna) response.GetHeaders().SetHeader("ContentFeatures.DLNA.ORG", dlna, false); } // transferMode.dlna.org value = request.GetHeaders().GetHeaderValue("transferMode.dlna.org"); if (value) { // Interactive mode not supported? /*if (value->Compare("Interactive", true) == 0) { response.SetStatus(406, "Not Acceptable"); return NPT_SUCCESS; }*/ response.GetHeaders().SetHeader("TransferMode.DLNA.ORG", value->GetChars(), false); } else { response.GetHeaders().SetHeader("TransferMode.DLNA.ORG", "Streaming", false); } if (request.GetHeaders().GetHeaderValue("TimeSeekRange.dlna.org")) { response.SetStatus(406, "Not Acceptable"); return NPT_SUCCESS; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | ShowResponse +---------------------------------------------------------------------*/ static void ShowResponse(NPT_HttpResponse* response, ShowMode mode) { // show response info NPT_Debug("RESPONSE: protocol=%s, code=%d, reason=%s\n", response->GetProtocol().GetChars(), response->GetStatusCode(), response->GetReasonPhrase().GetChars()); // show headers NPT_HttpHeaders& headers = response->GetHeaders(); NPT_List<NPT_HttpHeader*>::Iterator header = headers.GetHeaders().GetFirstItem(); while (header) { NPT_Debug("%s: %s\n", (const char*)(*header)->GetName(), (const char*)(*header)->GetValue()); ++header; } // show entity NPT_HttpEntity* entity = response->GetEntity(); if (entity != NULL) { NPT_Debug("ENTITY: length=%lld, type=%s, encoding=%s\n", entity->GetContentLength(), entity->GetContentType().GetChars(), entity->GetContentEncoding().GetChars()); switch (mode) { case SHOW_MODE_LOAD: { NPT_DataBuffer body; NPT_Result result =entity->Load(body); if (NPT_FAILED(result)) { NPT_Debug("ERROR: failed to load entity (%d)\n", result); } else { NPT_Debug("BODY: loaded %d bytes\n", (int)body.GetDataSize()); // dump the body NPT_OutputStreamReference output; NPT_File standard_out(NPT_FILE_STANDARD_OUTPUT); standard_out.Open(NPT_FILE_OPEN_MODE_WRITE); standard_out.GetOutputStream(output); NPT_Debug("%s", (char *)body.GetData()); // ÔÝʱ²»Ö§³Ö // output->Write(body.GetData(), body.GetDataSize()); } break; } case SHOW_MODE_STREAM_BLOCKING: { NPT_DataBuffer buffer(4096); NPT_Result result; NPT_InputStreamReference input; entity->GetInputStream(input); do { NPT_Size bytes_read = 0; result = input->Read(buffer.UseData(), 4096, &bytes_read); NPT_Debug("read %d bytes\n", bytes_read); } while (NPT_SUCCEEDED(result)); break; } } } }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { NPT_Result result; NPT_FileInfo info; NPT_ASSERT(NPT_File::GetInfo("foobar.doesnotexist", NULL) == NPT_ERROR_NO_SUCH_FILE); NPT_ASSERT(!NPT_File::Exists("foobar.doesnotexist")); // test special names NPT_File file(NPT_FILE_STANDARD_INPUT); NPT_ASSERT(NPT_SUCCEEDED(file.GetInfo(info))); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_SPECIAL); file = NPT_File(NPT_FILE_STANDARD_OUTPUT); NPT_ASSERT(NPT_SUCCEEDED(file.GetInfo(info))); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_SPECIAL); file = NPT_File(NPT_FILE_STANDARD_ERROR); NPT_ASSERT(NPT_SUCCEEDED(file.GetInfo(info))); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_SPECIAL); if (NPT_File::Exists("foobar.file1")) { result = NPT_File::DeleteFile("foobar.file1"); NPT_ASSERT(NPT_SUCCEEDED(result)); } result = CreateNewFile("foobar.file1", 9); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(NPT_File::Exists("foobar.file1")); result = NPT_File::GetInfo("foobar.file1", &info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR); NPT_ASSERT(info.m_Size == 9); { NPT_File f1("foobar.file1"); result = f1.GetInfo(info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR); NPT_ASSERT(info.m_Size == 9); } { NPT_File f1("foobar.file1"); NPT_LargeSize size; result = f1.GetSize(size); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(size == 9); } { NPT_File f1("foobar.file1"); result = f1.Rename("foobar.file1-r"); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(f1.GetPath() == "foobar.file1-r"); } NPT_ASSERT(NPT_File::Exists("foobar.file1-r")); result = NPT_File::GetInfo("foobar.file1-r", &info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR); NPT_ASSERT(info.m_Size == 9); // dirs NPT_ASSERT(!NPT_File::Exists("foobar.dir")); result = NPT_File::CreateDirectory("foobar.dir"); NPT_ASSERT(NPT_SUCCEEDED(result)); result = NPT_File::GetInfo("foobar.dir", &info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY); { NPT_File f1("foobar.dir"); result = f1.GetInfo(info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY); } NPT_String dirname = "foobar.dir"; NPT_String fname; fname = dirname; fname += NPT_FilePath::Separator; fname += "file1"; result = CreateNewFile(fname, 1); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file2"; result = CreateNewFile(fname, 2); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file3"; result = CreateNewFile(fname, 3); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_List<NPT_String> entries; result = NPT_File::ListDirectory("foobar.dir", entries); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(entries.GetItemCount() == 3); result = NPT_File::DeleteFile("foobar.dir"); NPT_ASSERT(NPT_FAILED(result)); result = NPT_File::DeleteDirectory("foobar.dir"); NPT_ASSERT(result == NPT_ERROR_DIRECTORY_NOT_EMPTY); result = NPT_File::Rename("foobar.dir", "foobar.dir-r"); NPT_ASSERT(NPT_SUCCEEDED(result)); dirname = "foobar.dir-r"; fname = dirname; fname += NPT_FilePath::Separator; fname += "file1"; result = NPT_File::DeleteFile(fname); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file2"; result = NPT_File::DeleteFile(fname); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file3"; result = NPT_File::DeleteFile(fname); NPT_ASSERT(NPT_SUCCEEDED(result)); result = NPT_File::DeleteDirectory("foobar.dir-r"); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(!NPT_File::Exists("foobar.dir-r")); // paths NPT_String test; test = NPT_FilePath::BaseName(""); NPT_ASSERT(test == ""); test = NPT_FilePath::BaseName("a"); NPT_ASSERT(test == "a"); test = NPT_FilePath::BaseName("a"+NPT_FilePath::Separator+"b"); NPT_ASSERT(test == "b"); test = NPT_FilePath::BaseName("a"+NPT_FilePath::Separator+"b"+NPT_FilePath::Separator); NPT_ASSERT(test == ""); test = NPT_FilePath::BaseName(NPT_FilePath::Separator+"a"); NPT_ASSERT(test == "a"); test = NPT_FilePath::BaseName(NPT_FilePath::Separator); NPT_ASSERT(test == ""); test = NPT_FilePath::DirectoryName(""); NPT_ASSERT(test == ""); test = NPT_FilePath::DirectoryName("a"); NPT_ASSERT(test == ""); test = NPT_FilePath::DirectoryName("a"+NPT_FilePath::Separator+"b"); NPT_ASSERT(test == "a"); test = NPT_FilePath::DirectoryName("a"+NPT_FilePath::Separator+"b"+NPT_FilePath::Separator); NPT_ASSERT(test == "a"+NPT_FilePath::Separator+"b"); test = NPT_FilePath::DirectoryName(NPT_FilePath::Separator+"a"); NPT_ASSERT(test == NPT_FilePath::Separator); test = NPT_FilePath::DirectoryName(NPT_FilePath::Separator); NPT_ASSERT(test == NPT_FilePath::Separator); // large files if (argc == 2) { result = CreateNewFile(argv[1], 0x10000, 0x10007); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_String new_name = argv[1]; new_name += ".renamed"; result = NPT_File::Rename(argv[1], new_name); NPT_ASSERT(NPT_SUCCEEDED(result)); file = NPT_File(new_name); result = file.Open(NPT_FILE_OPEN_MODE_READ); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_InputStreamReference input; file.GetInputStream(input); NPT_Position position; result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == 0); NPT_LargeSize large_size = (NPT_LargeSize)0x10007 * (NPT_LargeSize)0x10000; result = input->Seek(large_size-0x10007); NPT_ASSERT(NPT_SUCCEEDED(result)); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == large_size-0x10007); unsigned char* buffer = new unsigned char[0x10007]; result = input->ReadFully(buffer, 0x10007); NPT_ASSERT(NPT_SUCCEEDED(result)); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == large_size); for (unsigned int i=0; i<0x10007; i++) { NPT_ASSERT(buffer[i] == (unsigned char)i); } file.Close(); NPT_File::DeleteFile(new_name); } return 0; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int /*argc*/, char** /*argv*/) { // setup debugging #if defined(WIN32) && defined(_DEBUG) int flags = _crtDbgFlag | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF; _CrtSetDbgFlag(flags); //AllocConsole(); //freopen("CONOUT$", "w", stdout); #endif NPT_Result result; TcpServerThread* server_thread = NULL; NPT_TcpClientSocket* tcp_client = NULL; NPT_TcpServerSocket* tcp_server = NULL; CancellerThread* canceller = NULL; NPT_SocketAddress address(NPT_IpAddress(127,0,0,1), 10000); #if 0 result = RemoteIpAddress.ResolveName("www.google.com"); CHECK(result == NPT_SUCCESS); NPT_Console::Output("--- test for immediate connection\n"); NPT_Console::Output("[01] starting write server thread\n"); server_thread = new TcpServerThread(); server_thread->Start(); NPT_Console::Output("[01] waiting for server to be ready...\n"); server_thread->m_Ready.WaitUntilEquals(1); NPT_Console::Output("[01] server thread ready\n"); NPT_Console::Output("[01] waiting a while...\n"); NPT_System::Sleep(3.0); tcp_client = new NPT_TcpClientSocket(); NPT_Console::Output("[01] connection to 127.0.0.1:10000\n"); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_SUCCESS); delete tcp_client; NPT_Console::Output("[01] terminating server\n"); server_thread->m_Interrupted = true; server_thread->Wait(); delete server_thread; NPT_Console::Output("\n--- test for refused local connection\n"); address.SetPort(89); tcp_client = new NPT_TcpClientSocket(); NPT_Console::Output("[01] connecting to 127.0.0.1:89\n"); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_ERROR_CONNECTION_REFUSED); delete tcp_client; /*NPT_Console::Output("\n--- test for refused remote connection\n"); address.SetIpAddress(RemoteIpAddress); address.SetPort(81); tcp_client = new NPT_TcpClientSocket(); NPT_Console::Output("[01] connecting to www.google.com:81\n"); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_ERROR_CONNECTION_REFUSED); delete tcp_client;*/ NPT_Console::Output("\n--- test for connection timeout\n"); address.SetIpAddress(NPT_IpAddress(1,1,1,1)); NPT_Console::Output("[01] connecting to 1.1.1.1:89\n"); tcp_client = new NPT_TcpClientSocket(); result = tcp_client->Connect(address, 3000); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_ERROR_TIMEOUT); delete tcp_client; NPT_Console::Output("\n--- test for remote connection\n"); address.SetIpAddress(RemoteIpAddress); address.SetPort(80); NPT_Console::Output("[01] connecting to www.google.com:80\n"); tcp_client = new NPT_TcpClientSocket(); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_SUCCESS); delete tcp_client; #endif for (int i=0; i<2; i++) { NPT_Console::OutputF("\n--- test for cancelled connection, shutdown=%d\n", i); address.SetIpAddress(NPT_IpAddress(1,1,1,1)); address.SetPort(89); NPT_Console::Output("[01] connecting to 1.1.1.1:89\n"); tcp_client = new NPT_TcpClientSocket(NPT_SOCKET_FLAG_CANCELLABLE); canceller = new CancellerThread(tcp_client, 3.0f, i==1); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_ERROR_CANCELLED); canceller->Wait(); delete canceller; delete tcp_client; } for (int i=0; i<2; i++) { NPT_Console::OutputF("\n--- testing read cancellation, shutdown=%d\n", i); address.SetIpAddress(RemoteIpAddress); address.SetPort(80); NPT_Console::Output("[01] connecting to www.google.com:80\n"); tcp_client = new NPT_TcpClientSocket(NPT_SOCKET_FLAG_CANCELLABLE); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_SUCCESS); canceller = new CancellerThread(tcp_client, 3.0f, i==1); NPT_InputStreamReference input; tcp_client->GetInputStream(input); unsigned char buffer[4096]; NPT_SetMemory(buffer, 0, sizeof(buffer)); result = input->Read(buffer, 4096); NPT_Console::OutputF("{00} read returned %d (%s)\n", result, NPT_ResultText(result)); CHECK(result == NPT_ERROR_CANCELLED); delete tcp_client; canceller->Wait(); delete canceller; } for (int i=0; i<2; i++) { NPT_Console::OutputF("\n--- testing write cancellation, shutdown=%d\n", i); server_thread = new TcpServerThread(); server_thread->Start(); NPT_Console::Output("[01] waiting for server to be ready...\n"); server_thread->m_Ready.WaitUntilEquals(1); NPT_Console::Output("[01] server thread ready\n"); NPT_Console::Output("[01] waiting a while...\n"); NPT_System::Sleep(3.0); address.SetIpAddress(NPT_IpAddress(127,0,0,1)); address.SetPort(10000); NPT_Console::Output("[01] connecting to localhost:10000\n"); tcp_client = new NPT_TcpClientSocket(NPT_SOCKET_FLAG_CANCELLABLE); result = tcp_client->Connect(address); NPT_Console::OutputF("[01] connect returns %d : %s\n", result, NPT_ResultText(result)); CHECK(result == NPT_SUCCESS); canceller = new CancellerThread(tcp_client, 3.0f, i==1); NPT_OutputStreamReference output; tcp_client->GetOutputStream(output); NPT_Size total_written = 0; unsigned char buffer[4096]; NPT_SetMemory(buffer, 0, sizeof(buffer)); do { NPT_Size bytes_written = 0; result = output->Write(buffer, 4096, &bytes_written); if (NPT_SUCCEEDED(result)) { total_written += bytes_written; } } while (NPT_SUCCEEDED(result)); output = NULL; NPT_Console::OutputF("{01} write returned %d (%s)\n", result, NPT_ResultText(result)); NPT_Console::OutputF("{01} wrote %d bytes total\n", total_written); CHECK(result == NPT_ERROR_CANCELLED); delete tcp_client; canceller->Wait(); delete canceller; server_thread->m_Interrupted = true; server_thread->Wait(); delete server_thread; } for (int i=0; i<2; i++) { NPT_Console::OutputF("\n--- testing accept cancellation, shutdown=%d\n", i); NPT_Console::Output("{03} waiting for connection on port 10000\n"); address.SetIpAddress(NPT_IpAddress(127,0,0,1)); address.SetPort(10000); tcp_server = new NPT_TcpServerSocket(NPT_SOCKET_FLAG_CANCELLABLE); result = tcp_server->Bind(address, true); CHECK(result == NPT_SUCCESS); canceller = new CancellerThread(tcp_server, 3.0f, i==1); NPT_Socket* new_client = NULL; result = tcp_server->WaitForNewClient(new_client); NPT_Console::OutputF("{03} WaitForNewClient returned %d (%s)\n", result, NPT_ResultText(result)); CHECK(result == NPT_ERROR_CANCELLED); canceller->Wait(); delete canceller; delete tcp_server; } NPT_Console::Output("------------\n"); NPT_Console::Output("bye bye\n"); #if defined(WIN32) && defined(_DEBUG) _CrtDumpMemoryLeaks(); #endif return 0; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { NPT_Result result; NPT_FileInfo info; NPT_ASSERT(NPT_File::GetInfo("foobar.doesnotexist", NULL) == NPT_ERROR_NO_SUCH_FILE); NPT_ASSERT(!NPT_File::Exists("foobar.doesnotexist")); // test special names NPT_File file(NPT_FILE_STANDARD_INPUT); NPT_ASSERT(NPT_SUCCEEDED(file.GetInfo(info))); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_SPECIAL); file = NPT_File(NPT_FILE_STANDARD_OUTPUT); NPT_ASSERT(NPT_SUCCEEDED(file.GetInfo(info))); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_SPECIAL); file = NPT_File(NPT_FILE_STANDARD_ERROR); NPT_ASSERT(NPT_SUCCEEDED(file.GetInfo(info))); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_SPECIAL); if (NPT_File::Exists("foobar.file1")) { result = NPT_File::RemoveFile("foobar.file1"); NPT_ASSERT(NPT_SUCCEEDED(result)); } result = CreateNewFile("foobar.file1", 9); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(NPT_File::Exists("foobar.file1")); result = NPT_File::GetInfo("foobar.file1", &info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR); NPT_ASSERT(info.m_Size == 9); { NPT_File f1("foobar.file1"); result = f1.GetInfo(info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR); NPT_ASSERT(info.m_Size == 9); } { NPT_File f1("foobar.file1"); NPT_LargeSize size; result = f1.GetSize(size); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(size == 9); } { NPT_File f1("foobar.file1"); result = f1.Rename("foobar.file1-r"); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(f1.GetPath() == "foobar.file1-r"); } NPT_ASSERT(NPT_File::Exists("foobar.file1-r")); result = NPT_File::GetInfo("foobar.file1-r", &info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR); NPT_ASSERT(info.m_Size == 9); // dirs NPT_ASSERT(!NPT_File::Exists("foobar.dir")); result = NPT_File::CreateDir("foobar.dir"); NPT_ASSERT(NPT_SUCCEEDED(result)); result = NPT_File::GetInfo("foobar.dir", &info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY); { NPT_File f1("foobar.dir"); result = f1.GetInfo(info); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY); } NPT_String dirname = "foobar.dir"; NPT_String fname; fname = dirname; fname += NPT_FilePath::Separator; fname += "file1"; result = CreateNewFile(fname, 1); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file2"; result = CreateNewFile(fname, 2); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file3"; result = CreateNewFile(fname, 3); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_List<NPT_String> entries; result = NPT_File::ListDir("foobar.dir", entries); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(entries.GetItemCount() == 3); result = NPT_File::RemoveFile("foobar.dir"); NPT_ASSERT(NPT_FAILED(result)); result = NPT_File::RemoveDir("foobar.dir"); NPT_ASSERT(result == NPT_ERROR_DIRECTORY_NOT_EMPTY); result = NPT_File::Rename("foobar.dir", "foobar.dir-r"); NPT_ASSERT(NPT_SUCCEEDED(result)); dirname = "foobar.dir-r"; fname = dirname; fname += NPT_FilePath::Separator; fname += "file1"; result = NPT_File::RemoveFile(fname); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file2"; result = NPT_File::RemoveFile(fname); NPT_ASSERT(NPT_SUCCEEDED(result)); fname = dirname; fname += NPT_FilePath::Separator; fname += "file3"; result = NPT_File::RemoveFile(fname); NPT_ASSERT(NPT_SUCCEEDED(result)); result = NPT_File::RemoveDir("foobar.dir-r"); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(!NPT_File::Exists("foobar.dir-r")); // paths NPT_String test; test = NPT_FilePath::BaseName(""); NPT_ASSERT(test == ""); test = NPT_FilePath::BaseName("a"); NPT_ASSERT(test == "a"); test = NPT_FilePath::BaseName("a"+NPT_FilePath::Separator+"b"); NPT_ASSERT(test == "b"); test = NPT_FilePath::BaseName("a"+NPT_FilePath::Separator+"b"+NPT_FilePath::Separator); NPT_ASSERT(test == ""); test = NPT_FilePath::BaseName(NPT_FilePath::Separator+"a"); NPT_ASSERT(test == "a"); test = NPT_FilePath::BaseName(NPT_FilePath::Separator); NPT_ASSERT(test == ""); test = NPT_FilePath::DirName(""); NPT_ASSERT(test == ""); test = NPT_FilePath::DirName("a"); NPT_ASSERT(test == ""); test = NPT_FilePath::DirName("a"+NPT_FilePath::Separator+"b"); NPT_ASSERT(test == "a"); test = NPT_FilePath::DirName("a"+NPT_FilePath::Separator+"b"+NPT_FilePath::Separator); NPT_ASSERT(test == "a"+NPT_FilePath::Separator+"b"); test = NPT_FilePath::DirName(NPT_FilePath::Separator+"a"); NPT_ASSERT(test == NPT_FilePath::Separator); test = NPT_FilePath::DirName(NPT_FilePath::Separator); NPT_ASSERT(test == NPT_FilePath::Separator); // small files result = CreateNewFile("small.bin", 0x100, 0x107); NPT_ASSERT(NPT_SUCCEEDED(result)); file = NPT_File("small.bin"); result = file.Open(NPT_FILE_OPEN_MODE_READ); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_InputStreamReference input; file.GetInputStream(input); NPT_Position position; result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == 0); NPT_LargeSize large_size = (NPT_LargeSize)0x107 * (NPT_LargeSize)0x100; result = input->Seek(large_size-0x107); NPT_ASSERT(NPT_SUCCEEDED(result)); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == large_size-0x107); unsigned char* buffer = new unsigned char[0x107]; result = input->ReadFully(buffer, 0x107); NPT_ASSERT(NPT_SUCCEEDED(result)); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == large_size); for (unsigned int i=0; i<0x107; i++) { NPT_ASSERT(buffer[i] == (unsigned char)i); } file.Close(); NPT_File::RemoveFile(file.GetPath()); // large files if (argc == 2) { result = CreateNewFile(argv[1], 0x10000, 0x10007); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_String new_name = argv[1]; new_name += ".renamed"; result = NPT_File::Rename(argv[1], new_name); NPT_ASSERT(NPT_SUCCEEDED(result)); file = NPT_File(new_name); result = file.Open(NPT_FILE_OPEN_MODE_READ); NPT_ASSERT(NPT_SUCCEEDED(result)); file.GetInputStream(input); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == 0); large_size = (NPT_LargeSize)0x10007 * (NPT_LargeSize)0x10000; result = input->Seek(large_size-0x10007); NPT_ASSERT(NPT_SUCCEEDED(result)); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == large_size-0x10007); buffer = new unsigned char[0x10007]; result = input->ReadFully(buffer, 0x10007); NPT_ASSERT(NPT_SUCCEEDED(result)); result = input->Tell(position); NPT_ASSERT(NPT_SUCCEEDED(result)); NPT_ASSERT(position == large_size); for (unsigned int i=0; i<0x10007; i++) { NPT_ASSERT(buffer[i] == (unsigned char)i); } file.Close(); NPT_File::RemoveFile(new_name); } // test dynamic size //NPT_LargeSize size; unsigned char buff[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; const char* filename = "pi.\xCF\x80.test"; NPT_TimeInterval wait(2.0f); if (argc > 1) { filename = argv[1]; } NPT_File file1(filename); NPT_OutputStreamReference output; NPT_ASSERT(NPT_SUCCEEDED(file1.Open(NPT_FILE_OPEN_MODE_CREATE | NPT_FILE_OPEN_MODE_WRITE | NPT_FILE_OPEN_MODE_READ | NPT_FILE_OPEN_MODE_TRUNCATE))); NPT_ASSERT(NPT_SUCCEEDED(file1.GetSize(size))); NPT_ASSERT(size == 0); NPT_ASSERT(NPT_SUCCEEDED(file1.GetOutputStream(output))); NPT_ASSERT(NPT_SUCCEEDED(file1.GetInputStream(input))); NPT_ASSERT(NPT_SUCCEEDED(output->Tell(position))); NPT_ASSERT(position == 0); NPT_ASSERT(NPT_SUCCEEDED(input->Tell(position))); NPT_ASSERT(position == 0); NPT_ASSERT(NPT_SUCCEEDED(output->WriteFully(buff, 16))); output->Flush(); NPT_System::Sleep(wait); NPT_ASSERT(NPT_SUCCEEDED(file1.GetSize(size))); NPT_ASSERT(size == 16); NPT_ASSERT(NPT_SUCCEEDED(output->Tell(position))); NPT_ASSERT(NPT_SUCCEEDED(input->GetSize(size))); NPT_ASSERT(size == 16); NPT_ASSERT(position == 16); NPT_ASSERT(NPT_SUCCEEDED(input->Tell(position))); NPT_ASSERT(position == 16); NPT_ASSERT(NPT_SUCCEEDED(output->Seek(8))); NPT_ASSERT(NPT_SUCCEEDED(output->Tell(position))); NPT_ASSERT(position == 8); NPT_File file2(filename); NPT_InputStreamReference input2; NPT_ASSERT(NPT_SUCCEEDED(file2.Open(NPT_FILE_OPEN_MODE_READ))); NPT_ASSERT(NPT_SUCCEEDED(file2.GetSize(size))); NPT_ASSERT(size == 16); NPT_ASSERT(NPT_SUCCEEDED(file2.GetInputStream(input2))); NPT_ASSERT(NPT_SUCCEEDED(input2->GetSize(size))); NPT_ASSERT(size == 16); NPT_ASSERT(NPT_SUCCEEDED(input2->Tell(position))); NPT_ASSERT(position == 0); NPT_ASSERT(NPT_SUCCEEDED(input2->Seek(8))); NPT_ASSERT(NPT_SUCCEEDED(input2->Tell(position))); NPT_ASSERT(position == 8); NPT_ASSERT(NPT_SUCCEEDED(output->WriteFully(buff, 16))); output->Flush(); NPT_System::Sleep(wait); NPT_ASSERT(NPT_SUCCEEDED(file2.GetSize(size))); NPT_ASSERT(size == 24); NPT_ASSERT(NPT_SUCCEEDED(output->Tell(position))); NPT_ASSERT(position == 24); NPT_ASSERT(NPT_SUCCEEDED(input->Tell(position))); NPT_ASSERT(position == 24); NPT_ASSERT(NPT_SUCCEEDED(input2->GetSize(size))); NPT_ASSERT(size == 24); NPT_ASSERT(NPT_SUCCEEDED(input2->Seek(20))); NPT_ASSERT(NPT_SUCCEEDED(input2->Read(buff, 4, NULL))); return 0; }