PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/Awk.Net/ext/SocketExtension.cs

http://awkdotnet.codeplex.com
C# | 1672 lines | 905 code | 136 blank | 631 comment | 93 complexity | eb0f462f92afb24acfa99575d15e07d4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Net.Sockets;
  5. using java.util;
  6. using System.Threading;
  7. namespace org.jawk.ext
  8. {
  9. /// <summary>Enable Socket processing in Jawk.</summary>
  10. /// <remarks>
  11. /// Enable Socket processing in Jawk.
  12. /// <p>
  13. /// To use:
  14. /// <blockquote><pre>
  15. /// ## example echo server using CServerSocket (character-based)
  16. /// BEGIN {
  17. /// css = CServerSocket(7777);
  18. /// }
  19. /// $0 = SocketAcceptBlock(css,
  20. /// SocketInputBlock(handles,
  21. /// SocketCloseBlock(css, handles \
  22. /// )));
  23. /// $1 == "SocketAccept" {
  24. /// handles[SocketAccept($2)] = 1
  25. /// }
  26. /// $1 == "SocketClose" {
  27. /// SocketClose($2)
  28. /// delete handles[$2]
  29. /// }
  30. /// $1 == "SocketInput" {
  31. /// input = SocketRead($2)
  32. /// SocketWrite($2, input); ## do the echo
  33. /// }
  34. /// </pre></blockquote>
  35. /// <p>
  36. /// The extension functions are as follows:
  37. /// <ul>
  38. /// <hr>
  39. /// <li><strong><em><font size=+1>ServerSocket</font></em></strong> -<br />
  40. /// Sets up a server socket to listen for incomming
  41. /// connections. SocketRead on sockets accepted
  42. /// by ServerSocket return arbitrary-length Strings
  43. /// (bytes buffered by the input stream, converted
  44. /// to a string).<br />
  45. /// <strong>Parameters:</strong>
  46. /// <ul>
  47. /// <li>port number - required
  48. /// </ul>
  49. /// <strong>Returns:</strong>
  50. /// <ul>
  51. /// <li>A string handle to a serversocket.
  52. /// </ul><p>
  53. /// <li><strong><em><font size=+1>CServerSocket</font></em></strong> -<br />
  54. /// Sets up a server socket to listen for incomming
  55. /// connections. SocketRead on sockets accepted
  56. /// by CServerSocket return strings which terminate
  57. /// by a newline, or text in the input buffer just
  58. /// prior to the closing of the socket.<br />
  59. /// <strong>Parameters:</strong>
  60. /// <ul>
  61. /// <li>port number - required
  62. /// </ul>
  63. /// <strong>Returns:</strong>
  64. /// <ul>
  65. /// <li>A string handle to a cserversocket.
  66. /// </ul><p>
  67. /// <hr>
  68. /// <li><strong><em><font size=+1>Socket</font></em></strong> -<br />
  69. /// Create a Socket and connect it to a TCP socket
  70. /// endpoint. SocketRead on sockets returned
  71. /// by Socket return arbitrary-length Strings
  72. /// (bytes buffered by the input stream, converted
  73. /// to a string).<br />
  74. /// <strong>Parameters:</strong>
  75. /// <ul>
  76. /// <li>hostname/ip/"localhost" - required
  77. /// <li>port number - required
  78. /// </ul>
  79. /// <strong>Returns:</strong>
  80. /// <ul>
  81. /// <li>A string handle to a socket.
  82. /// </ul><p>
  83. /// <li><strong><em><font size=+1>CSocket</font></em></strong> -<br />
  84. /// Create a Socket and connect it to a TCP socket
  85. /// endpoint. SocketRead on sockets returned
  86. /// by Socket return strings which terminate
  87. /// by a newline, or text in the input buffer just
  88. /// prior to the closing of the socket.<br />
  89. /// <strong>Parameters:</strong>
  90. /// <ul>
  91. /// <li>hostname/ip/"localhost" - required
  92. /// <li>port number - required
  93. /// </ul>
  94. /// <strong>Returns:</strong>
  95. /// <ul>
  96. /// <li>A string handle to a csocket.
  97. /// </ul><p>
  98. /// <hr>
  99. /// <li><strong><em><font size=+1>SocketAcceptBlock</font></em></strong> -<br />
  100. /// Blocks until a serversocket or cserversocket
  101. /// is ready to accept a connecting socket.<br />
  102. /// <strong>Parameters:</strong>
  103. /// <ul>
  104. /// <li>Any mix of
  105. /// serversocket or cserversocket handles
  106. /// and/or associative arrays whose keys
  107. /// are serversocket or cserversocket handles.
  108. /// The last argument can optionally be
  109. /// another block call for block chaining.
  110. /// </ul>
  111. /// <strong>Returns:</strong>
  112. /// <ul>
  113. /// <li>A string of the form:
  114. /// <code><font size=+1>SocketAccept<em>OFS</em>handle</font></code>
  115. /// where handle is a serversocket or cserversocket
  116. /// handle.
  117. /// </ul><p>
  118. /// <li><strong><em><font size=+1>SocketInputBlock</font></em></strong> -<br />
  119. /// Blocks until a socket or csocket is ready
  120. /// to accept input (via SocketRead).<br />
  121. /// <strong>Parameters:</strong>
  122. /// <ul>
  123. /// <li>Any mix of
  124. /// socket or csocket handles and/or associative
  125. /// arrays whose keys are socket or csocket handles.
  126. /// The last argument can optionally be
  127. /// another block call for block chaining.
  128. /// </ul>
  129. /// <strong>Returns:</strong>
  130. /// <ul>
  131. /// <li>A string of the form: <code><font size=+1>SocketInput<em>OFS</em>handle</font></code>
  132. /// where handle is a socket or csocket
  133. /// handle.
  134. /// </ul><p>
  135. /// <li><strong><em><font size=+1>SocketCloseBlock</font></em></strong> -<br />
  136. /// Blocks until a serversocket, cserversocket,
  137. /// socket, or csocket has been closed on the
  138. /// remote end.<br />
  139. /// <strong>Parameters:</strong>
  140. /// <ul>
  141. /// <li>Any mix of
  142. /// serversocket, cserversocket, socket, or csocket
  143. /// handles and/or associative
  144. /// arrays whose keys are serversocket, cserversocket,
  145. /// socket, or csocket handles.
  146. /// The last argument can optionally be
  147. /// another block call for block chaining.
  148. /// </ul>
  149. /// <strong>Returns:</strong>
  150. /// <ul>
  151. /// <li>A string of the form: <code><font size=+1>SocketClose<em>OFS</em>handle</font></code>
  152. /// where handle is a serversocket, cserversocket, socket,
  153. /// or csocket handle.
  154. /// </ul><p>
  155. /// <hr>
  156. /// <li><strong><em><font size=+1>SocketAccept</font></em></strong> -<br />
  157. /// Accepts a socket from a serversocket or
  158. /// a cserversocket. The operation will
  159. /// block if there is no socket to accept.<br />
  160. /// <strong>Parameters:</strong>
  161. /// <ul>
  162. /// <li>serversocket-or-cserversocket handle - required
  163. /// </ul>
  164. /// <strong>Returns:</strong>
  165. /// <ul>
  166. /// <li>A string handle to a socket or csocket.
  167. /// </ul><p>
  168. /// <hr>
  169. /// <li><strong><em><font size=+1>SocketRead</font></em></strong> -<br />
  170. /// Reads input from the input stream of a socket
  171. /// or a csocket. For a socket, the input length
  172. /// is arbitrary. For a csocket, the input
  173. /// length is bounded by a newline or upon
  174. /// termination of the socket.
  175. /// The operation will block if there is no input
  176. /// on the socket.<br />
  177. /// <strong>Parameters:</strong>
  178. /// <ul>
  179. /// <li>socket-or-csocket handle - required
  180. /// </ul>
  181. /// <strong>Returns:</strong>
  182. /// <ul>
  183. /// <li>A string containing the input on the socket.
  184. /// </ul><p>
  185. /// <li><strong><em><font size=+1>SocketWrite</font></em></strong> -<br />
  186. /// Writes data to the socket or csocket.
  187. /// For a socket, the string is converted
  188. /// to bytes (via java.lang.String.getBytes()),
  189. /// and the bytes are sent to the socket's
  190. /// output stream.
  191. /// For a csocket, println() is called on the
  192. /// underlying socket's PrintStream.<br />
  193. /// <strong>Parameters:</strong>
  194. /// <ul>
  195. /// <li>socket-or-csocket handle - required
  196. /// <li>msg - required - The string to write to
  197. /// the socket. For a csocket, a newline
  198. /// is added to it (via the
  199. /// java.io.PrintStream.println() method).
  200. /// </ul>
  201. /// <strong>Returns:</strong>
  202. /// <ul>
  203. /// <li>1 upon a successful write, 0 otherwise
  204. /// </ul><p>
  205. /// <li><strong><em><font size=+1>SocketFlush</font></em></strong> -<br />
  206. /// Flushes the output stream of a socket or csocket.<br />
  207. /// <strong>Parameters:</strong>
  208. /// <ul>
  209. /// <li>socket-or-csocket handle - required
  210. /// </ul>
  211. /// <strong>Returns:</strong>
  212. /// <ul>
  213. /// <li>1 upon a successful flush, 0 otherwise
  214. /// </ul><p>
  215. /// <hr>
  216. /// <li><strong><em><font size=+1>SocketClose</font></em></strong> -<br />
  217. /// Closes the socket/csocket on the local end,
  218. /// or a serversocket/cserversocket.
  219. /// Can be called in response to a SocketCloseBlock
  220. /// event, or to force a socket/csocket connection to
  221. /// terminate.<br />
  222. /// <strong>Parameters:</strong>
  223. /// <ul>
  224. /// <li>socket/csocket/serversocket/cserversocket handle - required
  225. /// </ul>
  226. /// <strong>Returns:</strong>
  227. /// <ul>
  228. /// <li>1 upon successful close, 0 otherwise
  229. /// </ul><p>
  230. /// <hr>
  231. /// </ul>
  232. /// </remarks>
  233. public class SocketExtension : org.jawk.ext.AbstractExtension
  234. {
  235. /// <summary>
  236. /// Either threaded or non-threaded (nio-style) socket
  237. /// handling.
  238. /// </summary>
  239. /// <remarks>
  240. /// Either threaded or non-threaded (nio-style) socket
  241. /// handling. The threaded implementation is provided
  242. /// upon initial release. Non-threaded
  243. /// functionality will be available in a subsequent
  244. /// release.
  245. /// </remarks>
  246. private org.jawk.ext.IIO_Style impl_delegate;
  247. public sealed override void Init(org.jawk.jrt.IVariableManager vm, org.jawk.jrt.JRT
  248. jrt)
  249. {
  250. base.Init(vm, jrt);
  251. impl_delegate = new org.jawk.ext.Threaded_IO_Style(vm);
  252. }
  253. public sealed override string GetExtensionName()
  254. {
  255. return "Socket Support";
  256. }
  257. public sealed override string[] ExtensionKeywords()
  258. {
  259. return new string[] { "ServerSocket", "CServerSocket", "Socket", "CSocket", "SocketAcceptBlock"
  260. , "SocketInputBlock", "SocketCloseBlock", "SocketAccept", "SocketRead", "SocketWrite"
  261. , "SocketFlush", "SocketClose" };
  262. }
  263. // i.e., ss = ServerSocket(8080) or ss = ServerSocket("ip", 8080)
  264. // i.e., css = CServerSocket(8080) or css = CServerSocket("ip", 8080)
  265. // i.e., s = Socket("localhost", 8080)
  266. // i.e., cs = CSocket("localhost", 8080)
  267. // i.e., $0 = SocketAcceptBlock(ss, css,
  268. // i.e., SocketInputBlock(s, cs,
  269. // i.e., SocketCloseBlock(ss,css, s,cs)));
  270. // i.e., cs = SocketAccept(css)
  271. // i.e., buf = SocketRead(s) or line = SocketRead(cs)
  272. // i.e., SocketWrite(s, "hi there\n") or SocketWrite(cs, "hi there")
  273. // i.e., SocketFlush(s) or SocketFlush(cs)
  274. // i.e., SocketClose(ss) or SocketClose(cs)
  275. public sealed override object Invoke(string method_name, object[] args)
  276. {
  277. // large if-then-else block to decide which extension to invoke
  278. if (false)
  279. {
  280. throw new System.Exception("Should never reach.");
  281. }
  282. else
  283. {
  284. if (method_name.Equals("ServerSocket"))
  285. {
  286. if (args.Length == 1)
  287. {
  288. return impl_delegate.Serversocket(null, (int)org.jawk.jrt.JRT.ToDouble(args[0]));
  289. }
  290. else
  291. {
  292. if (args.Length == 2)
  293. {
  294. return impl_delegate.Serversocket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble
  295. (args[1]));
  296. }
  297. else
  298. {
  299. throw new org.jawk.jrt.IllegalAwkArgumentException("Expecting 1 or 2 arguments, not "
  300. + args.Length);
  301. }
  302. }
  303. }
  304. else
  305. {
  306. if (method_name.Equals("CServerSocket"))
  307. {
  308. if (args.Length == 1)
  309. {
  310. return impl_delegate.Cserversocket(null, (int)org.jawk.jrt.JRT.ToDouble(args[0]));
  311. }
  312. else
  313. {
  314. if (args.Length == 2)
  315. {
  316. return impl_delegate.Cserversocket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble
  317. (args[1]));
  318. }
  319. else
  320. {
  321. throw new org.jawk.jrt.IllegalAwkArgumentException("Expecting 1 or 2 arguments, not "
  322. + args.Length);
  323. }
  324. }
  325. }
  326. else
  327. {
  328. if (method_name.Equals("Socket"))
  329. {
  330. CheckNumArgs(args, 2);
  331. return impl_delegate.Socket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble(
  332. args[1]));
  333. }
  334. else
  335. {
  336. if (method_name.Equals("CSocket"))
  337. {
  338. CheckNumArgs(args, 2);
  339. return impl_delegate.Csocket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble
  340. (args[1]));
  341. }
  342. else
  343. {
  344. if (method_name.Equals("SocketAcceptBlock"))
  345. {
  346. return impl_delegate.Socketacceptblock(args);
  347. }
  348. else
  349. {
  350. if (method_name.Equals("SocketInputBlock"))
  351. {
  352. return impl_delegate.Socketinputblock(args);
  353. }
  354. else
  355. {
  356. if (method_name.Equals("SocketCloseBlock"))
  357. {
  358. return impl_delegate.Socketcloseblock(args);
  359. }
  360. else
  361. {
  362. if (method_name.Equals("SocketAccept"))
  363. {
  364. CheckNumArgs(args, 1);
  365. return impl_delegate.Socketaccept(ToAwkString(args[0]));
  366. }
  367. else
  368. {
  369. if (method_name.Equals("SocketRead"))
  370. {
  371. CheckNumArgs(args, 1);
  372. return impl_delegate.Socketread(ToAwkString(args[0]));
  373. }
  374. else
  375. {
  376. if (method_name.Equals("SocketWrite"))
  377. {
  378. CheckNumArgs(args, 2);
  379. return impl_delegate.Socketwrite(ToAwkString(args[0]), ToAwkString(args[1]));
  380. }
  381. else
  382. {
  383. if (method_name.Equals("SocketFlush"))
  384. {
  385. CheckNumArgs(args, 1);
  386. return impl_delegate.Socketflush(ToAwkString(args[0]));
  387. }
  388. else
  389. {
  390. if (method_name.Equals("SocketClose"))
  391. {
  392. CheckNumArgs(args, 1);
  393. return impl_delegate.Socketclose(ToAwkString(args[0]));
  394. }
  395. else
  396. {
  397. throw new org.jawk.NotImplementedError(method_name);
  398. }
  399. }
  400. }
  401. }
  402. }
  403. }
  404. }
  405. }
  406. }
  407. }
  408. }
  409. }
  410. }
  411. }
  412. }
  413. /// <summary>
  414. /// Interface to the socket handling delegate which
  415. /// does all the work.
  416. /// </summary>
  417. /// <remarks>
  418. /// Interface to the socket handling delegate which
  419. /// does all the work. The SocketExtension manager
  420. /// class delegates all concrete socket IO
  421. /// processing to an instance of this interface.
  422. /// </remarks>
  423. internal interface IIO_Style
  424. {
  425. // public class SocketExtension {AbstractExtension}
  426. //
  427. // INTERFACE TO DELEGATE
  428. //
  429. /// <summary>
  430. /// Sets up a server socket to listen for incomming
  431. /// connections.
  432. /// </summary>
  433. /// <remarks>
  434. /// Sets up a server socket to listen for incomming
  435. /// connections. SocketRead on sockets accepted
  436. /// by ServerSocket return arbitrary-length Strings
  437. /// (bytes buffered by the input stream, converted
  438. /// to a string).
  439. /// </remarks>
  440. /// <param name="hostname">
  441. /// The hostname or IP address as a string.
  442. /// hostname can be null.
  443. /// </param>
  444. /// <param name="port">The port number.</param>
  445. /// <returns>A handle to a newly created serversocket.</returns>
  446. string Serversocket(string hostname, int port);
  447. /// <summary>
  448. /// Sets up a server socket to listen for incomming
  449. /// connections.
  450. /// </summary>
  451. /// <remarks>
  452. /// Sets up a server socket to listen for incomming
  453. /// connections. SocketRead on sockets accepted
  454. /// by CServerSocket return strings which terminate
  455. /// by a newline, or text in the input buffer just
  456. /// prior to the closing of the socket.
  457. /// </remarks>
  458. /// <param name="hostname">
  459. /// The hostname or IP address as a string.
  460. /// hostname can be null.
  461. /// </param>
  462. /// <param name="port">The port number.</param>
  463. /// <returns>A handle to a newly created cserversocket.</returns>
  464. string Cserversocket(string hostname, int port);
  465. /// <summary>
  466. /// Create a Socket and connect it to a TCP socket
  467. /// endpoint.
  468. /// </summary>
  469. /// <remarks>
  470. /// Create a Socket and connect it to a TCP socket
  471. /// endpoint. SocketRead on sockets returned
  472. /// by Socket return arbitrary-length Strings
  473. /// (bytes buffered by the input stream, converted
  474. /// to a string).
  475. /// </remarks>
  476. /// <param name="hostname">
  477. /// The hostname or IP address as a string.
  478. /// hostname can be null.
  479. /// </param>
  480. /// <param name="port">The port number.</param>
  481. /// <returns>A handle to a newly created socket.</returns>
  482. string Socket(string hostname, int port);
  483. /// <summary>
  484. /// Create a Socket and connect it to a TCP socket
  485. /// endpoint.
  486. /// </summary>
  487. /// <remarks>
  488. /// Create a Socket and connect it to a TCP socket
  489. /// endpoint. SocketRead on sockets returned
  490. /// by Socket return strings which terminate
  491. /// by a newline, or text in the input buffer just
  492. /// prior to the closing of the socket.
  493. /// </remarks>
  494. /// <param name="hostname">
  495. /// The hostname or IP address as a string.
  496. /// hostname can be null.
  497. /// </param>
  498. /// <param name="port">The port number.</param>
  499. /// <returns>A handle to a newly created csocket.</returns>
  500. string Csocket(string hostname, int port);
  501. /// <summary>
  502. /// Blocks until a serversocket or cserversocket
  503. /// is ready to accept a connecting socket.
  504. /// </summary>
  505. /// <remarks>
  506. /// Blocks until a serversocket or cserversocket
  507. /// is ready to accept a connecting socket.
  508. /// </remarks>
  509. /// <param name="args">
  510. /// An array of
  511. /// serversocket or cserversocket handles
  512. /// and/or associative arrays whose keys
  513. /// are serversocket or cserversocket handles.
  514. /// The last argument can optionally be
  515. /// another block call for block chaining.
  516. /// </param>
  517. /// <returns>
  518. /// A block object conditioned
  519. /// to block on the acceptance of
  520. /// socket connections from any of
  521. /// the serversockets / cserversockets
  522. /// referred to by the handles passed
  523. /// in to the object array.
  524. /// </returns>
  525. org.jawk.jrt.BlockObject Socketacceptblock(object[] args);
  526. /// <summary>
  527. /// Blocks until a socket or csocket is ready
  528. /// to accept input (via SocketRead).
  529. /// </summary>
  530. /// <remarks>
  531. /// Blocks until a socket or csocket is ready
  532. /// to accept input (via SocketRead).
  533. /// </remarks>
  534. /// <param name="args">
  535. /// An array of
  536. /// socket or csocket handles and/or associative
  537. /// arrays whose keys are socket or csocket handles.
  538. /// The last argument can optionally be
  539. /// another block call for block chaining.
  540. /// </param>
  541. /// <returns>
  542. /// A block object conditioned
  543. /// to block on the availability of
  544. /// input from any of the sockets / csockets
  545. /// referred to by the handles passed
  546. /// in to the object array.
  547. /// </returns>
  548. org.jawk.jrt.BlockObject Socketinputblock(object[] args);
  549. /// <summary>
  550. /// Blocks until a serversocket, cserversocket,
  551. /// socket, or csocket has been closed on the
  552. /// remote end.
  553. /// </summary>
  554. /// <remarks>
  555. /// Blocks until a serversocket, cserversocket,
  556. /// socket, or csocket has been closed on the
  557. /// remote end.
  558. /// </remarks>
  559. /// <param name="args">
  560. /// An array of
  561. /// serversocket, cserversocket, socket, or csocket
  562. /// handles and/or associative
  563. /// arrays whose keys are serversocket, cserversocket,
  564. /// socket, or csocket handles.
  565. /// The last argument can optionally be
  566. /// another block call for block chaining.
  567. /// </param>
  568. /// <returns>
  569. /// A block object conditioned
  570. /// to block until any of the sockets /
  571. /// csockets / serversockets / cserversockets
  572. /// in to the object array have closed.
  573. /// </returns>
  574. org.jawk.jrt.BlockObject Socketcloseblock(object[] args);
  575. /// <summary>
  576. /// Accepts a socket from a serversocket or
  577. /// a cserversocket.
  578. /// </summary>
  579. /// <remarks>
  580. /// Accepts a socket from a serversocket or
  581. /// a cserversocket. The operation will
  582. /// block if there is no socket to accept.
  583. /// </remarks>
  584. /// <param name="handle">
  585. /// A string handle to a serversocket
  586. /// or cserversocket.
  587. /// </param>
  588. /// <returns>
  589. /// A handle to a socket or csocket that
  590. /// has connected to the serversocket / cserversocket
  591. /// referred to by the handle argument.
  592. /// </returns>
  593. string Socketaccept(string handle);
  594. /// <summary>
  595. /// Reads input from the input stream of a socket
  596. /// or a csocket.
  597. /// </summary>
  598. /// <remarks>
  599. /// Reads input from the input stream of a socket
  600. /// or a csocket. For a socket, the input length
  601. /// is arbitrary. For a csocket, the input
  602. /// length is bounded by a newline or upon
  603. /// termination of the socket.
  604. /// The operation will block if there is no input
  605. /// on the socket.
  606. /// </remarks>
  607. /// <param name="handle">
  608. /// A string handle to a socket
  609. /// or csocket.
  610. /// </param>
  611. /// <returns>
  612. /// A block of byte input from a socket
  613. /// (converted to a string), or a line of
  614. /// string input from a csocket bounded by
  615. /// a newline in the stream or upon the closing
  616. /// of the csocket.
  617. /// </returns>
  618. string Socketread(string handle);
  619. /// <summary>Writes data to the socket or csocket.</summary>
  620. /// <remarks>
  621. /// Writes data to the socket or csocket.
  622. /// For a socket, the string is converted
  623. /// to bytes (via java.lang.String.getBytes()),
  624. /// and the bytes are sent to the underlying
  625. /// socket's output stream.
  626. /// For a csocket, println() is called on the
  627. /// underlying socket's PrintStream.
  628. /// </remarks>
  629. /// <param name="handle">
  630. /// A string handle to a socket
  631. /// or csocket.
  632. /// </param>
  633. /// <param name="buf">
  634. /// The string containing the
  635. /// bytes to write. SocketWrite writes
  636. /// the contents of the resulting buf.getBytes()
  637. /// call to the socket.
  638. /// </param>
  639. /// <param name="handle">
  640. /// A String handle to a socket
  641. /// or csocket.
  642. /// </param>
  643. /// <param name="buf">
  644. /// A string containing a block of
  645. /// bytes to write to a socket (via
  646. /// java.lang.String.getBytes()) if handle
  647. /// refers to a socket. If handle refers
  648. /// to a csocket, the line of text to write
  649. /// via PrintStream.println(String).
  650. /// </param>
  651. /// <returns>
  652. /// 1 upon a successful write,
  653. /// 0 upon an IO exception/error.
  654. /// </returns>
  655. int Socketwrite(string handle, string buf);
  656. /// <summary>Flushes the output stream of a socket or csocket.</summary>
  657. /// <remarks>Flushes the output stream of a socket or csocket.</remarks>
  658. /// <param name="handle">
  659. /// A string handle to a socket
  660. /// or csocket.
  661. /// </param>
  662. /// <returns>
  663. /// 1 upon a successful flush operation,
  664. /// 0 upon an IO exception/error.
  665. /// </returns>
  666. int Socketflush(string handle);
  667. /// <summary>
  668. /// Closes the socket/csocket on the local end,
  669. /// or a serversocket/cserversocket.
  670. /// </summary>
  671. /// <remarks>
  672. /// Closes the socket/csocket on the local end,
  673. /// or a serversocket/cserversocket.
  674. /// Can be called in response to a SocketCloseBlock
  675. /// event, or to force a socket/csocket connection to
  676. /// terminate.
  677. /// </remarks>
  678. /// <param name="handle">
  679. /// A string handle to a socket,
  680. /// csocket, serversocket, or cserversocket.
  681. /// </param>
  682. /// <returns>
  683. /// 1 upon a successful close operation,
  684. /// 0 upon an IO exception/error.
  685. /// </returns>
  686. int Socketclose(string handle);
  687. }
  688. /// <summary>A view of two maps as one map.</summary>
  689. /// <remarks>A view of two maps as one map.</remarks>
  690. internal class MapUnion<K, V> : Dictionary<K, V>
  691. {
  692. private System.Collections.Generic.IDictionary<K, V> m1;
  693. private System.Collections.Generic.IDictionary<K, V> m2;
  694. internal MapUnion(System.Collections.Generic.IDictionary<K, V> m1, System.Collections.Generic.IDictionary
  695. <K, V> m2)
  696. {
  697. this.m1 = m1;
  698. this.m2 = m2;
  699. }
  700. public System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair <K, V>> EntrySet()
  701. {
  702. // build the entry set
  703. System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<K, V>> entry_set = new List<KeyValuePair<K, V>>();
  704. System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<K, V>> s1 = m1;
  705. System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<K, V>> s2 = m2;
  706. foreach (System.Collections.Generic.KeyValuePair<K, V> me in s1)
  707. {
  708. entry_set.Add(me);
  709. }
  710. foreach (System.Collections.Generic.KeyValuePair<K, V> me in s2)
  711. {
  712. entry_set.Add(me);
  713. }
  714. return entry_set;
  715. }
  716. }
  717. internal class Threaded_IO_Style : org.jawk.ext.IIO_Style
  718. {
  719. private string last_err = null;
  720. /// <summary>
  721. /// Map of "Socket"/"CSocket" handles to
  722. /// the objects which perform the actual
  723. /// read and block operations.
  724. /// </summary>
  725. /// <remarks>
  726. /// Map of "Socket"/"CSocket" handles to
  727. /// the objects which perform the actual
  728. /// read and block operations.
  729. /// <p>
  730. /// <strong>Note:</strong>
  731. /// "consumers" originally was of type
  732. /// Map<String,Consumer>, but changed to ...,Closeable.
  733. /// (Likewise, "accepters" was originally ...,Accepter,
  734. /// but then changed to ...,Closeable.)
  735. /// Why? Because MapUnion could not infer that "Consumer"
  736. /// nor "Accepter" were extensions of "Blockable".
  737. /// MapUnion originally accepted 3 generic parameters:
  738. /// K, V1 extends Blockable, and V2 extends Blockable.
  739. /// And, close_blocker's BulkBlockObject Map parameter was:
  740. /// new MapUnion<String,Accepter,Consumer>(accepters,consumers).
  741. /// But, it wouldn't compile.
  742. /// The resulting warning/error messages stated that
  743. /// "capture #XXX of ? extends Blockable" does not
  744. /// match "? extends Blockable". I believe the error
  745. /// results from Blockable being compiled against
  746. /// Java 1.5.x and extensions being developed against
  747. /// Java 1.6.x, and that they don't grok one another
  748. /// in this scenario.
  749. /// We, then, decided to assign its lowest common
  750. /// subclass, "Closeable", and typecast when we need
  751. /// specific "Accepter" and "Consumer" functionality.
  752. /// This resolved the issue while losing some
  753. /// compile-time type safety.
  754. /// </remarks>
  755. private readonly System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable> consumers = new System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable>();
  756. /// <summary>
  757. /// Map of "ServerSocket"/"CServerSocket" handles
  758. /// to the objects which perform the actual
  759. /// socket accept operation.
  760. /// </summary>
  761. /// <remarks>
  762. /// Map of "ServerSocket"/"CServerSocket" handles
  763. /// to the objects which perform the actual
  764. /// socket accept operation.
  765. /// <p>
  766. /// <strong>Note:</strong>
  767. /// See lengthy diatribe above for "consumers".
  768. /// The same applies for "accepters"'s generic
  769. /// type choice for values of the Map.
  770. /// </remarks>
  771. private readonly System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable> accepters = new System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable>();
  772. private readonly org.jawk.jrt.IVariableManager vm;
  773. private readonly org.jawk.jrt.BulkBlockObject accept_blocker;
  774. private readonly org.jawk.jrt.BulkBlockObject input_blocker;
  775. private readonly org.jawk.jrt.BulkBlockObject close_blocker;
  776. internal Threaded_IO_Style(org.jawk.jrt.IVariableManager vm)
  777. {
  778. accept_handle_validator = new _IBlockHandleValidator_759(this);
  779. input_handle_validator = new _IBlockHandleValidator_772(this);
  780. close_handle_validator = new _IBlockHandleValidator_785(this);
  781. //assert vm != null;
  782. this.vm = vm;
  783. accept_blocker = new org.jawk.jrt.BulkBlockObject("SocketAccept", accepters, vm);
  784. input_blocker = new org.jawk.jrt.BulkBlockObject("SocketInput", consumers, vm);
  785. close_blocker = new org.jawk.jrt.BulkBlockObject("SocketClose", new org.jawk.ext.MapUnion<string, org.jawk.jrt.ICloseable>(accepters, consumers), vm);
  786. }
  787. public string Serversocket(string hostname, int port)
  788. {
  789. try
  790. {
  791. TcpListener ss = null;
  792. if (hostname == null)
  793. {
  794. ss = new TcpListener(System.Net.IPAddress.Any, port);
  795. }
  796. else
  797. {
  798. // 0 = default backlog
  799. System.Net.IPAddress[] tab = System.Net.Dns.GetHostAddresses(hostname);
  800. System.Net.IPAddress address = System.Net.IPAddress.Any;
  801. if(tab!=null && tab.Length>0)
  802. {
  803. address = tab[0];
  804. }
  805. ss = new TcpListener(address, port);
  806. }
  807. string handle = CreateHandle(ss);
  808. //ssockets.put(handle, ss);
  809. org.jawk.ext.Threaded_IO_Style.Accepter accepter_thread = new org.jawk.ext.Threaded_IO_Style.Accepter
  810. (this, handle, ss);
  811. accepters[handle] = accepter_thread;
  812. accepter_thread.Start();
  813. return handle;
  814. }
  815. catch (System.IO.IOException ioe)
  816. {
  817. Console.Error.WriteLine(ioe.ToString());
  818. last_err = ioe.ToString();
  819. return string.Empty;
  820. }
  821. }
  822. public string Cserversocket(string hostname, int port)
  823. {
  824. try
  825. {
  826. TcpListener ss;
  827. if (hostname == null)
  828. {
  829. ss = new TcpListener(System.Net.IPAddress.Any,port);
  830. }
  831. else
  832. {
  833. // 0 = default backlog
  834. System.Net.IPAddress[] tab = System.Net.Dns.GetHostAddresses(hostname);
  835. System.Net.IPAddress address = System.Net.IPAddress.Any;
  836. if (tab != null && tab.Length > 0)
  837. {
  838. address = tab[0];
  839. }
  840. ss = new TcpListener(address, port);
  841. }
  842. string handle = CreateHandle(ss);
  843. //ssockets.put(handle, ss);
  844. org.jawk.ext.Threaded_IO_Style.Accepter accepter_thread = new org.jawk.ext.Threaded_IO_Style.CAccepter
  845. (this, handle, ss);
  846. accepters[handle] = accepter_thread;
  847. accepter_thread.Start();
  848. return handle;
  849. }
  850. catch (System.IO.IOException ioe)
  851. {
  852. Console.Error.WriteLine(ioe.ToString());
  853. last_err = ioe.ToString();
  854. return string.Empty;
  855. }
  856. }
  857. public string Socket(string hostname, int port)
  858. {
  859. // create the socket
  860. try
  861. {
  862. TcpClient socket = new TcpClient(hostname, port);
  863. string handle = CreateHandle(socket);
  864. //sockets.put(handle, socket);
  865. // start the reader
  866. org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.ByteConsumer
  867. (this, handle, socket);
  868. consumers[handle] = reader_thread;
  869. reader_thread.Start();
  870. return handle;
  871. }
  872. catch (System.IO.IOException ioe)
  873. {
  874. Console.Error.WriteLine(ioe.ToString());
  875. last_err = ioe.ToString();
  876. return string.Empty;
  877. }
  878. }
  879. public string Csocket(string hostname, int port)
  880. {
  881. try
  882. {
  883. // create the socket
  884. TcpClient socket = new TcpClient(hostname, port);
  885. string handle = CreateHandle(socket);
  886. //sockets.put(handle, socket);
  887. // start the reader
  888. org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.CharacterConsumer
  889. (this, handle, socket);
  890. consumers[handle] = reader_thread;
  891. reader_thread.Start();
  892. return handle;
  893. }
  894. catch (System.IO.IOException ioe)
  895. {
  896. Console.Error.WriteLine(ioe.ToString());
  897. last_err = ioe.ToString();
  898. return string.Empty;
  899. }
  900. }
  901. private int socket_idx = 0;
  902. private int ssocket_idx = 0;
  903. private string CreateHandle(TcpListener socket)
  904. {
  905. System.Net.IPEndPoint endPoint = socket.LocalEndpoint as System.Net.IPEndPoint;
  906. if (endPoint != null)
  907. {
  908. return "Socket:" + endPoint.Address.ToString() + ":" + endPoint.Port + "/" + (++ssocket_idx);
  909. }
  910. else
  911. {
  912. return "Socket:" + socket.LocalEndpoint.Serialize().ToString() + "/" + (++ssocket_idx);
  913. }
  914. }
  915. private string CreateHandle(TcpClient socket)
  916. {
  917. System.Net.IPEndPoint endPoint = socket.Client.LocalEndPoint as System.Net.IPEndPoint;
  918. if (endPoint != null)
  919. {
  920. return "Socket:" + endPoint.Address.ToString() + ":" + endPoint.Port + "/" + (++socket_idx);
  921. }
  922. else
  923. {
  924. return "Socket:" + socket.Client.LocalEndPoint.Serialize().ToString() + "/" + (++socket_idx);
  925. }
  926. }
  927. private sealed class _IBlockHandleValidator_759 : org.jawk.jrt.IBlockHandleValidator
  928. {
  929. public _IBlockHandleValidator_759(Threaded_IO_Style _enclosing)
  930. {
  931. this._enclosing = _enclosing;
  932. }
  933. //////////////////////////////////////////////////////////////////
  934. //////////////////////////////////////////////////////////////////
  935. //////////////////////////////////////////////////////////////////
  936. // to satisfy the BlockHandleValidator interface
  937. public string IsBlockHandleValid(string handle)
  938. {
  939. org.jawk.jrt.ICloseable closeable = null;
  940. if(this._enclosing.accepters.ContainsKey(handle))
  941. {
  942. closeable = this._enclosing.accepters[handle];
  943. }
  944. if (closeable == null)
  945. {
  946. return "Invalid ServerSocket handle.";
  947. }
  948. if (closeable.IsClosed())
  949. {
  950. return "ServerSocket is closed.";
  951. }
  952. else
  953. {
  954. return null;
  955. }
  956. }
  957. private readonly Threaded_IO_Style _enclosing;
  958. }
  959. private readonly org.jawk.jrt.IBlockHandleValidator accept_handle_validator;
  960. private sealed class _IBlockHandleValidator_772 : org.jawk.jrt.IBlockHandleValidator
  961. {
  962. public _IBlockHandleValidator_772(Threaded_IO_Style _enclosing)
  963. {
  964. this._enclosing = _enclosing;
  965. }
  966. // valid
  967. // to satisfy the BlockHandleValidator interface
  968. public string IsBlockHandleValid(string handle)
  969. {
  970. org.jawk.jrt.ICloseable closeable = null;
  971. if (this._enclosing.consumers.ContainsKey(handle))
  972. {
  973. closeable = this._enclosing.consumers[handle];
  974. }
  975. if (closeable == null)
  976. {
  977. return "Invalid socket handle. (Could have already been closed?)";
  978. }
  979. if (closeable.IsClosed())
  980. {
  981. return "Socket is closed.";
  982. }
  983. else
  984. {
  985. return null;
  986. }
  987. }
  988. private readonly Threaded_IO_Style _enclosing;
  989. }
  990. private readonly org.jawk.jrt.IBlockHandleValidator input_handle_validator;
  991. private sealed class _IBlockHandleValidator_785 : org.jawk.jrt.IBlockHandleValidator
  992. {
  993. public _IBlockHandleValidator_785(Threaded_IO_Style _enclosing)
  994. {
  995. this._enclosing = _enclosing;
  996. }
  997. // valid
  998. // to satisfy the BlockHandleValidator interface
  999. public string IsBlockHandleValid(string handle)
  1000. {
  1001. org.jawk.jrt.ICloseable closeable = null;
  1002. if(this._enclosing.accepters.ContainsKey(handle))
  1003. {
  1004. closeable = this._enclosing.accepters[handle];
  1005. }
  1006. if (closeable == null && this._enclosing.consumers.ContainsKey(handle))
  1007. {
  1008. closeable = this._enclosing.consumers[handle];
  1009. }
  1010. if (closeable == null)
  1011. {
  1012. return "Invalid socket handle. (Could have already been closed?)";
  1013. }
  1014. if (closeable.IsClosed())
  1015. {
  1016. return "Socket is already closed.";
  1017. }
  1018. else
  1019. {
  1020. return null;
  1021. }
  1022. }
  1023. private readonly Threaded_IO_Style _enclosing;
  1024. }
  1025. private readonly org.jawk.jrt.IBlockHandleValidator close_handle_validator;
  1026. // valid
  1027. public org.jawk.jrt.BlockObject Socketacceptblock(object[] args)
  1028. {
  1029. return accept_blocker.PopulateHandleSet(args, vm, accept_handle_validator);
  1030. }
  1031. public org.jawk.jrt.BlockObject Socketinputblock(object[] args)
  1032. {
  1033. return input_blocker.PopulateHandleSet(args, vm, input_handle_validator);
  1034. }
  1035. public org.jawk.jrt.BlockObject Socketcloseblock(object[] args)
  1036. {
  1037. return close_blocker.PopulateHandleSet(args, vm, close_handle_validator);
  1038. }
  1039. public string Socketaccept(string handle)
  1040. {
  1041. try
  1042. {
  1043. org.jawk.ext.Threaded_IO_Style.Accepter accepter = null;
  1044. if(accepters.ContainsKey(handle))
  1045. {
  1046. accepter = (org.jawk.ext.Threaded_IO_Style.Accepter)accepters[handle];
  1047. }
  1048. if (accepter == null)
  1049. {
  1050. throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid server socket handle : "
  1051. + handle);
  1052. }
  1053. // it's "as if" accept_blocker is querying whether to block or not
  1054. if (accepter.WillBlock(accept_blocker) && accepter.IsClosed())
  1055. {
  1056. last_err = "Server closed.";
  1057. return string.Empty;
  1058. }
  1059. return accepter.GetSocket();
  1060. }
  1061. catch (System.IO.IOException ioe)
  1062. {
  1063. Console.Error.WriteLine(ioe.ToString());
  1064. throw new System.Exception("Error occurred during creation of accepted socket.");
  1065. }
  1066. catch (System.Exception ie)
  1067. {
  1068. Console.Error.WriteLine(ie.ToString());
  1069. throw new System.Exception("A queue operation cannot be interrupted.");
  1070. }
  1071. }
  1072. public string Socketread(string handle)
  1073. {
  1074. try
  1075. {
  1076. org.jawk.jrt.IConsumer consumer = null;
  1077. if(consumers.ContainsKey(handle))
  1078. {
  1079. consumer = (org.jawk.jrt.IConsumer)consumers[handle];
  1080. }
  1081. if (consumer == null)
  1082. {
  1083. throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid socket handle : " + handle
  1084. );
  1085. }
  1086. // it's "as if" input_blocker is querying whether to block or not
  1087. if (consumer.WillBlock(input_blocker) && consumer.IsClosed())
  1088. {
  1089. last_err = "No more input.";
  1090. return string.Empty;
  1091. }
  1092. return consumer.GetInput();
  1093. }
  1094. catch (System.Exception ie)
  1095. {
  1096. Console.Error.WriteLine(ie);
  1097. throw new System.Exception("A queue operation cannot be interrupted.");
  1098. }
  1099. }
  1100. public int Socketwrite(string handle, string buf)
  1101. {
  1102. org.jawk.jrt.IConsumer consumer = null;
  1103. if(consumers.ContainsKey(handle))
  1104. {
  1105. consumer = (org.jawk.jrt.IConsumer)consumers[handle];
  1106. }
  1107. if (consumer == null)
  1108. {
  1109. throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid socket handle : " + handle
  1110. );
  1111. }
  1112. return consumer.Write(buf);
  1113. }
  1114. public int Socketflush(string handle)
  1115. {
  1116. org.jawk.jrt.IConsumer consumer = null;
  1117. if(consumers.ContainsKey(handle))
  1118. {
  1119. consumer = (org.jawk.jrt.IConsumer)consumers[handle];
  1120. }
  1121. if (consumer == null)
  1122. {
  1123. throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid socket handle : " + handle
  1124. );
  1125. }
  1126. return consumer.Flush();
  1127. }
  1128. public int Socketclose(string handle)
  1129. {
  1130. org.jawk.jrt.ICloseable t = null;
  1131. if (consumers.ContainsKey(handle))
  1132. {
  1133. t = consumers[handle];
  1134. consumers.Remove(handle);
  1135. }
  1136. if (t == null && accepters.ContainsKey(handle))
  1137. {
  1138. t = accepters[handle];
  1139. accepters.Remove(handle);
  1140. }
  1141. if (t == null)
  1142. {
  1143. throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid [server]socket handle : " + handle);
  1144. }
  1145. int retval;
  1146. try
  1147. {
  1148. t.Close();
  1149. retval = 1;
  1150. }
  1151. catch (System.IO.IOException ioe)
  1152. {
  1153. Console.Error.WriteLine(ioe);
  1154. retval = 0;
  1155. }
  1156. // interrupt the thread
  1157. t.Interrupt();
  1158. // join on the thread
  1159. try
  1160. {
  1161. t.Join();
  1162. }
  1163. catch (System.Exception)
  1164. {
  1165. throw new System.Exception("A socket close() cannot be interrupted.");
  1166. }
  1167. return retval;
  1168. }
  1169. private class Accepter : IThread, org.jawk.jrt.ICloseable
  1170. {
  1171. private string handle;
  1172. private TcpListener ssocket;
  1173. protected java.util.BlockingQueue<TcpClient> queue = new java.util.BlockingQueue
  1174. <TcpClient>(1);
  1175. //////////////////////////////////////////////////////////////////
  1176. //////////////////////////////////////////////////////////////////
  1177. //////////////////////////////////////////////////////////////////
  1178. // only 1 slot
  1179. //private BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
  1180. public virtual bool WillBlock(org.jawk.jrt.BlockObject bo)
  1181. {
  1182. return this.queue.Count == 0;
  1183. }
  1184. /// <exception cref="System.IO.IOException"></exception>
  1185. public Accepter(Threaded_IO_Style _enclosing, string handle, TcpListener ssocket)
  1186. {
  1187. this._enclosing = _enclosing;
  1188. this.handle = handle;
  1189. //ssocket = ssockets.get(handle);
  1190. this.ssocket = ssocket;
  1191. mThread = new Thread(Run);
  1192. }
  1193. //assert ssocket != null;
  1194. public void Run()
  1195. {
  1196. if (Thread.CurrentThread != mThread)
  1197. {
  1198. throw new System.Exception("Invalid thread access : " + Thread.CurrentThread);
  1199. }
  1200. try
  1201. {
  1202. TcpClient socket;
  1203. while (true)
  1204. {
  1205. socket = this.ssocket.AcceptTcpClient();
  1206. this.queue.Put(socket);
  1207. lock (this._enclosing.accept_blocker)
  1208. {
  1209. Monitor.Pulse(this._enclosing.accept_blocker);
  1210. }
  1211. }
  1212. }
  1213. catch (System.Net.Sockets.SocketException se)
  1214. {
  1215. Console.Error.WriteLine(se);
  1216. }
  1217. catch (System.IO.IOException ioe)
  1218. {
  1219. // no big deal
  1220. // assume we should just shutdown now
  1221. Console.Error.WriteLine(ioe);
  1222. }
  1223. catch (System.Exception ie)
  1224. {
  1225. Console.Error.WriteLine(ie);
  1226. throw new System.Exception("A queue operation cannot be interrupted.");
  1227. }
  1228. // no big deal
  1229. lock (this._enclosing.close_blocker)
  1230. {
  1231. Monitor.Pulse(this._enclosing.close_blocker);
  1232. }
  1233. }
  1234. // can be overridden
  1235. /// <exception cref="System.IO.IOException"></exception>
  1236. /// <exception cref="System.Exception"></exception>
  1237. public virtual string GetSocket()
  1238. {
  1239. TcpClient socket = this.queue.Take();
  1240. // ... same as socket() method ...
  1241. string handle = this._enclosing.CreateHandle(socket);
  1242. // start the reader
  1243. org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.ByteConsumer
  1244. (this._enclosing, handle, socket);
  1245. reader_thread.Start();
  1246. this._enclosing.consumers[handle] = reader_thread;
  1247. return handle;
  1248. }
  1249. public virtual bool IsClosed()
  1250. {
  1251. return !mThread.IsAlive;
  1252. }
  1253. /// <exception cref="System.IO.IOException"></exception>
  1254. public void Close()
  1255. {
  1256. this.ssocket.Stop();
  1257. }
  1258. private readonly Threaded_IO_Style _enclosing;
  1259. #region IThread Members
  1260. private Thread mThread;
  1261. public void Start()
  1262. {
  1263. mThread.Start();
  1264. }
  1265. public void SetDaemon(bool b)
  1266. {
  1267. mThread.IsBackground = b;
  1268. }
  1269. #endregion
  1270. #region IJoinable Members
  1271. public void Join()
  1272. {
  1273. mThread.Join();
  1274. }
  1275. public void Interrupt()
  1276. {
  1277. mThread.Interrupt();
  1278. }
  1279. #endregion
  1280. }
  1281. private sealed class CAccepter : org.jawk.ext.Threaded_IO_Style.Accepter
  1282. {
  1283. /// <exception cref="System.IO.IOException"></exception>
  1284. public CAccepter(Threaded_IO_Style _enclosing, string handle, TcpListener
  1285. ssocket) : base(_enclosing, handle, ssocket)
  1286. {
  1287. this._enclosing = _enclosing;
  1288. }
  1289. /// <exception cref="System.IO.IOException"></exception>
  1290. /// <exception cref="System.Exception"></exception>
  1291. public sealed override string GetSocket()
  1292. {
  1293. TcpClient socket = this.queue.Take();
  1294. // ... same as socket() method ...
  1295. string handle = this._enclosing.CreateHandle(socket);
  1296. // start the reader
  1297. org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.CharacterConsumer
  1298. (this._enclosing, handle, socket);
  1299. reader_thread.Start();
  1300. this._enclosing.consumers[handle] = reader_thread;
  1301. return handle;
  1302. }
  1303. private readonly Threaded_IO_Style _enclosing;
  1304. }
  1305. private abstract class AbstractConsumer<T> : IThread, org.jawk.jrt.IConsumer
  1306. {
  1307. private readonly string handle;
  1308. protected readonly TcpClient socket;
  1309. protected readonly System.IO.TextWriter ps;
  1310. private int state = org.jawk.ext.Threaded_IO_Style.ACTIVE_STATE;
  1311. protected java.util.BlockingQueue<T> queue = new java.util.BlockingQueue
  1312. <T>(1);
  1313. // only 1 slot
  1314. public bool WillBlock(org.jawk.jrt.BlockObject bo)
  1315. {
  1316. if (bo == this._enclosing.input_blocker)
  1317. {
  1318. return this.queue.Count == 0;
  1319. }
  1320. else
  1321. {
  1322. if (bo == this._enclosing.close_blocker)
  1323. {
  1324. return this.state == org.jawk.ext.Threaded_IO_Style.ACTIVE_STATE;
  1325. }
  1326. else
  1327. {
  1328. throw new System.Exception("Unknown block object : " + bo.GetNotifierTag());
  1329. }
  1330. }
  1331. }
  1332. /// <exception cref="System.IO.IOException"></exception>
  1333. protected AbstractConsumer(Threaded_IO_Style _enclosing, string handle, TcpClient
  1334. socket)
  1335. {
  1336. this._enclosing = _enclosing;
  1337. this.handle = handle;
  1338. //socket = sockets.get(handle);
  1339. this.socket = socket;
  1340. //assert socket != null;
  1341. this.ps = new System.IO.StreamWriter(socket.GetStream());
  1342. mThread = new Thread(new ThreadStart(Run));
  1343. }
  1344. /// <exception cref="System.IO.IOException"></exception>
  1345. protected abstract T ReadFromSocket();
  1346. public void Run()
  1347. {
  1348. if (Thread.CurrentThread != this.mThread)
  1349. {
  1350. throw new System.Exception("Invalid thread access : " + Thread.CurrentThread);
  1351. }
  1352. try
  1353. {
  1354. T input;
  1355. while ((input = this.ReadFromSocket()) != null)
  1356. {
  1357. this.queue.Put(input);
  1358. lock (this._enclosing.input_blocker)
  1359. {
  1360. Monitor.Pulse(this._enclosing.input_blocker);
  1361. }
  1362. }
  1363. }
  1364. catch (System.Net.Sockets.SocketException se)
  1365. {
  1366. Console.Error.WriteLine(se);
  1367. }
  1368. catch (System.IO.IOException ioe)
  1369. {
  1370. // no big deal
  1371. // assume we should just shutdown now
  1372. Console.Error.WriteLine(ioe);
  1373. }
  1374. catch (System.Exception ie)
  1375. {
  1376. Console.Error.WriteLine(ie);
  1377. throw new System.Exception("A queue operation cannot be interrupted.");
  1378. }
  1379. // no big deal
  1380. lock (this._enclosing.close_blocker)
  1381. {
  1382. if (this.state == org.jawk.ext.Threaded_IO_Style.ACTIVE_STATE)
  1383. {
  1384. this.state = org.jawk.ext.Threaded_IO_Style.CLOSE_PENDING_STATE;
  1385. Monitor.Pulse(this._enclosing.close_blocker);
  1386. }
  1387. }
  1388. }
  1389. /// <exception cref="System.Exception"></exception>
  1390. protected abstract string ReadFromQueue();
  1391. /// <exception cref="System.Exception"></exception>
  1392. public string GetInput()
  1393. {
  1394. //assert state != CLOSED_STATE; // active or close_pending
  1395. string str = this.ReadFromQueue();
  1396. if (this.queue.Count == 0 && this.state
  1397. == org.jawk.ext.Threaded_IO_Style.CLOSE_PENDING_STATE)
  1398. {
  1399. lock (this._enclosing.close_blocker)
  1400. {
  1401. // could be either ACTIVE or CLOSE_PENDING states
  1402. //assert state != CLOSED_STATE;
  1403. Monitor.Pulse(this._enclosing.close_blocker);
  1404. }
  1405. }
  1406. return str;
  1407. }
  1408. // write is defined in subclasses
  1409. public int Flush()
  1410. {
  1411. this.ps.Flush();
  1412. return 1;
  1413. }
  1414. public bool IsClosed()
  1415. {
  1416. return this.state == org.jawk.ext.Threaded_IO_Style.CLOSED_STATE;
  1417. }
  1418. /// <exception cref="System.IO.IOException"></exception>
  1419. public void Close()
  1420. {
  1421. this.socket.Close();
  1422. }
  1423. public abstract int Write(string arg1);
  1424. private readonly Threaded_IO_Style _enclosing;
  1425. #region IThread Members
  1426. private Thread mThread = null;
  1427. public void Start()
  1428. {
  1429. mThread.Start();
  1430. }
  1431. public void SetDaemon(bool b)
  1432. {
  1433. mThread.IsBackground = b;
  1434. }
  1435. #endregion
  1436. #region IJoinable Members
  1437. public void Join()
  1438. {
  1439. mThread.Join();
  1440. }
  1441. public void Interrupt()
  1442. {
  1443. mThread.Interrupt();
  1444. }
  1445. #endregion
  1446. }
  1447. private const int ACTIVE_STATE = 1;
  1448. private const int CLOSE_PENDING_STATE = 2;
  1449. private const int CLOSED_STATE = 3;
  1450. private sealed class CharacterConsumer : org.jawk.ext.Threaded_IO_Style.AbstractConsumer
  1451. <string>
  1452. {
  1453. private readonly System.IO.StreamReader br;
  1454. /// <exception cref="System.IO.IOException"></exception>
  1455. public CharacterConsumer(Threaded_IO_Style _enclosing, string handle, TcpClient
  1456. socket) : base(_enclosing, handle, socket)
  1457. {
  1458. this._enclosing = _enclosing;
  1459. // private abstract class AbstractConsumer<T> {Thread} [Consumer]
  1460. // constructs socket (protected field in AbstractConsumer)
  1461. this.br = new StreamReader(socket.GetStream());
  1462. }
  1463. ~CharacterConsumer()
  1464. {
  1465. this.br.Dispose();
  1466. }
  1467. /// <exception cref="System.IO.IOException"></exception>
  1468. protected sealed override string ReadFromSocket()
  1469. {
  1470. return this.br.ReadLine();
  1471. }
  1472. /// <exception cref="System.Exception"></exception>
  1473. protected sealed override string ReadFromQueue()
  1474. {
  1475. return this.queue.Take();
  1476. }
  1477. public sealed override int Write(string buf)
  1478. {
  1479. this.ps.WriteLine(buf);
  1480. return 1;
  1481. }
  1482. private readonly Threaded_IO_Style _enclosing;
  1483. }
  1484. private sealed class ByteConsumer : org.jawk.ext.Threaded_IO_Style.AbstractConsumer
  1485. <int?>

Large files files are truncated, but you can click here to view the full file