//WritePeersToDAG writes peer list and returns merkledag key. func (m *Self) WritePeersToDAG(peers Peers, kprev key.Key) (key.Key, error) { log.Println("writing peers prev:", kprev) var nodes NodesProto nodes.Id = make([][]byte, len(peers)) i := 0 for _, p := range peers { nodes.Id[i] = []byte(p.ID) i++ } dat, err := proto.Marshal(&nodes) if log.If(err) { return "", err } n := &merkledag.Node{Data: dat} if kprev != "" { prev, errr := m.GetDAGNode(kprev) if log.If(errr) { return "", errr } if err = n.AddNodeLink("prev", prev); log.If(err) { return "", err } } k, err := m.AddDAGNode(n, true) if log.If(err) { return "", err } return k, nil }
//FromDAGNode creates Records from links of merkledag n and retuns it. //links must contain "Stamp" and "Thread" func FromDAGNode(self *peer.Self, n *merkledag.Node, sign []byte) (*Record, error) { r := &Record{ self: self, Stamp: time.Unix(0, 0), Sign: sign, Contents: make(map[string][]byte), } var err error r.Key, err = n.Key() if log.If(err) { return nil, err } for _, l := range n.Links { nn, err := r.self.GetLinkedNode(n, l.Name) if log.If(err) { return nil, err } r.Contents[l.Name] = nn.Data switch l.Name { case "thread": r.Thread = string(nn.Data) case "stamp": stamp := binary.BigEndian.Uint64(nn.Data) r.Stamp = time.Unix(0, int64(stamp)) } } if err := r.check(false); log.If(err) { return nil, err } return r, nil }
//StartListen starts listening and calls accept fucn if accepted. func (m *Self) StartListen(accept func(net.Stream) error) error { list, err := corenet.Listen(m.ipfsNode, "/app/"+m.RootPath) if log.If(err) { return err } log.Printf("starting to listen at peer: %s\n", m.ipfsNode.Identity.Pretty()) go func() { for { con, err := list.Accept() defer func() { log.If(con.Close()) }() if log.If(err) { continue } peer := con.Conn().RemotePeer() log.Printf("Connection from: %s\n", peer) p, err := FromBytes([]byte(peer), m) if log.If(err) { continue } if !p.IsAllowed() { log.Println(p, "denifed") continue } log.If(accept(con)) } }() return nil }
//Slice returns sorted records slice. //if insufficient number it returns atmost records slice. func (t *Thread) Slice(from, to int, spam slice.Key) (record.Records, error) { sl := make(record.Records, 0, to-from) troot, err := t.self.GetDAGNode(t.root) log.Println(t.root) if log.If(err) { return nil, err } root, err := t.next(troot) if log.If(err) { return nil, err } for i := 0; root != nil && i < to; i++ { kkk, _ := root.Key() if spam != nil { if _, exist := spam[kkk]; exist { log.Println(kkk, "is regarded as spam") i-- continue } } if i >= from { r, errr := t.toRecord(root) if log.If(errr) { return nil, errr } sl = append(sl, r) } root, err = t.next(root) if log.If(err) { return nil, err } } return sl, nil }
//New reeturns Manager obj. func New(cfg *config.Config, rootPath string) (*Manager, error) { self := peer.NewSelf(cfg, rootPath) m := &Manager{ self: self, } p := self.ToPeer() recent, err := p.ReadRecent() if log.If(err) { log.Println(err) } m.recent, err = thread.NewList(self, recent) m.peers, err = p.ReadPeers() log.If(err) if len(m.peers) == 0 { m.peers = self.LoadInitPeers() } m.tags, err = p.ReadTags() log.If(err) m.spams, err = p.ReadSpams() log.If(err) m.readThreads = self.ReadThreads() if err := self.StartListen(m.accept); log.If(err) { return nil, err } go func() { for { m.cron() time.Sleep(time.Hour) } }() return m, nil }
//search serches nearest and bigger than stamp and update all DAG after calling func f if needed. func (t *Thread) search(root *merkledag.Node, stamp time.Time, f func(bool, *merkledag.Node) (bool, error)) (*merkledag.Node, error) { link, err := getLinkName(root) if log.If(err) { return nil, err } var eq bool if link != nil { eq = link.stamp.Equal(stamp) } if link == nil || (eq || link.stamp.Before(stamp)) { updated, errr := f(eq, root) log.If(errr) if updated { return root, errr } return nil, errr } n, err := t.self.GetLinkedNode(root, link.string()) if log.If(err) { return nil, err } updated, err := t.search(n, stamp, f) if err != nil { return nil, err } if updated != nil { root, err = root.UpdateNodeLink(link.string(), updated) log.If(err) return root, err } return nil, err }
//Slice returns from~to record slice from thread.. func (l *List) Slice(thread string, from, to int) (record.Records, error) { t, err := l.GetThread(thread) if log.If(err) { return nil, err } rs, err := t.Slice(from, to, nil) log.If(err) return rs, err }
//GetDAGNode gets dag node from path ph. func (p *Peer) GetDAGNode(ph string) (*merkledag.Node, error) { log.Println("getting dag from", ph) k, err := p.nameResolve() if log.If(err) { return nil, err } node, err := p.myself.GetPathNode(k, ph) log.If(err) return node, err }
//Signer returns one who Signs if exists. func (r *Record) Signer() (ipfspeer.ID, error) { pubKey, err := crypto.UnmarshalPublicKey(r.Contents["pubkey"]) if log.If(err) { return "", err } var id ipfspeer.ID id, err = ipfspeer.IDFromPublicKey(pubKey) log.If(err) return id, err }
//ExchangeRecent sends hash and peers of recent hash and returns received recent key. func (m *Self) ExchangeRecent(target *Peer, recent key.Key, peers key.Key) (key.Key, error) { con, err := corenet.Dial(m.ipfsNode, target.ID, "/app/"+m.RootPath) if log.If(err) { return "", err } if err := WriteRequest(con, recent, peers); log.If(err) { return "", err } rrecent, err := ReadResponse(con) log.If(err) return rrecent, err }
//toDAGNode returns merkledag with Contents. //Contents must contain "Stamp" and "Thread" func (r *Record) toDAGNode() error { var err error n := &merkledag.Node{} for k, v := range r.Contents { if err := n.AddNodeLink(k, &merkledag.Node{Data: v}); log.If(err) { return err } } r.Key, err = r.self.AddDAGNode(n, false) log.If(err) return err }
//GetThread returns thread obj . func (l *List) GetThread(name string) (*Thread, error) { n, err := l.self.GetDAGNode(l.key) if log.If(err) { return nil, err } var tkey key.Key if l, errr := n.GetNodeLink(name); errr == nil { tkey = key.Key(l.Hash) } t, err := New(l.self, name, tkey) log.If(err) return t, err }
//NewSelf make repo if needed ,starts daemon and returns Self obj. func NewSelf(cfg *config.Config, rootPath string) *Self { InitRepo(cfg.IpfsRepo) n := &merkledag.Node{} k, err := n.Key() log.IfFatal(err) //workaround "ERROR bitswap: failed to find any peer in table" i := 0 var node *core.IpfsNode var ctx context.Context var cancel context.CancelFunc for i = 0; i < 10; i++ { log.Println("setting up node...") r, err := fsrepo.Open(cfg.IpfsRepo) log.IfFatal(err) ctx, cancel = context.WithCancel(context.Background()) node, err = core.NewNode(ctx, &core.BuildCfg{ Repo: r, Online: true, }) log.IfFatal(err) if err := node.Routing.Provide(ctx, k); log.If(err) { cancel() log.If(node.Close()) log.Println("retrying...") continue } break } if i == 10 { log.Fatal("cannot provide a key to network") } self := &Self{ RootPath: rootPath, ipfsNode: node, ctx: ctx, cancel: cancel, cfg: cfg, } self.follow = FromStringSlice(cfg.FollowPeers, self) parent, err := self.ToPeer().GetDAGNode("") if log.If(err) { parent = &merkledag.Node{} } self.myIpns, err = parent.Key() log.IfFatal(err) if _, err = parent.GetNodeLink(rootPath); err != nil { log.Println("initializing DAGs for saving status") self.makeInitNodes(parent) } return self }
//FromPubkey returns new Peer obj from RSA pubkey. func FromPubkey(pk []byte, my *Self) (*Peer, error) { rpk, err := crypto.UnmarshalPublicKey(pk) if log.If(err) { return nil, err } id, err := peer.IDFromPublicKey(rpk) if log.If(err) { return nil, err } return &Peer{ ID: id, myself: my, }, nil }
//AddDAGNode adds dagNode and returns key func (m *Self) AddDAGNode(dagNode *merkledag.Node, pin bool) (key.Key, error) { if err := m.ipfsNode.DAG.AddRecursive(dagNode); log.If(err) { return "", err } k, err := dagNode.Key() if log.If(err) { return "", err } log.Println("added DAG", k.B58String()) if pin { err = m.ipfsNode.Pinning.Pin(m.ctx, dagNode, true) } log.If(err) return k, err }
//ReadResponse reads hash of recent from con. func ReadResponse(con net.Stream) (key.Key, error) { rdat, err := ioutil.ReadAll(con) if log.If(err) { return "", err } var rmsg NodeProto if err := proto.Unmarshal(rdat, &rmsg); log.If(err) { return "", err } var r key.Key if rmsg.Id != nil { r = key.Key(rmsg.Id) } return r, nil }
//SetDefaults sets default values if empty func (c *Config) SetDefaults() { if c.FileDir == "" { c.FileDir = "./file" } if c.RunDir == "" { c.RunDir = "./run" } if c.IpfsRepo == "" { c.IpfsRepo = "./.ipfs" } dp := filepath.Join(c.FileDir, DeniedPeersTxt) c.DeniedPeers = NewConfList(dp, nil) sp := filepath.Join(c.FileDir, SpamsTxt) c.RegSpam = NewRegexpList(sp) ip := filepath.Join(c.FileDir, InitPeersTxt) c.InitPeers = NewConfList(ip, nil) fp := filepath.Join(c.FileDir, FollowTxt) strs, err := ioutil.ReadFile(fp) if log.If(err) { return } for _, line := range strings.Split(string(strs), "\n") { line = strings.TrimSpace(line) c.FollowPeers = append(c.FollowPeers, line) } }
func checkWriteable(dir string) error { _, err := os.Stat(dir) if err == nil { // dir exists, make sure we can write to it testfile := path.Join(dir, "test") fi, errr := os.Create(testfile) if errr != nil { if os.IsPermission(errr) { return fmt.Errorf("%s is not writeable by the current user", dir) } return fmt.Errorf("unexpected error while checking writeablility of repo root: %s", errr) } log.If(fi.Close()) return os.Remove(testfile) } if os.IsNotExist(err) { // dir doesnt exist, check that we can create it return os.Mkdir(dir, 0775) } if os.IsPermission(err) { return fmt.Errorf("cannot write to %s, incorrect permissions", err) } return err }
//WriteResponse writes hash of recent to con. func WriteResponse(con net.Stream, recent key.Key) error { var r []byte if recent != "" { r = []byte(recent) } msg := &NodeProto{ Id: r, } dat, err := proto.Marshal(msg) if log.If(err) { return err } _, err = con.Write(dat) log.If(err) return err }
//Search serrches nearest and bigger than record r. func (t *Thread) Search(stamp time.Time) (*merkledag.Node, bool, error) { troot, err := t.self.GetDAGNode(t.root) if log.If(err) { return nil, false, err } var dag *merkledag.Node var found bool _, err = t.search(troot, stamp, func(exist bool, n *merkledag.Node) (bool, error) { log.Println("!!!") found = exist dag = n return false, nil }) log.If(err) return dag, found, err }
func (t *Thread) next(root *merkledag.Node) (*merkledag.Node, error) { var err error link, err := getLinkName(root) if log.If(err) { return nil, err } if link == nil { return nil, nil } log.Println(link.stamp) root, err = t.self.GetLinkedNode(root, link.string()) if log.If(err) { return nil, err } return root, nil }
//ReadRecent reads recent key of Peer p. func (p *Peer) ReadRecent() (key.Key, error) { var recent NodeProto if err := p.readDAG(config.RecentPath, &recent); log.If(err) { return "", err } return key.Key(recent.Id), nil }
//ReadPeers reads peer list of Peer p. func (p *Peer) ReadPeers() (Peers, error) { var ps NodesProto if err := p.readDAG(config.PeersPath, &ps); log.If(err) { return nil, err } return fromProto(ps, p.myself) }
//GetDAGNode returns merkledag node. func (m *Self) GetDAGNode(k key.Key) (*merkledag.Node, error) { log.Println("get dag node key", k) n, err := m.ipfsNode.DAG.Get(m.ctx, k) if log.If(err) { return nil, err } return n, nil }
func (t *Thread) toRecord(n *merkledag.Node) (*record.Record, error) { var sign []byte if _, err := n.GetNodeLink("sign"); err == nil { s, err := t.self.GetLinkedNode(n, "sign") if log.If(err) { return nil, err } sign = s.Data } cont, err := t.self.GetLinkedNode(n, "contents") if log.If(err) { return nil, err } r, err := record.FromDAGNode(t.self, cont, sign) log.If(err) return r, err }
//Merge merges all records in list which has key and returns true if updated . func (l *List) Merge(tkey key.Key) (bool, error) { if l.key == tkey { log.Println("same key,nothing to do") return false, nil } root, err := l.self.GetDAGNode(l.key) if log.If(err) { return false, err } troot, err := l.self.GetDAGNode(tkey) if log.If(err) { return false, err } var t *Thread updated := false for _, link := range troot.Links { var k key.Key if th, errr := l.self.GetLinkedNode(root, link.Name); errr == nil { k, err = th.Key() if log.If(err) { return false, err } } t, err = New(l.self, link.Name, k) if log.If(err) { return false, err } kk := key.Key(link.Hash) if k == kk { continue } log.Println("adding to " + link.Name) u, errr := t.Merge(kk) if log.If(errr) { return false, err } if !u { continue } tn, errr := t.self.GetDAGNode(t.Key()) if log.If(errr) { return false, errr } root, errr = root.UpdateNodeLink(link.Name, tn) if log.If(errr) { return false, errr } updated = true } if updated { l.key, err = l.self.AddDAGNode(root, false) log.If(err) } return updated, err }
func (m *Self) saveSetting(msg proto.Message, p string) error { dat, err := proto.Marshal(msg) if log.If(err) { return err } root, err := m.GetDAGNode(m.myIpns) if log.If(err) { return err } nn, err := m.GetLinkedNode(root, m.RootPath) if log.If(err) { return err } n, err := m.GetLinkedNode(nn, p) if log.If(err) { return err } n.Data = dat nn, err = nn.UpdateNodeLink(p, n) if log.If(err) { return err } root, err = root.UpdateNodeLink(m.RootPath, nn) if log.If(err) { return err } m.myIpns, err = m.AddDAGNode(root, true) if log.If(err) { return err } return m.NamePublish() }
func (p *Peer) readDAG(pt string, obj proto.Message) error { log.Println("reading DAG from", pt) pa := p.myself.RootPath + "/" + pt n, err := p.GetDAGNode(pa) if log.If(err) { return err } return proto.Unmarshal(n.Data, obj) }
//AddRecord adds a record and returns true if updated. func (m *Manager) AddRecord(thread string, stamp time.Time, contents map[string][]byte, sign bool) (bool, error) { r, err := record.New(m.self, thread, stamp, contents, sign) if log.If(err) { return false, err } m.mutex.Lock() defer m.mutex.Unlock() return m.recent.Add(r) }
//GetRecords returns records in thread name. func (m *Manager) GetRecords(name string, from, to int) (record.Records, error) { m.mutex.RLock() defer m.mutex.RUnlock() t, err := m.recent.GetThread(name) if log.If(err) { return nil, err } return t.Slice(from, to, m.spams) }