GHStreamSocket.jvm.cs 33 KB

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