Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
c2a1b63a
Commit
c2a1b63a
authored
7 years ago
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
X naming: Packet = raw data; Message = meaningful object
Message can be delivered encoded in a packet.
parent
b13e8150
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
552 additions
and
555 deletions
+552
-555
go/neo/cluster_test.go
go/neo/cluster_test.go
+6
-0
go/neo/connection.go
go/neo/connection.go
+8
-8
go/neo/connection_test.go
go/neo/connection_test.go
+59
-70
go/neo/pkt.go
go/neo/pkt.go
+3
-1
go/neo/proto-marshal.go
go/neo/proto-marshal.go
+367
-367
go/neo/proto.go
go/neo/proto.go
+15
-15
go/neo/proto_test.go
go/neo/proto_test.go
+27
-27
go/neo/protogen.go
go/neo/protogen.go
+36
-36
go/neo/server/master.go
go/neo/server/master.go
+5
-5
go/neo/server/storage.go
go/neo/server/storage.go
+2
-2
go/neo/x_connection.go
go/neo/x_connection.go
+24
-24
No files found.
go/neo/cluster_test.go
View file @
c2a1b63a
...
...
@@ -53,6 +53,9 @@ func xfs1stor(net Network, path string) (*server.Storage, *fs1.FileStorage) {
// M drives cluster with 1 S through recovery -> verification -> service -> shutdown
func
TestMasterStorage
(
t
*
testing
.
T
)
{
// XXX temp disabled
return
net
:=
NetPipe
(
""
)
// test network FIXME New registers to global table
M
:=
server
.
NewMaster
(
"abc1"
)
S
,
_
:=
xfs1stor
(
net
,
"../zodb/storage/fs1/testdata/1.fs"
)
// XXX +readonly
...
...
@@ -70,6 +73,9 @@ func TestMasterStorage(t *testing.T) {
// basic interaction between Client -- Storage
func
TestClientStorage
(
t
*
testing
.
T
)
{
// XXX temp disabled
return
Cnl
,
Snl
:=
NodeLinkPipe
()
wg
:=
WorkGroup
()
...
...
This diff is collapsed.
Click to expand it.
go/neo/connection.go
View file @
c2a1b63a
...
...
@@ -297,7 +297,7 @@ func (nl *NodeLink) Accept() (c *Conn, err error) {
}
}
// errRecvShutdown returns appropriate error when c.down is found ready in
Recv
// errRecvShutdown returns appropriate error when c.down is found ready in
recvPkt
func
(
c
*
Conn
)
errRecvShutdown
()
error
{
switch
{
case
atomic
.
LoadUint32
(
&
c
.
closed
)
!=
0
:
...
...
@@ -323,8 +323,8 @@ func (c *Conn) errRecvShutdown() error {
}
}
//
Recv receives
packet from connection
func
(
c
*
Conn
)
Recv
()
(
*
PktBuf
,
error
)
{
//
recvPkt receives raw
packet from connection
func
(
c
*
Conn
)
recvPkt
()
(
*
PktBuf
,
error
)
{
select
{
case
<-
c
.
down
:
return
nil
,
c
.
err
(
"recv"
,
c
.
errRecvShutdown
())
...
...
@@ -441,13 +441,13 @@ func (c *Conn) errSendShutdown() error {
}
}
//
Send sends
packet via connection
func
(
c
*
Conn
)
Send
(
pkt
*
PktBuf
)
error
{
err
:=
c
.
send
(
pkt
)
//
sendPkt sends raw
packet via connection
func
(
c
*
Conn
)
sendPkt
(
pkt
*
PktBuf
)
error
{
err
:=
c
.
send
Pkt2
(
pkt
)
return
c
.
err
(
"send"
,
err
)
}
func
(
c
*
Conn
)
send
(
pkt
*
PktBuf
)
error
{
func
(
c
*
Conn
)
send
Pkt2
(
pkt
*
PktBuf
)
error
{
// set pkt connId associated with this connection
pkt
.
Header
()
.
ConnId
=
hton32
(
c
.
connId
)
var
err
error
...
...
@@ -541,7 +541,7 @@ func (nl *NodeLink) recvPkt() (*PktBuf, error) {
// first read to read pkt header and hopefully up to page of data in 1 syscall
pkt
:=
&
PktBuf
{
make
([]
byte
,
4096
)}
// TODO reenable, but NOTE next packet can be also prefetched here -> use buffering ?
//n, err := io.ReadAtLeast(nl.peerLink, p
kt
.Data, PktHeadLen)
//n, err := io.ReadAtLeast(nl.peerLink, p
tb
.Data, PktHeadLen)
n
,
err
:=
io
.
ReadFull
(
nl
.
peerLink
,
pkt
.
Data
[
:
PktHeadLen
])
if
err
!=
nil
{
return
nil
,
err
...
...
This diff is collapsed.
Click to expand it.
go/neo/connection_test.go
View file @
c2a1b63a
...
...
@@ -72,24 +72,13 @@ func xaccept(nl *NodeLink) *Conn {
return
c
}
func
xsend
(
c
*
Conn
,
pkt
*
PktBuf
)
{
err
:=
c
.
Send
(
pkt
)
func
xsend
Pkt
(
c
interface
{
sendPkt
(
*
PktBuf
)
error
}
,
pkt
*
PktBuf
)
{
err
:=
c
.
sendPkt
(
pkt
)
exc
.
Raiseif
(
err
)
}
func
xrecv
(
c
*
Conn
)
*
PktBuf
{
pkt
,
err
:=
c
.
Recv
()
exc
.
Raiseif
(
err
)
return
pkt
}
func
xsendPkt
(
nl
*
NodeLink
,
pkt
*
PktBuf
)
{
err
:=
nl
.
sendPkt
(
pkt
)
exc
.
Raiseif
(
err
)
}
func
xrecvPkt
(
nl
*
NodeLink
)
*
PktBuf
{
pkt
,
err
:=
nl
.
recvPkt
()
func
xrecvPkt
(
c
interface
{
recvPkt
()
(
*
PktBuf
,
error
)
})
*
PktBuf
{
pkt
,
err
:=
c
.
recvPkt
()
exc
.
Raiseif
(
err
)
return
pkt
}
...
...
@@ -134,7 +123,7 @@ func _mkpkt(connid uint32, msgcode uint16, payload []byte) *PktBuf {
}
func
mkpkt
(
msgcode
uint16
,
payload
[]
byte
)
*
PktBuf
{
// in Conn exchange connid is automatically set by Conn.
Send
// in Conn exchange connid is automatically set by Conn.
sendPkt
return
_mkpkt
(
0
,
msgcode
,
payload
)
}
...
...
@@ -300,7 +289,7 @@ func TestNodeLink(t *testing.T) {
// Test connections on top of nodelink
// Close vs
Recv
// Close vs
recvPkt
nl1
,
nl2
=
_nodeLinkPipe
(
0
,
linkNoRecvSend
)
c
=
xnewconn
(
nl1
)
wg
=
WorkGroup
()
...
...
@@ -308,15 +297,15 @@ func TestNodeLink(t *testing.T) {
tdelay
()
xclose
(
c
)
})
pkt
,
err
=
c
.
Recv
()
pkt
,
err
=
c
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
ErrClosedConn
)
{
t
.
Fatalf
(
"Conn.
Recv
() after close: pkt = %v err = %v"
,
pkt
,
err
)
t
.
Fatalf
(
"Conn.
recvPkt
() after close: pkt = %v err = %v"
,
pkt
,
err
)
}
xwait
(
wg
)
xclose
(
nl1
)
xclose
(
nl2
)
// Close vs
Send
// Close vs
sendPkt
nl1
,
nl2
=
_nodeLinkPipe
(
0
,
linkNoRecvSend
)
c
=
xnewconn
(
nl1
)
wg
=
WorkGroup
()
...
...
@@ -325,27 +314,27 @@ func TestNodeLink(t *testing.T) {
xclose
(
c
)
})
pkt
=
&
PktBuf
{[]
byte
(
"data"
)}
err
=
c
.
Send
(
pkt
)
err
=
c
.
sendPkt
(
pkt
)
if
xconnError
(
err
)
!=
ErrClosedConn
{
t
.
Fatalf
(
"Conn.
Send
() after close: err = %v"
,
err
)
t
.
Fatalf
(
"Conn.
sendPkt
() after close: err = %v"
,
err
)
}
xwait
(
wg
)
// NodeLink.Close vs Conn.
Send/Recv
// NodeLink.Close vs Conn.
sendPkt/recvPkt
c11
:=
xnewconn
(
nl1
)
c12
:=
xnewconn
(
nl1
)
wg
=
WorkGroup
()
wg
.
Gox
(
func
()
{
pkt
,
err
:=
c11
.
Recv
()
pkt
,
err
:=
c11
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
ErrLinkClosed
)
{
exc
.
Raisef
(
"Conn.
Recv
() after NodeLink close: pkt = %v err = %v"
,
pkt
,
err
)
exc
.
Raisef
(
"Conn.
recvPkt
() after NodeLink close: pkt = %v err = %v"
,
pkt
,
err
)
}
})
wg
.
Gox
(
func
()
{
pkt
:=
&
PktBuf
{[]
byte
(
"data"
)}
err
:=
c12
.
Send
(
pkt
)
err
:=
c12
.
sendPkt
(
pkt
)
if
xconnError
(
err
)
!=
ErrLinkClosed
{
exc
.
Raisef
(
"Conn.
Send
() after NodeLink close: err = %v"
,
err
)
exc
.
Raisef
(
"Conn.
sendPkt
() after NodeLink close: err = %v"
,
err
)
}
})
tdelay
()
...
...
@@ -355,7 +344,7 @@ func TestNodeLink(t *testing.T) {
xclose
(
c12
)
xclose
(
nl2
)
// NodeLink.Close vs Conn.
Send/Recv
and Accept on another side
// NodeLink.Close vs Conn.
sendPkt/recvPkt
and Accept on another side
nl1
,
nl2
=
_nodeLinkPipe
(
linkNoRecvSend
,
0
)
c21
:=
xnewconn
(
nl2
)
c22
:=
xnewconn
(
nl2
)
...
...
@@ -363,22 +352,22 @@ func TestNodeLink(t *testing.T) {
wg
=
WorkGroup
()
var
errRecv
error
wg
.
Gox
(
func
()
{
pkt
,
err
:=
c21
.
Recv
()
pkt
,
err
:=
c21
.
recvPkt
()
want1
:=
io
.
EOF
// if recvPkt wakes up due to peer close
want2
:=
io
.
ErrClosedPipe
// if recvPkt wakes up due to sendPkt wakes up first and closes nl1
cerr
:=
xconnError
(
err
)
if
!
(
pkt
==
nil
&&
(
cerr
==
want1
||
cerr
==
want2
))
{
exc
.
Raisef
(
"Conn.
Recv
after peer NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
exc
.
Raisef
(
"Conn.
recvPkt
after peer NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
}
errRecv
=
cerr
})
wg
.
Gox
(
func
()
{
pkt
:=
&
PktBuf
{[]
byte
(
"data"
)}
err
:=
c22
.
Send
(
pkt
)
err
:=
c22
.
sendPkt
(
pkt
)
want
:=
io
.
ErrClosedPipe
// always this in both due to peer close or recvPkt waking up and closing nl2
if
xconnError
(
err
)
!=
want
{
exc
.
Raisef
(
"Conn.
Send
after peer NodeLink shutdown: %v"
,
err
)
exc
.
Raisef
(
"Conn.
sendPkt
after peer NodeLink shutdown: %v"
,
err
)
}
})
...
...
@@ -406,46 +395,46 @@ func TestNodeLink(t *testing.T) {
t
.
Fatalf
(
"Accept after NodeLink shutdown: conn = %v err = %v"
,
c
,
err
)
}
//
Recv/Send
on another Conn
pkt
,
err
=
c23
.
Recv
()
//
recvPkt/sendPkt
on another Conn
pkt
,
err
=
c23
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
errRecv
)
{
t
.
Fatalf
(
"Conn.
Recv
2 after peer NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
t
.
Fatalf
(
"Conn.
recvPkt
2 after peer NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
}
err
=
c23
.
Send
(
&
PktBuf
{[]
byte
(
"data"
)})
err
=
c23
.
sendPkt
(
&
PktBuf
{[]
byte
(
"data"
)})
if
xconnError
(
err
)
!=
ErrLinkDown
{
t
.
Fatalf
(
"Conn.
Send
2 after peer NodeLink shutdown: %v"
,
err
)
t
.
Fatalf
(
"Conn.
sendPkt
2 after peer NodeLink shutdown: %v"
,
err
)
}
//
Recv/Send
error on second call
pkt
,
err
=
c21
.
Recv
()
//
recvPkt/sendPkt
error on second call
pkt
,
err
=
c21
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
ErrLinkDown
)
{
t
.
Fatalf
(
"Conn.
Recv
after NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
t
.
Fatalf
(
"Conn.
recvPkt
after NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
}
err
=
c22
.
Send
(
&
PktBuf
{[]
byte
(
"data"
)})
err
=
c22
.
sendPkt
(
&
PktBuf
{[]
byte
(
"data"
)})
if
xconnError
(
err
)
!=
ErrLinkDown
{
t
.
Fatalf
(
"Conn.
Send
after NodeLink shutdown: %v"
,
err
)
t
.
Fatalf
(
"Conn.
sendPkt
after NodeLink shutdown: %v"
,
err
)
}
xclose
(
c23
)
//
Recv/Send
on closed Conn but not closed NodeLink
pkt
,
err
=
c23
.
Recv
()
//
recvPkt/sendPkt
on closed Conn but not closed NodeLink
pkt
,
err
=
c23
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
ErrClosedConn
)
{
t
.
Fatalf
(
"Conn.
Recv
after close but only stopped NodeLink: pkt = %v err = %v"
,
pkt
,
err
)
t
.
Fatalf
(
"Conn.
recvPkt
after close but only stopped NodeLink: pkt = %v err = %v"
,
pkt
,
err
)
}
err
=
c23
.
Send
(
&
PktBuf
{[]
byte
(
"data"
)})
err
=
c23
.
sendPkt
(
&
PktBuf
{[]
byte
(
"data"
)})
if
xconnError
(
err
)
!=
ErrClosedConn
{
t
.
Fatalf
(
"Conn.
Send
after close but only stopped NodeLink: %v"
,
err
)
t
.
Fatalf
(
"Conn.
sendPkt
after close but only stopped NodeLink: %v"
,
err
)
}
xclose
(
nl2
)
//
Recv/Send
NewConn/Accept error after NodeLink close
pkt
,
err
=
c21
.
Recv
()
//
recvPkt/sendPkt
NewConn/Accept error after NodeLink close
pkt
,
err
=
c21
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
ErrLinkClosed
)
{
t
.
Fatalf
(
"Conn.
Recv
after NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
t
.
Fatalf
(
"Conn.
recvPkt
after NodeLink shutdown: pkt = %v err = %v"
,
pkt
,
err
)
}
err
=
c22
.
Send
(
&
PktBuf
{[]
byte
(
"data"
)})
err
=
c22
.
sendPkt
(
&
PktBuf
{[]
byte
(
"data"
)})
if
xconnError
(
err
)
!=
ErrLinkClosed
{
t
.
Fatalf
(
"Conn.
Send
after NodeLink shutdown: %v"
,
err
)
t
.
Fatalf
(
"Conn.
sendPkt
after NodeLink shutdown: %v"
,
err
)
}
c
,
err
=
nl2
.
NewConn
()
...
...
@@ -460,14 +449,14 @@ func TestNodeLink(t *testing.T) {
xclose
(
c21
)
xclose
(
c22
)
//
Recv/Send
error after Close & NodeLink shutdown
pkt
,
err
=
c21
.
Recv
()
//
recvPkt/sendPkt
error after Close & NodeLink shutdown
pkt
,
err
=
c21
.
recvPkt
()
if
!
(
pkt
==
nil
&&
xconnError
(
err
)
==
ErrClosedConn
)
{
t
.
Fatalf
(
"Conn.
Recv
after close and NodeLink close: pkt = %v err = %v"
,
pkt
,
err
)
t
.
Fatalf
(
"Conn.
recvPkt
after close and NodeLink close: pkt = %v err = %v"
,
pkt
,
err
)
}
err
=
c22
.
Send
(
&
PktBuf
{[]
byte
(
"data"
)})
err
=
c22
.
sendPkt
(
&
PktBuf
{[]
byte
(
"data"
)})
if
xconnError
(
err
)
!=
ErrClosedConn
{
t
.
Fatalf
(
"Conn.
Send
after close and NodeLink close: %v"
,
err
)
t
.
Fatalf
(
"Conn.
sendPkt
after close and NodeLink close: %v"
,
err
)
}
...
...
@@ -477,25 +466,25 @@ func TestNodeLink(t *testing.T) {
wg
.
Gox
(
func
()
{
c
:=
xaccept
(
nl2
)
pkt
:=
xrecv
(
c
)
pkt
:=
xrecv
Pkt
(
c
)
xverifyPkt
(
pkt
,
c
.
connId
,
33
,
[]
byte
(
"ping"
))
// change pkt a bit and send it back
xsend
(
c
,
mkpkt
(
34
,
[]
byte
(
"pong"
)))
xsend
Pkt
(
c
,
mkpkt
(
34
,
[]
byte
(
"pong"
)))
// one more time
pkt
=
xrecv
(
c
)
pkt
=
xrecv
Pkt
(
c
)
xverifyPkt
(
pkt
,
c
.
connId
,
35
,
[]
byte
(
"ping2"
))
xsend
(
c
,
mkpkt
(
36
,
[]
byte
(
"pong2"
)))
xsend
Pkt
(
c
,
mkpkt
(
36
,
[]
byte
(
"pong2"
)))
xclose
(
c
)
})
c
=
xnewconn
(
nl1
)
xsend
(
c
,
mkpkt
(
33
,
[]
byte
(
"ping"
)))
pkt
=
xrecv
(
c
)
xsend
Pkt
(
c
,
mkpkt
(
33
,
[]
byte
(
"ping"
)))
pkt
=
xrecv
Pkt
(
c
)
xverifyPkt
(
pkt
,
c
.
connId
,
34
,
[]
byte
(
"pong"
))
xsend
(
c
,
mkpkt
(
35
,
[]
byte
(
"ping2"
)))
pkt
=
xrecv
(
c
)
xsend
Pkt
(
c
,
mkpkt
(
35
,
[]
byte
(
"ping2"
)))
pkt
=
xrecv
Pkt
(
c
)
xverifyPkt
(
pkt
,
c
.
connId
,
36
,
[]
byte
(
"pong2"
))
xwait
(
wg
)
...
...
@@ -520,13 +509,13 @@ func TestNodeLink(t *testing.T) {
c
:=
xaccept
(
nl2
)
wg
.
Gox
(
func
()
{
pkt
:=
xrecv
(
c
)
pkt
:=
xrecv
Pkt
(
c
)
n
:=
ntoh16
(
pkt
.
Header
()
.
MsgCode
)
x
:=
replyOrder
[
n
]
// wait before it is our turn & echo pkt back
<-
x
.
start
xsend
(
c
,
pkt
)
xsend
Pkt
(
c
,
pkt
)
xclose
(
c
)
...
...
@@ -540,12 +529,12 @@ func TestNodeLink(t *testing.T) {
c1
:=
xnewconn
(
nl1
)
c2
:=
xnewconn
(
nl1
)
xsend
(
c1
,
mkpkt
(
1
,
[]
byte
(
""
)))
xsend
(
c2
,
mkpkt
(
2
,
[]
byte
(
""
)))
xsend
Pkt
(
c1
,
mkpkt
(
1
,
[]
byte
(
""
)))
xsend
Pkt
(
c2
,
mkpkt
(
2
,
[]
byte
(
""
)))
// replies must be coming in reverse order
xechoWait
:=
func
(
c
*
Conn
,
msgCode
uint16
)
{
pkt
:=
xrecv
(
c
)
pkt
:=
xrecv
Pkt
(
c
)
xverifyPkt
(
pkt
,
c
.
connId
,
msgCode
,
[]
byte
(
""
))
}
xechoWait
(
c2
,
2
)
...
...
This diff is collapsed.
Click to expand it.
go/neo/pkt.go
View file @
c2a1b63a
...
...
@@ -26,6 +26,8 @@ import (
// TODO organize rx buffers management (freelist etc)
// PktBuf is a buffer with full raw packet (header + data)
//
// variables of type PktBuf are usually named "pkb" (packet buffer), similar to "skb" in Linux
type
PktBuf
struct
{
Data
[]
byte
// whole packet data including all headers XXX -> Buf ?
}
...
...
@@ -61,7 +63,7 @@ func (pkt *PktBuf) String() string {
s
:=
fmt
.
Sprintf
(
".%d"
,
ntoh32
(
h
.
ConnId
))
msgCode
:=
ntoh16
(
h
.
MsgCode
)
msgType
:=
pkt
TypeRegistry
[
msgCode
]
msgType
:=
msg
TypeRegistry
[
msgCode
]
if
msgType
==
nil
{
s
+=
fmt
.
Sprintf
(
" ? (%d)"
,
msgCode
)
}
else
{
...
...
This diff is collapsed.
Click to expand it.
go/neo/proto-marshal.go
View file @
c2a1b63a
This diff is collapsed.
Click to expand it.
go/neo/proto.go
View file @
c2a1b63a
...
...
@@ -110,7 +110,7 @@ const (
// node finishes to replicate it. It means a partition is moved from 1 node
// to another.
FEEDING
//short: F
// Not really a state: only used in network
packet
s to tell storages to drop
// Not really a state: only used in network
message
s to tell storages to drop
// partitions.
DISCARDED
//short: D
// A check revealed that data differs from other replicas. Cell is neither
...
...
@@ -136,24 +136,24 @@ type NodeUUID int32
// TODO NodeType -> base NodeUUID
// ErrDecodeOverflow is the error returned by NEO
Pkt
Decode when decoding hit buffer overflow
// ErrDecodeOverflow is the error returned by NEO
Msg
Decode when decoding hit buffer overflow
var
ErrDecodeOverflow
=
errors
.
New
(
"decode: bufer overflow"
)
//
Pkt is the interface implemented by NEO packet
s to marshal/unmarshal them into/from wire format
type
Pkt
interface
{
// NEO
PktMsgCode returns message code needed to be used for particular packet
type
//
Msg is the interface implemented by NEO message
s to marshal/unmarshal them into/from wire format
type
Msg
interface
{
// NEO
MsgCode returns message code needed to be used for particular message
type
// on the wire
NEO
Pkt
MsgCode
()
uint16
NEOMsgCode
()
uint16
// NEO
PktEncodedLen returns how much space is needed to encode current state
NEO
Pkt
EncodedLen
()
int
// NEO
MsgEncodedLen returns how much space is needed to encode current message payload
NEO
Msg
EncodedLen
()
int
// NEO
PktEncode encodes current
state into buf.
// len(buf) must be >= NEO
Pkt
EncodedLen()
NEO
Pkt
Encode
(
buf
[]
byte
)
// NEO
MsgEncode encodes current message
state into buf.
// len(buf) must be >= NEO
Msg
EncodedLen()
NEO
Msg
Encode
(
buf
[]
byte
)
// NEO
PktDecode decodes data into current packet stat
e.
NEO
Pkt
Decode
(
data
[]
byte
)
(
nread
int
,
err
error
)
// NEO
MsgDecode decodes data into message in-plac
e.
NEO
Msg
Decode
(
data
[]
byte
)
(
nread
int
,
err
error
)
}
...
...
@@ -163,7 +163,7 @@ type Address struct {
}
// NOTE if Host == "" -> Port not added to wire (see py.PAddress):
// func (a *Address) NEO
Pkt
Encode(b []byte) int {
// func (a *Address) NEO
Msg
Encode(b []byte) int {
// n := string_NEOEncode(a.Host, b[0:])
// if a.Host != "" {
// BigEndian.PutUint16(b[n:], a.Port)
...
...
@@ -263,7 +263,7 @@ type Ping struct {
type
CloseClient
struct
{
}
// Request a node identification. This must be the first
packet
for any
// Request a node identification. This must be the first
message
for any
// connection. Any -> Any.
type
RequestIdentification
struct
{
NodeType
NodeType
// XXX name
...
...
This diff is collapsed.
Click to expand it.
go/neo/proto_test.go
View file @
c2a1b63a
...
...
@@ -68,10 +68,10 @@ func TestPktHeader(t *testing.T) {
}
}
// test marshalling for one
packet
type
func
test
PktMarshal
(
t
*
testing
.
T
,
pkt
Pkt
,
encoded
string
)
{
typ
:=
reflect
.
TypeOf
(
pkt
)
.
Elem
()
// type of *pkt
pkt2
:=
reflect
.
New
(
typ
)
.
Interface
()
.
(
Pkt
)
// test marshalling for one
message
type
func
test
MsgMarshal
(
t
*
testing
.
T
,
msg
Msg
,
encoded
string
)
{
typ
:=
reflect
.
TypeOf
(
msg
)
.
Elem
()
// type of *msg
msg2
:=
reflect
.
New
(
typ
)
.
Interface
()
.
(
Msg
)
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
t
.
Errorf
(
"%v: panic ↓↓↓:"
,
typ
)
...
...
@@ -79,10 +79,10 @@ func testPktMarshal(t *testing.T, pkt Pkt, encoded string) {
}
}()
//
pkt
.encode() == expected
msgCode
:=
pkt
.
NEOPkt
MsgCode
()
n
:=
pkt
.
NEOPkt
EncodedLen
()
msgType
:=
pkt
TypeRegistry
[
msgCode
]
//
msg
.encode() == expected
msgCode
:=
msg
.
NEO
MsgCode
()
n
:=
msg
.
NEOMsg
EncodedLen
()
msgType
:=
msg
TypeRegistry
[
msgCode
]
if
msgType
!=
typ
{
t
.
Errorf
(
"%v: msgCode = %v which corresponds to %v"
,
typ
,
msgCode
,
msgType
)
}
...
...
@@ -91,7 +91,7 @@ func testPktMarshal(t *testing.T, pkt Pkt, encoded string) {
}
buf
:=
make
([]
byte
,
n
)
pkt
.
NEOPkt
Encode
(
buf
)
msg
.
NEOMsg
Encode
(
buf
)
if
string
(
buf
)
!=
encoded
{
t
.
Errorf
(
"%v: encode result unexpected:"
,
typ
)
t
.
Errorf
(
"
\t
have: %s"
,
hexpkg
.
EncodeToString
(
buf
))
...
...
@@ -121,13 +121,13 @@ func testPktMarshal(t *testing.T, pkt Pkt, encoded string) {
}
}()
pkt
.
NEOPkt
Encode
(
buf
[
:
l
])
msg
.
NEOMsg
Encode
(
buf
[
:
l
])
}()
}
//
pkt
.decode() == expected
//
msg
.decode() == expected
data
:=
[]
byte
(
encoded
+
"noise"
)
n
,
err
:=
pkt2
.
NEOPkt
Decode
(
data
)
n
,
err
:=
msg2
.
NEOMsg
Decode
(
data
)
if
err
!=
nil
{
t
.
Errorf
(
"%v: decode error %v"
,
typ
,
err
)
}
...
...
@@ -135,13 +135,13 @@ func testPktMarshal(t *testing.T, pkt Pkt, encoded string) {
t
.
Errorf
(
"%v: nread = %v ; want %v"
,
typ
,
n
,
len
(
encoded
))
}
if
!
reflect
.
DeepEqual
(
pkt2
,
pkt
)
{
t
.
Errorf
(
"%v: decode result unexpected: %v ; want %v"
,
typ
,
pkt2
,
pkt
)
if
!
reflect
.
DeepEqual
(
msg2
,
msg
)
{
t
.
Errorf
(
"%v: decode result unexpected: %v ; want %v"
,
typ
,
msg2
,
msg
)
}
// decode must detect buffer overflow
for
l
:=
len
(
encoded
)
-
1
;
l
>=
0
;
l
--
{
n
,
err
=
pkt2
.
NEOPkt
Decode
(
data
[
:
l
])
n
,
err
=
msg2
.
NEOMsg
Decode
(
data
[
:
l
])
if
!
(
n
==
0
&&
err
==
ErrDecodeOverflow
)
{
t
.
Errorf
(
"%v: decode overflow not detected on [:%v]"
,
typ
,
l
)
}
...
...
@@ -149,10 +149,10 @@ func testPktMarshal(t *testing.T, pkt Pkt, encoded string) {
}
}
// test encoding/decoding of
packet
s
func
Test
Pkt
Marshal
(
t
*
testing
.
T
)
{
// test encoding/decoding of
message
s
func
Test
Msg
Marshal
(
t
*
testing
.
T
)
{
var
testv
=
[]
struct
{
pkt
Pkt
msg
Msg
encoded
string
// []byte
}
{
// empty
...
...
@@ -259,25 +259,25 @@ func TestPktMarshal(t *testing.T) {
}
for
_
,
tt
:=
range
testv
{
test
PktMarshal
(
t
,
tt
.
pkt
,
tt
.
encoded
)
test
MsgMarshal
(
t
,
tt
.
msg
,
tt
.
encoded
)
}
}
// For all
packet types: same as testPkt
Marshal but zero-values only
// For all
message types: same as testMsg
Marshal but zero-values only
// this way we additionally lightly check encode / decode overflow behaviour for all types.
func
Test
Pkt
MarshalAllOverflowLightly
(
t
*
testing
.
T
)
{
for
_
,
typ
:=
range
pkt
TypeRegistry
{
func
Test
Msg
MarshalAllOverflowLightly
(
t
*
testing
.
T
)
{
for
_
,
typ
:=
range
msg
TypeRegistry
{
// zero-value for a type
pkt
:=
reflect
.
New
(
typ
)
.
Interface
()
.
(
Pkt
)
l
:=
pkt
.
NEOPkt
EncodedLen
()
msg
:=
reflect
.
New
(
typ
)
.
Interface
()
.
(
Msg
)
l
:=
msg
.
NEOMsg
EncodedLen
()
zerol
:=
make
([]
byte
,
l
)
// decoding will turn nil slice & map into empty allocated ones.
// we need it so that reflect.DeepEqual works for
pkt
encode/decode comparison
n
,
err
:=
pkt
.
NEOPkt
Decode
(
zerol
)
// we need it so that reflect.DeepEqual works for
msg
encode/decode comparison
n
,
err
:=
msg
.
NEOMsg
Decode
(
zerol
)
if
!
(
n
==
l
&&
err
==
nil
)
{
t
.
Errorf
(
"%v: zero-decode unexpected: %v, %v ; want %v, nil"
,
typ
,
n
,
err
,
l
)
}
test
PktMarshal
(
t
,
pkt
,
string
(
zerol
))
test
MsgMarshal
(
t
,
msg
,
string
(
zerol
))
}
}
This diff is collapsed.
Click to expand it.
go/neo/protogen.go
View file @
c2a1b63a
...
...
@@ -20,15 +20,15 @@
/*
NEO. Protocol module. Code generator
This program generates marshalling code for
packet
types defined in proto.go .
For every type 4 methods are generated in accordance with neo.
Pkt
interface:
This program generates marshalling code for
message
types defined in proto.go .
For every type 4 methods are generated in accordance with neo.
Msg
interface:
NEO
Pkt
MsgCode() uint16
NEO
Pkt
EncodedLen() int
NEO
Pkt
Encode(buf []byte)
NEO
Pkt
Decode(data []byte) (nread int, err error)
NEOMsgCode() uint16
NEO
Msg
EncodedLen() int
NEO
Msg
Encode(buf []byte)
NEO
Msg
Decode(data []byte) (nread int, err error)
List of
packet
types is obtained via searching through proto.go AST - looking
List of
message
types is obtained via searching through proto.go AST - looking
for appropriate struct declarations there.
Code generation for a type is organized via recursively walking through type's
...
...
@@ -169,11 +169,11 @@ import (
"../zodb"
)`
)
pktTypeRegistry
:=
map
[
int
]
string
{}
// pkt
Code -> typename
msgTypeRegistry
:=
map
[
int
]
string
{}
// msg
Code -> typename
// go over
packet
types declaration and generate marshal code for them
buf
.
emit
(
"//
packet
s marshalling
\n
"
)
pkt
Code
:=
0
// go over
message
types declaration and generate marshal code for them
buf
.
emit
(
"//
message
s marshalling
\n
"
)
msg
Code
:=
0
for
_
,
decl
:=
range
f
.
Decls
{
// we look for types (which can be only under GenDecl)
gendecl
,
ok
:=
decl
.
(
*
ast
.
GenDecl
)
...
...
@@ -195,35 +195,35 @@ import (
continue
case
*
ast
.
StructType
:
fmt
.
Fprintf
(
&
buf
,
"// %d. %s
\n\n
"
,
pkt
Code
,
typename
)
fmt
.
Fprintf
(
&
buf
,
"// %d. %s
\n\n
"
,
msg
Code
,
typename
)
buf
.
emit
(
"func (_ *%s) NEO
Pkt
MsgCode() uint16 {"
,
typename
)
buf
.
emit
(
"return %d"
,
pkt
Code
)
buf
.
emit
(
"func (_ *%s) NEOMsgCode() uint16 {"
,
typename
)
buf
.
emit
(
"return %d"
,
msg
Code
)
buf
.
emit
(
"}
\n
"
)
buf
.
WriteString
(
generateCodecCode
(
typespec
,
&
sizer
{}))
buf
.
WriteString
(
generateCodecCode
(
typespec
,
&
encoder
{}))
buf
.
WriteString
(
generateCodecCode
(
typespec
,
&
decoder
{}))
pktTypeRegistry
[
pkt
Code
]
=
typename
pkt
Code
++
msgTypeRegistry
[
msg
Code
]
=
typename
msg
Code
++
}
}
}
// now generate
packet
types registry
buf
.
emit
(
"
\n
// registry of
packet
types"
)
buf
.
emit
(
"var
pktTypeRegistry = map[uint16]reflect.Type {"
)
// XXX key -> Pkt
Code ?
// now generate
message
types registry
buf
.
emit
(
"
\n
// registry of
message
types"
)
buf
.
emit
(
"var
msgTypeRegistry = map[uint16]reflect.Type {"
)
// XXX key -> Msg
Code ?
// ordered by
pkt
Code
pkt
CodeV
:=
[]
int
{}
for
pktCode
:=
range
pkt
TypeRegistry
{
pktCodeV
=
append
(
pktCodeV
,
pkt
Code
)
// ordered by
msg
Code
msg
CodeV
:=
[]
int
{}
for
msgCode
:=
range
msg
TypeRegistry
{
msgCodeV
=
append
(
msgCodeV
,
msg
Code
)
}
sort
.
Ints
(
pkt
CodeV
)
sort
.
Ints
(
msg
CodeV
)
for
_
,
pktCode
:=
range
pkt
CodeV
{
buf
.
emit
(
"%v: reflect.TypeOf(%v{}),"
,
pktCode
,
pktTypeRegistry
[
pkt
Code
])
for
_
,
msgCode
:=
range
msg
CodeV
{
buf
.
emit
(
"%v: reflect.TypeOf(%v{}),"
,
msgCode
,
msgTypeRegistry
[
msg
Code
])
}
buf
.
emit
(
"}"
)
...
...
@@ -456,21 +456,21 @@ func (o *OverflowCheck) AddExpr(format string, a ...interface{}) {
}
// sizer generates code to compute encoded size of a
packet
// sizer generates code to compute encoded size of a
message
//
// when type is recursively walked, for every case symbolic size is added appropriately.
// in case when it was needed to generate loops, runtime accumulator variable is additionally used.
// result is: symbolic size + (optionally) runtime accumulator.
type
sizer
struct
{
commonCodeGen
size
SymSize
// currently accumulated
packet
size
size
SymSize
// currently accumulated size
}
// encoder generates code to encode a
packet
// encoder generates code to encode a
message
//
// when type is recursively walked, for every case code to update `data[n:]` is generated.
// no overflow checks are generated as by neo.
Pkt
interface provided data
// buffer should have at least payloadLen length returned by NEO
Pkt
EncodedInfo()
// no overflow checks are generated as by neo.
Msg
interface provided data
// buffer should have at least payloadLen length returned by NEO
Msg
EncodedInfo()
// (the size computed by sizer).
//
// the code emitted looks like:
...
...
@@ -479,14 +479,14 @@ type sizer struct {
// encode<typ2>(data[n2:], path2)
// ...
//
// TODO encode have to care in NEO
Pkt
Encode to emit preambule such that bound
// TODO encode have to care in NEO
Msg
Encode to emit preambule such that bound
// checking is performed only once (currenty compiler emits many of them)
type
encoder
struct
{
commonCodeGen
n
int
// current write position in data
}
// decoder generates code to decode a
packet
// decoder generates code to decode a
message
//
// when type is recursively walked, for every case code to decode next item from
// `data[n:]` is generated.
...
...
@@ -527,7 +527,7 @@ var _ CodeGenerator = (*decoder)(nil)
func
(
s
*
sizer
)
generatedCode
()
string
{
code
:=
Buffer
{}
// prologue
code
.
emit
(
"func (%s *%s) NEO
Pkt
EncodedLen() int {"
,
s
.
recvName
,
s
.
typeName
)
code
.
emit
(
"func (%s *%s) NEO
Msg
EncodedLen() int {"
,
s
.
recvName
,
s
.
typeName
)
if
s
.
varUsed
[
"size"
]
{
code
.
emit
(
"var %s int"
,
s
.
var_
(
"size"
))
}
...
...
@@ -548,7 +548,7 @@ func (s *sizer) generatedCode() string {
func
(
e
*
encoder
)
generatedCode
()
string
{
code
:=
Buffer
{}
// prologue
code
.
emit
(
"func (%s *%s) NEO
Pkt
Encode(data []byte) {"
,
e
.
recvName
,
e
.
typeName
)
code
.
emit
(
"func (%s *%s) NEO
Msg
Encode(data []byte) {"
,
e
.
recvName
,
e
.
typeName
)
code
.
Write
(
e
.
buf
.
Bytes
())
...
...
@@ -655,7 +655,7 @@ func (d *decoder) generatedCode() string {
code
:=
Buffer
{}
// prologue
code
.
emit
(
"func (%s *%s) NEO
Pkt
Decode(data []byte) (int, error) {"
,
d
.
recvName
,
d
.
typeName
)
code
.
emit
(
"func (%s *%s) NEO
Msg
Decode(data []byte) (int, error) {"
,
d
.
recvName
,
d
.
typeName
)
if
d
.
varUsed
[
"nread"
]
{
code
.
emit
(
"var %v uint32"
,
d
.
var_
(
"nread"
))
}
...
...
This diff is collapsed.
Click to expand it.
go/neo/server/master.go
View file @
c2a1b63a
...
...
@@ -64,7 +64,7 @@ type Master struct {
type
nodeCome
struct
{
link
*
neo
.
NodeLink
idReq
neo
.
RequestIdentification
// we received this identification request
idResp
chan
neo
.
Pkt
// what we reply (AcceptIdentification | Error)
idResp
chan
neo
.
Msg
// what we reply (AcceptIdentification | Error)
}
// node disconnects
...
...
@@ -701,7 +701,7 @@ func (m *Master) ServeLink(ctx context.Context, link *neo.NodeLink) {
}
// convey identification request to master
idRespCh
:=
make
(
chan
neo
.
Pkt
)
idRespCh
:=
make
(
chan
neo
.
Msg
)
m
.
nodeCome
<-
nodeCome
{
link
,
idReq
,
idRespCh
}
idResp
:=
<-
idRespCh
...
...
@@ -757,7 +757,7 @@ func (m *Master) ServeLink(ctx context.Context, link *neo.NodeLink) {
m
.
stateMu
.
Unlock
()
go
func
()
{
var
pkt
neo
.
Pkt
var
msg
neo
.
Msg
for
{
select
{
...
...
@@ -767,7 +767,7 @@ func (m *Master) ServeLink(ctx context.Context, link *neo.NodeLink) {
return
case
nodeUpdateV
:=
<-
nodeCh
:
pkt
=
&
neo
.
NotifyNodeInformation
{
msg
=
&
neo
.
NotifyNodeInformation
{
IdTimestamp
:
math
.
NaN
(),
// XXX
NodeList
:
nodeUpdateV
,
}
...
...
@@ -776,7 +776,7 @@ func (m *Master) ServeLink(ctx context.Context, link *neo.NodeLink) {
// changed = true
}
err
=
neo
.
EncodeAndSend
(
connNotify
,
pkt
)
err
=
neo
.
EncodeAndSend
(
connNotify
,
msg
)
if
err
!=
nil
{
// XXX err
}
...
...
This diff is collapsed.
Click to expand it.
go/neo/server/storage.go
View file @
c2a1b63a
...
...
@@ -277,7 +277,7 @@ func (stor *Storage) ServeClient(ctx context.Context, conn *neo.Conn) {
xid
.
TidBefore
=
true
}
var
reply
neo
.
Pkt
var
reply
neo
.
Msg
data
,
tid
,
err
:=
stor
.
zstor
.
Load
(
xid
)
if
err
!=
nil
{
// TODO translate err to NEO protocol error codes
...
...
@@ -299,7 +299,7 @@ func (stor *Storage) ServeClient(ctx context.Context, conn *neo.Conn) {
neo
.
EncodeAndSend
(
conn
,
reply
)
// XXX err
case
*
neo
.
LastTransaction
:
var
reply
neo
.
Pkt
var
reply
neo
.
Msg
lastTid
,
err
:=
stor
.
zstor
.
LastTid
()
if
err
!=
nil
{
...
...
This diff is collapsed.
Click to expand it.
go/neo/x_connection.go
View file @
c2a1b63a
...
...
@@ -10,9 +10,9 @@ import (
"lab.nexedi.com/kirr/go123/xerr"
)
// Recv
AndDecode receives packet from conn and decodes
it
func
RecvAndDecode
(
conn
*
Conn
)
(
Pkt
,
error
)
{
pkt
,
err
:=
conn
.
Recv
()
// Recv
receives packet and decodes message from
it
func
RecvAndDecode
(
conn
*
Conn
)
(
Msg
,
error
)
{
pkt
,
err
:=
conn
.
recvPkt
()
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -20,7 +20,7 @@ func RecvAndDecode(conn *Conn) (Pkt, error) {
// decode packet
pkth
:=
pkt
.
Header
()
msgCode
:=
ntoh16
(
pkth
.
MsgCode
)
msgType
:=
pkt
TypeRegistry
[
msgCode
]
msgType
:=
msg
TypeRegistry
[
msgCode
]
if
msgType
==
nil
{
err
=
fmt
.
Errorf
(
"invalid msgCode (%d)"
,
msgCode
)
// XXX -> ProtoError ?
...
...
@@ -28,47 +28,47 @@ func RecvAndDecode(conn *Conn) (Pkt, error) {
}
// TODO use free-list for decoded packets + when possible decode in-place
pktObj
:=
reflect
.
New
(
msgType
)
.
Interface
()
.
(
Pkt
)
_
,
err
=
pktObj
.
NEOPkt
Decode
(
pkt
.
Payload
())
msg
:=
reflect
.
New
(
msgType
)
.
Interface
()
.
(
Msg
)
_
,
err
=
msg
.
NEOMsg
Decode
(
pkt
.
Payload
())
if
err
!=
nil
{
// XXX -> ProtoError ?
return
nil
,
&
ConnError
{
Conn
:
conn
,
Op
:
"decode"
,
Err
:
err
}
}
return
pktObj
,
nil
return
msg
,
nil
}
// EncodeAndSend encodes
pkt and sends it to conn
func
EncodeAndSend
(
conn
*
Conn
,
pkt
Pkt
)
error
{
l
:=
pkt
.
NEOPkt
EncodedLen
()
// EncodeAndSend encodes
message into packet and sends it
func
EncodeAndSend
(
conn
*
Conn
,
msg
Msg
)
error
{
l
:=
msg
.
NEOMsg
EncodedLen
()
buf
:=
PktBuf
{
make
([]
byte
,
PktHeadLen
+
l
)}
// XXX -> freelist
h
:=
buf
.
Header
()
// h.ConnId will be set by conn.Send
h
.
MsgCode
=
hton16
(
pkt
.
NEOPkt
MsgCode
())
h
.
MsgCode
=
hton16
(
msg
.
NEO
MsgCode
())
h
.
MsgLen
=
hton32
(
uint32
(
l
))
// XXX casting: think again
pkt
.
NEOPkt
Encode
(
buf
.
Payload
())
msg
.
NEOMsg
Encode
(
buf
.
Payload
())
return
conn
.
Send
(
&
buf
)
// XXX why pointer?
return
conn
.
sendPkt
(
&
buf
)
// XXX why pointer?
}
// Ask does simple request/response protocol exchange
// It expects the answer to be exactly of resp type and errors otherwise
func
Ask
(
conn
*
Conn
,
req
Pkt
,
resp
Pkt
)
error
{
func
Ask
(
conn
*
Conn
,
req
Msg
,
resp
Msg
)
error
{
err
:=
EncodeAndSend
(
conn
,
req
)
if
err
!=
nil
{
return
err
}
err
=
Expect
(
conn
,
resp
)
err
=
Expect
(
conn
,
resp
)
// XXX +Error
return
err
}
// ProtoError is returned when there wa
a
a protocol error, like receiving
// ProtoError is returned when there wa
s
a protocol error, like receiving
// unexpected packet or packet with wrong header
//
XXX -> ConnError{Op: "decode"} ?
//
FIXME -> ConnError{Op: "decode"}
type
ProtoError
struct
{
Conn
*
Conn
Err
error
...
...
@@ -80,8 +80,8 @@ func (e *ProtoError) Error() string {
// Expect receives 1 packet and expects it to be exactly of msg type
// XXX naming (-> Recv1 ?)
func
Expect
(
conn
*
Conn
,
msg
Pkt
)
(
err
error
)
{
pkt
,
err
:=
conn
.
Recv
()
func
Expect
(
conn
*
Conn
,
msg
Msg
)
(
err
error
)
{
pkt
,
err
:=
conn
.
recvPkt
()
if
err
!=
nil
{
return
err
}
...
...
@@ -92,11 +92,11 @@ func Expect(conn *Conn, msg Pkt) (err error) {
pkth
:=
pkt
.
Header
()
msgCode
:=
ntoh16
(
pkth
.
MsgCode
)
if
msgCode
!=
msg
.
NEO
Pkt
MsgCode
()
{
if
msgCode
!=
msg
.
NEOMsgCode
()
{
// unexpected Error response
if
msgCode
==
(
&
Error
{})
.
NEO
Pkt
MsgCode
()
{
if
msgCode
==
(
&
Error
{})
.
NEOMsgCode
()
{
errResp
:=
Error
{}
_
,
err
=
errResp
.
NEO
Pkt
Decode
(
pkt
.
Payload
())
_
,
err
=
errResp
.
NEO
Msg
Decode
(
pkt
.
Payload
())
if
err
!=
nil
{
return
&
ProtoError
{
conn
,
err
}
}
...
...
@@ -108,7 +108,7 @@ func Expect(conn *Conn, msg Pkt) (err error) {
return
ErrDecode
(
&
errResp
)
// XXX err ctx vs ^^^ errcontextf ?
}
msgType
:=
pkt
TypeRegistry
[
msgCode
]
msgType
:=
msg
TypeRegistry
[
msgCode
]
if
msgType
==
nil
{
return
&
ProtoError
{
conn
,
fmt
.
Errorf
(
"invalid msgCode (%d)"
,
msgCode
)}
}
...
...
@@ -116,7 +116,7 @@ func Expect(conn *Conn, msg Pkt) (err error) {
return
&
ProtoError
{
conn
,
fmt
.
Errorf
(
"unexpected packet: %v"
,
msgType
)}
}
_
,
err
=
msg
.
NEO
Pkt
Decode
(
pkt
.
Payload
())
_
,
err
=
msg
.
NEO
Msg
Decode
(
pkt
.
Payload
())
if
err
!=
nil
{
return
&
ProtoError
{
conn
,
err
}
}
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment