function init() { window.File && window.FileReader && window.FileList && window.Blob || $.log("The File APIs are not fully supported in this browser."); } function VMconnection(vm_conn, id) { function onOpen(evt) { sendClientHello(); } function onClose(evt) { -1 !== tmrId && (clearInterval(tmrId), tmrId = -1); } function onError(evt) { $.log(evt.data); } function sendClientHello() { client_hello[0] = 16, client_hello[1] = devType, setupSessionKey(), that.doSend(client_hello); } function setupSessionKey() { for (var sessionKey = document.cookie.replace(/(?:(?:^|.*;\s*)sessionKey\s*\=\s*([^;]*).*$)|^.*$/, "$1"), i = 0; i < sessionKey.length; i++) client_hello[2 + i] = sessionKey.charCodeAt(i); } function keepalive(ka) { const KEEPALIVE = 2; ka ? flags |= KEEPALIVE : flags &= -3; } function disconnect(dc) { const DISCONNECT = 4; dc ? flags |= DISCONNECT : flags &= -5; } this.file, this.media_sz, this.fdd_state = fddStateEnum.MEDIA_NOT_PRESENT, this.event_state = 0, this.media, this.wsUri = iLO.getBaseUrl("", "wss:") + "wss/vmport"; var websocket, flags, devType = vm_conn, vmConnId = id, client_hello = new Uint8Array(34), tmrId = -1, that = this; this.getDevType = function() { return devType; }, this.getVmConnId = function() { return vmConnId; }, this.getWebsocket = function() { return websocket; }, this.getTmrId = function() { return tmrId; }, this.setTmrId = function(id) { tmrId = id; }, this.setMedia_sz = function(size) { this.media_sz = size; }, this.setFile = function(f) { this.file = f; }, this.createWebSocket = function() { if (websocket && iLO.isFunction(websocket.close)) try { websocket.onclose = function() {}, websocket.close(); } catch (e) {} try { websocket = new WebSocket(this.wsUri), websocket.binaryType = "arraybuffer", websocket.onopen = function(evt) { onOpen(evt); }, websocket.onmessage = function(evt) { that.onMessage(evt); }, websocket.onerror = function(evt) { onError(evt); }, websocket.onclose = function(evt) { onClose(evt); }; } catch (e) { var dlgMsg = iLO.translateString("IRC.error.newWebsocketEx") + "
Error: " + e.Message, msgBox = { titleKey: "IRC.error.newWebsocketExTitle", icon: myIcons.critical, message: dlgMsg }; return void iLO.alert(msgBox); } }, this.client_test_unit_ready = function() { this.fdd_state === fddStateEnum.MEDIA_NOT_PRESENT ? that.sendRespHeader(2, 58, 0, 0) : this.fdd_state === fddStateEnum.MEDIA_CHANGED ? (that.sendRespHeader(6, 40, 0, 0), this.fdd_state = 2) : that.sendRespHeader(0, 0, 0, 0); }, this.sendKeepAlive = function() { keepalive(!0), that.sendRespHeader(0, 0, 0, 0), keepalive(!1); }, this.closeVMconnection = function() { websocket && 1 === websocket.readyState && (showIrcToast({ text: iLO.translateString("vm.processVMEject"), type: "ok", position: "bottom-right" }), disconnect(!0), that.sendRespHeader(0, 0, 0, 0), disconnect(!1)); }, this.sendRespHeader = function(sense_key, asc, ascq, length) { var magic = 195936478, resp_hdr = new Uint8Array(16); resp_hdr[0] = 255 & magic, resp_hdr[1] = magic >> 8 & 255, resp_hdr[2] = magic >> 16 & 255, resp_hdr[3] = magic >> 24 & 255, resp_hdr[4] = 255 & flags, resp_hdr[5] = flags >> 8 & 255, resp_hdr[6] = flags >> 16 & 255, resp_hdr[7] = flags >> 24 & 255, resp_hdr[8] = this.media, resp_hdr[9] = sense_key, resp_hdr[10] = asc, resp_hdr[11] = ascq, resp_hdr[12] = 255 & length, resp_hdr[13] = length >> 8 & 255, resp_hdr[14] = length >> 16 & 255, resp_hdr[15] = length >> 24 & 255, that.doSend(resp_hdr); }, this.doSend = function(message) { websocket && websocket.send(message); }; } function VMconnection_fd(vm_conn, id) { VMconnection.call(this, vm_conn, id), this.buffer = new Uint8Array(131072), this.lba, this.writeLen; } function ejectDevice(obj) { var id = $(obj).data("id"); vm_conn[id].closeVMconnection(); } function imgFileHandler(fileInput) { var dlgMsg = "", id = $(fileInput).data("id"); if (/(\.img)$/i.exec(fileInput.value)) vm_conn[id] = new VMconnection_fd(vmConnType.FLOPPY, id), vm_conn[id].setFile(fileInput.files[0]), vm_conn[id].setMedia_sz(fileInput.files[0].size), vm_conn[id].createWebSocket(); else if (/(\.iso)$/i.exec(fileInput.value)) vm_conn[id] = new VMconnection(vmConnType.CDROM, id), vm_conn[id].setFile(fileInput.files[0]), vm_conn[id].setMedia_sz(fileInput.files[0].size), vm_conn[id].createWebSocket(); else { dlgMsg = iLO.translateString("IRC.error.UnsupportedFileType"); var msgBox = { titleKey: "IRC.title.Denied", icon: myIcons.critical, message: dlgMsg, closeOnClick: !1 }; iLO.alert(msgBox); } } const SCSI_READ_CAPACITY = 37, SCSI_READ_CAPACITIES = 35, SCSI_SEND_DIAGNOSTIC = 29, SCSI_START_STOP_UNIT = 27, SCSI_TEST_UNIT_READY = 0, SCSI_PA_MEDIA_REMOVAL = 30, SCSI_READ_10 = 40, SCSI_READ_12 = 168, SCSI_WRITE_10 = 42, SCSI_WRITE_12 = 170, CDROM_SECTOR_SIZE = 2048, FLOPPY_SECTOR_SIZE = 512, CDROM_MAX_CHUNK_SIZE = 32768, FLOPPY_MAX_CHUNK_SIZE = 32768; var fddStateEnum = { MEDIA_NOT_PRESENT: 0, MEDIA_CHANGED: 1, MEDIA_READY: 2 }, vmConnType = { FLOPPY: 1, CDROM: 2, USB: 3 }, maxNumVMConn = 10, vm_conn = new Array(maxNumVMConn); window.onbeforeunload = function() { for (var i = 0; maxNumVMConn > i; i++) if ("undefined" != typeof vm_conn[i] && vm_conn[i].getWebsocket() && iLO.isFunction(vm_conn[i].getWebsocket().close)) try { vm_conn[i].getWebsocket().onclose = function() {}, vm_conn[i].getWebsocket().close(); } catch (e) {} }, window.addEventListener("load", init, !1), VMconnection.prototype.onMessage = function(evt) { var currTmrId = this.getTmrId(); if (-1 !== currTmrId && (clearInterval(currTmrId), this.setTmrId(-1)), evt.data instanceof Blob) ; else if (evt.data instanceof ArrayBuffer) { var byteArray = new Uint8Array(evt.data); if (4 === evt.data.byteLength) { var status = byteArray[0], zero = byteArray[1], dlgMsg = ""; if (32 == status && 0 == zero) VMconnection.numDevs++, showIrcToast({ text: iLO.translateString("vm.imgInserted"), type: "ok", position: "bottom-right" }); else { switch (status) { case 33: dlgMsg = iLO.translateString("IRC.error.DriveInUse"); break; case 34: dlgMsg = iLO.translateString("IRC.error.InvalidKey"); break; case 35: dlgMsg = iLO.translateString("IRC.error.MediaNotLicensed"); break; case 36: dlgMsg = iLO.translateString("IRC.error.KeyExpired"); break; case 37: dlgMsg = iLO.translateString("IRC.error.DriveNotConfigured"); break; case 38: dlgMsg = iLO.translateString("IRC.error.MediaPermitRequired"); break; default: dlgMsg = iLO.translateString("IRC.error.CannotConnectDrive"); } if (dlgMsg.length > 0) { var msgBox = { titleKey: "IRC.title.UnableToConnect", icon: myIcons.critical, message: dlgMsg, closeOnClick: !1 }; iLO.alert(msgBox); } } } else 12 === evt.data.byteLength && this.processSCSIRequest(byteArray); } currTmrId = setInterval(this.sendKeepAlive, 2e3), this.setTmrId(currTmrId); }, VMconnection.prototype.processSCSIRequest = function(byteArray) { switch (renderer && renderer.onvmactivity && renderer.onvmactivity(), 0 === this.media_sz ? (this.media = 0, this.fdd_state = fddStateEnum.MEDIA_NOT_PRESENT, this.event_state = 0) : (this.media = 1, this.fdd_state++, this.fdd_state > fddStateEnum.MEDIA_READY && (this.fdd_state = fddStateEnum.MEDIA_READY), 4 === this.event_state && (this.event_state = 0), this.event_state++, this.event_state > 2 && (this.event_state = 2)), byteArray[0]) { case SCSI_TEST_UNIT_READY: this.client_test_unit_ready(); break; case SCSI_START_STOP_UNIT: this.client_start_stop_unit(byteArray); break; case SCSI_PA_MEDIA_REMOVAL: this.client_pa_media_removal(byteArray); break; case SCSI_READ_CAPACITY: this.client_read_capacity(); break; case SCSI_READ_10: case SCSI_READ_12: this.client_read(byteArray); break; default: $.log("UNHANDLED SCSI REQUEST: " + byteArray[0]), this.sendRespHeader(5, 36, 0, 0); } }, VMconnection.prototype.client_read_capacity = function() { var sz, data = new Uint8Array(8); this.fdd_state === fddStateEnum.MEDIA_NOT_PRESENT ? this.sendRespHeader(2, 58, 0, 0) : this.fdd_state === fddStateEnum.MEDIA_CHANGED ? this.sendRespHeader(6, 40, 0, 0) : this.fdd_state === fddStateEnum.MEDIA_READY && (sz = parseInt(this.media_sz / CDROM_SECTOR_SIZE) - 1, data[0] = sz >> 24 & 255, data[1] = sz >> 16 & 255, data[2] = sz >> 8 & 255, data[3] = sz >> 0 & 255, data[4] = 0, data[5] = 0, data[6] = 8, data[7] = 0, this.sendRespHeader(0, 0, 0, 8), this.doSend(data)); }, VMconnection.prototype.client_read = function(cmd) { var that = this, t = cmd[0] == SCSI_READ_12 ? 1 : 0, offset = VMconnection.mk_int32(cmd, 2) * CDROM_SECTOR_SIZE, length = t ? VMconnection.mk_int32(cmd, 6) : VMconnection.mk_int16(cmd, 7); length *= CDROM_SECTOR_SIZE; var reader = new FileReader(), bytesSent = 0, sendBytes = 0; if (offset >= 0 && offset + length <= this.media_sz || ($.log("offset out of range."), this.sendRespHeader(5, 33, 0, 0), length = 0), length > 0 && 131072 >= length) { reader.onloadend = function(e) { for (that.sendRespHeader(0, 0, 0, length); length > bytesSent; ) { sendBytes = Math.min(CDROM_MAX_CHUNK_SIZE, length - bytesSent); var bytes = new Uint8Array(e.target.result.slice(bytesSent, bytesSent + sendBytes)); that.doSend(bytes), bytesSent += sendBytes; } }, reader.onerror = function(e) { $.log("reader.onerror", e), that.sendRespHeader(3, 16, 0, 0); }; var blob = that.file.slice(offset, offset + length); reader.readAsArrayBuffer(blob); } else $.log("Legacy read [not implemented]"); }, VMconnection.prototype.client_start_stop_unit = function(cmd) { this.sendRespHeader(0, 0, 0, 0), 2 === (3 & cmd[4]) && (this.fdd_state = fddStateEnum.MEDIA_NOT_PRESENT, this.event_state = 4, this.closeVMconnection()); }, VMconnection.prototype.client_pa_media_removal = function(cmd) { 0 !== (1 & cmd[4]), this.sendRespHeader(0, 0, 0, 0); }, VMconnection.numDevs = 0, VMconnection.mk_int32 = function(cmd, pos) { var temp0 = cmd[pos + 0], temp1 = cmd[pos + 1], temp2 = cmd[pos + 2], temp3 = cmd[pos + 3], result = (255 & temp0) << 24 | (255 & temp1) << 16 | (255 & temp2) << 8 | 255 & temp3; return result; }, VMconnection.mk_int16 = function(cmd, pos) { var temp0 = cmd[pos + 0], temp1 = cmd[pos + 1], result = (255 & temp0) << 8 | 255 & temp1; return result; }, VMconnection.convertNumArrayToHexString = function(list) { for (var result = [], i = 0; i < list.length; i++) result.push(list[i].toString(16)); return result.join(","); }, VMconnection_fd.prototype.onMessage = function(evt) { var currTmrId = this.getTmrId(); if (-1 !== currTmrId && (clearInterval(currTmrId), this.setTmrId(-1)), evt.data instanceof Blob) ; else if (evt.data instanceof ArrayBuffer) { var byteArray = new Uint8Array(evt.data); if (4 === evt.data.byteLength) { var status = byteArray[0], zero = byteArray[1], dlgMsg = ""; if (32 == status && 0 == zero) VMconnection.numDevs++, showIrcToast({ text: iLO.translateString("vm.imgInserted"), type: "ok", position: "bottom-right" }); else { switch (status) { case 33: dlgMsg = iLO.translateString("IRC.error.DriveInUse"); break; case 34: dlgMsg = iLO.translateString("IRC.error.InvalidKey"); break; case 35: dlgMsg = iLO.translateString("IRC.error.MediaNotLicensed"); break; case 36: dlgMsg = iLO.translateString("IRC.error.KeyExpired"); break; case 37: dlgMsg = iLO.translateString("IRC.error.DriveNotConfigured"); break; case 38: dlgMsg = iLO.translateString("IRC.error.MediaPermitRequired"); break; default: dlgMsg = iLO.translateString("IRC.error.CannotConnectDrive"); } if (dlgMsg.length > 0) { var msgBox = { titleKey: "IRC.title.UnableToConnect", icon: myIcons.critical, message: dlgMsg, closeOnClick: !1 }; iLO.alert(msgBox); } } } else 12 === evt.data.byteLength ? this.processSCSIRequest(byteArray) : evt.data.byteLength >= FLOPPY_SECTOR_SIZE && this.client_getWriteData(byteArray); } currTmrId = setInterval(this.sendKeepAlive, 2e3), this.setTmrId(currTmrId); }, VMconnection_fd.prototype.processSCSIRequest = function(byteArray) { switch (renderer && renderer.onvmactivity && renderer.onvmactivity(), this.media_sz <= 0 ? (this.media = 0, this.fdd_state = fddStateEnum.MEDIA_NOT_PRESENT) : (this.media = 36, this.fdd_state++, this.fdd_state > fddStateEnum.MEDIA_READY && (this.fdd_state = fddStateEnum.MEDIA_READY)), byteArray[0]) { case SCSI_TEST_UNIT_READY: this.client_test_unit_ready(); break; case SCSI_START_STOP_UNIT: this.client_start_stop_unit(byteArray); break; case SCSI_PA_MEDIA_REMOVAL: this.client_pa_media_removal(byteArray); break; case SCSI_READ_CAPACITIES: this.client_read_capacities(); break; case SCSI_READ_CAPACITY: this.client_read_capacity(); break; case SCSI_READ_10: case SCSI_READ_12: this.client_read(byteArray); break; case SCSI_WRITE_10: case SCSI_WRITE_12: this.client_getWriteLen(byteArray); break; default: this.sendRespHeader(5, 36, 0, 0); } }, VMconnection_fd.prototype.client_read_capacities = function() { var sz, rcs_resp = new Uint8Array([ 0, 0, 0, 16, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 11, 64, 0, 0, 2, 0 ]); this.fdd_state !== fddStateEnum.MEDIA_CHANGED ? this.sendRespHeader(0, 0, 0, rcs_resp.length) : (this.sendRespHeader(6, 40, 0, rcs_resp.length), this.fdd_state = fddStateEnum.MEDIA_READY), sz = parseInt(this.media_sz / FLOPPY_SECTOR_SIZE), rcs_resp[4] = sz >> 24 & 255, rcs_resp[5] = sz >> 16 & 255, rcs_resp[6] = sz >> 8 & 255, rcs_resp[7] = sz >> 0 & 255, rcs_resp[10] = 2, rcs_resp[11] = 0, this.doSend(rcs_resp); }, VMconnection_fd.prototype.client_read_capacity = function() { var sz, data = new Uint8Array(8); this.fdd_state === fddStateEnum.MEDIA_NOT_PRESENT ? this.sendRespHeader(2, 58, 0, 0) : this.fdd_state === fddStateEnum.MEDIA_CHANGED ? this.sendRespHeader(6, 40, 0, 0) : this.fdd_state === fddStateEnum.MEDIA_READY && (sz = parseInt(this.media_sz / FLOPPY_SECTOR_SIZE) - 1, data[0] = sz >> 24 & 255, data[1] = sz >> 16 & 255, data[2] = sz >> 8 & 255, data[3] = sz >> 0 & 255, data[6] = 2, this.sendRespHeader(0, 0, 0, 8), this.doSend(data)); }, VMconnection_fd.prototype.client_read = function(cmd) { var that = this, t = cmd[0] == SCSI_READ_12 ? 1 : 0, offset = VMconnection.mk_int32(cmd, 2) * FLOPPY_SECTOR_SIZE, length = t ? VMconnection.mk_int32(cmd, 6) : VMconnection.mk_int16(cmd, 7); length *= FLOPPY_SECTOR_SIZE; var reader = new FileReader(), bytesSent = 0, sendBytes = 0; if (offset >= 0 && offset < this.media_sz) { reader.onloadend = function(e) { for (that.sendRespHeader(0, 0, 0, length); length > bytesSent; ) { sendBytes = Math.min(FLOPPY_MAX_CHUNK_SIZE, length - bytesSent); var bytes = new Uint8Array(e.target.result.slice(bytesSent, bytesSent + sendBytes)); that.doSend(bytes), bytesSent += sendBytes; } }, reader.onerror = function(e) { that.sendRespHeader(3, 16, 0, 0); }; var blob = this.file.slice(offset, offset + length); reader.readAsArrayBuffer(blob); } else this.sendRespHeader(5, 33, 0, 0); }, VMconnection_fd.prototype.client_start_stop_unit = function(cmd) { this.sendRespHeader(0, 0, 0, 0), 2 === (3 & cmd[4]) && (this.fdd_state = fddStateEnum.MEDIA_NOT_PRESENT, this.closeVMconnection()); }, VMconnection_fd.prototype.client_pa_media_removal = function(cmd) { 0 !== (2 & cmd[4]) ? this.sendRespHeader(5, 36, 0, 0) : this.sendRespHeader(0, 0, 0, 0); }, VMconnection_fd.prototype.client_getWriteLen = function(cmd) { var t = 170 === cmd[0]; this.lba = VMconnection.mk_int32(cmd, 2) * FLOPPY_SECTOR_SIZE, this.writeLen = t ? VMconnection.mk_int32(cmd, 6) : VMconnection.mk_int16(cmd, 7), this.writeLen *= FLOPPY_SECTOR_SIZE; }, VMconnection_fd.prototype.client_getWriteData = function(cmd) { var numRead = cmd.length; "undefined" == typeof this.client_getWriteData.offset && (this.client_getWriteData.offset = 0); for (var i = this.client_getWriteData.offset; numRead > i; i++) this.buffer[i] = cmd[i]; this.client_getWriteData.offset += numRead, this.writeLen -= numRead, this.writeLen <= 0 && this.client_fileWrite(this.buffer); }, VMconnection_fd.prototype.client_fileWrite = function(buffer) { this.sendRespHeader(0, 0, 0, 0); };