////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2001 Microsoft Corporation // // Module Name: // tdisample.cpp // // Abstract: // test executable--demonstrates the tdi client by calling it via the library // ////////////////////////////////////////////////////////////////////////// #include "libbase.h" const ULONG MAX_ADDRESS_SIZE = sizeof(TRANSPORT_ADDRESS) + TDI_ADDRESS_LENGTH_OSI_TSAP; const USHORT DGRAM_SERVER_PORT = 0x5555; const USHORT DGRAM_CLIENT_PORT = 0x4444; const USHORT CONN_SERVER_PORT = 0x5656; const USHORT CONN_CLIENT_PORT = 0x4545; VOID ServerTest(ULONG ulType, ULONG ulNumDevices); VOID ClientTest(ULONG ulType, ULONG ulNumDevices); ///////////////////////////////////////////////// // // Function: main // // Descript: parse the arguments to the program, initialize library and driver, // then call client or server side of test // ///////////////////////////////////////////////// int __cdecl main(ULONG argc, TCHAR *argv[]) { // // first step: get the arguments for this run // BOOLEAN fIsServer = FALSE; ULONG ulType = TDI_ADDRESS_TYPE_UNSPEC; BOOLEAN fArgsOk = FALSE; TCHAR *pArgStr; if(argc > 1) { for(ULONG ulArg = 1; ulArg < argc; ulArg++) { pArgStr = argv[ulArg]; if ((*pArgStr == TEXT('/')) || (*pArgStr == TEXT('-'))) { pArgStr++; } if (_tcsicmp(pArgStr, TEXT("server")) == 0) { if (fIsServer) { fArgsOk = FALSE; break; } fIsServer = TRUE; } else { fArgsOk = FALSE; if (ulType) { break; } if (_tcsicmp(pArgStr, TEXT("ipx")) == 0) { fArgsOk = TRUE; ulType = TDI_ADDRESS_TYPE_IPX; } else if (_tcsicmp(pArgStr, TEXT("ipv4")) == 0) { fArgsOk = TRUE; ulType = TDI_ADDRESS_TYPE_IP; } else if (_tcsicmp(pArgStr, TEXT("netbt")) == 0) { fArgsOk = TRUE; ulType = TDI_ADDRESS_TYPE_NETBIOS; } else { break; } } } } if (!fArgsOk) { _putts(TEXT("Usage: tdisample [/server] [/ipx | /ipv4 | /netbt] \n")); return 0; } // // ready to go. Initialize the library, connect to the driver, etc // if (TdiLibInit()) { // // change this to limit debug output for kernel mode driver // 0 = none, 1 = commands, 2 = handlers, 3 = both // DoDebugLevel(0x03); ULONG ulNumDevices = DoGetNumDevices(ulType); if (ulNumDevices) { if (fIsServer) { ServerTest(ulType, ulNumDevices); } else { ClientTest(ulType, ulNumDevices); } } TdiLibClose(); } return 0; } ////////////////////////////////////////////////////////////////////////// // server-side test functions ////////////////////////////////////////////////////////////////////////// ULONG_PTR __cdecl ServerThread(LPVOID pvDummy); BOOLEAN WaitForClient( ULONG TdiHandle, PTRANSPORT_ADDRESS pRemoteAddr ); CRITICAL_SECTION CriticalSection; HANDLE hEvent; ULONG ulServerCount; ///////////////////////////////////////////////// // // Function: IncServerCount // // Descript: multi-thread safe incrementing of server count // ///////////////////////////////////////////////// VOID IncServerCount() { EnterCriticalSection(&CriticalSection); ++ulServerCount; LeaveCriticalSection(&CriticalSection); } ///////////////////////////////////////////////// // // Function: DecServerCount // // Descript: multi-thread safe decrementing of server count // when last one done, sets event // ///////////////////////////////////////////////// VOID DecServerCount() { BOOLEAN fDone = FALSE; EnterCriticalSection(&CriticalSection); --ulServerCount; if (!ulServerCount) { fDone = TRUE; } LeaveCriticalSection(&CriticalSection); if (fDone) { SetEvent(hEvent); } } struct THREAD_DATA { ULONG ulType; ULONG ulSlot; }; typedef THREAD_DATA *PTHREAD_DATA; // ---------------------------------------------- // // Function: ServerTest // // Arguments: ulType -- protocol type to use // NumDevices -- number of devices of this protocol type // // Descript: this function controls the server side of the test // // ---------------------------------------------- VOID ServerTest(ULONG ulType, ULONG ulNumDevices) { // // initialize globals // try { InitializeCriticalSection(&CriticalSection); } catch(...) { return; } hEvent = CreateEvent(NULL, TRUE, // manual reset FALSE, // starts reset NULL); ulServerCount = 1; // a single bogus reference, so event doesn't fire prematurely // // go thru our list of nodes, starting a thread for each one // for(ULONG ulCount = 0; ulCount < ulNumDevices; ulCount++) { ULONG ulThreadId; PTHREAD_DATA pThreadData = (PTHREAD_DATA)LocalAllocateMemory(sizeof(THREAD_DATA)); if (!pThreadData) { _putts(TEXT("ServerTest: unable to allocate memory for pThreadData\n")); break; } pThreadData->ulType = ulType; pThreadData->ulSlot = ulCount; // // reference for one starting now // IncServerCount(); HANDLE hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0, (LPTHREAD_START_ROUTINE)ServerThread, (LPVOID)pThreadData, 0, &ulThreadId); if (!hThread) { _putts(TEXT("ServerTest: failed starting server thread\n")); DecServerCount(); } Sleep(100); } // // get rid of bogus reference // DecServerCount(); // // wait until all the threads have completed // WaitForSingleObject(hEvent, INFINITE); // // cleanup // CloseHandle(hEvent); DeleteCriticalSection(&CriticalSection); } ///////////////////////////////////////////////// // // Function: ServerThread // // Arguments: pvData -- actually pThreadData for this server // // Descript: This is the thread that runs for each server instance // ///////////////////////////////////////////////// ULONG_PTR __cdecl ServerThread(LPVOID pvData) { PTHREAD_DATA pThreadData = (PTHREAD_DATA)pvData; PTRANSPORT_ADDRESS pTransAddr = NULL; PTRANSPORT_ADDRESS pRemoteAddr = NULL; TCHAR *pDeviceName = NULL; BOOLEAN fSuccessful = FALSE; while (TRUE) { // // stores local interface address (server) // pTransAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE); if (!pTransAddr) { _putts(TEXT("ServerThread: unable to allocate memory for pTransAddr\n")); break; } pTransAddr->TAAddressCount = 1; // // stores remote interface address (client) // pRemoteAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE); if (!pRemoteAddr) { _putts(TEXT("ServerThread: unable to allocate memory for pRemoteAddr\n")); break; } pRemoteAddr->TAAddressCount = 1; // // stores local interface name (server) // pDeviceName = (TCHAR *)LocalAllocateMemory(256 * sizeof(TCHAR)); if (!pDeviceName) { _putts(TEXT("ServerThread: unable to allocate memory for pDeviceName\n")); break; } // // get name of local device // if (DoGetDeviceName(pThreadData->ulType, pThreadData->ulSlot, pDeviceName) != STATUS_SUCCESS) { break; } TCHAR *pDataDeviceName = NULL; TCHAR *pConnDeviceName = NULL; // // for netbios, each "address" has its own name. You open a device based mostly on the name // if (pThreadData->ulType == TDI_ADDRESS_TYPE_NETBIOS) { pDataDeviceName = pDeviceName; pConnDeviceName = pDeviceName; PTA_NETBIOS_ADDRESS pTaAddr = (PTA_NETBIOS_ADDRESS)pTransAddr; pTaAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; pTaAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_NETBIOS; pTaAddr->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; memcpy(pTaAddr->Address[0].Address[0].NetbiosName, "SERVER", 7); // NOTE: ascii string } // // for others, there is one name for the datagram device and another for the "connected" // device. You open an interface based largely on the address // else { if (DoGetAddress(pThreadData->ulType, pThreadData->ulSlot, pTransAddr) != STATUS_SUCCESS) { break; } switch (pThreadData->ulType) { case TDI_ADDRESS_TYPE_IPX: { PTA_IPX_ADDRESS pAddr = (PTA_IPX_ADDRESS)pTransAddr; pAddr->Address[0].Address[0].Socket = DGRAM_SERVER_PORT; pDataDeviceName = TEXT("\\device\\nwlnkipx"); pConnDeviceName = TEXT("\\device\\nwlnkspx"); break; } case TDI_ADDRESS_TYPE_IP: { PTA_IP_ADDRESS pAddr = (PTA_IP_ADDRESS)pTransAddr; pAddr->Address[0].Address[0].sin_port = DGRAM_SERVER_PORT; pDataDeviceName = TEXT("\\device\\udp"); pConnDeviceName = TEXT("\\device\\tcp"); break; } } } _tprintf(TEXT("ServerThread: DeviceName: %s\n"), pDeviceName); _putts(TEXT("Device Address:\n")); DoPrintAddress(pTransAddr); // // wait for a client to contact us // ULONG TdiHandle = DoOpenAddress(pDataDeviceName, pTransAddr); if (!TdiHandle) { _putts(TEXT("ServerThread: failed to open address object\n")); break; } DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR); DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE_DATAGRAM); if (!WaitForClient(TdiHandle, pRemoteAddr)) { _putts(TEXT("ServerThread: Timed out waiting for client\n")); DoCloseAddress(TdiHandle); break; } _putts(TEXT("ServerThread: Found by client. Client address:\n")); DoPrintAddress(pTransAddr); // // echo datagram packets until we get one that is TEXT("Last Packet"), or until we time out // for (ULONG ulCount = 1; ulCount < 60000; ulCount++) { ULONG ulNumBytes; PUCHAR pucData; Sleep(10); ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, pRemoteAddr, &pucData); if (ulNumBytes) { DoSendDatagram(TdiHandle, pRemoteAddr, pucData, ulNumBytes); TCHAR *pString = (TCHAR *)pucData; _tprintf(TEXT("ServerThread: Packet Received: %s\n"), pString); if (_tcscmp(pString, TEXT("Last Packet"))) { ulCount = 0; } LocalFreeMemory(pucData); if (ulCount) { _putts(TEXT("ServerThread: Exitting datagram receive loop\n")); break; } } } Sleep(50); DoCloseAddress(TdiHandle); // // now, open an endpoint, and wait for a connection request // switch (pThreadData->ulType) { case TDI_ADDRESS_TYPE_IPX: { PTA_IPX_ADDRESS pAddr = (PTA_IPX_ADDRESS)pTransAddr; pAddr->Address[0].Address[0].Socket = CONN_SERVER_PORT; break; } case TDI_ADDRESS_TYPE_IP: { PTA_IP_ADDRESS pAddr = (PTA_IP_ADDRESS)pTransAddr; pAddr->Address[0].Address[0].sin_port = CONN_SERVER_PORT; break; } } TdiHandle = DoOpenEndpoint(pConnDeviceName, pTransAddr); if (!TdiHandle) { _putts(TEXT("ServerThread: unable to open endpoint\n")); break; } DoEnableEventHandler(TdiHandle, TDI_EVENT_CONNECT); DoEnableEventHandler(TdiHandle, TDI_EVENT_DISCONNECT); DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR); DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE); fSuccessful = FALSE; for (ULONG ulCount = 0; ulCount < 100; ulCount++) { if (DoIsConnected(TdiHandle)) { _putts(TEXT("ServerThread: connect successful\n")); fSuccessful = TRUE; break; } Sleep(20); } if (!fSuccessful) { _putts(TEXT("ServerThread: timed out waiting for connect\n")); DoCloseEndpoint(TdiHandle); break; } // // echo packets until we get one that is TEXT("Last Packet") // for (ULONG ulCount = 0; ulCount < 60000; ulCount++) { ULONG ulNumBytes; PUCHAR pucData; Sleep(10); ulNumBytes = DoReceive(TdiHandle, &pucData); if (ulNumBytes) { DoSend(TdiHandle, pucData, ulNumBytes, 0); TCHAR *pString = (TCHAR *)pucData; _tprintf(TEXT("ServerThread: Packet received: %s\n"), pString); if (_tcscmp(pString, TEXT("Last Packet"))) { ulCount = 0; } LocalFreeMemory(pucData); if (ulCount) { _putts(TEXT("ServerThread: Exitting connected receive loop\n")); break; } } } for (ulCount = 0; ulCount < 1000; ulCount++) { if (!DoIsConnected(TdiHandle)) { break; } } DoCloseEndpoint(TdiHandle); break; } // // cleanup // if (pTransAddr) { LocalFreeMemory(pTransAddr); } if (pRemoteAddr) { LocalFreeMemory(pTransAddr); } if (pDeviceName) { LocalFreeMemory(pDeviceName); } LocalFreeMemory(pvData); DecServerCount(); _putts(TEXT("ServerThread: exitting\n")); return 0; } ///////////////////////////////////////////////// // // Function: WaitForClient // // Arguments: TdiHandle -- address object handle for calling driver // pRemoteAddr -- returns address received from // // Returns: TRUE if hear from client before timeout // // Descript: This function is used by the server side of the test to // wait for contact with the client side. // ///////////////////////////////////////////////// BOOLEAN WaitForClient(ULONG TdiHandle, PTRANSPORT_ADDRESS pRemoteAddr) { while(TRUE) { // // wait for up to a 2 minutes for first packet (broadcast) // BOOLEAN fSuccessful = FALSE; for (ULONG ulCount = 0; ulCount < 6000; ulCount++) { ULONG ulNumBytes; PUCHAR pucData; Sleep(20); ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, pRemoteAddr, &pucData); if (ulNumBytes) { if (ulNumBytes == 4) { PULONG pulValue = (PULONG)pucData; if (*pulValue == 0x12345678) { _putts(TEXT("WaitForClient: first packet received\n")); fSuccessful = TRUE; } else { _putts(TEXT("WaitForClient: unexpected packet received\n")); } } LocalFreeMemory(pucData); // // break out of wait loop if successful // if (fSuccessful) { break; } } } // // check for timed out // if (!fSuccessful) { _putts(TEXT("WaitForClient: timed out waiting for first packet\n")); break; } // // send 1st response // ULONG ulBuffer = 0x98765432; DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG)); // // wait for second response (directed) // fSuccessful = FALSE; for (ULONG ulCount = 0; ulCount < 1000; ulCount++) { ULONG ulNumBytes; PUCHAR pucData; Sleep(10); ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, NULL, &pucData); if (ulNumBytes) { if (ulNumBytes == 4) { PULONG pulValue = (PULONG)pucData; if (*pulValue == 0x22222222) { _putts(TEXT("WaitForClient: Second packet received\n")); fSuccessful = TRUE; } else { _putts(TEXT("WaitForClient: unexpected packet received\n")); } } LocalFreeMemory(pucData); // // break out if recieved // if (fSuccessful) { break; } } } // // if received second packet, send second response // if (fSuccessful) { ulBuffer = 0x33333333; DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG)); return TRUE; } // // else reloop and wait again for broadcast // _putts(TEXT("WaitForClient: timed out waiting for second packet\n")); } return FALSE; } ////////////////////////////////////////////////////////////////////////// // client-side test functions ////////////////////////////////////////////////////////////////////////// BOOLEAN FindServer(TCHAR *pDataDeviceName, PTRANSPORT_ADDRESS pTransAddr, PTRANSPORT_ADDRESS pRemoteAddr); ///////////////////////////////////////////////// // // Function: ClientTest // // Arguments: ulType -- protocol type to use // NumDevices -- number of devices of this protocol type // // Descript: this function controls the client side of the test // ///////////////////////////////////////////////// VOID ClientTest(ULONG ulType, ULONG ulNumDevices) { // // address of local interface // PTRANSPORT_ADDRESS pTransAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE); if (!pTransAddr) { _putts(TEXT("ClientTest: unable to allocate memory for pTransAddr\n")); return; } pTransAddr->TAAddressCount = 1; // // address of remote interface // PTRANSPORT_ADDRESS pRemoteAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE); if (!pRemoteAddr) { _putts(TEXT("ClientTest: unable to allocate memory for pRemoteAddr\n")); LocalFreeMemory(pTransAddr); return; } pRemoteAddr->TAAddressCount = 1; // // name of device (from driver) // TCHAR *pDeviceName = (TCHAR *)LocalAllocateMemory(256 * sizeof(TCHAR)); if (!pDeviceName) { _putts(TEXT("ClientTest: unable to allocate memory for pDeviceNameAddr\n")); LocalFreeMemory(pTransAddr); LocalFreeMemory(pRemoteAddr); return; } // // name of tdi datagram interface to open // TCHAR *pDataDeviceName = NULL; // // name of tdi connection endpoint interface to open // TCHAR *pConnDeviceName = NULL; // // Stores handle used by driver to access interface // ULONG TdiHandle; // // for netbios, each "address" has its own name. You open a device based on the name // if (ulType == TDI_ADDRESS_TYPE_NETBIOS) { PTA_NETBIOS_ADDRESS pTaAddr = (PTA_NETBIOS_ADDRESS)pTransAddr; pTaAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; pTaAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_NETBIOS; pTaAddr->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; memcpy(pTaAddr->Address[0].Address[0].NetbiosName, "CLIENT", 7); // NOTE: ascii string } // // for others, there is one name for the datagram device and another for the "connected" // device. You open an interface based on the address // else { switch (ulType) { case TDI_ADDRESS_TYPE_IPX: pDataDeviceName = TEXT("\\device\\nwlnkipx"); pConnDeviceName = TEXT("\\device\\nwlnkspx"); break; case TDI_ADDRESS_TYPE_IP: pDataDeviceName = TEXT("\\device\\udp"); pConnDeviceName = TEXT("\\device\\tcp"); break; } _putts(TEXT("ClientTest: get provider information\n")); TdiHandle = DoOpenControl(pDataDeviceName); if (TdiHandle) { PTDI_PROVIDER_INFO pInfo = (PTDI_PROVIDER_INFO)DoTdiQuery(TdiHandle, TDI_QUERY_PROVIDER_INFO); if (pInfo) { DoPrintProviderInfo(pInfo); LocalFreeMemory(pInfo); } DoCloseControl(TdiHandle); } } // // loop thru the available devices, trying each one in turn.. // for (ULONG ulCount = 0; ulCount < ulNumDevices; ulCount++) { // // collect necessary information // if (DoGetDeviceName(ulType, ulCount, pDeviceName) != STATUS_SUCCESS) { continue; } _tprintf(TEXT("ClientTest: LocalDeviceName = %s\n"), pDeviceName); if (ulType == TDI_ADDRESS_TYPE_NETBIOS) { pDataDeviceName = pDeviceName; pConnDeviceName = pDeviceName; _putts(TEXT("ClientTest: get provider information\n")); TdiHandle = DoOpenControl(pDataDeviceName); if (TdiHandle) { PTDI_PROVIDER_INFO pInfo = (PTDI_PROVIDER_INFO)DoTdiQuery(TdiHandle, TDI_QUERY_PROVIDER_INFO); if (pInfo) { DoPrintProviderInfo(pInfo); LocalFreeMemory(pInfo); } DoCloseControl(TdiHandle); } } else { if (DoGetAddress(ulType, ulCount, pTransAddr) != STATUS_SUCCESS) { continue; } } _putts(TEXT("ClientTest: Local device address:\n")); DoPrintAddress(pTransAddr); // // try to contact server // if (FindServer(pDataDeviceName, pTransAddr, pRemoteAddr)) { _putts(TEXT("Remote interface found:\n")); DoPrintAddress(pRemoteAddr); // // do a datagram send/receive test // TdiHandle = DoOpenAddress(pDataDeviceName, pTransAddr); if (TdiHandle) { _putts(TEXT("ClientTest: Sending first test packet\n")); TCHAR *strBuffer = TEXT("This is only a test"); DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR); DoPostReceiveBuffer(TdiHandle, 128); DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer))); Sleep(300); PUCHAR pucData; ULONG ulNumBytes = DoFetchReceiveBuffer(TdiHandle, &pucData); if (ulNumBytes) { strBuffer = (TCHAR *)pucData; _tprintf(TEXT("ClientTest: Response received: %s\n"), strBuffer); LocalFreeMemory(pucData); } else { _putts(TEXT("ClientTest: Response packet not received\n")); } _putts(TEXT("ClientTest: Sending second test packet\n")); DoPostReceiveBuffer(TdiHandle, 128); strBuffer = TEXT("Last Packet"); DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer))); Sleep(300); ulNumBytes = DoFetchReceiveBuffer(TdiHandle, &pucData); if (ulNumBytes) { strBuffer = (TCHAR *)pucData; _tprintf(TEXT("ClientTest: Response received: %s\n"), strBuffer); LocalFreeMemory(pucData); } else { _putts(TEXT("ClientTest: Response packet not received\n")); } Sleep(50); DoCloseAddress(TdiHandle); } else { _putts(TEXT("ClientTest: unable to open address object\n")); } // // adjust addresses... // switch (ulType) { case TDI_ADDRESS_TYPE_IPX: { PTA_IPX_ADDRESS pAddr = (PTA_IPX_ADDRESS)pRemoteAddr; pAddr->Address[0].Address[0].Socket = CONN_SERVER_PORT; pAddr = (PTA_IPX_ADDRESS)pTransAddr; pAddr->Address[0].Address[0].Socket = CONN_CLIENT_PORT; break; } case TDI_ADDRESS_TYPE_IP: { PTA_IP_ADDRESS pAddr = (PTA_IP_ADDRESS)pRemoteAddr; pAddr->Address[0].Address[0].sin_port = CONN_SERVER_PORT; pAddr = (PTA_IP_ADDRESS)pTransAddr; pAddr->Address[0].Address[0].sin_port = CONN_CLIENT_PORT; break; } } // // establish a connection // _putts(TEXT("ClientTest: Attempt to establish a connection\n")); TdiHandle = DoOpenEndpoint(pConnDeviceName, pTransAddr); if (TdiHandle) { DoEnableEventHandler(TdiHandle, TDI_EVENT_CONNECT); DoEnableEventHandler(TdiHandle, TDI_EVENT_DISCONNECT); DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR); DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE); if (DoConnect(TdiHandle, pRemoteAddr, 20) == STATUS_SUCCESS) { _putts(TEXT("ClientTest: Sending first packet over connection\n")); // // do a connected send/receive test // TCHAR *strBuffer = TEXT("This is only a test"); DoSend(TdiHandle, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer)), 0); // // wait for response // for (ULONG ulWait = 0; ulWait < 100; ulWait++) { Sleep(10); PUCHAR pucData; ULONG ulNumBytes = DoReceive(TdiHandle, &pucData); if (ulNumBytes) { _tprintf(TEXT("ClientTest: Response received: %s\n"), (TCHAR *)pucData); LocalFreeMemory(pucData); break; } } _putts(TEXT("ClientTest: Sending second packet over connection\n")); strBuffer = TEXT("Last Packet"); DoSend(TdiHandle, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer)), 0); // // wait for response // for (ULONG ulWait = 0; ulWait < 100; ulWait++) { Sleep(10); PUCHAR pucData; ULONG ulNumBytes = DoReceive(TdiHandle, &pucData); if (ulNumBytes) { _tprintf(TEXT("ClientTest: Response received: %s\n"), (TCHAR *)pucData); LocalFreeMemory(pucData); break; } } // // shut down the connection // _putts(TEXT("ClientTest: closing connection\n")); DoDisconnect(TdiHandle, TDI_DISCONNECT_RELEASE); } else { _putts(TEXT("ClientTest: failed to establish connection\n")); } DoCloseEndpoint(TdiHandle); } else { _putts(TEXT("ClientTest: failed to open endpoint\n")); } } else { _putts(TEXT("Unable to find remote server")); } if (ulType == TDI_ADDRESS_TYPE_NETBIOS) { _putts(TEXT("ClientTest: get provider status\n")); TdiHandle = DoOpenControl(pDataDeviceName); if (TdiHandle) { PADAPTER_STATUS pStatus = (PADAPTER_STATUS)DoTdiQuery(TdiHandle, TDI_QUERY_ADAPTER_STATUS); if (pStatus) { DoPrintAdapterStatus(pStatus); LocalFreeMemory(pStatus); } DoCloseControl(TdiHandle); } } } if (ulType != TDI_ADDRESS_TYPE_NETBIOS) { _putts(TEXT("ClientTest: get provider statistics\n")); TdiHandle = DoOpenControl(pDataDeviceName); if (TdiHandle) { PTDI_PROVIDER_STATISTICS pStats = (PTDI_PROVIDER_STATISTICS)DoTdiQuery(TdiHandle, TDI_QUERY_PROVIDER_STATISTICS); if (pStats) { DoPrintProviderStats(pStats); LocalFreeMemory(pStats); } DoCloseControl(TdiHandle); } } LocalFreeMemory(pDeviceName); LocalFreeMemory(pTransAddr); } ///////////////////////////////////////////////// // // Function: FindServer // // Arguments: pDataDeviceName -- name of data device to open // pTransAddr -- address of data device to open // pRemoteAddr -- on return, address of remote device // // Returns: TRUE if able to establish communication with server, // FALSE if it times out // // Descript: This function is called by the client to find a server // to participate with it in the tests. // ///////////////////////////////////////////////// BOOLEAN FindServer(TCHAR *pDataDeviceName, PTRANSPORT_ADDRESS pTransAddr, PTRANSPORT_ADDRESS pRemoteAddr) { // // set up remote and local address for broadcast/multicast search for server // pRemoteAddr->Address[0].AddressLength = pTransAddr->Address[0].AddressLength; pRemoteAddr->Address[0].AddressType = pTransAddr->Address[0].AddressType; switch (pTransAddr->Address[0].AddressType) { case TDI_ADDRESS_TYPE_IP: { PTDI_ADDRESS_IP pTdiAddressIp = (PTDI_ADDRESS_IP)pTransAddr->Address[0].Address; ULONG ulAddr = pTdiAddressIp->in_addr; pTdiAddressIp->sin_port = DGRAM_CLIENT_PORT; pTdiAddressIp = (PTDI_ADDRESS_IP)pRemoteAddr->Address[0].Address; pTdiAddressIp->in_addr = 0xFFFF0000 | ulAddr; pTdiAddressIp->sin_port = DGRAM_SERVER_PORT; } break; case TDI_ADDRESS_TYPE_IPX: { PTDI_ADDRESS_IPX pTdiAddressIpx = (PTDI_ADDRESS_IPX)pTransAddr->Address[0].Address; ULONG TempNetwork = pTdiAddressIpx->NetworkAddress; pTdiAddressIpx->Socket = DGRAM_CLIENT_PORT; pTdiAddressIpx = (PTDI_ADDRESS_IPX)pRemoteAddr->Address[0].Address; pTdiAddressIpx->NetworkAddress = TempNetwork; pTdiAddressIpx->Socket = DGRAM_SERVER_PORT; memset(pTdiAddressIpx->NodeAddress, 0xFF, 6); } break; case TDI_ADDRESS_TYPE_NETBIOS: { PTDI_ADDRESS_NETBIOS pTdiAddressNetbios = (PTDI_ADDRESS_NETBIOS)pRemoteAddr->Address[0].Address; pTdiAddressNetbios->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; memcpy(pTdiAddressNetbios->NetbiosName, "SERVER", 7 ); // NOTE: ascii string } break; default: _putts(TEXT("FindServer: invalid address type\n")); return FALSE; } // // try to find server program to test against // BOOLEAN fSuccessful = FALSE; ULONG TdiHandle; _putts(TEXT("FindServer: try to find remote test server\n")); while (TRUE) { TdiHandle = DoOpenAddress(pDataDeviceName, pTransAddr); if (!TdiHandle) { _putts(TEXT("FindServer: unable to open address object\n")); break; } DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR); DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE_DATAGRAM); // // send broadcast query // _putts(TEXT("FindServer: send first packet (broadcast)\n")); ULONG ulBuffer = 0x12345678; DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG)); // // wait for first response // for (ULONG ulCount = 0; ulCount < 100; ulCount++) { Sleep(10); PUCHAR pucData; ULONG ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, pRemoteAddr, &pucData); if (ulNumBytes) { if (ulNumBytes == 4) { PULONG pulValue = (PULONG)pucData; if (*pulValue == 0x98765432) { _putts(TEXT("FindServer: first response received\n")); fSuccessful = TRUE; } } LocalFreeMemory(pucData); // // break out of loop if received response // if (fSuccessful) { break; } } } // // timed out -- no response // if (!fSuccessful) { _putts(TEXT("FindServer: did not receive first response\n")); break; } // // send second message // fSuccessful = FALSE; ulBuffer = 0x22222222; _putts(TEXT("FindServer: send second packet (directed)\n")); DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG)); // // wait for second response // for (ULONG ulCount = 0; ulCount < 50; ulCount++) { Sleep(10); PUCHAR pucData; ULONG ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, NULL, &pucData); if (ulNumBytes) { if (ulNumBytes == 4) { PULONG pulValue = (PULONG)pucData; if (*pulValue == 0x33333333) { _putts(TEXT("FindServer: second response received\n")); fSuccessful = TRUE; } } LocalFreeMemory(pucData); // // break out if got response // if (fSuccessful) { break; } } } break; } if (!fSuccessful) { _putts(TEXT("FindServer: second response not received\n")); } if (TdiHandle) { DoCloseAddress(TdiHandle); } return fSuccessful; } /////////////////////////////////////////////////////////////////////////////// // end of file tdisample.cpp ///////////////////////////////////////////////////////////////////////////////