// Performs handling of all Change Request Protocol messages, // over all connections. Has exclusive access to forward timeout information, // and uses requestTimeoutLock for access to request timeout information. // Top-level function of the processing goroutine. func process() { for { select { // Requesting Change Request Timeout case timeout := <-requestTimedOut: requestTimeoutLock.Lock() if timeout.canceled { break } log.Print("shared/chrequest: request timeout: ", *timeout.request.RequestId) // Remove this request timeout. cancelRequestTimeout( uint16(*timeout.request.RequestNode), *timeout.request.RequestId) // Request the change again, with double the timeout. addRequestTimeout(timeout.request, timeout.duration*2) requestTimeoutLock.Unlock() forward := new(chproto.ChangeForward) forward.Request = timeout.request processForward(forward) // Forwarded Change Forward Timeout case timeout := <-forwardTimedOut: if timeout.canceled { break } // Remove this forward timeout. cancelForwardTimeout( uint16(*timeout.forward.Request.RequestNode), *timeout.forward.Request.RequestId) // Try sending it somewhere else. processForward(timeout.forward) // New Change Request case newRequest := <-newRequestCh: requestTimeoutLock.Lock() addRequestTimeout(newRequest, config.CHANGE_TIMEOUT_PERIOD) requestTimeoutLock.Unlock() forward := new(chproto.ChangeForward) forward.Request = newRequest processForward(forward) // Received Change Forward Message case receivedForward := <-receivedForwardCh: processForward(receivedForward.forward) // Received Change Forward Ack Message case receivedAck := <-receivedAckCh: ack := receivedAck.ack // If we did not have a forwarded change forward, // with this requesting node and request ID, // and this node as the last node it was sent to, // discard the message. timeout, exists := getForwardTimeout( uint16(*ack.RequestNode), *ack.RequestId) if !exists { break } ignores := timeout.forward.Ignores if uint16(ignores[len(ignores)-1]) != receivedAck.node { break } // Remove this forward timeout. cancelForwardTimeout( uint16(*timeout.forward.Request.RequestNode), *timeout.forward.Request.RequestId) // Connection Terminated case terminatedConn := <-terminatedConnCh: node := terminatedConn.node conn := terminatedConn.conn // Remove this connection from our connection list. index := -1 for i, _ := range connections[node] { if conn == connections[node][i] { index = i break } } if index == -1 { break } connections[node] = append(connections[node][:index], connections[node][index+1:]...) // Connection Received case receivedConn := <-receivedConnCh: node := receivedConn.node conn := receivedConn.conn // Add to our connections list. connections[node] = append(connections[node], conn) } } }