github.com/jshiv/can-go@v0.2.1-0.20210224011015-069e90e90bdf/pkg/socketcan/dial.go (about) 1 package socketcan 2 3 import ( 4 "context" 5 "net" 6 ) 7 8 const udp = "udp" 9 10 // Dial connects to the address on the named net. 11 // 12 // Linux only: If net is "can" it creates a SocketCAN connection to the device 13 // (address is interpreted as a device name). 14 // 15 // If net is "udp" it assumes UDP multicast and sets up 2 connections, one for 16 // receiving and one for transmitting. 17 // See: https://golang.org/pkg/net/#Dial 18 func Dial(network, address string) (net.Conn, error) { 19 switch network { 20 case udp: 21 return udpTransceiver(network, address) 22 case canRawNetwork: 23 return dialRaw(address) // platform-specific 24 default: 25 return net.Dial(network, address) 26 } 27 } 28 29 // DialContext connects to the address on the named net using 30 // the provided context. 31 // 32 // Linux only: If net is "can" it creates a SocketCAN connection to the device 33 // (address is interpreted as a device name). 34 // 35 // See: https://golang.org/pkg/net/#Dialer.DialContext 36 func DialContext(ctx context.Context, network, address string) (net.Conn, error) { 37 switch network { 38 case canRawNetwork: 39 return dialCtx(ctx, func() (net.Conn, error) { 40 return dialRaw(address) 41 }) 42 case udp: 43 return dialCtx(ctx, func() (net.Conn, error) { 44 return udpTransceiver(network, address) 45 }) 46 default: 47 var d net.Dialer 48 return d.DialContext(ctx, network, address) 49 } 50 } 51 52 func dialCtx(ctx context.Context, connProvider func() (net.Conn, error)) (net.Conn, error) { 53 resultChan := make(chan struct { 54 conn net.Conn 55 err error 56 }) 57 go func() { 58 conn, err := connProvider() 59 resultChan <- struct { 60 conn net.Conn 61 err error 62 }{conn: conn, err: err} 63 }() 64 // wait for connection or timeout 65 select { 66 case result := <-resultChan: 67 return result.conn, result.err 68 case <-ctx.Done(): 69 // timeout - make sure we clean up the connection 70 // error handling not possible since we've already returned 71 go func() { 72 result := <-resultChan 73 if result.conn != nil { 74 _ = result.conn.Close() 75 } 76 }() 77 return nil, ctx.Err() 78 } 79 }