Windows NT 4.0 source code leak
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.

1419 lines
35 KiB

4 years ago
  1. /* --------------------------------------------------------------------
  2. File : cmltclnt.c
  3. Title : Common client loadable transport module
  4. Description :
  5. History :
  6. 02-08-95 Mazhar Mohammed, forked from clnttcp.c
  7. -------------------------------------------------------------------- */
  8. #include "sysinc.h"
  9. #define FD_SETSIZE 1
  10. #ifdef NTENV
  11. #include <winsock2.h>
  12. #else
  13. #include <winsock.h>
  14. #endif
  15. #ifdef NTENV
  16. #include <tdi.h>
  17. #include <afd.h>
  18. #endif
  19. #ifdef SPX
  20. #include <wsipx.h>
  21. #include <wsnwlink.h>
  22. #include <basetyps.h>
  23. #include "nsphack.h"
  24. #endif
  25. #include <stdlib.h>
  26. #include "rpc.h"
  27. #include "rpcdcep.h"
  28. #include "rpctran.h"
  29. #include "rpcerrp.h"
  30. #include "common.h"
  31. #ifdef SPX
  32. #include "gethost.h"
  33. #endif
  34. #define PFC_FIRST_FRAG 0x01
  35. typedef struct
  36. {
  37. unsigned char rpc_vers;
  38. unsigned char rpc_vers_minor;
  39. unsigned char PTYPE;
  40. unsigned char pfc_flags;
  41. unsigned char drep[4];
  42. unsigned short frag_length;
  43. unsigned short auth_length;
  44. unsigned long call_id;
  45. } message_header;
  46. typedef struct
  47. {
  48. SOCKET Socket;
  49. long Timeout;
  50. #ifndef SPX
  51. unsigned long TickCount;
  52. char PAPI * Buffer;
  53. message_header PeekedMessage;
  54. unsigned short State;
  55. unsigned short PeekInfo;
  56. unsigned short ShutdownRecvd;
  57. fd_set SockSet;
  58. BOOL LocalRpc;
  59. char PAPI *CoalescedBuffer ;
  60. unsigned int CBufferLength ;
  61. unsigned int CBufferDataLength ;
  62. #endif
  63. } CONNECTION, *PCONNECTION;
  64. #define ENDIAN_MASK 16
  65. #define NO_MORE_SENDS_OR_RECVS 2
  66. #define ENDPOINT_LEN 5
  67. #ifdef SPX
  68. #define MAXIMUM_SEND 5832
  69. #define HOSTNAME_LEN 255
  70. #define ADDRESS_FAMILY AF_NS
  71. #define PROTOCOL NSPROTO_SPXII
  72. #define DLL_NAME "rpcltccm.dll"
  73. #define ENDPOINT_MAPPER_EP "34280"
  74. #define TransInfo SPX_TransInfo
  75. #else
  76. // The maximum send is the size of four user data frames on an ethernet.
  77. #define MAXIMUM_SEND 5840
  78. #define HOSTNAME_LEN 255
  79. #define ADDRESS_FAMILY AF_INET
  80. #define PROTOCOL 0
  81. #define DLL_NAME "rpcltccm.dll"
  82. #define ENDPOINT_MAPPER_EP "135"
  83. #define TransInfo TCP_TransInfo
  84. #endif
  85. #define ByteSwapLong(Value) \
  86. Value = ( (((unsigned long) (Value) & 0xFF000000) >> 24) \
  87. | (((unsigned long) (Value) & 0x00FF0000) >> 8) \
  88. | (((unsigned long) (Value) & 0x0000FF00) << 8) \
  89. | (((unsigned long) (Value) & 0x000000FF) << 24))
  90. #define ByteSwapShort(Value) \
  91. Value = ( (((unsigned short) (Value) & 0x00FF) << 8) \
  92. | (((unsigned short) (Value) & 0xFF00) >> 8))
  93. /*
  94. Shutdown Detection Garbage
  95. */
  96. #define MAXTICKSBEFOREPEEK 10000
  97. #define NOPENDINGRPC 0
  98. #define RPCINITIATED 1
  99. #define NOPEEKINFO 0
  100. #define PEEKEDHEADER 1
  101. #define PEEKEDBUFFER 2
  102. #define rpc_shutdown 17
  103. #define rpc_fault 3
  104. /*
  105. Following Macros and structs are needed for Tower Stuff
  106. */
  107. #pragma pack(1)
  108. #ifdef SPX
  109. #define TRANSPORTID 0x0c
  110. #define TRANSPORTHOSTID 0x0d
  111. #define TOWERFLOORS 5
  112. /*Endpoint = 2 bytes, HostId = 10 bytes*/
  113. #define TOWEREPSIZE 10
  114. #define TOWERSIZE (TOWEREPSIZE+2)
  115. #define PROTSEQ "ncacn_spx"
  116. #else
  117. #define TRANSPORTID 0x07
  118. #define TRANSPORTHOSTID 0x09
  119. #define TOWERFLOORS 5
  120. /*Endpoint = 2 bytes, HostId = 4 bytes*/
  121. #define TOWEREPSIZE 4
  122. #define TOWERSIZE (TOWEREPSIZE+2)
  123. #define PROTSEQ "ncacn_ip_tcp"
  124. #endif
  125. typedef struct _FLOOR_234 {
  126. unsigned short ProtocolIdByteCount;
  127. unsigned char FloorId;
  128. unsigned short AddressByteCount;
  129. unsigned char Data[2];
  130. } FLOOR_234;
  131. typedef FLOOR_234 PAPI UNALIGNED * PFLOOR_234;
  132. #define NEXTFLOOR(t,x) (t)((unsigned char PAPI *)x +((t)x)->ProtocolIdByteCount\
  133. + ((t)x)->AddressByteCount\
  134. + sizeof(((t)x)->ProtocolIdByteCount)\
  135. + sizeof(((t)x)->AddressByteCount))
  136. /*
  137. End of Tower Stuff!
  138. */
  139. #pragma pack()
  140. STATIC
  141. RPC_STATUS RPC_ENTRY
  142. ClientOpen (
  143. IN PCONNECTION pConn,
  144. IN RPC_CHAR * NetworkAddress,
  145. IN RPC_CHAR * Endpoint,
  146. IN RPC_CHAR * NetworkOptions,
  147. IN RPC_CHAR * TransportAddress,
  148. IN RPC_CHAR * RpcProtocolSequence,
  149. IN unsigned int Timeout
  150. )
  151. // Open a client connection
  152. {
  153. #ifdef SPX
  154. SOCKADDR_IPX server;
  155. SOCKADDR_IPX client;
  156. #else
  157. struct sockaddr_in server;
  158. struct sockaddr_in client;
  159. int SetNagglingOff = TRUE;
  160. #endif
  161. unsigned char host[HOSTNAME_LEN+1];
  162. #ifndef SPX
  163. unsigned char localhostname[HOSTNAME_LEN+1];
  164. unsigned long RecvWindow;
  165. static int KeepAliveOn = 1;
  166. #endif
  167. unsigned char port[10];
  168. int status;
  169. int PendingAlert;
  170. int PortIn ;
  171. size_t length;
  172. unsigned Time;
  173. UNUSED(NetworkAddress);
  174. UNUSED(NetworkOptions);
  175. UNUSED(TransportAddress);
  176. UNUSED(RpcProtocolSequence);
  177. if (RpcpStringLength(NetworkAddress) > HOSTNAME_LEN)
  178. {
  179. return (RPC_S_INVALID_NET_ADDR) ;
  180. }
  181. unicode_to_ascii (NetworkAddress, host);
  182. unicode_to_ascii (Endpoint, port);
  183. #ifndef SPX
  184. if ( host[0] == '\0')
  185. {
  186. pConn->LocalRpc = TRUE;
  187. }
  188. else
  189. {
  190. gethostname (localhostname, HOSTNAME_LEN);
  191. if (_stricmp(localhostname , host) == 0)
  192. pConn->LocalRpc = TRUE;
  193. else
  194. pConn->LocalRpc = FALSE;
  195. }
  196. #endif
  197. // Verify the NetworkAddress and Endpoint.
  198. length = strlen(port);
  199. if (length <= 0 || length > ENDPOINT_LEN ||
  200. length != strspn( port, "0123456789" ))
  201. return( RPC_S_INVALID_ENDPOINT_FORMAT );
  202. PortIn = atoi (port);
  203. if (PortIn > 65535)
  204. return (RPC_S_INVALID_ENDPOINT_FORMAT);
  205. memset((char *)&server, 0, sizeof (server));
  206. memset((char *)&client, 0, sizeof (client));
  207. #ifdef NTENV
  208. PendingAlert = NtTestAlert() == STATUS_ALERTED;
  209. #else
  210. PendingAlert = 0;
  211. #endif // NTENV
  212. retry:
  213. //
  214. // Get a socket
  215. //
  216. if ((pConn->Socket = socket(ADDRESS_FAMILY, SOCK_STREAM, PROTOCOL)) ==
  217. INVALID_SOCKET)
  218. {
  219. return (RPC_S_OUT_OF_RESOURCES);
  220. }
  221. pConn->Timeout = RPC_C_CANCEL_INFINITE_TIMEOUT;
  222. #ifndef SPX
  223. pConn->State = NOPENDINGRPC;
  224. pConn->PeekInfo = NOPEEKINFO;
  225. pConn->TickCount = 0;
  226. pConn->ShutdownRecvd = 0;
  227. pConn->CoalescedBuffer = 0;
  228. pConn->CBufferLength = 0;
  229. pConn->CBufferDataLength = 0;
  230. setsockopt( pConn->Socket, IPPROTO_TCP, TCP_NODELAY,
  231. (char FAR *)&SetNagglingOff, sizeof (int) );
  232. setsockopt( pConn->Socket, IPPROTO_TCP, SO_KEEPALIVE,
  233. (char *)&KeepAliveOn, sizeof(KeepAliveOn) );
  234. FD_ZERO(&(pConn->SockSet));
  235. FD_SET(pConn->Socket, &(pConn->SockSet));
  236. #ifdef NTENV
  237. I_RpcConnectionInqSockBuffSize2(&RecvWindow);
  238. if (RecvWindow != 0)
  239. {
  240. //
  241. // Runtime should not accept a recvwindow of >64K
  242. //
  243. ASSERT(RecvWindow <= 0xFFFF);
  244. setsockopt(pConn->Socket, SOL_SOCKET,SO_RCVBUF,
  245. (char *)&RecvWindow, sizeof(RecvWindow));
  246. }
  247. //#else
  248. // setsockopt( pConn->Socket,
  249. // IPPROTO_TCP,
  250. // TCP_NODELAY,
  251. // (char FAR *)&SetNagglingOff,
  252. // sizeof (int) );
  253. #endif // NTENV
  254. #endif // SPX
  255. //
  256. // B O G U S H A C K !!
  257. //
  258. //
  259. // Winsock doesn't support connecting with an unbound socket! This
  260. // is a joke, right? Unfortunately, it's not a joke.
  261. //
  262. #ifdef SPX
  263. client.sa_family = ADDRESS_FAMILY;
  264. #else
  265. client.sin_family = ADDRESS_FAMILY;
  266. #endif
  267. if (bind (pConn->Socket, (struct sockaddr *) &client, sizeof (client)))
  268. {
  269. closesocket(pConn->Socket);
  270. pConn->Socket = 0;
  271. return(RPC_S_OUT_OF_MEMORY);
  272. }
  273. //
  274. // Convert the network address.
  275. //
  276. #ifdef SPX
  277. status = spx_get_host_by_name( pConn->Socket, &server, host, PROTOCOL, Timeout, &Time);
  278. #else
  279. status = tcp_get_host_by_name( pConn->Socket, &server, host);
  280. #endif
  281. if (status != 0)
  282. {
  283. closesocket(pConn->Socket);
  284. pConn->Socket = 0;
  285. return status;
  286. }
  287. #ifdef SPX
  288. server.sa_family = ADDRESS_FAMILY;
  289. server.sa_socket = htons((unsigned short) PortIn);
  290. #else
  291. server.sin_family = ADDRESS_FAMILY;
  292. server.sin_port = htons((unsigned short) PortIn);
  293. #endif
  294. //
  295. // Try to connect...
  296. //
  297. if (connect(pConn->Socket, (struct sockaddr *) &server,
  298. sizeof (server)) < 0)
  299. {
  300. #if DBG
  301. PrintToDebugger( "%s: ClientOpen failed calling connect ... %d\n",
  302. DLL_NAME, WSAGetLastError() );
  303. #endif
  304. closesocket(pConn->Socket);
  305. pConn->Socket = 0;
  306. #ifdef SPX
  307. //
  308. // If we didn't contact the server, the cache might throw away the entry as stale.
  309. //
  310. if (TRUE == CachedServerNotContacted(host))
  311. {
  312. goto retry;
  313. }
  314. #endif
  315. return (RPC_S_SERVER_UNAVAILABLE);
  316. }
  317. #ifdef SPX
  318. CachedServerContacted(host);
  319. #endif
  320. #ifdef NTENV
  321. if (PendingAlert) {
  322. NtAlertThread(NtCurrentThread());
  323. }
  324. #endif
  325. return (RPC_S_OK);
  326. }
  327. STATIC
  328. RPC_STATUS RPC_ENTRY
  329. ClientClose (
  330. IN PCONNECTION pConn
  331. )
  332. // Close a client connection
  333. {
  334. #ifndef SPX
  335. if (pConn->CoalescedBuffer)
  336. {
  337. I_RpcFree(pConn->CoalescedBuffer) ;
  338. }
  339. #endif
  340. closesocket(pConn->Socket);
  341. pConn->Socket = 0;
  342. return (RPC_S_OK);
  343. }
  344. STATIC
  345. RPC_STATUS RPC_ENTRY
  346. ClientSend (
  347. IN PCONNECTION pConn,
  348. IN void PAPI * Buffer,
  349. IN unsigned int BufferLength
  350. )
  351. // Write a message to a connection. This operation is retried in case
  352. // the server is "busy".
  353. {
  354. int bytes;
  355. #ifndef SPX
  356. int i = 4;
  357. int total_bytes = 0;
  358. int Status;
  359. struct timeval Timeout;
  360. unsigned long PrevTicks;
  361. //
  362. // Send a message on the socket
  363. //
  364. //if this is the first frag for this rpc
  365. //hopefully indicated by the STATE
  366. //we peek for async shutdown pdu from OSF 1.1 Servers!
  367. pConn->ShutdownRecvd = 0;
  368. if ( ( pConn->LocalRpc != TRUE) && (pConn->State == NOPENDINGRPC) )
  369. {
  370. ASSERT(pConn->PeekInfo == NOPEEKINFO);
  371. ASSERT( (((message_header PAPI *)Buffer)->PTYPE != 0x0)
  372. ||(((message_header PAPI *)Buffer)->pfc_flags & PFC_FIRST_FRAG) );
  373. PrevTicks = pConn->TickCount;
  374. pConn->TickCount = GetTickCount();
  375. if ( (pConn->TickCount - PrevTicks) > MAXTICKSBEFOREPEEK )
  376. {
  377. //Peek To See If Any Async PDUs showed up..
  378. // Do 4 peeks, 3 for shutdowns and 1 for failures
  379. // if there is a real shutdown
  380. Timeout.tv_sec = 0;
  381. Timeout.tv_usec= 0;
  382. while (i)
  383. {
  384. total_bytes = 0;
  385. Status = select(
  386. 0,
  387. &(pConn->SockSet),
  388. 0,
  389. 0,
  390. &Timeout
  391. );
  392. if (Status != 0)
  393. {
  394. //recv and check to see if it is a fault or
  395. //Shutdown
  396. do
  397. {
  398. bytes = recv (
  399. pConn->Socket,
  400. ((char *)&(pConn->PeekedMessage)) + total_bytes,
  401. sizeof(message_header) - total_bytes,
  402. 0
  403. );
  404. if (bytes <= 0)
  405. {
  406. ClientClose(pConn);
  407. return(RPC_P_SEND_FAILED);
  408. }
  409. total_bytes += bytes;
  410. }
  411. while(total_bytes < sizeof(message_header));
  412. //PTYPE is a byte and hence we defer byteswaps till later
  413. if ( (pConn->PeekedMessage.PTYPE == rpc_shutdown)
  414. ||(pConn->PeekedMessage.PTYPE == rpc_fault) )
  415. {
  416. pConn->ShutdownRecvd = 1 ;
  417. FD_SET(pConn->Socket, &(pConn->SockSet)) ;
  418. i--;
  419. }
  420. else
  421. {
  422. pConn->PeekInfo = PEEKEDHEADER;
  423. #if DBG
  424. PrintToDebugger("RPCLTCCM: Peeked a header\n") ;
  425. #endif
  426. }
  427. } //if select says there is some data available
  428. else
  429. {
  430. FD_SET(pConn->Socket, &(pConn->SockSet));
  431. break;
  432. }
  433. }
  434. }
  435. pConn->State = RPCINITIATED;
  436. }
  437. #endif
  438. bytes = send(pConn->Socket, (char *) Buffer, (int) BufferLength, 0);
  439. if (bytes != (int) BufferLength)
  440. {
  441. ClientClose ( pConn );
  442. return(RPC_P_SEND_FAILED);
  443. }
  444. return(RPC_S_OK);
  445. }
  446. #ifdef NTENV
  447. STATIC RPC_STATUS
  448. RecvAlertable(
  449. IN PCONNECTION pConn,
  450. IN LPVOID Buf,
  451. IN unsigned int BufLen,
  452. OUT LPDWORD retlen,
  453. IN DWORD dwTimeout
  454. )
  455. {
  456. DWORD status;
  457. LARGE_INTEGER Timeout;
  458. LARGE_INTEGER CancelTimeout ;
  459. PLARGE_INTEGER pWaitTime = NULL;
  460. IO_STATUS_BLOCK IoStatusBlock;
  461. IO_STATUS_BLOCK CancelIoStatusBlock;
  462. AFD_RECV_INFO recvInfo;
  463. WSABUF wsaBuf;
  464. RPC_STATUS RpcStatus;
  465. int IsAlerted = 0;
  466. wsaBuf.buf = Buf;
  467. wsaBuf.len = (u_long)BufLen;
  468. recvInfo.BufferArray = &wsaBuf;
  469. recvInfo.BufferCount = 1;
  470. recvInfo.AfdFlags = 0;
  471. recvInfo.TdiFlags = TDI_RECEIVE_NORMAL;
  472. status = NtDeviceIoControlFile(
  473. (HANDLE)pConn->Socket,
  474. NULL,
  475. NULL,
  476. NULL,
  477. &IoStatusBlock,
  478. IOCTL_AFD_RECEIVE,
  479. &recvInfo,
  480. sizeof(recvInfo),
  481. NULL,
  482. 0);
  483. if (status == STATUS_PENDING)
  484. {
  485. if (dwTimeout)
  486. {
  487. Timeout.QuadPart = Int32x32To64(-10*1000*1000L, dwTimeout);
  488. pWaitTime = &Timeout;
  489. }
  490. do {
  491. status = NtWaitForSingleObject(
  492. (HANDLE)pConn->Socket,
  493. TRUE,
  494. pWaitTime);
  495. ASSERT( ((status == STATUS_TIMEOUT) && (pWaitTime != 0))
  496. ||(status == STATUS_ALERTED)
  497. ||(status == STATUS_USER_APC)
  498. ||(status == 0 ));
  499. if (status == STATUS_TIMEOUT)
  500. {
  501. if (IsAlerted == 0)
  502. {
  503. if (I_RpcTransPingServer(pConn) == RPC_S_OK)
  504. {
  505. status = STATUS_ALERTED;
  506. continue;
  507. }
  508. else
  509. {
  510. NtCancelIoFile((HANDLE)pConn->Socket, &CancelIoStatusBlock);
  511. ClientClose(pConn);
  512. return (RPC_P_RECEIVE_FAILED);
  513. }
  514. }
  515. else
  516. {
  517. NtCancelIoFile((HANDLE)pConn->Socket, &CancelIoStatusBlock);
  518. return (RPC_S_CALL_CANCELLED);
  519. }
  520. }
  521. if (status == STATUS_ALERTED)
  522. {
  523. RpcStatus = I_RpcIOAlerted(pConn);
  524. IsAlerted = 1 ;
  525. if (RpcStatus == RPC_S_CALL_CANCELLED)
  526. {
  527. NtCancelIoFile((HANDLE)pConn->Socket, &CancelIoStatusBlock);
  528. return(RPC_S_CALL_CANCELLED);
  529. }
  530. else
  531. {
  532. if (pConn->Timeout != RPC_C_CANCEL_INFINITE_TIMEOUT)
  533. {
  534. CancelTimeout.QuadPart =
  535. Int32x32To64(-10*1000*1000L, pConn->Timeout);
  536. pWaitTime = &CancelTimeout;
  537. }
  538. continue;
  539. }
  540. }
  541. } while ( (status == STATUS_USER_APC) || (status == STATUS_ALERTED) );
  542. status = IoStatusBlock.Status;
  543. }
  544. if ( (status != STATUS_SUCCESS)
  545. || (IoStatusBlock.Status != STATUS_SUCCESS)
  546. #ifdef SPX
  547. || (IoStatusBlock.Information == 0))
  548. #else
  549. || ((IoStatusBlock.Information == 0) &&
  550. (pConn->ShutdownRecvd == 0)))
  551. #endif
  552. {
  553. ClientClose(pConn);
  554. return (RPC_P_RECEIVE_FAILED);
  555. }
  556. #ifndef SPX
  557. if (IoStatusBlock.Information == 0)
  558. {
  559. if (pConn->ShutdownRecvd == 1)
  560. {
  561. ClientClose(pConn);
  562. return (RPC_P_CONNECTION_SHUTDOWN) ;
  563. }
  564. }
  565. #endif
  566. *retlen = IoStatusBlock.Information;
  567. if(*retlen > BufLen)
  568. {
  569. ClientClose(pConn);
  570. return RPC_P_RECEIVE_FAILED;
  571. }
  572. return (RPC_S_OK);
  573. }
  574. #endif // defined (NTENV)
  575. #ifndef SPX
  576. RPC_TRANS_STATUS
  577. SaveBuffer (
  578. IN PCONNECTION pConn,
  579. IN void *Buffer,
  580. IN unsigned int BufferLength
  581. )
  582. {
  583. void PAPI *Temp ;
  584. #if DBG
  585. PrintToDebugger("RPCLTCCM: Saving away %d bytes\n", BufferLength) ;
  586. #endif
  587. if (pConn->CoalescedBuffer == 0 ||
  588. pConn->CBufferDataLength+BufferLength > pConn->CBufferLength)
  589. {
  590. Temp = I_RpcAllocate(pConn->CBufferDataLength+BufferLength) ;
  591. if (Temp == 0)
  592. {
  593. return (RPC_S_OUT_OF_MEMORY) ;
  594. }
  595. if (pConn->CoalescedBuffer)
  596. {
  597. RpcpMemoryCopy(Temp, pConn->CoalescedBuffer,
  598. pConn->CBufferDataLength);
  599. I_RpcFree(pConn->CoalescedBuffer) ;
  600. }
  601. pConn->CBufferLength = BufferLength + pConn->CBufferDataLength ;
  602. pConn->CoalescedBuffer = Temp ;
  603. }
  604. RpcpMemoryCopy((char *) pConn->CoalescedBuffer+pConn->CBufferDataLength
  605. ,Buffer, BufferLength) ;
  606. pConn->CBufferDataLength += BufferLength ;
  607. return (RPC_S_OK) ;
  608. }
  609. RPC_TRANS_STATUS RPC_ENTRY
  610. TCP_ClientRecv (
  611. IN PCONNECTION pConn,
  612. IN OUT void PAPI * PAPI * Buffer,
  613. IN OUT unsigned int PAPI * BufferLength
  614. )
  615. // Read a message from a connection.
  616. {
  617. RPC_STATUS RpcStatus;
  618. DWORD bytes;
  619. int total_bytes = 0;
  620. message_header *header = (message_header *) *Buffer;
  621. int native_length = 0;
  622. unsigned int maximum_receive;
  623. if (pConn->State == RPCINITIATED)
  624. {
  625. pConn->State = NOPENDINGRPC;
  626. /*
  627. pConn->TickCount = GetTickCount();
  628. */
  629. }
  630. ASSERT(*BufferLength > sizeof(message_header)) ;
  631. maximum_receive = I_RpcTransClientMaxFrag( pConn );
  632. if (*BufferLength < maximum_receive)
  633. maximum_receive = *BufferLength;
  634. if (pConn->CBufferDataLength > 0)
  635. {
  636. // if we have a peeked header, copy it into the coalesced buffer
  637. if (pConn->PeekInfo == PEEKEDHEADER)
  638. {
  639. if (SaveBuffer(pConn, &(pConn->PeekedMessage), sizeof(message_header))
  640. != RPC_S_OK)
  641. {
  642. return (RPC_S_OUT_OF_MEMORY) ;
  643. }
  644. pConn->PeekInfo = NOPEEKINFO ;
  645. }
  646. if (pConn->CBufferDataLength >= sizeof(message_header))
  647. {
  648. total_bytes = sizeof(message_header) ;
  649. RpcpMemoryCopy((char *) *Buffer, pConn->CoalescedBuffer,
  650. sizeof(message_header)) ;
  651. pConn->CBufferDataLength -= sizeof(message_header) ;
  652. if (pConn->CBufferDataLength)
  653. {
  654. RpcpMemoryMove(pConn->CoalescedBuffer,
  655. (char *) pConn->CoalescedBuffer+sizeof(message_header),
  656. pConn->CBufferDataLength) ;
  657. }
  658. }
  659. else
  660. {
  661. total_bytes = pConn->CBufferDataLength ;
  662. RpcpMemoryCopy((char *) *Buffer, pConn->CoalescedBuffer,
  663. total_bytes) ;
  664. pConn->CBufferDataLength = 0 ;
  665. }
  666. }
  667. else
  668. {
  669. if (pConn->PeekInfo == PEEKEDHEADER)
  670. {
  671. total_bytes = sizeof(message_header);
  672. RpcpMemoryCopy((char *)*Buffer, &(pConn->PeekedMessage),
  673. sizeof(message_header));
  674. #if DBG
  675. memset((char *)&(pConn->PeekedMessage), 0xDEADBEEFL, 4);
  676. #endif
  677. pConn->PeekInfo = NOPEEKINFO;
  678. }
  679. }
  680. //
  681. // Read protocol header to see how big
  682. // the record is...
  683. //
  684. while (total_bytes < sizeof(message_header))
  685. {
  686. #ifdef NTENV
  687. RpcStatus = RecvAlertable (pConn, (char *)*Buffer+total_bytes,
  688. (maximum_receive - total_bytes), &bytes, 0);
  689. if (RpcStatus != RPC_S_OK)
  690. {
  691. return (RpcStatus);
  692. }
  693. #else // !NTENV
  694. bytes = recv ( pConn->Socket,
  695. (char *)*Buffer + total_bytes,
  696. maximum_receive - total_bytes,
  697. 0);
  698. if (bytes <= 0)
  699. {
  700. ClientClose ( pConn );
  701. return (RPC_P_RECEIVE_FAILED);
  702. }
  703. #endif // NTENV
  704. total_bytes += bytes;
  705. }
  706. //
  707. // If this fragment header comes from a reverse-endian machine,
  708. // we will need to swap the bytes of the frag_length field...
  709. //
  710. if ( (header->drep[0] & ENDIAN_MASK) == 0)
  711. {
  712. // Big endian...swap
  713. //
  714. ((unsigned char *) &native_length)[0] =
  715. ((unsigned char *) &header->frag_length)[1];
  716. ((unsigned char *) &native_length)[1] =
  717. ((unsigned char *) &header->frag_length)[0];
  718. }
  719. else
  720. // Little endian, just like us...
  721. //
  722. native_length = header->frag_length;
  723. ASSERT( total_bytes <= native_length );
  724. //
  725. // Make sure buffer is big enough. If it isn't, then go back
  726. // to the runtime to reallocate it.
  727. //
  728. if (native_length > (unsigned short) *BufferLength)
  729. {
  730. RpcStatus = I_RpcTransClientReallocBuffer (pConn,
  731. Buffer,
  732. total_bytes,
  733. native_length);
  734. if (RpcStatus != RPC_S_OK)
  735. {
  736. return(RPC_S_OUT_OF_MEMORY);
  737. }
  738. }
  739. *BufferLength = native_length;
  740. if (pConn->CBufferDataLength >= native_length-sizeof(message_header))
  741. {
  742. ASSERT(total_bytes == sizeof(message_header)) ;
  743. RpcpMemoryCopy((char *) *Buffer+sizeof(message_header),
  744. pConn->CoalescedBuffer,
  745. native_length-sizeof(message_header)) ;
  746. pConn->CBufferDataLength -= (native_length-sizeof(message_header)) ;
  747. if (pConn->CBufferDataLength)
  748. {
  749. RpcpMemoryMove(pConn->CoalescedBuffer,
  750. (char *) pConn->CoalescedBuffer+
  751. (native_length-sizeof(message_header)),
  752. pConn->CBufferDataLength) ;
  753. }
  754. return (RPC_S_OK) ;
  755. }
  756. else
  757. {
  758. if (pConn->CBufferDataLength)
  759. {
  760. ASSERT(total_bytes == sizeof(message_header)) ;
  761. RpcpMemoryCopy((char *) *Buffer+sizeof(message_header),
  762. pConn->CoalescedBuffer,
  763. pConn->CBufferDataLength) ;
  764. total_bytes += pConn->CBufferDataLength ;
  765. pConn->CBufferDataLength = 0 ;
  766. }
  767. while (total_bytes < native_length)
  768. {
  769. #ifdef NTENV
  770. RpcStatus = RecvAlertable(pConn,
  771. (unsigned char *) *Buffer + total_bytes,
  772. (int) (native_length - total_bytes),
  773. &bytes, 0);
  774. if (RpcStatus != RPC_S_OK)
  775. {
  776. return (RpcStatus);
  777. }
  778. else
  779. {
  780. total_bytes += bytes;
  781. }
  782. #else // !NTENV
  783. bytes = recv ( pConn->Socket,
  784. (char *)*Buffer + total_bytes,
  785. (int) (native_length - total_bytes),
  786. 0);
  787. if (bytes <= 0)
  788. {
  789. ClientClose ( pConn );
  790. return (RPC_P_RECEIVE_FAILED);
  791. }
  792. else
  793. {
  794. total_bytes += bytes;
  795. }
  796. #endif // NTENV
  797. }
  798. // save away the extra part
  799. if (total_bytes > native_length)
  800. {
  801. if (SaveBuffer(pConn, (unsigned char *) *Buffer+native_length,
  802. total_bytes-native_length) != RPC_S_OK)
  803. {
  804. return (RPC_S_OUT_OF_MEMORY) ;
  805. }
  806. }
  807. return (RPC_S_OK);
  808. }
  809. }
  810. #else
  811. RPC_TRANS_STATUS RPC_ENTRY
  812. SPX_ClientRecv (
  813. IN PCONNECTION pConn,
  814. IN OUT void PAPI * PAPI * Buffer,
  815. IN OUT unsigned int PAPI * BufferLength
  816. )
  817. // Read a message from a connection.
  818. {
  819. RPC_STATUS RpcStatus;
  820. DWORD bytes;
  821. int total_bytes = 0;
  822. message_header *header = (message_header *) *Buffer;
  823. int native_length = 0;
  824. unsigned int maximum_receive;
  825. maximum_receive = I_RpcTransClientMaxFrag( pConn );
  826. if (*BufferLength < maximum_receive)
  827. maximum_receive = *BufferLength;
  828. //
  829. // Read protocol header to see how big
  830. // the record is...
  831. //
  832. while (total_bytes < sizeof(message_header))
  833. {
  834. #ifdef NTENV
  835. RpcStatus = RecvAlertable (pConn,
  836. (char *)*Buffer + total_bytes,
  837. maximum_receive - total_bytes,
  838. &bytes,
  839. 0);
  840. if (RpcStatus != RPC_S_OK)
  841. {
  842. return (RpcStatus);
  843. }
  844. #else // !defined (NTENV)
  845. bytes = recv ( pConn->Socket,
  846. (char *)*Buffer + total_bytes,
  847. maximum_receive - total_bytes,
  848. 0);
  849. if (bytes <= 0)
  850. {
  851. ClientClose ( pConn );
  852. return (RPC_P_RECEIVE_FAILED);
  853. }
  854. #endif // NTENV
  855. total_bytes += bytes;
  856. }
  857. //
  858. // If this fragment header comes from a reverse-endian machine,
  859. // we will need to swap the bytes of the frag_length field...
  860. //
  861. if ( (header->drep[0] & ENDIAN_MASK) == 0)
  862. {
  863. // Big endian...swap
  864. //
  865. ((unsigned char *) &native_length)[0] =
  866. ((unsigned char *) &header->frag_length)[1];
  867. ((unsigned char *) &native_length)[1] =
  868. ((unsigned char *) &header->frag_length)[0];
  869. }
  870. else
  871. // Little endian, just like us...
  872. //
  873. native_length = header->frag_length;
  874. ASSERT( total_bytes <= native_length );
  875. //
  876. // Make sure buffer is big enough. If it isn't, then go back
  877. // to the runtime to reallocate it.
  878. //
  879. if (native_length > (unsigned short) *BufferLength)
  880. {
  881. RpcStatus = I_RpcTransClientReallocBuffer (pConn,
  882. Buffer,
  883. total_bytes,
  884. native_length);
  885. if (RpcStatus != RPC_S_OK)
  886. {
  887. return(RPC_S_OUT_OF_MEMORY);
  888. }
  889. }
  890. *BufferLength = native_length;
  891. while (total_bytes < native_length)
  892. {
  893. #ifdef NTENV
  894. RpcStatus = RecvAlertable(pConn,
  895. (unsigned char *) *Buffer + total_bytes,
  896. (int) (native_length - total_bytes),
  897. &bytes, 0);
  898. if (RpcStatus != RPC_S_OK)
  899. {
  900. return (RpcStatus);
  901. }
  902. else
  903. {
  904. total_bytes += bytes;
  905. }
  906. #else // !DEFINED (NTENV)
  907. bytes = recv( pConn->Socket,
  908. (unsigned char *) *Buffer + total_bytes,
  909. (int) (native_length - total_bytes),
  910. 0);
  911. if (bytes <= 0)
  912. {
  913. ClientClose (pConn);
  914. return (RPC_P_RECEIVE_FAILED);
  915. }
  916. else
  917. {
  918. total_bytes += bytes;
  919. }
  920. #endif // NTENV
  921. }
  922. return(RPC_S_OK);
  923. }
  924. #endif
  925. STATIC
  926. RPC_TRANS_STATUS RPC_ENTRY
  927. ClientSetTimeout (
  928. IN PCONNECTION pConn,
  929. IN long Timeout
  930. )
  931. // Read a message from a connection with timeout.
  932. {
  933. ASSERT (Timeout != 0);
  934. pConn->Timeout = Timeout;
  935. return (RPC_S_OK);
  936. }
  937. #pragma pack(1)
  938. STATIC
  939. RPC_STATUS RPC_ENTRY
  940. ClientTowerConstruct(
  941. IN char PAPI * Endpoint,
  942. IN char PAPI * NetworkAddress,
  943. OUT short PAPI * Floors,
  944. OUT unsigned long PAPI * ByteCount,
  945. OUT unsigned char PAPI * PAPI * Tower,
  946. IN char PAPI * Protseq
  947. )
  948. {
  949. unsigned long TowerSize;
  950. unsigned short portnum;
  951. UNALIGNED PFLOOR_234 Floor;
  952. #ifdef SPX
  953. SOCKADDR_IPX netaddr;
  954. #else
  955. unsigned long hostval;
  956. #endif
  957. UNUSED(Protseq);
  958. /* Compute the memory size of the tower. */
  959. *Floors = TOWERFLOORS;
  960. TowerSize = TOWERSIZE;
  961. TowerSize += 2*sizeof(FLOOR_234) - 4;
  962. /* Allocate memory for the tower. */
  963. *ByteCount = TowerSize;
  964. if ((*Tower = (unsigned char PAPI*)I_RpcAllocate(TowerSize)) == NULL)
  965. {
  966. return (RPC_S_OUT_OF_MEMORY);
  967. }
  968. /* Put the endpoint address and transport protocol id in the first floor. */
  969. Floor = (PFLOOR_234) *Tower;
  970. Floor->ProtocolIdByteCount = 1;
  971. Floor->FloorId = (unsigned char)(TRANSPORTID & 0xFF);
  972. Floor->AddressByteCount = 2;
  973. if (Endpoint == NULL || *Endpoint == '\0')
  974. {
  975. Endpoint = ENDPOINT_MAPPER_EP;
  976. }
  977. portnum = (unsigned short) htons ( (unsigned short) atoi (Endpoint));
  978. memcpy((char PAPI *)&Floor->Data[0], &portnum, sizeof(portnum));
  979. /* Put the network address and the transport host protocol id in the
  980. second floor. */
  981. Floor = NEXTFLOOR(PFLOOR_234, Floor);
  982. Floor->ProtocolIdByteCount = 1;
  983. Floor->FloorId = (unsigned char)(TRANSPORTHOSTID & 0xFF);
  984. Floor->AddressByteCount = TOWEREPSIZE;
  985. Floor->Data[0] = '\0';
  986. Floor->Data[1] = '\0';
  987. if ((NetworkAddress) && (*NetworkAddress))
  988. {
  989. #ifdef SPX
  990. memset(&Floor->Data[0], 0, sizeof(netaddr.sa_netnum));
  991. memset(&Floor->Data[4], 0, sizeof(netaddr.sa_nodenum));
  992. #else
  993. hostval = inet_addr((char *) NetworkAddress);
  994. memcpy((char PAPI *)&Floor->Data[0], &hostval, sizeof(hostval));
  995. #endif
  996. }
  997. return(RPC_S_OK);
  998. }
  999. STATIC
  1000. RPC_STATUS RPC_ENTRY
  1001. ClientTowerExplode(
  1002. IN unsigned char PAPI * Tower,
  1003. OUT char PAPI * PAPI * Protseq,
  1004. OUT char PAPI * PAPI * Endpoint,
  1005. OUT char PAPI * PAPI * NetworkAddress
  1006. )
  1007. {
  1008. UNALIGNED PFLOOR_234 Floor = (PFLOOR_234) Tower;
  1009. RPC_STATUS Status = RPC_S_OK;
  1010. unsigned short portnum;
  1011. UNALIGNED unsigned short *Port;
  1012. if (Protseq != NULL)
  1013. {
  1014. *Protseq = I_RpcAllocate(strlen(PROTSEQ) + 1);
  1015. if (*Protseq == NULL)
  1016. Status = RPC_S_OUT_OF_MEMORY;
  1017. else
  1018. memcpy(*Protseq, PROTSEQ, strlen(PROTSEQ) + 1);
  1019. }
  1020. if ((Endpoint == NULL) || (Status != RPC_S_OK))
  1021. {
  1022. return (Status);
  1023. }
  1024. *Endpoint = I_RpcAllocate(ENDPOINT_LEN+1); //Ports are all <64K [5 decimal dig +1]
  1025. if (*Endpoint == NULL)
  1026. {
  1027. Status = RPC_S_OUT_OF_MEMORY;
  1028. if (Protseq != NULL)
  1029. {
  1030. I_RpcFree(*Protseq);
  1031. }
  1032. }
  1033. else
  1034. {
  1035. #if defined(MIPS) || defined(_ALPHA_)
  1036. memcpy(&portnum, (char PAPI *)&Floor->Data[0], sizeof(portnum));
  1037. #else
  1038. Port = (unsigned short *)&Floor->Data[0];
  1039. portnum = *Port;
  1040. #endif
  1041. RpcItoa(ByteSwapShort(portnum), *Endpoint, 10);
  1042. }
  1043. return(Status);
  1044. }
  1045. #ifdef NTENV
  1046. STATIC
  1047. RPC_TRANS_STATUS RPC_ENTRY
  1048. ClientRecvWithTimeout (
  1049. IN PCONNECTION pConn,
  1050. IN OUT void PAPI * PAPI * Buffer,
  1051. IN OUT unsigned int PAPI * BufferLength,
  1052. IN DWORD dwTimeout
  1053. )
  1054. // Read a message from a connection.
  1055. {
  1056. RPC_STATUS RpcStatus;
  1057. DWORD bytes;
  1058. int total_bytes = 0;
  1059. message_header *header = (message_header *) *Buffer;
  1060. int native_length = 0;
  1061. unsigned int maximum_receive;
  1062. #ifndef SPX
  1063. if (pConn->State == RPCINITIATED)
  1064. {
  1065. pConn->State = NOPENDINGRPC;
  1066. /*
  1067. pConn->TickCount = GetTickCount();
  1068. */
  1069. }
  1070. #endif
  1071. maximum_receive = I_RpcTransClientMaxFrag( pConn );
  1072. if (*BufferLength < maximum_receive)
  1073. maximum_receive = *BufferLength;
  1074. #ifndef SPX
  1075. if (pConn->PeekInfo == PEEKEDHEADER)
  1076. {
  1077. total_bytes = sizeof(message_header);
  1078. memcpy((char *)*Buffer, &(pConn->PeekedMessage), sizeof(message_header));
  1079. #if DBG
  1080. memset((char *)&(pConn->PeekedMessage), 0xDEADBEEFL, 4);
  1081. #endif
  1082. pConn->PeekInfo = NOPEEKINFO;
  1083. }
  1084. #endif
  1085. //
  1086. // Read protocol header to see how big
  1087. // the record is...
  1088. //
  1089. while (total_bytes < sizeof(message_header))
  1090. {
  1091. RpcStatus = RecvAlertable (pConn,
  1092. (char *)*Buffer+total_bytes,
  1093. (maximum_receive - total_bytes),
  1094. &bytes,
  1095. dwTimeout);
  1096. if (RpcStatus != RPC_S_OK)
  1097. {
  1098. return (RpcStatus);
  1099. }
  1100. total_bytes += bytes;
  1101. }
  1102. //
  1103. // If this fragment header comes from a reverse-endian machine,
  1104. // we will need to swap the bytes of the frag_length field...
  1105. //
  1106. if ( (header->drep[0] & ENDIAN_MASK) == 0)
  1107. {
  1108. // Big endian...swap
  1109. //
  1110. ((unsigned char *) &native_length)[0] =
  1111. ((unsigned char *) &header->frag_length)[1];
  1112. ((unsigned char *) &native_length)[1] =
  1113. ((unsigned char *) &header->frag_length)[0];
  1114. }
  1115. else
  1116. // Little endian, just like us...
  1117. //
  1118. native_length = header->frag_length;
  1119. ASSERT( total_bytes <= native_length );
  1120. //
  1121. // Make sure buffer is big enough. If it isn't, then go back
  1122. // to the runtime to reallocate it.
  1123. //
  1124. if (native_length > (unsigned short) *BufferLength)
  1125. {
  1126. RpcStatus = I_RpcTransClientReallocBuffer (pConn,
  1127. Buffer,
  1128. total_bytes,
  1129. native_length);
  1130. if (RpcStatus != RPC_S_OK)
  1131. {
  1132. return(RPC_S_OUT_OF_MEMORY);
  1133. }
  1134. }
  1135. *BufferLength = native_length;
  1136. while (total_bytes < native_length)
  1137. {
  1138. RpcStatus = RecvAlertable(pConn,
  1139. (unsigned char *) *Buffer + total_bytes,
  1140. (int) (native_length - total_bytes, dwTimeout),
  1141. &bytes, dwTimeout);
  1142. if (RpcStatus != RPC_S_OK)
  1143. {
  1144. return (RpcStatus);
  1145. }
  1146. else
  1147. {
  1148. total_bytes += bytes;
  1149. }
  1150. }
  1151. return(RPC_S_OK);
  1152. }
  1153. #endif // NTENV
  1154. #pragma pack()
  1155. RPC_CLIENT_TRANSPORT_INFO TransInfo =
  1156. {
  1157. RPC_TRANSPORT_INTERFACE_VERSION,
  1158. TRANSPORTID,
  1159. ClientTowerConstruct,
  1160. ClientTowerExplode,
  1161. MAXIMUM_SEND,
  1162. sizeof (CONNECTION),
  1163. ClientOpen,
  1164. ClientClose,
  1165. ClientSend,
  1166. #ifdef SPX
  1167. SPX_ClientRecv,
  1168. #else
  1169. TCP_ClientRecv,
  1170. #endif
  1171. NULL,
  1172. ClientSetTimeout,
  1173. #ifdef NTENV
  1174. ClientRecvWithTimeout,
  1175. #else
  1176. NULL,
  1177. #endif
  1178. NULL
  1179. };