= cockpit.js: Raw ChannelsAt a low level Cockpit communicates with the system via messages passedthrough various channels. These are usually exposed via higher levelAPIs, such as the `+cockpit.spawn()+` function. It is rare to use rawchannels directly.[[cockpit-channels-channel]]== cockpit.channel()....channel = cockpit.channel(options)....This function creates a new channel for communication with the system.It returns a new channel object. The `+options+` argument is a plainobject. At least the `+"payload"+` option is required, and based on thepayload type, other options may be required.`+"binary"+`::Set to `+true+` to transfer binary payloads. Both messages sent vialink:#cockpit-channels-send[`+channel.send()+`] and those received vialink:#cockpit-channels-message[`+channel.onmessage+`] should be arraysof bytes, either `+Uint8Array+` or `+Array+` depending on browsersupport.`+"payload"+`::The payload type for the channel. Only specific payload types aresupported.`+"superuser"+`::Set to `+"require"+` to open this channel as root. If the currentlylogged in user is not permitted to become root (eg: via `+pkexec+`)then the `+channel+` will immediately belink:#cockpit-channels-close-ev[closed] with a `+"access-denied"+`problem code.+Set to `+"try"+` to try to open the channel as root, but if thatfails, then fall back to an unprivileged channel.The channel object returned has the following fields and methods andevents. You should call the `+channel.close()+` method when done withthe channel.A valid channel will always be returned and the is ready to`+channel.send()+`. The channel maylink:#cockpit-channels-close-ev[close shortly afterword] due to afailure.[[cockpit-channels-binary]]== channel.binaryWill be `+true+` for an binary channel. Will be set to `+false+` if thechannel is textual.[[cockpit-channels-options]]== channel.optionsThe options used to open this channel. This should not be changed.[[cockpit-channels-valid]]== channel.validWill be `+true+` for an open channel. Will be set to `+false+` if thechannel closes.[[cockpit-channels-send]]== channel.send()....channel.send(data)....Send a message over the channel. The contents of the message depends onthe payload type of the channel. If a binary channel, then `+data+` isexpected to be an `+Array+` of bytes or a `+Uint8Array+`. If not binary,then the `+data+` will be converted to a string if not already a string.[[cockpit-channels-control]]== channel.control()....channel.control(options)....Notify the channel to tune certain parameters on the fly. The`+options+` is a plain javascript object, and the contents depend on the`+"payload"+` of the channel.One common operation is to set `+"command"+` to `+"done"+` in theoptions field. To indicate that no further messages will be sent throughthe channel.[[cockpit-channels-wait]]== channel.wait()....promise = channel.wait([callback])....Returns a `+promise+` that is ready when the channel is ready, or failsif the client closes. If a `+callback+` is specified, it is attached tothe promise. The promise will be rejected or resolved with the contents`+options+` passed to thelink:#cockpit-channels-onready[channel.onready] andlink:#cockpit-channels-close-ev[channel.onclose] events respectively.In general it's not necessary to wait for the channel before starting touse the channel.[[cockpit-channels-close]]== channel.close()....channel.close([options])....Close the channel.If `+options+` is present it can be a plain javascript object containingadditional channel close options to send to the peer. If closing forbecause of a problem, set the `+"problem"+` field to axref:cockpit-error.adoc#cockpit-problems[problem code]. If `+options+` is not an object itwill be treated as a `+"problem"+`.The link:#cockpit-channels-close-ev[close event] will fire. A channelcan also be closed by a peer or if the underlying transport closes.[[cockpit-channels-message]]== channel.onmessage....channel.addEventListener("message", function(event, data) { ... })....An event triggered when the channel receives a message. The message ispassed as a string to the handler in the `+data+`. In the case of binarychannels `+data+` is an `+Uint8Array+` or an `+Array+` of bytes if theformer is not supported by the browser. The contents of the messagedepends on the payload type of the channel.[[cockpit-channels-oncontrol]]== channel.oncontrol....channel.addEventListener("control", function(event, options) { ... })....An event triggered when the channel receives an control message in themiddle of the flow. One particular use is when the `+command+` is set to`+"done"+` then no further messages will be received in the channel. Theexact form of these messages depend on the `+"payload"+` of the channel.[[cockpit-channels-onready]]== channel.onready....channel.addEventListener("ready", function(event, options) { ... })....An event triggered when the other end of the channel is ready to startprocessing messages. This indicates the channel is completely open. Itis possible to start sending messages on the channel before this point.[[cockpit-channels-close-ev]]== channel.onclose....channel.addEventListener("close", function(event, options) { ... })....An event triggered when the channel closes. This can happen eitherbecause link:#cockpit-channels-close[channel.close()] function wascalled, or if the peer closed the channel, or the underlying transportcloses.The `+options+` will contain various close information, including a`+"problem"+` field which will be set if the channel was closed becauseof a problem.[[cockpit-transport-origin]]== cockpit.transport.origin....cockpit.transport.origin....The HTTP origin that is being used by the underlying channel transport.This is read-only, you should not assign a value. If the browsersupports `+window.location.origin+` then this will be identical to thatvalue.[[cockpit-transport-host]]== cockpit.transport.host....cockpit.transport.host....The host that this transport is going to talk to by default. This isread-only, you should not assign a value. If the value is null thatmeans that the transport has not been setup yet.[[cockpit-transport-csrf-token]]== cockpit.transport.csrf_token....cockpit.transport.csrf_token....A cross site request forgery token for use with external channels. Thisbecomes valid once the connection is properly established.[[cockpit-transport-options]]== cockpit.transport.options....cockpit.transport.options....Initialization options received over the underlying channel transport.These will be empty until connection is properly established.[[cockpit-transport-wait]]== cockpit.transport.wait()....cockpit.transport.wait(callback)....Call the `+callback+` function once the underlying channel transport isinitialized. This will start the initialization if not already inprogress or completed. If the channel transport is already initialized,then `+callback+` will be called immediately.In general it's not necessary to wait for the transport before startingto open channels.[[cockpit-transport-close]]== cockpit.transport.close()....cockpit.transport.close([problem])....Close the underlying channel transport. All channels open channels willclose. The `+problem+` argument should be a problem code string. If notspecified it will default to `+"disconnected"+`.[[cockpit-transport-filter]]== cockpit.transport.filter()....cockpit.transport.filter((message, channelid, control) => { ... })....Add a filter to the underlying channel transport. All incoming messageswill be passed to each of the filter callbacks that are registered.This function is rarely used.Filter callbacks are called in the order they are registered. If afilter callback returns `+false+` then the message will not bedispatched further, whether to other filters, or to channels, etc.The `+message+` is the string or array with the raw message including,the framing. The `+channelid+` is the channel identifier or an emptystring for control messages. If `+control+` is set then this is acontrol message,d and the `+control+` argument contains the parsed JSONobject of the control message.[[cockpit-transport-inject]]== cockpit.transport.inject()....cockpit.transport.inject(message, [out])....Inject a message into the underlying channel transport. The `+message+`should be a `+string+` or an array of bytes, and should be validaccording to the Cockpit message protocol. If the `+out+` argument isequal to `+false+` then the message will be injected as an incomingmessage as if it was received on the underlying channel transport.This function is rarely used. In general you should only `+inject()+`messages you got from a `+filter()+`.[[cockpit-base64-encode]]== cockpit.base64_encode()....string = cockpit.base64_encode(data)....Encode binary data into a string using the Base64 encoding. The `+data+`argument can either be a `+string+`, an `+Array+`, an `+ArrayBuffer+` ora `+Uint8Array+`. The return value is a string.[[cockpit-base64-decode]]== cockpit.base64_decode()....data = cockpit.base64_decode(string, [constructor])....Decode binary data from a Base64 encoded string. The `+string+` argumentshould be a javascript string. The returned `+data+`> will be an arrayof bytes.You can pass `+Uint8Array+`, `+Array+` or `+String+` as an alternate`+constructor+` if you want the decoded data in an alternate form. Thedefault is to return an `+Array+`. Note that if you use a `+String+` forthe decoded data, then you must guarantee that the data does not containbytes that would be invalid for a string.