Exemplo n.º 1
0
func listenConnect(myID protocol.NodeID, m *model.Model, tlsCfg *tls.Config) {
	var conns = make(chan *tls.Conn)

	// Listen
	for _, addr := range cfg.Options.ListenAddress {
		go listenTLS(conns, addr, tlsCfg)
	}

	// Connect
	go dialTLS(m, conns, tlsCfg)

next:
	for conn := range conns {
		certs := conn.ConnectionState().PeerCertificates
		if cl := len(certs); cl != 1 {
			l.Infof("Got peer certificate list of length %d != 1 from %s; protocol error", cl, conn.RemoteAddr())
			conn.Close()
			continue
		}
		remoteID := protocol.NewNodeID(certs[0].Raw)

		if remoteID == myID {
			l.Infof("Connected to myself (%s) - should not happen", remoteID)
			conn.Close()
			continue
		}

		if m.ConnectedTo(remoteID) {
			l.Infof("Connected to already connected node (%s)", remoteID)
			conn.Close()
			continue
		}

		for _, nodeCfg := range cfg.Nodes {
			if nodeCfg.NodeID == remoteID {
				var wr io.Writer = conn
				if rateBucket != nil {
					wr = &limitedWriter{conn, rateBucket}
				}
				name := fmt.Sprintf("%s-%s", conn.LocalAddr(), conn.RemoteAddr())
				protoConn := protocol.NewConnection(remoteID, conn, wr, m, name)

				l.Infof("Established secure connection to %s at %s", remoteID, name)
				if debugNet {
					l.Debugf("cipher suite %04X", conn.ConnectionState().CipherSuite)
				}
				events.Default.Log(events.NodeConnected, map[string]string{
					"id":   remoteID.String(),
					"addr": conn.RemoteAddr().String(),
				})

				m.AddConnection(conn, protoConn)
				continue next
			}
		}

		l.Infof("Connection from %s with unknown node ID %s; ignoring", conn.RemoteAddr(), remoteID)
		conn.Close()
	}
}
Exemplo n.º 2
0
func connect(target string) {
	cert, err := loadCert(confDir)
	if err != nil {
		log.Fatal(err)
	}

	myID := string(certID(cert.Certificate[0]))

	tlsCfg := &tls.Config{
		Certificates:           []tls.Certificate{cert},
		NextProtos:             []string{"bep/1.0"},
		ServerName:             myID,
		ClientAuth:             tls.RequestClientCert,
		SessionTicketsDisabled: true,
		InsecureSkipVerify:     true,
		MinVersion:             tls.VersionTLS12,
	}

	conn, err := tls.Dial("tcp", target, tlsCfg)
	if err != nil {
		log.Fatal(err)
	}

	remoteID := certID(conn.ConnectionState().PeerCertificates[0].Raw)

	pc = protocol.NewConnection(remoteID, conn, conn, Model{})

	select {}
}
Exemplo n.º 3
0
func listen(myID string, addr string, m *Model, tlsCfg *tls.Config, connOpts map[string]string) {
	if strings.Contains(trace, "connect") {
		debugln("NET: Listening on", addr)
	}
	l, err := tls.Listen("tcp", addr, tlsCfg)
	fatalErr(err)

listen:
	for {
		conn, err := l.Accept()
		if err != nil {
			warnln(err)
			continue
		}

		if strings.Contains(trace, "connect") {
			debugln("NET: Connect from", conn.RemoteAddr())
		}

		tc := conn.(*tls.Conn)
		err = tc.Handshake()
		if err != nil {
			warnln(err)
			tc.Close()
			continue
		}

		remoteID := certID(tc.ConnectionState().PeerCertificates[0].Raw)

		if remoteID == myID {
			warnf("Connect from myself (%s) - should not happen", remoteID)
			conn.Close()
			continue
		}

		if m.ConnectedTo(remoteID) {
			warnf("Connect from connected node (%s)", remoteID)
		}

		for _, nodeCfg := range cfg.Repositories[0].Nodes {
			if nodeCfg.NodeID == remoteID {
				protoConn := protocol.NewConnection(remoteID, conn, conn, m, connOpts)
				m.AddConnection(conn, protoConn)
				continue listen
			}
		}
		conn.Close()
	}
}
Exemplo n.º 4
0
func connect(myID string, disc *discover.Discoverer, m *Model, tlsCfg *tls.Config, connOpts map[string]string) {
	for {
	nextNode:
		for _, nodeCfg := range cfg.Repositories[0].Nodes {
			if nodeCfg.NodeID == myID {
				continue
			}
			if m.ConnectedTo(nodeCfg.NodeID) {
				continue
			}
			for _, addr := range nodeCfg.Addresses {
				if addr == "dynamic" {
					if disc != nil {
						t := disc.Lookup(nodeCfg.NodeID)
						if len(t) == 0 {
							continue
						}
						addr = t[0] //XXX: Handle all of them
					}
				}

				if strings.Contains(trace, "connect") {
					debugln("NET: Dial", nodeCfg.NodeID, addr)
				}
				conn, err := tls.Dial("tcp", addr, tlsCfg)
				if err != nil {
					if strings.Contains(trace, "connect") {
						debugln("NET:", err)
					}
					continue
				}

				remoteID := certID(conn.ConnectionState().PeerCertificates[0].Raw)
				if remoteID != nodeCfg.NodeID {
					warnln("Unexpected nodeID", remoteID, "!=", nodeCfg.NodeID)
					conn.Close()
					continue
				}

				protoConn := protocol.NewConnection(remoteID, conn, conn, m, connOpts)
				m.AddConnection(conn, protoConn)
				continue nextNode
			}
		}

		time.Sleep(time.Duration(cfg.Options.ReconnectIntervalS) * time.Second)
	}
}
Exemplo n.º 5
0
func listen(myID string, addr string, m *model.Model, cfg *tls.Config) {
	l, err := tls.Listen("tcp", addr, cfg)
	fatalErr(err)

listen:
	for {
		conn, err := l.Accept()
		if err != nil {
			warnln(err)
			continue
		}

		if opts.Debug.TraceConnect {
			debugln("NET: Connect from", conn.RemoteAddr())
		}

		tc := conn.(*tls.Conn)
		err = tc.Handshake()
		if err != nil {
			warnln(err)
			tc.Close()
			continue
		}

		remoteID := certId(tc.ConnectionState().PeerCertificates[0].Raw)

		if remoteID == myID {
			warnf("Connect from myself (%s) - should not happen", remoteID)
			conn.Close()
			continue
		}

		if m.ConnectedTo(remoteID) {
			warnf("Connect from connected node (%s)", remoteID)
		}

		for nodeID := range nodeAddrs {
			if nodeID == remoteID {
				protoConn := protocol.NewConnection(remoteID, conn, conn, m)
				m.AddConnection(conn, protoConn)
				continue listen
			}
		}
		conn.Close()
	}
}
Exemplo n.º 6
0
func (m *Model) AddConnection(conn io.ReadWriteCloser, nodeID string) {
	node := protocol.NewConnection(nodeID, conn, conn, m)

	m.Lock()
	m.nodes[nodeID] = node
	m.rawConn[nodeID] = conn
	m.Unlock()

	infoln("Connected to node", nodeID)

	m.RLock()
	idx := m.protocolIndex()
	m.RUnlock()

	go func() {
		node.Index(idx)
		infoln("Sent initial index to node", nodeID)
	}()
}
Exemplo n.º 7
0
func listenConnect(myID string, m *model.Model, tlsCfg *tls.Config) {
	var conns = make(chan *tls.Conn)

	// Listen
	for _, addr := range cfg.Options.ListenAddress {
		addr := addr
		go func() {
			if debugNet {
				l.Debugln("listening on", addr)
			}
			listener, err := tls.Listen("tcp", addr, tlsCfg)
			l.FatalErr(err)

			for {
				conn, err := listener.Accept()
				if err != nil {
					l.Warnln(err)
					continue
				}

				if debugNet {
					l.Debugln("connect from", conn.RemoteAddr())
				}

				tc := conn.(*tls.Conn)
				err = tc.Handshake()
				if err != nil {
					l.Warnln(err)
					tc.Close()
					continue
				}

				conns <- tc
			}
		}()
	}

	// Connect
	go func() {
		for {
		nextNode:
			for _, nodeCfg := range cfg.Nodes {
				if nodeCfg.NodeID == myID {
					continue
				}
				if m.ConnectedTo(nodeCfg.NodeID) {
					continue
				}

				var addrs []string
				for _, addr := range nodeCfg.Addresses {
					if addr == "dynamic" {
						if discoverer != nil {
							t := discoverer.Lookup(nodeCfg.NodeID)
							if len(t) == 0 {
								continue
							}
							addrs = append(addrs, t...)
						}
					} else {
						addrs = append(addrs, addr)
					}
				}

				for _, addr := range addrs {
					host, port, err := net.SplitHostPort(addr)
					if err != nil && strings.HasPrefix(err.Error(), "missing port") {
						// addr is on the form "1.2.3.4"
						addr = net.JoinHostPort(addr, "22000")
					} else if err == nil && port == "" {
						// addr is on the form "1.2.3.4:"
						addr = net.JoinHostPort(host, "22000")
					}
					if debugNet {
						l.Debugln("dial", nodeCfg.NodeID, addr)
					}
					conn, err := tls.Dial("tcp", addr, tlsCfg)
					if err != nil {
						if debugNet {
							l.Debugln(err)
						}
						continue
					}

					conns <- conn
					continue nextNode
				}
			}

			time.Sleep(time.Duration(cfg.Options.ReconnectIntervalS) * time.Second)
		}
	}()

next:
	for conn := range conns {
		certs := conn.ConnectionState().PeerCertificates
		if cl := len(certs); cl != 1 {
			l.Warnf("Got peer certificate list of length %d != 1; protocol error", cl)
			conn.Close()
			continue
		}
		remoteID := certID(certs[0].Raw)

		if remoteID == myID {
			l.Warnf("Connected to myself (%s) - should not happen", remoteID)
			conn.Close()
			continue
		}

		if m.ConnectedTo(remoteID) {
			l.Warnf("Connected to already connected node (%s)", remoteID)
			conn.Close()
			continue
		}

		for _, nodeCfg := range cfg.Nodes {
			if nodeCfg.NodeID == remoteID {
				var wr io.Writer = conn
				if rateBucket != nil {
					wr = &limitedWriter{conn, rateBucket}
				}
				protoConn := protocol.NewConnection(remoteID, conn, wr, m)
				m.AddConnection(conn, protoConn)
				continue next
			}
		}
		conn.Close()
	}
}
Exemplo n.º 8
0
func connect(myID string, addr string, nodeAddrs map[string][]string, m *model.Model, cfg *tls.Config) {
	_, portstr, err := net.SplitHostPort(addr)
	fatalErr(err)
	port, _ := strconv.Atoi(portstr)

	if opts.Discovery.NoLocalDiscovery {
		port = -1
	} else {
		infoln("Sending local discovery announcements")
	}

	if opts.Discovery.NoExternalDiscovery {
		opts.Discovery.ExternalPort = -1
	} else {
		infoln("Sending external discovery announcements")
	}

	disc, err := discover.NewDiscoverer(myID, port, opts.Discovery.ExternalPort, opts.Discovery.ExternalServer)

	if err != nil {
		warnf("No discovery possible (%v)", err)
	}

	for {
	nextNode:
		for nodeID, addrs := range nodeAddrs {
			if nodeID == myID {
				continue
			}
			if m.ConnectedTo(nodeID) {
				continue
			}
			for _, addr := range addrs {
				if addr == "dynamic" {
					var ok bool
					if disc != nil {
						addr, ok = disc.Lookup(nodeID)
					}
					if !ok {
						continue
					}
				}

				if opts.Debug.TraceConnect {
					debugln("NET: Dial", nodeID, addr)
				}
				conn, err := tls.Dial("tcp", addr, cfg)
				if err != nil {
					if opts.Debug.TraceConnect {
						debugln("NET:", err)
					}
					continue
				}

				remoteID := certId(conn.ConnectionState().PeerCertificates[0].Raw)
				if remoteID != nodeID {
					warnln("Unexpected nodeID", remoteID, "!=", nodeID)
					conn.Close()
					continue
				}

				protoConn := protocol.NewConnection(remoteID, conn, conn, m)
				m.AddConnection(conn, protoConn)
				continue nextNode
			}
		}

		time.Sleep(opts.Advanced.ConnInterval)
	}
}