GHStreamSocket.jvm.cs 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. using java.nio.channels;
  2. using java.security;
  3. using javax.net.ssl;
  4. namespace System.Net.Sockets
  5. {
  6. /// <summary>
  7. /// Summary description for GHStreamSocket.
  8. /// </summary>
  9. internal class GHStreamSocket : GHSocket
  10. {
  11. java.net.ServerSocket jServerSocket;
  12. java.net.Socket jSocket;
  13. java.nio.channels.ServerSocketChannel jServerSocketChannel;
  14. java.nio.channels.SocketChannel jSocketChannel;
  15. // This field I need because a bug in the java.nio.channels.SocketAdapter, which
  16. // returns local port 0 if the socket is not connected (even if the socket is bound)
  17. // so I need temporary use regular socket (not channel socket) to bind it to the
  18. // local address and use this address in the LocalPoint property and to create the
  19. // actual client/server channel sockets
  20. // The bug #5076965 (SocketChannel does not report local address after binding to a wildcard )
  21. // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5076965
  22. java.net.InetSocketAddress jTempLocalSocketAddress;
  23. public GHStreamSocket()
  24. {
  25. jSocketChannel = java.nio.channels.SocketChannel.open();
  26. jSocket = jSocketChannel.socket();
  27. }
  28. public GHStreamSocket(java.nio.channels.SocketChannel socketChannel)
  29. {
  30. jSocketChannel = socketChannel;
  31. jSocket = jSocketChannel.socket();
  32. }
  33. public override int GetHashCode ()
  34. {
  35. if (jSocket == null && jServerSocket == null)
  36. return -1;
  37. if (jServerSocket != null) {
  38. return jServerSocket.ToString ().GetHashCode ();
  39. }
  40. return jSocket.ToString ().GetHashCode ();
  41. }
  42. public int Available_internal(out int error)
  43. {
  44. error = 0;
  45. int r = 0;
  46. if (jSocket == null || !jSocket.isConnected())
  47. {
  48. return r;
  49. }
  50. try
  51. {
  52. r = jSocket.getInputStream().available();
  53. }
  54. catch (Exception e)
  55. {
  56. error = 10054; //WSAECONNRESET (Connection reset by peer)
  57. r = 0;
  58. #if DEBUG
  59. Console.WriteLine("Caught exception during Available_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  60. #endif
  61. }
  62. return r;
  63. }
  64. public void Blocking_internal(bool block, out int error)
  65. {
  66. error = 0;
  67. if (jSocket == null && jServerSocket == null)
  68. {
  69. error = 10022; //WSAEINVAL (Invalid argument)
  70. return;
  71. }
  72. try
  73. {
  74. if (jServerSocket != null)
  75. {
  76. jServerSocketChannel.configureBlocking(block);
  77. }
  78. else
  79. {
  80. jSocketChannel.configureBlocking(block);
  81. }
  82. }
  83. catch (Exception e)
  84. {
  85. error = 10022; //WSAEINVAL (Invalid argument)
  86. #if DEBUG
  87. Console.WriteLine("Caught exception during Blocking_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  88. #endif
  89. }
  90. }
  91. public EndPoint LocalEndPoint_internal(out int error)
  92. {
  93. error = 0;
  94. java.net.InetSocketAddress localAddr = null;
  95. try
  96. {
  97. if (jTempLocalSocketAddress != null)
  98. {
  99. localAddr = jTempLocalSocketAddress;
  100. }
  101. else if (jServerSocket != null)
  102. {
  103. localAddr = (java.net.InetSocketAddress)jServerSocket.getLocalSocketAddress();
  104. }
  105. else
  106. {
  107. localAddr = (java.net.InetSocketAddress)jSocket.getLocalSocketAddress();
  108. }
  109. }
  110. catch (Exception e)
  111. {
  112. localAddr = null;
  113. #if DEBUG
  114. Console.WriteLine("Caught exception during LocalEndPoint_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  115. #endif
  116. }
  117. if (localAddr == null || localAddr.getAddress() == null || localAddr.getPort() < 0)
  118. {
  119. return null;
  120. }
  121. IPHostEntry lipa = Dns.Resolve(localAddr.getHostName());
  122. IPEndPoint ret = new IPEndPoint(lipa.AddressList[0], localAddr.getPort());
  123. return ret;
  124. }
  125. public EndPoint RemoteEndPoint_internal(out int error)
  126. {
  127. error = 0;
  128. java.net.InetSocketAddress remoteAddr = null;
  129. if (jSocket == null || !jSocket.isBound())
  130. {
  131. return null;
  132. }
  133. try
  134. {
  135. remoteAddr = (java.net.InetSocketAddress)jSocket.getRemoteSocketAddress();
  136. }
  137. catch (Exception e)
  138. {
  139. remoteAddr = null;
  140. #if DEBUG
  141. Console.WriteLine("Caught exception during RemoteEndPoint_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  142. #endif
  143. }
  144. if (remoteAddr == null || remoteAddr.getAddress() == null || remoteAddr.getPort() <= 0)
  145. {
  146. error = 10057; //WSAENOTCONN (Socket is not connected)
  147. return null;
  148. }
  149. IPHostEntry lipa = Dns.Resolve(remoteAddr.getHostName());
  150. IPEndPoint ret = new IPEndPoint(lipa.AddressList[0], remoteAddr.getPort());
  151. return ret;
  152. }
  153. public GHSocket Accept_internal(out int error)
  154. {
  155. error = 0;
  156. if (jServerSocket == null)
  157. {
  158. throw new InvalidOperationException("You must call Bind and Listen before calling Accept.");
  159. }
  160. try
  161. {
  162. /*
  163. If this channel is in non-blocking mode then this method will immediately
  164. return null if there are no pending connections.
  165. Otherwise it will block indefinitely until a new connection is
  166. available or an I/O error occurs.
  167. */
  168. java.nio.channels.SocketChannel acceptedSocket = jServerSocketChannel.accept();
  169. if (acceptedSocket == null)
  170. {
  171. error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
  172. #if DEBUG
  173. Console.WriteLine("The Accept_internal is in non-blocking mode and no pending connections are available");
  174. #endif
  175. return null;
  176. }
  177. return new GHStreamSocket(acceptedSocket);
  178. }
  179. catch (AsynchronousCloseException) {
  180. error = 10004;
  181. }
  182. catch (Exception e)
  183. {
  184. error = 10061; //WSAECONNREFUSED (Connection refused)
  185. #if DEBUG
  186. Console.WriteLine("Caught exception during Accept_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  187. #endif
  188. }
  189. return null;
  190. }
  191. public void Bind_internal(EndPoint sa, out int error)
  192. {
  193. error = 0;
  194. IPEndPoint addr = sa as IPEndPoint;
  195. if (addr == null)
  196. {
  197. error = 10044; //WSAESOCKTNOSUPPORT (Socket type not supported)
  198. return;
  199. }
  200. if (jSocket == null || jSocket.isBound() || jSocket.isConnected() || jSocketChannel.isConnectionPending())
  201. {
  202. error = 10022; //WSAEINVAL (Invalid argument)
  203. return;
  204. }
  205. try
  206. {
  207. // This code I need because a bug in the java.nio.channels.SocketAdapter, which
  208. // returns local port 0 if the socket is not connected (even if the socket is bound)
  209. // so I need temporary use regular socket (not channel socket) to bind it to the
  210. // local address and use this address in the LocalPoint property and to create the
  211. // actual client/server channel sockets
  212. // The bug #5076965 (SocketChannel does not report local address after binding to a wildcard )
  213. // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5076965
  214. java.net.Socket jTempSocket = new java.net.Socket();
  215. jTempSocket.bind(new java.net.InetSocketAddress(java.net.InetAddress.getByName(addr.Address.ToString()),
  216. addr.Port));
  217. jTempLocalSocketAddress = (java.net.InetSocketAddress)jTempSocket.getLocalSocketAddress();
  218. jTempSocket.close();
  219. jSocket.bind(jTempLocalSocketAddress);
  220. }
  221. catch (Exception e)
  222. {
  223. error = 10048; //WSAEADDRINUSE (Address already in use)
  224. #if DEBUG
  225. Console.WriteLine("Caught exception during Bind_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  226. #endif
  227. }
  228. }
  229. public void Close_internal(out int error)
  230. {
  231. error = 0;
  232. if (jServerSocket != null)
  233. {
  234. try
  235. {
  236. jServerSocket.close();
  237. }
  238. catch (Exception e)
  239. {
  240. error = 10022; //WSAEINVAL (Invalid argument)
  241. #if DEBUG
  242. Console.WriteLine("Caught exception during Close_internal jServerSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  243. #endif
  244. }
  245. try
  246. {
  247. jServerSocketChannel.close();
  248. }
  249. catch (Exception e)
  250. {
  251. error = 10022; //WSAEINVAL (Invalid argument)
  252. #if DEBUG
  253. Console.WriteLine("Caught exception during Close_internal jServerSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  254. #endif
  255. }
  256. jServerSocket = null;
  257. jServerSocketChannel = null;
  258. }
  259. else if (jSocket != null)
  260. {
  261. try
  262. {
  263. jSocket.close();
  264. }
  265. catch (Exception e)
  266. {
  267. error = 10022; //WSAEINVAL (Invalid argument)
  268. #if DEBUG
  269. Console.WriteLine("Caught exception during Close_internal jSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  270. #endif
  271. }
  272. try
  273. {
  274. jSocketChannel.close();
  275. }
  276. catch (Exception e)
  277. {
  278. error = 10022; //WSAEINVAL (Invalid argument)
  279. #if DEBUG
  280. Console.WriteLine("Caught exception during Close_internal jSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  281. #endif
  282. }
  283. jSocket = null;
  284. jSocketChannel = null;
  285. }
  286. }
  287. public void Connect_internal(EndPoint sa, out int error)
  288. {
  289. error = 0;
  290. IPEndPoint addr = sa as IPEndPoint;
  291. if (addr == null)
  292. {
  293. error = 10044; //WSAESOCKTNOSUPPORT (Socket type not supported)
  294. return;
  295. }
  296. if (jSocket == null)
  297. {
  298. error = 10022; //WSAEINVAL (Invalid argument)
  299. return;
  300. }
  301. if (jSocket.isConnected() || jSocketChannel.isConnectionPending())
  302. {
  303. error = 10056; //WSAEISCONN (Socket is already connected)
  304. return;
  305. }
  306. try
  307. {
  308. /*
  309. If this channel is in non-blocking mode then an invocation of this method
  310. initiates a non-blocking connection operation. If the connection is
  311. established immediately, as can happen with a local connection, then this
  312. method returns true. Otherwise this method returns false.
  313. If this channel is in blocking mode then an invocation of this method
  314. will block until the connection is established or an I/O error occurs.
  315. */
  316. bool status = jSocketChannel.connect(new java.net.InetSocketAddress(
  317. java.net.InetAddress.getByName(addr.Address.ToString()),
  318. addr.Port));
  319. if (!status)
  320. {
  321. error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
  322. }
  323. }
  324. catch (java.nio.channels.AlreadyConnectedException ae)
  325. {
  326. error = 10056; //WSAEISCONN (Socket is already connected)
  327. }
  328. catch (java.nio.channels.ConnectionPendingException cpe)
  329. {
  330. error = 10036; //WSAEINPROGRESS (Operation now in progress)
  331. }
  332. catch (java.nio.channels.UnresolvedAddressException uae)
  333. {
  334. error = 10039; //WSAEDESTADDRREQ (Destination address required)
  335. }
  336. catch (java.nio.channels.UnsupportedAddressTypeException uate)
  337. {
  338. error = 10041; //WSAEPROTOTYPE (Protocol wrong type for socket)
  339. }
  340. catch (AsynchronousCloseException) {
  341. error = 10004;
  342. }
  343. catch (Exception e)
  344. {
  345. error = 10061; //WSAECONNREFUSED (Connection refused)
  346. #if DEBUG
  347. Console.WriteLine("Caught exception during Connect_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  348. #endif
  349. }
  350. }
  351. public void Listen_internal(int backlog, out int error)
  352. {
  353. error = 0;
  354. if (jSocket == null || !jSocket.isBound())
  355. {
  356. error = 10022; //WSAEINVAL (Invalid argument)
  357. return;
  358. }
  359. if (jSocket.isConnected() || jSocketChannel.isConnectionPending())
  360. {
  361. error = 10056; //WSAEISCONN (Socket is already connected)
  362. return;
  363. }
  364. bool blockMode = jSocketChannel.isBlocking();
  365. bool reuseAddr = jSocket.getReuseAddress();
  366. try
  367. {
  368. jSocket.close();
  369. }
  370. catch (Exception e)
  371. {
  372. #if DEBUG
  373. Console.WriteLine("Caught exception during Listen_internal close old jSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  374. #endif
  375. }
  376. try
  377. {
  378. jSocketChannel.close();
  379. }
  380. catch (Exception e)
  381. {
  382. #if DEBUG
  383. Console.WriteLine("Caught exception during Listen_internal close old jSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  384. #endif
  385. }
  386. jSocket = null;
  387. jSocketChannel = null;
  388. try
  389. {
  390. jServerSocketChannel = java.nio.channels.ServerSocketChannel.open();
  391. jServerSocket = jServerSocketChannel.socket();
  392. jServerSocket.bind(jTempLocalSocketAddress, backlog);
  393. jServerSocketChannel.configureBlocking(blockMode);
  394. jServerSocket.setReuseAddress(reuseAddr);
  395. }
  396. catch (Exception e)
  397. {
  398. error = 10048; //WSAEADDRINUSE (Address already in use)
  399. #if DEBUG
  400. Console.WriteLine("Caught exception during Listen_internal create server socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  401. #endif
  402. }
  403. }
  404. public bool Poll_internal (SelectMode mode, int timeout, Socket source, out int error)
  405. {
  406. error = 0;
  407. if (mode == SelectMode.SelectError && !jSocketChannel.isConnectionPending())
  408. {
  409. return false;
  410. }
  411. java.nio.channels.Selector selector = java.nio.channels.Selector.open();
  412. RegisterSelector(selector, ((mode == SelectMode.SelectRead)?0:1), source, out error);
  413. if (error != 0)
  414. {
  415. error = 0;
  416. GHSocketFactory.CloseSelector(selector);
  417. return (mode == SelectMode.SelectError);
  418. }
  419. bool retVal = false;
  420. long timeOutMillis = 1;
  421. if (timeout < 0)
  422. {
  423. timeOutMillis = 0;
  424. }
  425. else if (timeout > 999)
  426. {
  427. timeOutMillis = (long)(timeout / 1000);
  428. }
  429. int readyCount = 0;
  430. try
  431. {
  432. readyCount = selector.select(timeOutMillis);
  433. }
  434. catch (Exception e)
  435. {
  436. error = 10022; //WSAEINVAL (Invalid argument)
  437. #if DEBUG
  438. Console.WriteLine("Caught exception during Poll_internal selector.select - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  439. #endif
  440. }
  441. if (readyCount > 0)
  442. {
  443. if (jSocket != null && jSocketChannel.isConnectionPending())
  444. {
  445. bool status = false;
  446. try
  447. {
  448. status = jSocketChannel.finishConnect();
  449. }
  450. catch (Exception e)
  451. {
  452. #if DEBUG
  453. Console.WriteLine("Caught exception during Poll_internal, finishConnect - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  454. #endif
  455. }
  456. if (status)
  457. {
  458. retVal = (mode != SelectMode.SelectError);
  459. }
  460. else
  461. {
  462. retVal = (mode == SelectMode.SelectError);
  463. }
  464. }
  465. else
  466. {
  467. retVal = true;
  468. }
  469. }
  470. GHSocketFactory.CloseSelector(selector);
  471. return retVal;
  472. }
  473. public void RegisterSelector(java.nio.channels.Selector selector, int mode, Socket source, out int error)
  474. {
  475. error = 0;
  476. if (jServerSocket != null)
  477. {
  478. // only accept operation, which included to the read list, is allowed for server sockets
  479. if (mode != 0)
  480. {
  481. // error = 10038; //WSAENOTSOCK (Socket operation on nonsocket)
  482. #if DEBUG
  483. Console.WriteLine("RegisterSelector, invalid mode {0} for the server socket", mode);
  484. #endif
  485. return;
  486. }
  487. try
  488. {
  489. if (jServerSocketChannel.isBlocking())
  490. {
  491. /*
  492. A channel must be placed into non-blocking mode before being registered
  493. with a selector, and may not be returned to blocking mode until it has been
  494. deregistered.
  495. */
  496. jServerSocketChannel.configureBlocking(false);
  497. }
  498. jServerSocketChannel.register(selector, java.nio.channels.SelectionKey.OP_ACCEPT, source);
  499. }
  500. catch (Exception e)
  501. {
  502. error = 10022; //WSAEINVAL (Invalid argument)
  503. #if DEBUG
  504. Console.WriteLine("Caught exception during RegisterSelector, register server socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  505. #endif
  506. }
  507. }
  508. else
  509. {
  510. try
  511. {
  512. int ops = java.nio.channels.SelectionKey.OP_READ;
  513. if (mode > 0)
  514. {
  515. if (jSocketChannel.isConnectionPending())
  516. {
  517. ops = java.nio.channels.SelectionKey.OP_CONNECT;
  518. }
  519. else
  520. {
  521. ops = java.nio.channels.SelectionKey.OP_WRITE;
  522. }
  523. }
  524. if (jSocketChannel.isBlocking())
  525. {
  526. /*
  527. A channel must be placed into non-blocking mode before being registered
  528. with a selector, and may not be returned to blocking mode until it has been
  529. deregistered.
  530. */
  531. jSocketChannel.configureBlocking(false);
  532. }
  533. jSocketChannel.register(selector, ops, source);
  534. }
  535. catch (Exception e)
  536. {
  537. error = 10022; //WSAEINVAL (Invalid argument)
  538. #if DEBUG
  539. Console.WriteLine("Caught exception during RegisterSelector, register client socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  540. #endif
  541. }
  542. }
  543. }
  544. public bool CheckConnectionFinished()
  545. {
  546. bool status = true;
  547. if (jSocket != null && jSocketChannel.isConnectionPending())
  548. {
  549. try
  550. {
  551. status = jSocketChannel.finishConnect();
  552. }
  553. catch (Exception e)
  554. {
  555. status = false;
  556. #if DEBUG
  557. Console.WriteLine("Caught exception during Poll_internal, finishConnect - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  558. #endif
  559. }
  560. }
  561. return status;
  562. }
  563. public int Receive_internal(byte[] buffer, int offset, int count, SocketFlags flags,
  564. out int error)
  565. {
  566. error = 0;
  567. int ret = 0;
  568. if (jSocket == null)
  569. {
  570. error = 10057; //WSAENOTCONN (Socket is not connected)
  571. return ret;
  572. }
  573. try
  574. {
  575. if (jSocketChannel.isConnectionPending())
  576. {
  577. bool status = jSocketChannel.finishConnect();
  578. if (!status)
  579. {
  580. error = 10022; //WSAEINVAL (Invalid argument)
  581. #if DEBUG
  582. Console.WriteLine("Receive_internal, jSocketChannel.finishConnect return false");
  583. #endif
  584. return 0;
  585. }
  586. }
  587. else if (!jSocketChannel.isConnected())
  588. {
  589. error = 10057; //WSAENOTCONN (Socket is not connected)
  590. return ret;
  591. }
  592. java.nio.ByteBuffer readBuff = java.nio.ByteBuffer.wrap(vmw.common.TypeUtils.ToSByteArray(buffer), offset, count);
  593. ret = jSocketChannel.read(readBuff);
  594. if (ret < 0) ret = 0;
  595. }
  596. catch (Exception e)
  597. {
  598. error = 10054; //WSAECONNRESET (Connection reset by peer)
  599. ret = 0;
  600. #if DEBUG
  601. Console.WriteLine("Caught exception during Receive_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  602. #endif
  603. }
  604. if (ret == 0 && !jSocketChannel.isBlocking())
  605. {
  606. error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
  607. }
  608. return ret;
  609. }
  610. public int RecvFrom_internal(byte[] buffer, int offset, int count, SocketFlags flags,
  611. ref SocketAddress sockaddr, out int error)
  612. {
  613. return Receive_internal(buffer, offset, count, flags, out error);
  614. }
  615. public int Send_internal(byte[] buf, int offset, int count, SocketFlags flags,
  616. out int error)
  617. {
  618. error = 0;
  619. int ret = 0;
  620. if (jSocket == null)
  621. {
  622. error = 10057; //WSAENOTCONN (Socket is not connected)
  623. return ret;
  624. }
  625. try
  626. {
  627. if (jSocketChannel.isConnectionPending())
  628. {
  629. bool status = jSocketChannel.finishConnect();
  630. if (!status)
  631. {
  632. error = 10022; //WSAEINVAL (Invalid argument)
  633. #if DEBUG
  634. Console.WriteLine("Send_internal, jSocketChannel.finishConnect return false");
  635. #endif
  636. return 0;
  637. }
  638. }
  639. else if (!jSocketChannel.isConnected())
  640. {
  641. error = 10057; //WSAENOTCONN (Socket is not connected)
  642. return ret;
  643. }
  644. java.nio.ByteBuffer writeBuff = java.nio.ByteBuffer.wrap(vmw.common.TypeUtils.ToSByteArray(buf), offset, count);
  645. ret = jSocketChannel.write(writeBuff);
  646. if (ret < 0) ret = 0;
  647. }
  648. catch (Exception e)
  649. {
  650. error = 10054; //WSAECONNRESET (Connection reset by peer)
  651. ret = 0;
  652. #if DEBUG
  653. Console.WriteLine("Caught exception during Send_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  654. #endif
  655. }
  656. if (ret == 0 && !jSocketChannel.isBlocking())
  657. {
  658. error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
  659. }
  660. return ret;
  661. }
  662. public int SendTo_internal(byte[] buffer, int offset, int count,
  663. SocketFlags flags, SocketAddress sa, out int error)
  664. {
  665. return Send_internal(buffer, offset, count, flags, out error);
  666. }
  667. public void SetSocketOption_internal (SocketOptionLevel level,
  668. SocketOptionName name, object obj_val,
  669. byte [] byte_val, int int_val, out int error)
  670. {
  671. error = 0;
  672. if (byte_val != null)
  673. {
  674. error = -1;
  675. throw new NotImplementedException();
  676. }
  677. if (jSocket == null && jServerSocket == null)
  678. {
  679. error = 10022; //WSAEINVAL (Invalid argument)
  680. return;
  681. }
  682. switch (level)
  683. {
  684. case SocketOptionLevel.IPv6:
  685. error = 10042; //WSAENOPROTOOPT (Bad protocol option)
  686. return;
  687. case SocketOptionLevel.IP:
  688. if (name != SocketOptionName.NoDelay)
  689. {
  690. error = 10042; //WSAENOPROTOOPT (Bad protocol option)
  691. return;
  692. }
  693. break;
  694. case SocketOptionLevel.Udp:
  695. if (name == SocketOptionName.NoDelay)
  696. {
  697. error = 10042; //WSAENOPROTOOPT (Bad protocol option)
  698. }
  699. else
  700. {
  701. error = 10022; //WSAEINVAL (Invalid argument)
  702. }
  703. return;
  704. case SocketOptionLevel.Tcp:
  705. if (name != SocketOptionName.NoDelay)
  706. {
  707. error = 10022; //WSAEINVAL (Invalid argument)
  708. return;
  709. }
  710. break;
  711. }
  712. try
  713. {
  714. bool bval = false;
  715. int ival = 0;
  716. switch (name)
  717. {
  718. case SocketOptionName.DontLinger:
  719. jSocket.setSoLinger(false, 0);
  720. break;
  721. case SocketOptionName.Linger:
  722. LingerOption lval = obj_val as LingerOption;
  723. if (lval != null)
  724. {
  725. jSocket.setSoLinger(lval.Enabled, lval.LingerTime);
  726. }
  727. else
  728. {
  729. error = 10022; //WSAEINVAL (Invalid argument)
  730. }
  731. break;
  732. case SocketOptionName.KeepAlive:
  733. if (obj_val != null)
  734. {
  735. bval = ((int)obj_val == 0)?false:true;
  736. }
  737. else
  738. {
  739. bval = (int_val == 0)?false:true;
  740. }
  741. jSocket.setKeepAlive(bval);
  742. break;
  743. case SocketOptionName.NoDelay:
  744. if (obj_val != null)
  745. {
  746. bval = ((int)obj_val == 0)?false:true;
  747. }
  748. else
  749. {
  750. bval = (int_val == 0)?false:true;
  751. }
  752. jSocket.setTcpNoDelay(bval);
  753. break;
  754. case SocketOptionName.ReceiveBuffer:
  755. ival = int_val;
  756. if (obj_val != null)
  757. {
  758. ival = (int) obj_val;
  759. }
  760. if (jServerSocket != null)
  761. {
  762. jServerSocket.setReceiveBufferSize(ival);
  763. }
  764. else
  765. {
  766. jSocket.setReceiveBufferSize(ival);
  767. }
  768. break;
  769. case SocketOptionName.ReceiveTimeout:
  770. ival = int_val;
  771. if (obj_val != null)
  772. {
  773. ival = (int) obj_val;
  774. }
  775. if (jServerSocket != null)
  776. {
  777. jServerSocket.setSoTimeout(ival);
  778. }
  779. else
  780. {
  781. jSocket.setSoTimeout(ival);
  782. }
  783. break;
  784. case SocketOptionName.ReuseAddress:
  785. if (obj_val != null)
  786. {
  787. bval = ((int)obj_val == 0)?false:true;
  788. }
  789. else
  790. {
  791. bval = (int_val == 0)?false:true;
  792. }
  793. if (jServerSocket != null)
  794. {
  795. jServerSocket.setReuseAddress(bval);
  796. }
  797. else
  798. {
  799. jSocket.setReuseAddress(bval);
  800. }
  801. break;
  802. case SocketOptionName.SendBuffer:
  803. ival = int_val;
  804. if (obj_val != null)
  805. {
  806. ival = (int) obj_val;
  807. }
  808. jSocket.setSendBufferSize(ival);
  809. break;
  810. case SocketOptionName.OutOfBandInline:
  811. if (obj_val != null)
  812. {
  813. bval = ((int)obj_val == 0)?false:true;
  814. }
  815. else
  816. {
  817. bval = (int_val == 0)?false:true;
  818. }
  819. jSocket.setOOBInline(bval);
  820. break;
  821. default:
  822. error = 10022; //WSAEINVAL (Invalid argument)
  823. break;
  824. }
  825. }
  826. catch (Exception e)
  827. {
  828. error = 10022; //WSAEINVAL (Invalid argument)
  829. obj_val = null;
  830. }
  831. }
  832. public void GetSocketOption_obj_internal(SocketOptionLevel level, SocketOptionName name,
  833. out object obj_val, out int error)
  834. {
  835. obj_val = null;
  836. error = 0;
  837. if (jSocket == null && jServerSocket == null)
  838. {
  839. error = 10022; //WSAEINVAL (Invalid argument)
  840. return;
  841. }
  842. switch (level)
  843. {
  844. case SocketOptionLevel.IPv6:
  845. error = 10042; //WSAENOPROTOOPT (Bad protocol option)
  846. return;
  847. case SocketOptionLevel.IP:
  848. if (name != SocketOptionName.NoDelay)
  849. {
  850. error = 10042; //WSAENOPROTOOPT (Bad protocol option)
  851. return;
  852. }
  853. break;
  854. case SocketOptionLevel.Udp:
  855. if (name == SocketOptionName.NoDelay)
  856. {
  857. error = 10042; //WSAENOPROTOOPT (Bad protocol option)
  858. }
  859. else
  860. {
  861. error = 10022; //WSAEINVAL (Invalid argument)
  862. }
  863. return;
  864. case SocketOptionLevel.Tcp:
  865. if (name != SocketOptionName.NoDelay)
  866. {
  867. error = 10022; //WSAEINVAL (Invalid argument)
  868. return;
  869. }
  870. break;
  871. }
  872. try
  873. {
  874. bool bval = false;
  875. int ival = 0;
  876. switch (name)
  877. {
  878. case SocketOptionName.DontLinger:
  879. ival = jSocket.getSoLinger();
  880. if (ival == -1)
  881. {
  882. obj_val = 1;
  883. }
  884. else
  885. {
  886. obj_val = 0;
  887. }
  888. break;
  889. case SocketOptionName.Linger:
  890. ival = jSocket.getSoLinger();
  891. if (ival == -1)
  892. {
  893. ival = 0;
  894. }
  895. LingerOption ret = new LingerOption((ival != 0), ival);
  896. obj_val = ret;
  897. break;
  898. case SocketOptionName.KeepAlive:
  899. bval = jSocket.getKeepAlive();
  900. obj_val = ((bval)?1:0);
  901. break;
  902. case SocketOptionName.NoDelay:
  903. bval = jSocket.getTcpNoDelay();
  904. obj_val = ((bval)?1:0);
  905. break;
  906. case SocketOptionName.ReceiveBuffer:
  907. if (jServerSocket != null)
  908. {
  909. ival = jServerSocket.getReceiveBufferSize();
  910. }
  911. else
  912. {
  913. ival = jSocket.getReceiveBufferSize();
  914. }
  915. obj_val = ival;
  916. break;
  917. case SocketOptionName.ReceiveTimeout:
  918. if (jServerSocket != null)
  919. {
  920. ival = jServerSocket.getSoTimeout();
  921. }
  922. else
  923. {
  924. ival = jSocket.getSoTimeout();
  925. }
  926. obj_val = ival;
  927. break;
  928. case SocketOptionName.ReuseAddress:
  929. if (jServerSocket != null)
  930. {
  931. bval = jServerSocket.getReuseAddress();
  932. }
  933. else
  934. {
  935. bval = jSocket.getReuseAddress();
  936. }
  937. obj_val = ((bval)?1:0);
  938. break;
  939. case SocketOptionName.SendBuffer:
  940. ival = jSocket.getSendBufferSize();
  941. obj_val = ival;
  942. break;
  943. case SocketOptionName.OutOfBandInline:
  944. bval = jSocket.getOOBInline();
  945. obj_val = ((bval)?1:0);
  946. break;
  947. default:
  948. error = 10022; //WSAEINVAL (Invalid argument)
  949. break;
  950. }
  951. }
  952. catch (Exception e)
  953. {
  954. error = 10022; //WSAEINVAL (Invalid argument)
  955. obj_val = null;
  956. }
  957. }
  958. public void GetSocketOption_arr_internal(SocketOptionLevel level, SocketOptionName name,
  959. ref byte[] byte_val, out int error)
  960. {
  961. error = -1;
  962. throw new NotImplementedException();
  963. }
  964. public int WSAIoctl (int ioctl_code, byte [] input, byte [] output, out int error)
  965. {
  966. error = -1;
  967. throw new NotImplementedException();
  968. }
  969. public void Shutdown_internal(SocketShutdown how, out int error)
  970. {
  971. error = 0;
  972. if (jServerSocket != null || jSocket == null || !jSocket.isConnected())
  973. {
  974. error = 10057; //WSAENOTCONN (Socket is not connected)
  975. return;
  976. }
  977. try
  978. {
  979. switch (how)
  980. {
  981. case SocketShutdown.Receive:
  982. jSocket.shutdownInput();
  983. break;
  984. case SocketShutdown.Send:
  985. jSocket.shutdownOutput();
  986. break;
  987. case SocketShutdown.Both:
  988. jSocket.shutdownInput();
  989. jSocket.shutdownOutput();
  990. break;
  991. }
  992. }
  993. catch (Exception e)
  994. {
  995. error = 10022; //WSAEINVAL (Invalid argument)
  996. #if DEBUG
  997. Console.WriteLine("Caught exception during Shutdown_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
  998. #endif
  999. }
  1000. }
  1001. private java.io.FileInputStream searchDefaultCacerts()
  1002. {
  1003. try
  1004. {
  1005. string javaHome = java.lang.System.getProperty("java.home");
  1006. if(javaHome == null)
  1007. return null;
  1008. string keyStorePath = javaHome + "/lib/security/cacerts";
  1009. //Console.WriteLine("keyStorePath = {0}", keyStorePath);
  1010. java.io.File f = new java.io.File(keyStorePath);
  1011. if(!f.exists())
  1012. return null;
  1013. return new java.io.FileInputStream(f);
  1014. }
  1015. catch(Exception e)
  1016. {
  1017. #if DEBUG
  1018. //todo log it
  1019. Console.WriteLine(e.GetType() + ":" + e.Message + "\n" + e.StackTrace);
  1020. #endif
  1021. return null;
  1022. }
  1023. }
  1024. private SSLSocketFactory getSSLSocketFactory()
  1025. {
  1026. SSLSocketFactory factory = null;
  1027. try
  1028. {
  1029. //reading the keyStore path and password from the environment properties
  1030. string keyStorePath = java.lang.System.getProperty("javax.net.ssl.keyStore");
  1031. java.io.FileInputStream keyStoreStream = null;
  1032. if (keyStorePath != null)
  1033. {
  1034. java.io.File file = new java.io.File(keyStorePath);
  1035. if(file.exists())
  1036. keyStoreStream = new java.io.FileInputStream(file);
  1037. else
  1038. keyStoreStream = searchDefaultCacerts();
  1039. }
  1040. else
  1041. keyStoreStream = searchDefaultCacerts();
  1042. string keyStorePassWord = java.lang.System.getProperty("javax.net.ssl.keyStorePassword");
  1043. if (keyStorePassWord == null)
  1044. keyStorePassWord = "changeit";
  1045. char[] passphrase = keyStorePassWord.ToCharArray();
  1046. //initiating SSLContext
  1047. SSLContext ctx = SSLContext.getInstance("TLS");
  1048. KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  1049. TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  1050. KeyStore ks = KeyStore.getInstance("JKS");
  1051. if (keyStoreStream != null)
  1052. ks.load(keyStoreStream,passphrase);
  1053. else
  1054. ks.load(null,null);
  1055. kmf.init(ks, passphrase);
  1056. tmf.init(ks);
  1057. ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  1058. factory = ctx.getSocketFactory();
  1059. }
  1060. catch (Exception e)
  1061. {
  1062. factory = null;
  1063. #if DEBUG
  1064. Console.WriteLine("Can't get SSL Socket Factory, the exception is {0}, {1}", e.GetType(), e.Message);
  1065. #endif
  1066. }
  1067. return factory;
  1068. }
  1069. public GHSocket ChangeToSSL(EndPoint remote_end)
  1070. {
  1071. if (jSocket == null)
  1072. {
  1073. throw new InvalidOperationException("The underlying socket is null");
  1074. }
  1075. if (!jSocketChannel.isBlocking())
  1076. {
  1077. throw new NotImplementedException("The SSL Socket for non-blocking mode is not supported");
  1078. }
  1079. SSLSocketFactory factory = getSSLSocketFactory();
  1080. if (factory == null)
  1081. {
  1082. throw new ApplicationException("Can't get SSL Socket Factory");
  1083. }
  1084. int err;
  1085. // The problem with local address, when I closed the socket and try to create the new one
  1086. // bounded to the given local address, I receive exception "Address already in use"
  1087. IPEndPoint localEndPoint = null;
  1088. // IPEndPoint localEndPoint = (IPEndPoint) LocalEndPoint_internal(out err);
  1089. // if (err != 0)
  1090. // localEndPoint = null;
  1091. IPEndPoint remoteEndPoint = remote_end as IPEndPoint;
  1092. if (remoteEndPoint == null)
  1093. {
  1094. remoteEndPoint = (IPEndPoint) RemoteEndPoint_internal(out err);
  1095. if (err != 0)
  1096. remoteEndPoint = null;
  1097. }
  1098. java.net.Socket sslSocket = null;
  1099. try
  1100. {
  1101. if (remoteEndPoint != null)
  1102. {
  1103. if (localEndPoint != null)
  1104. {
  1105. sslSocket = factory.createSocket(
  1106. java.net.InetAddress.getByName(remoteEndPoint.Address.ToString()),
  1107. remoteEndPoint.Port,
  1108. java.net.InetAddress.getByName(localEndPoint.Address.ToString()),
  1109. localEndPoint.Port);
  1110. }
  1111. else
  1112. {
  1113. sslSocket = factory.createSocket(
  1114. jSocket,
  1115. remoteEndPoint.Address.ToString(),
  1116. remoteEndPoint.Port,
  1117. false);
  1118. }
  1119. if (sslSocket != null)
  1120. {
  1121. String[] protocols = { "TLSv1", "SSLv3" };
  1122. ((SSLSocket)sslSocket).setUseClientMode(true);
  1123. ((SSLSocket)sslSocket).startHandshake();
  1124. }
  1125. }
  1126. else
  1127. {
  1128. sslSocket = factory.createSocket();
  1129. }
  1130. }
  1131. catch (Exception e)
  1132. {
  1133. sslSocket = null;
  1134. #if DEBUG
  1135. Console.WriteLine("Can't create SSL Socket, the exception is {0}, {1}", e.GetType(), e.Message);
  1136. #endif
  1137. }
  1138. if (sslSocket == null)
  1139. {
  1140. // throw new ApplicationException("Can't create SSL Socket");
  1141. // it is important to the Socket class to distinguish if the underlying
  1142. // handle (GHSocket) is still valid and can be used as non-SSL, or it is already
  1143. // closed by this function and can't be used any more.
  1144. return null;
  1145. }
  1146. /*
  1147. string[] arr = ((SSLSocket)sslSocket).getEnabledProtocols();
  1148. if (arr != null)
  1149. {
  1150. foreach (string s in arr)
  1151. Console.WriteLine("s:"+s);
  1152. }
  1153. string [] arr1 = ((SSLSocket)sslSocket).getEnabledCipherSuites();
  1154. if (arr1 != null)
  1155. {
  1156. foreach (string s in arr1)
  1157. Console.WriteLine("s:"+s);
  1158. }
  1159. */
  1160. return new GHStreamSocketSSL(sslSocket);
  1161. }
  1162. }
  1163. }