PageRenderTime 50ms CodeModel.GetById 2ms app.highlight 37ms RepoModel.GetById 1ms 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

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

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