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 #import("dart:math"); | 9 #import("dart:math"); |
10 | 10 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 User(this._handle) { | 59 User(this._handle) { |
60 // TODO(sgjesse) Generate more secure and unique session id's. | 60 // TODO(sgjesse) Generate more secure and unique session id's. |
61 var rand = new Random(); | 61 var rand = new Random(); |
62 _sessionId = "a${rand.nextInt(1000000)}"; | 62 _sessionId = "a${rand.nextInt(1000000)}"; |
63 markActivity(); | 63 markActivity(); |
64 } | 64 } |
65 | 65 |
66 void markActivity() { _lastActive = new Date.now(); } | 66 void markActivity() { _lastActive = new Date.now(); } |
67 Duration idleTime(Date now) => now.difference(_lastActive); | 67 Duration idleTime(Date now) => now.difference(_lastActive); |
68 | 68 |
69 String get handle() => _handle; | 69 String get handle => _handle; |
70 String get sessionId() => _sessionId; | 70 String get sessionId => _sessionId; |
71 | 71 |
72 String _handle; | 72 String _handle; |
73 String _sessionId; | 73 String _sessionId; |
74 Date _lastActive; | 74 Date _lastActive; |
75 } | 75 } |
76 | 76 |
77 | 77 |
78 class Message { | 78 class Message { |
79 static const int JOIN = 0; | 79 static const int JOIN = 0; |
80 static const int MESSAGE = 1; | 80 static const int MESSAGE = 1; |
81 static const int LEAVE = 2; | 81 static const int LEAVE = 2; |
82 static const int TIMEOUT = 3; | 82 static const int TIMEOUT = 3; |
83 static const List<String> _typeName = | 83 static const List<String> _typeName = |
84 const [ "join", "message", "leave", "timeout"]; | 84 const [ "join", "message", "leave", "timeout"]; |
85 | 85 |
86 Message.join(this._from) | 86 Message.join(this._from) |
87 : _received = new Date.now(), _type = JOIN; | 87 : _received = new Date.now(), _type = JOIN; |
88 Message(this._from, this._message) | 88 Message(this._from, this._message) |
89 : _received = new Date.now(), _type = MESSAGE; | 89 : _received = new Date.now(), _type = MESSAGE; |
90 Message.leave(this._from) | 90 Message.leave(this._from) |
91 : _received = new Date.now(), _type = LEAVE; | 91 : _received = new Date.now(), _type = LEAVE; |
92 Message.timeout(this._from) | 92 Message.timeout(this._from) |
93 : _received = new Date.now(), _type = TIMEOUT; | 93 : _received = new Date.now(), _type = TIMEOUT; |
94 | 94 |
95 User get from() => _from; | 95 User get from => _from; |
96 Date get received() => _received; | 96 Date get received => _received; |
97 String get message() => _message; | 97 String get message => _message; |
98 void set messageNumber(int n) { _messageNumber = n; } | 98 void set messageNumber(int n) { _messageNumber = n; } |
99 | 99 |
100 Map toMap() { | 100 Map toMap() { |
101 Map map = new Map(); | 101 Map map = new Map(); |
102 map["from"] = _from.handle; | 102 map["from"] = _from.handle; |
103 map["received"] = _received.toString(); | 103 map["received"] = _received.toString(); |
104 map["type"] = _typeName[_type]; | 104 map["type"] = _typeName[_type]; |
105 if (_type == MESSAGE) map["message"] = _message; | 105 if (_type == MESSAGE) map["message"] = _message; |
106 map["number"] = _messageNumber; | 106 map["number"] = _messageNumber; |
107 return map; | 107 return map; |
108 } | 108 } |
109 | 109 |
110 User _from; | 110 User _from; |
111 Date _received; | 111 Date _received; |
112 int _type; | 112 int _type; |
113 String _message; | 113 String _message; |
114 int _messageNumber; | 114 int _messageNumber; |
115 } | 115 } |
116 | 116 |
117 | 117 |
118 class Topic { | 118 class Topic { |
119 static const int DEFAULT_IDLE_TIMEOUT = 60 * 60 * 1000; // One hour. | 119 static const int DEFAULT_IDLE_TIMEOUT = 60 * 60 * 1000; // One hour. |
120 Topic() | 120 Topic() |
121 : _activeUsers = new Map(), | 121 : _activeUsers = new Map(), |
122 _messages = new List(), | 122 _messages = new List(), |
123 _nextMessageNumber = 0, | 123 _nextMessageNumber = 0, |
124 _callbacks = new Map(); | 124 _callbacks = new Map(); |
125 | 125 |
126 int get activeUsers() => _activeUsers.length; | 126 int get activeUsers => _activeUsers.length; |
127 | 127 |
128 User _userJoined(String handle) { | 128 User _userJoined(String handle) { |
129 User user = new User(handle); | 129 User user = new User(handle); |
130 _activeUsers[user.sessionId] = user; | 130 _activeUsers[user.sessionId] = user; |
131 Message message = new Message.join(user); | 131 Message message = new Message.join(user); |
132 _addMessage(message); | 132 _addMessage(message); |
133 return user; | 133 return user; |
134 } | 134 } |
135 | 135 |
136 User _userLookup(String sessionId) => _activeUsers[sessionId]; | 136 User _userLookup(String sessionId) => _activeUsers[sessionId]; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 static const START = 0; | 222 static const START = 0; |
223 static const STOP = 1; | 223 static const STOP = 1; |
224 | 224 |
225 ChatServerCommand.start(String this._host, | 225 ChatServerCommand.start(String this._host, |
226 int this._port, | 226 int this._port, |
227 [int backlog = 5, | 227 [int backlog = 5, |
228 bool logging = false]) | 228 bool logging = false]) |
229 : _command = START, _backlog = backlog, _logging = logging; | 229 : _command = START, _backlog = backlog, _logging = logging; |
230 ChatServerCommand.stop() : _command = STOP; | 230 ChatServerCommand.stop() : _command = STOP; |
231 | 231 |
232 bool get isStart() => _command == START; | 232 bool get isStart => _command == START; |
233 bool get isStop() => _command == STOP; | 233 bool get isStop => _command == STOP; |
234 | 234 |
235 String get host() => _host; | 235 String get host => _host; |
236 int get port() => _port; | 236 int get port => _port; |
237 bool get logging() => _logging; | 237 bool get logging => _logging; |
238 int get backlog() => _backlog; | 238 int get backlog => _backlog; |
239 | 239 |
240 int _command; | 240 int _command; |
241 String _host; | 241 String _host; |
242 int _port; | 242 int _port; |
243 int _backlog; | 243 int _backlog; |
244 bool _logging; | 244 bool _logging; |
245 } | 245 } |
246 | 246 |
247 | 247 |
248 class ChatServerStatus { | 248 class ChatServerStatus { |
249 static const STARTING = 0; | 249 static const STARTING = 0; |
250 static const STARTED = 1; | 250 static const STARTED = 1; |
251 static const STOPPING = 2; | 251 static const STOPPING = 2; |
252 static const STOPPED = 3; | 252 static const STOPPED = 3; |
253 static const ERROR = 4; | 253 static const ERROR = 4; |
254 | 254 |
255 ChatServerStatus(this._state, this._message); | 255 ChatServerStatus(this._state, this._message); |
256 ChatServerStatus.starting() : _state = STARTING; | 256 ChatServerStatus.starting() : _state = STARTING; |
257 ChatServerStatus.started(this._port) : _state = STARTED; | 257 ChatServerStatus.started(this._port) : _state = STARTED; |
258 ChatServerStatus.stopping() : _state = STOPPING; | 258 ChatServerStatus.stopping() : _state = STOPPING; |
259 ChatServerStatus.stopped() : _state = STOPPED; | 259 ChatServerStatus.stopped() : _state = STOPPED; |
260 ChatServerStatus.error([this._error]) : _state = ERROR; | 260 ChatServerStatus.error([this._error]) : _state = ERROR; |
261 | 261 |
262 bool get isStarting() => _state == STARTING; | 262 bool get isStarting => _state == STARTING; |
263 bool get isStarted() => _state == STARTED; | 263 bool get isStarted => _state == STARTED; |
264 bool get isStopping() => _state == STOPPING; | 264 bool get isStopping => _state == STOPPING; |
265 bool get isStopped() => _state == STOPPED; | 265 bool get isStopped => _state == STOPPED; |
266 bool get isError() => _state == ERROR; | 266 bool get isError => _state == ERROR; |
267 | 267 |
268 int get state() => _state; | 268 int get state => _state; |
269 String get message() { | 269 String get message { |
270 if (_message != null) return _message; | 270 if (_message != null) return _message; |
271 switch (_state) { | 271 switch (_state) { |
272 case STARTING: return "Server starting"; | 272 case STARTING: return "Server starting"; |
273 case STARTED: return "Server listening"; | 273 case STARTED: return "Server listening"; |
274 case STOPPING: return "Server stopping"; | 274 case STOPPING: return "Server stopping"; |
275 case STOPPED: return "Server stopped"; | 275 case STOPPED: return "Server stopped"; |
276 case ERROR: | 276 case ERROR: |
277 if (_error == null) { | 277 if (_error == null) { |
278 return "Server error"; | 278 return "Server error"; |
279 } else { | 279 } else { |
280 return "Server error: $_error"; | 280 return "Server error: $_error"; |
281 } | 281 } |
282 } | 282 } |
283 } | 283 } |
284 | 284 |
285 int get port() => _port; | 285 int get port => _port; |
286 Dynamic get error() => _error; | 286 Dynamic get error => _error; |
287 | 287 |
288 int _state; | 288 int _state; |
289 String _message; | 289 String _message; |
290 int _port; | 290 int _port; |
291 var _error; | 291 var _error; |
292 } | 292 } |
293 | 293 |
294 | 294 |
295 class IsolatedServer { | 295 class IsolatedServer { |
296 static const String redirectPageHtml = """ | 296 static const String redirectPageHtml = """ |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 } | 648 } |
649 } | 649 } |
650 | 650 |
651 // Record the specified number of events. | 651 // Record the specified number of events. |
652 void record(int count) { | 652 void record(int count) { |
653 _timePassed(); | 653 _timePassed(); |
654 _buckets[_currentBucket] = _buckets[_currentBucket] + count; | 654 _buckets[_currentBucket] = _buckets[_currentBucket] + count; |
655 } | 655 } |
656 | 656 |
657 // Returns the current rate of events for the time range. | 657 // Returns the current rate of events for the time range. |
658 num get rate() { | 658 num get rate { |
659 _timePassed(); | 659 _timePassed(); |
660 return _sum; | 660 return _sum; |
661 } | 661 } |
662 | 662 |
663 // Update the current sum as time passes. If time has passed by the | 663 // Update the current sum as time passes. If time has passed by the |
664 // current bucket add it to the sum and move forward to the bucket | 664 // current bucket add it to the sum and move forward to the bucket |
665 // matching the current time. Subtract all buckets vacated from the | 665 // matching the current time. Subtract all buckets vacated from the |
666 // sum as bucket for current time is located. | 666 // sum as bucket for current time is located. |
667 void _timePassed() { | 667 void _timePassed() { |
668 int time = new Date.now().millisecondsSinceEpoch; | 668 int time = new Date.now().millisecondsSinceEpoch; |
(...skipping 15 matching lines...) Expand all Loading... |
684 } | 684 } |
685 } | 685 } |
686 | 686 |
687 int _timeRange; | 687 int _timeRange; |
688 List<int> _buckets; | 688 List<int> _buckets; |
689 int _currentBucket; | 689 int _currentBucket; |
690 int _currentBucketTime; | 690 int _currentBucketTime; |
691 num _bucketTimeRange; | 691 num _bucketTimeRange; |
692 int _sum; | 692 int _sum; |
693 } | 693 } |
OLD | NEW |