| OLD | NEW |
| 1 // Copyright (c) 2012, 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:json' as json; | 9 import 'dart:json' as json; |
| 10 import 'dart:math'; | 10 import 'dart:math'; |
| 11 | 11 |
| 12 void startChatServer() { | 12 void startChatServer() { |
| 13 var server = new ChatServer(); | 13 var server = new ChatServer(); |
| 14 server.init(); | 14 server.init(); |
| 15 port.receive(server.dispatch); | 15 port.receive(server.dispatch); |
| 16 } | 16 } |
| 17 | 17 |
| 18 class ChatServer extends IsolatedServer { | 18 class ChatServer extends IsolatedServer { |
| 19 } | 19 } |
| 20 | 20 |
| 21 class ServerMain { | 21 class ServerMain { |
| 22 ServerMain.start(SendPort serverPort, | 22 ServerMain.start(SendPort serverPort, |
| 23 String hostAddress, | 23 String hostAddress, |
| 24 int tcpPort, | 24 int tcpPort) |
| 25 [int listenBacklog = 5]) | |
| 26 : _statusPort = new ReceivePort(), | 25 : _statusPort = new ReceivePort(), |
| 27 _serverPort = serverPort { | 26 _serverPort = serverPort { |
| 28 // We can only guess this is the right URL. At least it gives a | 27 // We can only guess this is the right URL. At least it gives a |
| 29 // hint to the user. | 28 // hint to the user. |
| 30 print('Server starting http://${hostAddress}:${tcpPort}/'); | 29 print('Server starting http://${hostAddress}:${tcpPort}/'); |
| 31 _start(hostAddress, tcpPort, listenBacklog); | 30 _start(hostAddress, tcpPort); |
| 32 } | 31 } |
| 33 | 32 |
| 34 void _start(String hostAddress, int tcpPort, int listenBacklog) { | 33 void _start(String hostAddress, int tcpPort) { |
| 35 // Handle status messages from the server. | 34 // Handle status messages from the server. |
| 36 _statusPort.receive((var message, SendPort replyTo) { | 35 _statusPort.receive((var message, SendPort replyTo) { |
| 37 String status = message.message; | 36 String status = message.message; |
| 38 print("Received status: $status"); | 37 print("Received status: $status"); |
| 39 }); | 38 }); |
| 40 | 39 |
| 41 // Send server start message to the server. | 40 // Send server start message to the server. |
| 42 var command = new ChatServerCommand.start(hostAddress, | 41 var command = new ChatServerCommand.start(hostAddress, tcpPort); |
| 43 tcpPort, | |
| 44 backlog: listenBacklog); | |
| 45 _serverPort.send(command, _statusPort.toSendPort()); | 42 _serverPort.send(command, _statusPort.toSendPort()); |
| 46 } | 43 } |
| 47 | 44 |
| 48 void shutdown() { | 45 void shutdown() { |
| 49 // Send server stop message to the server. | 46 // Send server stop message to the server. |
| 50 _serverPort.send(new ChatServerCommand.stop(), _statusPort.toSendPort()); | 47 _serverPort.send(new ChatServerCommand.stop(), _statusPort.toSendPort()); |
| 51 _statusPort.close(); | 48 _statusPort.close(); |
| 52 } | 49 } |
| 53 | 50 |
| 54 ReceivePort _statusPort; // Port for receiving messages from the server. | 51 ReceivePort _statusPort; // Port for receiving messages from the server. |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 Map<String, Function> _callbacks; | 215 Map<String, Function> _callbacks; |
| 219 } | 216 } |
| 220 | 217 |
| 221 | 218 |
| 222 class ChatServerCommand { | 219 class ChatServerCommand { |
| 223 static const START = 0; | 220 static const START = 0; |
| 224 static const STOP = 1; | 221 static const STOP = 1; |
| 225 | 222 |
| 226 ChatServerCommand.start(String this._host, | 223 ChatServerCommand.start(String this._host, |
| 227 int this._port, | 224 int this._port, |
| 228 {int backlog: 5, | 225 {bool logging: false}) |
| 229 bool logging: false}) | 226 : _command = START, _logging = logging; |
| 230 : _command = START, _backlog = backlog, _logging = logging; | |
| 231 ChatServerCommand.stop() : _command = STOP; | 227 ChatServerCommand.stop() : _command = STOP; |
| 232 | 228 |
| 233 bool get isStart => _command == START; | 229 bool get isStart => _command == START; |
| 234 bool get isStop => _command == STOP; | 230 bool get isStop => _command == STOP; |
| 235 | 231 |
| 236 String get host => _host; | 232 String get host => _host; |
| 237 int get port => _port; | 233 int get port => _port; |
| 238 bool get logging => _logging; | 234 bool get logging => _logging; |
| 239 int get backlog => _backlog; | |
| 240 | 235 |
| 241 int _command; | 236 int _command; |
| 242 String _host; | 237 String _host; |
| 243 int _port; | 238 int _port; |
| 244 int _backlog; | |
| 245 bool _logging; | 239 bool _logging; |
| 246 } | 240 } |
| 247 | 241 |
| 248 | 242 |
| 249 class ChatServerStatus { | 243 class ChatServerStatus { |
| 250 static const STARTING = 0; | 244 static const STARTING = 0; |
| 251 static const STARTED = 1; | 245 static const STARTED = 1; |
| 252 static const STOPPING = 2; | 246 static const STOPPING = 2; |
| 253 static const STOPPED = 3; | 247 static const STOPPED = 3; |
| 254 static const ERROR = 4; | 248 static const ERROR = 4; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 static const String notFoundPageHtml = """ | 296 static const String notFoundPageHtml = """ |
| 303 <html><head> | 297 <html><head> |
| 304 <title>404 Not Found</title> | 298 <title>404 Not Found</title> |
| 305 </head><body> | 299 </head><body> |
| 306 <h1>Not Found</h1> | 300 <h1>Not Found</h1> |
| 307 <p>The requested URL was not found on this server.</p> | 301 <p>The requested URL was not found on this server.</p> |
| 308 </body></html>"""; | 302 </body></html>"""; |
| 309 | 303 |
| 310 void _sendJSONResponse(HttpResponse response, Map responseData) { | 304 void _sendJSONResponse(HttpResponse response, Map responseData) { |
| 311 response.headers.set("Content-Type", "application/json; charset=UTF-8"); | 305 response.headers.set("Content-Type", "application/json; charset=UTF-8"); |
| 312 response.outputStream.writeString(json.stringify(responseData)); | 306 response.addString(json.stringify(responseData)); |
| 313 response.outputStream.close(); | 307 response.close(); |
| 314 } | 308 } |
| 315 | 309 |
| 316 void redirectPageHandler(HttpRequest request, | 310 void redirectPageHandler(HttpRequest request, |
| 317 HttpResponse response, | 311 HttpResponse response, |
| 318 String redirectPath) { | 312 String redirectPath) { |
| 319 if (_redirectPage == null) { | 313 if (_redirectPage == null) { |
| 320 _redirectPage = redirectPageHtml.charCodes; | 314 _redirectPage = redirectPageHtml.charCodes; |
| 321 } | 315 } |
| 322 response.statusCode = HttpStatus.FOUND; | 316 response.statusCode = HttpStatus.FOUND; |
| 323 response.headers.set( | 317 response.headers.set( |
| 324 "Location", "http://$_host:$_port/${redirectPath}"); | 318 "Location", "http://$_host:$_port/${redirectPath}"); |
| 325 response.contentLength = _redirectPage.length; | 319 response.contentLength = _redirectPage.length; |
| 326 response.outputStream.write(_redirectPage); | 320 response.add(_redirectPage); |
| 327 response.outputStream.close(); | 321 response.close(); |
| 328 } | 322 } |
| 329 | 323 |
| 330 // Serve the content of a file. | 324 // Serve the content of a file. |
| 331 void fileHandler( | 325 void fileHandler( |
| 332 HttpRequest request, HttpResponse response, [String fileName = null]) { | 326 HttpRequest request, HttpResponse response, [String fileName = null]) { |
| 333 final int BUFFER_SIZE = 4096; | 327 final int BUFFER_SIZE = 4096; |
| 334 if (fileName == null) { | 328 if (fileName == null) { |
| 335 fileName = request.path.substring(1); | 329 fileName = request.uri.path.substring(1); |
| 336 } | 330 } |
| 337 File file = new File(fileName); | 331 File file = new File(fileName); |
| 338 if (file.existsSync()) { | 332 if (file.existsSync()) { |
| 339 String mimeType = "text/html; charset=UTF-8"; | 333 String mimeType = "text/html; charset=UTF-8"; |
| 340 int lastDot = fileName.lastIndexOf(".", fileName.length); | 334 int lastDot = fileName.lastIndexOf(".", fileName.length); |
| 341 if (lastDot != -1) { | 335 if (lastDot != -1) { |
| 342 String extension = fileName.substring(lastDot); | 336 String extension = fileName.substring(lastDot); |
| 343 if (extension == ".css") { mimeType = "text/css"; } | 337 if (extension == ".css") { mimeType = "text/css"; } |
| 344 if (extension == ".js") { mimeType = "application/javascript"; } | 338 if (extension == ".js") { mimeType = "application/javascript"; } |
| 345 if (extension == ".ico") { mimeType = "image/vnd.microsoft.icon"; } | 339 if (extension == ".ico") { mimeType = "image/vnd.microsoft.icon"; } |
| 346 if (extension == ".png") { mimeType = "image/png"; } | 340 if (extension == ".png") { mimeType = "image/png"; } |
| 347 } | 341 } |
| 348 response.headers.set("Content-Type", mimeType); | 342 response.headers.set("Content-Type", mimeType); |
| 349 // Get the length of the file for setting the Content-Length header. | 343 // Get the length of the file for setting the Content-Length header. |
| 350 RandomAccessFile openedFile = file.openSync(); | 344 RandomAccessFile openedFile = file.openSync(); |
| 351 response.contentLength = openedFile.lengthSync(); | 345 response.contentLength = openedFile.lengthSync(); |
| 352 openedFile.closeSync(); | 346 openedFile.closeSync(); |
| 353 // Pipe the file content into the response. | 347 // Pipe the file content into the response. |
| 354 file.openInputStream().pipe(response.outputStream); | 348 file.openRead().pipe(response); |
| 355 } else { | 349 } else { |
| 356 print("File not found: $fileName"); | 350 print("File not found: $fileName"); |
| 357 _notFoundHandler(request, response); | 351 _notFoundHandler(request, response); |
| 358 } | 352 } |
| 359 } | 353 } |
| 360 | 354 |
| 361 // Serve the not found page. | 355 // Serve the not found page. |
| 362 void _notFoundHandler(HttpRequest request, HttpResponse response) { | 356 void _notFoundHandler(HttpRequest request, HttpResponse response) { |
| 363 if (_notFoundPage == null) { | 357 if (_notFoundPage == null) { |
| 364 _notFoundPage = notFoundPageHtml.charCodes; | 358 _notFoundPage = notFoundPageHtml.charCodes; |
| 365 } | 359 } |
| 366 response.statusCode = HttpStatus.NOT_FOUND; | 360 response.statusCode = HttpStatus.NOT_FOUND; |
| 367 response.headers.set("Content-Type", "text/html; charset=UTF-8"); | 361 response.headers.set("Content-Type", "text/html; charset=UTF-8"); |
| 368 response.contentLength = _notFoundPage.length; | 362 response.contentLength = _notFoundPage.length; |
| 369 response.outputStream.write(_notFoundPage); | 363 response.add(_notFoundPage); |
| 370 response.outputStream.close(); | 364 response.close(); |
| 371 } | 365 } |
| 372 | 366 |
| 373 // Unexpected protocol data. | 367 // Unexpected protocol data. |
| 374 void _protocolError(HttpRequest request, HttpResponse response) { | 368 void _protocolError(HttpRequest request, HttpResponse response) { |
| 375 response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR; | 369 response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR; |
| 376 response.contentLength = 0; | 370 response.contentLength = 0; |
| 377 response.outputStream.close(); | 371 response.close(); |
| 378 } | 372 } |
| 379 | 373 |
| 380 // Join request: | 374 // Join request: |
| 381 // { "request": "join", | 375 // { "request": "join", |
| 382 // "handle": <handle> } | 376 // "handle": <handle> } |
| 383 void _joinHandler(HttpRequest request, HttpResponse response) { | 377 void _joinHandler(HttpRequest request, HttpResponse response) { |
| 384 StringBuffer body = new StringBuffer(); | 378 StringBuffer body = new StringBuffer(); |
| 385 StringInputStream input = new StringInputStream(request.inputStream); | 379 request.listen( |
| 386 input.onData = () => body.add(input.read()); | 380 (data) => body.add(new String.fromCharCodes(data)), |
| 387 input.onClosed = () { | 381 onDone: () { |
| 388 String data = body.toString(); | 382 String data = body.toString(); |
| 389 if (data != null) { | 383 if (data != null) { |
| 390 var requestData = json.parse(data); | 384 var requestData = json.parse(data); |
| 391 if (requestData["request"] == "join") { | 385 if (requestData["request"] == "join") { |
| 392 String handle = requestData["handle"]; | 386 String handle = requestData["handle"]; |
| 393 if (handle != null) { | 387 if (handle != null) { |
| 394 // New user joining. | 388 // New user joining. |
| 395 User user = _topic._userJoined(handle); | 389 User user = _topic._userJoined(handle); |
| 396 | 390 |
| 397 // Send response. | 391 // Send response. |
| 398 Map responseData = new Map(); | 392 Map responseData = new Map(); |
| 399 responseData["response"] = "join"; | 393 responseData["response"] = "join"; |
| 400 responseData["sessionId"] = user.sessionId; | 394 responseData["sessionId"] = user.sessionId; |
| 401 _sendJSONResponse(response, responseData); | 395 _sendJSONResponse(response, responseData); |
| 396 } else { |
| 397 _protocolError(request, response); |
| 398 } |
| 402 } else { | 399 } else { |
| 403 _protocolError(request, response); | 400 _protocolError(request, response); |
| 404 } | 401 } |
| 405 } else { | 402 } else { |
| 406 _protocolError(request, response); | 403 _protocolError(request, response); |
| 407 } | 404 } |
| 408 } else { | 405 }); |
| 409 _protocolError(request, response); | |
| 410 } | |
| 411 }; | |
| 412 } | 406 } |
| 413 | 407 |
| 414 // Leave request: | 408 // Leave request: |
| 415 // { "request": "leave", | 409 // { "request": "leave", |
| 416 // "sessionId": <sessionId> } | 410 // "sessionId": <sessionId> } |
| 417 void _leaveHandler(HttpRequest request, HttpResponse response) { | 411 void _leaveHandler(HttpRequest request, HttpResponse response) { |
| 418 StringBuffer body = new StringBuffer(); | 412 StringBuffer body = new StringBuffer(); |
| 419 StringInputStream input = new StringInputStream(request.inputStream); | 413 request.listen( |
| 420 input.onData = () => body.add(input.read()); | 414 (data) => body.add(new String.fromCharCodes(data)), |
| 421 input.onClosed = () { | 415 onDone: () { |
| 422 String data = body.toString(); | 416 String data = body.toString(); |
| 423 var requestData = json.parse(data); | 417 var requestData = json.parse(data); |
| 424 if (requestData["request"] == "leave") { | 418 if (requestData["request"] == "leave") { |
| 425 String sessionId = requestData["sessionId"]; | 419 String sessionId = requestData["sessionId"]; |
| 426 if (sessionId != null) { | 420 if (sessionId != null) { |
| 427 // User leaving. | 421 // User leaving. |
| 428 _topic._userLeft(sessionId); | 422 _topic._userLeft(sessionId); |
| 429 | 423 |
| 430 // Send response. | 424 // Send response. |
| 431 Map responseData = new Map(); | 425 Map responseData = new Map(); |
| 432 responseData["response"] = "leave"; | 426 responseData["response"] = "leave"; |
| 433 _sendJSONResponse(response, responseData); | 427 _sendJSONResponse(response, responseData); |
| 428 } else { |
| 429 _protocolError(request, response); |
| 430 } |
| 434 } else { | 431 } else { |
| 435 _protocolError(request, response); | 432 _protocolError(request, response); |
| 436 } | 433 } |
| 437 } else { | 434 }); |
| 438 _protocolError(request, response); | |
| 439 } | |
| 440 }; | |
| 441 } | 435 } |
| 442 | 436 |
| 443 // Message request: | 437 // Message request: |
| 444 // { "request": "message", | 438 // { "request": "message", |
| 445 // "sessionId": <sessionId>, | 439 // "sessionId": <sessionId>, |
| 446 // "message": <message> } | 440 // "message": <message> } |
| 447 void _messageHandler(HttpRequest request, HttpResponse response) { | 441 void _messageHandler(HttpRequest request, HttpResponse response) { |
| 448 StringBuffer body = new StringBuffer(); | 442 StringBuffer body = new StringBuffer(); |
| 449 StringInputStream input = new StringInputStream(request.inputStream); | 443 request.listen( |
| 450 input.onData = () => body.add(input.read()); | 444 (data) => body.add(new String.fromCharCodes(data)), |
| 451 input.onClosed = () { | 445 onDone: () { |
| 452 String data = body.toString(); | 446 String data = body.toString(); |
| 453 _messageCount++; | 447 _messageCount++; |
| 454 _messageRate.record(1); | 448 _messageRate.record(1); |
| 455 var requestData = json.parse(data); | 449 var requestData = json.parse(data); |
| 456 if (requestData["request"] == "message") { | 450 if (requestData["request"] == "message") { |
| 457 String sessionId = requestData["sessionId"]; | 451 String sessionId = requestData["sessionId"]; |
| 458 if (sessionId != null) { | 452 if (sessionId != null) { |
| 459 // New message from user. | 453 // New message from user. |
| 460 bool success = _topic._userMessage(requestData); | 454 bool success = _topic._userMessage(requestData); |
| 461 | 455 |
| 462 // Send response. | 456 // Send response. |
| 463 if (success) { | 457 if (success) { |
| 464 Map responseData = new Map(); | 458 Map responseData = new Map(); |
| 465 responseData["response"] = "message"; | 459 responseData["response"] = "message"; |
| 466 _sendJSONResponse(response, responseData); | 460 _sendJSONResponse(response, responseData); |
| 461 } else { |
| 462 _protocolError(request, response); |
| 463 } |
| 467 } else { | 464 } else { |
| 468 _protocolError(request, response); | 465 _protocolError(request, response); |
| 469 } | 466 } |
| 470 } else { | 467 } else { |
| 471 _protocolError(request, response); | 468 _protocolError(request, response); |
| 472 } | 469 } |
| 473 } else { | 470 }); |
| 474 _protocolError(request, response); | |
| 475 } | |
| 476 }; | |
| 477 } | 471 } |
| 478 | 472 |
| 479 // Receive request: | 473 // Receive request: |
| 480 // { "request": "receive", | 474 // { "request": "receive", |
| 481 // "sessionId": <sessionId>, | 475 // "sessionId": <sessionId>, |
| 482 // "nextMessage": <nextMessage>, | 476 // "nextMessage": <nextMessage>, |
| 483 // "maxMessages": <maxMesssages> } | 477 // "maxMessages": <maxMesssages> } |
| 484 void _receiveHandler(HttpRequest request, HttpResponse response) { | 478 void _receiveHandler(HttpRequest request, HttpResponse response) { |
| 485 StringBuffer body = new StringBuffer(); | 479 StringBuffer body = new StringBuffer(); |
| 486 StringInputStream input = new StringInputStream(request.inputStream); | 480 request.listen( |
| 487 input.onData = () => body.add(input.read()); | 481 (data) => body.add(new String.fromCharCodes(data)), |
| 488 input.onClosed = () { | 482 onDone: () { |
| 489 String data = body.toString(); | 483 String data = body.toString(); |
| 490 var requestData = json.parse(data); | 484 var requestData = json.parse(data); |
| 491 if (requestData["request"] == "receive") { | 485 if (requestData["request"] == "receive") { |
| 492 String sessionId = requestData["sessionId"]; | 486 String sessionId = requestData["sessionId"]; |
| 493 int nextMessage = requestData["nextMessage"]; | 487 int nextMessage = requestData["nextMessage"]; |
| 494 int maxMessages = requestData["maxMessages"]; | 488 int maxMessages = requestData["maxMessages"]; |
| 495 if (sessionId != null && nextMessage != null) { | 489 if (sessionId != null && nextMessage != null) { |
| 496 | 490 |
| 497 void sendResponse(messages) { | 491 void sendResponse(messages) { |
| 498 // Send response. | 492 // Send response. |
| 499 Map responseData = new Map(); | 493 Map responseData = new Map(); |
| 500 responseData["response"] = "receive"; | 494 responseData["response"] = "receive"; |
| 501 if (messages != null) { | 495 if (messages != null) { |
| 502 responseData["messages"] = messages; | 496 responseData["messages"] = messages; |
| 503 responseData["activeUsers"] = _topic.activeUsers; | 497 responseData["activeUsers"] = _topic.activeUsers; |
| 504 responseData["upTime"] = | 498 responseData["upTime"] = |
| 505 new DateTime.now().difference(_serverStart).inMilliseconds; | 499 new DateTime.now().difference(_serverStart).inMilliseconds; |
| 500 } else { |
| 501 responseData["disconnect"] = true; |
| 502 } |
| 503 _sendJSONResponse(response, responseData); |
| 504 } |
| 505 |
| 506 // Receive request from user. |
| 507 List messages = _topic.messagesFrom(nextMessage, maxMessages); |
| 508 if (messages == null) { |
| 509 _topic.registerChangeCallback(sessionId, sendResponse); |
| 506 } else { | 510 } else { |
| 507 responseData["disconnect"] = true; | 511 sendResponse(messages); |
| 508 } | 512 } |
| 509 _sendJSONResponse(response, responseData); | 513 |
| 514 } else { |
| 515 _protocolError(request, response); |
| 510 } | 516 } |
| 511 | |
| 512 // Receive request from user. | |
| 513 List messages = _topic.messagesFrom(nextMessage, maxMessages); | |
| 514 if (messages == null) { | |
| 515 _topic.registerChangeCallback(sessionId, sendResponse); | |
| 516 } else { | |
| 517 sendResponse(messages); | |
| 518 } | |
| 519 | |
| 520 } else { | 517 } else { |
| 521 _protocolError(request, response); | 518 _protocolError(request, response); |
| 522 } | 519 } |
| 523 } else { | 520 }); |
| 524 _protocolError(request, response); | |
| 525 } | |
| 526 }; | |
| 527 } | 521 } |
| 528 | 522 |
| 529 void init() { | 523 void init() { |
| 530 _logRequests = false; | 524 _logRequests = false; |
| 531 _topic = new Topic(); | 525 _topic = new Topic(); |
| 532 _serverStart = new DateTime.now(); | 526 _serverStart = new DateTime.now(); |
| 533 _messageCount = 0; | 527 _messageCount = 0; |
| 534 _messageRate = new Rate(); | 528 _messageRate = new Rate(); |
| 535 | 529 |
| 536 // Start a timer for cleanup events. | 530 // Start a timer for cleanup events. |
| 537 _cleanupTimer = new Timer.repeating(const Duration(seconds: 10), | 531 _cleanupTimer = new Timer.repeating(const Duration(seconds: 10), |
| 538 _topic._handleTimer); | 532 _topic._handleTimer); |
| 539 } | 533 } |
| 540 | 534 |
| 541 // Start timer for periodic logging. | 535 // Start timer for periodic logging. |
| 542 void _handleLogging(Timer timer) { | 536 void _handleLogging(Timer timer) { |
| 543 if (_logging) { | 537 if (_logging) { |
| 544 print("${_messageRate.rate} messages/s " | 538 print("${_messageRate.rate} messages/s " |
| 545 "(total $_messageCount messages)"); | 539 "(total $_messageCount messages)"); |
| 546 } | 540 } |
| 547 } | 541 } |
| 548 | 542 |
| 549 void dispatch(message, replyTo) { | 543 void dispatch(message, replyTo) { |
| 550 if (message.isStart) { | 544 if (message.isStart) { |
| 551 _host = message.host; | 545 _host = message.host; |
| 552 _port = message.port; | 546 _port = message.port; |
| 553 _logging = message.logging; | 547 _logging = message.logging; |
| 554 replyTo.send(new ChatServerStatus.starting(), null); | 548 replyTo.send(new ChatServerStatus.starting(), null); |
| 555 _server = new HttpServer(); | 549 var handlers = {}; |
| 556 _server.defaultRequestHandler = _notFoundHandler; | 550 void addRequestHandler(String path, Function handler) { |
| 557 _server.addRequestHandler( | 551 handlers[path] = handler; |
| 558 (request) => request.path == "/", | |
| 559 (HttpRequest request, HttpResponse response) => | |
| 560 redirectPageHandler( | |
| 561 request, response, "dart_client/index.html")); | |
| 562 _server.addRequestHandler( | |
| 563 (request) => request.path == "/js_client/index.html", | |
| 564 (HttpRequest request, HttpResponse response) => | |
| 565 fileHandler(request, response)); | |
| 566 _server.addRequestHandler( | |
| 567 (request) => request.path == "/js_client/code.js", | |
| 568 (HttpRequest request, HttpResponse response) => | |
| 569 fileHandler(request, response)); | |
| 570 _server.addRequestHandler( | |
| 571 (request) => request.path == "/dart_client/index.html", | |
| 572 (HttpRequest request, HttpResponse response) => | |
| 573 fileHandler(request, response)); | |
| 574 _server.addRequestHandler( | |
| 575 (request) => request.path == "/out.js", | |
| 576 (HttpRequest request, HttpResponse response) => | |
| 577 fileHandler(request, response)); | |
| 578 _server.addRequestHandler( | |
| 579 (request) => request.path == "/favicon.ico", | |
| 580 (HttpRequest request, HttpResponse response) => | |
| 581 fileHandler(request, response, "static/favicon.ico")); | |
| 582 | |
| 583 _server.addRequestHandler( | |
| 584 (request) => request.path == "/join", _joinHandler); | |
| 585 _server.addRequestHandler( | |
| 586 (request) => request.path == "/leave", _leaveHandler); | |
| 587 _server.addRequestHandler( | |
| 588 (request) => request.path == "/message", _messageHandler); | |
| 589 _server.addRequestHandler( | |
| 590 (request) => request.path == "/receive", _receiveHandler); | |
| 591 try { | |
| 592 _server.listen(_host, _port, backlog: message.backlog); | |
| 593 replyTo.send(new ChatServerStatus.started(_server.port), null); | |
| 594 _loggingTimer = | |
| 595 new Timer.repeating(const Duration(seconds: 1), _handleLogging); | |
| 596 } catch (e) { | |
| 597 replyTo.send(new ChatServerStatus.error2(e.toString()), null); | |
| 598 } | 552 } |
| 553 addRequestHandler("/", (request, response) { |
| 554 redirectPageHandler(request, response, "dart_client/index.html"); |
| 555 }); |
| 556 addRequestHandler("/js_client/index.html", fileHandler); |
| 557 addRequestHandler("/js_client/code.js", fileHandler); |
| 558 addRequestHandler("/dart_client/index.html", fileHandler); |
| 559 addRequestHandler("/out.js", fileHandler); |
| 560 addRequestHandler("/favicon.ico", (request, response) { |
| 561 fileHandler(request, response, "static/favicon.ico"); |
| 562 }); |
| 563 addRequestHandler("/join", _joinHandler); |
| 564 addRequestHandler("/leave", _leaveHandler); |
| 565 addRequestHandler("/message", _messageHandler); |
| 566 addRequestHandler("/receive", _receiveHandler); |
| 567 HttpServer.bind(_host, _port) |
| 568 .then((s) { |
| 569 _server = s; |
| 570 _server.listen((request) { |
| 571 if (handlers.containsKey(request.uri.path)) { |
| 572 handlers[request.uri.path](request, request.response); |
| 573 } else { |
| 574 _notFoundHandler(request, request.response); |
| 575 } |
| 576 }); |
| 577 replyTo.send(new ChatServerStatus.started(_server.port), null); |
| 578 _loggingTimer = |
| 579 new Timer.repeating(const Duration(seconds: 1), _handleLogging); |
| 580 }) |
| 581 .catchError((e) { |
| 582 replyTo.send(new ChatServerStatus.error2(e.toString()), null); |
| 583 }); |
| 599 } else if (message.isStop) { | 584 } else if (message.isStop) { |
| 600 replyTo.send(new ChatServerStatus.stopping(), null); | 585 replyTo.send(new ChatServerStatus.stopping(), null); |
| 601 stop(); | 586 stop(); |
| 602 replyTo.send(new ChatServerStatus.stopped(), null); | 587 replyTo.send(new ChatServerStatus.stopped(), null); |
| 603 } | 588 } |
| 604 } | 589 } |
| 605 | 590 |
| 606 stop() { | 591 stop() { |
| 607 _server.close(); | 592 _server.close(); |
| 608 _cleanupTimer.cancel(); | 593 _cleanupTimer.cancel(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 } | 671 } |
| 687 } | 672 } |
| 688 | 673 |
| 689 int _timeRange; | 674 int _timeRange; |
| 690 List<int> _buckets; | 675 List<int> _buckets; |
| 691 int _currentBucket; | 676 int _currentBucket; |
| 692 int _currentBucketTime; | 677 int _currentBucketTime; |
| 693 num _bucketTimeRange; | 678 num _bucketTimeRange; |
| 694 int _sum; | 679 int _sum; |
| 695 } | 680 } |
| OLD | NEW |