/Awk.Net/ext/SocketExtension.cs
C# | 1672 lines | 905 code | 136 blank | 631 comment | 93 complexity | eb0f462f92afb24acfa99575d15e07d4 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net.Sockets;
- using java.util;
- using System.Threading;
-
- namespace org.jawk.ext
- {
- /// <summary>Enable Socket processing in Jawk.</summary>
- /// <remarks>
- /// Enable Socket processing in Jawk.
- /// <p>
- /// To use:
- /// <blockquote><pre>
- /// ## example echo server using CServerSocket (character-based)
- /// BEGIN {
- /// css = CServerSocket(7777);
- /// }
- /// $0 = SocketAcceptBlock(css,
- /// SocketInputBlock(handles,
- /// SocketCloseBlock(css, handles \
- /// )));
- /// $1 == "SocketAccept" {
- /// handles[SocketAccept($2)] = 1
- /// }
- /// $1 == "SocketClose" {
- /// SocketClose($2)
- /// delete handles[$2]
- /// }
- /// $1 == "SocketInput" {
- /// input = SocketRead($2)
- /// SocketWrite($2, input); ## do the echo
- /// }
- /// </pre></blockquote>
- /// <p>
- /// The extension functions are as follows:
- /// <ul>
- /// <hr>
- /// <li><strong><em><font size=+1>ServerSocket</font></em></strong> -<br />
- /// Sets up a server socket to listen for incomming
- /// connections. SocketRead on sockets accepted
- /// by ServerSocket return arbitrary-length Strings
- /// (bytes buffered by the input stream, converted
- /// to a string).<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>port number - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string handle to a serversocket.
- /// </ul><p>
- /// <li><strong><em><font size=+1>CServerSocket</font></em></strong> -<br />
- /// Sets up a server socket to listen for incomming
- /// connections. SocketRead on sockets accepted
- /// by CServerSocket return strings which terminate
- /// by a newline, or text in the input buffer just
- /// prior to the closing of the socket.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>port number - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string handle to a cserversocket.
- /// </ul><p>
- /// <hr>
- /// <li><strong><em><font size=+1>Socket</font></em></strong> -<br />
- /// Create a Socket and connect it to a TCP socket
- /// endpoint. SocketRead on sockets returned
- /// by Socket return arbitrary-length Strings
- /// (bytes buffered by the input stream, converted
- /// to a string).<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>hostname/ip/"localhost" - required
- /// <li>port number - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string handle to a socket.
- /// </ul><p>
- /// <li><strong><em><font size=+1>CSocket</font></em></strong> -<br />
- /// Create a Socket and connect it to a TCP socket
- /// endpoint. SocketRead on sockets returned
- /// by Socket return strings which terminate
- /// by a newline, or text in the input buffer just
- /// prior to the closing of the socket.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>hostname/ip/"localhost" - required
- /// <li>port number - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string handle to a csocket.
- /// </ul><p>
- /// <hr>
- /// <li><strong><em><font size=+1>SocketAcceptBlock</font></em></strong> -<br />
- /// Blocks until a serversocket or cserversocket
- /// is ready to accept a connecting socket.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>Any mix of
- /// serversocket or cserversocket handles
- /// and/or associative arrays whose keys
- /// are serversocket or cserversocket handles.
- /// The last argument can optionally be
- /// another block call for block chaining.
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string of the form:
- /// <code><font size=+1>SocketAccept<em>OFS</em>handle</font></code>
- /// where handle is a serversocket or cserversocket
- /// handle.
- /// </ul><p>
- /// <li><strong><em><font size=+1>SocketInputBlock</font></em></strong> -<br />
- /// Blocks until a socket or csocket is ready
- /// to accept input (via SocketRead).<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>Any mix of
- /// socket or csocket handles and/or associative
- /// arrays whose keys are socket or csocket handles.
- /// The last argument can optionally be
- /// another block call for block chaining.
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string of the form: <code><font size=+1>SocketInput<em>OFS</em>handle</font></code>
- /// where handle is a socket or csocket
- /// handle.
- /// </ul><p>
- /// <li><strong><em><font size=+1>SocketCloseBlock</font></em></strong> -<br />
- /// Blocks until a serversocket, cserversocket,
- /// socket, or csocket has been closed on the
- /// remote end.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>Any mix of
- /// serversocket, cserversocket, socket, or csocket
- /// handles and/or associative
- /// arrays whose keys are serversocket, cserversocket,
- /// socket, or csocket handles.
- /// The last argument can optionally be
- /// another block call for block chaining.
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string of the form: <code><font size=+1>SocketClose<em>OFS</em>handle</font></code>
- /// where handle is a serversocket, cserversocket, socket,
- /// or csocket handle.
- /// </ul><p>
- /// <hr>
- /// <li><strong><em><font size=+1>SocketAccept</font></em></strong> -<br />
- /// Accepts a socket from a serversocket or
- /// a cserversocket. The operation will
- /// block if there is no socket to accept.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>serversocket-or-cserversocket handle - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string handle to a socket or csocket.
- /// </ul><p>
- /// <hr>
- /// <li><strong><em><font size=+1>SocketRead</font></em></strong> -<br />
- /// Reads input from the input stream of a socket
- /// or a csocket. For a socket, the input length
- /// is arbitrary. For a csocket, the input
- /// length is bounded by a newline or upon
- /// termination of the socket.
- /// The operation will block if there is no input
- /// on the socket.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>socket-or-csocket handle - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>A string containing the input on the socket.
- /// </ul><p>
- /// <li><strong><em><font size=+1>SocketWrite</font></em></strong> -<br />
- /// Writes data to the socket or csocket.
- /// For a socket, the string is converted
- /// to bytes (via java.lang.String.getBytes()),
- /// and the bytes are sent to the socket's
- /// output stream.
- /// For a csocket, println() is called on the
- /// underlying socket's PrintStream.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>socket-or-csocket handle - required
- /// <li>msg - required - The string to write to
- /// the socket. For a csocket, a newline
- /// is added to it (via the
- /// java.io.PrintStream.println() method).
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>1 upon a successful write, 0 otherwise
- /// </ul><p>
- /// <li><strong><em><font size=+1>SocketFlush</font></em></strong> -<br />
- /// Flushes the output stream of a socket or csocket.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>socket-or-csocket handle - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>1 upon a successful flush, 0 otherwise
- /// </ul><p>
- /// <hr>
- /// <li><strong><em><font size=+1>SocketClose</font></em></strong> -<br />
- /// Closes the socket/csocket on the local end,
- /// or a serversocket/cserversocket.
- /// Can be called in response to a SocketCloseBlock
- /// event, or to force a socket/csocket connection to
- /// terminate.<br />
- /// <strong>Parameters:</strong>
- /// <ul>
- /// <li>socket/csocket/serversocket/cserversocket handle - required
- /// </ul>
- /// <strong>Returns:</strong>
- /// <ul>
- /// <li>1 upon successful close, 0 otherwise
- /// </ul><p>
- /// <hr>
- /// </ul>
- /// </remarks>
- public class SocketExtension : org.jawk.ext.AbstractExtension
- {
- /// <summary>
- /// Either threaded or non-threaded (nio-style) socket
- /// handling.
- /// </summary>
- /// <remarks>
- /// Either threaded or non-threaded (nio-style) socket
- /// handling. The threaded implementation is provided
- /// upon initial release. Non-threaded
- /// functionality will be available in a subsequent
- /// release.
- /// </remarks>
- private org.jawk.ext.IIO_Style impl_delegate;
-
- public sealed override void Init(org.jawk.jrt.IVariableManager vm, org.jawk.jrt.JRT
- jrt)
- {
- base.Init(vm, jrt);
- impl_delegate = new org.jawk.ext.Threaded_IO_Style(vm);
- }
-
- public sealed override string GetExtensionName()
- {
- return "Socket Support";
- }
-
- public sealed override string[] ExtensionKeywords()
- {
- return new string[] { "ServerSocket", "CServerSocket", "Socket", "CSocket", "SocketAcceptBlock"
- , "SocketInputBlock", "SocketCloseBlock", "SocketAccept", "SocketRead", "SocketWrite"
- , "SocketFlush", "SocketClose" };
- }
-
- // i.e., ss = ServerSocket(8080) or ss = ServerSocket("ip", 8080)
- // i.e., css = CServerSocket(8080) or css = CServerSocket("ip", 8080)
- // i.e., s = Socket("localhost", 8080)
- // i.e., cs = CSocket("localhost", 8080)
- // i.e., $0 = SocketAcceptBlock(ss, css,
- // i.e., SocketInputBlock(s, cs,
- // i.e., SocketCloseBlock(ss,css, s,cs)));
- // i.e., cs = SocketAccept(css)
- // i.e., buf = SocketRead(s) or line = SocketRead(cs)
- // i.e., SocketWrite(s, "hi there\n") or SocketWrite(cs, "hi there")
- // i.e., SocketFlush(s) or SocketFlush(cs)
- // i.e., SocketClose(ss) or SocketClose(cs)
- public sealed override object Invoke(string method_name, object[] args)
- {
- // large if-then-else block to decide which extension to invoke
- if (false)
- {
- throw new System.Exception("Should never reach.");
- }
- else
- {
- if (method_name.Equals("ServerSocket"))
- {
- if (args.Length == 1)
- {
- return impl_delegate.Serversocket(null, (int)org.jawk.jrt.JRT.ToDouble(args[0]));
- }
- else
- {
- if (args.Length == 2)
- {
- return impl_delegate.Serversocket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble
- (args[1]));
- }
- else
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Expecting 1 or 2 arguments, not "
- + args.Length);
- }
- }
- }
- else
- {
- if (method_name.Equals("CServerSocket"))
- {
- if (args.Length == 1)
- {
- return impl_delegate.Cserversocket(null, (int)org.jawk.jrt.JRT.ToDouble(args[0]));
- }
- else
- {
- if (args.Length == 2)
- {
- return impl_delegate.Cserversocket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble
- (args[1]));
- }
- else
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Expecting 1 or 2 arguments, not "
- + args.Length);
- }
- }
- }
- else
- {
- if (method_name.Equals("Socket"))
- {
- CheckNumArgs(args, 2);
- return impl_delegate.Socket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble(
- args[1]));
- }
- else
- {
- if (method_name.Equals("CSocket"))
- {
- CheckNumArgs(args, 2);
- return impl_delegate.Csocket(ToAwkString(args[0]), (int)org.jawk.jrt.JRT.ToDouble
- (args[1]));
- }
- else
- {
- if (method_name.Equals("SocketAcceptBlock"))
- {
- return impl_delegate.Socketacceptblock(args);
- }
- else
- {
- if (method_name.Equals("SocketInputBlock"))
- {
- return impl_delegate.Socketinputblock(args);
- }
- else
- {
- if (method_name.Equals("SocketCloseBlock"))
- {
- return impl_delegate.Socketcloseblock(args);
- }
- else
- {
- if (method_name.Equals("SocketAccept"))
- {
- CheckNumArgs(args, 1);
- return impl_delegate.Socketaccept(ToAwkString(args[0]));
- }
- else
- {
- if (method_name.Equals("SocketRead"))
- {
- CheckNumArgs(args, 1);
- return impl_delegate.Socketread(ToAwkString(args[0]));
- }
- else
- {
- if (method_name.Equals("SocketWrite"))
- {
- CheckNumArgs(args, 2);
- return impl_delegate.Socketwrite(ToAwkString(args[0]), ToAwkString(args[1]));
- }
- else
- {
- if (method_name.Equals("SocketFlush"))
- {
- CheckNumArgs(args, 1);
- return impl_delegate.Socketflush(ToAwkString(args[0]));
- }
- else
- {
- if (method_name.Equals("SocketClose"))
- {
- CheckNumArgs(args, 1);
- return impl_delegate.Socketclose(ToAwkString(args[0]));
- }
- else
- {
- throw new org.jawk.NotImplementedError(method_name);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Interface to the socket handling delegate which
- /// does all the work.
- /// </summary>
- /// <remarks>
- /// Interface to the socket handling delegate which
- /// does all the work. The SocketExtension manager
- /// class delegates all concrete socket IO
- /// processing to an instance of this interface.
- /// </remarks>
- internal interface IIO_Style
- {
- // public class SocketExtension {AbstractExtension}
- //
- // INTERFACE TO DELEGATE
- //
- /// <summary>
- /// Sets up a server socket to listen for incomming
- /// connections.
- /// </summary>
- /// <remarks>
- /// Sets up a server socket to listen for incomming
- /// connections. SocketRead on sockets accepted
- /// by ServerSocket return arbitrary-length Strings
- /// (bytes buffered by the input stream, converted
- /// to a string).
- /// </remarks>
- /// <param name="hostname">
- /// The hostname or IP address as a string.
- /// hostname can be null.
- /// </param>
- /// <param name="port">The port number.</param>
- /// <returns>A handle to a newly created serversocket.</returns>
- string Serversocket(string hostname, int port);
-
- /// <summary>
- /// Sets up a server socket to listen for incomming
- /// connections.
- /// </summary>
- /// <remarks>
- /// Sets up a server socket to listen for incomming
- /// connections. SocketRead on sockets accepted
- /// by CServerSocket return strings which terminate
- /// by a newline, or text in the input buffer just
- /// prior to the closing of the socket.
- /// </remarks>
- /// <param name="hostname">
- /// The hostname or IP address as a string.
- /// hostname can be null.
- /// </param>
- /// <param name="port">The port number.</param>
- /// <returns>A handle to a newly created cserversocket.</returns>
- string Cserversocket(string hostname, int port);
-
- /// <summary>
- /// Create a Socket and connect it to a TCP socket
- /// endpoint.
- /// </summary>
- /// <remarks>
- /// Create a Socket and connect it to a TCP socket
- /// endpoint. SocketRead on sockets returned
- /// by Socket return arbitrary-length Strings
- /// (bytes buffered by the input stream, converted
- /// to a string).
- /// </remarks>
- /// <param name="hostname">
- /// The hostname or IP address as a string.
- /// hostname can be null.
- /// </param>
- /// <param name="port">The port number.</param>
- /// <returns>A handle to a newly created socket.</returns>
- string Socket(string hostname, int port);
-
- /// <summary>
- /// Create a Socket and connect it to a TCP socket
- /// endpoint.
- /// </summary>
- /// <remarks>
- /// Create a Socket and connect it to a TCP socket
- /// endpoint. SocketRead on sockets returned
- /// by Socket return strings which terminate
- /// by a newline, or text in the input buffer just
- /// prior to the closing of the socket.
- /// </remarks>
- /// <param name="hostname">
- /// The hostname or IP address as a string.
- /// hostname can be null.
- /// </param>
- /// <param name="port">The port number.</param>
- /// <returns>A handle to a newly created csocket.</returns>
- string Csocket(string hostname, int port);
-
- /// <summary>
- /// Blocks until a serversocket or cserversocket
- /// is ready to accept a connecting socket.
- /// </summary>
- /// <remarks>
- /// Blocks until a serversocket or cserversocket
- /// is ready to accept a connecting socket.
- /// </remarks>
- /// <param name="args">
- /// An array of
- /// serversocket or cserversocket handles
- /// and/or associative arrays whose keys
- /// are serversocket or cserversocket handles.
- /// The last argument can optionally be
- /// another block call for block chaining.
- /// </param>
- /// <returns>
- /// A block object conditioned
- /// to block on the acceptance of
- /// socket connections from any of
- /// the serversockets / cserversockets
- /// referred to by the handles passed
- /// in to the object array.
- /// </returns>
- org.jawk.jrt.BlockObject Socketacceptblock(object[] args);
-
- /// <summary>
- /// Blocks until a socket or csocket is ready
- /// to accept input (via SocketRead).
- /// </summary>
- /// <remarks>
- /// Blocks until a socket or csocket is ready
- /// to accept input (via SocketRead).
- /// </remarks>
- /// <param name="args">
- /// An array of
- /// socket or csocket handles and/or associative
- /// arrays whose keys are socket or csocket handles.
- /// The last argument can optionally be
- /// another block call for block chaining.
- /// </param>
- /// <returns>
- /// A block object conditioned
- /// to block on the availability of
- /// input from any of the sockets / csockets
- /// referred to by the handles passed
- /// in to the object array.
- /// </returns>
- org.jawk.jrt.BlockObject Socketinputblock(object[] args);
-
- /// <summary>
- /// Blocks until a serversocket, cserversocket,
- /// socket, or csocket has been closed on the
- /// remote end.
- /// </summary>
- /// <remarks>
- /// Blocks until a serversocket, cserversocket,
- /// socket, or csocket has been closed on the
- /// remote end.
- /// </remarks>
- /// <param name="args">
- /// An array of
- /// serversocket, cserversocket, socket, or csocket
- /// handles and/or associative
- /// arrays whose keys are serversocket, cserversocket,
- /// socket, or csocket handles.
- /// The last argument can optionally be
- /// another block call for block chaining.
- /// </param>
- /// <returns>
- /// A block object conditioned
- /// to block until any of the sockets /
- /// csockets / serversockets / cserversockets
- /// in to the object array have closed.
- /// </returns>
- org.jawk.jrt.BlockObject Socketcloseblock(object[] args);
-
- /// <summary>
- /// Accepts a socket from a serversocket or
- /// a cserversocket.
- /// </summary>
- /// <remarks>
- /// Accepts a socket from a serversocket or
- /// a cserversocket. The operation will
- /// block if there is no socket to accept.
- /// </remarks>
- /// <param name="handle">
- /// A string handle to a serversocket
- /// or cserversocket.
- /// </param>
- /// <returns>
- /// A handle to a socket or csocket that
- /// has connected to the serversocket / cserversocket
- /// referred to by the handle argument.
- /// </returns>
- string Socketaccept(string handle);
-
- /// <summary>
- /// Reads input from the input stream of a socket
- /// or a csocket.
- /// </summary>
- /// <remarks>
- /// Reads input from the input stream of a socket
- /// or a csocket. For a socket, the input length
- /// is arbitrary. For a csocket, the input
- /// length is bounded by a newline or upon
- /// termination of the socket.
- /// The operation will block if there is no input
- /// on the socket.
- /// </remarks>
- /// <param name="handle">
- /// A string handle to a socket
- /// or csocket.
- /// </param>
- /// <returns>
- /// A block of byte input from a socket
- /// (converted to a string), or a line of
- /// string input from a csocket bounded by
- /// a newline in the stream or upon the closing
- /// of the csocket.
- /// </returns>
- string Socketread(string handle);
-
- /// <summary>Writes data to the socket or csocket.</summary>
- /// <remarks>
- /// Writes data to the socket or csocket.
- /// For a socket, the string is converted
- /// to bytes (via java.lang.String.getBytes()),
- /// and the bytes are sent to the underlying
- /// socket's output stream.
- /// For a csocket, println() is called on the
- /// underlying socket's PrintStream.
- /// </remarks>
- /// <param name="handle">
- /// A string handle to a socket
- /// or csocket.
- /// </param>
- /// <param name="buf">
- /// The string containing the
- /// bytes to write. SocketWrite writes
- /// the contents of the resulting buf.getBytes()
- /// call to the socket.
- /// </param>
- /// <param name="handle">
- /// A String handle to a socket
- /// or csocket.
- /// </param>
- /// <param name="buf">
- /// A string containing a block of
- /// bytes to write to a socket (via
- /// java.lang.String.getBytes()) if handle
- /// refers to a socket. If handle refers
- /// to a csocket, the line of text to write
- /// via PrintStream.println(String).
- /// </param>
- /// <returns>
- /// 1 upon a successful write,
- /// 0 upon an IO exception/error.
- /// </returns>
- int Socketwrite(string handle, string buf);
-
- /// <summary>Flushes the output stream of a socket or csocket.</summary>
- /// <remarks>Flushes the output stream of a socket or csocket.</remarks>
- /// <param name="handle">
- /// A string handle to a socket
- /// or csocket.
- /// </param>
- /// <returns>
- /// 1 upon a successful flush operation,
- /// 0 upon an IO exception/error.
- /// </returns>
- int Socketflush(string handle);
-
- /// <summary>
- /// Closes the socket/csocket on the local end,
- /// or a serversocket/cserversocket.
- /// </summary>
- /// <remarks>
- /// Closes the socket/csocket on the local end,
- /// or a serversocket/cserversocket.
- /// Can be called in response to a SocketCloseBlock
- /// event, or to force a socket/csocket connection to
- /// terminate.
- /// </remarks>
- /// <param name="handle">
- /// A string handle to a socket,
- /// csocket, serversocket, or cserversocket.
- /// </param>
- /// <returns>
- /// 1 upon a successful close operation,
- /// 0 upon an IO exception/error.
- /// </returns>
- int Socketclose(string handle);
- }
-
- /// <summary>A view of two maps as one map.</summary>
- /// <remarks>A view of two maps as one map.</remarks>
- internal class MapUnion<K, V> : Dictionary<K, V>
- {
- private System.Collections.Generic.IDictionary<K, V> m1;
-
- private System.Collections.Generic.IDictionary<K, V> m2;
-
- internal MapUnion(System.Collections.Generic.IDictionary<K, V> m1, System.Collections.Generic.IDictionary
- <K, V> m2)
- {
- this.m1 = m1;
- this.m2 = m2;
- }
-
- public System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair <K, V>> EntrySet()
- {
- // build the entry set
- System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<K, V>> entry_set = new List<KeyValuePair<K, V>>();
- System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<K, V>> s1 = m1;
- System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<K, V>> s2 = m2;
- foreach (System.Collections.Generic.KeyValuePair<K, V> me in s1)
- {
- entry_set.Add(me);
- }
- foreach (System.Collections.Generic.KeyValuePair<K, V> me in s2)
- {
- entry_set.Add(me);
- }
- return entry_set;
- }
- }
-
- internal class Threaded_IO_Style : org.jawk.ext.IIO_Style
- {
- private string last_err = null;
-
- /// <summary>
- /// Map of "Socket"/"CSocket" handles to
- /// the objects which perform the actual
- /// read and block operations.
- /// </summary>
- /// <remarks>
- /// Map of "Socket"/"CSocket" handles to
- /// the objects which perform the actual
- /// read and block operations.
- /// <p>
- /// <strong>Note:</strong>
- /// "consumers" originally was of type
- /// Map<String,Consumer>, but changed to ...,Closeable.
- /// (Likewise, "accepters" was originally ...,Accepter,
- /// but then changed to ...,Closeable.)
- /// Why? Because MapUnion could not infer that "Consumer"
- /// nor "Accepter" were extensions of "Blockable".
- /// MapUnion originally accepted 3 generic parameters:
- /// K, V1 extends Blockable, and V2 extends Blockable.
- /// And, close_blocker's BulkBlockObject Map parameter was:
- /// new MapUnion<String,Accepter,Consumer>(accepters,consumers).
- /// But, it wouldn't compile.
- /// The resulting warning/error messages stated that
- /// "capture #XXX of ? extends Blockable" does not
- /// match "? extends Blockable". I believe the error
- /// results from Blockable being compiled against
- /// Java 1.5.x and extensions being developed against
- /// Java 1.6.x, and that they don't grok one another
- /// in this scenario.
- /// We, then, decided to assign its lowest common
- /// subclass, "Closeable", and typecast when we need
- /// specific "Accepter" and "Consumer" functionality.
- /// This resolved the issue while losing some
- /// compile-time type safety.
- /// </remarks>
- private readonly System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable> consumers = new System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable>();
-
- /// <summary>
- /// Map of "ServerSocket"/"CServerSocket" handles
- /// to the objects which perform the actual
- /// socket accept operation.
- /// </summary>
- /// <remarks>
- /// Map of "ServerSocket"/"CServerSocket" handles
- /// to the objects which perform the actual
- /// socket accept operation.
- /// <p>
- /// <strong>Note:</strong>
- /// See lengthy diatribe above for "consumers".
- /// The same applies for "accepters"'s generic
- /// type choice for values of the Map.
- /// </remarks>
- private readonly System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable> accepters = new System.Collections.Generic.Dictionary<string, org.jawk.jrt.ICloseable>();
-
- private readonly org.jawk.jrt.IVariableManager vm;
-
- private readonly org.jawk.jrt.BulkBlockObject accept_blocker;
-
- private readonly org.jawk.jrt.BulkBlockObject input_blocker;
-
- private readonly org.jawk.jrt.BulkBlockObject close_blocker;
-
- internal Threaded_IO_Style(org.jawk.jrt.IVariableManager vm)
- {
- accept_handle_validator = new _IBlockHandleValidator_759(this);
- input_handle_validator = new _IBlockHandleValidator_772(this);
- close_handle_validator = new _IBlockHandleValidator_785(this);
- //assert vm != null;
- this.vm = vm;
- accept_blocker = new org.jawk.jrt.BulkBlockObject("SocketAccept", accepters, vm);
- input_blocker = new org.jawk.jrt.BulkBlockObject("SocketInput", consumers, vm);
- close_blocker = new org.jawk.jrt.BulkBlockObject("SocketClose", new org.jawk.ext.MapUnion<string, org.jawk.jrt.ICloseable>(accepters, consumers), vm);
- }
-
- public string Serversocket(string hostname, int port)
- {
- try
- {
-
- TcpListener ss = null;
-
- if (hostname == null)
- {
- ss = new TcpListener(System.Net.IPAddress.Any, port);
- }
- else
- {
- // 0 = default backlog
- System.Net.IPAddress[] tab = System.Net.Dns.GetHostAddresses(hostname);
-
- System.Net.IPAddress address = System.Net.IPAddress.Any;
- if(tab!=null && tab.Length>0)
- {
- address = tab[0];
- }
- ss = new TcpListener(address, port);
- }
- string handle = CreateHandle(ss);
- //ssockets.put(handle, ss);
- org.jawk.ext.Threaded_IO_Style.Accepter accepter_thread = new org.jawk.ext.Threaded_IO_Style.Accepter
- (this, handle, ss);
- accepters[handle] = accepter_thread;
- accepter_thread.Start();
- return handle;
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe.ToString());
- last_err = ioe.ToString();
- return string.Empty;
- }
- }
-
- public string Cserversocket(string hostname, int port)
- {
- try
- {
- TcpListener ss;
- if (hostname == null)
- {
- ss = new TcpListener(System.Net.IPAddress.Any,port);
- }
- else
- {
- // 0 = default backlog
- System.Net.IPAddress[] tab = System.Net.Dns.GetHostAddresses(hostname);
-
- System.Net.IPAddress address = System.Net.IPAddress.Any;
- if (tab != null && tab.Length > 0)
- {
- address = tab[0];
- }
- ss = new TcpListener(address, port);
- }
- string handle = CreateHandle(ss);
- //ssockets.put(handle, ss);
- org.jawk.ext.Threaded_IO_Style.Accepter accepter_thread = new org.jawk.ext.Threaded_IO_Style.CAccepter
- (this, handle, ss);
- accepters[handle] = accepter_thread;
- accepter_thread.Start();
- return handle;
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe.ToString());
- last_err = ioe.ToString();
- return string.Empty;
- }
- }
-
- public string Socket(string hostname, int port)
- {
- // create the socket
- try
- {
- TcpClient socket = new TcpClient(hostname, port);
- string handle = CreateHandle(socket);
- //sockets.put(handle, socket);
- // start the reader
- org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.ByteConsumer
- (this, handle, socket);
- consumers[handle] = reader_thread;
- reader_thread.Start();
- return handle;
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe.ToString());
- last_err = ioe.ToString();
- return string.Empty;
- }
- }
-
- public string Csocket(string hostname, int port)
- {
- try
- {
- // create the socket
- TcpClient socket = new TcpClient(hostname, port);
- string handle = CreateHandle(socket);
- //sockets.put(handle, socket);
- // start the reader
- org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.CharacterConsumer
- (this, handle, socket);
- consumers[handle] = reader_thread;
- reader_thread.Start();
- return handle;
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe.ToString());
- last_err = ioe.ToString();
- return string.Empty;
- }
- }
-
- private int socket_idx = 0;
-
- private int ssocket_idx = 0;
-
- private string CreateHandle(TcpListener socket)
- {
- System.Net.IPEndPoint endPoint = socket.LocalEndpoint as System.Net.IPEndPoint;
-
- if (endPoint != null)
- {
- return "Socket:" + endPoint.Address.ToString() + ":" + endPoint.Port + "/" + (++ssocket_idx);
- }
- else
- {
- return "Socket:" + socket.LocalEndpoint.Serialize().ToString() + "/" + (++ssocket_idx);
- }
- }
-
- private string CreateHandle(TcpClient socket)
- {
- System.Net.IPEndPoint endPoint = socket.Client.LocalEndPoint as System.Net.IPEndPoint;
-
- if (endPoint != null)
- {
- return "Socket:" + endPoint.Address.ToString() + ":" + endPoint.Port + "/" + (++socket_idx);
- }
- else
- {
- return "Socket:" + socket.Client.LocalEndPoint.Serialize().ToString() + "/" + (++socket_idx);
- }
- }
-
- private sealed class _IBlockHandleValidator_759 : org.jawk.jrt.IBlockHandleValidator
- {
- public _IBlockHandleValidator_759(Threaded_IO_Style _enclosing)
- {
- this._enclosing = _enclosing;
- }
-
- //////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////
- // to satisfy the BlockHandleValidator interface
- public string IsBlockHandleValid(string handle)
- {
- org.jawk.jrt.ICloseable closeable = null;
- if(this._enclosing.accepters.ContainsKey(handle))
- {
- closeable = this._enclosing.accepters[handle];
- }
- if (closeable == null)
- {
- return "Invalid ServerSocket handle.";
- }
- if (closeable.IsClosed())
- {
- return "ServerSocket is closed.";
- }
- else
- {
- return null;
- }
- }
-
- private readonly Threaded_IO_Style _enclosing;
- }
-
- private readonly org.jawk.jrt.IBlockHandleValidator accept_handle_validator;
-
- private sealed class _IBlockHandleValidator_772 : org.jawk.jrt.IBlockHandleValidator
- {
- public _IBlockHandleValidator_772(Threaded_IO_Style _enclosing)
- {
- this._enclosing = _enclosing;
- }
-
- // valid
- // to satisfy the BlockHandleValidator interface
- public string IsBlockHandleValid(string handle)
- {
- org.jawk.jrt.ICloseable closeable = null;
- if (this._enclosing.consumers.ContainsKey(handle))
- {
- closeable = this._enclosing.consumers[handle];
- }
- if (closeable == null)
- {
- return "Invalid socket handle. (Could have already been closed?)";
- }
- if (closeable.IsClosed())
- {
- return "Socket is closed.";
- }
- else
- {
- return null;
- }
- }
-
- private readonly Threaded_IO_Style _enclosing;
- }
-
- private readonly org.jawk.jrt.IBlockHandleValidator input_handle_validator;
-
- private sealed class _IBlockHandleValidator_785 : org.jawk.jrt.IBlockHandleValidator
- {
- public _IBlockHandleValidator_785(Threaded_IO_Style _enclosing)
- {
- this._enclosing = _enclosing;
- }
-
- // valid
- // to satisfy the BlockHandleValidator interface
- public string IsBlockHandleValid(string handle)
- {
- org.jawk.jrt.ICloseable closeable = null;
- if(this._enclosing.accepters.ContainsKey(handle))
- {
- closeable = this._enclosing.accepters[handle];
- }
- if (closeable == null && this._enclosing.consumers.ContainsKey(handle))
- {
- closeable = this._enclosing.consumers[handle];
- }
- if (closeable == null)
- {
- return "Invalid socket handle. (Could have already been closed?)";
- }
- if (closeable.IsClosed())
- {
- return "Socket is already closed.";
- }
- else
- {
- return null;
- }
- }
-
- private readonly Threaded_IO_Style _enclosing;
- }
-
- private readonly org.jawk.jrt.IBlockHandleValidator close_handle_validator;
-
- // valid
- public org.jawk.jrt.BlockObject Socketacceptblock(object[] args)
- {
- return accept_blocker.PopulateHandleSet(args, vm, accept_handle_validator);
- }
-
- public org.jawk.jrt.BlockObject Socketinputblock(object[] args)
- {
- return input_blocker.PopulateHandleSet(args, vm, input_handle_validator);
- }
-
- public org.jawk.jrt.BlockObject Socketcloseblock(object[] args)
- {
- return close_blocker.PopulateHandleSet(args, vm, close_handle_validator);
- }
-
- public string Socketaccept(string handle)
- {
- try
- {
- org.jawk.ext.Threaded_IO_Style.Accepter accepter = null;
- if(accepters.ContainsKey(handle))
- {
- accepter = (org.jawk.ext.Threaded_IO_Style.Accepter)accepters[handle];
- }
- if (accepter == null)
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid server socket handle : "
- + handle);
- }
- // it's "as if" accept_blocker is querying whether to block or not
- if (accepter.WillBlock(accept_blocker) && accepter.IsClosed())
- {
- last_err = "Server closed.";
- return string.Empty;
- }
- return accepter.GetSocket();
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe.ToString());
- throw new System.Exception("Error occurred during creation of accepted socket.");
- }
- catch (System.Exception ie)
- {
- Console.Error.WriteLine(ie.ToString());
- throw new System.Exception("A queue operation cannot be interrupted.");
- }
- }
-
- public string Socketread(string handle)
- {
- try
- {
- org.jawk.jrt.IConsumer consumer = null;
- if(consumers.ContainsKey(handle))
- {
- consumer = (org.jawk.jrt.IConsumer)consumers[handle];
- }
- if (consumer == null)
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid socket handle : " + handle
- );
- }
- // it's "as if" input_blocker is querying whether to block or not
- if (consumer.WillBlock(input_blocker) && consumer.IsClosed())
- {
- last_err = "No more input.";
- return string.Empty;
- }
- return consumer.GetInput();
- }
- catch (System.Exception ie)
- {
- Console.Error.WriteLine(ie);
- throw new System.Exception("A queue operation cannot be interrupted.");
- }
- }
-
- public int Socketwrite(string handle, string buf)
- {
- org.jawk.jrt.IConsumer consumer = null;
- if(consumers.ContainsKey(handle))
- {
- consumer = (org.jawk.jrt.IConsumer)consumers[handle];
- }
- if (consumer == null)
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid socket handle : " + handle
- );
- }
- return consumer.Write(buf);
- }
-
- public int Socketflush(string handle)
- {
- org.jawk.jrt.IConsumer consumer = null;
- if(consumers.ContainsKey(handle))
- {
- consumer = (org.jawk.jrt.IConsumer)consumers[handle];
- }
- if (consumer == null)
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid socket handle : " + handle
- );
- }
- return consumer.Flush();
- }
-
- public int Socketclose(string handle)
- {
-
- org.jawk.jrt.ICloseable t = null;
-
- if (consumers.ContainsKey(handle))
- {
- t = consumers[handle];
- consumers.Remove(handle);
- }
-
- if (t == null && accepters.ContainsKey(handle))
- {
- t = accepters[handle];
- accepters.Remove(handle);
- }
-
- if (t == null)
- {
- throw new org.jawk.jrt.IllegalAwkArgumentException("Invalid [server]socket handle : " + handle);
- }
- int retval;
- try
- {
- t.Close();
- retval = 1;
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe);
- retval = 0;
- }
- // interrupt the thread
- t.Interrupt();
- // join on the thread
- try
- {
- t.Join();
- }
- catch (System.Exception)
- {
- throw new System.Exception("A socket close() cannot be interrupted.");
- }
- return retval;
- }
-
- private class Accepter : IThread, org.jawk.jrt.ICloseable
- {
- private string handle;
-
- private TcpListener ssocket;
-
- protected java.util.BlockingQueue<TcpClient> queue = new java.util.BlockingQueue
- <TcpClient>(1);
-
- //////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////
- // only 1 slot
- //private BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
- public virtual bool WillBlock(org.jawk.jrt.BlockObject bo)
- {
- return this.queue.Count == 0;
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- public Accepter(Threaded_IO_Style _enclosing, string handle, TcpListener ssocket)
- {
- this._enclosing = _enclosing;
- this.handle = handle;
- //ssocket = ssockets.get(handle);
- this.ssocket = ssocket;
-
- mThread = new Thread(Run);
- }
-
- //assert ssocket != null;
- public void Run()
- {
- if (Thread.CurrentThread != mThread)
- {
- throw new System.Exception("Invalid thread access : " + Thread.CurrentThread);
- }
- try
- {
- TcpClient socket;
- while (true)
- {
- socket = this.ssocket.AcceptTcpClient();
- this.queue.Put(socket);
- lock (this._enclosing.accept_blocker)
- {
- Monitor.Pulse(this._enclosing.accept_blocker);
- }
- }
- }
- catch (System.Net.Sockets.SocketException se)
- {
- Console.Error.WriteLine(se);
- }
- catch (System.IO.IOException ioe)
- {
- // no big deal
- // assume we should just shutdown now
- Console.Error.WriteLine(ioe);
- }
- catch (System.Exception ie)
- {
- Console.Error.WriteLine(ie);
- throw new System.Exception("A queue operation cannot be interrupted.");
- }
- // no big deal
- lock (this._enclosing.close_blocker)
- {
- Monitor.Pulse(this._enclosing.close_blocker);
- }
- }
-
- // can be overridden
- /// <exception cref="System.IO.IOException"></exception>
- /// <exception cref="System.Exception"></exception>
- public virtual string GetSocket()
- {
- TcpClient socket = this.queue.Take();
- // ... same as socket() method ...
- string handle = this._enclosing.CreateHandle(socket);
- // start the reader
- org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.ByteConsumer
- (this._enclosing, handle, socket);
- reader_thread.Start();
- this._enclosing.consumers[handle] = reader_thread;
- return handle;
- }
-
- public virtual bool IsClosed()
- {
- return !mThread.IsAlive;
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- public void Close()
- {
- this.ssocket.Stop();
- }
-
- private readonly Threaded_IO_Style _enclosing;
-
- #region IThread Members
-
- private Thread mThread;
- public void Start()
- {
- mThread.Start();
- }
-
- public void SetDaemon(bool b)
- {
- mThread.IsBackground = b;
- }
-
- #endregion
-
- #region IJoinable Members
-
- public void Join()
- {
- mThread.Join();
- }
-
- public void Interrupt()
- {
- mThread.Interrupt();
- }
-
- #endregion
- }
-
- private sealed class CAccepter : org.jawk.ext.Threaded_IO_Style.Accepter
- {
- /// <exception cref="System.IO.IOException"></exception>
- public CAccepter(Threaded_IO_Style _enclosing, string handle, TcpListener
- ssocket) : base(_enclosing, handle, ssocket)
- {
- this._enclosing = _enclosing;
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- /// <exception cref="System.Exception"></exception>
- public sealed override string GetSocket()
- {
- TcpClient socket = this.queue.Take();
- // ... same as socket() method ...
- string handle = this._enclosing.CreateHandle(socket);
- // start the reader
- org.jawk.jrt.IConsumer reader_thread = new org.jawk.ext.Threaded_IO_Style.CharacterConsumer
- (this._enclosing, handle, socket);
- reader_thread.Start();
- this._enclosing.consumers[handle] = reader_thread;
- return handle;
- }
-
- private readonly Threaded_IO_Style _enclosing;
- }
-
-
-
-
-
- private abstract class AbstractConsumer<T> : IThread, org.jawk.jrt.IConsumer
- {
- private readonly string handle;
-
- protected readonly TcpClient socket;
-
- protected readonly System.IO.TextWriter ps;
-
- private int state = org.jawk.ext.Threaded_IO_Style.ACTIVE_STATE;
-
- protected java.util.BlockingQueue<T> queue = new java.util.BlockingQueue
- <T>(1);
-
- // only 1 slot
- public bool WillBlock(org.jawk.jrt.BlockObject bo)
- {
- if (bo == this._enclosing.input_blocker)
- {
- return this.queue.Count == 0;
- }
- else
- {
- if (bo == this._enclosing.close_blocker)
- {
- return this.state == org.jawk.ext.Threaded_IO_Style.ACTIVE_STATE;
- }
- else
- {
- throw new System.Exception("Unknown block object : " + bo.GetNotifierTag());
- }
- }
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- protected AbstractConsumer(Threaded_IO_Style _enclosing, string handle, TcpClient
- socket)
- {
- this._enclosing = _enclosing;
- this.handle = handle;
- //socket = sockets.get(handle);
- this.socket = socket;
- //assert socket != null;
- this.ps = new System.IO.StreamWriter(socket.GetStream());
-
-
- mThread = new Thread(new ThreadStart(Run));
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- protected abstract T ReadFromSocket();
-
- public void Run()
- {
- if (Thread.CurrentThread != this.mThread)
- {
- throw new System.Exception("Invalid thread access : " + Thread.CurrentThread);
- }
- try
- {
- T input;
- while ((input = this.ReadFromSocket()) != null)
- {
- this.queue.Put(input);
- lock (this._enclosing.input_blocker)
- {
- Monitor.Pulse(this._enclosing.input_blocker);
- }
- }
- }
- catch (System.Net.Sockets.SocketException se)
- {
- Console.Error.WriteLine(se);
- }
- catch (System.IO.IOException ioe)
- {
- // no big deal
- // assume we should just shutdown now
- Console.Error.WriteLine(ioe);
- }
- catch (System.Exception ie)
- {
- Console.Error.WriteLine(ie);
- throw new System.Exception("A queue operation cannot be interrupted.");
- }
- // no big deal
- lock (this._enclosing.close_blocker)
- {
- if (this.state == org.jawk.ext.Threaded_IO_Style.ACTIVE_STATE)
- {
- this.state = org.jawk.ext.Threaded_IO_Style.CLOSE_PENDING_STATE;
- Monitor.Pulse(this._enclosing.close_blocker);
- }
- }
- }
-
- /// <exception cref="System.Exception"></exception>
- protected abstract string ReadFromQueue();
-
- /// <exception cref="System.Exception"></exception>
- public string GetInput()
- {
- //assert state != CLOSED_STATE; // active or close_pending
- string str = this.ReadFromQueue();
- if (this.queue.Count == 0 && this.state
- == org.jawk.ext.Threaded_IO_Style.CLOSE_PENDING_STATE)
- {
- lock (this._enclosing.close_blocker)
- {
- // could be either ACTIVE or CLOSE_PENDING states
- //assert state != CLOSED_STATE;
- Monitor.Pulse(this._enclosing.close_blocker);
- }
- }
- return str;
- }
-
- // write is defined in subclasses
- public int Flush()
- {
- this.ps.Flush();
- return 1;
- }
-
- public bool IsClosed()
- {
- return this.state == org.jawk.ext.Threaded_IO_Style.CLOSED_STATE;
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- public void Close()
- {
- this.socket.Close();
- }
-
- public abstract int Write(string arg1);
-
- private readonly Threaded_IO_Style _enclosing;
-
- #region IThread Members
-
- private Thread mThread = null;
- public void Start()
- {
- mThread.Start();
- }
-
- public void SetDaemon(bool b)
- {
- mThread.IsBackground = b;
- }
- #endregion
-
- #region IJoinable Members
-
- public void Join()
- {
- mThread.Join();
- }
-
- public void Interrupt()
- {
- mThread.Interrupt();
- }
-
- #endregion
- }
-
- private const int ACTIVE_STATE = 1;
-
- private const int CLOSE_PENDING_STATE = 2;
-
- private const int CLOSED_STATE = 3;
-
- private sealed class CharacterConsumer : org.jawk.ext.Threaded_IO_Style.AbstractConsumer
- <string>
- {
- private readonly System.IO.StreamReader br;
-
- /// <exception cref="System.IO.IOException"></exception>
- public CharacterConsumer(Threaded_IO_Style _enclosing, string handle, TcpClient
- socket) : base(_enclosing, handle, socket)
- {
- this._enclosing = _enclosing;
- // private abstract class AbstractConsumer<T> {Thread} [Consumer]
- // constructs socket (protected field in AbstractConsumer)
- this.br = new StreamReader(socket.GetStream());
- }
-
- ~CharacterConsumer()
- {
- this.br.Dispose();
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- protected sealed override string ReadFromSocket()
- {
- return this.br.ReadLine();
- }
-
- /// <exception cref="System.Exception"></exception>
- protected sealed override string ReadFromQueue()
- {
- return this.queue.Take();
- }
-
- public sealed override int Write(string buf)
- {
- this.ps.WriteLine(buf);
- return 1;
- }
-
- private readonly Threaded_IO_Style _enclosing;
- }
-
- private sealed class ByteConsumer : org.jawk.ext.Threaded_IO_Style.AbstractConsumer
- <int?>
- {
- private readonly Stream bis;
-
- private readonly byte[] buf = new byte[4096];
-
- /// <exception cref="System.IO.IOException"></exception>
- public ByteConsumer(Threaded_IO_Style _enclosing, string handle, TcpClient
- socket)
- : base(_enclosing,handle, socket)
- {
- this._enclosing = _enclosing;
- // constructs socket (protected field in AbstractConsumer)
- this.bis = socket.GetStream();
- }
-
- /// <exception cref="System.IO.IOException"></exception>
- protected sealed override int? ReadFromSocket()
- {
- int len = this.bis.Read(this.buf, 0, this.buf.Length);
- if (len < 0)
- {
- return null;
- }
- else
- {
- return len;
- }
- }
-
- /// <exception cref="System.Exception"></exception>
- protected sealed override string ReadFromQueue()
- {
- int len = this.queue.Take().GetValueOrDefault(0);
-
- string str = System.Text.Encoding.UTF8.GetString(this.buf,0,len);
- return str;
- }
-
- public sealed override int Write(string buf)
- {
- try
- {
- byte[] b = System.Text.Encoding.UTF8.GetBytes(buf);
- this.ps.Write(b);
- return 1;
- }
- catch (System.IO.IOException ioe)
- {
- Console.Error.WriteLine(ioe);
- this._enclosing.last_err = ioe.ToString();
- return 0;
- }
- }
-
- private readonly Threaded_IO_Style _enclosing;
- }
- }
- }