go.dedis.ch/onet/v4@v4.0.0-pre1/network/router.go (about)

     1  package network
     2  
     3  import (
     4  	"crypto/tls"
     5  	"strings"
     6  	"sync"
     7  
     8  	"go.dedis.ch/onet/v4/log"
     9  	"golang.org/x/xerrors"
    10  )
    11  
    12  // Router handles all networking operations such as:
    13  //   * listening to incoming connections using a host.Listener method
    14  //   * opening up new connections using host.Connect method
    15  //   * dispatching incoming message using a Dispatcher
    16  //   * dispatching outgoing message maintaining a translation
    17  //   between ServerIdentity <-> address
    18  //   * managing the re-connections of non-working Conn
    19  // Most caller should use the creation function like NewTCPRouter(...),
    20  // NewLocalRouter(...) then use the Host such as:
    21  //
    22  //   router.Start() // will listen for incoming Conn and block
    23  //   router.Stop() // will stop the listening and the managing of all Conn
    24  type Router struct {
    25  	// id is our own ServerIdentity
    26  	ServerIdentity *ServerIdentity
    27  	// address is the real-actual address used by the listener.
    28  	address Address
    29  	// Dispatcher is used to dispatch incoming message to the right recipient
    30  	Dispatcher
    31  	// Host listens for new connections
    32  	host Host
    33  	// connections keeps track of all active connections. Because a connection
    34  	// can be opened at the same time on both endpoints, there can be more
    35  	// than one connection per ServerIdentityID.
    36  	connections map[ServerIdentityID][]Conn
    37  	sync.Mutex
    38  
    39  	// boolean flag indicating that the router is already clos{ing,ed}.
    40  	isClosed bool
    41  
    42  	// wg waits for all handleConn routines to be done.
    43  	wg sync.WaitGroup
    44  
    45  	// Every handler in this list is called by this router when a network error occurs (Timeout, Connection
    46  	// Closed, or EOF). Those handler should be added by using SetErrorHandler(). The 1st argument is the remote
    47  	// server with whom the error happened
    48  	connectionErrorHandlers []func(*ServerIdentity)
    49  
    50  	// keep bandwidth of closed connections
    51  	traffic    counterSafe
    52  	msgTraffic counterSafe
    53  	// If paused is not nil, then handleConn will stop processing. When unpaused
    54  	// it will break the connection. This is for testing node failure cases.
    55  	paused chan bool
    56  	// This field should only be set during testing. It disables an important
    57  	// log message meant to discourage TCP connections.
    58  	UnauthOk bool
    59  	// Quiets the startup of the server if set to true.
    60  	Quiet bool
    61  }
    62  
    63  // NewRouter returns a new Router attached to a ServerIdentity and the host we want to
    64  // use.
    65  func NewRouter(own *ServerIdentity, h Host) *Router {
    66  	r := &Router{
    67  		ServerIdentity:          own,
    68  		connections:             make(map[ServerIdentityID][]Conn),
    69  		host:                    h,
    70  		Dispatcher:              NewBlockingDispatcher(),
    71  		connectionErrorHandlers: make([]func(*ServerIdentity), 0),
    72  	}
    73  	r.address = h.Address()
    74  	return r
    75  }
    76  
    77  // Pause casues the router to stop after reading the next incoming message. It
    78  // sleeps until it is woken up by Unpause. For testing use only.
    79  func (r *Router) Pause() {
    80  	r.Lock()
    81  	if r.paused == nil {
    82  		r.paused = make(chan bool)
    83  	}
    84  	r.Unlock()
    85  }
    86  
    87  // Unpause reverses a previous call to Pause. All paused connections are closed
    88  // and the Router is again ready to process messages normally. For testing use only.
    89  func (r *Router) Unpause() {
    90  	r.Lock()
    91  	if r.paused != nil {
    92  		close(r.paused)
    93  		r.paused = nil
    94  	}
    95  	r.Unlock()
    96  }
    97  
    98  // Start the listening routine of the underlying Host. This is a
    99  // blocking call until r.Stop() is called.
   100  func (r *Router) Start() {
   101  	if !r.Quiet {
   102  		log.Lvlf3("New router with address %s and public key %s", r.address, r.ServerIdentity.Public)
   103  	}
   104  
   105  	// Any incoming connection waits for the remote server identity
   106  	// and will create a new handling routine.
   107  	err := r.host.Listen(func(c Conn) {
   108  		dst, err := r.receiveServerIdentity(c)
   109  		if err != nil {
   110  			if !strings.Contains(err.Error(), "EOF") {
   111  				// Avoid printing error message if it's just a stray connection.
   112  				log.Errorf("receiving server identity from %#v failed: %v",
   113  					c.Remote().NetworkAddress(), err)
   114  			}
   115  			if err := c.Close(); err != nil {
   116  				log.Error("Couldn't close secure connection:",
   117  					err)
   118  			}
   119  			return
   120  		}
   121  		if err := r.registerConnection(dst, c); err != nil {
   122  			log.Lvl3(r.address, "does not accept incoming connection from", c.Remote(), "because it's closed")
   123  			return
   124  		}
   125  		// start handleConn in a go routine that waits for incoming messages and
   126  		// dispatches them.
   127  		if err := r.launchHandleRoutine(dst, c); err != nil {
   128  			log.Lvl3(r.address, "does not accept incoming connection from", c.Remote(), "because it's closed")
   129  			return
   130  		}
   131  	})
   132  	if err != nil {
   133  		log.Error("Error listening:", err)
   134  	}
   135  }
   136  
   137  // Stop the listening routine, and stop any routine of handling
   138  // connections. Calling r.Start(), then r.Stop() then r.Start() again leads to
   139  // an undefined behaviour. Callers should most of the time re-create a fresh
   140  // Router.
   141  func (r *Router) Stop() error {
   142  	var err error
   143  	err = r.host.Stop()
   144  	r.Unpause()
   145  	r.Lock()
   146  	// set the isClosed to true
   147  	r.isClosed = true
   148  
   149  	// then close all connections
   150  	for _, arr := range r.connections {
   151  		// take all connections to close
   152  		for _, c := range arr {
   153  			if err := c.Close(); err != nil {
   154  				log.Lvl5(err)
   155  			}
   156  		}
   157  	}
   158  	// wait for all handleConn to finish
   159  	r.Unlock()
   160  	r.wg.Wait()
   161  
   162  	if err != nil {
   163  		return xerrors.Errorf("stopping: %v", err)
   164  	}
   165  	return nil
   166  }
   167  
   168  // Send sends to an ServerIdentity without wrapping the msg into a ProtocolMsg
   169  func (r *Router) Send(e *ServerIdentity, msg Message) (uint64, error) {
   170  	if msg == nil {
   171  		return 0, xerrors.New("Can't send nil-packet")
   172  	}
   173  
   174  	// Update the message counter with the new message about to be sent.
   175  	r.msgTraffic.updateTx(1)
   176  
   177  	// If sending to ourself, directly dispatch it
   178  	if e.ID.Equal(r.ServerIdentity.ID) {
   179  		log.Lvlf4("Sending to ourself (%s) msg: %+v", e, msg)
   180  		packet := &Envelope{
   181  			ServerIdentity: e,
   182  			MsgType:        MessageType(msg),
   183  			Msg:            msg,
   184  		}
   185  		if err := r.Dispatch(packet); err != nil {
   186  			return 0, xerrors.Errorf("Error dispatching: %s", err)
   187  		}
   188  		// Marshal the message to get its length
   189  		b, err := Marshal(msg)
   190  		if err != nil {
   191  			return 0, xerrors.Errorf("marshaling: %v", err)
   192  		}
   193  		log.Lvl5("Message sent")
   194  
   195  		return uint64(len(b)), nil
   196  	}
   197  
   198  	var totSentLen uint64
   199  	c := r.connection(e.ID)
   200  	if c == nil {
   201  		var sentLen uint64
   202  		var err error
   203  		c, sentLen, err = r.connect(e)
   204  		totSentLen += sentLen
   205  		if err != nil {
   206  			return totSentLen, xerrors.Errorf("connecting: %v", err)
   207  		}
   208  	}
   209  
   210  	log.Lvlf4("%s sends to %s msg: %+v", r.address, e, msg)
   211  	sentLen, err := c.Send(msg)
   212  	totSentLen += sentLen
   213  	if err != nil {
   214  		log.Lvl2(r.address, "Couldn't send to", e, ":", err, "trying again")
   215  		c, sentLen, err := r.connect(e)
   216  		totSentLen += sentLen
   217  		if err != nil {
   218  			return totSentLen, xerrors.Errorf("connecting: %v", err)
   219  		}
   220  		sentLen, err = c.Send(msg)
   221  		totSentLen += sentLen
   222  		if err != nil {
   223  			return totSentLen, xerrors.Errorf("connecting: %v", err)
   224  		}
   225  	}
   226  	log.Lvl5("Message sent")
   227  	return totSentLen, nil
   228  }
   229  
   230  // connect starts a new connection and launches the listener for incoming
   231  // messages.
   232  func (r *Router) connect(si *ServerIdentity) (Conn, uint64, error) {
   233  	log.Lvl3(r.address, "Connecting to", si.Address)
   234  	c, err := r.host.Connect(si)
   235  	if err != nil {
   236  		log.Lvl3("Could not connect to", si.Address, err)
   237  		return nil, 0, xerrors.Errorf("connecting: %v", err)
   238  	}
   239  	log.Lvl3(r.address, "Connected to", si.Address)
   240  	var sentLen uint64
   241  	if sentLen, err = c.Send(r.ServerIdentity); err != nil {
   242  		return nil, sentLen, xerrors.Errorf("sending: %v", err)
   243  	}
   244  
   245  	if err = r.registerConnection(si, c); err != nil {
   246  		return nil, sentLen, xerrors.Errorf("register connection: %v", err)
   247  	}
   248  
   249  	if err = r.launchHandleRoutine(si, c); err != nil {
   250  		return nil, sentLen, xerrors.Errorf("handling routine: %v", err)
   251  	}
   252  	return c, sentLen, nil
   253  
   254  }
   255  
   256  func (r *Router) removeConnection(si *ServerIdentity, c Conn) {
   257  	r.Lock()
   258  	defer r.Unlock()
   259  
   260  	var toDelete = -1
   261  	arr := r.connections[si.ID]
   262  	for i, cc := range arr {
   263  		if c == cc {
   264  			toDelete = i
   265  		}
   266  	}
   267  
   268  	if toDelete == -1 {
   269  		log.Error("Remove a connection which is not registered !?")
   270  		return
   271  	}
   272  
   273  	arr[toDelete] = arr[len(arr)-1]
   274  	arr[len(arr)-1] = nil
   275  	r.connections[si.ID] = arr[:len(arr)-1]
   276  }
   277  
   278  // triggerConnectionErrorHandlers trigger all registered connectionsErrorHandlers
   279  func (r *Router) triggerConnectionErrorHandlers(remote *ServerIdentity) {
   280  	for _, v := range r.connectionErrorHandlers {
   281  		v(remote)
   282  	}
   283  }
   284  
   285  // handleConn waits for incoming messages and calls the dispatcher for
   286  // each new message. It only quits if the connection is closed or another
   287  // unrecoverable error in the connection appears.
   288  func (r *Router) handleConn(remote *ServerIdentity, c Conn) {
   289  	defer func() {
   290  		// Clean up the connection by making sure it's closed.
   291  		if err := c.Close(); err != nil {
   292  			log.Lvl5(r.address, "having error closing conn to", remote.Address, ":", err)
   293  		}
   294  		rx, tx := c.Rx(), c.Tx()
   295  		r.traffic.updateRx(rx)
   296  		r.traffic.updateTx(tx)
   297  		r.wg.Done()
   298  		r.removeConnection(remote, c)
   299  		log.Lvl4("onet close", c.Remote(), "rx", rx, "tx", tx)
   300  	}()
   301  	address := c.Remote()
   302  	log.Lvl3(r.address, "Handling new connection from", remote.Address)
   303  	for {
   304  		packet, err := c.Receive()
   305  
   306  		// Be careful not to hold r's mutex while
   307  		// pausing, or else Unpause would deadlock.
   308  		r.Lock()
   309  		paused := r.paused
   310  		r.Unlock()
   311  		if paused != nil {
   312  			<-paused
   313  			r.Lock()
   314  			r.paused = nil
   315  			r.Unlock()
   316  			return
   317  		}
   318  
   319  		if r.Closed() {
   320  			return
   321  		}
   322  
   323  		if err != nil {
   324  			if xerrors.Is(err, ErrTimeout) {
   325  				log.Lvlf5("%s drops %s connection: timeout", r.ServerIdentity.Address, remote.Address)
   326  				r.triggerConnectionErrorHandlers(remote)
   327  				return
   328  			}
   329  
   330  			if xerrors.Is(err, ErrClosed) || xerrors.Is(err, ErrEOF) {
   331  				// Connection got closed.
   332  				log.Lvlf5("%s drops %s connection: closed", r.ServerIdentity.Address, remote.Address)
   333  				r.triggerConnectionErrorHandlers(remote)
   334  				return
   335  			}
   336  			if xerrors.Is(err, ErrUnknown) {
   337  				// The error might not be recoverable so the connection is dropped
   338  				log.Lvlf5("%v drops %v connection: unknown", r.ServerIdentity, remote)
   339  				r.triggerConnectionErrorHandlers(remote)
   340  				return
   341  			}
   342  			// Temporary error, continue.
   343  			log.Lvl3(r.ServerIdentity, "Error with connection", address, "=>", err)
   344  			continue
   345  		}
   346  
   347  		packet.ServerIdentity = remote
   348  
   349  		// Update the message counter with the new message about to be processed.
   350  		r.msgTraffic.updateRx(1)
   351  
   352  		if err := r.Dispatch(packet); err != nil {
   353  			log.Lvl3("Error dispatching:", err)
   354  		}
   355  
   356  	}
   357  }
   358  
   359  // connection returns the first connection associated with this ServerIdentity.
   360  // If no connection is found, it returns nil.
   361  func (r *Router) connection(sid ServerIdentityID) Conn {
   362  	r.Lock()
   363  	defer r.Unlock()
   364  	arr := r.connections[sid]
   365  	if len(arr) == 0 {
   366  		return nil
   367  	}
   368  	return arr[0]
   369  }
   370  
   371  // registerConnection registers a ServerIdentity for a new connection, mapped with the
   372  // real physical address of the connection and the connection itself.
   373  // It uses the networkLock mutex.
   374  func (r *Router) registerConnection(remote *ServerIdentity, c Conn) error {
   375  	log.Lvl4(r.address, "Registers", remote.Address)
   376  	r.Lock()
   377  	defer r.Unlock()
   378  	if r.isClosed {
   379  		return xerrors.Errorf("closing: %w", ErrClosed)
   380  	}
   381  	_, okc := r.connections[remote.ID]
   382  	if okc {
   383  		log.Lvl5("Connection already registered. Appending new connection to same identity.")
   384  	}
   385  	r.connections[remote.ID] = append(r.connections[remote.ID], c)
   386  	return nil
   387  }
   388  
   389  func (r *Router) launchHandleRoutine(dst *ServerIdentity, c Conn) error {
   390  	r.Lock()
   391  	defer r.Unlock()
   392  	if r.isClosed {
   393  		return xerrors.Errorf("closing: %w", ErrClosed)
   394  	}
   395  	r.wg.Add(1)
   396  	go r.handleConn(dst, c)
   397  	return nil
   398  }
   399  
   400  // Closed returns true if the router is closed (or is closing). For a router
   401  // to be closed means that a call to Stop() must have been made.
   402  func (r *Router) Closed() bool {
   403  	r.Lock()
   404  	defer r.Unlock()
   405  	return r.isClosed
   406  }
   407  
   408  // Tx implements monitor/CounterIO
   409  // It returns the Tx for all connections managed by this router
   410  func (r *Router) Tx() uint64 {
   411  	r.Lock()
   412  	defer r.Unlock()
   413  	var tx uint64
   414  	for _, arr := range r.connections {
   415  		for _, c := range arr {
   416  			tx += c.Tx()
   417  		}
   418  	}
   419  	tx += r.traffic.Tx()
   420  	return tx
   421  }
   422  
   423  // Rx implements monitor/CounterIO
   424  // It returns the Rx for all connections managed by this router
   425  func (r *Router) Rx() uint64 {
   426  	r.Lock()
   427  	defer r.Unlock()
   428  	var rx uint64
   429  	for _, arr := range r.connections {
   430  		for _, c := range arr {
   431  			rx += c.Rx()
   432  		}
   433  	}
   434  	rx += r.traffic.Rx()
   435  	return rx
   436  }
   437  
   438  // MsgTx implements monitor/CounterIO.
   439  // It returns the number of messages transmitted by the interface.
   440  func (r *Router) MsgTx() uint64 {
   441  	return r.msgTraffic.Tx()
   442  }
   443  
   444  // MsgRx implements monitor/CounterIO.
   445  // It returns the number of messages received by the interface.
   446  func (r *Router) MsgRx() uint64 {
   447  	return r.msgTraffic.Rx()
   448  }
   449  
   450  // Listening returns true if this router is started.
   451  func (r *Router) Listening() bool {
   452  	return r.host.Listening()
   453  }
   454  
   455  // receiveServerIdentity takes a fresh new conn issued by the listener and
   456  // wait for the server identities of the remote party. It returns
   457  // the ServerIdentity of the remote party and register the connection.
   458  func (r *Router) receiveServerIdentity(c Conn) (*ServerIdentity, error) {
   459  	// Receive the other ServerIdentity
   460  	nm, err := c.Receive()
   461  	if err != nil {
   462  		return nil, xerrors.Errorf("Error while receiving ServerIdentity during negotiation %s", err)
   463  	}
   464  	// Check if it is correct
   465  	if nm.MsgType != ServerIdentityType {
   466  		return nil, xerrors.Errorf("Received wrong type during negotiation %s", nm.MsgType.String())
   467  	}
   468  
   469  	// Set the ServerIdentity for this connection
   470  	dst := nm.Msg.(*ServerIdentity)
   471  
   472  	// See if we have a cryptographically proven pubkey for this peer. If so,
   473  	// check it against dst.Public.
   474  	if tcpConn, ok := c.(*TCPConn); ok {
   475  		if tlsConn, ok := tcpConn.conn.(*tls.Conn); ok {
   476  			cs := tlsConn.ConnectionState()
   477  			if len(cs.PeerCertificates) == 0 {
   478  				return nil, xerrors.New("TLS connection with no peer certs?")
   479  			}
   480  			pub, err := pubFromCN(tcpConn.suite, cs.PeerCertificates[0].Subject.CommonName)
   481  			if err != nil {
   482  				return nil, xerrors.Errorf("decoding key: %v", err)
   483  			}
   484  
   485  			if !pub.Equal(dst.Public) {
   486  				return nil, xerrors.New("mismatch between certificate CommonName and ServerIdentity.Public")
   487  			}
   488  			log.Lvl4(r.address, "Public key from CommonName and ServerIdentity match:", pub)
   489  		} else {
   490  			// We get here for TCPConn && !tls.Conn. Make them wish they were using TLS...
   491  			if !r.UnauthOk {
   492  				log.Warn("Public key", dst.Public, "from ServerIdentity not authenticated.")
   493  			}
   494  		}
   495  	}
   496  	log.Lvlf3("%s: Identity received si=%v from %s", r.address, dst.Public, dst.Address)
   497  	return dst, nil
   498  }
   499  
   500  // AddErrorHandler adds a network error handler function for this router. The functions will be called
   501  // on network error (e.g. Timeout, Connection Closed, or EOF) with the identity of the faulty
   502  // remote host as 1st parameter.
   503  func (r *Router) AddErrorHandler(errorHandler func(*ServerIdentity)) {
   504  	r.connectionErrorHandlers = append(r.connectionErrorHandlers, errorHandler)
   505  }