@cryptotaxi247 / kubo / commits / 6b0440c05

versionExchange: first stab in the dark

Henry committed Oct 16, 2014 at 11:35 UTC 6b0440c0502be4f44a1f33433e1e0e5e842ef294
5 files changed +160
net/swarm/conn.go
+56
@@ -7,7 +7,9 @@ import (
7 spipe "github.com/jbenet/go-ipfs/crypto/spipe"
8 conn "github.com/jbenet/go-ipfs/net/conn"
9 msg "github.com/jbenet/go-ipfs/net/message"
10 + version "github.com/jbenet/go-ipfs/net/version"
11
12 + proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
13 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
14 manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
15 )
@@ -109,6 +111,10 @@ func (s *Swarm) connSetup(c *conn.Conn) error {
111 // add address of connection to Peer. Maybe it should happen in connSecure.
112 c.Peer.AddAddress(c.Addr)
113
114 + if err := s.connVersionExchange(c); err != nil {
115 + return fmt.Errorf("Conn version exchange error: %v", err)
116 + }
117 +
118 // add to conns
119 s.connsLock.Lock()
120 if _, ok := s.conns[c.Peer.Key()]; ok {
@@ -152,6 +158,56 @@ func (s *Swarm) connSecure(c *conn.Conn) error {
158 return nil
159 }
160
161 +// connVersionExchange exchanges local and remote versions and compares them
162 +// closes remote and returns an error in case of major difference
163 +func (s *Swarm) connVersionExchange(remote *conn.Conn) error {
164 + var remoteVersion, myVersion *version.SemVer
165 + myVersion = version.Current()
166 +
167 + myVersionMsg, err := msg.FromObject(s.local, myVersion)
168 + if err != nil {
169 + return fmt.Errorf("connVersionExchange: could not prepare local version: %q", err)
170 + }
171 +
172 + var gotTheirs, sendMine bool
173 + for {
174 + if gotTheirs && sendMine {
175 + break
176 + }
177 +
178 + select {
179 + case <-s.ctx.Done():
180 + // close Conn.
181 + remote.Close()
182 + return nil // BUG(cryptix): should this be an error?
183 +
184 + case <-remote.Closed:
185 + return errors.New("remote closed connection during version exchange")
186 +
187 + case remote.Secure.Out <- myVersionMsg.Data():
188 + log.Debug("[peer: %s] Send my version(%s) to %s", s.local, myVersion, remote.Peer)
189 + sendMine = true
190 +
191 + case data, ok := <-remote.Secure.In:
192 + if !ok {
193 + return fmt.Errorf("Error retrieving from conn: %v", remote.Peer)
194 + }
195 +
196 + log.Debug("[peer: %s] Received message [from = %s]", s.local, remote.Peer)
197 +
198 + remoteVersion = new(version.SemVer)
199 + err = proto.Unmarshal(data, remoteVersion)
200 + if err != nil {
201 + s.Close()
202 + return fmt.Errorf("connSetup: could not decode remote version: %q", err)
203 + }
204 + gotTheirs = true
205 + }
206 + }
207 +
208 + return errors.New("not yet")
209 +}
210 +
211 // Handles the unwrapping + sending of messages to the right connection.
212 func (s *Swarm) fanOut() {
213 for {
net/version/Makefile new
+8
@@ -0,0 +1,8 @@
1 +
2 +all: semver.pb.go
3 +
4 +semver.pb.go: semver.proto
5 + protoc --gogo_out=. --proto_path=../../../../../:/usr/include/google:. $<
6 +
7 +clean:
8 + rm semver.pb.go
net/version/semver.pb.go new
+56
@@ -0,0 +1,56 @@
1 +// Code generated by protoc-gen-gogo.
2 +// source: semver.proto
3 +// DO NOT EDIT!
4 +
5 +/*
6 +Package version is a generated protocol buffer package.
7 +
8 +It is generated from these files:
9 + semver.proto
10 +
11 +It has these top-level messages:
12 + SemVer
13 +*/
14 +package version
15 +
16 +import proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/gogoprotobuf/proto"
17 +import math "math"
18 +
19 +// Reference imports to suppress errors if they are not otherwise used.
20 +var _ = proto.Marshal
21 +var _ = math.Inf
22 +
23 +type SemVer struct {
24 + Major *int64 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
25 + Minor *int64 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
26 + Patch *int64 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
27 + XXX_unrecognized []byte `json:"-"`
28 +}
29 +
30 +func (m *SemVer) Reset() { *m = SemVer{} }
31 +func (m *SemVer) String() string { return proto.CompactTextString(m) }
32 +func (*SemVer) ProtoMessage() {}
33 +
34 +func (m *SemVer) GetMajor() int64 {
35 + if m != nil && m.Major != nil {
36 + return *m.Major
37 + }
38 + return 0
39 +}
40 +
41 +func (m *SemVer) GetMinor() int64 {
42 + if m != nil && m.Minor != nil {
43 + return *m.Minor
44 + }
45 + return 0
46 +}
47 +
48 +func (m *SemVer) GetPatch() int64 {
49 + if m != nil && m.Patch != nil {
50 + return *m.Patch
51 + }
52 + return 0
53 +}
54 +
55 +func init() {
56 +}
net/version/semver.proto new
+8
@@ -0,0 +1,8 @@
1 +package version;
2 +
3 +message SemVer {
4 + optional int64 major = 1;
5 + optional int64 minor = 2;
6 + optional int64 patch = 3;
7 + // BUG(cryptix): do we need PreRelease and Metadata too?
8 +}
net/version/version.go new
+32
@@ -0,0 +1,32 @@
1 +package version
2 +
3 +import semver "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/coreos/go-semver/semver"
4 +
5 +var currentVersion = semver.Version{
6 + Major: 0,
7 + Minor: 1,
8 + Patch: 0,
9 +}
10 +
11 +// Current returns the current protocol version as a protobuf message
12 +func Current() *SemVer {
13 + return toPBSemVer(currentVersion)
14 +}
15 +
16 +// toPBSemVar converts a coreos/semver to our protobuf SemVer
17 +func toPBSemVer(in semver.Version) (out *SemVer) {
18 + return &SemVer{
19 + Major: &in.Major,
20 + Minor: &in.Minor,
21 + Patch: &in.Patch,
22 + }
23 +}
24 +
25 +// toPBSemVar converts our protobuf SemVer to a coreos/semver
26 +func fromPBSemVer(in SemVer) *semver.Version {
27 + return &semver.Version{
28 + Major: *in.Major,
29 + Minor: *in.Minor,
30 + Patch: *in.Patch,
31 + }
32 +}