| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of dart.io; |
| |
| /// The type, or address family, of an [InternetAddress]. |
| /// |
| /// Currently, IP version 4 (IPv4), IP version 6 (IPv6) |
| /// and Unix domain address are supported. |
| /// Unix domain sockets are available only on Linux, MacOS and Android. |
| class InternetAddressType { |
| static const InternetAddressType IPv4 = const InternetAddressType._(0); |
| static const InternetAddressType IPv6 = const InternetAddressType._(1); |
| @Since("2.8") |
| static const InternetAddressType unix = const InternetAddressType._(2); |
| static const InternetAddressType any = const InternetAddressType._(-1); |
| |
| @Deprecated("Use IPv4 instead") |
| static const InternetAddressType IP_V4 = IPv4; |
| @Deprecated("Use IPv6 instead") |
| static const InternetAddressType IP_V6 = IPv6; |
| @Deprecated("Use any instead") |
| static const InternetAddressType ANY = any; |
| |
| final int _value; |
| |
| const InternetAddressType._(this._value); |
| |
| factory InternetAddressType._from(int value) { |
| if (value == IPv4._value) return IPv4; |
| if (value == IPv6._value) return IPv6; |
| if (value == unix._value) return unix; |
| throw new ArgumentError("Invalid type: $value"); |
| } |
| |
| /// Get the name of the type, e.g. "IPv4" or "IPv6". |
| String get name => const ["ANY", "IPv4", "IPv6", "Unix"][_value + 1]; |
| |
| String toString() => "InternetAddressType: $name"; |
| } |
| |
| /// An internet address or a Unix domain address. |
| /// |
| /// This object holds an internet address. If this internet address |
| /// is the result of a DNS lookup, the address also holds the hostname |
| /// used to make the lookup. |
| /// An Internet address combined with a port number represents an |
| /// endpoint to which a socket can connect or a listening socket can |
| /// bind. |
| abstract class InternetAddress { |
| /// IP version 4 loopback address. |
| /// |
| /// Use this address when listening on or connecting |
| /// to the loopback adapter using IP version 4 (IPv4). |
| static InternetAddress get loopbackIPv4 => LOOPBACK_IP_V4; |
| @Deprecated("Use loopbackIPv4 instead") |
| external static InternetAddress get LOOPBACK_IP_V4; |
| |
| /// IP version 6 loopback address. |
| /// |
| /// Use this address when listening on or connecting to |
| /// the loopback adapter using IP version 6 (IPv6). |
| static InternetAddress get loopbackIPv6 => LOOPBACK_IP_V6; |
| @Deprecated("Use loopbackIPv6 instead") |
| external static InternetAddress get LOOPBACK_IP_V6; |
| |
| /// IP version 4 any address. |
| /// |
| /// Use this address when listening on the addresses |
| /// of all adapters using IP version 4 (IPv4). |
| static InternetAddress get anyIPv4 => ANY_IP_V4; |
| @Deprecated("Use anyIPv4 instead") |
| external static InternetAddress get ANY_IP_V4; |
| |
| /// IP version 6 any address. |
| /// |
| /// Use this address when listening on the addresses |
| /// of all adapters using IP version 6 (IPv6). |
| static InternetAddress get anyIPv6 => ANY_IP_V6; |
| @Deprecated("Use anyIPv6 instead") |
| external static InternetAddress get ANY_IP_V6; |
| |
| /// The address family of the [InternetAddress]. |
| InternetAddressType get type; |
| |
| /// The numeric address of the host. |
| /// |
| /// For IPv4 addresses this is using the dotted-decimal notation. |
| /// For IPv6 it is using the hexadecimal representation. |
| /// For Unix domain addresses, this is a file path. |
| String get address; |
| |
| /// The host used to lookup the address. |
| /// |
| /// If there is no host associated with the address this returns the [address]. |
| String get host; |
| |
| /// The raw address of this [InternetAddress]. |
| /// |
| /// For an IP address, the result is either a 4 or 16 byte long list. |
| /// For a Unix domain address, UTF-8 encoded byte sequences that represents |
| /// [address] is returned. |
| /// |
| /// The returned list is a fresh copy, making it possible to change the list without |
| /// modifying the [InternetAddress]. |
| Uint8List get rawAddress; |
| |
| /// Whether the [InternetAddress] is a loopback address. |
| bool get isLoopback; |
| |
| /// Whether the scope of the [InternetAddress] is a link-local. |
| bool get isLinkLocal; |
| |
| /// Whether the scope of the [InternetAddress] is multicast. |
| bool get isMulticast; |
| |
| /// Creates a new [InternetAddress] from a numeric address or a file path. |
| /// |
| /// If [type] is [InternetAddressType.IPv4], [address] must be a numeric IPv4 |
| /// address (dotted-decimal notation). |
| /// If [type] is [InternetAddressType.IPv6], [address] must be a numeric IPv6 |
| /// address (hexadecimal notation). |
| /// If [type] is [InternetAddressType.unix], [address] must be a a valid file |
| /// path. |
| /// If [type] is omitted, [address] must be either a numeric IPv4 or IPv6 |
| /// address and the type is inferred from the format. |
| external factory InternetAddress(String address, |
| {@Since("2.8") InternetAddressType? type}); |
| |
| /// Creates a new [InternetAddress] from the provided raw address bytes. |
| /// |
| /// If the [type] is [InternetAddressType.IPv4], the [rawAddress] must have |
| /// length 4. |
| /// If the [type] is [InternetAddressType.IPv6], the [rawAddress] must have |
| /// length 16. |
| /// If the [type] is [InternetAddressType.unix], the [rawAddress] must be a |
| /// valid UTF-8 encoded file path. |
| /// |
| /// If [type] is omitted, the [rawAddress] must have a length of either 4 or |
| /// 16, in which case the type defaults to [InternetAddressType.IPv4] or |
| /// [InternetAddressType.IPv6] respectively. |
| external factory InternetAddress.fromRawAddress(Uint8List rawAddress, |
| {@Since("2.8") InternetAddressType? type}); |
| |
| /// Performs a reverse DNS lookup on this [address] |
| /// |
| /// Returns a new [InternetAddress] with the same address, but where the [host] |
| /// field set to the result of the lookup. |
| /// |
| /// If this address is Unix domain addresses, no lookup is performed and this |
| /// address is returned directly. |
| Future<InternetAddress> reverse(); |
| |
| /// Looks up the addresses of a host. |
| /// |
| /// If [type] is [InternetAddressType.any], it will lookup both |
| /// IP version 4 (IPv4) and IP version 6 (IPv6) addresses. |
| /// If [type] is either [InternetAddressType.IPv4] or |
| /// [InternetAddressType.IPv6] it will only lookup addresses of the |
| /// specified type. The order of the list can, and most likely will, |
| /// change over time. |
| external static Future<List<InternetAddress>> lookup(String host, |
| {InternetAddressType type = InternetAddressType.any}); |
| |
| /// Clones the given [address] with the new [host]. |
| /// |
| /// The [address] must be an [InternetAddress] that was created with one |
| /// of the static methods of this class. |
| external static InternetAddress _cloneWithNewHost( |
| InternetAddress address, String host); |
| |
| /// Attempts to parse [address] as a numeric address. |
| /// |
| /// Returns `null` If [address] is not a numeric IPv4 (dotted-decimal |
| /// notation) or IPv6 (hexadecimal representation) address. |
| external static InternetAddress? tryParse(String address); |
| } |
| |
| /// A [NetworkInterface] represents an active network interface on the current |
| /// system. It contains a list of [InternetAddress]es that are bound to the |
| /// interface. |
| abstract class NetworkInterface { |
| /// The name of the [NetworkInterface]. |
| String get name; |
| |
| /// The index of the [NetworkInterface]. |
| int get index; |
| |
| /// The list of [InternetAddress]es currently bound to this |
| /// [NetworkInterface]. |
| List<InternetAddress> get addresses; |
| |
| /// Whether the [list] method is supported. |
| /// |
| /// The [list] method is currently unsupported on Android. |
| external static bool get listSupported; |
| |
| /// Query the system for [NetworkInterface]s. |
| /// |
| /// If [includeLoopback] is `true`, the returned list will include the |
| /// loopback device. Default is `false`. |
| /// |
| /// If [includeLinkLocal] is `true`, the list of addresses of the returned |
| /// [NetworkInterface]s, may include link local addresses. Default is `false`. |
| /// |
| /// If [type] is either [InternetAddressType.IPv4] or |
| /// [InternetAddressType.IPv6] it will only lookup addresses of the |
| /// specified type. Default is [InternetAddressType.any]. |
| external static Future<List<NetworkInterface>> list( |
| {bool includeLoopback = false, |
| bool includeLinkLocal = false, |
| InternetAddressType type = InternetAddressType.any}); |
| } |
| |
| /// A listening socket. |
| /// |
| /// A `RawServerSocket` and provides a stream of low-level [RawSocket] objects, |
| /// one for each connection made to the listening socket. |
| /// |
| /// See [RawSocket] for more info. |
| abstract class RawServerSocket implements Stream<RawSocket> { |
| /// Listens on a given address and port. |
| /// |
| /// When the returned future completes the server socket is bound |
| /// to the given [address] and [port] and has started listening on it. |
| /// |
| /// The [address] can either be a [String] or an |
| /// [InternetAddress]. If [address] is a [String], [bind] will |
| /// perform a [InternetAddress.lookup] and use the first value in the |
| /// list. To listen on the loopback adapter, which will allow only |
| /// incoming connections from the local host, use the value |
| /// [InternetAddress.loopbackIPv4] or |
| /// [InternetAddress.loopbackIPv6]. To allow for incoming |
| /// connection from the network use either one of the values |
| /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to |
| /// bind to all interfaces or the IP address of a specific interface. |
| /// |
| /// If an IP version 6 (IPv6) address is used, both IP version 6 |
| /// (IPv6) and version 4 (IPv4) connections will be accepted. To |
| /// restrict this to version 6 (IPv6) only, use [v6Only] to set |
| /// version 6 only. |
| /// |
| /// If [port] has the value `0` an ephemeral port will |
| /// be chosen by the system. The actual port used can be retrieved |
| /// using the `port` getter. |
| /// |
| /// The optional argument [backlog] can be used to specify the listen |
| /// backlog for the underlying OS listen setup. If [backlog] has the |
| /// value of `0` (the default) a reasonable value will be chosen by |
| /// the system. |
| /// |
| /// The optional argument [shared] specifies whether additional RawServerSocket |
| /// objects can bind to the same combination of [address], [port] and [v6Only]. |
| /// If [shared] is `true` and more [RawServerSocket]s from this isolate or |
| /// other isolates are bound to the port, then the incoming connections will be |
| /// distributed among all the bound [RawServerSocket]s. Connections can be |
| /// distributed over multiple isolates this way. |
| external static Future<RawServerSocket> bind(address, int port, |
| {int backlog = 0, bool v6Only = false, bool shared = false}); |
| |
| /// The port used by this socket. |
| int get port; |
| |
| /// The address used by this socket. |
| InternetAddress get address; |
| |
| /// Closes the socket. |
| /// |
| /// The returned future completes when the socket |
| /// is fully closed and is no longer bound. |
| Future<RawServerSocket> close(); |
| } |
| |
| /// A listening socket. |
| /// |
| /// A [ServerSocket] provides a stream of [Socket] objects, |
| /// one for each connection made to the listening socket. |
| /// |
| /// See [Socket] for more info. |
| abstract class ServerSocket implements Stream<Socket> { |
| /// Listens on a given address and port. |
| /// |
| /// When the returned future completes the server socket is bound |
| /// to the given [address] and [port] and has started listening on it. |
| /// |
| /// The [address] can either be a [String] or an |
| /// [InternetAddress]. If [address] is a [String], [bind] will |
| /// perform a [InternetAddress.lookup] and use the first value in the |
| /// list. To listen on the loopback adapter, which will allow only |
| /// incoming connections from the local host, use the value |
| /// [InternetAddress.loopbackIPv4] or |
| /// [InternetAddress.loopbackIPv6]. To allow for incoming |
| /// connection from the network use either one of the values |
| /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to |
| /// bind to all interfaces or the IP address of a specific interface. |
| /// |
| /// If an IP version 6 (IPv6) address is used, both IP version 6 |
| /// (IPv6) and version 4 (IPv4) connections will be accepted. To |
| /// restrict this to version 6 (IPv6) only, use [v6Only] to set |
| /// version 6 only. |
| /// |
| /// If [port] has the value `0` an ephemeral port will be chosen by |
| /// the system. The actual port used can be retrieved using the |
| /// [port] getter. |
| /// |
| /// The optional argument [backlog] can be used to specify the listen |
| /// backlog for the underlying OS listen setup. If [backlog] has the |
| /// value of `0` (the default) a reasonable value will be chosen by |
| /// the system. |
| /// |
| /// The optional argument [shared] specifies whether additional ServerSocket |
| /// objects can bind to the same combination of [address], [port] and |
| /// [v6Only]. If [shared] is `true` and more server sockets from this |
| /// isolate or other isolates are bound to the port, then the incoming |
| /// connections will be distributed among all the bound server sockets. |
| /// Connections can be distributed over multiple isolates this way. |
| static Future<ServerSocket> bind(address, int port, |
| {int backlog = 0, bool v6Only = false, bool shared = false}) { |
| final IOOverrides? overrides = IOOverrides.current; |
| if (overrides == null) { |
| return ServerSocket._bind(address, port, |
| backlog: backlog, v6Only: v6Only, shared: shared); |
| } |
| return overrides.serverSocketBind(address, port, |
| backlog: backlog, v6Only: v6Only, shared: shared); |
| } |
| |
| external static Future<ServerSocket> _bind(address, int port, |
| {int backlog = 0, bool v6Only = false, bool shared = false}); |
| |
| /// The port used by this socket. |
| int get port; |
| |
| /// The address used by this socket. |
| InternetAddress get address; |
| |
| /// Closes the socket. |
| /// |
| /// The returned future completes when the socket |
| /// is fully closed and is no longer bound. |
| Future<ServerSocket> close(); |
| } |
| |
| /// The [SocketDirection] is used as a parameter to [Socket.close] and |
| /// [RawSocket.close] to close a socket in the specified direction(s). |
| class SocketDirection { |
| static const SocketDirection receive = const SocketDirection._(0); |
| static const SocketDirection send = const SocketDirection._(1); |
| static const SocketDirection both = const SocketDirection._(2); |
| |
| @Deprecated("Use receive instead") |
| static const SocketDirection RECEIVE = receive; |
| @Deprecated("Use send instead") |
| static const SocketDirection SEND = send; |
| @Deprecated("Use both instead") |
| static const SocketDirection BOTH = both; |
| |
| final _value; |
| |
| const SocketDirection._(this._value); |
| } |
| |
| /// An option for a socket which is configured using [Socket.setOption]. |
| /// |
| /// The [SocketOption] is used as a parameter to [Socket.setOption] and |
| /// [RawSocket.setOption] to customize the behaviour of the underlying |
| /// socket. |
| class SocketOption { |
| /// Enable or disable no-delay on the socket. If tcpNoDelay is enabled, the |
| /// socket will not buffer data internally, but instead write each data chunk |
| /// as an individual TCP packet. |
| /// |
| /// tcpNoDelay is disabled by default. |
| static const SocketOption tcpNoDelay = const SocketOption._(0); |
| @Deprecated("Use tcpNoDelay instead") |
| static const SocketOption TCP_NODELAY = tcpNoDelay; |
| |
| static const SocketOption _ipMulticastLoop = const SocketOption._(1); |
| static const SocketOption _ipMulticastHops = const SocketOption._(2); |
| static const SocketOption _ipMulticastIf = const SocketOption._(3); |
| static const SocketOption _ipBroadcast = const SocketOption._(4); |
| |
| final _value; |
| |
| const SocketOption._(this._value); |
| } |
| |
| // Must be kept in sync with enum in socket.cc |
| enum _RawSocketOptions { |
| SOL_SOCKET, // 0 |
| IPPROTO_IP, // 1 |
| IP_MULTICAST_IF, // 2 |
| IPPROTO_IPV6, // 3 |
| IPV6_MULTICAST_IF, // 4 |
| IPPROTO_TCP, // 5 |
| IPPROTO_UDP, // 6 |
| } |
| |
| /// The [RawSocketOption] is used as a parameter to [Socket.setRawOption] and |
| /// [RawSocket.setRawOption] to customize the behaviour of the underlying |
| /// socket. |
| /// |
| /// It allows for fine grained control of the socket options, and its values |
| /// will be passed to the underlying platform's implementation of setsockopt and |
| /// getsockopt. |
| @Since("2.2") |
| class RawSocketOption { |
| /// Creates a [RawSocketOption] for [RawSocket.getRawOption] |
| /// and [RawSocket.setRawOption]. |
| /// |
| /// The [level] and [option] arguments correspond to `level` and `optname` arguments |
| /// on the `getsockopt()` and `setsockopt()` native calls. |
| /// |
| /// The value argument and its length correspond to the optval and length |
| /// arguments on the native call. |
| /// |
| /// For a [RawSocket.getRawOption] call, the value parameter will be updated |
| /// after a successful call (although its length will not be changed). |
| /// |
| /// For a [RawSocket.setRawOption] call, the value parameter will be used set |
| /// the option. |
| const RawSocketOption(this.level, this.option, this.value); |
| |
| /// Convenience constructor for creating an integer based [RawSocketOption]. |
| factory RawSocketOption.fromInt(int level, int option, int value) { |
| final Uint8List list = Uint8List(4); |
| final buffer = ByteData.view(list.buffer, list.offsetInBytes); |
| buffer.setInt32(0, value, Endian.host); |
| return RawSocketOption(level, option, list); |
| } |
| |
| /// Convenience constructor for creating a boolean based [RawSocketOption]. |
| factory RawSocketOption.fromBool(int level, int option, bool value) => |
| RawSocketOption.fromInt(level, option, value ? 1 : 0); |
| |
| /// The level for the option to set or get. |
| /// |
| /// See also: |
| /// * [RawSocketOption.levelSocket] |
| /// * [RawSocketOption.levelIPv4] |
| /// * [RawSocketOption.levelIPv6] |
| /// * [RawSocketOption.levelTcp] |
| /// * [RawSocketOption.levelUdp] |
| final int level; |
| |
| /// The numeric ID of the option to set or get. |
| final int option; |
| |
| /// The raw data to set, or the array to write the current option value into. |
| /// |
| /// This list must be the correct length for the expected option. For most |
| /// options that take [int] or [bool] values, the length should be 4. For options |
| /// that expect a struct (such as an in_addr_t), the length should be the |
| /// correct length for that struct. |
| final Uint8List value; |
| |
| /// Socket level option for `SOL_SOCKET`. |
| static int get levelSocket => |
| _getOptionValue(_RawSocketOptions.SOL_SOCKET.index); |
| |
| /// Socket level option for `IPPROTO_IP`. |
| static int get levelIPv4 => |
| _getOptionValue(_RawSocketOptions.IPPROTO_IP.index); |
| |
| /// Socket option for `IP_MULTICAST_IF`. |
| static int get IPv4MulticastInterface => |
| _getOptionValue(_RawSocketOptions.IP_MULTICAST_IF.index); |
| |
| /// Socket level option for `IPPROTO_IPV6`. |
| static int get levelIPv6 => |
| _getOptionValue(_RawSocketOptions.IPPROTO_IPV6.index); |
| |
| /// Socket option for `IPV6_MULTICAST_IF`. |
| static int get IPv6MulticastInterface => |
| _getOptionValue(_RawSocketOptions.IPV6_MULTICAST_IF.index); |
| |
| /// Socket level option for `IPPROTO_TCP`. |
| static int get levelTcp => |
| _getOptionValue(_RawSocketOptions.IPPROTO_TCP.index); |
| |
| /// Socket level option for `IPPROTO_UDP`. |
| static int get levelUdp => |
| _getOptionValue(_RawSocketOptions.IPPROTO_UDP.index); |
| |
| external static int _getOptionValue(int key); |
| } |
| |
| /// Events for the [RawSocket]. |
| /// |
| /// These event objects are used by the [Stream] behavior of [RawSocket] |
| /// (for example [RawSocket.listen], [RawSocket.forEach]) |
| /// when the socket's state change. |
| class RawSocketEvent { |
| /// An event indicates the socket is ready to be read. |
| static const RawSocketEvent read = const RawSocketEvent._(0); |
| |
| /// An event indicates the socket is ready to write. |
| static const RawSocketEvent write = const RawSocketEvent._(1); |
| |
| /// An event indicates the reading from the socket is closed |
| static const RawSocketEvent readClosed = const RawSocketEvent._(2); |
| |
| /// An event indicates the socket is closed. |
| static const RawSocketEvent closed = const RawSocketEvent._(3); |
| |
| @Deprecated("Use read instead") |
| static const RawSocketEvent READ = read; |
| @Deprecated("Use write instead") |
| static const RawSocketEvent WRITE = write; |
| @Deprecated("Use readClosed instead") |
| static const RawSocketEvent READ_CLOSED = readClosed; |
| @Deprecated("Use closed instead") |
| static const RawSocketEvent CLOSED = closed; |
| |
| final int _value; |
| |
| const RawSocketEvent._(this._value); |
| String toString() { |
| return const [ |
| 'RawSocketEvent.read', |
| 'RawSocketEvent.write', |
| 'RawSocketEvent.readClosed', |
| 'RawSocketEvent.closed' |
| ][_value]; |
| } |
| } |
| |
| /// A cancelable connection attempt. |
| /// |
| /// Returned by the `startConnect` methods on client-side socket types `S`, |
| /// `ConnectionTask<S>` allows cancelling an attempt to connect to a host. |
| class ConnectionTask<S> { |
| /// A `Future` that completes with value that `S.connect()` would return |
| /// unless [cancel] is called on this [ConnectionTask]. |
| /// |
| /// If [cancel] is called, the future completes with a [SocketException] |
| /// error whose message indicates that the connection attempt was cancelled. |
| final Future<S> socket; |
| final void Function() _onCancel; |
| |
| ConnectionTask._(Future<S> this.socket, void Function() onCancel) |
| : _onCancel = onCancel; |
| |
| /// Cancels the connection attempt. |
| /// |
| /// This also causes the [socket] `Future` to complete with a |
| /// [SocketException] error. |
| void cancel() { |
| _onCancel(); |
| } |
| } |
| |
| /// A TCP connection. |
| /// |
| /// A *socket connection* connects a *local* socket to a *remote* socket. |
| /// Data, as [Uint8List]s, is received by the local socket and made |
| /// available by the [read] method, and can be sent to the remote socket |
| /// through the [write] method. |
| /// |
| /// The [Stream] interface of this class provides event notification about when |
| /// a certain change has happened, for example when data has become available |
| /// ([RawSocketEvent.read]) or when the remote end has stopped listening |
| /// ([RawSocketEvent.closed]). |
| abstract class RawSocket implements Stream<RawSocketEvent> { |
| /// Set or get, if the [RawSocket] should listen for [RawSocketEvent.read] |
| /// events. Default is `true`. |
| abstract bool readEventsEnabled; |
| |
| /// Set or get, if the [RawSocket] should listen for [RawSocketEvent.write] |
| /// events. Default is `true`. |
| /// This is a one-shot listener, and writeEventsEnabled must be set |
| /// to true again to receive another write event. |
| abstract bool writeEventsEnabled; |
| |
| /// Creates a new socket connection to the host and port. |
| /// |
| /// Returns a [Future] that will complete with either a [RawSocket] |
| /// once connected, or an error if the host-lookup or connection failed. |
| /// |
| /// The [host] can either be a [String] or an [InternetAddress]. If [host] is a |
| /// [String], [connect] will perform a [InternetAddress.lookup] and try |
| /// all returned [InternetAddress]es, until connected. Unless a |
| /// connection was established, the error from the first failing connection is |
| /// returned. |
| /// |
| /// The argument [sourceAddress] can be used to specify the local |
| /// address to bind when making the connection. The [sourceAddress] can either |
| /// be a [String] or an [InternetAddress]. If a [String] is passed it must |
| /// hold a numeric IP address. |
| /// |
| /// The [sourcePort] defines the local port to bind to. If [sourcePort] is |
| /// not specified or zero, a port will be chosen. |
| /// |
| /// The argument [timeout] is used to specify the maximum allowed time to wait |
| /// for a connection to be established. If [timeout] is longer than the system |
| /// level timeout duration, a timeout may occur sooner than specified in |
| /// [timeout]. On timeout, a [SocketException] is thrown and all ongoing |
| /// connection attempts to [host] are cancelled. |
| external static Future<RawSocket> connect(host, int port, |
| {sourceAddress, int sourcePort = 0, Duration? timeout}); |
| |
| /// Like [connect], but returns a [Future] that completes with a |
| /// [ConnectionTask] that can be cancelled if the [RawSocket] is no |
| /// longer needed. |
| external static Future<ConnectionTask<RawSocket>> startConnect(host, int port, |
| {sourceAddress, int sourcePort = 0}); |
| |
| /// The number of received and non-read bytes in the socket that can be read. |
| int available(); |
| |
| /// Read up to [len] bytes from the socket. |
| /// |
| /// This function is non-blocking and will only return data |
| /// if data is available. |
| /// The number of bytes read can be less then [len] if fewer bytes are |
| /// available for immediate reading. If no data is available `null` |
| /// is returned. |
| Uint8List? read([int? len]); |
| |
| /// Reads a message containing up to [count] bytes from the socket. |
| /// |
| /// This function differs from [read] in that it will also return any |
| /// [SocketControlMessage] that have been sent. |
| /// |
| /// This function is non-blocking and will only return data |
| /// if data is available. |
| /// The number of bytes read can be less then [count] if fewer bytes are |
| /// available for immediate reading. |
| /// Length of data buffer in [SocketMessage] indicates number of bytes read. |
| /// |
| /// Returns `null` if no data is available. |
| /// |
| /// Unsupported by [RawSecureSocket]. |
| @Since("2.15") |
| SocketMessage? readMessage([int? count]); |
| |
| /// Writes up to [count] bytes of the buffer from [offset] buffer offset to |
| /// the socket. |
| /// |
| /// The number of successfully written bytes is returned. |
| /// This function is non-blocking and will only write data |
| /// if buffer space is available in the socket. |
| /// |
| /// The default value for [offset] is 0, and the default value for [count] is |
| /// `buffer.length - offset`. |
| int write(List<int> buffer, [int offset = 0, int? count]); |
| |
| /// Writes socket control messages and data bytes to the socket. |
| /// |
| /// Writes [controlMessages] and up to [count] bytes of [data], |
| /// starting at [offset], to the socket. If [count] is not provided, |
| /// as many bytes as possible are written. Use [write] instead if no control |
| /// messages are required to be sent. |
| /// |
| /// When sent control messages are received, they are retained until the |
| /// next call to [readMessage], where all currently available control messages |
| /// are provided as part of the returned [SocketMessage]. |
| /// Calling [read] will read only data bytes, and will not affect control |
| /// messages. |
| /// |
| /// The [count] must be positive (greater than zero). |
| /// |
| /// Returns the number of bytes written, which cannot be greater than |
| /// [count], nor greater than `data.length - offset`. |
| /// Return value of zero indicates that control messages were not sent. |
| /// |
| /// This function is non-blocking and will only write data |
| /// if buffer space is available in the socket. |
| /// |
| /// Throws an [OSError] if message could not be sent out. |
| /// |
| /// Unsupported by [RawSecureSocket]. |
| @Since("2.15") |
| int sendMessage(List<SocketControlMessage> controlMessages, List<int> data, |
| [int offset = 0, int? count]); |
| |
| /// The port used by this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| int get port; |
| |
| /// The remote port connected to by this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| int get remotePort; |
| |
| /// The [InternetAddress] used to connect this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| InternetAddress get address; |
| |
| /// The remote [InternetAddress] connected to by this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| InternetAddress get remoteAddress; |
| |
| /// Closes the socket. |
| /// |
| /// Returns a future that completes with this socket when the |
| /// underlying connection is completely destroyed. |
| /// |
| /// Calling [close] will never throw an exception |
| /// and calling it several times is supported. Calling [close] can result in |
| /// a [RawSocketEvent.readClosed] event. |
| Future<RawSocket> close(); |
| |
| /// Shuts down the socket in the [direction]. |
| /// |
| /// Calling [shutdown] will never throw an exception |
| /// and calling it several times is supported. Calling |
| /// shutdown with either [SocketDirection.both] or [SocketDirection.receive] |
| /// can result in a [RawSocketEvent.readClosed] event. |
| void shutdown(SocketDirection direction); |
| |
| /// Customize the [RawSocket]. |
| /// |
| /// See [SocketOption] for available options. |
| /// |
| /// Returns `true` if the option was set successfully, `false` otherwise. |
| bool setOption(SocketOption option, bool enabled); |
| |
| /// Reads low level information about the [RawSocket]. |
| /// |
| /// See [RawSocketOption] for available options. |
| /// |
| /// Returns the [RawSocketOption.value] on success. |
| /// |
| /// Throws an [OSError] on failure. |
| @Since("2.2") |
| Uint8List getRawOption(RawSocketOption option); |
| |
| /// Customizes the [RawSocket]. |
| /// |
| /// See [RawSocketOption] for available options. |
| /// |
| /// Throws an [OSError] on failure. |
| @Since("2.2") |
| void setRawOption(RawSocketOption option); |
| } |
| |
| /// A TCP connection between two sockets. |
| /// |
| /// A *socket connection* connects a *local* socket to a *remote* socket. |
| /// Data, as [Uint8List]s, is received by the local socket, made available |
| /// by the [Stream] interface of this class, and can be sent to the remote |
| /// socket through the [IOSink] interface of this class. |
| abstract class Socket implements Stream<Uint8List>, IOSink { |
| /// Creates a new socket connection to the host and port and returns a [Future] |
| /// that will complete with either a [Socket] once connected or an error |
| /// if the host-lookup or connection failed. |
| /// |
| /// [host] can either be a [String] or an [InternetAddress]. If [host] is a |
| /// [String], [connect] will perform a [InternetAddress.lookup] and try |
| /// all returned [InternetAddress]es, until connected. Unless a |
| /// connection was established, the error from the first failing connection is |
| /// returned. |
| /// |
| /// The argument [sourceAddress] can be used to specify the local |
| /// address to bind when making the connection. The [sourceAddress] can either |
| /// be a [String] or an [InternetAddress]. If a [String] is passed it must |
| /// hold a numeric IP address. |
| /// |
| /// The [sourcePort] defines the local port to bind to. If [sourcePort] is |
| /// not specified or zero, a port will be chosen. |
| /// |
| /// The argument [timeout] is used to specify the maximum allowed time to wait |
| /// for a connection to be established. If [timeout] is longer than the system |
| /// level timeout duration, a timeout may occur sooner than specified in |
| /// [timeout]. On timeout, a [SocketException] is thrown and all ongoing |
| /// connection attempts to [host] are cancelled. |
| static Future<Socket> connect(host, int port, |
| {sourceAddress, int sourcePort = 0, Duration? timeout}) { |
| final IOOverrides? overrides = IOOverrides.current; |
| if (overrides == null) { |
| return Socket._connect(host, port, |
| sourceAddress: sourceAddress, |
| sourcePort: sourcePort, |
| timeout: timeout); |
| } |
| return overrides.socketConnect(host, port, |
| sourceAddress: sourceAddress, sourcePort: sourcePort, timeout: timeout); |
| } |
| |
| /// Like [connect], but returns a [Future] that completes with a |
| /// [ConnectionTask] that can be cancelled if the [Socket] is no |
| /// longer needed. |
| static Future<ConnectionTask<Socket>> startConnect(host, int port, |
| {sourceAddress, int sourcePort = 0}) { |
| final IOOverrides? overrides = IOOverrides.current; |
| if (overrides == null) { |
| return Socket._startConnect(host, port, |
| sourceAddress: sourceAddress, sourcePort: sourcePort); |
| } |
| return overrides.socketStartConnect(host, port, |
| sourceAddress: sourceAddress, sourcePort: sourcePort); |
| } |
| |
| external static Future<Socket> _connect(host, int port, |
| {sourceAddress, int sourcePort = 0, Duration? timeout}); |
| |
| external static Future<ConnectionTask<Socket>> _startConnect(host, int port, |
| {sourceAddress, int sourcePort = 0}); |
| |
| /// Destroys the socket in both directions. |
| /// |
| /// Calling [destroy] will make the send a close event on the stream |
| /// and will no longer react on data being piped to it. |
| /// |
| /// Call [close] (inherited from [IOSink]) to only close the [Socket] |
| /// for sending data. |
| void destroy(); |
| |
| /// Customizes the [RawSocket]. |
| /// |
| /// See [SocketOption] for available options. |
| /// |
| /// Returns `true` if the option was set successfully, false otherwise. |
| /// |
| /// Throws a [SocketException] if the socket has been destroyed or upgraded to |
| /// a secure socket. |
| bool setOption(SocketOption option, bool enabled); |
| |
| /// Reads low level information about the [RawSocket]. |
| /// |
| /// See [RawSocketOption] for available options. |
| /// |
| /// Returns the [RawSocketOption.value] on success. |
| /// |
| /// Throws an [OSError] on failure and a [SocketException] if the socket has |
| /// been destroyed or upgraded to a secure socket. |
| Uint8List getRawOption(RawSocketOption option); |
| |
| /// Customizes the [RawSocket]. |
| /// |
| /// See [RawSocketOption] for available options. |
| /// |
| /// Throws an [OSError] on failure and a [SocketException] if the socket has |
| /// been destroyed or upgraded to a secure socket. |
| void setRawOption(RawSocketOption option); |
| |
| /// The port used by this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| /// The port is 0 if the socket is a Unix domain socket. |
| int get port; |
| |
| /// The remote port connected to by this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| /// The port is 0 if the socket is a Unix domain socket. |
| int get remotePort; |
| |
| /// The [InternetAddress] used to connect this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| InternetAddress get address; |
| |
| /// The remote [InternetAddress] connected to by this socket. |
| /// |
| /// Throws a [SocketException] if the socket is closed. |
| InternetAddress get remoteAddress; |
| |
| Future close(); |
| |
| Future get done; |
| } |
| |
| /// A data packet received by a [RawDatagramSocket]. |
| class Datagram { |
| /// The actual bytes of the message. |
| Uint8List data; |
| |
| /// The address of the socket which sends the data. |
| InternetAddress address; |
| |
| /// The port of the socket which sends the data. |
| int port; |
| |
| Datagram(this.data, this.address, this.port); |
| } |
| |
| /// A wrappper around OS resource handle so it can be passed via Socket |
| /// as part of [SocketMessage]. |
| abstract class ResourceHandle { |
| /// Creates wrapper around opened file. |
| external factory ResourceHandle.fromFile(RandomAccessFile file); |
| |
| /// Creates wrapper around opened socket. |
| external factory ResourceHandle.fromSocket(Socket socket); |
| |
| /// Creates wrapper around opened raw socket. |
| external factory ResourceHandle.fromRawSocket(RawSocket socket); |
| |
| /// Creates wrapper around opened raw datagram socket. |
| external factory ResourceHandle.fromRawDatagramSocket( |
| RawDatagramSocket socket); |
| |
| /// Creates wrapper around current stdin. |
| external factory ResourceHandle.fromStdin(Stdin stdin); |
| |
| /// Creates wrapper around current stdout. |
| external factory ResourceHandle.fromStdout(Stdout stdout); |
| |
| /// Extracts opened file from resource handle. |
| /// |
| /// This can also be used when receiving stdin and stdout handles. |
| /// |
| /// If this resource handle is not a file or stdio handle, the behavior of the |
| /// returned [RandomAccessFile] is completely unspecified. |
| /// Be very careful to avoid using a handle incorrectly. |
| RandomAccessFile toFile(); |
| |
| /// Extracts opened socket from resource handle. |
| /// |
| /// If this resource handle is not a socket handle, the behavior of the |
| /// returned [Socket] is completely unspecified. |
| /// Be very careful to avoid using a handle incorrectly. |
| Socket toSocket(); |
| |
| /// Extracts opened raw socket from resource handle. |
| /// |
| /// If this resource handle is not a socket handle, the behavior of the |
| /// returned [RawSocket] is completely unspecified. |
| /// Be very careful to avoid using a handle incorrectly. |
| RawSocket toRawSocket(); |
| |
| /// Extracts opened raw datagram socket from resource handle. |
| /// |
| /// If this resource handle is not a datagram socket handle, the behavior of |
| /// the returned [RawDatagramSocket] is completely unspecified. |
| /// Be very careful to avoid using a handle incorrectly. |
| RawDatagramSocket toRawDatagramSocket(); |
| } |
| |
| /// Control message part of the [SocketMessage] received by a call to |
| /// [RawSocket.readMessage]. |
| /// |
| /// Control messages could carry different information including |
| /// [ResourceHandle]. If [ResourceHandle]s are availabe as part of this message, |
| /// they can be extracted via [extractHandles]. |
| abstract class SocketControlMessage { |
| /// Creates a control message containing the provided [handles]. |
| /// |
| /// This is used by the sender when it sends handles across the socket. |
| /// Receiver can extract the handles from the message using [extractHandles]. |
| external factory SocketControlMessage.fromHandles( |
| List<ResourceHandle> handles); |
| |
| /// Extracts the list of handles embedded in this message. |
| /// |
| /// This method must only be used to extract handles from messages |
| /// received on a socket. It must not be used on a socket control |
| /// message that is created locally, and has not been sent using |
| /// [RawSocket.sendMessage]. |
| /// |
| /// This method must only be called once. |
| /// Calling it multiple times may cause duplicated handles with unspecified |
| /// behavior. |
| List<ResourceHandle> extractHandles(); |
| |
| /// A platform specific value used to determine the kind of control message. |
| /// |
| /// Together with [type], these two integers identify the kind of control |
| /// message in a platform specific way. |
| /// For example, on Linux certain combinations of these values indicate |
| /// that this is a control message that carries [ResourceHandle]s. |
| int get level; |
| |
| /// A platform specific value used to determine the kind of control message. |
| /// |
| /// Together with [level], these two integers identify the kind of control |
| /// message in a platform specific way. |
| /// For example, on Linux certain combinations of these values indicate |
| /// that this is a control message that carries [ResourceHandle]s. |
| int get type; |
| |
| /// Actual bytes that were passed as part of the control message by the |
| /// underlying platform. |
| /// |
| /// The bytes are interpreted differently depending on the [level] and |
| /// [type]. These actual bytes can be used to inspect and interpret |
| /// non-handle-carrying messages. |
| Uint8List get data; |
| } |
| |
| /// A socket message received by a [RawDatagramSocket]. |
| /// |
| /// A socket message consists of [data] bytes and [controlMessages]. |
| class SocketMessage { |
| /// The actual bytes of the message. |
| final Uint8List data; |
| |
| /// The control messages sent as part of this socket message. |
| /// |
| /// This list can be empty. |
| final List<SocketControlMessage> controlMessages; |
| |
| SocketMessage(this.data, this.controlMessages); |
| } |
| |
| /// An unbuffered interface to a UDP socket. |
| /// |
| /// The raw datagram socket delivers the datagrams in the same chunks as the |
| /// underlying operating system. It's a [Stream] of [RawSocketEvent]s. |
| /// |
| /// Note that the event [RawSocketEvent.readClosed] will never be |
| /// received as an UDP socket cannot be closed by a remote peer. |
| /// |
| /// It is not the same as a |
| /// [POSIX raw socket](http://man7.org/linux/man-pages/man7/raw.7.html). |
| abstract class RawDatagramSocket extends Stream<RawSocketEvent> { |
| /// Whether the [RawDatagramSocket] should listen for |
| /// [RawSocketEvent.read] events. |
| /// |
| /// Default is `true`. |
| abstract bool readEventsEnabled; |
| |
| /// Whether the [RawDatagramSocket] should listen for |
| /// [RawSocketEvent.write] events. |
| /// |
| /// Default is `true`. |
| /// This is a one-shot listener, and [writeEventsEnabled] must be set to true |
| /// again to receive another write event. |
| abstract bool writeEventsEnabled; |
| |
| /// Whether multicast traffic is looped back to the host. |
| /// |
| /// By default multicast loopback is enabled. |
| abstract bool multicastLoopback; |
| |
| /// The maximum network hops for multicast packages |
| /// originating from this socket. |
| /// |
| /// For IPv4 this is referred to as TTL (time to live). |
| /// |
| /// By default this value is 1 causing multicast traffic to stay on |
| /// the local network. |
| abstract int multicastHops; |
| |
| /// The network interface used for outgoing multicast packages. |
| /// |
| /// A value of `null` indicate that the system chooses the network |
| /// interface to use. |
| /// |
| /// By default this value is `null` |
| @Deprecated("This property is not implemented. Use getRawOption and " |
| "setRawOption instead.") |
| NetworkInterface? multicastInterface; |
| |
| /// Whether IPv4 broadcast is enabled. |
| /// |
| /// IPv4 broadcast needs to be enabled by the sender for sending IPv4 |
| /// broadcast packages. By default IPv4 broadcast is disabled. |
| /// |
| /// For IPv6 there is no general broadcast mechanism. Use multicast |
| /// instead. |
| abstract bool broadcastEnabled; |
| |
| /// Binds a socket to the given [host] and [port]. |
| /// |
| /// When the socket is bound and has started listening on [port], the returned |
| /// future completes with the [RawDatagramSocket] of the bound socket. |
| /// |
| /// The [host] can either be a [String] or an [InternetAddress]. If [host] is a |
| /// [String], [bind] will perform a [InternetAddress.lookup] and use the first |
| /// value in the list. To listen on the loopback interface, which will allow |
| /// only incoming connections from the local host, use the value |
| /// [InternetAddress.loopbackIPv4] or [InternetAddress.loopbackIPv6]. |
| /// To allow for incoming connection from any network use either one of |
| /// the values [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to |
| /// bind to all interfaces, or use the IP address of a specific interface. |
| /// |
| /// The [reuseAddress] should be set for all listeners that bind to the same |
| /// address. Otherwise, it will fail with a [SocketException]. |
| /// |
| /// The [reusePort] specifies whether the port can be reused. |
| /// |
| /// The [ttl] sets `time to live` of a datagram sent on the socket. |
| external static Future<RawDatagramSocket> bind(host, int port, |
| {bool reuseAddress = true, bool reusePort = false, int ttl = 1}); |
| |
| /// The port used by this socket. |
| int get port; |
| |
| /// The address used by this socket. |
| InternetAddress get address; |
| |
| /// Closes the datagram socket. |
| void close(); |
| |
| /// Sends a datagram. |
| /// |
| /// Returns the number of bytes written. This will always be either |
| /// the size of [buffer] or `0`. |
| int send(List<int> buffer, InternetAddress address, int port); |
| |
| /// Receives a datagram. |
| /// |
| /// Returns `null` if there are no datagrams available. |
| /// |
| /// The maximum length of the datagram that can be received is 65503 bytes. |
| Datagram? receive(); |
| |
| /// Joins a multicast group. |
| /// |
| /// If an error occur when trying to join the multicast group, an |
| /// exception is thrown. |
| void joinMulticast(InternetAddress group, [NetworkInterface? interface]); |
| |
| /// Leaves a multicast group. |
| /// |
| /// If an error occur when trying to join the multicast group, an |
| /// exception is thrown. |
| void leaveMulticast(InternetAddress group, [NetworkInterface? interface]); |
| |
| /// Reads low level information about the [RawSocket]. |
| /// |
| /// See [RawSocketOption] for available options. |
| /// |
| /// Returns [RawSocketOption.value] on success. |
| /// |
| /// Throws an [OSError] on failure. |
| Uint8List getRawOption(RawSocketOption option); |
| |
| /// Customizes the [RawSocket]. |
| /// |
| /// See [RawSocketOption] for available options. |
| /// |
| /// Throws an [OSError] on failure. |
| void setRawOption(RawSocketOption option); |
| } |
| |
| /// Exception thrown when a socket operation fails. |
| class SocketException implements IOException { |
| /// Description of the error. |
| final String message; |
| |
| /// The underlying OS error. |
| /// |
| /// If this exception is not thrown due to an OS error, the value is `null`. |
| final OSError? osError; |
| |
| /// The address of the socket giving rise to the exception. |
| /// |
| /// This is either the source or destination address of a socket, |
| /// or it can be `null` if no socket end-point was involved in the cause of |
| /// the exception. |
| final InternetAddress? address; |
| |
| /// The port of the socket giving rise to the exception. |
| /// |
| /// This is either the source or destination address of a socket, |
| /// or it can be `null` if no socket end-point was involved in the cause of |
| /// the exception. |
| final int? port; |
| |
| /// Creates a [SocketException] with the provided values. |
| const SocketException(this.message, {this.osError, this.address, this.port}); |
| |
| /// Creates an exception reporting that a socket was used after it was closed. |
| const SocketException.closed() |
| : message = 'Socket has been closed', |
| osError = null, |
| address = null, |
| port = null; |
| |
| String toString() { |
| StringBuffer sb = new StringBuffer(); |
| sb.write("SocketException"); |
| if (message.isNotEmpty) { |
| sb.write(": $message"); |
| if (osError != null) { |
| sb.write(" ($osError)"); |
| } |
| } else if (osError != null) { |
| sb.write(": $osError"); |
| } |
| if (address != null) { |
| sb.write(", address = ${address!.host}"); |
| } |
| if (port != null) { |
| sb.write(", port = $port"); |
| } |
| return sb.toString(); |
| } |
| } |