1 (function (globalObject) { 2 //============================================================================== 3 // PACKAGE MANAGEMENT 4 //============================================================================== 5 6 // JSDOC helpers 7 8 /** @namespace 9 @name net 10 @private */ 11 /** @namespace 12 @name net.user1 13 @private */ 14 /** @namespace 15 @name net.user1.events 16 @private */ 17 /** @namespace 18 @name net.user1.logger 19 @private */ 20 /** @namespace 21 @name net.user1.orbiter 22 */ 23 /** @namespace 24 @name net.user1.utils 25 */ 26 27 // create utils package 28 if (typeof globalObject.net == "undefined") { 29 globalObject.net = {}; 30 } 31 var net = globalObject.net; 32 net.user1 = net.user1 ? net.user1 : {}; 33 net.user1.utils = net.user1.utils ? net.user1.utils : {}; 34 35 // Convenience method to create packages 36 /** @function */ 37 net.user1.utils.createPackage = function (packageName) { 38 var parts = packageName.split("."); 39 var part = globalObject; 40 41 for (var i = 0; i < parts.length; i++) { 42 part = part[parts[i]] === undefined ? (part[parts[i]] = {}) : part[parts[i]]; 43 } 44 }; 45 //============================================================================== 46 // PACKAGE DECLARATIONS 47 //============================================================================== 48 net.user1.utils.createPackage("net.user1.logger"); 49 net.user1.utils.createPackage("net.user1.events"); 50 net.user1.utils.createPackage("net.user1.orbiter"); 51 net.user1.utils.createPackage("net.user1.orbiter.filters"); 52 net.user1.utils.createPackage("net.user1.orbiter.snapshot"); 53 net.user1.utils.createPackage("net.user1.orbiter.upc"); 54 net.user1.utils.createPackage("net.user1.utils"); 55 /** @function */ 56 net.user1.utils.extend = function (subclass, superclass) { 57 function superclassConstructor () {}; 58 superclassConstructor.prototype = superclass.prototype; 59 subclass.superclass = superclass.prototype; 60 subclass.prototype = new superclassConstructor(); 61 subclass.prototype.constructor = subclass; 62 }; 63 //============================================================================== 64 // ABSTRACT ERROR FUNCTION 65 //============================================================================== 66 67 // JSDOC helpers 68 69 /** @private */ 70 net.user1.utils.abstractError = function () { 71 throw new Error("Could not invoke abstract method. This method must be implemented by a subclass."); 72 }; 73 //============================================================================== 74 // CONNECTION REFUSAL REASON CONSTANTS 75 //============================================================================== 76 /** @class */ 77 net.user1.orbiter.ConnectionRefusalReason = new Object(); 78 /** @constant */ 79 net.user1.orbiter.ConnectionRefusalReason.BANNED = "BANNED"; 80 //============================================================================== 81 // CLASS DECLARATION 82 //============================================================================== 83 /** @class */ 84 net.user1.orbiter.ConnectionRefusal = function (reason, 85 description) { 86 /** 87 * @field 88 */ 89 this.bannedAt = NaN; 90 /** 91 * @field 92 */ 93 this.banDuration = NaN; 94 /** 95 * @field 96 */ 97 this.banReason = null; 98 /** 99 * @field 100 */ 101 this.reason = reason; 102 /** 103 * @field 104 */ 105 this.description = description; 106 107 var banDetails; 108 switch (reason) { 109 case net.user1.orbiter.ConnectionRefusalReason.BANNED: 110 banDetails = description.split(net.user1.orbiter.Tokens.RS); 111 this.bannedAt = parseFloat(banDetails[0]); 112 this.banDuration = parseFloat(banDetails[1]); 113 this.banReason = banDetails[2]; 114 break; 115 } 116 } 117 //============================================================================== 118 // CLASS DECLARATION 119 //============================================================================== 120 /** @class */ 121 net.user1.orbiter.VersionNumber = function (major, minor, revision, build) { 122 this.major = major; 123 this.minor = minor; 124 this.revision = revision; 125 this.build = build == undefined ? -1 : build; 126 }; 127 128 //============================================================================== 129 // INSTANCE METHODS 130 //============================================================================== 131 net.user1.orbiter.VersionNumber.prototype.fromVersionString = function (value) { 132 var upcVersionParts = value.split("."); 133 this.major = upcVersionParts[0]; 134 this.minor = upcVersionParts[1]; 135 this.revision = upcVersionParts[2]; 136 this.build = upcVersionParts.length == 4 ? upcVersionParts[4] : -1; 137 } 138 139 net.user1.orbiter.VersionNumber.prototype.toStringVerbose = function () { 140 var versionString = this.major + "." + this.minor + "." + this.revision 141 + ((this.build == -1) ? "" : " (Build " + this.build + ")"); 142 return versionString; 143 } 144 145 net.user1.orbiter.VersionNumber.prototype.toString = function () { 146 var versionString = this.major + "." + this.minor + "." + this.revision 147 + ((this.build == -1) ? "" : "." + this.build); 148 return versionString; 149 } 150 //============================================================================== 151 // PRODUCT CONSTANTS 152 //============================================================================== 153 /** @class 154 @private */ 155 net.user1.orbiter.Product = new Object(); 156 157 /** @private */ 158 net.user1.orbiter.Product.clientType = "Orbiter"; 159 net.user1.orbiter.Product.clientVersion = new net.user1.orbiter.VersionNumber(2,1,2,12); 160 net.user1.orbiter.Product.upcVersion = new net.user1.orbiter.VersionNumber(1,10,3); 161 //============================================================================== 162 // A COLLECTION OF OBJECT UTILITIES 163 //============================================================================== 164 /** @class */ 165 net.user1.utils.ObjectUtil = new Object(); 166 167 net.user1.utils.ObjectUtil.combine = function () { 168 var source = arguments.length == 1 ? arguments[0] : arguments; 169 var master = new Object(); 170 171 var object; 172 for (var i = 0; i < source.length; i++) { 173 object = source[i]; 174 for (var key in object) { 175 if (object.hasOwnProperty(key)) { 176 master[key] = object[key]; 177 } 178 } 179 } 180 return master; 181 }; 182 183 net.user1.utils.ObjectUtil.length = function (object) { 184 var len = 0; 185 for (var p in object) { 186 len++; 187 } 188 return len; 189 }; 190 191 //============================================================================== 192 // A COLLECTION OF ARRAY UTILITIES 193 //============================================================================== 194 /** @class */ 195 net.user1.utils.ArrayUtil = new Object(); 196 197 net.user1.utils.ArrayUtil.indexOf = function (arr, obj) { 198 if (arr.indexOf ) { 199 return arr.indexOf(obj); 200 } 201 202 for (var i = arr.length; --i >= 0; ) { 203 if (arr[i] === obj) { 204 return i; 205 } 206 } 207 208 return -1; 209 }; 210 211 net.user1.utils.ArrayUtil.remove = function (array, item) { 212 var itemIndex; 213 214 if (item == null) { 215 return false; 216 } else { 217 itemIndex = net.user1.utils.ArrayUtil.indexOf(array, item); 218 if (itemIndex == -1) { 219 return false; 220 } else { 221 array.splice(itemIndex, 1); 222 return true; 223 } 224 } 225 }; 226 227 net.user1.utils.ArrayUtil.isArray = function (value) { 228 return Object.prototype.toString.call(value) === '[object Array]'; 229 }; 230 //============================================================================== 231 // CLASS DECLARATION 232 //============================================================================== 233 /** @class A minimal in-memory storage map to mirror LocalData's persistent map. */ 234 net.user1.utils.MemoryStore = function () { 235 this.clear(); 236 }; 237 238 net.user1.utils.MemoryStore.prototype.write = function (record, field, value) { 239 if (typeof this.data[record] === "undefined") { 240 this.data[record] = new Object(); 241 } 242 this.data[record][field] = value 243 }; 244 245 net.user1.utils.MemoryStore.prototype.read = function (record, field) { 246 if (typeof this.data[record] !== "undefined" 247 && typeof this.data[record][field] !== "undefined") { 248 return this.data[record][field]; 249 } else { 250 return null; 251 } 252 }; 253 254 net.user1.utils.MemoryStore.prototype.remove = function (record, field) { 255 if (typeof this.data[record] !== "undefined") { 256 delete this.data[record][field]; 257 } 258 }; 259 260 net.user1.utils.MemoryStore.prototype.clear = function () { 261 this.data = new Object(); 262 }; 263 //============================================================================== 264 // CLASS DECLARATION 265 //============================================================================== 266 /** @class 267 * A minimal version of the browser localStorage object, 268 * for use in environments without native localStorage support. 269 * Provides in-memory storage only, with no persistence. 270 */ 271 net.user1.utils.LocalStorage = function () { 272 this.data = new net.user1.utils.MemoryStore(); 273 }; 274 275 net.user1.utils.LocalStorage.prototype.setItem = function (key, value) { 276 this.data.write("localStorage", key, value); 277 }; 278 279 net.user1.utils.LocalStorage.prototype.getItem = function (key) { 280 return this.data.read("localStorage", key); 281 }; 282 283 net.user1.utils.LocalStorage.prototype.removeItem = function (key) { 284 this.data.remove("localStorage", key); 285 }; 286 //============================================================================== 287 // CLASS DECLARATION 288 //============================================================================== 289 /** @class*/ 290 net.user1.utils.LocalData = new Object(); 291 292 if (typeof localStorage === "undefined") { 293 net.user1.utils.LocalData.data = new net.user1.utils.LocalStorage(); 294 } else { 295 net.user1.utils.LocalData.data = localStorage; 296 } 297 298 net.user1.utils.LocalData.write = function (record, field, value) { 299 // localStorage can't store objects, so combine record and field for keys 300 net.user1.utils.LocalData.data.setItem(record+field, value); 301 }; 302 303 net.user1.utils.LocalData.read = function (record, field) { 304 var value = net.user1.utils.LocalData.data.getItem(record+field); 305 return value == null ? null : value; 306 }; 307 308 net.user1.utils.LocalData.remove = function (record, field) { 309 var value = net.user1.utils.LocalData.data.getItem(record+field); 310 if (value != null) { 311 this.data.removeItem(record+field); 312 } 313 }; 314 //============================================================================== 315 // MESSAGE CONSTANTS 316 //============================================================================== 317 /** @class */ 318 net.user1.orbiter.Messages = new Object(); 319 /** @constant */ 320 net.user1.orbiter.Messages.CLIENT_HEARTBEAT = "CLIENT_HEARTBEAT"; 321 //============================================================================== 322 // RECEIVE MESSAGE BROADCAST TYPE CONSTANTS 323 //============================================================================== 324 /** @class 325 @private */ 326 net.user1.orbiter.ReceiveMessageBroadcastType = new Object(); 327 net.user1.orbiter.ReceiveMessageBroadcastType.TO_SERVER = "0"; 328 net.user1.orbiter.ReceiveMessageBroadcastType.TO_ROOMS = "1"; 329 net.user1.orbiter.ReceiveMessageBroadcastType.TO_CLIENTS = "2"; 330 //============================================================================== 331 // ROOM ID PARSING UTILITIES 332 //============================================================================== 333 /** @class */ 334 net.user1.orbiter.RoomIDParser = new Object(); 335 336 net.user1.orbiter.RoomIDParser.getSimpleRoomID = function (fullRoomID) { 337 if (fullRoomID.indexOf(".") == -1) { 338 return fullRoomID; 339 } else { 340 return fullRoomID.slice(fullRoomID.lastIndexOf(".")+1); 341 } 342 }; 343 344 net.user1.orbiter.RoomIDParser.getQualifier = function (fullRoomID) { 345 if (fullRoomID.indexOf(".") == -1) { 346 return ""; 347 } else { 348 return fullRoomID.slice(0, fullRoomID.lastIndexOf(".")); 349 } 350 }; 351 352 net.user1.orbiter.RoomIDParser.splitID = function (fullRoomID) { 353 return [getQualifier(fullRoomID), getSimpleRoomID(fullRoomID)]; 354 }; 355 //============================================================================== 356 // CLASS DECLARATION 357 //============================================================================== 358 /** @class */ 359 net.user1.utils.UDictionary = function () { 360 }; 361 //============================================================================== 362 // TOKEN CONSTANTS 363 //============================================================================== 364 /** @class 365 @private */ 366 net.user1.orbiter.Tokens = new Object(); 367 368 /** @private */ 369 net.user1.orbiter.Tokens.RS = "|"; 370 /** @private */ 371 net.user1.orbiter.Tokens.WILDCARD = "*"; 372 /** @private */ 373 net.user1.orbiter.Tokens.GLOBAL_ATTR = ""; 374 /** @private */ 375 net.user1.orbiter.Tokens.CUSTOM_CLASS_ATTR = "_CLASS"; 376 /** @private */ 377 net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR = "_MAX_CLIENTS"; 378 /** @private */ 379 net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR = "_DIE_ON_EMPTY"; 380 /** @private */ 381 net.user1.orbiter.Tokens.PASSWORD_ATTR = "_PASSWORD"; 382 /** @private */ 383 net.user1.orbiter.Tokens.ROLES_ATTR = "_ROLES"; 384 //============================================================================== 385 // CLASS DECLARATION 386 //============================================================================== 387 /** @class */ 388 net.user1.orbiter.System = function (window) { 389 this.window = window; 390 this.clientType = net.user1.orbiter.Product.clientType; 391 this.clientVersion = net.user1.orbiter.Product.clientVersion; 392 this.upcVersion = net.user1.orbiter.Product.upcVersion; 393 } 394 395 //============================================================================== 396 // INSTANCE METHODS 397 //============================================================================== 398 net.user1.orbiter.System.prototype.getClientType = function () { 399 return this.clientType; 400 } 401 402 /** @returns net.user1.orbiter.VersionNumber */ 403 net.user1.orbiter.System.prototype.getClientVersion = function () { 404 return this.clientVersion; 405 } 406 407 /** @returns net.user1.orbiter.VersionNumber */ 408 net.user1.orbiter.System.prototype.getUPCVersion = function () { 409 return this.upcVersion; 410 } 411 412 /** @returns Boolean */ 413 net.user1.orbiter.System.prototype.isJavaScriptCompatible = function () { 414 // Assume non-browser environments can do cross-origin XMLHttpRequests 415 if (this.window == null && typeof XMLHttpRequest != "undefined") { 416 return true; 417 } 418 419 if (this.window != null) { 420 // Standards-based browsers that support cross-origin requests 421 if (typeof XMLHttpRequest != "undefined" 422 && typeof new XMLHttpRequest().withCredentials != "undefined") { 423 return true; 424 } 425 426 // Versions of IE that support proprietary cross-origin requests 427 if (typeof XDomainRequest != "undefined" 428 && this.window.location.protocol != "file:") { 429 return true; 430 } 431 432 // Browsers that can communicate between windows 433 if (this.window.postMessage != null) { 434 return true; 435 } 436 } 437 438 // This environment has no way to connect to Union Server 439 return false; 440 } 441 442 /** 443 * <p> 444 * Returns true if the host environment supports direct cross-origin HTTP 445 * requests using CORS (see: <a href="http://www.w3.org/TR/cors/">http://www.w3.org/TR/cors/</a>). 446 * When hasHTTPDirectConnection() returns true, then Orbiter can safely use 447 * the HTTPDirectConnection class to communicate with Union Server over HTTP. When 448 * hasHTTPDirectConnection() returns false, Orbiter cannot use 449 * HTTPDirectConnection, and must instead use the HTTPIFrameConnection class to 450 * communicate with Union Server over HTTP. 451 * </p> 452 * 453 * <p> 454 * Note that Orbiter applications that use Orbiter's connect() or setServer() 455 * methods to connect to Union Server do not need to perform a capabilities check 456 * via hasHTTPDirectConnection(). The connect() and setServer() methods check 457 * the host environment's capabilities automatically, and choose the appropriate 458 * connection type for the environment. The hasHTTPDirectConnection() method is 459 * required in one situation only: when the application explicitly wishes to 460 * communicate over HTTP without trying a WebSocket connection first. 461 * </p> 462 * 463 * @returns Boolean 464 * 465 * @see net.user1.orbiter.HTTPDirectConnection 466 * @see net.user1.orbiter.HTTPIFrameConnection 467 * @see net.user1.orbiter.Orbiter#connect 468 * @see net.user1.orbiter.Orbiter#setServer 469 **/ 470 net.user1.orbiter.System.prototype.hasHTTPDirectConnection = function() { 471 // -If XHR has a "withCredentials" flag then CORS is supported. 472 // -In IE, if XDomainRequest is available, and the file wasn't loaded 473 // locally, then CORS is supported 474 // -In non-browser environments, assume cross-origin XMLHttpRequests are allowed 475 if ((typeof XMLHttpRequest != "undefined" && typeof new XMLHttpRequest().withCredentials != "undefined") 476 || (typeof XDomainRequest != "undefined" && this.window != null && this.window.location.protocol != "file:") 477 || (this.window == null && typeof XMLHttpRequest != "undefined")) { 478 return true; 479 } else { 480 return false; 481 } 482 } 483 484 /** 485 * <p> 486 * Returns true if the host environment supports WebSocket connections. 487 * When hasWebSocket() returns true, then Orbiter can safely use 488 * the WebSocketConnection class to communicate with Union Server over a 489 * persistent TCP/IP socket. When hasWebSocket() returns false, Orbiter cannot use 490 * WebSocketConnection, and must instead use HTTP communications (via either the 491 * HTTPDirectConnection class or the HTTPIFrameConnection class). 492 * </p> 493 * 494 * <p> 495 * Note that Orbiter applications that use Orbiter's connect() or setServer() 496 * methods to connect to Union Server do not need to perform a capabilities check 497 * via hasWebSocket(). The connect() and setServer() methods check 498 * the host environment's capabilities automatically, and choose the appropriate 499 * connection type for the environment. The hasWebSocket() method is 500 * required in one situation only: when the application explicitly wishes to 501 * determine whether WebSocket is supported for the purpose of application flow 502 * or user feedback. 503 * </p> 504 * 505 * @returns Boolean 506 * 507 * @see net.user1.orbiter.WebSocketConnection 508 * @see net.user1.orbiter.Orbiter#connect 509 **/ 510 net.user1.orbiter.System.prototype.hasWebSocket = function() { 511 return (typeof WebSocket !== "undefined" || typeof MozWebSocket !== "undefined"); 512 } 513 514 net.user1.orbiter.System.prototype.toString = function () { 515 return "[object System]"; 516 } 517 //============================================================================== 518 // A COLLECTION OF NUMERIC FORMATTING FUNCTIONS 519 //============================================================================== 520 /** @class */ 521 net.user1.utils.NumericFormatter = new Object(); 522 523 net.user1.utils.NumericFormatter.dateToLocalHrMinSec = function (date) { 524 var timeString = net.user1.utils.NumericFormatter.addLeadingZero(date.getHours()) + ":" 525 + net.user1.utils.NumericFormatter.addLeadingZero(date.getMinutes()) + ":" 526 + net.user1.utils.NumericFormatter.addLeadingZero(date.getSeconds()); 527 return timeString; 528 } 529 530 net.user1.utils.NumericFormatter.dateToLocalHrMinSecMs = function (date) { 531 return net.user1.utils.NumericFormatter.dateToLocalHrMinSec(date) + "." + net.user1.utils.NumericFormatter.addTrailingZeros(date.getMilliseconds()); 532 } 533 534 net.user1.utils.NumericFormatter.addLeadingZero = function (n) { 535 return ((n>9)?"":"0")+n; 536 } 537 538 net.user1.utils.NumericFormatter.addTrailingZeros = function (n) { 539 var ns = n.toString(); 540 541 if (ns.length == 1) { 542 return ns + "00"; 543 } else if (ns.length == 2) { 544 return ns + "0"; 545 } else { 546 return ns; 547 } 548 } 549 550 net.user1.utils.NumericFormatter.msToElapsedDayHrMinSec = function (ms) { 551 var sec = Math.floor(ms/1000); 552 553 var min = Math.floor(sec/60); 554 sec = sec % 60; 555 var timeString = net.user1.utils.NumericFormatter.addLeadingZero(sec); 556 557 var hr = Math.floor(min/60); 558 min = min % 60; 559 timeString = net.user1.utils.NumericFormatter.addLeadingZero(min) + ":" + timeString; 560 561 var day = Math.floor(hr/24); 562 hr = hr % 24; 563 timeString = net.user1.utils.NumericFormatter.addLeadingZero(hr) + ":" + timeString; 564 565 if (day > 0) { 566 timeString = day + "d " + timeString; 567 } 568 569 return timeString; 570 }; 571 //============================================================================== 572 // CLASS DECLARATION 573 //============================================================================== 574 /** @class */ 575 net.user1.events.EventListener = function (listener, 576 thisArg, 577 priority) { 578 this.listener = listener; 579 this.thisArg = thisArg; 580 this.priority = priority; 581 }; 582 583 //============================================================================== 584 // INSTANCE METHODS 585 //============================================================================== 586 net.user1.events.EventListener.prototype.getListenerFunction = function () { 587 return this.listener; 588 }; 589 590 net.user1.events.EventListener.prototype.getThisArg = function () { 591 return this.thisArg; 592 }; 593 594 net.user1.events.EventListener.prototype.getPriority = function () { 595 return this.priority; 596 }; 597 598 net.user1.events.EventListener.prototype.toString = function () { 599 return "[object EventListener]"; 600 }; 601 //============================================================================== 602 // CLASS DECLARATION 603 //============================================================================== 604 /** @class */ 605 net.user1.events.EventDispatcher = function (target) { 606 this.listeners = new Object(); 607 608 if (typeof target !== "undefined") { 609 this.target = target; 610 } else { 611 this.target = this; 612 } 613 }; 614 615 //============================================================================== 616 // INSTANCE METHODS 617 //============================================================================== 618 /** 619 * Registers a function or method to be invoked when the specified event type 620 * occurs. 621 * 622 * @param type The string name of the event (for example, "READY") 623 * @param listener A reference to the function or method to invoke. 624 * @param thisArg A reference to the object on which the listener will be invoked 625 * (i.e., the value of "this" within the listener's function body). 626 * @param priority An integer indicating the listener's priority. Listeners with 627 * higher priority are invoked before listeners with lower priority. 628 * Listeners with equal priority are invoked in the order they were 629 * added. Listener priority defaults to 0. 630 * @return {Boolean} true if the listener was added; false if the listener was 631 * already registered for the event. 632 * 633 * @example 634 * <pre> 635 * // Invoke readyListener() on 'this' when READY occurs: 636 * orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, readyListener, this); 637 * </pre> 638 */ 639 net.user1.events.EventDispatcher.prototype.addEventListener = function (type, 640 listener, 641 thisArg, 642 priority) { 643 if (typeof this.listeners[type] === "undefined") { 644 this.listeners[type] = new Array(); 645 } 646 var listenerArray = this.listeners[type]; 647 648 if (this.hasListener(type, listener, thisArg)) { 649 return false; 650 } 651 priority = priority || 0; 652 653 var newListener = new net.user1.events.EventListener(listener, 654 thisArg, 655 priority); 656 var added = false; 657 var thisListener; 658 for (var i = listenerArray.length; --i >= 0;) { 659 thisListener = listenerArray[i]; 660 if (priority <= thisListener.getPriority()) { 661 listenerArray.splice(i+1, 0, newListener); 662 added = true; 663 break; 664 } 665 } 666 if (!added) { 667 listenerArray.unshift(newListener); 668 } 669 return true; 670 }; 671 672 net.user1.events.EventDispatcher.prototype.removeEventListener = function (type, 673 listener, 674 thisArg) { 675 var listenerArray = this.listeners[type]; 676 if (typeof listenerArray === "undefined") { 677 return false; 678 } 679 680 var foundListener = false; 681 for (var i = 0; i < listenerArray.length; i++) { 682 if (listenerArray[i].getListenerFunction() === listener 683 && listenerArray[i].getThisArg() === thisArg) { 684 foundListener = true; 685 listenerArray.splice(i, 1); 686 break; 687 } 688 } 689 690 if (listenerArray.length == 0) { 691 delete this.listeners[type]; 692 } 693 694 return foundListener; 695 }; 696 697 net.user1.events.EventDispatcher.prototype.hasListener = function (type, 698 listener, 699 thisArg) { 700 var listenerArray = this.listeners[type]; 701 if (typeof listenerArray === "undefined") { 702 return false; 703 } 704 705 for (var i = 0; i < listenerArray.length; i++) { 706 if (listenerArray[i].getListenerFunction() === listener 707 && listenerArray[i].getThisArg() === thisArg) { 708 return true; 709 } 710 } 711 return false; 712 }; 713 714 net.user1.events.EventDispatcher.prototype.getListeners = function (type) { 715 return this.listeners[type]; 716 }; 717 718 net.user1.events.EventDispatcher.prototype.dispatchEvent = function (event) { 719 var listenerArray = this.listeners[event.type]; 720 if (typeof listenerArray === "undefined") { 721 return; 722 } 723 if (typeof event.type === "undefined") { 724 throw new Error("Event dispatch failed. No event name specified by " + event); 725 } 726 event.target = this.target; 727 var numListeners = listenerArray.length; 728 for (var i = 0; i < numListeners; i++) { 729 listenerArray[i].getListenerFunction().apply(listenerArray[i].getThisArg(), [event]); 730 } 731 }; 732 733 //============================================================================== 734 // TOSTRING 735 //============================================================================== 736 737 net.user1.events.EventDispatcher.prototype.toString = function () { 738 return "[object EventDispatcher]"; 739 }; 740 //============================================================================== 741 // CLASS DECLARATION 742 //============================================================================== 743 /** @class */ 744 net.user1.events.Event = function (type) { 745 if (type !== undefined) { 746 this.type = type; 747 } else { 748 throw new Error("Event creation failed. No type specified. Event: " + this); 749 } 750 this.target = null; 751 }; 752 753 net.user1.events.Event.prototype.toString = function () { 754 return "[object Event]"; 755 }; 756 //============================================================================== 757 // CLASS DECLARATION 758 //============================================================================== 759 /** @class 760 761 The ConsoleLogger class outputs Orbiter's log to the host environment's console, 762 if a console is available. 763 764 */ 765 net.user1.logger.ConsoleLogger = function (log) { 766 this.log = log; 767 this.log.addEventListener(net.user1.logger.LogEvent.UPDATE, this.updateListener, this); 768 // Print all messages already in the log 769 var history = this.log.getHistory(); 770 for (var i = 0; i < history.length; i++) { 771 this.out(history[i]); 772 } 773 }; 774 775 //============================================================================== 776 // INSTANCE METHODS 777 //============================================================================== 778 /** @private */ 779 net.user1.logger.ConsoleLogger.prototype.updateListener = function (e) { 780 var timeStamp = e.getTimeStamp(); 781 var level = e.getLevel(); 782 var bufferSpace = (level == net.user1.logger.Logger.INFO 783 || level == net.user1.logger.Logger.WARN) ? " " : ""; 784 785 this.out(timeStamp + (timeStamp == "" ? "" : " ") 786 + e.getLevel() + ": " + bufferSpace + e.getMessage()); 787 }; 788 789 /** @private */ 790 net.user1.logger.ConsoleLogger.prototype.out = function (value) { 791 if (typeof console === "undefined" || typeof console.log === "undefined") { 792 return; 793 } 794 console.log(value); 795 }; 796 797 /** @private */ 798 net.user1.logger.ConsoleLogger.prototype.dispose = function () { 799 this.log.removeEventListener(net.user1.logger.LogEvent.UPDATE, this.updateListener, this); 800 this.log = log = null; 801 }; 802 //============================================================================== 803 // CLASS DECLARATION 804 //============================================================================== 805 /** @class 806 @extends net.user1.events.Event 807 */ 808 net.user1.logger.LogEvent = function (type, message, level, timeStamp) { 809 net.user1.events.Event.call(this, type); 810 811 this.message = message; 812 this.level = level; 813 this.timeStamp = timeStamp; 814 }; 815 816 //============================================================================== 817 // INHERITANCE 818 //============================================================================== 819 net.user1.utils.extend(net.user1.logger.LogEvent, net.user1.events.Event); 820 821 //============================================================================== 822 // STATIC VARIABLES 823 //============================================================================== 824 /** @constant */ 825 net.user1.logger.LogEvent.UPDATE = "UPDATE"; 826 /** @constant */ 827 net.user1.logger.LogEvent.LEVEL_CHANGE = "LEVEL_CHANGE"; 828 829 //============================================================================== 830 // INSTANCE METHODS 831 //============================================================================== 832 net.user1.logger.LogEvent.prototype.getMessage = function () { 833 return this.message; 834 }; 835 836 net.user1.logger.LogEvent.prototype.getLevel = function () { 837 return this.level; 838 }; 839 840 net.user1.logger.LogEvent.prototype.getTimeStamp = function () { 841 return this.timeStamp; 842 }; 843 844 net.user1.logger.LogEvent.prototype.toString = function () { 845 return "[object LogEvent]"; 846 }; 847 848 //============================================================================== 849 // CLASS DECLARATION 850 //============================================================================== 851 /** @class 852 853 The Logger class dispatches the following events: 854 855 <ul class="summary"> 856 <li class="fixedFont">{@link net.user1.logger.LogEvent.LEVEL_CHANGE}</li> 857 <li class="fixedFont">{@link net.user1.logger.LogEvent.UPDATE}</li> 858 </ul> 859 860 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 861 862 863 @extends net.user1.events.EventDispatcher 864 */ 865 net.user1.logger.Logger = function (historyLength) { 866 // Invoke superclass constructor 867 net.user1.events.EventDispatcher.call(this); 868 869 // Instance variables 870 this.suppressionTerms = new Array(); 871 this.timeStampEnabled = false; 872 this.logLevel = 0; 873 this.messages = new Array(); 874 this.historyLength = 0; 875 876 // Initialization 877 this.setHistoryLength(historyLength == null ? 100 : historyLength); 878 this.enableTimeStamp(); 879 this.setLevel(net.user1.logger.Logger.INFO); 880 }; 881 882 //============================================================================== 883 // INHERITANCE 884 //============================================================================== 885 net.user1.utils.extend(net.user1.logger.Logger, net.user1.events.EventDispatcher); 886 887 //============================================================================== 888 // STATIC VARIABLES 889 //============================================================================== 890 /** @constant */ 891 net.user1.logger.Logger.FATAL = "FATAL"; 892 /** @constant */ 893 net.user1.logger.Logger.ERROR = "ERROR"; 894 /** @constant */ 895 net.user1.logger.Logger.WARN = "WARN"; 896 /** @constant */ 897 net.user1.logger.Logger.INFO = "INFO"; 898 /** @constant */ 899 net.user1.logger.Logger.DEBUG = "DEBUG"; 900 net.user1.logger.Logger.logLevels = new Array(net.user1.logger.Logger.FATAL, 901 net.user1.logger.Logger.ERROR, 902 net.user1.logger.Logger.WARN, 903 net.user1.logger.Logger.INFO, 904 net.user1.logger.Logger.DEBUG); 905 906 //============================================================================== 907 // INSTANCE METHODS 908 //============================================================================== 909 net.user1.logger.Logger.prototype.setLevel = function (level) { 910 if (level !== undefined) { 911 for (var i = 0; i < net.user1.logger.Logger.logLevels.length; i++) { 912 if (net.user1.logger.Logger.logLevels[i].toLowerCase() == level.toLowerCase()) { 913 this.logLevel = i; 914 this.dispatchEvent(new net.user1.logger.LogEvent(net.user1.logger.LogEvent.LEVEL_CHANGE, null, level)); 915 return; 916 } 917 } 918 } 919 920 this.warn("Invalid log level specified: " + level); 921 }; 922 923 net.user1.logger.Logger.prototype.getLevel = function () { 924 return net.user1.logger.Logger.logLevels[this.logLevel]; 925 }; 926 927 net.user1.logger.Logger.prototype.fatal = function (msg) { 928 this.addEntry(0, net.user1.logger.Logger.FATAL, msg); 929 }; 930 931 net.user1.logger.Logger.prototype.error = function (msg) { 932 this.addEntry(1, net.user1.logger.Logger.ERROR, msg); 933 }; 934 935 net.user1.logger.Logger.prototype.warn = function (msg) { 936 this.addEntry(2, net.user1.logger.Logger.WARN, msg); 937 }; 938 939 net.user1.logger.Logger.prototype.info = function (msg) { 940 this.addEntry(3, net.user1.logger.Logger.INFO, msg); 941 }; 942 943 net.user1.logger.Logger.prototype.debug = function (msg) { 944 this.addEntry(4, net.user1.logger.Logger.DEBUG, msg); 945 }; 946 947 net.user1.logger.Logger.prototype.addSuppressionTerm = function (term) { 948 this.debug("Added suppression term. Log messages containing '" 949 + term + "' will now be ignored."); 950 this.suppressionTerms.push(term); 951 }; 952 953 net.user1.logger.Logger.prototype.removeSuppressionTerm = function (term) { 954 var termIndex = net.user1.utils.ArrayUtil.indexOf(this.suppressionTerms, term); 955 if (termIndex != -1) { 956 this.suppressionTerms.splice(termIndex, 1); 957 this.debug("Removed suppression term. Log messages containing '" 958 + term + "' will now be shown."); 959 return true; 960 } 961 return false; 962 }; 963 964 /** @private */ 965 net.user1.logger.Logger.prototype.addEntry = function (level, levelName, msg) { 966 var timeStamp = ""; 967 var time; 968 969 // Abort if the log's level is lower than the message's level. 970 if (this.logLevel < level) { 971 return; 972 } 973 974 // Don't log messages if they contain any of the suppression terms. 975 for (var i = this.suppressionTerms.length; --i >= 0;) { 976 if (msg.indexOf(this.suppressionTerms[i]) != -1) { 977 return; 978 } 979 } 980 981 if (this.timeStampEnabled) { 982 time = new Date(); 983 timeStamp = time.getMonth()+1 + "/" + String(time.getDate()) 984 + "/" + String(time.getFullYear()).substr(2) 985 + " " + net.user1.utils.NumericFormatter.dateToLocalHrMinSecMs(time) 986 + " UTC" + (time.getTimezoneOffset() >= 0 ? "-" : "+") 987 + Math.abs(time.getTimezoneOffset() / 60); 988 } 989 990 // Log the message. 991 this.addToHistory(levelName, msg, timeStamp); 992 993 var e = new net.user1.logger.LogEvent(net.user1.logger.LogEvent.UPDATE, 994 msg, levelName, timeStamp); 995 this.dispatchEvent(e); 996 }; 997 998 /** @private */ 999 net.user1.logger.Logger.prototype.setHistoryLength = function (newHistoryLength) { 1000 this.historyLength = newHistoryLength; 1001 1002 if (this.messages.length > this.historyLength) { 1003 this.messages.splice(this.historyLength); 1004 } 1005 }; 1006 1007 net.user1.logger.Logger.prototype.getHistoryLength = function () { 1008 return this.historyLength; 1009 }; 1010 1011 /** @private */ 1012 net.user1.logger.Logger.prototype.addToHistory = function (level, msg, timeStamp) { 1013 this.messages.push(timeStamp + (timeStamp == "" ? "" : " ") + level + ": " + msg); 1014 if (this.messages.length > this.historyLength) { 1015 this.messages.shift(); 1016 } 1017 }; 1018 1019 net.user1.logger.Logger.prototype.getHistory = function () { 1020 return this.messages.slice(0); 1021 }; 1022 1023 net.user1.logger.Logger.prototype.enableTimeStamp = function () { 1024 this.timeStampEnabled = true; 1025 }; 1026 1027 net.user1.logger.Logger.prototype.disableTimeStamp = function () { 1028 this.timeStampEnabled = false; 1029 }; 1030 1031 net.user1.logger.Logger.prototype.toString = function () { 1032 return "[object Logger]"; 1033 }; 1034 //============================================================================== 1035 // CLASS DECLARATION 1036 //============================================================================== 1037 /** @class 1038 @extends net.user1.events.Event 1039 */ 1040 net.user1.orbiter.ConnectionManagerEvent = function (type, connection, status) { 1041 net.user1.events.Event.call(this, type); 1042 1043 this.connection = connection 1044 this.status = status; 1045 }; 1046 1047 //============================================================================== 1048 // INHERITANCE 1049 //============================================================================== 1050 net.user1.utils.extend(net.user1.orbiter.ConnectionManagerEvent, net.user1.events.Event); 1051 1052 //============================================================================== 1053 // STATIC VARIABLES 1054 //============================================================================== 1055 1056 /** @constant */ 1057 net.user1.orbiter.ConnectionManagerEvent.BEGIN_CONNECT = "BEGIN_CONNECT"; 1058 /** @constant */ 1059 net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION = "SELECT_CONNECTION"; 1060 /** @constant */ 1061 net.user1.orbiter.ConnectionManagerEvent.READY = "READY"; 1062 /** @constant */ 1063 net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE = "CONNECT_FAILURE"; 1064 /** @constant */ 1065 net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT = "CLIENT_KILL_CONNECT"; 1066 /** @constant */ 1067 net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT = "SERVER_KILL_CONNECT"; 1068 /** @constant */ 1069 net.user1.orbiter.ConnectionManagerEvent.DISCONNECT = "DISCONNECT"; 1070 /** @constant */ 1071 net.user1.orbiter.ConnectionManagerEvent.CONNECTION_STATE_CHANGE = "CONNECTION_STATE_CHANGE"; 1072 1073 //============================================================================== 1074 // INSTANCE METHODS 1075 //============================================================================== 1076 1077 net.user1.orbiter.ConnectionManagerEvent.prototype.getConnection = function () { 1078 return this.connection; 1079 } 1080 1081 net.user1.orbiter.ConnectionManagerEvent.prototype.getStatus = function () { 1082 return this.status; 1083 } 1084 1085 net.user1.orbiter.ConnectionManagerEvent.prototype.toString = function () { 1086 return "[object ConnectionManagerEvent]"; 1087 } 1088 1089 //============================================================================== 1090 // CLASS DECLARATION 1091 //============================================================================== 1092 /** @class 1093 1094 The ConnectionManager class dispatches the following events: 1095 1096 <ul class="summary"> 1097 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.BEGIN_CONNECT}</li> 1098 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION}</li> 1099 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE}</li> 1100 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.DISCONNECT}</li> 1101 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT}</li> 1102 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT}</li> 1103 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.READY}</li> 1104 </ul> 1105 1106 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 1107 1108 @extends net.user1.events.EventDispatcher 1109 1110 * @see net.user1.orbiter.Orbiter#connect 1111 */ 1112 net.user1.orbiter.ConnectionManager = function (orbiter) { 1113 // Call superconstructor 1114 net.user1.events.EventDispatcher.call(this); 1115 1116 // Variables 1117 this.orbiter = orbiter; 1118 this.connectAttemptCount = 0; 1119 this.connectAbortCount = 0; 1120 this.readyCount = 0; 1121 this.connectFailedCount = 0; 1122 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1123 this.readyTimeout = 0; 1124 this.connections = new Array(); 1125 this.activeConnection = null; 1126 this.inProgressConnection = null; 1127 this.currentConnectionIndex = 0; 1128 this.attemptedConnections = null; 1129 this.setReadyTimeout(net.user1.orbiter.ConnectionManager.DEFAULT_READY_TIMEOUT); 1130 1131 // Initialization 1132 // Make all Orbiter instances in this VM share the same server affinity 1133 this.setGlobalAffinity(true); 1134 }; 1135 1136 //============================================================================== 1137 // INHERITANCE 1138 //============================================================================== 1139 net.user1.utils.extend(net.user1.orbiter.ConnectionManager, net.user1.events.EventDispatcher); 1140 1141 //============================================================================== 1142 // STATIC VARIABLES 1143 //============================================================================== 1144 net.user1.orbiter.ConnectionManager.DEFAULT_READY_TIMEOUT = 10000; 1145 1146 // ============================================================================= 1147 // CONNECT AND DISCONNECT 1148 // ============================================================================= 1149 net.user1.orbiter.ConnectionManager.prototype.connect = function () { 1150 if (this.connections.length == 0) { 1151 this.orbiter.getLog().error("[CONNECTION_MANAGER] No connections defined. Connection request ignored."); 1152 return; 1153 } 1154 1155 this.connectAttemptCount++; 1156 this.attemptedConnections = new Array(); 1157 1158 switch (this.connectionState) { 1159 case net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS: 1160 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection attempt already in " 1161 + "progress. Existing attempt must be aborted before" 1162 + " new connection attempt begins..."); 1163 this.disconnect(); 1164 break; 1165 1166 case net.user1.orbiter.ConnectionState.READY: 1167 this.orbiter.getLog().info("[CONNECTION_MANAGER] Existing connection to Union" 1168 + " must be disconnected before new connection" 1169 + " attempt begins."); 1170 this.disconnect(); 1171 break; 1172 } 1173 this.setConnectionState(net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS); 1174 1175 this.orbiter.getLog().debug("[CONNECTION_MANAGER] Searching for most recent valid connection."); 1176 var originalConnectionIndex = this.currentConnectionIndex; 1177 while (!this.getCurrentConnection().isValid()) { 1178 this.advance(); 1179 if (this.currentConnectionIndex == originalConnectionIndex) { 1180 // Couldn't find a valid connection, so start the connection with 1181 // the first connection in the connection list 1182 this.orbiter.getLog().debug("[CONNECTION_MANAGER] No valid connection found. Starting connection attempt with first connection."); 1183 this.currentConnectionIndex = 0; 1184 break; 1185 } 1186 } 1187 1188 this.dispatchBeginConnect(); 1189 this.connectCurrentConnection(); 1190 }; 1191 1192 net.user1.orbiter.ConnectionManager.prototype.disconnect = function () { 1193 if (this.connections.length == 0) { 1194 this.dispatchConnectFailure("No connections defined. Disconnection attempt failed."); 1195 return; 1196 } 1197 1198 switch (this.connectionState) { 1199 // Currently connected 1200 case net.user1.orbiter.ConnectionState.READY: 1201 this.orbiter.getLog().info("[CONNECTION_MANAGER] Closing existing connection: " 1202 + this.getActiveConnection().toString()); 1203 this.setConnectionState(net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS); 1204 this.disconnectConnection(this.getActiveConnection()); 1205 break; 1206 1207 // Currently attempting to connect 1208 case net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS: 1209 this.orbiter.getLog().info("[CONNECTION_MANAGER] Aborting existing connection attempt: " 1210 + this.getInProgressConnection().toString()); 1211 this.connectAbortCount++; 1212 this.setConnectionState(net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS); 1213 this.disconnectConnection(this.getInProgressConnection()); 1214 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection abort complete."); 1215 break; 1216 1217 // Currently attempting to disconnect 1218 case net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS: 1219 this.orbiter.getLog().info("[CONNECTION_MANAGER] Disconnection request ignored." 1220 + " Already disconnecting."); 1221 break; 1222 } 1223 }; 1224 1225 /** @private */ 1226 net.user1.orbiter.ConnectionManager.prototype.disconnectConnection = function (connection) { 1227 connection.disconnect(); 1228 }; 1229 1230 /** @private */ 1231 net.user1.orbiter.ConnectionManager.prototype.connectCurrentConnection = function () { 1232 // If there are no Connections defined, fail immediately 1233 if (this.connections.length == 0) { 1234 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1235 this.connectFailedCount++; 1236 this.dispatchConnectFailure("No connections defined. Connection attempt failed."); 1237 return; 1238 } 1239 1240 this.inProgressConnection = this.getCurrentConnection(); 1241 1242 // If the requested connection has already been attempted this round, 1243 // ignore it. 1244 if (net.user1.utils.ArrayUtil.indexOf(this.attemptedConnections, this.inProgressConnection) != -1) { 1245 this.advanceAndConnect(); 1246 return; 1247 } 1248 1249 this.dispatchSelectConnection(this.inProgressConnection); 1250 this.orbiter.getLog().info("[CONNECTION_MANAGER] Attempting connection via " 1251 + this.inProgressConnection.toString() + ". (Connection " 1252 + (this.attemptedConnections.length+1) + " of " 1253 + this.connections.length + ". Attempt " + this.connectAttemptCount +" since last successful connection)."); 1254 this.addConnectionListeners(this.inProgressConnection); 1255 this.inProgressConnection.connect(); 1256 }; 1257 1258 /** @private */ 1259 net.user1.orbiter.ConnectionManager.prototype.advanceAndConnect = function () { 1260 if (!this.connectAttemptComplete()) { 1261 this.advance(); 1262 this.connectCurrentConnection(); 1263 } else { 1264 // Tried all connections, so give up and dispatch CONNECT_FAILURE 1265 this.connectFailedCount++; 1266 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1267 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection failed for all specified hosts and ports."); 1268 this.dispatchConnectFailure("Connection failed for all specified hosts and ports."); 1269 } 1270 }; 1271 1272 /** @private */ 1273 net.user1.orbiter.ConnectionManager.prototype.connectAttemptComplete = function () { 1274 return this.attemptedConnections.length == this.connections.length; 1275 }; 1276 1277 /** @private */ 1278 net.user1.orbiter.ConnectionManager.prototype.advance = function () { 1279 this.currentConnectionIndex++; 1280 if (this.currentConnectionIndex == this.connections.length) { 1281 this.currentConnectionIndex = 0; 1282 } 1283 }; 1284 1285 // ============================================================================= 1286 // CONNECTION OBJECT MANAGEMENT 1287 // ============================================================================= 1288 net.user1.orbiter.ConnectionManager.prototype.addConnection = function (connection) { 1289 if (connection != null) { 1290 this.orbiter.getLog().info("[CONNECTION_MANAGER] New connection added. " 1291 + connection.toString() + "."); 1292 connection.setOrbiter(this.orbiter); 1293 this.connections.push(connection); 1294 } 1295 }; 1296 1297 net.user1.orbiter.ConnectionManager.prototype.removeConnection = function (connection) { 1298 if (connection != null) { 1299 connection.disconnect(); 1300 this.removeConnectionListeners(connection); 1301 return net.user1.utils.ArrayUtil.remove(this.connections, connection); 1302 } else { 1303 return false; 1304 } 1305 }; 1306 1307 net.user1.orbiter.ConnectionManager.prototype.removeAllConnections = function () { 1308 if (this.connections.length == 0) { 1309 this.orbiter.getLog().info("[CONNECTION_MANAGER] removeAllConnections() ignored. " + 1310 " No connections to remove."); 1311 return; 1312 } 1313 1314 this.orbiter.getLog().info("[CONNECTION_MANAGER] Removing all connections..."); 1315 this.disconnect(); 1316 while (this.connections.length > 0) { 1317 this.removeConnection(this.connections[0]); 1318 } 1319 this.currentConnectionIndex = 0; 1320 this.orbiter.getLog().info("[CONNECTION_MANAGER] All connections removed."); 1321 }; 1322 1323 // ============================================================================= 1324 // CONNECTION ACCESS 1325 // ============================================================================= 1326 net.user1.orbiter.ConnectionManager.prototype.getActiveConnection = function () { 1327 return this.activeConnection; 1328 }; 1329 1330 net.user1.orbiter.ConnectionManager.prototype.getInProgressConnection = function () { 1331 return this.inProgressConnection; 1332 }; 1333 1334 net.user1.orbiter.ConnectionManager.prototype.getConnections = function () { 1335 return this.connections.slice(); 1336 }; 1337 1338 /** @private */ 1339 net.user1.orbiter.ConnectionManager.prototype.getCurrentConnection = function () { 1340 return this.connections[this.currentConnectionIndex]; 1341 }; 1342 1343 // ============================================================================= 1344 // CONNECTION LISTENER REGISTRATION 1345 // ============================================================================= 1346 /** @private */ 1347 net.user1.orbiter.ConnectionManager.prototype.addConnectionListeners = function(connection) { 1348 if (connection != null) { 1349 connection.addEventListener(net.user1.orbiter.ConnectionEvent.READY, this.readyListener, this); 1350 connection.addEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, this.connectFailureListener, this); 1351 connection.addEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, this.disconnectListener, this); 1352 connection.addEventListener(net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT, this.clientKillConnectListener, this); 1353 connection.addEventListener(net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT, this.serverKillConnectListener, this); 1354 } 1355 }; 1356 1357 /** @private */ 1358 net.user1.orbiter.ConnectionManager.prototype.removeConnectionListeners = function (connection) { 1359 if (connection != null) { 1360 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.READY, this.readyListener, this); 1361 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, this.connectFailureListener, this); 1362 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, this.disconnectListener, this); 1363 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT, this.clientKillConnectListener, this); 1364 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT, this.serverKillConnectListener, this); 1365 } 1366 }; 1367 1368 // ============================================================================= 1369 // CONNECTION STATE ACCESS 1370 // ============================================================================= 1371 net.user1.orbiter.ConnectionManager.prototype.isReady = function () { 1372 return this.connectionState == net.user1.orbiter.ConnectionState.READY; 1373 } 1374 1375 net.user1.orbiter.ConnectionManager.prototype.setConnectionState = function (state) { 1376 var changed = false; 1377 if (state != this.connectionState) { 1378 changed = true; 1379 } 1380 this.connectionState = state; 1381 if (changed) { 1382 this.dispatchConnectionStateChange(); 1383 } 1384 }; 1385 1386 net.user1.orbiter.ConnectionManager.prototype.getConnectionState = function () { 1387 return this.connectionState; 1388 }; 1389 1390 // ============================================================================= 1391 // CONNECTION COUNT MANAGEMENT 1392 // ============================================================================= 1393 net.user1.orbiter.ConnectionManager.prototype.getReadyCount = function () { 1394 return this.readyCount; 1395 }; 1396 1397 net.user1.orbiter.ConnectionManager.prototype.getConnectFailedCount = function () { 1398 return this.connectFailedCount; 1399 }; 1400 1401 net.user1.orbiter.ConnectionManager.prototype.getConnectAttemptCount = function () { 1402 return this.connectAttemptCount; 1403 }; 1404 1405 net.user1.orbiter.ConnectionManager.prototype.getConnectAbortCount = function () { 1406 return this.connectAbortCount; 1407 }; 1408 1409 // ============================================================================= 1410 // CURRENT CONNECTION LISTENERS 1411 // ============================================================================= 1412 /** @private */ 1413 net.user1.orbiter.ConnectionManager.prototype.readyListener = function (e) { 1414 this.setConnectionState(net.user1.orbiter.ConnectionState.READY); 1415 this.inProgressConnection = null; 1416 this.activeConnection = e.target; 1417 this.readyCount++; 1418 this.connectFailedCount = 0; 1419 this.connectAttemptCount = 0; 1420 this.connectAbortCount = 0; 1421 this.dispatchReady(); 1422 }; 1423 1424 /** @private */ 1425 net.user1.orbiter.ConnectionManager.prototype.connectFailureListener = function (e) { 1426 var failedConnection = e.target; 1427 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Connection failed for " 1428 + failedConnection.toString() 1429 + ". Status: [" + e.getStatus() + "]"); 1430 1431 this.removeConnectionListeners(failedConnection); 1432 this.inProgressConnection = null; 1433 1434 if (this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 1435 this.dispatchConnectFailure("Connection closed by client."); 1436 } else { 1437 if (failedConnection.getHost() != failedConnection.getRequestedHost()) { 1438 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection failed for affinity address [" + failedConnection.getHost() + "]. Removing affinity."); 1439 this.clearAffinity(failedConnection.getRequestedHost()); 1440 } 1441 1442 this.attemptedConnections.push(failedConnection); 1443 this.advanceAndConnect(); 1444 } 1445 }; 1446 1447 /** @private */ 1448 net.user1.orbiter.ConnectionManager.prototype.disconnectListener = function (e) { 1449 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1450 this.removeConnectionListeners(e.target); 1451 this.activeConnection = null; 1452 this.dispatchDisconnect(e.target); 1453 }; 1454 1455 /** @private */ 1456 net.user1.orbiter.ConnectionManager.prototype.clientKillConnectListener = function (e) { 1457 this.dispatchClientKillConnect(e.target); 1458 // This event is always followed by a DISCONNECT event 1459 }; 1460 1461 /** @private */ 1462 net.user1.orbiter.ConnectionManager.prototype.serverKillConnectListener = function (e) { 1463 this.dispatchServerKillConnect(e.target); 1464 // This event is always followed by a DISCONNECT event 1465 }; 1466 1467 // ============================================================================= 1468 // READY TIMEOUT MANAGEMENT 1469 // ============================================================================= 1470 1471 net.user1.orbiter.ConnectionManager.prototype.setReadyTimeout = function (milliseconds) { 1472 if (milliseconds > 0) { 1473 this.readyTimeout = milliseconds; 1474 this.orbiter.getLog().info("[CONNECTION_MANAGER] Ready timeout set to " + milliseconds + " ms."); 1475 if (milliseconds < 3000) { 1476 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Current ready timeout (" 1477 + milliseconds + ") may not allow sufficient time" 1478 + " to connect to Union Server over a typical" 1479 + " internet connection."); 1480 } 1481 } else { 1482 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Invalid ready timeout specified: " 1483 + milliseconds + ". Duration must be greater than zero."); 1484 } 1485 }; 1486 1487 net.user1.orbiter.ConnectionManager.prototype.getReadyTimeout = function () { 1488 return this.readyTimeout; 1489 }; 1490 1491 // ============================================================================= 1492 // SERVER AFFINITY 1493 // ============================================================================= 1494 net.user1.orbiter.ConnectionManager.prototype.getAffinity = function (host) { 1495 var address = this.affinityData.read("affinity", host+"address"); 1496 var until = parseFloat(this.affinityData.read("affinity", host+"until")); 1497 1498 if (address != null) { 1499 var now = new Date().getTime(); 1500 if (now >= until) { 1501 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Affinity duration expired for address [" 1502 + address + "], host [" + host + "]. Removing affinity."); 1503 this.clearAffinity(host); 1504 } else { 1505 return address; 1506 } 1507 } 1508 1509 return host; 1510 }; 1511 1512 /** 1513 * @private 1514 */ 1515 net.user1.orbiter.ConnectionManager.prototype.setAffinity = function (host, address, duration) { 1516 var until = new Date().getTime() + (duration*60*1000); 1517 // Don't use JSON stringify for affinity values because not all JavaScript 1518 // environments support JSON natively (e.g., non-browser VMs) 1519 this.affinityData.write("affinity", host+"address", address); 1520 this.affinityData.write("affinity", host+"until", until); 1521 1522 this.orbiter.getLog().info("[CONNECTION_MANAGER] Assigning affinity address [" 1523 + address + "] for supplied host [" +host + "]. Duration (minutes): " 1524 + duration); 1525 }; 1526 1527 /** 1528 * @private 1529 */ 1530 net.user1.orbiter.ConnectionManager.prototype.clearAffinity = function (host) { 1531 this.affinityData.remove("affinity", host+"address"); 1532 this.affinityData.remove("affinity", host+"until"); 1533 }; 1534 1535 net.user1.orbiter.ConnectionManager.prototype.setGlobalAffinity = function (enabled) { 1536 if (enabled) { 1537 this.orbiter.getLog().info("[CONNECTION_MANAGER] Global server affinity selected." 1538 + " Using current environment's shared server affinity."); 1539 this.affinityData = net.user1.utils.LocalData; 1540 } else { 1541 this.orbiter.getLog().info("[CONNECTION_MANAGER] Local server affinity selected." 1542 + " The current client will maintain its own, individual server affinity."); 1543 this.affinityData = new net.user1.utils.MemoryStore(); 1544 } 1545 }; 1546 1547 // ============================================================================= 1548 // EVENT DISPATCHING 1549 // ============================================================================= 1550 1551 /** @private */ 1552 net.user1.orbiter.ConnectionManager.prototype.dispatchBeginConnect = function () { 1553 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.BEGIN_CONNECT)); 1554 }; 1555 1556 /** @private */ 1557 net.user1.orbiter.ConnectionManager.prototype.dispatchSelectConnection = function (connection) { 1558 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 1559 connection)); 1560 }; 1561 1562 /** @private */ 1563 net.user1.orbiter.ConnectionManager.prototype.dispatchConnectFailure = function (status) { 1564 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE, 1565 null, status)); 1566 }; 1567 1568 /** @private */ 1569 net.user1.orbiter.ConnectionManager.prototype.dispatchDisconnect = function (connection) { 1570 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.DISCONNECT, 1571 connection)); 1572 }; 1573 1574 /** @private */ 1575 net.user1.orbiter.ConnectionManager.prototype.dispatchServerKillConnect = function (connection) { 1576 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT, 1577 connection)); 1578 }; 1579 1580 /** @private */ 1581 net.user1.orbiter.ConnectionManager.prototype.dispatchClientKillConnect = function (connection) { 1582 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT, 1583 connection)); 1584 }; 1585 1586 /** @private */ 1587 net.user1.orbiter.ConnectionManager.prototype.dispatchReady = function () { 1588 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.READY)); 1589 }; 1590 1591 /** @private */ 1592 net.user1.orbiter.ConnectionManager.prototype.dispatchConnectionStateChange = function () { 1593 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.CONNECTION_STATE_CHANGE)); 1594 }; 1595 1596 // ============================================================================= 1597 // DISPOSAL 1598 // ============================================================================= 1599 net.user1.orbiter.ConnectionManager.prototype.dispose = function () { 1600 this.removeAllConnections(); 1601 this.attemptedConnections = null; 1602 this.activeConnection = null; 1603 this.inProgressConnection = null; 1604 this.connections = null; 1605 }; 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 //============================================================================== 1629 // CLASS DECLARATION 1630 //============================================================================== 1631 /** @class */ 1632 net.user1.orbiter.ConnectionMonitor = function (orbiter) { 1633 // Instance variables 1634 this.connectionTimeout = 0; 1635 this.heartbeatIntervalID = -1; 1636 this.heartbeatCounter = 0; 1637 this.heartbeatEnabled = true; 1638 this.heartbeats = new net.user1.utils.UDictionary(); 1639 1640 this.oldestHeartbeat = 0; 1641 this.heartBeatFrequency = -1; 1642 1643 this.sharedPing = false; 1644 1645 this.autoReconnectMinMS = 0; 1646 this.autoReconnectMaxMS = 0; 1647 this.autoReconnectFrequency = -1; 1648 this.autoReconnectDelayFirstAttempt = false; 1649 this.autoReconnectTimeoutID = -1; 1650 this.autoReconnectAttemptLimit = -1; 1651 1652 this.orbiter = orbiter; 1653 this.msgManager = orbiter.getMessageManager(); 1654 this.log = orbiter.getLog(); 1655 1656 this.disposed = false; 1657 1658 // Initialization 1659 this.orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, this.connectReadyListener, this); 1660 this.orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.CLOSE, this.connectCloseListener, this); 1661 this.disableHeartbeatLogging(); 1662 }; 1663 1664 //============================================================================== 1665 // STATIC VARIABLES 1666 //============================================================================== 1667 net.user1.orbiter.ConnectionMonitor.DEFAULT_HEARTBEAT_FREQUENCY = 10000; 1668 net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY = 20; 1669 net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_FREQUENCY = -1; 1670 net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_ATTEMPT_LIMIT = -1; 1671 net.user1.orbiter.ConnectionMonitor.DEFAULT_CONNECTION_TIMEOUT = 60000; 1672 1673 //============================================================================== 1674 // CONNECTION MONITORING 1675 //============================================================================== 1676 /** @private */ 1677 net.user1.orbiter.ConnectionMonitor.prototype.connectReadyListener = function (e) { 1678 this.msgManager.addMessageListener(net.user1.orbiter.Messages.CLIENT_HEARTBEAT, this.heartbeatMessageListener, this); 1679 this.startHeartbeat(); 1680 this.stopReconnect(); 1681 } 1682 1683 /** @private */ 1684 net.user1.orbiter.ConnectionMonitor.prototype.connectCloseListener = function (e) { 1685 this.stopHeartbeat(); 1686 1687 var numAttempts = this.orbiter.getConnectionManager().getConnectAttemptCount(); 1688 if (numAttempts == 0) { 1689 this.selectReconnectFrequency(); 1690 } 1691 1692 if (this.autoReconnectFrequency > -1) { 1693 if (this.autoReconnectTimeoutID != -1) { 1694 return; 1695 } else { 1696 // Defer reconnection until after all other listeners have processed the 1697 // CLOSE event 1698 var self = this; 1699 setTimeout(function () { 1700 // If another listener disposed of Orbiter, or disabled autoreconnect, quit 1701 if (!self.disposed && self.autoReconnectFrequency != -1) { 1702 self.log.warn("[CONNECTION_MONITOR] Disconnection detected."); 1703 if (self.autoReconnectDelayFirstAttempt 1704 && ( 1705 (numAttempts == 0) 1706 || 1707 (numAttempts == 1 && self.orbiter.getConnectionManager().getReadyCount() == 0) 1708 ) 1709 ) { 1710 self.log.info("[CONNECTION_MONITOR] Delaying reconnection attempt" 1711 + " by " + self.autoReconnectFrequency + " ms..."); 1712 self.scheduleReconnect(self.autoReconnectFrequency); 1713 } else { 1714 self.doReconnect(); 1715 } 1716 } 1717 }, 1); 1718 } 1719 } 1720 } 1721 1722 //============================================================================== 1723 // HEARTBEAT 1724 //============================================================================== 1725 1726 net.user1.orbiter.ConnectionMonitor.prototype.enableHeartbeat = function () { 1727 this.log.info("[CONNECTION_MONITOR] Heartbeat enabled."); 1728 this.heartbeatEnabled = true; 1729 this.startHeartbeat(); 1730 } 1731 1732 net.user1.orbiter.ConnectionMonitor.prototype.disableHeartbeat = function () { 1733 this.log.info("[CONNECTION_MONITOR] Heartbeat disabled."); 1734 this.heartbeatEnabled = false; 1735 this.stopHeartbeat(); 1736 } 1737 1738 /** @private */ 1739 net.user1.orbiter.ConnectionMonitor.prototype.startHeartbeat = function () { 1740 if (!this.heartbeatEnabled) { 1741 this.log.info("[CONNECTION_MONITOR] Heartbeat is currently disabled. Ignoring start request."); 1742 return; 1743 } 1744 1745 this.stopHeartbeat(); 1746 1747 this.heartbeats = new net.user1.utils.UDictionary(); 1748 1749 var currentObj = this; 1750 var callback = this.heartbeatTimerListener; 1751 this.heartbeatIntervalID = setInterval(function () { 1752 callback.call(currentObj); 1753 }, this.heartBeatFrequency); 1754 1755 } 1756 1757 /** @private */ 1758 net.user1.orbiter.ConnectionMonitor.prototype.stopHeartbeat = function () { 1759 clearInterval(this.heartbeatIntervalID); 1760 this.heartbeats = null; 1761 } 1762 1763 /** @private */ 1764 net.user1.orbiter.ConnectionMonitor.prototype.heartbeatTimerListener = function () { 1765 if (!this.orbiter.isReady()) { 1766 this.log.info("[CONNECTION_MONITOR] Orbiter is not connected. Stopping heartbeat."); 1767 this.stopHeartbeat(); 1768 return; 1769 } 1770 1771 var timeSinceOldestHeartbeat; 1772 var now = new Date().getTime(); 1773 1774 this.heartbeats[this.heartbeatCounter] = now; 1775 this.orbiter.getMessageManager().sendUPC("u2", 1776 net.user1.orbiter.Messages.CLIENT_HEARTBEAT, 1777 this.orbiter.getClientID(), 1778 "", 1779 this.heartbeatCounter); 1780 this.heartbeatCounter++; 1781 1782 // Assign the oldest heartbeat 1783 if (net.user1.utils.ObjectUtil.length(this.heartbeats) == 1) { 1784 this.oldestHeartbeat = now; 1785 } else { 1786 this.oldestHeartbeat = Number.MAX_VALUE; 1787 for (var p in this.heartbeats) { 1788 if (this.heartbeats[p] < this.oldestHeartbeat) { 1789 this.oldestHeartbeat = this.heartbeats[p]; 1790 } 1791 } 1792 } 1793 // Close connection if too much time has passed since the last response 1794 timeSinceOldestHeartbeat = now - this.oldestHeartbeat; 1795 if (timeSinceOldestHeartbeat > this.connectionTimeout) { 1796 this.log.warn("[CONNECTION_MONITOR] No response from server in " + 1797 timeSinceOldestHeartbeat + "ms. Starting automatic disconnect."); 1798 this.orbiter.disconnect(); 1799 } 1800 } 1801 1802 /** @private */ 1803 net.user1.orbiter.ConnectionMonitor.prototype.heartbeatMessageListener = function (fromClientID, id) { 1804 var ping = new Date().getTime() - this.heartbeats[parseInt(id)]; 1805 if (typeof this.orbiter.self().setAttribute === "undefined") { 1806 // OrbiterMicro 1807 this.orbiter.self().ping = ping; 1808 this.orbiter.getMessageManager().sendUPC("u3", 1809 this.orbiter.getClientID(), 1810 "", 1811 "_PING", 1812 ping.toString(), 1813 "", 1814 this.sharedPing ? "4" : "0"); 1815 } else { 1816 // Orbiter 1817 this.orbiter.self().setAttribute("_PING", 1818 ping.toString(), 1819 null, 1820 this.sharedPing); 1821 } 1822 delete this.heartbeats[parseInt(id)]; 1823 } 1824 1825 //============================================================================== 1826 // RECONNECTION 1827 //============================================================================== 1828 /** @private */ 1829 net.user1.orbiter.ConnectionMonitor.prototype.reconnectTimerListener = function (e) { 1830 this.stopReconnect(); 1831 if (this.orbiter.getConnectionManager().connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED) { 1832 this.doReconnect(); 1833 } 1834 } 1835 1836 /** @private */ 1837 net.user1.orbiter.ConnectionMonitor.prototype.stopReconnect = function () { 1838 clearTimeout(this.autoReconnectTimeoutID); 1839 this.autoReconnectTimeoutID = -1 1840 } 1841 1842 /** @private */ 1843 net.user1.orbiter.ConnectionMonitor.prototype.scheduleReconnect = function (milliseconds) { 1844 // Reset the timer 1845 this.stopReconnect(); 1846 var currentObj = this; 1847 var callback = this.reconnectTimerListener; 1848 this.autoReconnectTimeoutID = setTimeout(function () { 1849 currentObj.autoReconnectTimeoutID = -1; 1850 callback.call(currentObj); 1851 }, milliseconds); 1852 }; 1853 1854 /** @private */ 1855 net.user1.orbiter.ConnectionMonitor.prototype.selectReconnectFrequency = function () { 1856 if (this.autoReconnectMinMS == -1) { 1857 this.autoReconnectFrequency = -1; 1858 } else if (this.autoReconnectMinMS == this.autoReconnectMaxMS) { 1859 this.autoReconnectFrequency = this.autoReconnectMinMS; 1860 } else { 1861 this.autoReconnectFrequency = getRandInt(this.autoReconnectMinMS, this.autoReconnectMaxMS); 1862 this.log.info("[CONNECTION_MONITOR] Random auto-reconnect frequency selected: [" + 1863 this.autoReconnectFrequency + "] ms."); 1864 } 1865 1866 function getRandInt (min, max) { 1867 return min + Math.floor(Math.random()*(max+1 - min)); 1868 } 1869 }; 1870 1871 /** @private */ 1872 net.user1.orbiter.ConnectionMonitor.prototype.doReconnect = function () { 1873 var numActualAttempts = this.orbiter.getConnectionManager().getConnectAttemptCount(); 1874 var numReconnectAttempts; 1875 1876 if (this.orbiter.getConnectionManager().getReadyCount() == 0) { 1877 numReconnectAttempts = numActualAttempts - 1; 1878 } else { 1879 numReconnectAttempts = numActualAttempts; 1880 } 1881 1882 if (this.autoReconnectAttemptLimit != -1 1883 && numReconnectAttempts > 0 1884 && numReconnectAttempts % (this.autoReconnectAttemptLimit) == 0) { 1885 this.log.warn("[CONNECTION_MONITOR] Automatic reconnect attempt limit reached." 1886 + " No further automatic connection attempts will be made until" 1887 + " the next manual connection attempt."); 1888 return; 1889 } 1890 1891 this.scheduleReconnect(this.autoReconnectFrequency); 1892 1893 this.log.warn("[CONNECTION_MONITOR] Attempting automatic reconnect. (Next attempt in " 1894 + this.autoReconnectFrequency + "ms.)"); 1895 this.orbiter.connect(); 1896 } 1897 1898 //============================================================================== 1899 // CONFIGURATION 1900 //============================================================================== 1901 1902 net.user1.orbiter.ConnectionMonitor.prototype.restoreDefaults = function () { 1903 this.setAutoReconnectFrequency(net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_FREQUENCY); 1904 this.setAutoReconnectAttemptLimit(net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_ATTEMPT_LIMIT); 1905 this.setConnectionTimeout(net.user1.orbiter.ConnectionMonitor.DEFAULT_CONNECTION_TIMEOUT); 1906 this.setHeartbeatFrequency(net.user1.orbiter.ConnectionMonitor.DEFAULT_HEARTBEAT_FREQUENCY); 1907 } 1908 1909 net.user1.orbiter.ConnectionMonitor.prototype.setHeartbeatFrequency = function (milliseconds) { 1910 if (milliseconds >= net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY) { 1911 this.heartBeatFrequency = milliseconds; 1912 this.log.info("[CONNECTION_MONITOR] Heartbeat frequency set to " 1913 + milliseconds + " ms."); 1914 // Log a warning for low heartbeat frequencies... 1915 if (milliseconds >= net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY && milliseconds < 1000) { 1916 this.log.info("[CONNECTION_MONITOR] HEARTBEAT FREQUENCY WARNING: " 1917 + milliseconds + " ms. Current frequency will generate " 1918 + (Math.floor((1000/milliseconds)*10)/10) 1919 + " messages per second per connected client."); 1920 } 1921 1922 // If the connection is ready, then restart 1923 // the heartbeat when the heartbeat frequency changes. 1924 if (this.orbiter.isReady()) { 1925 this.startHeartbeat(); 1926 } 1927 } else { 1928 this.log.warn("[CONNECTION_MONITOR] Invalid heartbeat frequency specified: " 1929 + milliseconds + ". Frequency must be " 1930 + net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY + " or greater."); 1931 } 1932 } 1933 1934 net.user1.orbiter.ConnectionMonitor.prototype.getHeartbeatFrequency = function () { 1935 return this.heartBeatFrequency; 1936 } 1937 1938 net.user1.orbiter.ConnectionMonitor.prototype.setAutoReconnectFrequency = function (minMS, maxMS, delayFirstAttempt) { 1939 maxMS = (typeof maxMS == "undefined") ? -1 : maxMS; 1940 delayFirstAttempt = (typeof delayFirstAttempt == "undefined") ? false : delayFirstAttempt; 1941 1942 if (minMS == 0 || minMS < -1) { 1943 this.log.warn("[CONNECTION_MONITOR] Invalid auto-reconnect minMS specified: [" 1944 + minMS + "]. Value must not be zero or less than -1. Value adjusted" 1945 + " to [-1] (no reconnect)."); 1946 minMS = -1; 1947 } 1948 if (minMS == -1) { 1949 this.stopReconnect(); 1950 } else { 1951 if (maxMS == -1) { 1952 maxMS = minMS; 1953 } 1954 if (maxMS < minMS) { 1955 this.log.warn("[CONNECTION_MONITOR] Invalid auto-reconnect maxMS specified: [" 1956 + maxMS + "]." + " Value of maxMS must be greater than or equal " 1957 + "to minMS. Value adjusted to [" + minMS + "]."); 1958 maxMS = minMS; 1959 } 1960 } 1961 1962 this.autoReconnectDelayFirstAttempt = delayFirstAttempt; 1963 this.autoReconnectMinMS = minMS; 1964 this.autoReconnectMaxMS = maxMS; 1965 1966 this.log.info("[CONNECTION_MONITOR] Assigning auto-reconnect frequency settings: [minMS: " 1967 + minMS + ", maxMS: " + maxMS + ", delayFirstAttempt: " 1968 + delayFirstAttempt.toString() + "]."); 1969 if (minMS > 0 && minMS < 1000) { 1970 this.log.info("[CONNECTION_MONITOR] RECONNECT FREQUENCY WARNING: " 1971 + minMS + " minMS specified. Current frequency will cause " 1972 + (Math.floor((1000/minMS)*10)/10).toString() 1973 + " reconnection attempts per second."); 1974 } 1975 this.selectReconnectFrequency(); 1976 } 1977 1978 net.user1.orbiter.ConnectionMonitor.prototype.getAutoReconnectFrequency = function () { 1979 return this.autoReconnectFrequency; 1980 } 1981 1982 net.user1.orbiter.ConnectionMonitor.prototype.setAutoReconnectAttemptLimit = function (attempts) { 1983 if (attempts < -1 || attempts == 0) { 1984 this.log.warn("[CONNECTION_MONITOR] Invalid Auto-reconnect attempt limit specified: " 1985 + attempts + ". Limit must -1 or greater than 1."); 1986 return; 1987 } 1988 1989 this.autoReconnectAttemptLimit = attempts; 1990 1991 if (attempts == -1) { 1992 this.log.info("[CONNECTION_MONITOR] Auto-reconnect attempt limit set to none."); 1993 } else { 1994 this.log.info("[CONNECTION_MONITOR] Auto-reconnect attempt limit set to " 1995 + attempts + " attempt(s)."); 1996 } 1997 }; 1998 1999 net.user1.orbiter.ConnectionMonitor.prototype.getAutoReconnectAttemptLimit = function () { 2000 return this.autoReconnectAttemptLimit; 2001 } 2002 2003 net.user1.orbiter.ConnectionMonitor.prototype.setConnectionTimeout = function (milliseconds) { 2004 if (milliseconds > 0) { 2005 this.connectionTimeout = milliseconds; 2006 this.log.info("[CONNECTION_MONITOR] Connection timeout set to " 2007 + milliseconds + " ms."); 2008 } else { 2009 this.log.warn("[CONNECTION_MONITOR] Invalid connection timeout specified: " 2010 + milliseconds + ". Frequency must be greater " 2011 + "than zero."); 2012 } 2013 } 2014 2015 net.user1.orbiter.ConnectionMonitor.prototype.getConnectionTimeout = function () { 2016 return this.connectionTimeout; 2017 } 2018 2019 net.user1.orbiter.ConnectionMonitor.prototype.sharePing = function (share) { 2020 this.sharedPing = share; 2021 } 2022 2023 net.user1.orbiter.ConnectionMonitor.prototype.isPingShared = function () { 2024 return this.sharedPing; 2025 } 2026 2027 net.user1.orbiter.ConnectionMonitor.prototype.disableHeartbeatLogging = function () { 2028 this.log.addSuppressionTerm("<A>CLIENT_HEARTBEAT</A>"); 2029 this.log.addSuppressionTerm("<A>_PING</A>"); 2030 this.log.addSuppressionTerm("[_PING]"); 2031 this.log.addSuppressionTerm("<![CDATA[_PING]]>"); 2032 } 2033 2034 net.user1.orbiter.ConnectionMonitor.prototype.enableHeartbeatLogging = function () { 2035 this.log.removeSuppressionTerm("<A>CLIENT_HEARTBEAT</A>"); 2036 this.log.removeSuppressionTerm("<A>_PING</A>"); 2037 this.log.removeSuppressionTerm("[_PING]"); 2038 this.log.removeSuppressionTerm("<![CDATA[_PING]]>"); 2039 } 2040 2041 // ============================================================================= 2042 // DISPOSAL 2043 // ============================================================================= 2044 2045 net.user1.orbiter.ConnectionMonitor.prototype.dispose = function () { 2046 this.disposed = true; 2047 2048 this.stopHeartbeat(); 2049 this.stopReconnect(); 2050 2051 this.heartbeats = null; 2052 2053 this.orbiter.removeEventListener(net.user1.orbiter.OrbiterEvent.READY, this.connectReadyListener, this); 2054 this.orbiter.removeEventListener(net.user1.orbiter.OrbiterEvent.CLOSE, this.connectCloseListener, this); 2055 this.orbiter = null; 2056 this.msgManager.removeMessageListener("u7", this.u7); 2057 this.msgManager(null); 2058 this.log = null; 2059 }; 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 //============================================================================== 2078 // CLASS DECLARATION 2079 //============================================================================== 2080 /** @class 2081 @extends net.user1.events.Event 2082 */ 2083 net.user1.orbiter.OrbiterEvent = function (type, 2084 serverUPCVersion, 2085 connectionRefusal) { 2086 net.user1.events.Event.call(this, type); 2087 2088 this.serverUPCVersion = serverUPCVersion; 2089 this.connectionRefusal = connectionRefusal; 2090 }; 2091 2092 //============================================================================== 2093 // INHERITANCE 2094 //============================================================================== 2095 net.user1.utils.extend(net.user1.orbiter.OrbiterEvent, net.user1.events.Event); 2096 2097 //============================================================================== 2098 // STATIC VARIABLES 2099 //============================================================================== 2100 /** @constant */ 2101 net.user1.orbiter.OrbiterEvent.READY = "READY"; 2102 /** @constant */ 2103 net.user1.orbiter.OrbiterEvent.CLOSE = "CLOSE"; 2104 /** @constant */ 2105 net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE = "PROTOCOL_INCOMPATIBLE"; 2106 /** @constant */ 2107 net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED = "CONNECT_REFUSED"; 2108 2109 //============================================================================== 2110 // INSTANCE METHODS 2111 //============================================================================== 2112 net.user1.orbiter.OrbiterEvent.prototype.getServerUPCVersion = function () { 2113 return this.serverUPCVersion; 2114 } 2115 2116 net.user1.orbiter.OrbiterEvent.prototype.getConnectionRefusal = function () { 2117 return this.connectionRefusal; 2118 } 2119 2120 net.user1.orbiter.OrbiterEvent.prototype.toString = function () { 2121 return "[object OrbiterEvent]"; 2122 } 2123 2124 //============================================================================== 2125 // CLASS DECLARATION 2126 //============================================================================== 2127 /** @class 2128 2129 The Snapshot class dispatches the following events: 2130 2131 <ul class="summary"> 2132 <li class="fixedFont">{@link net.user1.orbiter.SnapshotEvent.LOAD}</li> 2133 <li class="fixedFont">{@link net.user1.orbiter.SnapshotEvent.STATUS}</li> 2134 </ul> 2135 2136 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 2137 2138 @extends net.user1.events.EventDispatcher 2139 */ 2140 net.user1.orbiter.snapshot.Snapshot = function () { 2141 // Call superconstructor 2142 net.user1.events.EventDispatcher.call(this); 2143 this.method; 2144 this.args = new Array(); 2145 this.hasStatus; 2146 this.statusReceived; 2147 this.loaded; 2148 this._updateInProgress; 2149 this._status; 2150 this.onLoad = function () {}; 2151 }; 2152 2153 //============================================================================== 2154 // INHERITANCE 2155 //============================================================================== 2156 net.user1.utils.extend(net.user1.orbiter.snapshot.Snapshot, net.user1.events.EventDispatcher); 2157 2158 //============================================================================== 2159 // INSTANCE METHODS 2160 //============================================================================== 2161 net.user1.orbiter.snapshot.Snapshot.prototype.updateInProgress = function () { 2162 return this._updateInProgress; 2163 }; 2164 2165 /** 2166 * @private 2167 */ 2168 net.user1.orbiter.snapshot.Snapshot.prototype.setUpdateInProgress = function (value) { 2169 this._updateInProgress = value; 2170 }; 2171 2172 /** 2173 * @private 2174 */ 2175 net.user1.orbiter.snapshot.Snapshot.prototype.dispatchLoaded = function () { 2176 this.dispatchEvent(new net.user1.orbiter.snapshot.SnapshotEvent(net.user1.orbiter.snapshot.SnapshotEvent.LOAD, this)); 2177 }; 2178 2179 /** 2180 * @private 2181 */ 2182 net.user1.orbiter.snapshot.Snapshot.prototype.dispatchStatus = function () { 2183 this.dispatchEvent(new net.user1.orbiter.snapshot.SnapshotEvent(net.user1.orbiter.snapshot.SnapshotEvent.STATUS, this)); 2184 }; 2185 2186 net.user1.orbiter.snapshot.Snapshot.prototype.getStatus = function () { 2187 return this._status; 2188 }; 2189 2190 /** 2191 * @private 2192 */ 2193 net.user1.orbiter.snapshot.Snapshot.prototype.setStatus = function (value) { 2194 this._status = value; 2195 }; 2196 //============================================================================== 2197 // CLASS DECLARATION 2198 //============================================================================== 2199 /** 2200 * @class 2201 * @extends net.user1.events.Event 2202 */ 2203 net.user1.orbiter.snapshot.SnapshotEvent = function (type, 2204 snapshot) { 2205 net.user1.events.Event.call(this, type); 2206 this.snapshot = snapshot; 2207 }; 2208 2209 //============================================================================== 2210 // INHERITANCE 2211 //============================================================================== 2212 net.user1.utils.extend(net.user1.orbiter.snapshot.SnapshotEvent, net.user1.events.Event); 2213 2214 //============================================================================== 2215 // STATIC VARIABLES 2216 //============================================================================== 2217 2218 /** @constant */ 2219 net.user1.orbiter.snapshot.SnapshotEvent.LOAD = "LOAD"; 2220 /** @constant */ 2221 net.user1.orbiter.snapshot.SnapshotEvent.STATUS = "STATUS"; 2222 2223 net.user1.orbiter.snapshot.SnapshotEvent.prototype.toString = function () { 2224 return "[object SnapshotEvent]"; 2225 }; 2226 //============================================================================== 2227 // CLASS DECLARATION 2228 //============================================================================== 2229 /** 2230 * @private 2231 */ 2232 net.user1.orbiter.SnapshotManager = function (messageManager) { 2233 this.messageManager = messageManager; 2234 this.pendingSnapshots = new Object(); 2235 this.requestIDCounter = 0; 2236 }; 2237 2238 //============================================================================== 2239 // UPDATE SNAPSHOT 2240 //============================================================================== 2241 2242 net.user1.orbiter.SnapshotManager.prototype.updateSnapshot = function (snapshot) { 2243 var args; 2244 if (snapshot != null) { 2245 if (!snapshot.updateInProgress()) { 2246 this.requestIDCounter++; 2247 snapshot.setUpdateInProgress(true); 2248 snapshot.loaded = false; 2249 snapshot.statusReceived = false; 2250 snapshot.setStatus(null); 2251 this.pendingSnapshots[this.requestIDCounter.toString()] = snapshot; 2252 args = snapshot.args.slice(0); 2253 args.unshift(this.requestIDCounter); 2254 args.unshift(snapshot.method); 2255 this.messageManager.sendUPC.apply(this.messageManager, args); 2256 } 2257 } 2258 }; 2259 2260 //============================================================================== 2261 // RECEIVE SNAPSHOT RESULT 2262 //============================================================================== 2263 2264 net.user1.orbiter.SnapshotManager.prototype.receiveSnapshotResult = function (requestID, status) { 2265 var snapshot = this.pendingSnapshots[requestID]; 2266 if (snapshot == null) { 2267 throw new Error("[SNAPSHOT_MANAGER] Received snapshot result for unknown " 2268 + "request ID: [" + requestID + "]"); 2269 } 2270 snapshot.setStatus(status); 2271 this.setStatusReceived(snapshot, requestID); 2272 }; 2273 2274 //============================================================================== 2275 // RECEIVE CLIENTCOUNT SNAPSHOT 2276 //============================================================================== 2277 2278 net.user1.orbiter.SnapshotManager.prototype.receiveClientCountSnapshot = function (requestID, 2279 numClients) { 2280 var snapshot = this.pendingSnapshots[requestID]; 2281 if (snapshot == null) { 2282 throw new Error("[SNAPSHOT_MANAGER] Received client-count snapshot for unknown " 2283 + "request ID: [" + requestID + "]"); 2284 } 2285 snapshot.setCount(numClients); 2286 this.setLoaded(snapshot, requestID); 2287 }; 2288 2289 //============================================================================== 2290 // RECEIVE CLIENT SNAPSHOT 2291 //============================================================================== 2292 2293 net.user1.orbiter.SnapshotManager.prototype.receiveClientSnapshot = function (requestID, manifest) { 2294 var snapshot = this.pendingSnapshots[requestID]; 2295 if (snapshot == null) { 2296 throw new Error("[SNAPSHOT_MANAGER] Received client snapshot for unknown " 2297 + "request ID: [" + requestID + "]"); 2298 } 2299 snapshot.setManifest(manifest); 2300 this.setLoaded(snapshot, requestID); 2301 }; 2302 2303 //============================================================================== 2304 // RECEIVE ACCOUNT SNAPSHOT 2305 //============================================================================== 2306 2307 net.user1.orbiter.SnapshotManager.prototype.receiveAccountSnapshot = function (requestID, manifest) { 2308 var snapshot = this.pendingSnapshots[requestID]; 2309 if (snapshot == null) { 2310 throw new Error("[SNAPSHOT_MANAGER] Received account snapshot for unknown " 2311 + "request ID: [" + requestID + "]"); 2312 } 2313 snapshot.setManifest(manifest); 2314 this.setLoaded(snapshot, requestID); 2315 } 2316 2317 //============================================================================== 2318 // RECEIVE ROOMLIST SNAPSHOT 2319 //============================================================================== 2320 2321 net.user1.orbiter.SnapshotManager.prototype.receiveRoomListSnapshot = function (requestID, 2322 roomList, 2323 qualifier, 2324 recursive) { 2325 var snapshot = this.pendingSnapshots[requestID]; 2326 if (snapshot == null) { 2327 throw new Error("[SNAPSHOT_MANAGER] Received roomlist snapshot for unknown " 2328 + "request ID: [" + requestID + "]"); 2329 } 2330 snapshot.setRoomList(roomList); 2331 snapshot.setQualifier(qualifier == "" ? null : qualifier); 2332 snapshot.setRecursive(recursive); 2333 this.setLoaded(snapshot, requestID); 2334 }; 2335 2336 //============================================================================== 2337 // RECEIVE ROOM SNAPSHOT 2338 //============================================================================== 2339 2340 net.user1.orbiter.SnapshotManager.prototype.receiveRoomSnapshot = function (requestID, manifest) { 2341 var snapshot = this.pendingSnapshots[requestID]; 2342 if (snapshot == null) { 2343 throw new Error("[SNAPSHOT_MANAGER] Received room snapshot for unknown " 2344 + "request ID: [" + requestID + "]"); 2345 } 2346 snapshot.setManifest(manifest); 2347 this.setLoaded(snapshot, requestID); 2348 }; 2349 2350 //============================================================================== 2351 // RECEIVE CLIENTLIST SNAPSHOT 2352 //============================================================================== 2353 2354 net.user1.orbiter.SnapshotManager.prototype.receiveClientListSnapshot = function (requestID, clientList) { 2355 var snapshot = this.pendingSnapshots[requestID]; 2356 if (snapshot == null) { 2357 throw new Error("[SNAPSHOT_MANAGER] Received clientlist snapshot for unknown " 2358 + "request ID: [" + requestID + "]"); 2359 } 2360 snapshot.setClientList(clientList); 2361 this.setLoaded(snapshot, requestID); 2362 }; 2363 2364 //============================================================================== 2365 // RECEIVE ACCOUNTLIST SNAPSHOT 2366 //============================================================================== 2367 2368 net.user1.orbiter.SnapshotManager.prototype.receiveAccountListSnapshot = function (requestID, accountList) { 2369 var snapshot = this.pendingSnapshots[requestID]; 2370 if (snapshot == null) { 2371 throw new Error("[SNAPSHOT_MANAGER] Received accountlist snapshot for unknown " 2372 + "request ID: [" + requestID + "]"); 2373 } 2374 snapshot.setAccountList(accountList); 2375 this.setLoaded(snapshot, requestID); 2376 }; 2377 2378 //============================================================================== 2379 // RECEIVE BANNEDLIST SNAPSHOT 2380 //============================================================================== 2381 2382 net.user1.orbiter.SnapshotManager.prototype.receiveBannedListSnapshot = function (requestID, bannedList) { 2383 var snapshot = this.pendingSnapshots[requestID]; 2384 if (snapshot == null) { 2385 throw new Error("[SNAPSHOT_MANAGER] Received bannedlist snapshot for unknown " 2386 + "request ID: [" + requestID + "]"); 2387 } 2388 snapshot.setBannedList(bannedList); 2389 this.setLoaded(snapshot, requestID); 2390 }; 2391 2392 //============================================================================== 2393 // RECEIVE SERVERMODULELIST SNAPSHOT 2394 //============================================================================== 2395 2396 net.user1.orbiter.SnapshotManager.prototype.receiveServerModuleListSnapshot = function (requestID, moduleList) { 2397 var snapshot = this.pendingSnapshots[requestID]; 2398 if (snapshot == null) { 2399 throw new Error("[SNAPSHOT_MANAGER] Received server module list snapshot for unknown " 2400 + "request ID: [" + requestID + "]"); 2401 } 2402 snapshot.setModuleList(moduleList); 2403 this.setLoaded(snapshot, requestID); 2404 }; 2405 2406 //============================================================================== 2407 // RECEIVE UPCSTATS SNAPSHOT 2408 //============================================================================== 2409 2410 net.user1.orbiter.SnapshotManager.prototype.receiveUPCStatsSnapshot = function (requestID, 2411 totalUPCsProcessed, 2412 numUPCsInQueue, 2413 lastQueueWaitTime, 2414 longestUPCProcesses) { 2415 var snapshot = this.pendingSnapshots[requestID]; 2416 if (snapshot == null) { 2417 throw new Error("[SNAPSHOT_MANAGER] Received UPC stats snapshot for unknown " 2418 + "request ID: [" + requestID + "]"); 2419 } 2420 snapshot.setTotalUPCsProcessed(totalUPCsProcessed); 2421 snapshot.setNumUPCsInQueue(numUPCsInQueue); 2422 snapshot.setLastQueueWaitTime(lastQueueWaitTime); 2423 snapshot.setLongestUPCProcesses(longestUPCProcesses); 2424 this.setLoaded(snapshot, requestID); 2425 }; 2426 2427 //============================================================================== 2428 // RECEIVE NODELIST SNAPSHOT 2429 //============================================================================== 2430 2431 net.user1.orbiter.SnapshotManager.prototype.receiveNodeListSnapshot = function (requestID, nodeList) { 2432 var snapshot = this.pendingSnapshots[requestID]; 2433 if (snapshot == null) { 2434 throw new Error("[SNAPSHOT_MANAGER] Received server node list snapshot for unknown " 2435 + "request ID: [" + requestID + "]"); 2436 } 2437 snapshot.setNodeList(nodeList); 2438 this.setLoaded(snapshot, requestID); 2439 }; 2440 2441 2442 //============================================================================== 2443 // RECEIVE GATEWAYS SNAPSHOT 2444 //============================================================================== 2445 2446 net.user1.orbiter.SnapshotManager.prototype.receiveGatewaysSnapshot = function (requestID, gateways) { 2447 var snapshot = this.pendingSnapshots[requestID]; 2448 if (snapshot == null) { 2449 throw new Error("[SNAPSHOT_MANAGER] Received gateways snapshot for unknown " 2450 + "request ID: [" + requestID + "]"); 2451 } 2452 snapshot.setGateways(gateways); 2453 this.setLoaded(snapshot, requestID); 2454 }; 2455 2456 //============================================================================== 2457 // LOADED AND STATUS ASSIGNMENT 2458 //============================================================================== 2459 2460 net.user1.orbiter.SnapshotManager.prototype.setLoaded = function (snapshot, requestID) { 2461 snapshot.loaded = true; 2462 if (snapshot.hasStatus == false 2463 || (snapshot.hasStatus == true && snapshot.statusReceived)) { 2464 snapshot.setUpdateInProgress(false); 2465 delete this.pendingSnapshots[requestID]; 2466 } 2467 2468 if (snapshot.hasOwnProperty("onLoad")) { 2469 snapshot["onLoad"](); 2470 } 2471 snapshot.dispatchLoaded(); 2472 }; 2473 2474 net.user1.orbiter.SnapshotManager.prototype.setStatusReceived = function (snapshot, requestID) { 2475 if (snapshot.loaded) { 2476 snapshot.setUpdateInProgress(false); 2477 delete this.pendingSnapshots[requestID]; 2478 } 2479 snapshot.dispatchStatus(); 2480 }; 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 //============================================================================== 2500 // BOOLEAN GROUP TYPE CONSTANTS 2501 //============================================================================== 2502 /** @class */ 2503 net.user1.orbiter.filters.BooleanGroupType = new Object(); 2504 /** @constant */ 2505 net.user1.orbiter.filters.BooleanGroupType.AND = "AND"; 2506 /** @constant */ 2507 net.user1.orbiter.filters.BooleanGroupType.OR = "OR"; 2508 //============================================================================== 2509 // CLASS DECLARATION 2510 //============================================================================== 2511 /** 2512 * @class 2513 */ 2514 net.user1.orbiter.filters.BooleanGroup = function (type) { 2515 this.type = type; 2516 this.comparisons = new Array(); 2517 }; 2518 2519 net.user1.orbiter.filters.BooleanGroup.prototype.addComparison = function (comparison) { 2520 if (comparison == null) return; 2521 this.comparisons.push(comparison); 2522 }; 2523 2524 net.user1.orbiter.filters.BooleanGroup.prototype.toXMLString = function () { 2525 var s = type == net.user1.orbiter.filters.BooleanGroupType.AND ? "<and>\n" : "<or>\n"; 2526 2527 var comparison; 2528 for (var i = 0; i < this.comparisons.length; i++) { 2529 comparison = this.comparisons[i]; 2530 s += comparison.toXMLString() + "\n"; 2531 } 2532 s += this.type == net.user1.orbiter.filters.BooleanGroupType.AND ? "</and>" : "</or>"; 2533 return s; 2534 } 2535 //============================================================================== 2536 // CLASS DECLARATION 2537 //============================================================================== 2538 /** 2539 * @class 2540 * @extends net.user1.events.Event 2541 */ 2542 net.user1.orbiter.AccountEvent = function (type, 2543 status, 2544 userID, 2545 clientID, 2546 role) { 2547 net.user1.events.Event.call(this, type); 2548 2549 this.status = status; 2550 this.userID = userID; 2551 this.clientID = clientID; 2552 this.role = role; 2553 this.account = null; 2554 }; 2555 2556 //============================================================================== 2557 // INHERITANCE 2558 //============================================================================== 2559 net.user1.utils.extend(net.user1.orbiter.AccountEvent, net.user1.events.Event); 2560 2561 //============================================================================== 2562 // STATIC VARIABLES 2563 //============================================================================== 2564 2565 /** @constant */ 2566 net.user1.orbiter.AccountEvent.LOGIN_RESULT = "LOGIN_RESULT"; 2567 /** @constant */ 2568 net.user1.orbiter.AccountEvent.LOGIN = "LOGIN"; 2569 /** @constant */ 2570 net.user1.orbiter.AccountEvent.LOGOFF_RESULT = "LOGOFF_RESULT"; 2571 /** @constant */ 2572 net.user1.orbiter.AccountEvent.LOGOFF = "LOGOFF"; 2573 /** @constant */ 2574 net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT = "CHANGE_PASSWORD_RESULT"; 2575 /** @constant */ 2576 net.user1.orbiter.AccountEvent.CHANGE_PASSWORD = "CHANGE_PASSWORD"; 2577 /** @constant */ 2578 net.user1.orbiter.AccountEvent.OBSERVE = "OBSERVE"; 2579 /** @constant */ 2580 net.user1.orbiter.AccountEvent.STOP_OBSERVING = "STOP_OBSERVING"; 2581 /** @constant */ 2582 net.user1.orbiter.AccountEvent.OBSERVE_RESULT = "OBSERVE_RESULT"; 2583 /** @constant */ 2584 net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT = "STOP_OBSERVING_RESULT"; 2585 /** @constant */ 2586 net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT = "ADD_ROLE_RESULT"; 2587 /** @constant */ 2588 net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT = "REMOVE_ROLE_RESULT"; 2589 /** @constant */ 2590 net.user1.orbiter.AccountEvent.SYNCHRONIZE = "SYNCHRONIZE"; 2591 2592 2593 //============================================================================== 2594 // INSTANCE METHODS 2595 //============================================================================== 2596 net.user1.orbiter.AccountEvent.prototype.getAccount = function () { 2597 if (this.target instanceof net.user1.orbiter.AccountManager) { 2598 return this.account; 2599 } else if (this.target instanceof net.user1.orbiter.UserAccount) { 2600 return this.target; 2601 } else { 2602 throw new Error("[AccountEvent] Unexpected target type: " + this.target); 2603 } 2604 }; 2605 2606 /** 2607 * @private 2608 */ 2609 net.user1.orbiter.AccountEvent.prototype.setAccount = function (value) { 2610 this.account = value; 2611 }; 2612 2613 net.user1.orbiter.AccountEvent.prototype.getUserID = function () { 2614 return this.userID; 2615 }; 2616 2617 net.user1.orbiter.AccountEvent.prototype.getRole = function () { 2618 return this.role; 2619 }; 2620 2621 net.user1.orbiter.AccountEvent.prototype.getClientID = function () { 2622 return this.clientID; 2623 }; 2624 2625 net.user1.orbiter.AccountEvent.prototype.getStatus = function () { 2626 return this.status; 2627 }; 2628 2629 net.user1.orbiter.AccountEvent.prototype.toString = function () { 2630 return "[object AccountEvent]"; 2631 }; 2632 //============================================================================== 2633 // CLASS DECLARATION 2634 //============================================================================== 2635 /** 2636 * @class 2637 * @extends net.user1.orbiter.snapshot.Snapshot 2638 */ 2639 net.user1.orbiter.snapshot.AccountListSnapshot = function () { 2640 // Call superconstructor 2641 net.user1.orbiter.snapshot.Snapshot.call(this); 2642 this.accountList = null; 2643 this.method = net.user1.orbiter.UPC.GET_ACCOUNTLIST_SNAPSHOT; 2644 }; 2645 2646 //============================================================================== 2647 // INHERITANCE 2648 //============================================================================== 2649 net.user1.utils.extend(net.user1.orbiter.snapshot.AccountListSnapshot, net.user1.orbiter.snapshot.Snapshot); 2650 2651 //============================================================================== 2652 // INSTANCE METHODS 2653 //============================================================================== 2654 /** 2655 * @private 2656 */ 2657 net.user1.orbiter.snapshot.AccountListSnapshot.prototype.setAccountList = function (value) { 2658 this.accountList = value; 2659 } 2660 2661 net.user1.orbiter.snapshot.AccountListSnapshot.prototype.getAccountList = function () { 2662 if (!this.accountList) { 2663 return null; 2664 } 2665 return this.accountList.slice(); 2666 } 2667 //============================================================================== 2668 // CLASS DECLARATION 2669 //============================================================================== 2670 /** @class 2671 2672 The AccountManager class dispatches the following events: 2673 2674 <ul class="summary"> 2675 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT}</li> 2676 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT}</li> 2677 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT}</li> 2678 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED}</li> 2679 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED}</li> 2680 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF_RESULT}</li> 2681 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF}</li> 2682 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN_RESULT}</li> 2683 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN}</li> 2684 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD}</li> 2685 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE}</li> 2686 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING}</li> 2687 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT}</li> 2688 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT}</li> 2689 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE_RESULT}</li> 2690 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT}</li> 2691 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE}</li> 2692 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT}</li> 2693 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT}</li> 2694 </ul> 2695 2696 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 2697 2698 @extends net.user1.events.EventDispatcher 2699 */ 2700 net.user1.orbiter.AccountManager = function (log) { 2701 // Call superconstructor 2702 net.user1.events.EventDispatcher.call(this); 2703 2704 this.watchedAccounts = new net.user1.orbiter.AccountSet(); 2705 this.observedAccounts = new net.user1.orbiter.AccountSet(); 2706 this.accountCache = new net.user1.utils.LRUCache(10000); 2707 this.log = log; 2708 this._isWatchingForAccounts = false; 2709 this.accountCache; 2710 this.messageManager; 2711 this.clientManager; 2712 this.roomManager; 2713 }; 2714 2715 //============================================================================== 2716 // INHERITANCE 2717 //============================================================================== 2718 net.user1.utils.extend(net.user1.orbiter.AccountManager, net.user1.events.EventDispatcher); 2719 2720 // ============================================================================= 2721 // DEPENDENCIES 2722 // ============================================================================= 2723 /** 2724 * @private 2725 */ 2726 net.user1.orbiter.AccountManager.prototype.setMessageManager = function (value) { 2727 this.messageManager = value; 2728 } 2729 2730 /** 2731 * @private 2732 */ 2733 net.user1.orbiter.AccountManager.prototype.setClientManager = function (value) { 2734 this.clientManager = value; 2735 } 2736 2737 /** 2738 * @private 2739 */ 2740 net.user1.orbiter.AccountManager.prototype.setRoomManager = function (value) { 2741 this.roomManager = value; 2742 } 2743 2744 // ============================================================================= 2745 // REMOTE ACCOUNT CREATION/REMOVAL 2746 // ============================================================================= 2747 2748 net.user1.orbiter.AccountManager.prototype.createAccount = function (userID, password) { 2749 if (userID == null || userID == "") { 2750 this.log.warn("[ACCOUNT_MANAGER] Create account failed. No userID supplied."); 2751 } else if (password == null) { 2752 this.log.warn("[ACCOUNT_MANAGER] Create account failed. No password supplied."); 2753 } else { 2754 this.messageManager.sendUPC(net.user1.orbiter.UPC.CREATE_ACCOUNT, userID, password); 2755 } 2756 }; 2757 2758 net.user1.orbiter.AccountManager.prototype.removeAccount = function (userID, password) { 2759 if (userID == null || userID == "") { 2760 this.log.warn("[ACCOUNT_MANAGER] Remove account failed. No userID supplied."); 2761 } else { 2762 if (password == null) { 2763 this.log.warn("[ACCOUNT_MANAGER] Remove account: no password supplied." + 2764 " Removal will fail unless sender is an administrator."); 2765 } 2766 this.messageManager.sendUPC(net.user1.orbiter.UPC.REMOVE_ACCOUNT, userID, password); 2767 } 2768 } 2769 2770 // ============================================================================= 2771 // CHANGE PASSWORD 2772 // ============================================================================= 2773 2774 net.user1.orbiter.AccountManager.prototype.changePassword = function (userID, newPassword, oldPassword) { 2775 if (userID == null || userID == "") { 2776 this.log.warn("[ACCOUNT_MANAGER] Change password failed. No userID supplied."); 2777 } else if (newPassword == null || newPassword == "") { 2778 this.log.warn("[ACCOUNT_MANAGER] Change password failed for account [" 2779 + userID + "]. No new password supplied."); 2780 } else { 2781 if (oldPassword == null || oldPassword == "") { 2782 this.log.warn("[ACCOUNT_MANAGER] Change account password for account [" 2783 + userID + "]: no old password supplied." 2784 + " Operation will fail unless sender is an administrator."); 2785 oldPassword = ""; 2786 } 2787 this.messageManager.sendUPC(net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD, userID, oldPassword, newPassword); 2788 } 2789 }; 2790 2791 // ============================================================================= 2792 // ADD/REMOVE ROLE 2793 // ============================================================================= 2794 2795 net.user1.orbiter.AccountManager.prototype.addRole = function (userID, role) { 2796 if (userID == null || userID == "") { 2797 this.log.warn("[ACCOUNT_MANAGER] Add role failed. No userID supplied."); 2798 } else if (role == null || role == "") { 2799 this.log.warn("[ACCOUNT_MANAGER] Add role failed for account [" 2800 + userID + "]. No role supplied."); 2801 } else { 2802 this.messageManager.sendUPC(net.user1.orbiter.UPC.ADD_ROLE, userID, role); 2803 } 2804 }; 2805 2806 net.user1.orbiter.AccountManager.prototype.removeRole = function (userID, role) { 2807 if (userID == null || userID == "") { 2808 this.log.warn("[ACCOUNT_MANAGER] Remove role failed. No userID supplied."); 2809 } else if (role == null || role == "") { 2810 this.log.warn("[ACCOUNT_MANAGER] Remove role failed for account [" 2811 + userID + "]. No role supplied."); 2812 } else { 2813 this.messageManager.sendUPC(net.user1.orbiter.UPC.REMOVE_ROLE, userID, role); 2814 } 2815 }; 2816 2817 // ============================================================================= 2818 // LOCAL ACCOUNT CREATION/REMOVAL 2819 // ============================================================================= 2820 2821 /** 2822 * @private 2823 */ 2824 net.user1.orbiter.AccountManager.prototype.requestAccount = function (userID) { 2825 var account; 2826 2827 if (userID == null || userID == "") { 2828 return null; 2829 } else { 2830 account = this.getAccount(userID); 2831 if (account == null) { 2832 account = new net.user1.orbiter.UserAccount(userID, this.log, this, this.clientManager, this.roomManager); 2833 account.setAttributeManager(new net.user1.orbiter.AttributeManager(account, this.messageManager, this.log)); 2834 this.accountCache.put(userID, account); 2835 } 2836 return account; 2837 } 2838 }; 2839 2840 /** 2841 * @private 2842 */ 2843 net.user1.orbiter.AccountManager.prototype.deserializeWatchedAccounts = function (ids) { 2844 var idList = ids.split(Tokens.RS); 2845 var idHash = new net.user1.utils.UDictionary(); 2846 var len = idList.length; 2847 2848 // Generate a hash of clientID keys to dummy values for quick lookup 2849 for (var i = len; --i >= 0;) { 2850 idHash[idList[i]] = 1; 2851 } 2852 2853 // Remove all local accounts that are not in the new list from the server 2854 var accountStillExists; 2855 for (var accountID in watchedAccounts.getAll()) { 2856 if (!idHash.hasOwnProperty(accountID)) { 2857 removeWatchedAccount(accountID); 2858 } 2859 } 2860 2861 // Add accounts from the new list that are not known locally. Do not add 2862 // clients for the accounts because "watch for accounts" does not 2863 // include client knowledge. 2864 if (ids != "") { // Empty string means no accounts are on the server 2865 for (accountID in idHash) { 2866 if (accountID != "") { 2867 if (!this.watchedAccounts.containsUserID(accountID)) { 2868 this.addWatchedAccount(this.requestAccount(accountID)); 2869 } 2870 } else { 2871 throw new Error("[CORE_MESSAGE_LISTENER] Received empty account id in user list (u127)."); 2872 } 2873 } 2874 } 2875 2876 this.fireSynchronize(); 2877 }; 2878 2879 // ============================================================================= 2880 // OBSERVED ACCOUNTS 2881 // ============================================================================= 2882 2883 net.user1.orbiter.AccountManager.prototype.observeAccount = function (userID) { 2884 this.messageManager.sendUPC(net.user1.orbiter.UPC.OBSERVE_ACCOUNT, userID); 2885 }; 2886 2887 // This method is internal because the developer is expected to access 2888 // stopObserving() through the UserAccount directly. AccountManager's 2889 // observeAccount() exists only to allow developers to observe a 2890 // user that is currently unknown. 2891 /** 2892 * @private 2893 */ 2894 net.user1.orbiter.AccountManager.prototype.stopObservingAccount = function (userID) { 2895 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT, userID); 2896 }; 2897 2898 /** 2899 * @private 2900 */ 2901 net.user1.orbiter.AccountManager.prototype.addObservedAccount = function (account) { 2902 this.observedAccounts.add(account); 2903 this.fireObserveAccount(account.getUserID()); 2904 } 2905 2906 /** 2907 * @private 2908 */ 2909 net.user1.orbiter.AccountManager.prototype.removeObservedAccount = function (userID) { 2910 var account = this.observedAccounts.removeByUserID(userID); 2911 this.fireStopObservingAccount(userID); 2912 return account; 2913 } 2914 2915 /** 2916 * @private 2917 */ 2918 net.user1.orbiter.AccountManager.prototype.removeAllObservedAccounts = function () { 2919 this.observedAccounts.removeAll(); 2920 } 2921 2922 net.user1.orbiter.AccountManager.prototype.isObservingAccount = function (userID) { 2923 return this.observedAccounts.containsUserID(userID); 2924 } 2925 2926 //============================================================================== 2927 // WATCH FOR ACCOUNTS 2928 //============================================================================== 2929 2930 net.user1.orbiter.AccountManager.prototype.watchForAccounts = function () { 2931 this.messageManager.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS); 2932 } 2933 2934 net.user1.orbiter.AccountManager.prototype.stopWatchingForAccounts = function () { 2935 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS_RESULT); 2936 } 2937 2938 net.user1.orbiter.AccountManager.prototype.isWatchingForAccounts = function () { 2939 return this._isWatchingForAccounts; 2940 } 2941 2942 /** 2943 * @private 2944 */ 2945 net.user1.orbiter.AccountManager.prototype.setIsWatchingForAccounts = function (value) { 2946 this._isWatchingForAccounts = value; 2947 } 2948 2949 /** 2950 * @private 2951 */ 2952 net.user1.orbiter.AccountManager.prototype.addWatchedAccount = function (account) { 2953 this.watchedAccounts.add(account); 2954 this.fireAccountAdded(account.getUserID(), account); 2955 } 2956 2957 /** 2958 * @private 2959 */ 2960 net.user1.orbiter.AccountManager.prototype.removeWatchedAccount = function (userID) { 2961 return this.watchedAccounts.removeByUserID(userID); 2962 } 2963 2964 /** 2965 * @private 2966 */ 2967 net.user1.orbiter.AccountManager.prototype.removeAllWatchedAccounts = function () { 2968 this.watchedAccounts.removeAll(); 2969 } 2970 2971 net.user1.orbiter.AccountManager.prototype.hasWatchedAccount = function (userID) { 2972 return this.watchedAccounts.containsUserID(userID); 2973 } 2974 2975 // ============================================================================= 2976 // CLIENT ACCESS 2977 // ============================================================================= 2978 2979 /** 2980 * @private 2981 */ 2982 net.user1.orbiter.AccountManager.prototype.getClientsForObservedAccounts = function () { 2983 var clients = new Object(); 2984 var client; 2985 2986 var accounts = this.observedAccounts.getAll(); 2987 var account; 2988 for (var userID in accounts) { 2989 account = accounts[userID]; 2990 client = account.getInternalClient(); 2991 if (client != null) { 2992 clients[client.getClientID()] = client; 2993 } 2994 } 2995 2996 return clients; 2997 } 2998 2999 // ============================================================================= 3000 // LOCAL ACCOUNT ACCESS 3001 // ============================================================================= 3002 3003 net.user1.orbiter.AccountManager.prototype.getAccount = function (userID) { 3004 // Look in account cache 3005 var account = this.accountCache.get(userID); 3006 if (account) { 3007 return account; 3008 } 3009 3010 // Look in observed accounts 3011 account = this.observedAccounts.getByUserID(userID); 3012 if (account) { 3013 return account; 3014 } 3015 3016 // Look in watched accounts 3017 account = this.watchedAccounts.getByUserID(userID); 3018 if (account) { 3019 return account; 3020 } 3021 3022 // Look in connected accounts 3023 var connectedAccounts = new Object(); 3024 var clients = this.clientManager.getInternalClients(); 3025 var client; 3026 for (var clientID in clients) { 3027 account = clients[clientID].getAccount(); 3028 if (account != null && account.getUserID() == userID) { 3029 return account; 3030 } 3031 } 3032 3033 return null; 3034 }; 3035 3036 net.user1.orbiter.AccountManager.prototype.selfAccount = function () { 3037 return this.clientManager.self().getAccount(); 3038 }; 3039 3040 net.user1.orbiter.AccountManager.prototype.getAccounts = function () { 3041 var connectedAccounts = new Object(); 3042 var account; 3043 3044 var clients = this.clientManager.getInternalClients(); 3045 var client; 3046 for (var clientID in clients) { 3047 account = client.getAccount(); 3048 if (account != null) { 3049 connectedAccounts[account.getUserID()] = account; 3050 } 3051 } 3052 3053 return net.user1.utils.ObjectUtil.combine(connectedAccounts, this.observedAccounts.getAll(), this.watchedAccounts.getAll()); 3054 }; 3055 3056 net.user1.orbiter.AccountManager.prototype.accountIsKnown = function (userID) { 3057 for (var knownUserID in this.getAccounts()) { 3058 if (knownUserID == userID) { 3059 return true; 3060 } 3061 } 3062 return false; 3063 }; 3064 3065 net.user1.orbiter.AccountManager.prototype.getNumAccounts = function () { 3066 return this.getAccounts().length; 3067 }; 3068 3069 net.user1.orbiter.AccountManager.prototype.getNumAccountsOnServer = function () { 3070 return this.watchedAccounts.length(); 3071 }; 3072 3073 net.user1.orbiter.AccountManager.prototype.getNumLoggedInAccounts = function () { 3074 var count; 3075 var account; 3076 var accounts = this.getAccounts(); 3077 for (var userID in accounts) { 3078 account = accounts[userID]; 3079 if (account.isLoggedIn()) { 3080 count++; 3081 } 3082 } 3083 return count; 3084 }; 3085 3086 // ============================================================================= 3087 // LOGIN/LOGOFF 3088 // ============================================================================= 3089 3090 net.user1.orbiter.AccountManager.prototype.login = function (userID, password) { 3091 if (this.clientManager.self().getConnectionState() == net.user1.orbiter.ConnectionState.LOGGED_IN) { 3092 this.log.warn("[ACCOUNT_MANAGER] User [" + userID + "]: Login attempt" 3093 + " ignored. Already logged in. Current client must logoff before" 3094 + " logging in again."); 3095 this.fireLoginResult(userID, net.user1.orbiter.Status.ERROR); 3096 } else if (userID == null) { 3097 this.log.warn("[ACCOUNT_MANAGER] Login attempt" 3098 + " failed. No userID supplied."); 3099 } else if (password == null) { 3100 this.log.warn("[ACCOUNT_MANAGER] Login attempt failed for user " 3101 + "[" + userID + "] failed. No password supplied."); 3102 } else { 3103 this.messageManager.sendUPC(net.user1.orbiter.UPC.LOGIN, userID, password); 3104 } 3105 }; 3106 3107 net.user1.orbiter.AccountManager.prototype.logoff = function (userID, password) { 3108 if (userID == null) { 3109 // Current client 3110 if (this.clientManager.self().getConnectionState() != net.user1.orbiter.ConnectionState.LOGGED_IN) { 3111 this.log.warn("[ACCOUNT_MANAGER] Logoff failed. The current user is not logged in."); 3112 } else { 3113 this.clientManager.self().getAccount().logoff(); 3114 } 3115 } else if (userID == "") { 3116 // Invalid client 3117 this.log.warn("[ACCOUNT_MANAGER] Logoff failed. Supplied userID must not be the empty string."); 3118 } else { 3119 // UserID supplied 3120 if (password == null || password == "") { 3121 if (this.clientManager.self().getConnectionState() != net.user1.orbiter.ConnectionState.LOGGED_IN) { 3122 this.log.warn("[ACCOUNT_MANAGER] Logoff: no password supplied." + 3123 " Operation will fail unless sender is an administrator."); 3124 } 3125 password = ""; 3126 } 3127 this.messageManager.sendUPC(net.user1.orbiter.UPC.LOGOFF, userID, password); 3128 } 3129 } 3130 3131 //============================================================================== 3132 // EVENT DISPATCHING 3133 //============================================================================== 3134 3135 /** 3136 * @private 3137 */ 3138 net.user1.orbiter.AccountManager.prototype.fireCreateAccountResult = function (userID, status) { 3139 var e = new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT, 3140 userID, this.getAccount(userID), status); 3141 this.dispatchEvent(e); 3142 }; 3143 3144 /** 3145 * @private 3146 */ 3147 net.user1.orbiter.AccountManager.prototype.fireRemoveAccountResult = function (userID, status) { 3148 var e = new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT, 3149 userID, this.getAccount(userID), status); 3150 this.dispatchEvent(e); 3151 }; 3152 3153 /** 3154 * @private 3155 */ 3156 net.user1.orbiter.AccountManager.prototype.fireChangePasswordResult = function (userID, status) { 3157 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT, 3158 status, userID); 3159 e.setAccount(this.getAccount(userID)); 3160 this.dispatchEvent(e); 3161 }; 3162 3163 /** 3164 * @private 3165 */ 3166 net.user1.orbiter.AccountManager.prototype.fireAccountAdded = function (userID, account) { 3167 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED, 3168 userID, account)); 3169 }; 3170 3171 /** 3172 * @private 3173 */ 3174 net.user1.orbiter.AccountManager.prototype.fireAccountRemoved = function (userID, account) { 3175 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED, 3176 userID, account)); 3177 }; 3178 3179 /** 3180 * @private 3181 */ 3182 net.user1.orbiter.AccountManager.prototype.fireLogoffResult = function (userID, status) { 3183 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF_RESULT, 3184 status, userID); 3185 e.setAccount(this.getAccount(userID)); 3186 this.dispatchEvent(e); 3187 }; 3188 3189 /** 3190 * @private 3191 */ 3192 net.user1.orbiter.AccountManager.prototype.fireLogoff = function (account, clientID) { 3193 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF, 3194 net.user1.orbiter.Status.SUCCESS, account.getUserID(), clientID); 3195 e.setAccount(account); 3196 this.dispatchEvent(e); 3197 }; 3198 3199 /** 3200 * @private 3201 */ 3202 net.user1.orbiter.AccountManager.prototype.fireLoginResult = function (userID, status) { 3203 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN_RESULT, 3204 status, userID); 3205 e.setAccount(this.getAccount(userID)); 3206 this.dispatchEvent(e); 3207 }; 3208 3209 /** 3210 * @private 3211 */ 3212 net.user1.orbiter.AccountManager.prototype.fireLogin = function (account, clientID) { 3213 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN, 3214 net.user1.orbiter.Status.SUCCESS, account.getUserID(), clientID); 3215 e.setAccount(account); 3216 this.dispatchEvent(e); 3217 }; 3218 3219 /** 3220 * @private 3221 */ 3222 net.user1.orbiter.AccountManager.prototype.fireChangePassword = function (userID) { 3223 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD, 3224 net.user1.orbiter.Status.SUCCESS, userID); 3225 e.setAccount(this.getAccount(userID)); 3226 this.dispatchEvent(e); 3227 }; 3228 3229 /** 3230 * @private 3231 */ 3232 net.user1.orbiter.AccountManager.prototype.fireObserveAccount = function (userID) { 3233 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE, 3234 null, userID); 3235 e.setAccount(this.getAccount(userID)); 3236 this.dispatchEvent(e); 3237 }; 3238 3239 /** 3240 * @private 3241 */ 3242 net.user1.orbiter.AccountManager.prototype.fireStopObservingAccount = function (userID) { 3243 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING, 3244 null, userID); 3245 e.setAccount(this.getAccount(userID)); 3246 this.dispatchEvent(e); 3247 }; 3248 3249 /** 3250 * @private 3251 */ 3252 net.user1.orbiter.AccountManager.prototype.fireStopWatchingForAccountsResult = function (status) { 3253 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT, 3254 null, null, status)); 3255 } 3256 3257 /** 3258 * @private 3259 */ 3260 net.user1.orbiter.AccountManager.prototype.fireWatchForAccountsResult = function (status) { 3261 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT, 3262 null, null, status)); 3263 }; 3264 3265 /** 3266 * @private 3267 */ 3268 net.user1.orbiter.AccountManager.prototype.fireObserveAccountResult = function (userID, status) { 3269 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE_RESULT, 3270 status, userID); 3271 e.setAccount(this.getAccount(userID)); 3272 this.dispatchEvent(e); 3273 }; 3274 3275 /** 3276 * @private 3277 */ 3278 net.user1.orbiter.AccountManager.prototype.fireStopObservingAccountResult = function (userID, status) { 3279 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT, 3280 status, userID); 3281 e.setAccount(this.getAccount(userID)); 3282 this.dispatchEvent(e); 3283 }; 3284 3285 /** 3286 * @private 3287 */ 3288 net.user1.orbiter.AccountManager.prototype.fireAddRoleResult = function (userID, role, status) { 3289 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT, 3290 status, userID, null, role); 3291 e.setAccount(this.getAccount(userID)); 3292 this.dispatchEvent(e); 3293 }; 3294 3295 /** 3296 * @private 3297 */ 3298 net.user1.orbiter.AccountManager.prototype.fireRemoveRoleResult = function (userID, role, status) { 3299 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT, 3300 status, userID, null, role); 3301 e.setAccount(this.getAccount(userID)); 3302 this.dispatchEvent(e); 3303 }; 3304 3305 /** 3306 * @private 3307 */ 3308 net.user1.orbiter.AccountManager.prototype.fireSynchronize = function () { 3309 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE)); 3310 } 3311 3312 //============================================================================== 3313 // CLEANUP AND DISPOSAL 3314 //============================================================================== 3315 3316 /** 3317 * @private 3318 */ 3319 net.user1.orbiter.AccountManager.prototype.cleanup = function () { 3320 this.log.info("[ACCOUNT_MANAGER] Cleaning resources."); 3321 this.removeAllObservedAccounts(); 3322 this.removeAllWatchedAccounts(); 3323 this.setIsWatchingForAccounts(false); 3324 }; 3325 3326 //============================================================================== 3327 // CLASS DECLARATION 3328 //============================================================================== 3329 /** @class 3330 @extends net.user1.events.Event 3331 */ 3332 net.user1.orbiter.AccountManagerEvent = function (type, 3333 userID, 3334 account, 3335 status) { 3336 net.user1.events.Event.call(this, type); 3337 3338 this.account = account; 3339 this.userID = userID; 3340 this.status = status; 3341 }; 3342 3343 //============================================================================== 3344 // INHERITANCE 3345 //============================================================================== 3346 net.user1.utils.extend(net.user1.orbiter.AccountManagerEvent, net.user1.events.Event); 3347 3348 //============================================================================== 3349 // STATIC VARIABLES 3350 //============================================================================== 3351 3352 /** @constant */ 3353 net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT = "CREATE_ACCOUNT_RESULT"; 3354 /** @constant */ 3355 net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT = "REMOVE_ACCOUNT_RESULT"; 3356 /** @constant */ 3357 net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED = "ACCOUNT_ADDED"; 3358 /** @constant */ 3359 net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED = "ACCOUNT_REMOVED"; 3360 /** @constant */ 3361 net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT = "WATCH_FOR_ACCOUNTS_RESULT"; 3362 /** @constant */ 3363 net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT = "STOP_WATCHING_FOR_ACCOUNTS_RESULT"; 3364 /** @constant */ 3365 net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE = "SYNCHRONIZE"; 3366 3367 //============================================================================== 3368 // INSTANCE METHODS 3369 //============================================================================== 3370 net.user1.orbiter.AccountManagerEvent.prototype.getStatus = function () { 3371 return this.status; 3372 }; 3373 3374 net.user1.orbiter.AccountManagerEvent.prototype.getUserID = function () { 3375 return this.userID; 3376 }; 3377 3378 net.user1.orbiter.AccountManagerEvent.prototype.getAccount = function () { 3379 return this.account; 3380 }; 3381 3382 net.user1.orbiter.AccountManagerEvent.prototype.toString = function () { 3383 return "[object AccountManagerEvent]"; 3384 }; 3385 //============================================================================== 3386 // CLASS DECLARATION 3387 //============================================================================== 3388 /** 3389 * @private 3390 */ 3391 net.user1.orbiter.AccountSet = function () { 3392 this.accounts = new net.user1.utils.UDictionary(); 3393 }; 3394 3395 net.user1.orbiter.AccountSet.prototype.add = function (account) { 3396 this.accounts[account.getUserID()] = account; 3397 }; 3398 3399 net.user1.orbiter.AccountSet.prototype.remove = function (account) { 3400 var account = this.accounts[account.getUserID()]; 3401 delete this.accounts[account.getUserID()]; 3402 return account; 3403 } 3404 3405 net.user1.orbiter.AccountSet.prototype.removeAll = function () { 3406 this.accounts = new net.user1.utils.UDictionary(); 3407 } 3408 3409 net.user1.orbiter.AccountSet.prototype.removeByUserID = function (userID) { 3410 var account = this.accounts[userID]; 3411 delete this.accounts[userID]; 3412 return account; 3413 } 3414 3415 net.user1.orbiter.AccountSet.prototype.contains = function (account) { 3416 return this.accounts[account.getUserID()] != null; 3417 } 3418 3419 net.user1.orbiter.AccountSet.prototype.containsUserID = function (userID) { 3420 if (userID == "" || userID == null) { 3421 return false; 3422 } 3423 return this.getByUserID(userID) != null; 3424 } 3425 3426 net.user1.orbiter.AccountSet.prototype.getByUserID = function (userID) { 3427 return this.accounts[userID]; 3428 } 3429 3430 net.user1.orbiter.AccountSet.prototype.getByClient = function (client) { 3431 var account; 3432 for (var userID in this.accounts) { 3433 account = this.accounts[userID]; 3434 if (account.getInternalClient() == client) { 3435 return account; 3436 } 3437 } 3438 return null; 3439 } 3440 3441 net.user1.orbiter.AccountSet.prototype.getAll = function () { 3442 return this.accounts; 3443 } 3444 3445 net.user1.orbiter.AccountSet.prototype.length = function () { 3446 var count; 3447 for (var userID in this.accounts) { 3448 count++; 3449 } 3450 return count; 3451 } 3452 //============================================================================== 3453 // CLASS DECLARATION 3454 //============================================================================== 3455 /** 3456 * @class 3457 * @extends net.user1.orbiter.snapshot.Snapshot 3458 */ 3459 net.user1.orbiter.snapshot.AccountSnapshot = function (userID) { 3460 // Call superconstructor 3461 net.user1.orbiter.snapshot.Snapshot.call(this); 3462 this.manifest = null; 3463 this.method = net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT; 3464 this.args = [userID]; 3465 this.hasStatus = true; 3466 }; 3467 3468 //============================================================================== 3469 // INHERITANCE 3470 //============================================================================== 3471 net.user1.utils.extend(net.user1.orbiter.snapshot.AccountSnapshot, net.user1.orbiter.snapshot.Snapshot); 3472 3473 //============================================================================== 3474 // INSTANCE METHODS 3475 //============================================================================== 3476 /** 3477 * @private 3478 */ 3479 net.user1.orbiter.snapshot.AccountSnapshot.prototype.setManifest = function (value) { 3480 this.manifest = value; 3481 }; 3482 3483 net.user1.orbiter.snapshot.AccountSnapshot.prototype.getAttribute = function (name, scope) { 3484 if (!this.manifest) { 3485 return null; 3486 } 3487 return this.manifest.persistentAttributes.getAttribute(name, scope); 3488 }; 3489 3490 net.user1.orbiter.snapshot.AccountSnapshot.prototype.getAttributes = function () { 3491 if (!this.manifest) { 3492 return null; 3493 } 3494 return this.manifest.persistentAttributes.getAll(); 3495 }; 3496 3497 net.user1.orbiter.snapshot.AccountSnapshot.prototype.getUserID = function () { 3498 if (!this.manifest) { 3499 return null; 3500 } 3501 return this.manifest.userID; 3502 }; 3503 //============================================================================== 3504 // CLASS DECLARATION 3505 //============================================================================== 3506 /** 3507 * @class 3508 * @extends net.user1.orbiter.filters.BooleanGroup 3509 */ 3510 net.user1.orbiter.filters.AndGroup = function () { 3511 net.user1.orbiter.filters.BooleanGroup.call(this, net.user1.orbiter.filters.BooleanGroupType.AND); 3512 }; 3513 3514 //============================================================================== 3515 // INHERITANCE 3516 //============================================================================== 3517 net.user1.utils.extend(net.user1.orbiter.filters.AndGroup, net.user1.orbiter.filters.BooleanGroup); 3518 //============================================================================== 3519 // CLASS DECLARATION 3520 //============================================================================== 3521 /** 3522 * @class 3523 * @extends net.user1.orbiter.filters.AndGroup 3524 */ 3525 net.user1.orbiter.filters.Filter = function (filterType) { 3526 net.user1.orbiter.filters.AndGroup.call(this); 3527 this.filterType = filterType; 3528 }; 3529 3530 //============================================================================== 3531 // INHERITANCE 3532 //============================================================================== 3533 net.user1.utils.extend(net.user1.orbiter.filters.Filter, net.user1.orbiter.filters.AndGroup); 3534 3535 net.user1.orbiter.filters.Filter.prototype.toXMLString = function () { 3536 var s = '<f t="' + this.filterType + '">\n'; 3537 3538 var comparison; 3539 for (var i = 0; i < this.comparisons.length; i++) { 3540 comparison = this.comparisons[i]; 3541 s += comparison.toXMLString() + "\n"; 3542 } 3543 s += '</f>'; 3544 return s; 3545 }; 3546 net.user1.utils.ArrayUtil.combine = function () { 3547 var source = arguments.length == 1 ? arguments[0] : arguments; 3548 var master = []; 3549 3550 var array; 3551 var element; 3552 for (var i = 0; i < source.length; i++) { 3553 array = source[i]; 3554 if (net.user1.utils.ArrayUtil.isArray(array)) { 3555 for (var j = 0; j < array.length; j++) { 3556 element = array[j]; 3557 if (net.user1.utils.ArrayUtil.indexOf(master, element) == -1) { 3558 master.push(element); 3559 } 3560 } 3561 } 3562 } 3563 return master; 3564 }; 3565 //============================================================================== 3566 // CLASS DECLARATION 3567 //============================================================================== 3568 /** 3569 * @class 3570 */ 3571 net.user1.orbiter.Attribute = function (name, 3572 value, 3573 oldValue, 3574 scope, 3575 byClient) { 3576 /** 3577 * @field 3578 */ 3579 this.name = name; 3580 /** 3581 * @field 3582 */ 3583 this.value = value; 3584 /** 3585 * @field 3586 */ 3587 this.oldValue = oldValue; 3588 /** 3589 * @field 3590 */ 3591 this.scope = (scope == net.user1.orbiter.Tokens.GLOBAL_ATTR) || (scope == null) ? null : scope; 3592 /** 3593 * @field 3594 */ 3595 this.byClient = byClient; 3596 } 3597 3598 net.user1.orbiter.Attribute.prototype.toString = function () { 3599 return "Attribute: " + (this.scope == null ? "" : this.scope + ".") + this.name + " = " + this.value + "." + " Old value: " + this.oldValue; 3600 }; 3601 //============================================================================== 3602 // CLASS DECLARATION 3603 //============================================================================== 3604 /** @class 3605 3606 The AttributeCollection class dispatches the following events: 3607 3608 <ul class="summary"> 3609 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.UPDATE}</li> 3610 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE}</li> 3611 </ul> 3612 3613 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 3614 3615 @extends net.user1.events.EventDispatcher 3616 */ 3617 net.user1.orbiter.AttributeCollection = function () { 3618 // Call superconstructor 3619 net.user1.events.EventDispatcher.call(this); 3620 3621 this.attributes = new Object(); 3622 }; 3623 3624 //============================================================================== 3625 // INHERITANCE 3626 //============================================================================== 3627 net.user1.utils.extend(net.user1.orbiter.AttributeCollection, net.user1.events.EventDispatcher); 3628 3629 // ============================================================================= 3630 // ATTRIBUTE ASSIGNMENT 3631 // ============================================================================= 3632 /** 3633 * @private 3634 */ 3635 net.user1.orbiter.AttributeCollection.prototype.setAttribute = function (name, value, scope, byClient) { 3636 var scopeExists 3637 var attrExists; 3638 var oldVal; 3639 3640 // null scope means global scope 3641 scope = scope == null ? net.user1.orbiter.Tokens.GLOBAL_ATTR : scope; 3642 // Check if the scope and attr exist already 3643 scopeExists = this.attributes.hasOwnProperty(scope); 3644 attrExists = scopeExists ? this.attributes[scope].hasOwnProperty(name) : false; 3645 3646 // Find old value, if any 3647 if (attrExists) { 3648 oldVal = this.attributes[scope][name]; 3649 if (oldVal == value) { 3650 // Attribute value is unchanged, so abort 3651 return false; 3652 } 3653 } 3654 3655 // Make the scope record if necessary 3656 if (!scopeExists) { 3657 this.attributes[scope] = new Object(); 3658 } 3659 3660 // Set the attribute value 3661 this.attributes[scope][name] = value; 3662 3663 // Notify listeners 3664 this.fireUpdateAttribute(name, value, scope, oldVal, byClient); 3665 3666 return true; 3667 }; 3668 3669 // ============================================================================= 3670 // ATTRIBUTE DELETION 3671 // ============================================================================= 3672 /** 3673 * @private 3674 */ 3675 net.user1.orbiter.AttributeCollection.prototype.deleteAttribute = function (name, scope, byClient) { 3676 var lastAttr = true; 3677 var value; 3678 3679 // If the attribute exists... 3680 if (this.attributes.hasOwnProperty(scope) 3681 && this.attributes[scope].hasOwnProperty(name)) { 3682 value = this.attributes[scope][name]; 3683 delete this.attributes[scope][name]; 3684 // Check if this is the last attribute. If it is, remove the room scope object. 3685 for (var p in this.attributes[scope]) { 3686 lastAttr = false; 3687 break; 3688 } 3689 if (lastAttr) { 3690 delete this.attributes[scope]; 3691 } 3692 3693 // Notify listeners 3694 this.fireDeleteAttribute(name, value, scope, byClient); 3695 return true; 3696 } 3697 return false; 3698 }; 3699 3700 /** 3701 * @private 3702 */ 3703 net.user1.orbiter.AttributeCollection.prototype.clear = function () { 3704 this.attributes = new Object(); 3705 }; 3706 3707 // ============================================================================= 3708 // ATTRIBUTE RETRIEVAL 3709 // ============================================================================= 3710 3711 net.user1.orbiter.AttributeCollection.prototype.getByScope = function (scope) { 3712 var obj = new Object(); 3713 3714 if (scope == null) { 3715 for (var attrscope in this.attributes) { 3716 obj[attrscope] = new Object(); 3717 for (var attrname in this.attributes[attrscope]) { 3718 obj[attrscope][attrname] = this.attributes[attrscope][attrname]; 3719 } 3720 } 3721 } else { 3722 for (var name in this.attributes[scope]) { 3723 obj[name] = this.attributes[scope][name]; 3724 } 3725 } 3726 3727 return obj; 3728 }; 3729 3730 net.user1.orbiter.AttributeCollection.prototype.getAttributesNamesForScope = function (scope) { 3731 var names = new Array(); 3732 for (var name in this.attributes[scope]) { 3733 names.push(name); 3734 } 3735 return names; 3736 }; 3737 3738 net.user1.orbiter.AttributeCollection.prototype.getAll = function () { 3739 var attrs = new Object(); 3740 for (var attrScope in this.attributes) { 3741 for (var attrName in this.attributes[attrScope]) { 3742 attrs[attrScope == net.user1.orbiter.Tokens.GLOBAL_ATTR ? attrName : (attrScope + "." + attrName)] = this.attributes[attrScope][attrName]; 3743 } 3744 } 3745 return attrs; 3746 } 3747 3748 net.user1.orbiter.AttributeCollection.prototype.getAttribute = function (attrName, attrScope) { 3749 // Use the global scope when no scope is specified 3750 if (attrScope == null) { 3751 attrScope = net.user1.orbiter.Tokens.GLOBAL_ATTR; 3752 } 3753 3754 // Find and return the attribute. 3755 if (this.attributes.hasOwnProperty(attrScope) 3756 && this.attributes[attrScope].hasOwnProperty(attrName)) { 3757 return this.attributes[attrScope][attrName]; 3758 } else { 3759 // No attribute was found, so quit. 3760 return null; 3761 } 3762 }; 3763 3764 net.user1.orbiter.AttributeCollection.prototype.getScopes = function () { 3765 var scopes = new Array(); 3766 for (var scope in this.attributes) { 3767 scopes.push(scope); 3768 } 3769 return scopes; 3770 }; 3771 3772 // ============================================================================= 3773 // COLLECTION INSPECTION 3774 // ============================================================================= 3775 3776 net.user1.orbiter.AttributeCollection.prototype.contains = function (name, scope) { 3777 return this.attributes.hasOwnProperty(scope) ? this.attributes[scope].hasOwnProperty(name) : false; 3778 }; 3779 3780 // ============================================================================= 3781 // MERGING 3782 // ============================================================================= 3783 3784 /** 3785 * @private 3786 */ 3787 net.user1.orbiter.AttributeCollection.prototype.add = function (collection) { 3788 var scopes = collection.getScopes(); 3789 var scope; 3790 3791 var names; 3792 var name; 3793 3794 for (var i = 0; i <= scopes.length; i++) { 3795 scope = scopes[i]; 3796 names = collection.getAttributesNamesForScope(scope); 3797 for (var j = 0; j < names.length; j++) { 3798 name = names[j]; 3799 this.setAttribute(name, collection.getAttribute(name, scope), scope); 3800 } 3801 } 3802 }; 3803 3804 /** 3805 * @private 3806 */ 3807 net.user1.orbiter.AttributeCollection.prototype.synchronizeScope = function (scope, 3808 collection) { 3809 // Delete all existing attributes that are not in the new collection 3810 var names = this.getAttributesNamesForScope(scope); 3811 var name; 3812 3813 for (var i = 0; i < names.length; i++) { 3814 name = names[i]; 3815 if (!collection.contains(name, scope)) { 3816 this.deleteAttribute(name, scope); 3817 } 3818 } 3819 3820 // Set all new attributes (unchanged attributes are ignored) 3821 var names = collection.getAttributesNamesForScope(scope); 3822 for (i = 0; i < names.length; i++) { 3823 name = names[i]; 3824 this.setAttribute(name, collection.getAttribute(name, scope), scope); 3825 } 3826 }; 3827 3828 // ============================================================================= 3829 // EVENT DISPATCHING 3830 // ============================================================================= 3831 /** 3832 * @private 3833 */ 3834 net.user1.orbiter.AttributeCollection.prototype.fireUpdateAttribute = function (attrName, 3835 attrVal, 3836 attrScope, 3837 oldVal, 3838 byClient) { 3839 var changedAttr = new net.user1.orbiter.Attribute(attrName, attrVal, oldVal, attrScope, byClient); 3840 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.UPDATE, 3841 changedAttr); 3842 this.dispatchEvent(e); 3843 }; 3844 3845 /** 3846 * @private 3847 */ 3848 net.user1.orbiter.AttributeCollection.prototype.fireDeleteAttribute = function (attrName, 3849 attrValue, 3850 attrScope, 3851 byClient) { 3852 var changedAttr = new net.user1.orbiter.Attribute(attrName, null, attrValue, attrScope, byClient); 3853 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.DELETE, 3854 changedAttr); 3855 this.dispatchEvent(e); 3856 }; 3857 //============================================================================== 3858 // CLASS DECLARATION 3859 //============================================================================== 3860 /** 3861 * @class 3862 */ 3863 net.user1.orbiter.filters.AttributeComparison = function (name, 3864 value, 3865 compareType) { 3866 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 3867 throw new Error("Invalid attribute name specified for AttributeComparison: " 3868 + name); 3869 } 3870 this.name = name; 3871 this.value = value; 3872 this.compareType = compareType; 3873 }; 3874 3875 net.user1.orbiter.filters.AttributeComparison.prototype.toXMLString = function () { 3876 return '<a c="' + this.compareType + '"><n><![CDATA[' + this.name + ']]></n><v><![CDATA[' + this.value.toString() + ']]></v></a>'; 3877 }; 3878 //============================================================================== 3879 // CLASS DECLARATION 3880 //============================================================================== 3881 /** @class 3882 @extends net.user1.events.Event 3883 */ 3884 net.user1.orbiter.AttributeEvent = function (type, 3885 changedAttr, 3886 status) { 3887 net.user1.events.Event.call(this, type); 3888 3889 this.changedAttr = changedAttr; 3890 this.status = status; 3891 }; 3892 3893 //============================================================================== 3894 // INHERITANCE 3895 //============================================================================== 3896 net.user1.utils.extend(net.user1.orbiter.AttributeEvent, net.user1.events.Event); 3897 3898 //============================================================================== 3899 // STATIC VARIABLES 3900 //============================================================================== 3901 3902 /** @constant */ 3903 net.user1.orbiter.AttributeEvent.UPDATE = "UPDATE"; 3904 /** @constant */ 3905 net.user1.orbiter.AttributeEvent.DELETE = "DELETE"; 3906 /** @constant */ 3907 net.user1.orbiter.AttributeEvent.DELETE_RESULT = "DELETE_RESULT"; 3908 /** @constant */ 3909 net.user1.orbiter.AttributeEvent.SET_RESULT = "SET_RESULT"; 3910 3911 //============================================================================== 3912 // INSTANCE METHODS 3913 //============================================================================== 3914 net.user1.orbiter.AttributeEvent.prototype.getChangedAttr = function () { 3915 return this.changedAttr; 3916 } 3917 3918 net.user1.orbiter.AttributeEvent.prototype.getStatus = function () { 3919 return this.status; 3920 } 3921 3922 net.user1.orbiter.AttributeEvent.prototype.toString = function () { 3923 return "[object AttributeEvent]"; 3924 } 3925 //============================================================================== 3926 // CLASS DECLARATION 3927 //============================================================================== 3928 /** 3929 * @class 3930 * @extends net.user1.orbiter.filters.Filter 3931 */ 3932 net.user1.orbiter.filters.AttributeFilter = function () { 3933 net.user1.orbiter.filters.Filter.call(this, "A"); 3934 }; 3935 3936 3937 //============================================================================== 3938 // INHERITANCE 3939 //============================================================================== 3940 net.user1.utils.extend(net.user1.orbiter.filters.AttributeFilter, net.user1.orbiter.filters.Filter); 3941 //============================================================================== 3942 // CLASS DECLARATION 3943 //============================================================================== 3944 /** 3945 * @private 3946 */ 3947 net.user1.orbiter.AttributeManager = function (owner, 3948 messageManager, 3949 log) { 3950 // Call superconstructor 3951 net.user1.events.EventDispatcher.call(this); 3952 3953 this.attributes = null; 3954 this.owner = owner; 3955 this.messageManager = messageManager; 3956 this.log = log; 3957 this.setAttributeCollection(new net.user1.orbiter.AttributeCollection()); 3958 }; 3959 3960 //============================================================================== 3961 // INHERITANCE 3962 //============================================================================== 3963 net.user1.utils.extend(net.user1.orbiter.AttributeManager, net.user1.events.EventDispatcher); 3964 3965 //============================================================================== 3966 // DEPENDENCIES 3967 //============================================================================== 3968 3969 net.user1.orbiter.AttributeManager.prototype.getAttributeCollection = function () { 3970 return this.attributes; 3971 }; 3972 3973 net.user1.orbiter.AttributeManager.prototype.setAttributeCollection = function (value) { 3974 this.unregisterAttributeListeners(); 3975 this.attributes = value; 3976 this.registerAttributeListeners(); 3977 }; 3978 3979 //============================================================================== 3980 // SERVER-SIDE ASSIGNMENT 3981 //============================================================================== 3982 3983 net.user1.orbiter.AttributeManager.prototype.setAttribute = function (setRequest) { 3984 this.messageManager.sendUPCObject(setRequest); 3985 } 3986 3987 //============================================================================== 3988 // SERVER-SIDE DELETION 3989 //============================================================================== 3990 3991 net.user1.orbiter.AttributeManager.prototype.deleteAttribute = function (deleteRequest) { 3992 this.messageManager.sendUPCObject(deleteRequest); 3993 } 3994 3995 //============================================================================== 3996 // LOCAL RETRIEVAL 3997 //============================================================================== 3998 3999 net.user1.orbiter.AttributeManager.prototype.getAttribute = function (attrName, attrScope) { 4000 // Quit if there are no attrbutes. 4001 if (this.attributes == null) { 4002 return null; 4003 } else { 4004 return this.attributes.getAttribute(attrName, attrScope); 4005 } 4006 }; 4007 4008 net.user1.orbiter.AttributeManager.prototype.getAttributes = function () { 4009 return this.attributes.getAll(); 4010 } 4011 4012 net.user1.orbiter.AttributeManager.prototype.getAttributesByScope = function (scope) { 4013 return this.attributes.getByScope(scope); 4014 }; 4015 4016 //============================================================================== 4017 // LOCAL ASSIGNMENT 4018 //============================================================================== 4019 4020 /** 4021 * @private 4022 */ 4023 net.user1.orbiter.AttributeManager.prototype.setAttributeLocal = function (attrName, 4024 attrVal, 4025 attrScope, 4026 byClient) { 4027 var changed = this.attributes.setAttribute(attrName, attrVal, attrScope, byClient); 4028 if (!changed) { 4029 this.log.info(this.owner + " New attribute value for [" + attrName + "] matches old value. Not changed."); 4030 } 4031 }; 4032 4033 //============================================================================== 4034 // LOCAL REMOVAL 4035 //============================================================================== 4036 4037 /** 4038 * @private 4039 */ 4040 net.user1.orbiter.AttributeManager.prototype.removeAttributeLocal = function (attrName, 4041 attrScope, 4042 byClient) { 4043 var deleted = this.attributes.deleteAttribute(attrName, attrScope, byClient); 4044 if (!deleted) { 4045 this.log.info(owner + " Delete attribute failed for [" + attrName + "]. No such attribute."); 4046 } 4047 }; 4048 4049 /** 4050 * @private 4051 */ 4052 net.user1.orbiter.AttributeManager.prototype.removeAll = function () { 4053 this.attributes.clear(); 4054 } 4055 4056 //============================================================================== 4057 // EVENT REGISTRATION 4058 //============================================================================== 4059 4060 net.user1.orbiter.AttributeManager.prototype.registerAttributeListeners = function () { 4061 if (this.attributes != null) { 4062 // Can't use migrateListeners() here because we need to specify the listener priority (int.MAX_VALUE) 4063 this.attributes.addEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateAttributeListener, this, net.user1.utils.integer.MAX_VALUE); 4064 this.attributes.addEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteAttributeListener, this, net.user1.utils.integer.MAX_VALUE); 4065 } 4066 }; 4067 4068 net.user1.orbiter.AttributeManager.prototype.unregisterAttributeListeners = function () { 4069 if (this.attributes != null) { 4070 this.attributes.removeEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateAttributeListener, this); 4071 this.attributes.removeEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteAttributeListener, this); 4072 } 4073 } 4074 4075 //============================================================================== 4076 // EVENT LISTENERS 4077 //============================================================================== 4078 4079 net.user1.orbiter.AttributeManager.prototype.updateAttributeListener = function (e) { 4080 var attr = e.getChangedAttr(); 4081 4082 this.log.info(this.owner + " Setting attribute [" 4083 + ((attr.scope == null) ? "" : attr.scope + ".") 4084 + attr.name + "]. New value: [" + attr.value + "]. Old value: [" 4085 + attr.oldValue + "]."); 4086 this.owner.dispatchEvent(e); 4087 }; 4088 4089 net.user1.orbiter.AttributeManager.prototype.deleteAttributeListener = function (e) { 4090 this.owner.dispatchEvent(e); 4091 } 4092 4093 //============================================================================== 4094 // EVENT DISPATCHING 4095 //============================================================================== 4096 4097 /** 4098 * @private 4099 */ 4100 net.user1.orbiter.AttributeManager.prototype.fireSetAttributeResult = function (attrName, 4101 attrScope, 4102 status) { 4103 var attr = new net.user1.orbiter.Attribute(attrName, null, null, attrScope); 4104 4105 // Trigger event on listeners. 4106 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.SET_RESULT, 4107 attr, status); 4108 this.owner.dispatchEvent(e); 4109 }; 4110 4111 /** 4112 * @private 4113 */ 4114 net.user1.orbiter.AttributeManager.prototype.fireDeleteAttributeResult = function (attrName, 4115 attrScope, 4116 status) { 4117 var attr = new net.user1.orbiter.Attribute(attrName, null, null, attrScope); 4118 4119 // Trigger event on listeners. 4120 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.DELETE_RESULT, 4121 attr, status); 4122 this.owner.dispatchEvent(e); 4123 }; 4124 4125 // ============================================================================= 4126 // DISPOSAL 4127 // ============================================================================= 4128 4129 /** 4130 * @private 4131 */ 4132 net.user1.orbiter.AttributeManager.prototype.dispose = function () { 4133 this.messageManager = null; 4134 this.attributes = null; 4135 this.owner = null; 4136 this.log = null; 4137 }; 4138 //============================================================================== 4139 // ATTRIBUTE_OPTIONS CONSTANTS 4140 //============================================================================== 4141 /** @class 4142 @private */ 4143 net.user1.orbiter.AttributeOptions = new Object(); 4144 4145 /** @private */ 4146 net.user1.orbiter.AttributeOptions.FLAG_SHARED = 1 << 2; 4147 /** @private */ 4148 net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT = 1 << 3; 4149 /** @private */ 4150 net.user1.orbiter.AttributeOptions.FLAG_IMMUTABLE = 1 << 5; 4151 /** @private */ 4152 net.user1.orbiter.AttributeOptions.FLAG_EVALUATE = 1 << 8; 4153 //============================================================================== 4154 // CLASS DECLARATION 4155 //============================================================================== 4156 /** 4157 * @class 4158 * @extends net.user1.orbiter.snapshot.Snapshot 4159 */ 4160 net.user1.orbiter.snapshot.BannedListSnapshot = function () { 4161 // Call superconstructor 4162 net.user1.orbiter.snapshot.Snapshot.call(this); 4163 this.bannedList = null; 4164 this.method = net.user1.orbiter.UPC.GET_BANNED_LIST_SNAPSHOT; 4165 } 4166 4167 //============================================================================== 4168 // INHERITANCE 4169 //============================================================================== 4170 net.user1.utils.extend(net.user1.orbiter.snapshot.BannedListSnapshot, net.user1.orbiter.snapshot.Snapshot); 4171 4172 //============================================================================== 4173 // INSTANCE METHODS 4174 //============================================================================== 4175 /** 4176 * @private 4177 */ 4178 net.user1.orbiter.snapshot.BannedListSnapshot.prototype.setBannedList = function (value) { 4179 this.bannedList = value; 4180 }; 4181 4182 net.user1.orbiter.snapshot.BannedListSnapshot.prototype.getBannedList = function () { 4183 if (!this.bannedList) { 4184 return null; 4185 } 4186 return this.bannedList.slice(); 4187 }; 4188 //============================================================================== 4189 // CLASS DECLARATION 4190 //============================================================================== 4191 /** 4192 * @class 4193 */ 4194 net.user1.utils.CacheNode = function () { 4195 /** @field */ 4196 this.next; 4197 /** @field */ 4198 this.prev; 4199 /** @field */ 4200 this.key; 4201 /** @field */ 4202 this.value; 4203 }; 4204 //============================================================================== 4205 // CLASS DECLARATION 4206 //============================================================================== 4207 /** @class 4208 4209 The Client class dispatches the following events: 4210 4211 <ul class="summary"> 4212 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.JOIN_ROOM}</li> 4213 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.LEAVE_ROOM}</li> 4214 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE_ROOM}</li> 4215 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING_ROOM}</li> 4216 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE}</li> 4217 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING}</li> 4218 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE_RESULT}</li> 4219 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT}</li> 4220 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN}</li> 4221 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF}</li> 4222 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.SYNCHRONIZE}</li> 4223 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE}</li> 4224 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.UPDATE}</li> 4225 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.SET_RESULT}</li> 4226 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE_RESULT}</li> 4227 </ul> 4228 4229 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 4230 4231 @extends net.user1.events.EventDispatcher 4232 */ 4233 net.user1.orbiter.Client = function (clientID, 4234 clientManager, 4235 messageManager, 4236 roomManager, 4237 connectionManager, 4238 server, 4239 log) { 4240 // Call superconstructor 4241 net.user1.events.EventDispatcher.call(this); 4242 4243 this.clientID = ""; 4244 this._isSelf = false; 4245 this.account = null; 4246 this.disposed = false; 4247 4248 this.messageManager = messageManager; 4249 this.clientManager = clientManager; 4250 this.roomManager = roomManager; 4251 this.connectionManager = connectionManager; 4252 this.server = server; 4253 this.log = log; 4254 this.occupiedRoomIDs = new Array(); 4255 this.observedRoomIDs = new Array(); 4256 this.customClients = new Object(); 4257 this.attributeManager = new net.user1.orbiter.AttributeManager(this, this.messageManager, this.log); 4258 this.connectionState = net.user1.orbiter.ConnectionState.UNKNOWN; 4259 4260 this.setClientID(clientID); 4261 }; 4262 4263 //============================================================================== 4264 // INHERITANCE 4265 //============================================================================== 4266 net.user1.utils.extend(net.user1.orbiter.Client, net.user1.events.EventDispatcher); 4267 4268 //============================================================================== 4269 // STATIC VARIABLES 4270 //============================================================================== 4271 4272 /** @private */ 4273 net.user1.orbiter.Client.FLAG_ADMIN = 1 << 2; 4274 4275 // ============================================================================= 4276 // CLIENT ID 4277 // ============================================================================= 4278 net.user1.orbiter.Client.prototype.getClientID = function () { 4279 return this.clientID; 4280 }; 4281 4282 /** 4283 * @private 4284 */ 4285 net.user1.orbiter.Client.prototype.setClientID = function (id) { 4286 if (this.clientID != id) { 4287 this.clientID = id; 4288 } 4289 }; 4290 4291 net.user1.orbiter.Client.prototype.isSelf = function () { 4292 return this._isSelf; 4293 }; 4294 4295 /** 4296 * @private 4297 */ 4298 net.user1.orbiter.Client.prototype.setIsSelf = function () { 4299 this._isSelf = true; 4300 }; 4301 4302 // ============================================================================= 4303 // CONNECTION STATUS 4304 // ============================================================================= 4305 4306 net.user1.orbiter.Client.prototype.getConnectionState = function () { 4307 if (this.isSelf()) { 4308 if (this.disposed 4309 || this.clientManager.getInternalClient(this.getClientID()) == null) { 4310 return net.user1.orbiter.ConnectionState.NOT_CONNECTED; 4311 } else { 4312 return this.account != null ? this.account.getConnectionState() : this.connectionManager.getConnectionState(); 4313 } 4314 } else { 4315 if (this.connectionState != net.user1.orbiter.ConnectionState.UNKNOWN) { 4316 return this.connectionState; 4317 } else if (this.disposed 4318 || this.clientManager.getInternalClient(this.getClientID()) == null) { 4319 return net.user1.orbiter.ConnectionState.UNKNOWN; 4320 } else { 4321 return this.account != null ? this.account.getConnectionState() : net.user1.orbiter.ConnectionState.READY; 4322 } 4323 } 4324 }; 4325 4326 // Normally, this client's connection state is not assigned directly; it 4327 // it is deduced within getConnectionState(). But when Union 4328 // sends a u103, we know that this client has definitely disconnected from 4329 // the server, and this client object will never be reused, so CoreMessageListener 4330 // permanently assigns its connection state to NOT_CONNECTED. 4331 net.user1.orbiter.Client.prototype.setConnectionState = function (newState) { 4332 this.connectionState = newState; 4333 }; 4334 4335 // ============================================================================= 4336 // ROLES 4337 // ============================================================================= 4338 net.user1.orbiter.Client.prototype.isAdmin = function () { 4339 var rolesAttr = this.getAttribute(Tokens.ROLES_ATTR); 4340 var roles; 4341 if (rolesAttr != null) { 4342 return parseInt(rolesAttr) & net.user1.orbiter.Client.FLAG_ADMIN; 4343 } else { 4344 this.log.warn("[" + this.toString() + "] Could not determine admin status because the client is not synchronized."); 4345 return false; 4346 } 4347 }; 4348 4349 // ============================================================================= 4350 // OBSERVATION 4351 // ============================================================================= 4352 4353 net.user1.orbiter.Client.prototype.observe = function () { 4354 this.messageManager.sendUPC(net.user1.orbiter.UPC.OBSERVE_CLIENT, this.clientID); 4355 }; 4356 4357 net.user1.orbiter.Client.prototype.stopObserving = function () { 4358 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT, this.clientID); 4359 }; 4360 4361 // ============================================================================= 4362 // KICK / BAN 4363 // ============================================================================= 4364 4365 net.user1.orbiter.Client.prototype.kick = function () { 4366 if (this.getClientID() == null) { 4367 this.log.warn(this + " Kick attempt failed. Client not currently connected."); 4368 } 4369 this.messageManager.sendUPC(net.user1.orbiter.UPC.KICK_CLIENT, getClientID()); 4370 }; 4371 4372 net.user1.orbiter.Client.prototype.ban = function (duration, reason) { 4373 if (this.getClientID() == null) { 4374 this.log.warn(this + " Ban attempt failed. Client not currently connected."); 4375 } 4376 this.messageManager.sendUPC(net.user1.orbiter.UPC.BAN, null, getClientID(), duration.toString(), reason); 4377 }; 4378 4379 // ============================================================================= 4380 // CUSTOM CLASS MANAGEMENT 4381 // ============================================================================= 4382 4383 net.user1.orbiter.Client.prototype.setClientClass = function (scope, 4384 clientClass) { 4385 var fallbackClasses = Array.prototype.slice.call(arguments).slice(2); 4386 if (!this.isSelf()) { 4387 throw new Error("Custom client class assignment failed for : " 4388 + clientClass + ". A custom" 4389 + " class can be set for the current client (" 4390 + " i.e., ClientManager.self()) only."); 4391 } 4392 4393 fallbackClasses.unshift(clientClass); 4394 var classList = fallbackClasses.join(" "); 4395 setAttribute(Tokens.CUSTOM_CLASS_ATTR, classList, scope); 4396 }; 4397 4398 /** 4399 * @private 4400 */ 4401 net.user1.orbiter.Client.prototype.getCustomClient = function (scope) { 4402 var customClient; 4403 4404 // If the custom client already exists for the specified scope, return it. 4405 customClient = this.customClients[scope]; 4406 if (customClient != null) { 4407 return customClient; 4408 } 4409 4410 // Look for a custom class for the given scope, and create a custom client 4411 if (scope == null) { 4412 return this.setGlobalCustomClient(); 4413 } else { 4414 return this.setCustomClientForScope(scope); 4415 } 4416 }; 4417 4418 /** 4419 * @private 4420 */ 4421 net.user1.orbiter.Client.prototype.setGlobalCustomClient = function () { 4422 var defaultClientClass; 4423 var globalDefaultClientClass; 4424 var customClient; 4425 4426 // If this client has a default custom client class, use it 4427 defaultClientClass = this.getClientClass(null); 4428 if (defaultClientClass != null) { 4429 return this.createCustomClient(defaultClientClass, null); 4430 } 4431 4432 // No global class was set on the client, so check for a system-wide default 4433 globalDefaultClientClass = this.clientManager.getDefaultClientClass(); 4434 if (globalDefaultClientClass == null) { 4435 // No global custom client class exists 4436 return null; 4437 } else { 4438 // Global default class exists 4439 return this.createCustomClient(globalDefaultClientClass, null); 4440 } 4441 }; 4442 4443 /** 4444 * @private 4445 */ 4446 net.user1.orbiter.Client.prototype.setCustomClientForScope = function (scope) { 4447 var theRoom; 4448 var clientClass; 4449 var roomDefaultClientClass; 4450 var globalDefaultClientClass; 4451 4452 // If this client has a default custom client class, use it 4453 clientClass = this.getClientClass(scope); 4454 if (clientClass != null) { 4455 return this.createCustomClient(clientClass, scope); 4456 } 4457 4458 // No class was set on the client for the scope, so check for a room default 4459 theRoom = this.roomManager.getRoom(scope); 4460 if (theRoom != null) { 4461 roomDefaultClientClass = theRoom.getDefaultClientClass(); 4462 if (roomDefaultClientClass != null) { 4463 return this.createCustomClient(roomDefaultClientClass, scope); 4464 } 4465 } 4466 4467 // No class was set on the room for the scope, so check for a system-wide default 4468 // If a custom global client already exists, return it. 4469 var customClient = this.customClients[null]; 4470 if (customClient != null) { 4471 return customClient; 4472 } else { 4473 globalDefaultClientClass = this.clientManager.getDefaultClientClass(); 4474 if (globalDefaultClientClass == null) { 4475 // No global custom client class exists 4476 return null; 4477 } else { 4478 // Global default class exists 4479 return this.createCustomClient(globalDefaultClientClass, null); 4480 } 4481 } 4482 }; 4483 4484 /** 4485 * @private 4486 */ 4487 net.user1.orbiter.Client.prototype.getClientClass = function (scope) { 4488 var clientClassNames = this.getAttribute(net.user1.orbiter.Tokens.CUSTOM_CLASS_ATTR, scope); 4489 var clientClassList; 4490 4491 // Convert the custom class names to an array for processing 4492 if (clientClassNames != null) { 4493 clientClassList = clientClassNames.split(" "); 4494 } 4495 4496 // Search for a matching class definition. The first definition that's 4497 // found is returned. 4498 var className; 4499 if (clientClassList != null) { 4500 for (var i = 0; i < clientClassList.length; i++) { 4501 try { 4502 var theClass = net.user1.utils.resolveMemberExpression(className); 4503 if (!theClass instanceof Function) { 4504 this.log.debug(this.toString() + ": Definition for client class [" + className + "] is not a constructor function."); 4505 continue; 4506 } 4507 return theClass; 4508 } catch (e) { 4509 this.log.debug(this.toString() + ": No definition found for client class [" + className + "]"); 4510 continue; 4511 } 4512 } 4513 } 4514 return null; 4515 }; 4516 4517 /** 4518 * @private 4519 */ 4520 net.user1.orbiter.Client.prototype.createCustomClient = function (wrapperClass, scope) { 4521 var customClient; 4522 4523 // Wrap the client 4524 customClient = new wrapperClass(); 4525 this.customClients[scope] = customClient; 4526 4527 // Do custom client setup 4528 if (customClient instanceof CustomClient) { 4529 customClient.setClient(this); 4530 customClient.init(); 4531 return customClient; 4532 } else { 4533 this.log.debug("[CLIENT_MANAGER] Custom client class [" + wrapperClass + "] does not " 4534 + " extend CustomClient. Assuming specified class will manually " 4535 + " compose its own Client instance for client ID: " + clientID 4536 + ". See Client.setClientClass()."); 4537 return customClient; 4538 } 4539 }; 4540 4541 // ============================================================================= 4542 // ROOM MANAGEMENT 4543 // ============================================================================= 4544 4545 /** 4546 * @private 4547 */ 4548 net.user1.orbiter.Client.prototype.removeOccupiedRoomID = function (roomID) { 4549 if (this.isInRoom(roomID) && roomID != null) { 4550 this.occupiedRoomIDs.splice(net.user1.utils.ArrayUtil.indexOf(this.occupiedRoomIDs, roomID), 1); 4551 return true; 4552 } else { 4553 return false; 4554 } 4555 }; 4556 4557 /** 4558 * @private 4559 */ 4560 net.user1.orbiter.Client.prototype.removeObservedRoomID = function (roomID) { 4561 if (this.isObservingRoom(roomID) && roomID != null) { 4562 this.observedRoomIDs.splice(net.user1.utils.ArrayUtil.indexOf(this.observedRoomIDs, roomID), 1); 4563 return true; 4564 } else { 4565 return false; 4566 } 4567 }; 4568 4569 /** 4570 * @private 4571 */ 4572 net.user1.orbiter.Client.prototype.addOccupiedRoomID = function (roomID) { 4573 if (!this.isInRoom(roomID) && roomID != null) { 4574 this.log.info(this.toString() + " added occupied room ID [" + roomID + "]."); 4575 this.occupiedRoomIDs.push(roomID); 4576 } 4577 }; 4578 4579 /** 4580 * @private 4581 */ 4582 net.user1.orbiter.Client.prototype.addObservedRoomID = function (roomID) { 4583 if (!this.isObservingRoom(roomID) && roomID != null) { 4584 this.log.info("Client [" + this.getClientID() + "] added observed room ID [" + roomID + "]."); 4585 this.observedRoomIDs.push(roomID); 4586 } 4587 }; 4588 4589 net.user1.orbiter.Client.prototype.isInRoom = function (roomID) { 4590 return net.user1.utils.ArrayUtil.indexOf(this.getOccupiedRoomIDs(), roomID) != -1; 4591 }; 4592 4593 net.user1.orbiter.Client.prototype.isObservingRoom = function (roomID) { 4594 return net.user1.utils.ArrayUtil.indexOf(this.getObservedRoomIDs(), roomID) != -1; 4595 }; 4596 4597 net.user1.orbiter.Client.prototype.getOccupiedRoomIDs = function () { 4598 var ids; 4599 if (this.clientManager.isObservingClient(this.getClientID())) { 4600 // This client is under observation, so its occupiedRoomIDs array is 4601 // 100% accurate. 4602 return this.occupiedRoomIDs == null ? [] : this.occupiedRoomIDs.slice(0); 4603 } else { 4604 // This client is not under observation, so the current client can only 4605 // deduce this client's occupied room list based on its current sphere of awareness. 4606 ids = []; 4607 var knownRooms = this.roomManager.getRooms(); 4608 var numKnownRooms = knownRooms.length; 4609 var room; 4610 for (var i = 0; i < numKnownRooms; i++) { 4611 room = knownRooms[i]; 4612 if (room.clientIsInRoom(this.getClientID())) { 4613 ids.push(room.getRoomID()); 4614 } 4615 } 4616 return ids; 4617 } 4618 }; 4619 4620 net.user1.orbiter.Client.prototype.getObservedRoomIDs = function () { 4621 var ids; 4622 if (this.clientManager.isObservingClient(this.getClientID())) { 4623 // This client is under observation, so its occupiedRoomIDs array is 4624 // 100% accurate. 4625 return this.observedRoomIDs == null ? [] : this.observedRoomIDs.slice(0); 4626 } else { 4627 // This client is not under observation, so the current client can only 4628 // deduce this client's occupied room list based on its current sphere of awareness. 4629 ids = []; 4630 var knownRooms = this.roomManager.getRooms(); 4631 var numKnownRooms = knownRooms.length; 4632 var room; 4633 for (var i = 0; i < numKnownRooms; i++) { 4634 room = knownRooms[i]; 4635 if (room.clientIsObservingRoom(this.getClientID())) { 4636 ids.push(room.getRoomID()); 4637 } 4638 } 4639 return ids; 4640 } 4641 }; 4642 4643 net.user1.orbiter.Client.prototype.getUpdateLevels = function (roomID) { 4644 var levels; 4645 var levelsAttr = this.getAttribute("_UL", roomID); 4646 4647 if (levelsAttr != null) { 4648 levels = new net.user1.orbiter.UpdateLevels(); 4649 levels.fromInt(parseInt(levelsAttr)); 4650 return levels; 4651 } else { 4652 return null; 4653 } 4654 }; 4655 4656 // ============================================================================= 4657 // BUILT-IN ATTRIBUTE RETRIEVAL 4658 // ============================================================================= 4659 4660 net.user1.orbiter.Client.prototype.getIP = function () { 4661 return this.getAttribute("_IP"); 4662 }; 4663 4664 net.user1.orbiter.Client.prototype.getConnectTime = function () { 4665 var ct = this.getAttribute("_CT"); 4666 return ct == null ? NaN : parseFloat(ct); 4667 }; 4668 4669 net.user1.orbiter.Client.prototype.getPing = function () { 4670 var ping = this.getAttribute("_PING"); 4671 return ping == null ? -1 : parseInt(ping); 4672 }; 4673 4674 net.user1.orbiter.Client.prototype.getTimeOnline = function () { 4675 return this.server == null ? NaN : this.server.getServerTime() - this.getConnectTime(); 4676 }; 4677 4678 // ============================================================================= 4679 // MESSAGING 4680 // ============================================================================= 4681 4682 net.user1.orbiter.Client.prototype.sendMessage = function (messageName) { 4683 if (this.clientManager == null) { 4684 return; 4685 } 4686 // Delegate to ClientManager 4687 var rest = Array.prototype.slice.call(arguments).slice(1); 4688 var args = [messageName, 4689 [this.getClientID()], 4690 null]; 4691 this.clientManager.sendMessage.apply(this.clientManager, args.concat(rest)); 4692 }; 4693 4694 // ============================================================================= 4695 // ATTRIBUTES: PUBLIC API 4696 // ============================================================================= 4697 net.user1.orbiter.Client.prototype.setAttribute = function (attrName, 4698 attrValue, 4699 attrScope, 4700 isShared, 4701 evaluate) { 4702 attrScope = attrScope == undefined ? null : attrScope; 4703 isShared = isShared == undefined ? true : isShared; 4704 evaluate = evaluate == undefined ? false : evaluate; 4705 4706 // Create an integer to hold the attribute options. 4707 var attrOptions = (isShared ? net.user1.orbiter.AttributeOptions.FLAG_SHARED : 0) 4708 | (evaluate ? net.user1.orbiter.AttributeOptions.FLAG_EVALUATE : 0); 4709 // Make the SetClientAttr UPC first so inputs are validated 4710 var setClientAttr = new net.user1.orbiter.upc.SetClientAttr(attrName, attrValue, attrOptions, attrScope, this.getClientID()); 4711 4712 // Set the attribute locally now, unless: 4713 // -it is another client's attribute 4714 // -it is the current client's attribute, and the value has changed 4715 if (!(!this.isSelf() || evaluate)) { 4716 // Set the attribute locally 4717 this.attributeManager.setAttributeLocal(attrName, attrValue, attrScope, this); 4718 } 4719 4720 // Set the attribute on the server. 4721 this.messageManager.sendUPCObject(setClientAttr); 4722 }; 4723 4724 net.user1.orbiter.Client.prototype.deleteAttribute = function (attrName, attrScope) { 4725 var deleteRequest = new net.user1.orbiter.upc.RemoveClientAttr(this.getClientID(), null, attrName, attrScope); 4726 this.attributeManager.deleteAttribute(deleteRequest); 4727 }; 4728 4729 net.user1.orbiter.Client.prototype.getAttribute = function (attrName, attrScope) { 4730 return this.attributeManager.getAttribute(attrName, attrScope); 4731 }; 4732 4733 net.user1.orbiter.Client.prototype.getAttributes = function () { 4734 return this.attributeManager.getAttributes(); 4735 }; 4736 4737 net.user1.orbiter.Client.prototype.getAttributesByScope = function (scope) { 4738 return this.attributeManager.getAttributesByScope(scope); 4739 }; 4740 4741 // ============================================================================= 4742 // SYNCHRONIZATION 4743 // ============================================================================= 4744 4745 /** 4746 * @private 4747 */ 4748 net.user1.orbiter.Client.prototype.synchronize = function (clientManifest) { 4749 var scopes; 4750 this.synchronizeOccupiedRoomIDs(clientManifest.occupiedRoomIDs); 4751 this.synchronizeObservedRoomIDs(clientManifest.observedRoomIDs); 4752 4753 // Synchronize Client attributes 4754 scopes = clientManifest.transientAttributes.getScopes(); 4755 for (var i = scopes.length; --i >= 0;) { 4756 this.attributeManager.getAttributeCollection().synchronizeScope(scopes[i], clientManifest.transientAttributes); 4757 } 4758 // Synchronize UserAccount attributes 4759 if (this.account != null) { 4760 scopes = clientManifest.persistentAttributes.getScopes(); 4761 for (i = scopes.length; --i >= 0;) { 4762 this.account.getAttributeManager().getAttributeCollection().synchronizeScope(scopes[i], clientManifest.persistentAttributes); 4763 } 4764 } 4765 }; 4766 4767 /** 4768 * @private 4769 */ 4770 net.user1.orbiter.Client.prototype.synchronizeOccupiedRoomIDs = function (newOccupiedRoomIDs) { 4771 if (newOccupiedRoomIDs == null) { 4772 // Nothing to synchronize 4773 return; 4774 } 4775 4776 // Remove any rooms that are not in the new list 4777 var roomID; 4778 for (var i = this.occupiedRoomIDs.length; --i >= 0;) { 4779 roomID = this.occupiedRoomIDs[i]; 4780 if (net.user1.utils.ArrayUtil.indexOf(newOccupiedRoomIDs, roomID) == -1) { 4781 this.removeOccupiedRoomID(roomID); 4782 } 4783 } 4784 4785 // Add any rooms that are not in the old list (existing room IDs are ignored) 4786 for (i = newOccupiedRoomIDs.length; --i >= 0;) { 4787 roomID = newOccupiedRoomIDs[i]; 4788 this.addOccupiedRoomID(roomID); 4789 } 4790 }; 4791 4792 /** 4793 * @private 4794 */ 4795 net.user1.orbiter.Client.prototype.synchronizeObservedRoomIDs = function (newObservedRoomIDs) { 4796 if (newObservedRoomIDs == null) { 4797 // Nothing to synchronize 4798 return; 4799 } 4800 // Remove any rooms that are not in the new list 4801 var roomID; 4802 for (var i = this.observedRoomIDs.length; --i >= 0;) { 4803 roomID = this.observedRoomIDs[i]; 4804 if (net.user1.utils.ArrayUtil.indexOf(newObservedRoomIDs, roomID) == -1) { 4805 this.removeObservedRoomID(roomID); 4806 } 4807 } 4808 4809 // Add any rooms that are not in the old list (existing room IDs are ignored) 4810 for (i = newObservedRoomIDs.length; --i >= 0;) { 4811 roomID = newObservedRoomIDs[i]; 4812 this.addObservedRoomID(roomID); 4813 } 4814 }; 4815 4816 // ============================================================================= 4817 // DEPENDENCIES 4818 // ============================================================================= 4819 4820 /** 4821 * @private 4822 */ 4823 net.user1.orbiter.Client.prototype.getAttributeManager = function () { 4824 return this.attributeManager; 4825 }; 4826 4827 net.user1.orbiter.Client.prototype.getClientManager = function () { 4828 return this.clientManager; 4829 }; 4830 4831 net.user1.orbiter.Client.prototype.getAccount = function () { 4832 return this.account; 4833 }; 4834 4835 /** 4836 * @private 4837 */ 4838 net.user1.orbiter.Client.prototype.setAccount = function (value) { 4839 if (value == null) { 4840 this.account = null; 4841 } else { 4842 if (this.account != value) { 4843 this.account = value; 4844 this.account.setClient(this); 4845 } 4846 } 4847 }; 4848 4849 // ============================================================================= 4850 // TOSTRING 4851 // ============================================================================= 4852 4853 net.user1.orbiter.Client.prototype.toString = function () { 4854 return "[CLIENT clientID: " + this.getClientID() + ", userID: " + (this.account == null ? "" : this.account.getUserID()) + "]"; 4855 }; 4856 4857 // ============================================================================= 4858 // EVENT DISPATCHING 4859 // ============================================================================= 4860 4861 /** 4862 * @private 4863 */ 4864 net.user1.orbiter.Client.prototype.fireJoinRoom = function (room, roomID) { 4865 this.log.debug(this + " triggering ClientEvent.JOIN_ROOM event."); 4866 // Trigger event on listeners. 4867 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.JOIN_ROOM, 4868 null, room, roomID, this); 4869 this.dispatchEvent(e); 4870 }; 4871 4872 /** 4873 * @private 4874 */ 4875 net.user1.orbiter.Client.prototype.fireLeaveRoom = function (room, roomID) { 4876 this.log.debug(this + " triggering ClientEvent.LEAVE_ROOM event."); 4877 // Trigger event on listeners. 4878 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.LEAVE_ROOM, 4879 null, room, roomID, this); 4880 this.dispatchEvent(e); 4881 }; 4882 4883 /** 4884 * @private 4885 */ 4886 net.user1.orbiter.Client.prototype.fireObserveRoom = function (room, roomID) { 4887 this.log.debug(this + " triggering ClientEvent.OBSERVE_ROOM event."); 4888 // Trigger event on listeners. 4889 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE_ROOM, 4890 null, room, roomID, this); 4891 this.dispatchEvent(e); 4892 }; 4893 4894 /** 4895 * @private 4896 */ 4897 net.user1.orbiter.Client.prototype.fireStopObservingRoom = function (room, roomID) { 4898 this.log.debug(this + " triggering ClientEvent.STOP_OBSERVING_ROOM event."); 4899 // Trigger event on listeners. 4900 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING_ROOM, 4901 null, room, roomID, this); 4902 this.dispatchEvent(e); 4903 }; 4904 4905 /** 4906 * @private 4907 */ 4908 net.user1.orbiter.Client.prototype.fireObserve = function () { 4909 // Trigger event on listeners. 4910 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE, null, null, null, this); 4911 this.dispatchEvent(e); 4912 }; 4913 4914 /** 4915 * @private 4916 */ 4917 net.user1.orbiter.Client.prototype.fireStopObserving = function () { 4918 // Trigger event on listeners. 4919 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING, null, null, null, this); 4920 this.dispatchEvent(e); 4921 }; 4922 4923 /** 4924 * @private 4925 */ 4926 net.user1.orbiter.Client.prototype.fireObserveResult = function (status) { 4927 // Trigger event on listeners. 4928 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE_RESULT, 4929 null, null, null, this, status); 4930 this.dispatchEvent(e); 4931 }; 4932 4933 /** 4934 * @private 4935 */ 4936 net.user1.orbiter.Client.prototype.fireStopObservingResult = function (status) { 4937 // Trigger event on listeners. 4938 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT, 4939 null, null, null, this, status); 4940 this.dispatchEvent(e); 4941 }; 4942 4943 /** 4944 * @private 4945 */ 4946 net.user1.orbiter.Client.prototype.fireLogin = function () { 4947 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN, 4948 net.user1.orbiter.Status.SUCCESS, this.getAccount().getUserID(), this.getClientID()); 4949 this.dispatchEvent(e); 4950 }; 4951 4952 /** 4953 * @private 4954 */ 4955 net.user1.orbiter.Client.prototype.fireLogoff = function (userID) { 4956 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF, 4957 net.user1.orbiter.Status.SUCCESS, userID, this.getClientID()); 4958 this.dispatchEvent(e); 4959 }; 4960 4961 /** 4962 * @private 4963 */ 4964 net.user1.orbiter.Client.prototype.fireSynchronize = function () { 4965 // Trigger event on listeners. 4966 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.SYNCHRONIZE, null, null, null, this); 4967 this.dispatchEvent(e); 4968 }; 4969 4970 // ============================================================================= 4971 // DISPOSAL 4972 // ============================================================================= 4973 4974 net.user1.orbiter.Client.prototype.dispose = function () { 4975 this.occupiedRoomIDs = null; 4976 this.attributeManager.dispose(); 4977 this.attributeManager = null; 4978 this.clientID = null; 4979 this.log = null; 4980 this.account = null; 4981 this.customClients = null; 4982 this.messageManager = null; 4983 this.clientManager = null; 4984 this.roomManager = null; 4985 this.server = null; 4986 this.disposed = true; 4987 }; 4988 //============================================================================== 4989 // CLASS DECLARATION 4990 //============================================================================== 4991 /** 4992 * @class 4993 * @extends net.user1.orbiter.snapshot.Snapshot 4994 */ 4995 net.user1.orbiter.snapshot.ClientCountSnapshot = function () { 4996 // Call superconstructor 4997 net.user1.orbiter.snapshot.Snapshot.call(this); 4998 this.count = 0; 4999 this.method = net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT; 5000 this.hasStatus = true; 5001 }; 5002 5003 //============================================================================== 5004 // INHERITANCE 5005 //============================================================================== 5006 net.user1.utils.extend(net.user1.orbiter.snapshot.ClientCountSnapshot, net.user1.orbiter.snapshot.Snapshot); 5007 5008 //============================================================================== 5009 // INSTANCE METHODS 5010 //============================================================================== 5011 /** 5012 * @private 5013 */ 5014 net.user1.orbiter.snapshot.ClientCountSnapshot.prototype.setCount = function (value) { 5015 this.count = value; 5016 }; 5017 5018 net.user1.orbiter.snapshot.ClientCountSnapshot.prototype.getCount = function () { 5019 return this.count; 5020 }; 5021 //============================================================================== 5022 // CLASS DECLARATION 5023 //============================================================================== 5024 /** @class 5025 @extends net.user1.events.Event 5026 */ 5027 net.user1.orbiter.ClientEvent = function (type, 5028 changedAttr, 5029 room, 5030 roomID, 5031 client, 5032 status, 5033 clientID) { 5034 net.user1.events.Event.call(this, type); 5035 5036 this.changedAttr = changedAttr; 5037 this.room = room; 5038 this.roomID = roomID; 5039 this.client = client; 5040 this.status = status; 5041 this.clientID = clientID; 5042 }; 5043 5044 //============================================================================== 5045 // INHERITANCE 5046 //============================================================================== 5047 net.user1.utils.extend(net.user1.orbiter.ClientEvent, net.user1.events.Event); 5048 5049 //============================================================================== 5050 // STATIC VARIABLES 5051 //============================================================================== 5052 /** @constant */ 5053 net.user1.orbiter.ClientEvent.JOIN_ROOM = "JOIN_ROOM"; 5054 /** @constant */ 5055 net.user1.orbiter.ClientEvent.LEAVE_ROOM = "LEAVE_ROOM"; 5056 /** @constant */ 5057 net.user1.orbiter.ClientEvent.OBSERVE_ROOM = "OBSERVE_ROOM"; 5058 /** @constant */ 5059 net.user1.orbiter.ClientEvent.STOP_OBSERVING_ROOM = "STOP_OBSERVING_ROOM"; 5060 /** @constant */ 5061 net.user1.orbiter.ClientEvent.OBSERVE = "OBSERVE"; 5062 /** @constant */ 5063 net.user1.orbiter.ClientEvent.STOP_OBSERVING = "STOP_OBSERVING"; 5064 /** @constant */ 5065 net.user1.orbiter.ClientEvent.OBSERVE_RESULT = "OBSERVE_RESULT"; 5066 /** @constant */ 5067 net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT = "STOP_OBSERVING_RESULT"; 5068 /** @constant */ 5069 net.user1.orbiter.ClientEvent.SYNCHRONIZE = "SYNCHRONIZE"; 5070 5071 net.user1.orbiter.ClientEvent.prototype.getClient = function () { 5072 return this.client; 5073 }; 5074 5075 net.user1.orbiter.ClientEvent.prototype.getClientID = function () { 5076 if (this.client != null) { 5077 return this.client.getClientID(); 5078 } else { 5079 return this.clientID; 5080 } 5081 }; 5082 5083 net.user1.orbiter.ClientEvent.prototype.getRoom = function () { 5084 return this.room; 5085 }; 5086 5087 net.user1.orbiter.ClientEvent.prototype.getRoomID = function () { 5088 return this.roomID; 5089 } 5090 5091 net.user1.orbiter.ClientEvent.prototype.getStatus = function () { 5092 return this.status; 5093 }; 5094 5095 net.user1.orbiter.ClientEvent.prototype.toString = function () { 5096 return "[object ClientEvent]"; 5097 }; 5098 //============================================================================== 5099 // CLASS DECLARATION 5100 //============================================================================== 5101 /** 5102 * @class 5103 * @extends net.user1.orbiter.snapshot.Snapshot 5104 */ 5105 net.user1.orbiter.snapshot.ClientListSnapshot = function () { 5106 // Call superconstructor 5107 net.user1.orbiter.snapshot.Snapshot.call(this); 5108 this.clientList; 5109 this.method = net.user1.orbiter.UPC.GET_CLIENTLIST_SNAPSHOT; 5110 }; 5111 5112 //============================================================================== 5113 // INHERITANCE 5114 //============================================================================== 5115 net.user1.utils.extend(net.user1.orbiter.snapshot.ClientListSnapshot, net.user1.orbiter.snapshot.Snapshot); 5116 5117 //============================================================================== 5118 // INSTANCE METHODS 5119 //============================================================================== 5120 /** 5121 * @private 5122 */ 5123 net.user1.orbiter.snapshot.ClientListSnapshot.prototype.setClientList = function (value) { 5124 this.clientList = value; 5125 }; 5126 5127 net.user1.orbiter.snapshot.ClientListSnapshot.prototype.getClientList = function () { 5128 if (!this.clientList) { 5129 return null; 5130 } 5131 return this.clientList.slice(); 5132 } 5133 //============================================================================== 5134 // CLASS DECLARATION 5135 //============================================================================== 5136 /** @class 5137 5138 The ClientManager class dispatches the following events: 5139 5140 <ul class="summary"> 5141 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.CREATE_ACCOUNT_RESULT}</li> 5142 5143 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE}</li> 5144 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING}</li> 5145 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED}</li> 5146 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED}</li> 5147 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT}</li> 5148 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT}</li> 5149 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE_RESULT}</li> 5150 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT}</li> 5151 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.KICK_RESULT}</li> 5152 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.BAN_RESULT}</li> 5153 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.UNBAN_RESULT}</li> 5154 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT}</li> 5155 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT}</li> 5156 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED}</li> 5157 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED}</li> 5158 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST}</li> 5159 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE}</li> 5160 </ul> 5161 5162 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 5163 5164 @extends net.user1.events.EventDispatcher 5165 */ 5166 net.user1.orbiter.ClientManager = function (roomManager, 5167 accountManager, 5168 connectionManager, 5169 messageManager, 5170 server, 5171 log) { 5172 // Call superconstructor 5173 net.user1.events.EventDispatcher.call(this); 5174 5175 this.selfReference = null; 5176 this.defaultClientClass = null; 5177 this.lifetimeClientsRequested = 0; 5178 5179 this._isWatchingForClients; 5180 this._isWatchingForUsers; 5181 this._isWatchingForBannedAddresses; 5182 5183 this.watchedClients = new net.user1.orbiter.ClientSet(); 5184 this.observedClients = new net.user1.orbiter.ClientSet(); 5185 this.bannedAddresses = []; 5186 this.clientCache = new net.user1.utils.LRUCache(5000); 5187 5188 this.roomManager = roomManager; 5189 this.accountManager = accountManager; 5190 this.connectionManager = connectionManager; 5191 this.messageManager = messageManager; 5192 this.server = server; 5193 this.log = log; 5194 }; 5195 5196 //============================================================================== 5197 // INHERITANCE 5198 //============================================================================== 5199 net.user1.utils.extend(net.user1.orbiter.ClientManager, net.user1.events.EventDispatcher); 5200 5201 //============================================================================== 5202 // CLIENT OBJECT CREATION AND ACCESS 5203 //============================================================================== 5204 5205 /** 5206 * @private 5207 */ 5208 net.user1.orbiter.ClientManager.prototype.requestClient = function (clientID) { 5209 var client; 5210 5211 if (clientID == null || clientID === "") { 5212 throw new Error("[CLIENT_MANAGER] requestClient() called with empty clientID."); 5213 } 5214 5215 client = this.getInternalClient(clientID); 5216 5217 // If the client isn't already known 5218 if (client === null) { 5219 client = new net.user1.orbiter.Client(clientID, this, this.messageManager, this.roomManager, this.connectionManager, this.server, this.log); 5220 this.lifetimeClientsRequested++; 5221 this.clientCache.put(clientID, client); 5222 } 5223 5224 return client; 5225 } 5226 5227 net.user1.orbiter.ClientManager.prototype.getClient = function (clientID, scope) { 5228 var theClient; 5229 var theCustomClient; 5230 5231 if (clientID === "" || clientID == null) { 5232 throw new Error("ClientManager.getClient() failed. Client ID must not be null or the" + 5233 " empty string."); 5234 } 5235 5236 theClient = this.getInternalClient(clientID); 5237 if (theClient === null) { 5238 this.log.debug("[CLIENT_MANAGER] getClient() called for unknown client ID [" 5239 + clientID + "]."); 5240 return null; 5241 } else { 5242 theCustomClient = theClient.getCustomClient(scope); 5243 return theCustomClient === null ? theClient : theCustomClient; 5244 } 5245 }; 5246 5247 net.user1.orbiter.ClientManager.prototype.getClients = function () { 5248 // Get all internal clients 5249 var clients = this.getInternalClients(); 5250 var clientsList = new Array(); 5251 var customClient; 5252 5253 // Replace internal clients with custom clients where available 5254 var client; 5255 for (var clientID in clients) { 5256 client = clients[clientID]; 5257 customClient = client.getCustomClient(null); 5258 if (customClient != null) { 5259 clientsList.push(customClient); 5260 } else { 5261 clientsList.push(client); 5262 } 5263 } 5264 return clientsList; 5265 } 5266 5267 net.user1.orbiter.ClientManager.prototype.getInternalClients = function () { 5268 var clients = net.user1.utils.ObjectUtil.combine(this.roomManager.getAllClients(), 5269 this.accountManager.getClientsForObservedAccounts(), 5270 this.observedClients.getAll(), 5271 this.watchedClients.getAll()); 5272 if (this.selfReference != null) { 5273 clients[this.selfReference.getClientID()] = this.selfReference; 5274 } 5275 return clients; 5276 }; 5277 5278 net.user1.orbiter.ClientManager.prototype.getInternalClient = function (clientID) { 5279 var theClient; 5280 5281 // Error checking 5282 if (clientID === "" || clientID == null) { 5283 throw new Error("[CLIENT_MANAGER] this.getInternalClient() failed. Client ID must not be null or the" + 5284 " empty string."); 5285 } 5286 5287 theClient = this.clientCache.get(clientID); 5288 5289 if (theClient != null) { 5290 return theClient; 5291 } else { 5292 // Find the client... 5293 5294 // Look in rooms 5295 var clients = this.roomManager.getAllClients(); 5296 theClient = clients[clientID]; 5297 if (theClient != null) { 5298 this.clientCache.put(clientID, theClient); 5299 return theClient; 5300 } 5301 5302 // Look in observed accounts 5303 clients = this.accountManager.getClientsForObservedAccounts(); 5304 theClient = clients[clientID]; 5305 if (theClient != null) { 5306 this.clientCache.put(clientID, theClient); 5307 return theClient; 5308 } 5309 5310 // Look in observed clients 5311 theClient = this.observedClients.getByClientID(clientID); 5312 if (theClient != null) { 5313 this.clientCache.put(clientID, theClient); 5314 return theClient; 5315 } 5316 5317 // Look in watched clients 5318 theClient = this.watchedClients.getByClientID(clientID); 5319 if (theClient != null) { 5320 this.clientCache.put(clientID, theClient); 5321 return theClient; 5322 } 5323 } 5324 5325 // Client not found 5326 return null; 5327 } 5328 5329 net.user1.orbiter.ClientManager.prototype.getClientByUserID = function (userID, scope) { 5330 var theClient; 5331 var theCustomClient; 5332 var account; 5333 5334 if (userID === "" || userID == null) { 5335 throw new Error("ClientManager.getClientByUserID() failed. User ID must not be null or the" + 5336 " empty string."); 5337 } 5338 5339 // Search for the client in all known clients 5340 var client; 5341 var clients = this.getInternalClients(); 5342 for (var clientID in clients) { 5343 client = clients[clientID]; 5344 account = client.getAccount(); 5345 if (account != null && account.getUserID() === userID) { 5346 theClient = client; 5347 break; 5348 } 5349 } 5350 5351 if (theClient === null) { 5352 this.log.debug("[CLIENT_MANAGER] getClientByUserID() called for unknown user ID [" 5353 + userID + "]."); 5354 return null; 5355 } else { 5356 theCustomClient = theClient.getCustomClient(scope); 5357 return theCustomClient === null ? theClient : theCustomClient; 5358 } 5359 }; 5360 5361 net.user1.orbiter.ClientManager.prototype.getClientByAttribute = function (attributeName, 5362 attributeValue, 5363 attributeScope, 5364 roomScope) { 5365 var theCustomClient; 5366 5367 // Validate 5368 if (attributeName == null || attributeName === "") { 5369 return null; 5370 } 5371 5372 // Search for the client in all known clients 5373 var client; 5374 var clients = this.getInternalClients(); 5375 for (var clientID in clients) { 5376 client = clients[clientID]; 5377 if (client.getAttribute(attributeName, attributeScope) 5378 === attributeValue) { 5379 theCustomClient = client.getCustomClient(roomScope); 5380 return theCustomClient === null ? client : theCustomClient; 5381 } 5382 } 5383 return null; 5384 }; 5385 5386 net.user1.orbiter.ClientManager.prototype.clientIsKnown = function (clientID) { 5387 return this.getInternalClients()[clientID] !== null; 5388 }; 5389 5390 // ============================================================================= 5391 // WATCHED CLIENTS 5392 // ============================================================================= 5393 5394 net.user1.orbiter.ClientManager.prototype.watchForClients = function () { 5395 this.messageManager.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_CLIENTS); 5396 }; 5397 5398 net.user1.orbiter.ClientManager.prototype.stopWatchingForClients = function () { 5399 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS); 5400 }; 5401 5402 net.user1.orbiter.ClientManager.prototype.isWatchingForClients = function () { 5403 return this._isWatchingForClients; 5404 }; 5405 5406 net.user1.orbiter.ClientManager.prototype.hasWatchedClient = function (clientID) { 5407 return this.watchedClients.containsClientID(clientID); 5408 }; 5409 5410 /** 5411 * @private 5412 */ 5413 net.user1.orbiter.ClientManager.prototype.setIsWatchingForClients = function (value) { 5414 this._isWatchingForClients = value; 5415 }; 5416 5417 /** 5418 * @private 5419 */ 5420 net.user1.orbiter.ClientManager.prototype.addWatchedClient = function (client) { 5421 var customClient = client.getCustomClient(null); 5422 this.watchedClients.add(client); 5423 this.fireClientConnected(customClient === null ? client : customClient); 5424 }; 5425 5426 /** 5427 * @private 5428 */ 5429 net.user1.orbiter.ClientManager.prototype.removeWatchedClient = function (clientID) { 5430 this.watchedClients.removeByClientID(clientID); 5431 }; 5432 5433 /** 5434 * @private 5435 */ 5436 net.user1.orbiter.ClientManager.prototype.removeAllWatchedClients = function () { 5437 this.watchedClients.removeAll(); 5438 }; 5439 5440 /** 5441 * @private 5442 */ 5443 net.user1.orbiter.ClientManager.prototype.deserializeWatchedClients = function (ids) { 5444 var idList = ids.split(net.user1.orbiter.Tokens.RS); 5445 var idHash = new Object(); 5446 var localClients = this.watchedClients.getAll(); 5447 var len = idList.length; 5448 var theClient; 5449 var accountID; 5450 5451 // Client list received, so set isWatchingForClients now, otherwise, code 5452 // with side-effects may take action against the clients being added 5453 this.setIsWatchingForClients(true); 5454 5455 // Generate a hash of clientID keys to accountID values 5456 for (var i = len-2; i >= 0; i-=2) { 5457 idHash[idList[i]] = idList[i+1]; 5458 } 5459 5460 // Remove all local clients that are not in the new list from the server 5461 var clientStillExists; 5462 for (var clientID in localClients) { 5463 if (!idHash.hasOwnProperty(clientID)) { 5464 // For best performance, use direct access rather than removeByClientID() 5465 delete localClients[clientID]; 5466 } 5467 } 5468 5469 // Add all new clients that are not in the local set 5470 for (clientID in idHash) { 5471 if (clientID != "") { 5472 if (!this.watchedClients.containsClientID(clientID)) { 5473 theClient = this.requestClient(clientID); 5474 accountID = idHash[clientID]; 5475 if (accountID != "") { 5476 theClient.setAccount(this.accountManager.requestAccount(accountID)); 5477 } 5478 this.addWatchedClient(theClient); 5479 } 5480 } else { 5481 throw new Error("[CLIENT_MANAGER] Received empty client id in client list (u101)."); 5482 } 5483 } 5484 5485 this.fireSynchronize(); 5486 }; 5487 5488 // ============================================================================= 5489 // OBSERVED CLIENTS 5490 // ============================================================================= 5491 5492 net.user1.orbiter.ClientManager.prototype.observeClient = function (clientID) { 5493 this.messageManager.sendUPC(net.user1.orbiter.UPC.OBSERVE_CLIENT, clientID); 5494 }; 5495 5496 net.user1.orbiter.ClientManager.prototype.isObservingClient = function (clientID) { 5497 return this.observedClients.containsClientID(clientID); 5498 } 5499 5500 /** 5501 * @private 5502 */ 5503 net.user1.orbiter.ClientManager.prototype.addObservedClient = function (client) { 5504 var customClient = client.getCustomClient(null); 5505 this.observedClients.add(client); 5506 this.fireObserveClient(customClient === null ? client : customClient); 5507 }; 5508 5509 /** 5510 * @private 5511 */ 5512 net.user1.orbiter.ClientManager.prototype.removeObservedClient = function (clientID) { 5513 var client = this.observedClients.removeByClientID(clientID); 5514 var customClient; 5515 if (client != null) { 5516 customClient = client.getCustomClient(null); 5517 this.fireStopObservingClient(customClient === null ? client : customClient); 5518 } 5519 }; 5520 5521 /** 5522 * @private 5523 */ 5524 net.user1.orbiter.ClientManager.prototype.removeAllObservedClients = function () { 5525 this.observedClients.removeAll(); 5526 }; 5527 5528 //============================================================================== 5529 // CLIENT ATTRIBUTE ACCESS 5530 //============================================================================== 5531 5532 net.user1.orbiter.ClientManager.prototype.getAttributeForClients = function (clientIDs, 5533 attrName, 5534 attrScope) { 5535 var clientAttributes = new Array(); 5536 var thisClient; 5537 5538 for (var i = 0; i < clientIDs.length; i++) { 5539 thisClient = this.getInternalClient(clientIDs[i]); 5540 if (thisClient != null) { 5541 clientAttributes.push({clientID: clientIDs[i], 5542 value: thisClient.getAttribute(attrName, attrScope)}); 5543 } else { 5544 this.log.debug("[CLIENT_MANAGER] Attribute retrieval failed during " 5545 + " getAttributeForClients(). Unknown client ID [" + clientIDs[i] + "]"); 5546 } 5547 } 5548 return clientAttributes; 5549 }; 5550 5551 //============================================================================== 5552 // CUSTOM CLIENT MANAGEMENT 5553 //============================================================================== 5554 5555 net.user1.orbiter.ClientManager.prototype.setDefaultClientClass = function (defaultClass) { 5556 this.defaultClientClass = defaultClass; 5557 }; 5558 5559 net.user1.orbiter.ClientManager.prototype.getDefaultClientClass = function () { 5560 return this.defaultClientClass; 5561 }; 5562 5563 //============================================================================== 5564 // CURRENT CLIENT ASSIGNMENT AND ACCESS 5565 //============================================================================== 5566 5567 /** 5568 * @private 5569 */ 5570 net.user1.orbiter.ClientManager.prototype.self = function () { 5571 return this.selfReference; 5572 } 5573 5574 /** 5575 * @private 5576 */ 5577 net.user1.orbiter.ClientManager.prototype.setSelf = function (client) { 5578 this.selfReference = client; 5579 client.setIsSelf(); 5580 } 5581 5582 //============================================================================== 5583 // CLIENT MESSAGING 5584 //============================================================================== 5585 5586 net.user1.orbiter.ClientManager.prototype.sendMessage = function (messageName, 5587 clientIDs, 5588 filters) { 5589 var rest = Array.prototype.slice.call(arguments).slice(3); 5590 5591 // An array of arguments to send to the server. 5592 var args; 5593 5594 // Can't continue without a valid methodName. 5595 if (messageName == null || messageName == "") { 5596 this.log.warn("[CLIENT_MANAGER] sendMessage() failed. No messageName supplied."); 5597 return; 5598 } 5599 5600 // Send the UPC. 5601 args = [net.user1.orbiter.UPC.SEND_MESSAGE_TO_CLIENTS, 5602 messageName, 5603 clientIDs.join(net.user1.orbiter.Tokens.RS), 5604 filters != null ? filters.toXMLString() : ""]; 5605 this.messageManager.sendUPC.apply(this.messageManager, args.concat(rest)); 5606 }; 5607 5608 // ============================================================================= 5609 // BAN / UNBAN / KICK 5610 // ============================================================================= 5611 5612 net.user1.orbiter.ClientManager.prototype.ban = function (address, duration, reason) { 5613 this.messageManager.sendUPC(net.user1.orbiter.UPC.BAN, address, null, duration.toString(), reason); 5614 }; 5615 5616 net.user1.orbiter.ClientManager.prototype.unban = function (address) { 5617 this.messageManager.sendUPC(net.user1.orbiter.UPC.UNBAN, address); 5618 }; 5619 5620 net.user1.orbiter.ClientManager.prototype.kickClient = function (clientID) { 5621 if (clientID == null || clientID == "") { 5622 this.log.warn("[CLIENT_MANAGER] Kick attempt failed. No clientID supplied."); 5623 } 5624 this.messageManager.sendUPC(net.user1.orbiter.UPC.KICK_CLIENT, clientID); 5625 } 5626 5627 // ============================================================================= 5628 // WATCH BANNED ADDRESSES 5629 // ============================================================================= 5630 5631 net.user1.orbiter.ClientManager.prototype.watchForBannedAddresses = function () { 5632 this.messageManager.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES); 5633 }; 5634 5635 net.user1.orbiter.ClientManager.prototype.stopWatchingForBannedAddresses = function () { 5636 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES); 5637 }; 5638 5639 /** 5640 * @private 5641 */ 5642 net.user1.orbiter.ClientManager.prototype.setWatchedBannedAddresses = function (bannedList) { 5643 this.bannedAddresses = bannedList; 5644 this.fireSynchronizeBanlist(); 5645 }; 5646 5647 /** 5648 * @private 5649 */ 5650 net.user1.orbiter.ClientManager.prototype.addWatchedBannedAddress = function (address) { 5651 this.bannedAddresses.push(address); 5652 this.fireAddressBanned(address); 5653 }; 5654 5655 /** 5656 * @private 5657 */ 5658 net.user1.orbiter.ClientManager.prototype.removeWatchedBannedAddress = function (address) { 5659 var idx = net.user1.util.ArrayUtil.indexOf(bannedAddresses, address); 5660 if (idx === -1) { 5661 this.log.warn("[CLIENT_MANAGER] Request to remove watched banned address failed." 5662 + " Address not found."); 5663 } 5664 this.bannedAddresses.splice(idx, 1); 5665 this.fireAddressUnbanned(address); 5666 } 5667 5668 /** 5669 * @private 5670 */ 5671 net.user1.orbiter.ClientManager.prototype.setIsWatchingForBannedAddresses = function (value) { 5672 this._isWatchingForBannedAddresses = value; 5673 }; 5674 5675 net.user1.orbiter.ClientManager.prototype.isWatchingForBannedAddresses = function () { 5676 return this._isWatchingForBannedAddresses; 5677 }; 5678 5679 net.user1.orbiter.ClientManager.prototype.getBannedAddresses = function () { 5680 return this.bannedAddresses.slice(0); 5681 }; 5682 5683 //============================================================================== 5684 // STATISTICS 5685 //============================================================================== 5686 5687 net.user1.orbiter.ClientManager.prototype.getLifetimeNumClientsKnown = function () { 5688 // -1 for each "ready" state the connection has achieved because we don't 5689 // count the current client ("self") 5690 return this.lifetimeClientsRequested-this.connectionManager.getReadyCount(); 5691 }; 5692 5693 net.user1.orbiter.ClientManager.prototype.getNumClients = function () { 5694 return net.user1.utils.ObjectUtil.length(this.getInternalClients()); 5695 }; 5696 5697 net.user1.orbiter.ClientManager.prototype.getNumClientsOnServer = function () { 5698 return this.watchedClients.length(); 5699 } 5700 5701 //============================================================================== 5702 // EVENT DISPATCHING 5703 //============================================================================== 5704 5705 /** 5706 * @private 5707 */ 5708 net.user1.orbiter.ClientManager.prototype.fireObserveClient = function (client) { 5709 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE, null, null, null, client); 5710 this.dispatchEvent(e); 5711 }; 5712 5713 /** 5714 * @private 5715 */ 5716 net.user1.orbiter.ClientManager.prototype.fireStopObservingClient = function (client) { 5717 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING, null, null, null, client); 5718 this.dispatchEvent(e); 5719 }; 5720 5721 /** 5722 * @private 5723 */ 5724 net.user1.orbiter.ClientManager.prototype.fireClientConnected = function (client) { 5725 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED, 5726 client.getClientID(), client)); 5727 }; 5728 5729 /** 5730 * @private 5731 */ 5732 net.user1.orbiter.ClientManager.prototype.fireClientDisconnected = function (client) { 5733 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED, 5734 client.getClientID(), client)); 5735 }; 5736 5737 /** 5738 * @private 5739 */ 5740 net.user1.orbiter.ClientManager.prototype.fireStopWatchingForClientsResult = function (status) { 5741 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT, 5742 null, null, null, status)); 5743 }; 5744 5745 /** 5746 * @private 5747 */ 5748 net.user1.orbiter.ClientManager.prototype.fireWatchForClientsResult = function (status) { 5749 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT, 5750 null, null, null, status)); 5751 }; 5752 5753 /** 5754 * @private 5755 */ 5756 net.user1.orbiter.ClientManager.prototype.fireObserveClientResult = function (clientID, status) { 5757 this.dispatchEvent(new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE_RESULT, 5758 null, null, null, this.getClient(clientID), status, clientID)); 5759 }; 5760 5761 /** 5762 * @private 5763 */ 5764 net.user1.orbiter.ClientManager.prototype.fireStopObservingClientResult = function (clientID, status) { 5765 this.dispatchEvent(new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT, 5766 null, null, null, this.getClient(clientID), status, clientID)); 5767 }; 5768 5769 /** 5770 * @private 5771 */ 5772 net.user1.orbiter.ClientManager.prototype.fireKickClientResult = function (clientID, status) { 5773 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.KICK_RESULT, 5774 clientID, null, null, status)); 5775 }; 5776 5777 /** 5778 * @private 5779 */ 5780 net.user1.orbiter.ClientManager.prototype.fireBanClientResult = function (address, clientID, status) { 5781 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.BAN_RESULT, 5782 clientID, null, address, status)); 5783 }; 5784 5785 /** 5786 * @private 5787 */ 5788 net.user1.orbiter.ClientManager.prototype.fireUnbanClientResult = function (address, status) { 5789 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.UNBAN_RESULT, 5790 null, null, address, status)); 5791 }; 5792 5793 /** 5794 * @private 5795 */ 5796 net.user1.orbiter.ClientManager.prototype.fireWatchForBannedAddressesResult = function (status) { 5797 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT, 5798 null, null, null, status)); 5799 }; 5800 5801 /** 5802 * @private 5803 */ 5804 net.user1.orbiter.ClientManager.prototype.fireStopWatchingForBannedAddressesResult = function (status) { 5805 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT, 5806 null, null, null, status)); 5807 }; 5808 5809 /** 5810 * @private 5811 */ 5812 net.user1.orbiter.ClientManager.prototype.fireAddressBanned = function (address) { 5813 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED, 5814 null, null, address)); 5815 }; 5816 5817 /** 5818 * @private 5819 */ 5820 net.user1.orbiter.ClientManager.prototype.fireAddressUnbanned = function (address) { 5821 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED, 5822 null, null, address)); 5823 }; 5824 5825 /** 5826 * @private 5827 */ 5828 net.user1.orbiter.ClientManager.prototype.fireSynchronizeBanlist = function () { 5829 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST)); 5830 }; 5831 5832 /** 5833 * @private 5834 */ 5835 net.user1.orbiter.ClientManager.prototype.fireSynchronize = function () { 5836 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE)); 5837 }; 5838 5839 //============================================================================== 5840 // CLEANUP AND DISPOSAL 5841 //============================================================================== 5842 5843 /** 5844 * @private 5845 */ 5846 net.user1.orbiter.ClientManager.prototype.cleanup = function () { 5847 this.log.info("[CLIENT_MANAGER] Cleaning resources."); 5848 this.selfReference = null; 5849 this.removeAllObservedClients(); 5850 this.removeAllWatchedClients(); 5851 this.setIsWatchingForClients(false); 5852 }; 5853 5854 net.user1.orbiter.ClientManager.prototype.dispose = function () { 5855 this.log.info("[CLIENT_MANAGER] Disposing resources."); 5856 this.watchedClients = null; 5857 this.observedClients = null; 5858 this.defaultClientClass = null; 5859 }; 5860 //============================================================================== 5861 // CLASS DECLARATION 5862 //============================================================================== 5863 /** @class 5864 @extends net.user1.events.Event 5865 */ 5866 net.user1.orbiter.ClientManagerEvent = function (type, 5867 clientID, 5868 client, 5869 address, 5870 status) { 5871 net.user1.events.Event.call(this, type); 5872 5873 this.clientID = clientID; 5874 this.client = client; 5875 this.address = address; 5876 this.status = status; 5877 }; 5878 5879 //============================================================================== 5880 // INHERITANCE 5881 //============================================================================== 5882 net.user1.utils.extend(net.user1.orbiter.ClientManagerEvent, net.user1.events.Event); 5883 5884 //============================================================================== 5885 // STATIC VARIABLES 5886 //============================================================================== 5887 /** @constant */ 5888 net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT = "WATCH_FOR_CLIENTS_RESULT"; 5889 /** @constant */ 5890 net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT = "STOP_WATCHING_FOR_CLIENTS_RESULT"; 5891 /** @constant */ 5892 net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED = "CLIENT_DISCONNECTED"; 5893 /** @constant */ 5894 net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED = "CLIENT_CONNECTED"; 5895 /** @constant */ 5896 net.user1.orbiter.ClientManagerEvent.KICK_RESULT = "KICK_RESULT"; 5897 /** @constant */ 5898 net.user1.orbiter.ClientManagerEvent.BAN_RESULT = "BAN_RESULT"; 5899 /** @constant */ 5900 net.user1.orbiter.ClientManagerEvent.UNBAN_RESULT = "UNBAN_RESULT"; 5901 /** @constant */ 5902 net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT = "WATCH_FOR_BANNED_ADDRESSES_RESULT"; 5903 /** @constant */ 5904 net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT = "STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT"; 5905 /** @constant */ 5906 net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED = "ADDRESS_BANNED"; 5907 /** @constant */ 5908 net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED = "ADDRESS_UNBANNED"; 5909 /** @constant */ 5910 net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST = "SYNCHRONIZE_BANLIST"; 5911 /** @constant */ 5912 net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE = "SYNCHRONIZE"; 5913 5914 net.user1.orbiter.ClientManagerEvent.prototype.getClientID = function () { 5915 return this.clientID; 5916 }; 5917 5918 net.user1.orbiter.ClientManagerEvent.prototype.getClient = function () { 5919 return this.client; 5920 }; 5921 5922 net.user1.orbiter.ClientManagerEvent.prototype.getAddress = function () { 5923 return this.address; 5924 }; 5925 5926 net.user1.orbiter.ClientManagerEvent.prototype.getStatus = function () { 5927 return this.status; 5928 }; 5929 5930 net.user1.orbiter.ClientManagerEvent.prototype.toString = function () { 5931 return "[object ClientManagerEvent]"; 5932 }; 5933 //============================================================================== 5934 // CLASS DECLARATION 5935 //============================================================================== 5936 net.user1.orbiter.ClientManifest = function () { 5937 this.clientID = null; 5938 this.userID = null; 5939 this.persistentAttributes = new net.user1.orbiter.AttributeCollection(); 5940 this.transientAttributes = new net.user1.orbiter.AttributeCollection(); 5941 this.occupiedRoomIDs = null; 5942 this.observedRoomIDs = null; 5943 }; 5944 5945 /** 5946 * @private 5947 */ 5948 net.user1.orbiter.ClientManifest.prototype.deserialize = function (clientID, 5949 userID, 5950 serializedOccupiedRoomIDs, 5951 serializedObservedRoomIDs, 5952 globalAttrs, 5953 roomAttrs) { 5954 this.clientID = clientID == "" ? null : clientID; 5955 this.userID = userID == "" ? null : userID; 5956 5957 // Room ids 5958 this.deserializeOccupiedRoomIDs(serializedOccupiedRoomIDs); 5959 this.deserializeObservedRoomIDs(serializedObservedRoomIDs); 5960 5961 // Global attrs 5962 this.deserializeAttributesByScope(net.user1.orbiter.Tokens.GLOBAL_ATTR, globalAttrs); 5963 5964 // Room attrs 5965 for (var i = 0; i < roomAttrs.length; i += 2) { 5966 this.deserializeAttributesByScope(roomAttrs[i], roomAttrs[i+1]); 5967 } 5968 }; 5969 5970 /** 5971 * @private 5972 */ 5973 net.user1.orbiter.ClientManifest.prototype.deserializeOccupiedRoomIDs = function (roomIDs) { 5974 // No rooms included in the manifest 5975 if (roomIDs == null) { 5976 return; 5977 } 5978 // Client is in no rooms 5979 if (roomIDs == "") { 5980 this.occupiedRoomIDs = []; 5981 return; 5982 } 5983 // Client is in one or more room 5984 this.occupiedRoomIDs = roomIDs.split(net.user1.orbiter.Tokens.RS); 5985 }; 5986 5987 /** 5988 * @private 5989 */ 5990 net.user1.orbiter.ClientManifest.prototype.deserializeObservedRoomIDs = function (roomIDs) { 5991 if (roomIDs == null) { 5992 return; 5993 } 5994 if (roomIDs == "") { 5995 this.observedRoomIDs = []; 5996 return; 5997 } 5998 this.observedRoomIDs = roomIDs.split(net.user1.orbiter.Tokens.RS); 5999 }; 6000 6001 /** 6002 * @private 6003 */ 6004 net.user1.orbiter.ClientManifest.prototype.deserializeAttributesByScope = function (scope, 6005 serializedAttributes) { 6006 var attrList; 6007 if (serializedAttributes == null || serializedAttributes == "") { 6008 return; 6009 } 6010 attrList = serializedAttributes.split(net.user1.orbiter.Tokens.RS); 6011 for (var i = attrList.length-3; i >= 0; i -=3) { 6012 if (parseInt(attrList[i+2]) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 6013 // Persistent 6014 this.persistentAttributes.setAttribute(attrList[i], attrList[i+1], scope); 6015 } else { 6016 // Non-persistent 6017 this.transientAttributes.setAttribute(attrList[i], attrList[i+1], scope); 6018 } 6019 } 6020 }; 6021 //============================================================================== 6022 // CLASS DECLARATION 6023 //============================================================================== 6024 /** 6025 * @private 6026 */ 6027 net.user1.orbiter.ClientSet = function () { 6028 this.clients = new net.user1.utils.UDictionary(); 6029 }; 6030 6031 net.user1.orbiter.ClientSet.prototype.add = function (client) { 6032 this.clients[client.getClientID()] = client; 6033 }; 6034 6035 net.user1.orbiter.ClientSet.prototype.remove = function (client) { 6036 var client = clients[client.getClientID()]; 6037 delete this.clients[client.getClientID()]; 6038 return client; 6039 }; 6040 6041 net.user1.orbiter.ClientSet.prototype.removeAll = function () { 6042 this.clients = new net.user1.utils.UDictionary(); 6043 } 6044 6045 net.user1.orbiter.ClientSet.prototype.removeByClientID = function (clientID) { 6046 var client = this.clients[clientID]; 6047 delete this.clients[clientID]; 6048 return client; 6049 }; 6050 6051 net.user1.orbiter.ClientSet.prototype.contains = function (client) { 6052 return this.clients[client.getClientID()] != null; 6053 }; 6054 6055 net.user1.orbiter.ClientSet.prototype.containsClientID = function (clientID) { 6056 if (clientID == "" || clientID == null) { 6057 return false; 6058 } 6059 return this.getByClientID(clientID) != null; 6060 }; 6061 6062 net.user1.orbiter.ClientSet.prototype.getByClientID = function (clientID) { 6063 return this.clients[clientID]; 6064 }; 6065 6066 net.user1.orbiter.ClientSet.prototype.getByUserID = function (userID) { 6067 var account; 6068 6069 var client; 6070 for (var clientID in this.clients) { 6071 client = this.clients[clientID]; 6072 account = client.getAccount(); 6073 if (account != null && account.getUserID() == userID) { 6074 return client; 6075 } 6076 } 6077 return null; 6078 }; 6079 6080 net.user1.orbiter.ClientSet.prototype.getAll = function () { 6081 return this.clients; 6082 } 6083 6084 net.user1.orbiter.ClientSet.prototype.getAllIDs = function () { 6085 var ids = []; 6086 for (var clientID in this.clients) { 6087 ids.push(clientID); 6088 } 6089 return ids; 6090 }; 6091 6092 net.user1.orbiter.ClientSet.prototype.length = function () { 6093 return net.user1.utils.ObjectUtil.length(this.clients); 6094 }; 6095 //============================================================================== 6096 // CLASS DECLARATION 6097 //============================================================================== 6098 /** 6099 * @class 6100 * @extends net.user1.orbiter.snapshot.Snapshot 6101 */ 6102 net.user1.orbiter.snapshot.ClientSnapshot = function (clientID) { 6103 // Call superconstructor 6104 net.user1.orbiter.snapshot.Snapshot.call(this); 6105 this.manifest = null; 6106 this.method = net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT; 6107 this.args = [clientID]; 6108 this.hasStatus = true; 6109 }; 6110 6111 //============================================================================== 6112 // INHERITANCE 6113 //============================================================================== 6114 net.user1.utils.extend(net.user1.orbiter.snapshot.ClientSnapshot, net.user1.orbiter.snapshot.Snapshot); 6115 6116 //============================================================================== 6117 // INSTANCE METHODS 6118 //============================================================================== 6119 /** 6120 * @private 6121 */ 6122 net.user1.orbiter.snapshot.ClientSnapshot.prototype.setManifest = function (value) { 6123 this.manifest = value; 6124 }; 6125 6126 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getAttribute = function (name, scope) { 6127 if (!this.manifest) { 6128 return null; 6129 } 6130 return this.manifest.transientAttributes.getAttribute(name, scope); 6131 }; 6132 6133 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getAttributes = function () { 6134 if (!this.manifest) { 6135 return null; 6136 } 6137 return this.manifest.transientAttributes.getAll(); 6138 }; 6139 6140 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getClientID = function () { 6141 if (!this.manifest) { 6142 return null; 6143 } 6144 return this.manifest.clientID; 6145 }; 6146 6147 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getUserID = function () { 6148 if (!this.manifest) { 6149 return null; 6150 } 6151 return this.manifest.userID; 6152 }; 6153 6154 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getOccupiedRoomIDs = function () { 6155 if (!this.manifest) { 6156 return null; 6157 } 6158 return this.manifest.occupiedRoomIDs.slice(); 6159 }; 6160 6161 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getObservedRoomIDs = function () { 6162 if (!this.manifest) { 6163 return null; 6164 } 6165 return this.manifest.observedRoomIDs.slice(); 6166 } 6167 //============================================================================== 6168 // CLASS DECLARATION 6169 //============================================================================== 6170 /** 6171 * @private 6172 */ 6173 net.user1.orbiter.CollectionEvent = function (type, item) { 6174 net.user1.events.Event.call(this, type); 6175 6176 this.item = item; 6177 }; 6178 6179 //============================================================================== 6180 // INHERITANCE 6181 //============================================================================== 6182 net.user1.utils.extend(net.user1.orbiter.CollectionEvent, net.user1.events.Event); 6183 6184 //============================================================================== 6185 // STATIC VARIABLES 6186 //============================================================================== 6187 6188 /** @constant */ 6189 net.user1.orbiter.CollectionEvent.REMOVE_ITEM = "REMOVE_ITEM"; 6190 /** @constant */ 6191 net.user1.orbiter.CollectionEvent.ADD_ITEM = "ADD_ITEM"; 6192 6193 net.user1.orbiter.CollectionEvent.prototype.getItem = function () { 6194 return this.item; 6195 }; 6196 6197 net.user1.orbiter.CollectionEvent.prototype.toString = function () { 6198 return "[object CollectionEvent]"; 6199 }; 6200 //============================================================================== 6201 // COMPARE TYPE CONSTANTS 6202 //============================================================================== 6203 /** @class */ 6204 net.user1.orbiter.filters.CompareType = new Object(); 6205 /** @constant */ 6206 net.user1.orbiter.filters.CompareType.EQUAL = "eq"; 6207 /** @constant */ 6208 net.user1.orbiter.filters.CompareType.NOT_EQUAL = "ne"; 6209 /** @constant */ 6210 net.user1.orbiter.filters.CompareType.GREATER_THAN = "gt"; 6211 /** @constant */ 6212 net.user1.orbiter.filters.CompareType.GREATER_THAN_OR_EQUAL = "ge"; 6213 /** @constant */ 6214 net.user1.orbiter.filters.CompareType.LESS_THAN = "lt"; 6215 /** @constant */ 6216 net.user1.orbiter.filters.CompareType.LESS_THAN_OR_EQUAL = "le"; 6217 //============================================================================== 6218 // CLASS DECLARATION 6219 //============================================================================== 6220 /** 6221 * @private 6222 */ 6223 net.user1.orbiter.CoreEventLogger = function (log, 6224 connectionMan, 6225 roomMan, 6226 accountMan, 6227 server, 6228 clientMan, 6229 orbiter) { 6230 this.log = log; 6231 6232 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT, 6233 this.stopWatchingForRoomsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6234 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, 6235 this.watchForRoomsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6236 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT, 6237 this.createRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6238 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT, 6239 this.removeRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6240 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.ROOM_ADDED, 6241 this.roomAddedListener, this, net.user1.utils.integer.MAX_VALUE); 6242 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED, 6243 this.roomRemovedListener, this, net.user1.utils.integer.MAX_VALUE); 6244 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.ROOM_COUNT, 6245 this.roomCountListener, this, net.user1.utils.integer.MAX_VALUE); 6246 roomMan.addEventListener(net.user1.orbiter.RoomEvent.JOIN_RESULT, 6247 this.joinRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6248 roomMan.addEventListener(net.user1.orbiter.RoomEvent.LEAVE_RESULT, 6249 this.leaveRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6250 roomMan.addEventListener(net.user1.orbiter.RoomEvent.OBSERVE_RESULT, 6251 this.observeRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6252 roomMan.addEventListener(net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT, 6253 this.stopObservingRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6254 6255 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT, 6256 this.createAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6257 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT, 6258 this.removeAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6259 accountMan.addEventListener(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT, 6260 this.changePasswordResultListener, this, net.user1.utils.integer.MAX_VALUE); 6261 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED, 6262 this.accountAddedListener, this, net.user1.utils.integer.MAX_VALUE); 6263 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED, 6264 this.accountRemovedListener, this, net.user1.utils.integer.MAX_VALUE); 6265 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGOFF_RESULT, 6266 this.logoffResultListener, this, net.user1.utils.integer.MAX_VALUE); 6267 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGOFF, 6268 this.logoffListener, this, net.user1.utils.integer.MAX_VALUE); 6269 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGIN_RESULT, 6270 this.loginResultListener, this, net.user1.utils.integer.MAX_VALUE); 6271 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGIN, 6272 this.loginListener, this, net.user1.utils.integer.MAX_VALUE); 6273 accountMan.addEventListener(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD, 6274 this.changePasswordListener, this, net.user1.utils.integer.MAX_VALUE); 6275 accountMan.addEventListener(net.user1.orbiter.AccountEvent.OBSERVE, 6276 this.observeAccountListener, this, net.user1.utils.integer.MAX_VALUE); 6277 accountMan.addEventListener(net.user1.orbiter.AccountEvent.STOP_OBSERVING, 6278 this.stopObservingAccountListener, this, net.user1.utils.integer.MAX_VALUE); 6279 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT, 6280 this.stopWatchingForAccountsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6281 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT, 6282 this.watchForAccountsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6283 accountMan.addEventListener(net.user1.orbiter.AccountEvent.OBSERVE_RESULT, 6284 this.observeAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6285 accountMan.addEventListener(net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT, 6286 this.stopObservingAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6287 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE, 6288 this.synchronizeAccountsListener, this, net.user1.utils.integer.MAX_VALUE); 6289 6290 server.addEventListener(net.user1.orbiter.ServerEvent.TIME_SYNC, this.timeSyncListener, this, net.user1.utils.integer.MAX_VALUE); 6291 6292 connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE, 6293 this.connectFailureListener, this, net.user1.utils.integer.MAX_VALUE); 6294 connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT, 6295 this.clientKillConnectListener, this, net.user1.utils.integer.MAX_VALUE); 6296 connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT, 6297 this.serverKillConnectListener, this, net.user1.utils.integer.MAX_VALUE); 6298 6299 clientMan.addEventListener(net.user1.orbiter.ClientEvent.OBSERVE, 6300 this.observeClientListener, this, net.user1.utils.integer.MAX_VALUE); 6301 clientMan.addEventListener(net.user1.orbiter.ClientEvent.STOP_OBSERVING, 6302 this.stopObservingClientListener, this, net.user1.utils.integer.MAX_VALUE); 6303 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED, 6304 this.clientConnectedListener, this, net.user1.utils.integer.MAX_VALUE); 6305 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED, 6306 this.clientDisconnectedListener, this, net.user1.utils.integer.MAX_VALUE); 6307 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT, 6308 this.stopWatchingForClientsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6309 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT, 6310 this.watchForClientsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6311 clientMan.addEventListener(net.user1.orbiter.ClientEvent.OBSERVE_RESULT, 6312 this.observeClientResultListener, this, net.user1.utils.integer.MAX_VALUE); 6313 clientMan.addEventListener(net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT, 6314 this.stopObservingClientResultListener, this, net.user1.utils.integer.MAX_VALUE); 6315 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE, 6316 this.synchronizeClientsListener, this, net.user1.utils.integer.MAX_VALUE); 6317 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED, 6318 this.addressBannedListener, this, net.user1.utils.integer.MAX_VALUE); 6319 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED, 6320 this.addressUnbannedListener, this, net.user1.utils.integer.MAX_VALUE); 6321 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT, 6322 this.stopWatchingForBannedAddressesResultListener, this, net.user1.utils.integer.MAX_VALUE); 6323 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT, 6324 this.watchForBannedAddressesResultListener, this, net.user1.utils.integer.MAX_VALUE); 6325 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST, 6326 this.synchronizeBanlistListener, this, net.user1.utils.integer.MAX_VALUE); 6327 6328 6329 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, this.readyListener, this, net.user1.utils.integer.MAX_VALUE); 6330 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE, this.protocolIncompatibleListener, this, net.user1.utils.integer.MAX_VALUE); 6331 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED, this.connectRefusedListener, this, net.user1.utils.integer.MAX_VALUE); 6332 6333 this.log.addEventListener(net.user1.logger.LogEvent.LEVEL_CHANGE, this.logLevelChangeListener, this, net.user1.utils.integer.MAX_VALUE); 6334 }; 6335 6336 6337 // ============================================================================= 6338 // Logger EVENT LISTENERS 6339 // ============================================================================= 6340 6341 /** 6342 * @private 6343 */ 6344 net.user1.orbiter.CoreEventLogger.prototype.logLevelChangeListener = function (e) { 6345 this.log.info("[LOGGER] Log level set to: [" + e.getLevel() + "]."); 6346 }; 6347 6348 // ============================================================================= 6349 // Orbiter EVENT LISTENERS 6350 // ============================================================================= 6351 6352 /** 6353 * @private 6354 */ 6355 net.user1.orbiter.CoreEventLogger.prototype.readyListener = function (e) { 6356 this.log.info("[ORBITER] Orbiter now connected and ready."); 6357 }; 6358 6359 /** 6360 * @private 6361 */ 6362 net.user1.orbiter.CoreEventLogger.prototype.protocolIncompatibleListener = function (e) { 6363 this.log.warn("[ORBITER] Orbiter UPC protocol incompatibility detected. Client " 6364 + "UPC version: " + e.target.getSystem().getUPCVersion().toString() 6365 + ". Server version: " + e.getServerUPCVersion().toString() + "."); 6366 }; 6367 6368 /** 6369 * @private 6370 */ 6371 net.user1.orbiter.CoreEventLogger.prototype.connectRefusedListener = function (e) { 6372 if (e.getConnectionRefusal().reason == net.user1.orbiter.ConnectionRefusalReason.BANNED) { 6373 this.log.warn("[ORBITER] Union Server refused the connection because the" 6374 + " client address is banned for the following reason: [" 6375 + e.getConnectionRefusal().banReason + "]. The ban started at: [" 6376 + new Date(e.getConnectionRefusal().bannedAt) + "]. The ban duration is: [" 6377 + net.user1.utils.NumericFormatter.msToElapsedDayHrMinSec(e.getConnectionRefusal().banDuration*1000) + "]."); 6378 } else { 6379 this.log.warn("[ORBITER] Union Server refused the connection. Reason: [" 6380 + e.getConnectionRefusal().reason + "]. Description: [" 6381 + e.getConnectionRefusal().description + "]."); 6382 } 6383 } 6384 6385 // ============================================================================= 6386 // Server EVENT LISTENERS 6387 // ============================================================================= 6388 6389 net.user1.orbiter.CoreEventLogger.prototype.timeSyncListener = function (e) { 6390 this.log.info("[SERVER] Server time synchronized with client. Approximate time on " + 6391 "server is now: " + new Date(e.target.getServerTime())); 6392 }; 6393 6394 // ============================================================================= 6395 // AccountManager EVENT LISTENERS 6396 // ============================================================================= 6397 net.user1.orbiter.CoreEventLogger.prototype.createAccountResultListener = function (e) { 6398 this.log.info("[ACCOUNT_MANAGER] Result for createAccount(). Account: " 6399 + e.getUserID() + ", Status: " + e.getStatus()); 6400 }; 6401 6402 net.user1.orbiter.CoreEventLogger.prototype.removeAccountResultListener = function (e) { 6403 this.log.info("[ACCOUNT_MANAGER] Result for removeAccount(). Account: " 6404 + e.getUserID() + ", Status: " + e.getStatus()); 6405 }; 6406 6407 net.user1.orbiter.CoreEventLogger.prototype.changePasswordResultListener = function (e) { 6408 this.log.info("[ACCOUNT_MANAGER] Result for changePassword(). Account: " 6409 + e.getUserID() + ", Status: " + e.getStatus()); 6410 }; 6411 6412 net.user1.orbiter.CoreEventLogger.prototype.accountAddedListener = function (e) { 6413 this.log.info("[ACCOUNT_MANAGER] Account added: " + e.getAccount()); 6414 }; 6415 6416 net.user1.orbiter.CoreEventLogger.prototype.accountRemovedListener = function (e) { 6417 this.log.info("[ACCOUNT_MANAGER] Account removed: " + e.getAccount()); 6418 }; 6419 6420 net.user1.orbiter.CoreEventLogger.prototype.logoffResultListener = function (e) { 6421 this.log.info("[ACCOUNT_MANAGER] Result for logoff(). Account: " 6422 + e.getAccount() + ", Status: " + e.getStatus()); 6423 }; 6424 6425 net.user1.orbiter.CoreEventLogger.prototype.logoffListener = function (e) { 6426 this.log.info("[ACCOUNT_MANAGER] Account logged off: " + e.getAccount()); 6427 }; 6428 6429 net.user1.orbiter.CoreEventLogger.prototype.loginResultListener = function (e) { 6430 this.log.info("[ACCOUNT_MANAGER] Result for login(). Account: " 6431 + e.getAccount() + ", Status: " + e.getStatus()); 6432 }; 6433 6434 net.user1.orbiter.CoreEventLogger.prototype.loginListener = function (e) { 6435 this.log.info("[ACCOUNT_MANAGER] Account logged in: " + e.getAccount()); 6436 }; 6437 6438 net.user1.orbiter.CoreEventLogger.prototype.changePasswordListener = function (e) { 6439 this.log.info("[ACCOUNT_MANAGER] Password changed for account: " + e.getUserID()); 6440 }; 6441 6442 net.user1.orbiter.CoreEventLogger.prototype.observeAccountListener = function (e) { 6443 this.log.info("[ACCOUNT_MANAGER] Account observed: " + e.getAccount()); 6444 }; 6445 6446 net.user1.orbiter.CoreEventLogger.prototype.stopObservingAccountListener = function (e) { 6447 this.log.info("[ACCOUNT_MANAGER] Stopped observing account: " + e.getUserID()); 6448 }; 6449 6450 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForAccountsResultListener = function (e) { 6451 this.log.info("[SERVER] 'Stop watching for accounts' result: " + e.getStatus()); 6452 }; 6453 6454 net.user1.orbiter.CoreEventLogger.prototype.watchForAccountsResultListener = function (e) { 6455 this.log.info("[ACCOUNT_MANAGER] 'Watch for accounts' result: " + e.getStatus()); 6456 }; 6457 6458 net.user1.orbiter.CoreEventLogger.prototype.observeAccountResultListener = function (e) { 6459 this.log.info("[ACCOUNT_MANAGER] 'Observe account result' for account: " 6460 + e.getAccount() + ", Status: " + e.getStatus()); 6461 }; 6462 6463 net.user1.orbiter.CoreEventLogger.prototype.stopObservingAccountResultListener = function (e) { 6464 this.log.info("[ACCOUNT_MANAGER] 'Stop observing account result' for account: " 6465 + e.getUserID() + ", Status: " + e.getStatus()); 6466 }; 6467 6468 net.user1.orbiter.CoreEventLogger.prototype.synchronizeAccountsListener = function (e) { 6469 this.log.info("[ACCOUNT_MANAGER] User account list synchronized with server."); 6470 }; 6471 6472 // ============================================================================= 6473 // CONNECTION EVENT LISTENERS 6474 // ============================================================================= 6475 6476 net.user1.orbiter.CoreEventLogger.prototype.connectFailureListener = function (e) { 6477 this.log.info("[CONNECTION_MANAGER] " + e.getStatus()); 6478 }; 6479 6480 net.user1.orbiter.CoreEventLogger.prototype.serverKillConnectListener = function (e) { 6481 this.log.info("[CONNECTION_MANAGER] Server closed the connection."); 6482 }; 6483 6484 net.user1.orbiter.CoreEventLogger.prototype.clientKillConnectListener = function (e) { 6485 this.log.info("[CONNECTION_MANAGER] Connection to server closed by client."); 6486 }; 6487 6488 // ============================================================================= 6489 // RoomManager EVENT LISTENERS 6490 // ============================================================================= 6491 6492 net.user1.orbiter.CoreEventLogger.prototype.watchForRoomsResultListener = function (e) { 6493 this.log.info("[ROOM_MANAGER] 'Watch for rooms' result for qualifier [" 6494 + e.getRoomIdQualifier() + "]: " + e.getStatus()); 6495 }; 6496 6497 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForRoomsResultListener = function (e) { 6498 this.log.info("[ROOM_MANAGER] 'Stop watching for rooms' result for" 6499 + " qualifier [" + e.getRoomIdQualifier() 6500 + "]: " + e.getStatus()); 6501 }; 6502 6503 net.user1.orbiter.CoreEventLogger.prototype.createRoomResultListener = function (e) { 6504 this.log.info("[ROOM_MANAGER] Room creation result for room [" 6505 + e.getRoomID() + "]: " + e.getStatus()); 6506 }; 6507 6508 net.user1.orbiter.CoreEventLogger.prototype.removeRoomResultListener = function (e) { 6509 this.log.info("[ROOM_MANAGER] Room removal result for room [" 6510 + e.getRoomID() + "]: " + e.getStatus()); 6511 }; 6512 6513 net.user1.orbiter.CoreEventLogger.prototype.roomAddedListener = function (e) { 6514 this.log.info("[ROOM_MANAGER] Room added: " + e.getRoom() + "."); 6515 }; 6516 6517 net.user1.orbiter.CoreEventLogger.prototype.roomRemovedListener = function (e) { 6518 this.log.info("[ROOM_MANAGER] Room removed: " + e.getRoom() + "."); 6519 }; 6520 6521 net.user1.orbiter.CoreEventLogger.prototype.roomCountListener = function (e) { 6522 this.log.info("[ROOM_MANAGER] New room count: " + e.getNumRooms() + "."); 6523 }; 6524 6525 net.user1.orbiter.CoreEventLogger.prototype.joinRoomResultListener = function (e) { 6526 this.log.info("[ROOM_MANAGER] Join result for room [" 6527 + e.getRoomID() + "]: " + e.getStatus()); 6528 }; 6529 6530 net.user1.orbiter.CoreEventLogger.prototype.leaveRoomResultListener = function (e) { 6531 this.log.info("[ROOM_MANAGER] Leave result for room [" 6532 + e.getRoomID() + "]: " + e.getStatus()); 6533 }; 6534 6535 net.user1.orbiter.CoreEventLogger.prototype.observeRoomResultListener = function (e) { 6536 this.log.info("[ROOM_MANAGER] Observe result for room [" 6537 + e.getRoomID() + "]: " + e.getStatus()); 6538 }; 6539 6540 net.user1.orbiter.CoreEventLogger.prototype.stopObservingRoomResultListener = function (e) { 6541 this.log.info("[ROOM_MANAGER] Stop observing result for room [" 6542 + e.getRoomID() + "]: " + e.getStatus()); 6543 }; 6544 6545 // ============================================================================= 6546 // ClientManager EVENT LISTENERS 6547 // ============================================================================= 6548 6549 net.user1.orbiter.CoreEventLogger.prototype.observeClientListener = function (e) { 6550 this.log.info("[CLIENT_MANAGER] Client observed: " + e.getClient()); 6551 }; 6552 6553 net.user1.orbiter.CoreEventLogger.prototype.stopObservingClientListener = function (e) { 6554 this.log.info("[CLIENT_MANAGER] Stopped observing client: " + e.getClient()); 6555 }; 6556 6557 net.user1.orbiter.CoreEventLogger.prototype.clientConnectedListener = function (e) { 6558 this.log.info("[CLIENT_MANAGER] Foreign client connected. ClientID: [" + e.getClientID() 6559 + "]."); 6560 }; 6561 6562 net.user1.orbiter.CoreEventLogger.prototype.clientDisconnectedListener = function (e) { 6563 this.log.info("[CLIENT_MANAGER] Foreign client disconnected. ClientID: [" + e.getClientID() 6564 + "]."); 6565 }; 6566 6567 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForClientsResultListener = function (e) { 6568 this.log.info("[CLIENT_MANAGER] 'Stop watching for clients' result: " + e.getStatus()); 6569 }; 6570 6571 net.user1.orbiter.CoreEventLogger.prototype.watchForClientsResultListener = function (e) { 6572 this.log.info("[CLIENT_MANAGER] 'Watch for clients' result: " + e.getStatus()); 6573 }; 6574 6575 net.user1.orbiter.CoreEventLogger.prototype.observeClientResultListener = function (e) { 6576 this.log.info("[CLIENT_MANAGER] 'Observe client' result for client: " 6577 + e.getClient() + ", status: " + e.getStatus()); 6578 }; 6579 6580 net.user1.orbiter.CoreEventLogger.prototype.stopObservingClientResultListener = function (e) { 6581 this.log.info("[CLIENT_MANAGER] 'Stop observing client' result for client: " 6582 + e.getClient() + ", status: " + e.getStatus()); 6583 }; 6584 6585 net.user1.orbiter.CoreEventLogger.prototype.synchronizeClientsListener = function (e) { 6586 this.log.info("[CLIENT_MANAGER] Client list synchronized with server."); 6587 }; 6588 6589 net.user1.orbiter.CoreEventLogger.prototype.addressBannedListener = function (e) { 6590 this.log.info("[CLIENT_MANAGER] Client address banned: [" + e.getAddress() 6591 + "]."); 6592 }; 6593 6594 net.user1.orbiter.CoreEventLogger.prototype.addressUnbannedListener = function (e) { 6595 this.log.info("[CLIENT_MANAGER] Client address unbanned. ClientID: [" + e.getAddress() 6596 + "]."); 6597 }; 6598 6599 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForBannedAddressesResultListener = function (e) { 6600 this.log.info("[CLIENT_MANAGER] 'Stop watching for banned addresses' result: " + e.getStatus()); 6601 }; 6602 6603 net.user1.orbiter.CoreEventLogger.prototype.watchForBannedAddressesResultListener = function (e) { 6604 this.log.info("[CLIENT_MANAGER] 'Watch for banned addresses' result: " + e.getStatus()); 6605 }; 6606 6607 net.user1.orbiter.CoreEventLogger.prototype.synchronizeBanlistListener = function (e) { 6608 this.log.info("[CLIENT_MANAGER] Banned list synchronized with server."); 6609 }; 6610 6611 6612 6613 6614 6615 //============================================================================== 6616 // CLASS DECLARATION 6617 //============================================================================== 6618 /** 6619 * @class 6620 * The CoreMessageListener class is an internal class that responds to the 6621 * built-in UPC messages sent by the Union Server to the Orbiter. The 6622 * CoreMessageListener class does not define any public methods or variables. 6623 * 6624 * @private 6625 */ 6626 net.user1.orbiter.CoreMessageListener = function (orbiter) { 6627 /** 6628 * @type net.user1.orbiter.Orbiter 6629 */ 6630 this.orbiter = orbiter; 6631 this.log = orbiter.getLog(); 6632 this.registerCoreListeners(); 6633 this.orbiter.getConnectionManager().addEventListener(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 6634 this.selectConnectionListener, this); 6635 6636 this.roomMan = this.orbiter.getRoomManager(); 6637 this.accountMan = this.orbiter.getAccountManager(); 6638 this.clientMan = this.orbiter.getClientManager(); 6639 this.snapshotMan = this.orbiter.getSnapshotManager(); 6640 }; 6641 6642 //============================================================================== 6643 // INSTANCE METHODS 6644 //============================================================================== 6645 net.user1.orbiter.CoreMessageListener.prototype.registerCoreListeners = function () { 6646 var msgMan = this.orbiter.getMessageManager(); 6647 msgMan.addMessageListener(net.user1.orbiter.UPC.JOINED_ROOM, this.u6, this); 6648 msgMan.addMessageListener(net.user1.orbiter.UPC.RECEIVE_MESSAGE, this.u7, this); 6649 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ATTR_UPDATE, this.u8, this); 6650 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_ATTR_UPDATE, this.u9, this); 6651 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_METADATA, this.u29, this); 6652 msgMan.addMessageListener(net.user1.orbiter.UPC.CREATE_ROOM_RESULT, this.u32, this); 6653 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ROOM_RESULT, this.u33, this); 6654 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENTCOUNT_SNAPSHOT, this.u34, this); 6655 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ADDED_TO_ROOM, this.u36, this); 6656 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_ROOM, this.u37, this); 6657 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOMLIST_SNAPSHOT, this.u38, this); 6658 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_ADDED, this.u39, this); 6659 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_REMOVED, this.u40, this); 6660 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_ROOMS_RESULT, this.u42, this); 6661 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS_RESULT, this.u43, this); 6662 msgMan.addMessageListener(net.user1.orbiter.UPC.LEFT_ROOM, this.u44, this); 6663 msgMan.addMessageListener(net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD_RESULT, this.u46, this); 6664 msgMan.addMessageListener(net.user1.orbiter.UPC.CREATE_ACCOUNT_RESULT, this.u47, this); 6665 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ACCOUNT_RESULT, this.u48, this); 6666 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGIN_RESULT, this.u49, this); 6667 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_SNAPSHOT, this.u54, this); 6668 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVED_ROOM, this.u59, this); 6669 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT_RESULT, this.u60, this); 6670 msgMan.addMessageListener(net.user1.orbiter.UPC.STOPPED_OBSERVING_ROOM, this.u62, this); 6671 msgMan.addMessageListener(net.user1.orbiter.UPC.SERVER_HELLO, this.u66, this); 6672 msgMan.addMessageListener(net.user1.orbiter.UPC.JOIN_ROOM_RESULT, this.u72, this); 6673 msgMan.addMessageListener(net.user1.orbiter.UPC.SET_CLIENT_ATTR_RESULT, this.u73, this); 6674 msgMan.addMessageListener(net.user1.orbiter.UPC.SET_ROOM_ATTR_RESULT, this.u74, this); 6675 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT_RESULT, this.u75, this); 6676 msgMan.addMessageListener(net.user1.orbiter.UPC.LEAVE_ROOM_RESULT, this.u76, this); 6677 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVE_ROOM_RESULT, this.u77, this); 6678 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_OBSERVING_ROOM_RESULT, this.u78, this); 6679 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_ATTR_REMOVED, this.u79, this); 6680 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ROOM_ATTR_RESULT, this.u80, this); 6681 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ATTR_REMOVED, this.u81, this); 6682 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR_RESULT, this.u82, this); 6683 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGOFF_RESULT, this.u87, this); 6684 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGGED_IN, this.u88, this); 6685 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGGED_OFF, this.u89, this); 6686 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_PASSWORD_CHANGED, this.u90, this); 6687 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENTLIST_SNAPSHOT, this.u101, this); 6688 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ADDED_TO_SERVER, this.u102, this); 6689 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_SERVER, this.u103, this); 6690 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_SNAPSHOT, this.u104, this); 6691 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVE_CLIENT_RESULT, this.u105, this); 6692 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT_RESULT, this.u106, this); 6693 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_CLIENTS_RESULT, this.u107, this); 6694 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS_RESULT, this.u108, this); 6695 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS_RESULT, this.u109, this); 6696 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS_RESULT, this.u110, this); 6697 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_ADDED, this.u111, this); 6698 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_REMOVED, this.u112, this); 6699 msgMan.addMessageListener(net.user1.orbiter.UPC.JOINED_ROOM_ADDED_TO_CLIENT, this.u113, this); 6700 msgMan.addMessageListener(net.user1.orbiter.UPC.JOINED_ROOM_REMOVED_FROM_CLIENT, this.u114, this); 6701 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT_RESULT, this.u115, this); 6702 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT_RESULT, this.u116, this); 6703 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVED_ROOM_ADDED_TO_CLIENT, this.u117, this); 6704 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVED_ROOM_REMOVED_FROM_CLIENT, this.u118, this); 6705 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_OBSERVED, this.u119, this); 6706 msgMan.addMessageListener(net.user1.orbiter.UPC.STOPPED_OBSERVING_CLIENT, this.u120, this); 6707 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVE_ACCOUNT_RESULT, this.u123, this); 6708 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_OBSERVED, this.u124, this); 6709 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT_RESULT, this.u125, this); 6710 msgMan.addMessageListener(net.user1.orbiter.UPC.STOPPED_OBSERVING_ACCOUNT, this.u126, this); 6711 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_LIST_UPDATE, this.u127, this); 6712 msgMan.addMessageListener(net.user1.orbiter.UPC.UPDATE_LEVELS_UPDATE, this.u128, this); 6713 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_OBSERVED_ROOM, this.u129, this); 6714 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_STOPPED_OBSERVING_ROOM, this.u130, this); 6715 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_OCCUPANTCOUNT_UPDATE, this.u131, this); 6716 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_OBSERVERCOUNT_UPDATE, this.u132, this); 6717 msgMan.addMessageListener(net.user1.orbiter.UPC.ADD_ROLE_RESULT, this.u134, this); 6718 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ROLE_RESULT, this.u136, this); 6719 msgMan.addMessageListener(net.user1.orbiter.UPC.BAN_RESULT, this.u138, this); 6720 msgMan.addMessageListener(net.user1.orbiter.UPC.UNBAN_RESULT, this.u140, this); 6721 msgMan.addMessageListener(net.user1.orbiter.UPC.BANNED_LIST_SNAPSHOT, this.u142, this); 6722 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES_RESULT, this.u144, this); 6723 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT, this.u146, this); 6724 msgMan.addMessageListener(net.user1.orbiter.UPC.BANNED_ADDRESS_ADDED, this.u147, this); 6725 msgMan.addMessageListener(net.user1.orbiter.UPC.BANNED_ADDRESS_REMOVED, this.u148, this); 6726 msgMan.addMessageListener(net.user1.orbiter.UPC.KICK_CLIENT_RESULT, this.u150, this); 6727 msgMan.addMessageListener(net.user1.orbiter.UPC.SERVERMODULELIST_SNAPSHOT, this.u152, this); 6728 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_UPC_STATS_SNAPSHOT_RESULT, this.u155, this); 6729 msgMan.addMessageListener(net.user1.orbiter.UPC.UPC_STATS_SNAPSHOT, this.u156, this); 6730 msgMan.addMessageListener(net.user1.orbiter.UPC.RESET_UPC_STATS_RESULT, this.u158, this); 6731 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_PROCESSED_UPCS_RESULT, this.u160, this); 6732 msgMan.addMessageListener(net.user1.orbiter.UPC.PROCESSED_UPC_ADDED, this.u161, this); 6733 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT, this.u163, this); 6734 msgMan.addMessageListener(net.user1.orbiter.UPC.NODELIST_SNAPSHOT, this.u166, this); 6735 msgMan.addMessageListener(net.user1.orbiter.UPC.GATEWAYS_SNAPSHOT, this.u168, this); 6736 } 6737 6738 net.user1.orbiter.CoreMessageListener.prototype.createHashFromArg = function (arg) { 6739 var list = arg.split(net.user1.orbiter.Tokens.RS); 6740 var hash = new Object(); 6741 6742 for (var i = 0; i < list.length; i += 2) { 6743 hash[list[i]] = list[i+1]; 6744 } 6745 return hash; 6746 }; 6747 6748 net.user1.orbiter.CoreMessageListener.prototype.selectConnectionListener = function (e) { 6749 var msgMan = this.orbiter.getMessageManager(); 6750 if (msgMan.removeListenersOnDisconnect) { 6751 this.registerCoreListeners(); 6752 } 6753 }; 6754 6755 /** 6756 * Room joined. 6757 */ 6758 net.user1.orbiter.CoreMessageListener.prototype.u6 = function (roomID) { 6759 // Add the room to the occupied room list 6760 var room = this.roomMan.addOccupiedRoom(roomID); 6761 // Tell the room to do its join duties 6762 room.doJoin(); 6763 // Fire JOIN through the client 6764 var selfClient = this.clientMan.self(); 6765 if (selfClient) { 6766 selfClient.fireJoinRoom(room, roomID); 6767 } 6768 }; 6769 6770 /** 6771 * Handles sendMessage() calls sent by other clients. 6772 */ 6773 net.user1.orbiter.CoreMessageListener.prototype.u7 = function (message, 6774 broadcastType, 6775 fromClientID, 6776 toRoomID) { 6777 var msgMan = this.orbiter.getMessageManager(); 6778 var listenerError; 6779 var fromClient; 6780 var toRoom; 6781 var args; // Args passed to the messsage listener 6782 var userDefinedArgs = Array.prototype.slice.call(arguments).slice(4); 6783 6784 // Retrieve the Room object for the recipient room. 6785 toRoom = this.roomMan.getRoom(toRoomID); 6786 6787 // Retrieve the Client object for the sender 6788 if (fromClientID == "") { 6789 // No client ID was supplied, so the message was generated by the 6790 // server, not by a client, so set fromClient to null. 6791 fromClient = null; 6792 } else { 6793 // A valid ID was supplied, so find or create the matching IClient object 6794 fromClient = this.clientMan.getClient(fromClientID); 6795 fromClient = fromClient == null ? this.clientMan.requestClient(fromClientID) : fromClient; 6796 } 6797 6798 // ===== To Clients, or To Server ===== 6799 // If the message was sent to a specific client, a list of specific clients, 6800 // or to the whole server, then args passed to registered message listeners 6801 // are: the Client object plus all user-defined arguments originally passed 6802 // to sendMessage(). 6803 if (broadcastType != net.user1.orbiter.ReceiveMessageBroadcastType.TO_ROOMS) { 6804 args = [fromClient].concat(userDefinedArgs); 6805 try { 6806 msgMan.notifyMessageListeners(message, args); 6807 } catch (e) { 6808 listenerError = e; 6809 } 6810 } else { 6811 6812 // ===== To Rooms ===== 6813 // Check if the room is valid 6814 if (toRoom == null) { 6815 this.log.warn("Message (u7) received for unknown room: [" + toRoomID + "]" 6816 + "Message: [" + message + "]"); 6817 return; 6818 } 6819 6820 // RECEIVE_MESSAGE was a response to SEND_MESSAGE_TO_ROOMS, so 6821 // we notify listeners only if they asked to be told about messages 6822 // sent to the recipient room. 6823 6824 // First, get the list of messsage listeners for this message 6825 var listeners = msgMan.getMessageListeners(message); 6826 6827 // Split the recipient room ID into two parts 6828 var toRoomSimpleID = net.user1.orbiter.RoomIDParser.getSimpleRoomID(toRoomID); 6829 var toRoomQualifier = net.user1.orbiter.RoomIDParser.getQualifier(toRoomID); 6830 6831 // If the message can be dispatched, set to true. 6832 var listenerFound; 6833 // If the listener isn't interested in messages sent to the 6834 // recipient room, set to true. 6835 var listenerIgnoredMessage; 6836 6837 // ===== Run once for each message listener ===== 6838 var messageListener; 6839 for (var i = 0; i < listeners.length; i++) { 6840 messageListener = listeners[i]; 6841 6842 // Assume this listener ignored the message until we prove it didn't 6843 listenerIgnoredMessage = true; 6844 6845 // --- Has no "forRoomIDs" filter --- 6846 // If the listener doesn't specify any forRoomIDs, then 6847 // just send it the message notification. (No-rooms-specified 6848 // means the listener wants all of these messages, no matter 6849 // which room they were sent to.) This listener is told which 6850 // room the message was sent to via args[1] (toRoomID). 6851 if (messageListener.getForRoomIDs() == null) { 6852 args = [fromClient, toRoom].concat(userDefinedArgs); 6853 try { 6854 messageListener.getListenerFunction().apply(messageListener.getThisArg(), args); 6855 } catch (e) { 6856 listenerError = e; 6857 } 6858 listenerFound = true; 6859 listenerIgnoredMessage = false; 6860 continue; // Done with this listener. On to the next. 6861 } 6862 6863 // --- Has a "forRoomIDs" filter --- 6864 // If the message was sent to any of the rooms the listener is 6865 // interested in, then notify that listener. Note that a listener 6866 // for messages sent to room foo.* means the listener wants 6867 // notifications for all rooms whose ids start with foo. 6868 var listenerRoomIDs = messageListener.getForRoomIDs(); 6869 var listenerRoomQualifier; 6870 var listenerRoomSimpleID; 6871 // ===== Run once for each room id ===== 6872 var listenerRoomIDString; 6873 for (var j = 0; j < listenerRoomIDs.length; j++) { 6874 listenerRoomIDString = listenerRoomIDs[j]; 6875 // Split the room id 6876 listenerRoomQualifier = net.user1.orbiter.RoomIDParser.getQualifier(listenerRoomIDString); 6877 listenerRoomSimpleID = net.user1.orbiter.RoomIDParser.getSimpleRoomID(listenerRoomIDString); 6878 6879 // Check if the listener is interested in the recipient room... 6880 if (listenerRoomQualifier == toRoomQualifier 6881 && 6882 (listenerRoomSimpleID == toRoomSimpleID 6883 || listenerRoomSimpleID == "*")) { 6884 // Found a match. Notify the listener... 6885 6886 // Prepare args. 6887 if (listenerRoomIDs.length == 1) { 6888 // The listener is interested in messages sent to a 6889 // specific room only, so omit the "toRoom" arg. 6890 // (The listener already knows the target room because 6891 // it's only notified if the message was sent to that room.) 6892 args = [fromClient].concat(userDefinedArgs); 6893 } else { 6894 // The listener is interested in messages sent to 6895 // multiple rooms. In this case, we have to 6896 // include the "toRoom" arg so the listener knows 6897 // which room received the message. 6898 args = [fromClient, toRoom].concat(userDefinedArgs); 6899 } 6900 6901 try { 6902 messageListener.getListenerFunction().apply(messageListener.getThisArg(), args); 6903 } catch (e) { 6904 listenerError = e; 6905 } 6906 listenerFound = true; 6907 listenerIgnoredMessage = false; 6908 break; // Stop looking at this listener's room ids 6909 } 6910 } // Done looking at this listener's room ids 6911 if (listenerIgnoredMessage) { 6912 this.log.debug("Message listener ignored message: " + message + ". " 6913 + "Listener registered to receive " 6914 + "messages sent to: " + messageListener.getForRoomIDs() 6915 + ", but message was sent to: " + toRoomID); 6916 } 6917 } 6918 if (!listenerFound) { 6919 this.log.warn("No message listener handled incoming message: " 6920 + message + ", sent to: " + toRoomID); 6921 } 6922 } // Done looking at listeners for the incoming message 6923 6924 if (listenerError != null) { 6925 throw new Error("A message listener for incoming message [" + message + "]" + 6926 (fromClient == null ? "" : ", received from client [" + fromClient.getClientID() + "],") + 6927 " encountered an error:\n\n" + listenerError.toString() + 6928 "\n\nEnsure that all [" + message + "] listeners supply a first" + 6929 " parameter whose datatype is Client (or a compatible type). Listeners" + 6930 " that registered for the message via MessageManager's addMessageListener()" + 6931 " with anything other than a single roomID for the toRoomIDs parameter must" + 6932 " also define a second paramter whose" + 6933 " datatype is Room (or a compatible type). Finally, ensure that" + 6934 " the listener's declared message parameters match the following actual message" + 6935 " arguments:\n " + userDefinedArgs 6936 + (typeof listenerError.stack === "undefined" ? "" : "\n\nStack trace follows:\n" + listenerError.stack) 6937 ); 6938 } 6939 } 6940 6941 /** 6942 * Client attribute update 6943 */ 6944 net.user1.orbiter.CoreMessageListener.prototype.u8 = function (attrScope, 6945 clientID, 6946 userID, 6947 attrName, 6948 attrVal, 6949 attrOptions) { 6950 var client; 6951 var account; 6952 var options = parseInt(attrOptions); 6953 6954 if (options &net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 6955 account = this.accountMan.getAccount(userID); 6956 if (account != null) { 6957 account.getAttributeManager().setAttributeLocal(attrName, attrVal, attrScope); 6958 } else { 6959 throw new Error("[CORE_MESSAGE_LISTENER] Received an attribute update for " 6960 + " an unknown user account [" + userID + "]. Please report this error with" 6961 + " the following log to union@user1.net.\n" 6962 + this.log.getHistory().join("\n")); 6963 } 6964 } else { 6965 client = this.clientMan.getInternalClient(clientID); 6966 if (client != null) { 6967 client.getAttributeManager().setAttributeLocal(attrName, attrVal, attrScope); 6968 } else { 6969 throw new Error("[CORE_MESSAGE_LISTENER] Received an attribute update for " 6970 + " an unknown client [" + clientID + "]. Please report this error with" 6971 + " the following log to union@user1.net.\n" 6972 + this.log.getHistory().join("\n")); 6973 } 6974 } 6975 }; 6976 6977 /** 6978 * Room attribute update 6979 */ 6980 net.user1.orbiter.CoreMessageListener.prototype.u9 = function (roomID, 6981 byClientID, 6982 attrName, 6983 attrVal) { 6984 var theRoom = this.roomMan.getRoom(roomID); 6985 var byClient; 6986 6987 // Quit if the room isn't found 6988 if (theRoom == null) { 6989 this.log.warn("Room attribute update received for server-side room with no" + 6990 " matching client-side Room object. Room ID [" + 6991 roomID + "]. Attribute: [" + attrName + "]."); 6992 return; 6993 } 6994 6995 // Retrieve the Client object for the sender 6996 if (byClientID == "") { 6997 // No client ID was supplied, so the message was generated by the 6998 // server, not by a client, so set fromClient to null. 6999 byClient = null; 7000 } else { 7001 // A valid ID was supplied, so find or create the matching IClient object 7002 byClient = this.clientMan.getClient(byClientID); 7003 byClient = byClient == null ? this.clientMan.requestClient(byClientID) : byClient; 7004 } 7005 7006 theRoom.getAttributeManager().setAttributeLocal(attrName, attrVal, net.user1.orbiter.Tokens.GLOBAL_ATTR, byClient); 7007 }; 7008 7009 /** 7010 * CLIENT_METADATA 7011 */ 7012 net.user1.orbiter.CoreMessageListener.prototype.u29 = function (id) { 7013 var theClient = this.clientMan.requestClient(id); 7014 this.clientMan.setSelf(theClient); 7015 }; 7016 7017 /** 7018 * CREATE_ROOM_RESULT 7019 */ 7020 net.user1.orbiter.CoreMessageListener.prototype.u32 = function (roomID, status) { 7021 var theRoom = this.roomMan.getRoom(roomID); 7022 switch (status) { 7023 case net.user1.orbiter.Status.ERROR: 7024 case net.user1.orbiter.Status.SUCCESS: 7025 case net.user1.orbiter.Status.ROOM_EXISTS: 7026 case net.user1.orbiter.Status.PERMISSION_DENIED: 7027 this.roomMan.fireCreateRoomResult(net.user1.orbiter.RoomIDParser.getQualifier(roomID), 7028 net.user1.orbiter.RoomIDParser.getSimpleRoomID(roomID), 7029 status); 7030 break; 7031 7032 default: 7033 this.log.warn("Unrecognized status code for u32." 7034 + " Room ID: [" + roomID + "], status: [" + status + "]."); 7035 } 7036 }; 7037 7038 /** 7039 * REMOVE_ROOM_RESULT 7040 */ 7041 net.user1.orbiter.CoreMessageListener.prototype.u33 = function (roomID, status) { 7042 this.roomMan.fireRemoveRoomResult(net.user1.orbiter.RoomIDParser.getQualifier(roomID), 7043 net.user1.orbiter.RoomIDParser.getSimpleRoomID(roomID), 7044 status); 7045 switch (status) { 7046 case net.user1.orbiter.Status.ERROR: 7047 this.log.warn("Server error for room removal attempt: " + roomID); 7048 break; 7049 case net.user1.orbiter.Status.PERMISSION_DENIED: 7050 this.log.info("Attempt to remove room [" + roomID 7051 + "] failed. Permission denied. See server log for details."); 7052 break; 7053 7054 case net.user1.orbiter.Status.SUCCESS: 7055 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7056 if (this.roomMan.getRoom(roomID) != null) { 7057 this.roomMan.disposeRoom(roomID); 7058 } 7059 break; 7060 7061 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7062 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7063 break; 7064 7065 default: 7066 this.log.warn("Unrecognized status code for u33." 7067 + " Room ID: [" + roomID + "], status: [" + status + "]."); 7068 } 7069 }; 7070 7071 /** 7072 * CLIENTCOUNT_SNAPSHOT 7073 */ 7074 net.user1.orbiter.CoreMessageListener.prototype.u34 = function (requestID, 7075 numClients) { 7076 this.snapshotMan.receiveClientCountSnapshot(requestID, parseInt(numClients)); 7077 }; 7078 7079 /** 7080 * CLIENT_ADDED_TO_ROOM 7081 */ 7082 net.user1.orbiter.CoreMessageListener.prototype.u36 = function (roomID, 7083 clientID, 7084 userID, 7085 globalAttributes, 7086 roomAttributes) { 7087 var theClient = this.clientMan.requestClient(clientID); 7088 var account = this.accountMan.requestAccount(userID); 7089 var clientManifest; 7090 if (account != null 7091 && theClient.getAccount() != account) { 7092 theClient.setAccount(account); 7093 } 7094 7095 // If it's not the current client, set the client's attributes. 7096 // (The current client obtains its own attributes through separate u8s.) 7097 var theRoom = this.roomMan.getRoom(roomID); 7098 if (!theClient.isSelf()) { 7099 clientManifest = new net.user1.orbiter.ClientManifest(); 7100 clientManifest.deserialize(clientID, userID, null, 7101 null, globalAttributes, [roomID, roomAttributes]); 7102 theClient.synchronize(clientManifest); 7103 7104 // If the client is observed, don't fire JOIN; observed clients always 7105 // fire JOIN based on observation updates. Likewise, don't fire JOIN 7106 // on self; self fires JOIN when it receives a u6. 7107 if (!this.clientMan.isObservingClient(clientID)) { 7108 theClient.fireJoinRoom(theRoom, roomID); 7109 } 7110 } 7111 7112 // Add the client to the given room. 7113 theRoom.addOccupant(theClient); 7114 }; 7115 7116 /** 7117 * CLIENT_REMOVED_FROM_ROOM 7118 */ 7119 net.user1.orbiter.CoreMessageListener.prototype.u37 = function (roomID, 7120 clientID) { 7121 // Remove the room from the client's list of occupied rooms 7122 var theClient = this.clientMan.requestClient(clientID); 7123 var theRoom = this.roomMan.getRoom(roomID); 7124 7125 // Remove the client from the given room 7126 theRoom.removeOccupant(clientID); 7127 7128 // Don't fire LEAVE on self; self fires LEAVE when it receives a u44. 7129 if (!theClient.isSelf()) { 7130 // If the client is observed, don't fire LEAVE; observed clients always 7131 // fire LEAVE based on observation updates. 7132 if (!this.clientMan.isObservingClient(clientID)) { 7133 theClient.fireLeaveRoom(theRoom, roomID); 7134 } 7135 } 7136 }; 7137 7138 /** 7139 * ROOMLIST_SNAPSHOT 7140 */ 7141 net.user1.orbiter.CoreMessageListener.prototype.u38 = function (requestID, 7142 requestedRoomIDQualifier, 7143 recursive) { 7144 var args = Array.prototype.slice.call(arguments).slice(3); 7145 var roomQualifier; 7146 var roomIDs; 7147 var roomList = []; 7148 7149 if (requestID == "") { 7150 // Synchronize 7151 for (var i = 0; i < args.length; i+=2) { 7152 roomQualifier = args[i]; 7153 roomIDs = args[i+1].split(net.user1.orbiter.Tokens.RS); 7154 7155 this.roomMan.setWatchedRooms(roomQualifier, roomIDs); 7156 } 7157 } else { 7158 // Snapshot 7159 for (i = 0; i < args.length; i+=2) { 7160 roomQualifier = args[i]; 7161 roomIDs = args[i+1].split(net.user1.orbiter.Tokens.RS); 7162 for (var j = 0; j < roomIDs.length; j++) { 7163 roomList.push(roomQualifier + (roomQualifier == "" ? "" : ".") + roomIDs[j]); 7164 } 7165 } 7166 this.snapshotMan.receiveRoomListSnapshot(requestID, roomList, requestedRoomIDQualifier, recursive == "true"); 7167 } 7168 }; 7169 7170 /** 7171 * ROOM_ADDED 7172 */ 7173 net.user1.orbiter.CoreMessageListener.prototype.u39 = function (roomID) { 7174 // Add the room 7175 this.roomMan.addWatchedRoom(roomID); 7176 }; 7177 7178 /** 7179 * ROOM_REMOVED 7180 */ 7181 net.user1.orbiter.CoreMessageListener.prototype.u40 = function (roomID) { 7182 this.roomMan.removeWatchedRoom(roomID); 7183 if (this.roomMan.getRoom(roomID) != null) { 7184 this.roomMan.disposeRoom(roomID); 7185 } 7186 }; 7187 7188 /** 7189 * WATCH_FOR_ROOMS_RESULT 7190 */ 7191 net.user1.orbiter.CoreMessageListener.prototype.u42 = function (roomIdQualifier, recursive, status) { 7192 // Broadcast the result of the observation attempt. 7193 this.roomMan.fireWatchForRoomsResult(roomIdQualifier, status); 7194 switch (status) { 7195 case net.user1.orbiter.Status.SUCCESS: 7196 case net.user1.orbiter.Status.ERROR: 7197 case net.user1.orbiter.Status.INVALID_QUALIFIER: 7198 case net.user1.orbiter.Status.ALREADY_WATCHING: 7199 case net.user1.orbiter.Status.PERMISSION_DENIED: 7200 break; 7201 7202 default: 7203 this.log.warn("Unrecognized status code for u42." 7204 + " Room ID Qualifier: [" + roomIdQualifier + "], recursive: [" 7205 + recursive + "], status: [" + status + "]."); 7206 } 7207 }; 7208 7209 /** 7210 * STOP_WATCHING_FOR_ROOMS_RESULT 7211 */ 7212 net.user1.orbiter.CoreMessageListener.prototype.u43 = function (roomIdQualifier, recursive, status) { 7213 switch (status) { 7214 case net.user1.orbiter.Status.SUCCESS: 7215 if (roomIdQualifier == "" && recursive == "true") { 7216 this.roomMan.removeAllWatchedRooms(); 7217 } else { 7218 // Remove all watched rooms for the qualifier 7219 this.roomMan.setWatchedRooms(roomIdQualifier, []); 7220 } 7221 case net.user1.orbiter.Status.ERROR: 7222 case net.user1.orbiter.Status.NOT_WATCHING: 7223 case net.user1.orbiter.Status.INVALID_QUALIFIER: 7224 this.roomMan.fireStopWatchingForRoomsResult(roomIdQualifier, status); 7225 break; 7226 7227 default: 7228 this.log.warn("Unrecognized status code for u43." 7229 + " Room ID Qualifier: [" + roomIdQualifier + "], recursive: [" 7230 + recursive + "], status: [" + status + "]."); 7231 } 7232 }; 7233 7234 /** 7235 * LEFT_ROOM 7236 */ 7237 net.user1.orbiter.CoreMessageListener.prototype.u44 = function (roomID) { 7238 var leftRoom = this.roomMan.getRoom(roomID); 7239 this.roomMan.removeOccupiedRoom(roomID); 7240 if (leftRoom != null) { 7241 leftRoom.doLeave(); 7242 this.clientMan.self().fireLeaveRoom(leftRoom, roomID); 7243 } 7244 }; 7245 7246 /** 7247 * CHANGE_ACCOUNT_PASSWORD_RESULT 7248 */ 7249 net.user1.orbiter.CoreMessageListener.prototype.u46 = function (userID, status) { 7250 var account = this.accountMan.getAccount(userID); 7251 if (account != null) { 7252 account.fireChangePasswordResult(status); 7253 } 7254 this.accountMan.fireChangePasswordResult(userID, status); 7255 }; 7256 7257 /** 7258 * CREATE_ACCOUNT_RESULT 7259 */ 7260 net.user1.orbiter.CoreMessageListener.prototype.u47 = function (userID, status) { 7261 switch (status) { 7262 case net.user1.orbiter.Status.SUCCESS: 7263 case net.user1.orbiter.Status.ERROR: 7264 case net.user1.orbiter.Status.ACCOUNT_EXISTS: 7265 case net.user1.orbiter.Status.PERMISSION_DENIED: 7266 this.orbiter.getAccountManager().fireCreateAccountResult(userID, status); 7267 break; 7268 default: 7269 this.log.warn("Unrecognized status code for u47." 7270 + " Account: [" + userID + "], status: [" + status + "]."); 7271 } 7272 }; 7273 7274 /** 7275 * REMOVE_ACCOUNT_RESULT 7276 */ 7277 net.user1.orbiter.CoreMessageListener.prototype.u48 = function (userID, status) { 7278 switch (status) { 7279 case net.user1.orbiter.Status.SUCCESS: 7280 case net.user1.orbiter.Status.ERROR: 7281 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7282 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7283 case net.user1.orbiter.Status.PERMISSION_DENIED: 7284 this.orbiter.getAccountManager().fireRemoveAccountResult(userID, status); 7285 break; 7286 default: 7287 this.log.warn("Unrecognized status code for u48." 7288 + " Account: [" + userID + "], status: [" + status + "]."); 7289 } 7290 }; 7291 7292 /** 7293 * LOGIN_RESULT 7294 */ 7295 net.user1.orbiter.CoreMessageListener.prototype.u49 = function (userID, status) { 7296 switch (status) { 7297 case net.user1.orbiter.Status.SUCCESS: 7298 case net.user1.orbiter.Status.ERROR: 7299 case net.user1.orbiter.Status.ALREADY_LOGGED_IN: 7300 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7301 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7302 case net.user1.orbiter.Status.PERMISSION_DENIED: 7303 this.orbiter.getAccountManager().fireLoginResult(userID, status); 7304 break; 7305 default: 7306 this.log.warn("Unrecognized status code for u49." 7307 + " Account: [" + userID + "], status: [" + status + "]."); 7308 } 7309 }; 7310 7311 /** 7312 * ROOM_SNAPSHOT 7313 */ 7314 net.user1.orbiter.CoreMessageListener.prototype.u54 = function (requestID, 7315 roomID, 7316 occupantCount, 7317 observerCount, 7318 roomAttributes) { 7319 var clientList = Array.prototype.slice.call(arguments).slice(5); 7320 var clientManifest; 7321 var roomManifest = new net.user1.orbiter.RoomManifest(); 7322 var theRoom; 7323 roomManifest.deserialize(roomID, 7324 roomAttributes, 7325 clientList, 7326 parseInt(occupantCount), 7327 parseInt(observerCount)); 7328 7329 if (requestID == "") { 7330 // Synchronize 7331 theRoom = this.roomMan.getRoom(roomID); 7332 7333 if (theRoom == null) { 7334 // If the server makes the current client join or observe a room, it 7335 // will first send a u54 before sending the u6 or u59 notice. In that 7336 // case, the room might be unknown briefly, so create a cached room 7337 // then wait for the u6 or u59 to arrive. 7338 theRoom = this.roomMan.addCachedRoom(roomID); 7339 } 7340 7341 theRoom.synchronize(roomManifest); 7342 } else { 7343 // Snapshot 7344 this.snapshotMan.receiveRoomSnapshot(requestID, roomManifest); 7345 } 7346 }; 7347 7348 7349 /** 7350 * OBSERVED_ROOM 7351 */ 7352 net.user1.orbiter.CoreMessageListener.prototype.u59 = function (roomID) { 7353 // Add the room to the observed room list 7354 var room = this.roomMan.addObservedRoom(roomID); 7355 // Tell the room to do its join duties 7356 room.doObserve(); 7357 // Fire OBSERVE through the client 7358 this.clientMan.self().fireObserveRoom(room, roomID); 7359 }; 7360 7361 /** 7362 * GET_ROOM_SNAPSHOT_RESULT 7363 */ 7364 net.user1.orbiter.CoreMessageListener.prototype.u60 = function (requestID, 7365 roomID, 7366 status) { 7367 switch (status) { 7368 case net.user1.orbiter.Status.SUCCESS: 7369 case net.user1.orbiter.Status.ERROR: 7370 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7371 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7372 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7373 case net.user1.orbiter.Status.PERMISSION_DENIED: 7374 this.snapshotMan.receiveSnapshotResult(requestID, status); 7375 break; 7376 default: 7377 this.log.warn("Unrecognized status code for u60." 7378 + " Request ID: [" + requestID + "], Room ID: [" 7379 + roomID + "], status: [" + status + "]."); 7380 } 7381 }; 7382 7383 /** 7384 * STOPPED_OBSERVING_ROOM 7385 */ 7386 net.user1.orbiter.CoreMessageListener.prototype.u62 = function (roomID) { 7387 var theRoom = this.roomMan.getRoom(roomID); 7388 this.roomMan.removeObservedRoom(roomID); 7389 if (theRoom != null) { 7390 theRoom.doStopObserving(); 7391 // self() might return null if a STOP_OBSERVING listener has closed the connection 7392 if (this.clientMan.self() != null) { 7393 this.clientMan.self().fireStopObservingRoom(theRoom, roomID); 7394 } 7395 } 7396 }; 7397 7398 /** 7399 * SERVER_HELLO 7400 */ 7401 net.user1.orbiter.CoreMessageListener.prototype.u66 = function (serverVersion, 7402 sessionID, 7403 serverUPCVersionString, 7404 protocolCompatible, 7405 affinityAddress, 7406 affinityDuration) { 7407 this.log.info("[ORBITER] Server version: " + serverVersion); 7408 this.log.info("[ORBITER] Server UPC version: " + serverUPCVersionString); 7409 7410 var serverUPCVersion = new net.user1.orbiter.VersionNumber(); 7411 serverUPCVersion.fromVersionString(serverUPCVersionString); 7412 this.orbiter.getServer().setVersion(serverVersion); 7413 this.orbiter.getServer().setUPCVersion(serverUPCVersion); 7414 7415 7416 var inProgressConnection = this.orbiter.getConnectionManager().getInProgressConnection(); 7417 var inProgressConnectionHost = inProgressConnection.getHost(); 7418 if (affinityAddress != "" 7419 && typeof affinityAddress !== "undefined" 7420 && affinityAddress != inProgressConnectionHost) { 7421 this.orbiter.getConnectionManager().setAffinity(inProgressConnectionHost, 7422 affinityAddress, 7423 parseFloat(affinityDuration)); 7424 inProgressConnection.applyAffinity(); 7425 } 7426 }; 7427 7428 7429 /** 7430 * JOIN_ROOM_RESULT 7431 */ 7432 net.user1.orbiter.CoreMessageListener.prototype.u72 = function (roomID, 7433 status) { 7434 var theRoom = this.roomMan.getRoom(roomID); 7435 switch (status) { 7436 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7437 if (this.roomMan.getRoom(roomID) != null) { 7438 this.roomMan.disposeRoom(roomID); 7439 } 7440 7441 case net.user1.orbiter.Status.ERROR: 7442 case net.user1.orbiter.Status.ROOM_FULL: 7443 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7444 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7445 case net.user1.orbiter.Status.SUCCESS: 7446 case net.user1.orbiter.Status.ALREADY_IN_ROOM: 7447 case net.user1.orbiter.Status.PERMISSION_DENIED: 7448 this.roomMan.fireJoinRoomResult(roomID, status); 7449 if (theRoom != null) { 7450 theRoom.doJoinResult(status); 7451 } 7452 break; 7453 7454 default: 7455 this.log.warn("Unrecognized status code for u72." 7456 + " Room ID: [" + roomID + "], status: [" + status + "]."); 7457 } 7458 }; 7459 7460 /** 7461 * SET_CLIENT_ATTR_RESULT 7462 */ 7463 net.user1.orbiter.CoreMessageListener.prototype.u73 = function (attrScope, 7464 clientID, 7465 userID, 7466 attrName, 7467 attrOptions, 7468 status) { 7469 var theClient; 7470 var theAccount; 7471 7472 switch (status) { 7473 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7474 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7475 break; 7476 7477 case net.user1.orbiter.Status.SUCCESS: 7478 case net.user1.orbiter.Status.ERROR: 7479 case net.user1.orbiter.Status.DUPLICATE_VALUE: 7480 case net.user1.orbiter.Status.IMMUTABLE: 7481 case net.user1.orbiter.Status.SERVER_ONLY: 7482 case net.user1.orbiter.Status.EVALUATION_FAILED: 7483 case net.user1.orbiter.Status.PERMISSION_DENIED: 7484 if (parseInt(attrOptions) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 7485 // Persistent attr 7486 theAccount = this.accountMan.requestAccount(userID); 7487 theAccount.getAttributeManager().fireSetAttributeResult(attrName, attrScope, status); 7488 } else { 7489 // Non-persistent attr 7490 theClient = this.clientMan.requestClient(clientID); 7491 theClient.getAttributeManager().fireSetAttributeResult(attrName, attrScope, status); 7492 } 7493 break; 7494 7495 default: 7496 this.log.warn("Unrecognized status received for u73: " + status); 7497 } 7498 }; 7499 7500 /** 7501 * SET_ROOM_ATTR_RESULT 7502 */ 7503 net.user1.orbiter.CoreMessageListener.prototype.u74 = function (roomID, 7504 attrName, 7505 status) { 7506 var theRoom = this.roomMan.getRoom(roomID); 7507 7508 // Quit if the room isn't found 7509 if (theRoom == null) { 7510 this.log.warn("Room attribute update received for room with no" + 7511 " client-side Room object. Room ID [" + 7512 roomID + "]. Attribute: [" + attrName + "]. Status: [" 7513 + status + "]."); 7514 return; 7515 } 7516 7517 switch (status) { 7518 case net.user1.orbiter.Status.SUCCESS: 7519 case net.user1.orbiter.Status.ERROR: 7520 case net.user1.orbiter.Status.IMMUTABLE: 7521 case net.user1.orbiter.Status.SERVER_ONLY: 7522 case net.user1.orbiter.Status.EVALUATION_FAILED: 7523 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7524 case net.user1.orbiter.Status.PERMISSION_DENIED: 7525 theRoom.getAttributeManager().fireSetAttributeResult(attrName, 7526 net.user1.orbiter.Tokens.GLOBAL_ATTR, 7527 status); 7528 break; 7529 7530 default: 7531 this.log.warn("Unrecognized status received for u74: " + status); 7532 } 7533 }; 7534 7535 /** 7536 * GET_CLIENTCOUNT_SNAPSHOT_RESULT 7537 */ 7538 net.user1.orbiter.CoreMessageListener.prototype.u75 = function (requestID, 7539 status) { 7540 this.snapshotMan.receiveSnapshotResult(requestID, status); 7541 }; 7542 7543 /** 7544 * LEAVE_ROOM_RESULT 7545 */ 7546 net.user1.orbiter.CoreMessageListener.prototype.u76 = function (roomID, 7547 status) { 7548 var leftRoom = this.roomMan.getRoom(roomID); 7549 7550 switch (status) { 7551 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7552 if (leftRoom != null) { 7553 this.roomMan.disposeRoom(roomID); 7554 } 7555 7556 case net.user1.orbiter.Status.SUCCESS: 7557 case net.user1.orbiter.Status.ERROR: 7558 case net.user1.orbiter.Status.NOT_IN_ROOM: 7559 this.roomMan.fireLeaveRoomResult(roomID, status); 7560 if (leftRoom != null) { 7561 leftRoom.doLeaveResult(status); 7562 } 7563 break; 7564 7565 default: 7566 this.log.warn("Unrecognized status code for u76." 7567 + " Room ID: [" + roomID + "]. Status: [" + status + "]."); 7568 } 7569 }; 7570 7571 /** 7572 * OBSERVE_ROOM_RESULT 7573 */ 7574 net.user1.orbiter.CoreMessageListener.prototype.u77 = function (roomID, 7575 status) { 7576 var theRoom = this.roomMan.getRoom(roomID); 7577 switch (status) { 7578 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7579 if (theRoom != null) { 7580 this.roomMan.disposeRoom(roomID); 7581 } 7582 7583 case net.user1.orbiter.Status.ERROR: 7584 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7585 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7586 case net.user1.orbiter.Status.SUCCESS: 7587 case net.user1.orbiter.Status.ALREADY_OBSERVING: 7588 case net.user1.orbiter.Status.PERMISSION_DENIED: 7589 this.roomMan.fireObserveRoomResult(roomID, status); 7590 7591 if (theRoom) { 7592 theRoom.doObserveResult(status); 7593 } 7594 break; 7595 7596 default: 7597 this.log.warn("Unrecognized status code for u77." 7598 + " Room ID: [" + roomID + "], status: " + status + "."); 7599 } 7600 } 7601 7602 /** 7603 * STOP_OBSERVING_ROOM_RESULT 7604 */ 7605 net.user1.orbiter.CoreMessageListener.prototype.u78 = function (roomID, 7606 status) { 7607 var theRoom = this.roomMan.getRoom(roomID); 7608 7609 switch (status) { 7610 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7611 if (theRoom != null) { 7612 this.roomMan.disposeRoom(roomID); 7613 } 7614 7615 case net.user1.orbiter.Status.SUCCESS: 7616 case net.user1.orbiter.Status.ERROR: 7617 case net.user1.orbiter.Status.NOT_OBSERVING: 7618 this.roomMan.fireStopObservingRoomResult(roomID, status); 7619 7620 if (theRoom != null) { 7621 theRoom.doStopObservingResult(status); 7622 } 7623 break; 7624 7625 default: 7626 this.log.warn("Unrecognized status code for u78." 7627 + " Room ID: [" + roomID + "], status: " + status + "."); 7628 } 7629 }; 7630 7631 /** 7632 * ROOM_ATTR_REMOVED 7633 */ 7634 net.user1.orbiter.CoreMessageListener.prototype.u79 = function (roomID, 7635 byClientID, 7636 attrName) { 7637 var theRoom = this.roomMan.getRoom(roomID); 7638 var theClient; 7639 7640 // Quit if the room isn't found 7641 if (theRoom == null) { 7642 this.log.warn("Room attribute removal notification received for room with no" + 7643 " client-side Room object. Room ID [" + 7644 roomID + "]. Attribute: [" + attrName + "]."); 7645 return; 7646 } 7647 7648 // If the clientID is "", the server removed the room, so there's no 7649 // corresponding client. 7650 theClient = byClientID == "" ? null : this.clientMan.requestClient(byClientID); 7651 theRoom.getAttributeManager().removeAttributeLocal(attrName, net.user1.orbiter.Tokens.GLOBAL_ATTR, theClient) 7652 } 7653 7654 /** 7655 * REMOVE_ROOM_ATTR_RESULT 7656 */ 7657 net.user1.orbiter.CoreMessageListener.prototype.u80 = function (roomID, 7658 attrName, 7659 status) { 7660 var theRoom = this.roomMan.getRoom(roomID); 7661 switch (status) { 7662 case net.user1.orbiter.Status.SUCCESS: 7663 case net.user1.orbiter.Status.ERROR: 7664 case net.user1.orbiter.Status.IMMUTABLE: 7665 case net.user1.orbiter.Status.SERVER_ONLY: 7666 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7667 case net.user1.orbiter.Status.ATTR_NOT_FOUND: 7668 case net.user1.orbiter.Status.PERMISSION_DENIED: 7669 if (theRoom != null) { 7670 theRoom.getAttributeManager().fireDeleteAttributeResult(attrName, 7671 net.user1.orbiter.Tokens.GLOBAL_ATTR, 7672 status); 7673 } 7674 break; 7675 7676 default: 7677 this.log.warn("Unrecognized status received for u80: " + status); 7678 } 7679 }; 7680 7681 /** 7682 * CLIENT_ATTR_REMOVED 7683 */ 7684 net.user1.orbiter.CoreMessageListener.prototype.u81 = function (attrScope, 7685 clientID, 7686 userID, 7687 attrName, 7688 attrOptions) { 7689 var client; 7690 var account; 7691 7692 if (parseInt(attrOptions) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 7693 // Persistent attr 7694 account = this.accountMan.requestAccount(userID); 7695 account.getAttributeManager().removeAttributeLocal(attrName, attrScope); 7696 } else { 7697 // Non-persistent attr 7698 client = this.clientMan.requestClient(clientID); 7699 client.getAttributeManager().removeAttributeLocal(attrName, attrScope); 7700 } 7701 }; 7702 7703 /** 7704 * REMOVE_CLIENT_ATTR_RESULT 7705 */ 7706 net.user1.orbiter.CoreMessageListener.prototype.u82 = function (attrScope, 7707 clientID, 7708 userID, 7709 attrName, 7710 attrOptions, 7711 status) { 7712 var client; 7713 var account; 7714 7715 7716 switch (status) { 7717 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7718 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7719 break; 7720 case net.user1.orbiter.Status.SUCCESS: 7721 case net.user1.orbiter.Status.ERROR: 7722 case net.user1.orbiter.Status.IMMUTABLE: 7723 case net.user1.orbiter.Status.SERVER_ONLY: 7724 case net.user1.orbiter.Status.ATTR_NOT_FOUND: 7725 case net.user1.orbiter.Status.EVALUATION_FAILED: 7726 case net.user1.orbiter.Status.PERMISSION_DENIED: 7727 if (parseInt(attrOptions) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 7728 // Persistent attr 7729 account = this.accountMan.requestAccount(userID); 7730 account.getAttributeManager().fireDeleteAttributeResult(attrName, attrScope, status); 7731 } else { 7732 // Non-persistent attr 7733 client = this.clientMan.requestClient(clientID); 7734 client.getAttributeManager().fireDeleteAttributeResult(attrName, attrScope, status); 7735 } 7736 break; 7737 7738 default: 7739 this.log.warn("Unrecognized status received for u82: " + status); 7740 } 7741 }; 7742 7743 /** 7744 * LOGOFF_RESULT 7745 */ 7746 net.user1.orbiter.CoreMessageListener.prototype.u87 = function (userID, status) { 7747 var account = this.accountMan.getAccount(userID); 7748 7749 switch (status) { 7750 case net.user1.orbiter.Status.SUCCESS: 7751 case net.user1.orbiter.Status.ERROR: 7752 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7753 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7754 case net.user1.orbiter.Status.NOT_LOGGED_IN: 7755 case net.user1.orbiter.Status.PERMISSION_DENIED: 7756 if (account != null) { 7757 account.fireLogoffResult(status); 7758 } 7759 // Tell the account manager 7760 this.accountMan.fireLogoffResult(userID, status); 7761 break; 7762 default: 7763 this.log.warn("Unrecognized status received for u87: " + status); 7764 } 7765 }; 7766 7767 /** 7768 * LOGGED_IN 7769 */ 7770 net.user1.orbiter.CoreMessageListener.prototype.u88 = function (clientID, 7771 userID, 7772 globalAttrs) { 7773 var roomAttrs = Array.prototype.slice.call(arguments).slice(3); 7774 var account = this.accountMan.requestAccount(userID); 7775 var client = this.clientMan.requestClient(clientID); 7776 var clientManifest = new net.user1.orbiter.ClientManifest(); 7777 clientManifest.deserialize(clientID, userID, null, null, globalAttrs, roomAttrs); 7778 // Update the account 7779 var scopes = clientManifest.persistentAttributes.getScopes(); 7780 var accountAttrs = account.getAttributeManager().getAttributeCollection(); 7781 for (var i = scopes.length; --i >= 0;) { 7782 accountAttrs.synchronizeScope(scopes[i], clientManifest.persistentAttributes); 7783 } 7784 7785 if (client.getAccount() == null) { 7786 // Client doesn't know about this account yet 7787 client.setAccount(account); 7788 client.fireLogin(); 7789 account.doLoginTasks(); 7790 this.accountMan.fireLogin(account, clientID); 7791 } else { 7792 // Do nothing if the account is known. Logins are reported for 7793 // observe-account, observe-client, and watch-for-clients, so a 7794 // client might receive multiple login notifications. 7795 } 7796 }; 7797 7798 /** 7799 * LOGGED_OFF 7800 */ 7801 net.user1.orbiter.CoreMessageListener.prototype.u89 = function (clientID, userID) { 7802 var client = this.clientMan.getInternalClient(clientID); 7803 var account = this.accountMan.getAccount(userID); 7804 7805 if (account != null) { 7806 if (account.getConnectionState() == net.user1.orbiter.ConnectionState.LOGGED_IN) { 7807 if (client != null) { 7808 client.fireLogoff(userID); 7809 } 7810 account.doLogoffTasks(); 7811 this.accountMan.fireLogoff(account, clientID); 7812 } else { 7813 // Do nothing if the account is unknown. Logoffs are reported for 7814 // observe-account, observe-client, and watch-for-clients, so a 7815 // client might receive multiple logoff notifications. 7816 } 7817 } else { 7818 throw new Error("LOGGED_OFF (u89) received for an unknown user: [" + userID + "]."); 7819 } 7820 } 7821 7822 /** 7823 * PASSWORD_CHANGED 7824 */ 7825 net.user1.orbiter.CoreMessageListener.prototype.u90 = function () { 7826 var self = this.orbiter.self(); 7827 var selfAccount = self.getAccount(); 7828 if (selfAccount != null) { 7829 selfAccount.fireChangePassword(); 7830 } 7831 this.accountMan.fireChangePassword(selfAccount ? selfAccount.getUserID() : null); 7832 }; 7833 7834 /** 7835 * CLIENTLIST_SNAPSHOT 7836 */ 7837 net.user1.orbiter.CoreMessageListener.prototype.u101 = function (requestID, serializedIDs) { 7838 var ids = serializedIDs.split(net.user1.orbiter.Tokens.RS); 7839 var clientList; 7840 var thisUserID; 7841 7842 if (requestID == "") { 7843 // Synchronize 7844 this.clientMan.deserializeWatchedClients(serializedIDs); 7845 } else { 7846 // Snapshot 7847 clientList = []; 7848 for (var i = ids.length-1; i >= 0; i-=2) { 7849 thisUserID = ids[i]; 7850 thisUserID = thisUserID == "" ? null : thisUserID; 7851 clientList.push({clientID:ids[i-1], userID:thisUserID}); 7852 } 7853 this.snapshotMan.receiveClientListSnapshot(requestID, clientList); 7854 } 7855 }; 7856 7857 /** 7858 * CLIENT_ADDED_TO_SERVER 7859 */ 7860 net.user1.orbiter.CoreMessageListener.prototype.u102 = function (clientID) { 7861 this.clientMan.addWatchedClient(this.clientMan.requestClient(clientID)); 7862 }; 7863 7864 /** 7865 * CLIENT_REMOVED_FROM_SERVER 7866 */ 7867 net.user1.orbiter.CoreMessageListener.prototype.u103 = function (clientID) { 7868 var client = this.clientMan.getInternalClient(clientID); 7869 7870 if (this.clientMan.hasWatchedClient(clientID)) { 7871 this.clientMan.removeWatchedClient(clientID); 7872 } 7873 if (this.clientMan.isObservingClient(clientID)) { 7874 this.clientMan.removeObservedClient(clientID); 7875 } 7876 7877 // If the current client is both observing a client and watching for clients, 7878 // it will receive two u103 notifications. When the second one arrives, the 7879 // client will be unknown, so no disconnection event should be dispatched. 7880 if (client != null) { 7881 client.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 7882 // Retrieve the client reference using getClient() here so that the 7883 // ClientManagerEvent.CLIENT_DISCONNECTED event provides the application 7884 // with access to the custom client, if available. 7885 this.clientMan.fireClientDisconnected(this.clientMan.getClient(clientID)); 7886 } 7887 }; 7888 7889 /** 7890 * CLIENT_SNAPSHOT 7891 */ 7892 net.user1.orbiter.CoreMessageListener.prototype.u104 = function (requestID, 7893 clientID, 7894 userID, 7895 serializedOccupiedRoomIDs, 7896 serializedObservedRoomIDs, 7897 globalAttrs) { 7898 var roomAttrs = Array.prototype.slice.call(arguments).slice(7); 7899 var theClient; 7900 var account = this.accountMan.requestAccount(userID); 7901 var clientManifest = new net.user1.orbiter.ClientManifest(); 7902 clientManifest.deserialize(clientID, userID, serializedOccupiedRoomIDs, 7903 serializedObservedRoomIDs, globalAttrs, roomAttrs); 7904 var scopes; // Used with UserAccount only 7905 7906 if (clientID != "") { 7907 // --- Client update --- 7908 7909 if (requestID == "") { 7910 // Synchronize 7911 theClient = this.clientMan.requestClient(clientID); 7912 theClient.setAccount(account); 7913 theClient.synchronize(clientManifest); 7914 theClient.fireSynchronize(); 7915 } else { 7916 // Snapshot 7917 this.snapshotMan.receiveClientSnapshot(requestID, clientManifest); 7918 } 7919 } else { 7920 // --- User account update --- 7921 7922 if (requestID == "") { 7923 // Synchronize 7924 scopes = clientManifest.persistentAttributes.getScopes(); 7925 for (var i = scopes.length; --i >= 0;) { 7926 account.getAttributeManager().getAttributeCollection().synchronizeScope(scopes[i], clientManifest.persistentAttributes); 7927 } 7928 account.fireSynchronize(); 7929 } else { 7930 // Snapshot 7931 this.snapshotMan.receiveAccountSnapshot(requestID, clientManifest); 7932 } 7933 } 7934 }; 7935 7936 /** 7937 * OBSERVE_CLIENT_RESULT 7938 */ 7939 net.user1.orbiter.CoreMessageListener.prototype.u105 = function (clientID, status) { 7940 var theClient = this.clientMan.getInternalClient(clientID); 7941 switch (status) { 7942 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7943 case net.user1.orbiter.Status.SUCCESS: 7944 case net.user1.orbiter.Status.ERROR: 7945 case net.user1.orbiter.Status.ALREADY_OBSERVING: 7946 case net.user1.orbiter.Status.PERMISSION_DENIED: 7947 this.clientMan.fireObserveClientResult(clientID, status); 7948 if (theClient != null) { 7949 theClient.fireObserveResult(status); 7950 } 7951 break; 7952 7953 default: 7954 this.log.warn("Unrecognized status code for u105." 7955 + " Client ID: [" + clientID + "], status: [" + status + "]."); 7956 } 7957 }; 7958 7959 /** 7960 * STOP_OBSERVING_CLIENT_RESULT 7961 */ 7962 net.user1.orbiter.CoreMessageListener.prototype.u106 = function (clientID, status) { 7963 var theClient = this.clientMan.getInternalClient(clientID); 7964 switch (status) { 7965 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7966 case net.user1.orbiter.Status.SUCCESS: 7967 case net.user1.orbiter.Status.ERROR: 7968 case net.user1.orbiter.Status.NOT_OBSERVING: 7969 this.clientMan.fireStopObservingClientResult(clientID, status); 7970 if (theClient != null) { 7971 theClient.fireStopObservingResult(status); 7972 } 7973 break; 7974 7975 default: 7976 this.log.warn("Unrecognized status code for u106." 7977 + " Client ID: [" + clientID + "], status: [" + status + "]."); 7978 } 7979 }; 7980 7981 /** 7982 * WATCH_FOR_CLIENTS_RESULT 7983 */ 7984 net.user1.orbiter.CoreMessageListener.prototype.u107 = function (status) { 7985 switch (status) { 7986 case net.user1.orbiter.Status.SUCCESS: 7987 case net.user1.orbiter.Status.ERROR: 7988 case net.user1.orbiter.Status.ALREADY_WATCHING: 7989 this.clientMan.fireWatchForClientsResult(status); 7990 break; 7991 7992 default: 7993 this.log.warn("Unrecognized status code for u107." 7994 + "Status: [" + status + "]."); 7995 } 7996 }; 7997 7998 /** 7999 * STOP_WATCHING_FOR_CLIENTS_RESULT 8000 */ 8001 net.user1.orbiter.CoreMessageListener.prototype.u108 = function (status) { 8002 switch (status) { 8003 case net.user1.orbiter.Status.SUCCESS: 8004 this.clientMan.setIsWatchingForClients(false); 8005 this.clientMan.removeAllWatchedClients(); 8006 case net.user1.orbiter.Status.ERROR: 8007 case net.user1.orbiter.Status.NOT_WATCHING: 8008 this.clientMan.fireStopWatchingForClientsResult(status); 8009 break; 8010 8011 default: 8012 this.log.warn("Unrecognized status code for u108." 8013 + "Status: [" + status + "]."); 8014 } 8015 }; 8016 8017 /** 8018 * WATCH_FOR_USERS_RESULT 8019 */ 8020 net.user1.orbiter.CoreMessageListener.prototype.u109 = function (status) { 8021 switch (status) { 8022 case net.user1.orbiter.Status.SUCCESS: 8023 this.accountMan.setIsWatchingForAccounts(true); 8024 case net.user1.orbiter.Status.ERROR: 8025 case net.user1.orbiter.Status.ALREADY_WATCHING: 8026 this.accountMan.fireWatchForAccountsResult(status); 8027 break; 8028 8029 default: 8030 this.log.warn("Unrecognized status code for u109." 8031 + "Status: [" + status + "]."); 8032 } 8033 }; 8034 8035 /** 8036 * STOP_WATCHING_FOR_USERS_RESULT 8037 */ 8038 net.user1.orbiter.CoreMessageListener.prototype.u110 = function (status) { 8039 switch (status) { 8040 case net.user1.orbiter.Status.SUCCESS: 8041 this.accountMan.setIsWatchingForAccounts(false); 8042 this.accountMan.removeAllWatchedAccounts(); 8043 case net.user1.orbiter.Status.ERROR: 8044 case net.user1.orbiter.Status.NOT_WATCHING: 8045 this.accountMan.fireStopWatchingForAccountsResult(status); 8046 break; 8047 8048 default: 8049 this.log.warn("Unrecognized status code for u110." 8050 + "Status: [" + status + "]."); 8051 } 8052 }; 8053 8054 /** 8055 * USER_ADDED 8056 */ 8057 net.user1.orbiter.CoreMessageListener.prototype.u111 = function (userID) { 8058 this.accountMan.addWatchedAccount(this.accountMan.requestAccount(userID)); 8059 }; 8060 8061 /** 8062 * USER_REMOVED 8063 */ 8064 net.user1.orbiter.CoreMessageListener.prototype.u112 = function (userID) { 8065 var account; 8066 if (this.accountMan.hasWatchedAccount(userID)) { 8067 account = this.accountMan.removeWatchedAccount(userID); 8068 } 8069 if (this.accountMan.isObservingAccount(userID)) { 8070 account = this.accountMan.removeObservedAccount(userID); 8071 } 8072 this.accountMan.fireAccountRemoved(userID, account); 8073 }; 8074 8075 /** 8076 * JOINED_ROOM_ADDED_TO_CLIENT 8077 */ 8078 net.user1.orbiter.CoreMessageListener.prototype.u113 = function (clientID, roomID) { 8079 var client = this.clientMan.requestClient(clientID); 8080 client.addOccupiedRoomID(roomID); 8081 client.fireJoinRoom(this.roomMan.getRoom(roomID), roomID); 8082 } 8083 8084 /** 8085 * JOINED_ROOM_REMOVED_FROM_CLIENT 8086 */ 8087 net.user1.orbiter.CoreMessageListener.prototype.u114 = function (clientID, roomID) { 8088 var client = this.clientMan.requestClient(clientID); 8089 client.removeOccupiedRoomID(roomID); 8090 client.fireLeaveRoom(this.roomMan.getRoom(roomID), roomID); 8091 }; 8092 8093 /** 8094 * GET_CLIENT_SNAPSHOT_RESULT 8095 */ 8096 net.user1.orbiter.CoreMessageListener.prototype.u115 = function (requestID, 8097 clientID, 8098 status) { 8099 this.snapshotMan.receiveSnapshotResult(requestID, status); 8100 }; 8101 8102 /** 8103 * GET_ACCOUNT_SNAPSHOT_RESULT 8104 */ 8105 net.user1.orbiter.CoreMessageListener.prototype.u116 = function (requestID, 8106 userID, 8107 status) { 8108 this.snapshotMan.receiveSnapshotResult(requestID, status); 8109 }; 8110 8111 /** 8112 * OBSERVED_ROOM_ADDED_TO_CLIENT 8113 */ 8114 net.user1.orbiter.CoreMessageListener.prototype.u117 = function (clientID, roomID) { 8115 var client = this.clientMan.requestClient(clientID); 8116 client.addObservedRoomID(roomID); 8117 client.fireObserveRoom(this.roomMan.getRoom(roomID), roomID); 8118 }; 8119 8120 /** 8121 * OBSERVED_ROOM_REMOVED_FROM_CLIENT 8122 */ 8123 net.user1.orbiter.CoreMessageListener.prototype.u118 = function (clientID, roomID) { 8124 var client = this.clientMan.requestClient(clientID); 8125 client.removeObservedRoomID(roomID); 8126 client.fireStopObservingRoom(this.roomMan.getRoom(roomID), roomID); 8127 } 8128 8129 /** 8130 * CLIENT_OBSERVED 8131 */ 8132 net.user1.orbiter.CoreMessageListener.prototype.u119 = function (clientID) { 8133 var client = this.clientMan.requestClient(clientID); 8134 this.clientMan.addObservedClient(client); 8135 client.fireObserve(); 8136 }; 8137 8138 /** 8139 * STOPPED_OBSERVING_CLIENT 8140 */ 8141 net.user1.orbiter.CoreMessageListener.prototype.u120 = function (clientID) { 8142 var client = this.clientMan.getInternalClient(clientID) 8143 this.clientMan.removeObservedClient(clientID); 8144 if (client != null) { 8145 client.fireStopObserving(); 8146 } 8147 }; 8148 8149 /** 8150 * OBSERVE_ACCOUNT_RESULT 8151 */ 8152 net.user1.orbiter.CoreMessageListener.prototype.u123 = function (userID, status) { 8153 var theAccount = this.accountMan.getAccount(userID); 8154 switch (status) { 8155 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8156 case net.user1.orbiter.Status.SUCCESS: 8157 case net.user1.orbiter.Status.ERROR: 8158 case net.user1.orbiter.Status.ALREADY_OBSERVING: 8159 this.accountMan.fireObserveAccountResult(userID, status); 8160 if (theAccount) { 8161 theAccount.fireObserveResult(status); 8162 } 8163 break; 8164 8165 default: 8166 this.log.warn("Unrecognized status code for u123." 8167 + " User ID: [" + userID + "], status: [" + status + "]."); 8168 } 8169 }; 8170 8171 /** 8172 * ACCOUNT_OBSERVED 8173 */ 8174 net.user1.orbiter.CoreMessageListener.prototype.u124 = function (userID) { 8175 var theAccount = this.accountMan.requestAccount(userID); 8176 this.accountMan.addObservedAccount(theAccount); 8177 theAccount.fireObserve(); 8178 }; 8179 8180 /** 8181 * STOP_OBSERVING_ACCOUNT_RESULT 8182 */ 8183 net.user1.orbiter.CoreMessageListener.prototype.u125 = function (userID, status) { 8184 var theAccount = this.accountMan.getAccount(userID); 8185 switch (status) { 8186 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8187 case net.user1.orbiter.Status.SUCCESS: 8188 case net.user1.orbiter.Status.ERROR: 8189 case net.user1.orbiter.Status.ALREADY_OBSERVING: 8190 this.accountMan.fireStopObservingAccountResult(userID, status); 8191 if (theAccount) { 8192 theAccount.fireStopObservingResult(status); 8193 } 8194 break; 8195 8196 default: 8197 this.log.warn("Unrecognized status code for u125." 8198 + " User ID: [" + userID + "], status: [" + status + "]."); 8199 } 8200 }; 8201 8202 /** 8203 * STOPPED_OBSERVING_ACCOUNT 8204 */ 8205 net.user1.orbiter.CoreMessageListener.prototype.u126 = function (userID) { 8206 var account = this.accountMan.getAccount(userID); 8207 this.accountMan.removeObservedAccount(userID); 8208 if (account != null) { 8209 account.fireStopObserving(); 8210 } 8211 }; 8212 8213 /** 8214 * ACCOUNT_LIST_UPDATE 8215 */ 8216 net.user1.orbiter.CoreMessageListener.prototype.u127 = function (requestID, serializedIDs) { 8217 var ids = serializedIDs.split(net.user1.orbiter.Tokens.RS); 8218 var accountList; 8219 8220 if (requestID == "") { 8221 // Synchronize 8222 this.accountMan.deserializeWatchedAccounts(serializedIDs); 8223 } else { 8224 // Snapshot 8225 accountList = []; 8226 for (var i = ids.length; --i >= 0;) { 8227 accountList.push(ids[i]); 8228 } 8229 this.snapshotMan.receiveAccountListSnapshot(requestID, accountList); 8230 } 8231 }; 8232 8233 /** 8234 * UPDATE_LEVELS_UPDATE 8235 */ 8236 net.user1.orbiter.CoreMessageListener.prototype.u128 = function (updateLevels, roomID) { 8237 var room = this.roomMan.getRoom(roomID); 8238 var levels = new net.user1.orbiter.UpdateLevels(); 8239 levels.fromInt(parseInt(updateLevels)); 8240 if (room != null) { 8241 if (!levels.occupantList) { 8242 var occupantID; 8243 var occupantIDs = room.getOccupantIDs(); 8244 var numOccupantIDs = occupantIDs.length; 8245 for (var i = 0; i < numOccupantIDs; i++) { 8246 occupantID = occupantIDs[i]; 8247 room.removeOccupant(occupantID); 8248 } 8249 } 8250 if (!levels.observerList) { 8251 var observerID; 8252 var observerIDs = room.getObserverIDs(); 8253 var numObserverIDs = observerIDs.length; 8254 for (i = 0; i < numObserverIDs; i++) { 8255 observerID = observerIDs[i]; 8256 room.removeObserver(observerID); 8257 } 8258 } 8259 if (!levels.sharedRoomAttributes 8260 && !levels.allRoomAttributes) { 8261 room.getAttributeManager().removeAll(); 8262 } 8263 } 8264 }; 8265 8266 /** 8267 * CLIENT_OBSERVED_ROOM 8268 */ 8269 net.user1.orbiter.CoreMessageListener.prototype.u129 = function (roomID, 8270 clientID, 8271 userID, 8272 globalAttributes, 8273 roomAttributes) { 8274 var theClient = this.clientMan.requestClient(clientID); 8275 var account = this.accountMan.requestAccount(userID); 8276 var clientManifest; 8277 if (account != null 8278 && theClient.getAccount() != account) { 8279 theClient.setAccount(account); 8280 } 8281 8282 // If it's not the current client, set the client's attributes. 8283 // (The current client obtains its own attributes through separate u8s.) 8284 var theRoom = this.roomMan.getRoom(roomID); 8285 if (!theClient.isSelf()) { 8286 clientManifest = new net.user1.orbiter.ClientManifest(); 8287 clientManifest.deserialize(clientID, userID, null, 8288 null, globalAttributes, [roomID, roomAttributes]); 8289 theClient.synchronize(clientManifest); 8290 8291 // If the client is observed, don't fire OBSERVE_ROOM; observed clients always 8292 // fire OBSERVE_ROOM based on observation updates. Likewise, don't fire OBSERVE_ROOM 8293 // on self; self fires OBSERVE_ROOM when it receives a u59. 8294 if (!this.clientMan.isObservingClient(clientID)) { 8295 theClient.fireObserveRoom(theRoom, roomID); 8296 } 8297 } 8298 8299 // Add the client to the room's observer list 8300 theRoom.addObserver(theClient); 8301 }; 8302 8303 /** 8304 * CLIENT_STOPPED_OBSERVING_ROOM 8305 */ 8306 net.user1.orbiter.CoreMessageListener.prototype.u130 = function (roomID, 8307 clientID) { 8308 // Remove the room from the client's list of observed rooms 8309 var theClient = this.clientMan.requestClient(clientID); 8310 var theRoom = this.roomMan.getRoom(roomID); 8311 8312 // Remove the client from the given room 8313 theRoom.removeObserver(clientID); 8314 8315 // Don't fire STOP_OBSERVING_ROOM on self; self fires STOP_OBSERVING_ROOM 8316 // when it receives a u62. 8317 if (!theClient.isSelf()) { 8318 // If the client is observed, don't fire STOP_OBSERVING_ROOM; observed 8319 // clients always fire STOP_OBSERVING_ROOM based on observation updates. 8320 if (!this.clientMan.isObservingClient(clientID)) { 8321 theClient.fireStopObservingRoom(theRoom, roomID); 8322 } 8323 } 8324 }; 8325 8326 /** 8327 * ROOM_OCCUPANTCOUNT_UPDATE 8328 */ 8329 net.user1.orbiter.CoreMessageListener.prototype.u131 = function (roomID, 8330 numClients) { 8331 var levels = this.clientMan.self().getUpdateLevels(roomID); 8332 8333 if (levels != null) { 8334 if (!levels.occupantList) { 8335 this.roomMan.getRoom(roomID).setNumOccupants(parseInt(numClients)); 8336 } 8337 } else { 8338 throw new Error("[CORE_MESSAGE_LISTENER] Received a room occupant count" + 8339 " update (u131), but update levels are unknown for the room. Synchronization" + 8340 " error. Please report this error to union@user1.net."); 8341 } 8342 }; 8343 8344 /** 8345 * ROOM_OBSERVERCOUNT_UPDATE 8346 */ 8347 net.user1.orbiter.CoreMessageListener.prototype.u132 = function (roomID, 8348 numClients) { 8349 var levels = this.clientMan.self().getUpdateLevels(roomID); 8350 8351 if (levels != null) { 8352 if (!levels.observerList) { 8353 this.roomMan.getRoom(roomID).setNumObservers(parseInt(numClients)); 8354 } 8355 } else { 8356 throw new Error("[CORE_MESSAGE_LISTENER] Received a room observer count" + 8357 " update (u132), but update levels are unknown for the room. Synchronization" + 8358 " error. Please report this error to union@user1.net."); 8359 } 8360 } 8361 8362 /** 8363 * ADD_ROLE_RESULT 8364 */ 8365 net.user1.orbiter.CoreMessageListener.prototype.u134 = function (userID, role, status) { 8366 var theAccount = this.accountMan.getAccount(userID); 8367 switch (status) { 8368 case net.user1.orbiter.Status.SUCCESS: 8369 case net.user1.orbiter.Status.ERROR: 8370 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8371 case net.user1.orbiter.Status.ROLE_NOT_FOUND: 8372 case net.user1.orbiter.Status.ALREADY_ASSIGNED: 8373 case net.user1.orbiter.Status.PERMISSION_DENIED: 8374 this.accountMan.fireAddRoleResult(userID, role, status); 8375 if (theAccount) { 8376 theAccount.fireAddRoleResult(role, status); 8377 } 8378 break; 8379 8380 default: 8381 this.log.warn("Unrecognized status code for u134." 8382 + " User ID: [" + userID + "], role: [" + role 8383 + "], status: [" + status + "]."); 8384 } 8385 }; 8386 8387 /** 8388 * REMOVE_ROLE_RESULT 8389 */ 8390 net.user1.orbiter.CoreMessageListener.prototype.u136 = function (userID, role, status) { 8391 var theAccount = this.accountMan.getAccount(userID); 8392 switch (status) { 8393 case net.user1.orbiter.Status.SUCCESS: 8394 case net.user1.orbiter.Status.ERROR: 8395 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8396 case net.user1.orbiter.Status.ROLE_NOT_FOUND: 8397 case net.user1.orbiter.Status.NOT_ASSIGNED: 8398 case net.user1.orbiter.Status.PERMISSION_DENIED: 8399 this.accountMan.fireRemoveRoleResult(userID, role, status); 8400 if (theAccount) { 8401 theAccount.fireRemoveRoleResult(role, status); 8402 } 8403 break; 8404 8405 default: 8406 this.log.warn("Unrecognized status code for u136." 8407 + " User ID: [" + userID + "], role: [" + role 8408 + "], status: [" + status + "]."); 8409 } 8410 }; 8411 8412 /** 8413 * BAN_RESULT 8414 */ 8415 net.user1.orbiter.CoreMessageListener.prototype.u138 = function (address, clientID, status) { 8416 switch (status) { 8417 case net.user1.orbiter.Status.SUCCESS: 8418 case net.user1.orbiter.Status.ERROR: 8419 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 8420 case net.user1.orbiter.Status.ALREADY_BANNED: 8421 case net.user1.orbiter.Status.PERMISSION_DENIED: 8422 this.clientMan.fireBanClientResult(address, clientID, status); 8423 break; 8424 8425 default: 8426 this.log.warn("Unrecognized status code for u138." 8427 + " Address: [" + address + "], clientID: [" + clientID 8428 + "], status: [" + status + "]."); 8429 } 8430 }; 8431 8432 /** 8433 * UNBAN_RESULT 8434 */ 8435 net.user1.orbiter.CoreMessageListener.prototype.u140 = function (address, status) { 8436 switch (status) { 8437 case net.user1.orbiter.Status.SUCCESS: 8438 case net.user1.orbiter.Status.ERROR: 8439 case net.user1.orbiter.Status.NOT_BANNED: 8440 case net.user1.orbiter.Status.PERMISSION_DENIED: 8441 this.clientMan.fireUnbanClientResult(address, status); 8442 break; 8443 8444 default: 8445 this.log.warn("Unrecognized status code for u140." 8446 + " Address: [" + address + "]," 8447 + " status: [" + status + "]."); 8448 } 8449 }; 8450 8451 /** 8452 * BANNED_LIST_SNAPSHOT 8453 */ 8454 net.user1.orbiter.CoreMessageListener.prototype.u142 = function (requestID, bannedListSource) { 8455 var bannedList = bannedListSource == "" ? [] : bannedListSource.split(net.user1.orbiter.Tokens.RS); 8456 8457 if (requestID == "") { 8458 this.clientMan.setWatchedBannedAddresses(bannedList); 8459 } else { 8460 // Snapshot 8461 this.snapshotMan.receiveBannedListSnapshot(requestID, bannedList); 8462 } 8463 }; 8464 8465 /** 8466 * WATCH_FOR_BANNED_ADDRESSES_RESULT 8467 */ 8468 net.user1.orbiter.CoreMessageListener.prototype.u144 = function (status) { 8469 switch (status) { 8470 case net.user1.orbiter.Status.SUCCESS: 8471 case net.user1.orbiter.Status.ERROR: 8472 case net.user1.orbiter.Status.ALREADY_WATCHING: 8473 case net.user1.orbiter.Status.PERMISSION_DENIED: 8474 this.clientMan.fireWatchForBannedAddressesResult(status); 8475 break; 8476 8477 default: 8478 this.log.warn("Unrecognized status code for u144:" 8479 + " [" + status + "]."); 8480 } 8481 }; 8482 8483 /** 8484 * STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT 8485 */ 8486 net.user1.orbiter.CoreMessageListener.prototype.u146 = function (status) { 8487 switch (status) { 8488 case net.user1.orbiter.Status.SUCCESS: 8489 case net.user1.orbiter.Status.ERROR: 8490 case net.user1.orbiter.Status.NOT_WATCHING: 8491 this.clientMan.fireStopWatchingForBannedAddressesResult(status); 8492 break; 8493 8494 default: 8495 this.log.warn("Unrecognized status code for u146:" 8496 + " [" + status + "]."); 8497 } 8498 }; 8499 8500 /** 8501 * BANNED_ADDRESS_ADDED 8502 */ 8503 net.user1.orbiter.CoreMessageListener.prototype.u147 = function (address) { 8504 this.clientMan.addWatchedBannedAddress(address); 8505 }; 8506 8507 /** 8508 * BANNED_ADDRESS_REMOVED 8509 */ 8510 net.user1.orbiter.CoreMessageListener.prototype.u148 = function (address) { 8511 this.clientMan.removeWatchedBannedAddress(address); 8512 }; 8513 8514 /** 8515 * KICK_RESULT 8516 */ 8517 net.user1.orbiter.CoreMessageListener.prototype.u150 = function (clientID, status) { 8518 switch (status) { 8519 case net.user1.orbiter.Status.SUCCESS: 8520 case net.user1.orbiter.Status.ERROR: 8521 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 8522 case net.user1.orbiter.Status.PERMISSION_DENIED: 8523 this.clientMan.fireKickClientResult(clientID, status); 8524 break; 8525 8526 default: 8527 this.log.warn("Unrecognized status code for u150:" 8528 + " [" + status + "]."); 8529 } 8530 }; 8531 8532 /** 8533 * SERVERMODULELIST_SNAPSHOT 8534 */ 8535 net.user1.orbiter.CoreMessageListener.prototype.u152 = function (requestID, serverModuleListSource) { 8536 var moduleListArray = serverModuleListSource == "" ? [] : serverModuleListSource.split(net.user1.orbiter.Tokens.RS); 8537 var moduleList = []; 8538 for (var i = 0; i < moduleListArray.length; i+= 3) { 8539 moduleList.push(new ModuleDefinition(moduleListArray[i], 8540 moduleListArray[i+1], 8541 moduleListArray[i+2])); 8542 } 8543 8544 if (requestID == "") { 8545 this.log.warn("Incoming SERVERMODULELIST_SNAPSHOT UPC missing required requestID. Ignoring message."); 8546 } else { 8547 // Snapshot 8548 this.snapshotMan.receiveServerModuleListSnapshot(requestID, moduleList); 8549 } 8550 }; 8551 8552 /** 8553 * GET_UPC_STATS_SNAPSHOT_RESULT 8554 */ 8555 net.user1.orbiter.CoreMessageListener.prototype.u155 = function (requestID, 8556 status) { 8557 this.snapshotMan.receiveSnapshotResult(requestID, status); 8558 }; 8559 8560 /** 8561 * UPC_STATS_SNAPSHOT 8562 */ 8563 net.user1.orbiter.CoreMessageListener.prototype.u156 = function (requestID, 8564 totalUPCsProcessed, 8565 numUPCsInQueue, 8566 lastQueueWaitTime) { 8567 var longestUPCProcesses = Array.prototype.slice.call(arguments).slice(5); 8568 var upcProcessingRecord; 8569 for (var i = 0; i < longestUPCProcesses.length; i++) { 8570 upcProcessingRecord = new net.user1.orbiter.UPCProcessingRecord(); 8571 upcProcessingRecord.deserialize(longestUPCProcesses[i]); 8572 longestUPCProcesses[i] = upcProcessingRecord; 8573 } 8574 8575 this.snapshotMan.receiveUPCStatsSnapshot(requestID, 8576 parseFloat(totalUPCsProcessed), 8577 parseFloat(numUPCsInQueue), 8578 parseFloat(lastQueueWaitTime), 8579 longestUPCProcesses); 8580 }; 8581 8582 /** 8583 * RESET_UPC_STATS_RESULT 8584 */ 8585 net.user1.orbiter.CoreMessageListener.prototype.u158 = function (status) { 8586 switch (status) { 8587 case net.user1.orbiter.Status.SUCCESS: 8588 case net.user1.orbiter.Status.ERROR: 8589 case net.user1.orbiter.Status.PERMISSION_DENIED: 8590 this.orbiter.getServer().dispatchResetUPCStatsResult(status); 8591 break; 8592 8593 default: 8594 this.log.warn("Unrecognized status code for u158." 8595 + "Status: [" + status + "]."); 8596 } 8597 }; 8598 8599 /** 8600 * WATCH_FOR_PROCESSED_UPCS_RESULT 8601 */ 8602 net.user1.orbiter.CoreMessageListener.prototype.u160 = function (status) { 8603 switch (status) { 8604 case net.user1.orbiter.Status.SUCCESS: 8605 this.orbiter.getServer().setIsWatchingForProcessedUPCs(true); 8606 case net.user1.orbiter.Status.ERROR: 8607 case net.user1.orbiter.Status.ALREADY_WATCHING: 8608 case net.user1.orbiter.Status.PERMISSION_DENIED: 8609 this.orbiter.getServer().dispatchWatchForProcessedUPCsResult(status); 8610 break; 8611 8612 default: 8613 this.log.warn("Unrecognized status code for u160." 8614 + "Status: [" + status + "]."); 8615 } 8616 }; 8617 8618 /** 8619 * PROCESSED_UPC_ADDED 8620 */ 8621 net.user1.orbiter.CoreMessageListener.prototype.u161 = function (fromClientID, 8622 fromUserID, 8623 fromClientAddress, 8624 queuedAt, 8625 processingStartedAt, 8626 processingFinishedAt, 8627 source) { 8628 var upcProcessingRecord = new net.user1.orbiter.UPCProcessingRecord(); 8629 upcProcessingRecord.deserializeParts(fromClientID, 8630 fromUserID, 8631 fromClientAddress, 8632 queuedAt, 8633 processingStartedAt, 8634 processingFinishedAt, 8635 source); 8636 this.orbiter.getServer().dispatchUPCProcessed(upcProcessingRecord); 8637 }; 8638 8639 /** 8640 * STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT 8641 */ 8642 net.user1.orbiter.CoreMessageListener.prototype.u163 = function (status) { 8643 switch (status) { 8644 case net.user1.orbiter.Status.SUCCESS: 8645 this.orbiter.getServer().setIsWatchingForProcessedUPCs(false); 8646 case net.user1.orbiter.Status.ERROR: 8647 case net.user1.orbiter.Status.NOT_WATCHING: 8648 case net.user1.orbiter.Status.PERMISSION_DENIED: 8649 this.orbiter.getServer().dispatchStopWatchingForProcessedUPCsResult(status); 8650 break; 8651 8652 default: 8653 this.log.warn("Unrecognized status code for u163." 8654 + "Status: [" + status + "]."); 8655 } 8656 }; 8657 8658 8659 /** 8660 * NODELIST_SNAPSHOT 8661 */ 8662 net.user1.orbiter.CoreMessageListener.prototype.u166 = function (requestID, nodeListSource) { 8663 var nodeIDs = nodeListSource == "" ? [] : nodeListSource.split(net.user1.orbiter.Tokens.RS); 8664 8665 if (requestID == "") { 8666 this.log.warn("Incoming NODELIST_SNAPSHOT UPC missing required requestID. Ignoring message."); 8667 } else { 8668 // Snapshot 8669 this.snapshotMan.receiveNodeListSnapshot(requestID, nodeIDs); 8670 } 8671 }; 8672 8673 /** 8674 * GATEWAYS_SNAPSHOT 8675 */ 8676 net.user1.orbiter.CoreMessageListener.prototype.u168 = function (requestID) { 8677 var gatewayListSource = Array.prototype.slice.call(arguments).slice(1); 8678 var gateways = []; 8679 8680 var gateway; 8681 var gatewayBandwidth; 8682 var gatewayBandwidthSource; 8683 var gatewayIntervalSource; 8684 for (var i = 0; i < gatewayListSource.length; i+=8) { 8685 gateway = new net.user1.orbiter.Gateway(); 8686 gateway.id = gatewayListSource[i]; 8687 gateway.type = gatewayListSource[i+1]; 8688 8689 gateway.lifetimeConnectionsByCategory = gatewayListSource[i+2] === "" ? {} : this.createHashFromArg(gatewayListSource[i+2]); 8690 for (var p in gateway.lifetimeConnectionsByCategory) { 8691 gateway.lifetimeConnectionsByCategory[p] = parseFloat(gateway.lifetimeConnectionsByCategory[p]); 8692 } 8693 gateway.lifetimeClientsByType = gatewayListSource[i+3] === "" ? {} : this.createHashFromArg(gatewayListSource[i+3]); 8694 for (p in gateway.lifetimeClientsByType) { 8695 gateway.lifetimeClientsByType[p] = parseFloat(gateway.lifetimeClientsByType[p]); 8696 } 8697 gateway.lifetimeClientsByUPCVersion = gatewayListSource[i+4] === "" ? {} : this.createHashFromArg(gatewayListSource[i+4]); 8698 for (p in gateway.lifetimeClientsByUPCVersion) { 8699 gateway.lifetimeClientsByUPCVersion[p] = parseFloat(gateway.lifetimeClientsByUPCVersion[p]); 8700 } 8701 gateway.attributes = gatewayListSource[i+5] === "" ? {} : this.createHashFromArg(gatewayListSource[i+5]); 8702 8703 gatewayIntervalSource = gatewayListSource[i+6].split(net.user1.orbiter.Tokens.RS); 8704 gateway.connectionsPerSecond = parseFloat(gatewayIntervalSource[0]); 8705 gateway.maxConnectionsPerSecond = parseFloat(gatewayIntervalSource[1]); 8706 gateway.clientsPerSecond = parseFloat(gatewayIntervalSource[2]); 8707 gateway.maxClientsPerSecond = parseFloat(gatewayIntervalSource[3]); 8708 8709 gatewayBandwidth = new net.user1.orbiter.GatewayBandwidth(); 8710 gatewayBandwidthSource = gatewayListSource[i+7].split(net.user1.orbiter.Tokens.RS); 8711 gatewayBandwidth.lifetimeRead = gatewayBandwidthSource[0] === "" ? 0 : parseFloat(gatewayBandwidthSource[0]); 8712 gatewayBandwidth.lifetimeWritten = gatewayBandwidthSource[1] === "" ? 0 : parseFloat(gatewayBandwidthSource[1]); 8713 gatewayBandwidth.averageRead = gatewayBandwidthSource[2] === "" ? 0 : parseFloat(gatewayBandwidthSource[2]); 8714 gatewayBandwidth.averageWritten = gatewayBandwidthSource[3] === "" ? 0 : parseFloat(gatewayBandwidthSource[3]); 8715 gatewayBandwidth.intervalRead = gatewayBandwidthSource[4] === "" ? 0 : parseFloat(gatewayBandwidthSource[4]); 8716 gatewayBandwidth.intervalWritten = gatewayBandwidthSource[5] === "" ? 0 : parseFloat(gatewayBandwidthSource[5]); 8717 gatewayBandwidth.maxIntervalRead = gatewayBandwidthSource[6] === "" ? 0 : parseFloat(gatewayBandwidthSource[6]); 8718 gatewayBandwidth.maxIntervalWritten = gatewayBandwidthSource[7] === "" ? 0 : parseFloat(gatewayBandwidthSource[7]); 8719 gatewayBandwidth.scheduledWrite = gatewayBandwidthSource[8] === "" ? 0 : parseFloat(gatewayBandwidthSource[8]); 8720 gateway.bandwidth = gatewayBandwidth; 8721 gateways.push(gateway); 8722 } 8723 8724 if (requestID == "") { 8725 this.log.warn("Incoming GATEWAYS_SNAPSHOT UPC missing required requestID. Ignoring message."); 8726 } else { 8727 // Snapshot 8728 this.snapshotMan.receiveGatewaysSnapshot(requestID, gateways); 8729 } 8730 }; 8731 //============================================================================== 8732 // CLASS DECLARATION 8733 //============================================================================== 8734 /** 8735 * @class 8736 */ 8737 net.user1.orbiter.CustomClient = function () { 8738 this.client = null; 8739 }; 8740 8741 /** 8742 * An initialization method invoked when this CustomClient object is ready 8743 * for use. Subclasses wishing to perform initialization tasks that require 8744 * this CustomClient's composed Client object should override this method. 8745 * 8746 * @since Orbiter 1.0.0 8747 */ 8748 net.user1.orbiter.CustomClient.prototype.init = function () { 8749 }; 8750 8751 net.user1.orbiter.CustomClient.prototype.addEventListener = function (type, 8752 listener, 8753 thisArg, 8754 priority) { 8755 this.client.addEventListener(type, listener, thisArg, priority); 8756 }; 8757 8758 net.user1.orbiter.CustomClient.prototype.dispatchEvent = function (event) { 8759 return this.client.dispatchEvent(event); 8760 }; 8761 8762 net.user1.orbiter.CustomClient.prototype.hasEventListener = function (type) { 8763 return this.client.hasEventListener(type); 8764 }; 8765 8766 net.user1.orbiter.CustomClient.prototype.removeEventListener = function (type, 8767 listener, 8768 thisObj) { 8769 this.client.removeEventListener(type, listener, thisObj); 8770 }; 8771 8772 net.user1.orbiter.CustomClient.prototype.willTrigger = function (type) { 8773 return this.client.willTrigger(type); 8774 }; 8775 8776 net.user1.orbiter.CustomClient.prototype.setClient = function (client) { 8777 this.client = client; 8778 }; 8779 8780 net.user1.orbiter.CustomClient.prototype.getClientID = function () { 8781 return this.client.getClientID(); 8782 }; 8783 8784 net.user1.orbiter.CustomClient.prototype.getConnectionState = function () { 8785 return this.client.getConnectionState(); 8786 }; 8787 8788 net.user1.orbiter.CustomClient.prototype.isSelf = function () { 8789 return this.client.isSelf(); 8790 }; 8791 8792 net.user1.orbiter.CustomClient.prototype.setClientClass = function (scope, 8793 clientClass) { 8794 var fallbackClasses = Array.prototype.slice.call(arguments).slice(2); 8795 this.client.setClientClass.apply(this.client, [scope, clientClass].concat(fallbackClasses)); 8796 }; 8797 8798 net.user1.orbiter.CustomClient.prototype.isInRoom = function (roomID) { 8799 return this.client.isInRoom(roomID); 8800 }; 8801 8802 net.user1.orbiter.CustomClient.prototype.isObservingRoom = function (roomID) { 8803 return this.client.isObservingRoom(roomID); 8804 }; 8805 8806 net.user1.orbiter.CustomClient.prototype.getOccupiedRoomIDs = function () { 8807 return this.client.getOccupiedRoomIDs(); 8808 }; 8809 8810 net.user1.orbiter.CustomClient.prototype.getObservedRoomIDs = function () { 8811 return this.client.getObservedRoomIDs(); 8812 }; 8813 8814 net.user1.orbiter.CustomClient.prototype.getIP = function () { 8815 return this.client.getIP(); 8816 }; 8817 8818 net.user1.orbiter.CustomClient.prototype.getConnectTime = function () { 8819 return this.client.getConnectTime(); 8820 }; 8821 8822 net.user1.orbiter.CustomClient.prototype.getPing = function () { 8823 return this.client.getPing(); 8824 }; 8825 8826 net.user1.orbiter.CustomClient.prototype.getTimeOnline = function () { 8827 return this.client.getTimeOnline(); 8828 }; 8829 8830 net.user1.orbiter.CustomClient.prototype.sendMessage = function (messageName) { 8831 var args = Array.prototype.slice.call(arguments).slice(0); 8832 this.client.sendMessage.apply(this.client, args); 8833 }; 8834 8835 net.user1.orbiter.CustomClient.prototype.setAttribute = function (attrName, 8836 attrValue, 8837 attrScope, 8838 isShared, 8839 evaluate) { 8840 this.client.setAttribute(attrName, attrValue, attrScope, isShared, evaluate); 8841 }; 8842 8843 net.user1.orbiter.CustomClient.prototype.deleteAttribute = function (attrName, attrScope) { 8844 this.client.deleteAttribute(attrName, attrScope); 8845 }; 8846 8847 net.user1.orbiter.CustomClient.prototype.getAttribute = function (attrName, attrScope) { 8848 return this.client.getAttribute(attrName, attrScope); 8849 }; 8850 8851 net.user1.orbiter.CustomClient.prototype.getAttributes = function () { 8852 return this.client.getAttributes(); 8853 }; 8854 8855 net.user1.orbiter.CustomClient.prototype.getAttributesByScope = function (scope) { 8856 return this.client.getAttributesByScope(); 8857 }; 8858 8859 net.user1.orbiter.CustomClient.prototype.getClientManager = function () { 8860 return this.client.getClientManager(); 8861 }; 8862 8863 net.user1.orbiter.CustomClient.prototype.getAccount = function () { 8864 return this.client.getAccount(); 8865 }; 8866 8867 net.user1.orbiter.CustomClient.prototype.kick = function () { 8868 this.client.kick(); 8869 }; 8870 8871 net.user1.orbiter.CustomClient.prototype.ban = function (duration, reason) { 8872 this.client.ban(duration, reason); 8873 }; 8874 8875 net.user1.orbiter.CustomClient.prototype.observe = function () { 8876 this.client.observe(); 8877 }; 8878 8879 net.user1.orbiter.CustomClient.prototype.stopObserving = function () { 8880 this.client.stopObserving(); 8881 }; 8882 8883 net.user1.orbiter.CustomClient.prototype.isAdmin = function () { 8884 return this.client.isAdmin(); 8885 }; 8886 8887 net.user1.orbiter.CustomClient.prototype.toString = function () { 8888 return "[object CustomClient, ID: " + this.getClientID() + "]"; 8889 }; 8890 //============================================================================== 8891 // EVENT UTILITIES 8892 //============================================================================== 8893 /** @class */ 8894 net.user1.utils.EventUtil = new Object(); 8895 8896 net.user1.utils.EventUtil.migrateListeners = function (oldObject, 8897 newObject, 8898 events, 8899 thisObj) { 8900 var len = events.length 8901 for (var i = 0; i < len; i += 2) { 8902 if (oldObject != null) { 8903 oldObject.removeEventListener(events[i], events[i+1], thisObj); 8904 } 8905 if (newObject != null) { 8906 newObject.addEventListener(events[i], events[i+1], thisObj); 8907 } 8908 } 8909 }; 8910 //============================================================================== 8911 // CLASS DECLARATION 8912 //============================================================================== 8913 /** 8914 * @class 8915 */ 8916 net.user1.orbiter.filters.FilterSet = function () { 8917 this.filters = new Array(); 8918 }; 8919 8920 net.user1.orbiter.filters.FilterSet.prototype.addFilter = function (filter) { 8921 this.filters.push(filter); 8922 }; 8923 8924 net.user1.orbiter.filters.FilterSet.prototype.getFilters = function () { 8925 return this.filters.slice(0); 8926 }; 8927 8928 net.user1.orbiter.filters.FilterSet.prototype.toXMLString = function () { 8929 var s = "<filters>\n"; 8930 8931 var filter; 8932 for (var i = 0; i < this.filters.length; i++) { 8933 filter = this.filters[i]; 8934 s += filter.toXMLString() + "\n"; 8935 } 8936 s += "</filters>"; 8937 return s; 8938 }; 8939 //============================================================================== 8940 // CLASS DECLARATION 8941 //============================================================================== 8942 /** 8943 * @class 8944 */ 8945 net.user1.orbiter.GatewayBandwidth = function () { 8946 /** 8947 * @field 8948 * @type Number 8949 */ 8950 this.lifetimeRead = 0; 8951 /** 8952 * @field 8953 * @type Number 8954 */ 8955 this.lifetimeWritten = 0; 8956 /** 8957 * @field 8958 * @type Number 8959 */ 8960 this.averageRead = 0; 8961 /** 8962 * @field 8963 * @type Number 8964 */ 8965 this.averageWritten = 0; 8966 /** 8967 * @field 8968 * @type Number 8969 */ 8970 this.intervalRead = 0; 8971 /** 8972 * @field 8973 * @type Number 8974 */ 8975 this.intervalWritten = 0; 8976 /** 8977 * @field 8978 * @type Number 8979 */ 8980 this.maxIntervalRead = 0; 8981 /** 8982 * @field 8983 * @type Number 8984 */ 8985 this.maxIntervalWritten = 0; 8986 /** 8987 * @field 8988 * @type Number 8989 */ 8990 this.scheduledWrite = 0; 8991 }; 8992 //============================================================================== 8993 // CLASS DECLARATION 8994 //============================================================================== 8995 /** 8996 * @class 8997 */ 8998 net.user1.orbiter.Gateway = function () { 8999 /** 9000 * @field 9001 * @type String 9002 this.id = null; 9003 /** 9004 * @field 9005 * @type String 9006 */ 9007 this.type = null; 9008 /** 9009 * @field 9010 * @type Object 9011 */ 9012 this.lifetimeConnectionsByCategory = null; 9013 /** 9014 * @field 9015 * @type Object 9016 */ 9017 this.lifetimeClientsByType = null; 9018 /** 9019 * @field 9020 * @type Object 9021 */ 9022 this.lifetimeClientsByUPCVersion = null; 9023 /** 9024 * @field 9025 * @type Object 9026 */ 9027 this.attributes = null; 9028 /** 9029 * @field 9030 * @type Number 9031 */ 9032 this.connectionsPerSecond = 0; 9033 /** 9034 * @field 9035 * @type Number 9036 */ 9037 this.maxConnectionsPerSecond = 0; 9038 /** 9039 * @field 9040 * @type Number 9041 */ 9042 this.clientsPerSecond = 0; 9043 /** 9044 * @field 9045 * @type Number 9046 */ 9047 this.maxClientsPerSecond = 0; 9048 /** 9049 * @field 9050 * @type net.user1.orbiter.GatewayBandwidth 9051 */ 9052 this.bandwidth = null; 9053 }; 9054 //============================================================================== 9055 // CLASS DECLARATION 9056 //============================================================================== 9057 /** 9058 * @class 9059 */ 9060 net.user1.utils.LRUCache = function (maxLength) { 9061 this.maxLength = maxLength; 9062 this.length = 0; 9063 this.hash = new net.user1.utils.UDictionary(); 9064 this.first = null; 9065 this.last = null; 9066 }; 9067 9068 net.user1.utils.LRUCache.prototype.get = function (key) { 9069 var node = this.hash[key]; 9070 9071 if (node != null) { 9072 this.moveToHead(node); 9073 return node.value; 9074 } else { 9075 return null; 9076 } 9077 }; 9078 9079 net.user1.utils.LRUCache.prototype.put = function (key, value) { 9080 var node = this.hash[key]; 9081 if (node == null) { 9082 if (this.length >= this.maxLength) { 9083 this.removeLast(); 9084 } else { 9085 this.length++; 9086 } 9087 node = new net.user1.utils.CacheNode(); 9088 } 9089 9090 node.value = value; 9091 node.key = key; 9092 this.moveToHead(node); 9093 this.hash[key] = node; 9094 }; 9095 9096 net.user1.utils.LRUCache.prototype.remove = function (key) { 9097 var node = this.hash[key]; 9098 if (node != null) { 9099 if (node.prev != null) { 9100 node.prev.next = node.next; 9101 } 9102 if (node.next != null) { 9103 node.next.prev = node.prev; 9104 } 9105 if (this.last == node) { 9106 this.last = node.prev; 9107 } 9108 if (this.first == node) { 9109 this.first = node.next; 9110 } 9111 } 9112 return node; 9113 } 9114 9115 net.user1.utils.LRUCache.prototype.clear = function () { 9116 this.first = null; 9117 this.last = null; 9118 this.length = 0; 9119 this.hash = new net.user1.utils.UDictionary(); 9120 }; 9121 9122 /** 9123 * @private 9124 */ 9125 net.user1.utils.LRUCache.prototype.removeLast = function () { 9126 if (this.last != null) { 9127 delete this.hash[this.last.key]; 9128 if (this.last.prev != null) { 9129 this.last.prev.next = null; 9130 } else { 9131 this.first = null; 9132 } 9133 this.last = this.last.prev; 9134 } 9135 }; 9136 9137 /** 9138 * @private 9139 */ 9140 net.user1.utils.LRUCache.prototype.moveToHead = function (node) { 9141 if (node == this.first) { 9142 return; 9143 } 9144 if (node.prev != null) { 9145 node.prev.next = node.next; 9146 } 9147 if (node.next != null) { 9148 node.next.prev = node.prev; 9149 } 9150 if (this.last == node) { 9151 this.last = node.prev; 9152 } 9153 if (this.first != null) { 9154 node.next = this.first; 9155 this.first.prev = node; 9156 } 9157 this.first = node; 9158 node.prev = null; 9159 if (this.last == null) { 9160 this.last = this.first; 9161 } 9162 }; 9163 //============================================================================== 9164 // CLASS DECLARATION 9165 //============================================================================== 9166 /** 9167 * @class 9168 */ 9169 net.user1.orbiter.ModuleDefinition = function (id, type, source) { 9170 this.id = id; 9171 this.type = type; 9172 this.source = source; 9173 }; 9174 //============================================================================== 9175 // MODULE TYPE CONSTANTS 9176 //============================================================================== 9177 /** @class */ 9178 net.user1.orbiter.ModuleType = new Object(); 9179 /** @constant */ 9180 net.user1.orbiter.ModuleType.CLASS = "class"; 9181 /** @constant */ 9182 net.user1.orbiter.ModuleType.SCRIPT = "script"; 9183 //============================================================================== 9184 // CLASS DECLARATION 9185 //============================================================================== 9186 /** 9187 * @class 9188 * @extends net.user1.orbiter.snapshot.Snapshot 9189 */ 9190 net.user1.orbiter.snapshot.NodeListSnapshot = function () { 9191 // Call superconstructor 9192 net.user1.orbiter.snapshot.Snapshot.call(this); 9193 this.nodeList = null; 9194 this.method = net.user1.orbiter.UPC.GET_NODELIST_SNAPSHOT; 9195 }; 9196 9197 //============================================================================== 9198 // INHERITANCE 9199 //============================================================================== 9200 net.user1.utils.extend(net.user1.orbiter.snapshot.NodeListSnapshot, net.user1.orbiter.snapshot.Snapshot); 9201 9202 //============================================================================== 9203 // INSTANCE METHODS 9204 //============================================================================== 9205 /** 9206 * @private 9207 */ 9208 net.user1.orbiter.snapshot.NodeListSnapshot.prototype.setNodeList = function (value) { 9209 this.nodeList = value; 9210 } 9211 9212 net.user1.orbiter.snapshot.NodeListSnapshot.prototype.getNodeList = function () { 9213 if (!this.nodeList) { 9214 return null; 9215 } 9216 return this.nodeList.slice(); 9217 }; 9218 //============================================================================== 9219 // A COLLECTION OF NUMERIC UTILITIES 9220 //============================================================================== 9221 /** @class */ 9222 net.user1.utils.integer = new Object(); 9223 /** @constant */ 9224 net.user1.utils.integer.MAX_VALUE = Math.pow(2,32) - 1; 9225 //============================================================================== 9226 // CLASS DECLARATION 9227 //============================================================================== 9228 /** 9229 * @class 9230 * @extends net.user1.orbiter.filters.BooleanGroup 9231 */ 9232 net.user1.orbiter.filters.OrGroup = function () { 9233 net.user1.orbiter.filters.BooleanGroup.call(this, net.user1.orbiter.filters.BooleanGroupType.OR); 9234 }; 9235 9236 //============================================================================== 9237 // INHERITANCE 9238 //============================================================================== 9239 net.user1.utils.extend(net.user1.orbiter.filters.OrGroup, net.user1.orbiter.filters.BooleanGroup); 9240 /** 9241 * @private 9242 */ 9243 net.user1.orbiter.upc.RemoveClientAttr = function (clientID, userID, name, scope) { 9244 // Abort if name is invalid. 9245 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 9246 throw new Error("Cannot delete attribute. Illegal name" + 9247 " (see Validator.isValidAttributeName()): " + name); 9248 } 9249 9250 // Abort if scope is invalid. 9251 if (!net.user1.orbiter.Validator.isValidAttributeScope(scope)) { 9252 throw new Error("Cannot delete client attribute. Illegal scope" + 9253 " (see Validator.isValidAttributeScope()): " + scope); 9254 } 9255 9256 this.method = net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR; 9257 this.args = [clientID, userID, name, scope]; 9258 }; 9259 /** 9260 * @private 9261 */ 9262 net.user1.orbiter.upc.RemoveRoomAttr = function (roomID, name) { 9263 // Abort if name is invalid. 9264 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 9265 throw new Error("Cannot delete attribute. Illegal name" + 9266 " (see Validator.isValidAttributeName()): " + name); 9267 } 9268 9269 this.method = net.user1.orbiter.UPC.REMOVE_ROOM_ATTR; 9270 this.args = [roomID, name]; 9271 }; 9272 /** @function */ 9273 net.user1.utils.resolveMemberExpression = function (value) { 9274 var parts = value.split("."); 9275 var reference = globalObject; 9276 for (var i = 0; i < parts.length; i++) { 9277 reference = reference[parts[i]]; 9278 } 9279 return reference; 9280 }; 9281 //============================================================================== 9282 // CLASS DECLARATION 9283 //============================================================================== 9284 /** @class 9285 9286 The Room class dispatches the following events: 9287 9288 <ul class="summary"> 9289 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.JOIN}</li> 9290 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.JOIN_RESULT}</li> 9291 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.LEAVE}</li> 9292 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.LEAVE_RESULT}</li> 9293 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.ADD_OCCUPANT}</li> 9294 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.REMOVE_OCCUPANT}</li> 9295 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.ADD_OBSERVER}</li> 9296 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.REMOVE_OBSERVER}</li> 9297 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.UPDATE_CLIENT_ATTRIBUTE}</li> 9298 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.DELETE_CLIENT_ATTRIBUTE}</li> 9299 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OCCUPANT_COUNT}</li> 9300 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OSERVER_COUNT}</li> 9301 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.SYNCHRONIZE}</li> 9302 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OBSERVE}</li> 9303 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OBSERVE_RESULT}</li> 9304 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.STOP_OBSERVING}</li> 9305 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT}</li> 9306 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.REMOVED}</li> 9307 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE}</li> 9308 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.UPDATE}</li> 9309 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.SET_RESULT}</li> 9310 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE_RESULT}</li> 9311 </ul> 9312 9313 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 9314 9315 @extends net.user1.events.EventDispatcher 9316 */ 9317 net.user1.orbiter.Room = function (id, 9318 roomManager, 9319 messageManager, 9320 clientManager, 9321 accountManager, 9322 log) { 9323 // Call superconstructor 9324 net.user1.events.EventDispatcher.call(this); 9325 9326 // Variables 9327 this.disposed = false; 9328 this.id = null; 9329 this.syncState = null; 9330 this._clientIsInRoom = false; 9331 this._clientIsObservingRoom = false; 9332 this.numOccupants = 0; 9333 this.numObservers = 0; 9334 this.defaultClientClass = null; 9335 9336 // Initialization 9337 this.setRoomID(id); 9338 this.roomManager = roomManager; 9339 this.messageManager = messageManager; 9340 this.clientManager = clientManager; 9341 this.accountManager = accountManager; 9342 this.log = log; 9343 9344 this.occupantList = new net.user1.orbiter.ClientSet(); 9345 this.observerList = new net.user1.orbiter.ClientSet(); 9346 this.attributeManager = new net.user1.orbiter.AttributeManager(this, this.messageManager, this.log); 9347 9348 this.setSyncState(net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED); 9349 } 9350 9351 //============================================================================== 9352 // INHERITANCE 9353 //============================================================================== 9354 net.user1.utils.extend(net.user1.orbiter.Room, net.user1.events.EventDispatcher); 9355 9356 // ============================================================================= 9357 // DEPENDENCIES 9358 // ============================================================================= 9359 /** @private */ 9360 net.user1.orbiter.Room.prototype.getAttributeManager = function () { 9361 return this.attributeManager; 9362 }; 9363 9364 // ============================================================================= 9365 // ROOM ID MANAGEMENT 9366 // ============================================================================= 9367 9368 /** 9369 * @private 9370 */ 9371 net.user1.orbiter.Room.prototype.setRoomID = function (roomID) { 9372 var errorMsg; 9373 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 9374 errorMsg = "Invalid room ID specified during room creation. Offending ID: " + roomID; 9375 this.log.error(errorMsg); 9376 throw new Error(errorMsg); 9377 } 9378 this.id = roomID; 9379 }; 9380 9381 net.user1.orbiter.Room.prototype.getRoomID = function () { 9382 return this.id; 9383 }; 9384 9385 net.user1.orbiter.Room.prototype.getSimpleRoomID = function () { 9386 return net.user1.orbiter.RoomIDParser.getSimpleRoomID(this.id); 9387 }; 9388 9389 net.user1.orbiter.Room.prototype.getQualifier = function () { 9390 return net.user1.orbiter.RoomIDParser.getQualifier(this.id); 9391 }; 9392 9393 // ============================================================================= 9394 // JOIN/LEAVE 9395 // ============================================================================= 9396 9397 net.user1.orbiter.Room.prototype.join = function (password, 9398 updateLevels) { 9399 if (this.disposed) return; 9400 9401 // Client can't join a room the its already in. 9402 if (this.clientIsInRoom()) { 9403 this.log.warn(this + "Room join attempt aborted. Already in room."); 9404 return; 9405 } 9406 // Validate the password 9407 if (password == null) { 9408 password = ""; 9409 } 9410 if (!net.user1.orbiter.Validator.isValidPassword(password)) { 9411 this.log.error(this + "Invalid room password supplied to join(). " 9412 + " Join request not sent. See Validator.isValidPassword()."); 9413 return; 9414 } 9415 9416 // If any update levels are specified, send them before joining. 9417 if (updateLevels != null) { 9418 this.setUpdateLevels(updateLevels); 9419 } 9420 9421 this.messageManager.sendUPC(net.user1.orbiter.UPC.JOIN_ROOM, 9422 this.getRoomID(), 9423 password); 9424 }; 9425 9426 net.user1.orbiter.Room.prototype.leave = function () { 9427 if (this.disposed) return; 9428 9429 if (this.clientIsInRoom()) { 9430 this.messageManager.sendUPC(net.user1.orbiter.UPC.LEAVE_ROOM, this.getRoomID()); 9431 } else { 9432 this.log.debug(this + " Leave-room request ignored. Not in room."); 9433 } 9434 }; 9435 9436 /** 9437 * @private 9438 */ 9439 net.user1.orbiter.Room.prototype.doJoin = function () { 9440 this._clientIsInRoom = true; 9441 this.fireJoin(); 9442 }; 9443 9444 /** 9445 * @private 9446 */ 9447 net.user1.orbiter.Room.prototype.doJoinResult = function (status) { 9448 this.fireJoinResult(status); 9449 }; 9450 9451 /** 9452 * @private 9453 */ 9454 net.user1.orbiter.Room.prototype.doLeave = function () { 9455 var rid = this.getRoomID(); 9456 9457 // If the client is not observing the room, then dispose 9458 // of all of the room's information. 9459 if (!this.clientIsObservingRoom()) { 9460 this.purgeRoomData(); 9461 } 9462 9463 // Note that the client is no longer in this room. 9464 this._clientIsInRoom = false; 9465 this.fireLeave(); 9466 } 9467 9468 /** 9469 * @private 9470 */ 9471 net.user1.orbiter.Room.prototype.doLeaveResult = function (status) { 9472 this.fireLeaveResult(status); 9473 }; 9474 9475 //============================================================================== 9476 // MESSAGING 9477 //============================================================================== 9478 9479 net.user1.orbiter.Room.prototype.sendMessage = function (messageName, 9480 includeSelf, 9481 filters) { 9482 if (this.disposed) return; 9483 9484 // Delegate to RoomManager.sendMessage() 9485 var rest = Array.prototype.slice.call(arguments).slice(3) 9486 var roomMan = this.roomManager; 9487 var args = [messageName, 9488 [this.getRoomID()], 9489 includeSelf, 9490 filters != null ? filters : null]; 9491 roomMan.sendMessage.apply(roomMan, args.concat(rest)); 9492 }; 9493 9494 net.user1.orbiter.Room.prototype.addMessageListener = function (message, listener, thisArg) { 9495 if (this.messageManager != null) { 9496 this.messageManager.addMessageListener(message, 9497 listener, 9498 thisArg, 9499 [this.getRoomID()]); 9500 } 9501 }; 9502 9503 net.user1.orbiter.Room.prototype.removeMessageListener = function (message, listener) { 9504 if (this.messageManager != null) { 9505 this.messageManager.removeMessageListener(message, 9506 listener); 9507 } 9508 }; 9509 9510 net.user1.orbiter.Room.prototype.hasMessageListener = function (message, 9511 listener) { 9512 // First, get the list of messsage listeners for this message 9513 var listeners = this.messageManager.getMessageListeners(message); 9514 var messageListener; 9515 for (var i = 0; i < listeners.length; i++) { 9516 messageListener = listeners[i]; 9517 var listenerRoomIDs = messageListener.getForRoomIDs(); 9518 // ===== Run once for each room id ===== 9519 var listenerRoomID; 9520 for (var j = 0; j < listenerRoomIDs.length; j++) { 9521 listenerRoomID = listenerRoomIDs[i]; 9522 if (listenerRoomID == this.getRoomID()) { 9523 return true; 9524 } 9525 } 9526 } 9527 return false; 9528 }; 9529 9530 //============================================================================== 9531 // SYNCHRONIZATION 9532 //============================================================================== 9533 9534 /** 9535 * @private 9536 */ 9537 net.user1.orbiter.Room.prototype.synchronize = function (manifest) { 9538 var oldSyncState = this.getSyncState(); 9539 this.log.debug(this + " Begin synchronization."); 9540 this.setSyncState(net.user1.orbiter.SynchronizationState.SYNCHRONIZING); 9541 9542 // SYNC ROOM ATTRIBUTES 9543 this.getAttributeManager().getAttributeCollection().synchronizeScope(net.user1.orbiter.Tokens.GLOBAL_ATTR, manifest.attributes); 9544 if (this.disposed) { 9545 return; 9546 } 9547 9548 // SYNC OCCUPANT LIST 9549 var oldOccupantList = this.getOccupantIDs(); 9550 var newOccupantList = []; 9551 var thisOccupantClientID; 9552 var thisOccupantUserID; 9553 var thisOccupant; 9554 var thisOccupantAccount; 9555 9556 // Add all unknown occupants to the room's occupant list, and 9557 // synchronize all existing occupants. 9558 for (var i = manifest.occupants.length; --i >= 0;) { 9559 thisOccupantClientID = manifest.occupants[i].clientID; 9560 thisOccupantUserID = manifest.occupants[i].userID; 9561 9562 newOccupantList.push(thisOccupantClientID); 9563 9564 thisOccupant = this.clientManager.requestClient(thisOccupantClientID); 9565 // Init user account, if any 9566 thisOccupantAccount = this.accountManager.requestAccount(thisOccupantUserID); 9567 if (thisOccupantAccount != null) { 9568 thisOccupant.setAccount(thisOccupantAccount); 9569 } 9570 9571 // If it's not the current client, update it. 9572 // The current client obtains its attributes through separate u8s. 9573 if (!thisOccupant.isSelf()) { 9574 thisOccupant.synchronize(manifest.occupants[i]); 9575 } 9576 9577 this.addOccupant(thisOccupant); 9578 if (this.disposed) { 9579 return; 9580 } 9581 } 9582 9583 // Remove occupants that are now gone... 9584 var oldClientID; 9585 for (i = oldOccupantList.length; --i >= 0;) { 9586 oldClientID = oldOccupantList[i]; 9587 if (net.user1.utils.ArrayUtil.indexOf(newOccupantList, oldClientID) == -1) { 9588 this.removeOccupant(oldClientID); 9589 if (this.disposed) { 9590 return; 9591 } 9592 } 9593 } 9594 9595 // SYNC OBSERVER LIST 9596 var oldObserverList = this.getObserverIDs(); 9597 var newObserverList = []; 9598 var thisObserverClientID; 9599 var thisObserverUserID; 9600 var thisObserver; 9601 var thisObserverAccount; 9602 9603 // Add all unknown observers to the room's observer list, and 9604 // synchronize all existing observers. 9605 for (i = manifest.observers.length; --i >= 0;) { 9606 thisObserverClientID = manifest.observers[i].clientID; 9607 thisObserverUserID = manifest.observers[i].userID; 9608 9609 newObserverList.push(thisObserverClientID); 9610 9611 thisObserver = this.clientManager.requestClient(thisObserverClientID); 9612 // Init user account, if any 9613 thisObserverAccount = this.accountManager.requestAccount(thisObserverUserID); 9614 if (thisObserverAccount != null) { 9615 thisObserver.setAccount(thisObserverAccount); 9616 } 9617 9618 // If it's not the current client, update it. 9619 // The current client obtains its attributes through separate u8s. 9620 if (!thisObserver.isSelf()) { 9621 thisObserver.synchronize(manifest.observers[i]); 9622 } 9623 9624 this.addObserver(thisObserver); 9625 if (this.disposed) { 9626 return; 9627 } 9628 } 9629 9630 // Remove observers that are now gone... 9631 var oldClientID; 9632 for (i = oldObserverList.length; --i >= 0;) { 9633 oldClientID = oldObserverList[i] 9634 if (net.user1.utils.ArrayUtil.indexOf(newObserverList, oldClientID) == -1) { 9635 this.removeObserver(oldClientID); 9636 if (this.disposed) { 9637 return; 9638 } 9639 } 9640 } 9641 9642 // UPDATE CLIENT COUNTS 9643 // If a client list is available, use its length to calculate the 9644 // client count. That way, the list length and the "get count" method 9645 // return values will be the same (e.g., getOccupants().length and 9646 // getNumOccupants()). Otherwise, rely on the server's reported count. 9647 var levels = this.clientManager.self().getUpdateLevels(this.getRoomID()); 9648 if (levels.occupantList) { 9649 this.setNumOccupants(this.occupantList.length()); 9650 } else if (levels.occupantCount) { 9651 this.setNumOccupants(manifest.occupantCount); 9652 } 9653 if (levels.observerList) { 9654 this.setNumObservers(this.observerList.length()); 9655 } else if (levels.observerCount) { 9656 this.setNumObservers(manifest.observerCount); 9657 } 9658 9659 // Update sync state 9660 this.setSyncState(oldSyncState); 9661 9662 // Tell listeners that synchronization is complete 9663 this.fireSynchronize(net.user1.orbiter.Status.SUCCESS); 9664 } 9665 9666 /** 9667 * @private 9668 */ 9669 net.user1.orbiter.Room.prototype.setSyncState = function (newSyncState) { 9670 this.syncState = newSyncState; 9671 }; 9672 9673 /** 9674 * @private 9675 */ 9676 net.user1.orbiter.Room.prototype.updateSyncState = function () { 9677 if (this.disposed) { 9678 this.setSyncState(net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED); 9679 } else { 9680 if (this.roomManager.hasObservedRoom(this.getRoomID()) 9681 || this.roomManager.hasOccupiedRoom(this.getRoomID()) 9682 || this.roomManager.hasWatchedRoom(this.getRoomID())) { 9683 this.setSyncState(net.user1.orbiter.SynchronizationState.SYNCHRONIZED); 9684 } else { 9685 this.setSyncState(net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED); 9686 } 9687 } 9688 } 9689 9690 net.user1.orbiter.Room.prototype.getSyncState = function () { 9691 return this.syncState; 9692 }; 9693 9694 //============================================================================== 9695 // UPDATE LEVELS 9696 //============================================================================== 9697 9698 net.user1.orbiter.Room.prototype.setUpdateLevels = function (updateLevels) { 9699 if (this.messageManager) { 9700 this.messageManager.sendUPC(net.user1.orbiter.UPC.SET_ROOM_UPDATE_LEVELS, 9701 this.getRoomID(), 9702 updateLevels.toInt()); 9703 } 9704 }; 9705 9706 //============================================================================== 9707 // OBSERVATION 9708 //============================================================================== 9709 9710 net.user1.orbiter.Room.prototype.observe = function (password, 9711 updateLevels) { 9712 if (this.disposed) return; 9713 9714 this.roomManager.observeRoom(this.getRoomID(), 9715 password, 9716 updateLevels); 9717 }; 9718 9719 9720 net.user1.orbiter.Room.prototype.stopObserving = function () { 9721 if (this.disposed) return; 9722 9723 if (this.clientIsObservingRoom()) { 9724 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_OBSERVING_ROOM, this.getRoomID()); 9725 } else { 9726 this.log.debug(this + " Stop-observing-room request ignored. Not observing room."); 9727 } 9728 }; 9729 9730 /** 9731 * @private 9732 */ 9733 net.user1.orbiter.Room.prototype.doObserve = function () { 9734 this._clientIsObservingRoom = true; 9735 this.fireObserve(); 9736 }; 9737 9738 /** 9739 * @private 9740 */ 9741 net.user1.orbiter.Room.prototype.doObserveResult = function (status) { 9742 this.fireObserveResult(status); 9743 }; 9744 9745 /** 9746 * @private 9747 */ 9748 net.user1.orbiter.Room.prototype.doStopObserving = function () { 9749 var rid = this.getRoomID(); 9750 9751 // If the client is not in the room, then we dispose 9752 // of all of the room's information. 9753 if (!this.clientIsInRoom()) { 9754 this.purgeRoomData(); 9755 } 9756 9757 this._clientIsObservingRoom = false; 9758 9759 this.fireStopObserving(); 9760 }; 9761 9762 /** 9763 * @private 9764 */ 9765 net.user1.orbiter.Room.prototype.doStopObservingResult = function (status) { 9766 this.fireStopObservingResult(status); 9767 } 9768 9769 //============================================================================== 9770 // OCCUPANT MANAGEMENT 9771 //============================================================================== 9772 9773 /** 9774 * @private 9775 */ 9776 net.user1.orbiter.Room.prototype.addOccupant = function (client) { 9777 // Don't add the client if it's already in the list. 9778 if (this.occupantList.contains(client)) { 9779 this.log.info(this + " ignored addOccupant() request. Occupant list" + 9780 " already contains client:" + client + "."); 9781 return; 9782 } 9783 9784 // Add the client 9785 this.occupantList.add(client); 9786 9787 // Update the number of clients in the room 9788 this.setNumOccupants(this.occupantList.length()); 9789 9790 // Register for attribute change events 9791 if (!this.observerList.contains(client)) { 9792 this.addClientAttributeListeners(client); 9793 } 9794 9795 // Tell listeners an occupant was added 9796 this.fireAddOccupant(client.getClientID()); 9797 }; 9798 9799 /** 9800 * @private 9801 */ 9802 net.user1.orbiter.Room.prototype.removeOccupant = function (clientID) { 9803 var client = this.occupantList.removeByClientID(clientID); 9804 var clientFound = client != null; 9805 9806 // Update the number of clients in the room 9807 this.setNumOccupants(this.occupantList.length()); 9808 9809 // Unregister for attribute change events 9810 if (!this.observerList.contains(client)) { 9811 this.removeClientAttributeListeners(client); 9812 } 9813 9814 // Tell listeners an occupant was removed 9815 var customClient = client.getCustomClient(this.getRoomID()); 9816 this.fireRemoveOccupant(customClient != null ? customClient : client); 9817 9818 if (!clientFound) { 9819 this.log.debug(this + " could not remove occupant: " 9820 + clientID + ". No such client in the room's occupant list."); 9821 } 9822 }; 9823 9824 net.user1.orbiter.Room.prototype.getOccupantIDs = function () { 9825 if (this.disposed) return null; 9826 9827 return this.occupantList.getAllIDs(); 9828 } 9829 9830 net.user1.orbiter.Room.prototype.getOccupants = function () { 9831 if (this.disposed) return null; 9832 9833 var occupants = this.occupantList.getAll(); 9834 var occupantsList = new Array(); 9835 var customClient; 9836 var occupant; 9837 9838 for (var clientID in occupants) { 9839 occupant = occupants[clientID]; 9840 customClient = occupant.getCustomClient(this.getRoomID()); 9841 if (customClient != null) { 9842 occupantsList.push(customClient); 9843 } else { 9844 occupantsList.push(occupant); 9845 } 9846 } 9847 return occupantsList; 9848 } 9849 9850 /** 9851 * @private 9852 */ 9853 net.user1.orbiter.Room.prototype.getOccupantsInternal = function () { 9854 return this.occupantList.getAll(); 9855 } 9856 9857 net.user1.orbiter.Room.prototype.clientIsInRoom = function (clientID) { 9858 if (this.disposed) return false; 9859 9860 if (clientID == null) { 9861 return this._clientIsInRoom; 9862 } 9863 return this.occupantList.containsClientID(clientID); 9864 }; 9865 9866 net.user1.orbiter.Room.prototype.getNumOccupants = function () { 9867 if (this.disposed) return 0; 9868 9869 var levels = this.clientManager.self().getUpdateLevels(this.getRoomID());; 9870 if (levels != null) { 9871 if (levels.occupantCount || levels.occupantList) { 9872 return this.numOccupants; 9873 } else { 9874 this.log.warn(this + " getNumOccupants() called, but no occupant count is " + 9875 "available. To enable occupant count, turn on occupant list" + 9876 " updates or occupant count updates via the Room's setUpdateLevels()" + 9877 " method."); 9878 return 0; 9879 } 9880 } else { 9881 this.log.debug(this + " getNumOccupants() called, but the current client's update" 9882 + " levels for the room are unknown. To determine the room's" 9883 + " occupant count, first join or observe the room."); 9884 return 0; 9885 } 9886 }; 9887 9888 /** 9889 * @private 9890 */ 9891 net.user1.orbiter.Room.prototype.setNumOccupants = function (newNumOccupants) { 9892 var oldNumClients = this.numOccupants; 9893 this.numOccupants = newNumOccupants; 9894 9895 // Tell listeners that the number of clients in the room has changed. 9896 if (oldNumClients != newNumOccupants) { 9897 this.fireOccupantCount(newNumOccupants); 9898 } 9899 }; 9900 9901 //============================================================================== 9902 // ROOM SETTINGS 9903 //============================================================================== 9904 9905 net.user1.orbiter.Room.prototype.getRoomSettings = function () { 9906 if (this.disposed) return null; 9907 9908 var settings = new net.user1.orbiter.RoomSettings(); 9909 var maxClients = this.getAttribute(net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR); 9910 var removeOnEmpty = this.getAttribute(net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR); 9911 9912 settings.maxClients = maxClients == null ? null : maxClients; 9913 switch (removeOnEmpty) { 9914 case null: 9915 settings.removeOnEmpty = null; 9916 break; 9917 9918 case "true": 9919 settings.removeOnEmpty = true; 9920 break; 9921 9922 case "false": 9923 settings.removeOnEmpty = false; 9924 break; 9925 } 9926 9927 return settings; 9928 }; 9929 9930 net.user1.orbiter.Room.prototype.setRoomSettings = function (settings) { 9931 if (this.disposed) return; 9932 9933 if (settings.maxClients != null) { 9934 this.setAttribute(net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR, settings.maxClients.toString()); 9935 } 9936 if (settings.password != null) { 9937 this.setAttribute(net.user1.orbiter.Tokens.PASSWORD_ATTR, settings.password); 9938 } 9939 if (settings.removeOnEmpty != null) { 9940 this.setAttribute(net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR, settings.removeOnEmpty.toString()); 9941 } 9942 }; 9943 9944 //============================================================================== 9945 // OBSERVER MANAGEMENT 9946 //============================================================================== 9947 9948 /** 9949 * @private 9950 */ 9951 net.user1.orbiter.Room.prototype.addObserver = function (client) { 9952 // Don't add the client if it's already in the list. 9953 if (this.observerList.contains(client)) { 9954 this.log.info(this + " ignored addObserver() request. Observer list" + 9955 " already contains client:" + client + "."); 9956 return; 9957 } 9958 9959 // Add the client 9960 this.observerList.add(client); 9961 9962 // Update the number of clients in the room 9963 this.setNumObservers(this.observerList.length()); 9964 9965 // Register for attribute change events 9966 if (!this.occupantList.contains(client)) { 9967 this.addClientAttributeListeners(client); 9968 } 9969 9970 // Tell listeners an observer was added 9971 this.fireAddObserver(client.getClientID()); 9972 }; 9973 9974 /** 9975 * @private 9976 */ 9977 net.user1.orbiter.Room.prototype.removeObserver = function (clientID) { 9978 var client = this.observerList.removeByClientID(clientID); 9979 var clientFound = client != null; 9980 9981 // Update the number of clients in the room 9982 this.setNumObservers(this.observerList.length()); 9983 9984 // Unregister for attribute change events 9985 if (!this.occupantList.contains(client)) { 9986 this.removeClientAttributeListeners(client); 9987 } 9988 9989 // Tell listeners an observer was removed 9990 var customClient = client.getCustomClient(this.getRoomID()); 9991 this.fireRemoveObserver(customClient != null ? customClient : client); 9992 9993 if (!clientFound) { 9994 this.log.debug(this + " could not remove observer: " 9995 + clientID + ". No such client in the room's observer list."); 9996 } 9997 }; 9998 9999 net.user1.orbiter.Room.prototype.getObserverIDs = function () { 10000 if (this.disposed) return null; 10001 10002 return this.observerList.getAllIDs(); 10003 }; 10004 10005 net.user1.orbiter.Room.prototype.getObservers = function () { 10006 if (this.disposed) return null; 10007 10008 var observers = this.observerList.getAll(); 10009 var observersList = new Array(); 10010 var customClient; 10011 var observer; 10012 10013 for (var clientID in observers) { 10014 observer = observers[clientID]; 10015 customClient = observer.getCustomClient(this.getRoomID()); 10016 if (customClient != null) { 10017 observersList.push(customClient); 10018 } else { 10019 observersList.push(observer); 10020 } 10021 } 10022 return observersList; 10023 }; 10024 10025 /** 10026 * @private 10027 */ 10028 net.user1.orbiter.Room.prototype.getObserversInternal = function () { 10029 return this.observerList.getAll(); 10030 } 10031 10032 net.user1.orbiter.Room.prototype.clientIsObservingRoom = function (clientID) { 10033 if (this.disposed) return false; 10034 10035 if (clientID == null) { 10036 return this._clientIsObservingRoom; 10037 } 10038 return this.observerList.containsClientID(clientID); 10039 } 10040 10041 net.user1.orbiter.Room.prototype.getNumObservers = function () { 10042 if (this.disposed) return 0; 10043 10044 var levels = this.clientManager.self().getUpdateLevels(this.getRoomID()); 10045 if (levels != null) { 10046 if (levels.observerCount || levels.observerList) { 10047 return this.numObservers; 10048 } else { 10049 this.log.warn(this + " getNumObservers() called, but no observer count is " + 10050 "available. To enable observer count, turn on observer list" + 10051 " updates or observer count updates via the Room's setUpdateLevels()" + 10052 " method."); 10053 return 0; 10054 } 10055 } else { 10056 this.log.warn(this + " getNumObservers() called, but the current client's update " 10057 + " levels for the room are unknown. Please report this issue to union@user1.net."); 10058 return 0; 10059 } 10060 }; 10061 10062 /** 10063 * @private 10064 */ 10065 net.user1.orbiter.Room.prototype.setNumObservers = function (newNumObservers) { 10066 var oldNumClients = this.numObservers; 10067 this.numObservers = newNumObservers; 10068 10069 // Tell listeners that the number of clients in the room has changed. 10070 if (oldNumClients != newNumObservers) { 10071 this.fireObserverCount(newNumObservers); 10072 } 10073 }; 10074 10075 //============================================================================== 10076 // CLIENT ACCESS 10077 //============================================================================== 10078 10079 net.user1.orbiter.Room.prototype.getClient = function (id) { 10080 if (this.disposed) return null; 10081 10082 var customClient; 10083 var client = this.occupantList.getByClientID(id); 10084 client = (client == null) ? this.observerList.getByClientID(id) : client; 10085 10086 if (client != null) { 10087 customClient = client.getCustomClient(this.getRoomID()); 10088 } 10089 return customClient == null ? client : customClient; 10090 }; 10091 10092 //============================================================================== 10093 // CLIENT ATTRIBUTE LISTENERS 10094 //============================================================================== 10095 /** private */ 10096 net.user1.orbiter.Room.prototype.addClientAttributeListeners = function (client) { 10097 client.addEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateClientAttributeListener, this); 10098 client.addEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteClientAttributeListener, this); 10099 }; 10100 10101 /** private */ 10102 net.user1.orbiter.Room.prototype.removeClientAttributeListeners = function (client) { 10103 client.removeEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateClientAttributeListener, this); 10104 client.removeEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteClientAttributeListener, this); 10105 }; 10106 10107 /** private */ 10108 net.user1.orbiter.Room.prototype.updateClientAttributeListener = function (e) { 10109 var attr = e.getChangedAttr(); 10110 var client = e.target; 10111 var customClient = client.getCustomClient(this.getRoomID()); 10112 10113 this.fireUpdateClientAttribute(customClient == null ? client : customClient, 10114 attr.scope, attr.name, attr.value, attr.oldValue); 10115 }; 10116 10117 /** private */ 10118 net.user1.orbiter.Room.prototype.deleteClientAttributeListener = function (e) { 10119 var attr = e.getChangedAttr(); 10120 var client = e.target; 10121 var customClient = client.getCustomClient(this.getRoomID()); 10122 10123 this.fireDeleteClientAttribute(customClient == null ? client : customClient, 10124 attr.scope, attr.name, attr.value); 10125 } 10126 10127 //============================================================================== 10128 // CLIENT CLASS 10129 //============================================================================== 10130 10131 net.user1.orbiter.Room.prototype.setDefaultClientClass = function (defaultClass) { 10132 this.defaultClientClass = defaultClass; 10133 }; 10134 10135 net.user1.orbiter.Room.prototype.getDefaultClientClass = function () { 10136 return this.defaultClientClass; 10137 } 10138 10139 //============================================================================== 10140 // ATTRIBUTES 10141 //============================================================================== 10142 10143 net.user1.orbiter.Room.prototype.setAttribute = function (attrName, 10144 attrValue, 10145 isShared, 10146 isPersistent, 10147 evaluate) { 10148 if (this.disposed) return; 10149 10150 if (isShared !== false) { 10151 isShared = true; 10152 } 10153 10154 // Create an integer to hold the attribute options. 10155 var attrOptions = (isShared ? net.user1.orbiter.AttributeOptions.FLAG_SHARED : 0) 10156 | (isPersistent ? net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT : 0) 10157 | (evaluate ? net.user1.orbiter.AttributeOptions.FLAG_EVALUATE : 0); 10158 this.attributeManager.setAttribute(new net.user1.orbiter.upc.SetRoomAttr(attrName, attrValue, attrOptions, this.getRoomID())); 10159 } 10160 10161 net.user1.orbiter.Room.prototype.deleteAttribute = function (attrName) { 10162 if (this.disposed) return; 10163 10164 var deleteRequest = new net.user1.orbiter.upc.RemoveRoomAttr(this.getRoomID(), attrName); 10165 this.attributeManager.deleteAttribute(deleteRequest); 10166 }; 10167 10168 net.user1.orbiter.Room.prototype.getAttribute = function (attrName) { 10169 if (this.disposed) return null; 10170 10171 return this.attributeManager.getAttribute(attrName); 10172 }; 10173 10174 net.user1.orbiter.Room.prototype.getAttributes = function () { 10175 if (this.disposed) return null; 10176 10177 // Room attributes are considered global 10178 return this.attributeManager.getAttributesByScope(net.user1.orbiter.Tokens.GLOBAL_ATTR); 10179 } 10180 10181 // ============================================================================= 10182 // ROOM MODULES 10183 // ============================================================================= 10184 10185 net.user1.orbiter.Room.prototype.sendModuleMessage = function (messageName, 10186 messageArguments) { 10187 if (this.disposed) return; 10188 10189 var sendupcArgs = [net.user1.orbiter.UPC.SEND_ROOMMODULE_MESSAGE, this.getRoomID(), messageName]; 10190 10191 for (var arg in messageArguments) { 10192 sendupcArgs.push(arg + "|" + messageArguments[arg]); 10193 } 10194 10195 this.messageManager.sendUPC.apply(this.messageManager, sendupcArgs); 10196 }; 10197 10198 // ============================================================================= 10199 // ROOM REMOVAL 10200 // ============================================================================= 10201 10202 net.user1.orbiter.Room.prototype.remove = function (password) { 10203 if (this.disposed) return; 10204 10205 this.roomManager.removeRoom(this.getRoomID(), password); 10206 }; 10207 10208 // ============================================================================= 10209 // TOSTRING 10210 // ============================================================================= 10211 10212 net.user1.orbiter.Room.prototype.toString = function () { 10213 return "[ROOM id: " + this.getRoomID() + "]"; 10214 }; 10215 10216 10217 // ============================================================================= 10218 // EVENT DISPATCHING 10219 // ============================================================================= 10220 10221 /** 10222 * @private 10223 */ 10224 net.user1.orbiter.Room.prototype.fireJoin = function () { 10225 if (this.log) this.log.info(this + " Room joined."); 10226 10227 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.JOIN); 10228 this.dispatchEvent(e); 10229 }; 10230 10231 /** 10232 * @private 10233 */ 10234 net.user1.orbiter.Room.prototype.fireJoinResult = function (status) { 10235 if (this.log) this.log.info(this + " Join result: " + status); 10236 10237 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.JOIN_RESULT, 10238 null, null, status); 10239 this.dispatchEvent(e); 10240 }; 10241 10242 /** 10243 * @private 10244 */ 10245 net.user1.orbiter.Room.prototype.fireLeave = function () { 10246 if (this.log) this.log.info(this + " Room left."); 10247 10248 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.LEAVE); 10249 this.dispatchEvent(e); 10250 }; 10251 10252 /** 10253 * @private 10254 */ 10255 net.user1.orbiter.Room.prototype.fireLeaveResult = function (status) { 10256 if (this.log) this.log.info(this + " Leave result: " + status); 10257 10258 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.LEAVE_RESULT, 10259 null, null, status); 10260 this.dispatchEvent(e); 10261 }; 10262 10263 /** 10264 * @private 10265 */ 10266 net.user1.orbiter.Room.prototype.fireAddOccupant = function (id) { 10267 if (this.log) this.log.info(this + " Added occupant: [" + id + "]."); 10268 10269 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.ADD_OCCUPANT, 10270 this.getClient(id), 10271 id); 10272 this.dispatchEvent(e); 10273 }; 10274 10275 /** 10276 * @private 10277 */ 10278 net.user1.orbiter.Room.prototype.fireRemoveOccupant = function (client) { 10279 if (this.log) this.log.info(this + " Removed occupant: " + client + "."); 10280 10281 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.REMOVE_OCCUPANT, 10282 client, 10283 client.getClientID()); 10284 this.dispatchEvent(e); 10285 }; 10286 10287 /** 10288 * @private 10289 */ 10290 net.user1.orbiter.Room.prototype.fireAddObserver = function (id) { 10291 if (this.log) this.log.info(this + " Added observer: [" + id + "]."); 10292 10293 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.ADD_OBSERVER, 10294 this.getClient(id), 10295 id); 10296 this.dispatchEvent(e); 10297 }; 10298 10299 /** 10300 * @private 10301 */ 10302 net.user1.orbiter.Room.prototype.fireRemoveObserver = function (client) { 10303 if (this.log) this.log.info(this + " Removed observer: " + client + "."); 10304 10305 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.REMOVE_OBSERVER, 10306 client, 10307 client.getClientID()); 10308 this.dispatchEvent(e); 10309 }; 10310 10311 /** 10312 * @private 10313 */ 10314 net.user1.orbiter.Room.prototype.fireUpdateClientAttribute = function (client, 10315 scope, 10316 attrName, 10317 attrVal, 10318 oldVal) { 10319 if (this.log) this.log.info(this + " Client attribute updated on " + client + "." 10320 + " Attribute [" + attrName + "] is now: [" 10321 + attrVal + "]. Old value was: [" + oldVal + "]."); 10322 10323 var changedAttr = new net.user1.orbiter.Attribute (attrName, 10324 attrVal, 10325 oldVal, 10326 scope); 10327 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.UPDATE_CLIENT_ATTRIBUTE, 10328 client, 10329 client.getClientID(), 10330 null, 10331 changedAttr); 10332 this.dispatchEvent(e); 10333 }; 10334 10335 /** 10336 * @private 10337 */ 10338 net.user1.orbiter.Room.prototype.fireDeleteClientAttribute = function (client, 10339 scope, 10340 attrName, 10341 attrValue) { 10342 if (this.log) this.log.info(this + " Client attribute deleted from " + client + "." 10343 + " Deleted attribute: [" + attrName + "]."); 10344 10345 var deletedAttr = new net.user1.orbiter.Attribute(attrName, attrValue, null, scope); 10346 10347 // Trigger event on listeners. 10348 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.DELETE_CLIENT_ATTRIBUTE, 10349 client, 10350 client.getClientID(), 10351 null, 10352 deletedAttr); 10353 this.dispatchEvent(e); 10354 }; 10355 10356 /** 10357 * @private 10358 */ 10359 net.user1.orbiter.Room.prototype.fireOccupantCount = function (newNumClients) { 10360 if (this.log) this.log.info(this + " New occupant count: " + newNumClients); 10361 10362 // Trigger event on listeners. 10363 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OCCUPANT_COUNT, 10364 null, null, null, null, newNumClients); 10365 this.dispatchEvent(e); 10366 }; 10367 10368 /** 10369 * @private 10370 */ 10371 net.user1.orbiter.Room.prototype.fireObserverCount = function (newNumClients) { 10372 if (this.log) this.log.info(this + " New observer count: " + newNumClients); 10373 10374 // Trigger event on listeners. 10375 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVER_COUNT, 10376 null, null, null, null, newNumClients); 10377 this.dispatchEvent(e); 10378 }; 10379 10380 /** 10381 * @private 10382 */ 10383 net.user1.orbiter.Room.prototype.fireSynchronize = function (status) { 10384 if (this.log) this.log.info(this + " Synchronization complete."); 10385 10386 // Trigger event on listeners. 10387 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.SYNCHRONIZE, 10388 null, null, status); 10389 this.dispatchEvent(e); 10390 }; 10391 10392 /** 10393 * @private 10394 */ 10395 net.user1.orbiter.Room.prototype.fireObserve = function () { 10396 if (this.log) this.log.info(this + " Room observed."); 10397 10398 // Trigger event on listeners. 10399 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVE); 10400 this.dispatchEvent(e); 10401 }; 10402 10403 /** 10404 * @private 10405 */ 10406 net.user1.orbiter.Room.prototype.fireObserveResult = function (status) { 10407 if (this.log) this.log.info(this + " Observe result: " + status); 10408 10409 // Trigger event on listeners. 10410 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVE_RESULT, null, null, status); 10411 this.dispatchEvent(e); 10412 }; 10413 10414 /** 10415 * @private 10416 */ 10417 net.user1.orbiter.Room.prototype.fireStopObserving = function () { 10418 if (this.log) this.log.info(this + " Observation stopped."); 10419 10420 // Trigger event on listeners. 10421 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.STOP_OBSERVING); 10422 this.dispatchEvent(e); 10423 }; 10424 10425 /** 10426 * @private 10427 */ 10428 net.user1.orbiter.Room.prototype.fireStopObservingResult = function (status) { 10429 if (this.log) this.log.info(this + "Stop observing result: " + 10430 status); 10431 10432 // Trigger event on listeners. 10433 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT, 10434 null, null, status); 10435 this.dispatchEvent(e); 10436 }; 10437 10438 /** 10439 * @private 10440 */ 10441 net.user1.orbiter.Room.prototype.fireRemoved = function () { 10442 // Trigger event on listeners. 10443 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.REMOVED); 10444 this.dispatchEvent(e); 10445 }; 10446 10447 //============================================================================== 10448 // CLEANUP and DISPOSAL 10449 //============================================================================== 10450 /** private */ 10451 net.user1.orbiter.Room.prototype.purgeRoomData = function () { 10452 if (this.disposed) return; 10453 10454 // Clear the client lists 10455 this.log.debug(this + " Clearing occupant list."); 10456 for (var occupantID in this.occupantList.getAll()) { 10457 this.removeClientAttributeListeners(this.occupantList.getByClientID(occupantID)); 10458 } 10459 this.occupantList.removeAll(); 10460 10461 this.log.debug(this + " Clearing observer list."); 10462 for (var observerID in this.observerList.getAll()) { 10463 this.removeClientAttributeListeners(this.observerList.getByClientID(observerID)); 10464 } 10465 this.observerList.removeAll(); 10466 10467 // Clear room attributes. 10468 this.log.debug(this + " Clearing room attributes."); 10469 this.attributeManager.removeAll(); 10470 }; 10471 10472 /** 10473 * @private 10474 */ 10475 net.user1.orbiter.Room.prototype.shutdown = function () { 10476 if (this.disposed) return; 10477 10478 // Store a temp reference to the log for use in this method after 10479 // the room has released all its resources. 10480 var theLog = this.log; 10481 10482 theLog.debug(this + " Shutdown started."); 10483 10484 // Notify the room's listeners that the client left the room. 10485 if (this.clientIsInRoom()) { 10486 theLog.info(this + " Current client is in the room. Forcing the client to leave..."); 10487 this.doLeave(); 10488 } 10489 10490 // Notify the room's listeners that the client stopped observing the room. 10491 if (this.clientIsObservingRoom()) { 10492 theLog.info(this + " Current client is observing the room. Forcing the client to stop observing..."); 10493 this.doStopObserving(); 10494 } 10495 10496 theLog.info(this + " Dereferencing resources."); 10497 10498 // Dereference objects. 10499 this.purgeRoomData(); 10500 10501 this.attributeManager.dispose(); 10502 // Fire removed before nulling the MessageManager object so that listeners have a 10503 // last chance to respond by communicating with the server (or by 10504 // removing themselves from the connection's listener list) 10505 this.fireRemoved(); 10506 this.dispose(); 10507 10508 theLog.info(this + " Shutdown complete."); 10509 } 10510 10511 /** 10512 * @private 10513 */ 10514 net.user1.orbiter.Room.prototype.dispose = function () { 10515 this.log = null; 10516 this.syncState = null; 10517 this.occupantList = null; 10518 this.observerList = null; 10519 this.attributeManager = null; 10520 this.numOccupants = 0; 10521 this.defaultClientClass = null 10522 this.messageManager = null; 10523 this.roomManager = null; 10524 this.disposed = true; 10525 }; 10526 //============================================================================== 10527 // CLASS DECLARATION 10528 //============================================================================== 10529 /** 10530 * @class 10531 */ 10532 net.user1.orbiter.RoomClassRegistry = function () { 10533 this.registry = new Object(); 10534 }; 10535 10536 net.user1.orbiter.RoomClassRegistry.prototype.setRoomClass = function (roomID, roomClass) { 10537 this.registry[roomID] = roomClass; 10538 }; 10539 10540 net.user1.orbiter.RoomClassRegistry.prototype.clearRoomClass = function (roomID) { 10541 delete this.registry[roomID]; 10542 }; 10543 10544 10545 net.user1.orbiter.RoomClassRegistry.prototype.getRoomClass = function (roomID) { 10546 return this.registry[roomID] ? this.registry[roomID] : net.user1.orbiter.Room; 10547 }; 10548 //============================================================================== 10549 // CLASS DECLARATION 10550 //============================================================================== 10551 /** @class 10552 @extends net.user1.events.Event 10553 */ 10554 net.user1.orbiter.RoomEvent = function (type, 10555 client, 10556 clientID, 10557 status, 10558 changedAttr, 10559 numClients, 10560 roomID) { 10561 net.user1.events.Event.call(this, type); 10562 10563 this.client = client; 10564 this.clientID = clientID == "" ? null : clientID; 10565 this.status = status; 10566 this.changedAttr = changedAttr; 10567 this.numClients = numClients; 10568 this.roomID = roomID; 10569 }; 10570 10571 10572 //============================================================================== 10573 // INHERITANCE 10574 //============================================================================== 10575 net.user1.utils.extend(net.user1.orbiter.RoomEvent, net.user1.events.Event); 10576 10577 //============================================================================== 10578 // STATIC VARIABLES 10579 //============================================================================== 10580 10581 /** @constant */ 10582 net.user1.orbiter.RoomEvent.JOIN = "JOIN"; 10583 /** @constant */ 10584 net.user1.orbiter.RoomEvent.JOIN_RESULT = "JOIN_RESULT"; 10585 /** @constant */ 10586 net.user1.orbiter.RoomEvent.LEAVE = "LEAVE"; 10587 /** @constant */ 10588 net.user1.orbiter.RoomEvent.LEAVE_RESULT = "LEAVE_RESULT"; 10589 /** @constant */ 10590 net.user1.orbiter.RoomEvent.OBSERVE = "OBSERVE"; 10591 /** @constant */ 10592 net.user1.orbiter.RoomEvent.OBSERVE_RESULT = "OBSERVE_RESULT"; 10593 /** @constant */ 10594 net.user1.orbiter.RoomEvent.STOP_OBSERVING = "STOP_OBSERVING"; 10595 /** @constant */ 10596 net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT = "STOP_OBSERVING_RESULT"; 10597 /** @constant */ 10598 net.user1.orbiter.RoomEvent.SYNCHRONIZE = "SYNCHRONIZE"; 10599 /** @constant */ 10600 net.user1.orbiter.RoomEvent.UPDATE_CLIENT_ATTRIBUTE = "UPDATE_CLIENT_ATTRIBUTE"; 10601 /** @constant */ 10602 net.user1.orbiter.RoomEvent.DELETE_CLIENT_ATTRIBUTE = "DELETE_CLIENT_ATTRIBUTE"; 10603 /** @constant */ 10604 net.user1.orbiter.RoomEvent.ADD_OCCUPANT = "ADD_OCCUPANT"; 10605 /** @constant */ 10606 net.user1.orbiter.RoomEvent.REMOVE_OCCUPANT = "REMOVE_OCCUPANT"; 10607 /** @constant */ 10608 net.user1.orbiter.RoomEvent.ADD_OBSERVER = "ADD_OBSERVER"; 10609 /** @constant */ 10610 net.user1.orbiter.RoomEvent.REMOVE_OBSERVER = "REMOVE_OBSERVER"; 10611 /** @constant */ 10612 net.user1.orbiter.RoomEvent.OCCUPANT_COUNT = "OCCUPANT_COUNT"; 10613 /** @constant */ 10614 net.user1.orbiter.RoomEvent.OBSERVER_COUNT = "OBSERVER_COUNT"; 10615 /** @constant */ 10616 net.user1.orbiter.RoomEvent.REMOVED = "REMOVED"; 10617 10618 10619 net.user1.orbiter.RoomEvent.prototype.getRoomID = function () { 10620 return this.roomID; 10621 }; 10622 10623 net.user1.orbiter.RoomEvent.prototype.getClient = function () { 10624 return this.client; 10625 }; 10626 10627 net.user1.orbiter.RoomEvent.prototype.getClientID = function () { 10628 return this.clientID; 10629 }; 10630 10631 net.user1.orbiter.RoomEvent.prototype.getStatus = function () { 10632 return this.status; 10633 }; 10634 10635 net.user1.orbiter.RoomEvent.prototype.getNumClients = function () { 10636 return this.numClients; 10637 }; 10638 10639 net.user1.orbiter.RoomEvent.prototype.getChangedAttr = function () { 10640 return this.changedAttr; 10641 }; 10642 10643 net.user1.orbiter.RoomEvent.prototype.toString = function () { 10644 return "[object RoomEvent]"; 10645 }; 10646 //============================================================================== 10647 // CLASS DECLARATION 10648 //============================================================================== 10649 /** 10650 * @private 10651 */ 10652 net.user1.orbiter.RoomList = function () { 10653 // Call superconstructor 10654 net.user1.events.EventDispatcher.call(this); 10655 10656 this.rooms = new Array(); 10657 }; 10658 10659 //============================================================================== 10660 // INHERITANCE 10661 //============================================================================== 10662 net.user1.utils.extend(net.user1.orbiter.RoomList, net.user1.events.EventDispatcher); 10663 10664 //============================================================================== 10665 // INSTANCE METHODS 10666 //============================================================================== 10667 net.user1.orbiter.RoomList.prototype.add = function (room) { 10668 if (!this.contains(room)) { 10669 this.rooms.push(room); 10670 this.dispatchAddItem(room); 10671 return room; 10672 } else { 10673 return null; 10674 } 10675 }; 10676 10677 net.user1.orbiter.RoomList.prototype.remove = function (room) { 10678 var index = net.user1.utils.ArrayUtil.indexOf(this.rooms, room); 10679 if (index != -1) { 10680 this.rooms.splice(index, 1)[0]; 10681 this.dispatchRemoveItem(room); 10682 return room; 10683 } else { 10684 return null; 10685 } 10686 }; 10687 10688 net.user1.orbiter.RoomList.prototype.removeAll = function () { 10689 var room; 10690 for (var i = this.rooms.length; --i >= 0; ) { 10691 room = this.rooms.splice(i, 1)[0]; 10692 this.dispatchRemoveItem(room); 10693 } 10694 }; 10695 10696 net.user1.orbiter.RoomList.prototype.removeByRoomID = function (roomID) { 10697 var room; 10698 for (var i = this.rooms.length; --i >= 0; ) { 10699 if (this.rooms[i].getRoomID() == roomID) { 10700 room = this.rooms.splice(i, 1)[0]; 10701 this.dispatchRemoveItem(room); 10702 return room; 10703 } 10704 } 10705 return null; 10706 }; 10707 10708 net.user1.orbiter.RoomList.prototype.contains = function (room) { 10709 return net.user1.utils.ArrayUtil.indexOf(this.rooms, room) != -1; 10710 } 10711 10712 net.user1.orbiter.RoomList.prototype.containsRoomID = function (roomID) { 10713 if (roomID == "" || roomID == null) { 10714 return false; 10715 } 10716 return this.getByRoomID(roomID) != null; 10717 } 10718 10719 net.user1.orbiter.RoomList.prototype.getByRoomID = function (roomID) { 10720 var room; 10721 for (var i = this.rooms.length; --i >= 0;) { 10722 room = this.rooms[i]; 10723 if (room.getRoomID() == roomID) { 10724 return room; 10725 } 10726 } 10727 return null; 10728 }; 10729 10730 net.user1.orbiter.RoomList.prototype.getAll = function () { 10731 return this.rooms.slice(0); 10732 }; 10733 10734 net.user1.orbiter.RoomList.prototype.length = function () { 10735 return this.rooms.length; 10736 } 10737 10738 net.user1.orbiter.RoomList.prototype.dispatchAddItem = function (item) { 10739 this.dispatchEvent(new net.user1.orbiter.CollectionEvent(net.user1.orbiter.CollectionEvent.ADD_ITEM, item)); 10740 }; 10741 10742 net.user1.orbiter.RoomList.prototype.dispatchRemoveItem = function (item) { 10743 this.dispatchEvent(new net.user1.orbiter.CollectionEvent(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, item)); 10744 }; 10745 //============================================================================== 10746 // CLASS DECLARATION 10747 //============================================================================== 10748 /** 10749 * @class 10750 * @extends net.user1.orbiter.snapshot.Snapshot 10751 */ 10752 net.user1.orbiter.snapshot.RoomListSnapshot = function (qualifier, 10753 recursive) { 10754 // Call superconstructor 10755 net.user1.orbiter.snapshot.Snapshot.call(this); 10756 this.roomList = null; 10757 this.qualifier = null; 10758 this.recursive = null; 10759 this.method = net.user1.orbiter.UPC.GET_ROOMLIST_SNAPSHOT; 10760 this.args = [qualifier, 10761 recursive]; 10762 }; 10763 10764 //============================================================================== 10765 // INHERITANCE 10766 //============================================================================== 10767 net.user1.utils.extend(net.user1.orbiter.snapshot.RoomListSnapshot, net.user1.orbiter.snapshot.Snapshot); 10768 10769 //============================================================================== 10770 // INSTANCE METHODS 10771 //============================================================================== 10772 /** 10773 * @private 10774 */ 10775 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.setRoomList = function (value) { 10776 this.roomList = value; 10777 }; 10778 10779 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.getRoomList = function () { 10780 if (!this.roomList) { 10781 return null; 10782 } 10783 return this.roomList.slice(); 10784 }; 10785 10786 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.getQualifier = function () { 10787 return this.qualifier; 10788 }; 10789 10790 /** 10791 * @private 10792 */ 10793 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.setQualifier = function (value) { 10794 this.qualifier = value; 10795 }; 10796 10797 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.getRecursive = function () { 10798 return this.recursive; 10799 }; 10800 10801 /** 10802 * @private 10803 */ 10804 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.setRecursive = function (value) { 10805 this.recursive = value; 10806 }; 10807 //============================================================================== 10808 // CLASS DECLARATION 10809 //============================================================================== 10810 /** @class 10811 10812 The RoomManager class dispatches the following events: 10813 10814 <ul class="summary"> 10815 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT}</li> 10816 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT}</li> 10817 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT}</li> 10818 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT}</li> 10819 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.ROOM_ADDED}</li> 10820 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED}</li> 10821 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.ROOM_COUNT}</li> 10822 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.JOIN_RESULT}</li> 10823 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.LEAVE_RESULT}</li> 10824 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OBSERVE_RESULT}</li> 10825 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT}</li> 10826 </ul> 10827 10828 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 10829 10830 @extends net.user1.events.EventDispatcher 10831 */ 10832 net.user1.orbiter.RoomManager = function (orbiter) { 10833 // Call superconstructor 10834 net.user1.events.EventDispatcher.call(this); 10835 10836 this.watchedQualifiers = []; 10837 10838 this.cachedRooms = new net.user1.orbiter.RoomList(); 10839 this.occupiedRooms = new net.user1.orbiter.RoomList(); 10840 this.observedRooms = new net.user1.orbiter.RoomList(); 10841 this.watchedRooms = new net.user1.orbiter.RoomList(); 10842 10843 this.cachedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10844 this.occupiedRooms.addEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 10845 this.occupiedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10846 this.observedRooms.addEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 10847 this.observedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10848 this.watchedRooms.addEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 10849 this.watchedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10850 10851 this.orbiter = orbiter; 10852 10853 this.addEventListener(net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, 10854 this.watchForRoomsResultListener, this); 10855 this.addEventListener(net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT, 10856 this.stopWatchingForRoomsResultListener, this); 10857 10858 10859 this.roomClassRegistry = new net.user1.orbiter.RoomClassRegistry(); 10860 10861 // Store a reference to the this.log. 10862 this.log = this.orbiter.getLog(); 10863 }; 10864 10865 //============================================================================== 10866 // INHERITANCE 10867 //============================================================================== 10868 net.user1.utils.extend(net.user1.orbiter.RoomManager, net.user1.events.EventDispatcher); 10869 10870 //============================================================================== 10871 // ROOM CREATION AND REMOVAL 10872 //============================================================================== 10873 /** 10874 * @param attributes An array of JavaScript objects that describes the initial room 10875 * attributes for the room in the following format (note that this format differs 10876 * from the XML format used for createRoom() by Reactor, Union's Flash client framework): 10877 * 10878 * [ 10879 * attribute: { 10880 * name:"attrName1", 10881 * value:"attrValue1", 10882 * shared:true, 10883 * persistent:false, 10884 * immutable:false 10885 * }, 10886 * attribute: { 10887 * name:"attrName2", 10888 * value:"attrValue2", 10889 * shared:true, 10890 * persistent:false, 10891 * immutable:false 10892 * } 10893 * ] 10894 * </listing> 10895 */ 10896 10897 net.user1.orbiter.RoomManager.prototype.createRoom = function (roomID, 10898 roomSettings, 10899 attributes, 10900 modules) { 10901 // GET ROOM SETTINGS 10902 if (roomSettings == null) { 10903 roomSettings = new net.user1.orbiter.RoomSettings(); 10904 } 10905 10906 // GET ROOM MODULES 10907 if (modules == null) { 10908 modules = new net.user1.orbiter.RoomModules(); 10909 } 10910 10911 // ERROR CHECKING 10912 10913 // Abort if invalid module name found. 10914 var moduleIDs = modules.getIdentifiers(); 10915 var moduleID; 10916 for (var i = moduleIDs.length; --i >= 0;) { 10917 var moduleID = moduleIDs[i]; 10918 if (!net.user1.orbiter.Validator.isValidModuleName(moduleID)) { 10919 throw new Error("[ROOM_MANAGER] createRoom() failed. Illegal room module name: [" 10920 + moduleID + "]. See net.user1.orbiter.Validator.isValidModuleName()."); 10921 } 10922 } 10923 10924 // If a roomID is specified, we must validated it 10925 if (roomID != null) { 10926 // Abort if the supplied id can't be resolved to a single room 10927 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 10928 throw new Error("[ROOM_MANAGER] createRoom() failed. Illegal room id: [" 10929 + roomID + "]. See net.user1.orbiter.Validator.isValidResolvedRoomID()."); 10930 } 10931 } 10932 10933 // MAKE THE ROOM LOCALLY 10934 10935 // Send "" as the roomID if no roomID is specified. When the server 10936 // receives a request to create a roomID of "", it auto-generates 10937 // the id, and returns it via RoomManagerEvent.CREATE_ROOM_RESULT. 10938 if (roomID == null) { 10939 // Don't make the local room. Instead wait for the server to 10940 // report the new room via u39. 10941 roomID = ""; 10942 } else { 10943 // Make the local room. 10944 this.addCachedRoom(roomID); 10945 } 10946 10947 // TELL THE SERVER TO MAKE THE ROOM 10948 10949 // Create attributes 10950 if (attributes != null) { 10951 var attr; 10952 var attrArg = ""; 10953 for (var i = 0; i < attributes.length; i++) { 10954 attr = attributes[i]; 10955 attrSettings = 0; 10956 attrSettings |= attr.shared ? AttributeOptions.FLAG_SHARED : 0; 10957 attrSettings |= attr.persistent ? AttributeOptions.FLAG_PERSISTENT : 0; 10958 attrSettings |= attr.immutable ? AttributeOptions.FLAG_IMMUTABLE : 0; 10959 attrArg += attr.NAME 10960 + net.user1.orbiter.Tokens.RS + attr.VALUE 10961 + net.user1.orbiter.Tokens.RS + attrSettings.toString(); 10962 10963 if (i < attributes.length-1) { 10964 attrArg += Tokens.RS; 10965 } 10966 } 10967 } 10968 10969 // Send the create room request to the server. 10970 var msgMan = this.orbiter.getMessageManager(); 10971 msgMan.sendUPC(net.user1.orbiter.UPC.CREATE_ROOM, 10972 roomID, 10973 roomSettings.serialize(), 10974 attrArg, 10975 modules.serialize()); 10976 10977 // RETURN A REFERENCE TO THE LOCAL ROOM, IF ONE WAS CREATED 10978 if (roomID == "") { 10979 return null; 10980 } else { 10981 return this.getRoom(roomID); 10982 } 10983 }; 10984 10985 net.user1.orbiter.RoomManager.prototype.removeRoom = function (roomID, password) { 10986 // Quit if no room specified. 10987 if (roomID == null || !net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 10988 throw new Error("Invalid room id supplied to removeRoom(): [" 10989 + roomID + "]. Request not sent."); 10990 } 10991 10992 if (password == null) { 10993 password = ""; 10994 } 10995 10996 var msgMan = this.orbiter.getMessageManager(); 10997 msgMan.sendUPC(net.user1.orbiter.UPC.REMOVE_ROOM, 10998 roomID, 10999 password); 11000 }; 11001 11002 //============================================================================== 11003 // ROOM OBSERVATION 11004 //============================================================================== 11005 11006 net.user1.orbiter.RoomManager.prototype.observeRoom = function (roomID, 11007 password, 11008 updateLevels) { 11009 var theRoom; 11010 11011 // If the room is not valid, quit 11012 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 11013 throw new Error("Invalid room id supplied to observeRoom(): [" 11014 + roomID + "]. Request not sent." 11015 + " See net.user1.orbiter.Validator.isValidResolvedRoomID()."); 11016 } 11017 11018 // Try to get a reference to the room 11019 theRoom = this.getRoom(roomID); 11020 11021 // If the room exists 11022 if (theRoom != null) { 11023 if (theRoom.clientIsObservingRoom()) { 11024 this.log.warn("[ROOM_MANAGER] Room observe attempt ignored. Already observing room: '" 11025 + roomID + "'."); 11026 return null; 11027 } 11028 } else { 11029 // Make the local room 11030 theRoom = this.addCachedRoom(roomID); 11031 } 11032 11033 // Validate the password 11034 if (password == null) { 11035 password = ""; 11036 } 11037 if (!net.user1.orbiter.Validator.isValidPassword(password)) { 11038 throw new Error("Invalid room password supplied to observeRoom(). " 11039 + " Room ID: [" + roomID + "], password: [" + password + "]." 11040 + " See net.user1.orbiter.Validator.isValidPassword()."); 11041 } 11042 11043 // If update levels were specified for this room, send them now. 11044 if (updateLevels != null) { 11045 theRoom.setUpdateLevels(updateLevels); 11046 } 11047 11048 // Send the UPC only if at least one valid room was found 11049 var msgMan = this.orbiter.getMessageManager(); 11050 msgMan.sendUPC(net.user1.orbiter.UPC.OBSERVE_ROOM, 11051 roomID, 11052 password); 11053 11054 return theRoom; 11055 }; 11056 11057 //============================================================================== 11058 // WATCHING FOR ROOMS 11059 //============================================================================== 11060 11061 net.user1.orbiter.RoomManager.prototype.watchForRooms = function (roomQualifier) { 11062 var recursive = false; 11063 11064 // null means watch the whole server 11065 if (roomQualifier == null) { 11066 roomQualifier = ""; 11067 recursive = true; 11068 } 11069 11070 var msgMan = this.orbiter.getMessageManager(); 11071 msgMan.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_ROOMS, 11072 roomQualifier, 11073 recursive.toString()); 11074 }; 11075 11076 net.user1.orbiter.RoomManager.prototype.stopWatchingForRooms = function (roomQualifier) { 11077 var recursive = false; 11078 // null means whole server 11079 if (roomQualifier == null) { 11080 roomQualifier = ""; 11081 recursive = true; 11082 } 11083 11084 var msgMan = this.orbiter.getMessageManager(); 11085 msgMan.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS, 11086 roomQualifier, 11087 recursive.toString()); 11088 }; 11089 11090 net.user1.orbiter.RoomManager.prototype.isWatchingQualifier = function (qualifier) { 11091 return net.user1.utils.ArrayUtil.indexOf(this.watchedQualifiers, qualifier) != -1; 11092 }; 11093 11094 /** 11095 * @private 11096 */ 11097 net.user1.orbiter.RoomManager.prototype.watchForRoomsResultListener = function (e) { 11098 if (e.getStatus() == net.user1.orbiter.Status.SUCCESS) { 11099 this.watchedQualifiers.push(e.getRoomIdQualifier()); 11100 } 11101 }; 11102 11103 /** 11104 * @private 11105 */ 11106 net.user1.orbiter.RoomManager.prototype.stopWatchingForRoomsResultListener = function (e) { 11107 var unwatchedQualifier = e.getRoomIdQualifier(); 11108 var unwatchedQualifierIndex; 11109 11110 if (e.getStatus() == net.user1.orbiter.Status.SUCCESS) { 11111 unwatchedQualifierIndex = net.user1.utils.ArrayUtil.indexOf(watchedQualifiers, unwatchedQualifier); 11112 if (unwatchedQualifierIndex != -1) { 11113 watchedQualifiers.splice(unwatchedQualifierIndex, 1); 11114 } 11115 } 11116 }; 11117 11118 //============================================================================== 11119 // SENDING MESSAGES 11120 //============================================================================== 11121 11122 net.user1.orbiter.RoomManager.prototype.sendMessage = function (messageName, 11123 rooms, 11124 includeSelf, 11125 filters) { 11126 var rest = Array.prototype.slice.call(arguments).slice(4); 11127 11128 // An array of arguments to send to the server. 11129 var args; 11130 11131 // Can't continue without a valid messageName. 11132 if (messageName == null || messageName == "") { 11133 this.log.warn("[ROOM_MANAGER] sendMessage() failed. No messageName supplied."); 11134 return; 11135 } 11136 11137 // Send the UPC. 11138 var msgMan = this.orbiter.getMessageManager(); 11139 args = [net.user1.orbiter.UPC.SEND_MESSAGE_TO_ROOMS, 11140 messageName, 11141 rooms.join(net.user1.orbiter.Tokens.RS), 11142 String(includeSelf), 11143 filters != null ? filters.toXMLString() : ""]; 11144 msgMan.sendUPC.apply(msgMan, args.concat(rest)); 11145 } 11146 11147 11148 //============================================================================== 11149 // JOINING ROOMS 11150 //============================================================================== 11151 11152 net.user1.orbiter.RoomManager.prototype.joinRoom = function (roomID, 11153 password, 11154 updateLevels) { 11155 if (!this.orbiter.isReady()) { 11156 this.log.warn("[ROOM_MANAGER] Connection not open. Request to join room [" 11157 + roomID + "] could not be sent."); 11158 return null; 11159 } 11160 11161 // If the room ID is not valid, quit 11162 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 11163 this.log.error("[ROOM_MANAGER] Invalid room id supplied to joinRoom(): [" 11164 + roomID + "]. Join request not sent." 11165 + " See net.user1.orbiter.Validator.isValidResolvedRoomID()."); 11166 return null; 11167 } 11168 11169 // Try to get a reference to the room 11170 var theRoom = this.getRoom(roomID); 11171 11172 // If the room exists 11173 if (theRoom != null) { 11174 // Can't join a room you're already in. 11175 if (theRoom.clientIsInRoom()) { 11176 this.log.warn("[ROOM_MANAGER] Room join attempt aborted. Already in room: [" 11177 + theRoom.getRoomID() + "]."); 11178 return theRoom; 11179 } 11180 } else { 11181 // Make the local room. 11182 theRoom = this.addCachedRoom(roomID); 11183 } 11184 11185 // Validate the password 11186 if (password == null) { 11187 password = ""; 11188 } 11189 if (!net.user1.orbiter.Validator.isValidPassword(password)) { 11190 this.log.error("[ROOM_MANAGER] Invalid room password supplied to joinRoom(): [" 11191 + roomID + "]. Join request not sent." 11192 + " See net.user1.orbiter.Validator.isValidPassword()."); 11193 return theRoom; 11194 } 11195 11196 11197 // If any update levels are specified, send them before joining. 11198 if (updateLevels != null) { 11199 theRoom.setUpdateLevels(updateLevels); 11200 } 11201 11202 var msgMan = this.orbiter.getMessageManager(); 11203 msgMan.sendUPC(net.user1.orbiter.UPC.JOIN_ROOM, 11204 roomID, 11205 password); 11206 return theRoom; 11207 }; 11208 11209 // ============================================================================= 11210 // ROOM OBJECT CREATION/DISPOSAL 11211 // ============================================================================= 11212 11213 /** 11214 * @private 11215 */ 11216 net.user1.orbiter.RoomManager.prototype.requestRoom = function (roomID) { 11217 if (roomID == "") { 11218 this.log.warn("[ROOM_MANAGER] requestRoom() failed. Supplied room ID was empty."); 11219 return null; 11220 } 11221 11222 var theRoom = this.getRoom(roomID); 11223 if (theRoom != null) { 11224 return theRoom; 11225 } else { 11226 this.log.debug("[ROOM_MANAGER] Creating new room object for id: [" + roomID + "]"); 11227 var RoomClass = this.roomClassRegistry.getRoomClass(roomID); 11228 theRoom = new RoomClass(roomID, 11229 this, 11230 this.orbiter.getMessageManager(), 11231 this.orbiter.getClientManager(), 11232 this.orbiter.getAccountManager(), 11233 this.log); 11234 return theRoom; 11235 } 11236 }; 11237 11238 /** 11239 * @private 11240 */ 11241 net.user1.orbiter.RoomManager.prototype.disposeRoom = function (roomID) { 11242 var room = this.getRoom(roomID); 11243 if (room != null) { 11244 this.log.debug("[ROOM_MANAGER] Disposing room: " + room); 11245 this.removeCachedRoom(roomID); 11246 this.removeWatchedRoom(roomID); 11247 this.removeOccupiedRoom(roomID); 11248 this.removeObservedRoom(roomID); 11249 } else { 11250 this.log.debug("[ROOM_MANAGER] disposeRoom() called for unknown room: [" + roomID + "]"); 11251 } 11252 }; 11253 11254 /** 11255 * @private 11256 */ 11257 net.user1.orbiter.RoomManager.prototype.removeAllRooms = function () { 11258 this.log.debug("[ROOM_MANAGER] Removing all local room object references."); 11259 this.cachedRooms.removeAll(); 11260 this.watchedRooms.removeAll(); 11261 this.occupiedRooms.removeAll(); 11262 this.observedRooms.removeAll(); 11263 }; 11264 11265 // ============================================================================= 11266 // CACHED ROOMS 11267 // ============================================================================= 11268 11269 /** 11270 * @private 11271 */ 11272 net.user1.orbiter.RoomManager.prototype.addCachedRoom = function (roomID) { 11273 var cachedRoom = this.cachedRooms.getByRoomID(roomID); 11274 if (cachedRoom == null) { 11275 this.log.debug("[ROOM_MANAGER] Adding cached room: [" + roomID + "]"); 11276 return this.cachedRooms.add(this.requestRoom(roomID)); 11277 } else { 11278 return cachedRoom; 11279 } 11280 }; 11281 11282 /** 11283 * @private 11284 */ 11285 net.user1.orbiter.RoomManager.prototype.removeCachedRoom = function (roomID) { 11286 if (this.cachedRooms.containsRoomID(roomID)) { 11287 this.cachedRooms.removeByRoomID(roomID); 11288 } else { 11289 throw new Error("[ROOM_MANAGER] Could not remove cached room: [" + roomID + "]." 11290 + " Room not found."); 11291 } 11292 }; 11293 11294 net.user1.orbiter.RoomManager.prototype.hasCachedRoom = function (roomID) { 11295 return this.cachedRooms.containsRoomID(roomID); 11296 }; 11297 11298 net.user1.orbiter.RoomManager.prototype.disposeCachedRooms = function () { 11299 var room; 11300 var rooms = cachedRooms.getAll(); 11301 for (var i = 0; i <= rooms.length; i++) { 11302 room = rooms[i]; 11303 removeCachedRoom(room.getRoomID()); 11304 } 11305 }; 11306 11307 // ============================================================================= 11308 // WATCHED ROOMS 11309 // ============================================================================= 11310 11311 /** 11312 * @private 11313 */ 11314 net.user1.orbiter.RoomManager.prototype.addWatchedRoom = function (roomID) { 11315 this.log.debug("[ROOM_MANAGER] Adding watched room: [" + roomID + "]"); 11316 var room = this.watchedRooms.add(this.requestRoom(roomID)); 11317 room.updateSyncState(); 11318 }; 11319 11320 /** 11321 * @private 11322 */ 11323 net.user1.orbiter.RoomManager.prototype.removeWatchedRoom = function (roomID) { 11324 var room = this.watchedRooms.removeByRoomID(roomID); 11325 if (room != null) { 11326 room.updateSyncState(); 11327 } else { 11328 this.log.debug("[ROOM_MANAGER] Request to remove watched room [" 11329 + roomID + "] ignored; room not in watched list."); 11330 } 11331 }; 11332 11333 /** 11334 * @private 11335 */ 11336 net.user1.orbiter.RoomManager.prototype.removeAllWatchedRooms = function () { 11337 var rooms = this.watchedRooms.getAll(); 11338 var room; 11339 for (var i = 0; i <= rooms.length; i++) { 11340 room = rooms[i]; 11341 removeWatchedRoom(room.getRoomID()); 11342 room.updateSyncState(); 11343 } 11344 }; 11345 11346 /** 11347 * @private 11348 */ 11349 net.user1.orbiter.RoomManager.prototype.setWatchedRooms = function (qualifier, newRoomIDs) { 11350 // Remove rooms from local list 11351 var rooms = this.getRoomsWithQualifier(qualifier); 11352 var room; 11353 for (var i = 0; i < rooms.length; i++) { 11354 room = rooms[i]; 11355 if (net.user1.utils.ArrayUtil.indexOf(newRoomIDs, room.getSimpleRoomID()) == -1) { 11356 this.removeWatchedRoom(room.getRoomID()); 11357 } 11358 } 11359 // Add rooms to local list 11360 var fullRoomID; 11361 var roomID; 11362 for (var i = 0; i < newRoomIDs.length; i++) { 11363 roomID = newRoomIDs[i]; 11364 fullRoomID = qualifier + (qualifier != "" ? "." : "") + roomID; 11365 if (!this.watchedRooms.containsRoomID(fullRoomID)) { 11366 this.addWatchedRoom(fullRoomID); 11367 } 11368 } 11369 }; 11370 11371 net.user1.orbiter.RoomManager.prototype.hasWatchedRoom = function (roomID) { 11372 return this.watchedRooms.containsRoomID(roomID); 11373 } 11374 11375 // ============================================================================= 11376 // OCCUPIED ROOMS 11377 // ============================================================================= 11378 11379 /** 11380 * @private 11381 */ 11382 net.user1.orbiter.RoomManager.prototype.addOccupiedRoom = function (roomID) { 11383 this.log.debug("[ROOM_MANAGER] Adding occupied room: [" + roomID + "]"); 11384 var room = this.occupiedRooms.add(this.requestRoom(roomID)); 11385 room.updateSyncState(); 11386 return room; 11387 }; 11388 11389 /** 11390 * @private 11391 */ 11392 net.user1.orbiter.RoomManager.prototype.removeOccupiedRoom = function (roomID) { 11393 var room = this.occupiedRooms.removeByRoomID(roomID); 11394 if (room != null) { 11395 room.updateSyncState(); 11396 } else { 11397 this.log.debug("[ROOM_MANAGER] Request to remove occupied room [" 11398 + roomID + "] ignored; client is not in room."); 11399 } 11400 }; 11401 11402 net.user1.orbiter.RoomManager.prototype.hasOccupiedRoom = function (roomID) { 11403 return this.occupiedRooms.containsRoomID(roomID); 11404 }; 11405 11406 // ============================================================================= 11407 // OBSERVED ROOMS 11408 // ============================================================================= 11409 11410 /** 11411 * @private 11412 */ 11413 net.user1.orbiter.RoomManager.prototype.addObservedRoom = function (roomID) { 11414 this.log.debug("[ROOM_MANAGER] Adding observed room: [" + roomID + "]"); 11415 var room = this.observedRooms.add(this.requestRoom(roomID)); 11416 room.updateSyncState(); 11417 return room; 11418 }; 11419 11420 /** 11421 * @private 11422 */ 11423 net.user1.orbiter.RoomManager.prototype.removeObservedRoom = function (roomID) { 11424 var room = this.observedRooms.removeByRoomID(roomID); 11425 if (room != null) { 11426 room.updateSyncState(); 11427 } else { 11428 this.log.debug("[ROOM_MANAGER] Request to remove observed room [" 11429 + roomID + "] ignored; client is not observing room."); 11430 } 11431 }; 11432 11433 net.user1.orbiter.RoomManager.prototype.hasObservedRoom = function (roomID) { 11434 return this.observedRooms.containsRoomID(roomID); 11435 }; 11436 11437 //============================================================================== 11438 // ROOM LIST LISTENERS 11439 //============================================================================== 11440 11441 /** 11442 * @private 11443 */ 11444 net.user1.orbiter.RoomManager.prototype.addRoomListener = function (e) { 11445 var room = e.getItem(); 11446 11447 // Only trigger added for first known reference 11448 if (this.getKnownReferenceCount(room.getRoomID()) == 1) { 11449 this.fireRoomAdded(room.getQualifier(), room.getRoomID(), room); 11450 this.fireRoomCount(this.getNumRooms()); 11451 } 11452 }; 11453 11454 /** 11455 * @private 11456 */ 11457 net.user1.orbiter.RoomManager.prototype.removeRoomListener = function (e) { 11458 var room = e.getItem(); 11459 var knownReferenceCount = this.getKnownReferenceCount(room.getRoomID()); 11460 11461 switch (e.target) { 11462 case this.occupiedRooms: 11463 this.log.debug("[ROOM_MANAGER] Removed occupied room: " + room); 11464 if (knownReferenceCount == 0) { 11465 this.fireRoomRemoved(room.getQualifier(), room.getRoomID(), room); 11466 this.fireRoomCount(this.getNumRooms()); 11467 } 11468 break; 11469 11470 case this.observedRooms: 11471 this.log.debug("[ROOM_MANAGER] Removed observed room: " + room); 11472 if (knownReferenceCount == 0) { 11473 this.fireRoomRemoved(room.getQualifier(), room.getRoomID(), room); 11474 this.fireRoomCount(this.getNumRooms()); 11475 } 11476 break; 11477 11478 case this.watchedRooms: 11479 this.log.debug("[ROOM_MANAGER] Removed watched room: " + room); 11480 if (knownReferenceCount == 0) { 11481 this.fireRoomRemoved(room.getQualifier(), room.getRoomID(), room); 11482 this.fireRoomCount(this.getNumRooms()); 11483 } 11484 break; 11485 11486 case this.cachedRooms: 11487 this.log.debug("[ROOM_MANAGER] Removed cached room: " + room); 11488 break; 11489 } 11490 11491 // When the RoomManager has no more references to the room, shut it down 11492 if (knownReferenceCount == 0 && !this.cachedRooms.contains(room)) { 11493 room.shutdown(); 11494 } 11495 }; 11496 11497 //============================================================================== 11498 // ROOM ACCESS 11499 //============================================================================== 11500 11501 /** 11502 * @private 11503 */ 11504 net.user1.orbiter.RoomManager.prototype.getKnownReferenceCount = function (roomID) { 11505 var count = 0; 11506 count += this.hasObservedRoom(roomID) ? 1 : 0; 11507 count += this.hasOccupiedRoom(roomID) ? 1 : 0; 11508 count += this.hasWatchedRoom(roomID) ? 1 : 0; 11509 return count; 11510 } 11511 11512 net.user1.orbiter.RoomManager.prototype.getRooms = function () { 11513 var roomlist = net.user1.utils.ArrayUtil.combine(this.occupiedRooms.getAll(), 11514 this.observedRooms.getAll(), 11515 this.watchedRooms.getAll()); 11516 return roomlist; 11517 }; 11518 11519 net.user1.orbiter.RoomManager.prototype.roomIsKnown = function (roomID) { 11520 var rooms = this.getRooms(); 11521 var room; 11522 for (var i = rooms.length; --i >= 0;) { 11523 room = rooms[i]; 11524 if (room.getRoomID() == roomID) { 11525 return true; 11526 } 11527 } 11528 return false; 11529 }; 11530 11531 net.user1.orbiter.RoomManager.prototype.getRoomIDs = function () { 11532 var roomIDs = new Array(); 11533 var rooms = this.getRooms(); 11534 11535 for (var i = 0; i <= rooms.length; i++) { 11536 roomIDs.push(rooms[i].getRoomID()); 11537 } 11538 11539 return roomIDs; 11540 }; 11541 11542 net.user1.orbiter.RoomManager.prototype.getAllRooms = function () { 11543 var roomlist = net.user1.utils.ArrayUtil.combine(this.occupiedRooms.getAll(), 11544 this.observedRooms.getAll(), 11545 this.watchedRooms.getAll(), 11546 this.cachedRooms.getAll()); 11547 11548 return roomlist; 11549 }; 11550 11551 net.user1.orbiter.RoomManager.prototype.getRoomsWithQualifier = function (qualifier) { 11552 if (qualifier == null) { 11553 return this.getRooms(); 11554 } 11555 11556 var roomlist = []; 11557 var rooms = this.getRooms(); 11558 var room; 11559 for (var i = 0; i < rooms.length; i++) { 11560 room = rooms[i]; 11561 if (net.user1.orbiter.RoomIDParser.getQualifier(room.getRoomID()) == qualifier) { 11562 roomlist.push(room); 11563 } 11564 } 11565 11566 return roomlist; 11567 }; 11568 11569 net.user1.orbiter.RoomManager.prototype.getNumRooms = function (qualifier) { 11570 return this.getRoomsWithQualifier(qualifier).length; 11571 } 11572 11573 net.user1.orbiter.RoomManager.prototype.getRoom = function (roomID) { 11574 var rooms = this.getAllRooms(); 11575 var room; 11576 for (var i = rooms.length; --i >= 0;) { 11577 room = rooms[i]; 11578 if (room.getRoomID() == roomID) { 11579 return room; 11580 } 11581 } 11582 return null; 11583 }; 11584 11585 // ============================================================================= 11586 // ROOM CLASS REGISTRY 11587 // ============================================================================= 11588 11589 net.user1.orbiter.RoomManager.prototype.getRoomClassRegistry = function () { 11590 return this.roomClassRegistry; 11591 }; 11592 11593 // ============================================================================= 11594 // CLIENT ACCESS 11595 // ============================================================================= 11596 11597 /** 11598 * @private 11599 */ 11600 net.user1.orbiter.RoomManager.prototype.getAllClients = function () { 11601 var clientSets = []; 11602 var rooms = this.getRooms(); 11603 var room; 11604 for (var i = rooms.length; --i >= 0;) { 11605 room = rooms[i]; 11606 clientSets.push(room.getOccupantsInternal()); 11607 clientSets.push(room.getObserversInternal()); 11608 } 11609 return net.user1.utils.ObjectUtil.combine(clientSets); 11610 }; 11611 11612 net.user1.orbiter.RoomManager.prototype.clientIsKnown = function (clientID) { 11613 var clientSets = []; 11614 11615 var rooms = this.getRooms(); 11616 var room; 11617 for (var i = rooms.length; --i >= 0;) { 11618 room = rooms[i]; 11619 clientSets.push(room.getOccupantsInternal()); 11620 clientSets.push(room.getObserversInternal()); 11621 } 11622 11623 for (var i = clientSets.length; --i >= 0;) { 11624 if (clientSets[i][clientID] != null) { 11625 return true; 11626 } 11627 } 11628 return false; 11629 }; 11630 11631 // ============================================================================= 11632 // EVENT DISPATCHING 11633 // ============================================================================= 11634 11635 /** 11636 * @private 11637 */ 11638 net.user1.orbiter.RoomManager.prototype.fireWatchForRoomsResult = function (roomIDQualifier, 11639 status) { 11640 var e = new net.user1.orbiter.RoomManagerEvent( 11641 net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, 11642 null, status, roomIDQualifier); 11643 this.dispatchEvent(e); 11644 }; 11645 11646 /** 11647 * @private 11648 */ 11649 net.user1.orbiter.RoomManager.prototype.fireStopWatchingForRoomsResult = function (roomIDQualifier, 11650 status) { 11651 var e = new net.user1.orbiter.RoomManagerEvent( 11652 net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT, 11653 null, status, roomIDQualifier); 11654 this.dispatchEvent(e); 11655 }; 11656 11657 /** 11658 * @private 11659 */ 11660 net.user1.orbiter.RoomManager.prototype.fireCreateRoomResult = function (roomIDQualifier, 11661 roomID, 11662 status) { 11663 var e = new net.user1.orbiter.RoomManagerEvent( 11664 net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT, 11665 roomID, status, roomIDQualifier); 11666 this.dispatchEvent(e); 11667 }; 11668 11669 /** 11670 * @private 11671 */ 11672 net.user1.orbiter.RoomManager.prototype.fireRemoveRoomResult = function (roomIDQualifier, 11673 roomID, 11674 status) { 11675 var e = new net.user1.orbiter.RoomManagerEvent( 11676 net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT, 11677 roomID, status, roomIDQualifier); 11678 11679 this.dispatchEvent(e); 11680 } 11681 11682 /** 11683 * @private 11684 */ 11685 net.user1.orbiter.RoomManager.prototype.fireRoomAdded = function (roomIDQualifier, 11686 roomID, 11687 theRoom) { 11688 var e = new net.user1.orbiter.RoomManagerEvent( 11689 net.user1.orbiter.RoomManagerEvent.ROOM_ADDED, 11690 roomID, null, roomIDQualifier, theRoom); 11691 this.dispatchEvent(e); 11692 } 11693 11694 /** 11695 * @private 11696 */ 11697 net.user1.orbiter.RoomManager.prototype.fireRoomRemoved = function (roomIDQualifier, 11698 roomID, 11699 theRoom) { 11700 var e = new net.user1.orbiter.RoomManagerEvent( 11701 net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED, 11702 roomID, 11703 null, 11704 roomIDQualifier, 11705 theRoom); 11706 this.dispatchEvent(e); 11707 } 11708 11709 /** 11710 * @private 11711 */ 11712 net.user1.orbiter.RoomManager.prototype.fireRoomCount = function (numRooms) { 11713 this.dispatchEvent(new net.user1.orbiter.RoomManagerEvent(net.user1.orbiter.RoomManagerEvent.ROOM_COUNT, 11714 null, null, null, null, numRooms)); 11715 }; 11716 11717 /** 11718 * @private 11719 */ 11720 net.user1.orbiter.RoomManager.prototype.fireJoinRoomResult = function (roomID, status) { 11721 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.JOIN_RESULT, null, null, 11722 status, null, 0, roomID)); 11723 } 11724 11725 /** 11726 * @private 11727 */ 11728 net.user1.orbiter.RoomManager.prototype.fireLeaveRoomResult = function (roomID, status) { 11729 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.LEAVE_RESULT, null, null, 11730 status, null, 0, roomID)); 11731 }; 11732 11733 /** 11734 * @private 11735 */ 11736 net.user1.orbiter.RoomManager.prototype.fireObserveRoomResult = function (roomID, status) { 11737 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVE_RESULT, null, null, 11738 status, null, 0, roomID)); 11739 }; 11740 11741 /** 11742 * @private 11743 */ 11744 net.user1.orbiter.RoomManager.prototype.fireStopObservingRoomResult = function (roomID, status) { 11745 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT, null, null, 11746 status, null, 0, roomID)); 11747 }; 11748 11749 11750 // ============================================================================= 11751 // CLEANUP and DISPOSAL 11752 // ============================================================================= 11753 11754 /** 11755 * @private 11756 * 11757 * Clears all resources. The object remains alive, and can be reused. To 11758 * permanently deactivate this object, use dispose(). 11759 */ 11760 net.user1.orbiter.RoomManager.prototype.cleanup = function () { 11761 this.log.info("[ROOM_MANAGER] Cleaning resources."); 11762 this.removeAllRooms(); 11763 this.watchedQualifiers = []; 11764 }; 11765 11766 /** 11767 * @private 11768 */ 11769 net.user1.orbiter.RoomManager.prototype.dispose = function () { 11770 this.log.info("[ROOM_MANAGER] Disposing resources."); 11771 this.watchedQualifiers = null; 11772 var room; 11773 var rooms = this.getAllRooms(); 11774 for (var i = this.getAllRooms().length; --i >= 0;) { 11775 room = rooms[i]; 11776 room.dispose(); 11777 } 11778 this.cachedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11779 this.occupiedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 11780 this.occupiedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11781 this.observedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 11782 this.observedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11783 this.watchedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 11784 this.watchedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11785 this.occupiedRooms = null; 11786 this.observedRooms = null; 11787 this.watchedRooms = null; 11788 this.cachedRooms = null; 11789 this.log = null; 11790 this.orbiter = null; 11791 this.roomClassRegistry = null; 11792 }; 11793 //============================================================================== 11794 // CLASS DECLARATION 11795 //============================================================================== 11796 /** @class 11797 @extends net.user1.events.Event 11798 */ 11799 net.user1.orbiter.RoomManagerEvent = function (type, 11800 roomID, 11801 status, 11802 roomIdQualifier, 11803 room, 11804 numRooms) { 11805 net.user1.events.Event.call(this, type); 11806 11807 this.roomID = roomID; 11808 this.status = status; 11809 this.roomIdQualifier = roomIdQualifier; 11810 this.room = room; 11811 this.numRooms = numRooms; 11812 }; 11813 11814 //============================================================================== 11815 // INHERITANCE 11816 //============================================================================== 11817 net.user1.utils.extend(net.user1.orbiter.RoomManagerEvent, net.user1.events.Event); 11818 11819 //============================================================================== 11820 // STATIC VARIABLES 11821 //============================================================================== 11822 11823 /** @constant */ 11824 net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT = "CREATE_ROOM_RESULT"; 11825 /** @constant */ 11826 net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT = "REMOVE_ROOM_RESULT"; 11827 /** @constant */ 11828 net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT = "WATCH_FOR_ROOMS_RESULT"; 11829 /** @constant */ 11830 net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT = "STOP_WATCHING_FOR_ROOMS_RESULT"; 11831 /** @constant */ 11832 net.user1.orbiter.RoomManagerEvent.ROOM_ADDED = "ROOM_ADDED"; 11833 /** @constant */ 11834 net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED = "ROOM_REMOVED"; 11835 /** @constant */ 11836 net.user1.orbiter.RoomManagerEvent.ROOM_COUNT = "ROOM_COUNT"; 11837 11838 net.user1.orbiter.RoomManagerEvent.prototype.getRoomIdQualifier = function () { 11839 if (this.roomIdQualifier == null && this.room != null) { 11840 return this.room.getQualifier(); 11841 } else { 11842 return this.roomIdQualifier; 11843 } 11844 }; 11845 11846 net.user1.orbiter.RoomManagerEvent.prototype.getRoomID = function () { 11847 var fullRoomID; 11848 var qualifier; 11849 11850 if (this.room != null) { 11851 return this.room.getRoomID(); 11852 } else if (this.roomID == null) { 11853 return null; 11854 } else { 11855 qualifier = this.getRoomIdQualifier(); 11856 fullRoomID = qualifier == "" || qualifier == null 11857 ? this.roomID 11858 : qualifier + "." + this.roomID; 11859 return fullRoomID; 11860 } 11861 }; 11862 11863 net.user1.orbiter.RoomManagerEvent.prototype.getSimpleRoomID = function () { 11864 if (this.roomID == null && this.room != null) { 11865 return this.room.getSimpleRoomID(); 11866 } else { 11867 return this.roomID; 11868 } 11869 }; 11870 11871 net.user1.orbiter.RoomManagerEvent.prototype.getRoom = function () { 11872 return this.room; 11873 } 11874 11875 net.user1.orbiter.RoomManagerEvent.prototype.getStatus = function () { 11876 return this.status; 11877 } 11878 11879 net.user1.orbiter.RoomManagerEvent.prototype.getNumRooms = function () { 11880 return this.numRooms; 11881 } 11882 11883 net.user1.orbiter.RoomManagerEvent.prototype.toString = function () { 11884 return "[object RoomManagerEvent]"; 11885 }; 11886 //============================================================================== 11887 // CLASS DECLARATION 11888 //============================================================================== 11889 /** 11890 * @private 11891 */ 11892 net.user1.orbiter.RoomManifest = function () { 11893 }; 11894 11895 net.user1.orbiter.RoomManifest.prototype.deserialize = function (roomID, 11896 serializedAttributes, 11897 clientList, 11898 occupantCount, 11899 observerCount) { 11900 this.roomID = roomID; 11901 this.attributes = null; 11902 this.occupantCount = occupantCount; 11903 this.observerCount = observerCount; 11904 this.occupants = []; 11905 this.observers = []; 11906 11907 this.deserializeAttributes(serializedAttributes); 11908 this.deserializeClientList(clientList); 11909 }; 11910 11911 /** 11912 * @private 11913 */ 11914 net.user1.orbiter.RoomManifest.prototype.deserializeAttributes = function (serializedAttributes) { 11915 var attrList = serializedAttributes.split(net.user1.orbiter.Tokens.RS); 11916 this.attributes = new net.user1.orbiter.AttributeCollection(); 11917 11918 for (var i = attrList.length-2; i >= 0; i -=2) { 11919 this.attributes.setAttribute(attrList[i], attrList[i+1], net.user1.orbiter.Tokens.GLOBAL_ATTR); 11920 } 11921 }; 11922 11923 /** 11924 * @private 11925 */ 11926 net.user1.orbiter.RoomManifest.prototype.deserializeClientList = function (clientList) { 11927 var clientManifest; 11928 11929 for (var i = clientList.length-5; i >= 0; i -=5) { 11930 clientManifest = new net.user1.orbiter.ClientManifest(); 11931 clientManifest.deserialize(clientList[i], clientList[i+1], null, null, clientList[i+3], [this.roomID, clientList[i+4]]); 11932 if (clientList[i+2] == "0") { 11933 this.occupants.push(clientManifest); 11934 } else { 11935 this.observers.push(clientManifest); 11936 } 11937 } 11938 }; 11939 //============================================================================== 11940 // CLASS DECLARATION 11941 //============================================================================== 11942 /** @class 11943 * 11944 * @example 11945 * var modules = new net.user1.orbiter.RoomModules(); 11946 * modules.addModule("com.business.StockTickerListener", net.user1.orbiter.ModuleType.CLASS); 11947 * orbiter.getRoomManager().createRoom("someRoomID", 11948 * null, 11949 * null, 11950 * modules); 11951 */ 11952 net.user1.orbiter.RoomModules = function () { 11953 this.modules = new Array(); 11954 }; 11955 11956 net.user1.orbiter.RoomModules.prototype.addModule = function (identifier, 11957 type) { 11958 this.modules.push([type, identifier]); 11959 }; 11960 11961 net.user1.orbiter.RoomModules.prototype.serialize = function () { 11962 var modulesString = ""; 11963 11964 var numModules = this.modules.length; 11965 for (var i = 0; i < numModules; i++) { 11966 modulesString += this.modules[i][0] + net.user1.orbiter.Tokens.RS + this.modules[i][1]; 11967 if (i < numModules-1) { 11968 modulesString += net.user1.orbiter.Tokens.RS; 11969 } 11970 } 11971 11972 return modulesString; 11973 }; 11974 11975 net.user1.orbiter.RoomModules.prototype.getIdentifiers = function () { 11976 var ids = new Array(); 11977 11978 var module; 11979 for (var i = 0; i < this.modules.length; i++) { 11980 module = this.modules[i]; 11981 ids.push(module[1]); 11982 } 11983 return ids; 11984 }; 11985 //============================================================================== 11986 // CLASS DECLARATION 11987 //============================================================================== 11988 /** @class */ 11989 net.user1.orbiter.RoomSettings = function () { 11990 this.removeOnEmpty = null; 11991 this.maxClients = null; 11992 this.password = null; 11993 }; 11994 11995 net.user1.orbiter.RoomSettings.prototype.serialize = function () { 11996 var RS = net.user1.orbiter.Tokens.RS; 11997 var settingsString = 11998 net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR + RS + 11999 (this.removeOnEmpty == null ? "true" : this.removeOnEmpty.toString()) 12000 + RS + net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR + RS + 12001 (this.maxClients == null ? "-1" : this.maxClients.toString()) 12002 + RS + net.user1.orbiter.Tokens.PASSWORD_ATTR + RS + 12003 (this.password == null ? "" : this.password); 12004 return settingsString; 12005 } 12006 //============================================================================== 12007 // CLASS DECLARATION 12008 //============================================================================== 12009 /** 12010 * @class 12011 * @extends net.user1.orbiter.snapshot.Snapshot 12012 */ 12013 net.user1.orbiter.snapshot.RoomSnapshot = function (roomID, password, updateLevels) { 12014 // Call superconstructor 12015 net.user1.orbiter.snapshot.Snapshot.call(this); 12016 this.manifest = null; 12017 this.method = net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT; 12018 this.args = [roomID, password, updateLevels != null ? updateLevels.toInt() : ""]; 12019 this.hasStatus = true; 12020 }; 12021 //============================================================================== 12022 // INHERITANCE 12023 //============================================================================== 12024 net.user1.utils.extend(net.user1.orbiter.snapshot.RoomSnapshot, net.user1.orbiter.snapshot.Snapshot); 12025 12026 //============================================================================== 12027 // INSTANCE METHODS 12028 //============================================================================== 12029 /** 12030 * @private 12031 */ 12032 net.user1.orbiter.snapshot.RoomSnapshot.prototype.setManifest = function (value) { 12033 this.manifest = value; 12034 }; 12035 12036 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getAttribute = function (name) { 12037 if (!this.manifest) { 12038 return null; 12039 } 12040 return this.manifest.attributes.getAttribute(name, net.user1.orbiter.Tokens.GLOBAL_ATTR); 12041 }; 12042 12043 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getAttributes = function () { 12044 if (!this.manifest) { 12045 return null; 12046 } 12047 return this.manifest.attributes.getByScope(net.user1.orbiter.Tokens.GLOBAL_ATTR); 12048 }; 12049 12050 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getRoomID = function () { 12051 if (!this.manifest) { 12052 return null; 12053 } 12054 return this.manifest.roomID; 12055 }; 12056 12057 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getOccupants = function () { 12058 return this.manifest.occupants.slice(); 12059 } 12060 12061 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getObservers = function () { 12062 return this.manifest.observers.slice(); 12063 } 12064 12065 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getOccupant = function (clientID) { 12066 var client; 12067 for (var i = this.manifest.occupants.length; --i >= 0;) { 12068 if (this.manifest.occupants[i].clientID == clientID) { 12069 return this.manifest.occupants[i]; 12070 } 12071 } 12072 return null; 12073 }; 12074 12075 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getObserver = function (clientID) { 12076 var client; 12077 for (var i = this.manifest.observers.length; --i >= 0;) { 12078 if (this.manifest.observers[i].clientID == clientID) { 12079 return this.manifest.observers[i]; 12080 } 12081 } 12082 return null; 12083 }; 12084 12085 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getNumOccupants = function () { 12086 return Math.max(this.manifest.occupants.length, this.manifest.occupantCount); 12087 } 12088 12089 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getNumObservers = function () { 12090 return Math.max(this.manifest.observers.length, this.manifest.observerCount); 12091 } 12092 //============================================================================== 12093 // SECURITY_ROLE CONSTANTS 12094 //============================================================================== 12095 /** @class */ 12096 net.user1.orbiter.SecurityRole = new Object(); 12097 /** @constant */ 12098 net.user1.orbiter.SecurityRole.MODERATOR = "MODERATOR"; 12099 //============================================================================== 12100 // CLASS DECLARATION 12101 //============================================================================== 12102 /** @class 12103 12104 The Server class dispatches the following events: 12105 12106 <ul class="summary"> 12107 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.TIME_SYNC}</li> 12108 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.UPC_PROCESSED}</li> 12109 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.WATCH_FOR_PROCESSED_UPCS_RESULT}</li> 12110 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT}</li> 12111 </ul> 12112 12113 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 12114 12115 @extends net.user1.events.EventDispatcher 12116 */ 12117 net.user1.orbiter.Server = function (orbiter) { 12118 // Call superconstructor 12119 net.user1.events.EventDispatcher.call(this); 12120 12121 this.orbiter = orbiter; 12122 this.version = null; 12123 this.upcVersion = null; 12124 this.localAgeAtLastSync = NaN; 12125 this.lastKnownServerTime = NaN; 12126 this._isWatchingForProcessedUPCs = false; 12127 12128 this.log = orbiter.getLog(); 12129 12130 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, this.readyListener, this); 12131 } 12132 12133 //============================================================================== 12134 // INHERITANCE 12135 //============================================================================== 12136 net.user1.utils.extend(net.user1.orbiter.Server, net.user1.events.EventDispatcher); 12137 12138 // ============================================================================= 12139 // SERVER-WIDE MESSAGING 12140 // ============================================================================= 12141 net.user1.orbiter.Server.prototype.sendMessage = function (messageName, 12142 includeSelf, 12143 filters) { 12144 var rest = Array.prototype.slice.call(arguments).slice(3); 12145 var args; 12146 12147 if (messageName == null || messageName == "") { 12148 this.log.warn("Server.sendMessage() failed. No messageName supplied."); 12149 return; 12150 } 12151 12152 var msgMan = this.orbiter.getMessageManager(); 12153 args = [net.user1.orbiter.UPC.SEND_MESSAGE_TO_SERVER, 12154 messageName, 12155 includeSelf.toString(), 12156 filters != null ? filters.toXMLString() : ""]; 12157 msgMan.sendUPC.apply(msgMan, args.concat(rest)); 12158 }; 12159 12160 // ============================================================================= 12161 // SERVER MODULES 12162 // ============================================================================= 12163 net.user1.orbiter.Server.prototype.sendModuleMessage = function (moduleID, 12164 messageName, 12165 messageArguments) { 12166 var sendupcArgs = [net.user1.orbiter.UPC.SEND_SERVERMODULE_MESSAGE, moduleID, messageName]; 12167 12168 for (var arg in messageArguments) { 12169 sendupcArgs.push(arg + net.user1.orbiter.Tokens.RS + messageArguments[arg]); 12170 } 12171 12172 this.orbiter.getMessageManager().sendUPC.apply(this.orbiter.getMessageManager(), sendupcArgs); 12173 }; 12174 12175 net.user1.orbiter.Server.prototype.clearModuleCache = function () { 12176 this.orbiter.getMessageManager().sendUPC(net.user1.orbiter.UPC.CLEAR_MODULE_CACHE); 12177 }; 12178 12179 // ============================================================================= 12180 // VERSION ACCESS 12181 // ============================================================================= 12182 12183 /** 12184 * @private 12185 */ 12186 net.user1.orbiter.Server.prototype.setVersion = function (value) { 12187 this.version = value; 12188 }; 12189 12190 net.user1.orbiter.Server.prototype.getVersion = function () { 12191 return this.version; 12192 }; 12193 12194 /** 12195 * @private 12196 */ 12197 net.user1.orbiter.Server.prototype.setUPCVersion = function (value) { 12198 this.upcVersion = value; 12199 }; 12200 12201 net.user1.orbiter.Server.prototype.getUPCVersion = function () { 12202 return this.upcVersion; 12203 }; 12204 12205 // ============================================================================= 12206 // UPC STATS AND PROCESSING 12207 // ============================================================================= 12208 12209 net.user1.orbiter.Server.prototype.resetUPCStats = function () { 12210 this.orbiter.getMessageManager().sendUPC(UPC.RESET_UPC_STATS); 12211 }; 12212 12213 net.user1.orbiter.Server.prototype.watchForProcessedUPCs = function () { 12214 this.orbiter.getMessageManager().sendUPC(net.user1.orbiter.UPC.WATCH_FOR_PROCESSED_UPCS); 12215 }; 12216 12217 net.user1.orbiter.Server.prototype.stopWatchingForProcessedUPCs = function () { 12218 this.orbiter.getMessageManager().sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_PROCESSED_UPCS); 12219 }; 12220 12221 net.user1.orbiter.Server.prototype.isWatchingForProcessedUPCs = function () { 12222 return this._isWatchingForProcessedUPCs; 12223 }; 12224 12225 net.user1.orbiter.Server.prototype.setIsWatchingForProcessedUPCs = function (value) { 12226 this._isWatchingForProcessedUPCs = value; 12227 }; 12228 12229 // ============================================================================= 12230 // TIME RETRIEVAL METHODS 12231 // ============================================================================= 12232 net.user1.orbiter.Server.prototype.getServerTime = function () { 12233 var self = this.orbiter.self(); 12234 var lastServerTime = NaN; 12235 var estimatedServerTime = NaN; 12236 12237 if (self != null) { 12238 lastServerTime = isNaN(this.lastKnownServerTime) 12239 ? self.getConnectTime() 12240 : this.lastKnownServerTime; 12241 12242 estimatedServerTime = isNaN(lastServerTime) 12243 ? NaN 12244 : (lastServerTime + (new Date().getTime()-this.localAgeAtLastSync)); 12245 } 12246 12247 if (estimatedServerTime == 0) { 12248 log.warn("Server time requested, but is unknown."); 12249 } 12250 12251 return estimatedServerTime; 12252 }; 12253 12254 net.user1.orbiter.Server.prototype.syncTime = function () { 12255 var msgMan = this.orbiter.getMessageManager(); 12256 msgMan.sendUPC(net.user1.orbiter.UPC.SYNC_TIME); 12257 }; 12258 12259 /** 12260 * @private 12261 */ 12262 net.user1.orbiter.Server.prototype.readyListener = function (e) { 12263 this.orbiter.getMessageManager().addMessageListener(net.user1.orbiter.UPC.SERVER_TIME_UPDATE, this.u50); 12264 this.localAgeAtLastSync = new Date().getTime();; 12265 }; 12266 12267 // ============================================================================= 12268 // EVENT DISPATCHING 12269 // ============================================================================= 12270 12271 /** 12272 * @private 12273 */ 12274 net.user1.orbiter.Server.prototype.fireTimeSync = function () { 12275 this.dispatchEvent(new net.user1.orbiter.ServerEvent(ServerEvent.TIME_SYNC)); 12276 }; 12277 12278 /** 12279 * @private 12280 */ 12281 net.user1.orbiter.Server.prototype.dispatchWatchForProcessedUPCsResult = function (status) { 12282 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.WATCH_FOR_PROCESSED_UPCS_RESULT, 12283 null, status)); 12284 }; 12285 12286 /** 12287 * @private 12288 */ 12289 net.user1.orbiter.Server.prototype.dispatchStopWatchingForProcessedUPCsResult = function (status) { 12290 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT, 12291 null, status)); 12292 }; 12293 12294 /** 12295 * @private 12296 */ 12297 net.user1.orbiter.Server.prototype.dispatchUPCProcessed = function (record) { 12298 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.UPC_PROCESSED, record)); 12299 }; 12300 12301 /** 12302 * @private 12303 */ 12304 net.user1.orbiter.Server.prototype.dispatchResetUPCStatsResult = function (status) { 12305 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.RESET_UPC_STATS_RESULT, 12306 null, status)); 12307 }; 12308 12309 //============================================================================== 12310 // UPC LISTENERS 12311 //============================================================================== 12312 12313 /** 12314 * @private 12315 */ 12316 net.user1.orbiter.Server.prototype.u50 = function (newTime) { // SERVER_TIME 12317 this.lastKnownServerTime = Number(newTime); 12318 this.localAgeAtLastSync = new Date().getTime(); 12319 this.fireTimeSync(); 12320 } 12321 12322 //============================================================================== 12323 // CLEANUP AND DISPOSAL 12324 //============================================================================== 12325 /** 12326 * @private 12327 */ 12328 net.user1.orbiter.Server.prototype.cleanup = function () { 12329 this.log.info("[SERVER] Cleaning resources."); 12330 this.setIsWatchingForProcessedUPCs(false); 12331 } 12332 //============================================================================== 12333 // CLASS DECLARATION 12334 //============================================================================== 12335 /** 12336 * @class 12337 * @extends net.user1.orbiter.snapshot.Snapshot 12338 */ 12339 net.user1.orbiter.snapshot.GatewaysSnapshot = function () { 12340 // Call superconstructor 12341 net.user1.orbiter.snapshot.Snapshot.call(this); 12342 this.gateways = null; 12343 this.method = net.user1.orbiter.UPC.GET_GATEWAYS_SNAPSHOT; 12344 }; 12345 12346 //============================================================================== 12347 // INHERITANCE 12348 //============================================================================== 12349 net.user1.utils.extend(net.user1.orbiter.snapshot.GatewaysSnapshot, net.user1.orbiter.snapshot.Snapshot); 12350 12351 //============================================================================== 12352 // INSTANCE METHODS 12353 //============================================================================== 12354 /** 12355 * @private 12356 */ 12357 net.user1.orbiter.snapshot.GatewaysSnapshot.prototype.setGateways = function (value) { 12358 this.gateways = value; 12359 }; 12360 12361 net.user1.orbiter.snapshot.GatewaysSnapshot.prototype.getGateways = function () { 12362 if (!this.gateways) { 12363 return []; 12364 } 12365 return this.gateways.slice(); 12366 }; 12367 //============================================================================== 12368 // CLASS DECLARATION 12369 //============================================================================== 12370 /** @class 12371 @extends net.user1.events.Event 12372 */ 12373 net.user1.orbiter.ServerEvent = function (type, 12374 upcProcessingRecord, 12375 status) { 12376 net.user1.events.Event.call(this, type); 12377 12378 this.upcProcessingRecord = upcProcessingRecord; 12379 this.status = status; 12380 }; 12381 12382 //============================================================================== 12383 // INHERITANCE 12384 //============================================================================== 12385 net.user1.utils.extend(net.user1.orbiter.ServerEvent, net.user1.events.Event); 12386 12387 //============================================================================== 12388 // STATIC VARIABLES 12389 //============================================================================== 12390 12391 /** @constant */ 12392 net.user1.orbiter.ServerEvent.TIME_SYNC = "TIME_SYNC"; 12393 /** @constant */ 12394 net.user1.orbiter.ServerEvent.UPC_PROCESSED = "UPC_PROCESSED"; 12395 /** @constant */ 12396 net.user1.orbiter.ServerEvent.WATCH_FOR_PROCESSED_UPCS_RESULT = "WATCH_FOR_PROCESSED_UPCS_RESULT"; 12397 /** @constant */ 12398 net.user1.orbiter.ServerEvent.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT = "STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT"; 12399 /** @constant */ 12400 net.user1.orbiter.ServerEvent.RESET_UPC_STATS_RESULT = "RESET_UPC_STATS_RESULT"; 12401 12402 //============================================================================== 12403 // VARIABLES 12404 //============================================================================== 12405 net.user1.orbiter.ServerEvent.prototype.getUPCProcessingRecord = function () { 12406 return upcProcessingRecord; 12407 } 12408 12409 net.user1.orbiter.ServerEvent.prototype.getStatus = function () { 12410 return status; 12411 } 12412 12413 12414 net.user1.orbiter.ServerEvent.prototype.toString = function () { 12415 return "[object ServerEvent]"; 12416 }; 12417 //============================================================================== 12418 // CLASS DECLARATION 12419 //============================================================================== 12420 /** 12421 * @class 12422 * @extends net.user1.orbiter.snapshot.Snapshot 12423 */ 12424 net.user1.orbiter.snapshot.ServerModuleListSnapshot = function () { 12425 // Call superconstructor 12426 net.user1.orbiter.snapshot.Snapshot.call(this); 12427 this.moduleList = null; 12428 this.method = net.user1.orbiter.UPC.GET_SERVERMODULELIST_SNAPSHOT; 12429 }; 12430 12431 //============================================================================== 12432 // INHERITANCE 12433 //============================================================================== 12434 net.user1.utils.extend(net.user1.orbiter.snapshot.ServerModuleListSnapshot, net.user1.orbiter.snapshot.Snapshot); 12435 12436 //============================================================================== 12437 // INSTANCE METHODS 12438 //============================================================================== 12439 /** 12440 * @private 12441 */ 12442 net.user1.orbiter.snapshot.ServerModuleListSnapshot.prototype.setModuleList = function (value) { 12443 this.moduleList = value; 12444 } 12445 12446 net.user1.orbiter.snapshot.ServerModuleListSnapshot.prototype.getModuleList = function () { 12447 if (!this.moduleList) { 12448 return null; 12449 } 12450 return this.moduleList.slice(); 12451 }; 12452 //============================================================================== 12453 // CLASS DECLARATION 12454 //============================================================================== 12455 /** 12456 * @private 12457 * @class 12458 */ 12459 net.user1.orbiter.upc.SetAttr = function (name, 12460 value, 12461 options) { 12462 12463 // Abort if name is invalid. 12464 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 12465 throw new Error("Cannot set attribute. Illegal name" + 12466 " (see Validator.isValidAttributeName()). " + 12467 " Illegal attribute is: " + name + "=" + value); 12468 } 12469 12470 // Abort if value is invalid. 12471 if (!net.user1.orbiter.Validator.isValidAttributeValue(value)) { 12472 throw new Error("Cannot set attribute. Illegal value" + 12473 " (see Validator.isValidAttributeValue()). " + 12474 " Illegal attribute is: " + name + "=" + value); 12475 } 12476 12477 if (value == null) { 12478 value = ""; 12479 } 12480 12481 // Validation passed, so assign instance vars. 12482 this.name = name; 12483 this.value = value; 12484 this.options = options; 12485 }; 12486 /** 12487 * @private 12488 */ 12489 net.user1.orbiter.upc.SetClientAttr = function (name, 12490 value, 12491 options, 12492 scope, 12493 clientID, 12494 userID) { 12495 // Call superconstructor 12496 net.user1.orbiter.upc.SetAttr.call(this, name, value, options); 12497 12498 // Abort if scope is invalid. 12499 if (!net.user1.orbiter.Validator.isValidAttributeScope(scope)) { 12500 throw new Error("Cannot set client attribute. Illegal scope" + 12501 " (see Validator.isValidAttributeScope()). " + 12502 " Illegal attribute is: " + name + "=" + value); 12503 } 12504 12505 // A scope null means the attribute is global. 12506 if (scope == null) { 12507 scope = net.user1.orbiter.Tokens.GLOBAL_ATTR; 12508 } 12509 12510 this.method = net.user1.orbiter.UPC.SET_CLIENT_ATTR; 12511 this.args = [clientID, userID, name, value, scope, options.toString()]; 12512 }; 12513 12514 //============================================================================== 12515 // INHERITANCE 12516 //============================================================================== 12517 net.user1.utils.extend(net.user1.orbiter.upc.SetClientAttr, net.user1.orbiter.upc.SetAttr); 12518 /** 12519 * @private 12520 */ 12521 net.user1.orbiter.upc.SetRoomAttr = function (name, 12522 value, 12523 options, 12524 roomID) { 12525 // Call superconstructor 12526 net.user1.orbiter.upc.SetAttr.call(this, name, value, options); 12527 12528 this.method = net.user1.orbiter.UPC.SET_ROOM_ATTR; 12529 this.args = [roomID, name, value, options.toString()]; 12530 }; 12531 12532 //============================================================================== 12533 // INHERITANCE 12534 //============================================================================== 12535 net.user1.utils.extend(net.user1.orbiter.upc.SetRoomAttr, net.user1.orbiter.upc.SetAttr); 12536 //============================================================================== 12537 // CLASS DECLARATION 12538 //============================================================================== 12539 /** 12540 * @class 12541 * 12542 * Note: Due to JavaScript's lack of memory measurement APIs and byte-measurement 12543 * APIs, Orbiter's Statistics class does not include many of the statistics found 12544 * in the equivalent Reactor Statistics class. 12545 */ 12546 net.user1.orbiter.Statistics = function (orbiter) { 12547 this.statsTimer; 12548 this.lastTick = NaN; 12549 this.lastTotalMessages = 0; 12550 this.messagesPerSecond = 0; 12551 12552 // Peaks 12553 this.peakMessagesPerSecond = 0; 12554 12555 this.orbiter = null; 12556 this.connection = null; 12557 12558 this.statsIntervalID = -1; 12559 12560 this.init(orbiter); 12561 }; 12562 12563 /** 12564 * @private 12565 */ 12566 net.user1.orbiter.Statistics.prototype.init = function (orbiter) { 12567 this.setOrbiter(orbiter); 12568 this.start(); 12569 }; 12570 12571 /** 12572 * @private 12573 */ 12574 net.user1.orbiter.Statistics.prototype.setOrbiter = function (orbiter) { 12575 // Register new orbiter 12576 this.orbiter = orbiter; 12577 }; 12578 12579 net.user1.orbiter.Statistics.prototype.start = function () { 12580 this.stop(); 12581 12582 this.statsIntervalID = setInterval(statsTimerListener, 1000); 12583 12584 this.lastTick = new Date().getTime(); 12585 this.lastTotalMessages = this.getTotalMessages(); 12586 }; 12587 12588 net.user1.orbiter.Statistics.prototype.stop = function () { 12589 clearInterval(statsIntervalID); 12590 this.clearStats(); 12591 }; 12592 12593 /** 12594 * @private 12595 */ 12596 net.user1.orbiter.Statistics.prototype.clearStats = function () { 12597 this.lastTick = 0; 12598 this.lastTotalMessages = 0; 12599 this.messagesPerSecond = 0; 12600 this.peakMessagesPerSecond = 0; 12601 }; 12602 12603 net.user1.orbiter.Statistics.prototype.getLifetimeNumClientsConnected = function () { 12604 return this.orbiter.getClientManager().getLifetimeNumClientsKnown(); 12605 }; 12606 12607 net.user1.orbiter.Statistics.prototype.getCurrentNumClientsConnected = function () { 12608 return this.orbiter.getClientManager().getNumClients(); 12609 }; 12610 12611 net.user1.orbiter.Statistics.prototype.getTotalMessagesReceived = function () { 12612 return this.orbiter.getMessageManager().getNumMessagesReceived(); 12613 } 12614 12615 net.user1.orbiter.Statistics.prototype.getTotalMessagesSent = function () { 12616 return this.orbiter.getMessageManager().getNumMessagesSent(); 12617 }; 12618 12619 net.user1.orbiter.Statistics.prototype.getTotalMessages = function () { 12620 return this.getTotalMessagesReceived() + this.getTotalMessagesSent(); 12621 }; 12622 12623 net.user1.orbiter.Statistics.prototype.getMessagesPerSecond = function () { 12624 return this.messagesPerSecond; 12625 }; 12626 12627 //============================================================================== 12628 // PEAK MESSAGES PER SECOND 12629 //============================================================================== 12630 12631 net.user1.orbiter.Statistics.prototype.getPeakMessagesPerSecond = function () { 12632 return this.peakMessagesPerSecond; 12633 }; 12634 12635 // ============================================================================= 12636 // TIMER LISTENER 12637 // ============================================================================= 12638 12639 /** 12640 * @private 12641 */ 12642 net.user1.orbiter.Statistics.prototype.statsTimerListener = function (e) { 12643 // Check elapsed time 12644 var now = new Date().getTime(); 12645 var elapsed = now - lastTick; 12646 lastTick = now; 12647 12648 // Calculate number of messages sent and received since last tick 12649 var totalMessages = this.getTotalMessages(); 12650 var tickNumMsgs = totalMessages - this.lastTotalMessages; 12651 this.lastTotalMessages = totalMessages; 12652 this.messagesPerSecond = Math.round((1000/elapsed) * tickNumMsgs); 12653 if (this.messagesPerSecond > this.peakMessagesPerSecond) { 12654 this.peakMessagesPerSecond = this.messagesPerSecond; 12655 } 12656 }; 12657 //============================================================================== 12658 // STATUS CONSTANTS 12659 //============================================================================== 12660 /** @class */ 12661 net.user1.orbiter.Status = new Object(); 12662 /** @constant */ 12663 net.user1.orbiter.Status.ACCOUNT_EXISTS = "ACCOUNT_EXISTS"; 12664 /** @constant */ 12665 net.user1.orbiter.Status.ACCOUNT_NOT_FOUND = "ACCOUNT_NOT_FOUND"; 12666 /** @constant */ 12667 net.user1.orbiter.Status.AUTHORIZATION_REQUIRED = "AUTHORIZATION_REQUIRED"; 12668 /** @constant */ 12669 net.user1.orbiter.Status.AUTHORIZATION_FAILED = "AUTHORIZATION_FAILED"; 12670 /** @constant */ 12671 net.user1.orbiter.Status.ALREADY_ASSIGNED = "ALREADY_ASSIGNED"; 12672 /** @constant */ 12673 net.user1.orbiter.Status.ALREADY_BANNED = "ALREADY_BANNED"; 12674 /** @constant */ 12675 net.user1.orbiter.Status.ALREADY_IN_ROOM = "ALREADY_IN_ROOM"; 12676 /** @constant */ 12677 net.user1.orbiter.Status.ALREADY_LOGGED_IN = "ALREADY_LOGGED_IN"; 12678 /** @constant */ 12679 net.user1.orbiter.Status.ALREADY_OBSERVING = "ALREADY_OBSERVING"; 12680 /** @constant */ 12681 net.user1.orbiter.Status.ALREADY_SYNCHRONIZED = "ALREADY_SYNCHRONIZED"; 12682 /** @constant */ 12683 net.user1.orbiter.Status.ALREADY_WATCHING = "ALREADY_WATCHING"; 12684 /** @constant */ 12685 net.user1.orbiter.Status.ATTR_NOT_FOUND = "ATTR_NOT_FOUND"; 12686 /** @constant */ 12687 net.user1.orbiter.Status.CLIENT_NOT_FOUND = "CLIENT_NOT_FOUND"; 12688 /** @constant */ 12689 net.user1.orbiter.Status.ERROR = "ERROR"; 12690 /** @constant */ 12691 net.user1.orbiter.Status.EVALUATION_FAILED = "EVALUATION_FAILED"; 12692 /** @constant */ 12693 net.user1.orbiter.Status.DUPLICATE_VALUE = "DUPLICATE_VALUE"; 12694 /** @constant */ 12695 net.user1.orbiter.Status.IMMUTABLE = "IMMUTABLE"; 12696 /** @constant */ 12697 net.user1.orbiter.Status.INVALID_QUALIFIER = "INVALID_QUALIFIER"; 12698 /** @constant */ 12699 net.user1.orbiter.Status.NAME_NOT_FOUND = "NAME_NOT_FOUND"; 12700 /** @constant */ 12701 net.user1.orbiter.Status.NAME_EXISTS = "NAME_EXISTS"; 12702 /** @constant */ 12703 net.user1.orbiter.Status.NOT_ASSIGNED = "NOT_ASSIGNED"; 12704 /** @constant */ 12705 net.user1.orbiter.Status.NOT_BANNED = "NOT_BANNED"; 12706 /** @constant */ 12707 net.user1.orbiter.Status.NOT_IN_ROOM = "NOT_IN_ROOM"; 12708 /** @constant */ 12709 net.user1.orbiter.Status.NOT_LOGGED_IN = "NOT_LOGGED_IN"; 12710 /** @constant */ 12711 net.user1.orbiter.Status.NOT_OBSERVING = "NOT_OBSERVING"; 12712 /** @constant */ 12713 net.user1.orbiter.Status.NOT_WATCHING = "NOT_WATCHING"; 12714 /** @constant */ 12715 net.user1.orbiter.Status.PERMISSION_DENIED = "PERMISSION_DENIED"; 12716 /** @constant */ 12717 net.user1.orbiter.Status.REMOVED = "REMOVED"; 12718 /** @constant */ 12719 net.user1.orbiter.Status.ROLE_NOT_FOUND = "ROLE_NOT_FOUND"; 12720 /** @constant */ 12721 net.user1.orbiter.Status.ROOM_EXISTS = "ROOM_EXISTS"; 12722 /** @constant */ 12723 net.user1.orbiter.Status.ROOM_FULL = "ROOM_FULL"; 12724 /** @constant */ 12725 net.user1.orbiter.Status.ROOM_NOT_FOUND = "ROOM_NOT_FOUND"; 12726 /** @constant */ 12727 net.user1.orbiter.Status.SERVER_ONLY = "SERVER_ONLY"; 12728 /** @constant */ 12729 net.user1.orbiter.Status.SUCCESS = "SUCCESS"; 12730 //============================================================================== 12731 // STATUS CONSTANTS 12732 //============================================================================== 12733 /** @class */ 12734 net.user1.orbiter.SynchronizationState = new Object(); 12735 /** @constant */ 12736 net.user1.orbiter.SynchronizationState.SYNCHRONIZED = "SYNCHRONIZED"; 12737 /** @constant */ 12738 net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED = "NOT_SYNCHRONIZED"; 12739 /** @constant */ 12740 net.user1.orbiter.SynchronizationState.SYNCHRONIZING = "SYNCHRONIZING"; 12741 //============================================================================== 12742 // CLASS DECLARATION 12743 //============================================================================== 12744 /** 12745 * @class 12746 */ 12747 net.user1.orbiter.UPCProcessingRecord = function () { 12748 /** 12749 * @field 12750 */ 12751 this.fromClientID = null; 12752 /** 12753 * @field 12754 */ 12755 this.fromUserID = null; 12756 /** 12757 * @field 12758 */ 12759 this.fromClientAddress = null; 12760 /** 12761 * @field 12762 */ 12763 this.processingStartedAt = NaN; 12764 /** 12765 * @field 12766 */ 12767 this.processingFinishedAt = NaN; 12768 /** 12769 * @field 12770 */ 12771 this.processingDuration = NaN; 12772 /** 12773 * @field 12774 */ 12775 this.queuedAt = NaN; 12776 /** 12777 * @field 12778 */ 12779 this.queueDuration = NaN; 12780 /** 12781 * @field 12782 */ 12783 this.UPCSource = null; 12784 }; 12785 12786 /** 12787 * @private 12788 */ 12789 net.user1.orbiter.UPCProcessingRecord.prototype.deserialize = function (serializedRecord) { 12790 var recordParts = []; 12791 var numSignificantSeparators = 6; 12792 var separatorIndices = []; 12793 var thisSeparatorIndex = 0; 12794 var previousSeparatorIndex = -1; 12795 12796 // Don't use split because the source might contain the record separator 12797 for (var i = 0; i < numSignificantSeparators; i++) { 12798 thisSeparatorIndex = serializedRecord.indexOf(net.user1.orbiter.Tokens.RS, previousSeparatorIndex+1); 12799 recordParts.push(serializedRecord.substring(previousSeparatorIndex+1, thisSeparatorIndex)); 12800 previousSeparatorIndex = thisSeparatorIndex; 12801 } 12802 recordParts.push(serializedRecord.substring(thisSeparatorIndex+1)); 12803 12804 this.deserializeParts(recordParts[0], 12805 recordParts[1], 12806 recordParts[2], 12807 recordParts[3], 12808 recordParts[4], 12809 recordParts[5], 12810 recordParts[6]); 12811 }; 12812 12813 /** 12814 * @private 12815 */ 12816 net.user1.orbiter.UPCProcessingRecord.prototype.deserializeParts = function (fromClientID, 12817 fromUserID, 12818 fromClientAddress, 12819 queuedAt, 12820 processingStartedAt, 12821 processingFinishedAt, 12822 source) { 12823 this.fromClientID = fromClientID; 12824 this.fromUserID = fromUserID; 12825 this.fromClientAddress = fromClientAddress; 12826 this.processingStartedAt = parseFloat(processingStartedAt); 12827 this.processingFinishedAt = parseFloat(processingFinishedAt); 12828 this.processingDuration = this.processingFinishedAt - this.processingStartedAt; 12829 this.queuedAt = parseFloat(queuedAt); 12830 this.queueDuration = this.processingStartedAt - this.queuedAt; 12831 this.UPCSource = source; 12832 var escapedCDStart = /<!\(\[CDATA\[/gi; 12833 var escapedCDEnd = /\]\]\)>/gi; 12834 this.UPCSource = this.UPCSource.replace(escapedCDStart, "<![CDATA["); 12835 this.UPCSource = this.UPCSource.replace(escapedCDEnd, "]]>"); 12836 } 12837 //============================================================================== 12838 // CLASS DECLARATION 12839 //============================================================================== 12840 /** 12841 * @class 12842 * @extends net.user1.orbiter.snapshot.Snapshot 12843 */ 12844 net.user1.orbiter.snapshot.UPCStatsSnapshot = function () { 12845 // Call superconstructor 12846 net.user1.orbiter.snapshot.Snapshot.call(this); 12847 this.totalUPCsProcessed; 12848 this.numUPCsInQueue; 12849 this.lastQueueWaitTime; 12850 this.longestUPCProcesses; 12851 this.method = net.user1.orbiter.UPC.GET_UPC_STATS_SNAPSHOT; 12852 this.hasStatus = true; 12853 }; 12854 12855 //============================================================================== 12856 // INHERITANCE 12857 //============================================================================== 12858 net.user1.utils.extend(net.user1.orbiter.snapshot.UPCStatsSnapshot, net.user1.orbiter.snapshot.Snapshot); 12859 12860 //============================================================================== 12861 // INSTANCE METHODS 12862 //============================================================================== 12863 /** 12864 * @private 12865 */ 12866 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setTotalUPCsProcessed = function (value) { 12867 this.totalUPCsProcessed = value; 12868 }; 12869 12870 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getTotalUPCsProcessed = function () { 12871 return this.totalUPCsProcessed; 12872 }; 12873 12874 /** 12875 * @private 12876 */ 12877 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setNumUPCsInQueue = function (value) { 12878 this.numUPCsInQueue = value; 12879 }; 12880 12881 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getNumUPCsInQueue = function () { 12882 return this.numUPCsInQueue; 12883 }; 12884 12885 /** 12886 * @private 12887 */ 12888 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setLastQueueWaitTime = function (value) { 12889 this.lastQueueWaitTime = value; 12890 }; 12891 12892 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getLastQueueWaitTime = function () { 12893 return this.lastQueueWaitTime; 12894 }; 12895 12896 /** 12897 * @private 12898 */ 12899 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setLongestUPCProcesses = function (value) { 12900 this.longestUPCProcesses = value; 12901 }; 12902 12903 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getLongestUPCProcesses = function () { 12904 if (!this.longestUPCProcesses) { 12905 return null; 12906 } 12907 return this.longestUPCProcesses.slice(); 12908 }; 12909 //============================================================================== 12910 // CLASS DECLARATION 12911 //============================================================================== 12912 net.user1.orbiter.UpdateLevels = function () { 12913 this.restoreDefaults(); 12914 }; 12915 12916 //============================================================================== 12917 // STATIC VARIABLES 12918 //============================================================================== 12919 net.user1.orbiter.UpdateLevels.FLAG_ROOM_MESSAGES = 1; 12920 net.user1.orbiter.UpdateLevels.FLAG_SHARED_ROOM_ATTRIBUTES = 1 << 1; 12921 net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_COUNT = 1 << 2; 12922 net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_COUNT = 1 << 3; 12923 net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LIST = 1 << 4; 12924 net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LIST = 1 << 5; 12925 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_ROOM = 1 << 6; 12926 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_ROOM = 1 << 7; 12927 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_GLOBAL = 1 << 8; 12928 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_GLOBAL = 1 << 9; 12929 net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LOGIN_LOGOFF = 1 << 10; 12930 net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LOGIN_LOGOFF = 1 << 11; 12931 net.user1.orbiter.UpdateLevels.FLAG_ALL_ROOM_ATTRIBUTES = 1 << 12; 12932 12933 //============================================================================== 12934 // INSTANCE METHODS 12935 //============================================================================== 12936 net.user1.orbiter.UpdateLevels.prototype.clearAll = function () { 12937 this.roomMessages = false; 12938 this.sharedRoomAttributes = false; 12939 this.occupantCount = false; 12940 this.observerCount = false; 12941 this.occupantList = false; 12942 this.observerList = false; 12943 this.sharedOccupantAttributesRoom = false; 12944 this.sharedOccupantAttributesGlobal = false; 12945 this.sharedObserverAttributesRoom = false; 12946 this.sharedObserverAttributesGlobal = false; 12947 this.occupantLoginLogoff = false; 12948 this.observerLoginLogoff = false; 12949 this.allRoomAttributes = false; 12950 }; 12951 12952 net.user1.orbiter.UpdateLevels.prototype.restoreDefaults = function () { 12953 this.roomMessages = true; 12954 this.sharedRoomAttributes = true; 12955 this.occupantCount = false; 12956 this.observerCount = false; 12957 this.occupantList = true; 12958 this.observerList = false; 12959 this.sharedOccupantAttributesRoom = true; 12960 this.sharedOccupantAttributesGlobal = true; 12961 this.sharedObserverAttributesRoom = false; 12962 this.sharedObserverAttributesGlobal = false; 12963 this.occupantLoginLogoff = true; 12964 this.observerLoginLogoff = false; 12965 this.allRoomAttributes = false; 12966 }; 12967 12968 net.user1.orbiter.UpdateLevels.prototype.toInt = function () { 12969 var levels = (this.roomMessages ? net.user1.orbiter.UpdateLevels.FLAG_ROOM_MESSAGES : 0) 12970 | (this.sharedRoomAttributes ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_ROOM_ATTRIBUTES : 0) 12971 | (this.occupantCount ? net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_COUNT : 0) 12972 | (this.observerCount ? net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_COUNT : 0) 12973 | (this.occupantList ? net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LIST : 0) 12974 | (this.observerList ? net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LIST : 0) 12975 | (this.sharedOccupantAttributesRoom ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_ROOM : 0) 12976 | (this.sharedOccupantAttributesGlobal ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_GLOBAL : 0) 12977 | (this.sharedObserverAttributesRoom ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_ROOM : 0) 12978 | (this.sharedObserverAttributesGlobal ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_GLOBAL : 0) 12979 | (this.occupantLoginLogoff ? net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LOGIN_LOGOFF : 0) 12980 | (this.observerLoginLogoff ? net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LOGIN_LOGOFF : 0) 12981 | (this.allRoomAttributes ? net.user1.orbiter.UpdateLevels.FLAG_ALL_ROOM_ATTRIBUTES : 0); 12982 12983 return levels; 12984 }; 12985 12986 net.user1.orbiter.UpdateLevels.prototype.fromInt = function (levels) { 12987 roomMessages = levels & net.user1.orbiter.UpdateLevels.FLAG_ROOM_MESSAGES; 12988 sharedRoomAttributes = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_ROOM_ATTRIBUTES; 12989 occupantCount = levels & net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_COUNT; 12990 observerCount = levels & net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_COUNT; 12991 occupantList = levels & net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LIST; 12992 observerList = levels & net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LIST; 12993 sharedOccupantAttributesRoom = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_ROOM; 12994 sharedOccupantAttributesGlobal = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_GLOBAL; 12995 sharedObserverAttributesRoom = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_ROOM; 12996 sharedObserverAttributesGlobal = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_GLOBAL; 12997 occupantLoginLogoff = levels & net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LOGIN_LOGOFF; 12998 observerLoginLogoff = levels & net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LOGIN_LOGOFF; 12999 allRoomAttributes = levels & net.user1.orbiter.UpdateLevels.FLAG_ALL_ROOM_ATTRIBUTES; 13000 }; 13001 //============================================================================== 13002 // CLASS DECLARATION 13003 //============================================================================== 13004 /** @class 13005 13006 The UserAccount class dispatches the following events: 13007 13008 <ul class="summary"> 13009 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN}</li> 13010 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF_RESULT}</li> 13011 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF}</li> 13012 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT}</li> 13013 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD}</li> 13014 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.SYNCHRONIZE}</li> 13015 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE}</li> 13016 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE_RESULT}</li> 13017 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING}</li> 13018 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT}</li> 13019 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT}</li> 13020 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT}</li> 13021 </ul> 13022 13023 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 13024 13025 @extends net.user1.events.EventDispatcher 13026 */ 13027 13028 net.user1.orbiter.UserAccount = function (userID, 13029 log, 13030 accountManager, 13031 clientManager, 13032 roomManager) { 13033 net.user1.events.EventDispatcher.call(this); 13034 13035 this.userID = userID; 13036 this.attributeManager = null; 13037 this.connectionState = 0; 13038 this.password = null; 13039 this.lastAttemptedPassword = null; 13040 this._client = null; 13041 this._accountManager = null; 13042 this._clientManager = null; 13043 this._roomManager = null; 13044 this._log = null; 13045 13046 this.setLog(log); 13047 this.setAccountManager(accountManager); 13048 this.setClientManager(clientManager); 13049 this.setRoomManager(roomManager); 13050 }; 13051 13052 //============================================================================== 13053 // INHERITANCE 13054 //============================================================================== 13055 net.user1.utils.extend(net.user1.orbiter.UserAccount, net.user1.events.EventDispatcher); 13056 13057 //============================================================================== 13058 // STATIC VARIABLES 13059 //============================================================================== 13060 /** @private */ 13061 net.user1.orbiter.UserAccount.FLAG_MODERATOR = 1 << 1; 13062 13063 //============================================================================== 13064 // DEPENDENCIES 13065 //============================================================================== 13066 13067 /** 13068 * @private 13069 */ 13070 net.user1.orbiter.UserAccount.prototype.getAttributeCollection = function () { 13071 return this.attributeManager.getAttributeCollection(); 13072 }; 13073 13074 /** 13075 * @private 13076 */ 13077 net.user1.orbiter.UserAccount.prototype.setAttributeManager = function (value) { 13078 this.attributeManager = value; 13079 }; 13080 13081 /** 13082 * @private 13083 */ 13084 net.user1.orbiter.UserAccount.prototype.getAttributeManager = function () { 13085 return this.attributeManager; 13086 }; 13087 13088 /** 13089 * @private 13090 */ 13091 net.user1.orbiter.UserAccount.prototype.getClientManager = function () { 13092 return this._clientManager; 13093 }; 13094 13095 /** 13096 * @private 13097 */ 13098 net.user1.orbiter.UserAccount.prototype.setClientManager = function (value) { 13099 this._clientManager = value; 13100 }; 13101 13102 /** 13103 * @private 13104 */ 13105 net.user1.orbiter.UserAccount.prototype.getRoomManager = function () { 13106 return this._roomManager; 13107 }; 13108 13109 /** 13110 * @private 13111 */ 13112 net.user1.orbiter.UserAccount.prototype.setRoomManager = function (value) { 13113 this._roomManager = value; 13114 }; 13115 13116 /** 13117 * @private 13118 */ 13119 net.user1.orbiter.UserAccount.prototype.getLog = function () { 13120 return this._log; 13121 }; 13122 13123 /** 13124 * @private 13125 */ 13126 net.user1.orbiter.UserAccount.prototype.setLog = function (value) { 13127 this._log = value; 13128 }; 13129 13130 /** 13131 * @private 13132 */ 13133 net.user1.orbiter.UserAccount.prototype.getAccountManager = function () { 13134 return this._accountManager; 13135 }; 13136 13137 /** 13138 * @private 13139 */ 13140 net.user1.orbiter.UserAccount.prototype.setAccountManager = function (value) { 13141 this._accountManager = value; 13142 }; 13143 13144 net.user1.orbiter.UserAccount.prototype.getClient = function () { 13145 var customClient; 13146 this.validateClientReference(); 13147 if (this._client != null) { 13148 customClient = this._client.getCustomClient(null); 13149 return customClient == null ? this._client : customClient; 13150 } else { 13151 return null; 13152 } 13153 }; 13154 13155 net.user1.orbiter.UserAccount.prototype.getInternalClient = function () { 13156 this.validateClientReference(); 13157 return this._client; 13158 } 13159 13160 /** 13161 * @private 13162 */ 13163 net.user1.orbiter.UserAccount.prototype.setClient = function (value) { 13164 if (value == null) { 13165 this._client = null; 13166 } else { 13167 if (this._client != value) { 13168 this._client = value; 13169 this._client.setAccount(this); 13170 } 13171 } 13172 }; 13173 13174 /** 13175 * @private 13176 */ 13177 net.user1.orbiter.UserAccount.prototype.validateClientReference = function () { 13178 if (this._client != null) { 13179 if (!this._client.isSelf() 13180 && !this._clientManager.isWatchingForClients() 13181 && !this._accountManager.isObservingAccount(this.getUserID()) 13182 && !this._clientManager.isObservingClient(this._client.getClientID()) 13183 && !this._roomManager.clientIsKnown(this._client.getClientID())) { 13184 this.setClient(null); 13185 } 13186 } 13187 }; 13188 13189 //============================================================================== 13190 // IS SELF 13191 //============================================================================== 13192 13193 net.user1.orbiter.UserAccount.prototype.isSelf = function () { 13194 return this._client == null ? false : this._client.isSelf(); 13195 }; 13196 13197 //============================================================================== 13198 // CONNECTION STATE 13199 //============================================================================== 13200 13201 net.user1.orbiter.UserAccount.prototype.getConnectionState = function () { 13202 if (this.getInternalClient() != null) { 13203 return net.user1.orbiter.ConnectionState.LOGGED_IN; 13204 } else if (!this._accountManager.isObservingAccount(this.getUserID())) { 13205 return net.user1.orbiter.ConnectionState.NOT_CONNECTED; 13206 } else if (this._clientManager.isWatchingForClients()) { 13207 return net.user1.orbiter.ConnectionState.NOT_CONNECTED; 13208 } else { 13209 // Not observing this user, not watching for clients, and no client means 13210 // this account's state is unknown. (This happens when watching for user 13211 // accounts). 13212 return net.user1.orbiter.ConnectionState.UNKNOWN; 13213 } 13214 }; 13215 13216 net.user1.orbiter.UserAccount.prototype.isLoggedIn = function () { 13217 return this.getConnectionState() == net.user1.orbiter.ConnectionState.LOGGED_IN; 13218 }; 13219 13220 //============================================================================== 13221 // USER ID 13222 //============================================================================== 13223 13224 net.user1.orbiter.UserAccount.prototype.getUserID = function () { 13225 return this.userID; 13226 }; 13227 13228 /** 13229 * @private 13230 */ 13231 net.user1.orbiter.UserAccount.prototype.setUserID = function (userID) { 13232 if (this.userID != userID) { 13233 this.userID = userID; 13234 } 13235 }; 13236 13237 // ============================================================================= 13238 // LOGOFF 13239 // ============================================================================= 13240 13241 net.user1.orbiter.UserAccount.prototype.logoff = function (password) { 13242 this._accountManager.logoff(this.getUserID(), password); 13243 }; 13244 13245 // ============================================================================= 13246 // CHANGE PASSWORD 13247 // ============================================================================= 13248 13249 net.user1.orbiter.UserAccount.prototype.changePassword = function (newPassword, oldPassword) { 13250 this._accountManager.changePassword(this.getUserID(), newPassword, oldPassword); 13251 }; 13252 13253 // ============================================================================= 13254 // ROLES 13255 // ============================================================================= 13256 13257 net.user1.orbiter.UserAccount.prototype.addRole = function (role) { 13258 this._accountManager.addRole(this.getUserID(), role); 13259 }; 13260 13261 net.user1.orbiter.UserAccount.prototype.removeRole = function (userID, role) { 13262 this._accountManager.removeRole(this.getUserID(), role); 13263 }; 13264 13265 net.user1.orbiter.UserAccount.prototype.isModerator = function () { 13266 var rolesAttr = this.getAttribute(net.user1.orbiter.Tokens.ROLES_ATTR); 13267 var roles; 13268 if (rolesAttr != null) { 13269 return (parseInt(rolesAttr) & UserAccount.FLAG_MODERATOR) > 0; 13270 } else { 13271 this.getLog().warn(this.toString() + " Could not determine moderator status because the account is not synchronized."); 13272 return false; 13273 } 13274 }; 13275 13276 // ============================================================================= 13277 // LOGIN/LOGOFF TASKS 13278 // ============================================================================= 13279 13280 /** 13281 * @private 13282 */ 13283 net.user1.orbiter.UserAccount.prototype.doLoginTasks = function () { 13284 this.fireLogin(); 13285 }; 13286 13287 /** 13288 * @private 13289 */ 13290 net.user1.orbiter.UserAccount.prototype.doLogoffTasks = function () { 13291 this.setClient(null); 13292 this.fireLogoff(); 13293 }; 13294 13295 // ============================================================================= 13296 // OBSERVATION 13297 // ============================================================================= 13298 13299 net.user1.orbiter.UserAccount.prototype.observe = function () { 13300 this._accountManager.observeAccount(this.getUserID()); 13301 }; 13302 13303 net.user1.orbiter.UserAccount.prototype.stopObserving = function () { 13304 this._accountManager.stopObservingAccount(this.getUserID()); 13305 }; 13306 13307 // ============================================================================= 13308 // ATTRIBUTES: PUBLIC API 13309 // ============================================================================= 13310 13311 net.user1.orbiter.UserAccount.prototype.setAttribute = function (attrName, 13312 attrValue, 13313 attrScope, 13314 isShared, 13315 evaluate) { 13316 // Create an integer to hold the attribute options 13317 var attrOptions = net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT 13318 | (isShared ? net.user1.orbiter.AttributeOptions.FLAG_SHARED : 0) 13319 | (evaluate ? net.user1.orbiter.AttributeOptions.FLAG_EVALUATE : 0); 13320 13321 // Set the attribute on the server. 13322 this.attributeManager.setAttribute(new net.user1.orbiter.upc.SetClientAttr(attrName, attrValue, attrOptions, attrScope, null, this.getUserID())); 13323 }; 13324 13325 net.user1.orbiter.UserAccount.prototype.deleteAttribute = function (attrName, attrScope) { 13326 var deleteRequest = new net.user1.orbiter.upc.RemoveClientAttr(null, this.getUserID(), attrName, attrScope); 13327 this.attributeManager.deleteAttribute(deleteRequest); 13328 }; 13329 13330 net.user1.orbiter.UserAccount.prototype.getAttribute = function (attrName, attrScope) { 13331 return this.attributeManager.getAttribute(attrName, attrScope); 13332 }; 13333 13334 net.user1.orbiter.UserAccount.prototype.getAttributes = function () { 13335 return this.attributeManager.getAttributes(); 13336 }; 13337 13338 net.user1.orbiter.UserAccount.prototype.getAttributesByScope = function (scope) { 13339 return this.attributeManager.getAttributesByScope(scope); 13340 }; 13341 13342 //============================================================================== 13343 // TOSTRING 13344 //============================================================================== 13345 13346 net.user1.orbiter.UserAccount.prototype.toString = function () { 13347 return "[USER_ACCOUNT userid: " + this.getUserID() + ", clientid: " + (this._client == null ? "" : this._client.getClientID()) + "]"; 13348 }; 13349 13350 //============================================================================== 13351 // EVENT DISPATCHING 13352 //============================================================================== 13353 13354 /** 13355 * @private 13356 */ 13357 net.user1.orbiter.UserAccount.prototype.fireLogin = function () { 13358 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN, 13359 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13360 this.dispatchEvent(e); 13361 }; 13362 13363 /** 13364 * @private 13365 */ 13366 net.user1.orbiter.UserAccount.prototype.fireLogoffResult = function (status) { 13367 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF_RESULT, 13368 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13369 this.dispatchEvent(e); 13370 }; 13371 13372 /** 13373 * @private 13374 */ 13375 net.user1.orbiter.UserAccount.prototype.fireLogoff = function () { 13376 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF, 13377 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13378 this.dispatchEvent(e); 13379 }; 13380 13381 /** 13382 * @private 13383 */ 13384 net.user1.orbiter.UserAccount.prototype.fireChangePasswordResult = function (status) { 13385 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT, 13386 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13387 this.dispatchEvent(e); 13388 }; 13389 13390 /** 13391 * @private 13392 */ 13393 net.user1.orbiter.UserAccount.prototype.fireChangePassword = function () { 13394 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD, 13395 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13396 this.dispatchEvent(e); 13397 }; 13398 13399 /** 13400 * @private 13401 */ 13402 net.user1.orbiter.UserAccount.prototype.fireSynchronize = function () { 13403 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.SYNCHRONIZE, 13404 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13405 this.dispatchEvent(e); 13406 }; 13407 13408 /** 13409 * @private 13410 */ 13411 net.user1.orbiter.UserAccount.prototype.fireObserve = function () { 13412 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE, 13413 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13414 this.dispatchEvent(e); 13415 }; 13416 13417 /** 13418 * @private 13419 */ 13420 net.user1.orbiter.UserAccount.prototype.fireObserveResult = function (status) { 13421 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE_RESULT, 13422 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13423 this.dispatchEvent(e); 13424 }; 13425 13426 /** 13427 * @private 13428 */ 13429 net.user1.orbiter.UserAccount.prototype.fireStopObserving = function () { 13430 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING, 13431 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13432 this.dispatchEvent(e); 13433 }; 13434 13435 /** 13436 * @private 13437 */ 13438 net.user1.orbiter.UserAccount.prototype.fireStopObservingResult = function (status) { 13439 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT, 13440 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13441 this.dispatchEvent(e); 13442 }; 13443 13444 /** 13445 * @private 13446 */ 13447 net.user1.orbiter.UserAccount.prototype.fireAddRoleResult = function (role, status) { 13448 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT, 13449 status, this.getUserID(), 13450 (this._client == null ? null : this._client.getClientID()), role); 13451 this.dispatchEvent(e); 13452 } 13453 13454 /** 13455 * @private 13456 */ 13457 net.user1.orbiter.UserAccount.prototype.fireRemoveRoleResult = function (role, status) { 13458 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT, 13459 status, this.getUserID(), 13460 (this._client == null ? null : this._client.getClientID()), role); 13461 this.dispatchEvent(e); 13462 } 13463 13464 13465 13466 13467 13468 13469 13470 13471 13472 13473 13474 13475 13476 //============================================================================== 13477 // VALIDATION UTILITIES 13478 //============================================================================== 13479 net.user1.orbiter.Validator = new Object(); 13480 13481 net.user1.orbiter.Validator.isValidRoomID = function (value) { 13482 // Can't be null, nor the empty string 13483 if (value == null || value == "") { 13484 return false; 13485 } 13486 // Can't contain "." 13487 if (value.indexOf(".") != -1) { 13488 return false; 13489 } 13490 // Can't contain RS 13491 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13492 return false; 13493 } 13494 // Can't contain WILDCARD 13495 if (value.indexOf(net.user1.orbiter.Tokens.WILDCARD) != -1) { 13496 return false; 13497 } 13498 13499 return true; 13500 }; 13501 13502 net.user1.orbiter.Validator.isValidRoomQualifier = function (value) { 13503 if (value == null || value == "") { 13504 return false; 13505 } 13506 // "*" is valid (it means the unnamed qualifier) 13507 if (value == "*") { 13508 return true; 13509 } 13510 13511 // Can't contain RS 13512 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13513 return false; 13514 } 13515 // Can't contain WILDCARD 13516 if (value.indexOf(net.user1.orbiter.Tokens.WILDCARD) != -1) { 13517 return false; 13518 } 13519 13520 return true; 13521 }; 13522 13523 net.user1.orbiter.Validator.isValidResolvedRoomID = function (value) { 13524 // Can't be null, nor the empty string 13525 if (value == null || value == "") { 13526 return false; 13527 } 13528 13529 // Can't contain RS 13530 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13531 return false; 13532 } 13533 // Can't contain WILDCARD 13534 if (value.indexOf(net.user1.orbiter.Tokens.WILDCARD) != -1) { 13535 return false; 13536 } 13537 13538 return true; 13539 }; 13540 13541 net.user1.orbiter.Validator.isValidAttributeName = function (value) { 13542 // Can't be empty 13543 if (value == "" || value == null) { 13544 return false; 13545 } 13546 13547 // Can't contain RS 13548 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13549 return false; 13550 } 13551 13552 return true; 13553 }; 13554 13555 net.user1.orbiter.Validator.isValidAttributeValue = function (value) { 13556 // Can't contain RS 13557 if (typeof value != "string") { 13558 // Non-string attribute values are coerced to strings at send time 13559 value = value.toString(); 13560 } 13561 if (value.indexOf(net.user1.orbiter.Tokens.RS) == -1) { 13562 return true; 13563 } else { 13564 return false; 13565 } 13566 }; 13567 13568 net.user1.orbiter.Validator.isValidAttributeScope = function (value) { 13569 // Can't contain RS 13570 if (value != null) { 13571 return this.isValidResolvedRoomID(value); 13572 } else { 13573 return true; 13574 } 13575 }; 13576 13577 net.user1.orbiter.Validator.isValidModuleName = function (value) { 13578 // Can't be empty (can be null) 13579 if (value == "") { 13580 return false; 13581 } 13582 13583 // Can't contain RS 13584 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13585 return false; 13586 } 13587 13588 return true; 13589 }; 13590 13591 net.user1.orbiter.Validator.isValidPassword = function (value) { 13592 // Can't contain RS 13593 if (value != null && value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13594 return false; 13595 } 13596 13597 return true; 13598 }; 13599 //============================================================================== 13600 // CLASS DECLARATION 13601 //============================================================================== 13602 /** @class 13603 * The Orbiter class is the root class of every Orbiter application. 13604 * It provides basic tools for connecting to Union server, and gives 13605 * the application access to the core Orbiter system modules. 13606 * Orbiter dispatches the following events: 13607 13608 <ul class="summary"> 13609 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.READY}</li> 13610 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.CLOSE}</li> 13611 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED}</li> 13612 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE}</li> 13613 </ul> 13614 13615 * To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 13616 * 13617 * @param configURL The URL of a connection-configuration file. When the file 13618 * finishes loading, the Orbiter client automatically attempts to connect to 13619 * Union Server at the specified address(es). Note that the configuration file 13620 * need not be loaded at construction time; it can be loaded later via Orbiter's 13621 * loadConfig() method. For configuration file details, see loadConfig(). 13622 * 13623 * @param traceLogMessages A flag indicating whether to send log messages to the 13624 * JavaScript output console. Applies to environments that support the 13625 * console.log() function only. 13626 * 13627 * @extends net.user1.events.EventDispatcher 13628 */ 13629 net.user1.orbiter.Orbiter = function (configURL, 13630 traceLogMessages) { 13631 // Call superconstructor 13632 net.user1.events.EventDispatcher.call(this); 13633 13634 // Initialization. For non-browser environments, set window to null. 13635 this.window = typeof window == "undefined" ? null : window; 13636 13637 traceLogMessages = traceLogMessages == null ? true : traceLogMessages; 13638 13639 this.useSecureConnect = false; 13640 this.statistics = null; 13641 this.sessionID = null; 13642 13643 // Initialize system versions 13644 this.system = new net.user1.orbiter.System(this.window); 13645 13646 // Set up the this.log. 13647 this.log = new net.user1.logger.Logger(); 13648 13649 // Output host version information. 13650 if (typeof navigator != "undefined") { 13651 this.log.info("User Agent: " + navigator.userAgent + " " + navigator.platform); 13652 } 13653 this.log.info("Union Client Version: " + this.system.getClientType() + " " + this.system.getClientVersion().toStringVerbose()); 13654 this.log.info("Client UPC Protocol Version: " + this.system.getUPCVersion().toString()); 13655 this.consoleLogger = null; 13656 13657 // Set up the connection manager. 13658 this.connectionMan = new net.user1.orbiter.ConnectionManager(this); 13659 13660 // Set up the room manager. 13661 this.roomMan = new net.user1.orbiter.RoomManager(this); 13662 13663 // Set up the message manager. 13664 this.messageMan = new net.user1.orbiter.MessageManager(this.log, this.connectionMan); 13665 13666 // Set up the server 13667 this.server = new net.user1.orbiter.Server(this); 13668 13669 // Make the account manager. 13670 this.accountMan = new net.user1.orbiter.AccountManager(this.log); 13671 13672 // Set up the client manager. 13673 this.clientMan = new net.user1.orbiter.ClientManager(this.roomMan, this.accountMan, this.connectionMan, this.messageMan, this.server, this.log); 13674 13675 // Set up the account manager. 13676 this.accountMan.setClientManager(this.clientMan); 13677 this.accountMan.setMessageManager(this.messageMan); 13678 this.accountMan.setRoomManager(this.roomMan); 13679 13680 // Set up the snapshot manager. 13681 this.snapshotMan = new net.user1.orbiter.SnapshotManager(this.messageMan); 13682 13683 // Set up the core message listener 13684 this.coreMsgListener = new net.user1.orbiter.CoreMessageListener(this); 13685 13686 // Log the core Reactor events 13687 this.coreEventLogger = new net.user1.orbiter.CoreEventLogger(this.log, this.connectionMan, this.roomMan, 13688 this.accountMan, this.server, this.clientMan, 13689 this); 13690 13691 // Register for ConnectionManager events. 13692 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.READY, 13693 this.readyListener, this); 13694 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE, 13695 this.connectFailureListener, this); 13696 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.DISCONNECT, 13697 this.disconnectListener, this); 13698 13699 // Set up the connection monitor 13700 this.connectionMonitor = new net.user1.orbiter.ConnectionMonitor(this); 13701 this.connectionMonitor.restoreDefaults(); 13702 13703 // Register to be notified when a new connection is about to be opened 13704 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 13705 this.selectConnectionListener, this); 13706 13707 // Enable HTTP failover connections 13708 this.httpFailoverEnabled = true; 13709 13710 if (traceLogMessages) { 13711 this.enableConsole(); 13712 } 13713 13714 // If the Reactor wasn't constructed with a config argument... 13715 if (configURL == null || configURL == "") { 13716 this.log.info("[ORBITER] Initialization complete."); 13717 } else { 13718 // ...otherwise, retrieve system settings from specified config file. 13719 this.loadConfig(configURL); 13720 } 13721 }; 13722 13723 //============================================================================== 13724 // INHERITANCE 13725 //============================================================================== 13726 net.user1.utils.extend(net.user1.orbiter.Orbiter, net.user1.events.EventDispatcher); 13727 13728 //============================================================================== 13729 // XML CONFIG METHODS 13730 //============================================================================== 13731 13732 /** 13733 * Loads the client-configuration file. When the file load completes, 13734 * Orbiter automatically attempts to connect to Union Server using 13735 * the settings specified by the configuration file. 13736 * 13737 * The configuration file has the following format: 13738 * 13739 * <pre> 13740 * <?xml version="1.0"?> 13741 * <config> 13742 * <connections> 13743 * <connection host="hostNameOrIP1" port="portNumber1" type="connectionType1" senddelay="milliseconds1" secure="false" /> 13744 * <connection host="hostNameOrIP2" port="portNumber2" type="connectionType2" senddelay="milliseconds2" secure="false" /> 13745 * ... 13746 * <connection host="hostNameOrIPn" port="portNumbern" type="connectionTypen" senddelay="millisecondsn" secure="false" /> 13747 * </connections> 13748 * <autoreconnectfrequency>frequency</autoreconnectfrequency> 13749 * <connectiontimeout>duration</connectiontimeout> 13750 * <heartbeatfrequency>frequency</heartbeatfrequency> 13751 * <readytimeout>timeout</readytimeout> 13752 * <loglevel>level</loglevel> 13753 * </config> 13754 * </pre> 13755 * 13756 * When the <code>secure</code> attribute is true, communication is 13757 * conducted over WSS or HTTPS using the environment's TLS implementation. 13758 */ 13759 net.user1.orbiter.Orbiter.prototype.loadConfig = function (configURL) { 13760 this.log.info("[ORBITER] Loading config from " + configURL +"."); 13761 var request = new XMLHttpRequest(); 13762 var self = this; 13763 13764 request.onerror = function () { 13765 self.configErrorListener(); 13766 }; 13767 13768 request.onreadystatechange = function (state) { 13769 if (request.readyState == 4) { 13770 self.configLoadCompleteListener(request); 13771 } 13772 } 13773 request.open("GET", configURL); 13774 request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); 13775 request.send(null); 13776 }; 13777 13778 /** 13779 * @private 13780 */ 13781 net.user1.orbiter.Orbiter.prototype.getTextForNode = function (tree, tagname) { 13782 var nodes = tree.getElementsByTagName(tagname); 13783 var node; 13784 if (nodes.length > 0) { 13785 node = nodes[0]; 13786 } 13787 13788 if (node != null 13789 && node.firstChild != null 13790 && node.firstChild.nodeType == 3 13791 && node.firstChild.nodeValue.length > 0) { 13792 return node.firstChild.nodeValue; 13793 } else { 13794 return null; 13795 } 13796 }; 13797 13798 13799 /** 13800 * @private 13801 */ 13802 net.user1.orbiter.Orbiter.prototype.configLoadCompleteListener = function (request) { 13803 var config = request.responseXML; 13804 if ((request.status != 200 && request.status != 0) || config == null) { 13805 this.log.error("[ORBITER] Configuration file failed to load."); 13806 return; 13807 } 13808 this.log.error("[ORBITER] Configuration file loaded."); 13809 try { 13810 var loglevel = this.getTextForNode(config, "logLevel"); 13811 if (loglevel != null) { 13812 this.log.setLevel(loglevel); 13813 } 13814 13815 var autoreconnectfrequencyNodes = config.getElementsByTagName("autoreconnectfrequency"); 13816 var autoreconnectfrequencyNode = null; 13817 if (autoreconnectfrequencyNodes.length == 1) { 13818 autoreconnectfrequencyNode = autoreconnectfrequencyNodes[0]; 13819 var nodetext = this.getTextForNode(config, "autoreconnectfrequency"); 13820 if (nodetext != null && !isNaN(parseInt(nodetext))) { 13821 this.connectionMonitor.setAutoReconnectFrequency( 13822 parseInt(nodetext), 13823 parseInt(nodetext), 13824 autoreconnectfrequencyNode.getAttribute("delayfirstattempt") == null ? false : 13825 autoreconnectfrequencyNode.getAttribute("delayfirstattempt").toLowerCase() == "true" 13826 ); 13827 } else { 13828 this.connectionMonitor.setAutoReconnectFrequency( 13829 parseInt(autoreconnectfrequencyNode.getAttribute("minms")), 13830 parseInt(autoreconnectfrequencyNode.getAttribute("maxms")), 13831 autoreconnectfrequencyNode.getAttribute("delayfirstattempt") == null ? false : 13832 autoreconnectfrequencyNode.getAttribute("delayfirstattempt").toLowerCase() == "true" 13833 ); 13834 } 13835 if (autoreconnectfrequencyNode.getAttribute("maxattempts") != null 13836 && autoreconnectfrequencyNode.getAttribute("maxattempts").length > 0) { 13837 this.connectionMonitor.setAutoReconnectAttemptLimit( 13838 parseInt(autoreconnectfrequencyNode.getAttribute("maxattempts")) 13839 ); 13840 } 13841 } 13842 13843 var connectiontimeout = this.getTextForNode(config, "connectionTimeout"); 13844 if (connectiontimeout != null) { 13845 this.connectionMonitor.setConnectionTimeout(parseInt(connectiontimeout)); 13846 } 13847 13848 var heartbeatfrequency = this.getTextForNode(config, "heartbeatFrequency"); 13849 if (heartbeatfrequency != null) { 13850 this.connectionMonitor.setHeartbeatFrequency(parseInt(heartbeatfrequency)); 13851 } 13852 13853 var readytimeout = this.getTextForNode(config, "readyTimeout"); 13854 if (readytimeout != null) { 13855 this.connectionMan.setReadyTimeout(parseInt(readytimeout)); 13856 } 13857 13858 var connections = config.getElementsByTagName("connection"); 13859 if (connections.length == 0) { 13860 this.log.error("[ORBITER] No connections specified in Orbiter configuration file."); 13861 return; 13862 } 13863 13864 // Make connections 13865 var connection; 13866 var host; 13867 var port; 13868 var type; 13869 var secure; 13870 var sendDelay; 13871 13872 for (var i = 0; i < connections.length; i++) { 13873 connection = connections[i]; 13874 host = connection.getAttribute("host"); 13875 port = connection.getAttribute("port"); 13876 type = connection.getAttribute("type"); 13877 if (type != null) { 13878 type = type.toUpperCase(); 13879 } 13880 secure = connection.getAttribute("secure"); 13881 sendDelay = connection.getAttribute("senddelay"); 13882 13883 switch (type) { 13884 // No type means make a socket connection with an http backup 13885 case null: 13886 if (secure === "true") { 13887 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET, -1); 13888 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP, sendDelay); 13889 } else { 13890 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.WEBSOCKET, -1); 13891 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.HTTP, sendDelay); 13892 } 13893 break; 13894 13895 case net.user1.orbiter.ConnectionType.WEBSOCKET: 13896 if (secure === "true") { 13897 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET, -1); 13898 } else { 13899 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.WEBSOCKET, -1); 13900 } 13901 break; 13902 13903 case net.user1.orbiter.ConnectionType.HTTP: 13904 if (secure === "true") { 13905 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP, sendDelay); 13906 } else { 13907 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.HTTP, sendDelay); 13908 } 13909 break; 13910 13911 default: 13912 this.log.error("[ORBITER] Unrecognized connection type in Orbiter configuration file: [" + type + "]. Connection ignored."); 13913 } 13914 } 13915 } catch (error) { 13916 this.log.error("[ORBITER] Error parsing connection in Orbiter configuration file: \n" 13917 + request.responseText + "\n" + error.toString()); 13918 } 13919 13920 this.connect(); 13921 }; 13922 13923 /** @private */ 13924 net.user1.orbiter.Orbiter.prototype.buildConnection = function (host, port, type, sendDelay) { 13925 var connection; 13926 13927 switch (type) { 13928 case net.user1.orbiter.ConnectionType.HTTP: 13929 if (this.system.hasHTTPDirectConnection()) { 13930 connection = new net.user1.orbiter.HTTPDirectConnection(); 13931 } else { 13932 connection = new net.user1.orbiter.HTTPIFrameConnection(); 13933 } 13934 break; 13935 13936 case net.user1.orbiter.ConnectionType.SECURE_HTTP: 13937 if (this.system.hasHTTPDirectConnection()) { 13938 connection = new net.user1.orbiter.SecureHTTPDirectConnection(); 13939 } else { 13940 connection = new net.user1.orbiter.SecureHTTPIFrameConnection(); 13941 } 13942 break; 13943 13944 case net.user1.orbiter.ConnectionType.WEBSOCKET: 13945 connection = new net.user1.orbiter.WebSocketConnection(); 13946 break; 13947 13948 case net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET: 13949 connection = new net.user1.orbiter.SecureWebSocketConnection(); 13950 break; 13951 13952 default: 13953 throw new Error("[ORBITER] Error at buildConnection(). Invalid type specified: [" + type + "]"); 13954 } 13955 13956 try { 13957 connection.setServer(host, port); 13958 } catch (e) { 13959 this.log.error("[CONNECTION] " + connection.toString() + " " + e); 13960 } finally { 13961 this.connectionMan.addConnection(connection); 13962 if (connection instanceof net.user1.orbiter.HTTPConnection) { 13963 // Set delay after adding connection so the connection object has 13964 // access to this Orbiter object 13965 if (sendDelay != null && sendDelay != "") { 13966 connection.setSendDelay(sendDelay); 13967 } 13968 } 13969 } 13970 }; 13971 13972 /** 13973 * @private 13974 */ 13975 net.user1.orbiter.Orbiter.prototype.configErrorListener = function (e) { 13976 this.log.fatal("[ORBITER] Configuration file could not be loaded."); 13977 }; 13978 13979 //============================================================================== 13980 // CONNECTION METHODS 13981 //============================================================================== 13982 13983 /** 13984 * <p> 13985 * The connect() method attempts to connect to Union Server at the specified 13986 * host and ports. If no host and ports are specified, Orbiter attempts to 13987 * connect using the ConnectionManager's current list of hosts and ports. 13988 * </p> 13989 * 13990 * @param host 13991 * @param port1 13992 * @param port2 13993 * @param ... 13994 * @param portn 13995 */ 13996 net.user1.orbiter.Orbiter.prototype.connect = function (host) { 13997 this.useSecureConnect = false; 13998 this.doConnect.apply(this, arguments); 13999 }; 14000 14001 /** 14002 * <p> 14003 * The secureConnect() method is identical to the connect() method, except that 14004 * it uses an encrypted connection (TLS or SSL) rather than an 14005 * unencrypted connection. Before secureConnect() can be used, Union Server 14006 * must be configured to accept client communications over a secure gateway, 14007 * which includes the installation of a server-side security certificate. For 14008 * instructions on configuring Union Server for secure communications, see 14009 * Union Server's documentation at http://unionplatform.com. 14010 * </p> 14011 * 14012 * @see net.user1.orbiter.Orbiter#connect 14013 */ 14014 net.user1.orbiter.Orbiter.prototype.secureConnect = function (host) { 14015 this.useSecureConnect = true; 14016 this.doConnect.apply(this, arguments); 14017 }; 14018 14019 /** 14020 * @private 14021 */ 14022 net.user1.orbiter.Orbiter.prototype.doConnect = function (host) { 14023 var ports = Array.prototype.slice.call(arguments).slice(1); 14024 if (host != null) { 14025 this.setServer.apply(this, [host].concat(ports)); 14026 } 14027 this.log.info("[ORBITER] Connecting to Union..."); 14028 this.connectionMan.connect(); 14029 }; 14030 14031 net.user1.orbiter.Orbiter.prototype.disconnect = function () { 14032 this.connectionMan.disconnect(); 14033 }; 14034 14035 net.user1.orbiter.Orbiter.prototype.setServer = function (host) { 14036 var ports = Array.prototype.slice.call(arguments).slice(1); 14037 if (host != null && ports.length > 0) { 14038 if (this.connectionMan.getConnections().length > 0) { 14039 this.connectionMan.removeAllConnections(); 14040 } 14041 // Where possible, create WebSocket connections for the specified 14042 // host and its ports. 14043 var connectionType; 14044 if (this.system.hasWebSocket()) { 14045 for (var i = 1; i < arguments.length; i++) { 14046 connectionType = this.useSecureConnect 14047 ? net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET 14048 : net.user1.orbiter.ConnectionType.WEBSOCKET; 14049 this.buildConnection(host, arguments[i], connectionType, -1); 14050 } 14051 } else { 14052 this.log.info("[ORBITER] WebSocket not found in host environment. Trying HTTP."); 14053 } 14054 // Next, if failover is enabled or WebSocket is not supported, create HTTPConnections 14055 if (this.isHTTPFailoverEnabled() || !this.system.hasWebSocket()) { 14056 for (i = 1; i < arguments.length; i++) { 14057 connectionType = this.useSecureConnect 14058 ? net.user1.orbiter.ConnectionType.SECURE_HTTP 14059 : net.user1.orbiter.ConnectionType.HTTP; 14060 this.buildConnection(host, 14061 arguments[i], 14062 connectionType, 14063 net.user1.orbiter.HTTPConnection.DEFAULT_SEND_DELAY); 14064 } 14065 } 14066 } else { 14067 this.log.error("[ORBITER] setServer() failed. Invalid host [" + host + "] or port [" + ports.join(",") + "]."); 14068 } 14069 }; 14070 14071 net.user1.orbiter.Orbiter.prototype.isReady = function () { 14072 return this.connectionMan.isReady(); 14073 }; 14074 14075 //============================================================================== 14076 // HTTP FAILOVER CONFIGURATION 14077 //============================================================================== 14078 14079 net.user1.orbiter.Orbiter.prototype.enableHTTPFailover = function () { 14080 this.httpFailoverEnabled = true; 14081 }; 14082 14083 net.user1.orbiter.Orbiter.prototype.disableHTTPFailover = function () { 14084 this.httpFailoverEnabled = false; 14085 }; 14086 14087 net.user1.orbiter.Orbiter.prototype.isHTTPFailoverEnabled = function () { 14088 return this.httpFailoverEnabled; 14089 }; 14090 14091 //============================================================================== 14092 // STATISTICS MANAGEMENT 14093 //============================================================================== 14094 14095 net.user1.orbiter.Orbiter.prototype.enableStatistics = function () { 14096 if (this.statistics == null) { 14097 this.statistics = new net.user1.orbiter.Statistics(this); 14098 } 14099 } 14100 14101 net.user1.orbiter.Orbiter.prototype.disableStatistics = function () { 14102 if (this.statistics != null) { 14103 this.statistics.stop(); 14104 } 14105 } 14106 14107 net.user1.orbiter.Orbiter.prototype.getStatistics = function () { 14108 return this.statistics; 14109 } 14110 14111 //============================================================================== 14112 // MANAGER AND SERVICE RETRIEVAL 14113 //============================================================================== 14114 net.user1.orbiter.Orbiter.prototype.getSystem = function () { 14115 return this.system; 14116 }; 14117 14118 net.user1.orbiter.Orbiter.prototype.getRoomManager = function () { 14119 return this.roomMan; 14120 }; 14121 14122 net.user1.orbiter.Orbiter.prototype.getConnectionManager = function () { 14123 return this.connectionMan; 14124 }; 14125 14126 net.user1.orbiter.Orbiter.prototype.getClientManager = function () { 14127 return this.clientMan; 14128 }; 14129 14130 net.user1.orbiter.Orbiter.prototype.getAccountManager = function () { 14131 return this.accountMan; 14132 }; 14133 14134 net.user1.orbiter.Orbiter.prototype.getMessageManager = function () { 14135 return this.messageMan; 14136 }; 14137 14138 net.user1.orbiter.Orbiter.prototype.getServer = function () { 14139 return this.server; 14140 }; 14141 14142 net.user1.orbiter.Orbiter.prototype.getConnectionMonitor = function () { 14143 return this.connectionMonitor; 14144 }; 14145 14146 /** 14147 * @private 14148 */ 14149 net.user1.orbiter.Orbiter.prototype.getCoreMessageListener = function () { 14150 return this.coreMsgListener; 14151 } 14152 14153 net.user1.orbiter.Orbiter.prototype.getLog = function () { 14154 return this.log; 14155 } 14156 14157 net.user1.orbiter.Orbiter.prototype.self = function () { 14158 var customGlobalClient; 14159 14160 if (this.clientMan == null || !this.isReady()) { 14161 return null; 14162 } else { 14163 customGlobalClient = this.clientMan.self().getCustomClient(null); 14164 if (customGlobalClient != null) { 14165 return customGlobalClient; 14166 } else { 14167 return this.clientMan.self(); 14168 } 14169 } 14170 }; 14171 14172 /** 14173 * @private 14174 */ 14175 net.user1.orbiter.Orbiter.prototype.getSnapshotManager = function () { 14176 return this.snapshotMan; 14177 }; 14178 14179 //============================================================================== 14180 // SNAPSHOT API 14181 //============================================================================== 14182 14183 net.user1.orbiter.Orbiter.prototype.updateSnapshot = function (snapshot) { 14184 this.snapshotMan.updateSnapshot(snapshot); 14185 } 14186 14187 //============================================================================== 14188 // CONNECTION EVENT LISTENERS 14189 //============================================================================== 14190 14191 /** 14192 * @private 14193 * Responds to a connection failure. 14194 */ 14195 net.user1.orbiter.Orbiter.prototype.connectFailureListener = function (e) { 14196 // Tell listeners that the connection is now closed. 14197 this.fireClose(); 14198 }; 14199 14200 /** 14201 * @private 14202 * Triggers a CLOSE event when the connection is lost. 14203 */ 14204 net.user1.orbiter.Orbiter.prototype.disconnectListener = function (e) { 14205 this.accountMan.cleanup(); 14206 this.roomMan.cleanup(); 14207 this.clientMan.cleanup(); 14208 this.server.cleanup(); 14209 this.fireClose(); 14210 }; 14211 14212 /** 14213 * @private 14214 * Triggers a READY event when the connection is ready. 14215 */ 14216 net.user1.orbiter.Orbiter.prototype.readyListener = function (e) { 14217 this.fireReady(); 14218 }; 14219 14220 net.user1.orbiter.Orbiter.prototype.selectConnectionListener = function (e) { 14221 this.messageMan.addMessageListener(net.user1.orbiter.UPC.SERVER_HELLO, this.u66, this); 14222 this.messageMan.addMessageListener(net.user1.orbiter.UPC.CONNECTION_REFUSED, this.u164, this); 14223 } 14224 14225 //============================================================================== 14226 // CLIENT ID 14227 //============================================================================== 14228 net.user1.orbiter.Orbiter.prototype.getClientID = function () { 14229 return this.self() ? this.self().getClientID() : ""; 14230 }; 14231 14232 //============================================================================== 14233 // EVENT DISPATCHING 14234 //============================================================================== 14235 14236 /** 14237 * @private 14238 * Notifies listeners that this Orbiter object's connection to the server 14239 * was lost or could not be established. 14240 */ 14241 net.user1.orbiter.Orbiter.prototype.fireClose = function () { 14242 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.CLOSE)); 14243 }; 14244 14245 /** 14246 * @private 14247 * Notifies listeners that the Orbiter is fully initialized and 14248 * ready to transact with the server. 14249 */ 14250 net.user1.orbiter.Orbiter.prototype.fireReady = function () { 14251 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.READY)); 14252 }; 14253 14254 /** 14255 * @private 14256 * Notifies listeners that the Orbiter is fully initialized and 14257 * ready to transact with the server. 14258 */ 14259 net.user1.orbiter.Orbiter.prototype.fireProtocolIncompatible = function (serverUPCVersion) { 14260 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE, 14261 serverUPCVersion)); 14262 }; 14263 14264 /** 14265 * @private 14266 * Notifies listeners that the server refused the connection. 14267 */ 14268 net.user1.orbiter.Orbiter.prototype.dispatchConnectRefused = function (refusal) { 14269 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED, 14270 null, refusal)); 14271 }; 14272 14273 //============================================================================== 14274 // UPC Listeners 14275 //============================================================================== 14276 14277 /** 14278 * @private 14279 * SERVER_HELLO 14280 */ 14281 net.user1.orbiter.Orbiter.prototype.u66 = function (serverVersion, 14282 sessionID, 14283 serverUPCVersionString, 14284 protocolCompatible, 14285 affinityAddress, 14286 affinityDuration) { 14287 var serverUPCVersion = new net.user1.orbiter.VersionNumber(); 14288 serverUPCVersion.fromVersionString(serverUPCVersionString); 14289 if (protocolCompatible == "false") { 14290 this.fireProtocolIncompatible(serverUPCVersion); 14291 } 14292 }; 14293 14294 /** 14295 * @private 14296 * CONNECTION_REFUSED 14297 */ 14298 net.user1.orbiter.Orbiter.prototype.u164 = function (reason, description) { 14299 this.connectionMonitor.setAutoReconnectFrequency(-1); 14300 this.dispatchConnectRefused(new net.user1.orbiter.ConnectionRefusal(reason, description)); 14301 }; 14302 14303 //============================================================================== 14304 // SESSION ID 14305 //============================================================================== 14306 14307 net.user1.orbiter.Orbiter.prototype.getSessionID = function () { 14308 return this.sessionID == null ? "" : this.sessionID; 14309 }; 14310 14311 /** 14312 * @private 14313 */ 14314 net.user1.orbiter.Orbiter.prototype.setSessionID = function (id) { 14315 this.sessionID = id; 14316 }; 14317 14318 //============================================================================== 14319 // CONSOLE LOGGING 14320 //============================================================================== 14321 net.user1.orbiter.Orbiter.prototype.enableConsole = function () { 14322 if (this.consoleLogger == null) { 14323 this.consoleLogger = new net.user1.logger.ConsoleLogger(this.log); 14324 } 14325 }; 14326 14327 net.user1.orbiter.Orbiter.prototype.disableConsole = function () { 14328 if (this.consoleLogger != null) { 14329 this.consoleLogger.dispose(); 14330 this.consoleLogger = null; 14331 } 14332 }; 14333 14334 //============================================================================== 14335 // CLEANUP 14336 //============================================================================== 14337 14338 /** 14339 * Permanently disables this object and releases all of its 14340 * resources. Once dispose() is called, the object can never 14341 * be used again. Use dispose() only when purging an object 14342 * from memory, as is required when unloading an iframe. 14343 * 14344 * To simply disconnect an Orbiter object, use disconnect(). 14345 */ 14346 net.user1.orbiter.Orbiter.prototype.dispose = function () { 14347 this.log.info("[ORBITER] Beginning disposal of all resources..."); 14348 this.connectionMan.dispose(); 14349 this.roomMan.dispose(); 14350 this.connectionMonitor.dispose(); 14351 this.clientMan.dispose(); 14352 this.messageMan.dispose(); 14353 if (this.statistics != null) { 14354 this.statistics.stop(); 14355 } 14356 this.log.info("[ORBITER] Disposal complete."); 14357 } 14358 //============================================================================== 14359 // CONNECTION STATE CONSTANTS 14360 //============================================================================== 14361 /** @class */ 14362 net.user1.orbiter.ConnectionState = new Object(); 14363 /** @constant */ 14364 net.user1.orbiter.ConnectionState.UNKNOWN = -1; 14365 /** @constant */ 14366 net.user1.orbiter.ConnectionState.NOT_CONNECTED = 0; 14367 /** @constant */ 14368 net.user1.orbiter.ConnectionState.READY = 1; 14369 /** @constant */ 14370 net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS = 2; 14371 /** @constant */ 14372 net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS = 3; 14373 /** @constant */ 14374 net.user1.orbiter.ConnectionState.LOGGED_IN = 4; 14375 //============================================================================== 14376 // CLASS DECLARATION 14377 //============================================================================== 14378 /** @class 14379 @extends net.user1.events.Event 14380 */ 14381 net.user1.orbiter.ConnectionEvent = function (type, upc, data, connection, status) { 14382 net.user1.events.Event.call(this, type); 14383 14384 this.upc = upc; 14385 this.data = data; 14386 this.connection = connection 14387 this.status = status; 14388 }; 14389 14390 //============================================================================== 14391 // INHERITANCE 14392 //============================================================================== 14393 net.user1.utils.extend(net.user1.orbiter.ConnectionEvent, net.user1.events.Event); 14394 14395 //============================================================================== 14396 // STATIC VARIABLES 14397 //============================================================================== 14398 14399 /** @constant */ 14400 net.user1.orbiter.ConnectionEvent.BEGIN_CONNECT = "BEGIN_CONNECT"; 14401 /** @constant */ 14402 net.user1.orbiter.ConnectionEvent.BEGIN_HANDSHAKE = "BEGIN_HANDSHAKE"; 14403 /** @constant */ 14404 net.user1.orbiter.ConnectionEvent.READY = "READY"; 14405 /** @constant */ 14406 net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE = "CONNECT_FAILURE"; 14407 /** @constant */ 14408 net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT = "CLIENT_KILL_CONNECT"; 14409 /** @constant */ 14410 net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT = "SERVER_KILL_CONNECT"; 14411 /** @constant */ 14412 net.user1.orbiter.ConnectionEvent.DISCONNECT = "DISCONNECT"; 14413 /** @constant */ 14414 net.user1.orbiter.ConnectionEvent.RECEIVE_UPC = "RECEIVE_UPC"; 14415 /** @constant */ 14416 net.user1.orbiter.ConnectionEvent.SEND_DATA = "SEND_DATA"; 14417 /** @constant */ 14418 net.user1.orbiter.ConnectionEvent.RECEIVE_DATA = "RECEIVE_DATA"; 14419 /** @constant */ 14420 net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED = "SESSION_TERMINATED"; 14421 /** @constant */ 14422 net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND = "SESSION_NOT_FOUND"; 14423 14424 //============================================================================== 14425 // INSTANCE METHODS 14426 //============================================================================== 14427 14428 net.user1.orbiter.ConnectionEvent.prototype.getUPC = function () { 14429 return this.upc; 14430 } 14431 14432 net.user1.orbiter.ConnectionEvent.prototype.getData = function () { 14433 return this.data; 14434 } 14435 14436 net.user1.orbiter.ConnectionEvent.prototype.getStatus = function () { 14437 return this.status; 14438 } 14439 14440 net.user1.orbiter.ConnectionEvent.prototype.toString = function () { 14441 return "[object ConnectionEvent]"; 14442 } 14443 14444 //============================================================================== 14445 // HTTP REQUEST MODE CONSTANTS 14446 //============================================================================== 14447 /** @class */ 14448 net.user1.orbiter.ConnectionType = new Object(); 14449 /** @constant */ 14450 net.user1.orbiter.ConnectionType.HTTP = "HTTP"; 14451 /** @constant */ 14452 net.user1.orbiter.ConnectionType.SECURE_HTTP = "SECURE_HTTP"; 14453 /** @constant */ 14454 net.user1.orbiter.ConnectionType.WEBSOCKET = "WEBSOCKET"; 14455 /** @constant */ 14456 net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET = "SECURE_WEBSOCKET"; 14457 //============================================================================== 14458 // CLASS DECLARATION 14459 //============================================================================== 14460 /** @class 14461 * Connection is the abstract superclass of HTTPConnection and WebSocketConnection; 14462 * it is used internally by Orbiter, and is not intended for direct use by Orbiter 14463 * developers. For information on communication with Union Server, see 14464 * Orbiter's connect() method, the WebSocketConnection class and the 14465 * HTTPDirectConnection and HTTPIFrameConnection classes. 14466 * 14467 * The Connection class dispatches the following events: 14468 14469 <ul class="summary"> 14470 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.BEGIN_CONNECT}</li> 14471 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.BEGIN_HANDSHAKE}</li> 14472 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.READY}</li> 14473 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE}</li> 14474 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT}</li> 14475 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT}</li> 14476 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.DISCONNECT}</li> 14477 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.RECEIVE_UPC}</li> 14478 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SEND_DATA}</li> 14479 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.RECEIVE_DATA}</li> 14480 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED}</li> 14481 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND}</li> 14482 </ul> 14483 14484 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 14485 14486 @extends net.user1.events.EventDispatcher 14487 14488 * 14489 * @see net.user1.orbiter.Orbiter#connect 14490 * @see net.user1.orbiter.Orbiter#secureConnect 14491 * @see net.user1.orbiter.HTTPDirectConnection 14492 * @see net.user1.orbiter.HTTPIFrameConnection 14493 * @see net.user1.orbiter.WebSocketConnection 14494 * @see net.user1.orbiter.SecureHTTPDirectConnection 14495 * @see net.user1.orbiter.SecureHTTPIFrameConnection 14496 * @see net.user1.orbiter.SecureWebSocketConnection 14497 */ 14498 net.user1.orbiter.Connection = function (host, port, type) { 14499 // Call superconstructor 14500 net.user1.events.EventDispatcher.call(this); 14501 14502 // Variables 14503 this.mostRecentConnectAchievedReady = false; 14504 this.mostRecentConnectTimedOut = false; 14505 this.readyCount = 0; 14506 this.connectAttemptCount = 0; 14507 this.connectAbortCount = 0; 14508 this.readyTimeoutID = 0; 14509 this.readyTimeout = 0; 14510 this.orbiter = null; 14511 this.disposed = false; 14512 this.requestedHost = null; 14513 14514 // Initialization 14515 this.setServer(host, port); 14516 this.connectionType = type; 14517 this.connectionState = net.user1.orbiter.ConnectionState.NOT_CONNECTED; 14518 }; 14519 14520 //============================================================================== 14521 // INHERITANCE 14522 //============================================================================== 14523 net.user1.utils.extend(net.user1.orbiter.Connection, net.user1.events.EventDispatcher); 14524 14525 //============================================================================== 14526 // DEPENDENCIES 14527 //============================================================================== 14528 /** @private */ 14529 net.user1.orbiter.Connection.prototype.setOrbiter = function (orbiter) { 14530 if (this.orbiter != null) { 14531 this.orbiter.getMessageManager().removeMessageListener("u63", this.u63); 14532 this.orbiter.getMessageManager().removeMessageListener("u66", this.u66); 14533 this.orbiter.getMessageManager().removeMessageListener("u84", this.u84); 14534 this.orbiter.getMessageManager().removeMessageListener("u85", this.u85); 14535 } 14536 this.orbiter = orbiter; 14537 } 14538 14539 //============================================================================== 14540 // CONNECT/DISCONNECT 14541 //============================================================================== 14542 net.user1.orbiter.Connection.prototype.connect = function () { 14543 this.disconnect(); 14544 this.applyAffinity(); 14545 this.orbiter.getLog().info(this.toString() + " Attempting connection..."); 14546 this.connectAttemptCount++; 14547 this.mostRecentConnectAchievedReady = false; 14548 this.mostRecentConnectTimedOut = false; 14549 this.connectionState = net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS; 14550 // Start the ready timer. Ready state must be achieved before the timer 14551 // completes or the connection will auto-disconnect. 14552 this.startReadyTimer(); 14553 this.dispatchBeginConnect(); 14554 } 14555 14556 net.user1.orbiter.Connection.prototype.disconnect = function () { 14557 var state = this.connectionState; 14558 14559 if (state != net.user1.orbiter.ConnectionState.NOT_CONNECTED) { 14560 this.deactivateConnection(); 14561 14562 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 14563 this.connectAbortCount++; 14564 this.dispatchConnectFailure("Client closed connection before READY state was achieved."); 14565 } else { 14566 this.dispatchClientKillConnect(); 14567 } 14568 } 14569 } 14570 14571 /** @private */ 14572 net.user1.orbiter.Connection.prototype.deactivateConnection = function () { 14573 this.connectionState = net.user1.orbiter.ConnectionState.NOT_CONNECTED; 14574 this.stopReadyTimer(); 14575 this.orbiter.setSessionID(""); 14576 } 14577 14578 //============================================================================== 14579 // CONNECTION CONFIGURATION 14580 //============================================================================== 14581 net.user1.orbiter.Connection.prototype.setServer = function (host, 14582 port) { 14583 this.requestedHost = host; 14584 14585 // Check for valid ports 14586 if (port < 1 || port > 65536) { 14587 throw new Error("Illegal port specified [" + port + "]. Must be greater than 0 and less than 65537."); 14588 } 14589 this.port = port; 14590 } 14591 14592 net.user1.orbiter.Connection.prototype.getRequestedHost = function () { 14593 return this.requestedHost; 14594 }; 14595 14596 net.user1.orbiter.Connection.prototype.getHost = function () { 14597 if (this.host == null) { 14598 return this.getRequestedHost(); 14599 } else { 14600 return this.host; 14601 } 14602 }; 14603 14604 net.user1.orbiter.Connection.prototype.getPort = function () { 14605 return this.port; 14606 }; 14607 14608 net.user1.orbiter.Connection.prototype.getType = function () { 14609 return this.connectionType; 14610 }; 14611 14612 //============================================================================== 14613 // READY HANDSHAKE 14614 //============================================================================== 14615 /** @private */ 14616 net.user1.orbiter.Connection.prototype.beginReadyHandshake = function () { 14617 this.dispatchBeginHandshake(); 14618 14619 if (!this.orbiter.getMessageManager().hasMessageListener("u63", this.u63)) { 14620 this.orbiter.getMessageManager().addMessageListener("u63", this.u63, this); 14621 this.orbiter.getMessageManager().addMessageListener("u66", this.u66, this); 14622 this.orbiter.getMessageManager().addMessageListener("u84", this.u84, this); 14623 this.orbiter.getMessageManager().addMessageListener("u85", this.u85, this); 14624 } 14625 14626 this.sendHello(); 14627 } 14628 14629 /** @private */ 14630 net.user1.orbiter.Connection.prototype.sendHello = function() { 14631 var helloString = this.buildHelloMessage(); 14632 this.orbiter.getLog().debug(this.toString() + " Sending CLIENT_HELLO: " + helloString); 14633 this.transmitHelloMessage(helloString); 14634 } 14635 14636 /** @private */ 14637 net.user1.orbiter.Connection.prototype.buildHelloMessage = function () { 14638 var helloString = "<U><M>u65</M>" 14639 + "<L>" 14640 + "<A>" + this.orbiter.getSystem().getClientType() + "</A>" 14641 + "<A>" + (typeof navigator != "undefined" ? navigator.userAgent + ";" : "") 14642 + this.orbiter.getSystem().getClientVersion().toStringVerbose() + "</A>" 14643 + "<A>" + this.orbiter.getSystem().getUPCVersion().toString() + "</A></L></U>"; 14644 return helloString; 14645 } 14646 14647 /** @private */ 14648 net.user1.orbiter.Connection.prototype.transmitHelloMessage = function (helloString) { 14649 this.send(helloString); 14650 } 14651 14652 //============================================================================== 14653 // READY TIMER 14654 //============================================================================== 14655 /** @private */ 14656 net.user1.orbiter.Connection.prototype.readyTimerListener = function () { 14657 this.stopReadyTimer(); 14658 if (this.connectionState == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 14659 this.orbiter.getLog().warn("[CONNECTION] " + this.toString() + " Failed to achieve" + 14660 " ready state after " + this.readyTimeout + "ms. Aborting connection..."); 14661 this.mostRecentConnectTimedOut = true; 14662 this.disconnect(); 14663 } 14664 } 14665 14666 /** @private */ 14667 net.user1.orbiter.Connection.prototype.stopReadyTimer = function () { 14668 if (this.readyTimeoutID != -1) { 14669 clearTimeout(this.readyTimeoutID); 14670 } 14671 } 14672 14673 /** @private */ 14674 net.user1.orbiter.Connection.prototype.startReadyTimer = function () { 14675 var currentObj = this; 14676 var callback = this.readyTimerListener; 14677 this.stopReadyTimer(); 14678 this.readyTimeout = this.orbiter.getConnectionManager().getReadyTimeout(); 14679 var self = this; 14680 this.readyTimeoutID = setTimeout (function () { 14681 callback.call(currentObj); 14682 }, self.readyTimeout); 14683 } 14684 14685 //============================================================================== 14686 // READY STATE ACCESS 14687 //============================================================================== 14688 /** @private */ 14689 net.user1.orbiter.Connection.prototype.getReadyCount = function () { 14690 return this.readyCount; 14691 } 14692 14693 net.user1.orbiter.Connection.prototype.isReady = function () { 14694 return this.connectionState == net.user1.orbiter.ConnectionState.READY; 14695 } 14696 14697 /** @private */ 14698 net.user1.orbiter.Connection.prototype.isValid = function () { 14699 if (this.mostRecentConnectAchievedReady) { 14700 this.orbiter.getLog().debug(this.toString() + " Connection is" 14701 + " valid because its last connection attempt succeeded."); 14702 return true; 14703 } 14704 14705 if (this.connectAttemptCount == 0) { 14706 this.orbiter.getLog().debug(this.toString() + " Connection is" 14707 + " valid because it has either never attempted to connect, or has not" 14708 + " attempted to connect since its last successful connection."); 14709 return true; 14710 } 14711 14712 if ((this.connectAttemptCount > 0) && 14713 (this.connectAttemptCount == this.connectAbortCount) 14714 && !this.mostRecentConnectTimedOut) { 14715 this.orbiter.getLog().debug(this.toString() + " Connection is" 14716 + " valid because either all connection attempts ever or all" 14717 + " connection attempts since its last successful connection were" 14718 + " aborted before the ready timeout was reached."); 14719 return true; 14720 } 14721 14722 this.orbiter.getLog().debug(this.toString() + " Connection is not" 14723 + " valid; its most recent connection failed to achieve a ready state."); 14724 return false; 14725 } 14726 14727 14728 //============================================================================== 14729 // UPC LISTENERS 14730 //============================================================================== 14731 /** @private */ 14732 net.user1.orbiter.Connection.prototype.u63 = function () { 14733 this.stopReadyTimer(); 14734 this.connectionState = net.user1.orbiter.ConnectionState.READY; 14735 this.mostRecentConnectAchievedReady = true; 14736 this.readyCount++; 14737 this.connectAttemptCount = 0; 14738 this.connectAbortCount = 0; 14739 this.dispatchReady(); 14740 } 14741 14742 /** @private */ 14743 net.user1.orbiter.Connection.prototype.u66 = function (serverVersion, 14744 sessionID, 14745 upcVersion, 14746 protocolCompatible, 14747 affinityAddress, 14748 affinityDuration) { 14749 this.orbiter.setSessionID(sessionID); 14750 }; 14751 14752 /** @private */ 14753 net.user1.orbiter.Connection.prototype.u84 = function () { 14754 this.dispatchSessionTerminated(); 14755 } 14756 14757 /** @private */ 14758 net.user1.orbiter.Connection.prototype.u85 = function () { 14759 this.dispatchSessionNotFound(); 14760 } 14761 14762 //============================================================================== 14763 // SERVER AFFINITY 14764 //============================================================================== 14765 /** @private */ 14766 net.user1.orbiter.Connection.prototype.applyAffinity = function () { 14767 var affinityAddress = this.orbiter.getConnectionManager().getAffinity(this.requestedHost); 14768 if (affinityAddress == this.requestedHost) { 14769 this.orbiter.getLog().info(this.toString() + " No affinity address found for requested host [" 14770 + this.requestedHost + "]. Using requested host for next connection attempt."); 14771 } else { 14772 this.orbiter.getLog().info(this.toString() + " Applying affinity address [" + affinityAddress + "] for supplied host [" + this.requestedHost + "]."); 14773 } 14774 this.host = affinityAddress; 14775 } 14776 14777 //============================================================================== 14778 // TOSTRING 14779 //============================================================================== 14780 net.user1.orbiter.Connection.prototype.toString = function () { 14781 var s = "[" + this.connectionType + ", requested host: " + this.requestedHost 14782 + ", host: " + (this.host == null ? "" : this.host) 14783 + ", port: " + this.port + "]"; 14784 return s; 14785 } 14786 14787 //============================================================================== 14788 // EVENT DISPATCHING 14789 //============================================================================== 14790 /** @private */ 14791 net.user1.orbiter.Connection.prototype.dispatchSendData = function (data) { 14792 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SEND_DATA, 14793 null, data, this)); 14794 } 14795 14796 /** @private */ 14797 net.user1.orbiter.Connection.prototype.dispatchReceiveData = function (data) { 14798 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.RECEIVE_DATA, 14799 null, data, this)); 14800 } 14801 14802 /** @private */ 14803 net.user1.orbiter.Connection.prototype.dispatchConnectFailure = function (status) { 14804 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, 14805 null, null, this, status)); 14806 } 14807 14808 /** @private */ 14809 net.user1.orbiter.Connection.prototype.dispatchBeginConnect = function () { 14810 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.BEGIN_CONNECT, 14811 null, null, this)); 14812 } 14813 14814 /** @private */ 14815 net.user1.orbiter.Connection.prototype.dispatchBeginHandshake = function () { 14816 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.BEGIN_HANDSHAKE, 14817 null, null, this)); 14818 } 14819 14820 /** @private */ 14821 net.user1.orbiter.Connection.prototype.dispatchReady = function () { 14822 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.READY, 14823 null, null, this)); 14824 } 14825 14826 /** @private */ 14827 net.user1.orbiter.Connection.prototype.dispatchServerKillConnect = function () { 14828 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT, 14829 null, null, this)); 14830 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.DISCONNECT, 14831 null, null, this)); 14832 } 14833 14834 /** @private */ 14835 net.user1.orbiter.Connection.prototype.dispatchClientKillConnect = function () { 14836 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT, 14837 null, null, this)); 14838 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.DISCONNECT, 14839 null, null, this)); 14840 } 14841 14842 /** @private */ 14843 net.user1.orbiter.Connection.prototype.dispatchSessionTerminated = function () { 14844 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED, 14845 null, null, this)); 14846 } 14847 14848 /** @private */ 14849 net.user1.orbiter.Connection.prototype.dispatchSessionNotFound = function () { 14850 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND, 14851 null, null, this)); 14852 } 14853 14854 //============================================================================== 14855 // DISPOSAL 14856 //============================================================================== 14857 /** @private */ 14858 net.user1.orbiter.Connection.prototype.dispose = function () { 14859 this.disposed = true; 14860 this.messageManager.removeMessageListener("u63", this.u63); 14861 this.messageManager.removeMessageListener("u66", this.u66); 14862 this.messageManager.removeMessageListener("u84", this.u84); 14863 this.messageManager.removeMessageListener("u85", this.u85); 14864 this.stopReadyTimer(); 14865 this.readyTimer = null; 14866 this.orbiter = null; 14867 } 14868 //============================================================================== 14869 // CLASS DECLARATION 14870 //============================================================================== 14871 /** 14872 * @class 14873 * 14874 * <p> 14875 * The WebSocketConnection class is used by Orbiter to communicate with 14876 * Union Server over a persistent TCP/IP socket. Normally, developers need not 14877 * use the WebSocketConnection class directly, and should instead make connections 14878 * via the Orbiter class's connect() method. However, the 14879 * WebSocketConnection class is required for fine-grained connection configuration, 14880 * such as defining failover socket connections for multiple Union Servers 14881 * running at different host addresses. 14882 * </p> 14883 * 14884 * <p> 14885 * By default, Orbiter uses WebSocketConnection connections to communicate 14886 * with Union Server. WebSocketConnection connections offer faster response times than 14887 * HTTP connections, but occupy an operating-system-level socket continuously 14888 * for the duration of the connection. If a WebSocketConnection connection 14889 * cannot be established (due to, say, a restrictive firewall), Orbiter 14890 * automatically attempts to communicate using HTTP requests sent via an 14891 * HTTPDirectConnection or HTTPIFrameConnection. Developers can override 14892 * Orbiter's default connection failover system by manually configuring 14893 * connections using the ConnectionManager class and Orbiter's 14894 * disableHTTPFailover() method.</p> 14895 * 14896 * <p> 14897 * For secure WebSocket and HTTP communications, see SecureWebSocketConnection, 14898 * SecureHTTPDirectConnection, and SecureHTTPIFrameConnection. 14899 * </p> 14900 * 14901 * For a list of events dispatched by WebSocketConnection, see 14902 * WebSocketConnection's superclass, {@link net.user1.orbiter.Connection}. 14903 * 14904 * @extends net.user1.orbiter.Connection 14905 * 14906 * @see net.user1.orbiter.Orbiter#connect 14907 * @see net.user1.orbiter.Orbiter#secureConnect 14908 * @see net.user1.orbiter.SecureWebSocketConnection 14909 * @see net.user1.orbiter.SecureHTTPDirectConnection 14910 * @see net.user1.orbiter.SecureHTTPIFrameConnection 14911 */ 14912 net.user1.orbiter.WebSocketConnection = function (host, port, type) { 14913 // Invoke superclass constructor 14914 net.user1.orbiter.Connection.call(this, host, port, type || net.user1.orbiter.ConnectionType.WEBSOCKET); 14915 14916 this.socket = null; 14917 }; 14918 14919 //============================================================================== 14920 // INHERITANCE 14921 //============================================================================== 14922 net.user1.utils.extend(net.user1.orbiter.WebSocketConnection, net.user1.orbiter.Connection); 14923 14924 //============================================================================== 14925 // SOCKET OBJECT MANAGEMENT 14926 //============================================================================== 14927 /** @private */ 14928 net.user1.orbiter.WebSocketConnection.prototype.getNewSocket = function () { 14929 // Deactivate the old socket 14930 this.deactivateSocket(this.socket); 14931 14932 // Create the new socket 14933 if (typeof MozWebSocket != "undefined") { 14934 // Firefox 6 14935 this.socket = new MozWebSocket(this.buildURL()); 14936 } else { 14937 // Other browsers 14938 this.socket = new WebSocket(this.buildURL()); 14939 } 14940 14941 // Register for socket events 14942 var self = this; 14943 this.socket.onopen = function (e) {self.connectListener(e)}; 14944 this.socket.onmessage = function (e) {self.dataListener(e)}; 14945 this.socket.onclose = function (e) {self.closeListener(e)}; 14946 this.socket.onerror = function (e) {self.ioErrorListener(e)}; 14947 }; 14948 14949 /** @private */ 14950 net.user1.orbiter.WebSocketConnection.prototype.buildURL = function () { 14951 return "ws://" + this.host + ":" + this.port; 14952 }; 14953 14954 /** @private */ 14955 net.user1.orbiter.WebSocketConnection.prototype.deactivateSocket = function (oldSocket) { 14956 if (oldSocket == null) { 14957 return; 14958 } 14959 14960 this.socket.onopen = null; 14961 this.socket.onmessage = null; 14962 this.socket.onclose = null; 14963 this.socket.onerror = null; 14964 14965 try { 14966 oldSocket.close() 14967 } catch (e) { 14968 // Do nothing 14969 } 14970 14971 this.socket = null; 14972 }; 14973 14974 //============================================================================== 14975 // CONNECTION AND DISCONNECTION 14976 //============================================================================== 14977 14978 net.user1.orbiter.WebSocketConnection.prototype.connect = function () { 14979 net.user1.orbiter.Connection.prototype.connect.call(this); 14980 14981 // Attempt to connect 14982 try { 14983 this.getNewSocket(); 14984 } catch (e) { 14985 // Socket could not be opened 14986 this.deactivateConnection(); 14987 this.dispatchConnectFailure(e.toString()); 14988 } 14989 }; 14990 14991 /** @private */ 14992 net.user1.orbiter.WebSocketConnection.prototype.deactivateConnection = function () { 14993 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Deactivating..."); 14994 this.connectionState = net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS; 14995 this.deactivateSocket(this.socket); 14996 net.user1.orbiter.Connection.prototype.deactivateConnection.call(this); 14997 }; 14998 14999 //============================================================================== 15000 // SOCKET CONNECTION LISTENERS 15001 //============================================================================== 15002 /** @private */ 15003 net.user1.orbiter.WebSocketConnection.prototype.connectListener = function (e) { 15004 if (this.disposed) return; 15005 15006 this.orbiter.getLog().debug(this.toString() + " Socket connected."); 15007 this.beginReadyHandshake(); 15008 } 15009 15010 /** @private */ 15011 net.user1.orbiter.WebSocketConnection.prototype.closeListener = function (e) { 15012 if (this.disposed) return; 15013 15014 var state = this.connectionState; 15015 this.deactivateConnection(); 15016 15017 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15018 this.dispatchConnectFailure("WebSocket onclose: Server closed connection before READY state was achieved."); 15019 } else { 15020 this.dispatchServerKillConnect(); 15021 } 15022 }; 15023 15024 /** @private */ 15025 net.user1.orbiter.WebSocketConnection.prototype.ioErrorListener = function (e) { 15026 if (this.disposed) return; 15027 15028 var state = this.connectionState; 15029 this.deactivateConnection(); 15030 15031 // Note: when Union closes the connection, Firefox 7 dispatches onerror, not 15032 // onclose, so treat onerror like an onclose event 15033 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15034 this.dispatchConnectFailure("WebSocket onerror: Server closed connection before READY state was achieved."); 15035 } else { 15036 this.dispatchServerKillConnect(); 15037 } 15038 }; 15039 15040 //============================================================================== 15041 // DATA RECEIVING AND SENDING 15042 //============================================================================== 15043 /** @private */ 15044 net.user1.orbiter.WebSocketConnection.prototype.dataListener = function (dataEvent) { 15045 if (this.disposed) return; 15046 15047 var data = dataEvent.data; 15048 this.dispatchReceiveData(data); 15049 15050 if (data.indexOf("<U>") == 0) { 15051 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent( 15052 net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, 15053 data)); 15054 } else { 15055 // The message isn't UPC. Must be an error... 15056 this.orbiter.getLog().error(this.toString() + " Received invalid message" 15057 + " (not UPC or malformed UPC): " + data); 15058 } 15059 }; 15060 15061 /** @private */ 15062 net.user1.orbiter.WebSocketConnection.prototype.send = function (data) { 15063 this.dispatchSendData(data); 15064 this.socket.send(data); 15065 }; 15066 15067 // ============================================================================= 15068 // DISPOSAL 15069 // ============================================================================= 15070 /** @private */ 15071 net.user1.orbiter.WebSocketConnection.prototype.dispose = function () { 15072 net.user1.orbiter.Connection.prototype.dispose.call(this); 15073 this.deactivateSocket(this.socket); 15074 }; 15075 //============================================================================== 15076 // CLASS DECLARATION 15077 //============================================================================== 15078 /** @class 15079 * 15080 * <p> 15081 * The SecureWebSocketConnection class is identical to WebSocketConnection 15082 * except that it performs communications over WSS (i.e., an encrypted TLS or 15083 * SSL socket connection) rather than plain WebSocket.</p> 15084 * 15085 * For a list of events dispatched by SecureWebSocketConnection, see 15086 * {@link net.user1.orbiter.Connection}. 15087 * 15088 * @extends net.user1.orbiter.WebSocketConnection 15089 * 15090 * @see net.user1.orbiter.WebSocketConnection 15091 */ 15092 net.user1.orbiter.SecureWebSocketConnection = function (host, port) { 15093 // Invoke superclass constructor 15094 net.user1.orbiter.WebSocketConnection.call(this, host, port, net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET); 15095 }; 15096 15097 //============================================================================== 15098 // INHERITANCE 15099 //============================================================================== 15100 net.user1.utils.extend(net.user1.orbiter.SecureWebSocketConnection, net.user1.orbiter.WebSocketConnection); 15101 15102 /** @private */ 15103 net.user1.orbiter.SecureWebSocketConnection.prototype.buildURL = function () { 15104 return "wss://" + this.host + ":" + this.port; 15105 }; 15106 //============================================================================== 15107 // CLASS DECLARATION 15108 //============================================================================== 15109 /** 15110 * @class 15111 * 15112 * HTTPConnection is the abstract superclass of HTTPDirectConnection and 15113 * HTTPIFrameConnection; it is used internally by Orbiter, and is not intended 15114 * for direct use by Orbiter developers. For information on HTTP communication 15115 * with Union Server, see the HTTPDirectConnection and HTTPIFrameConnection classes. 15116 * 15117 * For a list of events dispatched by HTTPConnection, see HTTPConnection's 15118 * superclass, {@link net.user1.orbiter.Connection}. 15119 * 15120 * @extends net.user1.orbiter.Connection 15121 * 15122 * 15123 * @see net.user1.orbiter.HTTPDirectConnection 15124 * @see net.user1.orbiter.HTTPIFrameConnection 15125 */ 15126 net.user1.orbiter.HTTPConnection = function (host, port, type) { 15127 // Invoke superclass constructor 15128 net.user1.orbiter.Connection.call(this, host, port, type || net.user1.orbiter.ConnectionType.HTTP); 15129 15130 // Instance variables 15131 this.url = ""; 15132 this.sendDelayTimerEnabled = true; 15133 this.sendDelayTimeoutID = -1; 15134 this.sendDelayTimerRunning = false; 15135 this.sendDelay = net.user1.orbiter.HTTPConnection.DEFAULT_SEND_DELAY; 15136 15137 this.messageQueue = new Array(); 15138 15139 this.retryDelay = 500; 15140 this.retryHelloTimeoutID = -1; 15141 this.retryIncomingTimeoutID = -1; 15142 this.retryOutgoingTimeoutID = -1; 15143 15144 this.helloResponsePending = false; 15145 this.outgoingResponsePending = false; 15146 15147 // Initialization 15148 this.addEventListener(net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED, this.sessionTerminatedListener, this); 15149 this.addEventListener(net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND, this.sessionNotFoundListener, this); 15150 }; 15151 15152 //============================================================================== 15153 // INHERITANCE 15154 //============================================================================== 15155 net.user1.utils.extend(net.user1.orbiter.HTTPConnection, net.user1.orbiter.Connection); 15156 15157 //============================================================================== 15158 // STATIC VARIABLES 15159 //============================================================================== 15160 /** @constant */ 15161 net.user1.orbiter.HTTPConnection.DEFAULT_SEND_DELAY = 300; 15162 15163 //============================================================================== 15164 // ABSTRACT METHODS (MUST BE IMPLEMENTED BY SUBCLASSES) 15165 //============================================================================== 15166 15167 net.user1.orbiter.HTTPConnection.prototype.doRequestDeactivation = net.user1.utils.abstractError; 15168 net.user1.orbiter.HTTPConnection.prototype.doSendHello = net.user1.utils.abstractError; 15169 net.user1.orbiter.HTTPConnection.prototype.doRetryHello = net.user1.utils.abstractError; 15170 net.user1.orbiter.HTTPConnection.prototype.doSendOutgoing = net.user1.utils.abstractError; 15171 net.user1.orbiter.HTTPConnection.prototype.doRetryOutgoing = net.user1.utils.abstractError; 15172 net.user1.orbiter.HTTPConnection.prototype.doSendIncoming = net.user1.utils.abstractError; 15173 net.user1.orbiter.HTTPConnection.prototype.doRetryIncoming = net.user1.utils.abstractError; 15174 net.user1.orbiter.HTTPConnection.prototype.doDispose = net.user1.utils.abstractError; 15175 15176 //============================================================================== 15177 // CONNECTION AND DISCONNECTION 15178 //============================================================================== 15179 net.user1.orbiter.HTTPConnection.prototype.connect = function () { 15180 net.user1.orbiter.Connection.prototype.connect.call(this); 15181 }; 15182 15183 /** @private */ 15184 net.user1.orbiter.HTTPConnection.prototype.deactivateConnection = function () { 15185 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Deactivating..."); 15186 this.connectionState = net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS; 15187 this.stopSendDelayTimer(); 15188 if (this.retryHelloTimeoutID != -1) { 15189 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Cancelling scheduled hello-request retry."); 15190 clearTimeout(this.retryHelloTimeoutID); 15191 this.retryHelloTimeoutID = -1 15192 } 15193 if (this.retryIncomingTimeoutID != -1) { 15194 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Cancelling scheduled incoming-request retry."); 15195 clearTimeout(this.retryIncomingTimeoutID); 15196 this.retryIncomingTimeoutID = -1 15197 } 15198 if (this.retryOutgoingTimeoutID != -1) { 15199 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Cancelling scheduled outgoing-request retry."); 15200 clearTimeout(this.retryOutgoingTimeoutID); 15201 this.retryOutgoingTimeoutID = -1 15202 } 15203 this.deactivateHTTPRequests(); 15204 net.user1.orbiter.Connection.prototype.deactivateConnection.call(this); 15205 }; 15206 15207 /** @private */ 15208 net.user1.orbiter.HTTPConnection.prototype.deactivateHTTPRequests = function () { 15209 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Closing all pending HTTP requests."); 15210 this.doRequestDeactivation(); 15211 this.helloResponsePending = false; 15212 this.outgoingResponsePending = false; 15213 }; 15214 15215 //============================================================================== 15216 // SESSION MANAGEMENT 15217 //============================================================================== 15218 15219 /** @private */ 15220 net.user1.orbiter.HTTPConnection.prototype.sessionTerminatedListener = function (e) { 15221 var state = this.connectionState; 15222 this.deactivateConnection(); 15223 15224 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15225 this.dispatchConnectFailure("Server terminated session before READY state was achieved."); 15226 } else { 15227 this.dispatchServerKillConnect(); 15228 } 15229 }; 15230 15231 /** @private */ 15232 net.user1.orbiter.HTTPConnection.prototype.sessionNotFoundListener = function (e) { 15233 var state = this.connectionState; 15234 15235 this.deactivateConnection(); 15236 15237 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15238 this.dispatchConnectFailure("Client attempted to reestablish an expired session" 15239 + " or establish an unknown session."); 15240 } else { 15241 this.dispatchServerKillConnect(); 15242 } 15243 } 15244 15245 15246 //============================================================================== 15247 // SERVER ASSIGNMENT 15248 //============================================================================== 15249 /** @private */ 15250 net.user1.orbiter.HTTPConnection.prototype.setServer = function (host, port) { 15251 try { 15252 net.user1.orbiter.Connection.prototype.setServer.call(this, host, port); 15253 } finally { 15254 this.buildURL(); 15255 } 15256 } 15257 15258 /** @private */ 15259 net.user1.orbiter.HTTPConnection.prototype.buildURL = function () { 15260 this.url = "http://" + this.host + ":" + this.port; 15261 } 15262 15263 //============================================================================== 15264 // OUTGOING DELAY TIMER 15265 //============================================================================== 15266 /** @private */ 15267 net.user1.orbiter.HTTPConnection.prototype.sendDelayTimerListener = function () { 15268 this.sendDelayTimerRunning = false; 15269 if (this.messageQueue.length > 0) { 15270 this.flushMessageQueue(); 15271 } else { 15272 // No messages in queue, so take no action. 15273 } 15274 } 15275 15276 /** @private */ 15277 net.user1.orbiter.HTTPConnection.prototype.stopSendDelayTimer = function () { 15278 this.sendDelayTimerRunning = false; 15279 if (this.sendDelayTimeoutID != -1) { 15280 clearTimeout(this.sendDelayTimeoutID); 15281 } 15282 this.sendDelayTimeoutID = -1; 15283 } 15284 15285 /** @private */ 15286 net.user1.orbiter.HTTPConnection.prototype.startSendDelayTimer = function () { 15287 this.stopSendDelayTimer(); 15288 var currentObj = this; 15289 var callback = this.sendDelayTimerListener; 15290 this.sendDelayTimerRunning = true; 15291 this.sendDelayTimeoutID = setTimeout(function () { 15292 callback.call(currentObj); 15293 }, this.sendDelay); 15294 } 15295 15296 net.user1.orbiter.HTTPConnection.prototype.setSendDelay = function (milliseconds) { 15297 if (milliseconds > 0) { 15298 if ((milliseconds != this.sendDelay)) { 15299 this.sendDelay = milliseconds; 15300 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Send delay set to: [" 15301 + milliseconds + "]."); 15302 } 15303 this.sendDelayTimerEnabled = true; 15304 } else if (milliseconds == -1) { 15305 this.orbiter.getLog().debug("[CONNECTION] " + toString() + " Send delay disabled."); 15306 this.sendDelayTimerEnabled = false; 15307 this.stopSendDelayTimer(); 15308 } else { 15309 throw new Error("[CONNECTION]" + this.toString() + " Invalid send-delay specified: [" 15310 + milliseconds + "]."); 15311 } 15312 } 15313 15314 net.user1.orbiter.HTTPConnection.prototype.getSendDelay = function () { 15315 return this.sendDelay; 15316 } 15317 15318 //============================================================================== 15319 // RETRY DELAY 15320 //============================================================================== 15321 net.user1.orbiter.HTTPConnection.prototype.setRetryDelay = function (milliseconds) { 15322 if (milliseconds > -1) { 15323 if (milliseconds != this.retryDelay) { 15324 this.retryDelay = milliseconds; 15325 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Retry delay set to: [" 15326 + milliseconds + "]."); 15327 } 15328 } else { 15329 throw new Error("[CONNECTION]" + this.toString() + " Invalid retry delay specified: [" 15330 + milliseconds + "]."); 15331 } 15332 } 15333 15334 //============================================================================== 15335 // DATA SENDING AND QUEUING 15336 //============================================================================== 15337 15338 net.user1.orbiter.HTTPConnection.prototype.send = function (data) { 15339 // If the timer isn't running... 15340 if (!this.sendDelayTimerRunning) { 15341 // ...it is either disabled or expired. Either way, it's time to 15342 // attempt to flush the queue. 15343 this.messageQueue.push(data); 15344 this.flushMessageQueue(); 15345 } else { 15346 // The send-delay timer is running, so we can't send yet. Just queue the message. 15347 this.messageQueue.push(data); 15348 } 15349 } 15350 15351 /** @private */ 15352 net.user1.orbiter.HTTPConnection.prototype.flushMessageQueue = function () { 15353 if (!this.outgoingResponsePending) { 15354 this.openNewOutgoingRequest(this.messageQueue.join("")); 15355 this.messageQueue = new Array(); 15356 } else { 15357 // AN OUTGOING RESPONSE IS STILL PENDING, SO DON'T SEND A NEW ONE 15358 } 15359 } 15360 15361 //============================================================================== 15362 // HELLO REQUEST MANAGEMENT 15363 //============================================================================== 15364 15365 /** @private */ 15366 net.user1.orbiter.HTTPConnection.prototype.transmitHelloMessage = function (helloString) { 15367 this.dispatchSendData(helloString); 15368 this.helloResponsePending = true; 15369 this.doSendHello(helloString); 15370 } 15371 15372 /** @private */ 15373 net.user1.orbiter.HTTPConnection.prototype.helloCompleteListener = function (data) { 15374 if (this.disposed) return; 15375 15376 if (this.helloResponsePending) { 15377 this.helloResponsePending = false; 15378 this.processIncomingData(data); 15379 15380 // Don't immediately open a request in the complete handler due to Win IE bug 15381 var self = this; 15382 setTimeout(function () { 15383 self.openNewIncomingRequest(); 15384 }, 0); 15385 } else { 15386 if (this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED) { 15387 this.orbiter.getLog().error("[CONNECTION]" + toString() + " u66 (SERVER_HELLO) received, but client is not connected. Ignoring."); 15388 } else { 15389 this.orbiter.getLog().error("[CONNECTION]" + toString() + " Redundant u66 (SERVER_HELLO) received. Ignoring."); 15390 } 15391 } 15392 } 15393 15394 /** @private */ 15395 net.user1.orbiter.HTTPConnection.prototype.helloErrorListener = function () { 15396 if (this.disposed) return; 15397 // There's already a retry scheduled 15398 if (this.retryHelloTimeoutID != -1) return; 15399 // The connection attempt has been aborted 15400 if (this.connectionState != net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15401 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " u65 (CLIENT_HELLO) request failed." 15402 + " Connection is no longer in progress, so no retry scheduled."); 15403 return; 15404 } 15405 15406 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " u65 (CLIENT_HELLO) request failed." 15407 + " Retrying in " + this.retryDelay + "ms."); 15408 15409 // Retry 15410 var self = this; 15411 this.retryHelloTimeoutID = setTimeout(function () { 15412 self.retryHelloTimeoutID = -1; 15413 self.doRetryHello(); 15414 }, this.retryDelay); 15415 } 15416 15417 //============================================================================== 15418 // OUTGOING REQUEST MANAGEMENT 15419 //============================================================================== 15420 15421 /** @private */ 15422 net.user1.orbiter.HTTPConnection.prototype.openNewOutgoingRequest = function (data) { 15423 this.dispatchSendData(data); 15424 this.outgoingResponsePending = true; 15425 this.doSendOutgoing(data); 15426 if (this.sendDelayTimerEnabled == true) { 15427 this.startSendDelayTimer(); 15428 } 15429 } 15430 15431 /** @private */ 15432 net.user1.orbiter.HTTPConnection.prototype.outgoingCompleteListener = function () { 15433 if (this.disposed) return; 15434 15435 this.outgoingResponsePending = false; 15436 15437 if (!this.sendDelayTimerRunning && this.messageQueue.length > 0) { 15438 // Don't immediately open a request in the complete handler due to Win IE bug 15439 var self = this; 15440 setTimeout(function () { 15441 self.flushMessageQueue(); 15442 }, 0); 15443 } 15444 } 15445 15446 /** @private */ 15447 net.user1.orbiter.HTTPConnection.prototype.outgoingErrorListener = function () { 15448 if (this.disposed) return; 15449 // There's already a retry scheduled 15450 if (this.retryOutgoingTimeoutID != -1) return; 15451 // The connection has been closed 15452 if (this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15453 || this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15454 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Outgoing request failed." 15455 + " Connection is closed, so no retry scheduled."); 15456 return; 15457 } 15458 15459 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Outgoing request failed." 15460 + " Retrying in " + this.retryDelay + "ms."); 15461 15462 // Retry 15463 var self = this; 15464 this.retryOutgoingTimeoutID = setTimeout(function () { 15465 self.retryOutgoingTimeoutID = -1; 15466 if (self.disposed 15467 || self.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15468 || self.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15469 return; 15470 } 15471 self.doRetryOutgoing(); 15472 }, this.retryDelay); 15473 } 15474 15475 //============================================================================== 15476 // INCOMING REQUEST MANAGEMENT 15477 //============================================================================== 15478 15479 /** @private */ 15480 net.user1.orbiter.HTTPConnection.prototype.openNewIncomingRequest = function () { 15481 this.doSendIncoming(); 15482 } 15483 15484 /** @private */ 15485 net.user1.orbiter.HTTPConnection.prototype.incomingCompleteListener = function (data) { 15486 if (this.disposed 15487 || this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15488 || this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15489 // Incoming request complete, but connection is closed. Ignore content. 15490 return; 15491 } 15492 15493 // Don't immediately open a request in the complete handler due to Win IE bug 15494 var self = this; 15495 setTimeout(function () { 15496 self.processIncomingData(data); 15497 // A message listener might have closed this connection in response to an incoming 15498 // message. Do not open a new incoming request unless the connection is still open. 15499 if (self.disposed 15500 || self.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15501 || self.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15502 return; 15503 } 15504 self.openNewIncomingRequest(); 15505 }, 0); 15506 } 15507 15508 /** @private */ 15509 net.user1.orbiter.HTTPConnection.prototype.incomingErrorListener = function () { 15510 if (this.disposed) return; 15511 // There's already a retry scheduled 15512 if (this.retryIncomingTimeoutID != -1) return; 15513 // The connection has been closed 15514 if (this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15515 || this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15516 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Incoming request failed." 15517 + " Connection is closed, so no retry scheduled."); 15518 return; 15519 } 15520 15521 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Incoming request failed." 15522 + " Retrying in " + this.retryDelay + "ms."); 15523 15524 // Retry 15525 var self = this; 15526 this.retryIncomingTimeoutID = setTimeout(function () { 15527 self.retryIncomingTimeoutID = -1; 15528 if (self.disposed 15529 || self.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15530 || self.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15531 return; 15532 } 15533 self.doRetryIncoming(); 15534 }, this.retryDelay); 15535 } 15536 15537 //============================================================================== 15538 // PROCESS DATA FROM THE SERVER 15539 //============================================================================== 15540 15541 /** @private */ 15542 net.user1.orbiter.HTTPConnection.prototype.processIncomingData = function (data) { 15543 if (this.disposed) return; 15544 var listeners; 15545 15546 this.dispatchReceiveData(data); 15547 15548 var upcs = new Array(); 15549 var upcEndTagIndex = data.indexOf("</U>"); 15550 // Empty responses are valid. 15551 if (upcEndTagIndex == -1 && data.length > 0) { 15552 this.orbiter.getLog().error("Invalid message received. No UPC found: [" + data + "]"); 15553 if (!this.isReady()) { 15554 // If invalid XML is received prior to achieving ready, then this 15555 // probably isn't a Union server, so disconnect. 15556 this.disconnect(); 15557 return; 15558 } 15559 } 15560 15561 while (upcEndTagIndex != -1) { 15562 upcs.push(data.substring(0, upcEndTagIndex+4)); 15563 data = data.substring(upcEndTagIndex+4); 15564 upcEndTagIndex = data.indexOf("</U>"); 15565 } 15566 for (var i = 0; i < upcs.length; i++) { 15567 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, upcs[i])); 15568 } 15569 } 15570 15571 //============================================================================== 15572 // SERVER AFFINITY 15573 //============================================================================== 15574 /** @private */ 15575 net.user1.orbiter.HTTPConnection.prototype.applyAffinity = function (data) { 15576 net.user1.orbiter.Connection.prototype.applyAffinity.call(this); 15577 this.buildURL(); 15578 }; 15579 15580 //============================================================================== 15581 // TOSTRING 15582 //============================================================================== 15583 net.user1.orbiter.HTTPConnection.prototype.toString = function () { 15584 var s = "[" + this.connectionType + ", requested host: " + this.requestedHost 15585 + ", host: " + (this.host == null ? "" : this.host) 15586 + ", port: " + this.port 15587 + ", send-delay: " + this.getSendDelay() + "]"; 15588 return s; 15589 } 15590 15591 // ============================================================================= 15592 // DISPOSAL 15593 // ============================================================================= 15594 /** @private */ 15595 net.user1.orbiter.HTTPConnection.prototype.dispose = function () { 15596 this.doDispose(); 15597 this.stopSendDelayTimer(); 15598 net.user1.orbiter.Connection.prototype.dispose.call(this); 15599 } 15600 //============================================================================== 15601 // CLASS DECLARATION 15602 //============================================================================== 15603 /** 15604 * @class 15605 * 15606 * The HTTPIFrameConnection class is used by Orbiter to communicate with 15607 * Union Server over HTTP in browsers that do not support CORS. 15608 * Rather than using CORS, HTTPIFrameConnection bypasses cross-origin restrictions 15609 * by proxying communications through a hidden HTML iframe. 15610 * 15611 * For a list of events dispatched by HTTPDirectConnection, 15612 * {@link net.user1.orbiter.Connection}. 15613 * 15614 * For more information on HTTP communication with Union Server, see 15615 * the HTTPDirectConnection class. 15616 * 15617 * @extends net.user1.orbiter.HTTPConnection 15618 * 15619 * @see net.user1.orbiter.HTTPDirectConnection 15620 * @see net.user1.orbiter.WebSocketConnection 15621 * @see net.user1.orbiter.SecureHTTPDirectConnection 15622 * @see net.user1.orbiter.SecureHTTPIFrameConnection 15623 * @see net.user1.orbiter.SecureWebSocketConnection 15624 */ 15625 net.user1.orbiter.HTTPIFrameConnection = function (host, port, type) { 15626 // Invoke superclass constructor 15627 net.user1.orbiter.HTTPConnection.call(this, host, port, type || net.user1.orbiter.ConnectionType.HTTP); 15628 this.postMessageInited = false; 15629 this.iFrameReady = false; 15630 }; 15631 15632 //============================================================================== 15633 // INHERITANCE 15634 //============================================================================== 15635 net.user1.utils.extend(net.user1.orbiter.HTTPIFrameConnection, net.user1.orbiter.HTTPConnection); 15636 15637 //============================================================================== 15638 // POSTMESSAGE INITIALIZATION 15639 //============================================================================== 15640 /** @private */ 15641 net.user1.orbiter.HTTPIFrameConnection.prototype.initPostMessage = function () { 15642 if (this.postMessageInited) { 15643 throw new Error("[HTTPIFrameConnection] Illegal duplicate initialization attempt."); 15644 } 15645 var self = this; 15646 var win = this.orbiter.window; 15647 var errorMsg = null; 15648 15649 if (win == null) { 15650 errorMsg = "[HTTPIFrameConnection] Unable to create connection." 15651 + " No window object found."; 15652 } else { 15653 if (typeof win.addEventListener != "undefined") { 15654 // ...the standard way 15655 win.addEventListener("message", postMessageListener, false); 15656 } else if (typeof win.attachEvent != "undefined") { 15657 // ...the IE-specific way 15658 win.attachEvent("onmessage", postMessageListener); 15659 } else { 15660 errorMsg = "[HTTPIFrameConnection] Unable to create connection." 15661 + " No event listener registration method found on window object."; 15662 } 15663 } 15664 15665 if (errorMsg != null) { 15666 this.orbiter.getLog().error(errorMsg); 15667 throw new Error(errorMsg); 15668 } 15669 15670 /** @private */ 15671 function postMessageListener (e) { 15672 // The connection's host might have been reassigned (normally to an ip) due 15673 // to server affinity in a clustered deployment, so allow for posts from both the 15674 // requestedHost and the host. 15675 if (e.origin.indexOf("//" + self.host + (self.port == 80 ? "" : (":" + self.port))) == -1 15676 && e.origin.indexOf("//" + self.requestedHost + (self.port == 80 ? "" : (":" + self.port))) == -1) { 15677 self.orbiter.getLog().error("[CONNECTION] " + self.toString() 15678 + " Ignored message from unknown origin: " + e.origin); 15679 return; 15680 } 15681 15682 self.processPostMessage(e.data); 15683 } 15684 15685 this.postMessageInited = true; 15686 }; 15687 15688 //============================================================================== 15689 // IFRAME MANAGEMENT 15690 //============================================================================== 15691 /** @private */ 15692 net.user1.orbiter.HTTPIFrameConnection.prototype.makeIFrame = function () { 15693 if (typeof this.orbiter.window.document == "undefined") { 15694 var errorMsg = "[HTTPIFrameConnection] Unable to create connection." 15695 + " No document object found."; 15696 this.orbiter.getLog().error(errorMsg); 15697 throw new Error(errorMsg); 15698 } 15699 var doc = this.orbiter.window.document; 15700 15701 this.iFrameReady = false; 15702 if (this.iframe != null) { 15703 this.postToIFrame("dispose"); 15704 doc.body.removeChild(this.iframe); 15705 } 15706 this.iframe = doc.createElement('iframe'); 15707 this.iframe.width = "0px"; 15708 this.iframe.height = "0px"; 15709 this.iframe.border = "0px"; 15710 this.iframe.frameBorder = "0"; 15711 this.iframe.style.visibility = "hidden"; 15712 this.iframe.style.display = "none"; 15713 this.iframe.src = this.url + "/orbiter"; 15714 doc.body.appendChild(this.iframe); 15715 } 15716 15717 /** @private */ 15718 net.user1.orbiter.HTTPIFrameConnection.prototype.onIFrameReady = function () { 15719 this.beginReadyHandshake(); 15720 } 15721 15722 /** @private */ 15723 net.user1.orbiter.HTTPIFrameConnection.prototype.postToIFrame = function (cmd, data) { 15724 if (this.iframe && this.iFrameReady) { 15725 data = data == undefined ? "" : data; 15726 // In order to post to the iframe, the targetOrigin must match the iframe's origin 15727 this.iframe.contentWindow.postMessage(cmd + "," + data, this.iframe.contentWindow.location.href); 15728 } 15729 } 15730 15731 /** @private */ 15732 net.user1.orbiter.HTTPIFrameConnection.prototype.processPostMessage = function (postedData) { 15733 var delimiterIndex = postedData.indexOf(","); 15734 var cmd = postedData.substring(0, delimiterIndex); 15735 var data = postedData.substring(delimiterIndex+1); 15736 15737 switch (cmd) { 15738 case"ready": 15739 this.iFrameReady = true; 15740 this.onIFrameReady(); 15741 break; 15742 15743 case "hellocomplete": 15744 this.helloCompleteListener(data); 15745 break; 15746 15747 case "helloerror": 15748 this.helloErrorListener(); 15749 break; 15750 15751 case "outgoingcomplete": 15752 this.outgoingCompleteListener(); 15753 break; 15754 15755 case "outgoingerror": 15756 this.outgoingErrorListener(); 15757 break; 15758 15759 case "incomingcomplete": 15760 this.incomingCompleteListener(data); 15761 break; 15762 15763 case "incomingerror": 15764 this.incomingErrorListener(); 15765 break; 15766 } 15767 } 15768 15769 //============================================================================== 15770 // CONNECTION AND DISCONNECTION 15771 //============================================================================== 15772 net.user1.orbiter.HTTPIFrameConnection.prototype.connect = function () { 15773 if (!this.postMessageInited) { 15774 this.initPostMessage(); 15775 } 15776 15777 net.user1.orbiter.HTTPConnection.prototype.connect.call(this); 15778 this.makeIFrame(); 15779 }; 15780 15781 /** @private */ 15782 net.user1.orbiter.HTTPIFrameConnection.prototype.doRequestDeactivation = function() { 15783 this.postToIFrame("deactivate"); 15784 }; 15785 15786 //============================================================================== 15787 // UPC LISTENERS (IFRAME-SPECIFIC IMPLEMENTATION) 15788 //============================================================================== 15789 15790 /** @private */ 15791 net.user1.orbiter.HTTPIFrameConnection.prototype.u66 = function (serverVersion, 15792 sessionID, 15793 upcVersion, 15794 protocolCompatible) { 15795 net.user1.orbiter.Connection.prototype.u66.call(this, 15796 serverVersion, 15797 sessionID, 15798 upcVersion, 15799 protocolCompatible); 15800 if (this.iframe != null) { 15801 this.postToIFrame("sessionid", sessionID); 15802 } 15803 } 15804 15805 //============================================================================== 15806 // HELLO REQUEST MANAGEMENT 15807 //============================================================================== 15808 15809 /** @private */ 15810 net.user1.orbiter.HTTPIFrameConnection.prototype.doSendHello = function (helloString) { 15811 this.postToIFrame("sendhello", helloString); 15812 }; 15813 15814 /** @private */ 15815 net.user1.orbiter.HTTPIFrameConnection.prototype.doRetryHello = function () { 15816 this.postToIFrame("retryhello"); 15817 } 15818 15819 //============================================================================== 15820 // OUTGOING REQUEST MANAGEMENT 15821 //============================================================================== 15822 15823 /** @private */ 15824 net.user1.orbiter.HTTPIFrameConnection.prototype.doSendOutgoing = function (data) { 15825 this.postToIFrame("sendoutgoing", data); 15826 }; 15827 15828 /** @private */ 15829 net.user1.orbiter.HTTPIFrameConnection.prototype.doRetryOutgoing = function () { 15830 this.postToIFrame("retryoutgoing"); 15831 }; 15832 15833 //============================================================================== 15834 // INCOMING REQUEST MANAGEMENT 15835 //============================================================================== 15836 15837 /** @private */ 15838 net.user1.orbiter.HTTPIFrameConnection.prototype.doSendIncoming = function () { 15839 this.postToIFrame("sendincoming"); 15840 }; 15841 15842 /** @private */ 15843 net.user1.orbiter.HTTPIFrameConnection.prototype.doRetryIncoming = function () { 15844 this.postToIFrame("retryincoming"); 15845 }; 15846 15847 //============================================================================== 15848 // TOSTRING 15849 //============================================================================== 15850 net.user1.orbiter.HTTPIFrameConnection.prototype.toString = function () { 15851 var s = "[HTTPIFrameConnection, requested host: " + this.requestedHost 15852 + ", host: " + (this.host == null ? "" : this.host) 15853 + ", port: " + this.port 15854 + ", send-delay: " + this.getSendDelay() + "]"; 15855 return s; 15856 }; 15857 15858 //============================================================================== 15859 // DISPOSAL 15860 //============================================================================== 15861 /** @private */ 15862 net.user1.orbiter.HTTPIFrameConnection.prototype.doDispose = function () { 15863 this.postToIFrame("dispose"); 15864 }; 15865 //============================================================================== 15866 // CLASS DECLARATION 15867 //============================================================================== 15868 /** 15869 * @class 15870 * <p> 15871 * The HTTPDirectConnection class is used by Orbiter to communicate with 15872 * Union Server over HTTP; it uses CORS to bypass cross-origin restrictions 15873 * when Union Server is hosted on a domain that does not match the domain at 15874 * which the Orbiter client is hosted. Normally, developers need not use the 15875 * HTTPDirectConnection class directly, and should instead make connections 15876 * via the Orbiter class's connect() method. However, the 15877 * HTTPDirectConnection class is required for fine-grained connection configuration, 15878 * such as defining failover connections for multiple Union Servers 15879 * running at different host addresses. 15880 * </p> 15881 * 15882 * <p> 15883 * By default, Orbiter uses the WebSocketConnection class, not the 15884 * HTTPDirectConnection class, to communicate with Union Server. The 15885 * HTTPDirectConnection class is used as a backup connection 15886 * when the primary WebSocketConnection connection is blocked by a firewall. 15887 * However, on a very heavily loaded server with limited persistent socket 15888 * connections available, communicating with Union Server over HTTP--which uses 15889 * short-lived socket connections--can improve performance at the 15890 * expense of realtime responsiveness. To reduce server load when communicating 15891 * over HTTP, use HTTPDirectConnection's setSendDelay() method to decrease the 15892 * frequency of Orbiter's requests for updates from Union Server. Developers 15893 * that wish to use HTTP connections as the primary form of communication with 15894 * Union Server must do so by manually configuring connections via the 15895 * ConnectionManager class's addConnection() method.</p> 15896 * 15897 * <p> 15898 * In environments that do not support CORS (such as IE8 on Windows), Orbiter 15899 * conducts HTTP communications using HTTPIFrameConnection instead of HTTPDirectConnection. 15900 * </p> 15901 * 15902 * <p> 15903 * For secure HTTP and WebSocket communications, see SecureHTTPDirectConnection, 15904 * SecureHTTPIFrameConnection, and SecureWebSocketConnection. 15905 * </p> 15906 * 15907 * 15908 * For a list of events dispatched by HTTPDirectConnection, 15909 * {@link net.user1.orbiter.Connection}. 15910 * 15911 * @extends net.user1.orbiter.HTTPConnection 15912 * 15913 * @see net.user1.orbiter.Orbiter#connect 15914 * @see net.user1.orbiter.Orbiter#secureConnect 15915 * 15916 * @see net.user1.orbiter.SecureHTTPDirectConnection 15917 * @see net.user1.orbiter.SecureHTTPIFrameConnection 15918 * @see net.user1.orbiter.SecureWebSocketConnection 15919 */ 15920 net.user1.orbiter.HTTPDirectConnection = function (host, port, type) { 15921 // Invoke superclass constructor 15922 net.user1.orbiter.HTTPConnection.call(this, host, port, type || net.user1.orbiter.ConnectionType.HTTP); 15923 15924 this.outgoingRequestID = 0; 15925 this.incomingRequestID = 0; 15926 15927 this.lastOutgoingPostData = null; 15928 this.lastIncomingPostData = null; 15929 this.lastHelloPostData = null; 15930 15931 this.pendingRequests = []; 15932 }; 15933 15934 //============================================================================== 15935 // INHERITANCE 15936 //============================================================================== 15937 net.user1.utils.extend(net.user1.orbiter.HTTPDirectConnection, net.user1.orbiter.HTTPConnection); 15938 15939 15940 //============================================================================== 15941 // CONNECTION AND DISCONNECTION 15942 //============================================================================== 15943 net.user1.orbiter.HTTPDirectConnection.prototype.connect = function () { 15944 net.user1.orbiter.HTTPConnection.prototype.connect.call(this); 15945 this.beginReadyHandshake(); 15946 }; 15947 15948 //============================================================================== 15949 // HELLO REQUEST MANAGEMENT 15950 //============================================================================== 15951 15952 /** @private Abstract method implementation */ 15953 net.user1.orbiter.HTTPDirectConnection.prototype.doSendHello = function (helloString) { 15954 this.newHelloRequest(helloString); 15955 }; 15956 15957 /** @private Abstract method implementation */ 15958 net.user1.orbiter.HTTPDirectConnection.prototype.doRetryHello = function () { 15959 this.retryHello(); 15960 } 15961 15962 /** @private */ 15963 net.user1.orbiter.HTTPDirectConnection.prototype.newHelloRequest = function (data) { 15964 this.lastHelloPostData = this.createHelloPostData(encodeURIComponent(data)); 15965 this.transmitRequest(this.lastHelloPostData, 15966 net.user1.orbiter.HTTPDirectConnection.helloRequestReadystatechangeListener, 15967 net.user1.orbiter.HTTPDirectConnection.helloRequestErrorListener); 15968 } 15969 15970 /** @private */ 15971 net.user1.orbiter.HTTPDirectConnection.prototype.createHelloPostData = function (data) { 15972 return "mode=d" + "&data=" + data; 15973 } 15974 15975 /** @private */ 15976 net.user1.orbiter.HTTPDirectConnection.prototype.retryHello = function () { 15977 this.transmitRequest(this.lastHelloPostData, 15978 net.user1.orbiter.HTTPDirectConnection.helloRequestReadystatechangeListener, 15979 net.user1.orbiter.HTTPDirectConnection.helloRequestErrorListener); 15980 } 15981 15982 /** @private */ 15983 net.user1.orbiter.HTTPDirectConnection.helloRequestReadystatechangeListener = function (xhr, connection) { 15984 if (xhr.readyState == 4) { 15985 connection.removePendingRequest(xhr); 15986 if (xhr.status >= 200 && xhr.status <= 299) { 15987 connection.helloCompleteListener(xhr.responseText); 15988 } else { 15989 connection.helloErrorListener(); 15990 } 15991 } 15992 } 15993 15994 /** @private */ 15995 net.user1.orbiter.HTTPDirectConnection.helloRequestErrorListener = function (xhr, connection) { 15996 connection.removePendingRequest(xhr); 15997 connection.helloErrorListener(); 15998 } 15999 16000 //============================================================================== 16001 // OUTGOING REQUEST MANAGEMENT 16002 //============================================================================== 16003 16004 /** @private Abstract method implementation */ 16005 net.user1.orbiter.HTTPDirectConnection.prototype.doSendOutgoing = function (data) { 16006 this.newOutgoingRequest(data); 16007 }; 16008 16009 /** @private Abstract method implementation */ 16010 net.user1.orbiter.HTTPDirectConnection.prototype.doRetryOutgoing = function () { 16011 this.retryOutgoing(); 16012 }; 16013 16014 /** @private */ 16015 net.user1.orbiter.HTTPDirectConnection.prototype.newOutgoingRequest = function (data) { 16016 this.lastOutgoingPostData = this.createOutgoingPostData(encodeURIComponent(data)); 16017 this.transmitRequest(this.lastOutgoingPostData, 16018 net.user1.orbiter.HTTPDirectConnection.outgoingRequestReadystatechangeListener, 16019 net.user1.orbiter.HTTPDirectConnection.outgoingRequestErrorListener); 16020 } 16021 16022 /** @private */ 16023 net.user1.orbiter.HTTPDirectConnection.prototype.createOutgoingPostData = function (data) { 16024 this.outgoingRequestID++; 16025 return "rid=" + this.outgoingRequestID + "&sid=" + this.orbiter.getSessionID() + "&mode=s" + "&data=" + data; 16026 } 16027 16028 /** @private */ 16029 net.user1.orbiter.HTTPDirectConnection.prototype.retryOutgoing = function () { 16030 this.transmitRequest(this.lastOutgoingPostData, 16031 net.user1.orbiter.HTTPDirectConnection.outgoingRequestReadystatechangeListener, 16032 net.user1.orbiter.HTTPDirectConnection.outgoingRequestErrorListener); 16033 } 16034 16035 /** @private */ 16036 net.user1.orbiter.HTTPDirectConnection.outgoingRequestReadystatechangeListener = function (xhr, connection) { 16037 if (xhr.readyState == 4) { 16038 connection.removePendingRequest(xhr); 16039 if (xhr.status >= 200 && xhr.status <= 299) { 16040 connection.outgoingCompleteListener(); 16041 } else { 16042 connection.outgoingErrorListener(); 16043 } 16044 } 16045 } 16046 16047 /** @private */ 16048 net.user1.orbiter.HTTPDirectConnection.outgoingRequestErrorListener = function (xhr, connection) { 16049 connection.removePendingRequest(xhr); 16050 connection.outgoingErrorListener(); 16051 } 16052 16053 //============================================================================== 16054 // INCOMING REQUEST MANAGEMENT 16055 //============================================================================== 16056 16057 /** @private Abstract method implementation */ 16058 net.user1.orbiter.HTTPDirectConnection.prototype.doSendIncoming = function () { 16059 this.newIncomingRequest(); 16060 }; 16061 16062 /** @private Abstract method implementation */ 16063 net.user1.orbiter.HTTPDirectConnection.prototype.doRetryIncoming = function () { 16064 this.retryIncoming(); 16065 }; 16066 16067 /** @private */ 16068 net.user1.orbiter.HTTPDirectConnection.prototype.newIncomingRequest = function () { 16069 this.lastIncomingPostData = this.createIncomingPostData(); 16070 this.transmitRequest(this.lastIncomingPostData, 16071 net.user1.orbiter.HTTPDirectConnection.incomingRequestReadystatechangeListener, 16072 net.user1.orbiter.HTTPDirectConnection.incomingRequestErrorListener); 16073 } 16074 16075 /** @private */ 16076 net.user1.orbiter.HTTPDirectConnection.prototype.createIncomingPostData = function () { 16077 this.incomingRequestID++; 16078 return "rid=" + this.incomingRequestID + "&sid=" + this.orbiter.getSessionID() + "&mode=c"; 16079 } 16080 16081 /** @private */ 16082 net.user1.orbiter.HTTPDirectConnection.prototype.retryIncoming = function () { 16083 this.transmitRequest(this.lastIncomingPostData, 16084 net.user1.orbiter.HTTPDirectConnection.incomingRequestReadystatechangeListener, 16085 net.user1.orbiter.HTTPDirectConnection.incomingRequestErrorListener); 16086 } 16087 16088 /** @private */ 16089 net.user1.orbiter.HTTPDirectConnection.incomingRequestReadystatechangeListener = function (xhr, connection) { 16090 if (xhr.readyState == 4) { 16091 connection.removePendingRequest(xhr); 16092 if (xhr.status >= 200 && xhr.status <= 299) { 16093 connection.incomingCompleteListener(xhr.responseText); 16094 } else { 16095 connection.incomingErrorListener(); 16096 } 16097 } 16098 } 16099 16100 /** @private */ 16101 net.user1.orbiter.HTTPDirectConnection.incomingRequestErrorListener = function (xhr, connection) { 16102 connection.removePendingRequest(xhr); 16103 connection.incomingErrorListener(); 16104 } 16105 16106 //============================================================================== 16107 // XHR MANAGEMENT 16108 //============================================================================== 16109 /** @private */ 16110 net.user1.orbiter.HTTPDirectConnection.prototype.transmitRequest = function (data, 16111 readystatechangeListener, 16112 errorListener) { 16113 var self = this; 16114 var request; 16115 16116 if (typeof XDomainRequest != "undefined") { 16117 // IE 16118 request = new XDomainRequest(); 16119 request.onload = function () { 16120 request.readyState = 4; // Emulate standards-based API 16121 request.status = 200; 16122 readystatechangeListener(this, self) 16123 }; 16124 request.onerror = function () { 16125 errorListener(this, self); 16126 }; 16127 request.ontimeout = function () { 16128 errorListener(this, self); 16129 }; 16130 request.onprogress = function () {}; // Do nothing (required) 16131 } else { 16132 // All other standards-based browsers 16133 var request = new XMLHttpRequest(); 16134 this.pendingRequests.push(request); 16135 request.onreadystatechange = function () { 16136 readystatechangeListener(this, self); 16137 }; 16138 request.onerror = function () { 16139 errorListener(this, self); 16140 }; 16141 } 16142 // Call open before setting header 16143 request.open("POST", this.url); 16144 // Standards-based browsers (IE doesn't allow the setting of headers) 16145 if (typeof request.setRequestHeader != "undefined") { 16146 request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); 16147 } 16148 request.send(data); 16149 } 16150 16151 /** @private */ 16152 net.user1.orbiter.HTTPDirectConnection.prototype.removePendingRequest = function (request) { 16153 for (var i = this.pendingRequests.length; --i >= 0; ) { 16154 if (this.pendingRequests[i] === request) { 16155 this.pendingRequests.splice(i, 1); 16156 } 16157 } 16158 } 16159 16160 /** @private Abstract method implementation */ 16161 net.user1.orbiter.HTTPDirectConnection.prototype.doRequestDeactivation = function () { 16162 for (var i = this.pendingRequests.length; --i >= 0;) { 16163 try { 16164 this.pendingRequests[i].abort(); 16165 } catch (e) { 16166 // Do nothing 16167 } 16168 } 16169 this.pendingRequests = []; 16170 } 16171 16172 //============================================================================== 16173 // TOSTRING 16174 //============================================================================== 16175 net.user1.orbiter.HTTPDirectConnection.prototype.toString = function () { 16176 var s = "[HTTPDirectConnection, requested host: " + this.requestedHost 16177 + ", host: " + (this.host == null ? "" : this.host) 16178 + ", port: " + this.port 16179 + ", send-delay: " + this.getSendDelay() + "]"; 16180 return s; 16181 }; 16182 16183 //============================================================================== 16184 // DISPOSAL 16185 //============================================================================== 16186 /** @private */ 16187 net.user1.orbiter.HTTPDirectConnection.prototype.doDispose = function () { 16188 this.deactivateHTTPRequests(); 16189 }; 16190 //============================================================================== 16191 // CLASS DECLARATION 16192 //============================================================================== 16193 /** @class 16194 * <p> 16195 * The SecureHTTPDirectConnection class is identical to HTTPDirectConnection 16196 * except that it performs communications over HTTPS (i.e., an encrypted TLS or 16197 * SSL connection) rather than plain HTTP.</p> 16198 * 16199 * For a list of events dispatched by SecureHTTPDirectConnection, see 16200 * {@link net.user1.orbiter.Connection}. 16201 * 16202 * @extends net.user1.orbiter.HTTPDirectConnection 16203 * 16204 * @see net.user1.orbiter.HTTPDirectConnection 16205 */ 16206 net.user1.orbiter.SecureHTTPDirectConnection = function (host, port) { 16207 // Invoke superclass constructor 16208 net.user1.orbiter.HTTPDirectConnection.call(this, host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP); 16209 }; 16210 16211 //============================================================================== 16212 // INHERITANCE 16213 //============================================================================== 16214 net.user1.utils.extend(net.user1.orbiter.SecureHTTPDirectConnection, net.user1.orbiter.HTTPDirectConnection); 16215 16216 /** @private */ 16217 net.user1.orbiter.SecureHTTPDirectConnection.prototype.buildURL = function () { 16218 this.url = "https://" + this.host + ":" + this.port; 16219 }; 16220 16221 //============================================================================== 16222 // TOSTRING 16223 //============================================================================== 16224 net.user1.orbiter.SecureHTTPDirectConnection.prototype.toString = function () { 16225 var s = "[SecureHTTPDirectConnection, requested host: " + this.requestedHost 16226 + ", host: " + (this.host == null ? "" : this.host) 16227 + ", port: " + this.port 16228 + ", send-delay: " + this.getSendDelay() + "]"; 16229 return s; 16230 }; 16231 //============================================================================== 16232 // CLASS DECLARATION 16233 //============================================================================== 16234 /** 16235 * @class 16236 * 16237 * <p> 16238 * The SecureHTTPIFrameConnection class is identical to HTTPIFrameConnection 16239 * except that it performs communications over HTTPS (i.e., an encrypted TLS or 16240 * SSL connection) rather than plain HTTP.</p> 16241 * 16242 * For a list of events dispatched by SecureHTTPIFrameConnection, 16243 * see {@link net.user1.orbiter.Connection}. 16244 * 16245 * @extends net.user1.orbiter.HTTPIFrameConnection 16246 * 16247 * @see net.user1.orbiter.HTTPIFrameConnection 16248 */ 16249 net.user1.orbiter.SecureHTTPIFrameConnection = function (host, port) { 16250 // Invoke superclass constructor 16251 net.user1.orbiter.HTTPIFrameConnection.call(this, host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP); 16252 }; 16253 16254 //============================================================================== 16255 // INHERITANCE 16256 //============================================================================== 16257 net.user1.utils.extend(net.user1.orbiter.SecureHTTPIFrameConnection, net.user1.orbiter.HTTPIFrameConnection); 16258 16259 /** @private */ 16260 net.user1.orbiter.SecureHTTPIFrameConnection.prototype.buildURL = function () { 16261 this.url = "https://" + this.host + ":" + this.port; 16262 }; 16263 16264 //============================================================================== 16265 // TOSTRING 16266 //============================================================================== 16267 net.user1.orbiter.SecureHTTPIFrameConnection.prototype.toString = function () { 16268 var s = "[SecureHTTPIFrameConnection, requested host: " + this.requestedHost 16269 + ", host: " + (this.host == null ? "" : this.host) 16270 + ", port: " + this.port 16271 + ", send-delay: " + this.getSendDelay() + "]"; 16272 return s; 16273 }; 16274 //============================================================================== 16275 // CLASS DECLARATION 16276 //============================================================================== 16277 /** @private */ 16278 net.user1.orbiter.MessageListener = function (listener, 16279 forRoomIDs, 16280 thisArg) { 16281 this.listener = listener; 16282 this.forRoomIDs = forRoomIDs; 16283 this.thisArg = thisArg; 16284 }; 16285 16286 //============================================================================== 16287 // INSTANCE METHODS 16288 //============================================================================== 16289 /** @private */ 16290 net.user1.orbiter.MessageListener.prototype.getListenerFunction = function () { 16291 return this.listener; 16292 }; 16293 16294 /** @private */ 16295 net.user1.orbiter.MessageListener.prototype.getForRoomIDs = function () { 16296 return this.forRoomIDs; 16297 }; 16298 16299 /** @private */ 16300 net.user1.orbiter.MessageListener.prototype.getThisArg = function () { 16301 return this.thisArg; 16302 }; 16303 16304 /** @private */ 16305 net.user1.orbiter.MessageListener.prototype.toString = function () { 16306 return "[object MessageListener]"; 16307 }; 16308 //============================================================================== 16309 // CLASS DECLARATION 16310 //============================================================================== 16311 /** @class */ 16312 net.user1.orbiter.MessageManager = function (log, connectionManager) { 16313 this.log = log; 16314 this.messageListeners = new Object(); 16315 this.removeListenersOnDisconnect = true; 16316 this.numMessagesSent = 0; 16317 this.numMessagesReceived = 0; 16318 this.currentConnection = null; 16319 this.connectionManager = connectionManager; 16320 this.connectionManager.addEventListener(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 16321 this.selectConnectionListener, this); 16322 }; 16323 16324 //============================================================================== 16325 // INSTANCE METHODS 16326 //============================================================================== 16327 net.user1.orbiter.MessageManager.prototype.getNumMessagesReceived = function () { 16328 return this.numMessagesReceived; 16329 } 16330 16331 net.user1.orbiter.MessageManager.prototype.getNumMessagesSent = function () { 16332 return this.numMessagesSent; 16333 } 16334 16335 net.user1.orbiter.MessageManager.prototype.getTotalMessages = function () { 16336 return this.numMessagesSent + this.numMessagesReceived; 16337 } 16338 16339 /** @private */ 16340 net.user1.orbiter.MessageManager.prototype.selectConnectionListener = function (e) { 16341 if (this.currentConnection != null) { 16342 this.currentConnection.removeEventListener(net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, 16343 this.upcReceivedListener, this); 16344 this.currentConnection.removeEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, 16345 this.disconnectListener, this); 16346 this.currentConnection.removeEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, 16347 this.connectFailureListener, this); 16348 } 16349 16350 this.currentConnection = e.getConnection(); 16351 16352 this.currentConnection.addEventListener(net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, 16353 this.upcReceivedListener, this); 16354 this.currentConnection.addEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, 16355 this.disconnectListener, this); 16356 this.currentConnection.addEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, 16357 this.connectFailureListener, this); 16358 } 16359 16360 /** @private */ 16361 net.user1.orbiter.MessageManager.prototype.disconnectListener = function (e) { 16362 this.cleanupAfterClosedConnection(e.target); 16363 } 16364 16365 /** @private */ 16366 net.user1.orbiter.MessageManager.prototype.connectFailureListener = function (e) { 16367 this.cleanupAfterClosedConnection(e.target); 16368 } 16369 16370 /** @private */ 16371 net.user1.orbiter.MessageManager.prototype.cleanupAfterClosedConnection = function (connection) { 16372 var listenerList; 16373 if (this.removeListenersOnDisconnect) { 16374 this.log.info("[MESSAGE_MANAGER] Removing registered message listeners."); 16375 for (var message in this.messageListeners) { 16376 listenerList = this.messageListeners[message]; 16377 for (var p in listenerList) { 16378 this.removeMessageListener(message, listenerList[p].getListenerFunction()); 16379 } 16380 } 16381 } else { 16382 this.log.warn("[MESSAGE_MANAGER] Leaving message listeners registered. \n" 16383 + "Be sure to remove any unwanted message listeners manually."); 16384 } 16385 16386 this.numMessagesReceived = 0; 16387 this.numMessagesSent = 0; 16388 } 16389 16390 net.user1.orbiter.MessageManager.prototype.sendUPC = function (message) { 16391 // Quit if the connection isn't ready... 16392 if (!this.connectionManager.isReady()) { 16393 this.log.warn("[MESSAGE_MANAGER] Connection not ready. UPC not sent. Message: " 16394 + message); 16395 return; 16396 } 16397 16398 // Build the UPC to send. 16399 var theUPC = "<U><M>" + message + "</M>"; 16400 var a; 16401 16402 if (arguments.length > 1) { 16403 theUPC += "<L>"; 16404 for (var i = 1; i < arguments.length; i++) { 16405 a = arguments[i]; 16406 a = a == undefined ? "" : a.toString(); 16407 // Wrap any non-filter argument that contains a start tag ("<") in CDATA 16408 if (a.indexOf("<") != -1) { 16409 if (a.indexOf('<f t=') != 0) { 16410 a = "<![CDATA[" + a + "]]>"; 16411 } 16412 } 16413 theUPC += "<A>" + a + "</A>"; 16414 } 16415 theUPC += "</L>"; 16416 } 16417 theUPC += "</U>"; 16418 16419 // Count the message 16420 this.numMessagesSent++; 16421 16422 // Send the UPC to the server 16423 this.log.debug("[MESSAGE_MANAGER] UPC sent: " + theUPC); 16424 this.connectionManager.getActiveConnection().send(theUPC); 16425 }; 16426 16427 /** @private */ 16428 net.user1.orbiter.MessageManager.prototype.sendUPCObject = function (upc) { 16429 var args = upc.args.slice(); 16430 args.unshift(upc.method); 16431 this.sendUPC.apply(this, args); 16432 }; 16433 16434 /** @private */ 16435 net.user1.orbiter.MessageManager.prototype.upcReceivedListener = function (e) { 16436 this.numMessagesReceived++; 16437 16438 var upc = e.getUPC(); 16439 this.log.debug("[MESSAGE_MANAGER] UPC received: " + upc ); 16440 16441 var method; 16442 var upcArgs = new Array(); 16443 16444 var closeMTagIndex = upc.indexOf("</M>"); 16445 method = upc.substring(6, closeMTagIndex); 16446 16447 var searchBeginIndex = upc.indexOf("<A>", closeMTagIndex); 16448 var closeATagIndex; 16449 var arg; 16450 while (searchBeginIndex != -1) { 16451 closeATagIndex = upc.indexOf("</A>", searchBeginIndex); 16452 arg = upc.substring(searchBeginIndex+3, closeATagIndex); 16453 if (arg.indexOf("<![CDATA[") == 0) { 16454 arg = arg.substr(9, arg.length-12); 16455 } 16456 upcArgs.push(arg); 16457 searchBeginIndex = upc.indexOf("<A>", closeATagIndex); 16458 } 16459 16460 this.notifyMessageListeners(method, upcArgs); 16461 }; 16462 16463 net.user1.orbiter.MessageManager.prototype.addMessageListener = function (message, 16464 listener, 16465 thisArg, 16466 forRoomIDs) { 16467 if (forRoomIDs != null) { 16468 var typeString = Object.prototype.toString.call(forRoomIDs); 16469 if (typeString != "[object Array]") { 16470 throw new Error("[MESSAGE_MANAGER] Illegal argument type " + typeString 16471 + " supplied for addMessageListener()'s forRoomIDs" 16472 + " parameter. Value must be an Array."); 16473 } 16474 } 16475 16476 // Each message gets a list of MessageListener objects. 16477 // If this message has no such list, make one. 16478 if (this.messageListeners[message] === undefined) { 16479 this.messageListeners[message] = new Array(); 16480 } 16481 var listenerArray = this.messageListeners[message]; 16482 16483 // Quit if the listener is already registered 16484 if (this.hasMessageListener(message, listener)) { 16485 return false; 16486 } 16487 16488 // Add the listener 16489 var newListener = new net.user1.orbiter.MessageListener(listener, 16490 forRoomIDs === undefined ? null : forRoomIDs, 16491 thisArg); 16492 listenerArray.push(newListener); 16493 return true; 16494 }; 16495 16496 net.user1.orbiter.MessageManager.prototype.removeMessageListener = function (message, 16497 listener) { 16498 // Quit if the message has no listeners 16499 var listenerArray = this.messageListeners[message]; 16500 if (listenerArray == null) { 16501 return false; 16502 } 16503 16504 // Remove the listener 16505 var foundListener; 16506 for (var i = 0; i < listenerArray.length; i++) { 16507 if (listenerArray[i].getListenerFunction() == listener) { 16508 foundListener = true; 16509 listenerArray.splice(i, 1); 16510 break; 16511 } 16512 } 16513 16514 // Delete the listeners array if it's now empty 16515 if (listenerArray.length == 0) { 16516 delete this.messageListeners[message]; 16517 } 16518 16519 return foundListener; 16520 }; 16521 16522 net.user1.orbiter.MessageManager.prototype.hasMessageListener = function (message, 16523 listener) { 16524 // Quit if the message has no listeners 16525 var listenerArray = this.messageListeners[message]; 16526 if (listenerArray == null) { 16527 return false; 16528 } 16529 16530 // Check for the listener 16531 for (var i = 0; i < listenerArray.length; i++) { 16532 if (listenerArray[i].getListenerFunction() 16533 == listener) { 16534 return true; 16535 } 16536 } 16537 return false; 16538 }; 16539 16540 net.user1.orbiter.MessageManager.prototype.getMessageListeners = function (message) { 16541 return this.messageListeners[message] != undefined ? this.messageListeners[message] : []; 16542 }; 16543 16544 /** @private */ 16545 net.user1.orbiter.MessageManager.prototype.notifyMessageListeners = function (message, args) { 16546 // Retrieve the list of listeners for this message. 16547 var listeners = this.messageListeners[message]; 16548 // If there are no listeners registered, then quit 16549 if (listeners === undefined) { 16550 // Log a warning if it's not a UPC 16551 if (!(message.charAt(0) == "u" && parseInt(message.substring(1)) > 1)) { 16552 this.log.warn("Message delivery failed. No listeners found. Message: " + 16553 message + ". Arguments: " + args.join()); 16554 } 16555 return; 16556 } else { 16557 listeners = listeners.slice(0); 16558 } 16559 var numListeners = listeners.length; 16560 for (var i = 0; i < numListeners; i++) { 16561 listeners[i].getListenerFunction().apply(listeners[i].getThisArg(), args); 16562 } 16563 }; 16564 16565 net.user1.orbiter.MessageManager.prototype.dispose = function () { 16566 this.log.info("[MESSAGE_MANAGER] Disposing resources."); 16567 this.log = null; 16568 this.orbiter = null; 16569 this.messageListeners = null; 16570 this.numMessagesSent = 0; 16571 this.numMessagesReceived = 0; 16572 this.currentConnection = null; 16573 } 16574 16575 net.user1.orbiter.MessageManager.prototype.toString = function () { 16576 return "[object MessageManager]"; 16577 }; 16578 16579 //============================================================================== 16580 // UPC CONSTANTS 16581 //============================================================================== 16582 /** @class */ 16583 net.user1.orbiter.UPC = new Object(); 16584 16585 // CLIENT TO SERVER 16586 /** @constant */ 16587 net.user1.orbiter.UPC.SEND_MESSAGE_TO_ROOMS = "u1"; 16588 /** @constant */ 16589 net.user1.orbiter.UPC.SEND_MESSAGE_TO_CLIENTS = "u2"; 16590 /** @constant */ 16591 net.user1.orbiter.UPC.SET_CLIENT_ATTR = "u3"; 16592 /** @constant */ 16593 net.user1.orbiter.UPC.JOIN_ROOM = "u4"; 16594 /** @constant */ 16595 net.user1.orbiter.UPC.SET_ROOM_ATTR = "u5"; 16596 /** @constant */ 16597 net.user1.orbiter.UPC.LEAVE_ROOM = "u10"; 16598 /** @constant */ 16599 net.user1.orbiter.UPC.CREATE_ACCOUNT = "u11"; 16600 /** @constant */ 16601 net.user1.orbiter.UPC.REMOVE_ACCOUNT = "u12"; 16602 /** @constant */ 16603 net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD = "u13"; 16604 /** @constant */ 16605 net.user1.orbiter.UPC.LOGIN = "u14"; 16606 /** @constant */ 16607 net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT = "u18"; 16608 /** @constant */ 16609 net.user1.orbiter.UPC.SYNC_TIME = "u19"; 16610 /** @constant */ 16611 net.user1.orbiter.UPC.GET_ROOMLIST_SNAPSHOT = "u21"; 16612 /** @constant */ 16613 net.user1.orbiter.UPC.CREATE_ROOM = "u24"; 16614 /** @constant */ 16615 net.user1.orbiter.UPC.REMOVE_ROOM = "u25"; 16616 /** @constant */ 16617 net.user1.orbiter.UPC.WATCH_FOR_ROOMS = "u26"; 16618 /** @constant */ 16619 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS = "u27"; 16620 /** @constant */ 16621 net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT = "u55"; 16622 /** @constant */ 16623 net.user1.orbiter.UPC.SEND_MESSAGE_TO_SERVER = "u57"; 16624 /** @constant */ 16625 net.user1.orbiter.UPC.OBSERVE_ROOM = "u58"; 16626 /** @constant */ 16627 net.user1.orbiter.UPC.STOP_OBSERVING_ROOM = "u61"; 16628 /** @constant */ 16629 net.user1.orbiter.UPC.SET_ROOM_UPDATE_LEVELS = "u64"; 16630 /** @constant */ 16631 net.user1.orbiter.UPC.CLIENT_HELLO = "u65"; 16632 /** @constant */ 16633 net.user1.orbiter.UPC.REMOVE_ROOM_ATTR = "u67"; 16634 /** @constant */ 16635 net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR = "u69"; 16636 /** @constant */ 16637 net.user1.orbiter.UPC.SEND_ROOMMODULE_MESSAGE = "u70"; 16638 /** @constant */ 16639 net.user1.orbiter.UPC.SEND_SERVERMODULE_MESSAGE = "u71"; 16640 /** @constant */ 16641 net.user1.orbiter.UPC.TERMINATE_SESSION = "u83"; 16642 /** @constant */ 16643 net.user1.orbiter.UPC.LOGOFF = "u86"; 16644 /** @constant */ 16645 net.user1.orbiter.UPC.GET_CLIENTLIST_SNAPSHOT = "u91"; 16646 /** @constant */ 16647 net.user1.orbiter.UPC.WATCH_FOR_CLIENTS = "u92"; 16648 /** @constant */ 16649 net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS = "u93"; 16650 /** @constant */ 16651 net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT = "u94"; 16652 /** @constant */ 16653 net.user1.orbiter.UPC.OBSERVE_CLIENT = "u95"; 16654 /** @constant */ 16655 net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT = "u96"; 16656 /** @constant */ 16657 net.user1.orbiter.UPC.GET_ACCOUNTLIST_SNAPSHOT = "u97"; 16658 /** @constant */ 16659 net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS = "u98"; 16660 /** @constant */ 16661 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS = "u99"; 16662 /** @constant */ 16663 net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT = "u100"; 16664 /** @constant */ 16665 net.user1.orbiter.UPC.OBSERVE_ACCOUNT = "u121"; 16666 /** @constant */ 16667 net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT = "u122"; 16668 /** @constant */ 16669 net.user1.orbiter.UPC.ADD_ROLE = "u133"; 16670 /** @constant */ 16671 net.user1.orbiter.UPC.REMOVE_ROLE = "u135"; 16672 /** @constant */ 16673 net.user1.orbiter.UPC.KICK_CLIENT = "u149"; 16674 /** @constant */ 16675 net.user1.orbiter.UPC.BAN = "u137"; 16676 /** @constant */ 16677 net.user1.orbiter.UPC.UNBAN = "u139"; 16678 /** @constant */ 16679 net.user1.orbiter.UPC.GET_BANNED_LIST_SNAPSHOT = "u141"; 16680 /** @constant */ 16681 net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES = "u143"; 16682 /** @constant */ 16683 net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES = "u145"; 16684 /** @constant */ 16685 net.user1.orbiter.UPC.GET_NODELIST_SNAPSHOT = "u165"; 16686 /** @constant */ 16687 net.user1.orbiter.UPC.GET_GATEWAYS_SNAPSHOT = "u167"; 16688 16689 // SERVER TO CLIENT 16690 /** @constant */ 16691 net.user1.orbiter.UPC.JOINED_ROOM = "u6"; 16692 /** @constant */ 16693 net.user1.orbiter.UPC.RECEIVE_MESSAGE = "u7"; 16694 /** @constant */ 16695 net.user1.orbiter.UPC.CLIENT_ATTR_UPDATE = "u8"; 16696 /** @constant */ 16697 net.user1.orbiter.UPC.ROOM_ATTR_UPDATE = "u9"; 16698 /** @constant */ 16699 net.user1.orbiter.UPC.CLIENT_METADATA = "u29"; 16700 /** @constant */ 16701 net.user1.orbiter.UPC.CREATE_ROOM_RESULT = "u32"; 16702 /** @constant */ 16703 net.user1.orbiter.UPC.REMOVE_ROOM_RESULT = "u33"; 16704 /** @constant */ 16705 net.user1.orbiter.UPC.CLIENTCOUNT_SNAPSHOT = "u34"; 16706 /** @constant */ 16707 net.user1.orbiter.UPC.CLIENT_ADDED_TO_ROOM = "u36"; 16708 /** @constant */ 16709 net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_ROOM = "u37"; 16710 /** @constant */ 16711 net.user1.orbiter.UPC.ROOMLIST_SNAPSHOT = "u38"; 16712 /** @constant */ 16713 net.user1.orbiter.UPC.ROOM_ADDED = "u39"; 16714 /** @constant */ 16715 net.user1.orbiter.UPC.ROOM_REMOVED = "u40"; 16716 /** @constant */ 16717 net.user1.orbiter.UPC.WATCH_FOR_ROOMS_RESULT = "u42"; 16718 /** @constant */ 16719 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS_RESULT = "u43"; 16720 /** @constant */ 16721 net.user1.orbiter.UPC.LEFT_ROOM = "u44"; 16722 /** @constant */ 16723 net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD_RESULT = "u46"; 16724 /** @constant */ 16725 net.user1.orbiter.UPC.CREATE_ACCOUNT_RESULT = "u47"; 16726 /** @constant */ 16727 net.user1.orbiter.UPC.REMOVE_ACCOUNT_RESULT = "u48"; 16728 /** @constant */ 16729 net.user1.orbiter.UPC.LOGIN_RESULT = "u49"; 16730 /** @constant */ 16731 net.user1.orbiter.UPC.SERVER_TIME_UPDATE = "u50"; 16732 /** @constant */ 16733 net.user1.orbiter.UPC.ROOM_SNAPSHOT = "u54"; 16734 /** @constant */ 16735 net.user1.orbiter.UPC.OBSERVED_ROOM = "u59"; 16736 /** @constant */ 16737 net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT_RESULT = "u60"; 16738 /** @constant */ 16739 net.user1.orbiter.UPC.STOPPED_OBSERVING_ROOM = "u62"; 16740 /** @constant */ 16741 net.user1.orbiter.UPC.CLIENT_READY = "u63"; 16742 /** @constant */ 16743 net.user1.orbiter.UPC.SERVER_HELLO = "u66"; 16744 /** @constant */ 16745 net.user1.orbiter.UPC.JOIN_ROOM_RESULT = "u72"; 16746 /** @constant */ 16747 net.user1.orbiter.UPC.SET_CLIENT_ATTR_RESULT = "u73"; 16748 /** @constant */ 16749 net.user1.orbiter.UPC.SET_ROOM_ATTR_RESULT = "u74"; 16750 /** @constant */ 16751 net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT_RESULT = "u75"; 16752 /** @constant */ 16753 net.user1.orbiter.UPC.LEAVE_ROOM_RESULT = "u76"; 16754 /** @constant */ 16755 net.user1.orbiter.UPC.OBSERVE_ROOM_RESULT = "u77"; 16756 /** @constant */ 16757 net.user1.orbiter.UPC.STOP_OBSERVING_ROOM_RESULT = "u78"; 16758 /** @constant */ 16759 net.user1.orbiter.UPC.ROOM_ATTR_REMOVED = "u79"; 16760 /** @constant */ 16761 net.user1.orbiter.UPC.REMOVE_ROOM_ATTR_RESULT = "u80"; 16762 /** @constant */ 16763 net.user1.orbiter.UPC.CLIENT_ATTR_REMOVED = "u81"; 16764 /** @constant */ 16765 net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR_RESULT = "u82"; 16766 /** @constant */ 16767 net.user1.orbiter.UPC.SESSION_TERMINATED = "u84"; 16768 /** @constant */ 16769 net.user1.orbiter.UPC.SESSION_NOT_FOUND = "u85"; 16770 /** @constant */ 16771 net.user1.orbiter.UPC.LOGOFF_RESULT = "u87"; 16772 /** @constant */ 16773 net.user1.orbiter.UPC.LOGGED_IN = "u88"; 16774 /** @constant */ 16775 net.user1.orbiter.UPC.LOGGED_OFF = "u89"; 16776 /** @constant */ 16777 net.user1.orbiter.UPC.ACCOUNT_PASSWORD_CHANGED = "u90"; 16778 /** @constant */ 16779 net.user1.orbiter.UPC.CLIENTLIST_SNAPSHOT = "u101"; 16780 /** @constant */ 16781 net.user1.orbiter.UPC.CLIENT_ADDED_TO_SERVER = "u102"; 16782 /** @constant */ 16783 net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_SERVER = "u103"; 16784 /** @constant */ 16785 net.user1.orbiter.UPC.CLIENT_SNAPSHOT = "u104"; 16786 /** @constant */ 16787 net.user1.orbiter.UPC.OBSERVE_CLIENT_RESULT = "u105"; 16788 /** @constant */ 16789 net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT_RESULT = "u106"; 16790 /** @constant */ 16791 net.user1.orbiter.UPC.WATCH_FOR_CLIENTS_RESULT = "u107"; 16792 /** @constant */ 16793 net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS_RESULT = "u108"; 16794 /** @constant */ 16795 net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS_RESULT = "u109"; 16796 /** @constant */ 16797 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS_RESULT = "u110"; 16798 /** @constant */ 16799 net.user1.orbiter.UPC.ACCOUNT_ADDED = "u111"; 16800 /** @constant */ 16801 net.user1.orbiter.UPC.ACCOUNT_REMOVED = "u112"; 16802 /** @constant */ 16803 net.user1.orbiter.UPC.JOINED_ROOM_ADDED_TO_CLIENT = "u113"; 16804 /** @constant */ 16805 net.user1.orbiter.UPC.JOINED_ROOM_REMOVED_FROM_CLIENT = "u114"; 16806 /** @constant */ 16807 net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT_RESULT = "u115"; 16808 /** @constant */ 16809 net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT_RESULT = "u116"; 16810 /** @constant */ 16811 net.user1.orbiter.UPC.OBSERVED_ROOM_ADDED_TO_CLIENT = "u117"; 16812 /** @constant */ 16813 net.user1.orbiter.UPC.OBSERVED_ROOM_REMOVED_FROM_CLIENT = "u118"; 16814 /** @constant */ 16815 net.user1.orbiter.UPC.CLIENT_OBSERVED = "u119"; 16816 /** @constant */ 16817 net.user1.orbiter.UPC.STOPPED_OBSERVING_CLIENT = "u120"; 16818 /** @constant */ 16819 net.user1.orbiter.UPC.OBSERVE_ACCOUNT_RESULT = "u123"; 16820 /** @constant */ 16821 net.user1.orbiter.UPC.ACCOUNT_OBSERVED = "u124"; 16822 /** @constant */ 16823 net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT_RESULT = "u125"; 16824 /** @constant */ 16825 net.user1.orbiter.UPC.STOPPED_OBSERVING_ACCOUNT = "u126"; 16826 /** @constant */ 16827 net.user1.orbiter.UPC.ACCOUNT_LIST_UPDATE = "u127"; 16828 /** @constant */ 16829 net.user1.orbiter.UPC.UPDATE_LEVELS_UPDATE = "u128"; 16830 /** @constant */ 16831 net.user1.orbiter.UPC.CLIENT_OBSERVED_ROOM = "u129"; 16832 /** @constant */ 16833 net.user1.orbiter.UPC.CLIENT_STOPPED_OBSERVING_ROOM = "u130"; 16834 /** @constant */ 16835 net.user1.orbiter.UPC.ROOM_OCCUPANTCOUNT_UPDATE = "u131"; 16836 /** @constant */ 16837 net.user1.orbiter.UPC.ROOM_OBSERVERCOUNT_UPDATE = "u132"; 16838 /** @constant */ 16839 net.user1.orbiter.UPC.ADD_ROLE_RESULT = "u134"; 16840 /** @constant */ 16841 net.user1.orbiter.UPC.REMOVE_ROLE_RESULT = "u136"; 16842 /** @constant */ 16843 net.user1.orbiter.UPC.BAN_RESULT = "u138"; 16844 /** @constant */ 16845 net.user1.orbiter.UPC.UNBAN_RESULT = "u140"; 16846 /** @constant */ 16847 net.user1.orbiter.UPC.BANNED_LIST_SNAPSHOT = "u142"; 16848 /** @constant */ 16849 net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES_RESULT = "u144"; 16850 /** @constant */ 16851 net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT = "u146"; 16852 /** @constant */ 16853 net.user1.orbiter.UPC.BANNED_ADDRESS_ADDED = "u147"; 16854 /** @constant */ 16855 net.user1.orbiter.UPC.BANNED_ADDRESS_REMOVED = "u148"; 16856 /** @constant */ 16857 net.user1.orbiter.UPC.KICK_CLIENT_RESULT = "u150"; 16858 /** @constant */ 16859 net.user1.orbiter.UPC.SERVERMODULELIST_SNAPSHOT = "u152"; 16860 /** @constant */ 16861 net.user1.orbiter.UPC.GET_UPC_STATS_SNAPSHOT_RESULT = "u155"; 16862 /** @constant */ 16863 net.user1.orbiter.UPC.UPC_STATS_SNAPSHOT = "u156"; 16864 /** @constant */ 16865 net.user1.orbiter.UPC.RESET_UPC_STATS_RESULT = "u158"; 16866 /** @constant */ 16867 net.user1.orbiter.UPC.WATCH_FOR_PROCESSED_UPCS_RESULT = "u160"; 16868 /** @constant */ 16869 net.user1.orbiter.UPC.PROCESSED_UPC_ADDED = "u161"; 16870 /** @constant */ 16871 net.user1.orbiter.UPC.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT = "u163"; 16872 /** @constant */ 16873 net.user1.orbiter.UPC.CONNECTION_REFUSED = "u164"; 16874 /** @constant */ 16875 net.user1.orbiter.UPC.NODELIST_SNAPSHOT = "u166"; 16876 /** @constant */ 16877 net.user1.orbiter.UPC.GATEWAYS_SNAPSHOT = "u168"; 16878 //============================================================================== 16879 // LOADED FLAG 16880 //============================================================================== 16881 /** 16882 * @constant 16883 * 16884 * Indicates that Orbiter has finished loading. 16885 */ 16886 net.user1.orbiter.LOADED = true; 16887 16888 })((typeof window == "undefined") ? this : window); 16889