Browse Source

[CS] added sys.net API

some functions missing
not shure about blocking...
Ingo Jakobs 12 years ago
parent
commit
93611f6bd2

+ 63 - 0
std/cs/_std/sys/net/Host.hx

@@ -0,0 +1,63 @@
+
+package sys.net;
+
+import cs.system.Array;
+import cs.system.net.Dns;
+import cs.system.net.IPAddress;
+import cs.system.net.IPHostEntry;
+import cs.system.net.sockets.AddressFamily;
+import haxe.io.Bytes;
+import haxe.io.BytesInput;
+
+/**
+	A given IP host name.
+**/
+@:coreapi 
+class Host {
+	public var hostEntry(default, null) : IPHostEntry;
+	public var ipAddress(default, null) : IPAddress;
+	
+	/**
+		The actual IP corresponding to the host.
+	**/
+	public var ip(get, null) : Int;
+	private function get_ip() : Int {
+		return new BytesInput(Bytes.ofData( ipAddress.GetAddressBytes() )).readInt32();
+	}
+	
+	/**
+		Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case
+		the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found.
+	**/
+	public function new( name : String ) : Void {
+		hostEntry = Dns.GetHostEntry(name);
+		for (i in 0...hostEntry.AddressList.Length) {
+			if (hostEntry.AddressList[i].AddressFamily == InterNetwork) {
+				ipAddress = hostEntry.AddressList[i];
+				break;
+			}
+		}
+	}
+
+	/**
+		Returns the IP representation of the host
+	**/
+	public function toString() : String {
+		return ipAddress.ToString();
+	}
+
+	/**
+		Perform a reverse-DNS query to resolve a host name from an IP.
+	**/
+	public function reverse() : String {
+		return hostEntry.HostName;
+	}
+
+	/**
+		Returns the local computer host name
+	**/
+	static public function localhost() : String {
+		return Dns.GetHostName();
+	}
+
+}

+ 187 - 0
std/cs/_std/sys/net/Socket.hx

