| 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 |