예제 #1
0
파일: sync.go 프로젝트: Javantea/h0tb0x
func (this *SyncMgr) onNotify(remote int, fp *crypto.Digest, in io.Reader, out io.Writer) error {
	var mesgs []dataMesg
	err := transfer.Decode(in, &mesgs)
	if err != nil {
		return err
	}

	// Find client
	this.cmut.Lock()
	cl, ok := this.clients[fp.String()]
	this.cmut.Unlock()

	if !ok {
		this.Log.Printf("Receiving notify from non-friend, ignoring")
	}

	for _, mesg := range mesgs {
		this.Log.Printf("Received data, topic = %s, key = %s", mesg.Topic, mesg.Key)
		row := this.Db.SingleQuery(`SELECT heard_seqno FROM TopicFriend 
					WHERE topic = ? AND friend_id = ? AND desired = 1`,
			mesg.Topic, remote)
		var prev_seq int
		if !this.Db.MaybeScan(row, &prev_seq) {
			continue
		}
		sink, ok := this.sinks[mesg.RecordType]
		if !ok || prev_seq >= mesg.Seqno {
			continue
		}
		sink(cl.friendId, fp, &mesg.Record)
		this.Db.Exec("Update TopicFriend SET heard_seqno = ? WHERE topic = ? AND friend_id = ?",
			mesg.Seqno, mesg.Topic, remote)
	}
	return nil
}
예제 #2
0
파일: data.go 프로젝트: Javantea/h0tb0x
// Reads from io.Reader and generates a new object, put it to the meta-data layer
func (this *DataMgr) GetData(topic string, key string, stream io.Writer) error {
	data := this.Get(topic, key)
	if data == nil {
		return fmt.Errorf("Unknown key")
	}
	var objHash *crypto.Digest
	err := transfer.DecodeBytes(data, &objHash)
	if err != nil {
		return err
	}
	okey := objHash.String()

	this.lock.Lock()
	obj := this.maybeGetObj(okey)
	if obj == nil || obj.State != DSLocal {
		return fmt.Errorf("File not local yet")
	}
	obj.Holds++
	this.writeObj(obj)
	this.lock.Unlock()

	name := path.Join(this.dir, okey)
	file, err := os.Open(name)
	if err == nil {
		_, err = io.Copy(stream, file)
	}

	this.lock.Lock()
	obj = this.getObj(okey)
	obj.Holds--
	this.writeObj(obj)
	this.lock.Unlock()

	return err
}
예제 #3
0
파일: link.go 프로젝트: Javantea/h0tb0x
// Add a new friend, or if the friend exists, update the host and port data.
func (this *LinkMgr) RemoveFriend(fp *crypto.Digest) {
	this.cmut.Lock()
	defer this.cmut.Unlock()
	fi, ok := this.friendsFp[fp.String()]
	if !ok {
		return
	}
	for _, f := range this.listeners {
		f(fi.id, fp, FriendRemoved)
	}
	this.Db.Exec("DELETE FROM FRIEND WHERE id = ?", fi.id)
	delete(this.friendsFp, fp.String())
	delete(this.friendsId, fi.id)
}
예제 #4
0
파일: link.go 프로젝트: Javantea/h0tb0x
// Add a new friend, or if the friend exists, update the host and port data.
func (this *LinkMgr) AddUpdateFriend(fp *crypto.Digest, host string, port uint16) {
	this.cmut.Lock()
	defer this.cmut.Unlock()
	// Make or insert friend
	this.Db.Exec(
		"INSERT OR IGNORE INTO Friend (id, fingerprint, host, port) VALUES (NULL, ?, ?, ?)",
		fp.Bytes(), host, port)

	row := this.Db.SingleQuery("SELECT id FROM Friend WHERE fingerprint = ?", fp.Bytes())
	var id int
	this.Db.Scan(row, &id)

	this.Db.Exec("UPDATE Friend SET host = ?, port = ? WHERE id = ?",
		host, port, id)

	_, ok := this.friendsFp[fp.String()]
	fi := &friendInfo{id: id, fingerprint: fp, host: host, port: port}
	this.friendsFp[fp.String()] = fi
	this.friendsId[id] = fi
	if !ok {
		// If it was added, signal upper layer
		for _, f := range this.listeners {
			f(id, fp, FriendAdded)
		}
	}
}
예제 #5
0
파일: link.go 프로젝트: Javantea/h0tb0x
// Kicks off the link manager, presumes Callbacks has been set
func (this *LinkMgr) Run() error {
	conn, err := net.Listen("tcp", this.server.Addr)
	if err != nil {
		return err
	}
	this.listener = tls.NewListener(conn, this.server.TLSConfig)

	rows := this.Db.MultiQuery("SELECT id, fingerprint, isgdid, host, port FROM Friend")
	for rows.Next() {
		var id int
		var isgdid int
		var fp []byte
		var host string
		var port uint16
		this.Db.Scan(rows, &id, &fp, &isgdid, &host, &port)
		var fingerprint *crypto.Digest
		err := transfer.DecodeBytes(fp, &fingerprint)
		if err != nil {
			panic(err)
		}
		fi := &friendInfo{
			id:          id,
			fingerprint: fingerprint,
			isgdid:      isgdid,
			host:        host,
			port:        port,
		}
		this.friendsFp[fingerprint.String()] = fi
		this.friendsId[id] = fi
	}

	this.cmut.RLock()
	for id, fi := range this.friendsId {
		for _, f := range this.listeners {
			f(id, fi.fingerprint, FriendStartup)
		}
	}
	this.cmut.RUnlock()

	this.wait.Add(1)
	go func() {
		this.server.Serve(this.listener)
		this.wait.Done()
	}()

	return nil
}
예제 #6
0
파일: sync.go 프로젝트: Javantea/h0tb0x
func (this *SyncMgr) onSubscribe(id int, fp *crypto.Digest, rec *Record) {
	this.cmut.RLock()
	client, ok := this.clients[fp.String()]
	this.cmut.RUnlock()
	if !ok {
		return
	}
	client.lock.Lock()
	this.Db.Exec("INSERT OR IGNORE INTO TopicFriend (friend_id, topic) VALUES (?, ?)",
		client.friendId, rec.Key)

	enable := (rec.Value[0] != 0)
	this.Db.Exec("UPDATE TopicFriend SET requested = ?, acked_seqno = ? WHERE friend_id = ? AND topic = ?",
		enable, rec.Priority, id, rec.Key)
	client.wakeNotify.Broadcast()
	client.lock.Unlock()
}
예제 #7
0
파일: data.go 프로젝트: Javantea/h0tb0x
func (this *DataMgr) onMeta(topic string, key string, data []byte, fp string, isUp bool) {
	var objHash *crypto.Digest
	err := transfer.DecodeBytes(data, &objHash)
	if err != nil {
		this.Log.Printf("Unable to decode meta-data value")
		return
	}
	objKey := objHash.String()
	this.lock.Lock()
	defer this.lock.Unlock()
	obj := this.getObj(objKey)
	if isUp {
		obj.metaUp(topic)
	} else {
		obj.metaDown(topic)
	}
	this.writeObj(obj)
}
예제 #8
0
파일: sync.go 프로젝트: Javantea/h0tb0x
// 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
}
예제 #9
0
파일: sync.go 프로젝트: Javantea/h0tb0x
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()
}
예제 #10
0
파일: api.go 프로젝트: Javantea/h0tb0x
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()
}
예제 #11
0
func (this *TestNode) OnFriendChange(id int, fingerprint *crypto.Digest, what FriendStatus) {
	this.Log.Printf("OnFriendChange(%d, %s, %d)", id, fingerprint.String(), what)
}