UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

657 lines (654 loc) 29.6 kB
import { ReplaySubject, mergeMap, take } from 'rxjs'; import { webSocket } from 'rxjs/webSocket'; import { LogLevel } from '../diagnostics/log-level'; import { Logging } from '../diagnostics/logging'; import { EnvironmentModule } from '../manifest/environment-modules'; import { headerConstants } from './http-constants'; import { Net } from './net'; /** * The state of Websocket connection. */ export var WebsocketStreamConnectionState; (function (WebsocketStreamConnectionState) { /** * Initializing. */ WebsocketStreamConnectionState[WebsocketStreamConnectionState["Initializing"] = 1] = "Initializing"; /** * Connected. */ WebsocketStreamConnectionState[WebsocketStreamConnectionState["Connected"] = 2] = "Connected"; /** * Disconnected. */ WebsocketStreamConnectionState[WebsocketStreamConnectionState["Disconnected"] = 3] = "Disconnected"; /** * Failed. */ WebsocketStreamConnectionState[WebsocketStreamConnectionState["Failed"] = 4] = "Failed"; /** * Not configured. */ WebsocketStreamConnectionState[WebsocketStreamConnectionState["NotConfigured"] = 5] = "NotConfigured"; })(WebsocketStreamConnectionState || (WebsocketStreamConnectionState = {})); /** * The state of Websocket stream packet. */ export var WebsocketStreamState; (function (WebsocketStreamState) { /** * Empty packet. */ WebsocketStreamState[WebsocketStreamState["Noop"] = 1] = "Noop"; /** * Data packet. */ WebsocketStreamState[WebsocketStreamState["Data"] = 2] = "Data"; /** * Error packet. (reserved for socket level error communication if any) */ WebsocketStreamState[WebsocketStreamState["Error"] = 3] = "Error"; })(WebsocketStreamState || (WebsocketStreamState = {})); /** * The request state of data such as CIM and PowerShell stream. */ export var WebsocketStreamDataRequestState; (function (WebsocketStreamDataRequestState) { /** * empty packet. */ WebsocketStreamDataRequestState[WebsocketStreamDataRequestState["Noop"] = 1] = "Noop"; /** * Data packet. */ WebsocketStreamDataRequestState[WebsocketStreamDataRequestState["Normal"] = 2] = "Normal"; /** * Cancel */ WebsocketStreamDataRequestState[WebsocketStreamDataRequestState["Cancel"] = 3] = "Cancel"; })(WebsocketStreamDataRequestState || (WebsocketStreamDataRequestState = {})); /** * The response state of data such as CIM and PowerShell stream. */ export var WebsocketStreamDataState; (function (WebsocketStreamDataState) { /** * empty packet. */ WebsocketStreamDataState[WebsocketStreamDataState["Noop"] = 1] = "Noop"; /** * Completed packet. */ WebsocketStreamDataState[WebsocketStreamDataState["Completed"] = 2] = "Completed"; /** * Data packet. */ WebsocketStreamDataState[WebsocketStreamDataState["Data"] = 3] = "Data"; /** * Error */ WebsocketStreamDataState[WebsocketStreamDataState["Error"] = 4] = "Error"; /** * Cancelled */ WebsocketStreamDataState[WebsocketStreamDataState["Cancelled"] = 5] = "Cancelled"; })(WebsocketStreamDataState || (WebsocketStreamDataState = {})); export var WebsocketStreamName; (function (WebsocketStreamName) { WebsocketStreamName["CimStreamName"] = "SME-CIM"; WebsocketStreamName["PowerShellStreamName"] = "SME-PowerShell"; WebsocketStreamName["SshStreamName"] = "SME-SSH"; WebsocketStreamName["SystemStreamName"] = "System"; })(WebsocketStreamName || (WebsocketStreamName = {})); ; /** * Websocket Stream Processor class. */ export class WebsocketStreamProcessor { observer; target; options; /** * Holding result if waitCompleted option is specified for multiple instances. */ response; /** * Track closing state. */ closing; /** * Track closed state. */ closed; /** * Track observer end call by unsubscribe or observer completion. */ end; /** * Sent once. */ sendOnce; /** * Initializes a new instance of the CimProcessor class. * @param observer Observer to send back result to caller. * @param target Stream Target object. * @param options Options for Cim stream query. */ constructor(observer, target, options) { this.observer = observer; this.target = target; this.options = options; } /** * Push the result to the observer. * @param result the result of TData. */ next(result) { this.observer?.next(result); this.sendOnce = true; } /** * Complete the observer. */ complete() { this.closing = true; this.observer?.complete(); this.closed = true; } /** * Error the observer. */ error(error) { this.closing = true; this.observer?.error(error); this.closed = true; } } /** * The Websocket stream class. */ export class WebsocketStream { gateway; static logSourceName = 'WebsocketStream'; static maxConnectionRetries = 10; static reconnectWaitTime = 500; socketStateRaw = WebsocketStreamConnectionState.Disconnected; socketState = new ReplaySubject(); socket; connectionRetries = WebsocketStream.maxConnectionRetries; handlers = new Map(); strings = MsftSme.getStrings().MsftSmeShell.Core.WebsocketStream; /** * Initializes a new instance of the WebsocketStream class. * * @param gateway the gateway connection object. */ constructor(gateway) { this.gateway = gateway; // initialize only after gateway data was populated via RPC. this.gateway.initialize().pipe(mergeMap(() => this.gateway.navigationReadyObservable), take(1)).subscribe(() => { // enable websocket stream only when the module added the options at initialization. const global = MsftSme.self(); if (!global.Init.websocket && !global.Init.sshWebsocket) { this.socketState.next(WebsocketStreamConnectionState.NotConfigured); this.socketStateRaw = WebsocketStreamConnectionState.NotConfigured; return; } this.initialize(true); }); } /** * Register the processor for the stream name. * @param name the name of stream. * @param handler the handler to process packet. */ registerProcessor(name, handler) { this.handlers.set(name, handler); } /** * Send next stream data to websocket. * * @param streamName the stream name. * @param data the data to send. * @param options the options. */ sendNext(streamName, data, options) { if (!this.socket) { throw new Error('WebsocketStream: socket is not ready.'); } const packet = { streamName, state: WebsocketStreamState.Data, data, options }; this.debugLog('Socket sending data.', packet); this.socket.next(JSON.stringify(packet)); } /** * Send error stream data to websocket. * * @param streamName the stream name. * @param error the error to send. * @param options the options. */ sendError(streamName, error, options) { if (!this.socket) { throw new Error('WebsocketStream: socket is not ready.'); } const packet = { streamName, state: WebsocketStreamState.Error, data: error, options }; this.debugLog('Socket sending error.', packet); this.socket.next(JSON.stringify(packet)); } /** * Get target data. * @param authorizationManager the authorization manager. * @param nodeName the node Name * @param endpoint the endpoint data. * @return WebsocketStreamDataTarget target data. */ getTarget(authorizationManager, nodeName, endpoint) { const headers = authorizationManager.createTokenHeaders(nodeName); if (endpoint) { headers[headerConstants.POWERSHELL_ENDPOINT] = endpoint; } const target = { nodeName, headers }; return target; } initialize(firstTime) { // get gateway socket url. const gatewaySocketUrl = this.gateway.gatewayUrl.replace('http', 'ws'); const moduleName = MsftSme.self().Init.moduleName; let url = Net.streamSocket.format(gatewaySocketUrl, moduleName); if (EnvironmentModule.isGatewayV200) { url = Net.streamSocketV200.format(gatewaySocketUrl, moduleName); } const isSsh = MsftSme.self().Init.sshWebsocket; if (isSsh) { url = Net.sshStreamSocket.format(gatewaySocketUrl); } this.debugLog('Socket initializing...: {0}'.format(url)); if (!firstTime) { this.handlers.forEach((value) => value.reset()); } // create stream socket. this.socketState.next(WebsocketStreamConnectionState.Initializing); this.socket = webSocket({ url: url, openObserver: { next: () => { this.debugLog('Socket opened: {0}'.format(url)); this.socketState.next(WebsocketStreamConnectionState.Connected); this.socketStateRaw = WebsocketStreamConnectionState.Connected; this.connectionRetries = WebsocketStream.maxConnectionRetries; } }, closeObserver: { next: () => { this.debugLog('Socket closed: {0}'.format(url)); this.socketState.next(WebsocketStreamConnectionState.Disconnected); this.socketStateRaw = WebsocketStreamConnectionState.Disconnected; this.reconnect(new Error(this.strings.Common.ConnectionRetiesError.message)); } }, // for compatibility with older version of rxjs websocket serializer: (value) => value }); this.socket.subscribe({ next: received => { const message = received; this.debugLog('Socket received data.', message); if (message.state === WebsocketStreamState.Data) { const handler = this.handlers.get(message.streamName); if (handler) { handler.process(message.data); } else { throw new Error(this.strings.Common.HandlerRegistrationError.message.format(message.streamName)); } } else if (message.state === WebsocketStreamState.Error) { let errorMessage = this.strings.Common.CommunicationError.message; if (message.data && message.data.error && message.data.error.message) { errorMessage = this.strings.Common.CommunicationErrorDetail.message.format(message.data.error.message); } Logging.log({ level: LogLevel.Error, source: WebsocketStream.logSourceName, message: errorMessage }); this.reconnect(new Error(errorMessage)); } }, error: error => this.reconnect(error) }); } dispose() { if (this.socket) { this.socket.unsubscribe(); this.socket = null; } } reconnect(error) { if (this.connectionRetries-- > 0) { this.dispose(); setTimeout(() => this.initialize(false), WebsocketStream.reconnectWaitTime); } else { this.socketState.next(WebsocketStreamConnectionState.Failed); throw error; } } debugLog(message, object) { Logging.log({ level: LogLevel.Debug, source: WebsocketStream.logSourceName, message: message }); if (object) { Logging.debug(object); } } } //# sourceMappingURL=websocket-stream.js.map // SIG // Begin signature block // SIG // MIIoKwYJKoZIhvcNAQcCoIIoHDCCKBgCAQExDzANBglg // SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor // SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC // SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg // SIG // l7gLfg9FnCzv4hqrqh6M7WntCYb5pa4/YXICbOcWJFug // SIG // gg12MIIF9DCCA9ygAwIBAgITMwAABARsdAb/VysncgAA // SIG // AAAEBDANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV // SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH // SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv // SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT // SIG // aWduaW5nIFBDQSAyMDExMB4XDTI0MDkxMjIwMTExNFoX // SIG // DTI1MDkxMTIwMTExNFowdDELMAkGA1UEBhMCVVMxEzAR // SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v // SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv // SIG // bjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9u // SIG // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA // SIG // tCg32mOdDA6rBBnZSMwxwXegqiDEUFlvQH9Sxww07hY3 // SIG // w7L52tJxLg0mCZjcszQddI6W4NJYb5E9QM319kyyE0l8 // SIG // EvA/pgcxgljDP8E6XIlgVf6W40ms286Cr0azaA1f7vaJ // SIG // jjNhGsMqOSSSXTZDNnfKs5ENG0bkXeB2q5hrp0qLsm/T // SIG // WO3oFjeROZVHN2tgETswHR3WKTm6QjnXgGNj+V6rSZJO // SIG // /WkTqc8NesAo3Up/KjMwgc0e67x9llZLxRyyMWUBE9co // SIG // T2+pUZqYAUDZ84nR1djnMY3PMDYiA84Gw5JpceeED38O // SIG // 0cEIvKdX8uG8oQa047+evMfDRr94MG9EWwIDAQABo4IB // SIG // czCCAW8wHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYB // SIG // BQUHAwMwHQYDVR0OBBYEFPIboTWxEw1PmVpZS+AzTDwo // SIG // oxFOMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQLExVNaWNy // SIG // b3NvZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzMDAx // SIG // Mis1MDI5MjMwHwYDVR0jBBgwFoAUSG5k5VAF04KqFzc3 // SIG // IrVtqMp1ApUwVAYDVR0fBE0wSzBJoEegRYZDaHR0cDov // SIG // L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWlj // SIG // Q29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNybDBhBggr // SIG // BgEFBQcBAQRVMFMwUQYIKwYBBQUHMAKGRWh0dHA6Ly93 // SIG // d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj // SIG // Q29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNydDAMBgNV // SIG // HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQCI5g/S // SIG // KUFb3wdUHob6Qhnu0Hk0JCkO4925gzI8EqhS+K4umnvS // SIG // BU3acsJ+bJprUiMimA59/5x7WhJ9F9TQYy+aD9AYwMtb // SIG // KsQ/rst+QflfML+Rq8YTAyT/JdkIy7R/1IJUkyIS6srf // SIG // G1AKlX8n6YeAjjEb8MI07wobQp1F1wArgl2B1mpTqHND // SIG // lNqBjfpjySCScWjUHNbIwbDGxiFr93JoEh5AhJqzL+8m // SIG // onaXj7elfsjzIpPnl8NyH2eXjTojYC9a2c4EiX0571Ko // SIG // mhENF3RtR25A7/X7+gk6upuE8tyMy4sBkl2MUSF08U+E // SIG // 2LOVcR8trhYxV1lUi9CdgEU2CxODspdcFwxdT1+G8YNc // SIG // gzHyjx3BNSI4nOZcdSnStUpGhCXbaOIXfvtOSfQX/UwJ // SIG // oruhCugvTnub0Wna6CQiturglCOMyIy/6hu5rMFvqk9A // SIG // ltIJ0fSR5FwljW6PHHDJNbCWrZkaEgIn24M2mG1M/Ppb // SIG // /iF8uRhbgJi5zWxo2nAdyDBqWvpWxYIoee/3yIWpquVY // SIG // cYGhJp/1I1sq/nD4gBVrk1SKX7Do2xAMMO+cFETTNSJq // SIG // fTSSsntTtuBLKRB5mw5qglHKuzapDiiBuD1Zt4QwxA/1 // SIG // kKcyQ5L7uBayG78kxlVNNbyrIOFH3HYmdH0Pv1dIX/Mq // SIG // 7avQpAfIiLpOWwcbjzCCB3owggVioAMCAQICCmEOkNIA // SIG // AAAAAAMwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYT // SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH // SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y // SIG // cG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290 // SIG // IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTEx // SIG // MDcwODIwNTkwOVoXDTI2MDcwODIxMDkwOVowfjELMAkG // SIG // A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO // SIG // BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m // SIG // dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0 // SIG // IENvZGUgU2lnbmluZyBQQ0EgMjAxMTCCAiIwDQYJKoZI // SIG // hvcNAQEBBQADggIPADCCAgoCggIBAKvw+nIQHC6t2G6q // SIG // ghBNNLrytlghn0IbKmvpWlCquAY4GgRJun/DDB7dN2vG // SIG // EtgL8DjCmQawyDnVARQxQtOJDXlkh36UYCRsr55JnOlo // SIG // XtLfm1OyCizDr9mpK656Ca/XllnKYBoF6WZ26DJSJhIv // SIG // 56sIUM+zRLdd2MQuA3WraPPLbfM6XKEW9Ea64DhkrG5k // SIG // NXimoGMPLdNAk/jj3gcN1Vx5pUkp5w2+oBN3vpQ97/vj // SIG // K1oQH01WKKJ6cuASOrdJXtjt7UORg9l7snuGG9k+sYxd // SIG // 6IlPhBryoS9Z5JA7La4zWMW3Pv4y07MDPbGyr5I4ftKd // SIG // gCz1TlaRITUlwzluZH9TupwPrRkjhMv0ugOGjfdf8NBS // SIG // v4yUh7zAIXQlXxgotswnKDglmDlKNs98sZKuHCOnqWbs // SIG // YR9q4ShJnV+I4iVd0yFLPlLEtVc/JAPw0XpbL9Uj43Bd // SIG // D1FGd7P4AOG8rAKCX9vAFbO9G9RVS+c5oQ/pI0m8GLhE // SIG // fEXkwcNyeuBy5yTfv0aZxe/CHFfbg43sTUkwp6uO3+xb // SIG // n6/83bBm4sGXgXvt1u1L50kppxMopqd9Z4DmimJ4X7Iv // SIG // hNdXnFy/dygo8e1twyiPLI9AN0/B4YVEicQJTMXUpUMv // SIG // dJX3bvh4IFgsE11glZo+TzOE2rCIF96eTvSWsLxGoGyY // SIG // 0uDWiIwLAgMBAAGjggHtMIIB6TAQBgkrBgEEAYI3FQEE // SIG // AwIBADAdBgNVHQ4EFgQUSG5k5VAF04KqFzc3IrVtqMp1 // SIG // ApUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD // SIG // VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j // SIG // BBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0f // SIG // BFMwUTBPoE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQu // SIG // Y29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0 // SIG // MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRS // SIG // MFAwTgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9z // SIG // b2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0MjAx // SIG // MV8yMDExXzAzXzIyLmNydDCBnwYDVR0gBIGXMIGUMIGR // SIG // BgkrBgEEAYI3LgMwgYMwPwYIKwYBBQUHAgEWM2h0dHA6 // SIG // Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvZG9jcy9w // SIG // cmltYXJ5Y3BzLmh0bTBABggrBgEFBQcCAjA0HjIgHQBM // SIG // AGUAZwBhAGwAXwBwAG8AbABpAGMAeQBfAHMAdABhAHQA // SIG // ZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEA // SIG // Z/KGpZjgVHkaLtPYdGcimwuWEeFjkplCln3SeQyQwWVf // SIG // Liw++MNy0W2D/r4/6ArKO79HqaPzadtjvyI1pZddZYSQ // SIG // fYtGUFXYDJJ80hpLHPM8QotS0LD9a+M+By4pm+Y9G6XU // SIG // tR13lDni6WTJRD14eiPzE32mkHSDjfTLJgJGKsKKELuk // SIG // qQUMm+1o+mgulaAqPyprWEljHwlpblqYluSD9MCP80Yr // SIG // 3vw70L01724lruWvJ+3Q3fMOr5kol5hNDj0L8giJ1h/D // SIG // Mhji8MUtzluetEk5CsYKwsatruWy2dsViFFFWDgycSca // SIG // f7H0J/jeLDogaZiyWYlobm+nt3TDQAUGpgEqKD6CPxNN // SIG // ZgvAs0314Y9/HG8VfUWnduVAKmWjw11SYobDHWM2l4bf // SIG // 2vP48hahmifhzaWX0O5dY0HjWwechz4GdwbRBrF1HxS+ // SIG // YWG18NzGGwS+30HHDiju3mUv7Jf2oVyW2ADWoUa9WfOX // SIG // pQlLSBCZgB/QACnFsZulP0V3HjXG0qKin3p6IvpIlR+r // SIG // +0cjgPWe+L9rt0uX4ut1eBrs6jeZeRhL/9azI2h15q/6 // SIG // /IvrC4DqaTuv/DDtBEyO3991bWORPdGdVk5Pv4BXIqF4 // SIG // ETIheu9BCrE/+6jMpF3BoYibV3FWTkhFwELJm3ZbCoBI // SIG // a/15n8G9bW1qyVJzEw16UM0xghoNMIIaCQIBATCBlTB+ // SIG // MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv // SIG // bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj // SIG // cm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNy // SIG // b3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExAhMzAAAE // SIG // BGx0Bv9XKydyAAAAAAQEMA0GCWCGSAFlAwQCAQUAoIGu // SIG // MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG // SIG // AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3 // SIG // DQEJBDEiBCAfLz3uW/sIu+KzidatpSodBRshTm/EKS3b // SIG // 6DRJIbciFjBCBgorBgEEAYI3AgEMMTQwMqAUgBIATQBp // SIG // AGMAcgBvAHMAbwBmAHShGoAYaHR0cDovL3d3dy5taWNy // SIG // b3NvZnQuY29tMA0GCSqGSIb3DQEBAQUABIIBAGVmcWgL // SIG // 8GuKeUejNk9hDHX1ThV4bk7grUk8+e9VT1YDUyNoBGMA // SIG // edN3idjJfLy4UPDJS3pnuZvmscvNzCVBv+zwBY5cuCtC // SIG // b6vKBYAh+GOSkySO0C14ENtqPu0sHLi3HkirbtXBzgha // SIG // qkqhbSWmatlq6x+b4aBGR3wp4qbpMOHotWkWtv+iI1pg // SIG // 35PaA2v5bvajjrFXK7Swwe+zGJ0jpeljfdPXb05RkuBh // SIG // o3LlMqKA3gudegC3bZ1gy/Urddhor1ez//E+znpZwjOo // SIG // luyfrma4nD5uhOOQshj5Gc7wlvnI61TlGiAe9UlELn3q // SIG // zyj6sQa3/B9Uzcp0yzMXL8he4xChgheXMIIXkwYKKwYB // SIG // BAGCNwMDATGCF4Mwghd/BgkqhkiG9w0BBwKgghdwMIIX // SIG // bAIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBUgYLKoZIhvcN // SIG // AQkQAQSgggFBBIIBPTCCATkCAQEGCisGAQQBhFkKAwEw // SIG // MTANBglghkgBZQMEAgEFAAQgV0MVZOzJvvMd5Fl2GcOd // SIG // eqfJQR4I++uvCgzFrvBaNwUCBmeuM89BDxgTMjAyNTAy // SIG // MjAxNTI4MzYuMzg5WjAEgAIB9KCB0aSBzjCByzELMAkG // SIG // A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO // SIG // BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m // SIG // dCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0 // SIG // IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNo // SIG // aWVsZCBUU1MgRVNOOkUwMDItMDVFMC1EOTQ3MSUwIwYD // SIG // VQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl // SIG // oIIR7TCCByAwggUIoAMCAQICEzMAAAHuBdMCMLKanacA // SIG // AQAAAe4wDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMC // SIG // VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT // SIG // B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw // SIG // b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt // SIG // U3RhbXAgUENBIDIwMTAwHhcNMjMxMjA2MTg0NTQ0WhcN // SIG // MjUwMzA1MTg0NTQ0WjCByzELMAkGA1UEBhMCVVMxEzAR // SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v // SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv // SIG // bjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3Bl // SIG // cmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNO // SIG // OkUwMDItMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3Nv // SIG // ZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG // SIG // 9w0BAQEFAAOCAg8AMIICCgKCAgEAvvG8pdeihImvMSku // SIG // L1S+0RDjkey82Ai1xLVoHqsjlZa87hM/gKAmuLQRhEo2 // SIG // x01xAnjDsD/Uz3imimpX01OV0ho6SYaRsefX8TCaE2Fj // SIG // 88w9DtkQJcgZjgQZoiw10Q0CS9UbbgI7woi7pVUHojyP // SIG // Fe/h4U0d/dU2wtW3kscF33SiamNaJ4w2sKgyQJrcLAP4 // SIG // Jql4B8BfX2VnMCkrl4mQU21OX3Jt24YZUTcOXdOC3deW // SIG // Vs1Zf1Q6f4kXqxqNiLP9FsJ/2t3hjnR6738CG35OpVas // SIG // GzUBNdTnnZ9rr0YylhMHq1y+9Drg2fLy88a8tMhHb0PJ // SIG // MvlX6vJnxF0vdO2O6zfx2F+nArAtrKMlxtzsArSwO6NP // SIG // /pCiWbjqw+R1K0s95H6oA5Zlsuu8/GWT45IgwtXWFtYz // SIG // e+7eYkpeVqdRygaeyVPEYkSPr2NotXG+V9kRJMN1qzVv // SIG // 426H1xLPbeG4HfslPLICp/TLVZ0OubOkBu9jP8mlGRth // SIG // zCN9bZvZqKB9vbzwTvYwzDiLtC8M1E5CFn5YHf7xFn0z // SIG // XD1hEI+37FrkqFbid7gasDZkUqZkA80nzGiM7srNKb1d // SIG // YxVqrasMAnGmP1l7G/2sZMQf8wk3R0gVCfE5t4uDzPbJ // SIG // Irp12PnEqh+fI1pKR22ywNzn7LO3viWzIypk3XI5kpG+ // SIG // aDfKlNcCAwEAAaOCAUkwggFFMB0GA1UdDgQWBBQQiM0/ // SIG // GtncIJ69+8Xftr9f3HamCDAfBgNVHSMEGDAWgBSfpxVd // SIG // AF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQ // SIG // hk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz // SIG // L2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB // SIG // JTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwG // SIG // CCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5j // SIG // b20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUt // SIG // U3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMB // SIG // Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4G // SIG // A1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEA // SIG // d2cgL2thCjlklaQZ2JM1/H/BmY2jrOe+xfaNeAJ4fZSs // SIG // urUt+MF6D1xMkKdb9YiO6yc2VRu66VM52stp/XLH596e // SIG // su5GJB6rUroAhpk4ogZMIRX0gcijyNPDJJYLybyk2W+u // SIG // 98hn6RcD40MGXiOhD4/zgLaWJE+yFF6jJItQkTCSoHmO // SIG // MFEQnHCLo3VkZKFb+Cd6v/OyhNKj0JgEfX6jDcYyN2Qp // SIG // VcQOMIjN7TVZUWxfUoKTp41aNz/yOafCXeNYTUlQsf/I // SIG // 96jO2i0irQ8zhFDbPmbY4c55mYFHe/wFhw4cAR3S+e0y // SIG // PYe54mZHzmTl53GLCsRuIK8k7IVOhurAGKW6nTBP/v4N // SIG // bnq+1RiB1LS6t1tAJ5vJQH0vT6rYbJGbeeCRdvAh3bBa // SIG // v+11QbRZcS/yoHEMpSTZ4mvmp4sVButMlA7dxTBkiSN+ // SIG // MRvTR7M9waaklrnhrSYUOWTdCvI7tLzVYBfg79ObIqz4 // SIG // NH7Uin/RVRAqfd6PKIBePI4fAk/wd9pc9Q+k67pOBM3M // SIG // OxNTobTjH+wx4DzFn+ljnWJ3/h2kice2U1wibFuaDpDN // SIG // LC4rcQaUqRnI9mI5zc5wqbBD2WrdIfune7pUWlkeURwF // SIG // MhRUPY0WuylmjRnRC07Ppx0pWI2HkKSuUEl44oHSpS0D // SIG // wZV/vczqBgCYaGX66Y6uJ0AwggdxMIIFWaADAgECAhMz // SIG // AAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUA // SIG // MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu // SIG // Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV // SIG // TWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylN // SIG // aWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp // SIG // dHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAx // SIG // ODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX // SIG // YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD // SIG // VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV // SIG // BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw // SIG // MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA // SIG // 5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1 // SIG // V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeF // SIG // RiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDc // SIG // wUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus // SIG // 9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130 // SIG // /o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHI // SIG // NSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTes // SIG // y+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGp // SIG // F1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+ // SIG // /NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fz // SIG // pk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNO // SIG // wTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLi // SIG // Mxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5 // SIG // UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9Q // SIG // BXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6H // SIG // XtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIG // SIG // CSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYE // SIG // FCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSf // SIG // pxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEG // SIG // DCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRw // SIG // Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv // SIG // UmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUH // SIG // AwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD // SIG // VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j // SIG // BBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0f // SIG // BE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQu // SIG // Y29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0 // SIG // XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBK // SIG // BggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQu // SIG // Y29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0w // SIG // Ni0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1Vffwq // SIG // reEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1 // SIG // OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpT // SIG // Td2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinL // SIG // btg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l // SIG // 9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJ // SIG // w7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2Fz // SIG // Lixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7 // SIG // hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY // SIG // 3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFX // SIG // SVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFU // SIG // a2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz // SIG // /gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/ // SIG // AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1 // SIG // ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328 // SIG // y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEG // SIG // ahC0HVUzWLOhcGbyoYIDUDCCAjgCAQEwgfmhgdGkgc4w // SIG // gcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n // SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN // SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p // SIG // Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNV // SIG // BAsTHm5TaGllbGQgVFNTIEVTTjpFMDAyLTA1RTAtRDk0 // SIG // NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg // SIG // U2VydmljZaIjCgEBMAcGBSsOAwIaAxUAiKOm1Tb35RcW // SIG // 1Fgg0N2GCsujvpOggYMwgYCkfjB8MQswCQYDVQQGEwJV // SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH // SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv // SIG // cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T // SIG // dGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAOth // SIG // Q4YwIhgPMjAyNTAyMjAwNjAwMzhaGA8yMDI1MDIyMTA2 // SIG // MDAzOFowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA62FD // SIG // hgIBADAKAgEAAgIOWwIB/zAHAgEAAgITLjAKAgUA62KV // SIG // BgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZ // SIG // CgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqG // SIG // SIb3DQEBCwUAA4IBAQCJm5tqhfJNGnCU6pzufu7oSZKV // SIG // kv+qUT6NPmaIzZj91+DmimfBb0YmUjGNsZHYZ+ZZcsRX // SIG // kTw2s3ZNXOL4R4lwl1wsBp3LeZhHAaaHYdDY4fJAGy5F // SIG // RPOKH2123IGxiX7HVxJ9cpcgc8n5XjhyYVLDie2DU4E4 // SIG // k+SMqAXEkt9Y+mnPhbyFkwjij9kjLMnRozEem8SSrQNk // SIG // wpvhm3a1Nv33xw2xGJbO2QW++gn7WtZyN8hQytYCvPpE // SIG // HQwmlEpURvW+AE3UaWklCnpbF3IlBTmJNxYxkxl2EWZP // SIG // RJrr1zrZ3TOAUhcChoymljIQT2I5ozMrbqD0wP4/eS7q // SIG // mD5oCPXlMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC // SIG // VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT // SIG // B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw // SIG // b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt // SIG // U3RhbXAgUENBIDIwMTACEzMAAAHuBdMCMLKanacAAQAA // SIG // Ae4wDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJ // SIG // AzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQg // SIG // 34gtae3RZkSdEB87CLGqvxQfKcedE9jU9ibW0+kma5Aw // SIG // gfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCBPUHcU // SIG // lYX6vlXX/gz7PuRCJAc/aAkvzkH5R5FUYX4wITCBmDCB // SIG // gKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo // SIG // aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK // SIG // ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT // SIG // HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMz // SIG // AAAB7gXTAjCymp2nAAEAAAHuMCIEIL8alJrYHTS+brqa // SIG // XihIgQYMTOuyPr8/IrVb9C65hr9FMA0GCSqGSIb3DQEB // SIG // CwUABIICAAhBxAPo42UpCOIv9nms88YjYRsQd8DPpSFO // SIG // RwXwLhCR/2na+cLf05juIB94/JWe0/B0SBGIKm6Mx473 // SIG // JQM5VS+9eY+Z3y/ezZ1kaeo1kd5DFZdgvOLafTkLvBc4 // SIG // KQRzxVy8HPIjVnop7i6eQgnN+h44C5nsu/1uVmIxJqRN // SIG // jJudDxTog7czWjbX9bodd5rwQip2a0oeQS/DRkpI2pm6 // SIG // ZHxiREl/nKIre2l/zJ52A9EaFIRW99VidcKU/uN2Gu7T // SIG // g5SrqSjbsuyF0n41wbpKEKbNS+xU0zo15LGgWvvNauf+ // SIG // GRl1P9tcXn0q3hFOvkDrxOzLv3yjFLyIQ/OrFN1kkWku // SIG // bT/yvbBIZLfVpgFVCV+lxCa7drh6WhBUXhP5dc2v6a2t // SIG // RbTaPpkaP158wTbHFO5JMm54HT/okfDXTP1OAMQrxQL0 // SIG // 1K3ubxpP7sEYiN2esL1CcQzhk6bWyjJNHXwIW+hodPz7 // SIG // RZPRmBw891gJF3+3P8WkyPge7zZaSmfA7rJdPW+/hBNI // SIG // o9HJjJ3NUvAIv4YREa8OH/Sd5sEjlJU3rrVC4GhwlZBk // SIG // TXP7hlXLZYVhXsT+/SLtMjKDloS0ETNGjQK+5c4PkcYR // SIG // WQ/3jT/aD3Eldob2c4P7bbautXZVb/aud/ajLoGdty92 // SIG // IVaw+UyS+TR3v8e1/rmKLEOgErPBwwBq // SIG // End signature block