// Handles the receiving + wrapping of messages, per conn. // Consider using reflect.Select with one goroutine instead of n. func (s *Swarm) fanInSingle(c conn.Conn) { // cleanup all data associated with this child Connection. defer func() { // remove it from the map. s.connsLock.Lock() delete(s.conns, c.RemotePeer().Key()) s.connsLock.Unlock() s.Children().Done() c.Children().Done() // child of Conn as well. }() i := 0 for { select { case <-s.Closing(): // Swarm closing return case <-c.Closing(): // Conn closing return case data, ok := <-c.In(): if !ok { log.Infof("%s in channel closed", c) return // channel closed. } i++ log.Debugf("%s received message from %s (%d)", s.local, c.RemotePeer(), i) s.Incoming <- msg.New(c.RemotePeer(), data) } } }
// connSetup takes a new connection, performs the IPFS handshake (handshake3) // and then adds it to the appropriate MultiConn. func (s *Swarm) connSetup(c conn.Conn) (conn.Conn, error) { if c == nil { return nil, errors.New("Tried to start nil connection.") } log.Event(context.TODO(), "connSetupBegin", c.LocalPeer(), c.RemotePeer()) // add address of connection to Peer. Maybe it should happen in connSecure. // NOT adding this address here, because the incoming address in TCP // is an EPHEMERAL address, and not the address we want to keep around. // addresses should be figured out through the DHT. // c.Remote.AddAddress(c.Conn.RemoteMultiaddr()) // handshake3 ctxT, _ := context.WithTimeout(c.Context(), conn.HandshakeTimeout) h3result, err := conn.Handshake3(ctxT, c) if err != nil { c.Close() return nil, fmt.Errorf("Handshake3 failed: %s", err) } // check for nats. you know, just in case. if h3result.LocalObservedAddress != nil { s.checkNATWarning(h3result.LocalObservedAddress) } else { log.Warningf("Received nil observed address from %s", c.RemotePeer()) } // add to conns mc, err := s.peerMultiConn(c.RemotePeer()) if err != nil { c.Close() return nil, err } mc.Add(c) log.Event(context.TODO(), "connSetupSuccess", c.LocalPeer(), c.RemotePeer()) return c, nil }