func (res *protocolIntroResults) doIntroV2(params protocolIntroParams, pubKey, privKey *[32]byte) error {
	// Public key exchange
	var wbuf []byte
	if pubKey == nil {
		wbuf = []byte{0}
	} else {
		wbuf = make([]byte, 1+len(*pubKey))
		wbuf[0] = 1
		copy(wbuf[1:], (*pubKey)[:])
	}

	// Write in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	writeDone := make(chan error, 1)
	go func() {
		_, err := params.Conn.Write(wbuf)
		writeDone <- err
	}()

	rbuf := make([]byte, 1)
	if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
		return err
	}

	switch rbuf[0] {
	case 0:
		if pubKey != nil {
			return errExpectedCrypto
		}

		res.Sender = newLengthPrefixTCPSender(params.Conn)
		res.Receiver = newLengthPrefixTCPReceiver(params.Conn)

	case 1:
		if pubKey == nil {
			return errExpectedNoCrypto
		}

		rbuf = make([]byte, len(pubKey))
		if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
			return err
		}

		res.Sender = newLengthPrefixTCPSender(params.Conn)
		res.Receiver = newLengthPrefixTCPReceiver(params.Conn)
		res.setupCrypto(params, rbuf, privKey)

	default:
		return fmt.Errorf("Bad encryption flag %d", rbuf[0])
	}

	if err := <-writeDone; err != nil {
		return err
	}

	// Features exchange
	go func() {
		buf := new(bytes.Buffer)
		if err := gob.NewEncoder(buf).Encode(&params.Features); err != nil {
			writeDone <- err
			return
		}

		writeDone <- res.Sender.Send(buf.Bytes())
	}()

	rbuf, err := res.Receiver.Receive()
	if err != nil {
		return err
	}

	if err := gob.NewDecoder(bytes.NewReader(rbuf)).Decode(&res.Features); err != nil {
		return err
	}

	if err := <-writeDone; err != nil {
		return err
	}

	return nil
}
func (res *protocolIntroResults) doIntroV2(params protocolIntroParams, pubKey, privKey *[32]byte) error {
	
	var wbuf []byte
	if pubKey == nil {
		wbuf = []byte{0}
	} else {
		wbuf = make([]byte, 1+len(*pubKey))
		wbuf[0] = 1
		copy(wbuf[1:], (*pubKey)[:])
	}

	
	
	
	
	writeDone := make(chan error, 1)
	go func() {
		_, err := params.Conn.Write(wbuf)
		writeDone <- err
	}()

	rbuf := make([]byte, 1)
	if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
		return err
	}

	switch rbuf[0] {
	case 0:
		if pubKey != nil {
			return errExpectedCrypto
		}

		res.Sender = newLengthPrefixTCPSender(params.Conn)
		res.Receiver = newLengthPrefixTCPReceiver(params.Conn)

	case 1:
		if pubKey == nil {
			return errExpectedNoCrypto
		}

		rbuf = make([]byte, len(pubKey))
		if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
			return err
		}

		res.Sender = newLengthPrefixTCPSender(params.Conn)
		res.Receiver = newLengthPrefixTCPReceiver(params.Conn)
		res.setupCrypto(params, rbuf, privKey)

	default:
		return fmt.Errorf("Bad encryption flag %d", rbuf[0])
	}

	if err := <-writeDone; err != nil {
		return err
	}

	
	go func() {
		buf := new(bytes.Buffer)
		if err := gob.NewEncoder(buf).Encode(&params.Features); err != nil {
			writeDone <- err
			return
		}

		writeDone <- res.Sender.Send(buf.Bytes())
	}()

	rbuf, err := res.Receiver.Receive()
	if err != nil {
		return err
	}

	if err := gob.NewDecoder(bytes.NewReader(rbuf)).Decode(&res.Features); err != nil {
		return err
	}

	if err := <-writeDone; err != nil {
		return err
	}

	return nil
}
func ( res * protocolIntroResults ) doIntroV2 ( params protocolIntroParams , pubKey , privKey * [ 32 ] byte ) error { // Public key exchange var wbuf [ ] byte if pubKey == nil { wbuf = [ ] byte { 0 } } else { wbuf = make ( [ ] byte , 1 + len ( * pubKey ) ) wbuf [ 0 ] = 1 copy ( wbuf [ 1 : ] , ( * pubKey ) [ : ] ) } // Write in a separate goroutine to avoid the possibility of // deadlock.  The result channel is of size 1 so that the // goroutine does not linger even if we encounter an error on // the read side. writeDone := make ( chan error , 1 ) go func ( ) { _ , err := params . Conn . Write ( wbuf ) writeDone <- err } ( ) rbuf := make ( [ ] byte , 1 ) if _ , err := io . ReadFull ( params . Conn , rbuf ) ; err != nil { return err } switch rbuf [ 0 ] { case 0 : if pubKey != nil { return errExpectedCrypto } res . Sender = newLengthPrefixTCPSender ( params . Conn ) res . Receiver = newLengthPrefixTCPReceiver ( params . Conn ) case 1 : if pubKey == nil { return errExpectedNoCrypto } rbuf = make ( [ ] byte , len ( pubKey ) ) if _ , err := io . ReadFull ( params . Conn , rbuf ) ; err != nil { return err } res . Sender = newLengthPrefixTCPSender ( params . Conn ) res . Receiver = newLengthPrefixTCPReceiver ( params . Conn ) res . setupCrypto ( params , rbuf , privKey ) default : return fmt . Errorf ( " " , rbuf [ 0 ] ) } if err := <- writeDone ; err != nil { return err } // Features exchange go func ( ) { buf := new ( bytes . Buffer ) if err := gob . NewEncoder ( buf ) . Encode ( & params . Features ) ; err != nil { writeDone <- err return } writeDone <- res . Sender . Send ( buf . Bytes ( ) ) } ( ) rbuf , err := res . Receiver . Receive ( ) if err != nil { return err } if err := gob . NewDecoder ( bytes . NewReader ( rbuf ) ) . Decode ( & res . Features ) ; err != nil { return err } if err := <- writeDone ; err != nil { return err } return nil }
// The V2 procotol consists of the protocol identification/version
// header, followed by:
//
// - A single "encryption flag" byte: 0 for no encryption, 1 for
// encryption.
//
// - When the connection is encrypted, 32 bytes follow containing the
// public key.
//
// - Then a stream of length-prefixed messages, which are encrypted
// for an encrypted connection.
//
// The first message contains the encoded features map (so in contrast
// to V1, it will be encrypted on an encrypted connection).
The V2 procotol consists of the protocol identification / version header followed by : - A single encryption flag byte : 0 for no encryption 1 for encryption . - When the connection is encrypted 32 bytes follow containing the public key . - Then a stream of length - prefixed messages which are encrypted for an encrypted connection . The first message contains the encoded features map ( so in contrast to V1 it will be encrypted on an encrypted connection ) .