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 63 return c.Reader.Read(p) 64 } 65 66 // Write implements the io.Writer interface. 67 func (c *Conn) Write(p []byte) (int, error) { 68 if !c.ReadDeadline.IsZero() && time.Now().After(c.WriteDeadline) { 69 return 0, ErrTimeout 70 } 71 72 return c.Writer.Write(p) 73 } 74 75 // LocalAddr returns the Local Address. 76 func (c *Conn) LocalAddr() net.Addr { 77 return c.Local 78 } 79 80 // RemoteAddr returns the Remote Address. 81 func (c *Conn) RemoteAddr() net.Addr { 82 return c.Remote 83 } 84 85 // SetDeadline implements the Conn SetDeadline method. 86 func (c *Conn) SetDeadline(t time.Time) error { 87 err := c.SetReadDeadline(t) 88 err2 := c.SetWriteDeadline(t) 89 90 if err != nil { 91 return err 92 } 93 94 return err2 95 } 96 97 // SetReadDeadline implements the Conn SetReadDeadline method. 98 func (c *Conn) SetReadDeadline(t time.Time) error { 99 c.ReadDeadline = t 100 101 if rd, ok := c.Writer.(interface { 102 SetReadDeadline(time.Time) error 103 }); ok { 104 return rd.SetReadDeadline(t) 105 } 106 107 return nil 108 } 109 110 // SetWriteDeadline implements the Conn SetWriteDeadline method. 111 func (c *Conn) SetWriteDeadline(t time.Time) error { 112 c.WriteDeadline = t 113 114 if wd, ok := c.Writer.(interface { 115 SetWriteDeadline(time.Time) error 116 }); ok { 117 return wd.SetWriteDeadline(t) 118 } 119 120 return nil 121 } 122 123 // Errors. 124 var ( 125 ErrTimeout = errors.New("timeout occurred") 126 ) 127