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.

599 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: sock.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "precomp.h"
  11. #include <malloc.h>
  12. #include <mswsock.h>
  13. #include <irmonftp.h>
  14. #define dwENUM_REST 100 // time to rest between successive
  15. // IRLMP_ENUMDEVICES queries
  16. #define dwCONN_REST 100 // time to rest between successive
  17. // connect() calls
  18. #define MAX_DEVICE_COUNT 20
  19. #define nMAX_TARGETS 8
  20. #define nMAX_ENUM_RETRIES 100
  21. #define nMAX_CONN_RETRIES 10
  22. #define nSOCKET_MAXCONN 8
  23. #define dwWRITEABLE_TIMEOUT 10000
  24. #define SOCKET_RECEIVE_TIMEOUT (1000 * 60 * 10)
  25. #define SINGLE_INST_MUTEX L"IRMutex_1A8452B5_A526_443C_8172_D29657B89F57"
  26. FILE_TRANSFER*
  27. InitializeSocket(
  28. char ServiceName[]
  29. )
  30. {
  31. int nSize;
  32. INT nRet;
  33. WORD wWinsockVersion;
  34. WSADATA wsadata;
  35. SOCKET listenSocket=INVALID_SOCKET;
  36. FILE_TRANSFER* Transfer;
  37. HANDLE FileMapping;
  38. PVOID FileView=NULL;
  39. LPWSAPROTOCOL_INFO ProtocolInfo;
  40. wWinsockVersion = MAKEWORD( 2, 0 );
  41. nRet = WSAStartup( wWinsockVersion, &wsadata );
  42. if ( 0 != nRet ) {
  43. goto lErr;
  44. }
  45. FileMapping=OpenFileMapping(
  46. FILE_MAP_READ,
  47. FALSE,
  48. TEXT("Global\\Irmon-shared-memory")
  49. );
  50. if (FileMapping != NULL) {
  51. FileView=MapViewOfFile(
  52. FileMapping,
  53. FILE_MAP_READ,
  54. 0,
  55. 0,
  56. 0
  57. );
  58. CloseHandle(FileMapping);
  59. } else {
  60. DbgPrint("irftp: could not open shared mem %d\n",GetLastError());
  61. }
  62. ProtocolInfo=(LPWSAPROTOCOL_INFO)FileView;
  63. if (ProtocolInfo != NULL) {
  64. if (lstrcmpA(ServiceName,SERVICE_NAME_2) == 0) {
  65. ProtocolInfo++;
  66. }
  67. listenSocket=WSASocket(FROM_PROTOCOL_INFO,FROM_PROTOCOL_INFO ,FROM_PROTOCOL_INFO ,ProtocolInfo, NULL, 0);
  68. UnmapViewOfFile(FileView);
  69. }
  70. if (listenSocket == INVALID_SOCKET) {
  71. //
  72. // establish listen socket
  73. //
  74. SOCKADDR_IRDA saListen;
  75. DbgPrint("irftp: WSASocketFailed %d\n",WSAGetLastError());
  76. listenSocket = socket( AF_IRDA, SOCK_STREAM, 0 );
  77. if( INVALID_SOCKET == listenSocket ) {
  78. UINT uErr = (UINT)WSAGetLastError();
  79. DbgLog3( SEV_ERROR, "listen on %s socket() failed with %d [0x%x]", ServiceName, uErr, uErr);
  80. goto lErr;
  81. }
  82. DbgLog2( SEV_INFO, "listen on %s socket ID: %ld", ServiceName, (DWORD)listenSocket );
  83. saListen.irdaAddressFamily = AF_IRDA;
  84. *(UINT *)saListen.irdaDeviceID = 0;
  85. StringCbCopyA(saListen.irdaServiceName,sizeof(saListen.irdaServiceName), ServiceName );
  86. nRet = bind( listenSocket, (const struct sockaddr *)&saListen, sizeof(saListen) );
  87. if( SOCKET_ERROR == nRet ) {
  88. UINT uErr = (UINT)WSAGetLastError();
  89. DbgLog3( SEV_ERROR, "listen on %s setsockopt failed with %d [0x%x]", ServiceName, uErr, uErr);
  90. closesocket(listenSocket);
  91. goto lErr;
  92. }
  93. nRet = listen( listenSocket, nSOCKET_MAXCONN );
  94. if( SOCKET_ERROR == nRet ) {
  95. UINT uErr = (UINT)WSAGetLastError();
  96. DbgLog3( SEV_ERROR, "listen on %s listen() failed with %d [0x%x]", ServiceName, uErr, uErr);
  97. closesocket(listenSocket);
  98. goto lErr;
  99. }
  100. } else {
  101. }
  102. Transfer=ListenForTransfer(listenSocket,TYPE_IRDA);
  103. if (Transfer == NULL) {
  104. closesocket(listenSocket);
  105. }
  106. return Transfer;
  107. lErr:
  108. return NULL;
  109. }
  110. DWORD
  111. FILE_TRANSFER::Sock_EstablishConnection(
  112. DWORD dwDeviceID,
  113. OBEX_DEVICE_TYPE DeviceType
  114. )
  115. {
  116. FILE_TRANSFER * transfer;
  117. _state = CONNECTING;
  118. if (DeviceType == TYPE_IRDA) {
  119. SOCKADDR_IRDA saRemote;
  120. saRemote.irdaAddressFamily = AF_IRDA;
  121. *(UINT *)saRemote.irdaDeviceID = dwDeviceID;
  122. StringCbCopyA(saRemote.irdaServiceName,sizeof(saRemote.irdaServiceName), SERVICE_NAME_1 );
  123. if ( 0 == connect( _socket, (const struct sockaddr *) &saRemote, sizeof(saRemote))) {
  124. return 0;
  125. }
  126. StringCbCopyA(saRemote.irdaServiceName,sizeof(saRemote.irdaServiceName), SERVICE_NAME_2 );
  127. if ( 0 == connect( _socket, (const struct sockaddr *) &saRemote, sizeof(saRemote))) {
  128. return 0;
  129. }
  130. } else {
  131. sockaddr_in Address;
  132. ZeroMemory(&Address,sizeof(Address));
  133. Address.sin_family=AF_INET;
  134. Address.sin_port=650;
  135. Address.sin_addr.S_un.S_addr=dwDeviceID;
  136. if ( 0 == connect( _socket, (const struct sockaddr *) &Address, sizeof(Address))) {
  137. return 0;
  138. }
  139. }
  140. return WSAGetLastError();
  141. }
  142. DWORD
  143. FILE_TRANSFER::SyncAccept(
  144. VOID
  145. )
  146. {
  147. DWORD status = 0;
  148. DWORD bytes = 0;
  149. DWORD dwEventStatus = 0;
  150. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  151. int size;
  152. SOCKADDR_IRDA s;
  153. sockaddr_in Address;
  154. BOOL bResult;
  155. status = 0;
  156. while (!m_StopListening) {
  157. _state = ACCEPTING;
  158. _dataXferRecv.dwFileSent = 0;
  159. if (m_DeviceType == TYPE_IRDA) {
  160. size = sizeof(SOCKADDR_IRDA);
  161. _socket = accept( m_ListenSocket, (sockaddr *) &s, &size );
  162. } else {
  163. size=sizeof(Address);
  164. _socket = accept( m_ListenSocket, (sockaddr *) &Address, &size );
  165. }
  166. if ( INVALID_SOCKET == _socket ) {
  167. if (!m_StopListening) {
  168. //
  169. // the thread has been request to stop listening for incoming connection
  170. //
  171. if (!dwEventStatus) {
  172. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_LISTEN_FAILED, WSAGetLastError());
  173. }
  174. Sleep(1 * 1000);
  175. }
  176. continue;
  177. }
  178. //
  179. // we are handling an incoming connection, don't suspend on timeout during the transfer
  180. //
  181. SetThreadExecutionState( ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
  182. _state = READING;
  183. //
  184. // Record the machine name for later use.
  185. //
  186. RecordDeviceName( &s );
  187. _fCancelled=FALSE;
  188. do {
  189. if (_fCancelled) {
  190. #if DBG
  191. DbgPrint("irmon: receive canceled\n");
  192. #endif
  193. status = ERROR_CANCELLED;
  194. break;
  195. }
  196. DWORD BytesToRead=Store_GetSize(_dataRecv.lpStore)-Store_GetDataUsed(_dataRecv.lpStore);
  197. bytes = recv( _socket, (char *) _buffer, BytesToRead, 0 );
  198. if (SOCKET_ERROR == bytes) {
  199. if (_dataRecv.state == osCONN) {
  200. //
  201. // workaround for nokia cell phones that drop the irda connection after sending
  202. // the file. If we are not in the middle of a file transfer then just left it close
  203. // normally
  204. //
  205. status = 0;
  206. break;
  207. } else {
  208. if (!dwEventStatus) {
  209. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_RECV_FAILED, WSAGetLastError());
  210. }
  211. }
  212. status = GetLastError();
  213. break;
  214. }
  215. if (0 == bytes) {
  216. status = 0;
  217. break;
  218. }
  219. HANDLE MutexHandle;
  220. MutexHandle=OpenMutex(SYNCHRONIZE,FALSE,SINGLE_INST_MUTEX);
  221. if (MutexHandle == NULL) {
  222. //
  223. // start the ui app, so we have something to rpc to.
  224. //
  225. LaunchUi( NULL);
  226. } else {
  227. //
  228. // The app is already running
  229. //
  230. CloseHandle(MutexHandle);
  231. }
  232. DbgLog1(SEV_FUNCTION,"SyncAccept(): Recv: %d bytes", bytes);
  233. ASSERT( _guard == GUARD_MAGIC );
  234. _dataXferRecv.dwFileSent += bytes;
  235. Obex_ReceiveData( xferRECV, _buffer, bytes );
  236. while (Obex_ConsumePackets( xferRECV, &status )) {
  237. if (status != ERROR_SUCCESS) {
  238. break;
  239. }
  240. }
  241. if (status == 0xffffffff) {
  242. status = 0;
  243. }
  244. } while (status == STATUS_SUCCESS);
  245. DbgLog1( status ? SEV_ERROR : SEV_INFO, "Obex_Consume returned %d", status);
  246. //
  247. // Clean up OBEX data.
  248. //
  249. HandleClosure( status );
  250. status = 0;
  251. if (_socket != INVALID_SOCKET) {
  252. closesocket(_socket);
  253. _socket=INVALID_SOCKET;
  254. }
  255. //
  256. // done with this connection, allow idle suspend
  257. //
  258. SetThreadExecutionState( ES_CONTINUOUS );
  259. }
  260. #if DBG
  261. DbgPrint("IRMON: accept thread exiting\n");
  262. #endif
  263. DecrementRefCount();
  264. return 0;
  265. }
  266. error_status_t
  267. FILE_TRANSFER::Sock_CheckForReply(
  268. long timeout
  269. )
  270. {
  271. int bytes;
  272. long seconds;
  273. long msec;
  274. fd_set FdSet;
  275. timeval BerkeleyTimeout;
  276. FD_ZERO( &FdSet );
  277. FD_SET( _socket, &FdSet );
  278. if (timeout == TIMEOUT_INFINITE) {
  279. int Result=0;
  280. while (Result == 0) {
  281. msec = 0;
  282. seconds = 5;
  283. BerkeleyTimeout.tv_sec = seconds;
  284. BerkeleyTimeout.tv_usec = msec * 1000;
  285. Result=select(0, &FdSet, NULL, NULL, &BerkeleyTimeout);
  286. // if (0 == Result) {
  287. //
  288. // return ERROR_TIMEOUT;
  289. // }
  290. if (_fCancelled) {
  291. return ERROR_OPERATION_ABORTED;
  292. }
  293. }
  294. } else {
  295. msec = timeout % 1000;
  296. seconds = timeout / 1000;
  297. BerkeleyTimeout.tv_sec = seconds;
  298. BerkeleyTimeout.tv_usec = msec * 1000;
  299. DbgLog1(SEV_INFO, "sock_checkForReply: timeout %ld", timeout);
  300. if (0 == select(0, &FdSet, NULL, NULL, &BerkeleyTimeout)) {
  301. return ERROR_TIMEOUT;
  302. }
  303. }
  304. bytes = recv( _socket, (char *) _buffer, cbSOCK_BUFFER_SIZE, 0 );
  305. if (bytes == SOCKET_ERROR) {
  306. return GetLastError();
  307. } else if (bytes == 0) {
  308. return WSAECONNRESET;
  309. } else {
  310. DbgLog1(SEV_FUNCTION,"Sock_CheckForReply(): Recv: %d bytes", bytes);
  311. Obex_ReceiveData( xferSEND, _buffer, bytes );
  312. return 0;
  313. }
  314. return 0;
  315. }
  316. DWORD
  317. AcceptThreadStartRoutine(
  318. PVOID Context
  319. )
  320. {
  321. FILE_TRANSFER * transfer=(FILE_TRANSFER *)Context;
  322. return transfer->SyncAccept();
  323. }
  324. FILE_TRANSFER *
  325. ListenForTransfer(
  326. SOCKET ListenSocket,
  327. OBEX_DEVICE_TYPE DeviceType
  328. )
  329. {
  330. FILE_TRANSFER * transfer;
  331. BOOL bResult;
  332. ULONG ThreadId;
  333. HANDLE ThreadHandle;
  334. transfer = new FILE_TRANSFER;
  335. if (transfer == NULL) {
  336. return NULL;
  337. }
  338. bResult=transfer->Xfer_Init(0, 0, dialWin95,DeviceType,FALSE,ListenSocket);
  339. if (!bResult) {
  340. delete transfer;
  341. return NULL;
  342. }
  343. ThreadHandle=CreateThread(
  344. NULL,
  345. 80000,
  346. AcceptThreadStartRoutine,
  347. (PVOID) transfer,
  348. STACK_SIZE_PARAM_IS_A_RESERVATION,
  349. &ThreadId
  350. );
  351. if (ThreadHandle == NULL) {
  352. delete transfer;
  353. return NULL;
  354. }
  355. CloseHandle(ThreadHandle);
  356. return transfer;
  357. }
  358. void
  359. FILE_TRANSFER::HandleClosure(
  360. DWORD error
  361. )
  362. {
  363. if (!error)
  364. {
  365. _state = CLOSING;
  366. }
  367. if (_state == ACCEPTING ||
  368. _state == READING )
  369. {
  370. SendReplyWin32( 0, error );
  371. }
  372. if (_fInUiReceiveList)
  373. {
  374. _fInUiReceiveList = FALSE;
  375. _ReceiveFinished( rpcBinding, _cookie, error );
  376. }
  377. if (error)
  378. {
  379. Xfer_FileAbort(); // just in case a file is being received
  380. }
  381. Obex_Reset(); // reset the state machine
  382. }
  383. error_status_t
  384. FILE_TRANSFER::Sock_Request( LPVOID lpvData, DWORD dwDataSize )
  385. {
  386. if (send( _socket, (char *) lpvData, dwDataSize, 0) != (int) dwDataSize)
  387. {
  388. return GetLastError();
  389. }
  390. DbgLog1(SEV_FUNCTION,"Sock_Request(): Send: %d bytes", dwDataSize);
  391. return 0;
  392. }
  393. error_status_t
  394. FILE_TRANSFER::Sock_Respond(
  395. LPVOID lpvData,
  396. DWORD dwDataSize
  397. )
  398. {
  399. if (send( _socket, (char *) lpvData, dwDataSize, 0) != (int) dwDataSize)
  400. {
  401. return GetLastError();
  402. }
  403. DbgLog1(SEV_FUNCTION,"Sock_Respond(): Send: %d bytes", dwDataSize);
  404. return 0;
  405. }