Пример #1
0
/*----------------------------------------------------------------------
|   NPT_String::SetLength
+---------------------------------------------------------------------*/
NPT_Result
NPT_String::SetLength(NPT_Size length, bool pad)
{
    // special case for 0
    if (length == 0) {
        Reset();
        return NPT_SUCCESS;
    }
    
    // reserve the space
    Reserve(length);

    // pad with spaces if necessary
    char* chars = UseChars();
    if (pad) {
        unsigned int current_length = GetLength();
        if (length > current_length) {
            unsigned int pad_length = length-current_length;
            NPT_SetMemory(chars+current_length, ' ', pad_length);
        }
    }
    
    // update the length and terminate the buffer
    GetBuffer()->SetLength(length);
    chars[length] = '\0';
    
    return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
 |   TestBenchmark
 +---------------------------------------------------------------------*/
static int
TestBenchmark()
{
    unsigned char* data = new unsigned char[16*1024];
    NPT_SetMemory(data, 0, sizeof(16*1024));
    NPT_TimeStamp before;
    NPT_TimeStamp after;
    float         elapsed;
    unsigned char key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
    NPT_BlockCipher* cipher;
    NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, 
                            NPT_BlockCipher::ENCRYPT,
                            key,
                            16,
                            cipher);
    NPT_System::GetCurrentTimeStamp(before);
    unsigned int block_count = 0;
    do {
        unsigned char out[16];
        for (unsigned int i=0; i<1024; i++) {
            cipher->ProcessBlock(data+16*i, out);
        }
        block_count += 1024;
        NPT_System::GetCurrentTimeStamp(after);
        elapsed  = after.ToSeconds()-before.ToSeconds();
    } while (elapsed < 10.0f);
    NPT_Console::OutputF("AES: %d blocks in 10 seconds: %f MB/s\n", block_count, ((block_count*16.0f)/1000000.0f)/elapsed);
    delete data;
    
    return 0;
}
Пример #3
0
/*----------------------------------------------------------------------
|   NPT_ZipInflateState::NPT_ZipInflateState
+---------------------------------------------------------------------*/
NPT_ZipInflateState::NPT_ZipInflateState()
{
    // initialize the state
    NPT_SetMemory(&m_Stream, 0, sizeof(m_Stream));

    // initialize the decompressor
    inflateInit2(&m_Stream, 15+32); // 15 = default window bits, +32 = automatic header
}
Пример #4
0
/*----------------------------------------------------------------------
|   NPT_File::GetInfo
+---------------------------------------------------------------------*/
NPT_Result
NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
{
    // default value
    if (info) NPT_SetMemory(info, 0, sizeof(*info));

    return NPT_SUCCESS;
}
Пример #5
0
/*----------------------------------------------------------------------
|   NPT_Zip::Deflate
+---------------------------------------------------------------------*/
NPT_Result 
NPT_Zip::Deflate(const NPT_DataBuffer& in,
                 NPT_DataBuffer&       out,
                 int                   compression_level,
                 Format                format /* = ZLIB */)
{
    // default return state
    out.SetDataSize(0);
    
    // check parameters
    if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
        compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
        return NPT_ERROR_INVALID_PARAMETERS;
    }
                
    // setup the stream
    z_stream stream;
    NPT_SetMemory(&stream, 0, sizeof(stream));
    stream.next_in   = (Bytef*)in.GetData();
    stream.avail_in  = (uInt)in.GetDataSize();
    
    // setup the memory functions
    stream.zalloc = (alloc_func)0;
    stream.zfree = (free_func)0;
    stream.opaque = (voidpf)0;

    // initialize the compressor
    int err = deflateInit2(&stream, 
                           compression_level,
                           Z_DEFLATED,
                           15 + (format == GZIP ? 16 : 0),
                           8,
                           Z_DEFAULT_STRATEGY);
    if (err != Z_OK) return MapError(err);

    // reserve an output buffer known to be large enough
    out.Reserve(deflateBound(&stream, stream.avail_in) + (format==GZIP?10:0));
    stream.next_out  = out.UseData();
    stream.avail_out = out.GetBufferSize();

    // decompress
    err = deflate(&stream, Z_FINISH);
    if (err != Z_STREAM_END) {
        deflateEnd(&stream);
        return MapError(err);
    }
    
    // update the output size
    out.SetDataSize(stream.total_out);

    // cleanup
    err = deflateEnd(&stream);
    return MapError(err);
}
/*----------------------------------------------------------------------
|   NPT_File::GetInfo
+---------------------------------------------------------------------*/
NPT_Result
NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
{
    // default value
    if (info) NPT_SetMemory(info, 0, sizeof(*info));
    
#if defined(_WIN32) || defined(_XBOX)
    // On Windows, stat will fail if a dir ends with a separator
    NPT_String _path = path;
    _path.TrimRight("\\/");
    // keep a separator at the end for drive names such as C:<backslash>
    if (NPT_StringLength(_path) ==  2 && _path[1] == ':') {
        _path += NPT_FilePath::Separator;
    }
#else
#define _path path
#endif
    
    // get the file info
    NPT_stat_struct stat_buffer;
    int result = NPT_stat(_path, &stat_buffer);
    if (result != 0) return MapErrno(errno);
    
    // setup the returned fields
    if (info) {
        info->m_Size = stat_buffer.st_size;
        if (S_ISREG(stat_buffer.st_mode)) {
            info->m_Type = NPT_FileInfo::FILE_TYPE_REGULAR;
        } else if (S_ISDIR(stat_buffer.st_mode)) {
            info->m_Type = NPT_FileInfo::FILE_TYPE_DIRECTORY;
        } else {
            info->m_Type = NPT_FileInfo::FILE_TYPE_OTHER;
        }
        info->m_AttributesMask &= NPT_FILE_ATTRIBUTE_READ_ONLY;
        if ((stat_buffer.st_mode & S_IWUSR) == 0) {
            info->m_Attributes &= NPT_FILE_ATTRIBUTE_READ_ONLY;
        }        
#if defined(NPT_CONFIG_HAVE_STAT_ST_BIRTHTIME)
        info->m_CreationTime.SetSeconds(stat_buffer.st_birthtime);
#elif defined(NPT_CONFIG_STAT_ST_CTIME_IS_ST_BIRTHTIME)
        info->m_CreationTime.SetSeconds(stat_buffer.st_ctime);
#else
        info->m_CreationTime.SetSeconds(0);
#endif
        info->m_ModificationTime.SetSeconds(stat_buffer.st_mtime);
    }

    return NPT_SUCCESS;
}
Пример #7
0
/*----------------------------------------------------------------------
|   NPT_IpAddress::Parse
+---------------------------------------------------------------------*/
NPT_Result
NPT_IpAddress::Parse(const char* name)
{
    // check the name
    if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS;

    // clear the address
    NPT_SetMemory(&m_Address[0], 0, sizeof(m_Address));

    // parse
    unsigned int  fragment;
    bool          fragment_empty = true;
    unsigned char address[4];
    unsigned int  accumulator;
    for (fragment = 0, accumulator = 0; fragment < 4; ++name) {
        if (*name == '\0' || *name == '.') {
            // fragment terminator
            if (fragment_empty) return NPT_ERROR_INVALID_SYNTAX;
            address[fragment++] = accumulator;
            if (*name == '\0') break;
            accumulator = 0;
            fragment_empty = true;
        } else if (*name >= '0' && *name <= '9') {
            // numerical character
            accumulator = accumulator*10 + (*name - '0');
            if (accumulator > 255) return NPT_ERROR_INVALID_SYNTAX;
            fragment_empty = false; 
        } else {
            // invalid character
            return NPT_ERROR_INVALID_SYNTAX;
        }
    }

    if (fragment == 4 && *name == '\0' && !fragment_empty) {
        m_Address[0] = address[0];
        m_Address[1] = address[1];
        m_Address[2] = address[2];
        m_Address[3] = address[3];
        return NPT_SUCCESS;
    } else {
        return NPT_ERROR_INVALID_SYNTAX;
    }
}
Пример #8
0
/*----------------------------------------------------------------------
|   NPT_ZipDeflateState::NPT_ZipDeflateState
+---------------------------------------------------------------------*/
NPT_ZipDeflateState::NPT_ZipDeflateState(int             compression_level,
                                         NPT_Zip::Format format)
{
    // check parameters
    if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
        compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
        compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT;
    }

    // initialize the state
    NPT_SetMemory(&m_Stream, 0, sizeof(m_Stream));

    // initialize the compressor
    deflateInit2(&m_Stream, 
                compression_level,
                Z_DEFLATED,
                15 + (format == NPT_Zip::GZIP ? 16 : 0),
                8,
                Z_DEFAULT_STRATEGY);
}
Пример #9
0
/*----------------------------------------------------------------------
|   NPT_Win32SerialPort::Open
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32SerialPort::Open(unsigned int              speed, 
                          NPT_SerialPortStopBits    stop_bits,
                          NPT_SerialPortFlowControl flow_control,
                          NPT_SerialPortParity      parity)
{
    // check if we're already open
    if (!m_HandleReference.IsNull()) {
        return NPT_ERROR_SERIAL_PORT_ALREADY_OPEN;
    }

    HANDLE handle = CreateFile(m_Name,  
                               GENERIC_READ | GENERIC_WRITE, 
                               0, 
                               0, 
                               OPEN_EXISTING,
                               0,
                               0);
    if (handle == INVALID_HANDLE_VALUE) {
        return NPT_ERROR_NO_SUCH_SERIAL_PORT;
    }

    // set the parameters
    DCB dcb;
    NPT_SetMemory(&dcb, 0, sizeof(dcb));
    dcb.DCBlength = sizeof(DCB);
    if (!GetCommState(handle, &dcb)) {
        CloseHandle(handle);
        return NPT_FAILURE;
    }
    dcb.fBinary = TRUE;
    dcb.BaudRate = speed;
    switch (stop_bits) {
        case NPT_SERIAL_PORT_STOP_BITS_1: dcb.StopBits   = ONESTOPBIT; break;
        case NPT_SERIAL_PORT_STOP_BITS_1_5: dcb.StopBits = ONE5STOPBITS; break;
        case NPT_SERIAL_PORT_STOP_BITS_2: dcb.StopBits   = TWOSTOPBITS; break;
    }
    switch (flow_control) {
        case NPT_SERIAL_PORT_FLOW_CONTROL_NONE:
            dcb.fOutX = dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = FALSE;
            dcb.fInX = dcb.fDsrSensitivity = FALSE;
            dcb.fRtsControl = RTS_CONTROL_DISABLE;
            dcb.fDtrControl = DTR_CONTROL_DISABLE;
            break;

        case NPT_SERIAL_PORT_FLOW_CONTROL_HARDWARE:
            dcb.fOutX = dcb.fOutxDsrFlow = FALSE;
            dcb.fOutxCtsFlow = TRUE;
            dcb.fInX = dcb.fDsrSensitivity = FALSE;
            dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
            dcb.fDtrControl = DTR_CONTROL_DISABLE;
            break;

        case NPT_SERIAL_PORT_FLOW_CONTROL_XON_XOFF:
            dcb.fOutX = TRUE;
            dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = FALSE;
            dcb.fInX = TRUE;
            dcb.fDsrSensitivity = FALSE;
            dcb.fRtsControl = RTS_CONTROL_DISABLE;
            dcb.fDtrControl = DTR_CONTROL_DISABLE;
            break;
    }
    switch (parity) {
        case NPT_SERIAL_PORT_PARITY_NONE: dcb.fParity = FALSE; dcb.Parity = NOPARITY; break;
        case NPT_SERIAL_PORT_PARITY_EVEN: dcb.fParity = TRUE;  dcb.Parity = EVENPARITY; break;
        case NPT_SERIAL_PORT_PARITY_ODD: dcb.fParity  = TRUE;  dcb.Parity = ODDPARITY; break;
        case NPT_SERIAL_PORT_PARITY_MARK: dcb.fParity = TRUE;  dcb.Parity = MARKPARITY; break;
    }
    if (!SetCommState(handle, &dcb)) {
        CloseHandle(handle);
        return NPT_FAILURE;
    }

    // create a reference to the FILE object
    m_HandleReference = new NPT_Win32HandleWrapper(handle);

    return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
|   TestBlockCiphers
+---------------------------------------------------------------------*/
static int
TestBlockCiphers()
{
    NPT_BlockCipher* cipher = NULL;
    NPT_UInt8        b0[16];
    NPT_UInt8        k1[16] =  
        { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
          0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
    NPT_UInt8        pt1[16] =       
        { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
    NPT_UInt8        ct1[16] =    
        { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 
          0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a };
    
    NPT_Result result;
    result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, 
                                     NPT_BlockCipher::ENCRYPT,
                                     k1,
                                     16,
                                     cipher);
    SHOULD_SUCCEED(result);
    SHOULD_EQUAL(cipher->GetBlockSize(), 16);
    result = cipher->ProcessBlock(pt1, b0);
    SHOULD_SUCCEED(result);
    SHOULD_EQUAL_MEM(b0, ct1, 16);
    delete cipher;
    
    result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, 
                                     NPT_BlockCipher::DECRYPT,
                                     k1,
                                     16,
                                     cipher);
    SHOULD_SUCCEED(result);
    SHOULD_EQUAL(cipher->GetBlockSize(), 16);
    result = cipher->ProcessBlock(ct1, b0);
    SHOULD_SUCCEED(result);
    SHOULD_EQUAL_MEM(b0, pt1, 16);
    delete cipher;

    NPT_UInt8 key[16];
    NPT_CopyMemory(key, k1, 16);
    for (unsigned int i=0; i<100; i++) {
        NPT_BlockCipher* encrypter;
        NPT_BlockCipher* decrypter;
        result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, 
                                         NPT_BlockCipher::ENCRYPT,
                                         key,
                                         16,
                                         encrypter);
        result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, 
                                         NPT_BlockCipher::DECRYPT,
                                         key,
                                         16,
                                         decrypter);
        NPT_UInt8 mem1[16];
        NPT_UInt8 mem2[16];
        NPT_UInt8 mem3[16];
        NPT_SetMemory(mem1, 0, 16);
        for (unsigned int j=0; j<1000; j++) {
            encrypter->ProcessBlock(mem1, mem2);
            decrypter->ProcessBlock(mem2, mem3);
            SHOULD_EQUAL_MEM(mem1, mem3, 16);
            NPT_CopyMemory(mem1, mem2, 16);
        }
        delete encrypter;
        delete decrypter;
        NPT_CopyMemory(key, mem1, 16);
    }
    
    return 0;
}
Пример #11
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;
}