Commit bc16d2ee authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 878bf8ca
...@@ -29,7 +29,11 @@ package neo ...@@ -29,7 +29,11 @@ package neo
// several messages and does not itself denote a separate message, its // several messages and does not itself denote a separate message, its
// definition is prefixed with `//neo:proto typeonly` comment. // definition is prefixed with `//neo:proto typeonly` comment.
// //
// XXX neo:proto answerto x? (btw just needs "answer" flag) // The order of message definitions is significant - messages are assigned
// message IDs in the same order they are defined.
//
// For compatibility with neo/py is a message should have its ID assigned with
// "answer" bit set its definition is prefixed with `//neo:proto answer` comment.
// TODO regroup messages definitions to stay more close to 1 communication topic // TODO regroup messages definitions to stay more close to 1 communication topic
// TODO document protocol itself better (who sends who what with which semantic) // TODO document protocol itself better (who sends who what with which semantic)
...@@ -60,7 +64,7 @@ const ( ...@@ -60,7 +64,7 @@ const (
MAX_PACKET_SIZE = 0x4000000 MAX_PACKET_SIZE = 0x4000000
RESPONSE_MASK = 0x8000 answerBit = 0x8000
) )
type ErrorCode uint32 type ErrorCode uint32
...@@ -192,7 +196,7 @@ type Msg interface { ...@@ -192,7 +196,7 @@ type Msg interface {
neoMsgDecode(data []byte) (nread int, err error) neoMsgDecode(data []byte) (nread int, err error)
} }
// FIXME not pkt //neo:proto typeonly
type Address struct { type Address struct {
Host string Host string
Port uint16 Port uint16
...@@ -303,7 +307,7 @@ type RequestIdentification struct { ...@@ -303,7 +307,7 @@ type RequestIdentification struct {
IdTimestamp float64 IdTimestamp float64
} }
// XXX -> ReplyIdentification? RequestIdentification.Answer somehow ? //neo:proto answer
type AcceptIdentification struct { type AcceptIdentification struct {
NodeType NodeType // XXX name NodeType NodeType // XXX name
MyUUID NodeUUID MyUUID NodeUUID
......
...@@ -168,6 +168,7 @@ func loadPkg(pkgPath string, sources ...string) *types.Package { ...@@ -168,6 +168,7 @@ func loadPkg(pkgPath string, sources ...string) *types.Package {
// `//neo:proto ...` annotations // `//neo:proto ...` annotations
type Annotation struct { type Annotation struct {
typeonly bool typeonly bool
answer bool
} }
// parse checks doc for specific comment annotations and, if present, loads them. // parse checks doc for specific comment annotations and, if present, loads them.
...@@ -188,16 +189,45 @@ func (a *Annotation) parse(doc *ast.CommentGroup) { ...@@ -188,16 +189,45 @@ func (a *Annotation) parse(doc *ast.CommentGroup) {
switch arg { switch arg {
case "typeonly": case "typeonly":
if a.typeonly { if a.typeonly {
log.Fatalf("%v: duplicate typeonly", cpos) log.Fatalf("%v: duplicate `typeonly`", cpos)
} }
a.typeonly = true a.typeonly = true
case "answer":
if a.answer {
log.Fatalf("%v: duplicate `answer`", cpos)
}
a.answer = true
default: default:
log.Fatalf("%v: unknown neo:proto directive %q", cpos, arg) log.Fatalf("%v: unknown neo:proto directive %q", cpos, arg)
} }
} }
} }
// MsgCode represents message code in symbolic form: `serial (| answerBit)?`
type MsgCode struct {
msgSerial int
answer bool
}
func (c MsgCode) String() string {
s := fmt.Sprintf("%d", c.msgSerial)
if c.answer {
s += " | answerBit"
}
return s
}
// sort MsgCode by serial
type BySerial []MsgCode
func (v BySerial) Less(i, j int) bool { return v[i].msgSerial < v[j].msgSerial }
func (v BySerial) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v BySerial) Len() int { return len(v) }
// ----------------------------------------
func main() { func main() {
var err error var err error
...@@ -223,11 +253,11 @@ import ( ...@@ -223,11 +253,11 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
)`) )`)
msgTypeRegistry := map[int]string{} // msgCode -> typename msgTypeRegistry := map[MsgCode]string{} // msgCode -> typename
// go over message types declaration and generate marshal code for them // go over message types declaration and generate marshal code for them
buf.emit("// messages marshalling\n") buf.emit("// messages marshalling\n")
msgCode := 0 msgSerial := 0
for _, decl := range f.Decls { for _, decl := range f.Decls {
// we look for types (which can be only under GenDecl) // we look for types (which can be only under GenDecl)
gendecl, ok := decl.(*ast.GenDecl) gendecl, ok := decl.(*ast.GenDecl)
...@@ -262,10 +292,17 @@ import ( ...@@ -262,10 +292,17 @@ import (
continue continue
} }
fmt.Fprintf(&buf, "// %d. %s\n\n", msgCode, typename) // generate code for this type to implement neo.Msg
msgCode := MsgCode{msgSerial, specAnnotation.answer}
fmt.Fprintf(&buf, "// %d. %s", msgSerial, typename)
if specAnnotation.answer {
fmt.Fprintf(&buf, " (answer)")
}
fmt.Fprintf(&buf, "\n\n")
buf.emit("func (*%s) neoMsgCode() uint16 {", typename) buf.emit("func (*%s) neoMsgCode() uint16 {", typename)
buf.emit("return %d", msgCode) buf.emit("return %s", msgCode)
buf.emit("}\n") buf.emit("}\n")
buf.WriteString(generateCodecCode(typespec, &sizer{})) buf.WriteString(generateCodecCode(typespec, &sizer{}))
...@@ -273,20 +310,20 @@ import ( ...@@ -273,20 +310,20 @@ import (
buf.WriteString(generateCodecCode(typespec, &decoder{})) buf.WriteString(generateCodecCode(typespec, &decoder{}))
msgTypeRegistry[msgCode] = typename msgTypeRegistry[msgCode] = typename
msgCode++ msgSerial++
} }
} }
// now generate message types registry // now generate message types registry
buf.emit("\n// registry of message types") buf.emit("\n// registry of message types")
buf.emit("var msgTypeRegistry = map[uint16]reflect.Type {") // XXX key -> MsgCode ? buf.emit("var msgTypeRegistry = map[uint16]reflect.Type {")
// ordered by msgCode // ordered by msgCode
msgCodeV := []int{} msgCodeV := []MsgCode{}
for msgCode := range msgTypeRegistry { for msgCode := range msgTypeRegistry {
msgCodeV = append(msgCodeV, msgCode) msgCodeV = append(msgCodeV, msgCode)
} }
sort.Ints(msgCodeV) sort.Sort(BySerial(msgCodeV))
for _, msgCode := range msgCodeV { for _, msgCode := range msgCodeV {
buf.emit("%v: reflect.TypeOf(%v{}),", msgCode, msgTypeRegistry[msgCode]) buf.emit("%v: reflect.TypeOf(%v{}),", msgCode, msgTypeRegistry[msgCode])
...@@ -545,8 +582,8 @@ type sizer struct { ...@@ -545,8 +582,8 @@ type sizer struct {
// encode<typ2>(data[n2:], path2) // encode<typ2>(data[n2:], path2)
// ... // ...
// //
// TODO encode have to care in neoMsgEncode to emit preambule such that bound // TODO encode have to care in neoMsgEncode to emit preamble such that bound
// checking is performed only once (currenty compiler emits many of them) // checking is performed only once (currently compiler emits many of them)
type encoder struct { type encoder struct {
commonCodeGen commonCodeGen
n int // current write position in data n int // current write position in data
...@@ -635,7 +672,7 @@ func (d *decoder) resetPos() { ...@@ -635,7 +672,7 @@ func (d *decoder) resetPos() {
// mark current place for insertion of overflow check code // mark current place for insertion of overflow check code
// //
// The check will be acutally inserted later. // The check will be actually inserted later.
// //
// later: because first we go forward in decode path scanning ahead as far as // later: because first we go forward in decode path scanning ahead as far as
// we can - until first seeing variable-size encoded something, and then - // we can - until first seeing variable-size encoded something, and then -
......
...@@ -123,10 +123,10 @@ overflow: ...@@ -123,10 +123,10 @@ overflow:
return 0, ErrDecodeOverflow return 0, ErrDecodeOverflow
} }
// 2. AcceptIdentification // 2. AcceptIdentification (answer)
func (*AcceptIdentification) neoMsgCode() uint16 { func (*AcceptIdentification) neoMsgCode() uint16 {
return 2 return 2 | answerBit
} }
func (p *AcceptIdentification) neoMsgEncodedLen() int { func (p *AcceptIdentification) neoMsgEncodedLen() int {
...@@ -3417,7 +3417,7 @@ func (p *NotifyReady) neoMsgDecode(data []byte) (int, error) { ...@@ -3417,7 +3417,7 @@ func (p *NotifyReady) neoMsgDecode(data []byte) (int, error) {
var msgTypeRegistry = map[uint16]reflect.Type{ var msgTypeRegistry = map[uint16]reflect.Type{
0: reflect.TypeOf(Error{}), 0: reflect.TypeOf(Error{}),
1: reflect.TypeOf(RequestIdentification{}), 1: reflect.TypeOf(RequestIdentification{}),
2: reflect.TypeOf(AcceptIdentification{}), 2 | answerBit: reflect.TypeOf(AcceptIdentification{}),
3: reflect.TypeOf(Ping{}), 3: reflect.TypeOf(Ping{}),
4: reflect.TypeOf(CloseClient{}), 4: reflect.TypeOf(CloseClient{}),
5: reflect.TypeOf(PrimaryMaster{}), 5: reflect.TypeOf(PrimaryMaster{}),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment