Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1267 lines
35 KiB

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // tdisample.cpp
  7. //
  8. // Abstract:
  9. // test executable--demonstrates the tdi client by calling it via the library
  10. //
  11. //////////////////////////////////////////////////////////////////////////
  12. #include "libbase.h"
  13. const ULONG MAX_ADDRESS_SIZE = sizeof(TRANSPORT_ADDRESS) + TDI_ADDRESS_LENGTH_OSI_TSAP;
  14. const USHORT DGRAM_SERVER_PORT = 0x5555;
  15. const USHORT DGRAM_CLIENT_PORT = 0x4444;
  16. const USHORT CONN_SERVER_PORT = 0x5656;
  17. const USHORT CONN_CLIENT_PORT = 0x4545;
  18. VOID
  19. ServerTest(ULONG ulType,
  20. ULONG ulNumDevices);
  21. VOID
  22. ClientTest(ULONG ulType,
  23. ULONG ulNumDevices);
  24. /////////////////////////////////////////////////
  25. //
  26. // Function: main
  27. //
  28. // Descript: parse the arguments to the program, initialize library and driver,
  29. // then call client or server side of test
  30. //
  31. /////////////////////////////////////////////////
  32. int __cdecl main(ULONG argc, TCHAR *argv[])
  33. {
  34. //
  35. // first step: get the arguments for this run
  36. //
  37. BOOLEAN fIsServer = FALSE;
  38. ULONG ulType = TDI_ADDRESS_TYPE_UNSPEC;
  39. BOOLEAN fArgsOk = FALSE;
  40. TCHAR *pArgStr;
  41. if(argc > 1)
  42. {
  43. for(ULONG ulArg = 1; ulArg < argc; ulArg++)
  44. {
  45. pArgStr = argv[ulArg];
  46. if ((*pArgStr == TEXT('/')) || (*pArgStr == TEXT('-')))
  47. {
  48. pArgStr++;
  49. }
  50. if (_tcsicmp(pArgStr, TEXT("server")) == 0)
  51. {
  52. if (fIsServer)
  53. {
  54. fArgsOk = FALSE;
  55. break;
  56. }
  57. fIsServer = TRUE;
  58. }
  59. else
  60. {
  61. fArgsOk = FALSE;
  62. if (ulType)
  63. {
  64. break;
  65. }
  66. if (_tcsicmp(pArgStr, TEXT("ipx")) == 0)
  67. {
  68. fArgsOk = TRUE;
  69. ulType = TDI_ADDRESS_TYPE_IPX;
  70. }
  71. else if (_tcsicmp(pArgStr, TEXT("ipv4")) == 0)
  72. {
  73. fArgsOk = TRUE;
  74. ulType = TDI_ADDRESS_TYPE_IP;
  75. }
  76. else if (_tcsicmp(pArgStr, TEXT("netbt")) == 0)
  77. {
  78. fArgsOk = TRUE;
  79. ulType = TDI_ADDRESS_TYPE_NETBIOS;
  80. }
  81. else
  82. {
  83. break;
  84. }
  85. }
  86. }
  87. }
  88. if (!fArgsOk)
  89. {
  90. _putts(TEXT("Usage: tdisample [/server] [/ipx | /ipv4 | /netbt] \n"));
  91. return 0;
  92. }
  93. //
  94. // ready to go. Initialize the library, connect to the driver, etc
  95. //
  96. if (TdiLibInit())
  97. {
  98. //
  99. // change this to limit debug output for kernel mode driver
  100. // 0 = none, 1 = commands, 2 = handlers, 3 = both
  101. //
  102. DoDebugLevel(0x03);
  103. ULONG ulNumDevices = DoGetNumDevices(ulType);
  104. if (ulNumDevices)
  105. {
  106. if (fIsServer)
  107. {
  108. ServerTest(ulType, ulNumDevices);
  109. }
  110. else
  111. {
  112. ClientTest(ulType, ulNumDevices);
  113. }
  114. }
  115. TdiLibClose();
  116. }
  117. return 0;
  118. }
  119. //////////////////////////////////////////////////////////////////////////
  120. // server-side test functions
  121. //////////////////////////////////////////////////////////////////////////
  122. ULONG_PTR
  123. __cdecl
  124. ServerThread(LPVOID pvDummy);
  125. BOOLEAN WaitForClient(
  126. ULONG TdiHandle,
  127. PTRANSPORT_ADDRESS pRemoteAddr
  128. );
  129. CRITICAL_SECTION CriticalSection;
  130. HANDLE hEvent;
  131. ULONG ulServerCount;
  132. /////////////////////////////////////////////////
  133. //
  134. // Function: IncServerCount
  135. //
  136. // Descript: multi-thread safe incrementing of server count
  137. //
  138. /////////////////////////////////////////////////
  139. VOID IncServerCount()
  140. {
  141. EnterCriticalSection(&CriticalSection);
  142. ++ulServerCount;
  143. LeaveCriticalSection(&CriticalSection);
  144. }
  145. /////////////////////////////////////////////////
  146. //
  147. // Function: DecServerCount
  148. //
  149. // Descript: multi-thread safe decrementing of server count
  150. // when last one done, sets event
  151. //
  152. /////////////////////////////////////////////////
  153. VOID DecServerCount()
  154. {
  155. BOOLEAN fDone = FALSE;
  156. EnterCriticalSection(&CriticalSection);
  157. --ulServerCount;
  158. if (!ulServerCount)
  159. {
  160. fDone = TRUE;
  161. }
  162. LeaveCriticalSection(&CriticalSection);
  163. if (fDone)
  164. {
  165. SetEvent(hEvent);
  166. }
  167. }
  168. struct THREAD_DATA
  169. {
  170. ULONG ulType;
  171. ULONG ulSlot;
  172. };
  173. typedef THREAD_DATA *PTHREAD_DATA;
  174. // ----------------------------------------------
  175. //
  176. // Function: ServerTest
  177. //
  178. // Arguments: ulType -- protocol type to use
  179. // NumDevices -- number of devices of this protocol type
  180. //
  181. // Descript: this function controls the server side of the test
  182. //
  183. // ----------------------------------------------
  184. VOID
  185. ServerTest(ULONG ulType, ULONG ulNumDevices)
  186. {
  187. //
  188. // initialize globals
  189. //
  190. try
  191. {
  192. InitializeCriticalSection(&CriticalSection);
  193. }
  194. catch(...)
  195. {
  196. return;
  197. }
  198. hEvent = CreateEvent(NULL,
  199. TRUE, // manual reset
  200. FALSE, // starts reset
  201. NULL);
  202. ulServerCount = 1; // a single bogus reference, so event doesn't fire prematurely
  203. //
  204. // go thru our list of nodes, starting a thread for each one
  205. //
  206. for(ULONG ulCount = 0; ulCount < ulNumDevices; ulCount++)
  207. {
  208. ULONG ulThreadId;
  209. PTHREAD_DATA pThreadData = (PTHREAD_DATA)LocalAllocateMemory(sizeof(THREAD_DATA));
  210. if (!pThreadData)
  211. {
  212. _putts(TEXT("ServerTest: unable to allocate memory for pThreadData\n"));
  213. break;
  214. }
  215. pThreadData->ulType = ulType;
  216. pThreadData->ulSlot = ulCount;
  217. //
  218. // reference for one starting now
  219. //
  220. IncServerCount();
  221. HANDLE hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
  222. 0,
  223. (LPTHREAD_START_ROUTINE)ServerThread,
  224. (LPVOID)pThreadData,
  225. 0,
  226. &ulThreadId);
  227. if (!hThread)
  228. {
  229. _putts(TEXT("ServerTest: failed starting server thread\n"));
  230. DecServerCount();
  231. }
  232. Sleep(100);
  233. }
  234. //
  235. // get rid of bogus reference
  236. //
  237. DecServerCount();
  238. //
  239. // wait until all the threads have completed
  240. //
  241. WaitForSingleObject(hEvent, INFINITE);
  242. //
  243. // cleanup
  244. //
  245. CloseHandle(hEvent);
  246. DeleteCriticalSection(&CriticalSection);
  247. }
  248. /////////////////////////////////////////////////
  249. //
  250. // Function: ServerThread
  251. //
  252. // Arguments: pvData -- actually pThreadData for this server
  253. //
  254. // Descript: This is the thread that runs for each server instance
  255. //
  256. /////////////////////////////////////////////////
  257. ULONG_PTR
  258. __cdecl
  259. ServerThread(LPVOID pvData)
  260. {
  261. PTHREAD_DATA pThreadData = (PTHREAD_DATA)pvData;
  262. PTRANSPORT_ADDRESS pTransAddr = NULL;
  263. PTRANSPORT_ADDRESS pRemoteAddr = NULL;
  264. TCHAR *pDeviceName = NULL;
  265. BOOLEAN fSuccessful = FALSE;
  266. while (TRUE)
  267. {
  268. //
  269. // stores local interface address (server)
  270. //
  271. pTransAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE);
  272. if (!pTransAddr)
  273. {
  274. _putts(TEXT("ServerThread: unable to allocate memory for pTransAddr\n"));
  275. break;
  276. }
  277. pTransAddr->TAAddressCount = 1;
  278. //
  279. // stores remote interface address (client)
  280. //
  281. pRemoteAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE);
  282. if (!pRemoteAddr)
  283. {
  284. _putts(TEXT("ServerThread: unable to allocate memory for pRemoteAddr\n"));
  285. break;
  286. }
  287. pRemoteAddr->TAAddressCount = 1;
  288. //
  289. // stores local interface name (server)
  290. //
  291. pDeviceName = (TCHAR *)LocalAllocateMemory(256 * sizeof(TCHAR));
  292. if (!pDeviceName)
  293. {
  294. _putts(TEXT("ServerThread: unable to allocate memory for pDeviceName\n"));
  295. break;
  296. }
  297. //
  298. // get name of local device
  299. //
  300. if (DoGetDeviceName(pThreadData->ulType, pThreadData->ulSlot, pDeviceName) != STATUS_SUCCESS)
  301. {
  302. break;
  303. }
  304. TCHAR *pDataDeviceName = NULL;
  305. TCHAR *pConnDeviceName = NULL;
  306. //
  307. // for netbios, each "address" has its own name. You open a device based mostly on the name
  308. //
  309. if (pThreadData->ulType == TDI_ADDRESS_TYPE_NETBIOS)
  310. {
  311. pDataDeviceName = pDeviceName;
  312. pConnDeviceName = pDeviceName;
  313. PTA_NETBIOS_ADDRESS pTaAddr = (PTA_NETBIOS_ADDRESS)pTransAddr;
  314. pTaAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  315. pTaAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
  316. pTaAddr->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  317. memcpy(pTaAddr->Address[0].Address[0].NetbiosName, "SERVER", 7); // NOTE: ascii string
  318. }
  319. //
  320. // for others, there is one name for the datagram device and another for the "connected"
  321. // device. You open an interface based largely on the address
  322. //
  323. else
  324. {
  325. if (DoGetAddress(pThreadData->ulType, pThreadData->ulSlot, pTransAddr) != STATUS_SUCCESS)
  326. {
  327. break;
  328. }
  329. switch (pThreadData->ulType)
  330. {
  331. case TDI_ADDRESS_TYPE_IPX:
  332. {
  333. PTA_IPX_ADDRESS pAddr = (PTA_IPX_ADDRESS)pTransAddr;
  334. pAddr->Address[0].Address[0].Socket = DGRAM_SERVER_PORT;
  335. pDataDeviceName = TEXT("\\device\\nwlnkipx");
  336. pConnDeviceName = TEXT("\\device\\nwlnkspx");
  337. break;
  338. }
  339. case TDI_ADDRESS_TYPE_IP:
  340. {
  341. PTA_IP_ADDRESS pAddr = (PTA_IP_ADDRESS)pTransAddr;
  342. pAddr->Address[0].Address[0].sin_port = DGRAM_SERVER_PORT;
  343. pDataDeviceName = TEXT("\\device\\udp");
  344. pConnDeviceName = TEXT("\\device\\tcp");
  345. break;
  346. }
  347. }
  348. }
  349. _tprintf(TEXT("ServerThread: DeviceName: %s\n"), pDeviceName);
  350. _putts(TEXT("Device Address:\n"));
  351. DoPrintAddress(pTransAddr);
  352. //
  353. // wait for a client to contact us
  354. //
  355. ULONG TdiHandle = DoOpenAddress(pDataDeviceName, pTransAddr);
  356. if (!TdiHandle)
  357. {
  358. _putts(TEXT("ServerThread: failed to open address object\n"));
  359. break;
  360. }
  361. DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR);
  362. DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE_DATAGRAM);
  363. if (!WaitForClient(TdiHandle, pRemoteAddr))
  364. {
  365. _putts(TEXT("ServerThread: Timed out waiting for client\n"));
  366. DoCloseAddress(TdiHandle);
  367. break;
  368. }
  369. _putts(TEXT("ServerThread: Found by client. Client address:\n"));
  370. DoPrintAddress(pTransAddr);
  371. //
  372. // echo datagram packets until we get one that is TEXT("Last Packet"), or until we time out
  373. //
  374. for (ULONG ulCount = 1; ulCount < 60000; ulCount++)
  375. {
  376. ULONG ulNumBytes;
  377. PUCHAR pucData;
  378. Sleep(10);
  379. ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, pRemoteAddr, &pucData);
  380. if (ulNumBytes)
  381. {
  382. DoSendDatagram(TdiHandle, pRemoteAddr, pucData, ulNumBytes);
  383. TCHAR *pString = (TCHAR *)pucData;
  384. _tprintf(TEXT("ServerThread: Packet Received: %s\n"), pString);
  385. if (_tcscmp(pString, TEXT("Last Packet")))
  386. {
  387. ulCount = 0;
  388. }
  389. LocalFreeMemory(pucData);
  390. if (ulCount)
  391. {
  392. _putts(TEXT("ServerThread: Exitting datagram receive loop\n"));
  393. break;
  394. }
  395. }
  396. }
  397. Sleep(50);
  398. DoCloseAddress(TdiHandle);
  399. //
  400. // now, open an endpoint, and wait for a connection request
  401. //
  402. switch (pThreadData->ulType)
  403. {
  404. case TDI_ADDRESS_TYPE_IPX:
  405. {
  406. PTA_IPX_ADDRESS pAddr = (PTA_IPX_ADDRESS)pTransAddr;
  407. pAddr->Address[0].Address[0].Socket = CONN_SERVER_PORT;
  408. break;
  409. }
  410. case TDI_ADDRESS_TYPE_IP:
  411. {
  412. PTA_IP_ADDRESS pAddr = (PTA_IP_ADDRESS)pTransAddr;
  413. pAddr->Address[0].Address[0].sin_port = CONN_SERVER_PORT;
  414. break;
  415. }
  416. }
  417. TdiHandle = DoOpenEndpoint(pConnDeviceName, pTransAddr);
  418. if (!TdiHandle)
  419. {
  420. _putts(TEXT("ServerThread: unable to open endpoint\n"));
  421. break;
  422. }
  423. DoEnableEventHandler(TdiHandle, TDI_EVENT_CONNECT);
  424. DoEnableEventHandler(TdiHandle, TDI_EVENT_DISCONNECT);
  425. DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR);
  426. DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE);
  427. fSuccessful = FALSE;
  428. for (ULONG ulCount = 0; ulCount < 100; ulCount++)
  429. {
  430. if (DoIsConnected(TdiHandle))
  431. {
  432. _putts(TEXT("ServerThread: connect successful\n"));
  433. fSuccessful = TRUE;
  434. break;
  435. }
  436. Sleep(20);
  437. }
  438. if (!fSuccessful)
  439. {
  440. _putts(TEXT("ServerThread: timed out waiting for connect\n"));
  441. DoCloseEndpoint(TdiHandle);
  442. break;
  443. }
  444. //
  445. // echo packets until we get one that is TEXT("Last Packet")
  446. //
  447. for (ULONG ulCount = 0; ulCount < 60000; ulCount++)
  448. {
  449. ULONG ulNumBytes;
  450. PUCHAR pucData;
  451. Sleep(10);
  452. ulNumBytes = DoReceive(TdiHandle, &pucData);
  453. if (ulNumBytes)
  454. {
  455. DoSend(TdiHandle, pucData, ulNumBytes, 0);
  456. TCHAR *pString = (TCHAR *)pucData;
  457. _tprintf(TEXT("ServerThread: Packet received: %s\n"), pString);
  458. if (_tcscmp(pString, TEXT("Last Packet")))
  459. {
  460. ulCount = 0;
  461. }
  462. LocalFreeMemory(pucData);
  463. if (ulCount)
  464. {
  465. _putts(TEXT("ServerThread: Exitting connected receive loop\n"));
  466. break;
  467. }
  468. }
  469. }
  470. for (ulCount = 0; ulCount < 1000; ulCount++)
  471. {
  472. if (!DoIsConnected(TdiHandle))
  473. {
  474. break;
  475. }
  476. }
  477. DoCloseEndpoint(TdiHandle);
  478. break;
  479. }
  480. //
  481. // cleanup
  482. //
  483. if (pTransAddr)
  484. {
  485. LocalFreeMemory(pTransAddr);
  486. }
  487. if (pRemoteAddr)
  488. {
  489. LocalFreeMemory(pTransAddr);
  490. }
  491. if (pDeviceName)
  492. {
  493. LocalFreeMemory(pDeviceName);
  494. }
  495. LocalFreeMemory(pvData);
  496. DecServerCount();
  497. _putts(TEXT("ServerThread: exitting\n"));
  498. return 0;
  499. }
  500. /////////////////////////////////////////////////
  501. //
  502. // Function: WaitForClient
  503. //
  504. // Arguments: TdiHandle -- address object handle for calling driver
  505. // pRemoteAddr -- returns address received from
  506. //
  507. // Returns: TRUE if hear from client before timeout
  508. //
  509. // Descript: This function is used by the server side of the test to
  510. // wait for contact with the client side.
  511. //
  512. /////////////////////////////////////////////////
  513. BOOLEAN WaitForClient(ULONG TdiHandle,
  514. PTRANSPORT_ADDRESS pRemoteAddr)
  515. {
  516. while(TRUE)
  517. {
  518. //
  519. // wait for up to a 2 minutes for first packet (broadcast)
  520. //
  521. BOOLEAN fSuccessful = FALSE;
  522. for (ULONG ulCount = 0; ulCount < 6000; ulCount++)
  523. {
  524. ULONG ulNumBytes;
  525. PUCHAR pucData;
  526. Sleep(20);
  527. ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, pRemoteAddr, &pucData);
  528. if (ulNumBytes)
  529. {
  530. if (ulNumBytes == 4)
  531. {
  532. PULONG pulValue = (PULONG)pucData;
  533. if (*pulValue == 0x12345678)
  534. {
  535. _putts(TEXT("WaitForClient: first packet received\n"));
  536. fSuccessful = TRUE;
  537. }
  538. else
  539. {
  540. _putts(TEXT("WaitForClient: unexpected packet received\n"));
  541. }
  542. }
  543. LocalFreeMemory(pucData);
  544. //
  545. // break out of wait loop if successful
  546. //
  547. if (fSuccessful)
  548. {
  549. break;
  550. }
  551. }
  552. }
  553. //
  554. // check for timed out
  555. //
  556. if (!fSuccessful)
  557. {
  558. _putts(TEXT("WaitForClient: timed out waiting for first packet\n"));
  559. break;
  560. }
  561. //
  562. // send 1st response
  563. //
  564. ULONG ulBuffer = 0x98765432;
  565. DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG));
  566. //
  567. // wait for second response (directed)
  568. //
  569. fSuccessful = FALSE;
  570. for (ULONG ulCount = 0; ulCount < 1000; ulCount++)
  571. {
  572. ULONG ulNumBytes;
  573. PUCHAR pucData;
  574. Sleep(10);
  575. ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, NULL, &pucData);
  576. if (ulNumBytes)
  577. {
  578. if (ulNumBytes == 4)
  579. {
  580. PULONG pulValue = (PULONG)pucData;
  581. if (*pulValue == 0x22222222)
  582. {
  583. _putts(TEXT("WaitForClient: Second packet received\n"));
  584. fSuccessful = TRUE;
  585. }
  586. else
  587. {
  588. _putts(TEXT("WaitForClient: unexpected packet received\n"));
  589. }
  590. }
  591. LocalFreeMemory(pucData);
  592. //
  593. // break out if recieved
  594. //
  595. if (fSuccessful)
  596. {
  597. break;
  598. }
  599. }
  600. }
  601. //
  602. // if received second packet, send second response
  603. //
  604. if (fSuccessful)
  605. {
  606. ulBuffer = 0x33333333;
  607. DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG));
  608. return TRUE;
  609. }
  610. //
  611. // else reloop and wait again for broadcast
  612. //
  613. _putts(TEXT("WaitForClient: timed out waiting for second packet\n"));
  614. }
  615. return FALSE;
  616. }
  617. //////////////////////////////////////////////////////////////////////////
  618. // client-side test functions
  619. //////////////////////////////////////////////////////////////////////////
  620. BOOLEAN
  621. FindServer(TCHAR *pDataDeviceName,
  622. PTRANSPORT_ADDRESS pTransAddr,
  623. PTRANSPORT_ADDRESS pRemoteAddr);
  624. /////////////////////////////////////////////////
  625. //
  626. // Function: ClientTest
  627. //
  628. // Arguments: ulType -- protocol type to use
  629. // NumDevices -- number of devices of this protocol type
  630. //
  631. // Descript: this function controls the client side of the test
  632. //
  633. /////////////////////////////////////////////////
  634. VOID
  635. ClientTest(ULONG ulType, ULONG ulNumDevices)
  636. {
  637. //
  638. // address of local interface
  639. //
  640. PTRANSPORT_ADDRESS pTransAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE);
  641. if (!pTransAddr)
  642. {
  643. _putts(TEXT("ClientTest: unable to allocate memory for pTransAddr\n"));
  644. return;
  645. }
  646. pTransAddr->TAAddressCount = 1;
  647. //
  648. // address of remote interface
  649. //
  650. PTRANSPORT_ADDRESS pRemoteAddr = (PTRANSPORT_ADDRESS)LocalAllocateMemory(MAX_ADDRESS_SIZE);
  651. if (!pRemoteAddr)
  652. {
  653. _putts(TEXT("ClientTest: unable to allocate memory for pRemoteAddr\n"));
  654. LocalFreeMemory(pTransAddr);
  655. return;
  656. }
  657. pRemoteAddr->TAAddressCount = 1;
  658. //
  659. // name of device (from driver)
  660. //
  661. TCHAR *pDeviceName = (TCHAR *)LocalAllocateMemory(256 * sizeof(TCHAR));
  662. if (!pDeviceName)
  663. {
  664. _putts(TEXT("ClientTest: unable to allocate memory for pDeviceNameAddr\n"));
  665. LocalFreeMemory(pTransAddr);
  666. LocalFreeMemory(pRemoteAddr);
  667. return;
  668. }
  669. //
  670. // name of tdi datagram interface to open
  671. //
  672. TCHAR *pDataDeviceName = NULL;
  673. //
  674. // name of tdi connection endpoint interface to open
  675. //
  676. TCHAR *pConnDeviceName = NULL;
  677. //
  678. // Stores handle used by driver to access interface
  679. //
  680. ULONG TdiHandle;
  681. //
  682. // for netbios, each "address" has its own name. You open a device based on the name
  683. //
  684. if (ulType == TDI_ADDRESS_TYPE_NETBIOS)
  685. {
  686. PTA_NETBIOS_ADDRESS pTaAddr = (PTA_NETBIOS_ADDRESS)pTransAddr;
  687. pTaAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  688. pTaAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
  689. pTaAddr->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  690. memcpy(pTaAddr->Address[0].Address[0].NetbiosName, "CLIENT", 7); // NOTE: ascii string
  691. }
  692. //
  693. // for others, there is one name for the datagram device and another for the "connected"
  694. // device. You open an interface based on the address
  695. //
  696. else
  697. {
  698. switch (ulType)
  699. {
  700. case TDI_ADDRESS_TYPE_IPX:
  701. pDataDeviceName = TEXT("\\device\\nwlnkipx");
  702. pConnDeviceName = TEXT("\\device\\nwlnkspx");
  703. break;
  704. case TDI_ADDRESS_TYPE_IP:
  705. pDataDeviceName = TEXT("\\device\\udp");
  706. pConnDeviceName = TEXT("\\device\\tcp");
  707. break;
  708. }
  709. _putts(TEXT("ClientTest: get provider information\n"));
  710. TdiHandle = DoOpenControl(pDataDeviceName);
  711. if (TdiHandle)
  712. {
  713. PTDI_PROVIDER_INFO pInfo = (PTDI_PROVIDER_INFO)DoTdiQuery(TdiHandle, TDI_QUERY_PROVIDER_INFO);
  714. if (pInfo)
  715. {
  716. DoPrintProviderInfo(pInfo);
  717. LocalFreeMemory(pInfo);
  718. }
  719. DoCloseControl(TdiHandle);
  720. }
  721. }
  722. //
  723. // loop thru the available devices, trying each one in turn..
  724. //
  725. for (ULONG ulCount = 0; ulCount < ulNumDevices; ulCount++)
  726. {
  727. //
  728. // collect necessary information
  729. //
  730. if (DoGetDeviceName(ulType, ulCount, pDeviceName) != STATUS_SUCCESS)
  731. {
  732. continue;
  733. }
  734. _tprintf(TEXT("ClientTest: LocalDeviceName = %s\n"), pDeviceName);
  735. if (ulType == TDI_ADDRESS_TYPE_NETBIOS)
  736. {
  737. pDataDeviceName = pDeviceName;
  738. pConnDeviceName = pDeviceName;
  739. _putts(TEXT("ClientTest: get provider information\n"));
  740. TdiHandle = DoOpenControl(pDataDeviceName);
  741. if (TdiHandle)
  742. {
  743. PTDI_PROVIDER_INFO pInfo = (PTDI_PROVIDER_INFO)DoTdiQuery(TdiHandle, TDI_QUERY_PROVIDER_INFO);
  744. if (pInfo)
  745. {
  746. DoPrintProviderInfo(pInfo);
  747. LocalFreeMemory(pInfo);
  748. }
  749. DoCloseControl(TdiHandle);
  750. }
  751. }
  752. else
  753. {
  754. if (DoGetAddress(ulType, ulCount, pTransAddr) != STATUS_SUCCESS)
  755. {
  756. continue;
  757. }
  758. }
  759. _putts(TEXT("ClientTest: Local device address:\n"));
  760. DoPrintAddress(pTransAddr);
  761. //
  762. // try to contact server
  763. //
  764. if (FindServer(pDataDeviceName, pTransAddr, pRemoteAddr))
  765. {
  766. _putts(TEXT("Remote interface found:\n"));
  767. DoPrintAddress(pRemoteAddr);
  768. //
  769. // do a datagram send/receive test
  770. //
  771. TdiHandle = DoOpenAddress(pDataDeviceName, pTransAddr);
  772. if (TdiHandle)
  773. {
  774. _putts(TEXT("ClientTest: Sending first test packet\n"));
  775. TCHAR *strBuffer = TEXT("This is only a test");
  776. DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR);
  777. DoPostReceiveBuffer(TdiHandle, 128);
  778. DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer)));
  779. Sleep(300);
  780. PUCHAR pucData;
  781. ULONG ulNumBytes = DoFetchReceiveBuffer(TdiHandle, &pucData);
  782. if (ulNumBytes)
  783. {
  784. strBuffer = (TCHAR *)pucData;
  785. _tprintf(TEXT("ClientTest: Response received: %s\n"), strBuffer);
  786. LocalFreeMemory(pucData);
  787. }
  788. else
  789. {
  790. _putts(TEXT("ClientTest: Response packet not received\n"));
  791. }
  792. _putts(TEXT("ClientTest: Sending second test packet\n"));
  793. DoPostReceiveBuffer(TdiHandle, 128);
  794. strBuffer = TEXT("Last Packet");
  795. DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer)));
  796. Sleep(300);
  797. ulNumBytes = DoFetchReceiveBuffer(TdiHandle, &pucData);
  798. if (ulNumBytes)
  799. {
  800. strBuffer = (TCHAR *)pucData;
  801. _tprintf(TEXT("ClientTest: Response received: %s\n"), strBuffer);
  802. LocalFreeMemory(pucData);
  803. }
  804. else
  805. {
  806. _putts(TEXT("ClientTest: Response packet not received\n"));
  807. }
  808. Sleep(50);
  809. DoCloseAddress(TdiHandle);
  810. }
  811. else
  812. {
  813. _putts(TEXT("ClientTest: unable to open address object\n"));
  814. }
  815. //
  816. // adjust addresses...
  817. //
  818. switch (ulType)
  819. {
  820. case TDI_ADDRESS_TYPE_IPX:
  821. {
  822. PTA_IPX_ADDRESS pAddr = (PTA_IPX_ADDRESS)pRemoteAddr;
  823. pAddr->Address[0].Address[0].Socket = CONN_SERVER_PORT;
  824. pAddr = (PTA_IPX_ADDRESS)pTransAddr;
  825. pAddr->Address[0].Address[0].Socket = CONN_CLIENT_PORT;
  826. break;
  827. }
  828. case TDI_ADDRESS_TYPE_IP:
  829. {
  830. PTA_IP_ADDRESS pAddr = (PTA_IP_ADDRESS)pRemoteAddr;
  831. pAddr->Address[0].Address[0].sin_port = CONN_SERVER_PORT;
  832. pAddr = (PTA_IP_ADDRESS)pTransAddr;
  833. pAddr->Address[0].Address[0].sin_port = CONN_CLIENT_PORT;
  834. break;
  835. }
  836. }
  837. //
  838. // establish a connection
  839. //
  840. _putts(TEXT("ClientTest: Attempt to establish a connection\n"));
  841. TdiHandle = DoOpenEndpoint(pConnDeviceName, pTransAddr);
  842. if (TdiHandle)
  843. {
  844. DoEnableEventHandler(TdiHandle, TDI_EVENT_CONNECT);
  845. DoEnableEventHandler(TdiHandle, TDI_EVENT_DISCONNECT);
  846. DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR);
  847. DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE);
  848. if (DoConnect(TdiHandle, pRemoteAddr, 20) == STATUS_SUCCESS)
  849. {
  850. _putts(TEXT("ClientTest: Sending first packet over connection\n"));
  851. //
  852. // do a connected send/receive test
  853. //
  854. TCHAR *strBuffer = TEXT("This is only a test");
  855. DoSend(TdiHandle, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer)), 0);
  856. //
  857. // wait for response
  858. //
  859. for (ULONG ulWait = 0; ulWait < 100; ulWait++)
  860. {
  861. Sleep(10);
  862. PUCHAR pucData;
  863. ULONG ulNumBytes = DoReceive(TdiHandle, &pucData);
  864. if (ulNumBytes)
  865. {
  866. _tprintf(TEXT("ClientTest: Response received: %s\n"), (TCHAR *)pucData);
  867. LocalFreeMemory(pucData);
  868. break;
  869. }
  870. }
  871. _putts(TEXT("ClientTest: Sending second packet over connection\n"));
  872. strBuffer = TEXT("Last Packet");
  873. DoSend(TdiHandle, (PUCHAR)strBuffer, sizeof(TCHAR) * (1 + _tcslen(strBuffer)), 0);
  874. //
  875. // wait for response
  876. //
  877. for (ULONG ulWait = 0; ulWait < 100; ulWait++)
  878. {
  879. Sleep(10);
  880. PUCHAR pucData;
  881. ULONG ulNumBytes = DoReceive(TdiHandle, &pucData);
  882. if (ulNumBytes)
  883. {
  884. _tprintf(TEXT("ClientTest: Response received: %s\n"), (TCHAR *)pucData);
  885. LocalFreeMemory(pucData);
  886. break;
  887. }
  888. }
  889. //
  890. // shut down the connection
  891. //
  892. _putts(TEXT("ClientTest: closing connection\n"));
  893. DoDisconnect(TdiHandle, TDI_DISCONNECT_RELEASE);
  894. }
  895. else
  896. {
  897. _putts(TEXT("ClientTest: failed to establish connection\n"));
  898. }
  899. DoCloseEndpoint(TdiHandle);
  900. }
  901. else
  902. {
  903. _putts(TEXT("ClientTest: failed to open endpoint\n"));
  904. }
  905. }
  906. else
  907. {
  908. _putts(TEXT("Unable to find remote server"));
  909. }
  910. if (ulType == TDI_ADDRESS_TYPE_NETBIOS)
  911. {
  912. _putts(TEXT("ClientTest: get provider status\n"));
  913. TdiHandle = DoOpenControl(pDataDeviceName);
  914. if (TdiHandle)
  915. {
  916. PADAPTER_STATUS pStatus = (PADAPTER_STATUS)DoTdiQuery(TdiHandle, TDI_QUERY_ADAPTER_STATUS);
  917. if (pStatus)
  918. {
  919. DoPrintAdapterStatus(pStatus);
  920. LocalFreeMemory(pStatus);
  921. }
  922. DoCloseControl(TdiHandle);
  923. }
  924. }
  925. }
  926. if (ulType != TDI_ADDRESS_TYPE_NETBIOS)
  927. {
  928. _putts(TEXT("ClientTest: get provider statistics\n"));
  929. TdiHandle = DoOpenControl(pDataDeviceName);
  930. if (TdiHandle)
  931. {
  932. PTDI_PROVIDER_STATISTICS pStats
  933. = (PTDI_PROVIDER_STATISTICS)DoTdiQuery(TdiHandle,
  934. TDI_QUERY_PROVIDER_STATISTICS);
  935. if (pStats)
  936. {
  937. DoPrintProviderStats(pStats);
  938. LocalFreeMemory(pStats);
  939. }
  940. DoCloseControl(TdiHandle);
  941. }
  942. }
  943. LocalFreeMemory(pDeviceName);
  944. LocalFreeMemory(pTransAddr);
  945. }
  946. /////////////////////////////////////////////////
  947. //
  948. // Function: FindServer
  949. //
  950. // Arguments: pDataDeviceName -- name of data device to open
  951. // pTransAddr -- address of data device to open
  952. // pRemoteAddr -- on return, address of remote device
  953. //
  954. // Returns: TRUE if able to establish communication with server,
  955. // FALSE if it times out
  956. //
  957. // Descript: This function is called by the client to find a server
  958. // to participate with it in the tests.
  959. //
  960. /////////////////////////////////////////////////
  961. BOOLEAN
  962. FindServer(TCHAR *pDataDeviceName,
  963. PTRANSPORT_ADDRESS pTransAddr,
  964. PTRANSPORT_ADDRESS pRemoteAddr)
  965. {
  966. //
  967. // set up remote and local address for broadcast/multicast search for server
  968. //
  969. pRemoteAddr->Address[0].AddressLength = pTransAddr->Address[0].AddressLength;
  970. pRemoteAddr->Address[0].AddressType = pTransAddr->Address[0].AddressType;
  971. switch (pTransAddr->Address[0].AddressType)
  972. {
  973. case TDI_ADDRESS_TYPE_IP:
  974. {
  975. PTDI_ADDRESS_IP pTdiAddressIp
  976. = (PTDI_ADDRESS_IP)pTransAddr->Address[0].Address;
  977. ULONG ulAddr = pTdiAddressIp->in_addr;
  978. pTdiAddressIp->sin_port = DGRAM_CLIENT_PORT;
  979. pTdiAddressIp = (PTDI_ADDRESS_IP)pRemoteAddr->Address[0].Address;
  980. pTdiAddressIp->in_addr = 0xFFFF0000 | ulAddr;
  981. pTdiAddressIp->sin_port = DGRAM_SERVER_PORT;
  982. }
  983. break;
  984. case TDI_ADDRESS_TYPE_IPX:
  985. {
  986. PTDI_ADDRESS_IPX pTdiAddressIpx
  987. = (PTDI_ADDRESS_IPX)pTransAddr->Address[0].Address;
  988. ULONG TempNetwork = pTdiAddressIpx->NetworkAddress;
  989. pTdiAddressIpx->Socket = DGRAM_CLIENT_PORT;
  990. pTdiAddressIpx = (PTDI_ADDRESS_IPX)pRemoteAddr->Address[0].Address;
  991. pTdiAddressIpx->NetworkAddress = TempNetwork;
  992. pTdiAddressIpx->Socket = DGRAM_SERVER_PORT;
  993. memset(pTdiAddressIpx->NodeAddress, 0xFF, 6);
  994. }
  995. break;
  996. case TDI_ADDRESS_TYPE_NETBIOS:
  997. {
  998. PTDI_ADDRESS_NETBIOS pTdiAddressNetbios
  999. = (PTDI_ADDRESS_NETBIOS)pRemoteAddr->Address[0].Address;
  1000. pTdiAddressNetbios->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  1001. memcpy(pTdiAddressNetbios->NetbiosName, "SERVER", 7 ); // NOTE: ascii string
  1002. }
  1003. break;
  1004. default:
  1005. _putts(TEXT("FindServer: invalid address type\n"));
  1006. return FALSE;
  1007. }
  1008. //
  1009. // try to find server program to test against
  1010. //
  1011. BOOLEAN fSuccessful = FALSE;
  1012. ULONG TdiHandle;
  1013. _putts(TEXT("FindServer: try to find remote test server\n"));
  1014. while (TRUE)
  1015. {
  1016. TdiHandle = DoOpenAddress(pDataDeviceName, pTransAddr);
  1017. if (!TdiHandle)
  1018. {
  1019. _putts(TEXT("FindServer: unable to open address object\n"));
  1020. break;
  1021. }
  1022. DoEnableEventHandler(TdiHandle, TDI_EVENT_ERROR);
  1023. DoEnableEventHandler(TdiHandle, TDI_EVENT_RECEIVE_DATAGRAM);
  1024. //
  1025. // send broadcast query
  1026. //
  1027. _putts(TEXT("FindServer: send first packet (broadcast)\n"));
  1028. ULONG ulBuffer = 0x12345678;
  1029. DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG));
  1030. //
  1031. // wait for first response
  1032. //
  1033. for (ULONG ulCount = 0; ulCount < 100; ulCount++)
  1034. {
  1035. Sleep(10);
  1036. PUCHAR pucData;
  1037. ULONG ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, pRemoteAddr, &pucData);
  1038. if (ulNumBytes)
  1039. {
  1040. if (ulNumBytes == 4)
  1041. {
  1042. PULONG pulValue = (PULONG)pucData;
  1043. if (*pulValue == 0x98765432)
  1044. {
  1045. _putts(TEXT("FindServer: first response received\n"));
  1046. fSuccessful = TRUE;
  1047. }
  1048. }
  1049. LocalFreeMemory(pucData);
  1050. //
  1051. // break out of loop if received response
  1052. //
  1053. if (fSuccessful)
  1054. {
  1055. break;
  1056. }
  1057. }
  1058. }
  1059. //
  1060. // timed out -- no response
  1061. //
  1062. if (!fSuccessful)
  1063. {
  1064. _putts(TEXT("FindServer: did not receive first response\n"));
  1065. break;
  1066. }
  1067. //
  1068. // send second message
  1069. //
  1070. fSuccessful = FALSE;
  1071. ulBuffer = 0x22222222;
  1072. _putts(TEXT("FindServer: send second packet (directed)\n"));
  1073. DoSendDatagram(TdiHandle, pRemoteAddr, (PUCHAR)&ulBuffer, sizeof(ULONG));
  1074. //
  1075. // wait for second response
  1076. //
  1077. for (ULONG ulCount = 0; ulCount < 50; ulCount++)
  1078. {
  1079. Sleep(10);
  1080. PUCHAR pucData;
  1081. ULONG ulNumBytes = DoReceiveDatagram(TdiHandle, NULL, NULL, &pucData);
  1082. if (ulNumBytes)
  1083. {
  1084. if (ulNumBytes == 4)
  1085. {
  1086. PULONG pulValue = (PULONG)pucData;
  1087. if (*pulValue == 0x33333333)
  1088. {
  1089. _putts(TEXT("FindServer: second response received\n"));
  1090. fSuccessful = TRUE;
  1091. }
  1092. }
  1093. LocalFreeMemory(pucData);
  1094. //
  1095. // break out if got response
  1096. //
  1097. if (fSuccessful)
  1098. {
  1099. break;
  1100. }
  1101. }
  1102. }
  1103. break;
  1104. }
  1105. if (!fSuccessful)
  1106. {
  1107. _putts(TEXT("FindServer: second response not received\n"));
  1108. }
  1109. if (TdiHandle)
  1110. {
  1111. DoCloseAddress(TdiHandle);
  1112. }
  1113. return fSuccessful;
  1114. }
  1115. ///////////////////////////////////////////////////////////////////////////////
  1116. // end of file tdisample.cpp
  1117. ///////////////////////////////////////////////////////////////////////////////