forked from libp2p/go-libp2p
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2d29093
commit 2d53c8f
Showing
15 changed files
with
243 additions
and
842 deletions.
There are no files selected for viewing
71 changes: 0 additions & 71 deletions
71
p2p/transport/websocket/browser_integration_browser_test.go
This file was deleted.
Oops, something went wrong.
109 changes: 0 additions & 109 deletions
109
p2p/transport/websocket/browser_integration_native_test.go
This file was deleted.
Oops, something went wrong.
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 |
---|---|---|
@@ -1,12 +1,149 @@ | ||
package websocket | ||
|
||
import ( | ||
"io" | ||
"net" | ||
"sync" | ||
"time" | ||
|
||
ws "github.com/gorilla/websocket" | ||
) | ||
|
||
// GracefulCloseTimeout is the time to wait trying to gracefully close a | ||
// connection before simply cutting it. | ||
var GracefulCloseTimeout = 100 * time.Millisecond | ||
|
||
// Conn implements net.Conn interface for gorilla/websocket. | ||
type Conn struct { | ||
*ws.Conn | ||
DefaultMessageType int | ||
reader io.Reader | ||
closeOnce sync.Once | ||
|
||
readLock, writeLock sync.Mutex | ||
} | ||
|
||
var _ net.Conn = (*Conn)(nil) | ||
|
||
func (c *Conn) Read(b []byte) (int, error) { | ||
c.readLock.Lock() | ||
defer c.readLock.Unlock() | ||
|
||
if c.reader == nil { | ||
if err := c.prepNextReader(); err != nil { | ||
return 0, err | ||
} | ||
} | ||
|
||
for { | ||
n, err := c.reader.Read(b) | ||
switch err { | ||
case io.EOF: | ||
c.reader = nil | ||
|
||
if n > 0 { | ||
return n, nil | ||
} | ||
|
||
if err := c.prepNextReader(); err != nil { | ||
return 0, err | ||
} | ||
|
||
// explicitly looping | ||
default: | ||
return n, err | ||
} | ||
} | ||
} | ||
|
||
func (c *Conn) prepNextReader() error { | ||
t, r, err := c.Conn.NextReader() | ||
if err != nil { | ||
if wserr, ok := err.(*ws.CloseError); ok { | ||
if wserr.Code == 1000 || wserr.Code == 1005 { | ||
return io.EOF | ||
} | ||
} | ||
return err | ||
} | ||
|
||
if t == ws.CloseMessage { | ||
return io.EOF | ||
} | ||
|
||
c.reader = r | ||
return nil | ||
} | ||
|
||
func (c *Conn) Write(b []byte) (n int, err error) { | ||
c.writeLock.Lock() | ||
defer c.writeLock.Unlock() | ||
|
||
if err := c.Conn.WriteMessage(c.DefaultMessageType, b); err != nil { | ||
return 0, err | ||
} | ||
|
||
return len(b), nil | ||
} | ||
|
||
// Close closes the connection. Only the first call to Close will receive the | ||
// close error, subsequent and concurrent calls will return nil. | ||
// This method is thread-safe. | ||
func (c *Conn) Close() error { | ||
var err error | ||
c.closeOnce.Do(func() { | ||
err1 := c.Conn.WriteControl( | ||
ws.CloseMessage, | ||
ws.FormatCloseMessage(ws.CloseNormalClosure, "closed"), | ||
time.Now().Add(GracefulCloseTimeout), | ||
) | ||
err2 := c.Conn.Close() | ||
switch { | ||
case err1 != nil: | ||
err = err1 | ||
case err2 != nil: | ||
err = err2 | ||
} | ||
}) | ||
return err | ||
} | ||
|
||
func (c *Conn) LocalAddr() net.Addr { | ||
return NewAddr(c.Conn.LocalAddr().String()) | ||
} | ||
|
||
func (c *Conn) RemoteAddr() net.Addr { | ||
return NewAddr(c.Conn.RemoteAddr().String()) | ||
} | ||
|
||
func (c *Conn) SetDeadline(t time.Time) error { | ||
if err := c.SetReadDeadline(t); err != nil { | ||
return err | ||
} | ||
|
||
return c.SetWriteDeadline(t) | ||
} | ||
|
||
func (c *Conn) SetReadDeadline(t time.Time) error { | ||
// Don't lock when setting the read deadline. That would prevent us from | ||
// interrupting an in-progress read. | ||
return c.Conn.SetReadDeadline(t) | ||
} | ||
|
||
func (c *Conn) SetWriteDeadline(t time.Time) error { | ||
// Unlike the read deadline, we need to lock when setting the write | ||
// deadline. | ||
|
||
c.writeLock.Lock() | ||
defer c.writeLock.Unlock() | ||
|
||
return c.Conn.SetWriteDeadline(t) | ||
} | ||
|
||
// NewConn creates a Conn given a regular gorilla/websocket Conn. | ||
func NewConn(raw *ws.Conn) *Conn { | ||
return &Conn{ | ||
Conn: raw, | ||
DefaultMessageType: ws.BinaryMessage, | ||
} | ||
} |
Oops, something went wrong.