github.com/pawelgaczynski/gain@v0.4.0-alpha.0.20230821120126-41f1e60a18da/socket.go (about) 1 // Copyright (c) 2023 Paweł Gaczyński 2 // Copyright (c) 2019 Andy Pan 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package gain 17 18 import ( 19 "net" 20 "runtime" 21 "strings" 22 23 "github.com/pawelgaczynski/gain/pkg/errors" 24 gainNet "github.com/pawelgaczynski/gain/pkg/net" 25 "github.com/pawelgaczynski/gain/pkg/socket" 26 ) 27 28 func parseProtoAddr(addr string) (string, string) { 29 network := gainNet.TCP 30 31 address := strings.ToLower(addr) 32 if strings.Contains(address, "://") { 33 pair := strings.Split(address, "://") 34 network = pair[0] 35 address = pair[1] 36 } 37 38 return network, address 39 } 40 41 type listener struct { 42 fd int 43 addr net.Addr 44 address, network string 45 sockOpts []socket.Option 46 } 47 48 func (ln *listener) normalize() error { 49 var err error 50 51 switch ln.network { 52 case gainNet.TCP, gainNet.TCP4, gainNet.TCP6: 53 ln.fd, ln.addr, err = socket.TCPSocket(ln.network, ln.address, true, ln.sockOpts...) 54 ln.network = gainNet.TCP 55 56 case gainNet.UDP, gainNet.UDP4, gainNet.UDP6: 57 ln.fd, ln.addr, err = socket.UDPSocket(ln.network, ln.address, false, ln.sockOpts...) 58 ln.network = gainNet.UDP 59 60 default: 61 err = errors.ErrUnsupportedProtocol 62 } 63 64 return err 65 } 66 67 func initListener(network, addr string, config Config) (*listener, error) { 68 var ( 69 ln *listener 70 err error 71 sockOpts []socket.Option 72 ) 73 74 sockOpt := socket.Option{SetSockOpt: socket.SetReuseport, Opt: 1} 75 sockOpts = append(sockOpts, sockOpt) 76 sockOpt = socket.Option{SetSockOpt: socket.SetReuseAddr, Opt: 1} 77 sockOpts = append(sockOpts, sockOpt) 78 79 if strings.HasPrefix(network, gainNet.TCP) { 80 sockOpt = socket.Option{SetSockOpt: socket.SetNoDelay, Opt: 1} 81 sockOpts = append(sockOpts, sockOpt) 82 83 sockOpt = socket.Option{SetSockOpt: socket.SetQuickAck, Opt: 1} 84 sockOpts = append(sockOpts, sockOpt) 85 86 sockOpt = socket.Option{SetSockOpt: socket.SetFastOpen, Opt: 1} 87 sockOpts = append(sockOpts, sockOpt) 88 } 89 90 if config.SocketRecvBufferSize > 0 { 91 sockOpt = socket.Option{SetSockOpt: socket.SetRecvBuffer, Opt: config.SocketRecvBufferSize} 92 sockOpts = append(sockOpts, sockOpt) 93 } 94 95 if config.SocketSendBufferSize > 0 { 96 sockOpt = socket.Option{SetSockOpt: socket.SetSendBuffer, Opt: config.SocketSendBufferSize} 97 sockOpts = append(sockOpts, sockOpt) 98 } 99 100 ln = &listener{network: network, address: addr, sockOpts: sockOpts} 101 err = ln.normalize() 102 103 if config.CBPFilter { 104 err = newFilter(uint32(runtime.NumCPU())).applyTo(ln.fd) 105 if err != nil { 106 return ln, err 107 } 108 } 109 110 return ln, err 111 }