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,19); 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 /** @constant */ 1073 net.user1.orbiter.ConnectionManagerEvent.SESSION_TERMINATED = "SESSION_TERMINATED"; 1074 1075 //============================================================================== 1076 // INSTANCE METHODS 1077 //============================================================================== 1078 1079 net.user1.orbiter.ConnectionManagerEvent.prototype.getConnection = function () { 1080 return this.connection; 1081 } 1082 1083 net.user1.orbiter.ConnectionManagerEvent.prototype.getStatus = function () { 1084 return this.status; 1085 } 1086 1087 net.user1.orbiter.ConnectionManagerEvent.prototype.toString = function () { 1088 return "[object ConnectionManagerEvent]"; 1089 } 1090 1091 //============================================================================== 1092 // CLASS DECLARATION 1093 //============================================================================== 1094 /** @class 1095 1096 The ConnectionManager class dispatches the following events: 1097 1098 <ul class="summary"> 1099 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.BEGIN_CONNECT}</li> 1100 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION}</li> 1101 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE}</li> 1102 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.DISCONNECT}</li> 1103 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT}</li> 1104 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT}</li> 1105 <li class="fixedFont">{@link net.user1.orbiter.ConnectionManagerEvent.READY}</li> 1106 </ul> 1107 1108 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 1109 1110 @extends net.user1.events.EventDispatcher 1111 1112 * @see net.user1.orbiter.Orbiter#connect 1113 */ 1114 net.user1.orbiter.ConnectionManager = function (orbiter) { 1115 // Call superconstructor 1116 net.user1.events.EventDispatcher.call(this); 1117 1118 // Variables 1119 this.orbiter = orbiter; 1120 this.connectAttemptCount = 0; 1121 this.connectAbortCount = 0; 1122 this.readyCount = 0; 1123 this.connectFailedCount = 0; 1124 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1125 this.readyTimeout = 0; 1126 this.connections = new Array(); 1127 this.activeConnection = null; 1128 this.inProgressConnection = null; 1129 this.currentConnectionIndex = 0; 1130 this.attemptedConnections = null; 1131 this.setReadyTimeout(net.user1.orbiter.ConnectionManager.DEFAULT_READY_TIMEOUT); 1132 1133 // Initialization 1134 // Make all Orbiter instances in this VM share the same server affinity 1135 this.setGlobalAffinity(true); 1136 }; 1137 1138 //============================================================================== 1139 // INHERITANCE 1140 //============================================================================== 1141 net.user1.utils.extend(net.user1.orbiter.ConnectionManager, net.user1.events.EventDispatcher); 1142 1143 //============================================================================== 1144 // STATIC VARIABLES 1145 //============================================================================== 1146 net.user1.orbiter.ConnectionManager.DEFAULT_READY_TIMEOUT = 10000; 1147 1148 // ============================================================================= 1149 // CONNECT AND DISCONNECT 1150 // ============================================================================= 1151 net.user1.orbiter.ConnectionManager.prototype.connect = function () { 1152 if (this.connections.length == 0) { 1153 this.orbiter.getLog().error("[CONNECTION_MANAGER] No connections defined. Connection request ignored."); 1154 return; 1155 } 1156 1157 this.connectAttemptCount++; 1158 this.attemptedConnections = new Array(); 1159 1160 switch (this.connectionState) { 1161 case net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS: 1162 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection attempt already in " 1163 + "progress. Existing attempt must be aborted before" 1164 + " new connection attempt begins..."); 1165 this.disconnect(); 1166 break; 1167 1168 case net.user1.orbiter.ConnectionState.READY: 1169 this.orbiter.getLog().info("[CONNECTION_MANAGER] Existing connection to Union" 1170 + " must be disconnected before new connection" 1171 + " attempt begins."); 1172 this.disconnect(); 1173 break; 1174 } 1175 this.setConnectionState(net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS); 1176 1177 this.orbiter.getLog().debug("[CONNECTION_MANAGER] Searching for most recent valid connection."); 1178 var originalConnectionIndex = this.currentConnectionIndex; 1179 while (!this.getCurrentConnection().isValid()) { 1180 this.advance(); 1181 if (this.currentConnectionIndex == originalConnectionIndex) { 1182 // Couldn't find a valid connection, so start the connection with 1183 // the first connection in the connection list 1184 this.orbiter.getLog().debug("[CONNECTION_MANAGER] No valid connection found. Starting connection attempt with first connection."); 1185 this.currentConnectionIndex = 0; 1186 break; 1187 } 1188 } 1189 1190 this.dispatchBeginConnect(); 1191 this.connectCurrentConnection(); 1192 }; 1193 1194 net.user1.orbiter.ConnectionManager.prototype.disconnect = function () { 1195 if (this.connections.length == 0) { 1196 this.dispatchConnectFailure("No connections defined. Disconnection attempt failed."); 1197 return; 1198 } 1199 1200 switch (this.connectionState) { 1201 // Currently connected 1202 case net.user1.orbiter.ConnectionState.READY: 1203 this.orbiter.getLog().info("[CONNECTION_MANAGER] Closing existing connection: " 1204 + this.getActiveConnection().toString()); 1205 this.setConnectionState(net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS); 1206 this.disconnectConnection(this.getActiveConnection()); 1207 break; 1208 1209 // Currently attempting to connect 1210 case net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS: 1211 this.orbiter.getLog().info("[CONNECTION_MANAGER] Aborting existing connection attempt: " 1212 + this.getInProgressConnection().toString()); 1213 this.connectAbortCount++; 1214 this.setConnectionState(net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS); 1215 this.disconnectConnection(this.getInProgressConnection()); 1216 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection abort complete."); 1217 break; 1218 1219 // Currently attempting to disconnect 1220 case net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS: 1221 this.orbiter.getLog().info("[CONNECTION_MANAGER] Disconnection request ignored." 1222 + " Already disconnecting."); 1223 break; 1224 } 1225 }; 1226 1227 /** @private */ 1228 net.user1.orbiter.ConnectionManager.prototype.disconnectConnection = function (connection) { 1229 connection.disconnect(); 1230 }; 1231 1232 /** @private */ 1233 net.user1.orbiter.ConnectionManager.prototype.connectCurrentConnection = function () { 1234 // If there are no Connections defined, fail immediately 1235 if (this.connections.length == 0) { 1236 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1237 this.connectFailedCount++; 1238 this.dispatchConnectFailure("No connections defined. Connection attempt failed."); 1239 return; 1240 } 1241 1242 this.inProgressConnection = this.getCurrentConnection(); 1243 1244 // If the requested connection has already been attempted this round, 1245 // ignore it. 1246 if (net.user1.utils.ArrayUtil.indexOf(this.attemptedConnections, this.inProgressConnection) != -1) { 1247 this.advanceAndConnect(); 1248 return; 1249 } 1250 1251 this.dispatchSelectConnection(this.inProgressConnection); 1252 this.orbiter.getLog().info("[CONNECTION_MANAGER] Attempting connection via " 1253 + this.inProgressConnection.toString() + ". (Connection " 1254 + (this.attemptedConnections.length+1) + " of " 1255 + this.connections.length + ". Attempt " + this.connectAttemptCount +" since last successful connection)."); 1256 this.addConnectionListeners(this.inProgressConnection); 1257 this.inProgressConnection.connect(); 1258 }; 1259 1260 /** @private */ 1261 net.user1.orbiter.ConnectionManager.prototype.advanceAndConnect = function () { 1262 if (!this.connectAttemptComplete()) { 1263 this.advance(); 1264 this.connectCurrentConnection(); 1265 } else { 1266 // Tried all connections, so give up and dispatch CONNECT_FAILURE 1267 this.connectFailedCount++; 1268 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1269 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection failed for all specified hosts and ports."); 1270 this.dispatchConnectFailure("Connection failed for all specified hosts and ports."); 1271 } 1272 }; 1273 1274 /** @private */ 1275 net.user1.orbiter.ConnectionManager.prototype.connectAttemptComplete = function () { 1276 return this.attemptedConnections.length == this.connections.length; 1277 }; 1278 1279 /** @private */ 1280 net.user1.orbiter.ConnectionManager.prototype.advance = function () { 1281 this.currentConnectionIndex++; 1282 if (this.currentConnectionIndex == this.connections.length) { 1283 this.currentConnectionIndex = 0; 1284 } 1285 }; 1286 1287 // ============================================================================= 1288 // CONNECTION OBJECT MANAGEMENT 1289 // ============================================================================= 1290 net.user1.orbiter.ConnectionManager.prototype.addConnection = function (connection) { 1291 if (connection != null) { 1292 this.orbiter.getLog().info("[CONNECTION_MANAGER] New connection added. " 1293 + connection.toString() + "."); 1294 connection.setOrbiter(this.orbiter); 1295 this.connections.push(connection); 1296 } 1297 }; 1298 1299 net.user1.orbiter.ConnectionManager.prototype.removeConnection = function (connection) { 1300 if (connection != null) { 1301 connection.disconnect(); 1302 this.removeConnectionListeners(connection); 1303 return net.user1.utils.ArrayUtil.remove(this.connections, connection); 1304 } else { 1305 return false; 1306 } 1307 }; 1308 1309 net.user1.orbiter.ConnectionManager.prototype.removeAllConnections = function () { 1310 if (this.connections.length == 0) { 1311 this.orbiter.getLog().info("[CONNECTION_MANAGER] removeAllConnections() ignored. " + 1312 " No connections to remove."); 1313 return; 1314 } 1315 1316 this.orbiter.getLog().info("[CONNECTION_MANAGER] Removing all connections..."); 1317 this.disconnect(); 1318 while (this.connections.length > 0) { 1319 this.removeConnection(this.connections[0]); 1320 } 1321 this.currentConnectionIndex = 0; 1322 this.orbiter.getLog().info("[CONNECTION_MANAGER] All connections removed."); 1323 }; 1324 1325 // ============================================================================= 1326 // CONNECTION ACCESS 1327 // ============================================================================= 1328 net.user1.orbiter.ConnectionManager.prototype.getActiveConnection = function () { 1329 return this.activeConnection; 1330 }; 1331 1332 net.user1.orbiter.ConnectionManager.prototype.getInProgressConnection = function () { 1333 return this.inProgressConnection; 1334 }; 1335 1336 net.user1.orbiter.ConnectionManager.prototype.getConnections = function () { 1337 return this.connections.slice(); 1338 }; 1339 1340 /** @private */ 1341 net.user1.orbiter.ConnectionManager.prototype.getCurrentConnection = function () { 1342 return this.connections[this.currentConnectionIndex]; 1343 }; 1344 1345 // ============================================================================= 1346 // CONNECTION LISTENER REGISTRATION 1347 // ============================================================================= 1348 /** @private */ 1349 net.user1.orbiter.ConnectionManager.prototype.addConnectionListeners = function(connection) { 1350 if (connection != null) { 1351 connection.addEventListener(net.user1.orbiter.ConnectionEvent.READY, this.readyListener, this); 1352 connection.addEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, this.connectFailureListener, this); 1353 connection.addEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, this.disconnectListener, this); 1354 connection.addEventListener(net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT, this.clientKillConnectListener, this); 1355 connection.addEventListener(net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT, this.serverKillConnectListener, this); 1356 } 1357 }; 1358 1359 /** @private */ 1360 net.user1.orbiter.ConnectionManager.prototype.removeConnectionListeners = function (connection) { 1361 if (connection != null) { 1362 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.READY, this.readyListener, this); 1363 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, this.connectFailureListener, this); 1364 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, this.disconnectListener, this); 1365 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT, this.clientKillConnectListener, this); 1366 connection.removeEventListener(net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT, this.serverKillConnectListener, this); 1367 } 1368 }; 1369 1370 // ============================================================================= 1371 // CONNECTION STATE ACCESS 1372 // ============================================================================= 1373 net.user1.orbiter.ConnectionManager.prototype.isReady = function () { 1374 return this.connectionState == net.user1.orbiter.ConnectionState.READY; 1375 } 1376 1377 net.user1.orbiter.ConnectionManager.prototype.setConnectionState = function (state) { 1378 var changed = false; 1379 if (state != this.connectionState) { 1380 changed = true; 1381 } 1382 this.connectionState = state; 1383 if (changed) { 1384 this.dispatchConnectionStateChange(); 1385 } 1386 }; 1387 1388 net.user1.orbiter.ConnectionManager.prototype.getConnectionState = function () { 1389 return this.connectionState; 1390 }; 1391 1392 // ============================================================================= 1393 // CONNECTION COUNT MANAGEMENT 1394 // ============================================================================= 1395 net.user1.orbiter.ConnectionManager.prototype.getReadyCount = function () { 1396 return this.readyCount; 1397 }; 1398 1399 net.user1.orbiter.ConnectionManager.prototype.getConnectFailedCount = function () { 1400 return this.connectFailedCount; 1401 }; 1402 1403 net.user1.orbiter.ConnectionManager.prototype.getConnectAttemptCount = function () { 1404 return this.connectAttemptCount; 1405 }; 1406 1407 net.user1.orbiter.ConnectionManager.prototype.getConnectAbortCount = function () { 1408 return this.connectAbortCount; 1409 }; 1410 1411 // ============================================================================= 1412 // CURRENT CONNECTION LISTENERS 1413 // ============================================================================= 1414 /** @private */ 1415 net.user1.orbiter.ConnectionManager.prototype.readyListener = function (e) { 1416 this.setConnectionState(net.user1.orbiter.ConnectionState.READY); 1417 this.inProgressConnection = null; 1418 this.activeConnection = e.target; 1419 this.readyCount++; 1420 this.connectFailedCount = 0; 1421 this.connectAttemptCount = 0; 1422 this.connectAbortCount = 0; 1423 this.dispatchReady(); 1424 }; 1425 1426 /** @private */ 1427 net.user1.orbiter.ConnectionManager.prototype.connectFailureListener = function (e) { 1428 var failedConnection = e.target; 1429 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Connection failed for " 1430 + failedConnection.toString() 1431 + ". Status: [" + e.getStatus() + "]"); 1432 1433 this.removeConnectionListeners(failedConnection); 1434 this.inProgressConnection = null; 1435 1436 if (this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 1437 this.dispatchConnectFailure("Connection closed by client."); 1438 } else { 1439 if (failedConnection.getHost() != failedConnection.getRequestedHost()) { 1440 this.orbiter.getLog().info("[CONNECTION_MANAGER] Connection failed for affinity address [" + failedConnection.getHost() + "]. Removing affinity."); 1441 this.clearAffinity(failedConnection.getRequestedHost()); 1442 } 1443 1444 this.attemptedConnections.push(failedConnection); 1445 this.advanceAndConnect(); 1446 } 1447 }; 1448 1449 /** @private */ 1450 net.user1.orbiter.ConnectionManager.prototype.disconnectListener = function (e) { 1451 this.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 1452 this.removeConnectionListeners(e.target); 1453 this.activeConnection = null; 1454 this.dispatchDisconnect(e.target); 1455 }; 1456 1457 /** @private */ 1458 net.user1.orbiter.ConnectionManager.prototype.clientKillConnectListener = function (e) { 1459 this.dispatchClientKillConnect(e.target); 1460 // This event is always followed by a DISCONNECT event 1461 }; 1462 1463 /** @private */ 1464 net.user1.orbiter.ConnectionManager.prototype.serverKillConnectListener = function (e) { 1465 this.dispatchServerKillConnect(e.target); 1466 // This event is always followed by a DISCONNECT event 1467 }; 1468 1469 // ============================================================================= 1470 // READY TIMEOUT MANAGEMENT 1471 // ============================================================================= 1472 1473 net.user1.orbiter.ConnectionManager.prototype.setReadyTimeout = function (milliseconds) { 1474 if (milliseconds > 0) { 1475 this.readyTimeout = milliseconds; 1476 this.orbiter.getLog().info("[CONNECTION_MANAGER] Ready timeout set to " + milliseconds + " ms."); 1477 if (milliseconds < 3000) { 1478 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Current ready timeout (" 1479 + milliseconds + ") may not allow sufficient time" 1480 + " to connect to Union Server over a typical" 1481 + " internet connection."); 1482 } 1483 } else { 1484 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Invalid ready timeout specified: " 1485 + milliseconds + ". Duration must be greater than zero."); 1486 } 1487 }; 1488 1489 net.user1.orbiter.ConnectionManager.prototype.getReadyTimeout = function () { 1490 return this.readyTimeout; 1491 }; 1492 1493 // ============================================================================= 1494 // SERVER AFFINITY 1495 // ============================================================================= 1496 net.user1.orbiter.ConnectionManager.prototype.getAffinity = function (host) { 1497 var address = this.affinityData.read("affinity", host+"address"); 1498 var until = parseFloat(this.affinityData.read("affinity", host+"until")); 1499 1500 if (address != null) { 1501 var now = new Date().getTime(); 1502 if (now >= until) { 1503 this.orbiter.getLog().warn("[CONNECTION_MANAGER] Affinity duration expired for address [" 1504 + address + "], host [" + host + "]. Removing affinity."); 1505 this.clearAffinity(host); 1506 } else { 1507 return address; 1508 } 1509 } 1510 1511 return host; 1512 }; 1513 1514 /** 1515 * @private 1516 */ 1517 net.user1.orbiter.ConnectionManager.prototype.setAffinity = function (host, address, duration) { 1518 var until = new Date().getTime() + (duration*60*1000); 1519 // Don't use JSON stringify for affinity values because not all JavaScript 1520 // environments support JSON natively (e.g., non-browser VMs) 1521 this.affinityData.write("affinity", host+"address", address); 1522 this.affinityData.write("affinity", host+"until", until); 1523 1524 this.orbiter.getLog().info("[CONNECTION_MANAGER] Assigning affinity address [" 1525 + address + "] for supplied host [" +host + "]. Duration (minutes): " 1526 + duration); 1527 }; 1528 1529 /** 1530 * @private 1531 */ 1532 net.user1.orbiter.ConnectionManager.prototype.clearAffinity = function (host) { 1533 this.affinityData.remove("affinity", host+"address"); 1534 this.affinityData.remove("affinity", host+"until"); 1535 }; 1536 1537 net.user1.orbiter.ConnectionManager.prototype.setGlobalAffinity = function (enabled) { 1538 if (enabled) { 1539 this.orbiter.getLog().info("[CONNECTION_MANAGER] Global server affinity selected." 1540 + " Using current environment's shared server affinity."); 1541 this.affinityData = net.user1.utils.LocalData; 1542 } else { 1543 this.orbiter.getLog().info("[CONNECTION_MANAGER] Local server affinity selected." 1544 + " The current client will maintain its own, individual server affinity."); 1545 this.affinityData = new net.user1.utils.MemoryStore(); 1546 } 1547 }; 1548 1549 // ============================================================================= 1550 // EVENT DISPATCHING 1551 // ============================================================================= 1552 1553 /** @private */ 1554 net.user1.orbiter.ConnectionManager.prototype.dispatchBeginConnect = function () { 1555 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.BEGIN_CONNECT)); 1556 }; 1557 1558 /** @private */ 1559 net.user1.orbiter.ConnectionManager.prototype.dispatchSelectConnection = function (connection) { 1560 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 1561 connection)); 1562 }; 1563 1564 /** @private */ 1565 net.user1.orbiter.ConnectionManager.prototype.dispatchConnectFailure = function (status) { 1566 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE, 1567 null, status)); 1568 }; 1569 1570 /** @private */ 1571 net.user1.orbiter.ConnectionManager.prototype.dispatchDisconnect = function (connection) { 1572 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.DISCONNECT, 1573 connection)); 1574 }; 1575 1576 /** @private */ 1577 net.user1.orbiter.ConnectionManager.prototype.dispatchServerKillConnect = function (connection) { 1578 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT, 1579 connection)); 1580 }; 1581 1582 /** @private */ 1583 net.user1.orbiter.ConnectionManager.prototype.dispatchClientKillConnect = function (connection) { 1584 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT, 1585 connection)); 1586 }; 1587 1588 /** @private */ 1589 net.user1.orbiter.ConnectionManager.prototype.dispatchReady = function () { 1590 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.READY)); 1591 }; 1592 1593 /** @private */ 1594 net.user1.orbiter.ConnectionManager.prototype.dispatchConnectionStateChange = function () { 1595 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.CONNECTION_STATE_CHANGE)); 1596 }; 1597 1598 /** @private */ 1599 net.user1.orbiter.ConnectionManager.prototype.dispatchSessionTerminated = function () { 1600 this.dispatchEvent(new net.user1.orbiter.ConnectionManagerEvent(net.user1.orbiter.ConnectionManagerEvent.SESSION_TERMINATED)); 1601 }; 1602 1603 // ============================================================================= 1604 // DISPOSAL 1605 // ============================================================================= 1606 net.user1.orbiter.ConnectionManager.prototype.dispose = function () { 1607 this.removeAllConnections(); 1608 this.attemptedConnections = null; 1609 this.activeConnection = null; 1610 this.inProgressConnection = null; 1611 this.connections = null; 1612 }; 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 //============================================================================== 1636 // CLASS DECLARATION 1637 //============================================================================== 1638 /** @class */ 1639 net.user1.orbiter.ConnectionMonitor = function (orbiter) { 1640 // Instance variables 1641 this.connectionTimeout = 0; 1642 this.heartbeatIntervalID = -1; 1643 this.heartbeatCounter = 0; 1644 this.heartbeatEnabled = true; 1645 this.heartbeats = new net.user1.utils.UDictionary(); 1646 1647 this.oldestHeartbeat = 0; 1648 this.heartBeatFrequency = -1; 1649 1650 this.sharedPing = false; 1651 1652 this.autoReconnectMinMS = 0; 1653 this.autoReconnectMaxMS = 0; 1654 this.autoReconnectFrequency = -1; 1655 this.autoReconnectDelayFirstAttempt = false; 1656 this.autoReconnectTimeoutID = -1; 1657 this.autoReconnectAttemptLimit = -1; 1658 1659 this.orbiter = orbiter; 1660 this.msgManager = orbiter.getMessageManager(); 1661 this.log = orbiter.getLog(); 1662 1663 this.disposed = false; 1664 1665 // Initialization 1666 this.orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, this.connectReadyListener, this); 1667 this.orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.CLOSE, this.connectCloseListener, this); 1668 this.disableHeartbeatLogging(); 1669 }; 1670 1671 //============================================================================== 1672 // STATIC VARIABLES 1673 //============================================================================== 1674 net.user1.orbiter.ConnectionMonitor.DEFAULT_HEARTBEAT_FREQUENCY = 10000; 1675 net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY = 20; 1676 net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_FREQUENCY = -1; 1677 net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_ATTEMPT_LIMIT = -1; 1678 net.user1.orbiter.ConnectionMonitor.DEFAULT_CONNECTION_TIMEOUT = 60000; 1679 1680 //============================================================================== 1681 // CONNECTION MONITORING 1682 //============================================================================== 1683 /** @private */ 1684 net.user1.orbiter.ConnectionMonitor.prototype.connectReadyListener = function (e) { 1685 this.msgManager.addMessageListener(net.user1.orbiter.Messages.CLIENT_HEARTBEAT, this.heartbeatMessageListener, this); 1686 this.startHeartbeat(); 1687 this.stopReconnect(); 1688 } 1689 1690 /** @private */ 1691 net.user1.orbiter.ConnectionMonitor.prototype.connectCloseListener = function (e) { 1692 this.stopHeartbeat(); 1693 1694 var numAttempts = this.orbiter.getConnectionManager().getConnectAttemptCount(); 1695 if (numAttempts == 0) { 1696 this.selectReconnectFrequency(); 1697 } 1698 1699 if (this.autoReconnectFrequency > -1) { 1700 if (this.autoReconnectTimeoutID != -1) { 1701 return; 1702 } else { 1703 // Defer reconnection until after all other listeners have processed the 1704 // CLOSE event 1705 var self = this; 1706 setTimeout(function () { 1707 // If another listener disposed of Orbiter, or disabled autoreconnect, quit 1708 if (!self.disposed && self.autoReconnectFrequency != -1) { 1709 self.log.warn("[CONNECTION_MONITOR] Disconnection detected."); 1710 if (self.autoReconnectDelayFirstAttempt 1711 && ( 1712 (numAttempts == 0) 1713 || 1714 (numAttempts == 1 && self.orbiter.getConnectionManager().getReadyCount() == 0) 1715 ) 1716 ) { 1717 self.log.info("[CONNECTION_MONITOR] Delaying reconnection attempt" 1718 + " by " + self.autoReconnectFrequency + " ms..."); 1719 self.scheduleReconnect(self.autoReconnectFrequency); 1720 } else { 1721 self.doReconnect(); 1722 } 1723 } 1724 }, 1); 1725 } 1726 } 1727 } 1728 1729 //============================================================================== 1730 // HEARTBEAT 1731 //============================================================================== 1732 1733 net.user1.orbiter.ConnectionMonitor.prototype.enableHeartbeat = function () { 1734 this.log.info("[CONNECTION_MONITOR] Heartbeat enabled."); 1735 this.heartbeatEnabled = true; 1736 this.startHeartbeat(); 1737 } 1738 1739 net.user1.orbiter.ConnectionMonitor.prototype.disableHeartbeat = function () { 1740 this.log.info("[CONNECTION_MONITOR] Heartbeat disabled."); 1741 this.heartbeatEnabled = false; 1742 this.stopHeartbeat(); 1743 } 1744 1745 /** @private */ 1746 net.user1.orbiter.ConnectionMonitor.prototype.startHeartbeat = function () { 1747 if (!this.heartbeatEnabled) { 1748 this.log.info("[CONNECTION_MONITOR] Heartbeat is currently disabled. Ignoring start request."); 1749 return; 1750 } 1751 1752 this.stopHeartbeat(); 1753 1754 this.heartbeats = new net.user1.utils.UDictionary(); 1755 1756 var currentObj = this; 1757 var callback = this.heartbeatTimerListener; 1758 this.heartbeatIntervalID = setInterval(function () { 1759 callback.call(currentObj); 1760 }, this.heartBeatFrequency); 1761 1762 } 1763 1764 /** @private */ 1765 net.user1.orbiter.ConnectionMonitor.prototype.stopHeartbeat = function () { 1766 clearInterval(this.heartbeatIntervalID); 1767 this.heartbeats = null; 1768 } 1769 1770 /** @private */ 1771 net.user1.orbiter.ConnectionMonitor.prototype.heartbeatTimerListener = function () { 1772 if (!this.orbiter.isReady()) { 1773 this.log.info("[CONNECTION_MONITOR] Orbiter is not connected. Stopping heartbeat."); 1774 this.stopHeartbeat(); 1775 return; 1776 } 1777 1778 var timeSinceOldestHeartbeat; 1779 var now = new Date().getTime(); 1780 1781 this.heartbeats[this.heartbeatCounter] = now; 1782 this.orbiter.getMessageManager().sendUPC("u2", 1783 net.user1.orbiter.Messages.CLIENT_HEARTBEAT, 1784 this.orbiter.getClientID(), 1785 "", 1786 this.heartbeatCounter); 1787 this.heartbeatCounter++; 1788 1789 // Assign the oldest heartbeat 1790 if (net.user1.utils.ObjectUtil.length(this.heartbeats) == 1) { 1791 this.oldestHeartbeat = now; 1792 } else { 1793 this.oldestHeartbeat = Number.MAX_VALUE; 1794 for (var p in this.heartbeats) { 1795 if (this.heartbeats[p] < this.oldestHeartbeat) { 1796 this.oldestHeartbeat = this.heartbeats[p]; 1797 } 1798 } 1799 } 1800 // Close connection if too much time has passed since the last response 1801 timeSinceOldestHeartbeat = now - this.oldestHeartbeat; 1802 if (timeSinceOldestHeartbeat > this.connectionTimeout) { 1803 this.log.warn("[CONNECTION_MONITOR] No response from server in " + 1804 timeSinceOldestHeartbeat + "ms. Starting automatic disconnect."); 1805 this.orbiter.disconnect(); 1806 } 1807 } 1808 1809 /** @private */ 1810 net.user1.orbiter.ConnectionMonitor.prototype.heartbeatMessageListener = function (fromClientID, id) { 1811 var ping = new Date().getTime() - this.heartbeats[parseInt(id)]; 1812 if (typeof this.orbiter.self().setAttribute === "undefined") { 1813 // OrbiterMicro 1814 this.orbiter.self().ping = ping; 1815 this.orbiter.getMessageManager().sendUPC("u3", 1816 this.orbiter.getClientID(), 1817 "", 1818 "_PING", 1819 ping.toString(), 1820 "", 1821 this.sharedPing ? "4" : "0"); 1822 } else { 1823 // Orbiter 1824 this.orbiter.self().setAttribute("_PING", 1825 ping.toString(), 1826 null, 1827 this.sharedPing); 1828 } 1829 delete this.heartbeats[parseInt(id)]; 1830 } 1831 1832 //============================================================================== 1833 // RECONNECTION 1834 //============================================================================== 1835 /** @private */ 1836 net.user1.orbiter.ConnectionMonitor.prototype.reconnectTimerListener = function (e) { 1837 this.stopReconnect(); 1838 if (this.orbiter.getConnectionManager().connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED) { 1839 this.doReconnect(); 1840 } 1841 } 1842 1843 /** @private */ 1844 net.user1.orbiter.ConnectionMonitor.prototype.stopReconnect = function () { 1845 clearTimeout(this.autoReconnectTimeoutID); 1846 this.autoReconnectTimeoutID = -1 1847 } 1848 1849 /** @private */ 1850 net.user1.orbiter.ConnectionMonitor.prototype.scheduleReconnect = function (milliseconds) { 1851 // Reset the timer 1852 this.stopReconnect(); 1853 var currentObj = this; 1854 var callback = this.reconnectTimerListener; 1855 this.autoReconnectTimeoutID = setTimeout(function () { 1856 currentObj.autoReconnectTimeoutID = -1; 1857 callback.call(currentObj); 1858 }, milliseconds); 1859 }; 1860 1861 /** @private */ 1862 net.user1.orbiter.ConnectionMonitor.prototype.selectReconnectFrequency = function () { 1863 if (this.autoReconnectMinMS == -1) { 1864 this.autoReconnectFrequency = -1; 1865 } else if (this.autoReconnectMinMS == this.autoReconnectMaxMS) { 1866 this.autoReconnectFrequency = this.autoReconnectMinMS; 1867 } else { 1868 this.autoReconnectFrequency = getRandInt(this.autoReconnectMinMS, this.autoReconnectMaxMS); 1869 this.log.info("[CONNECTION_MONITOR] Random auto-reconnect frequency selected: [" + 1870 this.autoReconnectFrequency + "] ms."); 1871 } 1872 1873 function getRandInt (min, max) { 1874 return min + Math.floor(Math.random()*(max+1 - min)); 1875 } 1876 }; 1877 1878 /** @private */ 1879 net.user1.orbiter.ConnectionMonitor.prototype.doReconnect = function () { 1880 var numActualAttempts = this.orbiter.getConnectionManager().getConnectAttemptCount(); 1881 var numReconnectAttempts; 1882 1883 if (this.orbiter.getConnectionManager().getReadyCount() == 0) { 1884 numReconnectAttempts = numActualAttempts - 1; 1885 } else { 1886 numReconnectAttempts = numActualAttempts; 1887 } 1888 1889 if (this.autoReconnectAttemptLimit != -1 1890 && numReconnectAttempts > 0 1891 && numReconnectAttempts % (this.autoReconnectAttemptLimit) == 0) { 1892 this.log.warn("[CONNECTION_MONITOR] Automatic reconnect attempt limit reached." 1893 + " No further automatic connection attempts will be made until" 1894 + " the next manual connection attempt."); 1895 return; 1896 } 1897 1898 this.scheduleReconnect(this.autoReconnectFrequency); 1899 1900 this.log.warn("[CONNECTION_MONITOR] Attempting automatic reconnect. (Next attempt in " 1901 + this.autoReconnectFrequency + "ms.)"); 1902 this.orbiter.connect(); 1903 } 1904 1905 //============================================================================== 1906 // CONFIGURATION 1907 //============================================================================== 1908 1909 net.user1.orbiter.ConnectionMonitor.prototype.restoreDefaults = function () { 1910 this.setAutoReconnectFrequency(net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_FREQUENCY); 1911 this.setAutoReconnectAttemptLimit(net.user1.orbiter.ConnectionMonitor.DEFAULT_AUTORECONNECT_ATTEMPT_LIMIT); 1912 this.setConnectionTimeout(net.user1.orbiter.ConnectionMonitor.DEFAULT_CONNECTION_TIMEOUT); 1913 this.setHeartbeatFrequency(net.user1.orbiter.ConnectionMonitor.DEFAULT_HEARTBEAT_FREQUENCY); 1914 } 1915 1916 net.user1.orbiter.ConnectionMonitor.prototype.setHeartbeatFrequency = function (milliseconds) { 1917 if (milliseconds >= net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY) { 1918 this.heartBeatFrequency = milliseconds; 1919 this.log.info("[CONNECTION_MONITOR] Heartbeat frequency set to " 1920 + milliseconds + " ms."); 1921 // Log a warning for low heartbeat frequencies... 1922 if (milliseconds >= net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY && milliseconds < 1000) { 1923 this.log.info("[CONNECTION_MONITOR] HEARTBEAT FREQUENCY WARNING: " 1924 + milliseconds + " ms. Current frequency will generate " 1925 + (Math.floor((1000/milliseconds)*10)/10) 1926 + " messages per second per connected client."); 1927 } 1928 1929 // If the connection is ready, then restart 1930 // the heartbeat when the heartbeat frequency changes. 1931 if (this.orbiter.isReady()) { 1932 this.startHeartbeat(); 1933 } 1934 } else { 1935 this.log.warn("[CONNECTION_MONITOR] Invalid heartbeat frequency specified: " 1936 + milliseconds + ". Frequency must be " 1937 + net.user1.orbiter.ConnectionMonitor.MIN_HEARTBEAT_FREQUENCY + " or greater."); 1938 } 1939 } 1940 1941 net.user1.orbiter.ConnectionMonitor.prototype.getHeartbeatFrequency = function () { 1942 return this.heartBeatFrequency; 1943 } 1944 1945 net.user1.orbiter.ConnectionMonitor.prototype.setAutoReconnectFrequency = function (minMS, maxMS, delayFirstAttempt) { 1946 maxMS = (typeof maxMS == "undefined") ? -1 : maxMS; 1947 delayFirstAttempt = (typeof delayFirstAttempt == "undefined") ? false : delayFirstAttempt; 1948 1949 if (minMS == 0 || minMS < -1) { 1950 this.log.warn("[CONNECTION_MONITOR] Invalid auto-reconnect minMS specified: [" 1951 + minMS + "]. Value must not be zero or less than -1. Value adjusted" 1952 + " to [-1] (no reconnect)."); 1953 minMS = -1; 1954 } 1955 if (minMS == -1) { 1956 this.stopReconnect(); 1957 } else { 1958 if (maxMS == -1) { 1959 maxMS = minMS; 1960 } 1961 if (maxMS < minMS) { 1962 this.log.warn("[CONNECTION_MONITOR] Invalid auto-reconnect maxMS specified: [" 1963 + maxMS + "]." + " Value of maxMS must be greater than or equal " 1964 + "to minMS. Value adjusted to [" + minMS + "]."); 1965 maxMS = minMS; 1966 } 1967 } 1968 1969 this.autoReconnectDelayFirstAttempt = delayFirstAttempt; 1970 this.autoReconnectMinMS = minMS; 1971 this.autoReconnectMaxMS = maxMS; 1972 1973 this.log.info("[CONNECTION_MONITOR] Assigning auto-reconnect frequency settings: [minMS: " 1974 + minMS + ", maxMS: " + maxMS + ", delayFirstAttempt: " 1975 + delayFirstAttempt.toString() + "]."); 1976 if (minMS > 0 && minMS < 1000) { 1977 this.log.info("[CONNECTION_MONITOR] RECONNECT FREQUENCY WARNING: " 1978 + minMS + " minMS specified. Current frequency will cause " 1979 + (Math.floor((1000/minMS)*10)/10).toString() 1980 + " reconnection attempts per second."); 1981 } 1982 this.selectReconnectFrequency(); 1983 } 1984 1985 net.user1.orbiter.ConnectionMonitor.prototype.getAutoReconnectFrequency = function () { 1986 return this.autoReconnectFrequency; 1987 } 1988 1989 net.user1.orbiter.ConnectionMonitor.prototype.setAutoReconnectAttemptLimit = function (attempts) { 1990 if (attempts < -1 || attempts == 0) { 1991 this.log.warn("[CONNECTION_MONITOR] Invalid Auto-reconnect attempt limit specified: " 1992 + attempts + ". Limit must -1 or greater than 1."); 1993 return; 1994 } 1995 1996 this.autoReconnectAttemptLimit = attempts; 1997 1998 if (attempts == -1) { 1999 this.log.info("[CONNECTION_MONITOR] Auto-reconnect attempt limit set to none."); 2000 } else { 2001 this.log.info("[CONNECTION_MONITOR] Auto-reconnect attempt limit set to " 2002 + attempts + " attempt(s)."); 2003 } 2004 }; 2005 2006 net.user1.orbiter.ConnectionMonitor.prototype.getAutoReconnectAttemptLimit = function () { 2007 return this.autoReconnectAttemptLimit; 2008 } 2009 2010 net.user1.orbiter.ConnectionMonitor.prototype.setConnectionTimeout = function (milliseconds) { 2011 if (milliseconds > 0) { 2012 this.connectionTimeout = milliseconds; 2013 this.log.info("[CONNECTION_MONITOR] Connection timeout set to " 2014 + milliseconds + " ms."); 2015 } else { 2016 this.log.warn("[CONNECTION_MONITOR] Invalid connection timeout specified: " 2017 + milliseconds + ". Frequency must be greater " 2018 + "than zero."); 2019 } 2020 } 2021 2022 net.user1.orbiter.ConnectionMonitor.prototype.getConnectionTimeout = function () { 2023 return this.connectionTimeout; 2024 } 2025 2026 net.user1.orbiter.ConnectionMonitor.prototype.sharePing = function (share) { 2027 this.sharedPing = share; 2028 } 2029 2030 net.user1.orbiter.ConnectionMonitor.prototype.isPingShared = function () { 2031 return this.sharedPing; 2032 } 2033 2034 net.user1.orbiter.ConnectionMonitor.prototype.disableHeartbeatLogging = function () { 2035 this.log.addSuppressionTerm("<A>CLIENT_HEARTBEAT</A>"); 2036 this.log.addSuppressionTerm("<A>_PING</A>"); 2037 this.log.addSuppressionTerm("[_PING]"); 2038 this.log.addSuppressionTerm("<![CDATA[_PING]]>"); 2039 } 2040 2041 net.user1.orbiter.ConnectionMonitor.prototype.enableHeartbeatLogging = function () { 2042 this.log.removeSuppressionTerm("<A>CLIENT_HEARTBEAT</A>"); 2043 this.log.removeSuppressionTerm("<A>_PING</A>"); 2044 this.log.removeSuppressionTerm("[_PING]"); 2045 this.log.removeSuppressionTerm("<![CDATA[_PING]]>"); 2046 } 2047 2048 // ============================================================================= 2049 // DISPOSAL 2050 // ============================================================================= 2051 2052 net.user1.orbiter.ConnectionMonitor.prototype.dispose = function () { 2053 this.disposed = true; 2054 2055 this.stopHeartbeat(); 2056 this.stopReconnect(); 2057 2058 this.heartbeats = null; 2059 2060 this.orbiter.removeEventListener(net.user1.orbiter.OrbiterEvent.READY, this.connectReadyListener, this); 2061 this.orbiter.removeEventListener(net.user1.orbiter.OrbiterEvent.CLOSE, this.connectCloseListener, this); 2062 this.orbiter = null; 2063 this.msgManager.removeMessageListener("u7", this.u7); 2064 this.msgManager(null); 2065 this.log = null; 2066 }; 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 //============================================================================== 2085 // CLASS DECLARATION 2086 //============================================================================== 2087 /** @class 2088 @extends net.user1.events.Event 2089 */ 2090 net.user1.orbiter.OrbiterEvent = function (type, 2091 serverUPCVersion, 2092 connectionRefusal) { 2093 net.user1.events.Event.call(this, type); 2094 2095 this.serverUPCVersion = serverUPCVersion; 2096 this.connectionRefusal = connectionRefusal; 2097 }; 2098 2099 //============================================================================== 2100 // INHERITANCE 2101 //============================================================================== 2102 net.user1.utils.extend(net.user1.orbiter.OrbiterEvent, net.user1.events.Event); 2103 2104 //============================================================================== 2105 // STATIC VARIABLES 2106 //============================================================================== 2107 /** @constant */ 2108 net.user1.orbiter.OrbiterEvent.READY = "READY"; 2109 /** @constant */ 2110 net.user1.orbiter.OrbiterEvent.CLOSE = "CLOSE"; 2111 /** @constant */ 2112 net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE = "PROTOCOL_INCOMPATIBLE"; 2113 /** @constant */ 2114 net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED = "CONNECT_REFUSED"; 2115 2116 //============================================================================== 2117 // INSTANCE METHODS 2118 //============================================================================== 2119 net.user1.orbiter.OrbiterEvent.prototype.getServerUPCVersion = function () { 2120 return this.serverUPCVersion; 2121 } 2122 2123 net.user1.orbiter.OrbiterEvent.prototype.getConnectionRefusal = function () { 2124 return this.connectionRefusal; 2125 } 2126 2127 net.user1.orbiter.OrbiterEvent.prototype.toString = function () { 2128 return "[object OrbiterEvent]"; 2129 } 2130 2131 //============================================================================== 2132 // CLASS DECLARATION 2133 //============================================================================== 2134 /** @class 2135 2136 The Snapshot class dispatches the following events: 2137 2138 <ul class="summary"> 2139 <li class="fixedFont">{@link net.user1.orbiter.SnapshotEvent.LOAD}</li> 2140 <li class="fixedFont">{@link net.user1.orbiter.SnapshotEvent.STATUS}</li> 2141 </ul> 2142 2143 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 2144 2145 @extends net.user1.events.EventDispatcher 2146 */ 2147 net.user1.orbiter.snapshot.Snapshot = function () { 2148 // Call superconstructor 2149 net.user1.events.EventDispatcher.call(this); 2150 this.method; 2151 this.args = new Array(); 2152 this.hasStatus; 2153 this.statusReceived; 2154 this.loaded; 2155 this._updateInProgress; 2156 this._status; 2157 this.onLoad = function () {}; 2158 }; 2159 2160 //============================================================================== 2161 // INHERITANCE 2162 //============================================================================== 2163 net.user1.utils.extend(net.user1.orbiter.snapshot.Snapshot, net.user1.events.EventDispatcher); 2164 2165 //============================================================================== 2166 // INSTANCE METHODS 2167 //============================================================================== 2168 net.user1.orbiter.snapshot.Snapshot.prototype.updateInProgress = function () { 2169 return this._updateInProgress; 2170 }; 2171 2172 /** 2173 * @private 2174 */ 2175 net.user1.orbiter.snapshot.Snapshot.prototype.setUpdateInProgress = function (value) { 2176 this._updateInProgress = value; 2177 }; 2178 2179 /** 2180 * @private 2181 */ 2182 net.user1.orbiter.snapshot.Snapshot.prototype.dispatchLoaded = function () { 2183 this.dispatchEvent(new net.user1.orbiter.snapshot.SnapshotEvent(net.user1.orbiter.snapshot.SnapshotEvent.LOAD, this)); 2184 }; 2185 2186 /** 2187 * @private 2188 */ 2189 net.user1.orbiter.snapshot.Snapshot.prototype.dispatchStatus = function () { 2190 this.dispatchEvent(new net.user1.orbiter.snapshot.SnapshotEvent(net.user1.orbiter.snapshot.SnapshotEvent.STATUS, this)); 2191 }; 2192 2193 net.user1.orbiter.snapshot.Snapshot.prototype.getStatus = function () { 2194 return this._status; 2195 }; 2196 2197 /** 2198 * @private 2199 */ 2200 net.user1.orbiter.snapshot.Snapshot.prototype.setStatus = function (value) { 2201 this._status = value; 2202 }; 2203 //============================================================================== 2204 // CLASS DECLARATION 2205 //============================================================================== 2206 /** 2207 * @class 2208 * @extends net.user1.events.Event 2209 */ 2210 net.user1.orbiter.snapshot.SnapshotEvent = function (type, 2211 snapshot) { 2212 net.user1.events.Event.call(this, type); 2213 this.snapshot = snapshot; 2214 }; 2215 2216 //============================================================================== 2217 // INHERITANCE 2218 //============================================================================== 2219 net.user1.utils.extend(net.user1.orbiter.snapshot.SnapshotEvent, net.user1.events.Event); 2220 2221 //============================================================================== 2222 // STATIC VARIABLES 2223 //============================================================================== 2224 2225 /** @constant */ 2226 net.user1.orbiter.snapshot.SnapshotEvent.LOAD = "LOAD"; 2227 /** @constant */ 2228 net.user1.orbiter.snapshot.SnapshotEvent.STATUS = "STATUS"; 2229 2230 net.user1.orbiter.snapshot.SnapshotEvent.prototype.toString = function () { 2231 return "[object SnapshotEvent]"; 2232 }; 2233 //============================================================================== 2234 // CLASS DECLARATION 2235 //============================================================================== 2236 /** 2237 * @private 2238 */ 2239 net.user1.orbiter.SnapshotManager = function (messageManager) { 2240 this.messageManager = messageManager; 2241 this.pendingSnapshots = new Object(); 2242 this.requestIDCounter = 0; 2243 }; 2244 2245 //============================================================================== 2246 // UPDATE SNAPSHOT 2247 //============================================================================== 2248 2249 net.user1.orbiter.SnapshotManager.prototype.updateSnapshot = function (snapshot) { 2250 var args; 2251 if (snapshot != null) { 2252 if (!snapshot.updateInProgress()) { 2253 this.requestIDCounter++; 2254 snapshot.setUpdateInProgress(true); 2255 snapshot.loaded = false; 2256 snapshot.statusReceived = false; 2257 snapshot.setStatus(null); 2258 this.pendingSnapshots[this.requestIDCounter.toString()] = snapshot; 2259 args = snapshot.args.slice(0); 2260 args.unshift(this.requestIDCounter); 2261 args.unshift(snapshot.method); 2262 this.messageManager.sendUPC.apply(this.messageManager, args); 2263 } 2264 } 2265 }; 2266 2267 //============================================================================== 2268 // RECEIVE SNAPSHOT RESULT 2269 //============================================================================== 2270 2271 net.user1.orbiter.SnapshotManager.prototype.receiveSnapshotResult = function (requestID, status) { 2272 var snapshot = this.pendingSnapshots[requestID]; 2273 if (snapshot == null) { 2274 throw new Error("[SNAPSHOT_MANAGER] Received snapshot result for unknown " 2275 + "request ID: [" + requestID + "]"); 2276 } 2277 snapshot.setStatus(status); 2278 this.setStatusReceived(snapshot, requestID); 2279 }; 2280 2281 //============================================================================== 2282 // RECEIVE CLIENTCOUNT SNAPSHOT 2283 //============================================================================== 2284 2285 net.user1.orbiter.SnapshotManager.prototype.receiveClientCountSnapshot = function (requestID, 2286 numClients) { 2287 var snapshot = this.pendingSnapshots[requestID]; 2288 if (snapshot == null) { 2289 throw new Error("[SNAPSHOT_MANAGER] Received client-count snapshot for unknown " 2290 + "request ID: [" + requestID + "]"); 2291 } 2292 snapshot.setCount(numClients); 2293 this.setLoaded(snapshot, requestID); 2294 }; 2295 2296 //============================================================================== 2297 // RECEIVE CLIENT SNAPSHOT 2298 //============================================================================== 2299 2300 net.user1.orbiter.SnapshotManager.prototype.receiveClientSnapshot = function (requestID, manifest) { 2301 var snapshot = this.pendingSnapshots[requestID]; 2302 if (snapshot == null) { 2303 throw new Error("[SNAPSHOT_MANAGER] Received client snapshot for unknown " 2304 + "request ID: [" + requestID + "]"); 2305 } 2306 snapshot.setManifest(manifest); 2307 this.setLoaded(snapshot, requestID); 2308 }; 2309 2310 //============================================================================== 2311 // RECEIVE ACCOUNT SNAPSHOT 2312 //============================================================================== 2313 2314 net.user1.orbiter.SnapshotManager.prototype.receiveAccountSnapshot = function (requestID, manifest) { 2315 var snapshot = this.pendingSnapshots[requestID]; 2316 if (snapshot == null) { 2317 throw new Error("[SNAPSHOT_MANAGER] Received account snapshot for unknown " 2318 + "request ID: [" + requestID + "]"); 2319 } 2320 snapshot.setManifest(manifest); 2321 this.setLoaded(snapshot, requestID); 2322 } 2323 2324 //============================================================================== 2325 // RECEIVE ROOMLIST SNAPSHOT 2326 //============================================================================== 2327 2328 net.user1.orbiter.SnapshotManager.prototype.receiveRoomListSnapshot = function (requestID, 2329 roomList, 2330 qualifier, 2331 recursive) { 2332 var snapshot = this.pendingSnapshots[requestID]; 2333 if (snapshot == null) { 2334 throw new Error("[SNAPSHOT_MANAGER] Received roomlist snapshot for unknown " 2335 + "request ID: [" + requestID + "]"); 2336 } 2337 snapshot.setRoomList(roomList); 2338 snapshot.setQualifier(qualifier == "" ? null : qualifier); 2339 snapshot.setRecursive(recursive); 2340 this.setLoaded(snapshot, requestID); 2341 }; 2342 2343 //============================================================================== 2344 // RECEIVE ROOM SNAPSHOT 2345 //============================================================================== 2346 2347 net.user1.orbiter.SnapshotManager.prototype.receiveRoomSnapshot = function (requestID, manifest) { 2348 var snapshot = this.pendingSnapshots[requestID]; 2349 if (snapshot == null) { 2350 throw new Error("[SNAPSHOT_MANAGER] Received room snapshot for unknown " 2351 + "request ID: [" + requestID + "]"); 2352 } 2353 snapshot.setManifest(manifest); 2354 this.setLoaded(snapshot, requestID); 2355 }; 2356 2357 //============================================================================== 2358 // RECEIVE CLIENTLIST SNAPSHOT 2359 //============================================================================== 2360 2361 net.user1.orbiter.SnapshotManager.prototype.receiveClientListSnapshot = function (requestID, clientList) { 2362 var snapshot = this.pendingSnapshots[requestID]; 2363 if (snapshot == null) { 2364 throw new Error("[SNAPSHOT_MANAGER] Received clientlist snapshot for unknown " 2365 + "request ID: [" + requestID + "]"); 2366 } 2367 snapshot.setClientList(clientList); 2368 this.setLoaded(snapshot, requestID); 2369 }; 2370 2371 //============================================================================== 2372 // RECEIVE ACCOUNTLIST SNAPSHOT 2373 //============================================================================== 2374 2375 net.user1.orbiter.SnapshotManager.prototype.receiveAccountListSnapshot = function (requestID, accountList) { 2376 var snapshot = this.pendingSnapshots[requestID]; 2377 if (snapshot == null) { 2378 throw new Error("[SNAPSHOT_MANAGER] Received accountlist snapshot for unknown " 2379 + "request ID: [" + requestID + "]"); 2380 } 2381 snapshot.setAccountList(accountList); 2382 this.setLoaded(snapshot, requestID); 2383 }; 2384 2385 //============================================================================== 2386 // RECEIVE BANNEDLIST SNAPSHOT 2387 //============================================================================== 2388 2389 net.user1.orbiter.SnapshotManager.prototype.receiveBannedListSnapshot = function (requestID, bannedList) { 2390 var snapshot = this.pendingSnapshots[requestID]; 2391 if (snapshot == null) { 2392 throw new Error("[SNAPSHOT_MANAGER] Received bannedlist snapshot for unknown " 2393 + "request ID: [" + requestID + "]"); 2394 } 2395 snapshot.setBannedList(bannedList); 2396 this.setLoaded(snapshot, requestID); 2397 }; 2398 2399 //============================================================================== 2400 // RECEIVE SERVERMODULELIST SNAPSHOT 2401 //============================================================================== 2402 2403 net.user1.orbiter.SnapshotManager.prototype.receiveServerModuleListSnapshot = function (requestID, moduleList) { 2404 var snapshot = this.pendingSnapshots[requestID]; 2405 if (snapshot == null) { 2406 throw new Error("[SNAPSHOT_MANAGER] Received server module list snapshot for unknown " 2407 + "request ID: [" + requestID + "]"); 2408 } 2409 snapshot.setModuleList(moduleList); 2410 this.setLoaded(snapshot, requestID); 2411 }; 2412 2413 //============================================================================== 2414 // RECEIVE UPCSTATS SNAPSHOT 2415 //============================================================================== 2416 2417 net.user1.orbiter.SnapshotManager.prototype.receiveUPCStatsSnapshot = function (requestID, 2418 totalUPCsProcessed, 2419 numUPCsInQueue, 2420 lastQueueWaitTime, 2421 longestUPCProcesses) { 2422 var snapshot = this.pendingSnapshots[requestID]; 2423 if (snapshot == null) { 2424 throw new Error("[SNAPSHOT_MANAGER] Received UPC stats snapshot for unknown " 2425 + "request ID: [" + requestID + "]"); 2426 } 2427 snapshot.setTotalUPCsProcessed(totalUPCsProcessed); 2428 snapshot.setNumUPCsInQueue(numUPCsInQueue); 2429 snapshot.setLastQueueWaitTime(lastQueueWaitTime); 2430 snapshot.setLongestUPCProcesses(longestUPCProcesses); 2431 this.setLoaded(snapshot, requestID); 2432 }; 2433 2434 //============================================================================== 2435 // RECEIVE NODELIST SNAPSHOT 2436 //============================================================================== 2437 2438 net.user1.orbiter.SnapshotManager.prototype.receiveNodeListSnapshot = function (requestID, nodeList) { 2439 var snapshot = this.pendingSnapshots[requestID]; 2440 if (snapshot == null) { 2441 throw new Error("[SNAPSHOT_MANAGER] Received server node list snapshot for unknown " 2442 + "request ID: [" + requestID + "]"); 2443 } 2444 snapshot.setNodeList(nodeList); 2445 this.setLoaded(snapshot, requestID); 2446 }; 2447 2448 2449 //============================================================================== 2450 // RECEIVE GATEWAYS SNAPSHOT 2451 //============================================================================== 2452 2453 net.user1.orbiter.SnapshotManager.prototype.receiveGatewaysSnapshot = function (requestID, gateways) { 2454 var snapshot = this.pendingSnapshots[requestID]; 2455 if (snapshot == null) { 2456 throw new Error("[SNAPSHOT_MANAGER] Received gateways snapshot for unknown " 2457 + "request ID: [" + requestID + "]"); 2458 } 2459 snapshot.setGateways(gateways); 2460 this.setLoaded(snapshot, requestID); 2461 }; 2462 2463 //============================================================================== 2464 // LOADED AND STATUS ASSIGNMENT 2465 //============================================================================== 2466 2467 net.user1.orbiter.SnapshotManager.prototype.setLoaded = function (snapshot, requestID) { 2468 snapshot.loaded = true; 2469 if (snapshot.hasStatus == false 2470 || (snapshot.hasStatus == true && snapshot.statusReceived)) { 2471 snapshot.setUpdateInProgress(false); 2472 delete this.pendingSnapshots[requestID]; 2473 } 2474 2475 if (snapshot.hasOwnProperty("onLoad")) { 2476 snapshot["onLoad"](); 2477 } 2478 snapshot.dispatchLoaded(); 2479 }; 2480 2481 net.user1.orbiter.SnapshotManager.prototype.setStatusReceived = function (snapshot, requestID) { 2482 if (snapshot.loaded) { 2483 snapshot.setUpdateInProgress(false); 2484 delete this.pendingSnapshots[requestID]; 2485 } 2486 snapshot.dispatchStatus(); 2487 }; 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 //============================================================================== 2507 // BOOLEAN GROUP TYPE CONSTANTS 2508 //============================================================================== 2509 /** @class */ 2510 net.user1.orbiter.filters.BooleanGroupType = new Object(); 2511 /** @constant */ 2512 net.user1.orbiter.filters.BooleanGroupType.AND = "AND"; 2513 /** @constant */ 2514 net.user1.orbiter.filters.BooleanGroupType.OR = "OR"; 2515 //============================================================================== 2516 // CLASS DECLARATION 2517 //============================================================================== 2518 /** 2519 * @class 2520 */ 2521 net.user1.orbiter.filters.BooleanGroup = function (type) { 2522 this.type = type; 2523 this.comparisons = new Array(); 2524 }; 2525 2526 net.user1.orbiter.filters.BooleanGroup.prototype.addComparison = function (comparison) { 2527 if (comparison == null) return; 2528 this.comparisons.push(comparison); 2529 }; 2530 2531 net.user1.orbiter.filters.BooleanGroup.prototype.toXMLString = function () { 2532 var s = type == net.user1.orbiter.filters.BooleanGroupType.AND ? "<and>\n" : "<or>\n"; 2533 2534 var comparison; 2535 for (var i = 0; i < this.comparisons.length; i++) { 2536 comparison = this.comparisons[i]; 2537 s += comparison.toXMLString() + "\n"; 2538 } 2539 s += this.type == net.user1.orbiter.filters.BooleanGroupType.AND ? "</and>" : "</or>"; 2540 return s; 2541 } 2542 //============================================================================== 2543 // CLASS DECLARATION 2544 //============================================================================== 2545 /** 2546 * @class 2547 * @extends net.user1.events.Event 2548 */ 2549 net.user1.orbiter.AccountEvent = function (type, 2550 status, 2551 userID, 2552 clientID, 2553 role) { 2554 net.user1.events.Event.call(this, type); 2555 2556 this.status = status; 2557 this.userID = userID; 2558 this.clientID = clientID; 2559 this.role = role; 2560 this.account = null; 2561 }; 2562 2563 //============================================================================== 2564 // INHERITANCE 2565 //============================================================================== 2566 net.user1.utils.extend(net.user1.orbiter.AccountEvent, net.user1.events.Event); 2567 2568 //============================================================================== 2569 // STATIC VARIABLES 2570 //============================================================================== 2571 2572 /** @constant */ 2573 net.user1.orbiter.AccountEvent.LOGIN_RESULT = "LOGIN_RESULT"; 2574 /** @constant */ 2575 net.user1.orbiter.AccountEvent.LOGIN = "LOGIN"; 2576 /** @constant */ 2577 net.user1.orbiter.AccountEvent.LOGOFF_RESULT = "LOGOFF_RESULT"; 2578 /** @constant */ 2579 net.user1.orbiter.AccountEvent.LOGOFF = "LOGOFF"; 2580 /** @constant */ 2581 net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT = "CHANGE_PASSWORD_RESULT"; 2582 /** @constant */ 2583 net.user1.orbiter.AccountEvent.CHANGE_PASSWORD = "CHANGE_PASSWORD"; 2584 /** @constant */ 2585 net.user1.orbiter.AccountEvent.OBSERVE = "OBSERVE"; 2586 /** @constant */ 2587 net.user1.orbiter.AccountEvent.STOP_OBSERVING = "STOP_OBSERVING"; 2588 /** @constant */ 2589 net.user1.orbiter.AccountEvent.OBSERVE_RESULT = "OBSERVE_RESULT"; 2590 /** @constant */ 2591 net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT = "STOP_OBSERVING_RESULT"; 2592 /** @constant */ 2593 net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT = "ADD_ROLE_RESULT"; 2594 /** @constant */ 2595 net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT = "REMOVE_ROLE_RESULT"; 2596 /** @constant */ 2597 net.user1.orbiter.AccountEvent.SYNCHRONIZE = "SYNCHRONIZE"; 2598 2599 2600 //============================================================================== 2601 // INSTANCE METHODS 2602 //============================================================================== 2603 net.user1.orbiter.AccountEvent.prototype.getAccount = function () { 2604 if (this.target instanceof net.user1.orbiter.AccountManager) { 2605 return this.account; 2606 } else if (this.target instanceof net.user1.orbiter.UserAccount) { 2607 return this.target; 2608 } else { 2609 throw new Error("[AccountEvent] Unexpected target type: " + this.target); 2610 } 2611 }; 2612 2613 /** 2614 * @private 2615 */ 2616 net.user1.orbiter.AccountEvent.prototype.setAccount = function (value) { 2617 this.account = value; 2618 }; 2619 2620 net.user1.orbiter.AccountEvent.prototype.getUserID = function () { 2621 return this.userID; 2622 }; 2623 2624 net.user1.orbiter.AccountEvent.prototype.getRole = function () { 2625 return this.role; 2626 }; 2627 2628 net.user1.orbiter.AccountEvent.prototype.getClientID = function () { 2629 return this.clientID; 2630 }; 2631 2632 net.user1.orbiter.AccountEvent.prototype.getStatus = function () { 2633 return this.status; 2634 }; 2635 2636 net.user1.orbiter.AccountEvent.prototype.toString = function () { 2637 return "[object AccountEvent]"; 2638 }; 2639 //============================================================================== 2640 // CLASS DECLARATION 2641 //============================================================================== 2642 /** 2643 * @class 2644 * @extends net.user1.orbiter.snapshot.Snapshot 2645 */ 2646 net.user1.orbiter.snapshot.AccountListSnapshot = function () { 2647 // Call superconstructor 2648 net.user1.orbiter.snapshot.Snapshot.call(this); 2649 this.accountList = null; 2650 this.method = net.user1.orbiter.UPC.GET_ACCOUNTLIST_SNAPSHOT; 2651 }; 2652 2653 //============================================================================== 2654 // INHERITANCE 2655 //============================================================================== 2656 net.user1.utils.extend(net.user1.orbiter.snapshot.AccountListSnapshot, net.user1.orbiter.snapshot.Snapshot); 2657 2658 //============================================================================== 2659 // INSTANCE METHODS 2660 //============================================================================== 2661 /** 2662 * @private 2663 */ 2664 net.user1.orbiter.snapshot.AccountListSnapshot.prototype.setAccountList = function (value) { 2665 this.accountList = value; 2666 } 2667 2668 net.user1.orbiter.snapshot.AccountListSnapshot.prototype.getAccountList = function () { 2669 if (!this.accountList) { 2670 return null; 2671 } 2672 return this.accountList.slice(); 2673 } 2674 //============================================================================== 2675 // CLASS DECLARATION 2676 //============================================================================== 2677 /** @class 2678 2679 The AccountManager class dispatches the following events: 2680 2681 <ul class="summary"> 2682 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT}</li> 2683 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT}</li> 2684 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT}</li> 2685 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED}</li> 2686 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED}</li> 2687 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF_RESULT}</li> 2688 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF}</li> 2689 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN_RESULT}</li> 2690 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN}</li> 2691 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD}</li> 2692 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE}</li> 2693 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING}</li> 2694 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT}</li> 2695 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT}</li> 2696 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE_RESULT}</li> 2697 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT}</li> 2698 <li class="fixedFont">{@link net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE}</li> 2699 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT}</li> 2700 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT}</li> 2701 </ul> 2702 2703 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 2704 2705 @extends net.user1.events.EventDispatcher 2706 */ 2707 net.user1.orbiter.AccountManager = function (log) { 2708 // Call superconstructor 2709 net.user1.events.EventDispatcher.call(this); 2710 2711 this.watchedAccounts = new net.user1.orbiter.AccountSet(); 2712 this.observedAccounts = new net.user1.orbiter.AccountSet(); 2713 this.accountCache = new net.user1.utils.LRUCache(10000); 2714 this.log = log; 2715 this._isWatchingForAccounts = false; 2716 this.accountCache; 2717 this.messageManager; 2718 this.clientManager; 2719 this.roomManager; 2720 }; 2721 2722 //============================================================================== 2723 // INHERITANCE 2724 //============================================================================== 2725 net.user1.utils.extend(net.user1.orbiter.AccountManager, net.user1.events.EventDispatcher); 2726 2727 // ============================================================================= 2728 // DEPENDENCIES 2729 // ============================================================================= 2730 /** 2731 * @private 2732 */ 2733 net.user1.orbiter.AccountManager.prototype.setMessageManager = function (value) { 2734 this.messageManager = value; 2735 } 2736 2737 /** 2738 * @private 2739 */ 2740 net.user1.orbiter.AccountManager.prototype.setClientManager = function (value) { 2741 this.clientManager = value; 2742 } 2743 2744 /** 2745 * @private 2746 */ 2747 net.user1.orbiter.AccountManager.prototype.setRoomManager = function (value) { 2748 this.roomManager = value; 2749 } 2750 2751 // ============================================================================= 2752 // REMOTE ACCOUNT CREATION/REMOVAL 2753 // ============================================================================= 2754 2755 net.user1.orbiter.AccountManager.prototype.createAccount = function (userID, password) { 2756 if (userID == null || userID == "") { 2757 this.log.warn("[ACCOUNT_MANAGER] Create account failed. No userID supplied."); 2758 } else if (password == null) { 2759 this.log.warn("[ACCOUNT_MANAGER] Create account failed. No password supplied."); 2760 } else { 2761 this.messageManager.sendUPC(net.user1.orbiter.UPC.CREATE_ACCOUNT, userID, password); 2762 } 2763 }; 2764 2765 net.user1.orbiter.AccountManager.prototype.removeAccount = function (userID, password) { 2766 if (userID == null || userID == "") { 2767 this.log.warn("[ACCOUNT_MANAGER] Remove account failed. No userID supplied."); 2768 } else { 2769 if (password == null) { 2770 this.log.warn("[ACCOUNT_MANAGER] Remove account: no password supplied." + 2771 " Removal will fail unless sender is an administrator."); 2772 } 2773 this.messageManager.sendUPC(net.user1.orbiter.UPC.REMOVE_ACCOUNT, userID, password); 2774 } 2775 } 2776 2777 // ============================================================================= 2778 // CHANGE PASSWORD 2779 // ============================================================================= 2780 2781 net.user1.orbiter.AccountManager.prototype.changePassword = function (userID, newPassword, oldPassword) { 2782 if (userID == null || userID == "") { 2783 this.log.warn("[ACCOUNT_MANAGER] Change password failed. No userID supplied."); 2784 } else if (newPassword == null || newPassword == "") { 2785 this.log.warn("[ACCOUNT_MANAGER] Change password failed for account [" 2786 + userID + "]. No new password supplied."); 2787 } else { 2788 if (oldPassword == null || oldPassword == "") { 2789 this.log.warn("[ACCOUNT_MANAGER] Change account password for account [" 2790 + userID + "]: no old password supplied." 2791 + " Operation will fail unless sender is an administrator."); 2792 oldPassword = ""; 2793 } 2794 this.messageManager.sendUPC(net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD, userID, oldPassword, newPassword); 2795 } 2796 }; 2797 2798 // ============================================================================= 2799 // ADD/REMOVE ROLE 2800 // ============================================================================= 2801 2802 net.user1.orbiter.AccountManager.prototype.addRole = function (userID, role) { 2803 if (userID == null || userID == "") { 2804 this.log.warn("[ACCOUNT_MANAGER] Add role failed. No userID supplied."); 2805 } else if (role == null || role == "") { 2806 this.log.warn("[ACCOUNT_MANAGER] Add role failed for account [" 2807 + userID + "]. No role supplied."); 2808 } else { 2809 this.messageManager.sendUPC(net.user1.orbiter.UPC.ADD_ROLE, userID, role); 2810 } 2811 }; 2812 2813 net.user1.orbiter.AccountManager.prototype.removeRole = function (userID, role) { 2814 if (userID == null || userID == "") { 2815 this.log.warn("[ACCOUNT_MANAGER] Remove role failed. No userID supplied."); 2816 } else if (role == null || role == "") { 2817 this.log.warn("[ACCOUNT_MANAGER] Remove role failed for account [" 2818 + userID + "]. No role supplied."); 2819 } else { 2820 this.messageManager.sendUPC(net.user1.orbiter.UPC.REMOVE_ROLE, userID, role); 2821 } 2822 }; 2823 2824 // ============================================================================= 2825 // LOCAL ACCOUNT CREATION/REMOVAL 2826 // ============================================================================= 2827 2828 /** 2829 * @private 2830 */ 2831 net.user1.orbiter.AccountManager.prototype.requestAccount = function (userID) { 2832 var account; 2833 2834 if (userID == null || userID == "") { 2835 return null; 2836 } else { 2837 account = this.getAccount(userID); 2838 if (account == null) { 2839 account = new net.user1.orbiter.UserAccount(userID, this.log, this, this.clientManager, this.roomManager); 2840 account.setAttributeManager(new net.user1.orbiter.AttributeManager(account, this.messageManager, this.log)); 2841 this.accountCache.put(userID, account); 2842 } 2843 return account; 2844 } 2845 }; 2846 2847 /** 2848 * @private 2849 */ 2850 net.user1.orbiter.AccountManager.prototype.deserializeWatchedAccounts = function (ids) { 2851 var idList = ids.split(Tokens.RS); 2852 var idHash = new net.user1.utils.UDictionary(); 2853 var len = idList.length; 2854 2855 // Generate a hash of clientID keys to dummy values for quick lookup 2856 for (var i = len; --i >= 0;) { 2857 idHash[idList[i]] = 1; 2858 } 2859 2860 // Remove all local accounts that are not in the new list from the server 2861 var accountStillExists; 2862 for (var accountID in watchedAccounts.getAll()) { 2863 if (!idHash.hasOwnProperty(accountID)) { 2864 removeWatchedAccount(accountID); 2865 } 2866 } 2867 2868 // Add accounts from the new list that are not known locally. Do not add 2869 // clients for the accounts because "watch for accounts" does not 2870 // include client knowledge. 2871 if (ids != "") { // Empty string means no accounts are on the server 2872 for (accountID in idHash) { 2873 if (accountID != "") { 2874 if (!this.watchedAccounts.containsUserID(accountID)) { 2875 this.addWatchedAccount(this.requestAccount(accountID)); 2876 } 2877 } else { 2878 throw new Error("[CORE_MESSAGE_LISTENER] Received empty account id in user list (u127)."); 2879 } 2880 } 2881 } 2882 2883 this.fireSynchronize(); 2884 }; 2885 2886 // ============================================================================= 2887 // OBSERVED ACCOUNTS 2888 // ============================================================================= 2889 2890 net.user1.orbiter.AccountManager.prototype.observeAccount = function (userID) { 2891 this.messageManager.sendUPC(net.user1.orbiter.UPC.OBSERVE_ACCOUNT, userID); 2892 }; 2893 2894 // This method is internal because the developer is expected to access 2895 // stopObserving() through the UserAccount directly. AccountManager's 2896 // observeAccount() exists only to allow developers to observe a 2897 // user that is currently unknown. 2898 /** 2899 * @private 2900 */ 2901 net.user1.orbiter.AccountManager.prototype.stopObservingAccount = function (userID) { 2902 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT, userID); 2903 }; 2904 2905 /** 2906 * @private 2907 */ 2908 net.user1.orbiter.AccountManager.prototype.addObservedAccount = function (account) { 2909 this.observedAccounts.add(account); 2910 this.fireObserveAccount(account.getUserID()); 2911 } 2912 2913 /** 2914 * @private 2915 */ 2916 net.user1.orbiter.AccountManager.prototype.removeObservedAccount = function (userID) { 2917 var account = this.observedAccounts.removeByUserID(userID); 2918 this.fireStopObservingAccount(userID); 2919 return account; 2920 } 2921 2922 /** 2923 * @private 2924 */ 2925 net.user1.orbiter.AccountManager.prototype.removeAllObservedAccounts = function () { 2926 this.observedAccounts.removeAll(); 2927 } 2928 2929 net.user1.orbiter.AccountManager.prototype.isObservingAccount = function (userID) { 2930 return this.observedAccounts.containsUserID(userID); 2931 } 2932 2933 //============================================================================== 2934 // WATCH FOR ACCOUNTS 2935 //============================================================================== 2936 2937 net.user1.orbiter.AccountManager.prototype.watchForAccounts = function () { 2938 this.messageManager.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS); 2939 } 2940 2941 net.user1.orbiter.AccountManager.prototype.stopWatchingForAccounts = function () { 2942 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS_RESULT); 2943 } 2944 2945 net.user1.orbiter.AccountManager.prototype.isWatchingForAccounts = function () { 2946 return this._isWatchingForAccounts; 2947 } 2948 2949 /** 2950 * @private 2951 */ 2952 net.user1.orbiter.AccountManager.prototype.setIsWatchingForAccounts = function (value) { 2953 this._isWatchingForAccounts = value; 2954 } 2955 2956 /** 2957 * @private 2958 */ 2959 net.user1.orbiter.AccountManager.prototype.addWatchedAccount = function (account) { 2960 this.watchedAccounts.add(account); 2961 this.fireAccountAdded(account.getUserID(), account); 2962 } 2963 2964 /** 2965 * @private 2966 */ 2967 net.user1.orbiter.AccountManager.prototype.removeWatchedAccount = function (userID) { 2968 return this.watchedAccounts.removeByUserID(userID); 2969 } 2970 2971 /** 2972 * @private 2973 */ 2974 net.user1.orbiter.AccountManager.prototype.removeAllWatchedAccounts = function () { 2975 this.watchedAccounts.removeAll(); 2976 } 2977 2978 net.user1.orbiter.AccountManager.prototype.hasWatchedAccount = function (userID) { 2979 return this.watchedAccounts.containsUserID(userID); 2980 } 2981 2982 // ============================================================================= 2983 // CLIENT ACCESS 2984 // ============================================================================= 2985 2986 /** 2987 * @private 2988 */ 2989 net.user1.orbiter.AccountManager.prototype.getClientsForObservedAccounts = function () { 2990 var clients = new Object(); 2991 var client; 2992 2993 var accounts = this.observedAccounts.getAll(); 2994 var account; 2995 for (var userID in accounts) { 2996 account = accounts[userID]; 2997 client = account.getInternalClient(); 2998 if (client != null) { 2999 clients[client.getClientID()] = client; 3000 } 3001 } 3002 3003 return clients; 3004 } 3005 3006 // ============================================================================= 3007 // LOCAL ACCOUNT ACCESS 3008 // ============================================================================= 3009 3010 net.user1.orbiter.AccountManager.prototype.getAccount = function (userID) { 3011 // Look in account cache 3012 var account = this.accountCache.get(userID); 3013 if (account) { 3014 return account; 3015 } 3016 3017 // Look in observed accounts 3018 account = this.observedAccounts.getByUserID(userID); 3019 if (account) { 3020 return account; 3021 } 3022 3023 // Look in watched accounts 3024 account = this.watchedAccounts.getByUserID(userID); 3025 if (account) { 3026 return account; 3027 } 3028 3029 // Look in connected accounts 3030 var connectedAccounts = new Object(); 3031 var clients = this.clientManager.getInternalClients(); 3032 var client; 3033 for (var clientID in clients) { 3034 account = clients[clientID].getAccount(); 3035 if (account != null && account.getUserID() == userID) { 3036 return account; 3037 } 3038 } 3039 3040 return null; 3041 }; 3042 3043 net.user1.orbiter.AccountManager.prototype.selfAccount = function () { 3044 return this.clientManager.self().getAccount(); 3045 }; 3046 3047 net.user1.orbiter.AccountManager.prototype.getAccounts = function () { 3048 var connectedAccounts = new Object(); 3049 var account; 3050 3051 var clients = this.clientManager.getInternalClients(); 3052 var client; 3053 for (var clientID in clients) { 3054 account = client.getAccount(); 3055 if (account != null) { 3056 connectedAccounts[account.getUserID()] = account; 3057 } 3058 } 3059 3060 return net.user1.utils.ObjectUtil.combine(connectedAccounts, this.observedAccounts.getAll(), this.watchedAccounts.getAll()); 3061 }; 3062 3063 net.user1.orbiter.AccountManager.prototype.accountIsKnown = function (userID) { 3064 for (var knownUserID in this.getAccounts()) { 3065 if (knownUserID == userID) { 3066 return true; 3067 } 3068 } 3069 return false; 3070 }; 3071 3072 net.user1.orbiter.AccountManager.prototype.getNumAccounts = function () { 3073 return this.getAccounts().length; 3074 }; 3075 3076 net.user1.orbiter.AccountManager.prototype.getNumAccountsOnServer = function () { 3077 return this.watchedAccounts.length(); 3078 }; 3079 3080 net.user1.orbiter.AccountManager.prototype.getNumLoggedInAccounts = function () { 3081 var count; 3082 var account; 3083 var accounts = this.getAccounts(); 3084 for (var userID in accounts) { 3085 account = accounts[userID]; 3086 if (account.isLoggedIn()) { 3087 count++; 3088 } 3089 } 3090 return count; 3091 }; 3092 3093 // ============================================================================= 3094 // LOGIN/LOGOFF 3095 // ============================================================================= 3096 3097 net.user1.orbiter.AccountManager.prototype.login = function (userID, password) { 3098 if (this.clientManager.self().getConnectionState() == net.user1.orbiter.ConnectionState.LOGGED_IN) { 3099 this.log.warn("[ACCOUNT_MANAGER] User [" + userID + "]: Login attempt" 3100 + " ignored. Already logged in. Current client must logoff before" 3101 + " logging in again."); 3102 this.fireLoginResult(userID, net.user1.orbiter.Status.ERROR); 3103 } else if (userID == null) { 3104 this.log.warn("[ACCOUNT_MANAGER] Login attempt" 3105 + " failed. No userID supplied."); 3106 } else if (password == null) { 3107 this.log.warn("[ACCOUNT_MANAGER] Login attempt failed for user " 3108 + "[" + userID + "] failed. No password supplied."); 3109 } else { 3110 this.messageManager.sendUPC(net.user1.orbiter.UPC.LOGIN, userID, password); 3111 } 3112 }; 3113 3114 net.user1.orbiter.AccountManager.prototype.logoff = function (userID, password) { 3115 if (userID == null) { 3116 // Current client 3117 if (this.clientManager.self().getConnectionState() != net.user1.orbiter.ConnectionState.LOGGED_IN) { 3118 this.log.warn("[ACCOUNT_MANAGER] Logoff failed. The current user is not logged in."); 3119 } else { 3120 this.clientManager.self().getAccount().logoff(); 3121 } 3122 } else if (userID == "") { 3123 // Invalid client 3124 this.log.warn("[ACCOUNT_MANAGER] Logoff failed. Supplied userID must not be the empty string."); 3125 } else { 3126 // UserID supplied 3127 if (password == null || password == "") { 3128 if (this.clientManager.self().getConnectionState() != net.user1.orbiter.ConnectionState.LOGGED_IN) { 3129 this.log.warn("[ACCOUNT_MANAGER] Logoff: no password supplied." + 3130 " Operation will fail unless sender is an administrator."); 3131 } 3132 password = ""; 3133 } 3134 this.messageManager.sendUPC(net.user1.orbiter.UPC.LOGOFF, userID, password); 3135 } 3136 } 3137 3138 //============================================================================== 3139 // EVENT DISPATCHING 3140 //============================================================================== 3141 3142 /** 3143 * @private 3144 */ 3145 net.user1.orbiter.AccountManager.prototype.fireCreateAccountResult = function (userID, status) { 3146 var e = new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT, 3147 userID, this.getAccount(userID), status); 3148 this.dispatchEvent(e); 3149 }; 3150 3151 /** 3152 * @private 3153 */ 3154 net.user1.orbiter.AccountManager.prototype.fireRemoveAccountResult = function (userID, status) { 3155 var e = new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT, 3156 userID, this.getAccount(userID), status); 3157 this.dispatchEvent(e); 3158 }; 3159 3160 /** 3161 * @private 3162 */ 3163 net.user1.orbiter.AccountManager.prototype.fireChangePasswordResult = function (userID, status) { 3164 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT, 3165 status, userID); 3166 e.setAccount(this.getAccount(userID)); 3167 this.dispatchEvent(e); 3168 }; 3169 3170 /** 3171 * @private 3172 */ 3173 net.user1.orbiter.AccountManager.prototype.fireAccountAdded = function (userID, account) { 3174 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED, 3175 userID, account)); 3176 }; 3177 3178 /** 3179 * @private 3180 */ 3181 net.user1.orbiter.AccountManager.prototype.fireAccountRemoved = function (userID, account) { 3182 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED, 3183 userID, account)); 3184 }; 3185 3186 /** 3187 * @private 3188 */ 3189 net.user1.orbiter.AccountManager.prototype.fireLogoffResult = function (userID, status) { 3190 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF_RESULT, 3191 status, userID); 3192 e.setAccount(this.getAccount(userID)); 3193 this.dispatchEvent(e); 3194 }; 3195 3196 /** 3197 * @private 3198 */ 3199 net.user1.orbiter.AccountManager.prototype.fireLogoff = function (account, clientID) { 3200 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF, 3201 net.user1.orbiter.Status.SUCCESS, account.getUserID(), clientID); 3202 e.setAccount(account); 3203 this.dispatchEvent(e); 3204 }; 3205 3206 /** 3207 * @private 3208 */ 3209 net.user1.orbiter.AccountManager.prototype.fireLoginResult = function (userID, status) { 3210 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN_RESULT, 3211 status, userID); 3212 e.setAccount(this.getAccount(userID)); 3213 this.dispatchEvent(e); 3214 }; 3215 3216 /** 3217 * @private 3218 */ 3219 net.user1.orbiter.AccountManager.prototype.fireLogin = function (account, clientID) { 3220 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN, 3221 net.user1.orbiter.Status.SUCCESS, account.getUserID(), clientID); 3222 e.setAccount(account); 3223 this.dispatchEvent(e); 3224 }; 3225 3226 /** 3227 * @private 3228 */ 3229 net.user1.orbiter.AccountManager.prototype.fireChangePassword = function (userID) { 3230 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD, 3231 net.user1.orbiter.Status.SUCCESS, userID); 3232 e.setAccount(this.getAccount(userID)); 3233 this.dispatchEvent(e); 3234 }; 3235 3236 /** 3237 * @private 3238 */ 3239 net.user1.orbiter.AccountManager.prototype.fireObserveAccount = function (userID) { 3240 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE, 3241 null, userID); 3242 e.setAccount(this.getAccount(userID)); 3243 this.dispatchEvent(e); 3244 }; 3245 3246 /** 3247 * @private 3248 */ 3249 net.user1.orbiter.AccountManager.prototype.fireStopObservingAccount = function (userID) { 3250 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING, 3251 null, userID); 3252 e.setAccount(this.getAccount(userID)); 3253 this.dispatchEvent(e); 3254 }; 3255 3256 /** 3257 * @private 3258 */ 3259 net.user1.orbiter.AccountManager.prototype.fireStopWatchingForAccountsResult = function (status) { 3260 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT, 3261 null, null, status)); 3262 } 3263 3264 /** 3265 * @private 3266 */ 3267 net.user1.orbiter.AccountManager.prototype.fireWatchForAccountsResult = function (status) { 3268 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT, 3269 null, null, status)); 3270 }; 3271 3272 /** 3273 * @private 3274 */ 3275 net.user1.orbiter.AccountManager.prototype.fireObserveAccountResult = function (userID, status) { 3276 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE_RESULT, 3277 status, userID); 3278 e.setAccount(this.getAccount(userID)); 3279 this.dispatchEvent(e); 3280 }; 3281 3282 /** 3283 * @private 3284 */ 3285 net.user1.orbiter.AccountManager.prototype.fireStopObservingAccountResult = function (userID, status) { 3286 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT, 3287 status, userID); 3288 e.setAccount(this.getAccount(userID)); 3289 this.dispatchEvent(e); 3290 }; 3291 3292 /** 3293 * @private 3294 */ 3295 net.user1.orbiter.AccountManager.prototype.fireAddRoleResult = function (userID, role, status) { 3296 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT, 3297 status, userID, null, role); 3298 e.setAccount(this.getAccount(userID)); 3299 this.dispatchEvent(e); 3300 }; 3301 3302 /** 3303 * @private 3304 */ 3305 net.user1.orbiter.AccountManager.prototype.fireRemoveRoleResult = function (userID, role, status) { 3306 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT, 3307 status, userID, null, role); 3308 e.setAccount(this.getAccount(userID)); 3309 this.dispatchEvent(e); 3310 }; 3311 3312 /** 3313 * @private 3314 */ 3315 net.user1.orbiter.AccountManager.prototype.fireSynchronize = function () { 3316 this.dispatchEvent(new net.user1.orbiter.AccountManagerEvent(net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE)); 3317 } 3318 3319 //============================================================================== 3320 // CLEANUP AND DISPOSAL 3321 //============================================================================== 3322 3323 /** 3324 * @private 3325 */ 3326 net.user1.orbiter.AccountManager.prototype.cleanup = function () { 3327 this.log.info("[ACCOUNT_MANAGER] Cleaning resources."); 3328 this.removeAllObservedAccounts(); 3329 this.removeAllWatchedAccounts(); 3330 this.setIsWatchingForAccounts(false); 3331 }; 3332 3333 //============================================================================== 3334 // CLASS DECLARATION 3335 //============================================================================== 3336 /** @class 3337 @extends net.user1.events.Event 3338 */ 3339 net.user1.orbiter.AccountManagerEvent = function (type, 3340 userID, 3341 account, 3342 status) { 3343 net.user1.events.Event.call(this, type); 3344 3345 this.account = account; 3346 this.userID = userID; 3347 this.status = status; 3348 }; 3349 3350 //============================================================================== 3351 // INHERITANCE 3352 //============================================================================== 3353 net.user1.utils.extend(net.user1.orbiter.AccountManagerEvent, net.user1.events.Event); 3354 3355 //============================================================================== 3356 // STATIC VARIABLES 3357 //============================================================================== 3358 3359 /** @constant */ 3360 net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT = "CREATE_ACCOUNT_RESULT"; 3361 /** @constant */ 3362 net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT = "REMOVE_ACCOUNT_RESULT"; 3363 /** @constant */ 3364 net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED = "ACCOUNT_ADDED"; 3365 /** @constant */ 3366 net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED = "ACCOUNT_REMOVED"; 3367 /** @constant */ 3368 net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT = "WATCH_FOR_ACCOUNTS_RESULT"; 3369 /** @constant */ 3370 net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT = "STOP_WATCHING_FOR_ACCOUNTS_RESULT"; 3371 /** @constant */ 3372 net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE = "SYNCHRONIZE"; 3373 3374 //============================================================================== 3375 // INSTANCE METHODS 3376 //============================================================================== 3377 net.user1.orbiter.AccountManagerEvent.prototype.getStatus = function () { 3378 return this.status; 3379 }; 3380 3381 net.user1.orbiter.AccountManagerEvent.prototype.getUserID = function () { 3382 return this.userID; 3383 }; 3384 3385 net.user1.orbiter.AccountManagerEvent.prototype.getAccount = function () { 3386 return this.account; 3387 }; 3388 3389 net.user1.orbiter.AccountManagerEvent.prototype.toString = function () { 3390 return "[object AccountManagerEvent]"; 3391 }; 3392 //============================================================================== 3393 // CLASS DECLARATION 3394 //============================================================================== 3395 /** 3396 * @private 3397 */ 3398 net.user1.orbiter.AccountSet = function () { 3399 this.accounts = new net.user1.utils.UDictionary(); 3400 }; 3401 3402 net.user1.orbiter.AccountSet.prototype.add = function (account) { 3403 this.accounts[account.getUserID()] = account; 3404 }; 3405 3406 net.user1.orbiter.AccountSet.prototype.remove = function (account) { 3407 var account = this.accounts[account.getUserID()]; 3408 delete this.accounts[account.getUserID()]; 3409 return account; 3410 } 3411 3412 net.user1.orbiter.AccountSet.prototype.removeAll = function () { 3413 this.accounts = new net.user1.utils.UDictionary(); 3414 } 3415 3416 net.user1.orbiter.AccountSet.prototype.removeByUserID = function (userID) { 3417 var account = this.accounts[userID]; 3418 delete this.accounts[userID]; 3419 return account; 3420 } 3421 3422 net.user1.orbiter.AccountSet.prototype.contains = function (account) { 3423 return this.accounts[account.getUserID()] != null; 3424 } 3425 3426 net.user1.orbiter.AccountSet.prototype.containsUserID = function (userID) { 3427 if (userID == "" || userID == null) { 3428 return false; 3429 } 3430 return this.getByUserID(userID) != null; 3431 } 3432 3433 net.user1.orbiter.AccountSet.prototype.getByUserID = function (userID) { 3434 return this.accounts[userID]; 3435 } 3436 3437 net.user1.orbiter.AccountSet.prototype.getByClient = function (client) { 3438 var account; 3439 for (var userID in this.accounts) { 3440 account = this.accounts[userID]; 3441 if (account.getInternalClient() == client) { 3442 return account; 3443 } 3444 } 3445 return null; 3446 } 3447 3448 net.user1.orbiter.AccountSet.prototype.getAll = function () { 3449 return this.accounts; 3450 } 3451 3452 net.user1.orbiter.AccountSet.prototype.length = function () { 3453 var count; 3454 for (var userID in this.accounts) { 3455 count++; 3456 } 3457 return count; 3458 } 3459 //============================================================================== 3460 // CLASS DECLARATION 3461 //============================================================================== 3462 /** 3463 * @class 3464 * @extends net.user1.orbiter.snapshot.Snapshot 3465 */ 3466 net.user1.orbiter.snapshot.AccountSnapshot = function (userID) { 3467 // Call superconstructor 3468 net.user1.orbiter.snapshot.Snapshot.call(this); 3469 this.manifest = null; 3470 this.method = net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT; 3471 this.args = [userID]; 3472 this.hasStatus = true; 3473 }; 3474 3475 //============================================================================== 3476 // INHERITANCE 3477 //============================================================================== 3478 net.user1.utils.extend(net.user1.orbiter.snapshot.AccountSnapshot, net.user1.orbiter.snapshot.Snapshot); 3479 3480 //============================================================================== 3481 // INSTANCE METHODS 3482 //============================================================================== 3483 /** 3484 * @private 3485 */ 3486 net.user1.orbiter.snapshot.AccountSnapshot.prototype.setManifest = function (value) { 3487 this.manifest = value; 3488 }; 3489 3490 net.user1.orbiter.snapshot.AccountSnapshot.prototype.getAttribute = function (name, scope) { 3491 if (!this.manifest) { 3492 return null; 3493 } 3494 return this.manifest.persistentAttributes.getAttribute(name, scope); 3495 }; 3496 3497 net.user1.orbiter.snapshot.AccountSnapshot.prototype.getAttributes = function () { 3498 if (!this.manifest) { 3499 return null; 3500 } 3501 return this.manifest.persistentAttributes.getAll(); 3502 }; 3503 3504 net.user1.orbiter.snapshot.AccountSnapshot.prototype.getUserID = function () { 3505 if (!this.manifest) { 3506 return null; 3507 } 3508 return this.manifest.userID; 3509 }; 3510 //============================================================================== 3511 // CLASS DECLARATION 3512 //============================================================================== 3513 /** 3514 * @class 3515 * @extends net.user1.orbiter.filters.BooleanGroup 3516 */ 3517 net.user1.orbiter.filters.AndGroup = function () { 3518 net.user1.orbiter.filters.BooleanGroup.call(this, net.user1.orbiter.filters.BooleanGroupType.AND); 3519 }; 3520 3521 //============================================================================== 3522 // INHERITANCE 3523 //============================================================================== 3524 net.user1.utils.extend(net.user1.orbiter.filters.AndGroup, net.user1.orbiter.filters.BooleanGroup); 3525 //============================================================================== 3526 // CLASS DECLARATION 3527 //============================================================================== 3528 /** 3529 * @class 3530 * @extends net.user1.orbiter.filters.AndGroup 3531 */ 3532 net.user1.orbiter.filters.Filter = function (filterType) { 3533 net.user1.orbiter.filters.AndGroup.call(this); 3534 this.filterType = filterType; 3535 }; 3536 3537 //============================================================================== 3538 // INHERITANCE 3539 //============================================================================== 3540 net.user1.utils.extend(net.user1.orbiter.filters.Filter, net.user1.orbiter.filters.AndGroup); 3541 3542 net.user1.orbiter.filters.Filter.prototype.toXMLString = function () { 3543 var s = '<f t="' + this.filterType + '">\n'; 3544 3545 var comparison; 3546 for (var i = 0; i < this.comparisons.length; i++) { 3547 comparison = this.comparisons[i]; 3548 s += comparison.toXMLString() + "\n"; 3549 } 3550 s += '</f>'; 3551 return s; 3552 }; 3553 net.user1.utils.ArrayUtil.combine = function () { 3554 var source = arguments.length == 1 ? arguments[0] : arguments; 3555 var master = []; 3556 3557 var array; 3558 var element; 3559 for (var i = 0; i < source.length; i++) { 3560 array = source[i]; 3561 if (net.user1.utils.ArrayUtil.isArray(array)) { 3562 for (var j = 0; j < array.length; j++) { 3563 element = array[j]; 3564 if (net.user1.utils.ArrayUtil.indexOf(master, element) == -1) { 3565 master.push(element); 3566 } 3567 } 3568 } 3569 } 3570 return master; 3571 }; 3572 //============================================================================== 3573 // CLASS DECLARATION 3574 //============================================================================== 3575 /** 3576 * @class 3577 */ 3578 net.user1.orbiter.Attribute = function (name, 3579 value, 3580 oldValue, 3581 scope, 3582 byClient) { 3583 /** 3584 * @field 3585 */ 3586 this.name = name; 3587 /** 3588 * @field 3589 */ 3590 this.value = value; 3591 /** 3592 * @field 3593 */ 3594 this.oldValue = oldValue; 3595 /** 3596 * @field 3597 */ 3598 this.scope = (scope == net.user1.orbiter.Tokens.GLOBAL_ATTR) || (scope == null) ? null : scope; 3599 /** 3600 * @field 3601 */ 3602 this.byClient = byClient; 3603 } 3604 3605 net.user1.orbiter.Attribute.prototype.toString = function () { 3606 return "Attribute: " + (this.scope == null ? "" : this.scope + ".") + this.name + " = " + this.value + "." + " Old value: " + this.oldValue; 3607 }; 3608 //============================================================================== 3609 // CLASS DECLARATION 3610 //============================================================================== 3611 /** @class 3612 3613 The AttributeCollection class dispatches the following events: 3614 3615 <ul class="summary"> 3616 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.UPDATE}</li> 3617 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE}</li> 3618 </ul> 3619 3620 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 3621 3622 @extends net.user1.events.EventDispatcher 3623 */ 3624 net.user1.orbiter.AttributeCollection = function () { 3625 // Call superconstructor 3626 net.user1.events.EventDispatcher.call(this); 3627 3628 this.attributes = new Object(); 3629 }; 3630 3631 //============================================================================== 3632 // INHERITANCE 3633 //============================================================================== 3634 net.user1.utils.extend(net.user1.orbiter.AttributeCollection, net.user1.events.EventDispatcher); 3635 3636 // ============================================================================= 3637 // ATTRIBUTE ASSIGNMENT 3638 // ============================================================================= 3639 /** 3640 * @private 3641 */ 3642 net.user1.orbiter.AttributeCollection.prototype.setAttribute = function (name, value, scope, byClient) { 3643 var scopeExists 3644 var attrExists; 3645 var oldVal; 3646 3647 // null scope means global scope 3648 scope = scope == null ? net.user1.orbiter.Tokens.GLOBAL_ATTR : scope; 3649 // Check if the scope and attr exist already 3650 scopeExists = this.attributes.hasOwnProperty(scope); 3651 attrExists = scopeExists ? this.attributes[scope].hasOwnProperty(name) : false; 3652 3653 // Find old value, if any 3654 if (attrExists) { 3655 oldVal = this.attributes[scope][name]; 3656 if (oldVal == value) { 3657 // Attribute value is unchanged, so abort 3658 return false; 3659 } 3660 } 3661 3662 // Make the scope record if necessary 3663 if (!scopeExists) { 3664 this.attributes[scope] = new Object(); 3665 } 3666 3667 // Set the attribute value 3668 this.attributes[scope][name] = value; 3669 3670 // Notify listeners 3671 this.fireUpdateAttribute(name, value, scope, oldVal, byClient); 3672 3673 return true; 3674 }; 3675 3676 // ============================================================================= 3677 // ATTRIBUTE DELETION 3678 // ============================================================================= 3679 /** 3680 * @private 3681 */ 3682 net.user1.orbiter.AttributeCollection.prototype.deleteAttribute = function (name, scope, byClient) { 3683 var lastAttr = true; 3684 var value; 3685 3686 // If the attribute exists... 3687 if (this.attributes.hasOwnProperty(scope) 3688 && this.attributes[scope].hasOwnProperty(name)) { 3689 value = this.attributes[scope][name]; 3690 delete this.attributes[scope][name]; 3691 // Check if this is the last attribute. If it is, remove the room scope object. 3692 for (var p in this.attributes[scope]) { 3693 lastAttr = false; 3694 break; 3695 } 3696 if (lastAttr) { 3697 delete this.attributes[scope]; 3698 } 3699 3700 // Notify listeners 3701 this.fireDeleteAttribute(name, value, scope, byClient); 3702 return true; 3703 } 3704 return false; 3705 }; 3706 3707 /** 3708 * @private 3709 */ 3710 net.user1.orbiter.AttributeCollection.prototype.clear = function () { 3711 this.attributes = new Object(); 3712 }; 3713 3714 // ============================================================================= 3715 // ATTRIBUTE RETRIEVAL 3716 // ============================================================================= 3717 3718 net.user1.orbiter.AttributeCollection.prototype.getByScope = function (scope) { 3719 var obj = new Object(); 3720 3721 if (scope == null) { 3722 for (var attrscope in this.attributes) { 3723 obj[attrscope] = new Object(); 3724 for (var attrname in this.attributes[attrscope]) { 3725 obj[attrscope][attrname] = this.attributes[attrscope][attrname]; 3726 } 3727 } 3728 } else { 3729 for (var name in this.attributes[scope]) { 3730 obj[name] = this.attributes[scope][name]; 3731 } 3732 } 3733 3734 return obj; 3735 }; 3736 3737 net.user1.orbiter.AttributeCollection.prototype.getAttributesNamesForScope = function (scope) { 3738 var names = new Array(); 3739 for (var name in this.attributes[scope]) { 3740 names.push(name); 3741 } 3742 return names; 3743 }; 3744 3745 net.user1.orbiter.AttributeCollection.prototype.getAll = function () { 3746 var attrs = new Object(); 3747 for (var attrScope in this.attributes) { 3748 for (var attrName in this.attributes[attrScope]) { 3749 attrs[attrScope == net.user1.orbiter.Tokens.GLOBAL_ATTR ? attrName : (attrScope + "." + attrName)] = this.attributes[attrScope][attrName]; 3750 } 3751 } 3752 return attrs; 3753 } 3754 3755 net.user1.orbiter.AttributeCollection.prototype.getAttribute = function (attrName, attrScope) { 3756 // Use the global scope when no scope is specified 3757 if (attrScope == null) { 3758 attrScope = net.user1.orbiter.Tokens.GLOBAL_ATTR; 3759 } 3760 3761 // Find and return the attribute. 3762 if (this.attributes.hasOwnProperty(attrScope) 3763 && this.attributes[attrScope].hasOwnProperty(attrName)) { 3764 return this.attributes[attrScope][attrName]; 3765 } else { 3766 // No attribute was found, so quit. 3767 return null; 3768 } 3769 }; 3770 3771 net.user1.orbiter.AttributeCollection.prototype.getScopes = function () { 3772 var scopes = new Array(); 3773 for (var scope in this.attributes) { 3774 scopes.push(scope); 3775 } 3776 return scopes; 3777 }; 3778 3779 // ============================================================================= 3780 // COLLECTION INSPECTION 3781 // ============================================================================= 3782 3783 net.user1.orbiter.AttributeCollection.prototype.contains = function (name, scope) { 3784 return this.attributes.hasOwnProperty(scope) ? this.attributes[scope].hasOwnProperty(name) : false; 3785 }; 3786 3787 // ============================================================================= 3788 // MERGING 3789 // ============================================================================= 3790 3791 /** 3792 * @private 3793 */ 3794 net.user1.orbiter.AttributeCollection.prototype.add = function (collection) { 3795 var scopes = collection.getScopes(); 3796 var scope; 3797 3798 var names; 3799 var name; 3800 3801 for (var i = 0; i <= scopes.length; i++) { 3802 scope = scopes[i]; 3803 names = collection.getAttributesNamesForScope(scope); 3804 for (var j = 0; j < names.length; j++) { 3805 name = names[j]; 3806 this.setAttribute(name, collection.getAttribute(name, scope), scope); 3807 } 3808 } 3809 }; 3810 3811 /** 3812 * @private 3813 */ 3814 net.user1.orbiter.AttributeCollection.prototype.synchronizeScope = function (scope, 3815 collection) { 3816 // Delete all existing attributes that are not in the new collection 3817 var names = this.getAttributesNamesForScope(scope); 3818 var name; 3819 3820 for (var i = 0; i < names.length; i++) { 3821 name = names[i]; 3822 if (!collection.contains(name, scope)) { 3823 this.deleteAttribute(name, scope); 3824 } 3825 } 3826 3827 // Set all new attributes (unchanged attributes are ignored) 3828 var names = collection.getAttributesNamesForScope(scope); 3829 for (i = 0; i < names.length; i++) { 3830 name = names[i]; 3831 this.setAttribute(name, collection.getAttribute(name, scope), scope); 3832 } 3833 }; 3834 3835 // ============================================================================= 3836 // EVENT DISPATCHING 3837 // ============================================================================= 3838 /** 3839 * @private 3840 */ 3841 net.user1.orbiter.AttributeCollection.prototype.fireUpdateAttribute = function (attrName, 3842 attrVal, 3843 attrScope, 3844 oldVal, 3845 byClient) { 3846 var changedAttr = new net.user1.orbiter.Attribute(attrName, attrVal, oldVal, attrScope, byClient); 3847 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.UPDATE, 3848 changedAttr); 3849 this.dispatchEvent(e); 3850 }; 3851 3852 /** 3853 * @private 3854 */ 3855 net.user1.orbiter.AttributeCollection.prototype.fireDeleteAttribute = function (attrName, 3856 attrValue, 3857 attrScope, 3858 byClient) { 3859 var changedAttr = new net.user1.orbiter.Attribute(attrName, null, attrValue, attrScope, byClient); 3860 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.DELETE, 3861 changedAttr); 3862 this.dispatchEvent(e); 3863 }; 3864 //============================================================================== 3865 // CLASS DECLARATION 3866 //============================================================================== 3867 /** 3868 * @class 3869 */ 3870 net.user1.orbiter.filters.AttributeComparison = function (name, 3871 value, 3872 compareType) { 3873 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 3874 throw new Error("Invalid attribute name specified for AttributeComparison: " 3875 + name); 3876 } 3877 this.name = name; 3878 this.value = value; 3879 this.compareType = compareType; 3880 }; 3881 3882 net.user1.orbiter.filters.AttributeComparison.prototype.toXMLString = function () { 3883 return '<a c="' + this.compareType + '"><n><![CDATA[' + this.name + ']]></n><v><![CDATA[' + this.value.toString() + ']]></v></a>'; 3884 }; 3885 //============================================================================== 3886 // CLASS DECLARATION 3887 //============================================================================== 3888 /** @class 3889 @extends net.user1.events.Event 3890 */ 3891 net.user1.orbiter.AttributeEvent = function (type, 3892 changedAttr, 3893 status) { 3894 net.user1.events.Event.call(this, type); 3895 3896 this.changedAttr = changedAttr; 3897 this.status = status; 3898 }; 3899 3900 //============================================================================== 3901 // INHERITANCE 3902 //============================================================================== 3903 net.user1.utils.extend(net.user1.orbiter.AttributeEvent, net.user1.events.Event); 3904 3905 //============================================================================== 3906 // STATIC VARIABLES 3907 //============================================================================== 3908 3909 /** @constant */ 3910 net.user1.orbiter.AttributeEvent.UPDATE = "UPDATE"; 3911 /** @constant */ 3912 net.user1.orbiter.AttributeEvent.DELETE = "DELETE"; 3913 /** @constant */ 3914 net.user1.orbiter.AttributeEvent.DELETE_RESULT = "DELETE_RESULT"; 3915 /** @constant */ 3916 net.user1.orbiter.AttributeEvent.SET_RESULT = "SET_RESULT"; 3917 3918 //============================================================================== 3919 // INSTANCE METHODS 3920 //============================================================================== 3921 net.user1.orbiter.AttributeEvent.prototype.getChangedAttr = function () { 3922 return this.changedAttr; 3923 } 3924 3925 net.user1.orbiter.AttributeEvent.prototype.getStatus = function () { 3926 return this.status; 3927 } 3928 3929 net.user1.orbiter.AttributeEvent.prototype.toString = function () { 3930 return "[object AttributeEvent]"; 3931 } 3932 //============================================================================== 3933 // CLASS DECLARATION 3934 //============================================================================== 3935 /** 3936 * @class 3937 * @extends net.user1.orbiter.filters.Filter 3938 */ 3939 net.user1.orbiter.filters.AttributeFilter = function () { 3940 net.user1.orbiter.filters.Filter.call(this, "A"); 3941 }; 3942 3943 3944 //============================================================================== 3945 // INHERITANCE 3946 //============================================================================== 3947 net.user1.utils.extend(net.user1.orbiter.filters.AttributeFilter, net.user1.orbiter.filters.Filter); 3948 //============================================================================== 3949 // CLASS DECLARATION 3950 //============================================================================== 3951 /** 3952 * @private 3953 */ 3954 net.user1.orbiter.AttributeManager = function (owner, 3955 messageManager, 3956 log) { 3957 // Call superconstructor 3958 net.user1.events.EventDispatcher.call(this); 3959 3960 this.attributes = null; 3961 this.owner = owner; 3962 this.messageManager = messageManager; 3963 this.log = log; 3964 this.setAttributeCollection(new net.user1.orbiter.AttributeCollection()); 3965 }; 3966 3967 //============================================================================== 3968 // INHERITANCE 3969 //============================================================================== 3970 net.user1.utils.extend(net.user1.orbiter.AttributeManager, net.user1.events.EventDispatcher); 3971 3972 //============================================================================== 3973 // DEPENDENCIES 3974 //============================================================================== 3975 3976 net.user1.orbiter.AttributeManager.prototype.getAttributeCollection = function () { 3977 return this.attributes; 3978 }; 3979 3980 net.user1.orbiter.AttributeManager.prototype.setAttributeCollection = function (value) { 3981 this.unregisterAttributeListeners(); 3982 this.attributes = value; 3983 this.registerAttributeListeners(); 3984 }; 3985 3986 //============================================================================== 3987 // SERVER-SIDE ASSIGNMENT 3988 //============================================================================== 3989 3990 net.user1.orbiter.AttributeManager.prototype.setAttribute = function (setRequest) { 3991 this.messageManager.sendUPCObject(setRequest); 3992 } 3993 3994 //============================================================================== 3995 // SERVER-SIDE DELETION 3996 //============================================================================== 3997 3998 net.user1.orbiter.AttributeManager.prototype.deleteAttribute = function (deleteRequest) { 3999 this.messageManager.sendUPCObject(deleteRequest); 4000 } 4001 4002 //============================================================================== 4003 // LOCAL RETRIEVAL 4004 //============================================================================== 4005 4006 net.user1.orbiter.AttributeManager.prototype.getAttribute = function (attrName, attrScope) { 4007 // Quit if there are no attrbutes. 4008 if (this.attributes == null) { 4009 return null; 4010 } else { 4011 return this.attributes.getAttribute(attrName, attrScope); 4012 } 4013 }; 4014 4015 net.user1.orbiter.AttributeManager.prototype.getAttributes = function () { 4016 return this.attributes.getAll(); 4017 } 4018 4019 net.user1.orbiter.AttributeManager.prototype.getAttributesByScope = function (scope) { 4020 return this.attributes.getByScope(scope); 4021 }; 4022 4023 //============================================================================== 4024 // LOCAL ASSIGNMENT 4025 //============================================================================== 4026 4027 /** 4028 * @private 4029 */ 4030 net.user1.orbiter.AttributeManager.prototype.setAttributeLocal = function (attrName, 4031 attrVal, 4032 attrScope, 4033 byClient) { 4034 var changed = this.attributes.setAttribute(attrName, attrVal, attrScope, byClient); 4035 if (!changed) { 4036 this.log.info(this.owner + " New attribute value for [" + attrName + "] matches old value. Not changed."); 4037 } 4038 }; 4039 4040 //============================================================================== 4041 // LOCAL REMOVAL 4042 //============================================================================== 4043 4044 /** 4045 * @private 4046 */ 4047 net.user1.orbiter.AttributeManager.prototype.removeAttributeLocal = function (attrName, 4048 attrScope, 4049 byClient) { 4050 var deleted = this.attributes.deleteAttribute(attrName, attrScope, byClient); 4051 if (!deleted) { 4052 this.log.info(owner + " Delete attribute failed for [" + attrName + "]. No such attribute."); 4053 } 4054 }; 4055 4056 /** 4057 * @private 4058 */ 4059 net.user1.orbiter.AttributeManager.prototype.removeAll = function () { 4060 this.attributes.clear(); 4061 } 4062 4063 //============================================================================== 4064 // EVENT REGISTRATION 4065 //============================================================================== 4066 4067 net.user1.orbiter.AttributeManager.prototype.registerAttributeListeners = function () { 4068 if (this.attributes != null) { 4069 // Can't use migrateListeners() here because we need to specify the listener priority (int.MAX_VALUE) 4070 this.attributes.addEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateAttributeListener, this, net.user1.utils.integer.MAX_VALUE); 4071 this.attributes.addEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteAttributeListener, this, net.user1.utils.integer.MAX_VALUE); 4072 } 4073 }; 4074 4075 net.user1.orbiter.AttributeManager.prototype.unregisterAttributeListeners = function () { 4076 if (this.attributes != null) { 4077 this.attributes.removeEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateAttributeListener, this); 4078 this.attributes.removeEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteAttributeListener, this); 4079 } 4080 } 4081 4082 //============================================================================== 4083 // EVENT LISTENERS 4084 //============================================================================== 4085 4086 net.user1.orbiter.AttributeManager.prototype.updateAttributeListener = function (e) { 4087 var attr = e.getChangedAttr(); 4088 4089 this.log.info(this.owner + " Setting attribute [" 4090 + ((attr.scope == null) ? "" : attr.scope + ".") 4091 + attr.name + "]. New value: [" + attr.value + "]. Old value: [" 4092 + attr.oldValue + "]."); 4093 this.owner.dispatchEvent(e); 4094 }; 4095 4096 net.user1.orbiter.AttributeManager.prototype.deleteAttributeListener = function (e) { 4097 this.owner.dispatchEvent(e); 4098 } 4099 4100 //============================================================================== 4101 // EVENT DISPATCHING 4102 //============================================================================== 4103 4104 /** 4105 * @private 4106 */ 4107 net.user1.orbiter.AttributeManager.prototype.fireSetAttributeResult = function (attrName, 4108 attrScope, 4109 status) { 4110 var attr = new net.user1.orbiter.Attribute(attrName, null, null, attrScope); 4111 4112 // Trigger event on listeners. 4113 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.SET_RESULT, 4114 attr, status); 4115 this.owner.dispatchEvent(e); 4116 }; 4117 4118 /** 4119 * @private 4120 */ 4121 net.user1.orbiter.AttributeManager.prototype.fireDeleteAttributeResult = function (attrName, 4122 attrScope, 4123 status) { 4124 var attr = new net.user1.orbiter.Attribute(attrName, null, null, attrScope); 4125 4126 // Trigger event on listeners. 4127 var e = new net.user1.orbiter.AttributeEvent(net.user1.orbiter.AttributeEvent.DELETE_RESULT, 4128 attr, status); 4129 this.owner.dispatchEvent(e); 4130 }; 4131 4132 // ============================================================================= 4133 // DISPOSAL 4134 // ============================================================================= 4135 4136 /** 4137 * @private 4138 */ 4139 net.user1.orbiter.AttributeManager.prototype.dispose = function () { 4140 this.messageManager = null; 4141 this.attributes = null; 4142 this.owner = null; 4143 this.log = null; 4144 }; 4145 //============================================================================== 4146 // ATTRIBUTE_OPTIONS CONSTANTS 4147 //============================================================================== 4148 /** @class 4149 @private */ 4150 net.user1.orbiter.AttributeOptions = new Object(); 4151 4152 /** @private */ 4153 net.user1.orbiter.AttributeOptions.FLAG_SHARED = 1 << 2; 4154 /** @private */ 4155 net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT = 1 << 3; 4156 /** @private */ 4157 net.user1.orbiter.AttributeOptions.FLAG_IMMUTABLE = 1 << 5; 4158 /** @private */ 4159 net.user1.orbiter.AttributeOptions.FLAG_EVALUATE = 1 << 8; 4160 //============================================================================== 4161 // CLASS DECLARATION 4162 //============================================================================== 4163 /** 4164 * @class 4165 * @extends net.user1.orbiter.snapshot.Snapshot 4166 */ 4167 net.user1.orbiter.snapshot.BannedListSnapshot = function () { 4168 // Call superconstructor 4169 net.user1.orbiter.snapshot.Snapshot.call(this); 4170 this.bannedList = null; 4171 this.method = net.user1.orbiter.UPC.GET_BANNED_LIST_SNAPSHOT; 4172 } 4173 4174 //============================================================================== 4175 // INHERITANCE 4176 //============================================================================== 4177 net.user1.utils.extend(net.user1.orbiter.snapshot.BannedListSnapshot, net.user1.orbiter.snapshot.Snapshot); 4178 4179 //============================================================================== 4180 // INSTANCE METHODS 4181 //============================================================================== 4182 /** 4183 * @private 4184 */ 4185 net.user1.orbiter.snapshot.BannedListSnapshot.prototype.setBannedList = function (value) { 4186 this.bannedList = value; 4187 }; 4188 4189 net.user1.orbiter.snapshot.BannedListSnapshot.prototype.getBannedList = function () { 4190 if (!this.bannedList) { 4191 return null; 4192 } 4193 return this.bannedList.slice(); 4194 }; 4195 //============================================================================== 4196 // CLASS DECLARATION 4197 //============================================================================== 4198 /** 4199 * @class 4200 */ 4201 net.user1.utils.CacheNode = function () { 4202 /** @field */ 4203 this.next; 4204 /** @field */ 4205 this.prev; 4206 /** @field */ 4207 this.key; 4208 /** @field */ 4209 this.value; 4210 }; 4211 //============================================================================== 4212 // CLASS DECLARATION 4213 //============================================================================== 4214 /** @class 4215 4216 The Client class dispatches the following events: 4217 4218 <ul class="summary"> 4219 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.JOIN_ROOM}</li> 4220 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.LEAVE_ROOM}</li> 4221 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE_ROOM}</li> 4222 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING_ROOM}</li> 4223 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE}</li> 4224 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING}</li> 4225 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE_RESULT}</li> 4226 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT}</li> 4227 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN}</li> 4228 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF}</li> 4229 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.SYNCHRONIZE}</li> 4230 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE}</li> 4231 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.UPDATE}</li> 4232 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.SET_RESULT}</li> 4233 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE_RESULT}</li> 4234 </ul> 4235 4236 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 4237 4238 @extends net.user1.events.EventDispatcher 4239 */ 4240 net.user1.orbiter.Client = function (clientID, 4241 clientManager, 4242 messageManager, 4243 roomManager, 4244 connectionManager, 4245 server, 4246 log) { 4247 // Call superconstructor 4248 net.user1.events.EventDispatcher.call(this); 4249 4250 this.clientID = ""; 4251 this._isSelf = false; 4252 this.account = null; 4253 this.disposed = false; 4254 4255 this.messageManager = messageManager; 4256 this.clientManager = clientManager; 4257 this.roomManager = roomManager; 4258 this.connectionManager = connectionManager; 4259 this.server = server; 4260 this.log = log; 4261 this.occupiedRoomIDs = new Array(); 4262 this.observedRoomIDs = new Array(); 4263 this.customClients = new Object(); 4264 this.attributeManager = new net.user1.orbiter.AttributeManager(this, this.messageManager, this.log); 4265 this.connectionState = net.user1.orbiter.ConnectionState.UNKNOWN; 4266 4267 this.setClientID(clientID); 4268 }; 4269 4270 //============================================================================== 4271 // INHERITANCE 4272 //============================================================================== 4273 net.user1.utils.extend(net.user1.orbiter.Client, net.user1.events.EventDispatcher); 4274 4275 //============================================================================== 4276 // STATIC VARIABLES 4277 //============================================================================== 4278 4279 /** @private */ 4280 net.user1.orbiter.Client.FLAG_ADMIN = 1 << 2; 4281 4282 // ============================================================================= 4283 // CLIENT ID 4284 // ============================================================================= 4285 net.user1.orbiter.Client.prototype.getClientID = function () { 4286 return this.clientID; 4287 }; 4288 4289 /** 4290 * @private 4291 */ 4292 net.user1.orbiter.Client.prototype.setClientID = function (id) { 4293 if (this.clientID != id) { 4294 this.clientID = id; 4295 } 4296 }; 4297 4298 net.user1.orbiter.Client.prototype.isSelf = function () { 4299 return this._isSelf; 4300 }; 4301 4302 /** 4303 * @private 4304 */ 4305 net.user1.orbiter.Client.prototype.setIsSelf = function () { 4306 this._isSelf = true; 4307 }; 4308 4309 // ============================================================================= 4310 // CONNECTION STATUS 4311 // ============================================================================= 4312 4313 net.user1.orbiter.Client.prototype.getConnectionState = function () { 4314 if (this.isSelf()) { 4315 if (this.disposed 4316 || this.clientManager.getInternalClient(this.getClientID()) == null) { 4317 return net.user1.orbiter.ConnectionState.NOT_CONNECTED; 4318 } else { 4319 return this.account != null ? this.account.getConnectionState() : this.connectionManager.getConnectionState(); 4320 } 4321 } else { 4322 if (this.connectionState != net.user1.orbiter.ConnectionState.UNKNOWN) { 4323 return this.connectionState; 4324 } else if (this.disposed 4325 || this.clientManager.getInternalClient(this.getClientID()) == null) { 4326 return net.user1.orbiter.ConnectionState.UNKNOWN; 4327 } else { 4328 return this.account != null ? this.account.getConnectionState() : net.user1.orbiter.ConnectionState.READY; 4329 } 4330 } 4331 }; 4332 4333 // Normally, this client's connection state is not assigned directly; it 4334 // it is deduced within getConnectionState(). But when Union 4335 // sends a u103, we know that this client has definitely disconnected from 4336 // the server, and this client object will never be reused, so CoreMessageListener 4337 // permanently assigns its connection state to NOT_CONNECTED. 4338 net.user1.orbiter.Client.prototype.setConnectionState = function (newState) { 4339 this.connectionState = newState; 4340 }; 4341 4342 // ============================================================================= 4343 // ROLES 4344 // ============================================================================= 4345 net.user1.orbiter.Client.prototype.isAdmin = function () { 4346 var rolesAttr = this.getAttribute(Tokens.ROLES_ATTR); 4347 var roles; 4348 if (rolesAttr != null) { 4349 return parseInt(rolesAttr) & net.user1.orbiter.Client.FLAG_ADMIN; 4350 } else { 4351 this.log.warn("[" + this.toString() + "] Could not determine admin status because the client is not synchronized."); 4352 return false; 4353 } 4354 }; 4355 4356 // ============================================================================= 4357 // OBSERVATION 4358 // ============================================================================= 4359 4360 net.user1.orbiter.Client.prototype.observe = function () { 4361 this.messageManager.sendUPC(net.user1.orbiter.UPC.OBSERVE_CLIENT, this.clientID); 4362 }; 4363 4364 net.user1.orbiter.Client.prototype.stopObserving = function () { 4365 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT, this.clientID); 4366 }; 4367 4368 // ============================================================================= 4369 // KICK / BAN 4370 // ============================================================================= 4371 4372 net.user1.orbiter.Client.prototype.kick = function () { 4373 if (this.getClientID() == null) { 4374 this.log.warn(this + " Kick attempt failed. Client not currently connected."); 4375 } 4376 this.messageManager.sendUPC(net.user1.orbiter.UPC.KICK_CLIENT, getClientID()); 4377 }; 4378 4379 net.user1.orbiter.Client.prototype.ban = function (duration, reason) { 4380 if (this.getClientID() == null) { 4381 this.log.warn(this + " Ban attempt failed. Client not currently connected."); 4382 } 4383 this.messageManager.sendUPC(net.user1.orbiter.UPC.BAN, null, getClientID(), duration.toString(), reason); 4384 }; 4385 4386 // ============================================================================= 4387 // CUSTOM CLASS MANAGEMENT 4388 // ============================================================================= 4389 4390 net.user1.orbiter.Client.prototype.setClientClass = function (scope, 4391 clientClass) { 4392 var fallbackClasses = Array.prototype.slice.call(arguments).slice(2); 4393 if (!this.isSelf()) { 4394 throw new Error("Custom client class assignment failed for : " 4395 + clientClass + ". A custom" 4396 + " class can be set for the current client (" 4397 + " i.e., ClientManager.self()) only."); 4398 } 4399 4400 fallbackClasses.unshift(clientClass); 4401 var classList = fallbackClasses.join(" "); 4402 setAttribute(Tokens.CUSTOM_CLASS_ATTR, classList, scope); 4403 }; 4404 4405 /** 4406 * @private 4407 */ 4408 net.user1.orbiter.Client.prototype.getCustomClient = function (scope) { 4409 var customClient; 4410 4411 // If the custom client already exists for the specified scope, return it. 4412 customClient = this.customClients[scope]; 4413 if (customClient != null) { 4414 return customClient; 4415 } 4416 4417 // Look for a custom class for the given scope, and create a custom client 4418 if (scope == null) { 4419 return this.setGlobalCustomClient(); 4420 } else { 4421 return this.setCustomClientForScope(scope); 4422 } 4423 }; 4424 4425 /** 4426 * @private 4427 */ 4428 net.user1.orbiter.Client.prototype.setGlobalCustomClient = function () { 4429 var defaultClientClass; 4430 var globalDefaultClientClass; 4431 var customClient; 4432 4433 // If this client has a default custom client class, use it 4434 defaultClientClass = this.getClientClass(null); 4435 if (defaultClientClass != null) { 4436 return this.createCustomClient(defaultClientClass, null); 4437 } 4438 4439 // No global class was set on the client, so check for a system-wide default 4440 globalDefaultClientClass = this.clientManager.getDefaultClientClass(); 4441 if (globalDefaultClientClass == null) { 4442 // No global custom client class exists 4443 return null; 4444 } else { 4445 // Global default class exists 4446 return this.createCustomClient(globalDefaultClientClass, null); 4447 } 4448 }; 4449 4450 /** 4451 * @private 4452 */ 4453 net.user1.orbiter.Client.prototype.setCustomClientForScope = function (scope) { 4454 var theRoom; 4455 var clientClass; 4456 var roomDefaultClientClass; 4457 var globalDefaultClientClass; 4458 4459 // If this client has a default custom client class, use it 4460 clientClass = this.getClientClass(scope); 4461 if (clientClass != null) { 4462 return this.createCustomClient(clientClass, scope); 4463 } 4464 4465 // No class was set on the client for the scope, so check for a room default 4466 theRoom = this.roomManager.getRoom(scope); 4467 if (theRoom != null) { 4468 roomDefaultClientClass = theRoom.getDefaultClientClass(); 4469 if (roomDefaultClientClass != null) { 4470 return this.createCustomClient(roomDefaultClientClass, scope); 4471 } 4472 } 4473 4474 // No class was set on the room for the scope, so check for a system-wide default 4475 // If a custom global client already exists, return it. 4476 var customClient = this.customClients[null]; 4477 if (customClient != null) { 4478 return customClient; 4479 } else { 4480 globalDefaultClientClass = this.clientManager.getDefaultClientClass(); 4481 if (globalDefaultClientClass == null) { 4482 // No global custom client class exists 4483 return null; 4484 } else { 4485 // Global default class exists 4486 return this.createCustomClient(globalDefaultClientClass, null); 4487 } 4488 } 4489 }; 4490 4491 /** 4492 * @private 4493 */ 4494 net.user1.orbiter.Client.prototype.getClientClass = function (scope) { 4495 var clientClassNames = this.getAttribute(net.user1.orbiter.Tokens.CUSTOM_CLASS_ATTR, scope); 4496 var clientClassList; 4497 4498 // Convert the custom class names to an array for processing 4499 if (clientClassNames != null) { 4500 clientClassList = clientClassNames.split(" "); 4501 } 4502 4503 // Search for a matching class definition. The first definition that's 4504 // found is returned. 4505 var className; 4506 if (clientClassList != null) { 4507 for (var i = 0; i < clientClassList.length; i++) { 4508 try { 4509 var theClass = net.user1.utils.resolveMemberExpression(className); 4510 if (!theClass instanceof Function) { 4511 this.log.debug(this.toString() + ": Definition for client class [" + className + "] is not a constructor function."); 4512 continue; 4513 } 4514 return theClass; 4515 } catch (e) { 4516 this.log.debug(this.toString() + ": No definition found for client class [" + className + "]"); 4517 continue; 4518 } 4519 } 4520 } 4521 return null; 4522 }; 4523 4524 /** 4525 * @private 4526 */ 4527 net.user1.orbiter.Client.prototype.createCustomClient = function (wrapperClass, scope) { 4528 var customClient; 4529 4530 // Wrap the client 4531 customClient = new wrapperClass(); 4532 this.customClients[scope] = customClient; 4533 4534 // Do custom client setup 4535 if (customClient instanceof CustomClient) { 4536 customClient.setClient(this); 4537 customClient.init(); 4538 return customClient; 4539 } else { 4540 this.log.debug("[CLIENT_MANAGER] Custom client class [" + wrapperClass + "] does not " 4541 + " extend CustomClient. Assuming specified class will manually " 4542 + " compose its own Client instance for client ID: " + clientID 4543 + ". See Client.setClientClass()."); 4544 return customClient; 4545 } 4546 }; 4547 4548 // ============================================================================= 4549 // ROOM MANAGEMENT 4550 // ============================================================================= 4551 4552 /** 4553 * @private 4554 */ 4555 net.user1.orbiter.Client.prototype.removeOccupiedRoomID = function (roomID) { 4556 if (this.isInRoom(roomID) && roomID != null) { 4557 this.occupiedRoomIDs.splice(net.user1.utils.ArrayUtil.indexOf(this.occupiedRoomIDs, roomID), 1); 4558 return true; 4559 } else { 4560 return false; 4561 } 4562 }; 4563 4564 /** 4565 * @private 4566 */ 4567 net.user1.orbiter.Client.prototype.removeObservedRoomID = function (roomID) { 4568 if (this.isObservingRoom(roomID) && roomID != null) { 4569 this.observedRoomIDs.splice(net.user1.utils.ArrayUtil.indexOf(this.observedRoomIDs, roomID), 1); 4570 return true; 4571 } else { 4572 return false; 4573 } 4574 }; 4575 4576 /** 4577 * @private 4578 */ 4579 net.user1.orbiter.Client.prototype.addOccupiedRoomID = function (roomID) { 4580 if (!this.isInRoom(roomID) && roomID != null) { 4581 this.log.info(this.toString() + " added occupied room ID [" + roomID + "]."); 4582 this.occupiedRoomIDs.push(roomID); 4583 } 4584 }; 4585 4586 /** 4587 * @private 4588 */ 4589 net.user1.orbiter.Client.prototype.addObservedRoomID = function (roomID) { 4590 if (!this.isObservingRoom(roomID) && roomID != null) { 4591 this.log.info("Client [" + this.getClientID() + "] added observed room ID [" + roomID + "]."); 4592 this.observedRoomIDs.push(roomID); 4593 } 4594 }; 4595 4596 net.user1.orbiter.Client.prototype.isInRoom = function (roomID) { 4597 return net.user1.utils.ArrayUtil.indexOf(this.getOccupiedRoomIDs(), roomID) != -1; 4598 }; 4599 4600 net.user1.orbiter.Client.prototype.isObservingRoom = function (roomID) { 4601 return net.user1.utils.ArrayUtil.indexOf(this.getObservedRoomIDs(), roomID) != -1; 4602 }; 4603 4604 net.user1.orbiter.Client.prototype.getOccupiedRoomIDs = function () { 4605 var ids; 4606 if (this.clientManager.isObservingClient(this.getClientID())) { 4607 // This client is under observation, so its occupiedRoomIDs array is 4608 // 100% accurate. 4609 return this.occupiedRoomIDs == null ? [] : this.occupiedRoomIDs.slice(0); 4610 } else { 4611 // This client is not under observation, so the current client can only 4612 // deduce this client's occupied room list based on its current sphere of awareness. 4613 ids = []; 4614 var knownRooms = this.roomManager.getRooms(); 4615 var numKnownRooms = knownRooms.length; 4616 var room; 4617 for (var i = 0; i < numKnownRooms; i++) { 4618 room = knownRooms[i]; 4619 if (room.clientIsInRoom(this.getClientID())) { 4620 ids.push(room.getRoomID()); 4621 } 4622 } 4623 return ids; 4624 } 4625 }; 4626 4627 net.user1.orbiter.Client.prototype.getObservedRoomIDs = function () { 4628 var ids; 4629 if (this.clientManager.isObservingClient(this.getClientID())) { 4630 // This client is under observation, so its occupiedRoomIDs array is 4631 // 100% accurate. 4632 return this.observedRoomIDs == null ? [] : this.observedRoomIDs.slice(0); 4633 } else { 4634 // This client is not under observation, so the current client can only 4635 // deduce this client's occupied room list based on its current sphere of awareness. 4636 ids = []; 4637 var knownRooms = this.roomManager.getRooms(); 4638 var numKnownRooms = knownRooms.length; 4639 var room; 4640 for (var i = 0; i < numKnownRooms; i++) { 4641 room = knownRooms[i]; 4642 if (room.clientIsObservingRoom(this.getClientID())) { 4643 ids.push(room.getRoomID()); 4644 } 4645 } 4646 return ids; 4647 } 4648 }; 4649 4650 net.user1.orbiter.Client.prototype.getUpdateLevels = function (roomID) { 4651 var levels; 4652 var levelsAttr = this.getAttribute("_UL", roomID); 4653 4654 if (levelsAttr != null) { 4655 levels = new net.user1.orbiter.UpdateLevels(); 4656 levels.fromInt(parseInt(levelsAttr)); 4657 return levels; 4658 } else { 4659 return null; 4660 } 4661 }; 4662 4663 // ============================================================================= 4664 // BUILT-IN ATTRIBUTE RETRIEVAL 4665 // ============================================================================= 4666 4667 net.user1.orbiter.Client.prototype.getIP = function () { 4668 return this.getAttribute("_IP"); 4669 }; 4670 4671 net.user1.orbiter.Client.prototype.getConnectTime = function () { 4672 var ct = this.getAttribute("_CT"); 4673 return ct == null ? NaN : parseFloat(ct); 4674 }; 4675 4676 net.user1.orbiter.Client.prototype.getPing = function () { 4677 var ping = this.getAttribute("_PING"); 4678 return ping == null ? -1 : parseInt(ping); 4679 }; 4680 4681 net.user1.orbiter.Client.prototype.getTimeOnline = function () { 4682 return this.server == null ? NaN : this.server.getServerTime() - this.getConnectTime(); 4683 }; 4684 4685 // ============================================================================= 4686 // MESSAGING 4687 // ============================================================================= 4688 4689 net.user1.orbiter.Client.prototype.sendMessage = function (messageName) { 4690 if (this.clientManager == null) { 4691 return; 4692 } 4693 // Delegate to ClientManager 4694 var rest = Array.prototype.slice.call(arguments).slice(1); 4695 var args = [messageName, 4696 [this.getClientID()], 4697 null]; 4698 this.clientManager.sendMessage.apply(this.clientManager, args.concat(rest)); 4699 }; 4700 4701 // ============================================================================= 4702 // ATTRIBUTES: PUBLIC API 4703 // ============================================================================= 4704 net.user1.orbiter.Client.prototype.setAttribute = function (attrName, 4705 attrValue, 4706 attrScope, 4707 isShared, 4708 evaluate) { 4709 attrScope = attrScope == undefined ? null : attrScope; 4710 isShared = isShared == undefined ? true : isShared; 4711 evaluate = evaluate == undefined ? false : evaluate; 4712 4713 // Create an integer to hold the attribute options. 4714 var attrOptions = (isShared ? net.user1.orbiter.AttributeOptions.FLAG_SHARED : 0) 4715 | (evaluate ? net.user1.orbiter.AttributeOptions.FLAG_EVALUATE : 0); 4716 // Make the SetClientAttr UPC first so inputs are validated 4717 var setClientAttr = new net.user1.orbiter.upc.SetClientAttr(attrName, attrValue, attrOptions, attrScope, this.getClientID()); 4718 4719 // Set the attribute locally now, unless: 4720 // -it is another client's attribute 4721 // -it is the current client's attribute, and the value has changed 4722 if (!(!this.isSelf() || evaluate)) { 4723 // Set the attribute locally 4724 this.attributeManager.setAttributeLocal(attrName, attrValue, attrScope, this); 4725 } 4726 4727 // Set the attribute on the server. 4728 this.messageManager.sendUPCObject(setClientAttr); 4729 }; 4730 4731 net.user1.orbiter.Client.prototype.deleteAttribute = function (attrName, attrScope) { 4732 var deleteRequest = new net.user1.orbiter.upc.RemoveClientAttr(this.getClientID(), null, attrName, attrScope); 4733 this.attributeManager.deleteAttribute(deleteRequest); 4734 }; 4735 4736 net.user1.orbiter.Client.prototype.getAttribute = function (attrName, attrScope) { 4737 return this.attributeManager.getAttribute(attrName, attrScope); 4738 }; 4739 4740 net.user1.orbiter.Client.prototype.getAttributes = function () { 4741 return this.attributeManager.getAttributes(); 4742 }; 4743 4744 net.user1.orbiter.Client.prototype.getAttributesByScope = function (scope) { 4745 return this.attributeManager.getAttributesByScope(scope); 4746 }; 4747 4748 // ============================================================================= 4749 // SYNCHRONIZATION 4750 // ============================================================================= 4751 4752 /** 4753 * @private 4754 */ 4755 net.user1.orbiter.Client.prototype.synchronize = function (clientManifest) { 4756 var scopes; 4757 this.synchronizeOccupiedRoomIDs(clientManifest.occupiedRoomIDs); 4758 this.synchronizeObservedRoomIDs(clientManifest.observedRoomIDs); 4759 4760 // Synchronize Client attributes 4761 scopes = clientManifest.transientAttributes.getScopes(); 4762 for (var i = scopes.length; --i >= 0;) { 4763 this.attributeManager.getAttributeCollection().synchronizeScope(scopes[i], clientManifest.transientAttributes); 4764 } 4765 // Synchronize UserAccount attributes 4766 if (this.account != null) { 4767 scopes = clientManifest.persistentAttributes.getScopes(); 4768 for (i = scopes.length; --i >= 0;) { 4769 this.account.getAttributeManager().getAttributeCollection().synchronizeScope(scopes[i], clientManifest.persistentAttributes); 4770 } 4771 } 4772 }; 4773 4774 /** 4775 * @private 4776 */ 4777 net.user1.orbiter.Client.prototype.synchronizeOccupiedRoomIDs = function (newOccupiedRoomIDs) { 4778 if (newOccupiedRoomIDs == null) { 4779 // Nothing to synchronize 4780 return; 4781 } 4782 4783 // Remove any rooms that are not in the new list 4784 var roomID; 4785 for (var i = this.occupiedRoomIDs.length; --i >= 0;) { 4786 roomID = this.occupiedRoomIDs[i]; 4787 if (net.user1.utils.ArrayUtil.indexOf(newOccupiedRoomIDs, roomID) == -1) { 4788 this.removeOccupiedRoomID(roomID); 4789 } 4790 } 4791 4792 // Add any rooms that are not in the old list (existing room IDs are ignored) 4793 for (i = newOccupiedRoomIDs.length; --i >= 0;) { 4794 roomID = newOccupiedRoomIDs[i]; 4795 this.addOccupiedRoomID(roomID); 4796 } 4797 }; 4798 4799 /** 4800 * @private 4801 */ 4802 net.user1.orbiter.Client.prototype.synchronizeObservedRoomIDs = function (newObservedRoomIDs) { 4803 if (newObservedRoomIDs == null) { 4804 // Nothing to synchronize 4805 return; 4806 } 4807 // Remove any rooms that are not in the new list 4808 var roomID; 4809 for (var i = this.observedRoomIDs.length; --i >= 0;) { 4810 roomID = this.observedRoomIDs[i]; 4811 if (net.user1.utils.ArrayUtil.indexOf(newObservedRoomIDs, roomID) == -1) { 4812 this.removeObservedRoomID(roomID); 4813 } 4814 } 4815 4816 // Add any rooms that are not in the old list (existing room IDs are ignored) 4817 for (i = newObservedRoomIDs.length; --i >= 0;) { 4818 roomID = newObservedRoomIDs[i]; 4819 this.addObservedRoomID(roomID); 4820 } 4821 }; 4822 4823 // ============================================================================= 4824 // DEPENDENCIES 4825 // ============================================================================= 4826 4827 /** 4828 * @private 4829 */ 4830 net.user1.orbiter.Client.prototype.getAttributeManager = function () { 4831 return this.attributeManager; 4832 }; 4833 4834 net.user1.orbiter.Client.prototype.getClientManager = function () { 4835 return this.clientManager; 4836 }; 4837 4838 net.user1.orbiter.Client.prototype.getAccount = function () { 4839 return this.account; 4840 }; 4841 4842 /** 4843 * @private 4844 */ 4845 net.user1.orbiter.Client.prototype.setAccount = function (value) { 4846 if (value == null) { 4847 this.account = null; 4848 } else { 4849 if (this.account != value) { 4850 this.account = value; 4851 this.account.setClient(this); 4852 } 4853 } 4854 }; 4855 4856 // ============================================================================= 4857 // TOSTRING 4858 // ============================================================================= 4859 4860 net.user1.orbiter.Client.prototype.toString = function () { 4861 return "[CLIENT clientID: " + this.getClientID() + ", userID: " + (this.account == null ? "" : this.account.getUserID()) + "]"; 4862 }; 4863 4864 // ============================================================================= 4865 // EVENT DISPATCHING 4866 // ============================================================================= 4867 4868 /** 4869 * @private 4870 */ 4871 net.user1.orbiter.Client.prototype.fireJoinRoom = function (room, roomID) { 4872 this.log.debug(this + " triggering ClientEvent.JOIN_ROOM event."); 4873 // Trigger event on listeners. 4874 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.JOIN_ROOM, 4875 null, room, roomID, this); 4876 this.dispatchEvent(e); 4877 }; 4878 4879 /** 4880 * @private 4881 */ 4882 net.user1.orbiter.Client.prototype.fireLeaveRoom = function (room, roomID) { 4883 this.log.debug(this + " triggering ClientEvent.LEAVE_ROOM event."); 4884 // Trigger event on listeners. 4885 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.LEAVE_ROOM, 4886 null, room, roomID, this); 4887 this.dispatchEvent(e); 4888 }; 4889 4890 /** 4891 * @private 4892 */ 4893 net.user1.orbiter.Client.prototype.fireObserveRoom = function (room, roomID) { 4894 this.log.debug(this + " triggering ClientEvent.OBSERVE_ROOM event."); 4895 // Trigger event on listeners. 4896 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE_ROOM, 4897 null, room, roomID, this); 4898 this.dispatchEvent(e); 4899 }; 4900 4901 /** 4902 * @private 4903 */ 4904 net.user1.orbiter.Client.prototype.fireStopObservingRoom = function (room, roomID) { 4905 this.log.debug(this + " triggering ClientEvent.STOP_OBSERVING_ROOM event."); 4906 // Trigger event on listeners. 4907 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING_ROOM, 4908 null, room, roomID, this); 4909 this.dispatchEvent(e); 4910 }; 4911 4912 /** 4913 * @private 4914 */ 4915 net.user1.orbiter.Client.prototype.fireObserve = function () { 4916 // Trigger event on listeners. 4917 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE, null, null, null, this); 4918 this.dispatchEvent(e); 4919 }; 4920 4921 /** 4922 * @private 4923 */ 4924 net.user1.orbiter.Client.prototype.fireStopObserving = function () { 4925 // Trigger event on listeners. 4926 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING, null, null, null, this); 4927 this.dispatchEvent(e); 4928 }; 4929 4930 /** 4931 * @private 4932 */ 4933 net.user1.orbiter.Client.prototype.fireObserveResult = function (status) { 4934 // Trigger event on listeners. 4935 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE_RESULT, 4936 null, null, null, this, status); 4937 this.dispatchEvent(e); 4938 }; 4939 4940 /** 4941 * @private 4942 */ 4943 net.user1.orbiter.Client.prototype.fireStopObservingResult = function (status) { 4944 // Trigger event on listeners. 4945 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT, 4946 null, null, null, this, status); 4947 this.dispatchEvent(e); 4948 }; 4949 4950 /** 4951 * @private 4952 */ 4953 net.user1.orbiter.Client.prototype.fireLogin = function () { 4954 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN, 4955 net.user1.orbiter.Status.SUCCESS, this.getAccount().getUserID(), this.getClientID()); 4956 this.dispatchEvent(e); 4957 }; 4958 4959 /** 4960 * @private 4961 */ 4962 net.user1.orbiter.Client.prototype.fireLogoff = function (userID) { 4963 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF, 4964 net.user1.orbiter.Status.SUCCESS, userID, this.getClientID()); 4965 this.dispatchEvent(e); 4966 }; 4967 4968 /** 4969 * @private 4970 */ 4971 net.user1.orbiter.Client.prototype.fireSynchronize = function () { 4972 // Trigger event on listeners. 4973 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.SYNCHRONIZE, null, null, null, this); 4974 this.dispatchEvent(e); 4975 }; 4976 4977 // ============================================================================= 4978 // DISPOSAL 4979 // ============================================================================= 4980 4981 net.user1.orbiter.Client.prototype.dispose = function () { 4982 this.occupiedRoomIDs = null; 4983 this.attributeManager.dispose(); 4984 this.attributeManager = null; 4985 this.clientID = null; 4986 this.log = null; 4987 this.account = null; 4988 this.customClients = null; 4989 this.messageManager = null; 4990 this.clientManager = null; 4991 this.roomManager = null; 4992 this.server = null; 4993 this.disposed = true; 4994 }; 4995 //============================================================================== 4996 // CLASS DECLARATION 4997 //============================================================================== 4998 /** 4999 * @class 5000 * @extends net.user1.orbiter.snapshot.Snapshot 5001 */ 5002 net.user1.orbiter.snapshot.ClientCountSnapshot = function () { 5003 // Call superconstructor 5004 net.user1.orbiter.snapshot.Snapshot.call(this); 5005 this.count = 0; 5006 this.method = net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT; 5007 this.hasStatus = true; 5008 }; 5009 5010 //============================================================================== 5011 // INHERITANCE 5012 //============================================================================== 5013 net.user1.utils.extend(net.user1.orbiter.snapshot.ClientCountSnapshot, net.user1.orbiter.snapshot.Snapshot); 5014 5015 //============================================================================== 5016 // INSTANCE METHODS 5017 //============================================================================== 5018 /** 5019 * @private 5020 */ 5021 net.user1.orbiter.snapshot.ClientCountSnapshot.prototype.setCount = function (value) { 5022 this.count = value; 5023 }; 5024 5025 net.user1.orbiter.snapshot.ClientCountSnapshot.prototype.getCount = function () { 5026 return this.count; 5027 }; 5028 //============================================================================== 5029 // CLASS DECLARATION 5030 //============================================================================== 5031 /** @class 5032 @extends net.user1.events.Event 5033 */ 5034 net.user1.orbiter.ClientEvent = function (type, 5035 changedAttr, 5036 room, 5037 roomID, 5038 client, 5039 status, 5040 clientID) { 5041 net.user1.events.Event.call(this, type); 5042 5043 this.changedAttr = changedAttr; 5044 this.room = room; 5045 this.roomID = roomID; 5046 this.client = client; 5047 this.status = status; 5048 this.clientID = clientID; 5049 }; 5050 5051 //============================================================================== 5052 // INHERITANCE 5053 //============================================================================== 5054 net.user1.utils.extend(net.user1.orbiter.ClientEvent, net.user1.events.Event); 5055 5056 //============================================================================== 5057 // STATIC VARIABLES 5058 //============================================================================== 5059 /** @constant */ 5060 net.user1.orbiter.ClientEvent.JOIN_ROOM = "JOIN_ROOM"; 5061 /** @constant */ 5062 net.user1.orbiter.ClientEvent.LEAVE_ROOM = "LEAVE_ROOM"; 5063 /** @constant */ 5064 net.user1.orbiter.ClientEvent.OBSERVE_ROOM = "OBSERVE_ROOM"; 5065 /** @constant */ 5066 net.user1.orbiter.ClientEvent.STOP_OBSERVING_ROOM = "STOP_OBSERVING_ROOM"; 5067 /** @constant */ 5068 net.user1.orbiter.ClientEvent.OBSERVE = "OBSERVE"; 5069 /** @constant */ 5070 net.user1.orbiter.ClientEvent.STOP_OBSERVING = "STOP_OBSERVING"; 5071 /** @constant */ 5072 net.user1.orbiter.ClientEvent.OBSERVE_RESULT = "OBSERVE_RESULT"; 5073 /** @constant */ 5074 net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT = "STOP_OBSERVING_RESULT"; 5075 /** @constant */ 5076 net.user1.orbiter.ClientEvent.SYNCHRONIZE = "SYNCHRONIZE"; 5077 5078 net.user1.orbiter.ClientEvent.prototype.getClient = function () { 5079 return this.client; 5080 }; 5081 5082 net.user1.orbiter.ClientEvent.prototype.getClientID = function () { 5083 if (this.client != null) { 5084 return this.client.getClientID(); 5085 } else { 5086 return this.clientID; 5087 } 5088 }; 5089 5090 net.user1.orbiter.ClientEvent.prototype.getRoom = function () { 5091 return this.room; 5092 }; 5093 5094 net.user1.orbiter.ClientEvent.prototype.getRoomID = function () { 5095 return this.roomID; 5096 } 5097 5098 net.user1.orbiter.ClientEvent.prototype.getStatus = function () { 5099 return this.status; 5100 }; 5101 5102 net.user1.orbiter.ClientEvent.prototype.toString = function () { 5103 return "[object ClientEvent]"; 5104 }; 5105 //============================================================================== 5106 // CLASS DECLARATION 5107 //============================================================================== 5108 /** 5109 * @class 5110 * @extends net.user1.orbiter.snapshot.Snapshot 5111 */ 5112 net.user1.orbiter.snapshot.ClientListSnapshot = function () { 5113 // Call superconstructor 5114 net.user1.orbiter.snapshot.Snapshot.call(this); 5115 this.clientList; 5116 this.method = net.user1.orbiter.UPC.GET_CLIENTLIST_SNAPSHOT; 5117 }; 5118 5119 //============================================================================== 5120 // INHERITANCE 5121 //============================================================================== 5122 net.user1.utils.extend(net.user1.orbiter.snapshot.ClientListSnapshot, net.user1.orbiter.snapshot.Snapshot); 5123 5124 //============================================================================== 5125 // INSTANCE METHODS 5126 //============================================================================== 5127 /** 5128 * @private 5129 */ 5130 net.user1.orbiter.snapshot.ClientListSnapshot.prototype.setClientList = function (value) { 5131 this.clientList = value; 5132 }; 5133 5134 net.user1.orbiter.snapshot.ClientListSnapshot.prototype.getClientList = function () { 5135 if (!this.clientList) { 5136 return null; 5137 } 5138 return this.clientList.slice(); 5139 } 5140 //============================================================================== 5141 // CLASS DECLARATION 5142 //============================================================================== 5143 /** @class 5144 5145 The ClientManager class dispatches the following events: 5146 5147 <ul class="summary"> 5148 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.CREATE_ACCOUNT_RESULT}</li> 5149 5150 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE}</li> 5151 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING}</li> 5152 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED}</li> 5153 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED}</li> 5154 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT}</li> 5155 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT}</li> 5156 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.OBSERVE_RESULT}</li> 5157 <li class="fixedFont">{@link net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT}</li> 5158 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.KICK_RESULT}</li> 5159 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.BAN_RESULT}</li> 5160 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.UNBAN_RESULT}</li> 5161 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT}</li> 5162 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT}</li> 5163 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED}</li> 5164 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED}</li> 5165 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST}</li> 5166 <li class="fixedFont">{@link net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE}</li> 5167 </ul> 5168 5169 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 5170 5171 @extends net.user1.events.EventDispatcher 5172 */ 5173 net.user1.orbiter.ClientManager = function (roomManager, 5174 accountManager, 5175 connectionManager, 5176 messageManager, 5177 server, 5178 log) { 5179 // Call superconstructor 5180 net.user1.events.EventDispatcher.call(this); 5181 5182 this.selfReference = null; 5183 this.defaultClientClass = null; 5184 this.lifetimeClientsRequested = 0; 5185 5186 this._isWatchingForClients; 5187 this._isWatchingForUsers; 5188 this._isWatchingForBannedAddresses; 5189 5190 this.watchedClients = new net.user1.orbiter.ClientSet(); 5191 this.observedClients = new net.user1.orbiter.ClientSet(); 5192 this.bannedAddresses = []; 5193 this.clientCache = new net.user1.utils.LRUCache(5000); 5194 5195 this.roomManager = roomManager; 5196 this.accountManager = accountManager; 5197 this.connectionManager = connectionManager; 5198 this.messageManager = messageManager; 5199 this.server = server; 5200 this.log = log; 5201 }; 5202 5203 //============================================================================== 5204 // INHERITANCE 5205 //============================================================================== 5206 net.user1.utils.extend(net.user1.orbiter.ClientManager, net.user1.events.EventDispatcher); 5207 5208 //============================================================================== 5209 // CLIENT OBJECT CREATION AND ACCESS 5210 //============================================================================== 5211 5212 /** 5213 * @private 5214 */ 5215 net.user1.orbiter.ClientManager.prototype.requestClient = function (clientID) { 5216 var client; 5217 5218 if (clientID == null || clientID === "") { 5219 throw new Error("[CLIENT_MANAGER] requestClient() called with empty clientID."); 5220 } 5221 5222 client = this.getInternalClient(clientID); 5223 5224 // If the client isn't already known 5225 if (client === null) { 5226 client = new net.user1.orbiter.Client(clientID, this, this.messageManager, this.roomManager, this.connectionManager, this.server, this.log); 5227 this.lifetimeClientsRequested++; 5228 this.clientCache.put(clientID, client); 5229 } 5230 5231 return client; 5232 } 5233 5234 net.user1.orbiter.ClientManager.prototype.getClient = function (clientID, scope) { 5235 var theClient; 5236 var theCustomClient; 5237 5238 if (clientID === "" || clientID == null) { 5239 throw new Error("ClientManager.getClient() failed. Client ID must not be null or the" + 5240 " empty string."); 5241 } 5242 5243 theClient = this.getInternalClient(clientID); 5244 if (theClient === null) { 5245 this.log.debug("[CLIENT_MANAGER] getClient() called for unknown client ID [" 5246 + clientID + "]."); 5247 return null; 5248 } else { 5249 theCustomClient = theClient.getCustomClient(scope); 5250 return theCustomClient === null ? theClient : theCustomClient; 5251 } 5252 }; 5253 5254 net.user1.orbiter.ClientManager.prototype.getClients = function () { 5255 // Get all internal clients 5256 var clients = this.getInternalClients(); 5257 var clientsList = new Array(); 5258 var customClient; 5259 5260 // Replace internal clients with custom clients where available 5261 var client; 5262 for (var clientID in clients) { 5263 client = clients[clientID]; 5264 customClient = client.getCustomClient(null); 5265 if (customClient != null) { 5266 clientsList.push(customClient); 5267 } else { 5268 clientsList.push(client); 5269 } 5270 } 5271 return clientsList; 5272 } 5273 5274 net.user1.orbiter.ClientManager.prototype.getInternalClients = function () { 5275 var clients = net.user1.utils.ObjectUtil.combine(this.roomManager.getAllClients(), 5276 this.accountManager.getClientsForObservedAccounts(), 5277 this.observedClients.getAll(), 5278 this.watchedClients.getAll()); 5279 if (this.selfReference != null) { 5280 clients[this.selfReference.getClientID()] = this.selfReference; 5281 } 5282 return clients; 5283 }; 5284 5285 net.user1.orbiter.ClientManager.prototype.getInternalClient = function (clientID) { 5286 var theClient; 5287 5288 // Error checking 5289 if (clientID === "" || clientID == null) { 5290 throw new Error("[CLIENT_MANAGER] this.getInternalClient() failed. Client ID must not be null or the" + 5291 " empty string."); 5292 } 5293 5294 theClient = this.clientCache.get(clientID); 5295 5296 if (theClient != null) { 5297 return theClient; 5298 } else { 5299 // Find the client... 5300 5301 // Look in rooms 5302 var clients = this.roomManager.getAllClients(); 5303 theClient = clients[clientID]; 5304 if (theClient != null) { 5305 this.clientCache.put(clientID, theClient); 5306 return theClient; 5307 } 5308 5309 // Look in observed accounts 5310 clients = this.accountManager.getClientsForObservedAccounts(); 5311 theClient = clients[clientID]; 5312 if (theClient != null) { 5313 this.clientCache.put(clientID, theClient); 5314 return theClient; 5315 } 5316 5317 // Look in observed clients 5318 theClient = this.observedClients.getByClientID(clientID); 5319 if (theClient != null) { 5320 this.clientCache.put(clientID, theClient); 5321 return theClient; 5322 } 5323 5324 // Look in watched clients 5325 theClient = this.watchedClients.getByClientID(clientID); 5326 if (theClient != null) { 5327 this.clientCache.put(clientID, theClient); 5328 return theClient; 5329 } 5330 } 5331 5332 // Client not found 5333 return null; 5334 } 5335 5336 net.user1.orbiter.ClientManager.prototype.getClientByUserID = function (userID, scope) { 5337 var theClient; 5338 var theCustomClient; 5339 var account; 5340 5341 if (userID === "" || userID == null) { 5342 throw new Error("ClientManager.getClientByUserID() failed. User ID must not be null or the" + 5343 " empty string."); 5344 } 5345 5346 // Search for the client in all known clients 5347 var client; 5348 var clients = this.getInternalClients(); 5349 for (var clientID in clients) { 5350 client = clients[clientID]; 5351 account = client.getAccount(); 5352 if (account != null && account.getUserID() === userID) { 5353 theClient = client; 5354 break; 5355 } 5356 } 5357 5358 if (theClient === null) { 5359 this.log.debug("[CLIENT_MANAGER] getClientByUserID() called for unknown user ID [" 5360 + userID + "]."); 5361 return null; 5362 } else { 5363 theCustomClient = theClient.getCustomClient(scope); 5364 return theCustomClient === null ? theClient : theCustomClient; 5365 } 5366 }; 5367 5368 net.user1.orbiter.ClientManager.prototype.getClientByAttribute = function (attributeName, 5369 attributeValue, 5370 attributeScope, 5371 roomScope) { 5372 var theCustomClient; 5373 5374 // Validate 5375 if (attributeName == null || attributeName === "") { 5376 return null; 5377 } 5378 5379 // Search for the client in all known clients 5380 var client; 5381 var clients = this.getInternalClients(); 5382 for (var clientID in clients) { 5383 client = clients[clientID]; 5384 if (client.getAttribute(attributeName, attributeScope) 5385 === attributeValue) { 5386 theCustomClient = client.getCustomClient(roomScope); 5387 return theCustomClient === null ? client : theCustomClient; 5388 } 5389 } 5390 return null; 5391 }; 5392 5393 net.user1.orbiter.ClientManager.prototype.clientIsKnown = function (clientID) { 5394 return this.getInternalClients()[clientID] !== null; 5395 }; 5396 5397 // ============================================================================= 5398 // WATCHED CLIENTS 5399 // ============================================================================= 5400 5401 net.user1.orbiter.ClientManager.prototype.watchForClients = function () { 5402 this.messageManager.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_CLIENTS); 5403 }; 5404 5405 net.user1.orbiter.ClientManager.prototype.stopWatchingForClients = function () { 5406 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS); 5407 }; 5408 5409 net.user1.orbiter.ClientManager.prototype.isWatchingForClients = function () { 5410 return this._isWatchingForClients; 5411 }; 5412 5413 net.user1.orbiter.ClientManager.prototype.hasWatchedClient = function (clientID) { 5414 return this.watchedClients.containsClientID(clientID); 5415 }; 5416 5417 /** 5418 * @private 5419 */ 5420 net.user1.orbiter.ClientManager.prototype.setIsWatchingForClients = function (value) { 5421 this._isWatchingForClients = value; 5422 }; 5423 5424 /** 5425 * @private 5426 */ 5427 net.user1.orbiter.ClientManager.prototype.addWatchedClient = function (client) { 5428 var customClient = client.getCustomClient(null); 5429 this.watchedClients.add(client); 5430 this.fireClientConnected(customClient === null ? client : customClient); 5431 }; 5432 5433 /** 5434 * @private 5435 */ 5436 net.user1.orbiter.ClientManager.prototype.removeWatchedClient = function (clientID) { 5437 this.watchedClients.removeByClientID(clientID); 5438 }; 5439 5440 /** 5441 * @private 5442 */ 5443 net.user1.orbiter.ClientManager.prototype.removeAllWatchedClients = function () { 5444 this.watchedClients.removeAll(); 5445 }; 5446 5447 /** 5448 * @private 5449 */ 5450 net.user1.orbiter.ClientManager.prototype.deserializeWatchedClients = function (ids) { 5451 var idList = ids.split(net.user1.orbiter.Tokens.RS); 5452 var idHash = new Object(); 5453 var localClients = this.watchedClients.getAll(); 5454 var len = idList.length; 5455 var theClient; 5456 var accountID; 5457 5458 // Client list received, so set isWatchingForClients now, otherwise, code 5459 // with side-effects may take action against the clients being added 5460 this.setIsWatchingForClients(true); 5461 5462 // Generate a hash of clientID keys to accountID values 5463 for (var i = len-2; i >= 0; i-=2) { 5464 idHash[idList[i]] = idList[i+1]; 5465 } 5466 5467 // Remove all local clients that are not in the new list from the server 5468 var clientStillExists; 5469 for (var clientID in localClients) { 5470 if (!idHash.hasOwnProperty(clientID)) { 5471 // For best performance, use direct access rather than removeByClientID() 5472 delete localClients[clientID]; 5473 } 5474 } 5475 5476 // Add all new clients that are not in the local set 5477 for (clientID in idHash) { 5478 if (clientID != "") { 5479 if (!this.watchedClients.containsClientID(clientID)) { 5480 theClient = this.requestClient(clientID); 5481 accountID = idHash[clientID]; 5482 if (accountID != "") { 5483 theClient.setAccount(this.accountManager.requestAccount(accountID)); 5484 } 5485 this.addWatchedClient(theClient); 5486 } 5487 } else { 5488 throw new Error("[CLIENT_MANAGER] Received empty client id in client list (u101)."); 5489 } 5490 } 5491 5492 this.fireSynchronize(); 5493 }; 5494 5495 // ============================================================================= 5496 // OBSERVED CLIENTS 5497 // ============================================================================= 5498 5499 net.user1.orbiter.ClientManager.prototype.observeClient = function (clientID) { 5500 this.messageManager.sendUPC(net.user1.orbiter.UPC.OBSERVE_CLIENT, clientID); 5501 }; 5502 5503 net.user1.orbiter.ClientManager.prototype.isObservingClient = function (clientID) { 5504 return this.observedClients.containsClientID(clientID); 5505 } 5506 5507 /** 5508 * @private 5509 */ 5510 net.user1.orbiter.ClientManager.prototype.addObservedClient = function (client) { 5511 var customClient = client.getCustomClient(null); 5512 this.observedClients.add(client); 5513 this.fireObserveClient(customClient === null ? client : customClient); 5514 }; 5515 5516 /** 5517 * @private 5518 */ 5519 net.user1.orbiter.ClientManager.prototype.removeObservedClient = function (clientID) { 5520 var client = this.observedClients.removeByClientID(clientID); 5521 var customClient; 5522 if (client != null) { 5523 customClient = client.getCustomClient(null); 5524 this.fireStopObservingClient(customClient === null ? client : customClient); 5525 } 5526 }; 5527 5528 /** 5529 * @private 5530 */ 5531 net.user1.orbiter.ClientManager.prototype.removeAllObservedClients = function () { 5532 this.observedClients.removeAll(); 5533 }; 5534 5535 //============================================================================== 5536 // CLIENT ATTRIBUTE ACCESS 5537 //============================================================================== 5538 5539 net.user1.orbiter.ClientManager.prototype.getAttributeForClients = function (clientIDs, 5540 attrName, 5541 attrScope) { 5542 var clientAttributes = new Array(); 5543 var thisClient; 5544 5545 for (var i = 0; i < clientIDs.length; i++) { 5546 thisClient = this.getInternalClient(clientIDs[i]); 5547 if (thisClient != null) { 5548 clientAttributes.push({clientID: clientIDs[i], 5549 value: thisClient.getAttribute(attrName, attrScope)}); 5550 } else { 5551 this.log.debug("[CLIENT_MANAGER] Attribute retrieval failed during " 5552 + " getAttributeForClients(). Unknown client ID [" + clientIDs[i] + "]"); 5553 } 5554 } 5555 return clientAttributes; 5556 }; 5557 5558 //============================================================================== 5559 // CUSTOM CLIENT MANAGEMENT 5560 //============================================================================== 5561 5562 net.user1.orbiter.ClientManager.prototype.setDefaultClientClass = function (defaultClass) { 5563 this.defaultClientClass = defaultClass; 5564 }; 5565 5566 net.user1.orbiter.ClientManager.prototype.getDefaultClientClass = function () { 5567 return this.defaultClientClass; 5568 }; 5569 5570 //============================================================================== 5571 // CURRENT CLIENT ASSIGNMENT AND ACCESS 5572 //============================================================================== 5573 5574 /** 5575 * @private 5576 */ 5577 net.user1.orbiter.ClientManager.prototype.self = function () { 5578 return this.selfReference; 5579 } 5580 5581 /** 5582 * @private 5583 */ 5584 net.user1.orbiter.ClientManager.prototype.setSelf = function (client) { 5585 this.selfReference = client; 5586 client.setIsSelf(); 5587 } 5588 5589 //============================================================================== 5590 // CLIENT MESSAGING 5591 //============================================================================== 5592 5593 net.user1.orbiter.ClientManager.prototype.sendMessage = function (messageName, 5594 clientIDs, 5595 filters) { 5596 var rest = Array.prototype.slice.call(arguments).slice(3); 5597 5598 // An array of arguments to send to the server. 5599 var args; 5600 5601 // Can't continue without a valid methodName. 5602 if (messageName == null || messageName == "") { 5603 this.log.warn("[CLIENT_MANAGER] sendMessage() failed. No messageName supplied."); 5604 return; 5605 } 5606 5607 // Send the UPC. 5608 args = [net.user1.orbiter.UPC.SEND_MESSAGE_TO_CLIENTS, 5609 messageName, 5610 clientIDs.join(net.user1.orbiter.Tokens.RS), 5611 filters != null ? filters.toXMLString() : ""]; 5612 this.messageManager.sendUPC.apply(this.messageManager, args.concat(rest)); 5613 }; 5614 5615 // ============================================================================= 5616 // BAN / UNBAN / KICK 5617 // ============================================================================= 5618 5619 net.user1.orbiter.ClientManager.prototype.ban = function (address, duration, reason) { 5620 this.messageManager.sendUPC(net.user1.orbiter.UPC.BAN, address, null, duration.toString(), reason); 5621 }; 5622 5623 net.user1.orbiter.ClientManager.prototype.unban = function (address) { 5624 this.messageManager.sendUPC(net.user1.orbiter.UPC.UNBAN, address); 5625 }; 5626 5627 net.user1.orbiter.ClientManager.prototype.kickClient = function (clientID) { 5628 if (clientID == null || clientID == "") { 5629 this.log.warn("[CLIENT_MANAGER] Kick attempt failed. No clientID supplied."); 5630 } 5631 this.messageManager.sendUPC(net.user1.orbiter.UPC.KICK_CLIENT, clientID); 5632 } 5633 5634 // ============================================================================= 5635 // WATCH BANNED ADDRESSES 5636 // ============================================================================= 5637 5638 net.user1.orbiter.ClientManager.prototype.watchForBannedAddresses = function () { 5639 this.messageManager.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES); 5640 }; 5641 5642 net.user1.orbiter.ClientManager.prototype.stopWatchingForBannedAddresses = function () { 5643 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES); 5644 }; 5645 5646 /** 5647 * @private 5648 */ 5649 net.user1.orbiter.ClientManager.prototype.setWatchedBannedAddresses = function (bannedList) { 5650 this.bannedAddresses = bannedList; 5651 this.fireSynchronizeBanlist(); 5652 }; 5653 5654 /** 5655 * @private 5656 */ 5657 net.user1.orbiter.ClientManager.prototype.addWatchedBannedAddress = function (address) { 5658 this.bannedAddresses.push(address); 5659 this.fireAddressBanned(address); 5660 }; 5661 5662 /** 5663 * @private 5664 */ 5665 net.user1.orbiter.ClientManager.prototype.removeWatchedBannedAddress = function (address) { 5666 var idx = net.user1.util.ArrayUtil.indexOf(bannedAddresses, address); 5667 if (idx === -1) { 5668 this.log.warn("[CLIENT_MANAGER] Request to remove watched banned address failed." 5669 + " Address not found."); 5670 } 5671 this.bannedAddresses.splice(idx, 1); 5672 this.fireAddressUnbanned(address); 5673 } 5674 5675 /** 5676 * @private 5677 */ 5678 net.user1.orbiter.ClientManager.prototype.setIsWatchingForBannedAddresses = function (value) { 5679 this._isWatchingForBannedAddresses = value; 5680 }; 5681 5682 net.user1.orbiter.ClientManager.prototype.isWatchingForBannedAddresses = function () { 5683 return this._isWatchingForBannedAddresses; 5684 }; 5685 5686 net.user1.orbiter.ClientManager.prototype.getBannedAddresses = function () { 5687 return this.bannedAddresses.slice(0); 5688 }; 5689 5690 //============================================================================== 5691 // STATISTICS 5692 //============================================================================== 5693 5694 net.user1.orbiter.ClientManager.prototype.getLifetimeNumClientsKnown = function () { 5695 // -1 for each "ready" state the connection has achieved because we don't 5696 // count the current client ("self") 5697 return this.lifetimeClientsRequested-this.connectionManager.getReadyCount(); 5698 }; 5699 5700 net.user1.orbiter.ClientManager.prototype.getNumClients = function () { 5701 return net.user1.utils.ObjectUtil.length(this.getInternalClients()); 5702 }; 5703 5704 net.user1.orbiter.ClientManager.prototype.getNumClientsOnServer = function () { 5705 return this.watchedClients.length(); 5706 } 5707 5708 //============================================================================== 5709 // EVENT DISPATCHING 5710 //============================================================================== 5711 5712 /** 5713 * @private 5714 */ 5715 net.user1.orbiter.ClientManager.prototype.fireObserveClient = function (client) { 5716 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE, null, null, null, client); 5717 this.dispatchEvent(e); 5718 }; 5719 5720 /** 5721 * @private 5722 */ 5723 net.user1.orbiter.ClientManager.prototype.fireStopObservingClient = function (client) { 5724 var e = new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING, null, null, null, client); 5725 this.dispatchEvent(e); 5726 }; 5727 5728 /** 5729 * @private 5730 */ 5731 net.user1.orbiter.ClientManager.prototype.fireClientConnected = function (client) { 5732 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED, 5733 client.getClientID(), client)); 5734 }; 5735 5736 /** 5737 * @private 5738 */ 5739 net.user1.orbiter.ClientManager.prototype.fireClientDisconnected = function (client) { 5740 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED, 5741 client.getClientID(), client)); 5742 }; 5743 5744 /** 5745 * @private 5746 */ 5747 net.user1.orbiter.ClientManager.prototype.fireStopWatchingForClientsResult = function (status) { 5748 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT, 5749 null, null, null, status)); 5750 }; 5751 5752 /** 5753 * @private 5754 */ 5755 net.user1.orbiter.ClientManager.prototype.fireWatchForClientsResult = function (status) { 5756 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT, 5757 null, null, null, status)); 5758 }; 5759 5760 /** 5761 * @private 5762 */ 5763 net.user1.orbiter.ClientManager.prototype.fireObserveClientResult = function (clientID, status) { 5764 this.dispatchEvent(new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.OBSERVE_RESULT, 5765 null, null, null, this.getClient(clientID), status, clientID)); 5766 }; 5767 5768 /** 5769 * @private 5770 */ 5771 net.user1.orbiter.ClientManager.prototype.fireStopObservingClientResult = function (clientID, status) { 5772 this.dispatchEvent(new net.user1.orbiter.ClientEvent(net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT, 5773 null, null, null, this.getClient(clientID), status, clientID)); 5774 }; 5775 5776 /** 5777 * @private 5778 */ 5779 net.user1.orbiter.ClientManager.prototype.fireKickClientResult = function (clientID, status) { 5780 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.KICK_RESULT, 5781 clientID, null, null, status)); 5782 }; 5783 5784 /** 5785 * @private 5786 */ 5787 net.user1.orbiter.ClientManager.prototype.fireBanClientResult = function (address, clientID, status) { 5788 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.BAN_RESULT, 5789 clientID, null, address, status)); 5790 }; 5791 5792 /** 5793 * @private 5794 */ 5795 net.user1.orbiter.ClientManager.prototype.fireUnbanClientResult = function (address, status) { 5796 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.UNBAN_RESULT, 5797 null, null, address, status)); 5798 }; 5799 5800 /** 5801 * @private 5802 */ 5803 net.user1.orbiter.ClientManager.prototype.fireWatchForBannedAddressesResult = function (status) { 5804 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT, 5805 null, null, null, status)); 5806 }; 5807 5808 /** 5809 * @private 5810 */ 5811 net.user1.orbiter.ClientManager.prototype.fireStopWatchingForBannedAddressesResult = function (status) { 5812 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT, 5813 null, null, null, status)); 5814 }; 5815 5816 /** 5817 * @private 5818 */ 5819 net.user1.orbiter.ClientManager.prototype.fireAddressBanned = function (address) { 5820 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED, 5821 null, null, address)); 5822 }; 5823 5824 /** 5825 * @private 5826 */ 5827 net.user1.orbiter.ClientManager.prototype.fireAddressUnbanned = function (address) { 5828 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED, 5829 null, null, address)); 5830 }; 5831 5832 /** 5833 * @private 5834 */ 5835 net.user1.orbiter.ClientManager.prototype.fireSynchronizeBanlist = function () { 5836 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST)); 5837 }; 5838 5839 /** 5840 * @private 5841 */ 5842 net.user1.orbiter.ClientManager.prototype.fireSynchronize = function () { 5843 this.dispatchEvent(new net.user1.orbiter.ClientManagerEvent(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE)); 5844 }; 5845 5846 //============================================================================== 5847 // CLEANUP AND DISPOSAL 5848 //============================================================================== 5849 5850 /** 5851 * @private 5852 */ 5853 net.user1.orbiter.ClientManager.prototype.cleanup = function () { 5854 this.log.info("[CLIENT_MANAGER] Cleaning resources."); 5855 this.selfReference = null; 5856 this.removeAllObservedClients(); 5857 this.removeAllWatchedClients(); 5858 this.setIsWatchingForClients(false); 5859 }; 5860 5861 net.user1.orbiter.ClientManager.prototype.dispose = function () { 5862 this.log.info("[CLIENT_MANAGER] Disposing resources."); 5863 this.watchedClients = null; 5864 this.observedClients = null; 5865 this.defaultClientClass = null; 5866 }; 5867 //============================================================================== 5868 // CLASS DECLARATION 5869 //============================================================================== 5870 /** @class 5871 @extends net.user1.events.Event 5872 */ 5873 net.user1.orbiter.ClientManagerEvent = function (type, 5874 clientID, 5875 client, 5876 address, 5877 status) { 5878 net.user1.events.Event.call(this, type); 5879 5880 this.clientID = clientID; 5881 this.client = client; 5882 this.address = address; 5883 this.status = status; 5884 }; 5885 5886 //============================================================================== 5887 // INHERITANCE 5888 //============================================================================== 5889 net.user1.utils.extend(net.user1.orbiter.ClientManagerEvent, net.user1.events.Event); 5890 5891 //============================================================================== 5892 // STATIC VARIABLES 5893 //============================================================================== 5894 /** @constant */ 5895 net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT = "WATCH_FOR_CLIENTS_RESULT"; 5896 /** @constant */ 5897 net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT = "STOP_WATCHING_FOR_CLIENTS_RESULT"; 5898 /** @constant */ 5899 net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED = "CLIENT_DISCONNECTED"; 5900 /** @constant */ 5901 net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED = "CLIENT_CONNECTED"; 5902 /** @constant */ 5903 net.user1.orbiter.ClientManagerEvent.KICK_RESULT = "KICK_RESULT"; 5904 /** @constant */ 5905 net.user1.orbiter.ClientManagerEvent.BAN_RESULT = "BAN_RESULT"; 5906 /** @constant */ 5907 net.user1.orbiter.ClientManagerEvent.UNBAN_RESULT = "UNBAN_RESULT"; 5908 /** @constant */ 5909 net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT = "WATCH_FOR_BANNED_ADDRESSES_RESULT"; 5910 /** @constant */ 5911 net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT = "STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT"; 5912 /** @constant */ 5913 net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED = "ADDRESS_BANNED"; 5914 /** @constant */ 5915 net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED = "ADDRESS_UNBANNED"; 5916 /** @constant */ 5917 net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST = "SYNCHRONIZE_BANLIST"; 5918 /** @constant */ 5919 net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE = "SYNCHRONIZE"; 5920 5921 net.user1.orbiter.ClientManagerEvent.prototype.getClientID = function () { 5922 return this.clientID; 5923 }; 5924 5925 net.user1.orbiter.ClientManagerEvent.prototype.getClient = function () { 5926 return this.client; 5927 }; 5928 5929 net.user1.orbiter.ClientManagerEvent.prototype.getAddress = function () { 5930 return this.address; 5931 }; 5932 5933 net.user1.orbiter.ClientManagerEvent.prototype.getStatus = function () { 5934 return this.status; 5935 }; 5936 5937 net.user1.orbiter.ClientManagerEvent.prototype.toString = function () { 5938 return "[object ClientManagerEvent]"; 5939 }; 5940 //============================================================================== 5941 // CLASS DECLARATION 5942 //============================================================================== 5943 net.user1.orbiter.ClientManifest = function () { 5944 this.clientID = null; 5945 this.userID = null; 5946 this.persistentAttributes = new net.user1.orbiter.AttributeCollection(); 5947 this.transientAttributes = new net.user1.orbiter.AttributeCollection(); 5948 this.occupiedRoomIDs = null; 5949 this.observedRoomIDs = null; 5950 }; 5951 5952 /** 5953 * @private 5954 */ 5955 net.user1.orbiter.ClientManifest.prototype.deserialize = function (clientID, 5956 userID, 5957 serializedOccupiedRoomIDs, 5958 serializedObservedRoomIDs, 5959 globalAttrs, 5960 roomAttrs) { 5961 this.clientID = clientID == "" ? null : clientID; 5962 this.userID = userID == "" ? null : userID; 5963 5964 // Room ids 5965 this.deserializeOccupiedRoomIDs(serializedOccupiedRoomIDs); 5966 this.deserializeObservedRoomIDs(serializedObservedRoomIDs); 5967 5968 // Global attrs 5969 this.deserializeAttributesByScope(net.user1.orbiter.Tokens.GLOBAL_ATTR, globalAttrs); 5970 5971 // Room attrs 5972 for (var i = 0; i < roomAttrs.length; i += 2) { 5973 this.deserializeAttributesByScope(roomAttrs[i], roomAttrs[i+1]); 5974 } 5975 }; 5976 5977 /** 5978 * @private 5979 */ 5980 net.user1.orbiter.ClientManifest.prototype.deserializeOccupiedRoomIDs = function (roomIDs) { 5981 // No rooms included in the manifest 5982 if (roomIDs == null) { 5983 return; 5984 } 5985 // Client is in no rooms 5986 if (roomIDs == "") { 5987 this.occupiedRoomIDs = []; 5988 return; 5989 } 5990 // Client is in one or more room 5991 this.occupiedRoomIDs = roomIDs.split(net.user1.orbiter.Tokens.RS); 5992 }; 5993 5994 /** 5995 * @private 5996 */ 5997 net.user1.orbiter.ClientManifest.prototype.deserializeObservedRoomIDs = function (roomIDs) { 5998 if (roomIDs == null) { 5999 return; 6000 } 6001 if (roomIDs == "") { 6002 this.observedRoomIDs = []; 6003 return; 6004 } 6005 this.observedRoomIDs = roomIDs.split(net.user1.orbiter.Tokens.RS); 6006 }; 6007 6008 /** 6009 * @private 6010 */ 6011 net.user1.orbiter.ClientManifest.prototype.deserializeAttributesByScope = function (scope, 6012 serializedAttributes) { 6013 var attrList; 6014 if (serializedAttributes == null || serializedAttributes == "") { 6015 return; 6016 } 6017 attrList = serializedAttributes.split(net.user1.orbiter.Tokens.RS); 6018 for (var i = attrList.length-3; i >= 0; i -=3) { 6019 if (parseInt(attrList[i+2]) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 6020 // Persistent 6021 this.persistentAttributes.setAttribute(attrList[i], attrList[i+1], scope); 6022 } else { 6023 // Non-persistent 6024 this.transientAttributes.setAttribute(attrList[i], attrList[i+1], scope); 6025 } 6026 } 6027 }; 6028 //============================================================================== 6029 // CLASS DECLARATION 6030 //============================================================================== 6031 /** 6032 * @private 6033 */ 6034 net.user1.orbiter.ClientSet = function () { 6035 this.clients = new net.user1.utils.UDictionary(); 6036 }; 6037 6038 net.user1.orbiter.ClientSet.prototype.add = function (client) { 6039 this.clients[client.getClientID()] = client; 6040 }; 6041 6042 net.user1.orbiter.ClientSet.prototype.remove = function (client) { 6043 var client = clients[client.getClientID()]; 6044 delete this.clients[client.getClientID()]; 6045 return client; 6046 }; 6047 6048 net.user1.orbiter.ClientSet.prototype.removeAll = function () { 6049 this.clients = new net.user1.utils.UDictionary(); 6050 } 6051 6052 net.user1.orbiter.ClientSet.prototype.removeByClientID = function (clientID) { 6053 var client = this.clients[clientID]; 6054 delete this.clients[clientID]; 6055 return client; 6056 }; 6057 6058 net.user1.orbiter.ClientSet.prototype.contains = function (client) { 6059 return this.clients[client.getClientID()] != null; 6060 }; 6061 6062 net.user1.orbiter.ClientSet.prototype.containsClientID = function (clientID) { 6063 if (clientID == "" || clientID == null) { 6064 return false; 6065 } 6066 return this.getByClientID(clientID) != null; 6067 }; 6068 6069 net.user1.orbiter.ClientSet.prototype.getByClientID = function (clientID) { 6070 return this.clients[clientID]; 6071 }; 6072 6073 net.user1.orbiter.ClientSet.prototype.getByUserID = function (userID) { 6074 var account; 6075 6076 var client; 6077 for (var clientID in this.clients) { 6078 client = this.clients[clientID]; 6079 account = client.getAccount(); 6080 if (account != null && account.getUserID() == userID) { 6081 return client; 6082 } 6083 } 6084 return null; 6085 }; 6086 6087 net.user1.orbiter.ClientSet.prototype.getAll = function () { 6088 return this.clients; 6089 } 6090 6091 net.user1.orbiter.ClientSet.prototype.getAllIDs = function () { 6092 var ids = []; 6093 for (var clientID in this.clients) { 6094 ids.push(clientID); 6095 } 6096 return ids; 6097 }; 6098 6099 net.user1.orbiter.ClientSet.prototype.length = function () { 6100 return net.user1.utils.ObjectUtil.length(this.clients); 6101 }; 6102 //============================================================================== 6103 // CLASS DECLARATION 6104 //============================================================================== 6105 /** 6106 * @class 6107 * @extends net.user1.orbiter.snapshot.Snapshot 6108 */ 6109 net.user1.orbiter.snapshot.ClientSnapshot = function (clientID) { 6110 // Call superconstructor 6111 net.user1.orbiter.snapshot.Snapshot.call(this); 6112 this.manifest = null; 6113 this.method = net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT; 6114 this.args = [clientID]; 6115 this.hasStatus = true; 6116 }; 6117 6118 //============================================================================== 6119 // INHERITANCE 6120 //============================================================================== 6121 net.user1.utils.extend(net.user1.orbiter.snapshot.ClientSnapshot, net.user1.orbiter.snapshot.Snapshot); 6122 6123 //============================================================================== 6124 // INSTANCE METHODS 6125 //============================================================================== 6126 /** 6127 * @private 6128 */ 6129 net.user1.orbiter.snapshot.ClientSnapshot.prototype.setManifest = function (value) { 6130 this.manifest = value; 6131 }; 6132 6133 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getAttribute = function (name, scope) { 6134 if (!this.manifest) { 6135 return null; 6136 } 6137 return this.manifest.transientAttributes.getAttribute(name, scope); 6138 }; 6139 6140 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getAttributes = function () { 6141 if (!this.manifest) { 6142 return null; 6143 } 6144 return this.manifest.transientAttributes.getAll(); 6145 }; 6146 6147 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getClientID = function () { 6148 if (!this.manifest) { 6149 return null; 6150 } 6151 return this.manifest.clientID; 6152 }; 6153 6154 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getUserID = function () { 6155 if (!this.manifest) { 6156 return null; 6157 } 6158 return this.manifest.userID; 6159 }; 6160 6161 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getOccupiedRoomIDs = function () { 6162 if (!this.manifest) { 6163 return null; 6164 } 6165 return this.manifest.occupiedRoomIDs.slice(); 6166 }; 6167 6168 net.user1.orbiter.snapshot.ClientSnapshot.prototype.getObservedRoomIDs = function () { 6169 if (!this.manifest) { 6170 return null; 6171 } 6172 return this.manifest.observedRoomIDs.slice(); 6173 } 6174 //============================================================================== 6175 // CLASS DECLARATION 6176 //============================================================================== 6177 /** 6178 * @private 6179 */ 6180 net.user1.orbiter.CollectionEvent = function (type, item) { 6181 net.user1.events.Event.call(this, type); 6182 6183 this.item = item; 6184 }; 6185 6186 //============================================================================== 6187 // INHERITANCE 6188 //============================================================================== 6189 net.user1.utils.extend(net.user1.orbiter.CollectionEvent, net.user1.events.Event); 6190 6191 //============================================================================== 6192 // STATIC VARIABLES 6193 //============================================================================== 6194 6195 /** @constant */ 6196 net.user1.orbiter.CollectionEvent.REMOVE_ITEM = "REMOVE_ITEM"; 6197 /** @constant */ 6198 net.user1.orbiter.CollectionEvent.ADD_ITEM = "ADD_ITEM"; 6199 6200 net.user1.orbiter.CollectionEvent.prototype.getItem = function () { 6201 return this.item; 6202 }; 6203 6204 net.user1.orbiter.CollectionEvent.prototype.toString = function () { 6205 return "[object CollectionEvent]"; 6206 }; 6207 //============================================================================== 6208 // COMPARE TYPE CONSTANTS 6209 //============================================================================== 6210 /** @class */ 6211 net.user1.orbiter.filters.CompareType = new Object(); 6212 /** @constant */ 6213 net.user1.orbiter.filters.CompareType.EQUAL = "eq"; 6214 /** @constant */ 6215 net.user1.orbiter.filters.CompareType.NOT_EQUAL = "ne"; 6216 /** @constant */ 6217 net.user1.orbiter.filters.CompareType.GREATER_THAN = "gt"; 6218 /** @constant */ 6219 net.user1.orbiter.filters.CompareType.GREATER_THAN_OR_EQUAL = "ge"; 6220 /** @constant */ 6221 net.user1.orbiter.filters.CompareType.LESS_THAN = "lt"; 6222 /** @constant */ 6223 net.user1.orbiter.filters.CompareType.LESS_THAN_OR_EQUAL = "le"; 6224 //============================================================================== 6225 // CLASS DECLARATION 6226 //============================================================================== 6227 /** 6228 * @private 6229 */ 6230 net.user1.orbiter.CoreEventLogger = function (log, 6231 connectionMan, 6232 roomMan, 6233 accountMan, 6234 server, 6235 clientMan, 6236 orbiter) { 6237 this.log = log; 6238 6239 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT, 6240 this.stopWatchingForRoomsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6241 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, 6242 this.watchForRoomsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6243 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT, 6244 this.createRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6245 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT, 6246 this.removeRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6247 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.ROOM_ADDED, 6248 this.roomAddedListener, this, net.user1.utils.integer.MAX_VALUE); 6249 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED, 6250 this.roomRemovedListener, this, net.user1.utils.integer.MAX_VALUE); 6251 roomMan.addEventListener(net.user1.orbiter.RoomManagerEvent.ROOM_COUNT, 6252 this.roomCountListener, this, net.user1.utils.integer.MAX_VALUE); 6253 roomMan.addEventListener(net.user1.orbiter.RoomEvent.JOIN_RESULT, 6254 this.joinRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6255 roomMan.addEventListener(net.user1.orbiter.RoomEvent.LEAVE_RESULT, 6256 this.leaveRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6257 roomMan.addEventListener(net.user1.orbiter.RoomEvent.OBSERVE_RESULT, 6258 this.observeRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6259 roomMan.addEventListener(net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT, 6260 this.stopObservingRoomResultListener, this, net.user1.utils.integer.MAX_VALUE); 6261 6262 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.CREATE_ACCOUNT_RESULT, 6263 this.createAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6264 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.REMOVE_ACCOUNT_RESULT, 6265 this.removeAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6266 accountMan.addEventListener(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT, 6267 this.changePasswordResultListener, this, net.user1.utils.integer.MAX_VALUE); 6268 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.ACCOUNT_ADDED, 6269 this.accountAddedListener, this, net.user1.utils.integer.MAX_VALUE); 6270 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.ACCOUNT_REMOVED, 6271 this.accountRemovedListener, this, net.user1.utils.integer.MAX_VALUE); 6272 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGOFF_RESULT, 6273 this.logoffResultListener, this, net.user1.utils.integer.MAX_VALUE); 6274 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGOFF, 6275 this.logoffListener, this, net.user1.utils.integer.MAX_VALUE); 6276 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGIN_RESULT, 6277 this.loginResultListener, this, net.user1.utils.integer.MAX_VALUE); 6278 accountMan.addEventListener(net.user1.orbiter.AccountEvent.LOGIN, 6279 this.loginListener, this, net.user1.utils.integer.MAX_VALUE); 6280 accountMan.addEventListener(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD, 6281 this.changePasswordListener, this, net.user1.utils.integer.MAX_VALUE); 6282 accountMan.addEventListener(net.user1.orbiter.AccountEvent.OBSERVE, 6283 this.observeAccountListener, this, net.user1.utils.integer.MAX_VALUE); 6284 accountMan.addEventListener(net.user1.orbiter.AccountEvent.STOP_OBSERVING, 6285 this.stopObservingAccountListener, this, net.user1.utils.integer.MAX_VALUE); 6286 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.STOP_WATCHING_FOR_ACCOUNTS_RESULT, 6287 this.stopWatchingForAccountsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6288 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.WATCH_FOR_ACCOUNTS_RESULT, 6289 this.watchForAccountsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6290 accountMan.addEventListener(net.user1.orbiter.AccountEvent.OBSERVE_RESULT, 6291 this.observeAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6292 accountMan.addEventListener(net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT, 6293 this.stopObservingAccountResultListener, this, net.user1.utils.integer.MAX_VALUE); 6294 accountMan.addEventListener(net.user1.orbiter.AccountManagerEvent.SYNCHRONIZE, 6295 this.synchronizeAccountsListener, this, net.user1.utils.integer.MAX_VALUE); 6296 6297 server.addEventListener(net.user1.orbiter.ServerEvent.TIME_SYNC, this.timeSyncListener, this, net.user1.utils.integer.MAX_VALUE); 6298 6299 connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE, 6300 this.connectFailureListener, this, net.user1.utils.integer.MAX_VALUE); 6301 connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.CLIENT_KILL_CONNECT, 6302 this.clientKillConnectListener, this, net.user1.utils.integer.MAX_VALUE); 6303 connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.SERVER_KILL_CONNECT, 6304 this.serverKillConnectListener, this, net.user1.utils.integer.MAX_VALUE); 6305 6306 clientMan.addEventListener(net.user1.orbiter.ClientEvent.OBSERVE, 6307 this.observeClientListener, this, net.user1.utils.integer.MAX_VALUE); 6308 clientMan.addEventListener(net.user1.orbiter.ClientEvent.STOP_OBSERVING, 6309 this.stopObservingClientListener, this, net.user1.utils.integer.MAX_VALUE); 6310 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.CLIENT_CONNECTED, 6311 this.clientConnectedListener, this, net.user1.utils.integer.MAX_VALUE); 6312 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.CLIENT_DISCONNECTED, 6313 this.clientDisconnectedListener, this, net.user1.utils.integer.MAX_VALUE); 6314 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_CLIENTS_RESULT, 6315 this.stopWatchingForClientsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6316 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_CLIENTS_RESULT, 6317 this.watchForClientsResultListener, this, net.user1.utils.integer.MAX_VALUE); 6318 clientMan.addEventListener(net.user1.orbiter.ClientEvent.OBSERVE_RESULT, 6319 this.observeClientResultListener, this, net.user1.utils.integer.MAX_VALUE); 6320 clientMan.addEventListener(net.user1.orbiter.ClientEvent.STOP_OBSERVING_RESULT, 6321 this.stopObservingClientResultListener, this, net.user1.utils.integer.MAX_VALUE); 6322 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE, 6323 this.synchronizeClientsListener, this, net.user1.utils.integer.MAX_VALUE); 6324 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.ADDRESS_BANNED, 6325 this.addressBannedListener, this, net.user1.utils.integer.MAX_VALUE); 6326 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.ADDRESS_UNBANNED, 6327 this.addressUnbannedListener, this, net.user1.utils.integer.MAX_VALUE); 6328 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT, 6329 this.stopWatchingForBannedAddressesResultListener, this, net.user1.utils.integer.MAX_VALUE); 6330 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.WATCH_FOR_BANNED_ADDRESSES_RESULT, 6331 this.watchForBannedAddressesResultListener, this, net.user1.utils.integer.MAX_VALUE); 6332 clientMan.addEventListener(net.user1.orbiter.ClientManagerEvent.SYNCHRONIZE_BANLIST, 6333 this.synchronizeBanlistListener, this, net.user1.utils.integer.MAX_VALUE); 6334 6335 6336 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, this.readyListener, this, net.user1.utils.integer.MAX_VALUE); 6337 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE, this.protocolIncompatibleListener, this, net.user1.utils.integer.MAX_VALUE); 6338 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED, this.connectRefusedListener, this, net.user1.utils.integer.MAX_VALUE); 6339 6340 this.log.addEventListener(net.user1.logger.LogEvent.LEVEL_CHANGE, this.logLevelChangeListener, this, net.user1.utils.integer.MAX_VALUE); 6341 }; 6342 6343 6344 // ============================================================================= 6345 // Logger EVENT LISTENERS 6346 // ============================================================================= 6347 6348 /** 6349 * @private 6350 */ 6351 net.user1.orbiter.CoreEventLogger.prototype.logLevelChangeListener = function (e) { 6352 this.log.info("[LOGGER] Log level set to: [" + e.getLevel() + "]."); 6353 }; 6354 6355 // ============================================================================= 6356 // Orbiter EVENT LISTENERS 6357 // ============================================================================= 6358 6359 /** 6360 * @private 6361 */ 6362 net.user1.orbiter.CoreEventLogger.prototype.readyListener = function (e) { 6363 this.log.info("[ORBITER] Orbiter now connected and ready."); 6364 }; 6365 6366 /** 6367 * @private 6368 */ 6369 net.user1.orbiter.CoreEventLogger.prototype.protocolIncompatibleListener = function (e) { 6370 this.log.warn("[ORBITER] Orbiter UPC protocol incompatibility detected. Client " 6371 + "UPC version: " + e.target.getSystem().getUPCVersion().toString() 6372 + ". Server version: " + e.getServerUPCVersion().toString() + "."); 6373 }; 6374 6375 /** 6376 * @private 6377 */ 6378 net.user1.orbiter.CoreEventLogger.prototype.connectRefusedListener = function (e) { 6379 if (e.getConnectionRefusal().reason == net.user1.orbiter.ConnectionRefusalReason.BANNED) { 6380 this.log.warn("[ORBITER] Union Server refused the connection because the" 6381 + " client address is banned for the following reason: [" 6382 + e.getConnectionRefusal().banReason + "]. The ban started at: [" 6383 + new Date(e.getConnectionRefusal().bannedAt) + "]. The ban duration is: [" 6384 + net.user1.utils.NumericFormatter.msToElapsedDayHrMinSec(e.getConnectionRefusal().banDuration*1000) + "]."); 6385 } else { 6386 this.log.warn("[ORBITER] Union Server refused the connection. Reason: [" 6387 + e.getConnectionRefusal().reason + "]. Description: [" 6388 + e.getConnectionRefusal().description + "]."); 6389 } 6390 } 6391 6392 // ============================================================================= 6393 // Server EVENT LISTENERS 6394 // ============================================================================= 6395 6396 net.user1.orbiter.CoreEventLogger.prototype.timeSyncListener = function (e) { 6397 this.log.info("[SERVER] Server time synchronized with client. Approximate time on " + 6398 "server is now: " + new Date(e.target.getServerTime())); 6399 }; 6400 6401 // ============================================================================= 6402 // AccountManager EVENT LISTENERS 6403 // ============================================================================= 6404 net.user1.orbiter.CoreEventLogger.prototype.createAccountResultListener = function (e) { 6405 this.log.info("[ACCOUNT_MANAGER] Result for createAccount(). Account: " 6406 + e.getUserID() + ", Status: " + e.getStatus()); 6407 }; 6408 6409 net.user1.orbiter.CoreEventLogger.prototype.removeAccountResultListener = function (e) { 6410 this.log.info("[ACCOUNT_MANAGER] Result for removeAccount(). Account: " 6411 + e.getUserID() + ", Status: " + e.getStatus()); 6412 }; 6413 6414 net.user1.orbiter.CoreEventLogger.prototype.changePasswordResultListener = function (e) { 6415 this.log.info("[ACCOUNT_MANAGER] Result for changePassword(). Account: " 6416 + e.getUserID() + ", Status: " + e.getStatus()); 6417 }; 6418 6419 net.user1.orbiter.CoreEventLogger.prototype.accountAddedListener = function (e) { 6420 this.log.info("[ACCOUNT_MANAGER] Account added: " + e.getAccount()); 6421 }; 6422 6423 net.user1.orbiter.CoreEventLogger.prototype.accountRemovedListener = function (e) { 6424 this.log.info("[ACCOUNT_MANAGER] Account removed: " + e.getAccount()); 6425 }; 6426 6427 net.user1.orbiter.CoreEventLogger.prototype.logoffResultListener = function (e) { 6428 this.log.info("[ACCOUNT_MANAGER] Result for logoff(). Account: " 6429 + e.getAccount() + ", Status: " + e.getStatus()); 6430 }; 6431 6432 net.user1.orbiter.CoreEventLogger.prototype.logoffListener = function (e) { 6433 this.log.info("[ACCOUNT_MANAGER] Account logged off: " + e.getAccount()); 6434 }; 6435 6436 net.user1.orbiter.CoreEventLogger.prototype.loginResultListener = function (e) { 6437 this.log.info("[ACCOUNT_MANAGER] Result for login(). Account: " 6438 + e.getAccount() + ", Status: " + e.getStatus()); 6439 }; 6440 6441 net.user1.orbiter.CoreEventLogger.prototype.loginListener = function (e) { 6442 this.log.info("[ACCOUNT_MANAGER] Account logged in: " + e.getAccount()); 6443 }; 6444 6445 net.user1.orbiter.CoreEventLogger.prototype.changePasswordListener = function (e) { 6446 this.log.info("[ACCOUNT_MANAGER] Password changed for account: " + e.getUserID()); 6447 }; 6448 6449 net.user1.orbiter.CoreEventLogger.prototype.observeAccountListener = function (e) { 6450 this.log.info("[ACCOUNT_MANAGER] Account observed: " + e.getAccount()); 6451 }; 6452 6453 net.user1.orbiter.CoreEventLogger.prototype.stopObservingAccountListener = function (e) { 6454 this.log.info("[ACCOUNT_MANAGER] Stopped observing account: " + e.getUserID()); 6455 }; 6456 6457 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForAccountsResultListener = function (e) { 6458 this.log.info("[SERVER] 'Stop watching for accounts' result: " + e.getStatus()); 6459 }; 6460 6461 net.user1.orbiter.CoreEventLogger.prototype.watchForAccountsResultListener = function (e) { 6462 this.log.info("[ACCOUNT_MANAGER] 'Watch for accounts' result: " + e.getStatus()); 6463 }; 6464 6465 net.user1.orbiter.CoreEventLogger.prototype.observeAccountResultListener = function (e) { 6466 this.log.info("[ACCOUNT_MANAGER] 'Observe account result' for account: " 6467 + e.getAccount() + ", Status: " + e.getStatus()); 6468 }; 6469 6470 net.user1.orbiter.CoreEventLogger.prototype.stopObservingAccountResultListener = function (e) { 6471 this.log.info("[ACCOUNT_MANAGER] 'Stop observing account result' for account: " 6472 + e.getUserID() + ", Status: " + e.getStatus()); 6473 }; 6474 6475 net.user1.orbiter.CoreEventLogger.prototype.synchronizeAccountsListener = function (e) { 6476 this.log.info("[ACCOUNT_MANAGER] User account list synchronized with server."); 6477 }; 6478 6479 // ============================================================================= 6480 // CONNECTION EVENT LISTENERS 6481 // ============================================================================= 6482 6483 net.user1.orbiter.CoreEventLogger.prototype.connectFailureListener = function (e) { 6484 this.log.info("[CONNECTION_MANAGER] " + e.getStatus()); 6485 }; 6486 6487 net.user1.orbiter.CoreEventLogger.prototype.serverKillConnectListener = function (e) { 6488 this.log.info("[CONNECTION_MANAGER] Server closed the connection."); 6489 }; 6490 6491 net.user1.orbiter.CoreEventLogger.prototype.clientKillConnectListener = function (e) { 6492 this.log.info("[CONNECTION_MANAGER] Connection to server closed by client."); 6493 }; 6494 6495 // ============================================================================= 6496 // RoomManager EVENT LISTENERS 6497 // ============================================================================= 6498 6499 net.user1.orbiter.CoreEventLogger.prototype.watchForRoomsResultListener = function (e) { 6500 this.log.info("[ROOM_MANAGER] 'Watch for rooms' result for qualifier [" 6501 + e.getRoomIdQualifier() + "]: " + e.getStatus()); 6502 }; 6503 6504 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForRoomsResultListener = function (e) { 6505 this.log.info("[ROOM_MANAGER] 'Stop watching for rooms' result for" 6506 + " qualifier [" + e.getRoomIdQualifier() 6507 + "]: " + e.getStatus()); 6508 }; 6509 6510 net.user1.orbiter.CoreEventLogger.prototype.createRoomResultListener = function (e) { 6511 this.log.info("[ROOM_MANAGER] Room creation result for room [" 6512 + e.getRoomID() + "]: " + e.getStatus()); 6513 }; 6514 6515 net.user1.orbiter.CoreEventLogger.prototype.removeRoomResultListener = function (e) { 6516 this.log.info("[ROOM_MANAGER] Room removal result for room [" 6517 + e.getRoomID() + "]: " + e.getStatus()); 6518 }; 6519 6520 net.user1.orbiter.CoreEventLogger.prototype.roomAddedListener = function (e) { 6521 this.log.info("[ROOM_MANAGER] Room added: " + e.getRoom() + "."); 6522 }; 6523 6524 net.user1.orbiter.CoreEventLogger.prototype.roomRemovedListener = function (e) { 6525 this.log.info("[ROOM_MANAGER] Room removed: " + e.getRoom() + "."); 6526 }; 6527 6528 net.user1.orbiter.CoreEventLogger.prototype.roomCountListener = function (e) { 6529 this.log.info("[ROOM_MANAGER] New room count: " + e.getNumRooms() + "."); 6530 }; 6531 6532 net.user1.orbiter.CoreEventLogger.prototype.joinRoomResultListener = function (e) { 6533 this.log.info("[ROOM_MANAGER] Join result for room [" 6534 + e.getRoomID() + "]: " + e.getStatus()); 6535 }; 6536 6537 net.user1.orbiter.CoreEventLogger.prototype.leaveRoomResultListener = function (e) { 6538 this.log.info("[ROOM_MANAGER] Leave result for room [" 6539 + e.getRoomID() + "]: " + e.getStatus()); 6540 }; 6541 6542 net.user1.orbiter.CoreEventLogger.prototype.observeRoomResultListener = function (e) { 6543 this.log.info("[ROOM_MANAGER] Observe result for room [" 6544 + e.getRoomID() + "]: " + e.getStatus()); 6545 }; 6546 6547 net.user1.orbiter.CoreEventLogger.prototype.stopObservingRoomResultListener = function (e) { 6548 this.log.info("[ROOM_MANAGER] Stop observing result for room [" 6549 + e.getRoomID() + "]: " + e.getStatus()); 6550 }; 6551 6552 // ============================================================================= 6553 // ClientManager EVENT LISTENERS 6554 // ============================================================================= 6555 6556 net.user1.orbiter.CoreEventLogger.prototype.observeClientListener = function (e) { 6557 this.log.info("[CLIENT_MANAGER] Client observed: " + e.getClient()); 6558 }; 6559 6560 net.user1.orbiter.CoreEventLogger.prototype.stopObservingClientListener = function (e) { 6561 this.log.info("[CLIENT_MANAGER] Stopped observing client: " + e.getClient()); 6562 }; 6563 6564 net.user1.orbiter.CoreEventLogger.prototype.clientConnectedListener = function (e) { 6565 this.log.info("[CLIENT_MANAGER] Foreign client connected. ClientID: [" + e.getClientID() 6566 + "]."); 6567 }; 6568 6569 net.user1.orbiter.CoreEventLogger.prototype.clientDisconnectedListener = function (e) { 6570 this.log.info("[CLIENT_MANAGER] Foreign client disconnected. ClientID: [" + e.getClientID() 6571 + "]."); 6572 }; 6573 6574 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForClientsResultListener = function (e) { 6575 this.log.info("[CLIENT_MANAGER] 'Stop watching for clients' result: " + e.getStatus()); 6576 }; 6577 6578 net.user1.orbiter.CoreEventLogger.prototype.watchForClientsResultListener = function (e) { 6579 this.log.info("[CLIENT_MANAGER] 'Watch for clients' result: " + e.getStatus()); 6580 }; 6581 6582 net.user1.orbiter.CoreEventLogger.prototype.observeClientResultListener = function (e) { 6583 this.log.info("[CLIENT_MANAGER] 'Observe client' result for client: " 6584 + e.getClient() + ", status: " + e.getStatus()); 6585 }; 6586 6587 net.user1.orbiter.CoreEventLogger.prototype.stopObservingClientResultListener = function (e) { 6588 this.log.info("[CLIENT_MANAGER] 'Stop observing client' result for client: " 6589 + e.getClient() + ", status: " + e.getStatus()); 6590 }; 6591 6592 net.user1.orbiter.CoreEventLogger.prototype.synchronizeClientsListener = function (e) { 6593 this.log.info("[CLIENT_MANAGER] Client list synchronized with server."); 6594 }; 6595 6596 net.user1.orbiter.CoreEventLogger.prototype.addressBannedListener = function (e) { 6597 this.log.info("[CLIENT_MANAGER] Client address banned: [" + e.getAddress() 6598 + "]."); 6599 }; 6600 6601 net.user1.orbiter.CoreEventLogger.prototype.addressUnbannedListener = function (e) { 6602 this.log.info("[CLIENT_MANAGER] Client address unbanned. ClientID: [" + e.getAddress() 6603 + "]."); 6604 }; 6605 6606 net.user1.orbiter.CoreEventLogger.prototype.stopWatchingForBannedAddressesResultListener = function (e) { 6607 this.log.info("[CLIENT_MANAGER] 'Stop watching for banned addresses' result: " + e.getStatus()); 6608 }; 6609 6610 net.user1.orbiter.CoreEventLogger.prototype.watchForBannedAddressesResultListener = function (e) { 6611 this.log.info("[CLIENT_MANAGER] 'Watch for banned addresses' result: " + e.getStatus()); 6612 }; 6613 6614 net.user1.orbiter.CoreEventLogger.prototype.synchronizeBanlistListener = function (e) { 6615 this.log.info("[CLIENT_MANAGER] Banned list synchronized with server."); 6616 }; 6617 6618 6619 6620 6621 6622 //============================================================================== 6623 // CLASS DECLARATION 6624 //============================================================================== 6625 /** 6626 * @class 6627 * The CoreMessageListener class is an internal class that responds to the 6628 * built-in UPC messages sent by the Union Server to the Orbiter. The 6629 * CoreMessageListener class does not define any public methods or variables. 6630 * 6631 * @private 6632 */ 6633 net.user1.orbiter.CoreMessageListener = function (orbiter) { 6634 /** 6635 * @type net.user1.orbiter.Orbiter 6636 */ 6637 this.orbiter = orbiter; 6638 this.log = orbiter.getLog(); 6639 this.registerCoreListeners(); 6640 this.orbiter.getConnectionManager().addEventListener(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 6641 this.selectConnectionListener, this); 6642 6643 this.roomMan = this.orbiter.getRoomManager(); 6644 this.accountMan = this.orbiter.getAccountManager(); 6645 this.clientMan = this.orbiter.getClientManager(); 6646 this.snapshotMan = this.orbiter.getSnapshotManager(); 6647 }; 6648 6649 //============================================================================== 6650 // INSTANCE METHODS 6651 //============================================================================== 6652 net.user1.orbiter.CoreMessageListener.prototype.registerCoreListeners = function () { 6653 var msgMan = this.orbiter.getMessageManager(); 6654 msgMan.addMessageListener(net.user1.orbiter.UPC.JOINED_ROOM, this.u6, this); 6655 msgMan.addMessageListener(net.user1.orbiter.UPC.RECEIVE_MESSAGE, this.u7, this); 6656 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ATTR_UPDATE, this.u8, this); 6657 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_ATTR_UPDATE, this.u9, this); 6658 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_METADATA, this.u29, this); 6659 msgMan.addMessageListener(net.user1.orbiter.UPC.CREATE_ROOM_RESULT, this.u32, this); 6660 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ROOM_RESULT, this.u33, this); 6661 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENTCOUNT_SNAPSHOT, this.u34, this); 6662 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ADDED_TO_ROOM, this.u36, this); 6663 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_ROOM, this.u37, this); 6664 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOMLIST_SNAPSHOT, this.u38, this); 6665 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_ADDED, this.u39, this); 6666 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_REMOVED, this.u40, this); 6667 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_ROOMS_RESULT, this.u42, this); 6668 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS_RESULT, this.u43, this); 6669 msgMan.addMessageListener(net.user1.orbiter.UPC.LEFT_ROOM, this.u44, this); 6670 msgMan.addMessageListener(net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD_RESULT, this.u46, this); 6671 msgMan.addMessageListener(net.user1.orbiter.UPC.CREATE_ACCOUNT_RESULT, this.u47, this); 6672 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ACCOUNT_RESULT, this.u48, this); 6673 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGIN_RESULT, this.u49, this); 6674 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_SNAPSHOT, this.u54, this); 6675 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVED_ROOM, this.u59, this); 6676 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT_RESULT, this.u60, this); 6677 msgMan.addMessageListener(net.user1.orbiter.UPC.STOPPED_OBSERVING_ROOM, this.u62, this); 6678 msgMan.addMessageListener(net.user1.orbiter.UPC.SERVER_HELLO, this.u66, this); 6679 msgMan.addMessageListener(net.user1.orbiter.UPC.JOIN_ROOM_RESULT, this.u72, this); 6680 msgMan.addMessageListener(net.user1.orbiter.UPC.SET_CLIENT_ATTR_RESULT, this.u73, this); 6681 msgMan.addMessageListener(net.user1.orbiter.UPC.SET_ROOM_ATTR_RESULT, this.u74, this); 6682 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT_RESULT, this.u75, this); 6683 msgMan.addMessageListener(net.user1.orbiter.UPC.LEAVE_ROOM_RESULT, this.u76, this); 6684 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVE_ROOM_RESULT, this.u77, this); 6685 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_OBSERVING_ROOM_RESULT, this.u78, this); 6686 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_ATTR_REMOVED, this.u79, this); 6687 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ROOM_ATTR_RESULT, this.u80, this); 6688 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ATTR_REMOVED, this.u81, this); 6689 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR_RESULT, this.u82, this); 6690 msgMan.addMessageListener(net.user1.orbiter.UPC.SESSION_TERMINATED, this.u84, this); 6691 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGOFF_RESULT, this.u87, this); 6692 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGGED_IN, this.u88, this); 6693 msgMan.addMessageListener(net.user1.orbiter.UPC.LOGGED_OFF, this.u89, this); 6694 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_PASSWORD_CHANGED, this.u90, this); 6695 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENTLIST_SNAPSHOT, this.u101, this); 6696 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_ADDED_TO_SERVER, this.u102, this); 6697 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_SERVER, this.u103, this); 6698 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_SNAPSHOT, this.u104, this); 6699 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVE_CLIENT_RESULT, this.u105, this); 6700 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT_RESULT, this.u106, this); 6701 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_CLIENTS_RESULT, this.u107, this); 6702 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS_RESULT, this.u108, this); 6703 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS_RESULT, this.u109, this); 6704 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS_RESULT, this.u110, this); 6705 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_ADDED, this.u111, this); 6706 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_REMOVED, this.u112, this); 6707 msgMan.addMessageListener(net.user1.orbiter.UPC.JOINED_ROOM_ADDED_TO_CLIENT, this.u113, this); 6708 msgMan.addMessageListener(net.user1.orbiter.UPC.JOINED_ROOM_REMOVED_FROM_CLIENT, this.u114, this); 6709 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT_RESULT, this.u115, this); 6710 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT_RESULT, this.u116, this); 6711 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVED_ROOM_ADDED_TO_CLIENT, this.u117, this); 6712 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVED_ROOM_REMOVED_FROM_CLIENT, this.u118, this); 6713 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_OBSERVED, this.u119, this); 6714 msgMan.addMessageListener(net.user1.orbiter.UPC.STOPPED_OBSERVING_CLIENT, this.u120, this); 6715 msgMan.addMessageListener(net.user1.orbiter.UPC.OBSERVE_ACCOUNT_RESULT, this.u123, this); 6716 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_OBSERVED, this.u124, this); 6717 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT_RESULT, this.u125, this); 6718 msgMan.addMessageListener(net.user1.orbiter.UPC.STOPPED_OBSERVING_ACCOUNT, this.u126, this); 6719 msgMan.addMessageListener(net.user1.orbiter.UPC.ACCOUNT_LIST_UPDATE, this.u127, this); 6720 msgMan.addMessageListener(net.user1.orbiter.UPC.UPDATE_LEVELS_UPDATE, this.u128, this); 6721 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_OBSERVED_ROOM, this.u129, this); 6722 msgMan.addMessageListener(net.user1.orbiter.UPC.CLIENT_STOPPED_OBSERVING_ROOM, this.u130, this); 6723 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_OCCUPANTCOUNT_UPDATE, this.u131, this); 6724 msgMan.addMessageListener(net.user1.orbiter.UPC.ROOM_OBSERVERCOUNT_UPDATE, this.u132, this); 6725 msgMan.addMessageListener(net.user1.orbiter.UPC.ADD_ROLE_RESULT, this.u134, this); 6726 msgMan.addMessageListener(net.user1.orbiter.UPC.REMOVE_ROLE_RESULT, this.u136, this); 6727 msgMan.addMessageListener(net.user1.orbiter.UPC.BAN_RESULT, this.u138, this); 6728 msgMan.addMessageListener(net.user1.orbiter.UPC.UNBAN_RESULT, this.u140, this); 6729 msgMan.addMessageListener(net.user1.orbiter.UPC.BANNED_LIST_SNAPSHOT, this.u142, this); 6730 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES_RESULT, this.u144, this); 6731 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT, this.u146, this); 6732 msgMan.addMessageListener(net.user1.orbiter.UPC.BANNED_ADDRESS_ADDED, this.u147, this); 6733 msgMan.addMessageListener(net.user1.orbiter.UPC.BANNED_ADDRESS_REMOVED, this.u148, this); 6734 msgMan.addMessageListener(net.user1.orbiter.UPC.KICK_CLIENT_RESULT, this.u150, this); 6735 msgMan.addMessageListener(net.user1.orbiter.UPC.SERVERMODULELIST_SNAPSHOT, this.u152, this); 6736 msgMan.addMessageListener(net.user1.orbiter.UPC.GET_UPC_STATS_SNAPSHOT_RESULT, this.u155, this); 6737 msgMan.addMessageListener(net.user1.orbiter.UPC.UPC_STATS_SNAPSHOT, this.u156, this); 6738 msgMan.addMessageListener(net.user1.orbiter.UPC.RESET_UPC_STATS_RESULT, this.u158, this); 6739 msgMan.addMessageListener(net.user1.orbiter.UPC.WATCH_FOR_PROCESSED_UPCS_RESULT, this.u160, this); 6740 msgMan.addMessageListener(net.user1.orbiter.UPC.PROCESSED_UPC_ADDED, this.u161, this); 6741 msgMan.addMessageListener(net.user1.orbiter.UPC.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT, this.u163, this); 6742 msgMan.addMessageListener(net.user1.orbiter.UPC.NODELIST_SNAPSHOT, this.u166, this); 6743 msgMan.addMessageListener(net.user1.orbiter.UPC.GATEWAYS_SNAPSHOT, this.u168, this); 6744 } 6745 6746 net.user1.orbiter.CoreMessageListener.prototype.createHashFromArg = function (arg) { 6747 var list = arg.split(net.user1.orbiter.Tokens.RS); 6748 var hash = new Object(); 6749 6750 for (var i = 0; i < list.length; i += 2) { 6751 hash[list[i]] = list[i+1]; 6752 } 6753 return hash; 6754 }; 6755 6756 net.user1.orbiter.CoreMessageListener.prototype.selectConnectionListener = function (e) { 6757 var msgMan = this.orbiter.getMessageManager(); 6758 if (msgMan.removeListenersOnDisconnect) { 6759 this.registerCoreListeners(); 6760 } 6761 }; 6762 6763 /** 6764 * Room joined. 6765 */ 6766 net.user1.orbiter.CoreMessageListener.prototype.u6 = function (roomID) { 6767 // Add the room to the occupied room list 6768 var room = this.roomMan.addOccupiedRoom(roomID); 6769 // Tell the room to do its join duties 6770 room.doJoin(); 6771 // Fire JOIN through the client 6772 var selfClient = this.clientMan.self(); 6773 if (selfClient) { 6774 selfClient.fireJoinRoom(room, roomID); 6775 } 6776 }; 6777 6778 /** 6779 * Handles sendMessage() calls sent by other clients. 6780 */ 6781 net.user1.orbiter.CoreMessageListener.prototype.u7 = function (message, 6782 broadcastType, 6783 fromClientID, 6784 toRoomID) { 6785 var msgMan = this.orbiter.getMessageManager(); 6786 var listenerError; 6787 var fromClient; 6788 var toRoom; 6789 var args; // Args passed to the messsage listener 6790 var userDefinedArgs = Array.prototype.slice.call(arguments).slice(4); 6791 6792 // Retrieve the Room object for the recipient room. 6793 toRoom = this.roomMan.getRoom(toRoomID); 6794 6795 // Retrieve the Client object for the sender 6796 if (fromClientID == "") { 6797 // No client ID was supplied, so the message was generated by the 6798 // server, not by a client, so set fromClient to null. 6799 fromClient = null; 6800 } else { 6801 // A valid ID was supplied, so find or create the matching IClient object 6802 fromClient = this.clientMan.getClient(fromClientID); 6803 fromClient = fromClient == null ? this.clientMan.requestClient(fromClientID) : fromClient; 6804 } 6805 6806 // ===== To Clients, or To Server ===== 6807 // If the message was sent to a specific client, a list of specific clients, 6808 // or to the whole server, then args passed to registered message listeners 6809 // are: the Client object plus all user-defined arguments originally passed 6810 // to sendMessage(). 6811 if (broadcastType != net.user1.orbiter.ReceiveMessageBroadcastType.TO_ROOMS) { 6812 args = [fromClient].concat(userDefinedArgs); 6813 try { 6814 msgMan.notifyMessageListeners(message, args); 6815 } catch (e) { 6816 listenerError = e; 6817 } 6818 } else { 6819 6820 // ===== To Rooms ===== 6821 // Check if the room is valid 6822 if (toRoom == null) { 6823 this.log.warn("Message (u7) received for unknown room: [" + toRoomID + "]" 6824 + "Message: [" + message + "]"); 6825 return; 6826 } 6827 6828 // RECEIVE_MESSAGE was a response to SEND_MESSAGE_TO_ROOMS, so 6829 // we notify listeners only if they asked to be told about messages 6830 // sent to the recipient room. 6831 6832 // First, get the list of messsage listeners for this message 6833 var listeners = msgMan.getMessageListeners(message); 6834 6835 // Split the recipient room ID into two parts 6836 var toRoomSimpleID = net.user1.orbiter.RoomIDParser.getSimpleRoomID(toRoomID); 6837 var toRoomQualifier = net.user1.orbiter.RoomIDParser.getQualifier(toRoomID); 6838 6839 // If the message can be dispatched, set to true. 6840 var listenerFound; 6841 // If the listener isn't interested in messages sent to the 6842 // recipient room, set to true. 6843 var listenerIgnoredMessage; 6844 6845 // ===== Run once for each message listener ===== 6846 var messageListener; 6847 for (var i = 0; i < listeners.length; i++) { 6848 messageListener = listeners[i]; 6849 6850 // Assume this listener ignored the message until we prove it didn't 6851 listenerIgnoredMessage = true; 6852 6853 // --- Has no "forRoomIDs" filter --- 6854 // If the listener doesn't specify any forRoomIDs, then 6855 // just send it the message notification. (No-rooms-specified 6856 // means the listener wants all of these messages, no matter 6857 // which room they were sent to.) This listener is told which 6858 // room the message was sent to via args[1] (toRoomID). 6859 if (messageListener.getForRoomIDs() == null) { 6860 args = [fromClient, toRoom].concat(userDefinedArgs); 6861 try { 6862 messageListener.getListenerFunction().apply(messageListener.getThisArg(), args); 6863 } catch (e) { 6864 listenerError = e; 6865 } 6866 listenerFound = true; 6867 listenerIgnoredMessage = false; 6868 continue; // Done with this listener. On to the next. 6869 } 6870 6871 // --- Has a "forRoomIDs" filter --- 6872 // If the message was sent to any of the rooms the listener is 6873 // interested in, then notify that listener. Note that a listener 6874 // for messages sent to room foo.* means the listener wants 6875 // notifications for all rooms whose ids start with foo. 6876 var listenerRoomIDs = messageListener.getForRoomIDs(); 6877 var listenerRoomQualifier; 6878 var listenerRoomSimpleID; 6879 // ===== Run once for each room id ===== 6880 var listenerRoomIDString; 6881 for (var j = 0; j < listenerRoomIDs.length; j++) { 6882 listenerRoomIDString = listenerRoomIDs[j]; 6883 // Split the room id 6884 listenerRoomQualifier = net.user1.orbiter.RoomIDParser.getQualifier(listenerRoomIDString); 6885 listenerRoomSimpleID = net.user1.orbiter.RoomIDParser.getSimpleRoomID(listenerRoomIDString); 6886 6887 // Check if the listener is interested in the recipient room... 6888 if (listenerRoomQualifier == toRoomQualifier 6889 && 6890 (listenerRoomSimpleID == toRoomSimpleID 6891 || listenerRoomSimpleID == "*")) { 6892 // Found a match. Notify the listener... 6893 6894 // Prepare args. 6895 if (listenerRoomIDs.length == 1) { 6896 // The listener is interested in messages sent to a 6897 // specific room only, so omit the "toRoom" arg. 6898 // (The listener already knows the target room because 6899 // it's only notified if the message was sent to that room.) 6900 args = [fromClient].concat(userDefinedArgs); 6901 } else { 6902 // The listener is interested in messages sent to 6903 // multiple rooms. In this case, we have to 6904 // include the "toRoom" arg so the listener knows 6905 // which room received the message. 6906 args = [fromClient, toRoom].concat(userDefinedArgs); 6907 } 6908 6909 try { 6910 messageListener.getListenerFunction().apply(messageListener.getThisArg(), args); 6911 } catch (e) { 6912 listenerError = e; 6913 } 6914 listenerFound = true; 6915 listenerIgnoredMessage = false; 6916 break; // Stop looking at this listener's room ids 6917 } 6918 } // Done looking at this listener's room ids 6919 if (listenerIgnoredMessage) { 6920 this.log.debug("Message listener ignored message: " + message + ". " 6921 + "Listener registered to receive " 6922 + "messages sent to: " + messageListener.getForRoomIDs() 6923 + ", but message was sent to: " + toRoomID); 6924 } 6925 } 6926 if (!listenerFound) { 6927 this.log.warn("No message listener handled incoming message: " 6928 + message + ", sent to: " + toRoomID); 6929 } 6930 } // Done looking at listeners for the incoming message 6931 6932 if (listenerError != null) { 6933 throw new Error("A message listener for incoming message [" + message + "]" + 6934 (fromClient == null ? "" : ", received from client [" + fromClient.getClientID() + "],") + 6935 " encountered an error:\n\n" + listenerError.toString() + 6936 "\n\nEnsure that all [" + message + "] listeners supply a first" + 6937 " parameter whose datatype is Client (or a compatible type). Listeners" + 6938 " that registered for the message via MessageManager's addMessageListener()" + 6939 " with anything other than a single roomID for the toRoomIDs parameter must" + 6940 " also define a second paramter whose" + 6941 " datatype is Room (or a compatible type). Finally, ensure that" + 6942 " the listener's declared message parameters match the following actual message" + 6943 " arguments:\n " + userDefinedArgs 6944 + (typeof listenerError.stack === "undefined" ? "" : "\n\nStack trace follows:\n" + listenerError.stack) 6945 ); 6946 } 6947 } 6948 6949 /** 6950 * Client attribute update 6951 */ 6952 net.user1.orbiter.CoreMessageListener.prototype.u8 = function (attrScope, 6953 clientID, 6954 userID, 6955 attrName, 6956 attrVal, 6957 attrOptions) { 6958 var client; 6959 var account; 6960 var options = parseInt(attrOptions); 6961 6962 if (options &net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 6963 account = this.accountMan.getAccount(userID); 6964 if (account != null) { 6965 account.getAttributeManager().setAttributeLocal(attrName, attrVal, attrScope); 6966 } else { 6967 throw new Error("[CORE_MESSAGE_LISTENER] Received an attribute update for " 6968 + " an unknown user account [" + userID + "]. Please report this error with" 6969 + " the following log to union@user1.net.\n" 6970 + this.log.getHistory().join("\n")); 6971 } 6972 } else { 6973 client = this.clientMan.getInternalClient(clientID); 6974 if (client != null) { 6975 client.getAttributeManager().setAttributeLocal(attrName, attrVal, attrScope); 6976 } else { 6977 throw new Error("[CORE_MESSAGE_LISTENER] Received an attribute update for " 6978 + " an unknown client [" + clientID + "]. Please report this error with" 6979 + " the following log to union@user1.net.\n" 6980 + this.log.getHistory().join("\n")); 6981 } 6982 } 6983 }; 6984 6985 /** 6986 * Room attribute update 6987 */ 6988 net.user1.orbiter.CoreMessageListener.prototype.u9 = function (roomID, 6989 byClientID, 6990 attrName, 6991 attrVal) { 6992 var theRoom = this.roomMan.getRoom(roomID); 6993 var byClient; 6994 6995 // Quit if the room isn't found 6996 if (theRoom == null) { 6997 this.log.warn("Room attribute update received for server-side room with no" + 6998 " matching client-side Room object. Room ID [" + 6999 roomID + "]. Attribute: [" + attrName + "]."); 7000 return; 7001 } 7002 7003 // Retrieve the Client object for the sender 7004 if (byClientID == "") { 7005 // No client ID was supplied, so the message was generated by the 7006 // server, not by a client, so set fromClient to null. 7007 byClient = null; 7008 } else { 7009 // A valid ID was supplied, so find or create the matching IClient object 7010 byClient = this.clientMan.getClient(byClientID); 7011 byClient = byClient == null ? this.clientMan.requestClient(byClientID) : byClient; 7012 } 7013 7014 theRoom.getAttributeManager().setAttributeLocal(attrName, attrVal, net.user1.orbiter.Tokens.GLOBAL_ATTR, byClient); 7015 }; 7016 7017 /** 7018 * CLIENT_METADATA 7019 */ 7020 net.user1.orbiter.CoreMessageListener.prototype.u29 = function (id) { 7021 var theClient = this.clientMan.requestClient(id); 7022 this.clientMan.setSelf(theClient); 7023 }; 7024 7025 /** 7026 * CREATE_ROOM_RESULT 7027 */ 7028 net.user1.orbiter.CoreMessageListener.prototype.u32 = function (roomID, status) { 7029 var theRoom = this.roomMan.getRoom(roomID); 7030 switch (status) { 7031 case net.user1.orbiter.Status.ERROR: 7032 case net.user1.orbiter.Status.SUCCESS: 7033 case net.user1.orbiter.Status.ROOM_EXISTS: 7034 case net.user1.orbiter.Status.PERMISSION_DENIED: 7035 this.roomMan.fireCreateRoomResult(net.user1.orbiter.RoomIDParser.getQualifier(roomID), 7036 net.user1.orbiter.RoomIDParser.getSimpleRoomID(roomID), 7037 status); 7038 break; 7039 7040 default: 7041 this.log.warn("Unrecognized status code for u32." 7042 + " Room ID: [" + roomID + "], status: [" + status + "]."); 7043 } 7044 }; 7045 7046 /** 7047 * REMOVE_ROOM_RESULT 7048 */ 7049 net.user1.orbiter.CoreMessageListener.prototype.u33 = function (roomID, status) { 7050 this.roomMan.fireRemoveRoomResult(net.user1.orbiter.RoomIDParser.getQualifier(roomID), 7051 net.user1.orbiter.RoomIDParser.getSimpleRoomID(roomID), 7052 status); 7053 switch (status) { 7054 case net.user1.orbiter.Status.ERROR: 7055 this.log.warn("Server error for room removal attempt: " + roomID); 7056 break; 7057 case net.user1.orbiter.Status.PERMISSION_DENIED: 7058 this.log.info("Attempt to remove room [" + roomID 7059 + "] failed. Permission denied. See server log for details."); 7060 break; 7061 7062 case net.user1.orbiter.Status.SUCCESS: 7063 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7064 if (this.roomMan.getRoom(roomID) != null) { 7065 this.roomMan.disposeRoom(roomID); 7066 } 7067 break; 7068 7069 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7070 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7071 break; 7072 7073 default: 7074 this.log.warn("Unrecognized status code for u33." 7075 + " Room ID: [" + roomID + "], status: [" + status + "]."); 7076 } 7077 }; 7078 7079 /** 7080 * CLIENTCOUNT_SNAPSHOT 7081 */ 7082 net.user1.orbiter.CoreMessageListener.prototype.u34 = function (requestID, 7083 numClients) { 7084 this.snapshotMan.receiveClientCountSnapshot(requestID, parseInt(numClients)); 7085 }; 7086 7087 /** 7088 * CLIENT_ADDED_TO_ROOM 7089 */ 7090 net.user1.orbiter.CoreMessageListener.prototype.u36 = function (roomID, 7091 clientID, 7092 userID, 7093 globalAttributes, 7094 roomAttributes) { 7095 var theClient = this.clientMan.requestClient(clientID); 7096 var account = this.accountMan.requestAccount(userID); 7097 var clientManifest; 7098 if (account != null 7099 && theClient.getAccount() != account) { 7100 theClient.setAccount(account); 7101 } 7102 7103 // If it's not the current client, set the client's attributes. 7104 // (The current client obtains its own attributes through separate u8s.) 7105 var theRoom = this.roomMan.getRoom(roomID); 7106 if (!theClient.isSelf()) { 7107 clientManifest = new net.user1.orbiter.ClientManifest(); 7108 clientManifest.deserialize(clientID, userID, null, 7109 null, globalAttributes, [roomID, roomAttributes]); 7110 theClient.synchronize(clientManifest); 7111 7112 // If the client is observed, don't fire JOIN; observed clients always 7113 // fire JOIN based on observation updates. Likewise, don't fire JOIN 7114 // on self; self fires JOIN when it receives a u6. 7115 if (!this.clientMan.isObservingClient(clientID)) { 7116 theClient.fireJoinRoom(theRoom, roomID); 7117 } 7118 } 7119 7120 // Add the client to the given room. 7121 theRoom.addOccupant(theClient); 7122 }; 7123 7124 /** 7125 * CLIENT_REMOVED_FROM_ROOM 7126 */ 7127 net.user1.orbiter.CoreMessageListener.prototype.u37 = function (roomID, 7128 clientID) { 7129 // Remove the room from the client's list of occupied rooms 7130 var theClient = this.clientMan.requestClient(clientID); 7131 var theRoom = this.roomMan.getRoom(roomID); 7132 7133 // Remove the client from the given room 7134 theRoom.removeOccupant(clientID); 7135 7136 // Don't fire LEAVE on self; self fires LEAVE when it receives a u44. 7137 if (!theClient.isSelf()) { 7138 // If the client is observed, don't fire LEAVE; observed clients always 7139 // fire LEAVE based on observation updates. 7140 if (!this.clientMan.isObservingClient(clientID)) { 7141 theClient.fireLeaveRoom(theRoom, roomID); 7142 } 7143 } 7144 }; 7145 7146 /** 7147 * ROOMLIST_SNAPSHOT 7148 */ 7149 net.user1.orbiter.CoreMessageListener.prototype.u38 = function (requestID, 7150 requestedRoomIDQualifier, 7151 recursive) { 7152 var args = Array.prototype.slice.call(arguments).slice(3); 7153 var roomQualifier; 7154 var roomIDs; 7155 var roomList = []; 7156 7157 if (requestID == "") { 7158 // Synchronize 7159 for (var i = 0; i < args.length; i+=2) { 7160 roomQualifier = args[i]; 7161 roomIDs = args[i+1].split(net.user1.orbiter.Tokens.RS); 7162 7163 this.roomMan.setWatchedRooms(roomQualifier, roomIDs); 7164 } 7165 } else { 7166 // Snapshot 7167 for (i = 0; i < args.length; i+=2) { 7168 roomQualifier = args[i]; 7169 roomIDs = args[i+1].split(net.user1.orbiter.Tokens.RS); 7170 for (var j = 0; j < roomIDs.length; j++) { 7171 roomList.push(roomQualifier + (roomQualifier == "" ? "" : ".") + roomIDs[j]); 7172 } 7173 } 7174 this.snapshotMan.receiveRoomListSnapshot(requestID, roomList, requestedRoomIDQualifier, recursive == "true"); 7175 } 7176 }; 7177 7178 /** 7179 * ROOM_ADDED 7180 */ 7181 net.user1.orbiter.CoreMessageListener.prototype.u39 = function (roomID) { 7182 // Add the room 7183 this.roomMan.addWatchedRoom(roomID); 7184 }; 7185 7186 /** 7187 * ROOM_REMOVED 7188 */ 7189 net.user1.orbiter.CoreMessageListener.prototype.u40 = function (roomID) { 7190 this.roomMan.removeWatchedRoom(roomID); 7191 if (this.roomMan.getRoom(roomID) != null) { 7192 this.roomMan.disposeRoom(roomID); 7193 } 7194 }; 7195 7196 /** 7197 * WATCH_FOR_ROOMS_RESULT 7198 */ 7199 net.user1.orbiter.CoreMessageListener.prototype.u42 = function (roomIdQualifier, recursive, status) { 7200 // Broadcast the result of the observation attempt. 7201 this.roomMan.fireWatchForRoomsResult(roomIdQualifier, status); 7202 switch (status) { 7203 case net.user1.orbiter.Status.SUCCESS: 7204 case net.user1.orbiter.Status.ERROR: 7205 case net.user1.orbiter.Status.INVALID_QUALIFIER: 7206 case net.user1.orbiter.Status.ALREADY_WATCHING: 7207 case net.user1.orbiter.Status.PERMISSION_DENIED: 7208 break; 7209 7210 default: 7211 this.log.warn("Unrecognized status code for u42." 7212 + " Room ID Qualifier: [" + roomIdQualifier + "], recursive: [" 7213 + recursive + "], status: [" + status + "]."); 7214 } 7215 }; 7216 7217 /** 7218 * STOP_WATCHING_FOR_ROOMS_RESULT 7219 */ 7220 net.user1.orbiter.CoreMessageListener.prototype.u43 = function (roomIdQualifier, recursive, status) { 7221 switch (status) { 7222 case net.user1.orbiter.Status.SUCCESS: 7223 if (roomIdQualifier == "" && recursive == "true") { 7224 this.roomMan.removeAllWatchedRooms(); 7225 } else { 7226 // Remove all watched rooms for the qualifier 7227 this.roomMan.setWatchedRooms(roomIdQualifier, []); 7228 } 7229 case net.user1.orbiter.Status.ERROR: 7230 case net.user1.orbiter.Status.NOT_WATCHING: 7231 case net.user1.orbiter.Status.INVALID_QUALIFIER: 7232 this.roomMan.fireStopWatchingForRoomsResult(roomIdQualifier, status); 7233 break; 7234 7235 default: 7236 this.log.warn("Unrecognized status code for u43." 7237 + " Room ID Qualifier: [" + roomIdQualifier + "], recursive: [" 7238 + recursive + "], status: [" + status + "]."); 7239 } 7240 }; 7241 7242 /** 7243 * LEFT_ROOM 7244 */ 7245 net.user1.orbiter.CoreMessageListener.prototype.u44 = function (roomID) { 7246 var leftRoom = this.roomMan.getRoom(roomID); 7247 this.roomMan.removeOccupiedRoom(roomID); 7248 if (leftRoom != null) { 7249 leftRoom.doLeave(); 7250 this.clientMan.self().fireLeaveRoom(leftRoom, roomID); 7251 } 7252 }; 7253 7254 /** 7255 * CHANGE_ACCOUNT_PASSWORD_RESULT 7256 */ 7257 net.user1.orbiter.CoreMessageListener.prototype.u46 = function (userID, status) { 7258 var account = this.accountMan.getAccount(userID); 7259 if (account != null) { 7260 account.fireChangePasswordResult(status); 7261 } 7262 this.accountMan.fireChangePasswordResult(userID, status); 7263 }; 7264 7265 /** 7266 * CREATE_ACCOUNT_RESULT 7267 */ 7268 net.user1.orbiter.CoreMessageListener.prototype.u47 = function (userID, status) { 7269 switch (status) { 7270 case net.user1.orbiter.Status.SUCCESS: 7271 case net.user1.orbiter.Status.ERROR: 7272 case net.user1.orbiter.Status.ACCOUNT_EXISTS: 7273 case net.user1.orbiter.Status.PERMISSION_DENIED: 7274 this.orbiter.getAccountManager().fireCreateAccountResult(userID, status); 7275 break; 7276 default: 7277 this.log.warn("Unrecognized status code for u47." 7278 + " Account: [" + userID + "], status: [" + status + "]."); 7279 } 7280 }; 7281 7282 /** 7283 * REMOVE_ACCOUNT_RESULT 7284 */ 7285 net.user1.orbiter.CoreMessageListener.prototype.u48 = function (userID, status) { 7286 switch (status) { 7287 case net.user1.orbiter.Status.SUCCESS: 7288 case net.user1.orbiter.Status.ERROR: 7289 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7290 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7291 case net.user1.orbiter.Status.PERMISSION_DENIED: 7292 this.orbiter.getAccountManager().fireRemoveAccountResult(userID, status); 7293 break; 7294 default: 7295 this.log.warn("Unrecognized status code for u48." 7296 + " Account: [" + userID + "], status: [" + status + "]."); 7297 } 7298 }; 7299 7300 /** 7301 * LOGIN_RESULT 7302 */ 7303 net.user1.orbiter.CoreMessageListener.prototype.u49 = function (userID, status) { 7304 switch (status) { 7305 case net.user1.orbiter.Status.SUCCESS: 7306 case net.user1.orbiter.Status.ERROR: 7307 case net.user1.orbiter.Status.ALREADY_LOGGED_IN: 7308 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7309 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7310 case net.user1.orbiter.Status.PERMISSION_DENIED: 7311 this.orbiter.getAccountManager().fireLoginResult(userID, status); 7312 break; 7313 default: 7314 this.log.warn("Unrecognized status code for u49." 7315 + " Account: [" + userID + "], status: [" + status + "]."); 7316 } 7317 }; 7318 7319 /** 7320 * ROOM_SNAPSHOT 7321 */ 7322 net.user1.orbiter.CoreMessageListener.prototype.u54 = function (requestID, 7323 roomID, 7324 occupantCount, 7325 observerCount, 7326 roomAttributes) { 7327 var clientList = Array.prototype.slice.call(arguments).slice(5); 7328 var clientManifest; 7329 var roomManifest = new net.user1.orbiter.RoomManifest(); 7330 var theRoom; 7331 roomManifest.deserialize(roomID, 7332 roomAttributes, 7333 clientList, 7334 parseInt(occupantCount), 7335 parseInt(observerCount)); 7336 7337 if (requestID == "") { 7338 // Synchronize 7339 theRoom = this.roomMan.getRoom(roomID); 7340 7341 if (theRoom == null) { 7342 // If the server makes the current client join or observe a room, it 7343 // will first send a u54 before sending the u6 or u59 notice. In that 7344 // case, the room might be unknown briefly, so create a cached room 7345 // then wait for the u6 or u59 to arrive. 7346 theRoom = this.roomMan.addCachedRoom(roomID); 7347 } 7348 7349 theRoom.synchronize(roomManifest); 7350 } else { 7351 // Snapshot 7352 this.snapshotMan.receiveRoomSnapshot(requestID, roomManifest); 7353 } 7354 }; 7355 7356 7357 /** 7358 * OBSERVED_ROOM 7359 */ 7360 net.user1.orbiter.CoreMessageListener.prototype.u59 = function (roomID) { 7361 // Add the room to the observed room list 7362 var room = this.roomMan.addObservedRoom(roomID); 7363 // Tell the room to do its join duties 7364 room.doObserve(); 7365 // Fire OBSERVE through the client 7366 this.clientMan.self().fireObserveRoom(room, roomID); 7367 }; 7368 7369 /** 7370 * GET_ROOM_SNAPSHOT_RESULT 7371 */ 7372 net.user1.orbiter.CoreMessageListener.prototype.u60 = function (requestID, 7373 roomID, 7374 status) { 7375 switch (status) { 7376 case net.user1.orbiter.Status.SUCCESS: 7377 case net.user1.orbiter.Status.ERROR: 7378 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7379 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7380 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7381 case net.user1.orbiter.Status.PERMISSION_DENIED: 7382 this.snapshotMan.receiveSnapshotResult(requestID, status); 7383 break; 7384 default: 7385 this.log.warn("Unrecognized status code for u60." 7386 + " Request ID: [" + requestID + "], Room ID: [" 7387 + roomID + "], status: [" + status + "]."); 7388 } 7389 }; 7390 7391 /** 7392 * STOPPED_OBSERVING_ROOM 7393 */ 7394 net.user1.orbiter.CoreMessageListener.prototype.u62 = function (roomID) { 7395 var theRoom = this.roomMan.getRoom(roomID); 7396 this.roomMan.removeObservedRoom(roomID); 7397 if (theRoom != null) { 7398 theRoom.doStopObserving(); 7399 // self() might return null if a STOP_OBSERVING listener has closed the connection 7400 if (this.clientMan.self() != null) { 7401 this.clientMan.self().fireStopObservingRoom(theRoom, roomID); 7402 } 7403 } 7404 }; 7405 7406 /** 7407 * SERVER_HELLO 7408 */ 7409 net.user1.orbiter.CoreMessageListener.prototype.u66 = function (serverVersion, 7410 sessionID, 7411 serverUPCVersionString, 7412 protocolCompatible, 7413 affinityAddress, 7414 affinityDuration) { 7415 this.log.info("[ORBITER] Server version: " + serverVersion); 7416 this.log.info("[ORBITER] Server UPC version: " + serverUPCVersionString); 7417 7418 var serverUPCVersion = new net.user1.orbiter.VersionNumber(); 7419 serverUPCVersion.fromVersionString(serverUPCVersionString); 7420 this.orbiter.getServer().setVersion(serverVersion); 7421 this.orbiter.getServer().setUPCVersion(serverUPCVersion); 7422 7423 7424 var inProgressConnection = this.orbiter.getConnectionManager().getInProgressConnection(); 7425 var inProgressConnectionHost = inProgressConnection.getHost(); 7426 if (affinityAddress != "" 7427 && typeof affinityAddress !== "undefined" 7428 && affinityAddress != inProgressConnectionHost) { 7429 this.orbiter.getConnectionManager().setAffinity(inProgressConnectionHost, 7430 affinityAddress, 7431 parseFloat(affinityDuration)); 7432 inProgressConnection.applyAffinity(); 7433 } 7434 }; 7435 7436 7437 /** 7438 * JOIN_ROOM_RESULT 7439 */ 7440 net.user1.orbiter.CoreMessageListener.prototype.u72 = function (roomID, 7441 status) { 7442 var theRoom = this.roomMan.getRoom(roomID); 7443 switch (status) { 7444 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7445 if (this.roomMan.getRoom(roomID) != null) { 7446 this.roomMan.disposeRoom(roomID); 7447 } 7448 7449 case net.user1.orbiter.Status.ERROR: 7450 case net.user1.orbiter.Status.ROOM_FULL: 7451 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7452 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7453 case net.user1.orbiter.Status.SUCCESS: 7454 case net.user1.orbiter.Status.ALREADY_IN_ROOM: 7455 case net.user1.orbiter.Status.PERMISSION_DENIED: 7456 this.roomMan.fireJoinRoomResult(roomID, status); 7457 if (theRoom != null) { 7458 theRoom.doJoinResult(status); 7459 } 7460 break; 7461 7462 default: 7463 this.log.warn("Unrecognized status code for u72." 7464 + " Room ID: [" + roomID + "], status: [" + status + "]."); 7465 } 7466 }; 7467 7468 /** 7469 * SET_CLIENT_ATTR_RESULT 7470 */ 7471 net.user1.orbiter.CoreMessageListener.prototype.u73 = function (attrScope, 7472 clientID, 7473 userID, 7474 attrName, 7475 attrOptions, 7476 status) { 7477 var theClient; 7478 var theAccount; 7479 7480 switch (status) { 7481 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7482 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7483 break; 7484 7485 case net.user1.orbiter.Status.SUCCESS: 7486 case net.user1.orbiter.Status.ERROR: 7487 case net.user1.orbiter.Status.DUPLICATE_VALUE: 7488 case net.user1.orbiter.Status.IMMUTABLE: 7489 case net.user1.orbiter.Status.SERVER_ONLY: 7490 case net.user1.orbiter.Status.EVALUATION_FAILED: 7491 case net.user1.orbiter.Status.PERMISSION_DENIED: 7492 if (parseInt(attrOptions) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 7493 // Persistent attr 7494 theAccount = this.accountMan.requestAccount(userID); 7495 theAccount.getAttributeManager().fireSetAttributeResult(attrName, attrScope, status); 7496 } else { 7497 // Non-persistent attr 7498 theClient = this.clientMan.requestClient(clientID); 7499 theClient.getAttributeManager().fireSetAttributeResult(attrName, attrScope, status); 7500 } 7501 break; 7502 7503 default: 7504 this.log.warn("Unrecognized status received for u73: " + status); 7505 } 7506 }; 7507 7508 /** 7509 * SET_ROOM_ATTR_RESULT 7510 */ 7511 net.user1.orbiter.CoreMessageListener.prototype.u74 = function (roomID, 7512 attrName, 7513 status) { 7514 var theRoom = this.roomMan.getRoom(roomID); 7515 7516 // Quit if the room isn't found 7517 if (theRoom == null) { 7518 this.log.warn("Room attribute update received for room with no" + 7519 " client-side Room object. Room ID [" + 7520 roomID + "]. Attribute: [" + attrName + "]. Status: [" 7521 + status + "]."); 7522 return; 7523 } 7524 7525 switch (status) { 7526 case net.user1.orbiter.Status.SUCCESS: 7527 case net.user1.orbiter.Status.ERROR: 7528 case net.user1.orbiter.Status.IMMUTABLE: 7529 case net.user1.orbiter.Status.SERVER_ONLY: 7530 case net.user1.orbiter.Status.EVALUATION_FAILED: 7531 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7532 case net.user1.orbiter.Status.PERMISSION_DENIED: 7533 theRoom.getAttributeManager().fireSetAttributeResult(attrName, 7534 net.user1.orbiter.Tokens.GLOBAL_ATTR, 7535 status); 7536 break; 7537 7538 default: 7539 this.log.warn("Unrecognized status received for u74: " + status); 7540 } 7541 }; 7542 7543 /** 7544 * GET_CLIENTCOUNT_SNAPSHOT_RESULT 7545 */ 7546 net.user1.orbiter.CoreMessageListener.prototype.u75 = function (requestID, 7547 status) { 7548 this.snapshotMan.receiveSnapshotResult(requestID, status); 7549 }; 7550 7551 /** 7552 * LEAVE_ROOM_RESULT 7553 */ 7554 net.user1.orbiter.CoreMessageListener.prototype.u76 = function (roomID, 7555 status) { 7556 var leftRoom = this.roomMan.getRoom(roomID); 7557 7558 switch (status) { 7559 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7560 if (leftRoom != null) { 7561 this.roomMan.disposeRoom(roomID); 7562 } 7563 7564 case net.user1.orbiter.Status.SUCCESS: 7565 case net.user1.orbiter.Status.ERROR: 7566 case net.user1.orbiter.Status.NOT_IN_ROOM: 7567 this.roomMan.fireLeaveRoomResult(roomID, status); 7568 if (leftRoom != null) { 7569 leftRoom.doLeaveResult(status); 7570 } 7571 break; 7572 7573 default: 7574 this.log.warn("Unrecognized status code for u76." 7575 + " Room ID: [" + roomID + "]. Status: [" + status + "]."); 7576 } 7577 }; 7578 7579 /** 7580 * OBSERVE_ROOM_RESULT 7581 */ 7582 net.user1.orbiter.CoreMessageListener.prototype.u77 = function (roomID, 7583 status) { 7584 var theRoom = this.roomMan.getRoom(roomID); 7585 switch (status) { 7586 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7587 if (theRoom != null) { 7588 this.roomMan.disposeRoom(roomID); 7589 } 7590 7591 case net.user1.orbiter.Status.ERROR: 7592 case net.user1.orbiter.Status.AUTHORIZATION_REQUIRED: 7593 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7594 case net.user1.orbiter.Status.SUCCESS: 7595 case net.user1.orbiter.Status.ALREADY_OBSERVING: 7596 case net.user1.orbiter.Status.PERMISSION_DENIED: 7597 this.roomMan.fireObserveRoomResult(roomID, status); 7598 7599 if (theRoom) { 7600 theRoom.doObserveResult(status); 7601 } 7602 break; 7603 7604 default: 7605 this.log.warn("Unrecognized status code for u77." 7606 + " Room ID: [" + roomID + "], status: " + status + "."); 7607 } 7608 } 7609 7610 /** 7611 * STOP_OBSERVING_ROOM_RESULT 7612 */ 7613 net.user1.orbiter.CoreMessageListener.prototype.u78 = function (roomID, 7614 status) { 7615 var theRoom = this.roomMan.getRoom(roomID); 7616 7617 switch (status) { 7618 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7619 if (theRoom != null) { 7620 this.roomMan.disposeRoom(roomID); 7621 } 7622 7623 case net.user1.orbiter.Status.SUCCESS: 7624 case net.user1.orbiter.Status.ERROR: 7625 case net.user1.orbiter.Status.NOT_OBSERVING: 7626 this.roomMan.fireStopObservingRoomResult(roomID, status); 7627 7628 if (theRoom != null) { 7629 theRoom.doStopObservingResult(status); 7630 } 7631 break; 7632 7633 default: 7634 this.log.warn("Unrecognized status code for u78." 7635 + " Room ID: [" + roomID + "], status: " + status + "."); 7636 } 7637 }; 7638 7639 /** 7640 * ROOM_ATTR_REMOVED 7641 */ 7642 net.user1.orbiter.CoreMessageListener.prototype.u79 = function (roomID, 7643 byClientID, 7644 attrName) { 7645 var theRoom = this.roomMan.getRoom(roomID); 7646 var theClient; 7647 7648 // Quit if the room isn't found 7649 if (theRoom == null) { 7650 this.log.warn("Room attribute removal notification received for room with no" + 7651 " client-side Room object. Room ID [" + 7652 roomID + "]. Attribute: [" + attrName + "]."); 7653 return; 7654 } 7655 7656 // If the clientID is "", the server removed the room, so there's no 7657 // corresponding client. 7658 theClient = byClientID == "" ? null : this.clientMan.requestClient(byClientID); 7659 theRoom.getAttributeManager().removeAttributeLocal(attrName, net.user1.orbiter.Tokens.GLOBAL_ATTR, theClient) 7660 } 7661 7662 /** 7663 * REMOVE_ROOM_ATTR_RESULT 7664 */ 7665 net.user1.orbiter.CoreMessageListener.prototype.u80 = function (roomID, 7666 attrName, 7667 status) { 7668 var theRoom = this.roomMan.getRoom(roomID); 7669 switch (status) { 7670 case net.user1.orbiter.Status.SUCCESS: 7671 case net.user1.orbiter.Status.ERROR: 7672 case net.user1.orbiter.Status.IMMUTABLE: 7673 case net.user1.orbiter.Status.SERVER_ONLY: 7674 case net.user1.orbiter.Status.ROOM_NOT_FOUND: 7675 case net.user1.orbiter.Status.ATTR_NOT_FOUND: 7676 case net.user1.orbiter.Status.PERMISSION_DENIED: 7677 if (theRoom != null) { 7678 theRoom.getAttributeManager().fireDeleteAttributeResult(attrName, 7679 net.user1.orbiter.Tokens.GLOBAL_ATTR, 7680 status); 7681 } 7682 break; 7683 7684 default: 7685 this.log.warn("Unrecognized status received for u80: " + status); 7686 } 7687 }; 7688 7689 /** 7690 * CLIENT_ATTR_REMOVED 7691 */ 7692 net.user1.orbiter.CoreMessageListener.prototype.u81 = function (attrScope, 7693 clientID, 7694 userID, 7695 attrName, 7696 attrOptions) { 7697 var client; 7698 var account; 7699 7700 if (parseInt(attrOptions) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 7701 // Persistent attr 7702 account = this.accountMan.requestAccount(userID); 7703 account.getAttributeManager().removeAttributeLocal(attrName, attrScope); 7704 } else { 7705 // Non-persistent attr 7706 client = this.clientMan.requestClient(clientID); 7707 client.getAttributeManager().removeAttributeLocal(attrName, attrScope); 7708 } 7709 }; 7710 7711 /** 7712 * REMOVE_CLIENT_ATTR_RESULT 7713 */ 7714 net.user1.orbiter.CoreMessageListener.prototype.u82 = function (attrScope, 7715 clientID, 7716 userID, 7717 attrName, 7718 attrOptions, 7719 status) { 7720 var client; 7721 var account; 7722 7723 7724 switch (status) { 7725 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7726 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7727 break; 7728 case net.user1.orbiter.Status.SUCCESS: 7729 case net.user1.orbiter.Status.ERROR: 7730 case net.user1.orbiter.Status.IMMUTABLE: 7731 case net.user1.orbiter.Status.SERVER_ONLY: 7732 case net.user1.orbiter.Status.ATTR_NOT_FOUND: 7733 case net.user1.orbiter.Status.EVALUATION_FAILED: 7734 case net.user1.orbiter.Status.PERMISSION_DENIED: 7735 if (parseInt(attrOptions) & net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT) { 7736 // Persistent attr 7737 account = this.accountMan.requestAccount(userID); 7738 account.getAttributeManager().fireDeleteAttributeResult(attrName, attrScope, status); 7739 } else { 7740 // Non-persistent attr 7741 client = this.clientMan.requestClient(clientID); 7742 client.getAttributeManager().fireDeleteAttributeResult(attrName, attrScope, status); 7743 } 7744 break; 7745 7746 default: 7747 this.log.warn("Unrecognized status received for u82: " + status); 7748 } 7749 }; 7750 7751 /** 7752 * SESSION_TERMINATED 7753 */ 7754 net.user1.orbiter.CoreMessageListener.prototype.u84 = function () { 7755 this.orbiter.getConnectionManager().dispatchSessionTerminated(); 7756 }; 7757 7758 /** 7759 * LOGOFF_RESULT 7760 */ 7761 net.user1.orbiter.CoreMessageListener.prototype.u87 = function (userID, status) { 7762 var account = this.accountMan.getAccount(userID); 7763 7764 switch (status) { 7765 case net.user1.orbiter.Status.SUCCESS: 7766 case net.user1.orbiter.Status.ERROR: 7767 case net.user1.orbiter.Status.AUTHORIZATION_FAILED: 7768 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 7769 case net.user1.orbiter.Status.NOT_LOGGED_IN: 7770 case net.user1.orbiter.Status.PERMISSION_DENIED: 7771 if (account != null) { 7772 account.fireLogoffResult(status); 7773 } 7774 // Tell the account manager 7775 this.accountMan.fireLogoffResult(userID, status); 7776 break; 7777 default: 7778 this.log.warn("Unrecognized status received for u87: " + status); 7779 } 7780 }; 7781 7782 /** 7783 * LOGGED_IN 7784 */ 7785 net.user1.orbiter.CoreMessageListener.prototype.u88 = function (clientID, 7786 userID, 7787 globalAttrs) { 7788 var roomAttrs = Array.prototype.slice.call(arguments).slice(3); 7789 var account = this.accountMan.requestAccount(userID); 7790 var client = this.clientMan.requestClient(clientID); 7791 var clientManifest = new net.user1.orbiter.ClientManifest(); 7792 clientManifest.deserialize(clientID, userID, null, null, globalAttrs, roomAttrs); 7793 // Update the account 7794 var scopes = clientManifest.persistentAttributes.getScopes(); 7795 var accountAttrs = account.getAttributeManager().getAttributeCollection(); 7796 for (var i = scopes.length; --i >= 0;) { 7797 accountAttrs.synchronizeScope(scopes[i], clientManifest.persistentAttributes); 7798 } 7799 7800 if (client.getAccount() == null) { 7801 // Client doesn't know about this account yet 7802 client.setAccount(account); 7803 client.fireLogin(); 7804 account.doLoginTasks(); 7805 this.accountMan.fireLogin(account, clientID); 7806 } else { 7807 // Do nothing if the account is known. Logins are reported for 7808 // observe-account, observe-client, and watch-for-clients, so a 7809 // client might receive multiple login notifications. 7810 } 7811 }; 7812 7813 /** 7814 * LOGGED_OFF 7815 */ 7816 net.user1.orbiter.CoreMessageListener.prototype.u89 = function (clientID, userID) { 7817 var client = this.clientMan.getInternalClient(clientID); 7818 var account = this.accountMan.getAccount(userID); 7819 7820 if (account != null) { 7821 if (account.getConnectionState() == net.user1.orbiter.ConnectionState.LOGGED_IN) { 7822 if (client != null) { 7823 client.fireLogoff(userID); 7824 } 7825 account.doLogoffTasks(); 7826 this.accountMan.fireLogoff(account, clientID); 7827 } else { 7828 // Do nothing if the account is unknown. Logoffs are reported for 7829 // observe-account, observe-client, and watch-for-clients, so a 7830 // client might receive multiple logoff notifications. 7831 } 7832 } else { 7833 throw new Error("LOGGED_OFF (u89) received for an unknown user: [" + userID + "]."); 7834 } 7835 } 7836 7837 /** 7838 * PASSWORD_CHANGED 7839 */ 7840 net.user1.orbiter.CoreMessageListener.prototype.u90 = function () { 7841 var self = this.orbiter.self(); 7842 var selfAccount = self.getAccount(); 7843 if (selfAccount != null) { 7844 selfAccount.fireChangePassword(); 7845 } 7846 this.accountMan.fireChangePassword(selfAccount ? selfAccount.getUserID() : null); 7847 }; 7848 7849 /** 7850 * CLIENTLIST_SNAPSHOT 7851 */ 7852 net.user1.orbiter.CoreMessageListener.prototype.u101 = function (requestID, serializedIDs) { 7853 var ids = serializedIDs.split(net.user1.orbiter.Tokens.RS); 7854 var clientList; 7855 var thisUserID; 7856 7857 if (requestID == "") { 7858 // Synchronize 7859 this.clientMan.deserializeWatchedClients(serializedIDs); 7860 } else { 7861 // Snapshot 7862 clientList = []; 7863 for (var i = ids.length-1; i >= 0; i-=2) { 7864 thisUserID = ids[i]; 7865 thisUserID = thisUserID == "" ? null : thisUserID; 7866 clientList.push({clientID:ids[i-1], userID:thisUserID}); 7867 } 7868 this.snapshotMan.receiveClientListSnapshot(requestID, clientList); 7869 } 7870 }; 7871 7872 /** 7873 * CLIENT_ADDED_TO_SERVER 7874 */ 7875 net.user1.orbiter.CoreMessageListener.prototype.u102 = function (clientID) { 7876 this.clientMan.addWatchedClient(this.clientMan.requestClient(clientID)); 7877 }; 7878 7879 /** 7880 * CLIENT_REMOVED_FROM_SERVER 7881 */ 7882 net.user1.orbiter.CoreMessageListener.prototype.u103 = function (clientID) { 7883 var client = this.clientMan.getInternalClient(clientID); 7884 7885 if (this.clientMan.hasWatchedClient(clientID)) { 7886 this.clientMan.removeWatchedClient(clientID); 7887 } 7888 if (this.clientMan.isObservingClient(clientID)) { 7889 this.clientMan.removeObservedClient(clientID); 7890 } 7891 7892 // If the current client is both observing a client and watching for clients, 7893 // it will receive two u103 notifications. When the second one arrives, the 7894 // client will be unknown, so no disconnection event should be dispatched. 7895 if (client != null) { 7896 client.setConnectionState(net.user1.orbiter.ConnectionState.NOT_CONNECTED); 7897 // Retrieve the client reference using getClient() here so that the 7898 // ClientManagerEvent.CLIENT_DISCONNECTED event provides the application 7899 // with access to the custom client, if available. 7900 this.clientMan.fireClientDisconnected(this.clientMan.getClient(clientID)); 7901 } 7902 }; 7903 7904 /** 7905 * CLIENT_SNAPSHOT 7906 */ 7907 net.user1.orbiter.CoreMessageListener.prototype.u104 = function (requestID, 7908 clientID, 7909 userID, 7910 serializedOccupiedRoomIDs, 7911 serializedObservedRoomIDs, 7912 globalAttrs) { 7913 var roomAttrs = Array.prototype.slice.call(arguments).slice(7); 7914 var theClient; 7915 var account = this.accountMan.requestAccount(userID); 7916 var clientManifest = new net.user1.orbiter.ClientManifest(); 7917 clientManifest.deserialize(clientID, userID, serializedOccupiedRoomIDs, 7918 serializedObservedRoomIDs, globalAttrs, roomAttrs); 7919 var scopes; // Used with UserAccount only 7920 7921 if (clientID != "") { 7922 // --- Client update --- 7923 7924 if (requestID == "") { 7925 // Synchronize 7926 theClient = this.clientMan.requestClient(clientID); 7927 theClient.setAccount(account); 7928 theClient.synchronize(clientManifest); 7929 theClient.fireSynchronize(); 7930 } else { 7931 // Snapshot 7932 this.snapshotMan.receiveClientSnapshot(requestID, clientManifest); 7933 } 7934 } else { 7935 // --- User account update --- 7936 7937 if (requestID == "") { 7938 // Synchronize 7939 scopes = clientManifest.persistentAttributes.getScopes(); 7940 for (var i = scopes.length; --i >= 0;) { 7941 account.getAttributeManager().getAttributeCollection().synchronizeScope(scopes[i], clientManifest.persistentAttributes); 7942 } 7943 account.fireSynchronize(); 7944 } else { 7945 // Snapshot 7946 this.snapshotMan.receiveAccountSnapshot(requestID, clientManifest); 7947 } 7948 } 7949 }; 7950 7951 /** 7952 * OBSERVE_CLIENT_RESULT 7953 */ 7954 net.user1.orbiter.CoreMessageListener.prototype.u105 = function (clientID, status) { 7955 var theClient = this.clientMan.getInternalClient(clientID); 7956 switch (status) { 7957 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7958 case net.user1.orbiter.Status.SUCCESS: 7959 case net.user1.orbiter.Status.ERROR: 7960 case net.user1.orbiter.Status.ALREADY_OBSERVING: 7961 case net.user1.orbiter.Status.PERMISSION_DENIED: 7962 this.clientMan.fireObserveClientResult(clientID, status); 7963 if (theClient != null) { 7964 theClient.fireObserveResult(status); 7965 } 7966 break; 7967 7968 default: 7969 this.log.warn("Unrecognized status code for u105." 7970 + " Client ID: [" + clientID + "], status: [" + status + "]."); 7971 } 7972 }; 7973 7974 /** 7975 * STOP_OBSERVING_CLIENT_RESULT 7976 */ 7977 net.user1.orbiter.CoreMessageListener.prototype.u106 = function (clientID, status) { 7978 var theClient = this.clientMan.getInternalClient(clientID); 7979 switch (status) { 7980 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 7981 case net.user1.orbiter.Status.SUCCESS: 7982 case net.user1.orbiter.Status.ERROR: 7983 case net.user1.orbiter.Status.NOT_OBSERVING: 7984 this.clientMan.fireStopObservingClientResult(clientID, status); 7985 if (theClient != null) { 7986 theClient.fireStopObservingResult(status); 7987 } 7988 break; 7989 7990 default: 7991 this.log.warn("Unrecognized status code for u106." 7992 + " Client ID: [" + clientID + "], status: [" + status + "]."); 7993 } 7994 }; 7995 7996 /** 7997 * WATCH_FOR_CLIENTS_RESULT 7998 */ 7999 net.user1.orbiter.CoreMessageListener.prototype.u107 = function (status) { 8000 switch (status) { 8001 case net.user1.orbiter.Status.SUCCESS: 8002 case net.user1.orbiter.Status.ERROR: 8003 case net.user1.orbiter.Status.ALREADY_WATCHING: 8004 this.clientMan.fireWatchForClientsResult(status); 8005 break; 8006 8007 default: 8008 this.log.warn("Unrecognized status code for u107." 8009 + "Status: [" + status + "]."); 8010 } 8011 }; 8012 8013 /** 8014 * STOP_WATCHING_FOR_CLIENTS_RESULT 8015 */ 8016 net.user1.orbiter.CoreMessageListener.prototype.u108 = function (status) { 8017 switch (status) { 8018 case net.user1.orbiter.Status.SUCCESS: 8019 this.clientMan.setIsWatchingForClients(false); 8020 this.clientMan.removeAllWatchedClients(); 8021 case net.user1.orbiter.Status.ERROR: 8022 case net.user1.orbiter.Status.NOT_WATCHING: 8023 this.clientMan.fireStopWatchingForClientsResult(status); 8024 break; 8025 8026 default: 8027 this.log.warn("Unrecognized status code for u108." 8028 + "Status: [" + status + "]."); 8029 } 8030 }; 8031 8032 /** 8033 * WATCH_FOR_USERS_RESULT 8034 */ 8035 net.user1.orbiter.CoreMessageListener.prototype.u109 = function (status) { 8036 switch (status) { 8037 case net.user1.orbiter.Status.SUCCESS: 8038 this.accountMan.setIsWatchingForAccounts(true); 8039 case net.user1.orbiter.Status.ERROR: 8040 case net.user1.orbiter.Status.ALREADY_WATCHING: 8041 this.accountMan.fireWatchForAccountsResult(status); 8042 break; 8043 8044 default: 8045 this.log.warn("Unrecognized status code for u109." 8046 + "Status: [" + status + "]."); 8047 } 8048 }; 8049 8050 /** 8051 * STOP_WATCHING_FOR_USERS_RESULT 8052 */ 8053 net.user1.orbiter.CoreMessageListener.prototype.u110 = function (status) { 8054 switch (status) { 8055 case net.user1.orbiter.Status.SUCCESS: 8056 this.accountMan.setIsWatchingForAccounts(false); 8057 this.accountMan.removeAllWatchedAccounts(); 8058 case net.user1.orbiter.Status.ERROR: 8059 case net.user1.orbiter.Status.NOT_WATCHING: 8060 this.accountMan.fireStopWatchingForAccountsResult(status); 8061 break; 8062 8063 default: 8064 this.log.warn("Unrecognized status code for u110." 8065 + "Status: [" + status + "]."); 8066 } 8067 }; 8068 8069 /** 8070 * USER_ADDED 8071 */ 8072 net.user1.orbiter.CoreMessageListener.prototype.u111 = function (userID) { 8073 this.accountMan.addWatchedAccount(this.accountMan.requestAccount(userID)); 8074 }; 8075 8076 /** 8077 * USER_REMOVED 8078 */ 8079 net.user1.orbiter.CoreMessageListener.prototype.u112 = function (userID) { 8080 var account; 8081 if (this.accountMan.hasWatchedAccount(userID)) { 8082 account = this.accountMan.removeWatchedAccount(userID); 8083 } 8084 if (this.accountMan.isObservingAccount(userID)) { 8085 account = this.accountMan.removeObservedAccount(userID); 8086 } 8087 this.accountMan.fireAccountRemoved(userID, account); 8088 }; 8089 8090 /** 8091 * JOINED_ROOM_ADDED_TO_CLIENT 8092 */ 8093 net.user1.orbiter.CoreMessageListener.prototype.u113 = function (clientID, roomID) { 8094 var client = this.clientMan.requestClient(clientID); 8095 client.addOccupiedRoomID(roomID); 8096 client.fireJoinRoom(this.roomMan.getRoom(roomID), roomID); 8097 } 8098 8099 /** 8100 * JOINED_ROOM_REMOVED_FROM_CLIENT 8101 */ 8102 net.user1.orbiter.CoreMessageListener.prototype.u114 = function (clientID, roomID) { 8103 var client = this.clientMan.requestClient(clientID); 8104 client.removeOccupiedRoomID(roomID); 8105 client.fireLeaveRoom(this.roomMan.getRoom(roomID), roomID); 8106 }; 8107 8108 /** 8109 * GET_CLIENT_SNAPSHOT_RESULT 8110 */ 8111 net.user1.orbiter.CoreMessageListener.prototype.u115 = function (requestID, 8112 clientID, 8113 status) { 8114 this.snapshotMan.receiveSnapshotResult(requestID, status); 8115 }; 8116 8117 /** 8118 * GET_ACCOUNT_SNAPSHOT_RESULT 8119 */ 8120 net.user1.orbiter.CoreMessageListener.prototype.u116 = function (requestID, 8121 userID, 8122 status) { 8123 this.snapshotMan.receiveSnapshotResult(requestID, status); 8124 }; 8125 8126 /** 8127 * OBSERVED_ROOM_ADDED_TO_CLIENT 8128 */ 8129 net.user1.orbiter.CoreMessageListener.prototype.u117 = function (clientID, roomID) { 8130 var client = this.clientMan.requestClient(clientID); 8131 client.addObservedRoomID(roomID); 8132 client.fireObserveRoom(this.roomMan.getRoom(roomID), roomID); 8133 }; 8134 8135 /** 8136 * OBSERVED_ROOM_REMOVED_FROM_CLIENT 8137 */ 8138 net.user1.orbiter.CoreMessageListener.prototype.u118 = function (clientID, roomID) { 8139 var client = this.clientMan.requestClient(clientID); 8140 client.removeObservedRoomID(roomID); 8141 client.fireStopObservingRoom(this.roomMan.getRoom(roomID), roomID); 8142 } 8143 8144 /** 8145 * CLIENT_OBSERVED 8146 */ 8147 net.user1.orbiter.CoreMessageListener.prototype.u119 = function (clientID) { 8148 var client = this.clientMan.requestClient(clientID); 8149 this.clientMan.addObservedClient(client); 8150 client.fireObserve(); 8151 }; 8152 8153 /** 8154 * STOPPED_OBSERVING_CLIENT 8155 */ 8156 net.user1.orbiter.CoreMessageListener.prototype.u120 = function (clientID) { 8157 var client = this.clientMan.getInternalClient(clientID) 8158 this.clientMan.removeObservedClient(clientID); 8159 if (client != null) { 8160 client.fireStopObserving(); 8161 } 8162 }; 8163 8164 /** 8165 * OBSERVE_ACCOUNT_RESULT 8166 */ 8167 net.user1.orbiter.CoreMessageListener.prototype.u123 = function (userID, status) { 8168 var theAccount = this.accountMan.getAccount(userID); 8169 switch (status) { 8170 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8171 case net.user1.orbiter.Status.SUCCESS: 8172 case net.user1.orbiter.Status.ERROR: 8173 case net.user1.orbiter.Status.ALREADY_OBSERVING: 8174 this.accountMan.fireObserveAccountResult(userID, status); 8175 if (theAccount) { 8176 theAccount.fireObserveResult(status); 8177 } 8178 break; 8179 8180 default: 8181 this.log.warn("Unrecognized status code for u123." 8182 + " User ID: [" + userID + "], status: [" + status + "]."); 8183 } 8184 }; 8185 8186 /** 8187 * ACCOUNT_OBSERVED 8188 */ 8189 net.user1.orbiter.CoreMessageListener.prototype.u124 = function (userID) { 8190 var theAccount = this.accountMan.requestAccount(userID); 8191 this.accountMan.addObservedAccount(theAccount); 8192 theAccount.fireObserve(); 8193 }; 8194 8195 /** 8196 * STOP_OBSERVING_ACCOUNT_RESULT 8197 */ 8198 net.user1.orbiter.CoreMessageListener.prototype.u125 = function (userID, status) { 8199 var theAccount = this.accountMan.getAccount(userID); 8200 switch (status) { 8201 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8202 case net.user1.orbiter.Status.SUCCESS: 8203 case net.user1.orbiter.Status.ERROR: 8204 case net.user1.orbiter.Status.ALREADY_OBSERVING: 8205 this.accountMan.fireStopObservingAccountResult(userID, status); 8206 if (theAccount) { 8207 theAccount.fireStopObservingResult(status); 8208 } 8209 break; 8210 8211 default: 8212 this.log.warn("Unrecognized status code for u125." 8213 + " User ID: [" + userID + "], status: [" + status + "]."); 8214 } 8215 }; 8216 8217 /** 8218 * STOPPED_OBSERVING_ACCOUNT 8219 */ 8220 net.user1.orbiter.CoreMessageListener.prototype.u126 = function (userID) { 8221 var account = this.accountMan.getAccount(userID); 8222 this.accountMan.removeObservedAccount(userID); 8223 if (account != null) { 8224 account.fireStopObserving(); 8225 } 8226 }; 8227 8228 /** 8229 * ACCOUNT_LIST_UPDATE 8230 */ 8231 net.user1.orbiter.CoreMessageListener.prototype.u127 = function (requestID, serializedIDs) { 8232 var ids = serializedIDs.split(net.user1.orbiter.Tokens.RS); 8233 var accountList; 8234 8235 if (requestID == "") { 8236 // Synchronize 8237 this.accountMan.deserializeWatchedAccounts(serializedIDs); 8238 } else { 8239 // Snapshot 8240 accountList = []; 8241 for (var i = ids.length; --i >= 0;) { 8242 accountList.push(ids[i]); 8243 } 8244 this.snapshotMan.receiveAccountListSnapshot(requestID, accountList); 8245 } 8246 }; 8247 8248 /** 8249 * UPDATE_LEVELS_UPDATE 8250 */ 8251 net.user1.orbiter.CoreMessageListener.prototype.u128 = function (updateLevels, roomID) { 8252 var room = this.roomMan.getRoom(roomID); 8253 var levels = new net.user1.orbiter.UpdateLevels(); 8254 levels.fromInt(parseInt(updateLevels)); 8255 if (room != null) { 8256 if (!levels.occupantList) { 8257 var occupantID; 8258 var occupantIDs = room.getOccupantIDs(); 8259 var numOccupantIDs = occupantIDs.length; 8260 for (var i = 0; i < numOccupantIDs; i++) { 8261 occupantID = occupantIDs[i]; 8262 room.removeOccupant(occupantID); 8263 } 8264 } 8265 if (!levels.observerList) { 8266 var observerID; 8267 var observerIDs = room.getObserverIDs(); 8268 var numObserverIDs = observerIDs.length; 8269 for (i = 0; i < numObserverIDs; i++) { 8270 observerID = observerIDs[i]; 8271 room.removeObserver(observerID); 8272 } 8273 } 8274 if (!levels.sharedRoomAttributes 8275 && !levels.allRoomAttributes) { 8276 room.getAttributeManager().removeAll(); 8277 } 8278 } 8279 }; 8280 8281 /** 8282 * CLIENT_OBSERVED_ROOM 8283 */ 8284 net.user1.orbiter.CoreMessageListener.prototype.u129 = function (roomID, 8285 clientID, 8286 userID, 8287 globalAttributes, 8288 roomAttributes) { 8289 var theClient = this.clientMan.requestClient(clientID); 8290 var account = this.accountMan.requestAccount(userID); 8291 var clientManifest; 8292 if (account != null 8293 && theClient.getAccount() != account) { 8294 theClient.setAccount(account); 8295 } 8296 8297 // If it's not the current client, set the client's attributes. 8298 // (The current client obtains its own attributes through separate u8s.) 8299 var theRoom = this.roomMan.getRoom(roomID); 8300 if (!theClient.isSelf()) { 8301 clientManifest = new net.user1.orbiter.ClientManifest(); 8302 clientManifest.deserialize(clientID, userID, null, 8303 null, globalAttributes, [roomID, roomAttributes]); 8304 theClient.synchronize(clientManifest); 8305 8306 // If the client is observed, don't fire OBSERVE_ROOM; observed clients always 8307 // fire OBSERVE_ROOM based on observation updates. Likewise, don't fire OBSERVE_ROOM 8308 // on self; self fires OBSERVE_ROOM when it receives a u59. 8309 if (!this.clientMan.isObservingClient(clientID)) { 8310 theClient.fireObserveRoom(theRoom, roomID); 8311 } 8312 } 8313 8314 // Add the client to the room's observer list 8315 theRoom.addObserver(theClient); 8316 }; 8317 8318 /** 8319 * CLIENT_STOPPED_OBSERVING_ROOM 8320 */ 8321 net.user1.orbiter.CoreMessageListener.prototype.u130 = function (roomID, 8322 clientID) { 8323 // Remove the room from the client's list of observed rooms 8324 var theClient = this.clientMan.requestClient(clientID); 8325 var theRoom = this.roomMan.getRoom(roomID); 8326 8327 // Remove the client from the given room 8328 theRoom.removeObserver(clientID); 8329 8330 // Don't fire STOP_OBSERVING_ROOM on self; self fires STOP_OBSERVING_ROOM 8331 // when it receives a u62. 8332 if (!theClient.isSelf()) { 8333 // If the client is observed, don't fire STOP_OBSERVING_ROOM; observed 8334 // clients always fire STOP_OBSERVING_ROOM based on observation updates. 8335 if (!this.clientMan.isObservingClient(clientID)) { 8336 theClient.fireStopObservingRoom(theRoom, roomID); 8337 } 8338 } 8339 }; 8340 8341 /** 8342 * ROOM_OCCUPANTCOUNT_UPDATE 8343 */ 8344 net.user1.orbiter.CoreMessageListener.prototype.u131 = function (roomID, 8345 numClients) { 8346 var levels = this.clientMan.self().getUpdateLevels(roomID); 8347 8348 if (levels != null) { 8349 if (!levels.occupantList) { 8350 this.roomMan.getRoom(roomID).setNumOccupants(parseInt(numClients)); 8351 } 8352 } else { 8353 throw new Error("[CORE_MESSAGE_LISTENER] Received a room occupant count" + 8354 " update (u131), but update levels are unknown for the room. Synchronization" + 8355 " error. Please report this error to union@user1.net."); 8356 } 8357 }; 8358 8359 /** 8360 * ROOM_OBSERVERCOUNT_UPDATE 8361 */ 8362 net.user1.orbiter.CoreMessageListener.prototype.u132 = function (roomID, 8363 numClients) { 8364 var levels = this.clientMan.self().getUpdateLevels(roomID); 8365 8366 if (levels != null) { 8367 if (!levels.observerList) { 8368 this.roomMan.getRoom(roomID).setNumObservers(parseInt(numClients)); 8369 } 8370 } else { 8371 throw new Error("[CORE_MESSAGE_LISTENER] Received a room observer count" + 8372 " update (u132), but update levels are unknown for the room. Synchronization" + 8373 " error. Please report this error to union@user1.net."); 8374 } 8375 } 8376 8377 /** 8378 * ADD_ROLE_RESULT 8379 */ 8380 net.user1.orbiter.CoreMessageListener.prototype.u134 = function (userID, role, status) { 8381 var theAccount = this.accountMan.getAccount(userID); 8382 switch (status) { 8383 case net.user1.orbiter.Status.SUCCESS: 8384 case net.user1.orbiter.Status.ERROR: 8385 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8386 case net.user1.orbiter.Status.ROLE_NOT_FOUND: 8387 case net.user1.orbiter.Status.ALREADY_ASSIGNED: 8388 case net.user1.orbiter.Status.PERMISSION_DENIED: 8389 this.accountMan.fireAddRoleResult(userID, role, status); 8390 if (theAccount) { 8391 theAccount.fireAddRoleResult(role, status); 8392 } 8393 break; 8394 8395 default: 8396 this.log.warn("Unrecognized status code for u134." 8397 + " User ID: [" + userID + "], role: [" + role 8398 + "], status: [" + status + "]."); 8399 } 8400 }; 8401 8402 /** 8403 * REMOVE_ROLE_RESULT 8404 */ 8405 net.user1.orbiter.CoreMessageListener.prototype.u136 = function (userID, role, status) { 8406 var theAccount = this.accountMan.getAccount(userID); 8407 switch (status) { 8408 case net.user1.orbiter.Status.SUCCESS: 8409 case net.user1.orbiter.Status.ERROR: 8410 case net.user1.orbiter.Status.ACCOUNT_NOT_FOUND: 8411 case net.user1.orbiter.Status.ROLE_NOT_FOUND: 8412 case net.user1.orbiter.Status.NOT_ASSIGNED: 8413 case net.user1.orbiter.Status.PERMISSION_DENIED: 8414 this.accountMan.fireRemoveRoleResult(userID, role, status); 8415 if (theAccount) { 8416 theAccount.fireRemoveRoleResult(role, status); 8417 } 8418 break; 8419 8420 default: 8421 this.log.warn("Unrecognized status code for u136." 8422 + " User ID: [" + userID + "], role: [" + role 8423 + "], status: [" + status + "]."); 8424 } 8425 }; 8426 8427 /** 8428 * BAN_RESULT 8429 */ 8430 net.user1.orbiter.CoreMessageListener.prototype.u138 = function (address, clientID, status) { 8431 switch (status) { 8432 case net.user1.orbiter.Status.SUCCESS: 8433 case net.user1.orbiter.Status.ERROR: 8434 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 8435 case net.user1.orbiter.Status.ALREADY_BANNED: 8436 case net.user1.orbiter.Status.PERMISSION_DENIED: 8437 this.clientMan.fireBanClientResult(address, clientID, status); 8438 break; 8439 8440 default: 8441 this.log.warn("Unrecognized status code for u138." 8442 + " Address: [" + address + "], clientID: [" + clientID 8443 + "], status: [" + status + "]."); 8444 } 8445 }; 8446 8447 /** 8448 * UNBAN_RESULT 8449 */ 8450 net.user1.orbiter.CoreMessageListener.prototype.u140 = function (address, status) { 8451 switch (status) { 8452 case net.user1.orbiter.Status.SUCCESS: 8453 case net.user1.orbiter.Status.ERROR: 8454 case net.user1.orbiter.Status.NOT_BANNED: 8455 case net.user1.orbiter.Status.PERMISSION_DENIED: 8456 this.clientMan.fireUnbanClientResult(address, status); 8457 break; 8458 8459 default: 8460 this.log.warn("Unrecognized status code for u140." 8461 + " Address: [" + address + "]," 8462 + " status: [" + status + "]."); 8463 } 8464 }; 8465 8466 /** 8467 * BANNED_LIST_SNAPSHOT 8468 */ 8469 net.user1.orbiter.CoreMessageListener.prototype.u142 = function (requestID, bannedListSource) { 8470 var bannedList = bannedListSource == "" ? [] : bannedListSource.split(net.user1.orbiter.Tokens.RS); 8471 8472 if (requestID == "") { 8473 this.clientMan.setWatchedBannedAddresses(bannedList); 8474 } else { 8475 // Snapshot 8476 this.snapshotMan.receiveBannedListSnapshot(requestID, bannedList); 8477 } 8478 }; 8479 8480 /** 8481 * WATCH_FOR_BANNED_ADDRESSES_RESULT 8482 */ 8483 net.user1.orbiter.CoreMessageListener.prototype.u144 = function (status) { 8484 switch (status) { 8485 case net.user1.orbiter.Status.SUCCESS: 8486 case net.user1.orbiter.Status.ERROR: 8487 case net.user1.orbiter.Status.ALREADY_WATCHING: 8488 case net.user1.orbiter.Status.PERMISSION_DENIED: 8489 this.clientMan.fireWatchForBannedAddressesResult(status); 8490 break; 8491 8492 default: 8493 this.log.warn("Unrecognized status code for u144:" 8494 + " [" + status + "]."); 8495 } 8496 }; 8497 8498 /** 8499 * STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT 8500 */ 8501 net.user1.orbiter.CoreMessageListener.prototype.u146 = function (status) { 8502 switch (status) { 8503 case net.user1.orbiter.Status.SUCCESS: 8504 case net.user1.orbiter.Status.ERROR: 8505 case net.user1.orbiter.Status.NOT_WATCHING: 8506 this.clientMan.fireStopWatchingForBannedAddressesResult(status); 8507 break; 8508 8509 default: 8510 this.log.warn("Unrecognized status code for u146:" 8511 + " [" + status + "]."); 8512 } 8513 }; 8514 8515 /** 8516 * BANNED_ADDRESS_ADDED 8517 */ 8518 net.user1.orbiter.CoreMessageListener.prototype.u147 = function (address) { 8519 this.clientMan.addWatchedBannedAddress(address); 8520 }; 8521 8522 /** 8523 * BANNED_ADDRESS_REMOVED 8524 */ 8525 net.user1.orbiter.CoreMessageListener.prototype.u148 = function (address) { 8526 this.clientMan.removeWatchedBannedAddress(address); 8527 }; 8528 8529 /** 8530 * KICK_RESULT 8531 */ 8532 net.user1.orbiter.CoreMessageListener.prototype.u150 = function (clientID, status) { 8533 switch (status) { 8534 case net.user1.orbiter.Status.SUCCESS: 8535 case net.user1.orbiter.Status.ERROR: 8536 case net.user1.orbiter.Status.CLIENT_NOT_FOUND: 8537 case net.user1.orbiter.Status.PERMISSION_DENIED: 8538 this.clientMan.fireKickClientResult(clientID, status); 8539 break; 8540 8541 default: 8542 this.log.warn("Unrecognized status code for u150:" 8543 + " [" + status + "]."); 8544 } 8545 }; 8546 8547 /** 8548 * SERVERMODULELIST_SNAPSHOT 8549 */ 8550 net.user1.orbiter.CoreMessageListener.prototype.u152 = function (requestID, serverModuleListSource) { 8551 var moduleListArray = serverModuleListSource == "" ? [] : serverModuleListSource.split(net.user1.orbiter.Tokens.RS); 8552 var moduleList = []; 8553 for (var i = 0; i < moduleListArray.length; i+= 3) { 8554 moduleList.push(new ModuleDefinition(moduleListArray[i], 8555 moduleListArray[i+1], 8556 moduleListArray[i+2])); 8557 } 8558 8559 if (requestID == "") { 8560 this.log.warn("Incoming SERVERMODULELIST_SNAPSHOT UPC missing required requestID. Ignoring message."); 8561 } else { 8562 // Snapshot 8563 this.snapshotMan.receiveServerModuleListSnapshot(requestID, moduleList); 8564 } 8565 }; 8566 8567 /** 8568 * GET_UPC_STATS_SNAPSHOT_RESULT 8569 */ 8570 net.user1.orbiter.CoreMessageListener.prototype.u155 = function (requestID, 8571 status) { 8572 this.snapshotMan.receiveSnapshotResult(requestID, status); 8573 }; 8574 8575 /** 8576 * UPC_STATS_SNAPSHOT 8577 */ 8578 net.user1.orbiter.CoreMessageListener.prototype.u156 = function (requestID, 8579 totalUPCsProcessed, 8580 numUPCsInQueue, 8581 lastQueueWaitTime) { 8582 var longestUPCProcesses = Array.prototype.slice.call(arguments).slice(5); 8583 var upcProcessingRecord; 8584 for (var i = 0; i < longestUPCProcesses.length; i++) { 8585 upcProcessingRecord = new net.user1.orbiter.UPCProcessingRecord(); 8586 upcProcessingRecord.deserialize(longestUPCProcesses[i]); 8587 longestUPCProcesses[i] = upcProcessingRecord; 8588 } 8589 8590 this.snapshotMan.receiveUPCStatsSnapshot(requestID, 8591 parseFloat(totalUPCsProcessed), 8592 parseFloat(numUPCsInQueue), 8593 parseFloat(lastQueueWaitTime), 8594 longestUPCProcesses); 8595 }; 8596 8597 /** 8598 * RESET_UPC_STATS_RESULT 8599 */ 8600 net.user1.orbiter.CoreMessageListener.prototype.u158 = function (status) { 8601 switch (status) { 8602 case net.user1.orbiter.Status.SUCCESS: 8603 case net.user1.orbiter.Status.ERROR: 8604 case net.user1.orbiter.Status.PERMISSION_DENIED: 8605 this.orbiter.getServer().dispatchResetUPCStatsResult(status); 8606 break; 8607 8608 default: 8609 this.log.warn("Unrecognized status code for u158." 8610 + "Status: [" + status + "]."); 8611 } 8612 }; 8613 8614 /** 8615 * WATCH_FOR_PROCESSED_UPCS_RESULT 8616 */ 8617 net.user1.orbiter.CoreMessageListener.prototype.u160 = function (status) { 8618 switch (status) { 8619 case net.user1.orbiter.Status.SUCCESS: 8620 this.orbiter.getServer().setIsWatchingForProcessedUPCs(true); 8621 case net.user1.orbiter.Status.ERROR: 8622 case net.user1.orbiter.Status.ALREADY_WATCHING: 8623 case net.user1.orbiter.Status.PERMISSION_DENIED: 8624 this.orbiter.getServer().dispatchWatchForProcessedUPCsResult(status); 8625 break; 8626 8627 default: 8628 this.log.warn("Unrecognized status code for u160." 8629 + "Status: [" + status + "]."); 8630 } 8631 }; 8632 8633 /** 8634 * PROCESSED_UPC_ADDED 8635 */ 8636 net.user1.orbiter.CoreMessageListener.prototype.u161 = function (fromClientID, 8637 fromUserID, 8638 fromClientAddress, 8639 queuedAt, 8640 processingStartedAt, 8641 processingFinishedAt, 8642 source) { 8643 var upcProcessingRecord = new net.user1.orbiter.UPCProcessingRecord(); 8644 upcProcessingRecord.deserializeParts(fromClientID, 8645 fromUserID, 8646 fromClientAddress, 8647 queuedAt, 8648 processingStartedAt, 8649 processingFinishedAt, 8650 source); 8651 this.orbiter.getServer().dispatchUPCProcessed(upcProcessingRecord); 8652 }; 8653 8654 /** 8655 * STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT 8656 */ 8657 net.user1.orbiter.CoreMessageListener.prototype.u163 = function (status) { 8658 switch (status) { 8659 case net.user1.orbiter.Status.SUCCESS: 8660 this.orbiter.getServer().setIsWatchingForProcessedUPCs(false); 8661 case net.user1.orbiter.Status.ERROR: 8662 case net.user1.orbiter.Status.NOT_WATCHING: 8663 case net.user1.orbiter.Status.PERMISSION_DENIED: 8664 this.orbiter.getServer().dispatchStopWatchingForProcessedUPCsResult(status); 8665 break; 8666 8667 default: 8668 this.log.warn("Unrecognized status code for u163." 8669 + "Status: [" + status + "]."); 8670 } 8671 }; 8672 8673 8674 /** 8675 * NODELIST_SNAPSHOT 8676 */ 8677 net.user1.orbiter.CoreMessageListener.prototype.u166 = function (requestID, nodeListSource) { 8678 var nodeIDs = nodeListSource == "" ? [] : nodeListSource.split(net.user1.orbiter.Tokens.RS); 8679 8680 if (requestID == "") { 8681 this.log.warn("Incoming NODELIST_SNAPSHOT UPC missing required requestID. Ignoring message."); 8682 } else { 8683 // Snapshot 8684 this.snapshotMan.receiveNodeListSnapshot(requestID, nodeIDs); 8685 } 8686 }; 8687 8688 /** 8689 * GATEWAYS_SNAPSHOT 8690 */ 8691 net.user1.orbiter.CoreMessageListener.prototype.u168 = function (requestID) { 8692 var gatewayListSource = Array.prototype.slice.call(arguments).slice(1); 8693 var gateways = []; 8694 8695 var gateway; 8696 var gatewayBandwidth; 8697 var gatewayBandwidthSource; 8698 var gatewayIntervalSource; 8699 for (var i = 0; i < gatewayListSource.length; i+=8) { 8700 gateway = new net.user1.orbiter.Gateway(); 8701 gateway.id = gatewayListSource[i]; 8702 gateway.type = gatewayListSource[i+1]; 8703 8704 gateway.lifetimeConnectionsByCategory = gatewayListSource[i+2] === "" ? {} : this.createHashFromArg(gatewayListSource[i+2]); 8705 for (var p in gateway.lifetimeConnectionsByCategory) { 8706 gateway.lifetimeConnectionsByCategory[p] = parseFloat(gateway.lifetimeConnectionsByCategory[p]); 8707 } 8708 gateway.lifetimeClientsByType = gatewayListSource[i+3] === "" ? {} : this.createHashFromArg(gatewayListSource[i+3]); 8709 for (p in gateway.lifetimeClientsByType) { 8710 gateway.lifetimeClientsByType[p] = parseFloat(gateway.lifetimeClientsByType[p]); 8711 } 8712 gateway.lifetimeClientsByUPCVersion = gatewayListSource[i+4] === "" ? {} : this.createHashFromArg(gatewayListSource[i+4]); 8713 for (p in gateway.lifetimeClientsByUPCVersion) { 8714 gateway.lifetimeClientsByUPCVersion[p] = parseFloat(gateway.lifetimeClientsByUPCVersion[p]); 8715 } 8716 gateway.attributes = gatewayListSource[i+5] === "" ? {} : this.createHashFromArg(gatewayListSource[i+5]); 8717 8718 gatewayIntervalSource = gatewayListSource[i+6].split(net.user1.orbiter.Tokens.RS); 8719 gateway.connectionsPerSecond = parseFloat(gatewayIntervalSource[0]); 8720 gateway.maxConnectionsPerSecond = parseFloat(gatewayIntervalSource[1]); 8721 gateway.clientsPerSecond = parseFloat(gatewayIntervalSource[2]); 8722 gateway.maxClientsPerSecond = parseFloat(gatewayIntervalSource[3]); 8723 8724 gatewayBandwidth = new net.user1.orbiter.GatewayBandwidth(); 8725 gatewayBandwidthSource = gatewayListSource[i+7].split(net.user1.orbiter.Tokens.RS); 8726 gatewayBandwidth.lifetimeRead = gatewayBandwidthSource[0] === "" ? 0 : parseFloat(gatewayBandwidthSource[0]); 8727 gatewayBandwidth.lifetimeWritten = gatewayBandwidthSource[1] === "" ? 0 : parseFloat(gatewayBandwidthSource[1]); 8728 gatewayBandwidth.averageRead = gatewayBandwidthSource[2] === "" ? 0 : parseFloat(gatewayBandwidthSource[2]); 8729 gatewayBandwidth.averageWritten = gatewayBandwidthSource[3] === "" ? 0 : parseFloat(gatewayBandwidthSource[3]); 8730 gatewayBandwidth.intervalRead = gatewayBandwidthSource[4] === "" ? 0 : parseFloat(gatewayBandwidthSource[4]); 8731 gatewayBandwidth.intervalWritten = gatewayBandwidthSource[5] === "" ? 0 : parseFloat(gatewayBandwidthSource[5]); 8732 gatewayBandwidth.maxIntervalRead = gatewayBandwidthSource[6] === "" ? 0 : parseFloat(gatewayBandwidthSource[6]); 8733 gatewayBandwidth.maxIntervalWritten = gatewayBandwidthSource[7] === "" ? 0 : parseFloat(gatewayBandwidthSource[7]); 8734 gatewayBandwidth.scheduledWrite = gatewayBandwidthSource[8] === "" ? 0 : parseFloat(gatewayBandwidthSource[8]); 8735 gateway.bandwidth = gatewayBandwidth; 8736 gateways.push(gateway); 8737 } 8738 8739 if (requestID == "") { 8740 this.log.warn("Incoming GATEWAYS_SNAPSHOT UPC missing required requestID. Ignoring message."); 8741 } else { 8742 // Snapshot 8743 this.snapshotMan.receiveGatewaysSnapshot(requestID, gateways); 8744 } 8745 }; 8746 //============================================================================== 8747 // CLASS DECLARATION 8748 //============================================================================== 8749 /** 8750 * @class 8751 */ 8752 net.user1.orbiter.CustomClient = function () { 8753 this.client = null; 8754 }; 8755 8756 /** 8757 * An initialization method invoked when this CustomClient object is ready 8758 * for use. Subclasses wishing to perform initialization tasks that require 8759 * this CustomClient's composed Client object should override this method. 8760 * 8761 * @since Orbiter 1.0.0 8762 */ 8763 net.user1.orbiter.CustomClient.prototype.init = function () { 8764 }; 8765 8766 net.user1.orbiter.CustomClient.prototype.addEventListener = function (type, 8767 listener, 8768 thisArg, 8769 priority) { 8770 this.client.addEventListener(type, listener, thisArg, priority); 8771 }; 8772 8773 net.user1.orbiter.CustomClient.prototype.dispatchEvent = function (event) { 8774 return this.client.dispatchEvent(event); 8775 }; 8776 8777 net.user1.orbiter.CustomClient.prototype.hasEventListener = function (type) { 8778 return this.client.hasEventListener(type); 8779 }; 8780 8781 net.user1.orbiter.CustomClient.prototype.removeEventListener = function (type, 8782 listener, 8783 thisObj) { 8784 this.client.removeEventListener(type, listener, thisObj); 8785 }; 8786 8787 net.user1.orbiter.CustomClient.prototype.willTrigger = function (type) { 8788 return this.client.willTrigger(type); 8789 }; 8790 8791 net.user1.orbiter.CustomClient.prototype.setClient = function (client) { 8792 this.client = client; 8793 }; 8794 8795 net.user1.orbiter.CustomClient.prototype.getClientID = function () { 8796 return this.client.getClientID(); 8797 }; 8798 8799 net.user1.orbiter.CustomClient.prototype.getConnectionState = function () { 8800 return this.client.getConnectionState(); 8801 }; 8802 8803 net.user1.orbiter.CustomClient.prototype.isSelf = function () { 8804 return this.client.isSelf(); 8805 }; 8806 8807 net.user1.orbiter.CustomClient.prototype.setClientClass = function (scope, 8808 clientClass) { 8809 var fallbackClasses = Array.prototype.slice.call(arguments).slice(2); 8810 this.client.setClientClass.apply(this.client, [scope, clientClass].concat(fallbackClasses)); 8811 }; 8812 8813 net.user1.orbiter.CustomClient.prototype.isInRoom = function (roomID) { 8814 return this.client.isInRoom(roomID); 8815 }; 8816 8817 net.user1.orbiter.CustomClient.prototype.isObservingRoom = function (roomID) { 8818 return this.client.isObservingRoom(roomID); 8819 }; 8820 8821 net.user1.orbiter.CustomClient.prototype.getOccupiedRoomIDs = function () { 8822 return this.client.getOccupiedRoomIDs(); 8823 }; 8824 8825 net.user1.orbiter.CustomClient.prototype.getObservedRoomIDs = function () { 8826 return this.client.getObservedRoomIDs(); 8827 }; 8828 8829 net.user1.orbiter.CustomClient.prototype.getIP = function () { 8830 return this.client.getIP(); 8831 }; 8832 8833 net.user1.orbiter.CustomClient.prototype.getConnectTime = function () { 8834 return this.client.getConnectTime(); 8835 }; 8836 8837 net.user1.orbiter.CustomClient.prototype.getPing = function () { 8838 return this.client.getPing(); 8839 }; 8840 8841 net.user1.orbiter.CustomClient.prototype.getTimeOnline = function () { 8842 return this.client.getTimeOnline(); 8843 }; 8844 8845 net.user1.orbiter.CustomClient.prototype.sendMessage = function (messageName) { 8846 var args = Array.prototype.slice.call(arguments).slice(0); 8847 this.client.sendMessage.apply(this.client, args); 8848 }; 8849 8850 net.user1.orbiter.CustomClient.prototype.setAttribute = function (attrName, 8851 attrValue, 8852 attrScope, 8853 isShared, 8854 evaluate) { 8855 this.client.setAttribute(attrName, attrValue, attrScope, isShared, evaluate); 8856 }; 8857 8858 net.user1.orbiter.CustomClient.prototype.deleteAttribute = function (attrName, attrScope) { 8859 this.client.deleteAttribute(attrName, attrScope); 8860 }; 8861 8862 net.user1.orbiter.CustomClient.prototype.getAttribute = function (attrName, attrScope) { 8863 return this.client.getAttribute(attrName, attrScope); 8864 }; 8865 8866 net.user1.orbiter.CustomClient.prototype.getAttributes = function () { 8867 return this.client.getAttributes(); 8868 }; 8869 8870 net.user1.orbiter.CustomClient.prototype.getAttributesByScope = function (scope) { 8871 return this.client.getAttributesByScope(); 8872 }; 8873 8874 net.user1.orbiter.CustomClient.prototype.getClientManager = function () { 8875 return this.client.getClientManager(); 8876 }; 8877 8878 net.user1.orbiter.CustomClient.prototype.getAccount = function () { 8879 return this.client.getAccount(); 8880 }; 8881 8882 net.user1.orbiter.CustomClient.prototype.kick = function () { 8883 this.client.kick(); 8884 }; 8885 8886 net.user1.orbiter.CustomClient.prototype.ban = function (duration, reason) { 8887 this.client.ban(duration, reason); 8888 }; 8889 8890 net.user1.orbiter.CustomClient.prototype.observe = function () { 8891 this.client.observe(); 8892 }; 8893 8894 net.user1.orbiter.CustomClient.prototype.stopObserving = function () { 8895 this.client.stopObserving(); 8896 }; 8897 8898 net.user1.orbiter.CustomClient.prototype.isAdmin = function () { 8899 return this.client.isAdmin(); 8900 }; 8901 8902 net.user1.orbiter.CustomClient.prototype.toString = function () { 8903 return "[object CustomClient, ID: " + this.getClientID() + "]"; 8904 }; 8905 //============================================================================== 8906 // EVENT UTILITIES 8907 //============================================================================== 8908 /** @class */ 8909 net.user1.utils.EventUtil = new Object(); 8910 8911 net.user1.utils.EventUtil.migrateListeners = function (oldObject, 8912 newObject, 8913 events, 8914 thisObj) { 8915 var len = events.length 8916 for (var i = 0; i < len; i += 2) { 8917 if (oldObject != null) { 8918 oldObject.removeEventListener(events[i], events[i+1], thisObj); 8919 } 8920 if (newObject != null) { 8921 newObject.addEventListener(events[i], events[i+1], thisObj); 8922 } 8923 } 8924 }; 8925 //============================================================================== 8926 // CLASS DECLARATION 8927 //============================================================================== 8928 /** 8929 * @class 8930 */ 8931 net.user1.orbiter.filters.FilterSet = function () { 8932 this.filters = new Array(); 8933 }; 8934 8935 net.user1.orbiter.filters.FilterSet.prototype.addFilter = function (filter) { 8936 this.filters.push(filter); 8937 }; 8938 8939 net.user1.orbiter.filters.FilterSet.prototype.getFilters = function () { 8940 return this.filters.slice(0); 8941 }; 8942 8943 net.user1.orbiter.filters.FilterSet.prototype.toXMLString = function () { 8944 var s = "<filters>\n"; 8945 8946 var filter; 8947 for (var i = 0; i < this.filters.length; i++) { 8948 filter = this.filters[i]; 8949 s += filter.toXMLString() + "\n"; 8950 } 8951 s += "</filters>"; 8952 return s; 8953 }; 8954 //============================================================================== 8955 // CLASS DECLARATION 8956 //============================================================================== 8957 /** 8958 * @class 8959 */ 8960 net.user1.orbiter.GatewayBandwidth = function () { 8961 /** 8962 * @field 8963 * @type Number 8964 */ 8965 this.lifetimeRead = 0; 8966 /** 8967 * @field 8968 * @type Number 8969 */ 8970 this.lifetimeWritten = 0; 8971 /** 8972 * @field 8973 * @type Number 8974 */ 8975 this.averageRead = 0; 8976 /** 8977 * @field 8978 * @type Number 8979 */ 8980 this.averageWritten = 0; 8981 /** 8982 * @field 8983 * @type Number 8984 */ 8985 this.intervalRead = 0; 8986 /** 8987 * @field 8988 * @type Number 8989 */ 8990 this.intervalWritten = 0; 8991 /** 8992 * @field 8993 * @type Number 8994 */ 8995 this.maxIntervalRead = 0; 8996 /** 8997 * @field 8998 * @type Number 8999 */ 9000 this.maxIntervalWritten = 0; 9001 /** 9002 * @field 9003 * @type Number 9004 */ 9005 this.scheduledWrite = 0; 9006 }; 9007 //============================================================================== 9008 // CLASS DECLARATION 9009 //============================================================================== 9010 /** 9011 * @class 9012 */ 9013 net.user1.orbiter.Gateway = function () { 9014 /** 9015 * @field 9016 * @type String 9017 this.id = null; 9018 /** 9019 * @field 9020 * @type String 9021 */ 9022 this.type = null; 9023 /** 9024 * @field 9025 * @type Object 9026 */ 9027 this.lifetimeConnectionsByCategory = null; 9028 /** 9029 * @field 9030 * @type Object 9031 */ 9032 this.lifetimeClientsByType = null; 9033 /** 9034 * @field 9035 * @type Object 9036 */ 9037 this.lifetimeClientsByUPCVersion = null; 9038 /** 9039 * @field 9040 * @type Object 9041 */ 9042 this.attributes = null; 9043 /** 9044 * @field 9045 * @type Number 9046 */ 9047 this.connectionsPerSecond = 0; 9048 /** 9049 * @field 9050 * @type Number 9051 */ 9052 this.maxConnectionsPerSecond = 0; 9053 /** 9054 * @field 9055 * @type Number 9056 */ 9057 this.clientsPerSecond = 0; 9058 /** 9059 * @field 9060 * @type Number 9061 */ 9062 this.maxClientsPerSecond = 0; 9063 /** 9064 * @field 9065 * @type net.user1.orbiter.GatewayBandwidth 9066 */ 9067 this.bandwidth = null; 9068 }; 9069 //============================================================================== 9070 // CLASS DECLARATION 9071 //============================================================================== 9072 /** 9073 * @class 9074 */ 9075 net.user1.utils.LRUCache = function (maxLength) { 9076 this.maxLength = maxLength; 9077 this.length = 0; 9078 this.hash = new net.user1.utils.UDictionary(); 9079 this.first = null; 9080 this.last = null; 9081 }; 9082 9083 net.user1.utils.LRUCache.prototype.get = function (key) { 9084 var node = this.hash[key]; 9085 9086 if (node != null) { 9087 this.moveToHead(node); 9088 return node.value; 9089 } else { 9090 return null; 9091 } 9092 }; 9093 9094 net.user1.utils.LRUCache.prototype.put = function (key, value) { 9095 var node = this.hash[key]; 9096 if (node == null) { 9097 if (this.length >= this.maxLength) { 9098 this.removeLast(); 9099 } else { 9100 this.length++; 9101 } 9102 node = new net.user1.utils.CacheNode(); 9103 } 9104 9105 node.value = value; 9106 node.key = key; 9107 this.moveToHead(node); 9108 this.hash[key] = node; 9109 }; 9110 9111 net.user1.utils.LRUCache.prototype.remove = function (key) { 9112 var node = this.hash[key]; 9113 if (node != null) { 9114 if (node.prev != null) { 9115 node.prev.next = node.next; 9116 } 9117 if (node.next != null) { 9118 node.next.prev = node.prev; 9119 } 9120 if (this.last == node) { 9121 this.last = node.prev; 9122 } 9123 if (this.first == node) { 9124 this.first = node.next; 9125 } 9126 } 9127 return node; 9128 } 9129 9130 net.user1.utils.LRUCache.prototype.clear = function () { 9131 this.first = null; 9132 this.last = null; 9133 this.length = 0; 9134 this.hash = new net.user1.utils.UDictionary(); 9135 }; 9136 9137 /** 9138 * @private 9139 */ 9140 net.user1.utils.LRUCache.prototype.removeLast = function () { 9141 if (this.last != null) { 9142 delete this.hash[this.last.key]; 9143 if (this.last.prev != null) { 9144 this.last.prev.next = null; 9145 } else { 9146 this.first = null; 9147 } 9148 this.last = this.last.prev; 9149 } 9150 }; 9151 9152 /** 9153 * @private 9154 */ 9155 net.user1.utils.LRUCache.prototype.moveToHead = function (node) { 9156 if (node == this.first) { 9157 return; 9158 } 9159 if (node.prev != null) { 9160 node.prev.next = node.next; 9161 } 9162 if (node.next != null) { 9163 node.next.prev = node.prev; 9164 } 9165 if (this.last == node) { 9166 this.last = node.prev; 9167 } 9168 if (this.first != null) { 9169 node.next = this.first; 9170 this.first.prev = node; 9171 } 9172 this.first = node; 9173 node.prev = null; 9174 if (this.last == null) { 9175 this.last = this.first; 9176 } 9177 }; 9178 //============================================================================== 9179 // CLASS DECLARATION 9180 //============================================================================== 9181 /** 9182 * @class 9183 */ 9184 net.user1.orbiter.ModuleDefinition = function (id, type, source) { 9185 this.id = id; 9186 this.type = type; 9187 this.source = source; 9188 }; 9189 //============================================================================== 9190 // MODULE TYPE CONSTANTS 9191 //============================================================================== 9192 /** @class */ 9193 net.user1.orbiter.ModuleType = new Object(); 9194 /** @constant */ 9195 net.user1.orbiter.ModuleType.CLASS = "class"; 9196 /** @constant */ 9197 net.user1.orbiter.ModuleType.SCRIPT = "script"; 9198 //============================================================================== 9199 // CLASS DECLARATION 9200 //============================================================================== 9201 /** 9202 * @class 9203 * @extends net.user1.orbiter.snapshot.Snapshot 9204 */ 9205 net.user1.orbiter.snapshot.NodeListSnapshot = function () { 9206 // Call superconstructor 9207 net.user1.orbiter.snapshot.Snapshot.call(this); 9208 this.nodeList = null; 9209 this.method = net.user1.orbiter.UPC.GET_NODELIST_SNAPSHOT; 9210 }; 9211 9212 //============================================================================== 9213 // INHERITANCE 9214 //============================================================================== 9215 net.user1.utils.extend(net.user1.orbiter.snapshot.NodeListSnapshot, net.user1.orbiter.snapshot.Snapshot); 9216 9217 //============================================================================== 9218 // INSTANCE METHODS 9219 //============================================================================== 9220 /** 9221 * @private 9222 */ 9223 net.user1.orbiter.snapshot.NodeListSnapshot.prototype.setNodeList = function (value) { 9224 this.nodeList = value; 9225 } 9226 9227 net.user1.orbiter.snapshot.NodeListSnapshot.prototype.getNodeList = function () { 9228 if (!this.nodeList) { 9229 return null; 9230 } 9231 return this.nodeList.slice(); 9232 }; 9233 //============================================================================== 9234 // A COLLECTION OF NUMERIC UTILITIES 9235 //============================================================================== 9236 /** @class */ 9237 net.user1.utils.integer = new Object(); 9238 /** @constant */ 9239 net.user1.utils.integer.MAX_VALUE = Math.pow(2,32) - 1; 9240 //============================================================================== 9241 // CLASS DECLARATION 9242 //============================================================================== 9243 /** 9244 * @class 9245 * @extends net.user1.orbiter.filters.BooleanGroup 9246 */ 9247 net.user1.orbiter.filters.OrGroup = function () { 9248 net.user1.orbiter.filters.BooleanGroup.call(this, net.user1.orbiter.filters.BooleanGroupType.OR); 9249 }; 9250 9251 //============================================================================== 9252 // INHERITANCE 9253 //============================================================================== 9254 net.user1.utils.extend(net.user1.orbiter.filters.OrGroup, net.user1.orbiter.filters.BooleanGroup); 9255 /** 9256 * @private 9257 */ 9258 net.user1.orbiter.upc.RemoveClientAttr = function (clientID, userID, name, scope) { 9259 // Abort if name is invalid. 9260 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 9261 throw new Error("Cannot delete attribute. Illegal name" + 9262 " (see Validator.isValidAttributeName()): " + name); 9263 } 9264 9265 // Abort if scope is invalid. 9266 if (!net.user1.orbiter.Validator.isValidAttributeScope(scope)) { 9267 throw new Error("Cannot delete client attribute. Illegal scope" + 9268 " (see Validator.isValidAttributeScope()): " + scope); 9269 } 9270 9271 this.method = net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR; 9272 this.args = [clientID, userID, name, scope]; 9273 }; 9274 /** 9275 * @private 9276 */ 9277 net.user1.orbiter.upc.RemoveRoomAttr = function (roomID, name) { 9278 // Abort if name is invalid. 9279 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 9280 throw new Error("Cannot delete attribute. Illegal name" + 9281 " (see Validator.isValidAttributeName()): " + name); 9282 } 9283 9284 this.method = net.user1.orbiter.UPC.REMOVE_ROOM_ATTR; 9285 this.args = [roomID, name]; 9286 }; 9287 /** @function */ 9288 net.user1.utils.resolveMemberExpression = function (value) { 9289 var parts = value.split("."); 9290 var reference = globalObject; 9291 for (var i = 0; i < parts.length; i++) { 9292 reference = reference[parts[i]]; 9293 } 9294 return reference; 9295 }; 9296 //============================================================================== 9297 // CLASS DECLARATION 9298 //============================================================================== 9299 /** @class 9300 9301 The Room class dispatches the following events: 9302 9303 <ul class="summary"> 9304 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.JOIN}</li> 9305 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.JOIN_RESULT}</li> 9306 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.LEAVE}</li> 9307 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.LEAVE_RESULT}</li> 9308 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.ADD_OCCUPANT}</li> 9309 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.REMOVE_OCCUPANT}</li> 9310 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.ADD_OBSERVER}</li> 9311 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.REMOVE_OBSERVER}</li> 9312 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.UPDATE_CLIENT_ATTRIBUTE}</li> 9313 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.DELETE_CLIENT_ATTRIBUTE}</li> 9314 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OCCUPANT_COUNT}</li> 9315 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OSERVER_COUNT}</li> 9316 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.SYNCHRONIZE}</li> 9317 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OBSERVE}</li> 9318 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OBSERVE_RESULT}</li> 9319 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.STOP_OBSERVING}</li> 9320 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT}</li> 9321 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.REMOVED}</li> 9322 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE}</li> 9323 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.UPDATE}</li> 9324 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.SET_RESULT}</li> 9325 <li class="fixedFont">{@link net.user1.orbiter.AttributeEvent.DELETE_RESULT}</li> 9326 </ul> 9327 9328 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 9329 9330 @extends net.user1.events.EventDispatcher 9331 */ 9332 net.user1.orbiter.Room = function (id, 9333 roomManager, 9334 messageManager, 9335 clientManager, 9336 accountManager, 9337 log) { 9338 // Call superconstructor 9339 net.user1.events.EventDispatcher.call(this); 9340 9341 // Variables 9342 this.disposed = false; 9343 this.id = null; 9344 this.syncState = null; 9345 this._clientIsInRoom = false; 9346 this._clientIsObservingRoom = false; 9347 this.numOccupants = 0; 9348 this.numObservers = 0; 9349 this.defaultClientClass = null; 9350 9351 // Initialization 9352 this.setRoomID(id); 9353 this.roomManager = roomManager; 9354 this.messageManager = messageManager; 9355 this.clientManager = clientManager; 9356 this.accountManager = accountManager; 9357 this.log = log; 9358 9359 this.occupantList = new net.user1.orbiter.ClientSet(); 9360 this.observerList = new net.user1.orbiter.ClientSet(); 9361 this.attributeManager = new net.user1.orbiter.AttributeManager(this, this.messageManager, this.log); 9362 9363 this.setSyncState(net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED); 9364 } 9365 9366 //============================================================================== 9367 // INHERITANCE 9368 //============================================================================== 9369 net.user1.utils.extend(net.user1.orbiter.Room, net.user1.events.EventDispatcher); 9370 9371 // ============================================================================= 9372 // DEPENDENCIES 9373 // ============================================================================= 9374 /** @private */ 9375 net.user1.orbiter.Room.prototype.getAttributeManager = function () { 9376 return this.attributeManager; 9377 }; 9378 9379 // ============================================================================= 9380 // ROOM ID MANAGEMENT 9381 // ============================================================================= 9382 9383 /** 9384 * @private 9385 */ 9386 net.user1.orbiter.Room.prototype.setRoomID = function (roomID) { 9387 var errorMsg; 9388 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 9389 errorMsg = "Invalid room ID specified during room creation. Offending ID: " + roomID; 9390 this.log.error(errorMsg); 9391 throw new Error(errorMsg); 9392 } 9393 this.id = roomID; 9394 }; 9395 9396 net.user1.orbiter.Room.prototype.getRoomID = function () { 9397 return this.id; 9398 }; 9399 9400 net.user1.orbiter.Room.prototype.getSimpleRoomID = function () { 9401 return net.user1.orbiter.RoomIDParser.getSimpleRoomID(this.id); 9402 }; 9403 9404 net.user1.orbiter.Room.prototype.getQualifier = function () { 9405 return net.user1.orbiter.RoomIDParser.getQualifier(this.id); 9406 }; 9407 9408 // ============================================================================= 9409 // JOIN/LEAVE 9410 // ============================================================================= 9411 9412 net.user1.orbiter.Room.prototype.join = function (password, 9413 updateLevels) { 9414 if (this.disposed) return; 9415 9416 // Client can't join a room the its already in. 9417 if (this.clientIsInRoom()) { 9418 this.log.warn(this + "Room join attempt aborted. Already in room."); 9419 return; 9420 } 9421 // Validate the password 9422 if (password == null) { 9423 password = ""; 9424 } 9425 if (!net.user1.orbiter.Validator.isValidPassword(password)) { 9426 this.log.error(this + "Invalid room password supplied to join(). " 9427 + " Join request not sent. See Validator.isValidPassword()."); 9428 return; 9429 } 9430 9431 // If any update levels are specified, send them before joining. 9432 if (updateLevels != null) { 9433 this.setUpdateLevels(updateLevels); 9434 } 9435 9436 this.messageManager.sendUPC(net.user1.orbiter.UPC.JOIN_ROOM, 9437 this.getRoomID(), 9438 password); 9439 }; 9440 9441 net.user1.orbiter.Room.prototype.leave = function () { 9442 if (this.disposed) return; 9443 9444 if (this.clientIsInRoom()) { 9445 this.messageManager.sendUPC(net.user1.orbiter.UPC.LEAVE_ROOM, this.getRoomID()); 9446 } else { 9447 this.log.debug(this + " Leave-room request ignored. Not in room."); 9448 } 9449 }; 9450 9451 /** 9452 * @private 9453 */ 9454 net.user1.orbiter.Room.prototype.doJoin = function () { 9455 this._clientIsInRoom = true; 9456 this.fireJoin(); 9457 }; 9458 9459 /** 9460 * @private 9461 */ 9462 net.user1.orbiter.Room.prototype.doJoinResult = function (status) { 9463 this.fireJoinResult(status); 9464 }; 9465 9466 /** 9467 * @private 9468 */ 9469 net.user1.orbiter.Room.prototype.doLeave = function () { 9470 var rid = this.getRoomID(); 9471 9472 // If the client is not observing the room, then dispose 9473 // of all of the room's information. 9474 if (!this.clientIsObservingRoom()) { 9475 this.purgeRoomData(); 9476 } 9477 9478 // Note that the client is no longer in this room. 9479 this._clientIsInRoom = false; 9480 this.fireLeave(); 9481 } 9482 9483 /** 9484 * @private 9485 */ 9486 net.user1.orbiter.Room.prototype.doLeaveResult = function (status) { 9487 this.fireLeaveResult(status); 9488 }; 9489 9490 //============================================================================== 9491 // MESSAGING 9492 //============================================================================== 9493 9494 net.user1.orbiter.Room.prototype.sendMessage = function (messageName, 9495 includeSelf, 9496 filters) { 9497 if (this.disposed) return; 9498 9499 // Delegate to RoomManager.sendMessage() 9500 var rest = Array.prototype.slice.call(arguments).slice(3) 9501 var roomMan = this.roomManager; 9502 var args = [messageName, 9503 [this.getRoomID()], 9504 includeSelf, 9505 filters != null ? filters : null]; 9506 roomMan.sendMessage.apply(roomMan, args.concat(rest)); 9507 }; 9508 9509 net.user1.orbiter.Room.prototype.addMessageListener = function (message, listener, thisArg) { 9510 if (this.messageManager != null) { 9511 this.messageManager.addMessageListener(message, 9512 listener, 9513 thisArg, 9514 [this.getRoomID()]); 9515 } 9516 }; 9517 9518 net.user1.orbiter.Room.prototype.removeMessageListener = function (message, listener) { 9519 if (this.messageManager != null) { 9520 this.messageManager.removeMessageListener(message, 9521 listener); 9522 } 9523 }; 9524 9525 net.user1.orbiter.Room.prototype.hasMessageListener = function (message, 9526 listener) { 9527 // First, get the list of messsage listeners for this message 9528 var listeners = this.messageManager.getMessageListeners(message); 9529 var messageListener; 9530 for (var i = 0; i < listeners.length; i++) { 9531 messageListener = listeners[i]; 9532 var listenerRoomIDs = messageListener.getForRoomIDs(); 9533 // ===== Run once for each room id ===== 9534 var listenerRoomID; 9535 for (var j = 0; j < listenerRoomIDs.length; j++) { 9536 listenerRoomID = listenerRoomIDs[i]; 9537 if (listenerRoomID == this.getRoomID()) { 9538 return true; 9539 } 9540 } 9541 } 9542 return false; 9543 }; 9544 9545 //============================================================================== 9546 // SYNCHRONIZATION 9547 //============================================================================== 9548 9549 /** 9550 * @private 9551 */ 9552 net.user1.orbiter.Room.prototype.synchronize = function (manifest) { 9553 var oldSyncState = this.getSyncState(); 9554 this.log.debug(this + " Begin synchronization."); 9555 this.setSyncState(net.user1.orbiter.SynchronizationState.SYNCHRONIZING); 9556 9557 // SYNC ROOM ATTRIBUTES 9558 this.getAttributeManager().getAttributeCollection().synchronizeScope(net.user1.orbiter.Tokens.GLOBAL_ATTR, manifest.attributes); 9559 if (this.disposed) { 9560 return; 9561 } 9562 9563 // SYNC OCCUPANT LIST 9564 var oldOccupantList = this.getOccupantIDs(); 9565 var newOccupantList = []; 9566 var thisOccupantClientID; 9567 var thisOccupantUserID; 9568 var thisOccupant; 9569 var thisOccupantAccount; 9570 9571 // Add all unknown occupants to the room's occupant list, and 9572 // synchronize all existing occupants. 9573 for (var i = manifest.occupants.length; --i >= 0;) { 9574 thisOccupantClientID = manifest.occupants[i].clientID; 9575 thisOccupantUserID = manifest.occupants[i].userID; 9576 9577 newOccupantList.push(thisOccupantClientID); 9578 9579 thisOccupant = this.clientManager.requestClient(thisOccupantClientID); 9580 // Init user account, if any 9581 thisOccupantAccount = this.accountManager.requestAccount(thisOccupantUserID); 9582 if (thisOccupantAccount != null) { 9583 thisOccupant.setAccount(thisOccupantAccount); 9584 } 9585 9586 // If it's not the current client, update it. 9587 // The current client obtains its attributes through separate u8s. 9588 if (!thisOccupant.isSelf()) { 9589 thisOccupant.synchronize(manifest.occupants[i]); 9590 } 9591 9592 this.addOccupant(thisOccupant); 9593 if (this.disposed) { 9594 return; 9595 } 9596 } 9597 9598 // Remove occupants that are now gone... 9599 var oldClientID; 9600 for (i = oldOccupantList.length; --i >= 0;) { 9601 oldClientID = oldOccupantList[i]; 9602 if (net.user1.utils.ArrayUtil.indexOf(newOccupantList, oldClientID) == -1) { 9603 this.removeOccupant(oldClientID); 9604 if (this.disposed) { 9605 return; 9606 } 9607 } 9608 } 9609 9610 // SYNC OBSERVER LIST 9611 var oldObserverList = this.getObserverIDs(); 9612 var newObserverList = []; 9613 var thisObserverClientID; 9614 var thisObserverUserID; 9615 var thisObserver; 9616 var thisObserverAccount; 9617 9618 // Add all unknown observers to the room's observer list, and 9619 // synchronize all existing observers. 9620 for (i = manifest.observers.length; --i >= 0;) { 9621 thisObserverClientID = manifest.observers[i].clientID; 9622 thisObserverUserID = manifest.observers[i].userID; 9623 9624 newObserverList.push(thisObserverClientID); 9625 9626 thisObserver = this.clientManager.requestClient(thisObserverClientID); 9627 // Init user account, if any 9628 thisObserverAccount = this.accountManager.requestAccount(thisObserverUserID); 9629 if (thisObserverAccount != null) { 9630 thisObserver.setAccount(thisObserverAccount); 9631 } 9632 9633 // If it's not the current client, update it. 9634 // The current client obtains its attributes through separate u8s. 9635 if (!thisObserver.isSelf()) { 9636 thisObserver.synchronize(manifest.observers[i]); 9637 } 9638 9639 this.addObserver(thisObserver); 9640 if (this.disposed) { 9641 return; 9642 } 9643 } 9644 9645 // Remove observers that are now gone... 9646 var oldClientID; 9647 for (i = oldObserverList.length; --i >= 0;) { 9648 oldClientID = oldObserverList[i] 9649 if (net.user1.utils.ArrayUtil.indexOf(newObserverList, oldClientID) == -1) { 9650 this.removeObserver(oldClientID); 9651 if (this.disposed) { 9652 return; 9653 } 9654 } 9655 } 9656 9657 // UPDATE CLIENT COUNTS 9658 // If a client list is available, use its length to calculate the 9659 // client count. That way, the list length and the "get count" method 9660 // return values will be the same (e.g., getOccupants().length and 9661 // getNumOccupants()). Otherwise, rely on the server's reported count. 9662 var levels = this.clientManager.self().getUpdateLevels(this.getRoomID()); 9663 if (levels.occupantList) { 9664 this.setNumOccupants(this.occupantList.length()); 9665 } else if (levels.occupantCount) { 9666 this.setNumOccupants(manifest.occupantCount); 9667 } 9668 if (levels.observerList) { 9669 this.setNumObservers(this.observerList.length()); 9670 } else if (levels.observerCount) { 9671 this.setNumObservers(manifest.observerCount); 9672 } 9673 9674 // Update sync state 9675 this.setSyncState(oldSyncState); 9676 9677 // Tell listeners that synchronization is complete 9678 this.fireSynchronize(net.user1.orbiter.Status.SUCCESS); 9679 } 9680 9681 /** 9682 * @private 9683 */ 9684 net.user1.orbiter.Room.prototype.setSyncState = function (newSyncState) { 9685 this.syncState = newSyncState; 9686 }; 9687 9688 /** 9689 * @private 9690 */ 9691 net.user1.orbiter.Room.prototype.updateSyncState = function () { 9692 if (this.disposed) { 9693 this.setSyncState(net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED); 9694 } else { 9695 if (this.roomManager.hasObservedRoom(this.getRoomID()) 9696 || this.roomManager.hasOccupiedRoom(this.getRoomID()) 9697 || this.roomManager.hasWatchedRoom(this.getRoomID())) { 9698 this.setSyncState(net.user1.orbiter.SynchronizationState.SYNCHRONIZED); 9699 } else { 9700 this.setSyncState(net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED); 9701 } 9702 } 9703 } 9704 9705 net.user1.orbiter.Room.prototype.getSyncState = function () { 9706 return this.syncState; 9707 }; 9708 9709 //============================================================================== 9710 // UPDATE LEVELS 9711 //============================================================================== 9712 9713 net.user1.orbiter.Room.prototype.setUpdateLevels = function (updateLevels) { 9714 if (this.messageManager) { 9715 this.messageManager.sendUPC(net.user1.orbiter.UPC.SET_ROOM_UPDATE_LEVELS, 9716 this.getRoomID(), 9717 updateLevels.toInt()); 9718 } 9719 }; 9720 9721 //============================================================================== 9722 // OBSERVATION 9723 //============================================================================== 9724 9725 net.user1.orbiter.Room.prototype.observe = function (password, 9726 updateLevels) { 9727 if (this.disposed) return; 9728 9729 this.roomManager.observeRoom(this.getRoomID(), 9730 password, 9731 updateLevels); 9732 }; 9733 9734 9735 net.user1.orbiter.Room.prototype.stopObserving = function () { 9736 if (this.disposed) return; 9737 9738 if (this.clientIsObservingRoom()) { 9739 this.messageManager.sendUPC(net.user1.orbiter.UPC.STOP_OBSERVING_ROOM, this.getRoomID()); 9740 } else { 9741 this.log.debug(this + " Stop-observing-room request ignored. Not observing room."); 9742 } 9743 }; 9744 9745 /** 9746 * @private 9747 */ 9748 net.user1.orbiter.Room.prototype.doObserve = function () { 9749 this._clientIsObservingRoom = true; 9750 this.fireObserve(); 9751 }; 9752 9753 /** 9754 * @private 9755 */ 9756 net.user1.orbiter.Room.prototype.doObserveResult = function (status) { 9757 this.fireObserveResult(status); 9758 }; 9759 9760 /** 9761 * @private 9762 */ 9763 net.user1.orbiter.Room.prototype.doStopObserving = function () { 9764 var rid = this.getRoomID(); 9765 9766 // If the client is not in the room, then we dispose 9767 // of all of the room's information. 9768 if (!this.clientIsInRoom()) { 9769 this.purgeRoomData(); 9770 } 9771 9772 this._clientIsObservingRoom = false; 9773 9774 this.fireStopObserving(); 9775 }; 9776 9777 /** 9778 * @private 9779 */ 9780 net.user1.orbiter.Room.prototype.doStopObservingResult = function (status) { 9781 this.fireStopObservingResult(status); 9782 } 9783 9784 //============================================================================== 9785 // OCCUPANT MANAGEMENT 9786 //============================================================================== 9787 9788 /** 9789 * @private 9790 */ 9791 net.user1.orbiter.Room.prototype.addOccupant = function (client) { 9792 // Don't add the client if it's already in the list. 9793 if (this.occupantList.contains(client)) { 9794 this.log.info(this + " ignored addOccupant() request. Occupant list" + 9795 " already contains client:" + client + "."); 9796 return; 9797 } 9798 9799 // Add the client 9800 this.occupantList.add(client); 9801 9802 // Update the number of clients in the room 9803 this.setNumOccupants(this.occupantList.length()); 9804 9805 // Register for attribute change events 9806 if (!this.observerList.contains(client)) { 9807 this.addClientAttributeListeners(client); 9808 } 9809 9810 // Tell listeners an occupant was added 9811 this.fireAddOccupant(client.getClientID()); 9812 }; 9813 9814 /** 9815 * @private 9816 */ 9817 net.user1.orbiter.Room.prototype.removeOccupant = function (clientID) { 9818 var client = this.occupantList.removeByClientID(clientID); 9819 var clientFound = client != null; 9820 9821 // Update the number of clients in the room 9822 this.setNumOccupants(this.occupantList.length()); 9823 9824 // Unregister for attribute change events 9825 if (!this.observerList.contains(client)) { 9826 this.removeClientAttributeListeners(client); 9827 } 9828 9829 // Tell listeners an occupant was removed 9830 var customClient = client.getCustomClient(this.getRoomID()); 9831 this.fireRemoveOccupant(customClient != null ? customClient : client); 9832 9833 if (!clientFound) { 9834 this.log.debug(this + " could not remove occupant: " 9835 + clientID + ". No such client in the room's occupant list."); 9836 } 9837 }; 9838 9839 net.user1.orbiter.Room.prototype.getOccupantIDs = function () { 9840 if (this.disposed) return null; 9841 9842 return this.occupantList.getAllIDs(); 9843 } 9844 9845 net.user1.orbiter.Room.prototype.getOccupants = function () { 9846 if (this.disposed) return null; 9847 9848 var occupants = this.occupantList.getAll(); 9849 var occupantsList = new Array(); 9850 var customClient; 9851 var occupant; 9852 9853 for (var clientID in occupants) { 9854 occupant = occupants[clientID]; 9855 customClient = occupant.getCustomClient(this.getRoomID()); 9856 if (customClient != null) { 9857 occupantsList.push(customClient); 9858 } else { 9859 occupantsList.push(occupant); 9860 } 9861 } 9862 return occupantsList; 9863 } 9864 9865 /** 9866 * @private 9867 */ 9868 net.user1.orbiter.Room.prototype.getOccupantsInternal = function () { 9869 return this.occupantList.getAll(); 9870 } 9871 9872 net.user1.orbiter.Room.prototype.clientIsInRoom = function (clientID) { 9873 if (this.disposed) return false; 9874 9875 if (clientID == null) { 9876 return this._clientIsInRoom; 9877 } 9878 return this.occupantList.containsClientID(clientID); 9879 }; 9880 9881 net.user1.orbiter.Room.prototype.getNumOccupants = function () { 9882 if (this.disposed) return 0; 9883 9884 var levels = this.clientManager.self().getUpdateLevels(this.getRoomID());; 9885 if (levels != null) { 9886 if (levels.occupantCount || levels.occupantList) { 9887 return this.numOccupants; 9888 } else { 9889 this.log.warn(this + " getNumOccupants() called, but no occupant count is " + 9890 "available. To enable occupant count, turn on occupant list" + 9891 " updates or occupant count updates via the Room's setUpdateLevels()" + 9892 " method."); 9893 return 0; 9894 } 9895 } else { 9896 this.log.debug(this + " getNumOccupants() called, but the current client's update" 9897 + " levels for the room are unknown. To determine the room's" 9898 + " occupant count, first join or observe the room."); 9899 return 0; 9900 } 9901 }; 9902 9903 /** 9904 * @private 9905 */ 9906 net.user1.orbiter.Room.prototype.setNumOccupants = function (newNumOccupants) { 9907 var oldNumClients = this.numOccupants; 9908 this.numOccupants = newNumOccupants; 9909 9910 // Tell listeners that the number of clients in the room has changed. 9911 if (oldNumClients != newNumOccupants) { 9912 this.fireOccupantCount(newNumOccupants); 9913 } 9914 }; 9915 9916 //============================================================================== 9917 // ROOM SETTINGS 9918 //============================================================================== 9919 9920 net.user1.orbiter.Room.prototype.getRoomSettings = function () { 9921 if (this.disposed) return null; 9922 9923 var settings = new net.user1.orbiter.RoomSettings(); 9924 var maxClients = this.getAttribute(net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR); 9925 var removeOnEmpty = this.getAttribute(net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR); 9926 9927 settings.maxClients = maxClients == null ? null : maxClients; 9928 switch (removeOnEmpty) { 9929 case null: 9930 settings.removeOnEmpty = null; 9931 break; 9932 9933 case "true": 9934 settings.removeOnEmpty = true; 9935 break; 9936 9937 case "false": 9938 settings.removeOnEmpty = false; 9939 break; 9940 } 9941 9942 return settings; 9943 }; 9944 9945 net.user1.orbiter.Room.prototype.setRoomSettings = function (settings) { 9946 if (this.disposed) return; 9947 9948 if (settings.maxClients != null) { 9949 this.setAttribute(net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR, settings.maxClients.toString()); 9950 } 9951 if (settings.password != null) { 9952 this.setAttribute(net.user1.orbiter.Tokens.PASSWORD_ATTR, settings.password); 9953 } 9954 if (settings.removeOnEmpty != null) { 9955 this.setAttribute(net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR, settings.removeOnEmpty.toString()); 9956 } 9957 }; 9958 9959 //============================================================================== 9960 // OBSERVER MANAGEMENT 9961 //============================================================================== 9962 9963 /** 9964 * @private 9965 */ 9966 net.user1.orbiter.Room.prototype.addObserver = function (client) { 9967 // Don't add the client if it's already in the list. 9968 if (this.observerList.contains(client)) { 9969 this.log.info(this + " ignored addObserver() request. Observer list" + 9970 " already contains client:" + client + "."); 9971 return; 9972 } 9973 9974 // Add the client 9975 this.observerList.add(client); 9976 9977 // Update the number of clients in the room 9978 this.setNumObservers(this.observerList.length()); 9979 9980 // Register for attribute change events 9981 if (!this.occupantList.contains(client)) { 9982 this.addClientAttributeListeners(client); 9983 } 9984 9985 // Tell listeners an observer was added 9986 this.fireAddObserver(client.getClientID()); 9987 }; 9988 9989 /** 9990 * @private 9991 */ 9992 net.user1.orbiter.Room.prototype.removeObserver = function (clientID) { 9993 var client = this.observerList.removeByClientID(clientID); 9994 var clientFound = client != null; 9995 9996 // Update the number of clients in the room 9997 this.setNumObservers(this.observerList.length()); 9998 9999 // Unregister for attribute change events 10000 if (!this.occupantList.contains(client)) { 10001 this.removeClientAttributeListeners(client); 10002 } 10003 10004 // Tell listeners an observer was removed 10005 var customClient = client.getCustomClient(this.getRoomID()); 10006 this.fireRemoveObserver(customClient != null ? customClient : client); 10007 10008 if (!clientFound) { 10009 this.log.debug(this + " could not remove observer: " 10010 + clientID + ". No such client in the room's observer list."); 10011 } 10012 }; 10013 10014 net.user1.orbiter.Room.prototype.getObserverIDs = function () { 10015 if (this.disposed) return null; 10016 10017 return this.observerList.getAllIDs(); 10018 }; 10019 10020 net.user1.orbiter.Room.prototype.getObservers = function () { 10021 if (this.disposed) return null; 10022 10023 var observers = this.observerList.getAll(); 10024 var observersList = new Array(); 10025 var customClient; 10026 var observer; 10027 10028 for (var clientID in observers) { 10029 observer = observers[clientID]; 10030 customClient = observer.getCustomClient(this.getRoomID()); 10031 if (customClient != null) { 10032 observersList.push(customClient); 10033 } else { 10034 observersList.push(observer); 10035 } 10036 } 10037 return observersList; 10038 }; 10039 10040 /** 10041 * @private 10042 */ 10043 net.user1.orbiter.Room.prototype.getObserversInternal = function () { 10044 return this.observerList.getAll(); 10045 } 10046 10047 net.user1.orbiter.Room.prototype.clientIsObservingRoom = function (clientID) { 10048 if (this.disposed) return false; 10049 10050 if (clientID == null) { 10051 return this._clientIsObservingRoom; 10052 } 10053 return this.observerList.containsClientID(clientID); 10054 } 10055 10056 net.user1.orbiter.Room.prototype.getNumObservers = function () { 10057 if (this.disposed) return 0; 10058 10059 var levels = this.clientManager.self().getUpdateLevels(this.getRoomID()); 10060 if (levels != null) { 10061 if (levels.observerCount || levels.observerList) { 10062 return this.numObservers; 10063 } else { 10064 this.log.warn(this + " getNumObservers() called, but no observer count is " + 10065 "available. To enable observer count, turn on observer list" + 10066 " updates or observer count updates via the Room's setUpdateLevels()" + 10067 " method."); 10068 return 0; 10069 } 10070 } else { 10071 this.log.warn(this + " getNumObservers() called, but the current client's update " 10072 + " levels for the room are unknown. Please report this issue to union@user1.net."); 10073 return 0; 10074 } 10075 }; 10076 10077 /** 10078 * @private 10079 */ 10080 net.user1.orbiter.Room.prototype.setNumObservers = function (newNumObservers) { 10081 var oldNumClients = this.numObservers; 10082 this.numObservers = newNumObservers; 10083 10084 // Tell listeners that the number of clients in the room has changed. 10085 if (oldNumClients != newNumObservers) { 10086 this.fireObserverCount(newNumObservers); 10087 } 10088 }; 10089 10090 //============================================================================== 10091 // CLIENT ACCESS 10092 //============================================================================== 10093 10094 net.user1.orbiter.Room.prototype.getClient = function (id) { 10095 if (this.disposed) return null; 10096 10097 var customClient; 10098 var client = this.occupantList.getByClientID(id); 10099 client = (client == null) ? this.observerList.getByClientID(id) : client; 10100 10101 if (client != null) { 10102 customClient = client.getCustomClient(this.getRoomID()); 10103 } 10104 return customClient == null ? client : customClient; 10105 }; 10106 10107 //============================================================================== 10108 // CLIENT ATTRIBUTE LISTENERS 10109 //============================================================================== 10110 /** private */ 10111 net.user1.orbiter.Room.prototype.addClientAttributeListeners = function (client) { 10112 client.addEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateClientAttributeListener, this); 10113 client.addEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteClientAttributeListener, this); 10114 }; 10115 10116 /** private */ 10117 net.user1.orbiter.Room.prototype.removeClientAttributeListeners = function (client) { 10118 client.removeEventListener(net.user1.orbiter.AttributeEvent.UPDATE, this.updateClientAttributeListener, this); 10119 client.removeEventListener(net.user1.orbiter.AttributeEvent.DELETE, this.deleteClientAttributeListener, this); 10120 }; 10121 10122 /** private */ 10123 net.user1.orbiter.Room.prototype.updateClientAttributeListener = function (e) { 10124 var attr = e.getChangedAttr(); 10125 var client = e.target; 10126 var customClient = client.getCustomClient(this.getRoomID()); 10127 10128 this.fireUpdateClientAttribute(customClient == null ? client : customClient, 10129 attr.scope, attr.name, attr.value, attr.oldValue); 10130 }; 10131 10132 /** private */ 10133 net.user1.orbiter.Room.prototype.deleteClientAttributeListener = function (e) { 10134 var attr = e.getChangedAttr(); 10135 var client = e.target; 10136 var customClient = client.getCustomClient(this.getRoomID()); 10137 10138 this.fireDeleteClientAttribute(customClient == null ? client : customClient, 10139 attr.scope, attr.name, attr.value); 10140 } 10141 10142 //============================================================================== 10143 // CLIENT CLASS 10144 //============================================================================== 10145 10146 net.user1.orbiter.Room.prototype.setDefaultClientClass = function (defaultClass) { 10147 this.defaultClientClass = defaultClass; 10148 }; 10149 10150 net.user1.orbiter.Room.prototype.getDefaultClientClass = function () { 10151 return this.defaultClientClass; 10152 } 10153 10154 //============================================================================== 10155 // ATTRIBUTES 10156 //============================================================================== 10157 10158 net.user1.orbiter.Room.prototype.setAttribute = function (attrName, 10159 attrValue, 10160 isShared, 10161 isPersistent, 10162 evaluate) { 10163 if (this.disposed) return; 10164 10165 if (isShared !== false) { 10166 isShared = true; 10167 } 10168 10169 // Create an integer to hold the attribute options. 10170 var attrOptions = (isShared ? net.user1.orbiter.AttributeOptions.FLAG_SHARED : 0) 10171 | (isPersistent ? net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT : 0) 10172 | (evaluate ? net.user1.orbiter.AttributeOptions.FLAG_EVALUATE : 0); 10173 this.attributeManager.setAttribute(new net.user1.orbiter.upc.SetRoomAttr(attrName, attrValue, attrOptions, this.getRoomID())); 10174 } 10175 10176 net.user1.orbiter.Room.prototype.deleteAttribute = function (attrName) { 10177 if (this.disposed) return; 10178 10179 var deleteRequest = new net.user1.orbiter.upc.RemoveRoomAttr(this.getRoomID(), attrName); 10180 this.attributeManager.deleteAttribute(deleteRequest); 10181 }; 10182 10183 net.user1.orbiter.Room.prototype.getAttribute = function (attrName) { 10184 if (this.disposed) return null; 10185 10186 return this.attributeManager.getAttribute(attrName); 10187 }; 10188 10189 net.user1.orbiter.Room.prototype.getAttributes = function () { 10190 if (this.disposed) return null; 10191 10192 // Room attributes are considered global 10193 return this.attributeManager.getAttributesByScope(net.user1.orbiter.Tokens.GLOBAL_ATTR); 10194 } 10195 10196 // ============================================================================= 10197 // ROOM MODULES 10198 // ============================================================================= 10199 10200 net.user1.orbiter.Room.prototype.sendModuleMessage = function (messageName, 10201 messageArguments) { 10202 if (this.disposed) return; 10203 10204 var sendupcArgs = [net.user1.orbiter.UPC.SEND_ROOMMODULE_MESSAGE, this.getRoomID(), messageName]; 10205 10206 for (var arg in messageArguments) { 10207 sendupcArgs.push(arg + "|" + messageArguments[arg]); 10208 } 10209 10210 this.messageManager.sendUPC.apply(this.messageManager, sendupcArgs); 10211 }; 10212 10213 // ============================================================================= 10214 // ROOM REMOVAL 10215 // ============================================================================= 10216 10217 net.user1.orbiter.Room.prototype.remove = function (password) { 10218 if (this.disposed) return; 10219 10220 this.roomManager.removeRoom(this.getRoomID(), password); 10221 }; 10222 10223 // ============================================================================= 10224 // TOSTRING 10225 // ============================================================================= 10226 10227 net.user1.orbiter.Room.prototype.toString = function () { 10228 return "[ROOM id: " + this.getRoomID() + "]"; 10229 }; 10230 10231 10232 // ============================================================================= 10233 // EVENT DISPATCHING 10234 // ============================================================================= 10235 10236 /** 10237 * @private 10238 */ 10239 net.user1.orbiter.Room.prototype.fireJoin = function () { 10240 if (this.log) this.log.info(this + " Room joined."); 10241 10242 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.JOIN); 10243 this.dispatchEvent(e); 10244 }; 10245 10246 /** 10247 * @private 10248 */ 10249 net.user1.orbiter.Room.prototype.fireJoinResult = function (status) { 10250 if (this.log) this.log.info(this + " Join result: " + status); 10251 10252 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.JOIN_RESULT, 10253 null, null, status); 10254 this.dispatchEvent(e); 10255 }; 10256 10257 /** 10258 * @private 10259 */ 10260 net.user1.orbiter.Room.prototype.fireLeave = function () { 10261 if (this.log) this.log.info(this + " Room left."); 10262 10263 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.LEAVE); 10264 this.dispatchEvent(e); 10265 }; 10266 10267 /** 10268 * @private 10269 */ 10270 net.user1.orbiter.Room.prototype.fireLeaveResult = function (status) { 10271 if (this.log) this.log.info(this + " Leave result: " + status); 10272 10273 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.LEAVE_RESULT, 10274 null, null, status); 10275 this.dispatchEvent(e); 10276 }; 10277 10278 /** 10279 * @private 10280 */ 10281 net.user1.orbiter.Room.prototype.fireAddOccupant = function (id) { 10282 if (this.log) this.log.info(this + " Added occupant: [" + id + "]."); 10283 10284 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.ADD_OCCUPANT, 10285 this.getClient(id), 10286 id); 10287 this.dispatchEvent(e); 10288 }; 10289 10290 /** 10291 * @private 10292 */ 10293 net.user1.orbiter.Room.prototype.fireRemoveOccupant = function (client) { 10294 if (this.log) this.log.info(this + " Removed occupant: " + client + "."); 10295 10296 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.REMOVE_OCCUPANT, 10297 client, 10298 client.getClientID()); 10299 this.dispatchEvent(e); 10300 }; 10301 10302 /** 10303 * @private 10304 */ 10305 net.user1.orbiter.Room.prototype.fireAddObserver = function (id) { 10306 if (this.log) this.log.info(this + " Added observer: [" + id + "]."); 10307 10308 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.ADD_OBSERVER, 10309 this.getClient(id), 10310 id); 10311 this.dispatchEvent(e); 10312 }; 10313 10314 /** 10315 * @private 10316 */ 10317 net.user1.orbiter.Room.prototype.fireRemoveObserver = function (client) { 10318 if (this.log) this.log.info(this + " Removed observer: " + client + "."); 10319 10320 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.REMOVE_OBSERVER, 10321 client, 10322 client.getClientID()); 10323 this.dispatchEvent(e); 10324 }; 10325 10326 /** 10327 * @private 10328 */ 10329 net.user1.orbiter.Room.prototype.fireUpdateClientAttribute = function (client, 10330 scope, 10331 attrName, 10332 attrVal, 10333 oldVal) { 10334 if (this.log) this.log.info(this + " Client attribute updated on " + client + "." 10335 + " Attribute [" + attrName + "] is now: [" 10336 + attrVal + "]. Old value was: [" + oldVal + "]."); 10337 10338 var changedAttr = new net.user1.orbiter.Attribute (attrName, 10339 attrVal, 10340 oldVal, 10341 scope); 10342 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.UPDATE_CLIENT_ATTRIBUTE, 10343 client, 10344 client.getClientID(), 10345 null, 10346 changedAttr); 10347 this.dispatchEvent(e); 10348 }; 10349 10350 /** 10351 * @private 10352 */ 10353 net.user1.orbiter.Room.prototype.fireDeleteClientAttribute = function (client, 10354 scope, 10355 attrName, 10356 attrValue) { 10357 if (this.log) this.log.info(this + " Client attribute deleted from " + client + "." 10358 + " Deleted attribute: [" + attrName + "]."); 10359 10360 var deletedAttr = new net.user1.orbiter.Attribute(attrName, attrValue, null, scope); 10361 10362 // Trigger event on listeners. 10363 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.DELETE_CLIENT_ATTRIBUTE, 10364 client, 10365 client.getClientID(), 10366 null, 10367 deletedAttr); 10368 this.dispatchEvent(e); 10369 }; 10370 10371 /** 10372 * @private 10373 */ 10374 net.user1.orbiter.Room.prototype.fireOccupantCount = function (newNumClients) { 10375 if (this.log) this.log.info(this + " New occupant count: " + newNumClients); 10376 10377 // Trigger event on listeners. 10378 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OCCUPANT_COUNT, 10379 null, null, null, null, newNumClients); 10380 this.dispatchEvent(e); 10381 }; 10382 10383 /** 10384 * @private 10385 */ 10386 net.user1.orbiter.Room.prototype.fireObserverCount = function (newNumClients) { 10387 if (this.log) this.log.info(this + " New observer count: " + newNumClients); 10388 10389 // Trigger event on listeners. 10390 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVER_COUNT, 10391 null, null, null, null, newNumClients); 10392 this.dispatchEvent(e); 10393 }; 10394 10395 /** 10396 * @private 10397 */ 10398 net.user1.orbiter.Room.prototype.fireSynchronize = function (status) { 10399 if (this.log) this.log.info(this + " Synchronization complete."); 10400 10401 // Trigger event on listeners. 10402 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.SYNCHRONIZE, 10403 null, null, status); 10404 this.dispatchEvent(e); 10405 }; 10406 10407 /** 10408 * @private 10409 */ 10410 net.user1.orbiter.Room.prototype.fireObserve = function () { 10411 if (this.log) this.log.info(this + " Room observed."); 10412 10413 // Trigger event on listeners. 10414 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVE); 10415 this.dispatchEvent(e); 10416 }; 10417 10418 /** 10419 * @private 10420 */ 10421 net.user1.orbiter.Room.prototype.fireObserveResult = function (status) { 10422 if (this.log) this.log.info(this + " Observe result: " + status); 10423 10424 // Trigger event on listeners. 10425 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVE_RESULT, null, null, status); 10426 this.dispatchEvent(e); 10427 }; 10428 10429 /** 10430 * @private 10431 */ 10432 net.user1.orbiter.Room.prototype.fireStopObserving = function () { 10433 if (this.log) this.log.info(this + " Observation stopped."); 10434 10435 // Trigger event on listeners. 10436 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.STOP_OBSERVING); 10437 this.dispatchEvent(e); 10438 }; 10439 10440 /** 10441 * @private 10442 */ 10443 net.user1.orbiter.Room.prototype.fireStopObservingResult = function (status) { 10444 if (this.log) this.log.info(this + "Stop observing result: " + 10445 status); 10446 10447 // Trigger event on listeners. 10448 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT, 10449 null, null, status); 10450 this.dispatchEvent(e); 10451 }; 10452 10453 /** 10454 * @private 10455 */ 10456 net.user1.orbiter.Room.prototype.fireRemoved = function () { 10457 // Trigger event on listeners. 10458 var e = new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.REMOVED); 10459 this.dispatchEvent(e); 10460 }; 10461 10462 //============================================================================== 10463 // CLEANUP and DISPOSAL 10464 //============================================================================== 10465 /** private */ 10466 net.user1.orbiter.Room.prototype.purgeRoomData = function () { 10467 if (this.disposed) return; 10468 10469 // Clear the client lists 10470 this.log.debug(this + " Clearing occupant list."); 10471 for (var occupantID in this.occupantList.getAll()) { 10472 this.removeClientAttributeListeners(this.occupantList.getByClientID(occupantID)); 10473 } 10474 this.occupantList.removeAll(); 10475 10476 this.log.debug(this + " Clearing observer list."); 10477 for (var observerID in this.observerList.getAll()) { 10478 this.removeClientAttributeListeners(this.observerList.getByClientID(observerID)); 10479 } 10480 this.observerList.removeAll(); 10481 10482 // Clear room attributes. 10483 this.log.debug(this + " Clearing room attributes."); 10484 this.attributeManager.removeAll(); 10485 }; 10486 10487 /** 10488 * @private 10489 */ 10490 net.user1.orbiter.Room.prototype.shutdown = function () { 10491 if (this.disposed) return; 10492 10493 // Store a temp reference to the log for use in this method after 10494 // the room has released all its resources. 10495 var theLog = this.log; 10496 10497 theLog.debug(this + " Shutdown started."); 10498 10499 // Notify the room's listeners that the client left the room. 10500 if (this.clientIsInRoom()) { 10501 theLog.info(this + " Current client is in the room. Forcing the client to leave..."); 10502 this.doLeave(); 10503 } 10504 10505 // Notify the room's listeners that the client stopped observing the room. 10506 if (this.clientIsObservingRoom()) { 10507 theLog.info(this + " Current client is observing the room. Forcing the client to stop observing..."); 10508 this.doStopObserving(); 10509 } 10510 10511 theLog.info(this + " Dereferencing resources."); 10512 10513 // Dereference objects. 10514 this.purgeRoomData(); 10515 10516 this.attributeManager.dispose(); 10517 // Fire removed before nulling the MessageManager object so that listeners have a 10518 // last chance to respond by communicating with the server (or by 10519 // removing themselves from the connection's listener list) 10520 this.fireRemoved(); 10521 this.dispose(); 10522 10523 theLog.info(this + " Shutdown complete."); 10524 } 10525 10526 /** 10527 * @private 10528 */ 10529 net.user1.orbiter.Room.prototype.dispose = function () { 10530 this.log = null; 10531 this.syncState = null; 10532 this.occupantList = null; 10533 this.observerList = null; 10534 this.attributeManager = null; 10535 this.numOccupants = 0; 10536 this.defaultClientClass = null 10537 this.messageManager = null; 10538 this.roomManager = null; 10539 this.disposed = true; 10540 }; 10541 //============================================================================== 10542 // CLASS DECLARATION 10543 //============================================================================== 10544 /** 10545 * @class 10546 */ 10547 net.user1.orbiter.RoomClassRegistry = function () { 10548 this.registry = new Object(); 10549 }; 10550 10551 net.user1.orbiter.RoomClassRegistry.prototype.setRoomClass = function (roomID, roomClass) { 10552 this.registry[roomID] = roomClass; 10553 }; 10554 10555 net.user1.orbiter.RoomClassRegistry.prototype.clearRoomClass = function (roomID) { 10556 delete this.registry[roomID]; 10557 }; 10558 10559 10560 net.user1.orbiter.RoomClassRegistry.prototype.getRoomClass = function (roomID) { 10561 return this.registry[roomID] ? this.registry[roomID] : net.user1.orbiter.Room; 10562 }; 10563 //============================================================================== 10564 // CLASS DECLARATION 10565 //============================================================================== 10566 /** @class 10567 @extends net.user1.events.Event 10568 */ 10569 net.user1.orbiter.RoomEvent = function (type, 10570 client, 10571 clientID, 10572 status, 10573 changedAttr, 10574 numClients, 10575 roomID) { 10576 net.user1.events.Event.call(this, type); 10577 10578 this.client = client; 10579 this.clientID = clientID == "" ? null : clientID; 10580 this.status = status; 10581 this.changedAttr = changedAttr; 10582 this.numClients = numClients; 10583 this.roomID = roomID; 10584 }; 10585 10586 10587 //============================================================================== 10588 // INHERITANCE 10589 //============================================================================== 10590 net.user1.utils.extend(net.user1.orbiter.RoomEvent, net.user1.events.Event); 10591 10592 //============================================================================== 10593 // STATIC VARIABLES 10594 //============================================================================== 10595 10596 /** @constant */ 10597 net.user1.orbiter.RoomEvent.JOIN = "JOIN"; 10598 /** @constant */ 10599 net.user1.orbiter.RoomEvent.JOIN_RESULT = "JOIN_RESULT"; 10600 /** @constant */ 10601 net.user1.orbiter.RoomEvent.LEAVE = "LEAVE"; 10602 /** @constant */ 10603 net.user1.orbiter.RoomEvent.LEAVE_RESULT = "LEAVE_RESULT"; 10604 /** @constant */ 10605 net.user1.orbiter.RoomEvent.OBSERVE = "OBSERVE"; 10606 /** @constant */ 10607 net.user1.orbiter.RoomEvent.OBSERVE_RESULT = "OBSERVE_RESULT"; 10608 /** @constant */ 10609 net.user1.orbiter.RoomEvent.STOP_OBSERVING = "STOP_OBSERVING"; 10610 /** @constant */ 10611 net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT = "STOP_OBSERVING_RESULT"; 10612 /** @constant */ 10613 net.user1.orbiter.RoomEvent.SYNCHRONIZE = "SYNCHRONIZE"; 10614 /** @constant */ 10615 net.user1.orbiter.RoomEvent.UPDATE_CLIENT_ATTRIBUTE = "UPDATE_CLIENT_ATTRIBUTE"; 10616 /** @constant */ 10617 net.user1.orbiter.RoomEvent.DELETE_CLIENT_ATTRIBUTE = "DELETE_CLIENT_ATTRIBUTE"; 10618 /** @constant */ 10619 net.user1.orbiter.RoomEvent.ADD_OCCUPANT = "ADD_OCCUPANT"; 10620 /** @constant */ 10621 net.user1.orbiter.RoomEvent.REMOVE_OCCUPANT = "REMOVE_OCCUPANT"; 10622 /** @constant */ 10623 net.user1.orbiter.RoomEvent.ADD_OBSERVER = "ADD_OBSERVER"; 10624 /** @constant */ 10625 net.user1.orbiter.RoomEvent.REMOVE_OBSERVER = "REMOVE_OBSERVER"; 10626 /** @constant */ 10627 net.user1.orbiter.RoomEvent.OCCUPANT_COUNT = "OCCUPANT_COUNT"; 10628 /** @constant */ 10629 net.user1.orbiter.RoomEvent.OBSERVER_COUNT = "OBSERVER_COUNT"; 10630 /** @constant */ 10631 net.user1.orbiter.RoomEvent.REMOVED = "REMOVED"; 10632 10633 10634 net.user1.orbiter.RoomEvent.prototype.getRoomID = function () { 10635 return this.roomID; 10636 }; 10637 10638 net.user1.orbiter.RoomEvent.prototype.getClient = function () { 10639 return this.client; 10640 }; 10641 10642 net.user1.orbiter.RoomEvent.prototype.getClientID = function () { 10643 return this.clientID; 10644 }; 10645 10646 net.user1.orbiter.RoomEvent.prototype.getStatus = function () { 10647 return this.status; 10648 }; 10649 10650 net.user1.orbiter.RoomEvent.prototype.getNumClients = function () { 10651 return this.numClients; 10652 }; 10653 10654 net.user1.orbiter.RoomEvent.prototype.getChangedAttr = function () { 10655 return this.changedAttr; 10656 }; 10657 10658 net.user1.orbiter.RoomEvent.prototype.toString = function () { 10659 return "[object RoomEvent]"; 10660 }; 10661 //============================================================================== 10662 // CLASS DECLARATION 10663 //============================================================================== 10664 /** 10665 * @private 10666 */ 10667 net.user1.orbiter.RoomList = function () { 10668 // Call superconstructor 10669 net.user1.events.EventDispatcher.call(this); 10670 10671 this.rooms = new Array(); 10672 }; 10673 10674 //============================================================================== 10675 // INHERITANCE 10676 //============================================================================== 10677 net.user1.utils.extend(net.user1.orbiter.RoomList, net.user1.events.EventDispatcher); 10678 10679 //============================================================================== 10680 // INSTANCE METHODS 10681 //============================================================================== 10682 net.user1.orbiter.RoomList.prototype.add = function (room) { 10683 if (!this.contains(room)) { 10684 this.rooms.push(room); 10685 this.dispatchAddItem(room); 10686 return room; 10687 } else { 10688 return null; 10689 } 10690 }; 10691 10692 net.user1.orbiter.RoomList.prototype.remove = function (room) { 10693 var index = net.user1.utils.ArrayUtil.indexOf(this.rooms, room); 10694 if (index != -1) { 10695 this.rooms.splice(index, 1)[0]; 10696 this.dispatchRemoveItem(room); 10697 return room; 10698 } else { 10699 return null; 10700 } 10701 }; 10702 10703 net.user1.orbiter.RoomList.prototype.removeAll = function () { 10704 var room; 10705 for (var i = this.rooms.length; --i >= 0; ) { 10706 room = this.rooms.splice(i, 1)[0]; 10707 this.dispatchRemoveItem(room); 10708 } 10709 }; 10710 10711 net.user1.orbiter.RoomList.prototype.removeByRoomID = function (roomID) { 10712 var room; 10713 for (var i = this.rooms.length; --i >= 0; ) { 10714 if (this.rooms[i].getRoomID() == roomID) { 10715 room = this.rooms.splice(i, 1)[0]; 10716 this.dispatchRemoveItem(room); 10717 return room; 10718 } 10719 } 10720 return null; 10721 }; 10722 10723 net.user1.orbiter.RoomList.prototype.contains = function (room) { 10724 return net.user1.utils.ArrayUtil.indexOf(this.rooms, room) != -1; 10725 } 10726 10727 net.user1.orbiter.RoomList.prototype.containsRoomID = function (roomID) { 10728 if (roomID == "" || roomID == null) { 10729 return false; 10730 } 10731 return this.getByRoomID(roomID) != null; 10732 } 10733 10734 net.user1.orbiter.RoomList.prototype.getByRoomID = function (roomID) { 10735 var room; 10736 for (var i = this.rooms.length; --i >= 0;) { 10737 room = this.rooms[i]; 10738 if (room.getRoomID() == roomID) { 10739 return room; 10740 } 10741 } 10742 return null; 10743 }; 10744 10745 net.user1.orbiter.RoomList.prototype.getAll = function () { 10746 return this.rooms.slice(0); 10747 }; 10748 10749 net.user1.orbiter.RoomList.prototype.length = function () { 10750 return this.rooms.length; 10751 } 10752 10753 net.user1.orbiter.RoomList.prototype.dispatchAddItem = function (item) { 10754 this.dispatchEvent(new net.user1.orbiter.CollectionEvent(net.user1.orbiter.CollectionEvent.ADD_ITEM, item)); 10755 }; 10756 10757 net.user1.orbiter.RoomList.prototype.dispatchRemoveItem = function (item) { 10758 this.dispatchEvent(new net.user1.orbiter.CollectionEvent(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, item)); 10759 }; 10760 //============================================================================== 10761 // CLASS DECLARATION 10762 //============================================================================== 10763 /** 10764 * @class 10765 * @extends net.user1.orbiter.snapshot.Snapshot 10766 */ 10767 net.user1.orbiter.snapshot.RoomListSnapshot = function (qualifier, 10768 recursive) { 10769 // Call superconstructor 10770 net.user1.orbiter.snapshot.Snapshot.call(this); 10771 this.roomList = null; 10772 this.qualifier = null; 10773 this.recursive = null; 10774 this.method = net.user1.orbiter.UPC.GET_ROOMLIST_SNAPSHOT; 10775 this.args = [qualifier, 10776 recursive]; 10777 }; 10778 10779 //============================================================================== 10780 // INHERITANCE 10781 //============================================================================== 10782 net.user1.utils.extend(net.user1.orbiter.snapshot.RoomListSnapshot, net.user1.orbiter.snapshot.Snapshot); 10783 10784 //============================================================================== 10785 // INSTANCE METHODS 10786 //============================================================================== 10787 /** 10788 * @private 10789 */ 10790 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.setRoomList = function (value) { 10791 this.roomList = value; 10792 }; 10793 10794 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.getRoomList = function () { 10795 if (!this.roomList) { 10796 return null; 10797 } 10798 return this.roomList.slice(); 10799 }; 10800 10801 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.getQualifier = function () { 10802 return this.qualifier; 10803 }; 10804 10805 /** 10806 * @private 10807 */ 10808 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.setQualifier = function (value) { 10809 this.qualifier = value; 10810 }; 10811 10812 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.getRecursive = function () { 10813 return this.recursive; 10814 }; 10815 10816 /** 10817 * @private 10818 */ 10819 net.user1.orbiter.snapshot.RoomListSnapshot.prototype.setRecursive = function (value) { 10820 this.recursive = value; 10821 }; 10822 //============================================================================== 10823 // CLASS DECLARATION 10824 //============================================================================== 10825 /** @class 10826 10827 The RoomManager class dispatches the following events: 10828 10829 <ul class="summary"> 10830 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT}</li> 10831 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT}</li> 10832 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT}</li> 10833 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT}</li> 10834 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.ROOM_ADDED}</li> 10835 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED}</li> 10836 <li class="fixedFont">{@link net.user1.orbiter.RoomManagerEvent.ROOM_COUNT}</li> 10837 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.JOIN_RESULT}</li> 10838 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.LEAVE_RESULT}</li> 10839 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.OBSERVE_RESULT}</li> 10840 <li class="fixedFont">{@link net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT}</li> 10841 </ul> 10842 10843 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 10844 10845 @extends net.user1.events.EventDispatcher 10846 */ 10847 net.user1.orbiter.RoomManager = function (orbiter) { 10848 // Call superconstructor 10849 net.user1.events.EventDispatcher.call(this); 10850 10851 this.watchedQualifiers = []; 10852 10853 this.cachedRooms = new net.user1.orbiter.RoomList(); 10854 this.occupiedRooms = new net.user1.orbiter.RoomList(); 10855 this.observedRooms = new net.user1.orbiter.RoomList(); 10856 this.watchedRooms = new net.user1.orbiter.RoomList(); 10857 10858 this.cachedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10859 this.occupiedRooms.addEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 10860 this.occupiedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10861 this.observedRooms.addEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 10862 this.observedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10863 this.watchedRooms.addEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 10864 this.watchedRooms.addEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 10865 10866 this.orbiter = orbiter; 10867 10868 this.addEventListener(net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, 10869 this.watchForRoomsResultListener, this); 10870 this.addEventListener(net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT, 10871 this.stopWatchingForRoomsResultListener, this); 10872 10873 10874 this.roomClassRegistry = new net.user1.orbiter.RoomClassRegistry(); 10875 10876 // Store a reference to the this.log. 10877 this.log = this.orbiter.getLog(); 10878 }; 10879 10880 //============================================================================== 10881 // INHERITANCE 10882 //============================================================================== 10883 net.user1.utils.extend(net.user1.orbiter.RoomManager, net.user1.events.EventDispatcher); 10884 10885 //============================================================================== 10886 // ROOM CREATION AND REMOVAL 10887 //============================================================================== 10888 /** 10889 * @param attributes An array of JavaScript objects that describes the initial room 10890 * attributes for the room in the following format (note that this format differs 10891 * from the XML format used for createRoom() by Reactor, Union's Flash client framework): 10892 * 10893 * [ 10894 * attribute: { 10895 * name:"attrName1", 10896 * value:"attrValue1", 10897 * shared:true, 10898 * persistent:false, 10899 * immutable:false 10900 * }, 10901 * attribute: { 10902 * name:"attrName2", 10903 * value:"attrValue2", 10904 * shared:true, 10905 * persistent:false, 10906 * immutable:false 10907 * } 10908 * ] 10909 * </listing> 10910 */ 10911 10912 net.user1.orbiter.RoomManager.prototype.createRoom = function (roomID, 10913 roomSettings, 10914 attributes, 10915 modules) { 10916 // GET ROOM SETTINGS 10917 if (roomSettings == null) { 10918 roomSettings = new net.user1.orbiter.RoomSettings(); 10919 } 10920 10921 // GET ROOM MODULES 10922 if (modules == null) { 10923 modules = new net.user1.orbiter.RoomModules(); 10924 } 10925 10926 // ERROR CHECKING 10927 10928 // Abort if invalid module name found. 10929 var moduleIDs = modules.getIdentifiers(); 10930 var moduleID; 10931 for (var i = moduleIDs.length; --i >= 0;) { 10932 var moduleID = moduleIDs[i]; 10933 if (!net.user1.orbiter.Validator.isValidModuleName(moduleID)) { 10934 throw new Error("[ROOM_MANAGER] createRoom() failed. Illegal room module name: [" 10935 + moduleID + "]. See net.user1.orbiter.Validator.isValidModuleName()."); 10936 } 10937 } 10938 10939 // If a roomID is specified, we must validated it 10940 if (roomID != null) { 10941 // Abort if the supplied id can't be resolved to a single room 10942 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 10943 throw new Error("[ROOM_MANAGER] createRoom() failed. Illegal room id: [" 10944 + roomID + "]. See net.user1.orbiter.Validator.isValidResolvedRoomID()."); 10945 } 10946 } 10947 10948 // MAKE THE ROOM LOCALLY 10949 10950 // Send "" as the roomID if no roomID is specified. When the server 10951 // receives a request to create a roomID of "", it auto-generates 10952 // the id, and returns it via RoomManagerEvent.CREATE_ROOM_RESULT. 10953 if (roomID == null) { 10954 // Don't make the local room. Instead wait for the server to 10955 // report the new room via u39. 10956 roomID = ""; 10957 } else { 10958 // Make the local room. 10959 this.addCachedRoom(roomID); 10960 } 10961 10962 // TELL THE SERVER TO MAKE THE ROOM 10963 10964 // Create attributes 10965 if (attributes != null) { 10966 var attr; 10967 var attrArg = ""; 10968 for (var i = 0; i < attributes.length; i++) { 10969 attr = attributes[i]; 10970 attrSettings = 0; 10971 attrSettings |= attr.shared ? AttributeOptions.FLAG_SHARED : 0; 10972 attrSettings |= attr.persistent ? AttributeOptions.FLAG_PERSISTENT : 0; 10973 attrSettings |= attr.immutable ? AttributeOptions.FLAG_IMMUTABLE : 0; 10974 attrArg += attr.NAME 10975 + net.user1.orbiter.Tokens.RS + attr.VALUE 10976 + net.user1.orbiter.Tokens.RS + attrSettings.toString(); 10977 10978 if (i < attributes.length-1) { 10979 attrArg += Tokens.RS; 10980 } 10981 } 10982 } 10983 10984 // Send the create room request to the server. 10985 var msgMan = this.orbiter.getMessageManager(); 10986 msgMan.sendUPC(net.user1.orbiter.UPC.CREATE_ROOM, 10987 roomID, 10988 roomSettings.serialize(), 10989 attrArg, 10990 modules.serialize()); 10991 10992 // RETURN A REFERENCE TO THE LOCAL ROOM, IF ONE WAS CREATED 10993 if (roomID == "") { 10994 return null; 10995 } else { 10996 return this.getRoom(roomID); 10997 } 10998 }; 10999 11000 net.user1.orbiter.RoomManager.prototype.removeRoom = function (roomID, password) { 11001 // Quit if no room specified. 11002 if (roomID == null || !net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 11003 throw new Error("Invalid room id supplied to removeRoom(): [" 11004 + roomID + "]. Request not sent."); 11005 } 11006 11007 if (password == null) { 11008 password = ""; 11009 } 11010 11011 var msgMan = this.orbiter.getMessageManager(); 11012 msgMan.sendUPC(net.user1.orbiter.UPC.REMOVE_ROOM, 11013 roomID, 11014 password); 11015 }; 11016 11017 //============================================================================== 11018 // ROOM OBSERVATION 11019 //============================================================================== 11020 11021 net.user1.orbiter.RoomManager.prototype.observeRoom = function (roomID, 11022 password, 11023 updateLevels) { 11024 var theRoom; 11025 11026 // If the room is not valid, quit 11027 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 11028 throw new Error("Invalid room id supplied to observeRoom(): [" 11029 + roomID + "]. Request not sent." 11030 + " See net.user1.orbiter.Validator.isValidResolvedRoomID()."); 11031 } 11032 11033 // Try to get a reference to the room 11034 theRoom = this.getRoom(roomID); 11035 11036 // If the room exists 11037 if (theRoom != null) { 11038 if (theRoom.clientIsObservingRoom()) { 11039 this.log.warn("[ROOM_MANAGER] Room observe attempt ignored. Already observing room: '" 11040 + roomID + "'."); 11041 return null; 11042 } 11043 } else { 11044 // Make the local room 11045 theRoom = this.addCachedRoom(roomID); 11046 } 11047 11048 // Validate the password 11049 if (password == null) { 11050 password = ""; 11051 } 11052 if (!net.user1.orbiter.Validator.isValidPassword(password)) { 11053 throw new Error("Invalid room password supplied to observeRoom(). " 11054 + " Room ID: [" + roomID + "], password: [" + password + "]." 11055 + " See net.user1.orbiter.Validator.isValidPassword()."); 11056 } 11057 11058 // If update levels were specified for this room, send them now. 11059 if (updateLevels != null) { 11060 theRoom.setUpdateLevels(updateLevels); 11061 } 11062 11063 // Send the UPC only if at least one valid room was found 11064 var msgMan = this.orbiter.getMessageManager(); 11065 msgMan.sendUPC(net.user1.orbiter.UPC.OBSERVE_ROOM, 11066 roomID, 11067 password); 11068 11069 return theRoom; 11070 }; 11071 11072 //============================================================================== 11073 // WATCHING FOR ROOMS 11074 //============================================================================== 11075 11076 net.user1.orbiter.RoomManager.prototype.watchForRooms = function (roomQualifier) { 11077 var recursive = false; 11078 11079 // null means watch the whole server 11080 if (roomQualifier == null) { 11081 roomQualifier = ""; 11082 recursive = true; 11083 } 11084 11085 var msgMan = this.orbiter.getMessageManager(); 11086 msgMan.sendUPC(net.user1.orbiter.UPC.WATCH_FOR_ROOMS, 11087 roomQualifier, 11088 recursive.toString()); 11089 }; 11090 11091 net.user1.orbiter.RoomManager.prototype.stopWatchingForRooms = function (roomQualifier) { 11092 var recursive = false; 11093 // null means whole server 11094 if (roomQualifier == null) { 11095 roomQualifier = ""; 11096 recursive = true; 11097 } 11098 11099 var msgMan = this.orbiter.getMessageManager(); 11100 msgMan.sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS, 11101 roomQualifier, 11102 recursive.toString()); 11103 }; 11104 11105 net.user1.orbiter.RoomManager.prototype.isWatchingQualifier = function (qualifier) { 11106 return net.user1.utils.ArrayUtil.indexOf(this.watchedQualifiers, qualifier) != -1; 11107 }; 11108 11109 /** 11110 * @private 11111 */ 11112 net.user1.orbiter.RoomManager.prototype.watchForRoomsResultListener = function (e) { 11113 if (e.getStatus() == net.user1.orbiter.Status.SUCCESS) { 11114 this.watchedQualifiers.push(e.getRoomIdQualifier()); 11115 } 11116 }; 11117 11118 /** 11119 * @private 11120 */ 11121 net.user1.orbiter.RoomManager.prototype.stopWatchingForRoomsResultListener = function (e) { 11122 var unwatchedQualifier = e.getRoomIdQualifier(); 11123 var unwatchedQualifierIndex; 11124 11125 if (e.getStatus() == net.user1.orbiter.Status.SUCCESS) { 11126 unwatchedQualifierIndex = net.user1.utils.ArrayUtil.indexOf(watchedQualifiers, unwatchedQualifier); 11127 if (unwatchedQualifierIndex != -1) { 11128 watchedQualifiers.splice(unwatchedQualifierIndex, 1); 11129 } 11130 } 11131 }; 11132 11133 //============================================================================== 11134 // SENDING MESSAGES 11135 //============================================================================== 11136 11137 net.user1.orbiter.RoomManager.prototype.sendMessage = function (messageName, 11138 rooms, 11139 includeSelf, 11140 filters) { 11141 var rest = Array.prototype.slice.call(arguments).slice(4); 11142 11143 // An array of arguments to send to the server. 11144 var args; 11145 11146 // Can't continue without a valid messageName. 11147 if (messageName == null || messageName == "") { 11148 this.log.warn("[ROOM_MANAGER] sendMessage() failed. No messageName supplied."); 11149 return; 11150 } 11151 11152 // Send the UPC. 11153 var msgMan = this.orbiter.getMessageManager(); 11154 args = [net.user1.orbiter.UPC.SEND_MESSAGE_TO_ROOMS, 11155 messageName, 11156 rooms.join(net.user1.orbiter.Tokens.RS), 11157 String(includeSelf), 11158 filters != null ? filters.toXMLString() : ""]; 11159 msgMan.sendUPC.apply(msgMan, args.concat(rest)); 11160 } 11161 11162 11163 //============================================================================== 11164 // JOINING ROOMS 11165 //============================================================================== 11166 11167 net.user1.orbiter.RoomManager.prototype.joinRoom = function (roomID, 11168 password, 11169 updateLevels) { 11170 if (!this.orbiter.isReady()) { 11171 this.log.warn("[ROOM_MANAGER] Connection not open. Request to join room [" 11172 + roomID + "] could not be sent."); 11173 return null; 11174 } 11175 11176 // If the room ID is not valid, quit 11177 if (!net.user1.orbiter.Validator.isValidResolvedRoomID(roomID)) { 11178 this.log.error("[ROOM_MANAGER] Invalid room id supplied to joinRoom(): [" 11179 + roomID + "]. Join request not sent." 11180 + " See net.user1.orbiter.Validator.isValidResolvedRoomID()."); 11181 return null; 11182 } 11183 11184 // Try to get a reference to the room 11185 var theRoom = this.getRoom(roomID); 11186 11187 // If the room exists 11188 if (theRoom != null) { 11189 // Can't join a room you're already in. 11190 if (theRoom.clientIsInRoom()) { 11191 this.log.warn("[ROOM_MANAGER] Room join attempt aborted. Already in room: [" 11192 + theRoom.getRoomID() + "]."); 11193 return theRoom; 11194 } 11195 } else { 11196 // Make the local room. 11197 theRoom = this.addCachedRoom(roomID); 11198 } 11199 11200 // Validate the password 11201 if (password == null) { 11202 password = ""; 11203 } 11204 if (!net.user1.orbiter.Validator.isValidPassword(password)) { 11205 this.log.error("[ROOM_MANAGER] Invalid room password supplied to joinRoom(): [" 11206 + roomID + "]. Join request not sent." 11207 + " See net.user1.orbiter.Validator.isValidPassword()."); 11208 return theRoom; 11209 } 11210 11211 11212 // If any update levels are specified, send them before joining. 11213 if (updateLevels != null) { 11214 theRoom.setUpdateLevels(updateLevels); 11215 } 11216 11217 var msgMan = this.orbiter.getMessageManager(); 11218 msgMan.sendUPC(net.user1.orbiter.UPC.JOIN_ROOM, 11219 roomID, 11220 password); 11221 return theRoom; 11222 }; 11223 11224 // ============================================================================= 11225 // ROOM OBJECT CREATION/DISPOSAL 11226 // ============================================================================= 11227 11228 /** 11229 * @private 11230 */ 11231 net.user1.orbiter.RoomManager.prototype.requestRoom = function (roomID) { 11232 if (roomID == "") { 11233 this.log.warn("[ROOM_MANAGER] requestRoom() failed. Supplied room ID was empty."); 11234 return null; 11235 } 11236 11237 var theRoom = this.getRoom(roomID); 11238 if (theRoom != null) { 11239 return theRoom; 11240 } else { 11241 this.log.debug("[ROOM_MANAGER] Creating new room object for id: [" + roomID + "]"); 11242 var RoomClass = this.roomClassRegistry.getRoomClass(roomID); 11243 theRoom = new RoomClass(roomID, 11244 this, 11245 this.orbiter.getMessageManager(), 11246 this.orbiter.getClientManager(), 11247 this.orbiter.getAccountManager(), 11248 this.log); 11249 return theRoom; 11250 } 11251 }; 11252 11253 /** 11254 * @private 11255 */ 11256 net.user1.orbiter.RoomManager.prototype.disposeRoom = function (roomID) { 11257 var room = this.getRoom(roomID); 11258 if (room != null) { 11259 this.log.debug("[ROOM_MANAGER] Disposing room: " + room); 11260 this.removeCachedRoom(roomID); 11261 this.removeWatchedRoom(roomID); 11262 this.removeOccupiedRoom(roomID); 11263 this.removeObservedRoom(roomID); 11264 } else { 11265 this.log.debug("[ROOM_MANAGER] disposeRoom() called for unknown room: [" + roomID + "]"); 11266 } 11267 }; 11268 11269 /** 11270 * @private 11271 */ 11272 net.user1.orbiter.RoomManager.prototype.removeAllRooms = function () { 11273 this.log.debug("[ROOM_MANAGER] Removing all local room object references."); 11274 this.cachedRooms.removeAll(); 11275 this.watchedRooms.removeAll(); 11276 this.occupiedRooms.removeAll(); 11277 this.observedRooms.removeAll(); 11278 }; 11279 11280 // ============================================================================= 11281 // CACHED ROOMS 11282 // ============================================================================= 11283 11284 /** 11285 * @private 11286 */ 11287 net.user1.orbiter.RoomManager.prototype.addCachedRoom = function (roomID) { 11288 var cachedRoom = this.cachedRooms.getByRoomID(roomID); 11289 if (cachedRoom == null) { 11290 this.log.debug("[ROOM_MANAGER] Adding cached room: [" + roomID + "]"); 11291 return this.cachedRooms.add(this.requestRoom(roomID)); 11292 } else { 11293 return cachedRoom; 11294 } 11295 }; 11296 11297 /** 11298 * @private 11299 */ 11300 net.user1.orbiter.RoomManager.prototype.removeCachedRoom = function (roomID) { 11301 if (this.cachedRooms.containsRoomID(roomID)) { 11302 this.cachedRooms.removeByRoomID(roomID); 11303 } else { 11304 throw new Error("[ROOM_MANAGER] Could not remove cached room: [" + roomID + "]." 11305 + " Room not found."); 11306 } 11307 }; 11308 11309 net.user1.orbiter.RoomManager.prototype.hasCachedRoom = function (roomID) { 11310 return this.cachedRooms.containsRoomID(roomID); 11311 }; 11312 11313 net.user1.orbiter.RoomManager.prototype.disposeCachedRooms = function () { 11314 var room; 11315 var rooms = cachedRooms.getAll(); 11316 for (var i = 0; i <= rooms.length; i++) { 11317 room = rooms[i]; 11318 removeCachedRoom(room.getRoomID()); 11319 } 11320 }; 11321 11322 // ============================================================================= 11323 // WATCHED ROOMS 11324 // ============================================================================= 11325 11326 /** 11327 * @private 11328 */ 11329 net.user1.orbiter.RoomManager.prototype.addWatchedRoom = function (roomID) { 11330 this.log.debug("[ROOM_MANAGER] Adding watched room: [" + roomID + "]"); 11331 var room = this.watchedRooms.add(this.requestRoom(roomID)); 11332 room.updateSyncState(); 11333 }; 11334 11335 /** 11336 * @private 11337 */ 11338 net.user1.orbiter.RoomManager.prototype.removeWatchedRoom = function (roomID) { 11339 var room = this.watchedRooms.removeByRoomID(roomID); 11340 if (room != null) { 11341 room.updateSyncState(); 11342 } else { 11343 this.log.debug("[ROOM_MANAGER] Request to remove watched room [" 11344 + roomID + "] ignored; room not in watched list."); 11345 } 11346 }; 11347 11348 /** 11349 * @private 11350 */ 11351 net.user1.orbiter.RoomManager.prototype.removeAllWatchedRooms = function () { 11352 var rooms = this.watchedRooms.getAll(); 11353 var room; 11354 for (var i = 0; i <= rooms.length; i++) { 11355 room = rooms[i]; 11356 removeWatchedRoom(room.getRoomID()); 11357 room.updateSyncState(); 11358 } 11359 }; 11360 11361 /** 11362 * @private 11363 */ 11364 net.user1.orbiter.RoomManager.prototype.setWatchedRooms = function (qualifier, newRoomIDs) { 11365 // Remove rooms from local list 11366 var rooms = this.getRoomsWithQualifier(qualifier); 11367 var room; 11368 for (var i = 0; i < rooms.length; i++) { 11369 room = rooms[i]; 11370 if (net.user1.utils.ArrayUtil.indexOf(newRoomIDs, room.getSimpleRoomID()) == -1) { 11371 this.removeWatchedRoom(room.getRoomID()); 11372 } 11373 } 11374 // Add rooms to local list 11375 var fullRoomID; 11376 var roomID; 11377 for (var i = 0; i < newRoomIDs.length; i++) { 11378 roomID = newRoomIDs[i]; 11379 fullRoomID = qualifier + (qualifier != "" ? "." : "") + roomID; 11380 if (!this.watchedRooms.containsRoomID(fullRoomID)) { 11381 this.addWatchedRoom(fullRoomID); 11382 } 11383 } 11384 }; 11385 11386 net.user1.orbiter.RoomManager.prototype.hasWatchedRoom = function (roomID) { 11387 return this.watchedRooms.containsRoomID(roomID); 11388 } 11389 11390 // ============================================================================= 11391 // OCCUPIED ROOMS 11392 // ============================================================================= 11393 11394 /** 11395 * @private 11396 */ 11397 net.user1.orbiter.RoomManager.prototype.addOccupiedRoom = function (roomID) { 11398 this.log.debug("[ROOM_MANAGER] Adding occupied room: [" + roomID + "]"); 11399 var room = this.occupiedRooms.add(this.requestRoom(roomID)); 11400 room.updateSyncState(); 11401 return room; 11402 }; 11403 11404 /** 11405 * @private 11406 */ 11407 net.user1.orbiter.RoomManager.prototype.removeOccupiedRoom = function (roomID) { 11408 var room = this.occupiedRooms.removeByRoomID(roomID); 11409 if (room != null) { 11410 room.updateSyncState(); 11411 } else { 11412 this.log.debug("[ROOM_MANAGER] Request to remove occupied room [" 11413 + roomID + "] ignored; client is not in room."); 11414 } 11415 }; 11416 11417 net.user1.orbiter.RoomManager.prototype.hasOccupiedRoom = function (roomID) { 11418 return this.occupiedRooms.containsRoomID(roomID); 11419 }; 11420 11421 // ============================================================================= 11422 // OBSERVED ROOMS 11423 // ============================================================================= 11424 11425 /** 11426 * @private 11427 */ 11428 net.user1.orbiter.RoomManager.prototype.addObservedRoom = function (roomID) { 11429 this.log.debug("[ROOM_MANAGER] Adding observed room: [" + roomID + "]"); 11430 var room = this.observedRooms.add(this.requestRoom(roomID)); 11431 room.updateSyncState(); 11432 return room; 11433 }; 11434 11435 /** 11436 * @private 11437 */ 11438 net.user1.orbiter.RoomManager.prototype.removeObservedRoom = function (roomID) { 11439 var room = this.observedRooms.removeByRoomID(roomID); 11440 if (room != null) { 11441 room.updateSyncState(); 11442 } else { 11443 this.log.debug("[ROOM_MANAGER] Request to remove observed room [" 11444 + roomID + "] ignored; client is not observing room."); 11445 } 11446 }; 11447 11448 net.user1.orbiter.RoomManager.prototype.hasObservedRoom = function (roomID) { 11449 return this.observedRooms.containsRoomID(roomID); 11450 }; 11451 11452 //============================================================================== 11453 // ROOM LIST LISTENERS 11454 //============================================================================== 11455 11456 /** 11457 * @private 11458 */ 11459 net.user1.orbiter.RoomManager.prototype.addRoomListener = function (e) { 11460 var room = e.getItem(); 11461 11462 // Only trigger added for first known reference 11463 if (this.getKnownReferenceCount(room.getRoomID()) == 1) { 11464 this.fireRoomAdded(room.getQualifier(), room.getRoomID(), room); 11465 this.fireRoomCount(this.getNumRooms()); 11466 } 11467 }; 11468 11469 /** 11470 * @private 11471 */ 11472 net.user1.orbiter.RoomManager.prototype.removeRoomListener = function (e) { 11473 var room = e.getItem(); 11474 var knownReferenceCount = this.getKnownReferenceCount(room.getRoomID()); 11475 11476 switch (e.target) { 11477 case this.occupiedRooms: 11478 this.log.debug("[ROOM_MANAGER] Removed occupied room: " + room); 11479 if (knownReferenceCount == 0) { 11480 this.fireRoomRemoved(room.getQualifier(), room.getRoomID(), room); 11481 this.fireRoomCount(this.getNumRooms()); 11482 } 11483 break; 11484 11485 case this.observedRooms: 11486 this.log.debug("[ROOM_MANAGER] Removed observed room: " + room); 11487 if (knownReferenceCount == 0) { 11488 this.fireRoomRemoved(room.getQualifier(), room.getRoomID(), room); 11489 this.fireRoomCount(this.getNumRooms()); 11490 } 11491 break; 11492 11493 case this.watchedRooms: 11494 this.log.debug("[ROOM_MANAGER] Removed watched room: " + room); 11495 if (knownReferenceCount == 0) { 11496 this.fireRoomRemoved(room.getQualifier(), room.getRoomID(), room); 11497 this.fireRoomCount(this.getNumRooms()); 11498 } 11499 break; 11500 11501 case this.cachedRooms: 11502 this.log.debug("[ROOM_MANAGER] Removed cached room: " + room); 11503 break; 11504 } 11505 11506 // When the RoomManager has no more references to the room, shut it down 11507 if (knownReferenceCount == 0 && !this.cachedRooms.contains(room)) { 11508 room.shutdown(); 11509 } 11510 }; 11511 11512 //============================================================================== 11513 // ROOM ACCESS 11514 //============================================================================== 11515 11516 /** 11517 * @private 11518 */ 11519 net.user1.orbiter.RoomManager.prototype.getKnownReferenceCount = function (roomID) { 11520 var count = 0; 11521 count += this.hasObservedRoom(roomID) ? 1 : 0; 11522 count += this.hasOccupiedRoom(roomID) ? 1 : 0; 11523 count += this.hasWatchedRoom(roomID) ? 1 : 0; 11524 return count; 11525 } 11526 11527 net.user1.orbiter.RoomManager.prototype.getRooms = function () { 11528 var roomlist = net.user1.utils.ArrayUtil.combine(this.occupiedRooms.getAll(), 11529 this.observedRooms.getAll(), 11530 this.watchedRooms.getAll()); 11531 return roomlist; 11532 }; 11533 11534 net.user1.orbiter.RoomManager.prototype.roomIsKnown = function (roomID) { 11535 var rooms = this.getRooms(); 11536 var room; 11537 for (var i = rooms.length; --i >= 0;) { 11538 room = rooms[i]; 11539 if (room.getRoomID() == roomID) { 11540 return true; 11541 } 11542 } 11543 return false; 11544 }; 11545 11546 net.user1.orbiter.RoomManager.prototype.getRoomIDs = function () { 11547 var roomIDs = new Array(); 11548 var rooms = this.getRooms(); 11549 11550 for (var i = 0; i <= rooms.length; i++) { 11551 roomIDs.push(rooms[i].getRoomID()); 11552 } 11553 11554 return roomIDs; 11555 }; 11556 11557 net.user1.orbiter.RoomManager.prototype.getAllRooms = function () { 11558 var roomlist = net.user1.utils.ArrayUtil.combine(this.occupiedRooms.getAll(), 11559 this.observedRooms.getAll(), 11560 this.watchedRooms.getAll(), 11561 this.cachedRooms.getAll()); 11562 11563 return roomlist; 11564 }; 11565 11566 net.user1.orbiter.RoomManager.prototype.getRoomsWithQualifier = function (qualifier) { 11567 if (qualifier == null) { 11568 return this.getRooms(); 11569 } 11570 11571 var roomlist = []; 11572 var rooms = this.getRooms(); 11573 var room; 11574 for (var i = 0; i < rooms.length; i++) { 11575 room = rooms[i]; 11576 if (net.user1.orbiter.RoomIDParser.getQualifier(room.getRoomID()) == qualifier) { 11577 roomlist.push(room); 11578 } 11579 } 11580 11581 return roomlist; 11582 }; 11583 11584 net.user1.orbiter.RoomManager.prototype.getNumRooms = function (qualifier) { 11585 return this.getRoomsWithQualifier(qualifier).length; 11586 } 11587 11588 net.user1.orbiter.RoomManager.prototype.getRoom = function (roomID) { 11589 var rooms = this.getAllRooms(); 11590 var room; 11591 for (var i = rooms.length; --i >= 0;) { 11592 room = rooms[i]; 11593 if (room.getRoomID() == roomID) { 11594 return room; 11595 } 11596 } 11597 return null; 11598 }; 11599 11600 // ============================================================================= 11601 // ROOM CLASS REGISTRY 11602 // ============================================================================= 11603 11604 net.user1.orbiter.RoomManager.prototype.getRoomClassRegistry = function () { 11605 return this.roomClassRegistry; 11606 }; 11607 11608 // ============================================================================= 11609 // CLIENT ACCESS 11610 // ============================================================================= 11611 11612 /** 11613 * @private 11614 */ 11615 net.user1.orbiter.RoomManager.prototype.getAllClients = function () { 11616 var clientSets = []; 11617 var rooms = this.getRooms(); 11618 var room; 11619 for (var i = rooms.length; --i >= 0;) { 11620 room = rooms[i]; 11621 clientSets.push(room.getOccupantsInternal()); 11622 clientSets.push(room.getObserversInternal()); 11623 } 11624 return net.user1.utils.ObjectUtil.combine(clientSets); 11625 }; 11626 11627 net.user1.orbiter.RoomManager.prototype.clientIsKnown = function (clientID) { 11628 var clientSets = []; 11629 11630 var rooms = this.getRooms(); 11631 var room; 11632 for (var i = rooms.length; --i >= 0;) { 11633 room = rooms[i]; 11634 clientSets.push(room.getOccupantsInternal()); 11635 clientSets.push(room.getObserversInternal()); 11636 } 11637 11638 for (var i = clientSets.length; --i >= 0;) { 11639 if (clientSets[i][clientID] != null) { 11640 return true; 11641 } 11642 } 11643 return false; 11644 }; 11645 11646 // ============================================================================= 11647 // EVENT DISPATCHING 11648 // ============================================================================= 11649 11650 /** 11651 * @private 11652 */ 11653 net.user1.orbiter.RoomManager.prototype.fireWatchForRoomsResult = function (roomIDQualifier, 11654 status) { 11655 var e = new net.user1.orbiter.RoomManagerEvent( 11656 net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, 11657 null, status, roomIDQualifier); 11658 this.dispatchEvent(e); 11659 }; 11660 11661 /** 11662 * @private 11663 */ 11664 net.user1.orbiter.RoomManager.prototype.fireStopWatchingForRoomsResult = function (roomIDQualifier, 11665 status) { 11666 var e = new net.user1.orbiter.RoomManagerEvent( 11667 net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT, 11668 null, status, roomIDQualifier); 11669 this.dispatchEvent(e); 11670 }; 11671 11672 /** 11673 * @private 11674 */ 11675 net.user1.orbiter.RoomManager.prototype.fireCreateRoomResult = function (roomIDQualifier, 11676 roomID, 11677 status) { 11678 var e = new net.user1.orbiter.RoomManagerEvent( 11679 net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT, 11680 roomID, status, roomIDQualifier); 11681 this.dispatchEvent(e); 11682 }; 11683 11684 /** 11685 * @private 11686 */ 11687 net.user1.orbiter.RoomManager.prototype.fireRemoveRoomResult = function (roomIDQualifier, 11688 roomID, 11689 status) { 11690 var e = new net.user1.orbiter.RoomManagerEvent( 11691 net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT, 11692 roomID, status, roomIDQualifier); 11693 11694 this.dispatchEvent(e); 11695 } 11696 11697 /** 11698 * @private 11699 */ 11700 net.user1.orbiter.RoomManager.prototype.fireRoomAdded = function (roomIDQualifier, 11701 roomID, 11702 theRoom) { 11703 var e = new net.user1.orbiter.RoomManagerEvent( 11704 net.user1.orbiter.RoomManagerEvent.ROOM_ADDED, 11705 roomID, null, roomIDQualifier, theRoom); 11706 this.dispatchEvent(e); 11707 } 11708 11709 /** 11710 * @private 11711 */ 11712 net.user1.orbiter.RoomManager.prototype.fireRoomRemoved = function (roomIDQualifier, 11713 roomID, 11714 theRoom) { 11715 var e = new net.user1.orbiter.RoomManagerEvent( 11716 net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED, 11717 roomID, 11718 null, 11719 roomIDQualifier, 11720 theRoom); 11721 this.dispatchEvent(e); 11722 } 11723 11724 /** 11725 * @private 11726 */ 11727 net.user1.orbiter.RoomManager.prototype.fireRoomCount = function (numRooms) { 11728 this.dispatchEvent(new net.user1.orbiter.RoomManagerEvent(net.user1.orbiter.RoomManagerEvent.ROOM_COUNT, 11729 null, null, null, null, numRooms)); 11730 }; 11731 11732 /** 11733 * @private 11734 */ 11735 net.user1.orbiter.RoomManager.prototype.fireJoinRoomResult = function (roomID, status) { 11736 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.JOIN_RESULT, null, null, 11737 status, null, 0, roomID)); 11738 } 11739 11740 /** 11741 * @private 11742 */ 11743 net.user1.orbiter.RoomManager.prototype.fireLeaveRoomResult = function (roomID, status) { 11744 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.LEAVE_RESULT, null, null, 11745 status, null, 0, roomID)); 11746 }; 11747 11748 /** 11749 * @private 11750 */ 11751 net.user1.orbiter.RoomManager.prototype.fireObserveRoomResult = function (roomID, status) { 11752 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.OBSERVE_RESULT, null, null, 11753 status, null, 0, roomID)); 11754 }; 11755 11756 /** 11757 * @private 11758 */ 11759 net.user1.orbiter.RoomManager.prototype.fireStopObservingRoomResult = function (roomID, status) { 11760 this.dispatchEvent(new net.user1.orbiter.RoomEvent(net.user1.orbiter.RoomEvent.STOP_OBSERVING_RESULT, null, null, 11761 status, null, 0, roomID)); 11762 }; 11763 11764 11765 // ============================================================================= 11766 // CLEANUP and DISPOSAL 11767 // ============================================================================= 11768 11769 /** 11770 * @private 11771 * 11772 * Clears all resources. The object remains alive, and can be reused. To 11773 * permanently deactivate this object, use dispose(). 11774 */ 11775 net.user1.orbiter.RoomManager.prototype.cleanup = function () { 11776 this.log.info("[ROOM_MANAGER] Cleaning resources."); 11777 this.removeAllRooms(); 11778 this.watchedQualifiers = []; 11779 }; 11780 11781 /** 11782 * @private 11783 */ 11784 net.user1.orbiter.RoomManager.prototype.dispose = function () { 11785 this.log.info("[ROOM_MANAGER] Disposing resources."); 11786 this.watchedQualifiers = null; 11787 var room; 11788 var rooms = this.getAllRooms(); 11789 for (var i = this.getAllRooms().length; --i >= 0;) { 11790 room = rooms[i]; 11791 room.dispose(); 11792 } 11793 this.cachedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11794 this.occupiedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 11795 this.occupiedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11796 this.observedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 11797 this.observedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11798 this.watchedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.ADD_ITEM, this.addRoomListener, this); 11799 this.watchedRooms.removeEventListener(net.user1.orbiter.CollectionEvent.REMOVE_ITEM, this.removeRoomListener, this); 11800 this.occupiedRooms = null; 11801 this.observedRooms = null; 11802 this.watchedRooms = null; 11803 this.cachedRooms = null; 11804 this.log = null; 11805 this.orbiter = null; 11806 this.roomClassRegistry = null; 11807 }; 11808 //============================================================================== 11809 // CLASS DECLARATION 11810 //============================================================================== 11811 /** @class 11812 @extends net.user1.events.Event 11813 */ 11814 net.user1.orbiter.RoomManagerEvent = function (type, 11815 roomID, 11816 status, 11817 roomIdQualifier, 11818 room, 11819 numRooms) { 11820 net.user1.events.Event.call(this, type); 11821 11822 this.roomID = roomID; 11823 this.status = status; 11824 this.roomIdQualifier = roomIdQualifier; 11825 this.room = room; 11826 this.numRooms = numRooms; 11827 }; 11828 11829 //============================================================================== 11830 // INHERITANCE 11831 //============================================================================== 11832 net.user1.utils.extend(net.user1.orbiter.RoomManagerEvent, net.user1.events.Event); 11833 11834 //============================================================================== 11835 // STATIC VARIABLES 11836 //============================================================================== 11837 11838 /** @constant */ 11839 net.user1.orbiter.RoomManagerEvent.CREATE_ROOM_RESULT = "CREATE_ROOM_RESULT"; 11840 /** @constant */ 11841 net.user1.orbiter.RoomManagerEvent.REMOVE_ROOM_RESULT = "REMOVE_ROOM_RESULT"; 11842 /** @constant */ 11843 net.user1.orbiter.RoomManagerEvent.WATCH_FOR_ROOMS_RESULT = "WATCH_FOR_ROOMS_RESULT"; 11844 /** @constant */ 11845 net.user1.orbiter.RoomManagerEvent.STOP_WATCHING_FOR_ROOMS_RESULT = "STOP_WATCHING_FOR_ROOMS_RESULT"; 11846 /** @constant */ 11847 net.user1.orbiter.RoomManagerEvent.ROOM_ADDED = "ROOM_ADDED"; 11848 /** @constant */ 11849 net.user1.orbiter.RoomManagerEvent.ROOM_REMOVED = "ROOM_REMOVED"; 11850 /** @constant */ 11851 net.user1.orbiter.RoomManagerEvent.ROOM_COUNT = "ROOM_COUNT"; 11852 11853 net.user1.orbiter.RoomManagerEvent.prototype.getRoomIdQualifier = function () { 11854 if (this.roomIdQualifier == null && this.room != null) { 11855 return this.room.getQualifier(); 11856 } else { 11857 return this.roomIdQualifier; 11858 } 11859 }; 11860 11861 net.user1.orbiter.RoomManagerEvent.prototype.getRoomID = function () { 11862 var fullRoomID; 11863 var qualifier; 11864 11865 if (this.room != null) { 11866 return this.room.getRoomID(); 11867 } else if (this.roomID == null) { 11868 return null; 11869 } else { 11870 qualifier = this.getRoomIdQualifier(); 11871 fullRoomID = qualifier == "" || qualifier == null 11872 ? this.roomID 11873 : qualifier + "." + this.roomID; 11874 return fullRoomID; 11875 } 11876 }; 11877 11878 net.user1.orbiter.RoomManagerEvent.prototype.getSimpleRoomID = function () { 11879 if (this.roomID == null && this.room != null) { 11880 return this.room.getSimpleRoomID(); 11881 } else { 11882 return this.roomID; 11883 } 11884 }; 11885 11886 net.user1.orbiter.RoomManagerEvent.prototype.getRoom = function () { 11887 return this.room; 11888 } 11889 11890 net.user1.orbiter.RoomManagerEvent.prototype.getStatus = function () { 11891 return this.status; 11892 } 11893 11894 net.user1.orbiter.RoomManagerEvent.prototype.getNumRooms = function () { 11895 return this.numRooms; 11896 } 11897 11898 net.user1.orbiter.RoomManagerEvent.prototype.toString = function () { 11899 return "[object RoomManagerEvent]"; 11900 }; 11901 //============================================================================== 11902 // CLASS DECLARATION 11903 //============================================================================== 11904 /** 11905 * @private 11906 */ 11907 net.user1.orbiter.RoomManifest = function () { 11908 }; 11909 11910 net.user1.orbiter.RoomManifest.prototype.deserialize = function (roomID, 11911 serializedAttributes, 11912 clientList, 11913 occupantCount, 11914 observerCount) { 11915 this.roomID = roomID; 11916 this.attributes = null; 11917 this.occupantCount = occupantCount; 11918 this.observerCount = observerCount; 11919 this.occupants = []; 11920 this.observers = []; 11921 11922 this.deserializeAttributes(serializedAttributes); 11923 this.deserializeClientList(clientList); 11924 }; 11925 11926 /** 11927 * @private 11928 */ 11929 net.user1.orbiter.RoomManifest.prototype.deserializeAttributes = function (serializedAttributes) { 11930 var attrList = serializedAttributes.split(net.user1.orbiter.Tokens.RS); 11931 this.attributes = new net.user1.orbiter.AttributeCollection(); 11932 11933 for (var i = attrList.length-2; i >= 0; i -=2) { 11934 this.attributes.setAttribute(attrList[i], attrList[i+1], net.user1.orbiter.Tokens.GLOBAL_ATTR); 11935 } 11936 }; 11937 11938 /** 11939 * @private 11940 */ 11941 net.user1.orbiter.RoomManifest.prototype.deserializeClientList = function (clientList) { 11942 var clientManifest; 11943 11944 for (var i = clientList.length-5; i >= 0; i -=5) { 11945 clientManifest = new net.user1.orbiter.ClientManifest(); 11946 clientManifest.deserialize(clientList[i], clientList[i+1], null, null, clientList[i+3], [this.roomID, clientList[i+4]]); 11947 if (clientList[i+2] == "0") { 11948 this.occupants.push(clientManifest); 11949 } else { 11950 this.observers.push(clientManifest); 11951 } 11952 } 11953 }; 11954 //============================================================================== 11955 // CLASS DECLARATION 11956 //============================================================================== 11957 /** @class 11958 * 11959 * @example 11960 * var modules = new net.user1.orbiter.RoomModules(); 11961 * modules.addModule("com.business.StockTickerListener", net.user1.orbiter.ModuleType.CLASS); 11962 * orbiter.getRoomManager().createRoom("someRoomID", 11963 * null, 11964 * null, 11965 * modules); 11966 */ 11967 net.user1.orbiter.RoomModules = function () { 11968 this.modules = new Array(); 11969 }; 11970 11971 net.user1.orbiter.RoomModules.prototype.addModule = function (identifier, 11972 type) { 11973 this.modules.push([type, identifier]); 11974 }; 11975 11976 net.user1.orbiter.RoomModules.prototype.serialize = function () { 11977 var modulesString = ""; 11978 11979 var numModules = this.modules.length; 11980 for (var i = 0; i < numModules; i++) { 11981 modulesString += this.modules[i][0] + net.user1.orbiter.Tokens.RS + this.modules[i][1]; 11982 if (i < numModules-1) { 11983 modulesString += net.user1.orbiter.Tokens.RS; 11984 } 11985 } 11986 11987 return modulesString; 11988 }; 11989 11990 net.user1.orbiter.RoomModules.prototype.getIdentifiers = function () { 11991 var ids = new Array(); 11992 11993 var module; 11994 for (var i = 0; i < this.modules.length; i++) { 11995 module = this.modules[i]; 11996 ids.push(module[1]); 11997 } 11998 return ids; 11999 }; 12000 //============================================================================== 12001 // CLASS DECLARATION 12002 //============================================================================== 12003 /** @class */ 12004 net.user1.orbiter.RoomSettings = function () { 12005 this.removeOnEmpty = null; 12006 this.maxClients = null; 12007 this.password = null; 12008 }; 12009 12010 net.user1.orbiter.RoomSettings.prototype.serialize = function () { 12011 var RS = net.user1.orbiter.Tokens.RS; 12012 var settingsString = 12013 net.user1.orbiter.Tokens.REMOVE_ON_EMPTY_ATTR + RS + 12014 (this.removeOnEmpty == null ? "true" : this.removeOnEmpty.toString()) 12015 + RS + net.user1.orbiter.Tokens.MAX_CLIENTS_ATTR + RS + 12016 (this.maxClients == null ? "-1" : this.maxClients.toString()) 12017 + RS + net.user1.orbiter.Tokens.PASSWORD_ATTR + RS + 12018 (this.password == null ? "" : this.password); 12019 return settingsString; 12020 } 12021 //============================================================================== 12022 // CLASS DECLARATION 12023 //============================================================================== 12024 /** 12025 * @class 12026 * @extends net.user1.orbiter.snapshot.Snapshot 12027 */ 12028 net.user1.orbiter.snapshot.RoomSnapshot = function (roomID, password, updateLevels) { 12029 // Call superconstructor 12030 net.user1.orbiter.snapshot.Snapshot.call(this); 12031 this.manifest = null; 12032 this.method = net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT; 12033 this.args = [roomID, password, updateLevels != null ? updateLevels.toInt() : ""]; 12034 this.hasStatus = true; 12035 }; 12036 //============================================================================== 12037 // INHERITANCE 12038 //============================================================================== 12039 net.user1.utils.extend(net.user1.orbiter.snapshot.RoomSnapshot, net.user1.orbiter.snapshot.Snapshot); 12040 12041 //============================================================================== 12042 // INSTANCE METHODS 12043 //============================================================================== 12044 /** 12045 * @private 12046 */ 12047 net.user1.orbiter.snapshot.RoomSnapshot.prototype.setManifest = function (value) { 12048 this.manifest = value; 12049 }; 12050 12051 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getAttribute = function (name) { 12052 if (!this.manifest) { 12053 return null; 12054 } 12055 return this.manifest.attributes.getAttribute(name, net.user1.orbiter.Tokens.GLOBAL_ATTR); 12056 }; 12057 12058 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getAttributes = function () { 12059 if (!this.manifest) { 12060 return null; 12061 } 12062 return this.manifest.attributes.getByScope(net.user1.orbiter.Tokens.GLOBAL_ATTR); 12063 }; 12064 12065 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getRoomID = function () { 12066 if (!this.manifest) { 12067 return null; 12068 } 12069 return this.manifest.roomID; 12070 }; 12071 12072 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getOccupants = function () { 12073 return this.manifest.occupants.slice(); 12074 } 12075 12076 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getObservers = function () { 12077 return this.manifest.observers.slice(); 12078 } 12079 12080 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getOccupant = function (clientID) { 12081 var client; 12082 for (var i = this.manifest.occupants.length; --i >= 0;) { 12083 if (this.manifest.occupants[i].clientID == clientID) { 12084 return this.manifest.occupants[i]; 12085 } 12086 } 12087 return null; 12088 }; 12089 12090 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getObserver = function (clientID) { 12091 var client; 12092 for (var i = this.manifest.observers.length; --i >= 0;) { 12093 if (this.manifest.observers[i].clientID == clientID) { 12094 return this.manifest.observers[i]; 12095 } 12096 } 12097 return null; 12098 }; 12099 12100 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getNumOccupants = function () { 12101 return Math.max(this.manifest.occupants.length, this.manifest.occupantCount); 12102 } 12103 12104 net.user1.orbiter.snapshot.RoomSnapshot.prototype.getNumObservers = function () { 12105 return Math.max(this.manifest.observers.length, this.manifest.observerCount); 12106 } 12107 //============================================================================== 12108 // SECURITY_ROLE CONSTANTS 12109 //============================================================================== 12110 /** @class */ 12111 net.user1.orbiter.SecurityRole = new Object(); 12112 /** @constant */ 12113 net.user1.orbiter.SecurityRole.MODERATOR = "MODERATOR"; 12114 //============================================================================== 12115 // CLASS DECLARATION 12116 //============================================================================== 12117 /** @class 12118 12119 The Server class dispatches the following events: 12120 12121 <ul class="summary"> 12122 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.TIME_SYNC}</li> 12123 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.UPC_PROCESSED}</li> 12124 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.WATCH_FOR_PROCESSED_UPCS_RESULT}</li> 12125 <li class="fixedFont">{@link net.user1.orbiter.ServerEvent.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT}</li> 12126 </ul> 12127 12128 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 12129 12130 @extends net.user1.events.EventDispatcher 12131 */ 12132 net.user1.orbiter.Server = function (orbiter) { 12133 // Call superconstructor 12134 net.user1.events.EventDispatcher.call(this); 12135 12136 this.orbiter = orbiter; 12137 this.version = null; 12138 this.upcVersion = null; 12139 this.localAgeAtLastSync = NaN; 12140 this.lastKnownServerTime = NaN; 12141 this._isWatchingForProcessedUPCs = false; 12142 12143 this.log = orbiter.getLog(); 12144 12145 orbiter.addEventListener(net.user1.orbiter.OrbiterEvent.READY, this.readyListener, this); 12146 } 12147 12148 //============================================================================== 12149 // INHERITANCE 12150 //============================================================================== 12151 net.user1.utils.extend(net.user1.orbiter.Server, net.user1.events.EventDispatcher); 12152 12153 // ============================================================================= 12154 // SERVER-WIDE MESSAGING 12155 // ============================================================================= 12156 net.user1.orbiter.Server.prototype.sendMessage = function (messageName, 12157 includeSelf, 12158 filters) { 12159 var rest = Array.prototype.slice.call(arguments).slice(3); 12160 var args; 12161 12162 if (messageName == null || messageName == "") { 12163 this.log.warn("Server.sendMessage() failed. No messageName supplied."); 12164 return; 12165 } 12166 12167 var msgMan = this.orbiter.getMessageManager(); 12168 args = [net.user1.orbiter.UPC.SEND_MESSAGE_TO_SERVER, 12169 messageName, 12170 includeSelf.toString(), 12171 filters != null ? filters.toXMLString() : ""]; 12172 msgMan.sendUPC.apply(msgMan, args.concat(rest)); 12173 }; 12174 12175 // ============================================================================= 12176 // SERVER MODULES 12177 // ============================================================================= 12178 net.user1.orbiter.Server.prototype.sendModuleMessage = function (moduleID, 12179 messageName, 12180 messageArguments) { 12181 var sendupcArgs = [net.user1.orbiter.UPC.SEND_SERVERMODULE_MESSAGE, moduleID, messageName]; 12182 12183 for (var arg in messageArguments) { 12184 sendupcArgs.push(arg + net.user1.orbiter.Tokens.RS + messageArguments[arg]); 12185 } 12186 12187 this.orbiter.getMessageManager().sendUPC.apply(this.orbiter.getMessageManager(), sendupcArgs); 12188 }; 12189 12190 net.user1.orbiter.Server.prototype.clearModuleCache = function () { 12191 this.orbiter.getMessageManager().sendUPC(net.user1.orbiter.UPC.CLEAR_MODULE_CACHE); 12192 }; 12193 12194 // ============================================================================= 12195 // VERSION ACCESS 12196 // ============================================================================= 12197 12198 /** 12199 * @private 12200 */ 12201 net.user1.orbiter.Server.prototype.setVersion = function (value) { 12202 this.version = value; 12203 }; 12204 12205 net.user1.orbiter.Server.prototype.getVersion = function () { 12206 return this.version; 12207 }; 12208 12209 /** 12210 * @private 12211 */ 12212 net.user1.orbiter.Server.prototype.setUPCVersion = function (value) { 12213 this.upcVersion = value; 12214 }; 12215 12216 net.user1.orbiter.Server.prototype.getUPCVersion = function () { 12217 return this.upcVersion; 12218 }; 12219 12220 // ============================================================================= 12221 // UPC STATS AND PROCESSING 12222 // ============================================================================= 12223 12224 net.user1.orbiter.Server.prototype.resetUPCStats = function () { 12225 this.orbiter.getMessageManager().sendUPC(UPC.RESET_UPC_STATS); 12226 }; 12227 12228 net.user1.orbiter.Server.prototype.watchForProcessedUPCs = function () { 12229 this.orbiter.getMessageManager().sendUPC(net.user1.orbiter.UPC.WATCH_FOR_PROCESSED_UPCS); 12230 }; 12231 12232 net.user1.orbiter.Server.prototype.stopWatchingForProcessedUPCs = function () { 12233 this.orbiter.getMessageManager().sendUPC(net.user1.orbiter.UPC.STOP_WATCHING_FOR_PROCESSED_UPCS); 12234 }; 12235 12236 net.user1.orbiter.Server.prototype.isWatchingForProcessedUPCs = function () { 12237 return this._isWatchingForProcessedUPCs; 12238 }; 12239 12240 net.user1.orbiter.Server.prototype.setIsWatchingForProcessedUPCs = function (value) { 12241 this._isWatchingForProcessedUPCs = value; 12242 }; 12243 12244 // ============================================================================= 12245 // TIME RETRIEVAL METHODS 12246 // ============================================================================= 12247 net.user1.orbiter.Server.prototype.getServerTime = function () { 12248 var self = this.orbiter.self(); 12249 var lastServerTime = NaN; 12250 var estimatedServerTime = NaN; 12251 12252 if (self != null) { 12253 lastServerTime = isNaN(this.lastKnownServerTime) 12254 ? self.getConnectTime() 12255 : this.lastKnownServerTime; 12256 12257 estimatedServerTime = isNaN(lastServerTime) 12258 ? NaN 12259 : (lastServerTime + (new Date().getTime()-this.localAgeAtLastSync)); 12260 } 12261 12262 if (estimatedServerTime == 0) { 12263 log.warn("Server time requested, but is unknown."); 12264 } 12265 12266 return estimatedServerTime; 12267 }; 12268 12269 net.user1.orbiter.Server.prototype.syncTime = function () { 12270 var msgMan = this.orbiter.getMessageManager(); 12271 msgMan.sendUPC(net.user1.orbiter.UPC.SYNC_TIME); 12272 }; 12273 12274 /** 12275 * @private 12276 */ 12277 net.user1.orbiter.Server.prototype.readyListener = function (e) { 12278 this.orbiter.getMessageManager().addMessageListener(net.user1.orbiter.UPC.SERVER_TIME_UPDATE, this.u50); 12279 this.localAgeAtLastSync = new Date().getTime();; 12280 }; 12281 12282 // ============================================================================= 12283 // EVENT DISPATCHING 12284 // ============================================================================= 12285 12286 /** 12287 * @private 12288 */ 12289 net.user1.orbiter.Server.prototype.fireTimeSync = function () { 12290 this.dispatchEvent(new net.user1.orbiter.ServerEvent(ServerEvent.TIME_SYNC)); 12291 }; 12292 12293 /** 12294 * @private 12295 */ 12296 net.user1.orbiter.Server.prototype.dispatchWatchForProcessedUPCsResult = function (status) { 12297 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.WATCH_FOR_PROCESSED_UPCS_RESULT, 12298 null, status)); 12299 }; 12300 12301 /** 12302 * @private 12303 */ 12304 net.user1.orbiter.Server.prototype.dispatchStopWatchingForProcessedUPCsResult = function (status) { 12305 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT, 12306 null, status)); 12307 }; 12308 12309 /** 12310 * @private 12311 */ 12312 net.user1.orbiter.Server.prototype.dispatchUPCProcessed = function (record) { 12313 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.UPC_PROCESSED, record)); 12314 }; 12315 12316 /** 12317 * @private 12318 */ 12319 net.user1.orbiter.Server.prototype.dispatchResetUPCStatsResult = function (status) { 12320 this.dispatchEvent(new net.user1.orbiter.ServerEvent(net.user1.orbiter.ServerEvent.RESET_UPC_STATS_RESULT, 12321 null, status)); 12322 }; 12323 12324 //============================================================================== 12325 // UPC LISTENERS 12326 //============================================================================== 12327 12328 /** 12329 * @private 12330 */ 12331 net.user1.orbiter.Server.prototype.u50 = function (newTime) { // SERVER_TIME 12332 this.lastKnownServerTime = Number(newTime); 12333 this.localAgeAtLastSync = new Date().getTime(); 12334 this.fireTimeSync(); 12335 } 12336 12337 //============================================================================== 12338 // CLEANUP AND DISPOSAL 12339 //============================================================================== 12340 /** 12341 * @private 12342 */ 12343 net.user1.orbiter.Server.prototype.cleanup = function () { 12344 this.log.info("[SERVER] Cleaning resources."); 12345 this.setIsWatchingForProcessedUPCs(false); 12346 } 12347 //============================================================================== 12348 // CLASS DECLARATION 12349 //============================================================================== 12350 /** 12351 * @class 12352 * @extends net.user1.orbiter.snapshot.Snapshot 12353 */ 12354 net.user1.orbiter.snapshot.GatewaysSnapshot = function () { 12355 // Call superconstructor 12356 net.user1.orbiter.snapshot.Snapshot.call(this); 12357 this.gateways = null; 12358 this.method = net.user1.orbiter.UPC.GET_GATEWAYS_SNAPSHOT; 12359 }; 12360 12361 //============================================================================== 12362 // INHERITANCE 12363 //============================================================================== 12364 net.user1.utils.extend(net.user1.orbiter.snapshot.GatewaysSnapshot, net.user1.orbiter.snapshot.Snapshot); 12365 12366 //============================================================================== 12367 // INSTANCE METHODS 12368 //============================================================================== 12369 /** 12370 * @private 12371 */ 12372 net.user1.orbiter.snapshot.GatewaysSnapshot.prototype.setGateways = function (value) { 12373 this.gateways = value; 12374 }; 12375 12376 net.user1.orbiter.snapshot.GatewaysSnapshot.prototype.getGateways = function () { 12377 if (!this.gateways) { 12378 return []; 12379 } 12380 return this.gateways.slice(); 12381 }; 12382 //============================================================================== 12383 // CLASS DECLARATION 12384 //============================================================================== 12385 /** @class 12386 @extends net.user1.events.Event 12387 */ 12388 net.user1.orbiter.ServerEvent = function (type, 12389 upcProcessingRecord, 12390 status) { 12391 net.user1.events.Event.call(this, type); 12392 12393 this.upcProcessingRecord = upcProcessingRecord; 12394 this.status = status; 12395 }; 12396 12397 //============================================================================== 12398 // INHERITANCE 12399 //============================================================================== 12400 net.user1.utils.extend(net.user1.orbiter.ServerEvent, net.user1.events.Event); 12401 12402 //============================================================================== 12403 // STATIC VARIABLES 12404 //============================================================================== 12405 12406 /** @constant */ 12407 net.user1.orbiter.ServerEvent.TIME_SYNC = "TIME_SYNC"; 12408 /** @constant */ 12409 net.user1.orbiter.ServerEvent.UPC_PROCESSED = "UPC_PROCESSED"; 12410 /** @constant */ 12411 net.user1.orbiter.ServerEvent.WATCH_FOR_PROCESSED_UPCS_RESULT = "WATCH_FOR_PROCESSED_UPCS_RESULT"; 12412 /** @constant */ 12413 net.user1.orbiter.ServerEvent.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT = "STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT"; 12414 /** @constant */ 12415 net.user1.orbiter.ServerEvent.RESET_UPC_STATS_RESULT = "RESET_UPC_STATS_RESULT"; 12416 12417 //============================================================================== 12418 // VARIABLES 12419 //============================================================================== 12420 net.user1.orbiter.ServerEvent.prototype.getUPCProcessingRecord = function () { 12421 return upcProcessingRecord; 12422 } 12423 12424 net.user1.orbiter.ServerEvent.prototype.getStatus = function () { 12425 return status; 12426 } 12427 12428 12429 net.user1.orbiter.ServerEvent.prototype.toString = function () { 12430 return "[object ServerEvent]"; 12431 }; 12432 //============================================================================== 12433 // CLASS DECLARATION 12434 //============================================================================== 12435 /** 12436 * @class 12437 * @extends net.user1.orbiter.snapshot.Snapshot 12438 */ 12439 net.user1.orbiter.snapshot.ServerModuleListSnapshot = function () { 12440 // Call superconstructor 12441 net.user1.orbiter.snapshot.Snapshot.call(this); 12442 this.moduleList = null; 12443 this.method = net.user1.orbiter.UPC.GET_SERVERMODULELIST_SNAPSHOT; 12444 }; 12445 12446 //============================================================================== 12447 // INHERITANCE 12448 //============================================================================== 12449 net.user1.utils.extend(net.user1.orbiter.snapshot.ServerModuleListSnapshot, net.user1.orbiter.snapshot.Snapshot); 12450 12451 //============================================================================== 12452 // INSTANCE METHODS 12453 //============================================================================== 12454 /** 12455 * @private 12456 */ 12457 net.user1.orbiter.snapshot.ServerModuleListSnapshot.prototype.setModuleList = function (value) { 12458 this.moduleList = value; 12459 } 12460 12461 net.user1.orbiter.snapshot.ServerModuleListSnapshot.prototype.getModuleList = function () { 12462 if (!this.moduleList) { 12463 return null; 12464 } 12465 return this.moduleList.slice(); 12466 }; 12467 //============================================================================== 12468 // CLASS DECLARATION 12469 //============================================================================== 12470 /** 12471 * @private 12472 * @class 12473 */ 12474 net.user1.orbiter.upc.SetAttr = function (name, 12475 value, 12476 options) { 12477 12478 // Abort if name is invalid. 12479 if (!net.user1.orbiter.Validator.isValidAttributeName(name)) { 12480 throw new Error("Cannot set attribute. Illegal name" + 12481 " (see Validator.isValidAttributeName()). " + 12482 " Illegal attribute is: " + name + "=" + value); 12483 } 12484 12485 // Abort if value is invalid. 12486 if (!net.user1.orbiter.Validator.isValidAttributeValue(value)) { 12487 throw new Error("Cannot set attribute. Illegal value" + 12488 " (see Validator.isValidAttributeValue()). " + 12489 " Illegal attribute is: " + name + "=" + value); 12490 } 12491 12492 if (value == null) { 12493 value = ""; 12494 } 12495 12496 // Validation passed, so assign instance vars. 12497 this.name = name; 12498 this.value = value; 12499 this.options = options; 12500 }; 12501 /** 12502 * @private 12503 */ 12504 net.user1.orbiter.upc.SetClientAttr = function (name, 12505 value, 12506 options, 12507 scope, 12508 clientID, 12509 userID) { 12510 // Call superconstructor 12511 net.user1.orbiter.upc.SetAttr.call(this, name, value, options); 12512 12513 // Abort if scope is invalid. 12514 if (!net.user1.orbiter.Validator.isValidAttributeScope(scope)) { 12515 throw new Error("Cannot set client attribute. Illegal scope" + 12516 " (see Validator.isValidAttributeScope()). " + 12517 " Illegal attribute is: " + name + "=" + value); 12518 } 12519 12520 // A scope null means the attribute is global. 12521 if (scope == null) { 12522 scope = net.user1.orbiter.Tokens.GLOBAL_ATTR; 12523 } 12524 12525 this.method = net.user1.orbiter.UPC.SET_CLIENT_ATTR; 12526 this.args = [clientID, userID, name, value, scope, options.toString()]; 12527 }; 12528 12529 //============================================================================== 12530 // INHERITANCE 12531 //============================================================================== 12532 net.user1.utils.extend(net.user1.orbiter.upc.SetClientAttr, net.user1.orbiter.upc.SetAttr); 12533 /** 12534 * @private 12535 */ 12536 net.user1.orbiter.upc.SetRoomAttr = function (name, 12537 value, 12538 options, 12539 roomID) { 12540 // Call superconstructor 12541 net.user1.orbiter.upc.SetAttr.call(this, name, value, options); 12542 12543 this.method = net.user1.orbiter.UPC.SET_ROOM_ATTR; 12544 this.args = [roomID, name, value, options.toString()]; 12545 }; 12546 12547 //============================================================================== 12548 // INHERITANCE 12549 //============================================================================== 12550 net.user1.utils.extend(net.user1.orbiter.upc.SetRoomAttr, net.user1.orbiter.upc.SetAttr); 12551 //============================================================================== 12552 // CLASS DECLARATION 12553 //============================================================================== 12554 /** 12555 * @class 12556 * 12557 * Note: Due to JavaScript's lack of memory measurement APIs and byte-measurement 12558 * APIs, Orbiter's Statistics class does not include many of the statistics found 12559 * in the equivalent Reactor Statistics class. 12560 */ 12561 net.user1.orbiter.Statistics = function (orbiter) { 12562 this.statsTimer; 12563 this.lastTick = NaN; 12564 this.lastTotalMessages = 0; 12565 this.messagesPerSecond = 0; 12566 12567 // Peaks 12568 this.peakMessagesPerSecond = 0; 12569 12570 this.orbiter = null; 12571 this.connection = null; 12572 12573 this.statsIntervalID = -1; 12574 12575 this.init(orbiter); 12576 }; 12577 12578 /** 12579 * @private 12580 */ 12581 net.user1.orbiter.Statistics.prototype.init = function (orbiter) { 12582 this.setOrbiter(orbiter); 12583 this.start(); 12584 }; 12585 12586 /** 12587 * @private 12588 */ 12589 net.user1.orbiter.Statistics.prototype.setOrbiter = function (orbiter) { 12590 // Register new orbiter 12591 this.orbiter = orbiter; 12592 }; 12593 12594 net.user1.orbiter.Statistics.prototype.start = function () { 12595 this.stop(); 12596 12597 this.statsIntervalID = setInterval(statsTimerListener, 1000); 12598 12599 this.lastTick = new Date().getTime(); 12600 this.lastTotalMessages = this.getTotalMessages(); 12601 }; 12602 12603 net.user1.orbiter.Statistics.prototype.stop = function () { 12604 clearInterval(statsIntervalID); 12605 this.clearStats(); 12606 }; 12607 12608 /** 12609 * @private 12610 */ 12611 net.user1.orbiter.Statistics.prototype.clearStats = function () { 12612 this.lastTick = 0; 12613 this.lastTotalMessages = 0; 12614 this.messagesPerSecond = 0; 12615 this.peakMessagesPerSecond = 0; 12616 }; 12617 12618 net.user1.orbiter.Statistics.prototype.getLifetimeNumClientsConnected = function () { 12619 return this.orbiter.getClientManager().getLifetimeNumClientsKnown(); 12620 }; 12621 12622 net.user1.orbiter.Statistics.prototype.getCurrentNumClientsConnected = function () { 12623 return this.orbiter.getClientManager().getNumClients(); 12624 }; 12625 12626 net.user1.orbiter.Statistics.prototype.getTotalMessagesReceived = function () { 12627 return this.orbiter.getMessageManager().getNumMessagesReceived(); 12628 } 12629 12630 net.user1.orbiter.Statistics.prototype.getTotalMessagesSent = function () { 12631 return this.orbiter.getMessageManager().getNumMessagesSent(); 12632 }; 12633 12634 net.user1.orbiter.Statistics.prototype.getTotalMessages = function () { 12635 return this.getTotalMessagesReceived() + this.getTotalMessagesSent(); 12636 }; 12637 12638 net.user1.orbiter.Statistics.prototype.getMessagesPerSecond = function () { 12639 return this.messagesPerSecond; 12640 }; 12641 12642 //============================================================================== 12643 // PEAK MESSAGES PER SECOND 12644 //============================================================================== 12645 12646 net.user1.orbiter.Statistics.prototype.getPeakMessagesPerSecond = function () { 12647 return this.peakMessagesPerSecond; 12648 }; 12649 12650 // ============================================================================= 12651 // TIMER LISTENER 12652 // ============================================================================= 12653 12654 /** 12655 * @private 12656 */ 12657 net.user1.orbiter.Statistics.prototype.statsTimerListener = function (e) { 12658 // Check elapsed time 12659 var now = new Date().getTime(); 12660 var elapsed = now - lastTick; 12661 lastTick = now; 12662 12663 // Calculate number of messages sent and received since last tick 12664 var totalMessages = this.getTotalMessages(); 12665 var tickNumMsgs = totalMessages - this.lastTotalMessages; 12666 this.lastTotalMessages = totalMessages; 12667 this.messagesPerSecond = Math.round((1000/elapsed) * tickNumMsgs); 12668 if (this.messagesPerSecond > this.peakMessagesPerSecond) { 12669 this.peakMessagesPerSecond = this.messagesPerSecond; 12670 } 12671 }; 12672 //============================================================================== 12673 // STATUS CONSTANTS 12674 //============================================================================== 12675 /** @class */ 12676 net.user1.orbiter.Status = new Object(); 12677 /** @constant */ 12678 net.user1.orbiter.Status.ACCOUNT_EXISTS = "ACCOUNT_EXISTS"; 12679 /** @constant */ 12680 net.user1.orbiter.Status.ACCOUNT_NOT_FOUND = "ACCOUNT_NOT_FOUND"; 12681 /** @constant */ 12682 net.user1.orbiter.Status.AUTHORIZATION_REQUIRED = "AUTHORIZATION_REQUIRED"; 12683 /** @constant */ 12684 net.user1.orbiter.Status.AUTHORIZATION_FAILED = "AUTHORIZATION_FAILED"; 12685 /** @constant */ 12686 net.user1.orbiter.Status.ALREADY_ASSIGNED = "ALREADY_ASSIGNED"; 12687 /** @constant */ 12688 net.user1.orbiter.Status.ALREADY_BANNED = "ALREADY_BANNED"; 12689 /** @constant */ 12690 net.user1.orbiter.Status.ALREADY_IN_ROOM = "ALREADY_IN_ROOM"; 12691 /** @constant */ 12692 net.user1.orbiter.Status.ALREADY_LOGGED_IN = "ALREADY_LOGGED_IN"; 12693 /** @constant */ 12694 net.user1.orbiter.Status.ALREADY_OBSERVING = "ALREADY_OBSERVING"; 12695 /** @constant */ 12696 net.user1.orbiter.Status.ALREADY_SYNCHRONIZED = "ALREADY_SYNCHRONIZED"; 12697 /** @constant */ 12698 net.user1.orbiter.Status.ALREADY_WATCHING = "ALREADY_WATCHING"; 12699 /** @constant */ 12700 net.user1.orbiter.Status.ATTR_NOT_FOUND = "ATTR_NOT_FOUND"; 12701 /** @constant */ 12702 net.user1.orbiter.Status.CLIENT_NOT_FOUND = "CLIENT_NOT_FOUND"; 12703 /** @constant */ 12704 net.user1.orbiter.Status.ERROR = "ERROR"; 12705 /** @constant */ 12706 net.user1.orbiter.Status.EVALUATION_FAILED = "EVALUATION_FAILED"; 12707 /** @constant */ 12708 net.user1.orbiter.Status.DUPLICATE_VALUE = "DUPLICATE_VALUE"; 12709 /** @constant */ 12710 net.user1.orbiter.Status.IMMUTABLE = "IMMUTABLE"; 12711 /** @constant */ 12712 net.user1.orbiter.Status.INVALID_QUALIFIER = "INVALID_QUALIFIER"; 12713 /** @constant */ 12714 net.user1.orbiter.Status.NAME_NOT_FOUND = "NAME_NOT_FOUND"; 12715 /** @constant */ 12716 net.user1.orbiter.Status.NAME_EXISTS = "NAME_EXISTS"; 12717 /** @constant */ 12718 net.user1.orbiter.Status.NOT_ASSIGNED = "NOT_ASSIGNED"; 12719 /** @constant */ 12720 net.user1.orbiter.Status.NOT_BANNED = "NOT_BANNED"; 12721 /** @constant */ 12722 net.user1.orbiter.Status.NOT_IN_ROOM = "NOT_IN_ROOM"; 12723 /** @constant */ 12724 net.user1.orbiter.Status.NOT_LOGGED_IN = "NOT_LOGGED_IN"; 12725 /** @constant */ 12726 net.user1.orbiter.Status.NOT_OBSERVING = "NOT_OBSERVING"; 12727 /** @constant */ 12728 net.user1.orbiter.Status.NOT_WATCHING = "NOT_WATCHING"; 12729 /** @constant */ 12730 net.user1.orbiter.Status.PERMISSION_DENIED = "PERMISSION_DENIED"; 12731 /** @constant */ 12732 net.user1.orbiter.Status.REMOVED = "REMOVED"; 12733 /** @constant */ 12734 net.user1.orbiter.Status.ROLE_NOT_FOUND = "ROLE_NOT_FOUND"; 12735 /** @constant */ 12736 net.user1.orbiter.Status.ROOM_EXISTS = "ROOM_EXISTS"; 12737 /** @constant */ 12738 net.user1.orbiter.Status.ROOM_FULL = "ROOM_FULL"; 12739 /** @constant */ 12740 net.user1.orbiter.Status.ROOM_NOT_FOUND = "ROOM_NOT_FOUND"; 12741 /** @constant */ 12742 net.user1.orbiter.Status.SERVER_ONLY = "SERVER_ONLY"; 12743 /** @constant */ 12744 net.user1.orbiter.Status.SUCCESS = "SUCCESS"; 12745 //============================================================================== 12746 // STATUS CONSTANTS 12747 //============================================================================== 12748 /** @class */ 12749 net.user1.orbiter.SynchronizationState = new Object(); 12750 /** @constant */ 12751 net.user1.orbiter.SynchronizationState.SYNCHRONIZED = "SYNCHRONIZED"; 12752 /** @constant */ 12753 net.user1.orbiter.SynchronizationState.NOT_SYNCHRONIZED = "NOT_SYNCHRONIZED"; 12754 /** @constant */ 12755 net.user1.orbiter.SynchronizationState.SYNCHRONIZING = "SYNCHRONIZING"; 12756 //============================================================================== 12757 // CLASS DECLARATION 12758 //============================================================================== 12759 /** 12760 * @class 12761 */ 12762 net.user1.orbiter.UPCProcessingRecord = function () { 12763 /** 12764 * @field 12765 */ 12766 this.fromClientID = null; 12767 /** 12768 * @field 12769 */ 12770 this.fromUserID = null; 12771 /** 12772 * @field 12773 */ 12774 this.fromClientAddress = null; 12775 /** 12776 * @field 12777 */ 12778 this.processingStartedAt = NaN; 12779 /** 12780 * @field 12781 */ 12782 this.processingFinishedAt = NaN; 12783 /** 12784 * @field 12785 */ 12786 this.processingDuration = NaN; 12787 /** 12788 * @field 12789 */ 12790 this.queuedAt = NaN; 12791 /** 12792 * @field 12793 */ 12794 this.queueDuration = NaN; 12795 /** 12796 * @field 12797 */ 12798 this.UPCSource = null; 12799 }; 12800 12801 /** 12802 * @private 12803 */ 12804 net.user1.orbiter.UPCProcessingRecord.prototype.deserialize = function (serializedRecord) { 12805 var recordParts = []; 12806 var numSignificantSeparators = 6; 12807 var separatorIndices = []; 12808 var thisSeparatorIndex = 0; 12809 var previousSeparatorIndex = -1; 12810 12811 // Don't use split because the source might contain the record separator 12812 for (var i = 0; i < numSignificantSeparators; i++) { 12813 thisSeparatorIndex = serializedRecord.indexOf(net.user1.orbiter.Tokens.RS, previousSeparatorIndex+1); 12814 recordParts.push(serializedRecord.substring(previousSeparatorIndex+1, thisSeparatorIndex)); 12815 previousSeparatorIndex = thisSeparatorIndex; 12816 } 12817 recordParts.push(serializedRecord.substring(thisSeparatorIndex+1)); 12818 12819 this.deserializeParts(recordParts[0], 12820 recordParts[1], 12821 recordParts[2], 12822 recordParts[3], 12823 recordParts[4], 12824 recordParts[5], 12825 recordParts[6]); 12826 }; 12827 12828 /** 12829 * @private 12830 */ 12831 net.user1.orbiter.UPCProcessingRecord.prototype.deserializeParts = function (fromClientID, 12832 fromUserID, 12833 fromClientAddress, 12834 queuedAt, 12835 processingStartedAt, 12836 processingFinishedAt, 12837 source) { 12838 this.fromClientID = fromClientID; 12839 this.fromUserID = fromUserID; 12840 this.fromClientAddress = fromClientAddress; 12841 this.processingStartedAt = parseFloat(processingStartedAt); 12842 this.processingFinishedAt = parseFloat(processingFinishedAt); 12843 this.processingDuration = this.processingFinishedAt - this.processingStartedAt; 12844 this.queuedAt = parseFloat(queuedAt); 12845 this.queueDuration = this.processingStartedAt - this.queuedAt; 12846 this.UPCSource = source; 12847 var escapedCDStart = /<!\(\[CDATA\[/gi; 12848 var escapedCDEnd = /\]\]\)>/gi; 12849 this.UPCSource = this.UPCSource.replace(escapedCDStart, "<![CDATA["); 12850 this.UPCSource = this.UPCSource.replace(escapedCDEnd, "]]>"); 12851 } 12852 //============================================================================== 12853 // CLASS DECLARATION 12854 //============================================================================== 12855 /** 12856 * @class 12857 * @extends net.user1.orbiter.snapshot.Snapshot 12858 */ 12859 net.user1.orbiter.snapshot.UPCStatsSnapshot = function () { 12860 // Call superconstructor 12861 net.user1.orbiter.snapshot.Snapshot.call(this); 12862 this.totalUPCsProcessed; 12863 this.numUPCsInQueue; 12864 this.lastQueueWaitTime; 12865 this.longestUPCProcesses; 12866 this.method = net.user1.orbiter.UPC.GET_UPC_STATS_SNAPSHOT; 12867 this.hasStatus = true; 12868 }; 12869 12870 //============================================================================== 12871 // INHERITANCE 12872 //============================================================================== 12873 net.user1.utils.extend(net.user1.orbiter.snapshot.UPCStatsSnapshot, net.user1.orbiter.snapshot.Snapshot); 12874 12875 //============================================================================== 12876 // INSTANCE METHODS 12877 //============================================================================== 12878 /** 12879 * @private 12880 */ 12881 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setTotalUPCsProcessed = function (value) { 12882 this.totalUPCsProcessed = value; 12883 }; 12884 12885 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getTotalUPCsProcessed = function () { 12886 return this.totalUPCsProcessed; 12887 }; 12888 12889 /** 12890 * @private 12891 */ 12892 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setNumUPCsInQueue = function (value) { 12893 this.numUPCsInQueue = value; 12894 }; 12895 12896 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getNumUPCsInQueue = function () { 12897 return this.numUPCsInQueue; 12898 }; 12899 12900 /** 12901 * @private 12902 */ 12903 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setLastQueueWaitTime = function (value) { 12904 this.lastQueueWaitTime = value; 12905 }; 12906 12907 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getLastQueueWaitTime = function () { 12908 return this.lastQueueWaitTime; 12909 }; 12910 12911 /** 12912 * @private 12913 */ 12914 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.setLongestUPCProcesses = function (value) { 12915 this.longestUPCProcesses = value; 12916 }; 12917 12918 net.user1.orbiter.snapshot.UPCStatsSnapshot.prototype.getLongestUPCProcesses = function () { 12919 if (!this.longestUPCProcesses) { 12920 return null; 12921 } 12922 return this.longestUPCProcesses.slice(); 12923 }; 12924 //============================================================================== 12925 // CLASS DECLARATION 12926 //============================================================================== 12927 net.user1.orbiter.UpdateLevels = function () { 12928 this.restoreDefaults(); 12929 }; 12930 12931 //============================================================================== 12932 // STATIC VARIABLES 12933 //============================================================================== 12934 net.user1.orbiter.UpdateLevels.FLAG_ROOM_MESSAGES = 1; 12935 net.user1.orbiter.UpdateLevels.FLAG_SHARED_ROOM_ATTRIBUTES = 1 << 1; 12936 net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_COUNT = 1 << 2; 12937 net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_COUNT = 1 << 3; 12938 net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LIST = 1 << 4; 12939 net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LIST = 1 << 5; 12940 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_ROOM = 1 << 6; 12941 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_ROOM = 1 << 7; 12942 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_GLOBAL = 1 << 8; 12943 net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_GLOBAL = 1 << 9; 12944 net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LOGIN_LOGOFF = 1 << 10; 12945 net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LOGIN_LOGOFF = 1 << 11; 12946 net.user1.orbiter.UpdateLevels.FLAG_ALL_ROOM_ATTRIBUTES = 1 << 12; 12947 12948 //============================================================================== 12949 // INSTANCE METHODS 12950 //============================================================================== 12951 net.user1.orbiter.UpdateLevels.prototype.clearAll = function () { 12952 this.roomMessages = false; 12953 this.sharedRoomAttributes = false; 12954 this.occupantCount = false; 12955 this.observerCount = false; 12956 this.occupantList = false; 12957 this.observerList = false; 12958 this.sharedOccupantAttributesRoom = false; 12959 this.sharedOccupantAttributesGlobal = false; 12960 this.sharedObserverAttributesRoom = false; 12961 this.sharedObserverAttributesGlobal = false; 12962 this.occupantLoginLogoff = false; 12963 this.observerLoginLogoff = false; 12964 this.allRoomAttributes = false; 12965 }; 12966 12967 net.user1.orbiter.UpdateLevels.prototype.restoreDefaults = function () { 12968 this.roomMessages = true; 12969 this.sharedRoomAttributes = true; 12970 this.occupantCount = false; 12971 this.observerCount = false; 12972 this.occupantList = true; 12973 this.observerList = false; 12974 this.sharedOccupantAttributesRoom = true; 12975 this.sharedOccupantAttributesGlobal = true; 12976 this.sharedObserverAttributesRoom = false; 12977 this.sharedObserverAttributesGlobal = false; 12978 this.occupantLoginLogoff = true; 12979 this.observerLoginLogoff = false; 12980 this.allRoomAttributes = false; 12981 }; 12982 12983 net.user1.orbiter.UpdateLevels.prototype.toInt = function () { 12984 var levels = (this.roomMessages ? net.user1.orbiter.UpdateLevels.FLAG_ROOM_MESSAGES : 0) 12985 | (this.sharedRoomAttributes ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_ROOM_ATTRIBUTES : 0) 12986 | (this.occupantCount ? net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_COUNT : 0) 12987 | (this.observerCount ? net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_COUNT : 0) 12988 | (this.occupantList ? net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LIST : 0) 12989 | (this.observerList ? net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LIST : 0) 12990 | (this.sharedOccupantAttributesRoom ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_ROOM : 0) 12991 | (this.sharedOccupantAttributesGlobal ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_GLOBAL : 0) 12992 | (this.sharedObserverAttributesRoom ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_ROOM : 0) 12993 | (this.sharedObserverAttributesGlobal ? net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_GLOBAL : 0) 12994 | (this.occupantLoginLogoff ? net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LOGIN_LOGOFF : 0) 12995 | (this.observerLoginLogoff ? net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LOGIN_LOGOFF : 0) 12996 | (this.allRoomAttributes ? net.user1.orbiter.UpdateLevels.FLAG_ALL_ROOM_ATTRIBUTES : 0); 12997 12998 return levels; 12999 }; 13000 13001 net.user1.orbiter.UpdateLevels.prototype.fromInt = function (levels) { 13002 roomMessages = levels & net.user1.orbiter.UpdateLevels.FLAG_ROOM_MESSAGES; 13003 sharedRoomAttributes = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_ROOM_ATTRIBUTES; 13004 occupantCount = levels & net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_COUNT; 13005 observerCount = levels & net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_COUNT; 13006 occupantList = levels & net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LIST; 13007 observerList = levels & net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LIST; 13008 sharedOccupantAttributesRoom = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_ROOM; 13009 sharedOccupantAttributesGlobal = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OCCUPANT_ATTRIBUTES_GLOBAL; 13010 sharedObserverAttributesRoom = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_ROOM; 13011 sharedObserverAttributesGlobal = levels & net.user1.orbiter.UpdateLevels.FLAG_SHARED_OBSERVER_ATTRIBUTES_GLOBAL; 13012 occupantLoginLogoff = levels & net.user1.orbiter.UpdateLevels.FLAG_OCCUPANT_LOGIN_LOGOFF; 13013 observerLoginLogoff = levels & net.user1.orbiter.UpdateLevels.FLAG_OBSERVER_LOGIN_LOGOFF; 13014 allRoomAttributes = levels & net.user1.orbiter.UpdateLevels.FLAG_ALL_ROOM_ATTRIBUTES; 13015 }; 13016 //============================================================================== 13017 // CLASS DECLARATION 13018 //============================================================================== 13019 /** @class 13020 13021 The UserAccount class dispatches the following events: 13022 13023 <ul class="summary"> 13024 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGIN}</li> 13025 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF_RESULT}</li> 13026 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.LOGOFF}</li> 13027 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT}</li> 13028 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.CHANGE_PASSWORD}</li> 13029 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.SYNCHRONIZE}</li> 13030 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE}</li> 13031 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.OBSERVE_RESULT}</li> 13032 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING}</li> 13033 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT}</li> 13034 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT}</li> 13035 <li class="fixedFont">{@link net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT}</li> 13036 </ul> 13037 13038 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 13039 13040 @extends net.user1.events.EventDispatcher 13041 */ 13042 13043 net.user1.orbiter.UserAccount = function (userID, 13044 log, 13045 accountManager, 13046 clientManager, 13047 roomManager) { 13048 net.user1.events.EventDispatcher.call(this); 13049 13050 this.userID = userID; 13051 this.attributeManager = null; 13052 this.connectionState = 0; 13053 this.password = null; 13054 this.lastAttemptedPassword = null; 13055 this._client = null; 13056 this._accountManager = null; 13057 this._clientManager = null; 13058 this._roomManager = null; 13059 this._log = null; 13060 13061 this.setLog(log); 13062 this.setAccountManager(accountManager); 13063 this.setClientManager(clientManager); 13064 this.setRoomManager(roomManager); 13065 }; 13066 13067 //============================================================================== 13068 // INHERITANCE 13069 //============================================================================== 13070 net.user1.utils.extend(net.user1.orbiter.UserAccount, net.user1.events.EventDispatcher); 13071 13072 //============================================================================== 13073 // STATIC VARIABLES 13074 //============================================================================== 13075 /** @private */ 13076 net.user1.orbiter.UserAccount.FLAG_MODERATOR = 1 << 1; 13077 13078 //============================================================================== 13079 // DEPENDENCIES 13080 //============================================================================== 13081 13082 /** 13083 * @private 13084 */ 13085 net.user1.orbiter.UserAccount.prototype.getAttributeCollection = function () { 13086 return this.attributeManager.getAttributeCollection(); 13087 }; 13088 13089 /** 13090 * @private 13091 */ 13092 net.user1.orbiter.UserAccount.prototype.setAttributeManager = function (value) { 13093 this.attributeManager = value; 13094 }; 13095 13096 /** 13097 * @private 13098 */ 13099 net.user1.orbiter.UserAccount.prototype.getAttributeManager = function () { 13100 return this.attributeManager; 13101 }; 13102 13103 /** 13104 * @private 13105 */ 13106 net.user1.orbiter.UserAccount.prototype.getClientManager = function () { 13107 return this._clientManager; 13108 }; 13109 13110 /** 13111 * @private 13112 */ 13113 net.user1.orbiter.UserAccount.prototype.setClientManager = function (value) { 13114 this._clientManager = value; 13115 }; 13116 13117 /** 13118 * @private 13119 */ 13120 net.user1.orbiter.UserAccount.prototype.getRoomManager = function () { 13121 return this._roomManager; 13122 }; 13123 13124 /** 13125 * @private 13126 */ 13127 net.user1.orbiter.UserAccount.prototype.setRoomManager = function (value) { 13128 this._roomManager = value; 13129 }; 13130 13131 /** 13132 * @private 13133 */ 13134 net.user1.orbiter.UserAccount.prototype.getLog = function () { 13135 return this._log; 13136 }; 13137 13138 /** 13139 * @private 13140 */ 13141 net.user1.orbiter.UserAccount.prototype.setLog = function (value) { 13142 this._log = value; 13143 }; 13144 13145 /** 13146 * @private 13147 */ 13148 net.user1.orbiter.UserAccount.prototype.getAccountManager = function () { 13149 return this._accountManager; 13150 }; 13151 13152 /** 13153 * @private 13154 */ 13155 net.user1.orbiter.UserAccount.prototype.setAccountManager = function (value) { 13156 this._accountManager = value; 13157 }; 13158 13159 net.user1.orbiter.UserAccount.prototype.getClient = function () { 13160 var customClient; 13161 this.validateClientReference(); 13162 if (this._client != null) { 13163 customClient = this._client.getCustomClient(null); 13164 return customClient == null ? this._client : customClient; 13165 } else { 13166 return null; 13167 } 13168 }; 13169 13170 net.user1.orbiter.UserAccount.prototype.getInternalClient = function () { 13171 this.validateClientReference(); 13172 return this._client; 13173 } 13174 13175 /** 13176 * @private 13177 */ 13178 net.user1.orbiter.UserAccount.prototype.setClient = function (value) { 13179 if (value == null) { 13180 this._client = null; 13181 } else { 13182 if (this._client != value) { 13183 this._client = value; 13184 this._client.setAccount(this); 13185 } 13186 } 13187 }; 13188 13189 /** 13190 * @private 13191 */ 13192 net.user1.orbiter.UserAccount.prototype.validateClientReference = function () { 13193 if (this._client != null) { 13194 if (!this._client.isSelf() 13195 && !this._clientManager.isWatchingForClients() 13196 && !this._accountManager.isObservingAccount(this.getUserID()) 13197 && !this._clientManager.isObservingClient(this._client.getClientID()) 13198 && !this._roomManager.clientIsKnown(this._client.getClientID())) { 13199 this.setClient(null); 13200 } 13201 } 13202 }; 13203 13204 //============================================================================== 13205 // IS SELF 13206 //============================================================================== 13207 13208 net.user1.orbiter.UserAccount.prototype.isSelf = function () { 13209 return this._client == null ? false : this._client.isSelf(); 13210 }; 13211 13212 //============================================================================== 13213 // CONNECTION STATE 13214 //============================================================================== 13215 13216 net.user1.orbiter.UserAccount.prototype.getConnectionState = function () { 13217 if (this.getInternalClient() != null) { 13218 return net.user1.orbiter.ConnectionState.LOGGED_IN; 13219 } else if (!this._accountManager.isObservingAccount(this.getUserID())) { 13220 return net.user1.orbiter.ConnectionState.NOT_CONNECTED; 13221 } else if (this._clientManager.isWatchingForClients()) { 13222 return net.user1.orbiter.ConnectionState.NOT_CONNECTED; 13223 } else { 13224 // Not observing this user, not watching for clients, and no client means 13225 // this account's state is unknown. (This happens when watching for user 13226 // accounts). 13227 return net.user1.orbiter.ConnectionState.UNKNOWN; 13228 } 13229 }; 13230 13231 net.user1.orbiter.UserAccount.prototype.isLoggedIn = function () { 13232 return this.getConnectionState() == net.user1.orbiter.ConnectionState.LOGGED_IN; 13233 }; 13234 13235 //============================================================================== 13236 // USER ID 13237 //============================================================================== 13238 13239 net.user1.orbiter.UserAccount.prototype.getUserID = function () { 13240 return this.userID; 13241 }; 13242 13243 /** 13244 * @private 13245 */ 13246 net.user1.orbiter.UserAccount.prototype.setUserID = function (userID) { 13247 if (this.userID != userID) { 13248 this.userID = userID; 13249 } 13250 }; 13251 13252 // ============================================================================= 13253 // LOGOFF 13254 // ============================================================================= 13255 13256 net.user1.orbiter.UserAccount.prototype.logoff = function (password) { 13257 this._accountManager.logoff(this.getUserID(), password); 13258 }; 13259 13260 // ============================================================================= 13261 // CHANGE PASSWORD 13262 // ============================================================================= 13263 13264 net.user1.orbiter.UserAccount.prototype.changePassword = function (newPassword, oldPassword) { 13265 this._accountManager.changePassword(this.getUserID(), newPassword, oldPassword); 13266 }; 13267 13268 // ============================================================================= 13269 // ROLES 13270 // ============================================================================= 13271 13272 net.user1.orbiter.UserAccount.prototype.addRole = function (role) { 13273 this._accountManager.addRole(this.getUserID(), role); 13274 }; 13275 13276 net.user1.orbiter.UserAccount.prototype.removeRole = function (userID, role) { 13277 this._accountManager.removeRole(this.getUserID(), role); 13278 }; 13279 13280 net.user1.orbiter.UserAccount.prototype.isModerator = function () { 13281 var rolesAttr = this.getAttribute(net.user1.orbiter.Tokens.ROLES_ATTR); 13282 var roles; 13283 if (rolesAttr != null) { 13284 return (parseInt(rolesAttr) & UserAccount.FLAG_MODERATOR) > 0; 13285 } else { 13286 this.getLog().warn(this.toString() + " Could not determine moderator status because the account is not synchronized."); 13287 return false; 13288 } 13289 }; 13290 13291 // ============================================================================= 13292 // LOGIN/LOGOFF TASKS 13293 // ============================================================================= 13294 13295 /** 13296 * @private 13297 */ 13298 net.user1.orbiter.UserAccount.prototype.doLoginTasks = function () { 13299 this.fireLogin(); 13300 }; 13301 13302 /** 13303 * @private 13304 */ 13305 net.user1.orbiter.UserAccount.prototype.doLogoffTasks = function () { 13306 this.setClient(null); 13307 this.fireLogoff(); 13308 }; 13309 13310 // ============================================================================= 13311 // OBSERVATION 13312 // ============================================================================= 13313 13314 net.user1.orbiter.UserAccount.prototype.observe = function () { 13315 this._accountManager.observeAccount(this.getUserID()); 13316 }; 13317 13318 net.user1.orbiter.UserAccount.prototype.stopObserving = function () { 13319 this._accountManager.stopObservingAccount(this.getUserID()); 13320 }; 13321 13322 // ============================================================================= 13323 // ATTRIBUTES: PUBLIC API 13324 // ============================================================================= 13325 13326 net.user1.orbiter.UserAccount.prototype.setAttribute = function (attrName, 13327 attrValue, 13328 attrScope, 13329 isShared, 13330 evaluate) { 13331 // Create an integer to hold the attribute options 13332 var attrOptions = net.user1.orbiter.AttributeOptions.FLAG_PERSISTENT 13333 | (isShared ? net.user1.orbiter.AttributeOptions.FLAG_SHARED : 0) 13334 | (evaluate ? net.user1.orbiter.AttributeOptions.FLAG_EVALUATE : 0); 13335 13336 // Set the attribute on the server. 13337 this.attributeManager.setAttribute(new net.user1.orbiter.upc.SetClientAttr(attrName, attrValue, attrOptions, attrScope, null, this.getUserID())); 13338 }; 13339 13340 net.user1.orbiter.UserAccount.prototype.deleteAttribute = function (attrName, attrScope) { 13341 var deleteRequest = new net.user1.orbiter.upc.RemoveClientAttr(null, this.getUserID(), attrName, attrScope); 13342 this.attributeManager.deleteAttribute(deleteRequest); 13343 }; 13344 13345 net.user1.orbiter.UserAccount.prototype.getAttribute = function (attrName, attrScope) { 13346 return this.attributeManager.getAttribute(attrName, attrScope); 13347 }; 13348 13349 net.user1.orbiter.UserAccount.prototype.getAttributes = function () { 13350 return this.attributeManager.getAttributes(); 13351 }; 13352 13353 net.user1.orbiter.UserAccount.prototype.getAttributesByScope = function (scope) { 13354 return this.attributeManager.getAttributesByScope(scope); 13355 }; 13356 13357 //============================================================================== 13358 // TOSTRING 13359 //============================================================================== 13360 13361 net.user1.orbiter.UserAccount.prototype.toString = function () { 13362 return "[USER_ACCOUNT userid: " + this.getUserID() + ", clientid: " + (this._client == null ? "" : this._client.getClientID()) + "]"; 13363 }; 13364 13365 //============================================================================== 13366 // EVENT DISPATCHING 13367 //============================================================================== 13368 13369 /** 13370 * @private 13371 */ 13372 net.user1.orbiter.UserAccount.prototype.fireLogin = function () { 13373 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGIN, 13374 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13375 this.dispatchEvent(e); 13376 }; 13377 13378 /** 13379 * @private 13380 */ 13381 net.user1.orbiter.UserAccount.prototype.fireLogoffResult = function (status) { 13382 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF_RESULT, 13383 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13384 this.dispatchEvent(e); 13385 }; 13386 13387 /** 13388 * @private 13389 */ 13390 net.user1.orbiter.UserAccount.prototype.fireLogoff = function () { 13391 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.LOGOFF, 13392 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13393 this.dispatchEvent(e); 13394 }; 13395 13396 /** 13397 * @private 13398 */ 13399 net.user1.orbiter.UserAccount.prototype.fireChangePasswordResult = function (status) { 13400 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD_RESULT, 13401 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13402 this.dispatchEvent(e); 13403 }; 13404 13405 /** 13406 * @private 13407 */ 13408 net.user1.orbiter.UserAccount.prototype.fireChangePassword = function () { 13409 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.CHANGE_PASSWORD, 13410 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13411 this.dispatchEvent(e); 13412 }; 13413 13414 /** 13415 * @private 13416 */ 13417 net.user1.orbiter.UserAccount.prototype.fireSynchronize = function () { 13418 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.SYNCHRONIZE, 13419 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13420 this.dispatchEvent(e); 13421 }; 13422 13423 /** 13424 * @private 13425 */ 13426 net.user1.orbiter.UserAccount.prototype.fireObserve = function () { 13427 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE, 13428 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13429 this.dispatchEvent(e); 13430 }; 13431 13432 /** 13433 * @private 13434 */ 13435 net.user1.orbiter.UserAccount.prototype.fireObserveResult = function (status) { 13436 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.OBSERVE_RESULT, 13437 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13438 this.dispatchEvent(e); 13439 }; 13440 13441 /** 13442 * @private 13443 */ 13444 net.user1.orbiter.UserAccount.prototype.fireStopObserving = function () { 13445 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING, 13446 net.user1.orbiter.Status.SUCCESS, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13447 this.dispatchEvent(e); 13448 }; 13449 13450 /** 13451 * @private 13452 */ 13453 net.user1.orbiter.UserAccount.prototype.fireStopObservingResult = function (status) { 13454 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.STOP_OBSERVING_RESULT, 13455 status, this.getUserID(), (this._client == null ? null : this._client.getClientID())); 13456 this.dispatchEvent(e); 13457 }; 13458 13459 /** 13460 * @private 13461 */ 13462 net.user1.orbiter.UserAccount.prototype.fireAddRoleResult = function (role, status) { 13463 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.ADD_ROLE_RESULT, 13464 status, this.getUserID(), 13465 (this._client == null ? null : this._client.getClientID()), role); 13466 this.dispatchEvent(e); 13467 } 13468 13469 /** 13470 * @private 13471 */ 13472 net.user1.orbiter.UserAccount.prototype.fireRemoveRoleResult = function (role, status) { 13473 var e = new net.user1.orbiter.AccountEvent(net.user1.orbiter.AccountEvent.REMOVE_ROLE_RESULT, 13474 status, this.getUserID(), 13475 (this._client == null ? null : this._client.getClientID()), role); 13476 this.dispatchEvent(e); 13477 } 13478 13479 13480 13481 13482 13483 13484 13485 13486 13487 13488 13489 13490 13491 //============================================================================== 13492 // VALIDATION UTILITIES 13493 //============================================================================== 13494 net.user1.orbiter.Validator = new Object(); 13495 13496 net.user1.orbiter.Validator.isValidRoomID = function (value) { 13497 // Can't be null, nor the empty string 13498 if (value == null || value == "") { 13499 return false; 13500 } 13501 // Can't contain "." 13502 if (value.indexOf(".") != -1) { 13503 return false; 13504 } 13505 // Can't contain RS 13506 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13507 return false; 13508 } 13509 // Can't contain WILDCARD 13510 if (value.indexOf(net.user1.orbiter.Tokens.WILDCARD) != -1) { 13511 return false; 13512 } 13513 13514 return true; 13515 }; 13516 13517 net.user1.orbiter.Validator.isValidRoomQualifier = function (value) { 13518 if (value == null || value == "") { 13519 return false; 13520 } 13521 // "*" is valid (it means the unnamed qualifier) 13522 if (value == "*") { 13523 return true; 13524 } 13525 13526 // Can't contain RS 13527 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13528 return false; 13529 } 13530 // Can't contain WILDCARD 13531 if (value.indexOf(net.user1.orbiter.Tokens.WILDCARD) != -1) { 13532 return false; 13533 } 13534 13535 return true; 13536 }; 13537 13538 net.user1.orbiter.Validator.isValidResolvedRoomID = function (value) { 13539 // Can't be null, nor the empty string 13540 if (value == null || value == "") { 13541 return false; 13542 } 13543 13544 // Can't contain RS 13545 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13546 return false; 13547 } 13548 // Can't contain WILDCARD 13549 if (value.indexOf(net.user1.orbiter.Tokens.WILDCARD) != -1) { 13550 return false; 13551 } 13552 13553 return true; 13554 }; 13555 13556 net.user1.orbiter.Validator.isValidAttributeName = function (value) { 13557 // Can't be empty 13558 if (value == "" || value == null) { 13559 return false; 13560 } 13561 13562 // Can't contain RS 13563 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13564 return false; 13565 } 13566 13567 return true; 13568 }; 13569 13570 net.user1.orbiter.Validator.isValidAttributeValue = function (value) { 13571 // Can't contain RS 13572 if (typeof value != "string") { 13573 // Non-string attribute values are coerced to strings at send time 13574 value = value.toString(); 13575 } 13576 if (value.indexOf(net.user1.orbiter.Tokens.RS) == -1) { 13577 return true; 13578 } else { 13579 return false; 13580 } 13581 }; 13582 13583 net.user1.orbiter.Validator.isValidAttributeScope = function (value) { 13584 // Can't contain RS 13585 if (value != null) { 13586 return this.isValidResolvedRoomID(value); 13587 } else { 13588 return true; 13589 } 13590 }; 13591 13592 net.user1.orbiter.Validator.isValidModuleName = function (value) { 13593 // Can't be empty (can be null) 13594 if (value == "") { 13595 return false; 13596 } 13597 13598 // Can't contain RS 13599 if (value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13600 return false; 13601 } 13602 13603 return true; 13604 }; 13605 13606 net.user1.orbiter.Validator.isValidPassword = function (value) { 13607 // Can't contain RS 13608 if (value != null && value.indexOf(net.user1.orbiter.Tokens.RS) != -1) { 13609 return false; 13610 } 13611 13612 return true; 13613 }; 13614 //============================================================================== 13615 // CLASS DECLARATION 13616 //============================================================================== 13617 /** @class 13618 * The Orbiter class is the root class of every Orbiter application. 13619 * It provides basic tools for connecting to Union server, and gives 13620 * the application access to the core Orbiter system modules. 13621 * Orbiter dispatches the following events: 13622 13623 <ul class="summary"> 13624 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.READY}</li> 13625 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.CLOSE}</li> 13626 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED}</li> 13627 <li class="fixedFont">{@link net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE}</li> 13628 </ul> 13629 13630 * To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 13631 * 13632 * @param configURL The URL of a connection-configuration file. When the file 13633 * finishes loading, the Orbiter client automatically attempts to connect to 13634 * Union Server at the specified address(es). Note that the configuration file 13635 * need not be loaded at construction time; it can be loaded later via Orbiter's 13636 * loadConfig() method. For configuration file details, see loadConfig(). 13637 * 13638 * @param traceLogMessages A flag indicating whether to send log messages to the 13639 * JavaScript output console. Applies to environments that support the 13640 * console.log() function only. 13641 * 13642 * @extends net.user1.events.EventDispatcher 13643 */ 13644 net.user1.orbiter.Orbiter = function (configURL, 13645 traceLogMessages) { 13646 // Call superconstructor 13647 net.user1.events.EventDispatcher.call(this); 13648 13649 // Initialization. For non-browser environments, set window to null. 13650 this.window = typeof window == "undefined" ? null : window; 13651 13652 traceLogMessages = traceLogMessages == null ? true : traceLogMessages; 13653 13654 this.useSecureConnect = false; 13655 this.statistics = null; 13656 this.sessionID = null; 13657 13658 // Initialize system versions 13659 this.system = new net.user1.orbiter.System(this.window); 13660 13661 // Set up the this.log. 13662 this.log = new net.user1.logger.Logger(); 13663 13664 // Output host version information. 13665 if (typeof navigator != "undefined") { 13666 this.log.info("User Agent: " + navigator.userAgent + " " + navigator.platform); 13667 } 13668 this.log.info("Union Client Version: " + this.system.getClientType() + " " + this.system.getClientVersion().toStringVerbose()); 13669 this.log.info("Client UPC Protocol Version: " + this.system.getUPCVersion().toString()); 13670 this.consoleLogger = null; 13671 13672 // Set up the connection manager. 13673 this.connectionMan = new net.user1.orbiter.ConnectionManager(this); 13674 13675 // Set up the room manager. 13676 this.roomMan = new net.user1.orbiter.RoomManager(this); 13677 13678 // Set up the message manager. 13679 this.messageMan = new net.user1.orbiter.MessageManager(this.log, this.connectionMan); 13680 13681 // Set up the server 13682 this.server = new net.user1.orbiter.Server(this); 13683 13684 // Make the account manager. 13685 this.accountMan = new net.user1.orbiter.AccountManager(this.log); 13686 13687 // Set up the client manager. 13688 this.clientMan = new net.user1.orbiter.ClientManager(this.roomMan, this.accountMan, this.connectionMan, this.messageMan, this.server, this.log); 13689 13690 // Set up the account manager. 13691 this.accountMan.setClientManager(this.clientMan); 13692 this.accountMan.setMessageManager(this.messageMan); 13693 this.accountMan.setRoomManager(this.roomMan); 13694 13695 // Set up the snapshot manager. 13696 this.snapshotMan = new net.user1.orbiter.SnapshotManager(this.messageMan); 13697 13698 // Set up the core message listener 13699 this.coreMsgListener = new net.user1.orbiter.CoreMessageListener(this); 13700 13701 // Log the core Reactor events 13702 this.coreEventLogger = new net.user1.orbiter.CoreEventLogger(this.log, this.connectionMan, this.roomMan, 13703 this.accountMan, this.server, this.clientMan, 13704 this); 13705 13706 // Register for ConnectionManager events. 13707 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.READY, 13708 this.readyListener, this); 13709 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.CONNECT_FAILURE, 13710 this.connectFailureListener, this); 13711 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.DISCONNECT, 13712 this.disconnectListener, this); 13713 13714 // Set up the connection monitor 13715 this.connectionMonitor = new net.user1.orbiter.ConnectionMonitor(this); 13716 this.connectionMonitor.restoreDefaults(); 13717 13718 // Register to be notified when a new connection is about to be opened 13719 this.connectionMan.addEventListener(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 13720 this.selectConnectionListener, this); 13721 13722 // Enable HTTP failover connections 13723 this.httpFailoverEnabled = true; 13724 13725 if (traceLogMessages) { 13726 this.enableConsole(); 13727 } 13728 13729 // If the Reactor wasn't constructed with a config argument... 13730 if (configURL == null || configURL == "") { 13731 this.log.info("[ORBITER] Initialization complete."); 13732 } else { 13733 // ...otherwise, retrieve system settings from specified config file. 13734 this.loadConfig(configURL); 13735 } 13736 }; 13737 13738 //============================================================================== 13739 // INHERITANCE 13740 //============================================================================== 13741 net.user1.utils.extend(net.user1.orbiter.Orbiter, net.user1.events.EventDispatcher); 13742 13743 //============================================================================== 13744 // XML CONFIG METHODS 13745 //============================================================================== 13746 13747 /** 13748 * Loads the client-configuration file. When the file load completes, 13749 * Orbiter automatically attempts to connect to Union Server using 13750 * the settings specified by the configuration file. 13751 * 13752 * The configuration file has the following format: 13753 * 13754 * <pre> 13755 * <?xml version="1.0"?> 13756 * <config> 13757 * <connections> 13758 * <connection host="hostNameOrIP1" port="portNumber1" type="connectionType1" senddelay="milliseconds1" secure="false" /> 13759 * <connection host="hostNameOrIP2" port="portNumber2" type="connectionType2" senddelay="milliseconds2" secure="false" /> 13760 * ... 13761 * <connection host="hostNameOrIPn" port="portNumbern" type="connectionTypen" senddelay="millisecondsn" secure="false" /> 13762 * </connections> 13763 * <autoreconnectfrequency>frequency</autoreconnectfrequency> 13764 * <connectiontimeout>duration</connectiontimeout> 13765 * <heartbeatfrequency>frequency</heartbeatfrequency> 13766 * <readytimeout>timeout</readytimeout> 13767 * <loglevel>level</loglevel> 13768 * </config> 13769 * </pre> 13770 * 13771 * When the <code>secure</code> attribute is true, communication is 13772 * conducted over WSS or HTTPS using the environment's TLS implementation. 13773 */ 13774 net.user1.orbiter.Orbiter.prototype.loadConfig = function (configURL) { 13775 this.log.info("[ORBITER] Loading config from " + configURL +"."); 13776 var request = new XMLHttpRequest(); 13777 var self = this; 13778 13779 request.onerror = function () { 13780 self.configErrorListener(); 13781 }; 13782 13783 request.onreadystatechange = function (state) { 13784 if (request.readyState == 4) { 13785 self.configLoadCompleteListener(request); 13786 } 13787 } 13788 request.open("GET", configURL); 13789 request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); 13790 request.send(null); 13791 }; 13792 13793 /** 13794 * @private 13795 */ 13796 net.user1.orbiter.Orbiter.prototype.getTextForNode = function (tree, tagname) { 13797 var nodes = tree.getElementsByTagName(tagname); 13798 var node; 13799 if (nodes.length > 0) { 13800 node = nodes[0]; 13801 } 13802 13803 if (node != null 13804 && node.firstChild != null 13805 && node.firstChild.nodeType == 3 13806 && node.firstChild.nodeValue.length > 0) { 13807 return node.firstChild.nodeValue; 13808 } else { 13809 return null; 13810 } 13811 }; 13812 13813 13814 /** 13815 * @private 13816 */ 13817 net.user1.orbiter.Orbiter.prototype.configLoadCompleteListener = function (request) { 13818 var config = request.responseXML; 13819 if ((request.status != 200 && request.status != 0) || config == null) { 13820 this.log.error("[ORBITER] Configuration file failed to load."); 13821 return; 13822 } 13823 this.log.error("[ORBITER] Configuration file loaded."); 13824 try { 13825 var loglevel = this.getTextForNode(config, "logLevel"); 13826 if (loglevel != null) { 13827 this.log.setLevel(loglevel); 13828 } 13829 13830 var autoreconnectfrequencyNodes = config.getElementsByTagName("autoreconnectfrequency"); 13831 var autoreconnectfrequencyNode = null; 13832 if (autoreconnectfrequencyNodes.length == 1) { 13833 autoreconnectfrequencyNode = autoreconnectfrequencyNodes[0]; 13834 var nodetext = this.getTextForNode(config, "autoreconnectfrequency"); 13835 if (nodetext != null && !isNaN(parseInt(nodetext))) { 13836 this.connectionMonitor.setAutoReconnectFrequency( 13837 parseInt(nodetext), 13838 parseInt(nodetext), 13839 autoreconnectfrequencyNode.getAttribute("delayfirstattempt") == null ? false : 13840 autoreconnectfrequencyNode.getAttribute("delayfirstattempt").toLowerCase() == "true" 13841 ); 13842 } else { 13843 this.connectionMonitor.setAutoReconnectFrequency( 13844 parseInt(autoreconnectfrequencyNode.getAttribute("minms")), 13845 parseInt(autoreconnectfrequencyNode.getAttribute("maxms")), 13846 autoreconnectfrequencyNode.getAttribute("delayfirstattempt") == null ? false : 13847 autoreconnectfrequencyNode.getAttribute("delayfirstattempt").toLowerCase() == "true" 13848 ); 13849 } 13850 if (autoreconnectfrequencyNode.getAttribute("maxattempts") != null 13851 && autoreconnectfrequencyNode.getAttribute("maxattempts").length > 0) { 13852 this.connectionMonitor.setAutoReconnectAttemptLimit( 13853 parseInt(autoreconnectfrequencyNode.getAttribute("maxattempts")) 13854 ); 13855 } 13856 } 13857 13858 var connectiontimeout = this.getTextForNode(config, "connectionTimeout"); 13859 if (connectiontimeout != null) { 13860 this.connectionMonitor.setConnectionTimeout(parseInt(connectiontimeout)); 13861 } 13862 13863 var heartbeatfrequency = this.getTextForNode(config, "heartbeatFrequency"); 13864 if (heartbeatfrequency != null) { 13865 this.connectionMonitor.setHeartbeatFrequency(parseInt(heartbeatfrequency)); 13866 } 13867 13868 var readytimeout = this.getTextForNode(config, "readyTimeout"); 13869 if (readytimeout != null) { 13870 this.connectionMan.setReadyTimeout(parseInt(readytimeout)); 13871 } 13872 13873 var connections = config.getElementsByTagName("connection"); 13874 if (connections.length == 0) { 13875 this.log.error("[ORBITER] No connections specified in Orbiter configuration file."); 13876 return; 13877 } 13878 13879 // Make connections 13880 var connection; 13881 var host; 13882 var port; 13883 var type; 13884 var secure; 13885 var sendDelay; 13886 13887 for (var i = 0; i < connections.length; i++) { 13888 connection = connections[i]; 13889 host = connection.getAttribute("host"); 13890 port = connection.getAttribute("port"); 13891 type = connection.getAttribute("type"); 13892 if (type != null) { 13893 type = type.toUpperCase(); 13894 } 13895 secure = connection.getAttribute("secure"); 13896 sendDelay = connection.getAttribute("senddelay"); 13897 13898 switch (type) { 13899 // No type means make a socket connection with an http backup 13900 case null: 13901 if (secure === "true") { 13902 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET, -1); 13903 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP, sendDelay); 13904 } else { 13905 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.WEBSOCKET, -1); 13906 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.HTTP, sendDelay); 13907 } 13908 break; 13909 13910 case net.user1.orbiter.ConnectionType.WEBSOCKET: 13911 if (secure === "true") { 13912 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET, -1); 13913 } else { 13914 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.WEBSOCKET, -1); 13915 } 13916 break; 13917 13918 case net.user1.orbiter.ConnectionType.HTTP: 13919 if (secure === "true") { 13920 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP, sendDelay); 13921 } else { 13922 this.buildConnection(host, port, net.user1.orbiter.ConnectionType.HTTP, sendDelay); 13923 } 13924 break; 13925 13926 default: 13927 this.log.error("[ORBITER] Unrecognized connection type in Orbiter configuration file: [" + type + "]. Connection ignored."); 13928 } 13929 } 13930 } catch (error) { 13931 this.log.error("[ORBITER] Error parsing connection in Orbiter configuration file: \n" 13932 + request.responseText + "\n" + error.toString()); 13933 } 13934 13935 this.connect(); 13936 }; 13937 13938 /** @private */ 13939 net.user1.orbiter.Orbiter.prototype.buildConnection = function (host, port, type, sendDelay) { 13940 var connection; 13941 13942 switch (type) { 13943 case net.user1.orbiter.ConnectionType.HTTP: 13944 if (this.system.hasHTTPDirectConnection()) { 13945 connection = new net.user1.orbiter.HTTPDirectConnection(); 13946 } else { 13947 connection = new net.user1.orbiter.HTTPIFrameConnection(); 13948 } 13949 break; 13950 13951 case net.user1.orbiter.ConnectionType.SECURE_HTTP: 13952 if (this.system.hasHTTPDirectConnection()) { 13953 connection = new net.user1.orbiter.SecureHTTPDirectConnection(); 13954 } else { 13955 connection = new net.user1.orbiter.SecureHTTPIFrameConnection(); 13956 } 13957 break; 13958 13959 case net.user1.orbiter.ConnectionType.WEBSOCKET: 13960 connection = new net.user1.orbiter.WebSocketConnection(); 13961 break; 13962 13963 case net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET: 13964 connection = new net.user1.orbiter.SecureWebSocketConnection(); 13965 break; 13966 13967 default: 13968 throw new Error("[ORBITER] Error at buildConnection(). Invalid type specified: [" + type + "]"); 13969 } 13970 13971 try { 13972 connection.setServer(host, port); 13973 } catch (e) { 13974 this.log.error("[CONNECTION] " + connection.toString() + " " + e); 13975 } finally { 13976 this.connectionMan.addConnection(connection); 13977 if (connection instanceof net.user1.orbiter.HTTPConnection) { 13978 // Set delay after adding connection so the connection object has 13979 // access to this Orbiter object 13980 if (sendDelay != null && sendDelay != "") { 13981 connection.setSendDelay(sendDelay); 13982 } 13983 } 13984 } 13985 }; 13986 13987 /** 13988 * @private 13989 */ 13990 net.user1.orbiter.Orbiter.prototype.configErrorListener = function (e) { 13991 this.log.fatal("[ORBITER] Configuration file could not be loaded."); 13992 }; 13993 13994 //============================================================================== 13995 // CONNECTION METHODS 13996 //============================================================================== 13997 13998 /** 13999 * <p> 14000 * The connect() method attempts to connect to Union Server at the specified 14001 * host and ports. If no host and ports are specified, Orbiter attempts to 14002 * connect using the ConnectionManager's current list of hosts and ports. 14003 * </p> 14004 * 14005 * @param host 14006 * @param port1 14007 * @param port2 14008 * @param ... 14009 * @param portn 14010 */ 14011 net.user1.orbiter.Orbiter.prototype.connect = function (host) { 14012 this.useSecureConnect = false; 14013 this.doConnect.apply(this, arguments); 14014 }; 14015 14016 /** 14017 * <p> 14018 * The secureConnect() method is identical to the connect() method, except that 14019 * it uses an encrypted connection (TLS or SSL) rather than an 14020 * unencrypted connection. Before secureConnect() can be used, Union Server 14021 * must be configured to accept client communications over a secure gateway, 14022 * which includes the installation of a server-side security certificate. For 14023 * instructions on configuring Union Server for secure communications, see 14024 * Union Server's documentation at http://unionplatform.com. 14025 * </p> 14026 * 14027 * @see net.user1.orbiter.Orbiter#connect 14028 */ 14029 net.user1.orbiter.Orbiter.prototype.secureConnect = function (host) { 14030 this.useSecureConnect = true; 14031 this.doConnect.apply(this, arguments); 14032 }; 14033 14034 /** 14035 * @private 14036 */ 14037 net.user1.orbiter.Orbiter.prototype.doConnect = function (host) { 14038 var ports = Array.prototype.slice.call(arguments).slice(1); 14039 if (host != null) { 14040 this.setServer.apply(this, [host].concat(ports)); 14041 } 14042 this.log.info("[ORBITER] Connecting to Union..."); 14043 this.connectionMan.connect(); 14044 }; 14045 14046 net.user1.orbiter.Orbiter.prototype.disconnect = function () { 14047 this.connectionMan.disconnect(); 14048 }; 14049 14050 net.user1.orbiter.Orbiter.prototype.setServer = function (host) { 14051 var ports = Array.prototype.slice.call(arguments).slice(1); 14052 if (host != null && ports.length > 0) { 14053 if (this.connectionMan.getConnections().length > 0) { 14054 this.connectionMan.removeAllConnections(); 14055 } 14056 // Where possible, create WebSocket connections for the specified 14057 // host and its ports. 14058 var connectionType; 14059 if (this.system.hasWebSocket()) { 14060 for (var i = 1; i < arguments.length; i++) { 14061 connectionType = this.useSecureConnect 14062 ? net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET 14063 : net.user1.orbiter.ConnectionType.WEBSOCKET; 14064 this.buildConnection(host, arguments[i], connectionType, -1); 14065 } 14066 } else { 14067 this.log.info("[ORBITER] WebSocket not found in host environment. Trying HTTP."); 14068 } 14069 // Next, if failover is enabled or WebSocket is not supported, create HTTPConnections 14070 if (this.isHTTPFailoverEnabled() || !this.system.hasWebSocket()) { 14071 for (i = 1; i < arguments.length; i++) { 14072 connectionType = this.useSecureConnect 14073 ? net.user1.orbiter.ConnectionType.SECURE_HTTP 14074 : net.user1.orbiter.ConnectionType.HTTP; 14075 this.buildConnection(host, 14076 arguments[i], 14077 connectionType, 14078 net.user1.orbiter.HTTPConnection.DEFAULT_SEND_DELAY); 14079 } 14080 } 14081 } else { 14082 this.log.error("[ORBITER] setServer() failed. Invalid host [" + host + "] or port [" + ports.join(",") + "]."); 14083 } 14084 }; 14085 14086 net.user1.orbiter.Orbiter.prototype.isReady = function () { 14087 return this.connectionMan.isReady(); 14088 }; 14089 14090 //============================================================================== 14091 // HTTP FAILOVER CONFIGURATION 14092 //============================================================================== 14093 14094 net.user1.orbiter.Orbiter.prototype.enableHTTPFailover = function () { 14095 this.httpFailoverEnabled = true; 14096 }; 14097 14098 net.user1.orbiter.Orbiter.prototype.disableHTTPFailover = function () { 14099 this.httpFailoverEnabled = false; 14100 }; 14101 14102 net.user1.orbiter.Orbiter.prototype.isHTTPFailoverEnabled = function () { 14103 return this.httpFailoverEnabled; 14104 }; 14105 14106 //============================================================================== 14107 // STATISTICS MANAGEMENT 14108 //============================================================================== 14109 14110 net.user1.orbiter.Orbiter.prototype.enableStatistics = function () { 14111 if (this.statistics == null) { 14112 this.statistics = new net.user1.orbiter.Statistics(this); 14113 } 14114 } 14115 14116 net.user1.orbiter.Orbiter.prototype.disableStatistics = function () { 14117 if (this.statistics != null) { 14118 this.statistics.stop(); 14119 } 14120 } 14121 14122 net.user1.orbiter.Orbiter.prototype.getStatistics = function () { 14123 return this.statistics; 14124 } 14125 14126 //============================================================================== 14127 // MANAGER AND SERVICE RETRIEVAL 14128 //============================================================================== 14129 net.user1.orbiter.Orbiter.prototype.getSystem = function () { 14130 return this.system; 14131 }; 14132 14133 net.user1.orbiter.Orbiter.prototype.getRoomManager = function () { 14134 return this.roomMan; 14135 }; 14136 14137 net.user1.orbiter.Orbiter.prototype.getConnectionManager = function () { 14138 return this.connectionMan; 14139 }; 14140 14141 net.user1.orbiter.Orbiter.prototype.getClientManager = function () { 14142 return this.clientMan; 14143 }; 14144 14145 net.user1.orbiter.Orbiter.prototype.getAccountManager = function () { 14146 return this.accountMan; 14147 }; 14148 14149 net.user1.orbiter.Orbiter.prototype.getMessageManager = function () { 14150 return this.messageMan; 14151 }; 14152 14153 net.user1.orbiter.Orbiter.prototype.getServer = function () { 14154 return this.server; 14155 }; 14156 14157 net.user1.orbiter.Orbiter.prototype.getConnectionMonitor = function () { 14158 return this.connectionMonitor; 14159 }; 14160 14161 /** 14162 * @private 14163 */ 14164 net.user1.orbiter.Orbiter.prototype.getCoreMessageListener = function () { 14165 return this.coreMsgListener; 14166 } 14167 14168 net.user1.orbiter.Orbiter.prototype.getLog = function () { 14169 return this.log; 14170 } 14171 14172 net.user1.orbiter.Orbiter.prototype.self = function () { 14173 var customGlobalClient; 14174 14175 if (this.clientMan == null || !this.isReady()) { 14176 return null; 14177 } else { 14178 customGlobalClient = this.clientMan.self().getCustomClient(null); 14179 if (customGlobalClient != null) { 14180 return customGlobalClient; 14181 } else { 14182 return this.clientMan.self(); 14183 } 14184 } 14185 }; 14186 14187 /** 14188 * @private 14189 */ 14190 net.user1.orbiter.Orbiter.prototype.getSnapshotManager = function () { 14191 return this.snapshotMan; 14192 }; 14193 14194 //============================================================================== 14195 // SNAPSHOT API 14196 //============================================================================== 14197 14198 net.user1.orbiter.Orbiter.prototype.updateSnapshot = function (snapshot) { 14199 this.snapshotMan.updateSnapshot(snapshot); 14200 } 14201 14202 //============================================================================== 14203 // CONNECTION EVENT LISTENERS 14204 //============================================================================== 14205 14206 /** 14207 * @private 14208 * Responds to a connection failure. 14209 */ 14210 net.user1.orbiter.Orbiter.prototype.connectFailureListener = function (e) { 14211 // Tell listeners that the connection is now closed. 14212 this.fireClose(); 14213 }; 14214 14215 /** 14216 * @private 14217 * Triggers a CLOSE event when the connection is lost. 14218 */ 14219 net.user1.orbiter.Orbiter.prototype.disconnectListener = function (e) { 14220 this.accountMan.cleanup(); 14221 this.roomMan.cleanup(); 14222 this.clientMan.cleanup(); 14223 this.server.cleanup(); 14224 this.fireClose(); 14225 }; 14226 14227 /** 14228 * @private 14229 * Triggers a READY event when the connection is ready. 14230 */ 14231 net.user1.orbiter.Orbiter.prototype.readyListener = function (e) { 14232 this.fireReady(); 14233 }; 14234 14235 net.user1.orbiter.Orbiter.prototype.selectConnectionListener = function (e) { 14236 this.messageMan.addMessageListener(net.user1.orbiter.UPC.SERVER_HELLO, this.u66, this); 14237 this.messageMan.addMessageListener(net.user1.orbiter.UPC.CONNECTION_REFUSED, this.u164, this); 14238 } 14239 14240 //============================================================================== 14241 // CLIENT ID 14242 //============================================================================== 14243 net.user1.orbiter.Orbiter.prototype.getClientID = function () { 14244 return this.self() ? this.self().getClientID() : ""; 14245 }; 14246 14247 //============================================================================== 14248 // EVENT DISPATCHING 14249 //============================================================================== 14250 14251 /** 14252 * @private 14253 * Notifies listeners that this Orbiter object's connection to the server 14254 * was lost or could not be established. 14255 */ 14256 net.user1.orbiter.Orbiter.prototype.fireClose = function () { 14257 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.CLOSE)); 14258 }; 14259 14260 /** 14261 * @private 14262 * Notifies listeners that the Orbiter is fully initialized and 14263 * ready to transact with the server. 14264 */ 14265 net.user1.orbiter.Orbiter.prototype.fireReady = function () { 14266 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.READY)); 14267 }; 14268 14269 /** 14270 * @private 14271 * Notifies listeners that the Orbiter is fully initialized and 14272 * ready to transact with the server. 14273 */ 14274 net.user1.orbiter.Orbiter.prototype.fireProtocolIncompatible = function (serverUPCVersion) { 14275 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.PROTOCOL_INCOMPATIBLE, 14276 serverUPCVersion)); 14277 }; 14278 14279 /** 14280 * @private 14281 * Notifies listeners that the server refused the connection. 14282 */ 14283 net.user1.orbiter.Orbiter.prototype.dispatchConnectRefused = function (refusal) { 14284 this.dispatchEvent(new net.user1.orbiter.OrbiterEvent(net.user1.orbiter.OrbiterEvent.CONNECT_REFUSED, 14285 null, refusal)); 14286 }; 14287 14288 //============================================================================== 14289 // UPC Listeners 14290 //============================================================================== 14291 14292 /** 14293 * @private 14294 * SERVER_HELLO 14295 */ 14296 net.user1.orbiter.Orbiter.prototype.u66 = function (serverVersion, 14297 sessionID, 14298 serverUPCVersionString, 14299 protocolCompatible, 14300 affinityAddress, 14301 affinityDuration) { 14302 var serverUPCVersion = new net.user1.orbiter.VersionNumber(); 14303 serverUPCVersion.fromVersionString(serverUPCVersionString); 14304 if (protocolCompatible == "false") { 14305 this.fireProtocolIncompatible(serverUPCVersion); 14306 } 14307 }; 14308 14309 /** 14310 * @private 14311 * CONNECTION_REFUSED 14312 */ 14313 net.user1.orbiter.Orbiter.prototype.u164 = function (reason, description) { 14314 this.connectionMonitor.setAutoReconnectFrequency(-1); 14315 this.dispatchConnectRefused(new net.user1.orbiter.ConnectionRefusal(reason, description)); 14316 }; 14317 14318 //============================================================================== 14319 // SESSION ID 14320 //============================================================================== 14321 14322 net.user1.orbiter.Orbiter.prototype.getSessionID = function () { 14323 return this.sessionID == null ? "" : this.sessionID; 14324 }; 14325 14326 /** 14327 * @private 14328 */ 14329 net.user1.orbiter.Orbiter.prototype.setSessionID = function (id) { 14330 this.sessionID = id; 14331 }; 14332 14333 //============================================================================== 14334 // CONSOLE LOGGING 14335 //============================================================================== 14336 net.user1.orbiter.Orbiter.prototype.enableConsole = function () { 14337 if (this.consoleLogger == null) { 14338 this.consoleLogger = new net.user1.logger.ConsoleLogger(this.log); 14339 } 14340 }; 14341 14342 net.user1.orbiter.Orbiter.prototype.disableConsole = function () { 14343 if (this.consoleLogger != null) { 14344 this.consoleLogger.dispose(); 14345 this.consoleLogger = null; 14346 } 14347 }; 14348 14349 //============================================================================== 14350 // CLEANUP 14351 //============================================================================== 14352 14353 /** 14354 * Permanently disables this object and releases all of its 14355 * resources. Once dispose() is called, the object can never 14356 * be used again. Use dispose() only when purging an object 14357 * from memory, as is required when unloading an iframe. 14358 * 14359 * To simply disconnect an Orbiter object, use disconnect(). 14360 */ 14361 net.user1.orbiter.Orbiter.prototype.dispose = function () { 14362 this.log.info("[ORBITER] Beginning disposal of all resources..."); 14363 this.connectionMan.dispose(); 14364 this.roomMan.dispose(); 14365 this.connectionMonitor.dispose(); 14366 this.clientMan.dispose(); 14367 this.messageMan.dispose(); 14368 if (this.statistics != null) { 14369 this.statistics.stop(); 14370 } 14371 this.log.info("[ORBITER] Disposal complete."); 14372 } 14373 //============================================================================== 14374 // CONNECTION STATE CONSTANTS 14375 //============================================================================== 14376 /** @class */ 14377 net.user1.orbiter.ConnectionState = new Object(); 14378 /** @constant */ 14379 net.user1.orbiter.ConnectionState.UNKNOWN = -1; 14380 /** @constant */ 14381 net.user1.orbiter.ConnectionState.NOT_CONNECTED = 0; 14382 /** @constant */ 14383 net.user1.orbiter.ConnectionState.READY = 1; 14384 /** @constant */ 14385 net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS = 2; 14386 /** @constant */ 14387 net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS = 3; 14388 /** @constant */ 14389 net.user1.orbiter.ConnectionState.LOGGED_IN = 4; 14390 //============================================================================== 14391 // CLASS DECLARATION 14392 //============================================================================== 14393 /** @class 14394 @extends net.user1.events.Event 14395 */ 14396 net.user1.orbiter.ConnectionEvent = function (type, upc, data, connection, status) { 14397 net.user1.events.Event.call(this, type); 14398 14399 this.upc = upc; 14400 this.data = data; 14401 this.connection = connection 14402 this.status = status; 14403 }; 14404 14405 //============================================================================== 14406 // INHERITANCE 14407 //============================================================================== 14408 net.user1.utils.extend(net.user1.orbiter.ConnectionEvent, net.user1.events.Event); 14409 14410 //============================================================================== 14411 // STATIC VARIABLES 14412 //============================================================================== 14413 14414 /** @constant */ 14415 net.user1.orbiter.ConnectionEvent.BEGIN_CONNECT = "BEGIN_CONNECT"; 14416 /** @constant */ 14417 net.user1.orbiter.ConnectionEvent.BEGIN_HANDSHAKE = "BEGIN_HANDSHAKE"; 14418 /** @constant */ 14419 net.user1.orbiter.ConnectionEvent.READY = "READY"; 14420 /** @constant */ 14421 net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE = "CONNECT_FAILURE"; 14422 /** @constant */ 14423 net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT = "CLIENT_KILL_CONNECT"; 14424 /** @constant */ 14425 net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT = "SERVER_KILL_CONNECT"; 14426 /** @constant */ 14427 net.user1.orbiter.ConnectionEvent.DISCONNECT = "DISCONNECT"; 14428 /** @constant */ 14429 net.user1.orbiter.ConnectionEvent.RECEIVE_UPC = "RECEIVE_UPC"; 14430 /** @constant */ 14431 net.user1.orbiter.ConnectionEvent.SEND_DATA = "SEND_DATA"; 14432 /** @constant */ 14433 net.user1.orbiter.ConnectionEvent.RECEIVE_DATA = "RECEIVE_DATA"; 14434 /** @constant */ 14435 net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED = "SESSION_TERMINATED"; 14436 /** @constant */ 14437 net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND = "SESSION_NOT_FOUND"; 14438 14439 //============================================================================== 14440 // INSTANCE METHODS 14441 //============================================================================== 14442 14443 net.user1.orbiter.ConnectionEvent.prototype.getUPC = function () { 14444 return this.upc; 14445 } 14446 14447 net.user1.orbiter.ConnectionEvent.prototype.getData = function () { 14448 return this.data; 14449 } 14450 14451 net.user1.orbiter.ConnectionEvent.prototype.getStatus = function () { 14452 return this.status; 14453 } 14454 14455 net.user1.orbiter.ConnectionEvent.prototype.toString = function () { 14456 return "[object ConnectionEvent]"; 14457 } 14458 14459 //============================================================================== 14460 // HTTP REQUEST MODE CONSTANTS 14461 //============================================================================== 14462 /** @class */ 14463 net.user1.orbiter.ConnectionType = new Object(); 14464 /** @constant */ 14465 net.user1.orbiter.ConnectionType.HTTP = "HTTP"; 14466 /** @constant */ 14467 net.user1.orbiter.ConnectionType.SECURE_HTTP = "SECURE_HTTP"; 14468 /** @constant */ 14469 net.user1.orbiter.ConnectionType.WEBSOCKET = "WEBSOCKET"; 14470 /** @constant */ 14471 net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET = "SECURE_WEBSOCKET"; 14472 //============================================================================== 14473 // CLASS DECLARATION 14474 //============================================================================== 14475 /** @class 14476 * Connection is the abstract superclass of HTTPConnection and WebSocketConnection; 14477 * it is used internally by Orbiter, and is not intended for direct use by Orbiter 14478 * developers. For information on communication with Union Server, see 14479 * Orbiter's connect() method, the WebSocketConnection class and the 14480 * HTTPDirectConnection and HTTPIFrameConnection classes. 14481 * 14482 * The Connection class dispatches the following events: 14483 14484 <ul class="summary"> 14485 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.BEGIN_CONNECT}</li> 14486 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.BEGIN_HANDSHAKE}</li> 14487 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.READY}</li> 14488 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE}</li> 14489 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT}</li> 14490 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT}</li> 14491 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.DISCONNECT}</li> 14492 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.RECEIVE_UPC}</li> 14493 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SEND_DATA}</li> 14494 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.RECEIVE_DATA}</li> 14495 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED}</li> 14496 <li class="fixedFont">{@link net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND}</li> 14497 </ul> 14498 14499 To register for events, use {@link net.user1.events.EventDispatcher#addEventListener}. 14500 14501 @extends net.user1.events.EventDispatcher 14502 14503 * 14504 * @see net.user1.orbiter.Orbiter#connect 14505 * @see net.user1.orbiter.Orbiter#secureConnect 14506 * @see net.user1.orbiter.HTTPDirectConnection 14507 * @see net.user1.orbiter.HTTPIFrameConnection 14508 * @see net.user1.orbiter.WebSocketConnection 14509 * @see net.user1.orbiter.SecureHTTPDirectConnection 14510 * @see net.user1.orbiter.SecureHTTPIFrameConnection 14511 * @see net.user1.orbiter.SecureWebSocketConnection 14512 */ 14513 net.user1.orbiter.Connection = function (host, port, type) { 14514 // Call superconstructor 14515 net.user1.events.EventDispatcher.call(this); 14516 14517 // Variables 14518 this.mostRecentConnectAchievedReady = false; 14519 this.mostRecentConnectTimedOut = false; 14520 this.readyCount = 0; 14521 this.connectAttemptCount = 0; 14522 this.connectAbortCount = 0; 14523 this.readyTimeoutID = 0; 14524 this.readyTimeout = 0; 14525 this.orbiter = null; 14526 this.disposed = false; 14527 this.requestedHost = null; 14528 14529 // Initialization 14530 this.setServer(host, port); 14531 this.connectionType = type; 14532 this.connectionState = net.user1.orbiter.ConnectionState.NOT_CONNECTED; 14533 }; 14534 14535 //============================================================================== 14536 // INHERITANCE 14537 //============================================================================== 14538 net.user1.utils.extend(net.user1.orbiter.Connection, net.user1.events.EventDispatcher); 14539 14540 //============================================================================== 14541 // DEPENDENCIES 14542 //============================================================================== 14543 /** @private */ 14544 net.user1.orbiter.Connection.prototype.setOrbiter = function (orbiter) { 14545 if (this.orbiter != null) { 14546 this.orbiter.getMessageManager().removeMessageListener("u63", this.u63); 14547 this.orbiter.getMessageManager().removeMessageListener("u66", this.u66); 14548 this.orbiter.getMessageManager().removeMessageListener("u84", this.u84); 14549 this.orbiter.getMessageManager().removeMessageListener("u85", this.u85); 14550 } 14551 this.orbiter = orbiter; 14552 } 14553 14554 //============================================================================== 14555 // CONNECT/DISCONNECT 14556 //============================================================================== 14557 net.user1.orbiter.Connection.prototype.connect = function () { 14558 this.disconnect(); 14559 this.applyAffinity(); 14560 this.orbiter.getLog().info(this.toString() + " Attempting connection..."); 14561 this.connectAttemptCount++; 14562 this.mostRecentConnectAchievedReady = false; 14563 this.mostRecentConnectTimedOut = false; 14564 this.connectionState = net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS; 14565 // Start the ready timer. Ready state must be achieved before the timer 14566 // completes or the connection will auto-disconnect. 14567 this.startReadyTimer(); 14568 this.dispatchBeginConnect(); 14569 } 14570 14571 net.user1.orbiter.Connection.prototype.disconnect = function () { 14572 var state = this.connectionState; 14573 14574 if (state != net.user1.orbiter.ConnectionState.NOT_CONNECTED) { 14575 this.deactivateConnection(); 14576 14577 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 14578 this.connectAbortCount++; 14579 this.dispatchConnectFailure("Client closed connection before READY state was achieved."); 14580 } else { 14581 this.dispatchClientKillConnect(); 14582 } 14583 } 14584 } 14585 14586 /** @private */ 14587 net.user1.orbiter.Connection.prototype.deactivateConnection = function () { 14588 this.connectionState = net.user1.orbiter.ConnectionState.NOT_CONNECTED; 14589 this.stopReadyTimer(); 14590 this.orbiter.setSessionID(""); 14591 } 14592 14593 //============================================================================== 14594 // CONNECTION CONFIGURATION 14595 //============================================================================== 14596 net.user1.orbiter.Connection.prototype.setServer = function (host, 14597 port) { 14598 this.requestedHost = host; 14599 14600 // Check for valid ports 14601 if (port < 1 || port > 65536) { 14602 throw new Error("Illegal port specified [" + port + "]. Must be greater than 0 and less than 65537."); 14603 } 14604 this.port = port; 14605 } 14606 14607 net.user1.orbiter.Connection.prototype.getRequestedHost = function () { 14608 return this.requestedHost; 14609 }; 14610 14611 net.user1.orbiter.Connection.prototype.getHost = function () { 14612 if (this.host == null) { 14613 return this.getRequestedHost(); 14614 } else { 14615 return this.host; 14616 } 14617 }; 14618 14619 net.user1.orbiter.Connection.prototype.getPort = function () { 14620 return this.port; 14621 }; 14622 14623 net.user1.orbiter.Connection.prototype.getType = function () { 14624 return this.connectionType; 14625 }; 14626 14627 //============================================================================== 14628 // READY HANDSHAKE 14629 //============================================================================== 14630 /** @private */ 14631 net.user1.orbiter.Connection.prototype.beginReadyHandshake = function () { 14632 this.dispatchBeginHandshake(); 14633 14634 if (!this.orbiter.getMessageManager().hasMessageListener("u63", this.u63)) { 14635 this.orbiter.getMessageManager().addMessageListener("u63", this.u63, this); 14636 this.orbiter.getMessageManager().addMessageListener("u66", this.u66, this); 14637 this.orbiter.getMessageManager().addMessageListener("u84", this.u84, this); 14638 this.orbiter.getMessageManager().addMessageListener("u85", this.u85, this); 14639 } 14640 14641 this.sendHello(); 14642 } 14643 14644 /** @private */ 14645 net.user1.orbiter.Connection.prototype.sendHello = function() { 14646 var helloString = this.buildHelloMessage(); 14647 this.orbiter.getLog().debug(this.toString() + " Sending CLIENT_HELLO: " + helloString); 14648 this.transmitHelloMessage(helloString); 14649 } 14650 14651 /** @private */ 14652 net.user1.orbiter.Connection.prototype.buildHelloMessage = function () { 14653 var helloString = "<U><M>u65</M>" 14654 + "<L>" 14655 + "<A>" + this.orbiter.getSystem().getClientType() + "</A>" 14656 + "<A>" + (typeof navigator != "undefined" ? navigator.userAgent + ";" : "") 14657 + this.orbiter.getSystem().getClientVersion().toStringVerbose() + "</A>" 14658 + "<A>" + this.orbiter.getSystem().getUPCVersion().toString() + "</A></L></U>"; 14659 return helloString; 14660 } 14661 14662 /** @private */ 14663 net.user1.orbiter.Connection.prototype.transmitHelloMessage = function (helloString) { 14664 this.send(helloString); 14665 } 14666 14667 //============================================================================== 14668 // READY TIMER 14669 //============================================================================== 14670 /** @private */ 14671 net.user1.orbiter.Connection.prototype.readyTimerListener = function () { 14672 this.stopReadyTimer(); 14673 if (this.connectionState == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 14674 this.orbiter.getLog().warn("[CONNECTION] " + this.toString() + " Failed to achieve" + 14675 " ready state after " + this.readyTimeout + "ms. Aborting connection..."); 14676 this.mostRecentConnectTimedOut = true; 14677 this.disconnect(); 14678 } 14679 } 14680 14681 /** @private */ 14682 net.user1.orbiter.Connection.prototype.stopReadyTimer = function () { 14683 if (this.readyTimeoutID != -1) { 14684 clearTimeout(this.readyTimeoutID); 14685 } 14686 } 14687 14688 /** @private */ 14689 net.user1.orbiter.Connection.prototype.startReadyTimer = function () { 14690 var currentObj = this; 14691 var callback = this.readyTimerListener; 14692 this.stopReadyTimer(); 14693 this.readyTimeout = this.orbiter.getConnectionManager().getReadyTimeout(); 14694 var self = this; 14695 this.readyTimeoutID = setTimeout (function () { 14696 callback.call(currentObj); 14697 }, self.readyTimeout); 14698 } 14699 14700 //============================================================================== 14701 // READY STATE ACCESS 14702 //============================================================================== 14703 /** @private */ 14704 net.user1.orbiter.Connection.prototype.getReadyCount = function () { 14705 return this.readyCount; 14706 } 14707 14708 net.user1.orbiter.Connection.prototype.isReady = function () { 14709 return this.connectionState == net.user1.orbiter.ConnectionState.READY; 14710 } 14711 14712 /** @private */ 14713 net.user1.orbiter.Connection.prototype.isValid = function () { 14714 if (this.mostRecentConnectAchievedReady) { 14715 this.orbiter.getLog().debug(this.toString() + " Connection is" 14716 + " valid because its last connection attempt succeeded."); 14717 return true; 14718 } 14719 14720 if (this.connectAttemptCount == 0) { 14721 this.orbiter.getLog().debug(this.toString() + " Connection is" 14722 + " valid because it has either never attempted to connect, or has not" 14723 + " attempted to connect since its last successful connection."); 14724 return true; 14725 } 14726 14727 if ((this.connectAttemptCount > 0) && 14728 (this.connectAttemptCount == this.connectAbortCount) 14729 && !this.mostRecentConnectTimedOut) { 14730 this.orbiter.getLog().debug(this.toString() + " Connection is" 14731 + " valid because either all connection attempts ever or all" 14732 + " connection attempts since its last successful connection were" 14733 + " aborted before the ready timeout was reached."); 14734 return true; 14735 } 14736 14737 this.orbiter.getLog().debug(this.toString() + " Connection is not" 14738 + " valid; its most recent connection failed to achieve a ready state."); 14739 return false; 14740 } 14741 14742 14743 //============================================================================== 14744 // UPC LISTENERS 14745 //============================================================================== 14746 /** @private */ 14747 net.user1.orbiter.Connection.prototype.u63 = function () { 14748 this.stopReadyTimer(); 14749 this.connectionState = net.user1.orbiter.ConnectionState.READY; 14750 this.mostRecentConnectAchievedReady = true; 14751 this.readyCount++; 14752 this.connectAttemptCount = 0; 14753 this.connectAbortCount = 0; 14754 this.dispatchReady(); 14755 } 14756 14757 /** @private */ 14758 net.user1.orbiter.Connection.prototype.u66 = function (serverVersion, 14759 sessionID, 14760 upcVersion, 14761 protocolCompatible, 14762 affinityAddress, 14763 affinityDuration) { 14764 this.orbiter.setSessionID(sessionID); 14765 }; 14766 14767 /** @private */ 14768 net.user1.orbiter.Connection.prototype.u84 = function () { 14769 this.dispatchSessionTerminated(); 14770 } 14771 14772 /** @private */ 14773 net.user1.orbiter.Connection.prototype.u85 = function () { 14774 this.dispatchSessionNotFound(); 14775 } 14776 14777 //============================================================================== 14778 // SERVER AFFINITY 14779 //============================================================================== 14780 /** @private */ 14781 net.user1.orbiter.Connection.prototype.applyAffinity = function () { 14782 var affinityAddress = this.orbiter.getConnectionManager().getAffinity(this.requestedHost); 14783 if (affinityAddress == this.requestedHost) { 14784 this.orbiter.getLog().info(this.toString() + " No affinity address found for requested host [" 14785 + this.requestedHost + "]. Using requested host for next connection attempt."); 14786 } else { 14787 this.orbiter.getLog().info(this.toString() + " Applying affinity address [" + affinityAddress + "] for supplied host [" + this.requestedHost + "]."); 14788 } 14789 this.host = affinityAddress; 14790 } 14791 14792 //============================================================================== 14793 // TOSTRING 14794 //============================================================================== 14795 net.user1.orbiter.Connection.prototype.toString = function () { 14796 var s = "[" + this.connectionType + ", requested host: " + this.requestedHost 14797 + ", host: " + (this.host == null ? "" : this.host) 14798 + ", port: " + this.port + "]"; 14799 return s; 14800 } 14801 14802 //============================================================================== 14803 // EVENT DISPATCHING 14804 //============================================================================== 14805 /** @private */ 14806 net.user1.orbiter.Connection.prototype.dispatchSendData = function (data) { 14807 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SEND_DATA, 14808 null, data, this)); 14809 } 14810 14811 /** @private */ 14812 net.user1.orbiter.Connection.prototype.dispatchReceiveData = function (data) { 14813 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.RECEIVE_DATA, 14814 null, data, this)); 14815 } 14816 14817 /** @private */ 14818 net.user1.orbiter.Connection.prototype.dispatchConnectFailure = function (status) { 14819 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, 14820 null, null, this, status)); 14821 } 14822 14823 /** @private */ 14824 net.user1.orbiter.Connection.prototype.dispatchBeginConnect = function () { 14825 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.BEGIN_CONNECT, 14826 null, null, this)); 14827 } 14828 14829 /** @private */ 14830 net.user1.orbiter.Connection.prototype.dispatchBeginHandshake = function () { 14831 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.BEGIN_HANDSHAKE, 14832 null, null, this)); 14833 } 14834 14835 /** @private */ 14836 net.user1.orbiter.Connection.prototype.dispatchReady = function () { 14837 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.READY, 14838 null, null, this)); 14839 } 14840 14841 /** @private */ 14842 net.user1.orbiter.Connection.prototype.dispatchServerKillConnect = function () { 14843 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SERVER_KILL_CONNECT, 14844 null, null, this)); 14845 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.DISCONNECT, 14846 null, null, this)); 14847 } 14848 14849 /** @private */ 14850 net.user1.orbiter.Connection.prototype.dispatchClientKillConnect = function () { 14851 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.CLIENT_KILL_CONNECT, 14852 null, null, this)); 14853 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.DISCONNECT, 14854 null, null, this)); 14855 } 14856 14857 /** @private */ 14858 net.user1.orbiter.Connection.prototype.dispatchSessionTerminated = function () { 14859 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED, 14860 null, null, this)); 14861 } 14862 14863 /** @private */ 14864 net.user1.orbiter.Connection.prototype.dispatchSessionNotFound = function () { 14865 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND, 14866 null, null, this)); 14867 } 14868 14869 //============================================================================== 14870 // DISPOSAL 14871 //============================================================================== 14872 /** @private */ 14873 net.user1.orbiter.Connection.prototype.dispose = function () { 14874 this.disposed = true; 14875 this.messageManager.removeMessageListener("u63", this.u63); 14876 this.messageManager.removeMessageListener("u66", this.u66); 14877 this.messageManager.removeMessageListener("u84", this.u84); 14878 this.messageManager.removeMessageListener("u85", this.u85); 14879 this.stopReadyTimer(); 14880 this.readyTimer = null; 14881 this.orbiter = null; 14882 } 14883 //============================================================================== 14884 // CLASS DECLARATION 14885 //============================================================================== 14886 /** 14887 * @class 14888 * 14889 * <p> 14890 * The WebSocketConnection class is used by Orbiter to communicate with 14891 * Union Server over a persistent TCP/IP socket. Normally, developers need not 14892 * use the WebSocketConnection class directly, and should instead make connections 14893 * via the Orbiter class's connect() method. However, the 14894 * WebSocketConnection class is required for fine-grained connection configuration, 14895 * such as defining failover socket connections for multiple Union Servers 14896 * running at different host addresses. 14897 * </p> 14898 * 14899 * <p> 14900 * By default, Orbiter uses WebSocketConnection connections to communicate 14901 * with Union Server. WebSocketConnection connections offer faster response times than 14902 * HTTP connections, but occupy an operating-system-level socket continuously 14903 * for the duration of the connection. If a WebSocketConnection connection 14904 * cannot be established (due to, say, a restrictive firewall), Orbiter 14905 * automatically attempts to communicate using HTTP requests sent via an 14906 * HTTPDirectConnection or HTTPIFrameConnection. Developers can override 14907 * Orbiter's default connection failover system by manually configuring 14908 * connections using the ConnectionManager class and Orbiter's 14909 * disableHTTPFailover() method.</p> 14910 * 14911 * <p> 14912 * For secure WebSocket and HTTP communications, see SecureWebSocketConnection, 14913 * SecureHTTPDirectConnection, and SecureHTTPIFrameConnection. 14914 * </p> 14915 * 14916 * For a list of events dispatched by WebSocketConnection, see 14917 * WebSocketConnection's superclass, {@link net.user1.orbiter.Connection}. 14918 * 14919 * @extends net.user1.orbiter.Connection 14920 * 14921 * @see net.user1.orbiter.Orbiter#connect 14922 * @see net.user1.orbiter.Orbiter#secureConnect 14923 * @see net.user1.orbiter.SecureWebSocketConnection 14924 * @see net.user1.orbiter.SecureHTTPDirectConnection 14925 * @see net.user1.orbiter.SecureHTTPIFrameConnection 14926 */ 14927 net.user1.orbiter.WebSocketConnection = function (host, port, type) { 14928 // Invoke superclass constructor 14929 net.user1.orbiter.Connection.call(this, host, port, type || net.user1.orbiter.ConnectionType.WEBSOCKET); 14930 14931 this.socket = null; 14932 }; 14933 14934 //============================================================================== 14935 // INHERITANCE 14936 //============================================================================== 14937 net.user1.utils.extend(net.user1.orbiter.WebSocketConnection, net.user1.orbiter.Connection); 14938 14939 //============================================================================== 14940 // SOCKET OBJECT MANAGEMENT 14941 //============================================================================== 14942 /** @private */ 14943 net.user1.orbiter.WebSocketConnection.prototype.getNewSocket = function () { 14944 // Deactivate the old socket 14945 this.deactivateSocket(this.socket); 14946 14947 // Create the new socket 14948 if (typeof MozWebSocket != "undefined") { 14949 // Firefox 6 14950 this.socket = new MozWebSocket(this.buildURL()); 14951 } else { 14952 // Other browsers 14953 this.socket = new WebSocket(this.buildURL()); 14954 } 14955 14956 // Register for socket events 14957 var self = this; 14958 this.socket.onopen = function (e) {self.connectListener(e)}; 14959 this.socket.onmessage = function (e) {self.dataListener(e)}; 14960 this.socket.onclose = function (e) {self.closeListener(e)}; 14961 this.socket.onerror = function (e) {self.ioErrorListener(e)}; 14962 }; 14963 14964 /** @private */ 14965 net.user1.orbiter.WebSocketConnection.prototype.buildURL = function () { 14966 return "ws://" + this.host + ":" + this.port; 14967 }; 14968 14969 /** @private */ 14970 net.user1.orbiter.WebSocketConnection.prototype.deactivateSocket = function (oldSocket) { 14971 if (oldSocket == null) { 14972 return; 14973 } 14974 14975 this.socket.onopen = null; 14976 this.socket.onmessage = null; 14977 this.socket.onclose = null; 14978 this.socket.onerror = null; 14979 14980 try { 14981 oldSocket.close() 14982 } catch (e) { 14983 // Do nothing 14984 } 14985 14986 this.socket = null; 14987 }; 14988 14989 //============================================================================== 14990 // CONNECTION AND DISCONNECTION 14991 //============================================================================== 14992 14993 net.user1.orbiter.WebSocketConnection.prototype.connect = function () { 14994 net.user1.orbiter.Connection.prototype.connect.call(this); 14995 14996 // Attempt to connect 14997 try { 14998 this.getNewSocket(); 14999 } catch (e) { 15000 // Socket could not be opened 15001 this.deactivateConnection(); 15002 this.dispatchConnectFailure(e.toString()); 15003 } 15004 }; 15005 15006 /** @private */ 15007 net.user1.orbiter.WebSocketConnection.prototype.deactivateConnection = function () { 15008 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Deactivating..."); 15009 this.connectionState = net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS; 15010 this.deactivateSocket(this.socket); 15011 net.user1.orbiter.Connection.prototype.deactivateConnection.call(this); 15012 }; 15013 15014 //============================================================================== 15015 // SOCKET CONNECTION LISTENERS 15016 //============================================================================== 15017 /** @private */ 15018 net.user1.orbiter.WebSocketConnection.prototype.connectListener = function (e) { 15019 if (this.disposed) return; 15020 15021 this.orbiter.getLog().debug(this.toString() + " Socket connected."); 15022 this.beginReadyHandshake(); 15023 } 15024 15025 /** @private */ 15026 net.user1.orbiter.WebSocketConnection.prototype.closeListener = function (e) { 15027 if (this.disposed) return; 15028 15029 var state = this.connectionState; 15030 this.deactivateConnection(); 15031 15032 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15033 this.dispatchConnectFailure("WebSocket onclose: Server closed connection before READY state was achieved."); 15034 } else { 15035 this.dispatchServerKillConnect(); 15036 } 15037 }; 15038 15039 /** @private */ 15040 net.user1.orbiter.WebSocketConnection.prototype.ioErrorListener = function (e) { 15041 if (this.disposed) return; 15042 15043 var state = this.connectionState; 15044 this.deactivateConnection(); 15045 15046 // Note: when Union closes the connection, Firefox 7 dispatches onerror, not 15047 // onclose, so treat onerror like an onclose event 15048 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15049 this.dispatchConnectFailure("WebSocket onerror: Server closed connection before READY state was achieved."); 15050 } else { 15051 this.dispatchServerKillConnect(); 15052 } 15053 }; 15054 15055 //============================================================================== 15056 // DATA RECEIVING AND SENDING 15057 //============================================================================== 15058 /** @private */ 15059 net.user1.orbiter.WebSocketConnection.prototype.dataListener = function (dataEvent) { 15060 if (this.disposed) return; 15061 15062 var data = dataEvent.data; 15063 this.dispatchReceiveData(data); 15064 15065 if (data.indexOf("<U>") == 0) { 15066 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent( 15067 net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, 15068 data)); 15069 } else { 15070 // The message isn't UPC. Must be an error... 15071 this.orbiter.getLog().error(this.toString() + " Received invalid message" 15072 + " (not UPC or malformed UPC): " + data); 15073 } 15074 }; 15075 15076 /** @private */ 15077 net.user1.orbiter.WebSocketConnection.prototype.send = function (data) { 15078 this.dispatchSendData(data); 15079 this.socket.send(data); 15080 }; 15081 15082 // ============================================================================= 15083 // DISPOSAL 15084 // ============================================================================= 15085 /** @private */ 15086 net.user1.orbiter.WebSocketConnection.prototype.dispose = function () { 15087 net.user1.orbiter.Connection.prototype.dispose.call(this); 15088 this.deactivateSocket(this.socket); 15089 }; 15090 //============================================================================== 15091 // CLASS DECLARATION 15092 //============================================================================== 15093 /** @class 15094 * 15095 * <p> 15096 * The SecureWebSocketConnection class is identical to WebSocketConnection 15097 * except that it performs communications over WSS (i.e., an encrypted TLS or 15098 * SSL socket connection) rather than plain WebSocket.</p> 15099 * 15100 * For a list of events dispatched by SecureWebSocketConnection, see 15101 * {@link net.user1.orbiter.Connection}. 15102 * 15103 * @extends net.user1.orbiter.WebSocketConnection 15104 * 15105 * @see net.user1.orbiter.WebSocketConnection 15106 */ 15107 net.user1.orbiter.SecureWebSocketConnection = function (host, port) { 15108 // Invoke superclass constructor 15109 net.user1.orbiter.WebSocketConnection.call(this, host, port, net.user1.orbiter.ConnectionType.SECURE_WEBSOCKET); 15110 }; 15111 15112 //============================================================================== 15113 // INHERITANCE 15114 //============================================================================== 15115 net.user1.utils.extend(net.user1.orbiter.SecureWebSocketConnection, net.user1.orbiter.WebSocketConnection); 15116 15117 /** @private */ 15118 net.user1.orbiter.SecureWebSocketConnection.prototype.buildURL = function () { 15119 return "wss://" + this.host + ":" + this.port; 15120 }; 15121 //============================================================================== 15122 // CLASS DECLARATION 15123 //============================================================================== 15124 /** 15125 * @class 15126 * 15127 * HTTPConnection is the abstract superclass of HTTPDirectConnection and 15128 * HTTPIFrameConnection; it is used internally by Orbiter, and is not intended 15129 * for direct use by Orbiter developers. For information on HTTP communication 15130 * with Union Server, see the HTTPDirectConnection and HTTPIFrameConnection classes. 15131 * 15132 * For a list of events dispatched by HTTPConnection, see HTTPConnection's 15133 * superclass, {@link net.user1.orbiter.Connection}. 15134 * 15135 * @extends net.user1.orbiter.Connection 15136 * 15137 * 15138 * @see net.user1.orbiter.HTTPDirectConnection 15139 * @see net.user1.orbiter.HTTPIFrameConnection 15140 */ 15141 net.user1.orbiter.HTTPConnection = function (host, port, type) { 15142 // Invoke superclass constructor 15143 net.user1.orbiter.Connection.call(this, host, port, type || net.user1.orbiter.ConnectionType.HTTP); 15144 15145 // Instance variables 15146 this.url = ""; 15147 this.sendDelayTimerEnabled = true; 15148 this.sendDelayTimeoutID = -1; 15149 this.sendDelayTimerRunning = false; 15150 this.sendDelay = net.user1.orbiter.HTTPConnection.DEFAULT_SEND_DELAY; 15151 15152 this.messageQueue = new Array(); 15153 15154 this.retryDelay = 500; 15155 this.retryHelloTimeoutID = -1; 15156 this.retryIncomingTimeoutID = -1; 15157 this.retryOutgoingTimeoutID = -1; 15158 15159 this.helloResponsePending = false; 15160 this.outgoingResponsePending = false; 15161 15162 // Initialization 15163 this.addEventListener(net.user1.orbiter.ConnectionEvent.SESSION_TERMINATED, this.sessionTerminatedListener, this); 15164 this.addEventListener(net.user1.orbiter.ConnectionEvent.SESSION_NOT_FOUND, this.sessionNotFoundListener, this); 15165 }; 15166 15167 //============================================================================== 15168 // INHERITANCE 15169 //============================================================================== 15170 net.user1.utils.extend(net.user1.orbiter.HTTPConnection, net.user1.orbiter.Connection); 15171 15172 //============================================================================== 15173 // STATIC VARIABLES 15174 //============================================================================== 15175 /** @constant */ 15176 net.user1.orbiter.HTTPConnection.DEFAULT_SEND_DELAY = 300; 15177 15178 //============================================================================== 15179 // ABSTRACT METHODS (MUST BE IMPLEMENTED BY SUBCLASSES) 15180 //============================================================================== 15181 15182 net.user1.orbiter.HTTPConnection.prototype.doRequestDeactivation = net.user1.utils.abstractError; 15183 net.user1.orbiter.HTTPConnection.prototype.doSendHello = net.user1.utils.abstractError; 15184 net.user1.orbiter.HTTPConnection.prototype.doRetryHello = net.user1.utils.abstractError; 15185 net.user1.orbiter.HTTPConnection.prototype.doSendOutgoing = net.user1.utils.abstractError; 15186 net.user1.orbiter.HTTPConnection.prototype.doRetryOutgoing = net.user1.utils.abstractError; 15187 net.user1.orbiter.HTTPConnection.prototype.doSendIncoming = net.user1.utils.abstractError; 15188 net.user1.orbiter.HTTPConnection.prototype.doRetryIncoming = net.user1.utils.abstractError; 15189 net.user1.orbiter.HTTPConnection.prototype.doDispose = net.user1.utils.abstractError; 15190 15191 //============================================================================== 15192 // CONNECTION AND DISCONNECTION 15193 //============================================================================== 15194 net.user1.orbiter.HTTPConnection.prototype.connect = function () { 15195 net.user1.orbiter.Connection.prototype.connect.call(this); 15196 }; 15197 15198 /** @private */ 15199 net.user1.orbiter.HTTPConnection.prototype.deactivateConnection = function () { 15200 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Deactivating..."); 15201 this.connectionState = net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS; 15202 this.stopSendDelayTimer(); 15203 if (this.retryHelloTimeoutID != -1) { 15204 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Cancelling scheduled hello-request retry."); 15205 clearTimeout(this.retryHelloTimeoutID); 15206 this.retryHelloTimeoutID = -1 15207 } 15208 if (this.retryIncomingTimeoutID != -1) { 15209 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Cancelling scheduled incoming-request retry."); 15210 clearTimeout(this.retryIncomingTimeoutID); 15211 this.retryIncomingTimeoutID = -1 15212 } 15213 if (this.retryOutgoingTimeoutID != -1) { 15214 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Cancelling scheduled outgoing-request retry."); 15215 clearTimeout(this.retryOutgoingTimeoutID); 15216 this.retryOutgoingTimeoutID = -1 15217 } 15218 this.deactivateHTTPRequests(); 15219 net.user1.orbiter.Connection.prototype.deactivateConnection.call(this); 15220 }; 15221 15222 /** @private */ 15223 net.user1.orbiter.HTTPConnection.prototype.deactivateHTTPRequests = function () { 15224 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Closing all pending HTTP requests."); 15225 this.doRequestDeactivation(); 15226 this.helloResponsePending = false; 15227 this.outgoingResponsePending = false; 15228 }; 15229 15230 //============================================================================== 15231 // SESSION MANAGEMENT 15232 //============================================================================== 15233 15234 /** @private */ 15235 net.user1.orbiter.HTTPConnection.prototype.sessionTerminatedListener = function (e) { 15236 var state = this.connectionState; 15237 this.deactivateConnection(); 15238 15239 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15240 this.dispatchConnectFailure("Server terminated session before READY state was achieved."); 15241 } else { 15242 this.dispatchServerKillConnect(); 15243 } 15244 }; 15245 15246 /** @private */ 15247 net.user1.orbiter.HTTPConnection.prototype.sessionNotFoundListener = function (e) { 15248 var state = this.connectionState; 15249 15250 this.deactivateConnection(); 15251 15252 if (state == net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15253 this.dispatchConnectFailure("Client attempted to reestablish an expired session" 15254 + " or establish an unknown session."); 15255 } else { 15256 this.dispatchServerKillConnect(); 15257 } 15258 } 15259 15260 15261 //============================================================================== 15262 // SERVER ASSIGNMENT 15263 //============================================================================== 15264 /** @private */ 15265 net.user1.orbiter.HTTPConnection.prototype.setServer = function (host, port) { 15266 try { 15267 net.user1.orbiter.Connection.prototype.setServer.call(this, host, port); 15268 } finally { 15269 this.buildURL(); 15270 } 15271 } 15272 15273 /** @private */ 15274 net.user1.orbiter.HTTPConnection.prototype.buildURL = function () { 15275 this.url = "http://" + this.host + ":" + this.port; 15276 } 15277 15278 //============================================================================== 15279 // OUTGOING DELAY TIMER 15280 //============================================================================== 15281 /** @private */ 15282 net.user1.orbiter.HTTPConnection.prototype.sendDelayTimerListener = function () { 15283 this.sendDelayTimerRunning = false; 15284 if (this.messageQueue.length > 0) { 15285 this.flushMessageQueue(); 15286 } else { 15287 // No messages in queue, so take no action. 15288 } 15289 } 15290 15291 /** @private */ 15292 net.user1.orbiter.HTTPConnection.prototype.stopSendDelayTimer = function () { 15293 this.sendDelayTimerRunning = false; 15294 if (this.sendDelayTimeoutID != -1) { 15295 clearTimeout(this.sendDelayTimeoutID); 15296 } 15297 this.sendDelayTimeoutID = -1; 15298 } 15299 15300 /** @private */ 15301 net.user1.orbiter.HTTPConnection.prototype.startSendDelayTimer = function () { 15302 this.stopSendDelayTimer(); 15303 var currentObj = this; 15304 var callback = this.sendDelayTimerListener; 15305 this.sendDelayTimerRunning = true; 15306 this.sendDelayTimeoutID = setTimeout(function () { 15307 callback.call(currentObj); 15308 }, this.sendDelay); 15309 } 15310 15311 net.user1.orbiter.HTTPConnection.prototype.setSendDelay = function (milliseconds) { 15312 if (milliseconds > 0) { 15313 if ((milliseconds != this.sendDelay)) { 15314 this.sendDelay = milliseconds; 15315 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Send delay set to: [" 15316 + milliseconds + "]."); 15317 } 15318 this.sendDelayTimerEnabled = true; 15319 } else if (milliseconds == -1) { 15320 this.orbiter.getLog().debug("[CONNECTION] " + toString() + " Send delay disabled."); 15321 this.sendDelayTimerEnabled = false; 15322 this.stopSendDelayTimer(); 15323 } else { 15324 throw new Error("[CONNECTION]" + this.toString() + " Invalid send-delay specified: [" 15325 + milliseconds + "]."); 15326 } 15327 } 15328 15329 net.user1.orbiter.HTTPConnection.prototype.getSendDelay = function () { 15330 return this.sendDelay; 15331 } 15332 15333 //============================================================================== 15334 // RETRY DELAY 15335 //============================================================================== 15336 net.user1.orbiter.HTTPConnection.prototype.setRetryDelay = function (milliseconds) { 15337 if (milliseconds > -1) { 15338 if (milliseconds != this.retryDelay) { 15339 this.retryDelay = milliseconds; 15340 this.orbiter.getLog().debug("[CONNECTION] " + this.toString() + " Retry delay set to: [" 15341 + milliseconds + "]."); 15342 } 15343 } else { 15344 throw new Error("[CONNECTION]" + this.toString() + " Invalid retry delay specified: [" 15345 + milliseconds + "]."); 15346 } 15347 } 15348 15349 //============================================================================== 15350 // DATA SENDING AND QUEUING 15351 //============================================================================== 15352 15353 net.user1.orbiter.HTTPConnection.prototype.send = function (data) { 15354 // If the timer isn't running... 15355 if (!this.sendDelayTimerRunning) { 15356 // ...it is either disabled or expired. Either way, it's time to 15357 // attempt to flush the queue. 15358 this.messageQueue.push(data); 15359 this.flushMessageQueue(); 15360 } else { 15361 // The send-delay timer is running, so we can't send yet. Just queue the message. 15362 this.messageQueue.push(data); 15363 } 15364 } 15365 15366 /** @private */ 15367 net.user1.orbiter.HTTPConnection.prototype.flushMessageQueue = function () { 15368 if (!this.outgoingResponsePending) { 15369 this.openNewOutgoingRequest(this.messageQueue.join("")); 15370 this.messageQueue = new Array(); 15371 } else { 15372 // AN OUTGOING RESPONSE IS STILL PENDING, SO DON'T SEND A NEW ONE 15373 } 15374 } 15375 15376 //============================================================================== 15377 // HELLO REQUEST MANAGEMENT 15378 //============================================================================== 15379 15380 /** @private */ 15381 net.user1.orbiter.HTTPConnection.prototype.transmitHelloMessage = function (helloString) { 15382 this.dispatchSendData(helloString); 15383 this.helloResponsePending = true; 15384 this.doSendHello(helloString); 15385 } 15386 15387 /** @private */ 15388 net.user1.orbiter.HTTPConnection.prototype.helloCompleteListener = function (data) { 15389 if (this.disposed) return; 15390 15391 if (this.helloResponsePending) { 15392 this.helloResponsePending = false; 15393 this.processIncomingData(data); 15394 15395 // Don't immediately open a request in the complete handler due to Win IE bug 15396 var self = this; 15397 setTimeout(function () { 15398 self.openNewIncomingRequest(); 15399 }, 0); 15400 } else { 15401 if (this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED) { 15402 this.orbiter.getLog().error("[CONNECTION]" + toString() + " u66 (SERVER_HELLO) received, but client is not connected. Ignoring."); 15403 } else { 15404 this.orbiter.getLog().error("[CONNECTION]" + toString() + " Redundant u66 (SERVER_HELLO) received. Ignoring."); 15405 } 15406 } 15407 } 15408 15409 /** @private */ 15410 net.user1.orbiter.HTTPConnection.prototype.helloErrorListener = function () { 15411 if (this.disposed) return; 15412 // There's already a retry scheduled 15413 if (this.retryHelloTimeoutID != -1) return; 15414 // The connection attempt has been aborted 15415 if (this.connectionState != net.user1.orbiter.ConnectionState.CONNECTION_IN_PROGRESS) { 15416 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " u65 (CLIENT_HELLO) request failed." 15417 + " Connection is no longer in progress, so no retry scheduled."); 15418 return; 15419 } 15420 15421 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " u65 (CLIENT_HELLO) request failed." 15422 + " Retrying in " + this.retryDelay + "ms."); 15423 15424 // Retry 15425 var self = this; 15426 this.retryHelloTimeoutID = setTimeout(function () { 15427 self.retryHelloTimeoutID = -1; 15428 self.doRetryHello(); 15429 }, this.retryDelay); 15430 } 15431 15432 //============================================================================== 15433 // OUTGOING REQUEST MANAGEMENT 15434 //============================================================================== 15435 15436 /** @private */ 15437 net.user1.orbiter.HTTPConnection.prototype.openNewOutgoingRequest = function (data) { 15438 this.dispatchSendData(data); 15439 this.outgoingResponsePending = true; 15440 this.doSendOutgoing(data); 15441 if (this.sendDelayTimerEnabled == true) { 15442 this.startSendDelayTimer(); 15443 } 15444 } 15445 15446 /** @private */ 15447 net.user1.orbiter.HTTPConnection.prototype.outgoingCompleteListener = function () { 15448 if (this.disposed) return; 15449 15450 this.outgoingResponsePending = false; 15451 15452 if (!this.sendDelayTimerRunning && this.messageQueue.length > 0) { 15453 // Don't immediately open a request in the complete handler due to Win IE bug 15454 var self = this; 15455 setTimeout(function () { 15456 self.flushMessageQueue(); 15457 }, 0); 15458 } 15459 } 15460 15461 /** @private */ 15462 net.user1.orbiter.HTTPConnection.prototype.outgoingErrorListener = function () { 15463 if (this.disposed) return; 15464 // There's already a retry scheduled 15465 if (this.retryOutgoingTimeoutID != -1) return; 15466 // The connection has been closed 15467 if (this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15468 || this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15469 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Outgoing request failed." 15470 + " Connection is closed, so no retry scheduled."); 15471 return; 15472 } 15473 15474 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Outgoing request failed." 15475 + " Retrying in " + this.retryDelay + "ms."); 15476 15477 // Retry 15478 var self = this; 15479 this.retryOutgoingTimeoutID = setTimeout(function () { 15480 self.retryOutgoingTimeoutID = -1; 15481 if (self.disposed 15482 || self.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15483 || self.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15484 return; 15485 } 15486 self.doRetryOutgoing(); 15487 }, this.retryDelay); 15488 } 15489 15490 //============================================================================== 15491 // INCOMING REQUEST MANAGEMENT 15492 //============================================================================== 15493 15494 /** @private */ 15495 net.user1.orbiter.HTTPConnection.prototype.openNewIncomingRequest = function () { 15496 this.doSendIncoming(); 15497 } 15498 15499 /** @private */ 15500 net.user1.orbiter.HTTPConnection.prototype.incomingCompleteListener = function (data) { 15501 if (this.disposed 15502 || this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15503 || this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15504 // Incoming request complete, but connection is closed. Ignore content. 15505 return; 15506 } 15507 15508 // Don't immediately open a request in the complete handler due to Win IE bug 15509 var self = this; 15510 setTimeout(function () { 15511 self.processIncomingData(data); 15512 // A message listener might have closed this connection in response to an incoming 15513 // message. Do not open a new incoming request unless the connection is still open. 15514 if (self.disposed 15515 || self.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15516 || self.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15517 return; 15518 } 15519 self.openNewIncomingRequest(); 15520 }, 0); 15521 } 15522 15523 /** @private */ 15524 net.user1.orbiter.HTTPConnection.prototype.incomingErrorListener = function () { 15525 if (this.disposed) return; 15526 // There's already a retry scheduled 15527 if (this.retryIncomingTimeoutID != -1) return; 15528 // The connection has been closed 15529 if (this.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15530 || this.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15531 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Incoming request failed." 15532 + " Connection is closed, so no retry scheduled."); 15533 return; 15534 } 15535 15536 this.orbiter.getLog().error("[CONNECTION]" + this.toString() + " Incoming request failed." 15537 + " Retrying in " + this.retryDelay + "ms."); 15538 15539 // Retry 15540 var self = this; 15541 this.retryIncomingTimeoutID = setTimeout(function () { 15542 self.retryIncomingTimeoutID = -1; 15543 if (self.disposed 15544 || self.connectionState == net.user1.orbiter.ConnectionState.NOT_CONNECTED 15545 || self.connectionState == net.user1.orbiter.ConnectionState.DISCONNECTION_IN_PROGRESS) { 15546 return; 15547 } 15548 self.doRetryIncoming(); 15549 }, this.retryDelay); 15550 } 15551 15552 //============================================================================== 15553 // PROCESS DATA FROM THE SERVER 15554 //============================================================================== 15555 15556 /** @private */ 15557 net.user1.orbiter.HTTPConnection.prototype.processIncomingData = function (data) { 15558 if (this.disposed) return; 15559 var listeners; 15560 15561 this.dispatchReceiveData(data); 15562 15563 var upcs = new Array(); 15564 var upcEndTagIndex = data.indexOf("</U>"); 15565 // Empty responses are valid. 15566 if (upcEndTagIndex == -1 && data.length > 0) { 15567 this.orbiter.getLog().error("Invalid message received. No UPC found: [" + data + "]"); 15568 if (!this.isReady()) { 15569 // If invalid XML is received prior to achieving ready, then this 15570 // probably isn't a Union server, so disconnect. 15571 this.disconnect(); 15572 return; 15573 } 15574 } 15575 15576 while (upcEndTagIndex != -1) { 15577 upcs.push(data.substring(0, upcEndTagIndex+4)); 15578 data = data.substring(upcEndTagIndex+4); 15579 upcEndTagIndex = data.indexOf("</U>"); 15580 } 15581 for (var i = 0; i < upcs.length; i++) { 15582 this.dispatchEvent(new net.user1.orbiter.ConnectionEvent(net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, upcs[i])); 15583 } 15584 } 15585 15586 //============================================================================== 15587 // SERVER AFFINITY 15588 //============================================================================== 15589 /** @private */ 15590 net.user1.orbiter.HTTPConnection.prototype.applyAffinity = function (data) { 15591 net.user1.orbiter.Connection.prototype.applyAffinity.call(this); 15592 this.buildURL(); 15593 }; 15594 15595 //============================================================================== 15596 // TOSTRING 15597 //============================================================================== 15598 net.user1.orbiter.HTTPConnection.prototype.toString = function () { 15599 var s = "[" + this.connectionType + ", requested host: " + this.requestedHost 15600 + ", host: " + (this.host == null ? "" : this.host) 15601 + ", port: " + this.port 15602 + ", send-delay: " + this.getSendDelay() + "]"; 15603 return s; 15604 } 15605 15606 // ============================================================================= 15607 // DISPOSAL 15608 // ============================================================================= 15609 /** @private */ 15610 net.user1.orbiter.HTTPConnection.prototype.dispose = function () { 15611 this.doDispose(); 15612 this.stopSendDelayTimer(); 15613 net.user1.orbiter.Connection.prototype.dispose.call(this); 15614 } 15615 //============================================================================== 15616 // CLASS DECLARATION 15617 //============================================================================== 15618 /** 15619 * @class 15620 * 15621 * The HTTPIFrameConnection class is used by Orbiter to communicate with 15622 * Union Server over HTTP in browsers that do not support CORS. 15623 * Rather than using CORS, HTTPIFrameConnection bypasses cross-origin restrictions 15624 * by proxying communications through a hidden HTML iframe. 15625 * 15626 * For a list of events dispatched by HTTPDirectConnection, 15627 * {@link net.user1.orbiter.Connection}. 15628 * 15629 * For more information on HTTP communication with Union Server, see 15630 * the HTTPDirectConnection class. 15631 * 15632 * @extends net.user1.orbiter.HTTPConnection 15633 * 15634 * @see net.user1.orbiter.HTTPDirectConnection 15635 * @see net.user1.orbiter.WebSocketConnection 15636 * @see net.user1.orbiter.SecureHTTPDirectConnection 15637 * @see net.user1.orbiter.SecureHTTPIFrameConnection 15638 * @see net.user1.orbiter.SecureWebSocketConnection 15639 */ 15640 net.user1.orbiter.HTTPIFrameConnection = function (host, port, type) { 15641 // Invoke superclass constructor 15642 net.user1.orbiter.HTTPConnection.call(this, host, port, type || net.user1.orbiter.ConnectionType.HTTP); 15643 this.postMessageInited = false; 15644 this.iFrameReady = false; 15645 }; 15646 15647 //============================================================================== 15648 // INHERITANCE 15649 //============================================================================== 15650 net.user1.utils.extend(net.user1.orbiter.HTTPIFrameConnection, net.user1.orbiter.HTTPConnection); 15651 15652 //============================================================================== 15653 // POSTMESSAGE INITIALIZATION 15654 //============================================================================== 15655 /** @private */ 15656 net.user1.orbiter.HTTPIFrameConnection.prototype.initPostMessage = function () { 15657 if (this.postMessageInited) { 15658 throw new Error("[HTTPIFrameConnection] Illegal duplicate initialization attempt."); 15659 } 15660 var self = this; 15661 var win = this.orbiter.window; 15662 var errorMsg = null; 15663 15664 if (win == null) { 15665 errorMsg = "[HTTPIFrameConnection] Unable to create connection." 15666 + " No window object found."; 15667 } else { 15668 if (typeof win.addEventListener != "undefined") { 15669 // ...the standard way 15670 win.addEventListener("message", postMessageListener, false); 15671 } else if (typeof win.attachEvent != "undefined") { 15672 // ...the IE-specific way 15673 win.attachEvent("onmessage", postMessageListener); 15674 } else { 15675 errorMsg = "[HTTPIFrameConnection] Unable to create connection." 15676 + " No event listener registration method found on window object."; 15677 } 15678 } 15679 15680 if (errorMsg != null) { 15681 this.orbiter.getLog().error(errorMsg); 15682 throw new Error(errorMsg); 15683 } 15684 15685 /** @private */ 15686 function postMessageListener (e) { 15687 // The connection's host might have been reassigned (normally to an ip) due 15688 // to server affinity in a clustered deployment, so allow for posts from both the 15689 // requestedHost and the host. 15690 if (e.origin.indexOf("//" + self.host + (self.port == 80 ? "" : (":" + self.port))) == -1 15691 && e.origin.indexOf("//" + self.requestedHost + (self.port == 80 ? "" : (":" + self.port))) == -1) { 15692 self.orbiter.getLog().error("[CONNECTION] " + self.toString() 15693 + " Ignored message from unknown origin: " + e.origin); 15694 return; 15695 } 15696 15697 self.processPostMessage(e.data); 15698 } 15699 15700 this.postMessageInited = true; 15701 }; 15702 15703 //============================================================================== 15704 // IFRAME MANAGEMENT 15705 //============================================================================== 15706 /** @private */ 15707 net.user1.orbiter.HTTPIFrameConnection.prototype.makeIFrame = function () { 15708 if (typeof this.orbiter.window.document == "undefined") { 15709 var errorMsg = "[HTTPIFrameConnection] Unable to create connection." 15710 + " No document object found."; 15711 this.orbiter.getLog().error(errorMsg); 15712 throw new Error(errorMsg); 15713 } 15714 var doc = this.orbiter.window.document; 15715 15716 this.iFrameReady = false; 15717 if (this.iframe != null) { 15718 this.postToIFrame("dispose"); 15719 doc.body.removeChild(this.iframe); 15720 } 15721 this.iframe = doc.createElement('iframe'); 15722 this.iframe.width = "0px"; 15723 this.iframe.height = "0px"; 15724 this.iframe.border = "0px"; 15725 this.iframe.frameBorder = "0"; 15726 this.iframe.style.visibility = "hidden"; 15727 this.iframe.style.display = "none"; 15728 this.iframe.src = this.url + "/orbiter"; 15729 doc.body.appendChild(this.iframe); 15730 } 15731 15732 /** @private */ 15733 net.user1.orbiter.HTTPIFrameConnection.prototype.onIFrameReady = function () { 15734 this.beginReadyHandshake(); 15735 } 15736 15737 /** @private */ 15738 net.user1.orbiter.HTTPIFrameConnection.prototype.postToIFrame = function (cmd, data) { 15739 if (this.iframe && this.iFrameReady) { 15740 data = data == undefined ? "" : data; 15741 // In order to post to the iframe, the targetOrigin must match the iframe's origin 15742 this.iframe.contentWindow.postMessage(cmd + "," + data, this.iframe.contentWindow.location.href); 15743 } 15744 } 15745 15746 /** @private */ 15747 net.user1.orbiter.HTTPIFrameConnection.prototype.processPostMessage = function (postedData) { 15748 var delimiterIndex = postedData.indexOf(","); 15749 var cmd = postedData.substring(0, delimiterIndex); 15750 var data = postedData.substring(delimiterIndex+1); 15751 15752 switch (cmd) { 15753 case"ready": 15754 this.iFrameReady = true; 15755 this.onIFrameReady(); 15756 break; 15757 15758 case "hellocomplete": 15759 this.helloCompleteListener(data); 15760 break; 15761 15762 case "helloerror": 15763 this.helloErrorListener(); 15764 break; 15765 15766 case "outgoingcomplete": 15767 this.outgoingCompleteListener(); 15768 break; 15769 15770 case "outgoingerror": 15771 this.outgoingErrorListener(); 15772 break; 15773 15774 case "incomingcomplete": 15775 this.incomingCompleteListener(data); 15776 break; 15777 15778 case "incomingerror": 15779 this.incomingErrorListener(); 15780 break; 15781 } 15782 } 15783 15784 //============================================================================== 15785 // CONNECTION AND DISCONNECTION 15786 //============================================================================== 15787 net.user1.orbiter.HTTPIFrameConnection.prototype.connect = function () { 15788 if (!this.postMessageInited) { 15789 this.initPostMessage(); 15790 } 15791 15792 net.user1.orbiter.HTTPConnection.prototype.connect.call(this); 15793 this.makeIFrame(); 15794 }; 15795 15796 /** @private */ 15797 net.user1.orbiter.HTTPIFrameConnection.prototype.doRequestDeactivation = function() { 15798 this.postToIFrame("deactivate"); 15799 }; 15800 15801 //============================================================================== 15802 // UPC LISTENERS (IFRAME-SPECIFIC IMPLEMENTATION) 15803 //============================================================================== 15804 15805 /** @private */ 15806 net.user1.orbiter.HTTPIFrameConnection.prototype.u66 = function (serverVersion, 15807 sessionID, 15808 upcVersion, 15809 protocolCompatible) { 15810 net.user1.orbiter.Connection.prototype.u66.call(this, 15811 serverVersion, 15812 sessionID, 15813 upcVersion, 15814 protocolCompatible); 15815 if (this.iframe != null) { 15816 this.postToIFrame("sessionid", sessionID); 15817 } 15818 } 15819 15820 //============================================================================== 15821 // HELLO REQUEST MANAGEMENT 15822 //============================================================================== 15823 15824 /** @private */ 15825 net.user1.orbiter.HTTPIFrameConnection.prototype.doSendHello = function (helloString) { 15826 this.postToIFrame("sendhello", helloString); 15827 }; 15828 15829 /** @private */ 15830 net.user1.orbiter.HTTPIFrameConnection.prototype.doRetryHello = function () { 15831 this.postToIFrame("retryhello"); 15832 } 15833 15834 //============================================================================== 15835 // OUTGOING REQUEST MANAGEMENT 15836 //============================================================================== 15837 15838 /** @private */ 15839 net.user1.orbiter.HTTPIFrameConnection.prototype.doSendOutgoing = function (data) { 15840 this.postToIFrame("sendoutgoing", data); 15841 }; 15842 15843 /** @private */ 15844 net.user1.orbiter.HTTPIFrameConnection.prototype.doRetryOutgoing = function () { 15845 this.postToIFrame("retryoutgoing"); 15846 }; 15847 15848 //============================================================================== 15849 // INCOMING REQUEST MANAGEMENT 15850 //============================================================================== 15851 15852 /** @private */ 15853 net.user1.orbiter.HTTPIFrameConnection.prototype.doSendIncoming = function () { 15854 this.postToIFrame("sendincoming"); 15855 }; 15856 15857 /** @private */ 15858 net.user1.orbiter.HTTPIFrameConnection.prototype.doRetryIncoming = function () { 15859 this.postToIFrame("retryincoming"); 15860 }; 15861 15862 //============================================================================== 15863 // TOSTRING 15864 //============================================================================== 15865 net.user1.orbiter.HTTPIFrameConnection.prototype.toString = function () { 15866 var s = "[HTTPIFrameConnection, requested host: " + this.requestedHost 15867 + ", host: " + (this.host == null ? "" : this.host) 15868 + ", port: " + this.port 15869 + ", send-delay: " + this.getSendDelay() + "]"; 15870 return s; 15871 }; 15872 15873 //============================================================================== 15874 // DISPOSAL 15875 //============================================================================== 15876 /** @private */ 15877 net.user1.orbiter.HTTPIFrameConnection.prototype.doDispose = function () { 15878 this.postToIFrame("dispose"); 15879 }; 15880 //============================================================================== 15881 // CLASS DECLARATION 15882 //============================================================================== 15883 /** 15884 * @class 15885 * <p> 15886 * The HTTPDirectConnection class is used by Orbiter to communicate with 15887 * Union Server over HTTP; it uses CORS to bypass cross-origin restrictions 15888 * when Union Server is hosted on a domain that does not match the domain at 15889 * which the Orbiter client is hosted. Normally, developers need not use the 15890 * HTTPDirectConnection class directly, and should instead make connections 15891 * via the Orbiter class's connect() method. However, the 15892 * HTTPDirectConnection class is required for fine-grained connection configuration, 15893 * such as defining failover connections for multiple Union Servers 15894 * running at different host addresses. 15895 * </p> 15896 * 15897 * <p> 15898 * By default, Orbiter uses the WebSocketConnection class, not the 15899 * HTTPDirectConnection class, to communicate with Union Server. The 15900 * HTTPDirectConnection class is used as a backup connection 15901 * when the primary WebSocketConnection connection is blocked by a firewall. 15902 * However, on a very heavily loaded server with limited persistent socket 15903 * connections available, communicating with Union Server over HTTP--which uses 15904 * short-lived socket connections--can improve performance at the 15905 * expense of realtime responsiveness. To reduce server load when communicating 15906 * over HTTP, use HTTPDirectConnection's setSendDelay() method to decrease the 15907 * frequency of Orbiter's requests for updates from Union Server. Developers 15908 * that wish to use HTTP connections as the primary form of communication with 15909 * Union Server must do so by manually configuring connections via the 15910 * ConnectionManager class's addConnection() method.</p> 15911 * 15912 * <p> 15913 * In environments that do not support CORS (such as IE8 on Windows), Orbiter 15914 * conducts HTTP communications using HTTPIFrameConnection instead of HTTPDirectConnection. 15915 * </p> 15916 * 15917 * <p> 15918 * For secure HTTP and WebSocket communications, see SecureHTTPDirectConnection, 15919 * SecureHTTPIFrameConnection, and SecureWebSocketConnection. 15920 * </p> 15921 * 15922 * 15923 * For a list of events dispatched by HTTPDirectConnection, 15924 * {@link net.user1.orbiter.Connection}. 15925 * 15926 * @extends net.user1.orbiter.HTTPConnection 15927 * 15928 * @see net.user1.orbiter.Orbiter#connect 15929 * @see net.user1.orbiter.Orbiter#secureConnect 15930 * 15931 * @see net.user1.orbiter.SecureHTTPDirectConnection 15932 * @see net.user1.orbiter.SecureHTTPIFrameConnection 15933 * @see net.user1.orbiter.SecureWebSocketConnection 15934 */ 15935 net.user1.orbiter.HTTPDirectConnection = function (host, port, type) { 15936 // Invoke superclass constructor 15937 net.user1.orbiter.HTTPConnection.call(this, host, port, type || net.user1.orbiter.ConnectionType.HTTP); 15938 15939 this.outgoingRequestID = 0; 15940 this.incomingRequestID = 0; 15941 15942 this.lastOutgoingPostData = null; 15943 this.lastIncomingPostData = null; 15944 this.lastHelloPostData = null; 15945 15946 this.pendingRequests = []; 15947 }; 15948 15949 //============================================================================== 15950 // INHERITANCE 15951 //============================================================================== 15952 net.user1.utils.extend(net.user1.orbiter.HTTPDirectConnection, net.user1.orbiter.HTTPConnection); 15953 15954 15955 //============================================================================== 15956 // CONNECTION AND DISCONNECTION 15957 //============================================================================== 15958 net.user1.orbiter.HTTPDirectConnection.prototype.connect = function () { 15959 net.user1.orbiter.HTTPConnection.prototype.connect.call(this); 15960 this.beginReadyHandshake(); 15961 }; 15962 15963 //============================================================================== 15964 // HELLO REQUEST MANAGEMENT 15965 //============================================================================== 15966 15967 /** @private Abstract method implementation */ 15968 net.user1.orbiter.HTTPDirectConnection.prototype.doSendHello = function (helloString) { 15969 this.newHelloRequest(helloString); 15970 }; 15971 15972 /** @private Abstract method implementation */ 15973 net.user1.orbiter.HTTPDirectConnection.prototype.doRetryHello = function () { 15974 this.retryHello(); 15975 } 15976 15977 /** @private */ 15978 net.user1.orbiter.HTTPDirectConnection.prototype.newHelloRequest = function (data) { 15979 this.lastHelloPostData = this.createHelloPostData(encodeURIComponent(data)); 15980 this.transmitRequest(this.lastHelloPostData, 15981 net.user1.orbiter.HTTPDirectConnection.helloRequestReadystatechangeListener, 15982 net.user1.orbiter.HTTPDirectConnection.helloRequestErrorListener); 15983 } 15984 15985 /** @private */ 15986 net.user1.orbiter.HTTPDirectConnection.prototype.createHelloPostData = function (data) { 15987 return "mode=d" + "&data=" + data; 15988 } 15989 15990 /** @private */ 15991 net.user1.orbiter.HTTPDirectConnection.prototype.retryHello = function () { 15992 this.transmitRequest(this.lastHelloPostData, 15993 net.user1.orbiter.HTTPDirectConnection.helloRequestReadystatechangeListener, 15994 net.user1.orbiter.HTTPDirectConnection.helloRequestErrorListener); 15995 } 15996 15997 /** @private */ 15998 net.user1.orbiter.HTTPDirectConnection.helloRequestReadystatechangeListener = function (xhr, connection) { 15999 if (xhr.readyState == 4) { 16000 connection.removePendingRequest(xhr); 16001 if (xhr.status >= 200 && xhr.status <= 299) { 16002 connection.helloCompleteListener(xhr.responseText); 16003 } else { 16004 connection.helloErrorListener(); 16005 } 16006 } 16007 } 16008 16009 /** @private */ 16010 net.user1.orbiter.HTTPDirectConnection.helloRequestErrorListener = function (xhr, connection) { 16011 connection.removePendingRequest(xhr); 16012 connection.helloErrorListener(); 16013 } 16014 16015 //============================================================================== 16016 // OUTGOING REQUEST MANAGEMENT 16017 //============================================================================== 16018 16019 /** @private Abstract method implementation */ 16020 net.user1.orbiter.HTTPDirectConnection.prototype.doSendOutgoing = function (data) { 16021 this.newOutgoingRequest(data); 16022 }; 16023 16024 /** @private Abstract method implementation */ 16025 net.user1.orbiter.HTTPDirectConnection.prototype.doRetryOutgoing = function () { 16026 this.retryOutgoing(); 16027 }; 16028 16029 /** @private */ 16030 net.user1.orbiter.HTTPDirectConnection.prototype.newOutgoingRequest = function (data) { 16031 this.lastOutgoingPostData = this.createOutgoingPostData(encodeURIComponent(data)); 16032 this.transmitRequest(this.lastOutgoingPostData, 16033 net.user1.orbiter.HTTPDirectConnection.outgoingRequestReadystatechangeListener, 16034 net.user1.orbiter.HTTPDirectConnection.outgoingRequestErrorListener); 16035 } 16036 16037 /** @private */ 16038 net.user1.orbiter.HTTPDirectConnection.prototype.createOutgoingPostData = function (data) { 16039 this.outgoingRequestID++; 16040 return "rid=" + this.outgoingRequestID + "&sid=" + this.orbiter.getSessionID() + "&mode=s" + "&data=" + data; 16041 } 16042 16043 /** @private */ 16044 net.user1.orbiter.HTTPDirectConnection.prototype.retryOutgoing = function () { 16045 this.transmitRequest(this.lastOutgoingPostData, 16046 net.user1.orbiter.HTTPDirectConnection.outgoingRequestReadystatechangeListener, 16047 net.user1.orbiter.HTTPDirectConnection.outgoingRequestErrorListener); 16048 } 16049 16050 /** @private */ 16051 net.user1.orbiter.HTTPDirectConnection.outgoingRequestReadystatechangeListener = function (xhr, connection) { 16052 if (xhr.readyState == 4) { 16053 connection.removePendingRequest(xhr); 16054 if (xhr.status >= 200 && xhr.status <= 299) { 16055 connection.outgoingCompleteListener(); 16056 } else { 16057 connection.outgoingErrorListener(); 16058 } 16059 } 16060 } 16061 16062 /** @private */ 16063 net.user1.orbiter.HTTPDirectConnection.outgoingRequestErrorListener = function (xhr, connection) { 16064 connection.removePendingRequest(xhr); 16065 connection.outgoingErrorListener(); 16066 } 16067 16068 //============================================================================== 16069 // INCOMING REQUEST MANAGEMENT 16070 //============================================================================== 16071 16072 /** @private Abstract method implementation */ 16073 net.user1.orbiter.HTTPDirectConnection.prototype.doSendIncoming = function () { 16074 this.newIncomingRequest(); 16075 }; 16076 16077 /** @private Abstract method implementation */ 16078 net.user1.orbiter.HTTPDirectConnection.prototype.doRetryIncoming = function () { 16079 this.retryIncoming(); 16080 }; 16081 16082 /** @private */ 16083 net.user1.orbiter.HTTPDirectConnection.prototype.newIncomingRequest = function () { 16084 this.lastIncomingPostData = this.createIncomingPostData(); 16085 this.transmitRequest(this.lastIncomingPostData, 16086 net.user1.orbiter.HTTPDirectConnection.incomingRequestReadystatechangeListener, 16087 net.user1.orbiter.HTTPDirectConnection.incomingRequestErrorListener); 16088 } 16089 16090 /** @private */ 16091 net.user1.orbiter.HTTPDirectConnection.prototype.createIncomingPostData = function () { 16092 this.incomingRequestID++; 16093 return "rid=" + this.incomingRequestID + "&sid=" + this.orbiter.getSessionID() + "&mode=c"; 16094 } 16095 16096 /** @private */ 16097 net.user1.orbiter.HTTPDirectConnection.prototype.retryIncoming = function () { 16098 this.transmitRequest(this.lastIncomingPostData, 16099 net.user1.orbiter.HTTPDirectConnection.incomingRequestReadystatechangeListener, 16100 net.user1.orbiter.HTTPDirectConnection.incomingRequestErrorListener); 16101 } 16102 16103 /** @private */ 16104 net.user1.orbiter.HTTPDirectConnection.incomingRequestReadystatechangeListener = function (xhr, connection) { 16105 if (xhr.readyState == 4) { 16106 connection.removePendingRequest(xhr); 16107 if (xhr.status >= 200 && xhr.status <= 299) { 16108 connection.incomingCompleteListener(xhr.responseText); 16109 } else { 16110 connection.incomingErrorListener(); 16111 } 16112 } 16113 } 16114 16115 /** @private */ 16116 net.user1.orbiter.HTTPDirectConnection.incomingRequestErrorListener = function (xhr, connection) { 16117 connection.removePendingRequest(xhr); 16118 connection.incomingErrorListener(); 16119 } 16120 16121 //============================================================================== 16122 // XHR MANAGEMENT 16123 //============================================================================== 16124 /** @private */ 16125 net.user1.orbiter.HTTPDirectConnection.prototype.transmitRequest = function (data, 16126 readystatechangeListener, 16127 errorListener) { 16128 var self = this; 16129 var request; 16130 16131 if (typeof XDomainRequest != "undefined") { 16132 // IE 16133 request = new XDomainRequest(); 16134 request.onload = function () { 16135 request.readyState = 4; // Emulate standards-based API 16136 request.status = 200; 16137 readystatechangeListener(this, self) 16138 }; 16139 request.onerror = function () { 16140 errorListener(this, self); 16141 }; 16142 request.ontimeout = function () { 16143 errorListener(this, self); 16144 }; 16145 request.onprogress = function () {}; // Do nothing (required) 16146 } else { 16147 // All other standards-based browsers 16148 var request = new XMLHttpRequest(); 16149 this.pendingRequests.push(request); 16150 request.onreadystatechange = function () { 16151 readystatechangeListener(this, self); 16152 }; 16153 request.onerror = function () { 16154 errorListener(this, self); 16155 }; 16156 } 16157 // Call open before setting header 16158 request.open("POST", this.url); 16159 // Standards-based browsers (IE doesn't allow the setting of headers) 16160 if (typeof request.setRequestHeader != "undefined") { 16161 request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); 16162 } 16163 request.send(data); 16164 } 16165 16166 /** @private */ 16167 net.user1.orbiter.HTTPDirectConnection.prototype.removePendingRequest = function (request) { 16168 for (var i = this.pendingRequests.length; --i >= 0; ) { 16169 if (this.pendingRequests[i] === request) { 16170 this.pendingRequests.splice(i, 1); 16171 } 16172 } 16173 } 16174 16175 /** @private Abstract method implementation */ 16176 net.user1.orbiter.HTTPDirectConnection.prototype.doRequestDeactivation = function () { 16177 for (var i = this.pendingRequests.length; --i >= 0;) { 16178 try { 16179 this.pendingRequests[i].abort(); 16180 } catch (e) { 16181 // Do nothing 16182 } 16183 } 16184 this.pendingRequests = []; 16185 } 16186 16187 //============================================================================== 16188 // TOSTRING 16189 //============================================================================== 16190 net.user1.orbiter.HTTPDirectConnection.prototype.toString = function () { 16191 var s = "[HTTPDirectConnection, requested host: " + this.requestedHost 16192 + ", host: " + (this.host == null ? "" : this.host) 16193 + ", port: " + this.port 16194 + ", send-delay: " + this.getSendDelay() + "]"; 16195 return s; 16196 }; 16197 16198 //============================================================================== 16199 // DISPOSAL 16200 //============================================================================== 16201 /** @private */ 16202 net.user1.orbiter.HTTPDirectConnection.prototype.doDispose = function () { 16203 this.deactivateHTTPRequests(); 16204 }; 16205 //============================================================================== 16206 // CLASS DECLARATION 16207 //============================================================================== 16208 /** @class 16209 * <p> 16210 * The SecureHTTPDirectConnection class is identical to HTTPDirectConnection 16211 * except that it performs communications over HTTPS (i.e., an encrypted TLS or 16212 * SSL connection) rather than plain HTTP.</p> 16213 * 16214 * For a list of events dispatched by SecureHTTPDirectConnection, see 16215 * {@link net.user1.orbiter.Connection}. 16216 * 16217 * @extends net.user1.orbiter.HTTPDirectConnection 16218 * 16219 * @see net.user1.orbiter.HTTPDirectConnection 16220 */ 16221 net.user1.orbiter.SecureHTTPDirectConnection = function (host, port) { 16222 // Invoke superclass constructor 16223 net.user1.orbiter.HTTPDirectConnection.call(this, host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP); 16224 }; 16225 16226 //============================================================================== 16227 // INHERITANCE 16228 //============================================================================== 16229 net.user1.utils.extend(net.user1.orbiter.SecureHTTPDirectConnection, net.user1.orbiter.HTTPDirectConnection); 16230 16231 /** @private */ 16232 net.user1.orbiter.SecureHTTPDirectConnection.prototype.buildURL = function () { 16233 this.url = "https://" + this.host + ":" + this.port; 16234 }; 16235 16236 //============================================================================== 16237 // TOSTRING 16238 //============================================================================== 16239 net.user1.orbiter.SecureHTTPDirectConnection.prototype.toString = function () { 16240 var s = "[SecureHTTPDirectConnection, requested host: " + this.requestedHost 16241 + ", host: " + (this.host == null ? "" : this.host) 16242 + ", port: " + this.port 16243 + ", send-delay: " + this.getSendDelay() + "]"; 16244 return s; 16245 }; 16246 //============================================================================== 16247 // CLASS DECLARATION 16248 //============================================================================== 16249 /** 16250 * @class 16251 * 16252 * <p> 16253 * The SecureHTTPIFrameConnection class is identical to HTTPIFrameConnection 16254 * except that it performs communications over HTTPS (i.e., an encrypted TLS or 16255 * SSL connection) rather than plain HTTP.</p> 16256 * 16257 * For a list of events dispatched by SecureHTTPIFrameConnection, 16258 * see {@link net.user1.orbiter.Connection}. 16259 * 16260 * @extends net.user1.orbiter.HTTPIFrameConnection 16261 * 16262 * @see net.user1.orbiter.HTTPIFrameConnection 16263 */ 16264 net.user1.orbiter.SecureHTTPIFrameConnection = function (host, port) { 16265 // Invoke superclass constructor 16266 net.user1.orbiter.HTTPIFrameConnection.call(this, host, port, net.user1.orbiter.ConnectionType.SECURE_HTTP); 16267 }; 16268 16269 //============================================================================== 16270 // INHERITANCE 16271 //============================================================================== 16272 net.user1.utils.extend(net.user1.orbiter.SecureHTTPIFrameConnection, net.user1.orbiter.HTTPIFrameConnection); 16273 16274 /** @private */ 16275 net.user1.orbiter.SecureHTTPIFrameConnection.prototype.buildURL = function () { 16276 this.url = "https://" + this.host + ":" + this.port; 16277 }; 16278 16279 //============================================================================== 16280 // TOSTRING 16281 //============================================================================== 16282 net.user1.orbiter.SecureHTTPIFrameConnection.prototype.toString = function () { 16283 var s = "[SecureHTTPIFrameConnection, requested host: " + this.requestedHost 16284 + ", host: " + (this.host == null ? "" : this.host) 16285 + ", port: " + this.port 16286 + ", send-delay: " + this.getSendDelay() + "]"; 16287 return s; 16288 }; 16289 //============================================================================== 16290 // CLASS DECLARATION 16291 //============================================================================== 16292 /** @private */ 16293 net.user1.orbiter.MessageListener = function (listener, 16294 forRoomIDs, 16295 thisArg) { 16296 this.listener = listener; 16297 this.forRoomIDs = forRoomIDs; 16298 this.thisArg = thisArg; 16299 }; 16300 16301 //============================================================================== 16302 // INSTANCE METHODS 16303 //============================================================================== 16304 /** @private */ 16305 net.user1.orbiter.MessageListener.prototype.getListenerFunction = function () { 16306 return this.listener; 16307 }; 16308 16309 /** @private */ 16310 net.user1.orbiter.MessageListener.prototype.getForRoomIDs = function () { 16311 return this.forRoomIDs; 16312 }; 16313 16314 /** @private */ 16315 net.user1.orbiter.MessageListener.prototype.getThisArg = function () { 16316 return this.thisArg; 16317 }; 16318 16319 /** @private */ 16320 net.user1.orbiter.MessageListener.prototype.toString = function () { 16321 return "[object MessageListener]"; 16322 }; 16323 //============================================================================== 16324 // CLASS DECLARATION 16325 //============================================================================== 16326 /** @class */ 16327 net.user1.orbiter.MessageManager = function (log, connectionManager) { 16328 this.log = log; 16329 this.messageListeners = new Object(); 16330 this.removeListenersOnDisconnect = true; 16331 this.numMessagesSent = 0; 16332 this.numMessagesReceived = 0; 16333 this.currentConnection = null; 16334 this.connectionManager = connectionManager; 16335 this.connectionManager.addEventListener(net.user1.orbiter.ConnectionManagerEvent.SELECT_CONNECTION, 16336 this.selectConnectionListener, this); 16337 }; 16338 16339 //============================================================================== 16340 // INSTANCE METHODS 16341 //============================================================================== 16342 net.user1.orbiter.MessageManager.prototype.getNumMessagesReceived = function () { 16343 return this.numMessagesReceived; 16344 } 16345 16346 net.user1.orbiter.MessageManager.prototype.getNumMessagesSent = function () { 16347 return this.numMessagesSent; 16348 } 16349 16350 net.user1.orbiter.MessageManager.prototype.getTotalMessages = function () { 16351 return this.numMessagesSent + this.numMessagesReceived; 16352 } 16353 16354 /** @private */ 16355 net.user1.orbiter.MessageManager.prototype.selectConnectionListener = function (e) { 16356 if (this.currentConnection != null) { 16357 this.currentConnection.removeEventListener(net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, 16358 this.upcReceivedListener, this); 16359 this.currentConnection.removeEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, 16360 this.disconnectListener, this); 16361 this.currentConnection.removeEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, 16362 this.connectFailureListener, this); 16363 } 16364 16365 this.currentConnection = e.getConnection(); 16366 16367 this.currentConnection.addEventListener(net.user1.orbiter.ConnectionEvent.RECEIVE_UPC, 16368 this.upcReceivedListener, this); 16369 this.currentConnection.addEventListener(net.user1.orbiter.ConnectionEvent.DISCONNECT, 16370 this.disconnectListener, this); 16371 this.currentConnection.addEventListener(net.user1.orbiter.ConnectionEvent.CONNECT_FAILURE, 16372 this.connectFailureListener, this); 16373 } 16374 16375 /** @private */ 16376 net.user1.orbiter.MessageManager.prototype.disconnectListener = function (e) { 16377 this.cleanupAfterClosedConnection(e.target); 16378 } 16379 16380 /** @private */ 16381 net.user1.orbiter.MessageManager.prototype.connectFailureListener = function (e) { 16382 this.cleanupAfterClosedConnection(e.target); 16383 } 16384 16385 /** @private */ 16386 net.user1.orbiter.MessageManager.prototype.cleanupAfterClosedConnection = function (connection) { 16387 var listenerList; 16388 if (this.removeListenersOnDisconnect) { 16389 this.log.info("[MESSAGE_MANAGER] Removing registered message listeners."); 16390 for (var message in this.messageListeners) { 16391 listenerList = this.messageListeners[message]; 16392 for (var p in listenerList) { 16393 this.removeMessageListener(message, listenerList[p].getListenerFunction()); 16394 } 16395 } 16396 } else { 16397 this.log.warn("[MESSAGE_MANAGER] Leaving message listeners registered. \n" 16398 + "Be sure to remove any unwanted message listeners manually."); 16399 } 16400 16401 this.numMessagesReceived = 0; 16402 this.numMessagesSent = 0; 16403 } 16404 16405 net.user1.orbiter.MessageManager.prototype.sendUPC = function (message) { 16406 // Quit if the connection isn't ready... 16407 if (!this.connectionManager.isReady()) { 16408 this.log.warn("[MESSAGE_MANAGER] Connection not ready. UPC not sent. Message: " 16409 + message); 16410 return; 16411 } 16412 16413 // Build the UPC to send. 16414 var theUPC = "<U><M>" + message + "</M>"; 16415 var a; 16416 16417 if (arguments.length > 1) { 16418 theUPC += "<L>"; 16419 for (var i = 1; i < arguments.length; i++) { 16420 a = arguments[i]; 16421 a = a == undefined ? "" : a.toString(); 16422 // Wrap any non-filter argument that contains a start tag ("<") in CDATA 16423 if (a.indexOf("<") != -1) { 16424 if (a.indexOf('<f t=') != 0) { 16425 a = "<![CDATA[" + a + "]]>"; 16426 } 16427 } 16428 theUPC += "<A>" + a + "</A>"; 16429 } 16430 theUPC += "</L>"; 16431 } 16432 theUPC += "</U>"; 16433 16434 // Count the message 16435 this.numMessagesSent++; 16436 16437 // Send the UPC to the server 16438 this.log.debug("[MESSAGE_MANAGER] UPC sent: " + theUPC); 16439 this.connectionManager.getActiveConnection().send(theUPC); 16440 }; 16441 16442 /** @private */ 16443 net.user1.orbiter.MessageManager.prototype.sendUPCObject = function (upc) { 16444 var args = upc.args.slice(); 16445 args.unshift(upc.method); 16446 this.sendUPC.apply(this, args); 16447 }; 16448 16449 /** @private */ 16450 net.user1.orbiter.MessageManager.prototype.upcReceivedListener = function (e) { 16451 this.numMessagesReceived++; 16452 16453 var upc = e.getUPC(); 16454 this.log.debug("[MESSAGE_MANAGER] UPC received: " + upc ); 16455 16456 var method; 16457 var upcArgs = new Array(); 16458 16459 var closeMTagIndex = upc.indexOf("</M>"); 16460 method = upc.substring(6, closeMTagIndex); 16461 16462 var searchBeginIndex = upc.indexOf("<A>", closeMTagIndex); 16463 var closeATagIndex; 16464 var arg; 16465 while (searchBeginIndex != -1) { 16466 closeATagIndex = upc.indexOf("</A>", searchBeginIndex); 16467 arg = upc.substring(searchBeginIndex+3, closeATagIndex); 16468 if (arg.indexOf("<![CDATA[") == 0) { 16469 arg = arg.substr(9, arg.length-12); 16470 } 16471 upcArgs.push(arg); 16472 searchBeginIndex = upc.indexOf("<A>", closeATagIndex); 16473 } 16474 16475 this.notifyMessageListeners(method, upcArgs); 16476 }; 16477 16478 net.user1.orbiter.MessageManager.prototype.addMessageListener = function (message, 16479 listener, 16480 thisArg, 16481 forRoomIDs) { 16482 if (forRoomIDs != null) { 16483 var typeString = Object.prototype.toString.call(forRoomIDs); 16484 if (typeString != "[object Array]") { 16485 throw new Error("[MESSAGE_MANAGER] Illegal argument type " + typeString 16486 + " supplied for addMessageListener()'s forRoomIDs" 16487 + " parameter. Value must be an Array."); 16488 } 16489 } 16490 16491 // Each message gets a list of MessageListener objects. 16492 // If this message has no such list, make one. 16493 if (this.messageListeners[message] === undefined) { 16494 this.messageListeners[message] = new Array(); 16495 } 16496 var listenerArray = this.messageListeners[message]; 16497 16498 // Quit if the listener is already registered 16499 if (this.hasMessageListener(message, listener)) { 16500 return false; 16501 } 16502 16503 // Add the listener 16504 var newListener = new net.user1.orbiter.MessageListener(listener, 16505 forRoomIDs === undefined ? null : forRoomIDs, 16506 thisArg); 16507 listenerArray.push(newListener); 16508 return true; 16509 }; 16510 16511 net.user1.orbiter.MessageManager.prototype.removeMessageListener = function (message, 16512 listener) { 16513 // Quit if the message has no listeners 16514 var listenerArray = this.messageListeners[message]; 16515 if (listenerArray == null) { 16516 return false; 16517 } 16518 16519 // Remove the listener 16520 var foundListener; 16521 for (var i = 0; i < listenerArray.length; i++) { 16522 if (listenerArray[i].getListenerFunction() == listener) { 16523 foundListener = true; 16524 listenerArray.splice(i, 1); 16525 break; 16526 } 16527 } 16528 16529 // Delete the listeners array if it's now empty 16530 if (listenerArray.length == 0) { 16531 delete this.messageListeners[message]; 16532 } 16533 16534 return foundListener; 16535 }; 16536 16537 net.user1.orbiter.MessageManager.prototype.hasMessageListener = function (message, 16538 listener) { 16539 // Quit if the message has no listeners 16540 var listenerArray = this.messageListeners[message]; 16541 if (listenerArray == null) { 16542 return false; 16543 } 16544 16545 // Check for the listener 16546 for (var i = 0; i < listenerArray.length; i++) { 16547 if (listenerArray[i].getListenerFunction() 16548 == listener) { 16549 return true; 16550 } 16551 } 16552 return false; 16553 }; 16554 16555 net.user1.orbiter.MessageManager.prototype.getMessageListeners = function (message) { 16556 return this.messageListeners[message] != undefined ? this.messageListeners[message] : []; 16557 }; 16558 16559 /** @private */ 16560 net.user1.orbiter.MessageManager.prototype.notifyMessageListeners = function (message, args) { 16561 // Retrieve the list of listeners for this message. 16562 var listeners = this.messageListeners[message]; 16563 // If there are no listeners registered, then quit 16564 if (listeners === undefined) { 16565 // Log a warning if it's not a UPC 16566 if (!(message.charAt(0) == "u" && parseInt(message.substring(1)) > 1)) { 16567 this.log.warn("Message delivery failed. No listeners found. Message: " + 16568 message + ". Arguments: " + args.join()); 16569 } 16570 return; 16571 } else { 16572 listeners = listeners.slice(0); 16573 } 16574 var numListeners = listeners.length; 16575 for (var i = 0; i < numListeners; i++) { 16576 listeners[i].getListenerFunction().apply(listeners[i].getThisArg(), args); 16577 } 16578 }; 16579 16580 net.user1.orbiter.MessageManager.prototype.dispose = function () { 16581 this.log.info("[MESSAGE_MANAGER] Disposing resources."); 16582 this.log = null; 16583 this.orbiter = null; 16584 this.messageListeners = null; 16585 this.numMessagesSent = 0; 16586 this.numMessagesReceived = 0; 16587 this.currentConnection = null; 16588 } 16589 16590 net.user1.orbiter.MessageManager.prototype.toString = function () { 16591 return "[object MessageManager]"; 16592 }; 16593 16594 //============================================================================== 16595 // UPC CONSTANTS 16596 //============================================================================== 16597 /** @class */ 16598 net.user1.orbiter.UPC = new Object(); 16599 16600 // CLIENT TO SERVER 16601 /** @constant */ 16602 net.user1.orbiter.UPC.SEND_MESSAGE_TO_ROOMS = "u1"; 16603 /** @constant */ 16604 net.user1.orbiter.UPC.SEND_MESSAGE_TO_CLIENTS = "u2"; 16605 /** @constant */ 16606 net.user1.orbiter.UPC.SET_CLIENT_ATTR = "u3"; 16607 /** @constant */ 16608 net.user1.orbiter.UPC.JOIN_ROOM = "u4"; 16609 /** @constant */ 16610 net.user1.orbiter.UPC.SET_ROOM_ATTR = "u5"; 16611 /** @constant */ 16612 net.user1.orbiter.UPC.LEAVE_ROOM = "u10"; 16613 /** @constant */ 16614 net.user1.orbiter.UPC.CREATE_ACCOUNT = "u11"; 16615 /** @constant */ 16616 net.user1.orbiter.UPC.REMOVE_ACCOUNT = "u12"; 16617 /** @constant */ 16618 net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD = "u13"; 16619 /** @constant */ 16620 net.user1.orbiter.UPC.LOGIN = "u14"; 16621 /** @constant */ 16622 net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT = "u18"; 16623 /** @constant */ 16624 net.user1.orbiter.UPC.SYNC_TIME = "u19"; 16625 /** @constant */ 16626 net.user1.orbiter.UPC.GET_ROOMLIST_SNAPSHOT = "u21"; 16627 /** @constant */ 16628 net.user1.orbiter.UPC.CREATE_ROOM = "u24"; 16629 /** @constant */ 16630 net.user1.orbiter.UPC.REMOVE_ROOM = "u25"; 16631 /** @constant */ 16632 net.user1.orbiter.UPC.WATCH_FOR_ROOMS = "u26"; 16633 /** @constant */ 16634 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS = "u27"; 16635 /** @constant */ 16636 net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT = "u55"; 16637 /** @constant */ 16638 net.user1.orbiter.UPC.SEND_MESSAGE_TO_SERVER = "u57"; 16639 /** @constant */ 16640 net.user1.orbiter.UPC.OBSERVE_ROOM = "u58"; 16641 /** @constant */ 16642 net.user1.orbiter.UPC.STOP_OBSERVING_ROOM = "u61"; 16643 /** @constant */ 16644 net.user1.orbiter.UPC.SET_ROOM_UPDATE_LEVELS = "u64"; 16645 /** @constant */ 16646 net.user1.orbiter.UPC.CLIENT_HELLO = "u65"; 16647 /** @constant */ 16648 net.user1.orbiter.UPC.REMOVE_ROOM_ATTR = "u67"; 16649 /** @constant */ 16650 net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR = "u69"; 16651 /** @constant */ 16652 net.user1.orbiter.UPC.SEND_ROOMMODULE_MESSAGE = "u70"; 16653 /** @constant */ 16654 net.user1.orbiter.UPC.SEND_SERVERMODULE_MESSAGE = "u71"; 16655 /** @constant */ 16656 net.user1.orbiter.UPC.TERMINATE_SESSION = "u83"; 16657 /** @constant */ 16658 net.user1.orbiter.UPC.LOGOFF = "u86"; 16659 /** @constant */ 16660 net.user1.orbiter.UPC.GET_CLIENTLIST_SNAPSHOT = "u91"; 16661 /** @constant */ 16662 net.user1.orbiter.UPC.WATCH_FOR_CLIENTS = "u92"; 16663 /** @constant */ 16664 net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS = "u93"; 16665 /** @constant */ 16666 net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT = "u94"; 16667 /** @constant */ 16668 net.user1.orbiter.UPC.OBSERVE_CLIENT = "u95"; 16669 /** @constant */ 16670 net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT = "u96"; 16671 /** @constant */ 16672 net.user1.orbiter.UPC.GET_ACCOUNTLIST_SNAPSHOT = "u97"; 16673 /** @constant */ 16674 net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS = "u98"; 16675 /** @constant */ 16676 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS = "u99"; 16677 /** @constant */ 16678 net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT = "u100"; 16679 /** @constant */ 16680 net.user1.orbiter.UPC.OBSERVE_ACCOUNT = "u121"; 16681 /** @constant */ 16682 net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT = "u122"; 16683 /** @constant */ 16684 net.user1.orbiter.UPC.ADD_ROLE = "u133"; 16685 /** @constant */ 16686 net.user1.orbiter.UPC.REMOVE_ROLE = "u135"; 16687 /** @constant */ 16688 net.user1.orbiter.UPC.KICK_CLIENT = "u149"; 16689 /** @constant */ 16690 net.user1.orbiter.UPC.BAN = "u137"; 16691 /** @constant */ 16692 net.user1.orbiter.UPC.UNBAN = "u139"; 16693 /** @constant */ 16694 net.user1.orbiter.UPC.GET_BANNED_LIST_SNAPSHOT = "u141"; 16695 /** @constant */ 16696 net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES = "u143"; 16697 /** @constant */ 16698 net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES = "u145"; 16699 /** @constant */ 16700 net.user1.orbiter.UPC.GET_NODELIST_SNAPSHOT = "u165"; 16701 /** @constant */ 16702 net.user1.orbiter.UPC.GET_GATEWAYS_SNAPSHOT = "u167"; 16703 16704 // SERVER TO CLIENT 16705 /** @constant */ 16706 net.user1.orbiter.UPC.JOINED_ROOM = "u6"; 16707 /** @constant */ 16708 net.user1.orbiter.UPC.RECEIVE_MESSAGE = "u7"; 16709 /** @constant */ 16710 net.user1.orbiter.UPC.CLIENT_ATTR_UPDATE = "u8"; 16711 /** @constant */ 16712 net.user1.orbiter.UPC.ROOM_ATTR_UPDATE = "u9"; 16713 /** @constant */ 16714 net.user1.orbiter.UPC.CLIENT_METADATA = "u29"; 16715 /** @constant */ 16716 net.user1.orbiter.UPC.CREATE_ROOM_RESULT = "u32"; 16717 /** @constant */ 16718 net.user1.orbiter.UPC.REMOVE_ROOM_RESULT = "u33"; 16719 /** @constant */ 16720 net.user1.orbiter.UPC.CLIENTCOUNT_SNAPSHOT = "u34"; 16721 /** @constant */ 16722 net.user1.orbiter.UPC.CLIENT_ADDED_TO_ROOM = "u36"; 16723 /** @constant */ 16724 net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_ROOM = "u37"; 16725 /** @constant */ 16726 net.user1.orbiter.UPC.ROOMLIST_SNAPSHOT = "u38"; 16727 /** @constant */ 16728 net.user1.orbiter.UPC.ROOM_ADDED = "u39"; 16729 /** @constant */ 16730 net.user1.orbiter.UPC.ROOM_REMOVED = "u40"; 16731 /** @constant */ 16732 net.user1.orbiter.UPC.WATCH_FOR_ROOMS_RESULT = "u42"; 16733 /** @constant */ 16734 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ROOMS_RESULT = "u43"; 16735 /** @constant */ 16736 net.user1.orbiter.UPC.LEFT_ROOM = "u44"; 16737 /** @constant */ 16738 net.user1.orbiter.UPC.CHANGE_ACCOUNT_PASSWORD_RESULT = "u46"; 16739 /** @constant */ 16740 net.user1.orbiter.UPC.CREATE_ACCOUNT_RESULT = "u47"; 16741 /** @constant */ 16742 net.user1.orbiter.UPC.REMOVE_ACCOUNT_RESULT = "u48"; 16743 /** @constant */ 16744 net.user1.orbiter.UPC.LOGIN_RESULT = "u49"; 16745 /** @constant */ 16746 net.user1.orbiter.UPC.SERVER_TIME_UPDATE = "u50"; 16747 /** @constant */ 16748 net.user1.orbiter.UPC.ROOM_SNAPSHOT = "u54"; 16749 /** @constant */ 16750 net.user1.orbiter.UPC.OBSERVED_ROOM = "u59"; 16751 /** @constant */ 16752 net.user1.orbiter.UPC.GET_ROOM_SNAPSHOT_RESULT = "u60"; 16753 /** @constant */ 16754 net.user1.orbiter.UPC.STOPPED_OBSERVING_ROOM = "u62"; 16755 /** @constant */ 16756 net.user1.orbiter.UPC.CLIENT_READY = "u63"; 16757 /** @constant */ 16758 net.user1.orbiter.UPC.SERVER_HELLO = "u66"; 16759 /** @constant */ 16760 net.user1.orbiter.UPC.JOIN_ROOM_RESULT = "u72"; 16761 /** @constant */ 16762 net.user1.orbiter.UPC.SET_CLIENT_ATTR_RESULT = "u73"; 16763 /** @constant */ 16764 net.user1.orbiter.UPC.SET_ROOM_ATTR_RESULT = "u74"; 16765 /** @constant */ 16766 net.user1.orbiter.UPC.GET_CLIENTCOUNT_SNAPSHOT_RESULT = "u75"; 16767 /** @constant */ 16768 net.user1.orbiter.UPC.LEAVE_ROOM_RESULT = "u76"; 16769 /** @constant */ 16770 net.user1.orbiter.UPC.OBSERVE_ROOM_RESULT = "u77"; 16771 /** @constant */ 16772 net.user1.orbiter.UPC.STOP_OBSERVING_ROOM_RESULT = "u78"; 16773 /** @constant */ 16774 net.user1.orbiter.UPC.ROOM_ATTR_REMOVED = "u79"; 16775 /** @constant */ 16776 net.user1.orbiter.UPC.REMOVE_ROOM_ATTR_RESULT = "u80"; 16777 /** @constant */ 16778 net.user1.orbiter.UPC.CLIENT_ATTR_REMOVED = "u81"; 16779 /** @constant */ 16780 net.user1.orbiter.UPC.REMOVE_CLIENT_ATTR_RESULT = "u82"; 16781 /** @constant */ 16782 net.user1.orbiter.UPC.SESSION_TERMINATED = "u84"; 16783 /** @constant */ 16784 net.user1.orbiter.UPC.SESSION_NOT_FOUND = "u85"; 16785 /** @constant */ 16786 net.user1.orbiter.UPC.LOGOFF_RESULT = "u87"; 16787 /** @constant */ 16788 net.user1.orbiter.UPC.LOGGED_IN = "u88"; 16789 /** @constant */ 16790 net.user1.orbiter.UPC.LOGGED_OFF = "u89"; 16791 /** @constant */ 16792 net.user1.orbiter.UPC.ACCOUNT_PASSWORD_CHANGED = "u90"; 16793 /** @constant */ 16794 net.user1.orbiter.UPC.CLIENTLIST_SNAPSHOT = "u101"; 16795 /** @constant */ 16796 net.user1.orbiter.UPC.CLIENT_ADDED_TO_SERVER = "u102"; 16797 /** @constant */ 16798 net.user1.orbiter.UPC.CLIENT_REMOVED_FROM_SERVER = "u103"; 16799 /** @constant */ 16800 net.user1.orbiter.UPC.CLIENT_SNAPSHOT = "u104"; 16801 /** @constant */ 16802 net.user1.orbiter.UPC.OBSERVE_CLIENT_RESULT = "u105"; 16803 /** @constant */ 16804 net.user1.orbiter.UPC.STOP_OBSERVING_CLIENT_RESULT = "u106"; 16805 /** @constant */ 16806 net.user1.orbiter.UPC.WATCH_FOR_CLIENTS_RESULT = "u107"; 16807 /** @constant */ 16808 net.user1.orbiter.UPC.STOP_WATCHING_FOR_CLIENTS_RESULT = "u108"; 16809 /** @constant */ 16810 net.user1.orbiter.UPC.WATCH_FOR_ACCOUNTS_RESULT = "u109"; 16811 /** @constant */ 16812 net.user1.orbiter.UPC.STOP_WATCHING_FOR_ACCOUNTS_RESULT = "u110"; 16813 /** @constant */ 16814 net.user1.orbiter.UPC.ACCOUNT_ADDED = "u111"; 16815 /** @constant */ 16816 net.user1.orbiter.UPC.ACCOUNT_REMOVED = "u112"; 16817 /** @constant */ 16818 net.user1.orbiter.UPC.JOINED_ROOM_ADDED_TO_CLIENT = "u113"; 16819 /** @constant */ 16820 net.user1.orbiter.UPC.JOINED_ROOM_REMOVED_FROM_CLIENT = "u114"; 16821 /** @constant */ 16822 net.user1.orbiter.UPC.GET_CLIENT_SNAPSHOT_RESULT = "u115"; 16823 /** @constant */ 16824 net.user1.orbiter.UPC.GET_ACCOUNT_SNAPSHOT_RESULT = "u116"; 16825 /** @constant */ 16826 net.user1.orbiter.UPC.OBSERVED_ROOM_ADDED_TO_CLIENT = "u117"; 16827 /** @constant */ 16828 net.user1.orbiter.UPC.OBSERVED_ROOM_REMOVED_FROM_CLIENT = "u118"; 16829 /** @constant */ 16830 net.user1.orbiter.UPC.CLIENT_OBSERVED = "u119"; 16831 /** @constant */ 16832 net.user1.orbiter.UPC.STOPPED_OBSERVING_CLIENT = "u120"; 16833 /** @constant */ 16834 net.user1.orbiter.UPC.OBSERVE_ACCOUNT_RESULT = "u123"; 16835 /** @constant */ 16836 net.user1.orbiter.UPC.ACCOUNT_OBSERVED = "u124"; 16837 /** @constant */ 16838 net.user1.orbiter.UPC.STOP_OBSERVING_ACCOUNT_RESULT = "u125"; 16839 /** @constant */ 16840 net.user1.orbiter.UPC.STOPPED_OBSERVING_ACCOUNT = "u126"; 16841 /** @constant */ 16842 net.user1.orbiter.UPC.ACCOUNT_LIST_UPDATE = "u127"; 16843 /** @constant */ 16844 net.user1.orbiter.UPC.UPDATE_LEVELS_UPDATE = "u128"; 16845 /** @constant */ 16846 net.user1.orbiter.UPC.CLIENT_OBSERVED_ROOM = "u129"; 16847 /** @constant */ 16848 net.user1.orbiter.UPC.CLIENT_STOPPED_OBSERVING_ROOM = "u130"; 16849 /** @constant */ 16850 net.user1.orbiter.UPC.ROOM_OCCUPANTCOUNT_UPDATE = "u131"; 16851 /** @constant */ 16852 net.user1.orbiter.UPC.ROOM_OBSERVERCOUNT_UPDATE = "u132"; 16853 /** @constant */ 16854 net.user1.orbiter.UPC.ADD_ROLE_RESULT = "u134"; 16855 /** @constant */ 16856 net.user1.orbiter.UPC.REMOVE_ROLE_RESULT = "u136"; 16857 /** @constant */ 16858 net.user1.orbiter.UPC.BAN_RESULT = "u138"; 16859 /** @constant */ 16860 net.user1.orbiter.UPC.UNBAN_RESULT = "u140"; 16861 /** @constant */ 16862 net.user1.orbiter.UPC.BANNED_LIST_SNAPSHOT = "u142"; 16863 /** @constant */ 16864 net.user1.orbiter.UPC.WATCH_FOR_BANNED_ADDRESSES_RESULT = "u144"; 16865 /** @constant */ 16866 net.user1.orbiter.UPC.STOP_WATCHING_FOR_BANNED_ADDRESSES_RESULT = "u146"; 16867 /** @constant */ 16868 net.user1.orbiter.UPC.BANNED_ADDRESS_ADDED = "u147"; 16869 /** @constant */ 16870 net.user1.orbiter.UPC.BANNED_ADDRESS_REMOVED = "u148"; 16871 /** @constant */ 16872 net.user1.orbiter.UPC.KICK_CLIENT_RESULT = "u150"; 16873 /** @constant */ 16874 net.user1.orbiter.UPC.SERVERMODULELIST_SNAPSHOT = "u152"; 16875 /** @constant */ 16876 net.user1.orbiter.UPC.GET_UPC_STATS_SNAPSHOT_RESULT = "u155"; 16877 /** @constant */ 16878 net.user1.orbiter.UPC.UPC_STATS_SNAPSHOT = "u156"; 16879 /** @constant */ 16880 net.user1.orbiter.UPC.RESET_UPC_STATS_RESULT = "u158"; 16881 /** @constant */ 16882 net.user1.orbiter.UPC.WATCH_FOR_PROCESSED_UPCS_RESULT = "u160"; 16883 /** @constant */ 16884 net.user1.orbiter.UPC.PROCESSED_UPC_ADDED = "u161"; 16885 /** @constant */ 16886 net.user1.orbiter.UPC.STOP_WATCHING_FOR_PROCESSED_UPCS_RESULT = "u163"; 16887 /** @constant */ 16888 net.user1.orbiter.UPC.CONNECTION_REFUSED = "u164"; 16889 /** @constant */ 16890 net.user1.orbiter.UPC.NODELIST_SNAPSHOT = "u166"; 16891 /** @constant */ 16892 net.user1.orbiter.UPC.GATEWAYS_SNAPSHOT = "u168"; 16893 //============================================================================== 16894 // LOADED FLAG 16895 //============================================================================== 16896 /** 16897 * @constant 16898 * 16899 * Indicates that Orbiter has finished loading. 16900 */ 16901 net.user1.orbiter.LOADED = true; 16902 16903 })((typeof window == "undefined") ? this : window); 16904