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 }