Пример #1
0
/*----------------------------------------------------------------------
|   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;
}
Пример #2
0
/*----------------------------------------------------------------------
|   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;
}
Пример #3
0
/*----------------------------------------------------------------------
|   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));
}
Пример #4
0
/*----------------------------------------------------------------------
|   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);
}
Пример #5
0
/*----------------------------------------------------------------------
|   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;
}
Пример #6
0
/*----------------------------------------------------------------------
|   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;
}
Пример #7
0
/*----------------------------------------------------------------------
|   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));
    }
}
Пример #9
0
/*----------------------------------------------------------------------
|   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;
}
Пример #10
0
/*----------------------------------------------------------------------
|   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;
}
Пример #11
0
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);
}
Пример #12
0
/*----------------------------------------------------------------------
|   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;
}
Пример #13
0
/*----------------------------------------------------------------------
|   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;
}
Пример #14
0
/*----------------------------------------------------------------------
|       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;
    }
}
Пример #15
0
/*----------------------------------------------------------------------
|   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;
}
Пример #16
0
/*----------------------------------------------------------------------
|       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;
}
Пример #17
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
}
Пример #18
0
/*----------------------------------------------------------------------
|   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;
}
Пример #19
0
/*----------------------------------------------------------------------
|       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;
            }
        }
    }
}
Пример #20
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::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;
}
Пример #21
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;
}
Пример #22
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;
}