コード例 #1
0
ファイル: docker.js プロジェクト: andreasn/cockpit
        buffer.callback = function(data) {
            var ret = 0;
            var pos = 0;
            var parts;

            /* Look for end of headers first */
            if (headers === null) {
                pos = sequence_find(data, [ 13, 10, 13, 10 ]);
                if (pos == -1)
                    return ret;

                if (data.subarray)
                    headers = cockpit.utf8_decoder().decode(data.subarray(0, pos));
                else
                    headers = cockpit.utf8_decoder().decode(data.slice(0, pos));
                docker_debug(container_id + ": console headers: ", headers);

                parts = headers.split("\r\n", 1)[0].split(" ");
                if (parts[1] != "200") {
                    failure(parts.slice(2).join(" "));
                    buffer.callback = null;
                    return;
                } else if (data.subarray) {
                    data = data.subarray(pos + 4);
                    ret += pos + 4;
                } else {
                    data = data.slice(pos + 4);
                    ret += pos + 4;
                }
            }

            /* We need at least two bytes to determine stream type */
            if (tty === undefined || tty === null) {
                if (data.length < 2)
                    return ret;
                tty = !((data[0] === 0 || data[0] === 1 || data[0] === 2) && data[1] === 0);
                docker_debug(container_id + ": mode tty: " + tty);
            }

            if (tty)
                view = new DockerTerminal(self, channel);
            else
                view = new DockerLogs(self, channel);
            self.typeable(want_typeable);
            self.connected = true;

            buffer.callback = view.process;
            var consumed = view.process(data);
            return ret + consumed;
        };
コード例 #2
0
ファイル: docker.js プロジェクト: andreasn/cockpit
function DockerTerminal(parent, channel) {
    var self = this;

    var term = new Terminal({
        cols: 80,
        rows: 24,
        screenKeys: true,
        inlineStyle: false,
        useFocus: false,
    });

    var enable_input = true;
    var decoder = cockpit.utf8_decoder();
    var encoder = cockpit.utf8_encoder();

    /* term.js wants the parent element to build its terminal inside of */
    parent.empty();
    term.open(parent[0]);

    /* Shows and hides the cursor */
    self.typeable = function typeable(yes) {
        term.cursorHidden = !yes;
        term.refresh(term.y, term.y);
        enable_input = yes;
    };

    self.focus = function focus() {
        term.focus();
    };

    /* Allows caller to cleanup nicely */
    self.close = function close() {
        term.destroy();
    };

    if (typeof channel == "string") {
        term.write('\x1b[31m' + channel + '\x1b[m\r\n');
        self.close = function() { };
        self.typeable(false);
        return self;
    }

    $(channel)
            .on("close", function(ev, options) {
                var problem = options.problem || "disconnected";
                term.write('\x1b[31m' + problem + '\x1b[m\r\n');
                self.typeable(false);
                $(channel).off("message");
                channel = null;
            });

    self.process = function process(buffer) {
        term.write(decoder.decode(buffer));
        return buffer.length;
    };

    term.on('data', function(data) {
        /* Send typed input back through channel */
        if (enable_input && channel)
            channel.send(encoder.encode(data));
    });

    return self;
}
コード例 #3
0
ファイル: docker.js プロジェクト: andreasn/cockpit
function DockerLogs(parent, channel) {
    var self = this;

    var pre = $("<pre>");
    parent.empty();
    parent.append(pre);

    var wait;
    var writing = [];
    function write(data) {
        writing.push(data);
        if (!wait) {
            wait = window.setTimeout(function() {
                wait = null;
                var at_bottom = pre[0].scrollHeight - pre.scrollTop() <= pre.outerHeight();
                var span = $("<span>").text(writing.join(""));
                writing.length = 0;
                pre.append(span);
                if (at_bottom)
                    pre.scrollTop(pre.prop("scrollHeight"));
            }, 50);
        }
    }

    /* Just display the failure */
    if (typeof channel == "string") {
        write(channel);
        self.close = function() { };
        return self;
    }

    channel.control({ batch: 16384, latency: 50 });

    var decoder = cockpit.utf8_decoder(false);

    self.process = function process(buffer) {
        var at = 0;
        var size, block;
        var length = buffer.length;
        while (true) {
            if (length < at + 8)
                return at; /* more data */

            size = ((buffer[at + 4] & 0xFF) << 24) | ((buffer[at + 5] & 0xFF) << 16) |
                   ((buffer[at + 6] & 0xFF) << 8) | (buffer[at + 7] & 0xFF);

            if (length < at + 8 + size)
                return at; /* more data */

            /* Output the data */
            if (buffer.subarray)
                block = buffer.subarray(at + 8, at + 8 + size);
            else
                block = buffer.slice(at + 8, at + 8 + size);
            write(decoder.decode(block, { stream: true }));
            at += 8 + size;
        }
    };

    self.focus = function() {
        /* Nothing to do */
    };

    self.close = function() {
        /* Nothing to do */
    };

    /*
     * A raw channel over which we speak Docker's even stranger /logs
     * protocol. It starts with a HTTP GET, and then quickly
     * degenerates into a stream with framing.
     */
    $(channel)
            .on("close", function(ev, options) {
                write(options.reason || "disconnected");
                $(channel).off();
                channel = null;
            });

    return self;
}
コード例 #4
0
ファイル: utils.js プロジェクト: andreasn/cockpit
export function decode_filename(encoded) {
    return cockpit.utf8_decoder().decode(cockpit.base64_decode(encoded).slice(0, -1));
}