@@ -0,0 +1,187 @@
+
+package sys.net;
+
+import cs.system.net.IPEndPoint;
+import cs.system.net.sockets.AddressFamily;
+import cs.system.net.sockets.NetworkStream;
+import cs.system.net.sockets.ProtocolType;
+import cs.system.net.sockets.SocketFlags;
+import cs.system.net.sockets.SocketShutdown;
+import cs.system.net.sockets.SocketType;
+import cs.system.threading.Thread;
+import haxe.io.Bytes;
+import haxe.io.Error;
+import haxe.io.Input;
+import haxe.io.Output;
+
+/**
+	A TCP socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections.
+**/
+@:coreapi 
+class Socket {
+	private var sock : cs.system.net.sockets.Socket = null;
+	
+	/**
+		The stream on which you can read available data. By default the stream is blocking until the requested data is available,
+		use [setBlocking(false)] or [setTimeout] to prevent infinite waiting.
+	**/
+	public var input(default,null) : haxe.io.Input;
+
+	/**
+		The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use [setBlocking(false)] or [setTimeout] to prevent that.
+	**/
+	public var output(default,null) : haxe.io.Output;
+
+	/**
+		A custom value that can be associated with the socket. Can be used to retreive your custom infos after a [select].
+	***/
+	public var custom : Dynamic;
+
+	/**
+		Creates a new unconnected socket.
+	**/
+	public function new() : Void {
+		sock = new cs.system.net.sockets.Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
+		sock.Blocking = true;
+	}
+
+	/**
+		Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors.
+	**/
+	public function close() : Void {
+		sock.Close();
+		input = null;
+		output = null;
+	}
+
+	/**
+		Read the whole data available on the socket.
+	**/
+	public function read() : String {
+		return input.readAll().toString();
+	}
+
+	/**
+		Write the whole data to the socket output.
+	**/
+	public function write( content : String ) : Void {
+		output.writeString( content );
+	}
+
+	/**
+		Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
+	**/
+	public function connect( host : Host, port : Int ) : Void {
+		sock.Connect( host.ipAddress, port );
+		if (sock.Connected) {
+			this.output = new cs.io.NativeOutput( new NetworkStream(sock) );
+			this.input = new cs.io.NativeInput( new NetworkStream(sock) );
+		} else {
+			throw "Connection failed.";
+		}
+	}
+
+	/**
+		Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections.
+	**/
+	public function listen( connections : Int ) : Void {
+		sock.Listen( connections );
+	}
+
+	/**
+		Shutdown the socket, either for reading or writing.
+	**/
+	public function shutdown( read : Bool, write : Bool ) : Void {
+		if ( read && write ) {
+			sock.Shutdown( SocketShutdown.Both );
+			input = null;
+			output = null;
+		} else if ( read ) {
+			sock.Shutdown( SocketShutdown.Receive );
+			input = null;
+		} else if ( write ) {
+			sock.Shutdown( SocketShutdown.Send );
+			output = null;
+		}
+	}
+
+	/**
+		Bind the socket to the given host/port so it can afterwards listen for connections there.
+	**/
+	public function bind( host : Host, port : Int ) : Void {
+		sock = new cs.system.net.sockets.Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
+		sock.Bind( new IPEndPoint(host.ipAddress, port) );
+	}
+
+	/**
+		Accept a new connected client. This will return a connected socket on which you can read/write some data.
+	**/
+	public function accept() : Socket {
+		var r = new Socket();
+		r.sock = sock.Accept();
+		r.output = new cs.io.NativeOutput( new NetworkStream(r.sock) );
+		r.input = new cs.io.NativeInput( new NetworkStream(r.sock) );
+		return r;
+	}
+
+	/**
+		Return the informations about the other side of a connected socket.
+	**/
+	public function peer() : { host : Host, port : Int } {
+		var remoteIP = cast(sock.RemoteEndPoint, IPEndPoint);
+		return { host: new Host(remoteIP.Address.ToString()), port: remoteIP.Port };
+	}
+
+	/**
+		Return the informations about our side of a connected socket.
+	**/
+	public function host() : { host : Host, port : Int } {
+		var localIP = cast(sock.LocalEndPoint, IPEndPoint);
+		return { host: new Host(localIP.Address.ToString()), port: localIP.Port };
+	}
+
+	/**
+		Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception.
+	**/
+	public function setTimeout( timeout : Float ) : Void {
+		sock.ReceiveTimeout = sock.SendTimeout = Math.round(timeout * 1000);
+	}
+
+	/**
+		Block until some data is available for read on the socket.
+	**/
+	public function waitForRead() : Void {
+		var end = Date.now().getTime() + ((sock.ReceiveTimeout <= 0) ? Math.POSITIVE_INFINITY : sock.ReceiveTimeout);
+		while ( sock.Available == 0 && Date.now().getTime() < end) {
+			Thread.Sleep(5);
+		}
+	}
+	
+	/**
+		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
+	**/
+	public function setBlocking( b : Bool ) : Void {
+		sock.Blocking = b;
+	}
+	
+	/**
+		Allows the socket to immediatly send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
+	**/
+	public function setFastSend( b : Bool ) : Void {
+		sock.NoDelay = b;
+	}
+
+	/**
+		Wait until one of the sockets groups is ready for the given operation :
+		[read] contains sockets on which we want to wait for available data to be read,
+		[write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers,
+		[others] contains sockets on which we want to wait for exceptional conditions.
+		[select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true.
+		In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires.
+	**/
+	static public function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float) : { read: Array<Socket>,write: Array<Socket>,others: Array<Socket> } {
+		throw "Not implemented yet.";
+		return null;
+	}
+
+}

+ 24 - 0
std/cs/system/net/Dns.hx

@@ -0,0 +1,24 @@
+
+package cs.system.net;
+
+import Array;
+
+@:native("System.Net.Dns") 
+extern class Dns
+{
+	/**
+	 * Returns the Internet Protocol (IP) addresses for the specified host.
+	 */
+	public static function GetHostAddresses(hostNameOrAddress : String) : Array<IPAddress>;
+	
+	/**
+	 * Resolves an IP address to an IPHostEntry instance.
+	 */
+	@:overload(function ( address : IPAddress ) : IPHostEntry { } )
+	public static function GetHostEntry( hostNameOrAddress : String ) : IPHostEntry;
+	
+	/**
+	 * Gets the host name of the local computer.
+	 */
+	public static function GetHostName() : String;
+}

+ 10 - 0
std/cs/system/net/EndPoint.hx

@@ -0,0 +1,10 @@
+
+package cs.system.net;
+
+@:native("System.Net.EndPoint") 
+extern class EndPoint {
+	/**
+	 * Gets the address family to which the endpoint belongs.
+	 */
+	public var AddressFamily (get, never) : cs.system.net.sockets.AddressFamily;
+}

+ 26 - 0
std/cs/system/net/IPAddress.hx

