func (p *PeerImpl) chatWithPeer(peerAddress string) error { if len(peerAddress) == 0 { peerLogger.Debug("Starting up the first peer") return nil // nothing to do } for { time.Sleep(1 * time.Second) peerLogger.Debug("Initiating Chat with peer address: %s", peerAddress) conn, err := NewPeerClientConnectionWithAddress(peerAddress) if err != nil { e := fmt.Errorf("Error creating connection to peer address=%s: %s", peerAddress, err) peerLogger.Error(e.Error()) continue } serverClient := pb.NewPeerClient(conn) ctx := context.Background() stream, err := serverClient.Chat(ctx) if err != nil { e := fmt.Errorf("Error establishing chat with peer address=%s: %s", peerAddress, err) peerLogger.Error("%s", e.Error()) continue } peerLogger.Debug("Established Chat with peer address: %s", peerAddress) p.handleChat(ctx, stream, true) stream.CloseSend() } }
// SendTransactionsToPeer current temporary mechanism of forwarding transactions to the configured Validator. func sendTransactionsToThisPeer(peerAddress string, transaction *pb.Transaction) *pb.Response { conn, err := NewPeerClientConnectionWithAddress(peerAddress) if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transactions to peer address=%s: %s", peerAddress, err))} } serverClient := pb.NewPeerClient(conn) stream, err := serverClient.Chat(context.Background()) if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transactions to peer address=%s: %s", peerAddress, err))} } defer stream.CloseSend() peerLogger.Debug("Sending transaction %s to self", transaction.Type) data, err := proto.Marshal(transaction) if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transaction to local peer: %s", err))} } var ttyp pb.OpenchainMessage_Type if transaction.Type == pb.Transaction_CHAINCODE_EXECUTE || transaction.Type == pb.Transaction_CHAINCODE_NEW { ttyp = pb.OpenchainMessage_CHAIN_TRANSACTION } else { ttyp = pb.OpenchainMessage_CHAIN_QUERY } msg := &pb.OpenchainMessage{Type: ttyp, Payload: data, Timestamp: util.CreateUtcTimestamp()} peerLogger.Debug("Sending message %s with timestamp %v to self", msg.Type, msg.Timestamp) stream.Send(msg) waitc := make(chan struct{}) var response *pb.Response go func() { // Make sure to close the wait channel defer close(waitc) for { in, err := stream.Recv() if err == io.EOF { // read done. response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transactions to this peer, received EOF when expecting %s", pb.OpenchainMessage_DISC_HELLO))} return } if err != nil { response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Unexpected error receiving on stream from peer (%s): %s", peerAddress, err))} return } if in.Type == pb.OpenchainMessage_RESPONSE { peerLogger.Debug("Received %s message as expected, exiting out of receive loop", in.Type) response = &pb.Response{} err = proto.Unmarshal(in.Payload, response) if err != nil { response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error unpacking Payload from %s message: %s", pb.OpenchainMessage_CONSENSUS, err))} } return } peerLogger.Debug("Got unexpected message %s, with bytes length = %d, doing nothing", in.Type, len(in.Payload)) response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Got unexpected message %s, with bytes length = %d, doing nothing", in.Type, len(in.Payload)))} return } }() <-waitc return response }
func performChat(t testing.TB, conn *grpc.ClientConn) error { serverClient := pb.NewPeerClient(conn) stream, err := serverClient.Chat(context.Background()) if err != nil { t.Logf("%v.performChat(_) = _, %v", serverClient, err) return err } defer stream.CloseSend() t.Log("Starting performChat") waitc := make(chan struct{}) go func() { // Be sure to close the channel defer close(waitc) for { in, err := stream.Recv() if err == io.EOF { t.Logf("Received EOR, exiting chat") return } if err != nil { t.Errorf("stream closed with unexpected error: %s", err) return } if in.Type == pb.OpenchainMessage_DISC_HELLO { t.Logf("Received message: %s, sending %s", in.Type, pb.OpenchainMessage_DISC_GET_PEERS) stream.Send(&pb.OpenchainMessage{Type: pb.OpenchainMessage_DISC_GET_PEERS}) } else if in.Type == pb.OpenchainMessage_DISC_PEERS { //stream.Send(&pb.DiscoveryMessage{Type: pb.DiscoveryMessage_PEERS}) t.Logf("Received message: %s", in.Type) t.Logf("Closing stream and channel") return } else { t.Logf("Received message: %s", in.Type) } } }() select { case <-waitc: return nil case <-time.After(1 * time.Second): t.Fail() return fmt.Errorf("Timeout expired while performChat") } }
// SendTransactionsToPeer current temporary mechanism of forwarding transactions to the configured Validator. func (p *PeerImpl) SendTransactionsToPeer(peerAddress string, transaction *pb.Transaction) *pb.Response { conn, err := NewPeerClientConnectionWithAddress(peerAddress) if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error creating client to peer address=%s: %s", peerAddress, err))} } defer conn.Close() serverClient := pb.NewPeerClient(conn) stream, err := serverClient.Chat(context.Background()) if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error opening chat stream to peer address=%s: %s", peerAddress, err))} } peerLogger.Debug("Sending HELLO to Peer: %s", peerAddress) helloMessage, err := p.NewOpenchainDiscoveryHello() if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Unexpected error creating new HelloMessage (%s): %s", peerAddress, err))} } if err = stream.Send(helloMessage); err != nil { stream.CloseSend() return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending hello to peer address=%s: %s", peerAddress, err))} } waitc := make(chan struct{}) var response *pb.Response go func() { // Make sure to close the wait channel defer close(waitc) expectHello := true for { in, err := stream.Recv() if err == io.EOF { peerLogger.Debug("Received EOF") // read done. if response == nil { response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transactions to peer address=%s, received EOF when expecting %s", peerAddress, pb.OpenchainMessage_DISC_HELLO))} } return } if err != nil { response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Unexpected error receiving on stream from peer (%s): %s", peerAddress, err))} return } if in.Type == pb.OpenchainMessage_DISC_HELLO { expectHello = false peerLogger.Debug("Received %s message as expected, sending transaction...", in.Type) payload, err := proto.Marshal(transaction) if err != nil { response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error marshalling transaction to peer address=%s: %s", peerAddress, err))} return } var ttyp pb.OpenchainMessage_Type if transaction.Type == pb.Transaction_CHAINCODE_EXECUTE || transaction.Type == pb.Transaction_CHAINCODE_NEW { ttyp = pb.OpenchainMessage_CHAIN_TRANSACTION } else { ttyp = pb.OpenchainMessage_CHAIN_QUERY } msg := &pb.OpenchainMessage{Type: ttyp, Payload: payload, Timestamp: util.CreateUtcTimestamp()} peerLogger.Debug("Sending message %s with timestamp %v to Peer %s", msg.Type, msg.Timestamp, peerAddress) if err = stream.Send(msg); err != nil { peerLogger.Error(fmt.Sprintf("Error sending message %s with timestamp %v to Peer %s: %s", msg.Type, msg.Timestamp, peerAddress, err)) } //we are done with all our sends.... trigger stream close stream.CloseSend() } else if in.Type == pb.OpenchainMessage_RESPONSE { peerLogger.Debug("Received %s message as expected, will wait for EOF", in.Type) response = &pb.Response{} err = proto.Unmarshal(in.Payload, response) if err != nil { response = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error unpacking Payload from %s message: %s", pb.OpenchainMessage_CONSENSUS, err))} } //this should never happen but has to be tested (perhaps panic ?). //if we did get an out-of-band Response, CloseSend as we may not get a DISC_HELLO if expectHello { peerLogger.Error(fmt.Sprintf("Received unexpected %s message, will wait for EOF", in.Type)) stream.CloseSend() } } else { peerLogger.Debug("Got unexpected message %s, with bytes length = %d, doing nothing", in.Type, len(in.Payload)) } } }() //TODO Timeout handling <-waitc return response }