Index: runtime/bin/socket_patch.dart |
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart |
index f5c302656fb05e324a09839d69dc364ef4875e31..58c9ddd0547f12a6942202b8a03a54bc5f699535 100644 |
--- a/runtime/bin/socket_patch.dart |
+++ b/runtime/bin/socket_patch.dart |
@@ -12,12 +12,36 @@ patch class RawServerSocket { |
patch class RawSocket { |
- /* patch */ static Future<RawSocket> connect(String host, int port) { |
+ /* patch */ static Future<RawSocket> connect(host, int port) { |
return _RawSocket.connect(host, port); |
} |
} |
+patch class InternetAddress { |
+ /* patch */ static Future<List<InternetAddress>> lookup( |
+ String host, {InternetAddressType type: InternetAddressType.ANY}) { |
+ return _NativeSocket.lookup(host, type: type); |
+ } |
+} |
+ |
+class _InternetAddress implements InternetAddress { |
+ final InternetAddressType type; |
+ final String address; |
+ final String host; |
+ final Uint8List _sockaddr_storage; |
+ |
+ _InternetAddress(InternetAddressType this.type, |
+ String this.address, |
+ String this.host, |
+ List<int> this._sockaddr_storage); |
+ |
+ String toString() { |
+ return "InternetAddress('$address', ${type.name})"; |
+ } |
+} |
+ |
+ |
// The _NativeSocket class encapsulates an OS socket. |
class _NativeSocket extends NativeFieldWrapperClass1 { |
// Bit flags used when communicating between the eventhandler and |
@@ -74,57 +98,91 @@ class _NativeSocket extends NativeFieldWrapperClass1 { |
// Holds the port of the socket, null if not known. |
int localPort; |
- // Holds the host or address used to connect or bind the socket. |
- String localHost; |
+ // Holds the address used to connect or bind the socket. |
+ InternetAddress address; |
// Native port for socket services. |
static SendPort socketService; |
- static Future<_NativeSocket> connect(String host, int port) { |
- var completer = new Completer(); |
+ static Future<List<InternetAddress>> lookup( |
+ String host, {InternetAddressType type: InternetAddressType.ANY}) { |
ensureSocketService(); |
- socketService.call([HOST_NAME_LOOKUP, host]).then((response) { |
- if (isErrorResponse(response)) { |
- completer.completeError( |
- createError(response, "Failed host name lookup")); |
- } else { |
- var socket = new _NativeSocket.normal(); |
- socket.localHost = host; |
- var result = socket.nativeCreateConnect(response, port); |
- if (result is OSError) { |
- completer.completeError(createError(result, "Connection failed")); |
- } else { |
- // Setup handlers for receiving the first write event which |
- // indicate that the socket is fully connected. |
- socket.setHandlers( |
- write: () { |
- socket.setListening(read: false, write: false); |
- completer.complete(socket); |
- }, |
- error: (e) { |
- socket.close(); |
- completer.completeError(createError(e, "Connection failed")); |
- } |
- ); |
- socket.setListening(read: false, write: true); |
- } |
- } |
- }); |
- return completer.future; |
+ return socketService.call([HOST_NAME_LOOKUP, host, type._value]) |
+ .then((response) { |
+ if (isErrorResponse(response)) { |
+ throw createError(response, "Failed host name lookup"); |
+ } else { |
+ return response.skip(1).map((result) { |
+ var type = new InternetAddressType._from(result[0]); |
+ return new _InternetAddress(type, result[1], host, result[2]); |
+ }).toList(); |
+ } |
+ }); |
+ } |
+ |
+ static Future<_NativeSocket> connect(host, int port) { |
+ return new Future.value(host) |
+ .then((host) { |
+ if (host is _InternetAddress) return host; |
+ return lookup(host) |
+ .then((list) { |
+ if (list.length == 0) { |
+ throw createError(response, "Failed host name lookup"); |
+ } |
+ return list[0]; |
+ }); |
+ }) |
+ .then((address) { |
+ ensureSocketService(); |
+ var socket = new _NativeSocket.normal(); |
+ socket.address = address; |
+ var result = socket.nativeCreateConnect( |
+ address._sockaddr_storage, port); |
+ if (result is OSError) { |
+ throw createError(result, "Connection failed"); |
+ } else { |
+ var completer = new Completer(); |
+ // Setup handlers for receiving the first write event which |
+ // indicate that the socket is fully connected. |
+ socket.setHandlers( |
+ write: () { |
+ socket.setListening(read: false, write: false); |
+ completer.complete(socket); |
+ }, |
+ error: (e) { |
+ socket.close(); |
+ completer.completeError(createError(e, "Connection failed")); |
+ } |
+ ); |
+ socket.setListening(read: false, write: true); |
+ return completer.future; |
+ } |
+ }); |
} |
static Future<_NativeSocket> bind(String address, |
int port, |
int backlog) { |
- var socket = new _NativeSocket.listen(); |
- socket.localHost = address; |
- var result = socket.nativeCreateBindListen(address, port, backlog); |
- if (result is OSError) { |
- return new Future.error( |
- new SocketIOException("Failed to create server socket", result)); |
- } |
- if (port != 0) socket.localPort = port; |
- return new Future.value(socket); |
+ return lookup(address) |
+ .then((list) { |
+ if (list.length == 0) { |
+ throw createError(response, "Failed host name lookup"); |
+ } |
+ return list[0]; |
+ }) |
+ .then((address) { |
+ var socket = new _NativeSocket.listen(); |
+ socket.address = address; |
+ var result = socket.nativeCreateBindListen(address._sockaddr_storage, |
+ port, |
+ backlog); |
+ if (result is OSError) { |
+ throw new SocketIOException( |
+ "Failed to create server socket", result); |
+ } |
+ if (port != 0) socket.localPort = port; |
+ return socket; |
+ }); |
} |
_NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET { |
@@ -194,6 +252,8 @@ class _NativeSocket extends NativeFieldWrapperClass1 { |
_NativeSocket accept() { |
var socket = new _NativeSocket.normal(); |
if (nativeAccept(socket) != true) return null; |
+ socket.localPort = localPort; |
+ socket.address = address; |
return socket; |
} |
@@ -206,8 +266,6 @@ class _NativeSocket extends NativeFieldWrapperClass1 { |
return nativeGetRemotePeer()[1]; |
} |
- String get host => localHost; |
- |
String get remoteHost { |
return nativeGetRemotePeer()[0]; |
} |
@@ -409,8 +467,9 @@ class _NativeSocket extends NativeFieldWrapperClass1 { |
nativeRead(int len) native "Socket_Read"; |
nativeWrite(List<int> buffer, int offset, int bytes) |
native "Socket_WriteList"; |
- nativeCreateConnect(String host, int port) native "Socket_CreateConnect"; |
- nativeCreateBindListen(String address, int port, int backlog) |
+ nativeCreateConnect(List<int> addr, |
+ int port) native "Socket_CreateConnect"; |
+ nativeCreateBindListen(List<int> addr, int port, int backlog) |
native "ServerSocket_CreateBindListen"; |
nativeAccept(_NativeSocket socket) native "ServerSocket_Accept"; |
int nativeGetPort() native "Socket_GetPort"; |
@@ -503,7 +562,7 @@ class _RawSocket extends Stream<RawSocketEvent> |
bool _readEventsEnabled = true; |
bool _writeEventsEnabled = true; |
- static Future<RawSocket> connect(String host, int port) { |
+ static Future<RawSocket> connect(host, int port) { |
return _NativeSocket.connect(host, port) |
.then((socket) => new _RawSocket(socket)); |
} |
@@ -571,7 +630,7 @@ class _RawSocket extends Stream<RawSocketEvent> |
int get remotePort => _socket.remotePort; |
- String get host => _socket.host; |
+ InternetAddress get address => _socket.address; |
String get remoteHost => _socket.remoteHost; |
@@ -659,7 +718,7 @@ class _ServerSocket extends Stream<Socket> |
patch class Socket { |
- /* patch */ static Future<Socket> connect(String host, int port) { |
+ /* patch */ static Future<Socket> connect(host, int port) { |
return RawSocket.connect(host, port).then( |
(socket) => new _Socket(socket)); |
} |