@@ -0,0 +1,26 @@
+
+package cs.system.net;
+
+@:native("System.Net.IPAddress")
+extern class IPAddress
+{
+	/**
+	 * Provides a copy of the IPAddress as an array of bytes.
+	 */
+	public function GetAddressBytes() : haxe.io.BytesData;
+	
+	/**
+	 * Gets the address family of the IP address.
+	 */
+	public var AddressFamily(default, never) : cs.system.net.sockets.AddressFamily;
+	
+	/**
+	 * Determines whether a string is a valid IP address.
+	 * @param	ipString	The string to validate.
+	 * @param	address		(out) The IPAddress version of the string.
+	 * @return true if ipString is a valid IP address; otherwise, false.
+	 */
+	public static function TryParse( ipString : String, /* out */ address : IPAddress ) : Bool;
+	
+	public function ToString() : String;
+}

+ 14 - 0
std/cs/system/net/IPEndPoint.hx

@@ -0,0 +1,14 @@
+
+package cs.system.net;
+
+@:native("System.Net.IPEndPoint") 
+extern class IPEndPoint extends EndPoint {
+	
+	/**
+	 * Initializes a new instance of the IPEndPoint class with the specified address and port number.
+	 */
+	public function new( address : IPAddress, port : Int);
+	
+	public var Address (default, default) : IPAddress;
+	public var Port (default, default) : Int;
+}

+ 21 - 0
std/cs/system/net/IPHostEntry.hx

@@ -0,0 +1,21 @@
+
+package cs.system.net;
+
+@:native("System.Net.IPHostEntry") 
+extern class IPHostEntry
+{
+	/**
+	 * Gets or sets a list of IP addresses that are associated with a host.
+	 */
+	public var AddressList(default, default) : NativeArray<IPAddress>;
+	
+	/**
+	 * Gets or sets a list of aliases that are associated with a host.
+	 */
+	public var Aliases(default, default) : NativeArray<String>;
+	
+	/**
+	 * Gets or sets the DNS name of the host.
+	 */
+	public var HostName (default, default) : String;
+}

+ 37 - 0
std/cs/system/net/sockets/AddressFamily.hx

@@ -0,0 +1,37 @@
+
+package cs.system.net.sockets;
+
+@:native("System.Net.Sockets.AddressFamily")
+extern enum AddressFamily {
+	Unknown; // Unbekannte Adressfamilie. 
+	Unspecified; // Nicht definierte Adressfamilie. 
+	Unix; // UNIX-Hostadresse. 
+	InterNetwork; // Adresse für IP Version 4. 
+	ImpLink; // ARPANET IMP-Adresse. 
+	Pup; // Adresse für PUP-Protokolle. 
+	Chaos; // Adresse für MIT CHAOS-Protokolle. 
+	NS; // Adresse für Xerox NS-Protokolle. 
+	Ipx; // IPX- oder SPX-Adresse. 
+	Iso; // Adresse für ISO-Protokolle. 
+	Osi; // Adresse für ISO-Protokolle. 
+	Ecma; // ECMA-Adresse (European Computer Manufacturers Association). 
+	DataKit; // Adresse für Datakit-Protokolle. 
+	Ccitt; // Adressen für CCITT-Protokolle, z. B. X.25. 
+	Sna; // IBM SNA-Adresse. 
+	DecNet; // DECnet-Adresse. 
+	DataLink; // Adresse der Direct Data Link-Schnittstelle. 
+	Lat; // LAT-Adresse. 
+	HyperChannel; // NSC Hyperchannel-Adresse. 
+	AppleTalk; // AppleTalk-Adresse. 
+	NetBios; // NetBios-Adresse. 
+	VoiceView; // VoiceView-Adresse. 
+	FireFox; // FireFox-Adresse. 
+	Banyan; // Banyan-Adresse. 
+	Atm; // Systemeigene Adresse für ATM-Dienste. 
+	InterNetworkV6; // Adresse für IP Version 6. 
+	Cluster; // Adresse für Microsoft Cluster-Produkte. 
+	Ieee12844; // Adresse der IEEE 1284.4-Arbeitsgruppe. 
+	Irda; // IrDA-Adresse. 
+	NetworkDesigners; // Adresse für Network Designers OSI-Gateway-fähige Protokolle. 
+	Max; //MAX-Adresse. 
+}

+ 22 - 0
std/cs/system/net/sockets/NetworkStream.hx

@@ -0,0 +1,22 @@
+
+package cs.system.net.sockets;
+
+import cs.system.io.Stream;
+
+@:native("System.Net.Sockets.NetworkStream") 
+extern class NetworkStream extends Stream{
+	public function new( socket : Socket );
+	
+	/**
+	 * This method reads data into the buffer parameter and returns the number of bytes successfully read. 
+	 * If no data is available for reading, the Read method returns 0.
+	 * The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter.
+	 */
+	public override function Read( buffer : haxe.io.BytesData, offset : Int, size : Int ) : Int;
+	
+	/**
+	 * The Write method starts at the specified offset and sends size bytes from the contents of buffer to the network. 
+	 * The Write method blocks until the requested number of bytes is sent or a SocketException is thrown.
+	 */
+	public override function Write( buffer : haxe.io.BytesData, offset : Int, size : Int ) : Void;
+}

