Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import "dart:async"; | |
| 6 import "dart:io"; | |
| 7 import "dart:typed_data"; | |
| 8 | |
| 9 import "package:async_helper/async_helper.dart"; | |
| 10 import "package:expect/expect.dart"; | |
| 11 | |
| 12 class FutureExpect { | |
| 13 static Future check(Future result, check) => | |
| 14 result.then((value) => check(value)); | |
| 15 static Future throws(Future result) => | |
| 16 result.then((value) { | |
| 17 throw new ExpectException( | |
| 18 "FutureExpect.throws received $value instead of an exception"); | |
| 19 }, onError: (_) => null); | |
| 20 } | |
| 21 | |
| 22 testDatagramSocketOptions() { | |
| 23 test(address) { | |
| 24 asyncStart(); | |
| 25 RawDatagramSocket.bind(address, 0).then((socket) { | |
| 26 Expect.isTrue(socket.multicastLoopback); | |
| 27 Expect.equals(1, socket.multicastHops); | |
| 28 Expect.throws(() => socket.multicastInterface); | |
| 29 Expect.isFalse(socket.broadcastEnabled); | |
| 30 | |
| 31 socket.multicastLoopback = false; | |
| 32 socket.multicastHops = 4; | |
| 33 socket.broadcastEnabled = true; | |
| 34 Expect.isFalse(socket.multicastLoopback); | |
| 35 Expect.equals(4, socket.multicastHops); | |
| 36 Expect.throws(() => socket.multicastInterface = null); | |
| 37 Expect.isTrue(socket.broadcastEnabled); | |
| 38 | |
| 39 socket.multicastLoopback = true; | |
| 40 socket.multicastHops = 1; | |
| 41 socket.broadcastEnabled = false; | |
| 42 Expect.isTrue(socket.multicastLoopback); | |
| 43 Expect.equals(1, socket.multicastHops); | |
| 44 Expect.throws(() => socket.multicastInterface); | |
| 45 Expect.isFalse(socket.broadcastEnabled); | |
| 46 asyncEnd(); | |
| 47 }); | |
| 48 } | |
| 49 | |
| 50 test(InternetAddress.LOOPBACK_IP_V4); | |
| 51 test(InternetAddress.ANY_IP_V4); | |
| 52 test(InternetAddress.LOOPBACK_IP_V6); | |
| 53 test(InternetAddress.ANY_IP_V6); | |
| 54 } | |
| 55 | |
| 56 testDatagramSocketReuseAddress() { | |
| 57 test(address, reuseAddress) { | |
| 58 asyncStart(); | |
| 59 RawDatagramSocket.bind( | |
| 60 address, 0, reuseAddress: reuseAddress).then((socket) { | |
| 61 if (reuseAddress) { | |
| 62 RawDatagramSocket.bind(address, socket.port) | |
| 63 .then((s) => Expect.isTrue(s is RawDatagramSocket)) | |
| 64 .then(asyncSuccess); | |
| 65 } else { | |
| 66 FutureExpect.throws(RawDatagramSocket.bind(address, socket.port)) | |
| 67 .then(asyncSuccess); | |
| 68 } | |
| 69 }); | |
| 70 } | |
| 71 | |
| 72 test(InternetAddress.LOOPBACK_IP_V4, true); | |
| 73 test(new InternetAddress('224.0.0.0'), true); | |
| 74 test(InternetAddress.LOOPBACK_IP_V4, false); | |
| 75 test(new InternetAddress('224.0.0.0'), false); | |
| 76 test(InternetAddress.LOOPBACK_IP_V6, true); | |
| 77 test(new InternetAddress("ff11::0"), true); | |
| 78 test(InternetAddress.LOOPBACK_IP_V6, false); | |
| 79 test(new InternetAddress("ff11::0"), false); | |
| 80 } | |
| 81 | |
| 82 testBroadcast() { | |
| 83 test(bindAddress, broadcastAddress, enabled) { | |
| 84 asyncStart(); | |
| 85 Future.wait([RawDatagramSocket.bind(bindAddress, 0), | |
| 86 RawDatagramSocket.bind(bindAddress, 0)]).then((values) { | |
| 87 var broadcastTimer; | |
| 88 var sender = values[0]; | |
| 89 var receiver = values[1]; | |
| 90 sender.broadcastEnabled = enabled; | |
| 91 receiver.listen((event) { | |
| 92 if (event == RawSocketEvent.READ) { | |
| 93 Expect.isTrue(enabled); | |
| 94 sender.close(); | |
| 95 receiver.close(); | |
| 96 broadcastTimer.cancel(); | |
| 97 asyncEnd(); | |
| 98 } | |
| 99 }); | |
| 100 | |
| 101 int sendCount = 0; | |
| 102 send(_) { | |
| 103 sender.send(new Uint8List(1), broadcastAddress, receiver.port); | |
| 104 sendCount++; | |
| 105 if (!enabled && sendCount == 50) { | |
| 106 sender.close(); | |
| 107 receiver.close(); | |
| 108 broadcastTimer.cancel(); | |
| 109 asyncEnd(); | |
| 110 } | |
| 111 } | |
| 112 broadcastTimer = new Timer.periodic(new Duration(milliseconds: 10), send); | |
| 113 }); | |
| 114 } | |
| 115 | |
| 116 var broadcast = new InternetAddress("255.255.255.255"); | |
| 117 test(InternetAddress.ANY_IP_V4, broadcast, false); | |
| 118 test(InternetAddress.ANY_IP_V4, broadcast, true); | |
| 119 } | |
| 120 | |
| 121 testLoopbackMulticast() { | |
| 122 test(bindAddress, multicastAddress, enabled) { | |
| 123 asyncStart(); | |
| 124 Future.wait([RawDatagramSocket.bind(bindAddress, 0), | |
| 125 RawDatagramSocket.bind(bindAddress, 0)]).then((values) { | |
| 126 var senderTimer; | |
| 127 var sender = values[0]; | |
| 128 var receiver = values[1]; | |
| 129 | |
| 130 sender.join(multicastAddress); | |
| 131 receiver.join(multicastAddress); | |
| 132 receiver.multicastLoopback = false; | |
| 133 sender.multicastLoopback = enabled; | |
| 134 | |
| 135 receiver.listen((event) { | |
| 136 if (event == RawSocketEvent.READ) { | |
| 137 Expect.isTrue(enabled); | |
| 138 sender.close(); | |
| 139 receiver.close(); | |
| 140 senderTimer.cancel(); | |
| 141 asyncEnd(); | |
| 142 } | |
| 143 }); | |
| 144 | |
| 145 int sendCount = 0; | |
| 146 send(_) { | |
| 147 sender.send(new Uint8List(1), multicastAddress, receiver.port); | |
| 148 sendCount++; | |
| 149 if (!enabled && sendCount == 50) { | |
| 150 sender.close(); | |
| 151 receiver.close(); | |
| 152 senderTimer.cancel(); | |
| 153 asyncEnd(); | |
| 154 } | |
| 155 } | |
| 156 senderTimer = new Timer.periodic(new Duration(milliseconds: 10), send); | |
| 157 }); | |
| 158 } | |
| 159 | |
| 160 test(InternetAddress.ANY_IP_V4, new InternetAddress("224.0.0.0"), true); | |
| 161 test(InternetAddress.ANY_IP_V4, new InternetAddress("224.0.0.0"), false); | |
| 162 test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), true); | |
| 163 test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), false); | |
| 164 } | |
| 165 | |
| 166 testSendReceive(InternetAddress bindAddress) { | |
| 167 asyncStart(); | |
| 168 | |
| 169 var total = 10; | |
| 170 | |
| 171 int receivedSeq = 0; | |
| 172 var ackSeq = 0; | |
| 173 Timer ackTimer; | |
| 174 | |
| 175 Future.wait([RawDatagramSocket.bind(bindAddress, 0), | |
| 176 RawDatagramSocket.bind(bindAddress, 0)]).then((values) { | |
| 177 var sender = values[0]; | |
| 178 var receiver = values[1]; | |
| 179 if (bindAddress.isMulticast) { | |
| 180 sender.multicastLoopback = true; | |
| 181 receiver.multicastLoopback = true; | |
| 182 sender.join(bindAddress); | |
| 183 receiver.join(bindAddress); | |
| 184 } | |
| 185 | |
| 186 UInt8List createDataPackage(int seq) { | |
| 187 var data = new Uint8List(1000); | |
| 188 (new ByteData.view(data.buffer, 0, 4)).setUint32(0, seq); | |
| 189 return data; | |
| 190 } | |
| 191 | |
| 192 UInt8List createAckPackage(int seq) { | |
| 193 var data = new Uint8List(4); | |
| 194 new ByteData.view(data.buffer, 0, 4).setUint32(0, seq); | |
| 195 return data; | |
| 196 } | |
| 197 | |
| 198 int packageSeq(Datagram datagram) => | |
| 199 new ByteData.view(datagram.data.buffer).getUint32(0); | |
| 200 | |
| 201 void sendData(int seq) { | |
| 202 // Send a datagram acknowledging the received sequence. | |
| 203 sender.send(createDataPackage(seq), bindAddress, receiver.port); | |
|
Anders Johnsen
2013/11/29 12:36:54
Check send return value.
Søren Gjesse
2013/12/12 11:38:46
Done.
| |
| 204 } | |
| 205 | |
| 206 void sendAck(address, port) { | |
| 207 // Send a datagram acknowledging the received sequence. | |
| 208 receiver.send(createAckPackage(receivedSeq), address, port); | |
| 209 // Start a "long" timer for more data. | |
| 210 if (ackTimer != null) ackTimer.cancel(); | |
| 211 ackTimer = new Timer.periodic( | |
| 212 new Duration(milliseconds: 100), (_) => sendAck(address, port)); | |
| 213 } | |
| 214 | |
| 215 sender.listen((event) { | |
| 216 switch (event) { | |
| 217 case RawSocketEvent.READ: | |
| 218 var datagram = sender.receive(); | |
| 219 if (datagram != null) { | |
| 220 Expect.equals(datagram.port, receiver.port); | |
| 221 if (!bindAddress.isMulticast) { | |
| 222 Expect.equals(receiver.address, datagram.address); | |
| 223 } | |
| 224 ackSeq = packageSeq(datagram); | |
| 225 if (ackSeq < total) { | |
| 226 sender.writeEventsEnabled = true; | |
| 227 } else { | |
| 228 sender.close(); | |
| 229 receiver.close(); | |
| 230 ackTimer.cancel(); | |
| 231 asyncEnd(); | |
| 232 } | |
| 233 } | |
| 234 break; | |
| 235 case RawSocketEvent.WRITE: | |
| 236 // Send the next package. | |
| 237 sendData(ackSeq + 1); | |
| 238 break; | |
| 239 case RawSocketEvent.CLOSED: | |
| 240 break; | |
| 241 default: | |
| 242 throw "Unexpected event $event"; | |
| 243 } | |
| 244 }); | |
| 245 | |
| 246 receiver.writeEventsEnabled = false; | |
| 247 receiver.listen((event) { | |
| 248 switch (event) { | |
| 249 case RawSocketEvent.READ: | |
| 250 var datagram = receiver.receive(); | |
| 251 if (datagram != null) { | |
| 252 Expect.equals(datagram.port, sender.port); | |
| 253 if (!bindAddress.isMulticast) { | |
| 254 Expect.equals(receiver.address, datagram.address); | |
| 255 } | |
| 256 var seq = packageSeq(datagram); | |
| 257 if (seq == receivedSeq + 1) { | |
| 258 receivedSeq = seq; | |
| 259 sendAck(bindAddress, sender.port); | |
| 260 } | |
| 261 } | |
| 262 break; | |
| 263 case RawSocketEvent.WRITE: | |
| 264 throw "Unexpected WRITE"; | |
| 265 break; | |
| 266 case RawSocketEvent.CLOSED: | |
| 267 break; | |
| 268 default: | |
| 269 throw "Unexpected event $event"; | |
| 270 } | |
| 271 }); | |
| 272 }); | |
| 273 } | |
| 274 | |
| 275 | |
| 276 main() { | |
| 277 testDatagramSocketOptions(); | |
| 278 testDatagramSocketReuseAddress(); | |
| 279 testBroadcast(); | |
| 280 testLoopbackMulticast(); | |
| 281 testSendReceive(InternetAddress.LOOPBACK_IP_V4); | |
| 282 testSendReceive(new InternetAddress("224.0.0.0")); | |
| 283 testSendReceive(InternetAddress.LOOPBACK_IP_V6); | |
| 284 testSendReceive(new InternetAddress("ff11::114")); | |
| 285 } | |
| OLD | NEW |