diff --git a/build b/build index 66f94403..6b93ca77 100755 --- a/build +++ b/build @@ -45,7 +45,7 @@ elif [ $ANDROID ]; then github.com/yggdrasil-network/yggdrasil-extras/src/mobile \ github.com/yggdrasil-network/yggdrasil-extras/src/dummy else - for CMD in yggdrasil yggdrasilctl ; do + for CMD in yggdrasil yggdrasilctl yggdrasilsim; do echo "Building: $CMD" go build $ARGS -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" ./cmd/$CMD diff --git a/cmd/yggdrasilsim/main.go b/cmd/yggdrasilsim/main.go new file mode 100644 index 00000000..40fd9ce4 --- /dev/null +++ b/cmd/yggdrasilsim/main.go @@ -0,0 +1,15 @@ +package main + +import ( +//"github.com/yggdrasil-network/yggdrasil-go/src/address" +//"github.com/yggdrasil-network/yggdrasil-go/src/config" +//"github.com/yggdrasil-network/yggdrasil-go/src/crypto" +//"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" +) + +func main() { + store := makeStoreSquareGrid(4) + var block chan struct{} + <-block + panic(store) +} diff --git a/cmd/yggdrasilsim/node.go b/cmd/yggdrasilsim/node.go new file mode 100644 index 00000000..e23b5109 --- /dev/null +++ b/cmd/yggdrasilsim/node.go @@ -0,0 +1,23 @@ +package main + +import ( + "io/ioutil" + + "github.com/gologme/log" + + //"github.com/yggdrasil-network/yggdrasil-go/src/address" + "github.com/yggdrasil-network/yggdrasil-go/src/config" + //"github.com/yggdrasil-network/yggdrasil-go/src/crypto" + "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" +) + +type simNode struct { + core yggdrasil.Core + id int +} + +func newNode(id int) *simNode { + n := simNode{id: id} + n.core.Start(config.GenerateConfig(), log.New(ioutil.Discard, "", 0)) + return &n +} diff --git a/cmd/yggdrasilsim/store.go b/cmd/yggdrasilsim/store.go new file mode 100644 index 00000000..6fce81a4 --- /dev/null +++ b/cmd/yggdrasilsim/store.go @@ -0,0 +1,41 @@ +package main + +type nodeStore map[int]*simNode + +func makeStoreSingle() nodeStore { + s := make(nodeStore) + s[0] = newNode(0) + return s +} + +func linkNodes(a *simNode, b *simNode) { + la := a.core.NewSimlink() + lb := b.core.NewSimlink() + la.SetDestination(lb) + lb.SetDestination(la) + la.Start() + lb.Start() +} + +func makeStoreSquareGrid(sideLength int) nodeStore { + store := make(nodeStore) + nNodes := sideLength * sideLength + idxs := make([]int, 0, nNodes) + // TODO shuffle nodeIDs + for idx := 1; idx <= nNodes; idx++ { + idxs = append(idxs, idx) + } + for _, idx := range idxs { + n := newNode(idx) + store[idx] = n + } + for idx := 0; idx < nNodes; idx++ { + if (idx % sideLength) != 0 { + linkNodes(store[idxs[idx]], store[idxs[idx-1]]) + } + if idx >= sideLength { + linkNodes(store[idxs[idx]], store[idxs[idx-sideLength]]) + } + } + return store +} diff --git a/src/yggdrasil/simlink.go b/src/yggdrasil/simlink.go new file mode 100644 index 00000000..33332645 --- /dev/null +++ b/src/yggdrasil/simlink.go @@ -0,0 +1,88 @@ +package yggdrasil + +import ( + "errors" + "github.com/Arceliar/phony" + "github.com/yggdrasil-network/yggdrasil-go/src/util" +) + +type Simlink struct { + phony.Inbox + rch chan []byte + dest *Simlink + link *linkInterface + started bool +} + +func (s *Simlink) readMsg() ([]byte, error) { + bs := <-s.rch + if bs != nil { + return bs, nil + } else { + return nil, errors.New("read from closed Simlink") + } +} + +func (s *Simlink) _recvMetaBytes() ([]byte, error) { + return s.readMsg() +} + +func (s *Simlink) _sendMetaBytes(bs []byte) error { + _, err := s.writeMsgs([][]byte{bs}) + return err +} + +func (s *Simlink) close() error { + close(s.rch) + return nil +} + +func (s *Simlink) writeMsgs(msgs [][]byte) (int, error) { + if s.dest == nil { + return 0, errors.New("write to unpaired Simlink") + } + var size int + for _, msg := range msgs { + size += len(msg) + bs := append(util.GetBytes(), msg...) + phony.Block(s, func() { + s.dest.Act(s, func() { + defer func() { recover() }() + s.dest.rch <- bs + }) + }) + } + return size, nil +} + +func (c *Core) NewSimlink() *Simlink { + s := &Simlink{rch: make(chan []byte, 1)} + n := "Simlink" + s.link, _ = c.link.create(s, n, n, n, n, false, true) + return s +} + +func (s *Simlink) SetDestination(dest *Simlink) error { + var err error + phony.Block(s, func() { + if s.dest != nil { + err = errors.New("destination already set") + } else { + s.dest = dest + } + }) + return err +} + +func (s *Simlink) Start() error { + var err error + phony.Block(s, func() { + if s.started { + err = errors.New("already started") + } else { + s.started = true + go s.link.handler() + } + }) + return err +}