some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / playground / socket / socket.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/playground/socket/socket.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/playground/socket/socket.go
deleted file mode 100644 (file)
index 7101ce4..0000000
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !appengine
-
-// Package socket implements an WebSocket-based playground backend.
-// Clients connect to a websocket handler and send run/kill commands, and
-// the server sends the output and exit status of the running processes.
-// Multiple clients running multiple processes may be served concurrently.
-// The wire format is JSON and is described by the Message type.
-//
-// This will not run on App Engine as WebSockets are not supported there.
-package socket // import "golang.org/x/tools/playground/socket"
-
-import (
-       "bytes"
-       "encoding/json"
-       "errors"
-       "go/parser"
-       "go/token"
-       "io"
-       "io/ioutil"
-       "log"
-       "net"
-       "net/http"
-       "net/url"
-       "os"
-       "os/exec"
-       "path/filepath"
-       "runtime"
-       "strings"
-       "time"
-       "unicode/utf8"
-
-       "golang.org/x/net/websocket"
-       "golang.org/x/tools/txtar"
-)
-
-// RunScripts specifies whether the socket handler should execute shell scripts
-// (snippets that start with a shebang).
-var RunScripts = true
-
-// Environ provides an environment when a binary, such as the go tool, is
-// invoked.
-var Environ func() []string = os.Environ
-
-const (
-       // The maximum number of messages to send per session (avoid flooding).
-       msgLimit = 1000
-
-       // Batch messages sent in this interval and send as a single message.
-       msgDelay = 10 * time.Millisecond
-)
-
-// Message is the wire format for the websocket connection to the browser.
-// It is used for both sending output messages and receiving commands, as
-// distinguished by the Kind field.
-type Message struct {
-       Id      string // client-provided unique id for the process
-       Kind    string // in: "run", "kill" out: "stdout", "stderr", "end"
-       Body    string
-       Options *Options `json:",omitempty"`
-}
-
-// Options specify additional message options.
-type Options struct {
-       Race bool // use -race flag when building code (for "run" only)
-}
-
-// NewHandler returns a websocket server which checks the origin of requests.
-func NewHandler(origin *url.URL) websocket.Server {
-       return websocket.Server{
-               Config:    websocket.Config{Origin: origin},
-               Handshake: handshake,
-               Handler:   websocket.Handler(socketHandler),
-       }
-}
-
-// handshake checks the origin of a request during the websocket handshake.
-func handshake(c *websocket.Config, req *http.Request) error {
-       o, err := websocket.Origin(c, req)
-       if err != nil {
-               log.Println("bad websocket origin:", err)
-               return websocket.ErrBadWebSocketOrigin
-       }
-       _, port, err := net.SplitHostPort(c.Origin.Host)
-       if err != nil {
-               log.Println("bad websocket origin:", err)
-               return websocket.ErrBadWebSocketOrigin
-       }
-       ok := c.Origin.Scheme == o.Scheme && (c.Origin.Host == o.Host || c.Origin.Host == net.JoinHostPort(o.Host, port))
-       if !ok {
-               log.Println("bad websocket origin:", o)
-               return websocket.ErrBadWebSocketOrigin
-       }
-       log.Println("accepting connection from:", req.RemoteAddr)
-       return nil
-}
-
-// socketHandler handles the websocket connection for a given present session.
-// It handles transcoding Messages to and from JSON format, and starting
-// and killing processes.
-func socketHandler(c *websocket.Conn) {
-       in, out := make(chan *Message), make(chan *Message)
-       errc := make(chan error, 1)
-
-       // Decode messages from client and send to the in channel.
-       go func() {
-               dec := json.NewDecoder(c)
-               for {
-                       var m Message
-                       if err := dec.Decode(&m); err != nil {
-                               errc <- err
-                               return
-                       }
-                       in <- &m
-               }
-       }()
-
-       // Receive messages from the out channel and encode to the client.
-       go func() {
-               enc := json.NewEncoder(c)
-               for m := range out {
-                       if err := enc.Encode(m); err != nil {
-                               errc <- err
-                               return
-                       }
-               }
-       }()
-       defer close(out)
-
-       // Start and kill processes and handle errors.
-       proc := make(map[string]*process)
-       for {
-               select {
-               case m := <-in:
-                       switch m.Kind {
-                       case "run":
-                               log.Println("running snippet from:", c.Request().RemoteAddr)
-                               proc[m.Id].Kill()
-                               proc[m.Id] = startProcess(m.Id, m.Body, out, m.Options)
-                       case "kill":
-                               proc[m.Id].Kill()
-                       }
-               case err := <-errc:
-                       if err != io.EOF {
-                               // A encode or decode has failed; bail.
-                               log.Println(err)
-                       }
-                       // Shut down any running processes.
-                       for _, p := range proc {
-                               p.Kill()
-                       }
-                       return
-               }
-       }
-}
-
-// process represents a running process.
-type process struct {
-       out  chan<- *Message
-       done chan struct{} // closed when wait completes
-       run  *exec.Cmd
-       path string
-}
-
-// startProcess builds and runs the given program, sending its output
-// and end event as Messages on the provided channel.
-func startProcess(id, body string, dest chan<- *Message, opt *Options) *process {
-       var (
-               done = make(chan struct{})
-               out  = make(chan *Message)
-               p    = &process{out: out, done: done}
-       )
-       go func() {
-               defer close(done)
-               for m := range buffer(limiter(out, p), time.After) {
-                       m.Id = id
-                       dest <- m
-               }
-       }()
-       var err error
-       if path, args := shebang(body); path != "" {
-               if RunScripts {
-                       err = p.startProcess(path, args, body)
-               } else {
-                       err = errors.New("script execution is not allowed")
-               }
-       } else {
-               err = p.start(body, opt)
-       }
-       if err != nil {
-               p.end(err)
-               return nil
-       }
-       go func() {
-               p.end(p.run.Wait())
-       }()
-       return p
-}
-
-// end sends an "end" message to the client, containing the process id and the
-// given error value. It also removes the binary, if present.
-func (p *process) end(err error) {
-       if p.path != "" {
-               defer os.RemoveAll(p.path)
-       }
-       m := &Message{Kind: "end"}
-       if err != nil {
-               m.Body = err.Error()
-       }
-       p.out <- m
-       close(p.out)
-}
-
-// A killer provides a mechanism to terminate a process.
-// The Kill method returns only once the process has exited.
-type killer interface {
-       Kill()
-}
-
-// limiter returns a channel that wraps the given channel.
-// It receives Messages from the given channel and sends them to the returned
-// channel until it passes msgLimit messages, at which point it will kill the
-// process and pass only the "end" message.
-// When the given channel is closed, or when the "end" message is received,
-// it closes the returned channel.
-func limiter(in <-chan *Message, p killer) <-chan *Message {
-       out := make(chan *Message)
-       go func() {
-               defer close(out)
-               n := 0
-               for m := range in {
-                       switch {
-                       case n < msgLimit || m.Kind == "end":
-                               out <- m
-                               if m.Kind == "end" {
-                                       return
-                               }
-                       case n == msgLimit:
-                               // Kill in a goroutine as Kill will not return
-                               // until the process' output has been
-                               // processed, and we're doing that in this loop.
-                               go p.Kill()
-                       default:
-                               continue // don't increment
-                       }
-                       n++
-               }
-       }()
-       return out
-}
-
-// buffer returns a channel that wraps the given channel. It receives messages
-// from the given channel and sends them to the returned channel.
-// Message bodies are gathered over the period msgDelay and coalesced into a
-// single Message before they are passed on. Messages of the same kind are
-// coalesced; when a message of a different kind is received, any buffered
-// messages are flushed. When the given channel is closed, buffer flushes the
-// remaining buffered messages and closes the returned channel.
-// The timeAfter func should be time.After. It exists for testing.
-func buffer(in <-chan *Message, timeAfter func(time.Duration) <-chan time.Time) <-chan *Message {
-       out := make(chan *Message)
-       go func() {
-               defer close(out)
-               var (
-                       tc    <-chan time.Time
-                       buf   []byte
-                       kind  string
-                       flush = func() {
-                               if len(buf) == 0 {
-                                       return
-                               }
-                               out <- &Message{Kind: kind, Body: safeString(buf)}
-                               buf = buf[:0] // recycle buffer
-                               kind = ""
-                       }
-               )
-               for {
-                       select {
-                       case m, ok := <-in:
-                               if !ok {
-                                       flush()
-                                       return
-                               }
-                               if m.Kind == "end" {
-                                       flush()
-                                       out <- m
-                                       return
-                               }
-                               if kind != m.Kind {
-                                       flush()
-                                       kind = m.Kind
-                                       if tc == nil {
-                                               tc = timeAfter(msgDelay)
-                                       }
-                               }
-                               buf = append(buf, m.Body...)
-                       case <-tc:
-                               flush()
-                               tc = nil
-                       }
-               }
-       }()
-       return out
-}
-
-// Kill stops the process if it is running and waits for it to exit.
-func (p *process) Kill() {
-       if p == nil || p.run == nil {
-               return
-       }
-       p.run.Process.Kill()
-       <-p.done // block until process exits
-}
-
-// shebang looks for a shebang ('#!') at the beginning of the passed string.
-// If found, it returns the path and args after the shebang.
-// args includes the command as args[0].
-func shebang(body string) (path string, args []string) {
-       body = strings.TrimSpace(body)
-       if !strings.HasPrefix(body, "#!") {
-               return "", nil
-       }
-       if i := strings.Index(body, "\n"); i >= 0 {
-               body = body[:i]
-       }
-       fs := strings.Fields(body[2:])
-       return fs[0], fs
-}
-
-// startProcess starts a given program given its path and passing the given body
-// to the command standard input.
-func (p *process) startProcess(path string, args []string, body string) error {
-       cmd := &exec.Cmd{
-               Path:   path,
-               Args:   args,
-               Stdin:  strings.NewReader(body),
-               Stdout: &messageWriter{kind: "stdout", out: p.out},
-               Stderr: &messageWriter{kind: "stderr", out: p.out},
-       }
-       if err := cmd.Start(); err != nil {
-               return err
-       }
-       p.run = cmd
-       return nil
-}
-
-// start builds and starts the given program, sending its output to p.out,
-// and stores the running *exec.Cmd in the run field.
-func (p *process) start(body string, opt *Options) error {
-       // We "go build" and then exec the binary so that the
-       // resultant *exec.Cmd is a handle to the user's program
-       // (rather than the go tool process).
-       // This makes Kill work.
-
-       path, err := ioutil.TempDir("", "present-")
-       if err != nil {
-               return err
-       }
-       p.path = path // to be removed by p.end
-
-       out := "prog"
-       if runtime.GOOS == "windows" {
-               out = "prog.exe"
-       }
-       bin := filepath.Join(path, out)
-
-       // write body to x.go files
-       a := txtar.Parse([]byte(body))
-       if len(a.Comment) != 0 {
-               a.Files = append(a.Files, txtar.File{Name: "prog.go", Data: a.Comment})
-               a.Comment = nil
-       }
-       hasModfile := false
-       for _, f := range a.Files {
-               err = ioutil.WriteFile(filepath.Join(path, f.Name), f.Data, 0666)
-               if err != nil {
-                       return err
-               }
-               if f.Name == "go.mod" {
-                       hasModfile = true
-               }
-       }
-
-       // build x.go, creating x
-       args := []string{"go", "build", "-tags", "OMIT"}
-       if opt != nil && opt.Race {
-               p.out <- &Message{
-                       Kind: "stderr",
-                       Body: "Running with race detector.\n",
-               }
-               args = append(args, "-race")
-       }
-       args = append(args, "-o", bin)
-       cmd := p.cmd(path, args...)
-       if !hasModfile {
-               cmd.Env = append(cmd.Env, "GO111MODULE=off")
-       }
-       cmd.Stdout = cmd.Stderr // send compiler output to stderr
-       if err := cmd.Run(); err != nil {
-               return err
-       }
-
-       // run x
-       if isNacl() {
-               cmd, err = p.naclCmd(bin)
-               if err != nil {
-                       return err
-               }
-       } else {
-               cmd = p.cmd("", bin)
-       }
-       if opt != nil && opt.Race {
-               cmd.Env = append(cmd.Env, "GOMAXPROCS=2")
-       }
-       if err := cmd.Start(); err != nil {
-               // If we failed to exec, that might be because they built
-               // a non-main package instead of an executable.
-               // Check and report that.
-               if name, err := packageName(body); err == nil && name != "main" {
-                       return errors.New(`executable programs must use "package main"`)
-               }
-               return err
-       }
-       p.run = cmd
-       return nil
-}
-
-// cmd builds an *exec.Cmd that writes its standard output and error to the
-// process' output channel.
-func (p *process) cmd(dir string, args ...string) *exec.Cmd {
-       cmd := exec.Command(args[0], args[1:]...)
-       cmd.Dir = dir
-       cmd.Env = Environ()
-       cmd.Stdout = &messageWriter{kind: "stdout", out: p.out}
-       cmd.Stderr = &messageWriter{kind: "stderr", out: p.out}
-       return cmd
-}
-
-func isNacl() bool {
-       for _, v := range append(Environ(), os.Environ()...) {
-               if v == "GOOS=nacl" {
-                       return true
-               }
-       }
-       return false
-}
-
-// naclCmd returns an *exec.Cmd that executes bin under native client.
-func (p *process) naclCmd(bin string) (*exec.Cmd, error) {
-       pwd, err := os.Getwd()
-       if err != nil {
-               return nil, err
-       }
-       var args []string
-       env := []string{
-               "NACLENV_GOOS=" + runtime.GOOS,
-               "NACLENV_GOROOT=/go",
-               "NACLENV_NACLPWD=" + strings.Replace(pwd, runtime.GOROOT(), "/go", 1),
-       }
-       switch runtime.GOARCH {
-       case "amd64":
-               env = append(env, "NACLENV_GOARCH=amd64p32")
-               args = []string{"sel_ldr_x86_64"}
-       case "386":
-               env = append(env, "NACLENV_GOARCH=386")
-               args = []string{"sel_ldr_x86_32"}
-       case "arm":
-               env = append(env, "NACLENV_GOARCH=arm")
-               selLdr, err := exec.LookPath("sel_ldr_arm")
-               if err != nil {
-                       return nil, err
-               }
-               args = []string{"nacl_helper_bootstrap_arm", selLdr, "--reserved_at_zero=0xXXXXXXXXXXXXXXXX"}
-       default:
-               return nil, errors.New("native client does not support GOARCH=" + runtime.GOARCH)
-       }
-
-       cmd := p.cmd("", append(args, "-l", "/dev/null", "-S", "-e", bin)...)
-       cmd.Env = append(cmd.Env, env...)
-
-       return cmd, nil
-}
-
-func packageName(body string) (string, error) {
-       f, err := parser.ParseFile(token.NewFileSet(), "prog.go",
-               strings.NewReader(body), parser.PackageClauseOnly)
-       if err != nil {
-               return "", err
-       }
-       return f.Name.String(), nil
-}
-
-// messageWriter is an io.Writer that converts all writes to Message sends on
-// the out channel with the specified id and kind.
-type messageWriter struct {
-       kind string
-       out  chan<- *Message
-}
-
-func (w *messageWriter) Write(b []byte) (n int, err error) {
-       w.out <- &Message{Kind: w.kind, Body: safeString(b)}
-       return len(b), nil
-}
-
-// safeString returns b as a valid UTF-8 string.
-func safeString(b []byte) string {
-       if utf8.Valid(b) {
-               return string(b)
-       }
-       var buf bytes.Buffer
-       for len(b) > 0 {
-               r, size := utf8.DecodeRune(b)
-               b = b[size:]
-               buf.WriteRune(r)
-       }
-       return buf.String()
-}