+ 31 - 0
std/cs/system/net/sockets/ProtocolType.hx

@@ -0,0 +1,31 @@
+
+package cs.system.net.sockets;
+
+@:native("System.Net.Sockets.ProtocolType")
+extern enum ProtocolType {
+	IP; // Internet Protocol. 
+	IPv6HopByHopOptions; // IPv6 Hop by Hop Options header. 
+	Icmp; // Internet Control Message Protocol. 
+	Igmp; // Internet Group Management Protocol. 
+	Ggp; // Gateway To Gateway Protocol. 
+	IPv4; // Internet Protocol version 4. 
+	Tcp; // Transmission Control Protocol. 
+	Pup; // PARC Universal Packet Protocol. 
+	Udp; // User Datagram Protocol. 
+	Idp; // Internet Datagram Protocol. 
+	IPv6; // Internet Protocol version 6 (IPv6).  
+	IPv6RoutingHeader; // IPv6 Routing header. 
+	IPv6FragmentHeader; // IPv6 Fragment header. 
+	IPSecEncapsulatingSecurityPayload; // IPv6 Encapsulating Security Payload header. 
+	IPSecAuthenticationHeader; // IPv6 Authentication header. For details, see RFC 2292 section 2.2.1, available at http://www.ietf.org. 
+	IcmpV6; // Internet Control Message Protocol for IPv6. 
+	IPv6NoNextHeader; // IPv6 No next header. 
+	IPv6DestinationOptions; // IPv6 Destination Options header. 
+	ND; // Net Disk Protocol (unofficial). 
+	Raw; // Raw IP packet protocol. 
+	Unspecified; // Unspecified protocol. 
+	Ipx; // Internet Packet Exchange Protocol. 
+	Spx; // Sequenced Packet Exchange protocol. 
+	SpxII; // Sequenced Packet Exchange version 2 protocol. 
+	Unknown; // Unknown protocol. 
+}

+ 95 - 0
std/cs/system/net/sockets/Socket.hx

@@ -0,0 +1,95 @@
+
+package cs.system.net.sockets;
+
+@:native("System.Net.Sockets.Socket") 
+extern class Socket {
+	public function new ( addressFamily : AddressFamily, socketType : SocketType, protocolType : ProtocolType );
+	
+	/**
+	 * Gets the amount of data that has been received from the network and is available to be read.
+	 */
+	public var Available (default, never) : Int;
+	
+	/**
+	 * Gets or sets a value that indicates whether the Socket is in blocking mode.
+	 */
+	public var Blocking (default, default) : Bool;
+	
+	/**
+	 * Gets a value that indicates whether a Socket is connected to a remote host as of the last Send or Receive operation.
+	 */
+	public var Connected (default, never) : Bool;
+	
+	/**
+	 * The LocalEndPoint property gets an EndPoint that contains the local IP address and port number to which your Socket is bound.
+	 * You must cast this EndPoint to an IPEndPoint before retrieving any information.
+	 */
+	public var LocalEndPoint (default, never) : cs.system.net.EndPoint;
+	
+	/**
+	 * Gets or sets a Boolean value that specifies whether the stream Socket is using the Nagle algorithm.
+	 */
+	public var NoDelay(default, default) : Bool;
+	
+	/**
+	 * The time-out value, in milliseconds. 
+	 * The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.
+	 */
+	public var ReceiveTimeout (default, default) : Int;
+	
+	/**
+	 * If you are using a connection-oriented protocol, the RemoteEndPoint property gets the EndPoint that contains the remote IP address and port number to which the Socket is connected.
+	 */
+	public var RemoteEndPoint (default, null) : cs.system.net.EndPoint;
+	
+	/**
+	 * The time-out value, in milliseconds. 
+	 * If you set the property with a value between 1 and 499, the value will be changed to 500. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.
+	 */
+	public var SendTimeout (default, default) : Int;
+	
+	
+	/**
+	 * Creates a new Socket for a newly created connection.
+	 */
+	public function Accept() : Socket;
+	
+	/**
+	 * Associates a Socket with a local endpoint.
+	 */
+	public function Bind(localEP : EndPoint) : Void;
+	
+	/**
+	 * Establishes a connection to a remote host. The host is specified by an IP address and a port number.
+	 */
+	public function Connect(address : IPAddress, port : Int) : Void;
+	
+	/**
+	 * Closes the Socket connection and releases all associated resources.
+	 */
+	public function Close() : Void;
+	
+	/**
+	 * Places a Socket in a listening state.
+	 * @param	backlog		The maximum length of the pending connections queue. 
+	 */
+	public function Listen(	backlog : Int ) : Void;
+	
+	/**
+	 * Receives the specified number of bytes of data from a bound Socket into a receive buffer, using the specified SocketFlags.
+	 * @return The number of bytes received.
+	 */
+	@:overload(function ( buffer : haxe.io.BytesData ) : Int { } ) 
+	public function Receive( buffer : haxe.io.BytesData, size : Int, socketFlags : SocketFlags ) : Int;
+	
+	/**
+	 * Send synchronously sends data to the remote host specified in the Connect or Accept method and returns the number of bytes successfully sent.
+	 */
+	public function Send( buffer : haxe.io.BytesData ) : Int;
+	
+	/**
+	 * Disables sends and receives on a Socket.
+	 * @param	how		One of the SocketShutdown values that specifies the operation that will no longer be allowed.
+	 */
+	public function Shutdown(how : SocketShutdown) : Void;
+}

