github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/websocket/client.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package websocket 6 7 import ( 8 "bufio" 9 "io" 10 "net" 11 "net/url" 12 13 http "github.com/hxx258456/ccgo/gmhttp" 14 ) 15 16 // DialError is an error that occurs while dialling a websocket server. 17 type DialError struct { 18 *Config 19 Err error 20 } 21 22 func (e *DialError) Error() string { 23 return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error() 24 } 25 26 // NewConfig creates a new WebSocket config for client connection. 27 func NewConfig(server, origin string) (config *Config, err error) { 28 config = new(Config) 29 config.Version = ProtocolVersionHybi13 30 config.Location, err = url.ParseRequestURI(server) 31 if err != nil { 32 return 33 } 34 config.Origin, err = url.ParseRequestURI(origin) 35 if err != nil { 36 return 37 } 38 config.Header = http.Header(make(map[string][]string)) 39 return 40 } 41 42 // NewClient creates a new WebSocket client connection over rwc. 43 func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) { 44 br := bufio.NewReader(rwc) 45 bw := bufio.NewWriter(rwc) 46 err = hybiClientHandshake(config, br, bw) 47 if err != nil { 48 return 49 } 50 buf := bufio.NewReadWriter(br, bw) 51 ws = newHybiClientConn(config, buf, rwc) 52 return 53 } 54 55 // Dial opens a new client connection to a WebSocket. 56 func Dial(url_, protocol, origin string) (ws *Conn, err error) { 57 config, err := NewConfig(url_, origin) 58 if err != nil { 59 return nil, err 60 } 61 if protocol != "" { 62 config.Protocol = []string{protocol} 63 } 64 return DialConfig(config) 65 } 66 67 var portMap = map[string]string{ 68 "ws": "80", 69 "wss": "443", 70 } 71 72 func parseAuthority(location *url.URL) string { 73 if _, ok := portMap[location.Scheme]; ok { 74 if _, _, err := net.SplitHostPort(location.Host); err != nil { 75 return net.JoinHostPort(location.Host, portMap[location.Scheme]) 76 } 77 } 78 return location.Host 79 } 80 81 // DialConfig opens a new client connection to a WebSocket with a config. 82 func DialConfig(config *Config) (ws *Conn, err error) { 83 var client net.Conn 84 if config.Location == nil { 85 return nil, &DialError{config, ErrBadWebSocketLocation} 86 } 87 if config.Origin == nil { 88 return nil, &DialError{config, ErrBadWebSocketOrigin} 89 } 90 dialer := config.Dialer 91 if dialer == nil { 92 dialer = &net.Dialer{} 93 } 94 client, err = dialWithDialer(dialer, config) 95 if err != nil { 96 goto Error 97 } 98 ws, err = NewClient(config, client) 99 if err != nil { 100 client.Close() 101 goto Error 102 } 103 return 104 105 Error: 106 return nil, &DialError{config, err} 107 }