// Creates a collection with a specific uniq element, used for friend collections func (this *MetaMgr) CreateSpecialCollection(owner *crypto.SecretIdentity, uniq *crypto.Digest) (cid string) { pubkey := owner.Public() cb := &collectionBasis{ Uniq: uniq, Owner: pubkey, } cid = crypto.HashOf(cb.Owner.Fingerprint(), cb.Uniq).String() existing := this.SyncMgr.Get(sync.RTBasis, cid, "$") if existing != nil { return cid } basis := &sync.Record{ RecordType: sync.RTBasis, Topic: cid, Key: "$", Author: pubkey.Fingerprint().String(), Value: transfer.AsBytes(cb), } signRecord(basis, owner) this.SyncMgr.Put(basis) owr := &sync.Record{ RecordType: sync.RTWriter, Topic: cid, Key: pubkey.Fingerprint().String(), Value: transfer.AsBytes(pubkey), } signRecord(owr, owner) this.SyncMgr.Put(owr) return }
func verifyRecord(rec *sync.Record, writer *crypto.PublicIdentity) bool { hash := crypto.HashOf(rec.RecordType, rec.Topic, rec.Key, rec.Value, rec.Priority) var sig *crypto.Signature err := transfer.DecodeBytes(rec.Signature, &sig) if err != nil { panic(err) } return writer.Verify(hash, sig) }
func (this *ApiMgr) getSelf(w http.ResponseWriter, req *http.Request) { myFp := this.Ident.Public().Fingerprint() myCid := crypto.HashOf(myFp, myFp).String() json := SelfJson{ Id: myFp.String(), Host: this.ExtHost, Port: this.ExtPort, SelfCid: myCid, } this.sendJson(w, json) }
func (this *SyncMgr) onFriendChange(id int, fp *crypto.Digest, what link.FriendStatus) { this.cmut.Lock() if what == link.FriendStartup || what == link.FriendAdded { this.Log.Printf("Adding friend: %s", fp.String()) myFp := this.Ident.Public().Fingerprint() this.Db.Exec("INSERT OR IGNORE INTO TopicFriend (topic, friend_id, desired, requested) VALUES (?, ?, ?, ?)", crypto.HashOf(fp, myFp).String(), id, 1, 1) this.Db.Exec("INSERT OR IGNORE INTO TopicFriend (topic, friend_id, desired, requested) VALUES (?, ?, ?, ?)", crypto.HashOf(myFp, fp).String(), id, 1, 1) cl := newClientLooper(this, id) this.clients[fp.String()] = cl cl.run() } else { cl := this.clients[fp.String()] cl.stop() delete(this.clients, fp.String()) this.Db.Exec("DELETE INTO TopicFriend WHERE friend_id = ?", id) } this.cmut.Unlock() }
func (this *LinkMgr) UpdateIsGd(fi *friendInfo) { theHash := crypto.HashOf(fi.fingerprint, fi.isgdid) this.Log.Printf("Trying to update isGd for %s, id = %d", fi.fingerprint.String(), fi.isgdid) isgdurl := "http://is.gd/forward.php?format=json&shorturl=" + theHash.String()[0:24] this.Log.Printf("Doing get of: %s", isgdurl) resp, err := http.Get(isgdurl) this.Log.Printf("Get has returned") if err != nil { this.Log.Printf("Failed to do get of: %s", "http://is.gd/forward.php?format=json&shorturl="+theHash.String()) return } if resp.StatusCode != http.StatusOK { this.Log.Printf("Status not OK") return } dec := json.NewDecoder(resp.Body) var gd isGdJson err = dec.Decode(&gd) if err != nil { this.Log.Printf("Unable to decode") return } url, err := url.Parse(gd.Url) if err != nil { this.Log.Printf("Unable to parse as URL: '%s'", gd.Url) return } var ip1, ip2, ip3, ip4 int var port int _, err = fmt.Sscanf(url.Host, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip3, &port) if err != nil { this.Log.Printf("Unable to parse as host: '%s': %v", url.Host, err) return } host := fmt.Sprintf("%d.%d.%d.%d", ip1, ip2, ip3, ip4) this.Log.Printf("Updating %s to %s:%d", fi.fingerprint.String(), host, port) fi.host = host fi.port = uint16(port) fi.isgdid++ this.Db.Exec("UPDATE Friend SET host = ?, port = ?, isgdid = ? WHERE id = ?", host, port, fi.isgdid, fi.id) }
// Checks if basis record is valid, if so, returns owner ID, otherwise nil func (this *MetaMgr) decodeBasis(rec *sync.Record, check bool) *crypto.PublicIdentity { var cb *collectionBasis if rec == nil { return nil } err := transfer.DecodeBytes(rec.Value, &cb) if err != nil { this.Log.Printf("Unable to decode basis: %s", err) return nil } if check { cid := crypto.HashOf(cb.Owner.Fingerprint(), cb.Uniq).String() if cid != rec.Topic { this.Log.Printf("Basis hash mismatch: %s vs %s", cid, rec.Topic) return nil } } return cb.Owner }
// Update the subscription state for a topic on a particular friend. func (this *SyncMgr) Subscribe(id *crypto.Digest, topic string, enable bool) bool { this.cmut.RLock() client, ok := this.clients[id.String()] this.cmut.RUnlock() if !ok { return false } client.lock.Lock() this.Db.Exec("INSERT OR IGNORE INTO TopicFriend (friend_id, topic) VALUES (?, ?)", client.friendId, topic) this.Db.Exec("UPDATE TopicFriend SET desired = ? WHERE friend_id = ? AND topic = ?", enable, client.friendId, topic) row := this.Db.SingleQuery("SELECT heard_seqno FROM TopicFriend WHERE friend_id = ? AND topic = ?", client.friendId, topic) var heard int this.Db.Scan(row, &heard) enbyte := byte(0) if enable { enbyte = 1 } myFp := this.Ident.Public().Fingerprint() client.lock.Unlock() this.Put(&Record{ RecordType: RTSubscribe, Topic: crypto.HashOf(myFp, id).String(), Key: topic, Value: []byte{enbyte}, Priority: heard, Author: "$", }) return true }
func (this *ApiMgr) populateFriend(json *FriendJson, myFp, fp *crypto.Digest) { json.Id = fp.String() json.SelfCid = crypto.HashOf(fp, fp).String() json.SendCid = crypto.HashOf(myFp, fp).String() json.RecvCid = crypto.HashOf(fp, myFp).String() }
// Creates a new collection with a specific owner, no writers (except owner), and no data. func (this *MetaMgr) CreateNewCollection(owner *crypto.SecretIdentity) (cid string) { uniq := make([]byte, 16) io.ReadFull(rand.Reader, uniq) return this.CreateSpecialCollection(owner, crypto.HashOf(uniq)) }
func signRecord(rec *sync.Record, writer *crypto.SecretIdentity) { hash := crypto.HashOf(rec.RecordType, rec.Topic, rec.Key, rec.Value, rec.Priority) sig := writer.Sign(hash) rec.Author = writer.Fingerprint().String() rec.Signature = transfer.AsBytes(sig) }