+ 16 - 0
std/cs/system/net/sockets/SocketFlags.hx

@@ -0,0 +1,16 @@
+
+package cs.system.net.sockets;
+
+@:native("System.Net.Sockets.SocketFlags")
+extern enum SocketFlags {
+	None; // Use no flags for this call. 
+	OutOfBand; // Process out-of-band data. 
+	Peek; // Peek at the incoming message. 
+	DontRoute; // Send without using routing tables. 
+	MaxIOVectorLength; // Provides a standard value for the number of WSABUF structures that are used to send and receive data. 
+	Truncated; // The message was too large to fit into the specified buffer and was truncated. 
+	ControlDataTruncated; // Indicates that the control data did not fit into an internal 64-KB buffer and was truncated. 
+	Broadcast; // Indicates a broadcast packet. 
+	Multicast; // Indicates a multicast packet. 
+	Partial; // Partial send or receive for message. 
+}

+ 9 - 0
std/cs/system/net/sockets/SocketShutdown.hx

@@ -0,0 +1,9 @@
+
+package cs.system.net.sockets;
+
+@:native("System.Net.Sockets.SocketShutdown")
+extern enum SocketShutdown {
+	Receive; // Disables a Socket for receiving. This field is constant. 
+	Send; // Disables a Socket for sending. This field is constant. 
+	Both; // Disables a Socket for both sending and receiving. This field is constant. 
+}

+ 12 - 0
std/cs/system/net/sockets/SocketType.hx

@@ -0,0 +1,12 @@
+
+package cs.system.net.sockets;
+
+@:native("System.Net.Sockets.SocketType")
+extern enum SocketType {
+	Stream; // Supports reliable, two - way, connection - based byte streams without the duplication of data and without preservation of boundaries. A Socket of this type communicates with a single peer and requires a remote host connection before communication can begin. Stream uses the Transmission Control Protocol (Tcp) ProtocolType and the InterNetwork AddressFamily. 
+	Dgram; // Supports datagrams, which are connectionless, unreliable messages of a fixed (typically small) maximum length. Messages might be lost or duplicated and might arrive out of order. A Socket of type Dgram requires no connection prior to sending and receiving data, and can communicate with multiple peers. Dgram uses the Datagram Protocol (Udp) and the InterNetwork AddressFamily. 
+	Raw; // Supports access to the underlying transport protocol. Using the SocketType Raw, you can communicate using protocols like Internet Control Message Protocol (Icmp) and Internet Group Management Protocol (Igmp). Your application must provide a complete IP header when sending. Received datagrams return with the IP header and options intact. 
+	Rdm; // Supports connectionless, message-oriented, reliably delivered messages, and preserves message boundaries in data. Rdm (Reliably Delivered Messages) messages arrive unduplicated and in order. Furthermore, the sender is notified if messages are lost. If you initialize a Socket using Rdm, you do not require a remote host connection before sending and receiving data. With Rdm, you can communicate with multiple peers. 
+	Seqpacket; // Provides connection-oriented and reliable two-way transfer of ordered byte streams across a network. Seqpacket does not duplicate data, and it preserves boundaries within the data stream. A Socket of type Seqpacket communicates with a single peer and requires a remote host connection before communication can begin. 
+	Unknown; // Specifies an unknown Socket type.
+}