mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-23 18:15:24 +00:00
It works, sort of, amazingly
This commit is contained in:
parent
e1a2d666bf
commit
d7a1c04748
@ -15,7 +15,6 @@ type Conn struct {
|
|||||||
core *Core
|
core *Core
|
||||||
nodeID *crypto.NodeID
|
nodeID *crypto.NodeID
|
||||||
nodeMask *crypto.NodeID
|
nodeMask *crypto.NodeID
|
||||||
recv chan *wire_trafficPacket // Eventually gets attached to session.recv
|
|
||||||
mutex *sync.RWMutex
|
mutex *sync.RWMutex
|
||||||
session *sessionInfo
|
session *sessionInfo
|
||||||
readDeadline atomic.Value // time.Time // TODO timer
|
readDeadline atomic.Value // time.Time // TODO timer
|
||||||
@ -33,10 +32,11 @@ func (c *Conn) startSearch() {
|
|||||||
// The searchCompleted callback is given to the search
|
// The searchCompleted callback is given to the search
|
||||||
searchCompleted := func(sinfo *sessionInfo, err error) {
|
searchCompleted := func(sinfo *sessionInfo, err error) {
|
||||||
// Make sure that any blocks on read/write operations are lifted
|
// Make sure that any blocks on read/write operations are lifted
|
||||||
defer close(c.searchwait)
|
defer func() {
|
||||||
// Update the connection with the fact that the search completed, which
|
c.searching.Store(false)
|
||||||
// allows another search to be triggered if necessary
|
close(c.searchwait)
|
||||||
c.searching.Store(false)
|
c.searchwait = make(chan interface{})
|
||||||
|
}()
|
||||||
// If the search failed for some reason, e.g. it hit a dead end or timed
|
// If the search failed for some reason, e.g. it hit a dead end or timed
|
||||||
// out, then do nothing
|
// out, then do nothing
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,8 +64,6 @@ func (c *Conn) startSearch() {
|
|||||||
}
|
}
|
||||||
// doSearch will be called below in response to one or more conditions
|
// doSearch will be called below in response to one or more conditions
|
||||||
doSearch := func() {
|
doSearch := func() {
|
||||||
// Store the fact that we're searching, so that we don't start additional
|
|
||||||
// searches until this one has completed
|
|
||||||
c.searching.Store(true)
|
c.searching.Store(true)
|
||||||
// Check to see if there is a search already matching the destination
|
// Check to see if there is a search already matching the destination
|
||||||
sinfo, isIn := c.core.searches.searches[*c.nodeID]
|
sinfo, isIn := c.core.searches.searches[*c.nodeID]
|
||||||
@ -73,8 +71,6 @@ func (c *Conn) startSearch() {
|
|||||||
// Nothing was found, so create a new search
|
// Nothing was found, so create a new search
|
||||||
sinfo = c.core.searches.newIterSearch(c.nodeID, c.nodeMask, searchCompleted)
|
sinfo = c.core.searches.newIterSearch(c.nodeID, c.nodeMask, searchCompleted)
|
||||||
c.core.log.Debugf("%s DHT search started: %p", c.String(), sinfo)
|
c.core.log.Debugf("%s DHT search started: %p", c.String(), sinfo)
|
||||||
// Allow writes/reads to block until the search is complete
|
|
||||||
c.searchwait = make(chan interface{})
|
|
||||||
}
|
}
|
||||||
// Continue the search
|
// Continue the search
|
||||||
c.core.searches.continueSearch(sinfo)
|
c.core.searches.continueSearch(sinfo)
|
||||||
@ -111,23 +107,23 @@ func (c *Conn) Read(b []byte) (int, error) {
|
|||||||
sinfo := c.session
|
sinfo := c.session
|
||||||
c.mutex.RUnlock()
|
c.mutex.RUnlock()
|
||||||
// If there is a search in progress then wait for the result
|
// If there is a search in progress then wait for the result
|
||||||
if searching, ok := c.searching.Load().(bool); ok && searching {
|
if sinfo == nil {
|
||||||
|
// Wait for the search to complete
|
||||||
<-c.searchwait
|
<-c.searchwait
|
||||||
}
|
// Retrieve our session info again
|
||||||
// If the session is not initialised, do nothing. Currently in this instance
|
c.mutex.RLock()
|
||||||
// in a write, we would trigger a new session, but it doesn't make sense for
|
sinfo = c.session
|
||||||
// us to block forever here if the session will not reopen.
|
c.mutex.RUnlock()
|
||||||
// TODO: should this return an error or just a zero-length buffer?
|
// If sinfo is still nil at this point then the search failed and the
|
||||||
if sinfo == nil || !sinfo.init {
|
// searchwait channel has been recreated, so might as well give up and
|
||||||
time.Sleep(time.Second)
|
// return an error code
|
||||||
return 0, errors.New("session is closed")
|
if sinfo == nil {
|
||||||
|
return 0, errors.New("search failed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Wait for some traffic to come through from the session
|
// Wait for some traffic to come through from the session
|
||||||
fmt.Println(c.String(), "Start select")
|
|
||||||
select {
|
select {
|
||||||
// TODO...
|
case p, ok := <-sinfo.recv:
|
||||||
case p, ok := <-c.recv:
|
|
||||||
fmt.Println(c.String(), "Finish select")
|
|
||||||
// If the session is closed then do nothing
|
// If the session is closed then do nothing
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, errors.New("session is closed")
|
return 0, errors.New("session is closed")
|
||||||
@ -168,10 +164,6 @@ func (c *Conn) Read(b []byte) (int, error) {
|
|||||||
// If we've reached this point then everything went to plan, return the
|
// If we've reached this point then everything went to plan, return the
|
||||||
// number of bytes we populated back into the given slice
|
// number of bytes we populated back into the given slice
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
//case <-c.recvTimeout:
|
|
||||||
//case <-c.session.closed:
|
|
||||||
// c.expired = true
|
|
||||||
// return len(b), errors.New("session is closed")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,12 +171,9 @@ func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
|
|||||||
c.mutex.RLock()
|
c.mutex.RLock()
|
||||||
sinfo := c.session
|
sinfo := c.session
|
||||||
c.mutex.RUnlock()
|
c.mutex.RUnlock()
|
||||||
// If there is a search in progress then wait for the result
|
|
||||||
if searching, ok := c.searching.Load().(bool); ok && searching {
|
|
||||||
<-c.searchwait
|
|
||||||
}
|
|
||||||
// If the session doesn't exist, or isn't initialised (which probably means
|
// If the session doesn't exist, or isn't initialised (which probably means
|
||||||
// that the search didn't complete successfully) then try to search again
|
// that the search didn't complete successfully) then we may need to wait for
|
||||||
|
// the search to complete or start the search again
|
||||||
if sinfo == nil || !sinfo.init {
|
if sinfo == nil || !sinfo.init {
|
||||||
// Is a search already taking place?
|
// Is a search already taking place?
|
||||||
if searching, sok := c.searching.Load().(bool); !sok || (sok && !searching) {
|
if searching, sok := c.searching.Load().(bool); !sok || (sok && !searching) {
|
||||||
@ -192,13 +181,19 @@ func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
|
|||||||
c.core.router.doAdmin(func() {
|
c.core.router.doAdmin(func() {
|
||||||
c.startSearch()
|
c.startSearch()
|
||||||
})
|
})
|
||||||
//return 0, errors.New("starting search")
|
|
||||||
}
|
}
|
||||||
|
// Wait for the search to complete
|
||||||
<-c.searchwait
|
<-c.searchwait
|
||||||
if sinfo == nil || !sinfo.init {
|
// Retrieve our session info again
|
||||||
return 0, errors.New("search was failed")
|
c.mutex.RLock()
|
||||||
|
sinfo = c.session
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
// If sinfo is still nil at this point then the search failed and the
|
||||||
|
// searchwait channel has been recreated, so might as well give up and
|
||||||
|
// return an error code
|
||||||
|
if sinfo == nil {
|
||||||
|
return 0, errors.New("search failed")
|
||||||
}
|
}
|
||||||
//return 0, errors.New("waiting for search to complete")
|
|
||||||
}
|
}
|
||||||
// defer util.PutBytes(b)
|
// defer util.PutBytes(b)
|
||||||
var packet []byte
|
var packet []byte
|
||||||
|
@ -59,11 +59,11 @@ func (d *Dialer) Dial(network, address string) (Conn, error) {
|
|||||||
// NodeID parameters.
|
// NodeID parameters.
|
||||||
func (d *Dialer) DialByNodeIDandMask(nodeID, nodeMask *crypto.NodeID) (Conn, error) {
|
func (d *Dialer) DialByNodeIDandMask(nodeID, nodeMask *crypto.NodeID) (Conn, error) {
|
||||||
conn := Conn{
|
conn := Conn{
|
||||||
core: d.core,
|
core: d.core,
|
||||||
mutex: &sync.RWMutex{},
|
mutex: &sync.RWMutex{},
|
||||||
nodeID: nodeID,
|
nodeID: nodeID,
|
||||||
nodeMask: nodeMask,
|
nodeMask: nodeMask,
|
||||||
recv: make(chan *wire_trafficPacket, 32),
|
searchwait: make(chan interface{}),
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
@ -458,12 +458,12 @@ func (ss *sessions) handlePing(ping *sessionPing) {
|
|||||||
// TODO: this should not block if nothing is accepting
|
// TODO: this should not block if nothing is accepting
|
||||||
if !ping.IsPong && ss.listener != nil {
|
if !ping.IsPong && ss.listener != nil {
|
||||||
conn := &Conn{
|
conn := &Conn{
|
||||||
core: ss.core,
|
core: ss.core,
|
||||||
session: sinfo,
|
session: sinfo,
|
||||||
mutex: &sync.RWMutex{},
|
mutex: &sync.RWMutex{},
|
||||||
nodeID: crypto.GetNodeID(&sinfo.theirPermPub),
|
nodeID: crypto.GetNodeID(&sinfo.theirPermPub),
|
||||||
nodeMask: &crypto.NodeID{},
|
nodeMask: &crypto.NodeID{},
|
||||||
recv: sinfo.recv,
|
searchwait: make(chan interface{}),
|
||||||
}
|
}
|
||||||
for i := range conn.nodeMask {
|
for i := range conn.nodeMask {
|
||||||
conn.nodeMask[i] = 0xFF
|
conn.nodeMask[i] = 0xFF
|
||||||
|
Loading…
Reference in New Issue
Block a user