| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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:io"); | 6 #import("dart:io"); |
| 7 #import("dart:isolate"); | 7 #import("dart:isolate"); |
| 8 #import("dart:json"); | 8 #import("dart:json"); |
| 9 | 9 |
| 10 typedef void RequestHandler(HttpRequest request, HttpResponse response); | |
| 11 | |
| 12 class ChatServer extends IsolatedServer { | 10 class ChatServer extends IsolatedServer { |
| 13 ChatServer() : super() { | |
| 14 addHandler("/", | |
| 15 (HttpRequest request, HttpResponse response) => | |
| 16 redirectPageHandler( | |
| 17 request, response, "dart_client/index.html")); | |
| 18 addHandler("/js_client/index.html", | |
| 19 (HttpRequest request, HttpResponse response) => | |
| 20 fileHandler(request, response)); | |
| 21 addHandler("/js_client/code.js", | |
| 22 (HttpRequest request, HttpResponse response) => | |
| 23 fileHandler(request, response)); | |
| 24 addHandler("/dart_client/index.html", | |
| 25 (HttpRequest request, HttpResponse response) => | |
| 26 fileHandler(request, response)); | |
| 27 addHandler("/out/dart_client/chat.dart.app.js", | |
| 28 (HttpRequest request, HttpResponse response) => | |
| 29 fileHandler(request, response)); | |
| 30 addHandler("/favicon.ico", | |
| 31 (HttpRequest request, HttpResponse response) => | |
| 32 fileHandler(request, response, "static/favicon.ico")); | |
| 33 | |
| 34 addHandler("/join", _joinHandler); | |
| 35 addHandler("/leave", _leaveHandler); | |
| 36 addHandler("/message", _messageHandler); | |
| 37 addHandler("/receive", _receiveHandler); | |
| 38 } | |
| 39 } | 11 } |
| 40 | 12 |
| 41 class ServerMain { | 13 class ServerMain { |
| 42 ServerMain.start(IsolatedServer server, | 14 ServerMain.start(IsolatedServer server, |
| 43 String hostAddress, | 15 String hostAddress, |
| 44 int tcpPort, | 16 int tcpPort, |
| 45 [int listenBacklog = 5]) | 17 [int listenBacklog = 5]) |
| 46 : _statusPort = new ReceivePort(), | 18 : _statusPort = new ReceivePort(), |
| 47 _serverPort = null { | 19 _serverPort = null { |
| 48 server.spawn().then((SendPort port) { | 20 server.spawn().then((SendPort port) { |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 <h1>Not Found</h1> | 300 <h1>Not Found</h1> |
| 329 <p>The requested URL was not found on this server.</p> | 301 <p>The requested URL was not found on this server.</p> |
| 330 </body></html>"""; | 302 </body></html>"""; |
| 331 | 303 |
| 332 void _sendJSONResponse(HttpResponse response, Map responseData) { | 304 void _sendJSONResponse(HttpResponse response, Map responseData) { |
| 333 response.headers.set("Content-Type", "application/json; charset=UTF-8"); | 305 response.headers.set("Content-Type", "application/json; charset=UTF-8"); |
| 334 response.outputStream.writeString(JSON.stringify(responseData)); | 306 response.outputStream.writeString(JSON.stringify(responseData)); |
| 335 response.outputStream.close(); | 307 response.outputStream.close(); |
| 336 } | 308 } |
| 337 | 309 |
| 338 IsolatedServer() : super() { | |
| 339 _requestHandlers = new Map(); | |
| 340 } | |
| 341 | |
| 342 void redirectPageHandler(HttpRequest request, | 310 void redirectPageHandler(HttpRequest request, |
| 343 HttpResponse response, | 311 HttpResponse response, |
| 344 String redirectPath) { | 312 String redirectPath) { |
| 345 if (_redirectPage == null) { | 313 if (_redirectPage == null) { |
| 346 _redirectPage = redirectPageHtml.charCodes(); | 314 _redirectPage = redirectPageHtml.charCodes(); |
| 347 } | 315 } |
| 348 response.statusCode = HttpStatus.FOUND; | 316 response.statusCode = HttpStatus.FOUND; |
| 349 response.headers.set( | 317 response.headers.set( |
| 350 "Location", "http://$_host:$_port/${redirectPath}"); | 318 "Location", "http://$_host:$_port/${redirectPath}"); |
| 351 response.contentLength = _redirectPage.length; | 319 response.contentLength = _redirectPage.length; |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 513 |
| 546 } else { | 514 } else { |
| 547 _protocolError(request, response); | 515 _protocolError(request, response); |
| 548 } | 516 } |
| 549 } else { | 517 } else { |
| 550 _protocolError(request, response); | 518 _protocolError(request, response); |
| 551 } | 519 } |
| 552 }; | 520 }; |
| 553 } | 521 } |
| 554 | 522 |
| 555 void addHandler(String path, | |
| 556 void handler(HttpRequest request, HttpResponse response)) { | |
| 557 _requestHandlers[path] = handler; | |
| 558 } | |
| 559 | |
| 560 void main() { | 523 void main() { |
| 561 _logRequests = false; | 524 _logRequests = false; |
| 562 _topic = new Topic(); | 525 _topic = new Topic(); |
| 563 _serverStart = new Date.now(); | 526 _serverStart = new Date.now(); |
| 564 _messageCount = 0; | 527 _messageCount = 0; |
| 565 _messageRate = new Rate(); | 528 _messageRate = new Rate(); |
| 566 | 529 |
| 567 // Start a timer for cleanup events. | 530 // Start a timer for cleanup events. |
| 568 _cleanupTimer = | 531 _cleanupTimer = |
| 569 new Timer.repeating(10000, (timer) => _topic._handleTimer(timer)); | 532 new Timer.repeating(10000, (timer) => _topic._handleTimer(timer)); |
| 570 | 533 |
| 571 // Start timer for periodic logging. | 534 // Start timer for periodic logging. |
| 572 void _handleLogging(Timer timer) { | 535 void _handleLogging(Timer timer) { |
| 573 if (_logging) { | 536 if (_logging) { |
| 574 print((_messageRate.rate).toString() + | 537 print((_messageRate.rate).toString() + |
| 575 " messages/s (total " + | 538 " messages/s (total " + |
| 576 _messageCount + | 539 _messageCount + |
| 577 " messages)"); | 540 " messages)"); |
| 578 } | 541 } |
| 579 } | 542 } |
| 580 | 543 |
| 581 this.port.receive((var message, SendPort replyTo) { | 544 this.port.receive((var message, SendPort replyTo) { |
| 582 if (message.isStart) { | 545 if (message.isStart) { |
| 583 _host = message.host; | 546 _host = message.host; |
| 584 _port = message.port; | 547 _port = message.port; |
| 585 _logging = message.logging; | 548 _logging = message.logging; |
| 586 replyTo.send(new ChatServerStatus.starting(), null); | 549 replyTo.send(new ChatServerStatus.starting(), null); |
| 587 _server = new HttpServer(); | 550 _server = new HttpServer(); |
| 551 _server.defaultRequestHandler = _notFoundHandler; |
| 552 _server.addRequestHandler( |
| 553 new RegExp("^/\$"), |
| 554 (HttpRequest request, HttpResponse response) => |
| 555 redirectPageHandler( |
| 556 request, response, "dart_client/index.html")); |
| 557 _server.addRequestHandler( |
| 558 new RegExp("^/js_client/index.html\$"), |
| 559 (HttpRequest request, HttpResponse response) => |
| 560 fileHandler(request, response)); |
| 561 _server.addRequestHandler( |
| 562 new RegExp("^/js_client/code.js\$"), |
| 563 (HttpRequest request, HttpResponse response) => |
| 564 fileHandler(request, response)); |
| 565 _server.addRequestHandler( |
| 566 new RegExp("^/dart_client/index.html\$"), |
| 567 (HttpRequest request, HttpResponse response) => |
| 568 fileHandler(request, response)); |
| 569 _server.addRequestHandler( |
| 570 new RegExp("^/out/dart_client/chat.dart.app.js\$"), |
| 571 (HttpRequest request, HttpResponse response) => |
| 572 fileHandler(request, response)); |
| 573 _server.addRequestHandler( |
| 574 new RegExp("^/favicon.ico\$"), |
| 575 (HttpRequest request, HttpResponse response) => |
| 576 fileHandler(request, response, "static/favicon.ico")); |
| 577 |
| 578 _server.addRequestHandler(new RegExp("^/join\$"), _joinHandler); |
| 579 _server.addRequestHandler(new RegExp("^/leave\$"), _leaveHandler); |
| 580 _server.addRequestHandler(new RegExp("^/message\$"), _messageHandler); |
| 581 _server.addRequestHandler(new RegExp("^/receive\$"), _receiveHandler); |
| 588 try { | 582 try { |
| 589 _server.listen(_host, _port, backlog: message.backlog); | 583 _server.listen(_host, _port, backlog: message.backlog); |
| 590 _server.onRequest = (HttpRequest req, HttpResponse rsp) => | |
| 591 _requestReceivedHandler(req, rsp); | |
| 592 replyTo.send(new ChatServerStatus.started(_server.port), null); | 584 replyTo.send(new ChatServerStatus.started(_server.port), null); |
| 593 _loggingTimer = new Timer.repeating(1000, _handleLogging); | 585 _loggingTimer = new Timer.repeating(1000, _handleLogging); |
| 594 } catch (var e) { | 586 } catch (var e) { |
| 595 replyTo.send(new ChatServerStatus.error(e.toString()), null); | 587 replyTo.send(new ChatServerStatus.error(e.toString()), null); |
| 596 } | 588 } |
| 597 } else if (message.isStop) { | 589 } else if (message.isStop) { |
| 598 replyTo.send(new ChatServerStatus.stopping(), null); | 590 replyTo.send(new ChatServerStatus.stopping(), null); |
| 599 stop(); | 591 stop(); |
| 600 replyTo.send(new ChatServerStatus.stopped(), null); | 592 replyTo.send(new ChatServerStatus.stopped(), null); |
| 601 } | 593 } |
| 602 }); | 594 }); |
| 603 } | 595 } |
| 604 | 596 |
| 605 stop() { | 597 stop() { |
| 606 _server.close(); | 598 _server.close(); |
| 607 _cleanupTimer.cancel(); | 599 _cleanupTimer.cancel(); |
| 608 this.port.close(); | 600 this.port.close(); |
| 609 } | 601 } |
| 610 | 602 |
| 611 void _requestReceivedHandler(HttpRequest request, HttpResponse response) { | |
| 612 if (_logRequests) { | |
| 613 String method = request.method; | |
| 614 String uri = request.uri; | |
| 615 print("Request: $method $uri"); | |
| 616 print("Request headers:"); | |
| 617 request.headers.forEach( | |
| 618 (String name, String value) => print("$name: $value")); | |
| 619 print("Request parameters:"); | |
| 620 request.queryParameters.forEach( | |
| 621 (String name, String value) => print("$name = $value")); | |
| 622 print(""); | |
| 623 } | |
| 624 | |
| 625 var requestHandler =_requestHandlers[request.path]; | |
| 626 if (requestHandler != null) { | |
| 627 requestHandler(request, response); | |
| 628 } else { | |
| 629 print('No request handler found for ${request.path}'); | |
| 630 _notFoundHandler(request, response); | |
| 631 } | |
| 632 } | |
| 633 | |
| 634 String _host; | 603 String _host; |
| 635 int _port; | 604 int _port; |
| 636 HttpServer _server; // HTTP server instance. | 605 HttpServer _server; // HTTP server instance. |
| 637 Map _requestHandlers; | |
| 638 bool _logRequests; | 606 bool _logRequests; |
| 639 | 607 |
| 640 Topic _topic; | 608 Topic _topic; |
| 641 Timer _cleanupTimer; | 609 Timer _cleanupTimer; |
| 642 Timer _loggingTimer; | 610 Timer _loggingTimer; |
| 643 Date _serverStart; | 611 Date _serverStart; |
| 644 | 612 |
| 645 bool _logging; | 613 bool _logging; |
| 646 int _messageCount; | 614 int _messageCount; |
| 647 Rate _messageRate; | 615 Rate _messageRate; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 } | 677 } |
| 710 } | 678 } |
| 711 | 679 |
| 712 int _timeRange; | 680 int _timeRange; |
| 713 List<int> _buckets; | 681 List<int> _buckets; |
| 714 int _currentBucket; | 682 int _currentBucket; |
| 715 int _currentBucketTime; | 683 int _currentBucketTime; |
| 716 num _bucketTimeRange; | 684 num _bucketTimeRange; |
| 717 int _sum; | 685 int _sum; |
| 718 } | 686 } |
| OLD | NEW |