1*b65280ffSSui Chenconst { spawn } = require('child_process'); 2*b65280ffSSui Chenconst targz = require('targz'); 3*b65280ffSSui Chen 4*b65280ffSSui Chenconst DBUS_MONITOR_LEGACY = 5*b65280ffSSui Chen 'dbus-monitor --system | grep "sendMessage\\|ReceivedMessage" -A7 \n'; 6*b65280ffSSui Chenconst DBUS_MONITOR_NEW = 7*b65280ffSSui Chen 'dbus-monitor --system | grep "member=execute\\|method return" -A7 \n'; 8*b65280ffSSui Chen 9*b65280ffSSui Chen// Capture state for all scripts 10*b65280ffSSui Chenvar g_capture_state = 'not started'; 11*b65280ffSSui Chenvar g_capture_mode = 'live'; 12*b65280ffSSui Chen 13*b65280ffSSui Chen// For capturing IPMI requests live 14*b65280ffSSui Chenvar g_dbus_monitor_cmd = ''; 15*b65280ffSSui Chen 16*b65280ffSSui Chen// For tracking transfer 17*b65280ffSSui Chenvar g_hexdump = ''; 18*b65280ffSSui Chenvar g_hexdump_received_size = 0; 19*b65280ffSSui Chenvar g_hexdump_total_size = 0; 20*b65280ffSSui Chen 21*b65280ffSSui Chenfunction currTimestamp() { 22*b65280ffSSui Chen var tmp = new Date(); 23*b65280ffSSui Chen return (tmp.getTime() + tmp.getTimezoneOffset() * 60000) / 1000; 24*b65280ffSSui Chen} 25*b65280ffSSui Chen 26*b65280ffSSui Chenvar g_child; 27*b65280ffSSui Chenvar g_rz; 28*b65280ffSSui Chen 29*b65280ffSSui Chenvar g_capture_live = true; 30*b65280ffSSui Chenvar g_dbus_capture_tarfile_size = 0; 31*b65280ffSSui Chen 32*b65280ffSSui Chenfunction ParseHexDump(hd) { 33*b65280ffSSui Chen let ret = []; 34*b65280ffSSui Chen let lines = hd.split('\n'); 35*b65280ffSSui Chen let tot_size = 0; 36*b65280ffSSui Chen for (let i = 0; i < lines.length; i++) { 37*b65280ffSSui Chen const line = lines[i].trimEnd(); 38*b65280ffSSui Chen const sp = line.split(' '); 39*b65280ffSSui Chen if (line.length < 1) continue; 40*b65280ffSSui Chen if (sp.length < 1) continue; 41*b65280ffSSui Chen 42*b65280ffSSui Chen for (let j = 1; j < sp.length; j++) { 43*b65280ffSSui Chen let b0 = sp[j].slice(2); 44*b65280ffSSui Chen let b1 = sp[j].slice(0, 2); 45*b65280ffSSui Chen b0 = parseInt(b0, 16); 46*b65280ffSSui Chen b1 = parseInt(b1, 16); 47*b65280ffSSui Chen ret.push(b0); 48*b65280ffSSui Chen ret.push(b1); 49*b65280ffSSui Chen } 50*b65280ffSSui Chen 51*b65280ffSSui Chen console.log('[' + line + ']') 52*b65280ffSSui Chen 53*b65280ffSSui Chen { 54*b65280ffSSui Chen tot_size = parseInt(sp[0], 16); 55*b65280ffSSui Chen console.log('File size: ' + tot_size + ' ' + sp[0]); 56*b65280ffSSui Chen } 57*b65280ffSSui Chen } 58*b65280ffSSui Chen ret = ret.slice(0, tot_size); 59*b65280ffSSui Chen return new Buffer(ret); 60*b65280ffSSui Chen} 61*b65280ffSSui Chen 62*b65280ffSSui Chenfunction SaveHexdumpToFile(hd, file_name) { 63*b65280ffSSui Chen const buf = ParseHexDump(hd); 64*b65280ffSSui Chen fs.writeFileSync(file_name, buf) 65*b65280ffSSui Chen} 66*b65280ffSSui Chen 67*b65280ffSSui Chen// Delimiters: ">>>>>>" and "<<<<<<" 68*b65280ffSSui Chenfunction ExtractMyDelimitedStuff(x, parse_as = undefined) { 69*b65280ffSSui Chen let i0 = x.lastIndexOf('>>>>>>'), i1 = x.lastIndexOf('<<<<<<'); 70*b65280ffSSui Chen if (i0 != -1 && i1 != -1) { 71*b65280ffSSui Chen let ret = x.substr(i0 + 6, i1 - i0 - 6); 72*b65280ffSSui Chen if (parse_as == undefined) 73*b65280ffSSui Chen return ret; 74*b65280ffSSui Chen else if (parse_as == 'int') 75*b65280ffSSui Chen return parseInt(ret); 76*b65280ffSSui Chen } else 77*b65280ffSSui Chen return null; 78*b65280ffSSui Chen} 79*b65280ffSSui Chen 80*b65280ffSSui Chenfunction streamWrite(stream, chunk, encoding = 'utf8') { 81*b65280ffSSui Chen return new Promise((resolve, reject) => { 82*b65280ffSSui Chen const errListener = (err) => { 83*b65280ffSSui Chen stream.removeListener('error', errListener); 84*b65280ffSSui Chen reject(err); 85*b65280ffSSui Chen }; 86*b65280ffSSui Chen stream.addListener('error', errListener); 87*b65280ffSSui Chen const callback = () => { 88*b65280ffSSui Chen stream.removeListener('error', errListener); 89*b65280ffSSui Chen resolve(undefined); 90*b65280ffSSui Chen }; 91*b65280ffSSui Chen stream.write(chunk, encoding, callback); 92*b65280ffSSui Chen }); 93*b65280ffSSui Chen} 94*b65280ffSSui Chen 95*b65280ffSSui Chenfunction ExtractTarFile() { 96*b65280ffSSui Chen const tar_file = 'DBUS_MONITOR.tar.gz'; 97*b65280ffSSui Chen const target = '.'; 98*b65280ffSSui Chen targz.decompress({src: tar_file, dest: target}, function(err) { 99*b65280ffSSui Chen if (err) { 100*b65280ffSSui Chen console.log('Error decompressing .tar.gz file:' + err); 101*b65280ffSSui Chen } 102*b65280ffSSui Chen // Attempt to load even if error occurs 103*b65280ffSSui Chen // example error: "Error decompressing .tar.gz file:Error: incorrect data check" 104*b65280ffSSui Chen console.log('Done! will load file contents'); 105*b65280ffSSui Chen if (g_capture_mode == 'staged') { 106*b65280ffSSui Chen fs.readFile('./DBUS_MONITOR', {encoding: 'utf-8'}, (err, data) => { 107*b65280ffSSui Chen if (err) { 108*b65280ffSSui Chen console.log('Error in readFile: ' + err); 109*b65280ffSSui Chen } else { 110*b65280ffSSui Chen ParseIPMIDump(data); 111*b65280ffSSui Chen } 112*b65280ffSSui Chen }); 113*b65280ffSSui Chen } else if (g_capture_mode == 'staged2') { 114*b65280ffSSui Chen OpenDBusPcapFile('./DBUS_MONITOR'); 115*b65280ffSSui Chen } 116*b65280ffSSui Chen }); 117*b65280ffSSui Chen} 118*b65280ffSSui Chen 119*b65280ffSSui Chenfunction OnCaptureStart() { 120*b65280ffSSui Chen switch (g_capture_state) { 121*b65280ffSSui Chen case 'not started': 122*b65280ffSSui Chen capture_info.textContent = 'dbus-monitor running on BMC'; 123*b65280ffSSui Chen break; 124*b65280ffSSui Chen default: 125*b65280ffSSui Chen break; 126*b65280ffSSui Chen } 127*b65280ffSSui Chen} 128*b65280ffSSui Chen 129*b65280ffSSui Chenfunction OnCaptureStop() { 130*b65280ffSSui Chen btn_start_capture.disabled = false; 131*b65280ffSSui Chen select_capture_mode.disabled = false; 132*b65280ffSSui Chen text_hostname.disabled = false; 133*b65280ffSSui Chen g_capture_state = 'not started'; 134*b65280ffSSui Chen} 135*b65280ffSSui Chen 136*b65280ffSSui Chenasync function OnTransferCompleted() { 137*b65280ffSSui Chen setTimeout(function() { 138*b65280ffSSui Chen console.log('OnTransferCompleted'); 139*b65280ffSSui Chen g_child.kill('SIGINT'); 140*b65280ffSSui Chen }, 5000); 141*b65280ffSSui Chen 142*b65280ffSSui Chen capture_info.textContent = 'Loaded the capture file'; 143*b65280ffSSui Chen OnCaptureStop(); 144*b65280ffSSui Chen ExtractTarFile(); 145*b65280ffSSui Chen} 146*b65280ffSSui Chen 147*b65280ffSSui Chen// Example output from stderr: 148*b65280ffSSui Chen// ^M Bytes received: 2549/ 2549 BPS:6370 149*b65280ffSSui Chenasync function LaunchRZ() { 150*b65280ffSSui Chen // On the Host 151*b65280ffSSui Chen 152*b65280ffSSui Chen // Remove existing file 153*b65280ffSSui Chen const file_names = ['DBUS_MONITOR', 'DBUS_MONITOR.tar.gz']; 154*b65280ffSSui Chen try { 155*b65280ffSSui Chen for (let i = 0; i < 2; i++) { 156*b65280ffSSui Chen const fn = file_names[i]; 157*b65280ffSSui Chen if (fs.existsSync(fn)) { 158*b65280ffSSui Chen fs.unlinkSync(fn); // unlink is basically rm 159*b65280ffSSui Chen console.log('Removed file: ' + fn); 160*b65280ffSSui Chen } 161*b65280ffSSui Chen } 162*b65280ffSSui Chen } catch (err) { 163*b65280ffSSui Chen } 164*b65280ffSSui Chen 165*b65280ffSSui Chen g_rz = spawn( 166*b65280ffSSui Chen 'screen', ['rz', '-a', '-e', '-E', '-r', '-w', '32767'], {shell: false}); 167*b65280ffSSui Chen g_rz.stdout.on('data', (data) => { 168*b65280ffSSui Chen console.log('[rz] received ' + data.length + ' B'); 169*b65280ffSSui Chen console.log(data); 170*b65280ffSSui Chen console.log(data + ''); 171*b65280ffSSui Chen // data = MyCorrection(data); 172*b65280ffSSui Chen if (data != undefined) g_child.stdin.write(data); 173*b65280ffSSui Chen }); 174*b65280ffSSui Chen g_rz.stderr.on('data', (data) => { 175*b65280ffSSui Chen console.log('[rz] error: ' + data); 176*b65280ffSSui Chen let s = data.toString(); 177*b65280ffSSui Chen let idx = s.lastIndexOf('Bytes received:'); 178*b65280ffSSui Chen if (idx != -1) { 179*b65280ffSSui Chen capture_info.textContent = s.substr(idx); 180*b65280ffSSui Chen } 181*b65280ffSSui Chen if (data.indexOf('Transfer complete') != -1) { 182*b65280ffSSui Chen OnTransferCompleted(); 183*b65280ffSSui Chen } else if (data.indexOf('Transfer incomplete') != -1) { 184*b65280ffSSui Chen // todo: retry transfer 185*b65280ffSSui Chen // Bug info 186*b65280ffSSui Chen // Uncaught Error [ERR_STREAM_WRITE_AFTER_END]: write after end 187*b65280ffSSui Chen // at writeAfterEnd (_stream_writable.js:253) 188*b65280ffSSui Chen // at Socket.Writable.write (_stream_writable.js:302) 189*b65280ffSSui Chen // at Socket.<anonymous> (ipmi_capture.js:317) 190*b65280ffSSui Chen // at Socket.emit (events.js:210) 191*b65280ffSSui Chen // at addChunk (_stream_readable.js:308) 192*b65280ffSSui Chen // at readableAddChunk (_stream_readable.js:289) 193*b65280ffSSui Chen // at Socket.Readable.push (_stream_readable.js:223) 194*b65280ffSSui Chen // at Pipe.onStreamRead (internal/stream_base_commons.js:182) 195*b65280ffSSui Chen capture_info.textContent = 'Transfer incomplete'; 196*b65280ffSSui Chen } 197*b65280ffSSui Chen }); 198*b65280ffSSui Chen await Promise.all( 199*b65280ffSSui Chen [g_rz.stdin.pipe(g_child.stdout), g_rz.stdout.pipe(g_child.stdin)]); 200*b65280ffSSui Chen} 201*b65280ffSSui Chen 202*b65280ffSSui Chenfunction ClearAllPendingTimeouts() { 203*b65280ffSSui Chen var id = setTimeout(function() {}, 0); 204*b65280ffSSui Chen for (; id >= 0; id--) clearTimeout(id); 205*b65280ffSSui Chen} 206*b65280ffSSui Chen 207*b65280ffSSui Chenfunction StartDbusMonitorFileSizePollLoop() { 208*b65280ffSSui Chen QueueDbusMonitorFileSize(5); 209*b65280ffSSui Chen} 210*b65280ffSSui Chen 211*b65280ffSSui Chenfunction QueueDbusMonitorFileSize(secs = 5) { 212*b65280ffSSui Chen setTimeout(function() { 213*b65280ffSSui Chen g_child.stdin.write( 214*b65280ffSSui Chen 'a=`ls -l /run/initramfs/DBUS_MONITOR | awk \'{print $5}\'` ; echo ">>>>>>$a<<<<<<" \n\n\n\n'); 215*b65280ffSSui Chen QueueDbusMonitorFileSize(secs); 216*b65280ffSSui Chen }, secs * 1000); 217*b65280ffSSui Chen} 218*b65280ffSSui Chen 219*b65280ffSSui Chenfunction StopCapture() { 220*b65280ffSSui Chen switch (g_capture_mode) { 221*b65280ffSSui Chen case 'live': 222*b65280ffSSui Chen g_child.stdin.write('\x03 '); 223*b65280ffSSui Chen g_capture_state = 'stopping'; 224*b65280ffSSui Chen capture_info.textContent = 'Ctrl+C sent to BMC console'; 225*b65280ffSSui Chen break; 226*b65280ffSSui Chen case 'staged': 227*b65280ffSSui Chen ClearAllPendingTimeouts(); 228*b65280ffSSui Chen g_child.stdin.write( 229*b65280ffSSui Chen 'echo ">>>>>>" && killall busctl && echo "<<<<<<" \n\n\n\n'); 230*b65280ffSSui Chen g_capture_state = 'stopping'; 231*b65280ffSSui Chen capture_info.textContent = 'Stopping dbus-monitor'; 232*b65280ffSSui Chen case 'staged2': 233*b65280ffSSui Chen g_hexdump_received_size = 0; 234*b65280ffSSui Chen g_hexdump_total_size = 0; 235*b65280ffSSui Chen ClearAllPendingTimeouts(); 236*b65280ffSSui Chen g_child.stdin.write( 237*b65280ffSSui Chen 'echo ">>>>>>" && killall busctl && echo "<<<<<<" \n\n\n\n'); 238*b65280ffSSui Chen g_capture_state = 'stopping'; 239*b65280ffSSui Chen capture_info.textContent = 'Stopping busctl'; 240*b65280ffSSui Chen break; 241*b65280ffSSui Chen } 242*b65280ffSSui Chen} 243*b65280ffSSui Chen 244*b65280ffSSui Chenfunction QueueBMCConsoleHello(secs = 3) { 245*b65280ffSSui Chen setTimeout(function() { 246*b65280ffSSui Chen try { 247*b65280ffSSui Chen if (g_capture_state == 'not started') { 248*b65280ffSSui Chen console.log('Sending hello <cr> to the BMC'); 249*b65280ffSSui Chen g_child.stdin.write('\n'); 250*b65280ffSSui Chen QueueBMCConsoleHello(secs); 251*b65280ffSSui Chen } 252*b65280ffSSui Chen } catch (err) { 253*b65280ffSSui Chen console.log('g_child may have ended as intended'); 254*b65280ffSSui Chen } 255*b65280ffSSui Chen }, secs * 1000); 256*b65280ffSSui Chen} 257*b65280ffSSui Chen 258*b65280ffSSui Chen// The command line needed to access the BMC. The expectation is 259*b65280ffSSui Chen// executing this command brings the user to the BMC's console. 260*b65280ffSSui Chenfunction GetCMDLine() { 261*b65280ffSSui Chen let v = text_hostname.value.split(' '); 262*b65280ffSSui Chen return [v[0], v.slice(1, v.length)]; 263*b65280ffSSui Chen} 264*b65280ffSSui Chen 265*b65280ffSSui Chenasync function StartCapture(host) { 266*b65280ffSSui Chen // Disable buttons 267*b65280ffSSui Chen HideWelcomeScreen(); 268*b65280ffSSui Chen ShowIPMITimeline(); 269*b65280ffSSui Chen ShowNavigation(); 270*b65280ffSSui Chen let args = GetCMDLine(); 271*b65280ffSSui Chen btn_start_capture.disabled = true; 272*b65280ffSSui Chen select_capture_mode.disabled = true; 273*b65280ffSSui Chen text_hostname.disabled = true; 274*b65280ffSSui Chen capture_info.textContent = 'Contacting BMC console: ' + args.toString(); 275*b65280ffSSui Chen 276*b65280ffSSui Chen // On the B.M.C. 277*b65280ffSSui Chen let last_t = currTimestamp(); 278*b65280ffSSui Chen let attempt = 0; 279*b65280ffSSui Chen console.log('Args: ' + args); 280*b65280ffSSui Chen g_child = spawn(args[0], args[1], {shell: true}); 281*b65280ffSSui Chen g_child.stdout.on('data', async function(data) { 282*b65280ffSSui Chen QueueBMCConsoleHello(); 283*b65280ffSSui Chen 284*b65280ffSSui Chen var t = currTimestamp(); 285*b65280ffSSui Chen { 286*b65280ffSSui Chen switch (g_capture_state) { 287*b65280ffSSui Chen case 'not started': // Do nothing 288*b65280ffSSui Chen break; 289*b65280ffSSui Chen case 'started': 290*b65280ffSSui Chen attempt++; 291*b65280ffSSui Chen console.log('attempt ' + attempt); 292*b65280ffSSui Chen g_child.stdin.write('echo "haha" \n'); 293*b65280ffSSui Chen await streamWrite(g_child.stdin, 'whoami \n'); 294*b65280ffSSui Chen let idx = data.indexOf('haha'); 295*b65280ffSSui Chen if (idx != -1) { 296*b65280ffSSui Chen ClearAllPendingTimeouts(); 297*b65280ffSSui Chen OnCaptureStart(); // Successfully logged on, start 298*b65280ffSSui Chen 299*b65280ffSSui Chen if (g_capture_mode == 'live') { 300*b65280ffSSui Chen g_child.stdin.write( 301*b65280ffSSui Chen '\n\n' + 302*b65280ffSSui Chen 'a=`pidof btbridged`;b=`pidof kcsbridged`;c=`pidof netipmid`;' + 303*b65280ffSSui Chen 'echo ">>>>>>$a,$b,$c<<<<<<"\n\n'); 304*b65280ffSSui Chen g_capture_state = 'determine bridge daemon'; 305*b65280ffSSui Chen } else { 306*b65280ffSSui Chen g_capture_state = 'dbus monitor start'; 307*b65280ffSSui Chen } 308*b65280ffSSui Chen capture_info.textContent = 'Reached BMC console'; 309*b65280ffSSui Chen 310*b65280ffSSui Chen } else { 311*b65280ffSSui Chen console.log('idx=' + idx); 312*b65280ffSSui Chen } 313*b65280ffSSui Chen break; 314*b65280ffSSui Chen case 'determine bridge daemon': { 315*b65280ffSSui Chen const abc = ExtractMyDelimitedStuff(data.toString()); 316*b65280ffSSui Chen if (abc == null) break; 317*b65280ffSSui Chen const sp = abc.split(','); 318*b65280ffSSui Chen if (parseInt(sp[0]) >= 0) { // btbridged, legacy interface 319*b65280ffSSui Chen g_dbus_monitor_cmd = DBUS_MONITOR_LEGACY; 320*b65280ffSSui Chen console.log('The BMC is using btbridged.'); 321*b65280ffSSui Chen } else if (parseInt(sp[1]) >= 0) { // new iface 322*b65280ffSSui Chen g_dbus_monitor_cmd = DBUS_MONITOR_NEW; 323*b65280ffSSui Chen console.log('The BMC is using kcsbridged.'); 324*b65280ffSSui Chen } else if (parseInt(sp[2]) >= 0) { 325*b65280ffSSui Chen g_dbus_monitor_cmd = DBUS_MONITOR_NEW; 326*b65280ffSSui Chen console.log('The BMC is using netipmid.'); 327*b65280ffSSui Chen } else { 328*b65280ffSSui Chen console.log('Cannot determine the IPMI bridge daemon\n') 329*b65280ffSSui Chen return; 330*b65280ffSSui Chen } 331*b65280ffSSui Chen g_capture_state = 'dbus monitor start'; 332*b65280ffSSui Chen break; 333*b65280ffSSui Chen } 334*b65280ffSSui Chen case 'dbus monitor start': 335*b65280ffSSui Chen if (g_capture_mode == 'live') { 336*b65280ffSSui Chen // It would be good to make sure the console bit rate is greater 337*b65280ffSSui Chen // than the speed at which outputs are generated. 338*b65280ffSSui Chen // g_child.stdin.write("dbus-monitor --system | grep 339*b65280ffSSui Chen // \"sendMessage\\|ReceivedMessage\" -A7 \n") 340*b65280ffSSui Chen ClearAllPendingTimeouts(); 341*b65280ffSSui Chen g_child.stdin.write( 342*b65280ffSSui Chen 'dbus-monitor --system | grep "member=execute\\|method return" -A7 \n'); 343*b65280ffSSui Chen capture_info.textContent = 'Started dbus-monitor for live capture'; 344*b65280ffSSui Chen } else { 345*b65280ffSSui Chen // g_child.stdin.write("dbus-monitor --system | grep 346*b65280ffSSui Chen // \"sendMessage\\|ReceivedMessage\" -A7 > 347*b65280ffSSui Chen // /run/initramfs/DBUS_MONITOR & \n\n\n") 348*b65280ffSSui Chen ClearAllPendingTimeouts(); 349*b65280ffSSui Chen if (g_capture_mode == 'staged') { 350*b65280ffSSui Chen g_child.stdin.write( 351*b65280ffSSui Chen 'dbus-monitor --system > /run/initramfs/DBUS_MONITOR & \n\n\n'); 352*b65280ffSSui Chen capture_info.textContent = 353*b65280ffSSui Chen 'Started dbus-monitor for staged IPMI capture'; 354*b65280ffSSui Chen } else if (g_capture_mode == 'staged2') { 355*b65280ffSSui Chen g_child.stdin.write( 356*b65280ffSSui Chen 'busctl capture > /run/initramfs/DBUS_MONITOR & \n\n\n'); 357*b65280ffSSui Chen capture_info.textContent = 358*b65280ffSSui Chen 'Started busctl for staged IPMI + DBus capture'; 359*b65280ffSSui Chen } 360*b65280ffSSui Chen StartDbusMonitorFileSizePollLoop(); 361*b65280ffSSui Chen } 362*b65280ffSSui Chen g_capture_state = 'dbus monitor running'; 363*b65280ffSSui Chen break; 364*b65280ffSSui Chen case 'dbus monitor running': 365*b65280ffSSui Chen if (g_capture_mode == 'staged' || g_capture_mode == 'staged2') { 366*b65280ffSSui Chen let s = data.toString(); 367*b65280ffSSui Chen let tmp = ExtractMyDelimitedStuff(s, 'int'); 368*b65280ffSSui Chen if (tmp != undefined) { 369*b65280ffSSui Chen let sz = Math.floor(parseInt(tmp) / 1024); 370*b65280ffSSui Chen if (!isNaN(sz)) { 371*b65280ffSSui Chen capture_info.textContent = 372*b65280ffSSui Chen 'Raw Dbus capture size: ' + sz + ' KiB'; 373*b65280ffSSui Chen } else { // This can happen if the output is cut by half & may be 374*b65280ffSSui Chen // fixed by queuing console outputs 375*b65280ffSSui Chen } 376*b65280ffSSui Chen } 377*b65280ffSSui Chen } else { 378*b65280ffSSui Chen AppendToParseBuffer(data.toString()); 379*b65280ffSSui Chen MunchLines(); 380*b65280ffSSui Chen UpdateLayout(); 381*b65280ffSSui Chen ComputeHistogram(); 382*b65280ffSSui Chen } 383*b65280ffSSui Chen break; 384*b65280ffSSui Chen case 'dbus monitor end': // Todo: add speed check 385*b65280ffSSui Chen let s = data.toString(); 386*b65280ffSSui Chen let i0 = s.lastIndexOf('>>>>'), i1 = s.lastIndexOf('<<<<'); 387*b65280ffSSui Chen if (i0 != -1 && i1 != -1) { 388*b65280ffSSui Chen let tmp = s.substr(i0 + 4, i1 - i0 - 4); 389*b65280ffSSui Chen let sz = parseInt(tmp); 390*b65280ffSSui Chen if (isNaN(sz)) { 391*b65280ffSSui Chen console.log( 392*b65280ffSSui Chen 'Error: the tentative dbus-profile dump is not found!'); 393*b65280ffSSui Chen } else { 394*b65280ffSSui Chen let bps = sz / 10; 395*b65280ffSSui Chen console.log('dbus-monitor generates ' + bps + 'B per second'); 396*b65280ffSSui Chen } 397*b65280ffSSui Chen } 398*b65280ffSSui Chen g_child.kill('SIGINT'); 399*b65280ffSSui Chen break; 400*b65280ffSSui Chen case 'sz sending': 401*b65280ffSSui Chen console.log('[sz] Received a chunk of size ' + data.length); 402*b65280ffSSui Chen console.log(data); 403*b65280ffSSui Chen console.log(data + ''); 404*b65280ffSSui Chen // capture_info.textContent = "Received a chunk of size " + 405*b65280ffSSui Chen // data.length 406*b65280ffSSui Chen g_rz.stdin.write(data); 407*b65280ffSSui Chen break; 408*b65280ffSSui Chen case 'stopping': 409*b65280ffSSui Chen let t = data.toString(); 410*b65280ffSSui Chen if (g_capture_mode == 'live') { 411*b65280ffSSui Chen if (t.lastIndexOf('^C') != -1) { 412*b65280ffSSui Chen // Live mode 413*b65280ffSSui Chen g_child.kill('SIGINT'); 414*b65280ffSSui Chen g_capture_state = 'not started'; 415*b65280ffSSui Chen OnCaptureStop(); 416*b65280ffSSui Chen capture_info.textContent = 'connection to BMC closed'; 417*b65280ffSSui Chen // Log mode 418*b65280ffSSui Chen } 419*b65280ffSSui Chen } else if ( 420*b65280ffSSui Chen g_capture_mode == 'staged' || g_capture_mode == 'staged2') { 421*b65280ffSSui Chen ClearAllPendingTimeouts(); 422*b65280ffSSui Chen if (t.lastIndexOf('<<<<<<') != -1) { 423*b65280ffSSui Chen g_capture_state = 'compressing'; 424*b65280ffSSui Chen g_child.stdin.write( 425*b65280ffSSui Chen 'echo ">>>>>>" && cd /run/initramfs && tar cfz DBUS_MONITOR.tar.gz DBUS_MONITOR && echo "<<<<<<" \n\n\n\n'); 426*b65280ffSSui Chen capture_info.textContent = 'Compressing dbus monitor dump on BMC'; 427*b65280ffSSui Chen } 428*b65280ffSSui Chen } 429*b65280ffSSui Chen break; 430*b65280ffSSui Chen case 'compressing': 431*b65280ffSSui Chen g_child.stdin.write( 432*b65280ffSSui Chen '\n\na=`ls -l /run/initramfs/DBUS_MONITOR.tar.gz | awk \'{print $5}\'` && echo ">>>>>>$a<<<<<<" \n\n\n\n'); 433*b65280ffSSui Chen g_capture_state = 'dbus_monitor size'; 434*b65280ffSSui Chen capture_info.textContent = 'Obtaining size of compressed dbus dump'; 435*b65280ffSSui Chen break; 436*b65280ffSSui Chen case 'dbus_monitor size': 437*b65280ffSSui Chen // Starting RZ 438*b65280ffSSui Chen let tmp = ExtractMyDelimitedStuff(data.toString(), 'int'); 439*b65280ffSSui Chen if (tmp != null && !isNaN(tmp)) { // Wait until result shows up 440*b65280ffSSui Chen g_hexdump_total_size = tmp; 441*b65280ffSSui Chen console.log( 442*b65280ffSSui Chen 'dbus_monitor size tmp=' + tmp + ', ' + data.toString()); 443*b65280ffSSui Chen 444*b65280ffSSui Chen // if (tmp != undefined) { 445*b65280ffSSui Chen // g_dbus_capture_tarfile_size = tmp; 446*b65280ffSSui Chen // capture_info.textContent = 447*b65280ffSSui Chen // 'Starting rz and sz, file size: ' + Math.floor(tmp / 1024) 448*b65280ffSSui Chen // + ' KiB'; 449*b65280ffSSui Chen // } else { 450*b65280ffSSui Chen // capture_info.textContent = 'Starting rz and sz'; 451*b65280ffSSui Chen // } 452*b65280ffSSui Chen // g_capture_state = 'sz start'; 453*b65280ffSSui Chen // g_child.stdin.write( 454*b65280ffSSui Chen // '\n\n\n\n' + 455*b65280ffSSui Chen // 'sz -a -e -R -L 512 -w 32767 -y 456*b65280ffSSui Chen // /run/initramfs/DBUS_MONITOR.tar.gz\n'); 457*b65280ffSSui Chen // g_capture_state = 'sz sending'; 458*b65280ffSSui Chen // LaunchRZ(); 459*b65280ffSSui Chen g_child.stdin.write( 460*b65280ffSSui Chen 'echo ">>>>>>"; hexdump /run/initramfs/DBUS_MONITOR.tar.gz ; echo "<<<<<<"; \n'); 461*b65280ffSSui Chen g_capture_state = 'test hexdump running'; 462*b65280ffSSui Chen g_hexdump = new Buffer([]); 463*b65280ffSSui Chen } 464*b65280ffSSui Chen 465*b65280ffSSui Chen break; 466*b65280ffSSui Chen case 'test hexdump start': 467*b65280ffSSui Chen g_child.stdin.write( 468*b65280ffSSui Chen 'echo ">>>>>>"; hexdump /run/initramfs/DBUS_MONITOR.tar.gz ; echo "<<<<<<"; \n'); 469*b65280ffSSui Chen g_capture_state = 'test hexdump running'; 470*b65280ffSSui Chen g_hexdump = new Buffer([]); 471*b65280ffSSui Chen g_hexdump_received_size = 0; 472*b65280ffSSui Chen break; 473*b65280ffSSui Chen case 'test hexdump running': 474*b65280ffSSui Chen g_hexdump += data; 475*b65280ffSSui Chen const lines = data.toString().split('\n'); 476*b65280ffSSui Chen for (let j = lines.length - 1; j >= 0; j--) { 477*b65280ffSSui Chen sp = lines[j].trimEnd().split(' '); 478*b65280ffSSui Chen if (sp.length >= 1) { 479*b65280ffSSui Chen const sz = parseInt(sp[0], 16) 480*b65280ffSSui Chen if (!isNaN(sz)) { 481*b65280ffSSui Chen if (g_hexdump_received_size < sz) { 482*b65280ffSSui Chen g_hexdump_received_size = sz; 483*b65280ffSSui Chen capture_info.textContent = 'Receiving capture file: ' + sz + 484*b65280ffSSui Chen ' / ' + g_hexdump_total_size + ' B'; 485*b65280ffSSui Chen break; 486*b65280ffSSui Chen } 487*b65280ffSSui Chen } 488*b65280ffSSui Chen } 489*b65280ffSSui Chen } 490*b65280ffSSui Chen if (data.includes('<<<<<<') && !data.includes('echo')) { 491*b65280ffSSui Chen g_hexdump = ExtractMyDelimitedStuff(g_hexdump); 492*b65280ffSSui Chen SaveHexdumpToFile(g_hexdump, 'DBUS_MONITOR.tar.gz'); 493*b65280ffSSui Chen OnTransferCompleted(); 494*b65280ffSSui Chen } 495*b65280ffSSui Chen break; 496*b65280ffSSui Chen } 497*b65280ffSSui Chen last_t = t; 498*b65280ffSSui Chen } 499*b65280ffSSui Chen }); 500*b65280ffSSui Chen g_child.stderr.on('data', (data) => { 501*b65280ffSSui Chen console.log('[bmc] err=' + data); 502*b65280ffSSui Chen g_child.stdin.write('echo "haha" \n\n'); 503*b65280ffSSui Chen }); 504*b65280ffSSui Chen g_child.on('close', (code) => { 505*b65280ffSSui Chen console.log('return code: ' + code); 506*b65280ffSSui Chen }); 507*b65280ffSSui Chen} 508