aboutsummaryrefslogtreecommitdiff
path: root/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go')
-rw-r--r--vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go
new file mode 100644
index 000000000..c60012b21
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go
@@ -0,0 +1,132 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package remotecommand
+
+import (
+ "fmt"
+ "net/http"
+ "time"
+
+ "k8s.io/apimachinery/pkg/util/runtime"
+ "k8s.io/apiserver/pkg/server/httplog"
+ "k8s.io/apiserver/pkg/util/wsstream"
+)
+
+const (
+ stdinChannel = iota
+ stdoutChannel
+ stderrChannel
+ errorChannel
+ resizeChannel
+
+ preV4BinaryWebsocketProtocol = wsstream.ChannelWebSocketProtocol
+ preV4Base64WebsocketProtocol = wsstream.Base64ChannelWebSocketProtocol
+ v4BinaryWebsocketProtocol = "v4." + wsstream.ChannelWebSocketProtocol
+ v4Base64WebsocketProtocol = "v4." + wsstream.Base64ChannelWebSocketProtocol
+)
+
+// createChannels returns the standard channel types for a shell connection (STDIN 0, STDOUT 1, STDERR 2)
+// along with the approximate duplex value. It also creates the error (3) and resize (4) channels.
+func createChannels(opts *Options) []wsstream.ChannelType {
+ // open the requested channels, and always open the error channel
+ channels := make([]wsstream.ChannelType, 5)
+ channels[stdinChannel] = readChannel(opts.Stdin)
+ channels[stdoutChannel] = writeChannel(opts.Stdout)
+ channels[stderrChannel] = writeChannel(opts.Stderr)
+ channels[errorChannel] = wsstream.WriteChannel
+ channels[resizeChannel] = wsstream.ReadChannel
+ return channels
+}
+
+// readChannel returns wsstream.ReadChannel if real is true, or wsstream.IgnoreChannel.
+func readChannel(real bool) wsstream.ChannelType {
+ if real {
+ return wsstream.ReadChannel
+ }
+ return wsstream.IgnoreChannel
+}
+
+// writeChannel returns wsstream.WriteChannel if real is true, or wsstream.IgnoreChannel.
+func writeChannel(real bool) wsstream.ChannelType {
+ if real {
+ return wsstream.WriteChannel
+ }
+ return wsstream.IgnoreChannel
+}
+
+// createWebSocketStreams returns a context containing the websocket connection and
+// streams needed to perform an exec or an attach.
+func createWebSocketStreams(req *http.Request, w http.ResponseWriter, opts *Options, idleTimeout time.Duration) (*context, bool) {
+ channels := createChannels(opts)
+ conn := wsstream.NewConn(map[string]wsstream.ChannelProtocolConfig{
+ "": {
+ Binary: true,
+ Channels: channels,
+ },
+ preV4BinaryWebsocketProtocol: {
+ Binary: true,
+ Channels: channels,
+ },
+ preV4Base64WebsocketProtocol: {
+ Binary: false,
+ Channels: channels,
+ },
+ v4BinaryWebsocketProtocol: {
+ Binary: true,
+ Channels: channels,
+ },
+ v4Base64WebsocketProtocol: {
+ Binary: false,
+ Channels: channels,
+ },
+ })
+ conn.SetIdleTimeout(idleTimeout)
+ negotiatedProtocol, streams, err := conn.Open(httplog.Unlogged(w), req)
+ if err != nil {
+ runtime.HandleError(fmt.Errorf("Unable to upgrade websocket connection: %v", err))
+ return nil, false
+ }
+
+ // Send an empty message to the lowest writable channel to notify the client the connection is established
+ // TODO: make generic to SPDY and WebSockets and do it outside of this method?
+ switch {
+ case opts.Stdout:
+ streams[stdoutChannel].Write([]byte{})
+ case opts.Stderr:
+ streams[stderrChannel].Write([]byte{})
+ default:
+ streams[errorChannel].Write([]byte{})
+ }
+
+ ctx := &context{
+ conn: conn,
+ stdinStream: streams[stdinChannel],
+ stdoutStream: streams[stdoutChannel],
+ stderrStream: streams[stderrChannel],
+ tty: opts.TTY,
+ resizeStream: streams[resizeChannel],
+ }
+
+ switch negotiatedProtocol {
+ case v4BinaryWebsocketProtocol, v4Base64WebsocketProtocol:
+ ctx.writeStatus = v4WriteStatusFunc(streams[errorChannel])
+ default:
+ ctx.writeStatus = v1WriteStatusFunc(streams[errorChannel])
+ }
+
+ return ctx, true
+}