示例#1
0
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()
	}
}
示例#2
0
// 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
}
示例#3
0
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")
	}
}
示例#4
0
// 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
}