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.

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