-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
saves work to continue somewhere else
- Loading branch information
Showing
5 changed files
with
394 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package tcp | ||
|
||
import ( | ||
"strings" | ||
) | ||
|
||
// ErrRequest ... | ||
var ErrRequest = NewError("invalid request") | ||
|
||
// NewError ... | ||
func NewError(msg string, cause ...error) error { | ||
if cause == nil { | ||
return &Error{msg: msg} | ||
} | ||
return &Error{msg: msg, cause: cause[0]} | ||
} | ||
|
||
// Error ... | ||
type Error struct { | ||
msg string | ||
cause error | ||
} | ||
|
||
// Error implements the error interface. | ||
func (e *Error) Error() string { | ||
if e.cause == nil { | ||
return "tcp: " + e.msg | ||
} | ||
return "tcp: " + e.msg + ": " + e.cause.Error() | ||
} | ||
|
||
// Errors ... | ||
type Errors []error | ||
|
||
// Error implements the error interface. | ||
func (e Errors) Error() string { | ||
var ( | ||
b strings.Builder | ||
err error | ||
) | ||
for i, r := range e { | ||
if i > 0 { | ||
if _, err = b.WriteString(", "); err != nil { | ||
return err.Error() | ||
} | ||
} | ||
if _, err = b.WriteString(r.Error()); err != nil { | ||
return err.Error() | ||
} | ||
} | ||
return b.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package tcp | ||
|
||
import ( | ||
"context" | ||
"io" | ||
"io/ioutil" | ||
) | ||
|
||
// Request represents an TCP request. | ||
type Request struct { | ||
// Method specifies the TCP step (SYN, ACK, FIN). | ||
Method string | ||
|
||
// Body is the request's body. | ||
Body io.ReadCloser | ||
|
||
// RemoteAddr returns the remote network address. | ||
RemoteAddr string | ||
|
||
ctx context.Context | ||
cancel context.CancelFunc | ||
} | ||
|
||
// Close implements the io.Closer interface. | ||
func (r *Request) Cancel() { | ||
if r.cancel != nil { | ||
r.cancel() | ||
} | ||
} | ||
|
||
// Closed implements the Conn interface. | ||
func (r *Request) Closed() <-chan struct{} { | ||
return r.Context().Done() | ||
} | ||
|
||
// Context returns the request's context. | ||
func (r *Request) Context() context.Context { | ||
if r.ctx != nil { | ||
return r.ctx | ||
} | ||
return context.Background() | ||
} | ||
|
||
// WithCancel returns a shallow copy of the given request with its context changed to ctx. | ||
func (r *Request) WithCancel(ctx context.Context) *Request { | ||
if ctx == nil { | ||
// awkward: nothing to do | ||
return r | ||
} | ||
r2 := new(Request) | ||
*r2 = *r | ||
r2.ctx, r2.cancel = context.WithCancel(ctx) | ||
return r2 | ||
} | ||
|
||
// NewRequest ... | ||
func NewRequest(method string, body io.Reader) (*Request, error) { | ||
if method == "" { | ||
return nil, ErrRequest | ||
} | ||
rc, ok := body.(io.ReadCloser) | ||
if !ok && body != nil { | ||
rc = ioutil.NopCloser(body) | ||
} | ||
req := &Request{ | ||
Method: method, | ||
Body: rc, | ||
} | ||
return req, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package tcp | ||
|
||
import ( | ||
"io" | ||
"net" | ||
) | ||
|
||
const noWritten = 1 | ||
|
||
// ResponseWriter interface is used by an TCP handler to construct the response. | ||
type ResponseWriter interface { | ||
// Writer is the interface that wraps the basic Write method. | ||
io.Writer | ||
// WriteString allow to directly write string. | ||
WriteString(s string) (n int, err error) | ||
// Size returns the number of bytes already written into the response body. | ||
// -1: not already written | ||
Size() int | ||
} | ||
|
||
type responseWriter struct { | ||
conn io.Writer | ||
size int | ||
} | ||
|
||
func newResponseWriter(c net.Conn) *responseWriter { | ||
return &responseWriter{ | ||
conn: c, | ||
size: noWritten, | ||
} | ||
} | ||
|
||
// Write implements the ResponseWriter interface. | ||
func (w *responseWriter) Size() int { | ||
return w.size | ||
} | ||
|
||
// Write implements the ResponseWriter interface. | ||
func (w *responseWriter) Write(p []byte) (n int, err error) { | ||
n, err = w.conn.Write(p) | ||
w.incr(n) | ||
return | ||
} | ||
|
||
// Write implements the ResponseWriter interface. | ||
func (w *responseWriter) WriteString(s string) (n int, err error) { | ||
n, err = io.WriteString(w.conn, s) | ||
w.incr(n) | ||
return | ||
} | ||
|
||
func (w *responseWriter) incr(n int) { | ||
if n == noWritten { | ||
n = 0 | ||
} | ||
w.size += n | ||
} | ||
|
||
func (w *responseWriter) rebase(conn io.Writer) { | ||
w.conn = conn | ||
w.size = noWritten | ||
} |
Oops, something went wrong.