Leaked source code of windows server 2003
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.

1864 lines
47 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. homenet.exe is a proof-of-concept tool for the protocol-independent
  7. home networking transport.
  8. Author:
  9. Jim Schmidt (jimschm) 01-Jul-2000
  10. Revision History:
  11. <full name> (<alias>) <date> <comments>
  12. --*/
  13. #include "pch.h"
  14. #include <initguid.h>
  15. #include <winsock2.h>
  16. #include <wsipx.h>
  17. #include <wsnwlink.h>
  18. #include <wsnetbs.h>
  19. #include <nb30.h>
  20. #define TCPIP_BROADCAST_PORT 2048
  21. #define IPX_BROADCAST_PORT 1150
  22. #define NETBIOS_BROADCAST_PORT 0x50
  23. #define TCPIP_CONNECT_PORT 2049
  24. #define IPX_CONNECT_PORT 1151
  25. #define NETBIOS_CONNECT_PORT 0x51
  26. #define MAX_SOCKADDR (max(sizeof(SOCKADDR_IN),max(sizeof(SOCKADDR_IPX),sizeof(SOCKADDR_NB))))
  27. #define DBG_HOMENET "HomeNet"
  28. VOID
  29. pDoSource (
  30. VOID
  31. );
  32. VOID
  33. pDoDestination (
  34. VOID
  35. );
  36. // 36E4BE8D-0766-46E9-8679-8546529A90EE
  37. DEFINE_GUID(g_MyGuid, 0x36E4BE8D, 0x0766, 0x46e9, 0x86, 0x79, 0X85, 0x46, 0x52, 0X9A, 0x90, 0XEE);
  38. HANDLE g_StopHandle;
  39. HANDLE g_ConnectionDone;
  40. TCHAR g_StoragePath[MAX_PATH];
  41. #pragma pack(push,1)
  42. typedef struct {
  43. WORD PacketNumber;
  44. WORD DataLength;
  45. } DATAGRAM_PACKET, *PDATAGRAM_PACKET;
  46. #pragma pack(pop)
  47. typedef struct TAG_DATAGRAM_POOL_ITEM {
  48. struct TAG_DATAGRAM_POOL_ITEM *Next, *Prev;
  49. DATAGRAM_PACKET Header;
  50. PCBYTE PacketData;
  51. // PacketData follows
  52. } DATAGRAM_POOL_ITEM, *PDATAGRAM_POOL_ITEM;
  53. typedef struct {
  54. PMHANDLE Pool;
  55. SOCKET Socket;
  56. PDATAGRAM_POOL_ITEM FirstItem;
  57. WORD SendSequenceNumber;
  58. WORD RecvSequenceNumber;
  59. } DATAGRAM_POOL, *PDATAGRAM_POOL;
  60. BOOL
  61. pCallEntryPoints (
  62. DWORD Reason
  63. )
  64. {
  65. switch (Reason) {
  66. case DLL_PROCESS_ATTACH:
  67. UtInitialize (NULL);
  68. break;
  69. case DLL_PROCESS_DETACH:
  70. UtTerminate ();
  71. break;
  72. }
  73. return TRUE;
  74. }
  75. BOOL
  76. Init (
  77. VOID
  78. )
  79. {
  80. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  81. }
  82. VOID
  83. Terminate (
  84. VOID
  85. )
  86. {
  87. pCallEntryPoints (DLL_PROCESS_DETACH);
  88. }
  89. VOID
  90. HelpAndExit (
  91. VOID
  92. )
  93. {
  94. //
  95. // This routine is called whenever command line args are wrong
  96. //
  97. fprintf (
  98. stderr,
  99. "Command Line Syntax:\n\n"
  100. //
  101. // Describe command line syntax(es), indent 2 spaces
  102. //
  103. " homenet /S|/D\n"
  104. "\nDescription:\n\n"
  105. //
  106. // Describe tool, indent 2 spaces
  107. //
  108. " HomeNet.exe is a proof-of-concept tool for the home networking transport.\n"
  109. "\nArguments:\n\n"
  110. //
  111. // Describe args, indent 2 spaces, say optional if necessary
  112. //
  113. " /S Executes the tool in source mode\n"
  114. " /D Executes the tool in destination mode\n"
  115. );
  116. exit (1);
  117. }
  118. BOOL
  119. pCtrlCRoutine (
  120. IN DWORD CtrlType
  121. )
  122. {
  123. SetEvent (g_StopHandle);
  124. WaitForSingleObject (g_ConnectionDone, INFINITE);
  125. return FALSE;
  126. }
  127. INT
  128. __cdecl
  129. _tmain (
  130. INT argc,
  131. PCTSTR argv[]
  132. )
  133. {
  134. INT i;
  135. BOOL destination = FALSE;
  136. BOOL source = FALSE;
  137. WSADATA startupData;
  138. INT result;
  139. g_StopHandle = CreateEvent (NULL, TRUE, FALSE, NULL);
  140. g_ConnectionDone = CreateEvent (NULL, TRUE, FALSE, NULL);
  141. SetConsoleCtrlHandler (pCtrlCRoutine, TRUE);
  142. //
  143. // Parse command line here
  144. //
  145. for (i = 1 ; i < argc ; i++) {
  146. if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
  147. switch (_totlower (_tcsnextc (&argv[i][1]))) {
  148. case TEXT('s'):
  149. if (source || destination) {
  150. HelpAndExit();
  151. }
  152. source = TRUE;
  153. break;
  154. case TEXT('d'):
  155. if (source || destination) {
  156. HelpAndExit();
  157. }
  158. destination = TRUE;
  159. break;
  160. default:
  161. HelpAndExit();
  162. }
  163. } else {
  164. //
  165. // Parse other args that don't require / or -
  166. //
  167. // None
  168. HelpAndExit();
  169. }
  170. }
  171. //
  172. // Begin processing
  173. //
  174. if (!Init()) {
  175. return 0;
  176. }
  177. //
  178. // Start sockets
  179. //
  180. result = WSAStartup (2, &startupData);
  181. if (result) {
  182. printf ("Can't start sockets. Code=%u\n", result);
  183. exit (1);
  184. }
  185. //
  186. // Do work
  187. //
  188. if (source) {
  189. pDoSource();
  190. } else {
  191. pDoDestination();
  192. }
  193. //
  194. // Shut down sockets
  195. //
  196. WSACleanup();
  197. //
  198. // End of processing
  199. //
  200. Terminate();
  201. return 0;
  202. }
  203. typedef struct {
  204. SOCKET Socket;
  205. BYTE BroadcastAddress[MAX_SOCKADDR];
  206. INT AddressLen;
  207. INT Family;
  208. INT Protocol;
  209. } BROADCASTSOCKET, *PBROADCASTSOCKET;
  210. typedef struct {
  211. SOCKET Socket;
  212. INT Family;
  213. INT Protocol;
  214. BOOL Datagram;
  215. } LISTENSOCKET, *PLISTENSOCKET;
  216. typedef struct {
  217. SOCKET Socket;
  218. BYTE LocalAddress[MAX_SOCKADDR];
  219. INT LocalAddressLen;
  220. BYTE RemoteAddress[MAX_SOCKADDR];
  221. INT RemoteAddressLen;
  222. INT Family;
  223. INT Protocol;
  224. BOOL Datagram;
  225. DATAGRAM_POOL DatagramPool;
  226. } CONNECTIONSOCKET, *PCONNECTIONSOCKET;
  227. typedef struct {
  228. BYTE LocalAddress[MAX_SOCKADDR];
  229. INT LocalAddressLen;
  230. BYTE RemoteAddress[MAX_SOCKADDR];
  231. INT RemoteAddressLen;
  232. INT Family;
  233. INT Protocol;
  234. BOOL Datagram;
  235. TCHAR DestinationName[MAX_COMPUTER_NAME];
  236. } CONNECTADDRESS, *PCONNECTADDRESS;
  237. typedef struct {
  238. PBROADCASTSOCKET BroadcastSockets;
  239. INT BroadcastCount;
  240. PLISTENSOCKET ListenSockets;
  241. INT ListenCount;
  242. CONNECTIONSOCKET ConnectionSocket;
  243. PGROWBUFFER AddressArray;
  244. } BROADCASTARGS, *PBROADCASTARGS;
  245. typedef struct {
  246. UINT StructSize;
  247. UINT FileCount;
  248. LONGLONG TotalSize;
  249. } TRANSFERMETRICS, *PTRANSFERMETRICS;
  250. PBROADCASTSOCKET
  251. pOpenOneBroadcastSocket (
  252. IN OUT PGROWBUFFER BroadcastSockets,
  253. IN SOCKADDR *SockAddr,
  254. IN INT SockAddrLen,
  255. IN INT Family,
  256. IN INT Protocol,
  257. IN PCTSTR DebugText
  258. )
  259. {
  260. PBROADCASTSOCKET broadcastSocket;
  261. BOOL b;
  262. broadcastSocket = (PBROADCASTSOCKET) GbGrow (BroadcastSockets, sizeof (BROADCASTSOCKET));
  263. broadcastSocket->Socket = socket (Family, SOCK_DGRAM, Protocol);
  264. if (broadcastSocket->Socket != INVALID_SOCKET) {
  265. b = TRUE;
  266. setsockopt (broadcastSocket->Socket, SOL_SOCKET, SO_BROADCAST, (PBYTE) &b, sizeof (b));
  267. setsockopt (broadcastSocket->Socket, SOL_SOCKET, SO_REUSEADDR, (PBYTE) &b, sizeof (b));
  268. if (bind (broadcastSocket->Socket, SockAddr, SockAddrLen)) {
  269. DEBUGMSG ((DBG_ERROR, "Can't bind to %s socket", DebugText));
  270. closesocket (broadcastSocket->Socket);
  271. broadcastSocket->Socket = INVALID_SOCKET;
  272. }
  273. }
  274. if (broadcastSocket->Socket == INVALID_SOCKET) {
  275. BroadcastSockets->End -= sizeof (BROADCASTSOCKET);
  276. broadcastSocket = NULL;
  277. } else {
  278. DEBUGMSG ((
  279. DBG_HOMENET,
  280. "%s is available for broadcast on socket %u",
  281. DebugText,
  282. (BroadcastSockets->End / sizeof (BROADCASTSOCKET)) - 1
  283. ));
  284. broadcastSocket->AddressLen = SockAddrLen;
  285. MYASSERT (SockAddrLen <= MAX_SOCKADDR);
  286. CopyMemory (broadcastSocket->BroadcastAddress, (PBYTE) SockAddr, SockAddrLen);
  287. broadcastSocket->Family = Family;
  288. broadcastSocket->Protocol = Protocol;
  289. }
  290. return broadcastSocket;
  291. }
  292. INT
  293. pOpenBroadcastSockets (
  294. OUT PGROWBUFFER BroadcastSockets
  295. )
  296. {
  297. SOCKADDR_IPX ipxAddr;
  298. SOCKADDR_IN tcpipAddr;
  299. SOCKADDR_NB netbiosAddr;
  300. NCB ncbEnum;
  301. LANA_ENUM leBuf;
  302. INT rc;
  303. INT i;
  304. PBROADCASTSOCKET broadcastSocket;
  305. BOOL b;
  306. TCHAR netbiosDebugText[32];
  307. MYASSERT (!BroadcastSockets->Buf && !BroadcastSockets->End);
  308. //
  309. // Open sockets for broadcasts
  310. //
  311. // IPX
  312. ZeroMemory (&ipxAddr, sizeof (ipxAddr));
  313. ipxAddr.sa_family = AF_IPX;
  314. memset (ipxAddr.sa_nodenum, 0xFF, 6);
  315. ipxAddr.sa_socket = IPX_BROADCAST_PORT;
  316. pOpenOneBroadcastSocket (
  317. BroadcastSockets,
  318. (SOCKADDR *) &ipxAddr,
  319. sizeof (ipxAddr),
  320. AF_IPX,
  321. NSPROTO_IPX,
  322. TEXT("IPX")
  323. );
  324. // TCP/IP
  325. ZeroMemory (&tcpipAddr, sizeof (tcpipAddr));
  326. tcpipAddr.sin_family = AF_INET;
  327. tcpipAddr.sin_addr.s_addr = htonl (INADDR_ANY);
  328. tcpipAddr.sin_port = TCPIP_BROADCAST_PORT;
  329. broadcastSocket = pOpenOneBroadcastSocket (
  330. BroadcastSockets,
  331. (SOCKADDR *) &tcpipAddr,
  332. sizeof (tcpipAddr),
  333. AF_INET,
  334. IPPROTO_UDP,
  335. TEXT("UDP")
  336. );
  337. if (broadcastSocket) {
  338. tcpipAddr.sin_addr.s_addr = htonl (INADDR_BROADCAST);
  339. CopyMemory (broadcastSocket->BroadcastAddress, &tcpipAddr, sizeof (tcpipAddr));
  340. }
  341. // NetBIOS
  342. ZeroMemory (&ncbEnum, sizeof (NCB));
  343. ncbEnum.ncb_command = NCBENUM;
  344. ncbEnum.ncb_buffer = (PBYTE) &leBuf;
  345. ncbEnum.ncb_length = sizeof (LANA_ENUM);
  346. rc = Netbios (&ncbEnum);
  347. if (rc == NRC_GOODRET) {
  348. for (i = 0 ; i < leBuf.length ; i++) {
  349. SET_NETBIOS_SOCKADDR (&netbiosAddr, NETBIOS_GROUP_NAME, "usmt", NETBIOS_BROADCAST_PORT);
  350. wsprintf (netbiosDebugText, TEXT("NETBIOS cli lana %u"), leBuf.lana[i]);
  351. pOpenOneBroadcastSocket (
  352. BroadcastSockets,
  353. (SOCKADDR *) &netbiosAddr,
  354. sizeof (netbiosAddr),
  355. AF_NETBIOS,
  356. -leBuf.lana[i],
  357. netbiosDebugText
  358. );
  359. }
  360. }
  361. return BroadcastSockets->End / sizeof (BROADCASTSOCKET);
  362. }
  363. PLISTENSOCKET
  364. pOpenOneListenSocket (
  365. IN OUT PGROWBUFFER ListenSockets,
  366. IN SOCKADDR *SockAddr,
  367. IN INT SockAddrLen,
  368. IN INT Family,
  369. IN BOOL Multicast,
  370. IN INT Protocol,
  371. IN PCTSTR DebugText
  372. )
  373. {
  374. PLISTENSOCKET listenSocket;
  375. BOOL b;
  376. listenSocket = (PLISTENSOCKET) GbGrow (ListenSockets, sizeof (LISTENSOCKET));
  377. listenSocket->Socket = socket (Family, Multicast ? SOCK_DGRAM : SOCK_STREAM, Protocol);
  378. listenSocket->Datagram = Multicast;
  379. listenSocket->Family = Family;
  380. listenSocket->Protocol = Protocol;
  381. if (listenSocket->Socket != INVALID_SOCKET) {
  382. b = TRUE;
  383. setsockopt (listenSocket->Socket, SOL_SOCKET, SO_REUSEADDR, (PBYTE) &b, sizeof (b));
  384. if (Multicast) {
  385. setsockopt (listenSocket->Socket, SOL_SOCKET, SO_BROADCAST, (PBYTE) &b, sizeof (b));
  386. }
  387. if (bind (listenSocket->Socket, SockAddr, SockAddrLen) ||
  388. (!Multicast && listen (listenSocket->Socket, 1))
  389. ) {
  390. DEBUGMSG ((DBG_ERROR, "Can't bind/listen to %s socket", DebugText));
  391. closesocket (listenSocket->Socket);
  392. listenSocket->Socket = INVALID_SOCKET;
  393. }
  394. }
  395. if (listenSocket->Socket == INVALID_SOCKET) {
  396. ListenSockets->End -= sizeof (LISTENSOCKET);
  397. listenSocket = NULL;
  398. } else {
  399. DEBUGMSG ((
  400. DBG_HOMENET,
  401. "%s is availble for connection on socket %u",
  402. DebugText,
  403. (ListenSockets->End / sizeof (LISTENSOCKET)) - 1
  404. ));
  405. }
  406. return listenSocket;
  407. }
  408. INT
  409. pOpenListenSockets (
  410. OUT PGROWBUFFER ListenSockets
  411. )
  412. {
  413. SOCKADDR_IPX ipxAddr;
  414. SOCKADDR_IN tcpipAddr;
  415. SOCKADDR_NB netbiosAddr;
  416. NCB ncbEnum;
  417. LANA_ENUM leBuf;
  418. INT rc;
  419. INT i;
  420. TCHAR netbiosDebugText[32];
  421. MYASSERT (!ListenSockets->Buf && !ListenSockets->End);
  422. //
  423. // Open sockets to accept inbound connections
  424. //
  425. // SPX
  426. ZeroMemory (&ipxAddr, sizeof (ipxAddr));
  427. ipxAddr.sa_family = AF_IPX;
  428. ipxAddr.sa_socket = IPX_CONNECT_PORT;
  429. pOpenOneListenSocket (
  430. ListenSockets,
  431. (SOCKADDR *) &ipxAddr,
  432. sizeof (ipxAddr),
  433. AF_IPX,
  434. FALSE,
  435. NSPROTO_SPX,
  436. TEXT("SPX")
  437. );
  438. // TCP/IP
  439. ZeroMemory (&tcpipAddr, sizeof (tcpipAddr));
  440. tcpipAddr.sin_family = AF_INET;
  441. tcpipAddr.sin_port = TCPIP_CONNECT_PORT;
  442. pOpenOneListenSocket (
  443. ListenSockets,
  444. (SOCKADDR *) &tcpipAddr,
  445. sizeof (tcpipAddr),
  446. AF_INET,
  447. FALSE,
  448. IPPROTO_TCP,
  449. TEXT("TCP")
  450. );
  451. // NetBIOS
  452. ZeroMemory (&ncbEnum, sizeof (NCB));
  453. ncbEnum.ncb_command = NCBENUM;
  454. ncbEnum.ncb_buffer = (PBYTE) &leBuf;
  455. ncbEnum.ncb_length = sizeof (LANA_ENUM);
  456. rc = Netbios (&ncbEnum);
  457. if (rc == NRC_GOODRET) {
  458. for (i = 0 ; i < leBuf.length ; i++) {
  459. SET_NETBIOS_SOCKADDR (&netbiosAddr, NETBIOS_GROUP_NAME, "usmt", NETBIOS_CONNECT_PORT);
  460. wsprintf (netbiosDebugText, TEXT("NETBIOS srv lana %u"), leBuf.lana[i]);
  461. pOpenOneListenSocket (
  462. ListenSockets,
  463. (SOCKADDR *) &netbiosAddr,
  464. sizeof (netbiosAddr),
  465. AF_NETBIOS,
  466. TRUE,
  467. -leBuf.lana[i],
  468. netbiosDebugText
  469. );
  470. }
  471. }
  472. return ListenSockets->End / sizeof (LISTENSOCKET);
  473. }
  474. PCTSTR
  475. pGetNameFromMessage (
  476. IN PCTSTR Message
  477. )
  478. {
  479. PCTSTR p;
  480. PCTSTR name = NULL;
  481. INT len;
  482. CHARTYPE ch;
  483. if (_tcsprefixcmp (Message, TEXT("usmt-v2,"))) {
  484. p = Message + 8;
  485. len = 0;
  486. while (*p) {
  487. ch = _tcsnextc (p);
  488. p = _tcsinc (p);
  489. if (ch == TEXT(',')) {
  490. break;
  491. }
  492. if (ch < TEXT('0') || ch > TEXT('9')) {
  493. break;
  494. }
  495. len = len * 10 + (ch - TEXT('0'));
  496. }
  497. if (ch == TEXT(',') && len < MAX_COMPUTER_NAME) {
  498. name = p;
  499. while (*p && len) {
  500. if (*p < 32) {
  501. break;
  502. }
  503. p++;
  504. len--;
  505. }
  506. if (len || *p) {
  507. name = NULL;
  508. }
  509. }
  510. }
  511. return name;
  512. }
  513. VOID
  514. pTranslateBroadcastAddrToConnectAddr (
  515. IN INT Family,
  516. IN OUT PINT Protocol,
  517. IN OUT PBOOL Datagram,
  518. IN OUT SOCKADDR *SockAddr
  519. )
  520. {
  521. SOCKADDR_IPX *ipxAddr;
  522. SOCKADDR_IN *tcpipAddr;
  523. SOCKADDR_NB *netbiosAddr;
  524. switch (Family) {
  525. case AF_INET:
  526. *Protocol = IPPROTO_TCP;
  527. tcpipAddr = (SOCKADDR_IN *) SockAddr;
  528. tcpipAddr->sin_port = TCPIP_CONNECT_PORT;
  529. break;
  530. case AF_IPX:
  531. *Protocol = NSPROTO_SPX;
  532. ipxAddr = (SOCKADDR_IPX *) SockAddr;
  533. ipxAddr->sa_socket = IPX_CONNECT_PORT;
  534. break;
  535. case AF_NETBIOS:
  536. netbiosAddr = (SOCKADDR_NB *) SockAddr;
  537. netbiosAddr->snb_name[NETBIOS_NAME_LENGTH - 1] = NETBIOS_CONNECT_PORT;
  538. *Datagram = TRUE;
  539. break;
  540. }
  541. }
  542. VOID
  543. pResetPort (
  544. IN INT Family,
  545. IN OUT SOCKADDR *SockAddr
  546. )
  547. {
  548. SOCKADDR_IN *tcpipAddr;
  549. switch (Family) {
  550. case AF_INET:
  551. tcpipAddr = (SOCKADDR_IN *) SockAddr;
  552. tcpipAddr->sin_port = 0;
  553. break;
  554. }
  555. }
  556. INT
  557. pSourceBroadcast (
  558. PBROADCASTARGS Args
  559. )
  560. {
  561. INT i;
  562. INT bytesIn;
  563. DWORD rc;
  564. TCHAR message[256];
  565. UINT size;
  566. FD_SET set;
  567. TIMEVAL zero = {0,0};
  568. INT waitCycle = -1;
  569. BOOL result = FALSE;
  570. PCTSTR name;
  571. PCONNECTADDRESS address;
  572. PCONNECTADDRESS end;
  573. PBROADCASTSOCKET broadcastSocket;
  574. BYTE remoteAddr[MAX_SOCKADDR];
  575. INT remoteAddrLen;
  576. for (;;) {
  577. //
  578. // Check cancel
  579. //
  580. rc = WaitForSingleObject (g_StopHandle, 250);
  581. if (rc == WAIT_OBJECT_0) {
  582. result = FALSE;
  583. break;
  584. }
  585. //
  586. // Check time to live
  587. //
  588. if (waitCycle > -1) {
  589. waitCycle--;
  590. if (!waitCycle) {
  591. break;
  592. }
  593. }
  594. //
  595. // Check for a message
  596. //
  597. FD_ZERO (&set);
  598. for (i = 0 ; i < Args->BroadcastCount ; i++) {
  599. FD_SET (Args->BroadcastSockets[i].Socket, &set);
  600. }
  601. i = select (0, &set, NULL, NULL, &zero);
  602. if (i > 0) {
  603. // once we receive something, wait 15 additional seconds for other inbound datagrams
  604. if (waitCycle == -1) {
  605. waitCycle = 60;
  606. }
  607. for (i = 0 ; i < Args->BroadcastCount ; i++) {
  608. broadcastSocket = &Args->BroadcastSockets[i];
  609. if (FD_ISSET (broadcastSocket->Socket, &set)) {
  610. remoteAddrLen = MAX_SOCKADDR;
  611. bytesIn = recvfrom (
  612. broadcastSocket->Socket,
  613. message,
  614. 254,
  615. 0,
  616. (SOCKADDR *) remoteAddr,
  617. &remoteAddrLen
  618. );
  619. if (bytesIn > (10 * sizeof (TCHAR))) {
  620. message[bytesIn] = 0;
  621. message[bytesIn + 1] = 0;
  622. //
  623. // Parse the inbound text. It must be in the format of
  624. //
  625. // usmt-v2,<tchars>,<name>
  626. //
  627. name = pGetNameFromMessage (message);
  628. if (name) {
  629. result = TRUE;
  630. //
  631. // Scan the address list for the name
  632. //
  633. address = (PCONNECTADDRESS) Args->AddressArray->Buf;
  634. end = (PCONNECTADDRESS) (Args->AddressArray->Buf + Args->AddressArray->End);
  635. while (address < end) {
  636. if (StringIMatch (address->DestinationName, name)) {
  637. if (address->Family == broadcastSocket->Family) {
  638. break;
  639. }
  640. }
  641. address++;
  642. }
  643. if (address >= end) {
  644. //
  645. // New computer name; add to the address list
  646. //
  647. address = (PCONNECTADDRESS) GbGrow (Args->AddressArray, sizeof (CONNECTADDRESS));
  648. address->RemoteAddressLen = remoteAddrLen;
  649. CopyMemory (address->RemoteAddress, remoteAddr, remoteAddrLen);
  650. address->LocalAddressLen = MAX_SOCKADDR;
  651. if (getsockname (
  652. broadcastSocket->Socket,
  653. (SOCKADDR *) address->LocalAddress,
  654. &address->LocalAddressLen
  655. )) {
  656. address->LocalAddressLen = broadcastSocket->AddressLen;
  657. ZeroMemory (address->LocalAddress, broadcastSocket->AddressLen);
  658. DEBUGMSG ((DBG_HOMENET, "Failed to get local socket name; using nul name instead"));
  659. }
  660. address->Family = broadcastSocket->Family;
  661. address->Protocol = broadcastSocket->Protocol;
  662. address->Datagram = FALSE;
  663. pTranslateBroadcastAddrToConnectAddr (
  664. address->Family,
  665. &address->Protocol,
  666. &address->Datagram,
  667. (SOCKADDR *) &address->RemoteAddress
  668. );
  669. StringCopy (address->DestinationName, name);
  670. DEBUGMSG ((DBG_HOMENET, "Destination found: %s (protocol %i)", name, address->Family));
  671. }
  672. }
  673. ELSE_DEBUGMSG ((DBG_HOMENET, "garbage found: %s", message));
  674. }
  675. }
  676. }
  677. }
  678. }
  679. return result ? Args->AddressArray->End / sizeof (CONNECTADDRESS) : 0;
  680. }
  681. BOOL
  682. pDestinationBroadcast (
  683. PBROADCASTARGS Args
  684. )
  685. {
  686. INT i;
  687. DWORD rc;
  688. INT socketNum = 0;
  689. TCHAR message[256];
  690. TCHAR name[128];
  691. UINT size;
  692. FD_SET set;
  693. TIMEVAL zero = {0,0};
  694. PBROADCASTSOCKET broadcastSocket;
  695. BOOL result = FALSE;
  696. BYTE sockAddr[MAX_SOCKADDR];
  697. INT sockAddrLen;
  698. size = MAX_COMPUTER_NAME;
  699. GetComputerName (name, &size);
  700. size = wsprintf (message, TEXT("USMT-v2,%u,%s"), TcharCount (name), name);
  701. size = (size + 1) * sizeof (TCHAR);
  702. for (;;) {
  703. //
  704. // Check cancel
  705. //
  706. rc = WaitForSingleObject (g_StopHandle, 250);
  707. if (rc == WAIT_OBJECT_0) {
  708. break;
  709. }
  710. //
  711. // Send out the message
  712. //
  713. broadcastSocket = &Args->BroadcastSockets[socketNum];
  714. i = sendto (
  715. broadcastSocket->Socket,
  716. message,
  717. size,
  718. 0,
  719. (SOCKADDR *) broadcastSocket->BroadcastAddress,
  720. broadcastSocket->AddressLen
  721. );
  722. if (i == SOCKET_ERROR) {
  723. DEBUGMSG ((DBG_VERBOSE, "Error sending on socket %u: %u", socketNum, WSAGetLastError()));
  724. } else {
  725. DEBUGMSG ((DBG_HOMENET, "Sent data on socket %u", socketNum));
  726. }
  727. socketNum++;
  728. if (socketNum >= Args->BroadcastCount) {
  729. socketNum = 0;
  730. }
  731. //
  732. // Check for an inbound connection
  733. //
  734. FD_ZERO (&set);
  735. for (i = 0 ; i < Args->ListenCount ; i++) {
  736. FD_SET (Args->ListenSockets[i].Socket, &set);
  737. }
  738. i = select (0, &set, NULL, NULL, &zero);
  739. if (i > 0) {
  740. DEBUGMSG ((DBG_HOMENET, "Connection request count = %i", i));
  741. for (i = 0 ; i < Args->ListenCount ; i++) {
  742. if (FD_ISSET (Args->ListenSockets[i].Socket, &set)) {
  743. Args->ConnectionSocket.RemoteAddressLen = MAX_SOCKADDR;
  744. Args->ConnectionSocket.Socket = accept (
  745. Args->ListenSockets[i].Socket,
  746. (SOCKADDR *) Args->ConnectionSocket.RemoteAddress,
  747. &Args->ConnectionSocket.RemoteAddressLen
  748. );
  749. if (Args->ConnectionSocket.Socket != INVALID_SOCKET) {
  750. Args->ConnectionSocket.Family = Args->ListenSockets[i].Family;
  751. Args->ConnectionSocket.Protocol = Args->ListenSockets[i].Protocol;
  752. Args->ConnectionSocket.Datagram = Args->ListenSockets[i].Datagram;
  753. ZeroMemory (&Args->ConnectionSocket.DatagramPool, sizeof (DATAGRAM_POOL));
  754. if (Args->ConnectionSocket.Datagram) {
  755. Args->ConnectionSocket.DatagramPool.Pool = PmCreatePool();
  756. }
  757. Args->ConnectionSocket.LocalAddressLen = MAX_SOCKADDR;
  758. if (getsockname (
  759. Args->ConnectionSocket.Socket,
  760. (SOCKADDR *) Args->ConnectionSocket.LocalAddress,
  761. &Args->ConnectionSocket.LocalAddressLen
  762. )) {
  763. Args->ConnectionSocket.LocalAddressLen = broadcastSocket->AddressLen;
  764. ZeroMemory (Args->ConnectionSocket.LocalAddress, broadcastSocket->AddressLen);
  765. DEBUGMSG ((DBG_HOMENET, "Failed to get local socket name; using nul name instead"));
  766. }
  767. result = TRUE;
  768. break;
  769. } else {
  770. DEBUGMSG ((DBG_ERROR, "select indicated connection, but accept failed"));
  771. }
  772. }
  773. }
  774. if (result) {
  775. break;
  776. }
  777. }
  778. }
  779. return result;
  780. }
  781. INT
  782. pNameResolver (
  783. OUT PGROWBUFFER AddressBuffer,
  784. IN BOOL DestinationMode,
  785. OUT PCONNECTIONSOCKET ConnectionSocket
  786. )
  787. {
  788. INT size;
  789. BROADCASTARGS args;
  790. INT i;
  791. INT result = 0;
  792. BOOL b;
  793. BOOL connected = FALSE;
  794. GROWBUFFER broadcastSockets = INIT_GROWBUFFER;
  795. GROWBUFFER listenSockets = INIT_GROWBUFFER;
  796. INT broadcastSocketCount;
  797. INT listenSocketCount = 0;
  798. PLISTENSOCKET connection;
  799. __try {
  800. //
  801. // In source mode, we collect datagrams sent by destinations on the network. After
  802. // the first datagram is received, collection continues for 15 seconds. At
  803. // that point, we have a list of socket addresses, protocol, and destination names.
  804. //
  805. // In destination mode, we send out periodic broadcasts, and we wait until a source
  806. // connects or the cancel event is signaled.
  807. //
  808. broadcastSocketCount = pOpenBroadcastSockets (&broadcastSockets);
  809. if (!broadcastSocketCount) {
  810. __leave;
  811. }
  812. if (DestinationMode) {
  813. listenSocketCount = pOpenListenSockets (&listenSockets);
  814. if (!listenSocketCount) {
  815. DEBUGMSG ((DBG_ERROR, "Able to set up broadcast sockets but not connection sockets"));
  816. __leave;
  817. }
  818. }
  819. // call mode-specific routine
  820. ZeroMemory (&args, sizeof (args));
  821. args.AddressArray = AddressBuffer;
  822. args.BroadcastSockets = (PBROADCASTSOCKET) broadcastSockets.Buf;
  823. args.BroadcastCount = broadcastSocketCount;
  824. args.ListenSockets = (PLISTENSOCKET) listenSockets.Buf;
  825. args.ListenCount = listenSocketCount;
  826. b = DestinationMode ? pDestinationBroadcast (&args) : pSourceBroadcast (&args);
  827. //
  828. // Clean up all sockets
  829. //
  830. for (i = 0 ; i < args.BroadcastCount ; i++) {
  831. closesocket (args.BroadcastSockets[i].Socket);
  832. }
  833. if (DestinationMode) {
  834. for (i = 0 ; i < args.ListenCount ; i++) {
  835. closesocket (args.ListenSockets[i].Socket);
  836. }
  837. }
  838. if (b) {
  839. if (DestinationMode) {
  840. CopyMemory (ConnectionSocket, &args.ConnectionSocket, sizeof (CONNECTIONSOCKET));
  841. result = 1;
  842. } else {
  843. result = AddressBuffer->End / sizeof (CONNECTADDRESS);
  844. }
  845. }
  846. }
  847. __finally {
  848. GbFree (&broadcastSockets);
  849. GbFree (&listenSockets);
  850. SetEvent (g_ConnectionDone);
  851. }
  852. return result;
  853. }
  854. BOOL
  855. pSendExactData (
  856. IN SOCKET Socket,
  857. IN PBYTE Data,
  858. IN UINT DataLen
  859. )
  860. {
  861. INT result;
  862. result = send (Socket, Data, DataLen, 0);
  863. return result == (INT) DataLen;
  864. }
  865. BOOL
  866. pSendDatagramData (
  867. IN PDATAGRAM_POOL DatagramPool,
  868. IN PCBYTE Data,
  869. IN UINT DataLen
  870. )
  871. {
  872. PDATAGRAM_PACKET header;
  873. BYTE buffer[512];
  874. PBYTE dataPtr;
  875. UINT bytesSent = 0;
  876. UINT bytesToSend;
  877. INT result;
  878. header = (PDATAGRAM_PACKET) buffer;
  879. dataPtr = (PBYTE) (&header[1]);
  880. do {
  881. bytesToSend = DataLen - bytesSent;
  882. bytesToSend = min (bytesToSend, 256);
  883. header->PacketNumber = DatagramPool->SendSequenceNumber;
  884. DatagramPool->SendSequenceNumber++;
  885. header->DataLength = (WORD) bytesToSend;
  886. CopyMemory (dataPtr, Data, bytesToSend);
  887. result = send (
  888. DatagramPool->Socket,
  889. (PBYTE) header,
  890. header->DataLength + sizeof (DATAGRAM_PACKET),
  891. 0
  892. );
  893. if (result == SOCKET_ERROR) {
  894. break;
  895. }
  896. bytesToSend = (UINT) result - sizeof (DATAGRAM_PACKET);
  897. Data += bytesToSend;
  898. bytesSent += bytesToSend;
  899. } while (bytesSent < DataLen);
  900. return bytesSent == DataLen;
  901. }
  902. PBYTE
  903. pReceiveExactData (
  904. IN SOCKET Socket,
  905. IN OUT PGROWBUFFER Buffer,
  906. IN UINT BytesToReceive
  907. )
  908. {
  909. PBYTE recvBuf;
  910. PBYTE bufPos;
  911. UINT bytesSoFar = 0;
  912. INT result;
  913. UINT readSize;
  914. Buffer->End = 0;
  915. recvBuf = GbGrow (Buffer, BytesToReceive);
  916. bufPos = recvBuf;
  917. do {
  918. readSize = BytesToReceive - bytesSoFar;
  919. result = recv (Socket, bufPos, (INT) readSize, 0);
  920. if (result == SOCKET_ERROR) {
  921. DEBUGMSG ((DBG_ERROR, "Error reading from socket"));
  922. break;
  923. }
  924. bufPos += result;
  925. bytesSoFar += result;
  926. } while (bytesSoFar < BytesToReceive);
  927. MYASSERT (bytesSoFar <= BytesToReceive);
  928. return bytesSoFar == BytesToReceive ? recvBuf : NULL;
  929. }
  930. BOOL
  931. pReceiveDatagramData (
  932. IN PDATAGRAM_POOL DatagramPool,
  933. IN OUT PGROWBUFFER Buffer, OPTIONAL
  934. OUT PBYTE AlternateBuffer, OPTIONAL
  935. IN UINT BytesToReceive
  936. )
  937. {
  938. PDATAGRAM_POOL_ITEM itemHeader;
  939. PDATAGRAM_POOL_ITEM prevItem, nextItem;
  940. BYTE buffer[512];
  941. PBYTE dataPtr;
  942. PBYTE recvBuf;
  943. PBYTE bufPos;
  944. UINT bytesSoFar = 0;
  945. UINT bytesLeft;
  946. INT result;
  947. UINT readSize;
  948. PDATAGRAM_POOL_ITEM item;
  949. UINT newPacketNum;
  950. UINT currentPacketNum;
  951. if (Buffer) {
  952. Buffer->End = 0;
  953. recvBuf = GbGrow (Buffer, BytesToReceive);
  954. } else {
  955. recvBuf = AlternateBuffer;
  956. }
  957. bufPos = recvBuf;
  958. itemHeader = (PDATAGRAM_POOL_ITEM) buffer;
  959. dataPtr = (PBYTE) (&itemHeader[1]);
  960. for (;;) {
  961. //
  962. // Take all available data out of the pool
  963. //
  964. item = DatagramPool->FirstItem;
  965. bytesLeft = BytesToReceive - bytesSoFar;
  966. while (item) {
  967. if (item->Header.PacketNumber == DatagramPool->RecvSequenceNumber) {
  968. //
  969. // Two cases:
  970. //
  971. // 1. Want entire packet
  972. // 2. Want partial packet
  973. //
  974. if (bytesLeft >= item->Header.DataLength) {
  975. // entire packet
  976. CopyMemory (bufPos, item->PacketData, item->Header.DataLength);
  977. MYASSERT (!item->Prev);
  978. if (item->Next) {
  979. item->Next->Prev = NULL;
  980. }
  981. DatagramPool->FirstItem = item->Next;
  982. bytesSoFar += item->Header.DataLength;
  983. PmReleaseMemory (DatagramPool->Pool, item);
  984. DatagramPool->RecvSequenceNumber++;
  985. } else {
  986. // partial packet
  987. CopyMemory (bufPos, item->PacketData, bytesLeft);
  988. item->PacketData += bytesLeft;
  989. item->Header.DataLength -= (WORD) bytesLeft;
  990. bytesSoFar += bytesLeft;
  991. }
  992. if (BytesToReceive == bytesSoFar) {
  993. return TRUE;
  994. }
  995. }
  996. }
  997. //
  998. // Data is not available in the pool. Receive one packet and then try again.
  999. //
  1000. // header
  1001. if (!pReceiveExactData (
  1002. DatagramPool->Socket,
  1003. NULL,
  1004. (PBYTE) &itemHeader->Header,
  1005. sizeof (DATAGRAM_PACKET)
  1006. )) {
  1007. break;
  1008. }
  1009. if (itemHeader->Header.DataLength > 256) {
  1010. break;
  1011. }
  1012. // data
  1013. if (!pReceiveExactData (
  1014. DatagramPool->Socket,
  1015. NULL,
  1016. (PBYTE) dataPtr,
  1017. itemHeader->Header.DataLength
  1018. )) {
  1019. break;
  1020. }
  1021. //
  1022. // Put the packet in the item linked list, sorted by packet number
  1023. //
  1024. item = (PDATAGRAM_POOL_ITEM) PmDuplicateMemory (
  1025. DatagramPool->Pool,
  1026. (PCBYTE) itemHeader,
  1027. itemHeader->Header.DataLength + sizeof (DATAGRAM_PACKET)
  1028. );
  1029. item->PacketData = (PBYTE) (&item[1]);
  1030. prevItem = NULL;
  1031. nextItem = DatagramPool->FirstItem;
  1032. while (nextItem) {
  1033. //
  1034. // Account for wrapping; assume a packet number difference no more
  1035. // than 16383 out-of-sequence packets in the queue (about 4M of
  1036. // data)
  1037. //
  1038. if (nextItem->Header.PacketNumber >= 49152 && item->Header.PacketNumber < 16384) {
  1039. newPacketNum = (UINT) item->Header.PacketNumber + 65536;
  1040. currentPacketNum = (UINT) nextItem->Header.PacketNumber;
  1041. } else if (nextItem->Header.PacketNumber < 16384 && item->Header.PacketNumber >= 49152) {
  1042. newPacketNum = (UINT) item->Header.PacketNumber;
  1043. currentPacketNum = (UINT) nextItem->Header.PacketNumber + 65536;
  1044. } else {
  1045. newPacketNum = (UINT) item->Header.PacketNumber;
  1046. currentPacketNum = (UINT) nextItem->Header.PacketNumber;
  1047. }
  1048. if (newPacketNum < currentPacketNum) {
  1049. break;
  1050. }
  1051. prevItem = nextItem;
  1052. nextItem = nextItem->Next;
  1053. }
  1054. item->Next = nextItem;
  1055. item->Prev = prevItem;
  1056. if (!prevItem) {
  1057. DatagramPool->FirstItem = item;
  1058. }
  1059. }
  1060. return bytesSoFar == BytesToReceive;
  1061. }
  1062. BOOL
  1063. pSendFile (
  1064. IN SOCKET Socket,
  1065. IN PDATAGRAM_POOL DatagramPool, OPTIONAL
  1066. IN PCTSTR LocalFileName, OPTIONAL
  1067. IN PCTSTR DestFileName OPTIONAL
  1068. )
  1069. {
  1070. INT len;
  1071. GROWBUFFER data = INIT_GROWBUFFER;
  1072. BOOL result = FALSE;
  1073. HANDLE file = NULL;
  1074. LONGLONG fileSize;
  1075. __try {
  1076. //
  1077. // If no file was specified, send length of zero
  1078. //
  1079. if (!LocalFileName || !DestFileName) {
  1080. len = 0;
  1081. if (!pSendExactData (Socket, (PBYTE) &len, 4)) {
  1082. __leave;
  1083. }
  1084. result = TRUE;
  1085. __leave;
  1086. }
  1087. //
  1088. // Try to open the file
  1089. //
  1090. fileSize = BfGetFileSize (LocalFileName);
  1091. file = BfOpenFile (LocalFileName);
  1092. if (!file) {
  1093. __leave;
  1094. }
  1095. //
  1096. // Send the file name and file size
  1097. //
  1098. len = ByteCount (DestFileName);
  1099. if (!pSendExactData (Socket, (PBYTE) &len, 4)) {
  1100. __leave;
  1101. }
  1102. if (!pSendExactData (Socket, (PBYTE) DestFileName, len)) {
  1103. __leave;
  1104. }
  1105. if (!pSendExactData (Socket, (PBYTE) &fileSize, 8)) {
  1106. __leave;
  1107. }
  1108. //
  1109. // Send the data 64K at a time
  1110. //
  1111. GbGrow (&data, 0x10000);
  1112. while (fileSize) {
  1113. if (fileSize >= 0x10000) {
  1114. if (!BfReadFile (file, data.Buf, 0x10000)) {
  1115. DEBUGMSG ((DBG_ERROR, "Can't read from file"));
  1116. __leave;
  1117. }
  1118. if (!pSendExactData (Socket, data.Buf, 0x10000)) {
  1119. __leave;
  1120. }
  1121. fileSize -= 0x10000;
  1122. } else {
  1123. if (!BfReadFile (file, data.Buf, (UINT) fileSize)) {
  1124. DEBUGMSG ((DBG_ERROR, "Can't read from file"));
  1125. __leave;
  1126. }
  1127. if (!pSendExactData (Socket, data.Buf, (UINT) fileSize)) {
  1128. __leave;
  1129. }
  1130. fileSize = 0;
  1131. }
  1132. }
  1133. //
  1134. // Done!
  1135. //
  1136. result = TRUE;
  1137. }
  1138. __finally {
  1139. GbFree (&data);
  1140. if (file) {
  1141. CloseHandle (file);
  1142. }
  1143. }
  1144. return result;
  1145. }
  1146. BOOL
  1147. pReceiveStreamFile (
  1148. IN SOCKET Socket
  1149. )
  1150. {
  1151. TCHAR fileName[MAX_PATH * 2];
  1152. INT len;
  1153. INT bytesIn;
  1154. GROWBUFFER data = INIT_GROWBUFFER;
  1155. BOOL result = FALSE;
  1156. PTSTR p;
  1157. HANDLE file = NULL;
  1158. LONGLONG fileSize;
  1159. __try {
  1160. //
  1161. // Wait for file name
  1162. //
  1163. if (!pReceiveExactData (Socket, &data, 4)) {
  1164. __leave;
  1165. }
  1166. len = *((PDWORD) data.Buf);
  1167. if (!len) {
  1168. result = TRUE;
  1169. __leave;
  1170. }
  1171. if (len >= (MAX_PATH * sizeof (TCHAR))) {
  1172. __leave;
  1173. }
  1174. if (!pReceiveExactData (Socket, &data, len)) {
  1175. __leave;
  1176. }
  1177. StringCopy (fileName, g_StoragePath);
  1178. GbGrow (&data, sizeof (TCHAR) * 2);
  1179. p = (PTSTR) data.Buf;
  1180. p[len] = 0;
  1181. p[len + 1] = 0;
  1182. StringCopy (AppendWack (fileName), p);
  1183. //
  1184. // Get the file size
  1185. //
  1186. if (!pReceiveExactData (Socket, &data, 8)) {
  1187. __leave;
  1188. }
  1189. fileSize = *((PLONGLONG) data.Buf);
  1190. DEBUGMSG ((DBG_HOMENET, "Receiving %s", fileName));
  1191. //
  1192. // Create the file
  1193. //
  1194. file = BfCreateFile (fileName);
  1195. if (!file) {
  1196. __leave;
  1197. }
  1198. //
  1199. // Fetch the data 64K at a time
  1200. //
  1201. while (fileSize) {
  1202. if (fileSize >= 0x10000) {
  1203. if (!pReceiveExactData (Socket, &data, 0x10000)) {
  1204. __leave;
  1205. }
  1206. if (!BfWriteFile (file, data.Buf, data.End)) {
  1207. DEBUGMSG ((DBG_ERROR, "Can't write to file"));
  1208. __leave;
  1209. }
  1210. fileSize -= 0x10000;
  1211. } else {
  1212. if (!pReceiveExactData (Socket, &data, (UINT) fileSize)) {
  1213. __leave;
  1214. }
  1215. if (!BfWriteFile (file, data.Buf, data.End)) {
  1216. DEBUGMSG ((DBG_ERROR, "Can't write to file"));
  1217. __leave;
  1218. }
  1219. fileSize = 0;
  1220. }
  1221. }
  1222. //
  1223. // Done!
  1224. //
  1225. result = TRUE;
  1226. }
  1227. __finally {
  1228. GbFree (&data);
  1229. if (file) {
  1230. CloseHandle (file);
  1231. if (!result) {
  1232. DeleteFile (fileName);
  1233. }
  1234. }
  1235. }
  1236. return result;
  1237. }
  1238. BOOL
  1239. pReceiveFile (
  1240. IN SOCKET Socket,
  1241. IN BOOL Datagram
  1242. )
  1243. {
  1244. if (Datagram) {
  1245. return FALSE;
  1246. }
  1247. return pReceiveStreamFile (Socket);
  1248. }
  1249. BOOL
  1250. pSendMetrics (
  1251. IN SOCKET Socket,
  1252. IN BOOL Datagram,
  1253. IN PTRANSFERMETRICS Metrics
  1254. )
  1255. {
  1256. if (Datagram) {
  1257. return FALSE;
  1258. }
  1259. Metrics->StructSize = sizeof (TRANSFERMETRICS);
  1260. if (!pSendExactData (Socket, (PBYTE) Metrics, sizeof (TRANSFERMETRICS))) {
  1261. return FALSE;
  1262. }
  1263. return TRUE;
  1264. }
  1265. BOOL
  1266. pReceiveMetrics (
  1267. IN SOCKET Socket,
  1268. OUT PTRANSFERMETRICS Metrics
  1269. )
  1270. {
  1271. GROWBUFFER data = INIT_GROWBUFFER;
  1272. BOOL result = FALSE;
  1273. __try {
  1274. if (!pReceiveExactData (Socket, &data, sizeof (TRANSFERMETRICS))) {
  1275. __leave;
  1276. }
  1277. CopyMemory (Metrics, data.Buf, data.End);
  1278. if (Metrics->StructSize != sizeof (TRANSFERMETRICS)) {
  1279. DEBUGMSG ((DBG_ERROR, "Invalid transfer metrics received"));
  1280. __leave;
  1281. }
  1282. result = TRUE;
  1283. }
  1284. __finally {
  1285. GbFree (&data);
  1286. }
  1287. return result;
  1288. }
  1289. VOID
  1290. pDoDestination (
  1291. VOID
  1292. )
  1293. {
  1294. GROWBUFFER sourceAddress = INIT_GROWBUFFER;
  1295. CONNECTIONSOCKET connection;
  1296. TRANSFERMETRICS metrics;
  1297. UINT u;
  1298. ZeroMemory (&connection, sizeof (CONNECTIONSOCKET));
  1299. connection.Socket = INVALID_SOCKET;
  1300. __try {
  1301. GetTempPath (MAX_PATH, g_StoragePath);
  1302. if (!pNameResolver (&sourceAddress, TRUE, &connection)) {
  1303. __leave;
  1304. }
  1305. printf ("Connected!\n");
  1306. if (!pReceiveMetrics (connection.Socket, &metrics)) {
  1307. __leave;
  1308. }
  1309. for (u = 0 ; u < metrics.FileCount ; u++) {
  1310. if (!pReceiveFile (connection.Socket, connection.Datagram)) {
  1311. __leave;
  1312. }
  1313. }
  1314. }
  1315. __finally {
  1316. GbFree (&sourceAddress);
  1317. if (connection.Socket != INVALID_SOCKET) {
  1318. closesocket (connection.Socket);
  1319. }
  1320. }
  1321. }
  1322. BOOL
  1323. pConnectToDestination (
  1324. IN PCONNECTADDRESS Address,
  1325. OUT PCONNECTIONSOCKET Connection
  1326. )
  1327. {
  1328. BOOL result = FALSE;
  1329. BOOL b;
  1330. CopyMemory (Connection->LocalAddress, Address->LocalAddress, Address->LocalAddressLen);
  1331. Connection->LocalAddressLen = Address->LocalAddressLen;
  1332. CopyMemory (Connection->RemoteAddress, Address->RemoteAddress, Address->RemoteAddressLen);
  1333. Connection->RemoteAddressLen = Address->RemoteAddressLen;
  1334. Connection->Socket = socket (
  1335. Address->Family,
  1336. Address->Datagram ? SOCK_DGRAM : SOCK_STREAM,
  1337. Address->Protocol
  1338. );
  1339. if (Connection->Socket == INVALID_SOCKET) {
  1340. DEBUGMSG ((DBG_ERROR, "Can't create socket for connection"));
  1341. return FALSE;
  1342. }
  1343. __try {
  1344. b = TRUE;
  1345. setsockopt (Connection->Socket, SOL_SOCKET, SO_REUSEADDR, (PBYTE) &b, sizeof (b));
  1346. pResetPort (Address->Family, (SOCKADDR *) Address->LocalAddress);
  1347. if (bind (Connection->Socket, (SOCKADDR *) Address->LocalAddress, Address->LocalAddressLen)) {
  1348. DEBUGMSG ((DBG_ERROR, "Failed to bind to connection socket"));
  1349. __leave;
  1350. }
  1351. if (connect (Connection->Socket, (SOCKADDR *) Address->RemoteAddress, Address->RemoteAddressLen)) {
  1352. DEBUGMSG ((DBG_ERROR, "Failed to connect to socket"));
  1353. __leave;
  1354. }
  1355. Connection->Family = Address->Family;
  1356. Connection->Protocol = Address->Protocol;
  1357. Connection->Datagram = Address->Datagram;
  1358. result = TRUE;
  1359. }
  1360. __finally {
  1361. if (!result && Connection->Socket != INVALID_SOCKET) {
  1362. closesocket (Connection->Socket);
  1363. Connection->Socket = INVALID_SOCKET;
  1364. }
  1365. }
  1366. return result;
  1367. }
  1368. VOID
  1369. pDoSource (
  1370. VOID
  1371. )
  1372. {
  1373. GROWBUFFER destinationAddresses = INIT_GROWBUFFER;
  1374. INT destinationCount;
  1375. PCTSTR firstName;
  1376. PCONNECTADDRESS addressArray;
  1377. PCONNECTADDRESS address;
  1378. CONNECTIONSOCKET connection;
  1379. INT i;
  1380. TRANSFERMETRICS metrics;
  1381. PCTSTR localFileName = TEXT("c:\\debug.inf");
  1382. PCTSTR destFileName = TEXT("foo.inf");
  1383. ZeroMemory (&connection, sizeof (CONNECTIONSOCKET));
  1384. connection.Socket = INVALID_SOCKET;
  1385. __try {
  1386. destinationCount = pNameResolver (&destinationAddresses, FALSE, NULL);
  1387. if (!destinationCount) {
  1388. __leave;
  1389. }
  1390. addressArray = (PCONNECTADDRESS) destinationAddresses.Buf;
  1391. //
  1392. // Determine which address to use. Rules are:
  1393. //
  1394. // 1. Must have only one destination to choose from
  1395. // 2. Pick TCP/IP, then IPX, then NetBIOS
  1396. //
  1397. if (destinationCount > 1) {
  1398. firstName = addressArray[0].DestinationName;
  1399. for (i = 1 ; i < destinationCount ; i++) {
  1400. if (!StringIMatch (firstName, addressArray[i].DestinationName)) {
  1401. break;
  1402. }
  1403. }
  1404. if (i < destinationCount) {
  1405. DEBUGMSG ((DBG_ERROR, "Multiple destinations found on the subnet; can't continue"));
  1406. __leave;
  1407. }
  1408. }
  1409. for (i = 0 ; i < destinationCount ; i++) {
  1410. if (addressArray[i].Family == AF_INET) {
  1411. break;
  1412. }
  1413. }
  1414. if (i == destinationCount) {
  1415. for (i = 0 ; i < destinationCount ; i++) {
  1416. if (addressArray[i].Family == AF_IPX) {
  1417. break;
  1418. }
  1419. }
  1420. if (i == destinationCount) {
  1421. for (i = 0 ; i < destinationCount ; i++) {
  1422. if (addressArray[i].Family == AF_NETBIOS) {
  1423. break;
  1424. }
  1425. }
  1426. if (i == destinationCount) {
  1427. DEBUGMSG ((DBG_WHOOPS, "Connection is from unsupported protocol"));
  1428. __leave;
  1429. }
  1430. }
  1431. }
  1432. //
  1433. // Now connect to destination (at index i)
  1434. //
  1435. DEBUGMSG ((
  1436. DBG_HOMENET,
  1437. "Attempting connection to %s (protocol %i)",
  1438. addressArray[i].DestinationName,
  1439. addressArray[i].Protocol
  1440. ));
  1441. if (!pConnectToDestination (&addressArray[i], &connection)) {
  1442. __leave;
  1443. }
  1444. printf ("Connected!\n");
  1445. ZeroMemory (&metrics, sizeof (metrics));
  1446. metrics.FileCount = 1;
  1447. metrics.TotalSize = 0;
  1448. if (!pSendMetrics (connection.Socket, connection.Datagram, &metrics)) {
  1449. __leave;
  1450. }
  1451. if (!pSendFile (
  1452. connection.Socket,
  1453. connection.Datagram ? &connection.DatagramPool : NULL,
  1454. localFileName,
  1455. destFileName
  1456. )) {
  1457. __leave;
  1458. }
  1459. }
  1460. __finally {
  1461. GbFree (&destinationAddresses);
  1462. if (connection.Socket != INVALID_SOCKET) {
  1463. closesocket (connection.Socket);
  1464. }
  1465. }
  1466. }