1 // Package ioconn allows any combination of an io.Reader, io.Writer and io.Closer to become a net.Conn 2 package ioconn // import "vimagination.zapto.org/ioconn" 3 4 import ( 5 "errors" 6 "io" 7 "net" 8 "time" 9 ) 10 11 // CloserFunc is a func that implements the io.Closer interface allowing a 12 // closure or other function to be io.Closer 13 type CloserFunc func() error 14 15 // Close simply calls the CloserFunc func 16 func (c CloserFunc) Close() error { 17 return c() 18 } 19 20 // FileAddr is a net.Addr that represents a file. Should be a full path 21 type FileAddr string 22 23 // Network always returns "file" 24 func (f FileAddr) Network() string { 25 return "file" 26 } 27 28 // String returns file://path 29 func (f FileAddr) String() string { 30 return "file://" + string(f) 31 } 32 33 // Addr is a simple implementation of the net.Addr interface 34 type Addr struct { 35 Net, Str string 36 } 37 38 // Network returns the Net string 39 func (a Addr) Network() string { 40 return a.Net 41 } 42 43 // String returns the Str string 44 func (a Addr) String() string { 45 return a.Str 46 } 47 48 // Conn implements a net.Conn 49 type Conn struct { 50 io.Reader 51 io.Writer 52 io.Closer 53 Local, Remote net.Addr 54 ReadDeadline, WriteDeadline time.Time 55 } 56 57 // Read implements the io.Reader interface 58 func (c *Conn) Read(p []byte) (int, error) { 59 if !c.ReadDeadline.IsZero() && time.Now().After(c.ReadDeadline) { 60 return 0, ErrTimeout 61 } 62 return c.Reader.Read(p) 63 } 64 65 // Write implements the io.Writer interface 66 func (c *Conn) Write(p []byte) (int, error) { 67 if !c.ReadDeadline.IsZero() && time.Now().After(c.WriteDeadline) { 68 return 0, ErrTimeout 69 } 70 return c.Writer.Write(p) 71 } 72 73 // LocalAddr returns the Local Address 74 func (c *Conn) LocalAddr() net.Addr { 75 return c.Local 76 } 77 78 // RemoteAddr returns the Remote Address 79 func (c *Conn) RemoteAddr() net.Addr { 80 return c.Remote 81 } 82 83 // SetDeadline implements the Conn SetDeadline method 84 func (c *Conn) SetDeadline(t time.Time) error { 85 err := c.SetReadDeadline(t) 86 err2 := c.SetWriteDeadline(t) 87 if err != nil { 88 return err 89 } 90 return err2 91 } 92 93 // SetReadDeadline implements the Conn SetReadDeadline method 94 func (c *Conn) SetReadDeadline(t time.Time) error { 95 c.ReadDeadline = t 96 if rd, ok := c.Writer.(interface { 97 SetReadDeadline(time.Time) error 98 }); ok { 99 return rd.SetReadDeadline(t) 100 } 101 return nil 102 } 103 104 // SetWriteDeadline implements the Conn SetWriteDeadline method 105 func (c *Conn) SetWriteDeadline(t time.Time) error { 106 c.WriteDeadline = t 107 if wd, ok := c.Writer.(interface { 108 SetWriteDeadline(time.Time) error 109 }); ok { 110 return wd.SetWriteDeadline(t) 111 } 112 return nil 113 } 114 115 // Errors 116 var ( 117 ErrTimeout = errors.New("timeout occurred") 118 )