OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library chat_server; | 5 library chat_server; |
6 import 'dart:async'; | 6 import 'dart:async'; |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 import 'dart:isolate'; | 8 import 'dart:isolate'; |
9 import "dart:convert"; | 9 import 'dart:convert'; |
10 import 'dart:math'; | 10 import 'dart:math'; |
11 | 11 |
12 void startChatServer() { | 12 Future<SendPort> spawnChatServer() { |
| 13 var response = new ReceivePort(); |
| 14 return Isolate.spawn(startChatServer, response.sendPort) |
| 15 .then((remoteIsolate) => response.first) |
| 16 .whenComplete(() { response.close(); }); // Make sure the port is closed. |
| 17 } |
| 18 |
| 19 void startChatServer(SendPort replyTo) { |
13 var server = new ChatServer(); | 20 var server = new ChatServer(); |
14 server.init(); | 21 server.init(); |
15 port.receive(server.dispatch); | 22 replyTo.send(server.dispatchSendPort); |
16 } | 23 } |
17 | 24 |
18 class ChatServer extends IsolatedServer { | 25 class ChatServer extends IsolatedServer { |
19 } | 26 } |
20 | 27 |
21 class ServerMain { | 28 class ServerMain { |
22 ServerMain.start(SendPort serverPort, | 29 ServerMain.start(SendPort serverPort, |
23 String hostAddress, | 30 String hostAddress, |
24 int tcpPort) | 31 int tcpPort) |
25 : _statusPort = new ReceivePort(), | 32 : _statusPort = new ReceivePort(), |
26 _serverPort = serverPort { | 33 _serverPort = serverPort { |
27 // We can only guess this is the right URL. At least it gives a | 34 // We can only guess this is the right URL. At least it gives a |
28 // hint to the user. | 35 // hint to the user. |
29 print('Server starting http://${hostAddress}:${tcpPort}/'); | 36 print('Server starting http://${hostAddress}:${tcpPort}/'); |
30 _start(hostAddress, tcpPort); | 37 _start(hostAddress, tcpPort); |
31 } | 38 } |
32 | 39 |
33 void _start(String hostAddress, int tcpPort) { | 40 void _start(String hostAddress, int tcpPort) { |
34 // Handle status messages from the server. | 41 // Handle status messages from the server. |
35 _statusPort.receive((var message, SendPort replyTo) { | 42 _statusPort.listen((var message) { |
36 String status = message.message; | 43 String status = message.message; |
37 print("Received status: $status"); | 44 print("Received status: $status"); |
38 }); | 45 }); |
39 | 46 |
40 // Send server start message to the server. | 47 // Send server start message to the server. |
41 var command = new ChatServerCommand.start(hostAddress, tcpPort); | 48 var command = new ChatServerCommand.start(hostAddress, tcpPort); |
42 _serverPort.send(command, _statusPort.toSendPort()); | 49 _serverPort.send([command, _statusPort.sendPort]); |
43 } | 50 } |
44 | 51 |
45 void shutdown() { | 52 void shutdown() { |
46 // Send server stop message to the server. | 53 // Send server stop message to the server. |
47 _serverPort.send(new ChatServerCommand.stop(), _statusPort.toSendPort()); | 54 _serverPort.send([new ChatServerCommand.stop(), _statusPort.sendPort]); |
48 _statusPort.close(); | 55 _statusPort.close(); |
49 } | 56 } |
50 | 57 |
51 ReceivePort _statusPort; // Port for receiving messages from the server. | 58 ReceivePort _statusPort; // Port for receiving messages from the server. |
52 SendPort _serverPort; // Port for sending messages to the server. | 59 SendPort _serverPort; // Port for sending messages to the server. |
53 } | 60 } |
54 | 61 |
55 | 62 |
56 class User { | 63 class User { |
57 static int nextSessionId = 0; | 64 static int nextSessionId = 0; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 <body><h1>Redirecting to the front page...</h1></body> | 301 <body><h1>Redirecting to the front page...</h1></body> |
295 </html>"""; | 302 </html>"""; |
296 static const String notFoundPageHtml = """ | 303 static const String notFoundPageHtml = """ |
297 <html><head> | 304 <html><head> |
298 <title>404 Not Found</title> | 305 <title>404 Not Found</title> |
299 </head><body> | 306 </head><body> |
300 <h1>Not Found</h1> | 307 <h1>Not Found</h1> |
301 <p>The requested URL was not found on this server.</p> | 308 <p>The requested URL was not found on this server.</p> |
302 </body></html>"""; | 309 </body></html>"""; |
303 | 310 |
| 311 IsolatedServer() : _dispatchReceivePort = new ReceivePort() { |
| 312 _dispatchReceivePort.listen(dispatch); |
| 313 } |
| 314 |
304 void _sendJSONResponse(HttpResponse response, Map responseData) { | 315 void _sendJSONResponse(HttpResponse response, Map responseData) { |
305 response.headers.set("Content-Type", "application/json; charset=UTF-8"); | 316 response.headers.set("Content-Type", "application/json; charset=UTF-8"); |
306 response.write(JSON.encode(responseData)); | 317 response.write(JSON.encode(responseData)); |
307 response.close(); | 318 response.close(); |
308 } | 319 } |
309 | 320 |
310 void redirectPageHandler(HttpRequest request, | 321 void redirectPageHandler(HttpRequest request, |
311 HttpResponse response, | 322 HttpResponse response, |
312 String redirectPath) { | 323 String redirectPath) { |
313 if (_redirectPage == null) { | 324 if (_redirectPage == null) { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 } | 544 } |
534 | 545 |
535 // Start timer for periodic logging. | 546 // Start timer for periodic logging. |
536 void _handleLogging(Timer timer) { | 547 void _handleLogging(Timer timer) { |
537 if (_logging) { | 548 if (_logging) { |
538 print("${_messageRate.rate} messages/s " | 549 print("${_messageRate.rate} messages/s " |
539 "(total $_messageCount messages)"); | 550 "(total $_messageCount messages)"); |
540 } | 551 } |
541 } | 552 } |
542 | 553 |
543 void dispatch(message, replyTo) { | 554 SendPort get dispatchSendPort => _dispatchReceivePort.sendPort; |
544 if (message.isStart) { | 555 |
545 _host = message.host; | 556 void dispatch(message) { |
546 _port = message.port; | 557 var command = message[0]; |
547 _logging = message.logging; | 558 var replyTo = message[1]; |
548 replyTo.send(new ChatServerStatus.starting(), null); | 559 if (command.isStart) { |
| 560 _host = command.host; |
| 561 _port = command.port; |
| 562 _logging = command.logging; |
| 563 replyTo.send(new ChatServerStatus.starting()); |
549 var handlers = {}; | 564 var handlers = {}; |
550 void addRequestHandler(String path, Function handler) { | 565 void addRequestHandler(String path, Function handler) { |
551 handlers[path] = handler; | 566 handlers[path] = handler; |
552 } | 567 } |
553 addRequestHandler("/", (request, response) { | 568 addRequestHandler("/", (request, response) { |
554 redirectPageHandler(request, response, "dart_client/index.html"); | 569 redirectPageHandler(request, response, "dart_client/index.html"); |
555 }); | 570 }); |
556 addRequestHandler("/js_client/index.html", fileHandler); | 571 addRequestHandler("/js_client/index.html", fileHandler); |
557 addRequestHandler("/js_client/code.js", fileHandler); | 572 addRequestHandler("/js_client/code.js", fileHandler); |
558 addRequestHandler("/dart_client/index.html", fileHandler); | 573 addRequestHandler("/dart_client/index.html", fileHandler); |
559 addRequestHandler("/out.js", fileHandler); | 574 addRequestHandler("/out.js", fileHandler); |
560 addRequestHandler("/favicon.ico", (request, response) { | 575 addRequestHandler("/favicon.ico", (request, response) { |
561 fileHandler(request, response, "static/favicon.ico"); | 576 fileHandler(request, response, "static/favicon.ico"); |
562 }); | 577 }); |
563 addRequestHandler("/join", _joinHandler); | 578 addRequestHandler("/join", _joinHandler); |
564 addRequestHandler("/leave", _leaveHandler); | 579 addRequestHandler("/leave", _leaveHandler); |
565 addRequestHandler("/message", _messageHandler); | 580 addRequestHandler("/message", _messageHandler); |
566 addRequestHandler("/receive", _receiveHandler); | 581 addRequestHandler("/receive", _receiveHandler); |
567 HttpServer.bind(_host, _port) | 582 HttpServer.bind(_host, _port) |
568 .then((s) { | 583 .then((s) { |
569 _server = s; | 584 _server = s; |
570 _server.listen((request) { | 585 _server.listen((request) { |
571 if (handlers.containsKey(request.uri.path)) { | 586 if (handlers.containsKey(request.uri.path)) { |
572 handlers[request.uri.path](request, request.response); | 587 handlers[request.uri.path](request, request.response); |
573 } else { | 588 } else { |
574 _notFoundHandler(request, request.response); | 589 _notFoundHandler(request, request.response); |
575 } | 590 } |
576 }); | 591 }); |
577 replyTo.send(new ChatServerStatus.started(_server.port), null); | 592 replyTo.send(new ChatServerStatus.started(_server.port)); |
578 _loggingTimer = | 593 _loggingTimer = |
579 new Timer.periodic(const Duration(seconds: 1), _handleLogging); | 594 new Timer.periodic(const Duration(seconds: 1), _handleLogging); |
580 }) | 595 }) |
581 .catchError((e) { | 596 .catchError((e) { |
582 replyTo.send(new ChatServerStatus.error2(e.toString()), null); | 597 replyTo.send(new ChatServerStatus.error2(e.toString())); |
583 }); | 598 }); |
584 } else if (message.isStop) { | 599 } else if (command.isStop) { |
585 replyTo.send(new ChatServerStatus.stopping(), null); | 600 replyTo.send(new ChatServerStatus.stopping()); |
586 stop(); | 601 stop(); |
587 replyTo.send(new ChatServerStatus.stopped(), null); | 602 replyTo.send(new ChatServerStatus.stopped()); |
588 } | 603 } |
589 } | 604 } |
590 | 605 |
591 stop() { | 606 stop() { |
592 _server.close(); | 607 _server.close(); |
593 _cleanupTimer.cancel(); | 608 _cleanupTimer.cancel(); |
594 port.close(); | 609 _dispatchReceivePort.close(); |
595 } | 610 } |
596 | 611 |
597 String _host; | 612 String _host; |
| 613 ReceivePort _dispatchReceivePort; |
598 int _port; | 614 int _port; |
599 HttpServer _server; // HTTP server instance. | 615 HttpServer _server; // HTTP server instance. |
600 bool _logRequests; | 616 bool _logRequests; |
601 | 617 |
602 Topic _topic; | 618 Topic _topic; |
603 Timer _cleanupTimer; | 619 Timer _cleanupTimer; |
604 Timer _loggingTimer; | 620 Timer _loggingTimer; |
605 DateTime _serverStart; | 621 DateTime _serverStart; |
606 | 622 |
607 bool _logging; | 623 bool _logging; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 } | 687 } |
672 } | 688 } |
673 | 689 |
674 int _timeRange; | 690 int _timeRange; |
675 List<int> _buckets; | 691 List<int> _buckets; |
676 int _currentBucket; | 692 int _currentBucket; |
677 int _currentBucketTime; | 693 int _currentBucketTime; |
678 num _bucketTimeRange; | 694 num _bucketTimeRange; |
679 int _sum; | 695 int _sum; |
680 } | 696 } |
OLD | NEW |