mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-13 11:54:46 -04:00
fix merge conflicts
This commit is contained in:
4
go.mod
4
go.mod
@ -3,7 +3,11 @@ module github.com/go-i2p/go-i2p
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/dchest/siphash v1.2.3 // indirect
|
||||
github.com/emirpasic/gods v1.18.1
|
||||
github.com/flynn/noise v1.0.0
|
||||
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||
|
24
go.sum
24
go.sum
@ -1,26 +1,33 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
|
||||
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620 h1:MjTFQi2DyJifqefRVjAs+P2gaoUAj2rcDpYX7ERggEA=
|
||||
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620/go.mod h1:y9SBFk2hEIPWY7Aj3bXG+K1xp8wWnQ6kVq2wsYSPByU=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc h1:+q90ECDSAQirdykUN6sPEiBXBsp8Csjcca8Oy7bgLTA=
|
||||
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -31,7 +38,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -115,6 +115,14 @@ func TestHasDuplicateKeysFalseWithoutDuplicates(t *testing.T) {
|
||||
assert.Equal(false, mapping.HasDuplicateKeys(), "HasDuplicateKeys() did not report false when no duplicate keys present")
|
||||
}
|
||||
|
||||
func TestReadMappingHasDuplicateKeys(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
_, _, errs := NewMapping([]byte{0x00, 0x0c, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b})
|
||||
|
||||
assert.Equal("mapping format violation, duplicate key in mapping", errs[0].Error(), "ReadMapping should throw an error when duplicate keys are present.")
|
||||
}
|
||||
|
||||
func TestGoMapToMappingProducesCorrectMapping(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
@ -30,37 +30,17 @@ func ValuesToMapping(values MappingValues) *Mapping {
|
||||
}
|
||||
}
|
||||
|
||||
type byValue MappingValues
|
||||
|
||||
func (set byValue) Len() int { return len(set) }
|
||||
func (set byValue) Swap(i, j int) { set[i], set[j] = set[j], set[i] }
|
||||
func (set byValue) Less(i, j int) bool {
|
||||
data1, _ := set[i][1].Data()
|
||||
data2, _ := set[j][1].Data()
|
||||
return data1 < data2
|
||||
}
|
||||
|
||||
type byKey MappingValues
|
||||
|
||||
func (set byKey) Len() int { return len(set) }
|
||||
func (set byKey) Swap(i, j int) { set[i], set[j] = set[j], set[i] }
|
||||
func (set byKey) Less(i, j int) bool {
|
||||
data1, _ := set[i][0].Data()
|
||||
data2, _ := set[j][0].Data()
|
||||
return data1 < data2
|
||||
}
|
||||
|
||||
//
|
||||
// I2P Mappings require consistent order for for cryptographic signing, and sorting
|
||||
// by keys. When new Mappings are created, they are stable sorted first by values
|
||||
// than by keys to ensure a consistent order.
|
||||
//
|
||||
|
||||
// TODO: This sort doesn't appear to work the same as ref implementation.
|
||||
// It also appears to be unstable
|
||||
// I2P Mappings require consistent order in some cases for cryptographic signing, and sorting
|
||||
// by keys. The Mapping is sorted lexographically by keys. Duplicate keys are allowed in general,
|
||||
// but in implementations where they must be sorted like I2CP SessionConfig duplicate keys are not allowed.
|
||||
// In practice routers do not seem to allow duplicate keys.
|
||||
func mappingOrder(values MappingValues) {
|
||||
sort.Stable(byValue(values))
|
||||
sort.Stable(byKey(values))
|
||||
sort.SliceStable(values, func(i, j int) bool {
|
||||
// Lexographic sort on keys only
|
||||
data1, _ := values[i][0].Data()
|
||||
data2, _ := values[j][0].Data()
|
||||
return data1 < data2
|
||||
})
|
||||
}
|
||||
|
||||
// ReadMappingValues returns *MappingValues from a []byte.
|
||||
@ -109,6 +89,7 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
||||
errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data"))
|
||||
}
|
||||
|
||||
encounteredKeysMap := map[string]bool{}
|
||||
// pop off length bytes before parsing kv pairs
|
||||
remainder = remainder[2:]
|
||||
|
||||
@ -140,6 +121,23 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
||||
//return
|
||||
}
|
||||
}
|
||||
|
||||
// Check if key has already been encountered in this mapping
|
||||
keyBytes, _ := key_str.Data()
|
||||
keyAsString := string(keyBytes)
|
||||
_, ok := encounteredKeysMap[keyAsString]
|
||||
if ok {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"reason": "duplicate key in mapping",
|
||||
}).Error("mapping format violation")
|
||||
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
|
||||
// Based on other implementations this does not seem to happen often?
|
||||
// Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown.
|
||||
// i2pd as far as I can tell just overwrites the original value
|
||||
// Continue on, we can check if the Mapping contains duplicate keys later.
|
||||
}
|
||||
|
||||
if !beginsWith(remainder, 0x3d) {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
@ -177,6 +175,9 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
||||
if len(remainder) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// Store the encountered key with arbitrary data
|
||||
encounteredKeysMap[keyAsString] = true
|
||||
}
|
||||
values = &map_values
|
||||
return
|
||||
|
@ -1,38 +1,46 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMappingOrderSortsValuesThenKeys(t *testing.T) {
|
||||
a, _ := ToI2PString("a")
|
||||
b, _ := ToI2PString("b")
|
||||
aa, _ := ToI2PString("aa")
|
||||
ab, _ := ToI2PString("ab")
|
||||
ac, _ := ToI2PString("ac")
|
||||
values := MappingValues{
|
||||
[2]I2PString{b, b},
|
||||
[2]I2PString{b, a},
|
||||
[2]I2PString{a, b},
|
||||
[2]I2PString{ac, a},
|
||||
[2]I2PString{ab, b},
|
||||
[2]I2PString{aa, a},
|
||||
[2]I2PString{a, a},
|
||||
}
|
||||
mappingOrder(values)
|
||||
for i, pair := range values {
|
||||
key, _ := pair[0].Data()
|
||||
value, _ := pair[1].Data()
|
||||
switch i {
|
||||
case 0:
|
||||
if !(key == "a" && value == "a") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
if !(key == "a") {
|
||||
t.Fatal(fmt.Sprintf("mappingOrder expected key a, got %s at index", key), i)
|
||||
}
|
||||
case 1:
|
||||
if !(key == "a" && value == "b") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
if !(key == "aa") {
|
||||
t.Fatal(fmt.Sprintf("mappingOrder expected key aa, got %s at index", key), i)
|
||||
}
|
||||
case 2:
|
||||
if !(key == "b" && value == "a") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
if !(key == "ab") {
|
||||
t.Fatal(fmt.Sprintf("mappingOrder expected key ab, got %s at index", key), i)
|
||||
}
|
||||
case 3:
|
||||
if !(key == "b" && value == "b") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
if !(key == "ac") {
|
||||
t.Fatal(fmt.Sprintf("mappingOrder expected key ac, got %s at index", key), i)
|
||||
}
|
||||
case 4:
|
||||
if !(key == "b") {
|
||||
t.Fatal(fmt.Sprintf("mappingOrder expected key b, got %s at index", key), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
123
lib/transport/noise/client_handshake.go
Normal file
123
lib/transport/noise/client_handshake.go
Normal file
@ -0,0 +1,123 @@
|
||||
package noise
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/flynn/noise"
|
||||
)
|
||||
|
||||
func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
|
||||
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
|
||||
|
||||
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
|
||||
|
||||
}
|
||||
var pattern noise.HandshakePattern
|
||||
negData = make([]byte, 6)
|
||||
copy(negData, negotiationData)
|
||||
pattern = noise.HandshakeIK
|
||||
negData[5] = NOISE_PATTERN_IK
|
||||
var random io.Reader
|
||||
if len(ePrivate) == 0 {
|
||||
random = rand.Reader
|
||||
} else {
|
||||
random = bytes.NewBuffer(ePrivate)
|
||||
}
|
||||
prologue := make([]byte, 2, uint16Size+len(negData))
|
||||
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
|
||||
prologue = append(prologue, negData...)
|
||||
prologue = append(initString, prologue...)
|
||||
state, err = noise.NewHandshakeState(noise.Config{
|
||||
StaticKeypair: s,
|
||||
Initiator: true,
|
||||
Pattern: pattern,
|
||||
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherAESGCM, noise.HashBLAKE2b),
|
||||
PeerStatic: rs,
|
||||
Prologue: prologue,
|
||||
Random: random,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
padBuf := make([]byte, 2+len(payload))
|
||||
copy(padBuf[2:], payload)
|
||||
msg, _, _, err = state.WriteMessage(msg, padBuf)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *NoiseSession) RunClientHandshake() error {
|
||||
var (
|
||||
negData, msg []byte
|
||||
state *noise.HandshakeState
|
||||
err error
|
||||
)
|
||||
if negData, msg, state, err = ComposeInitiatorHandshakeMessage(c.StaticKey, nil, nil, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = c.Write(negData); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = c.Write(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
//read negotiation data
|
||||
/*if err := c.readPacket(); err != nil {
|
||||
return err
|
||||
}
|
||||
negotiationData := c.handshakeBuffer.Next(c.handshakeBuffer.Len())
|
||||
//read noise message
|
||||
if err := c.readPacket(); err != nil {
|
||||
return err
|
||||
}
|
||||
msg = c.handshakeBuffer.Next(c.handshakeBuffer.Len())
|
||||
if len(negotiationData) != 0 || len(msg) == 0 {
|
||||
return errors.New("Server returned error")
|
||||
}
|
||||
// cannot reuse msg for read, need another buf
|
||||
inBlock := c.NoiseTransport.newBlock()
|
||||
inBlock.reserve(len(msg))*/
|
||||
var payload int
|
||||
payload, c.CipherState, c.NoiseTransport.CipherState, err = state.ReadMessage(inBlock.data, msg)
|
||||
/*if err != nil {
|
||||
c.NoiseTransport.freeBlock(inBlock)
|
||||
return err
|
||||
}*/
|
||||
err = c.processCallback(state.PeerStatic(), payload)
|
||||
if err != nil {
|
||||
c.NoiseTransport.freeBlock(inBlock)
|
||||
return err
|
||||
}
|
||||
/*c.NoiseTransport.freeBlock(inBlock)
|
||||
if c.CipherState == nil && c.NoiseTransport.CipherState == nil {
|
||||
b := c.newBlock()
|
||||
if b.data, c.CipherState, c.NoiseTransport.CipherState, err = state.WriteMessage(b.data, pad(c.config.Payload)); err != nil {
|
||||
c.freeBlock(b)
|
||||
return err
|
||||
}
|
||||
if _, err = c.Write(nil); err != nil {
|
||||
c.freeBlock(b)
|
||||
return err
|
||||
}
|
||||
if _, err = c.Write(b.data); err != nil {
|
||||
c.freeBlock(b)
|
||||
return err
|
||||
}
|
||||
c.freeBlock(b)
|
||||
if c.CipherState == nil || c.NoiseTransport.CipherState == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(NoiseSession) RunClientHandshake",
|
||||
"reason": "unsupported session",
|
||||
}).Error("unsupported session")
|
||||
return errors.New("unsupported session")
|
||||
}
|
||||
}
|
||||
*/
|
||||
//c.in.padding, c.out.padding = c.config.Padding, c.config.Padding
|
||||
//c.channelBinding = state.ChannelBinding()
|
||||
c.handshakeComplete = true
|
||||
return nil
|
||||
}
|
75
lib/transport/noise/client_session.go
Normal file
75
lib/transport/noise/client_session.go
Normal file
@ -0,0 +1,75 @@
|
||||
package noise
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (c *NoiseSession) Write(b []byte) (int, error) {
|
||||
// interlock with Close below
|
||||
for {
|
||||
x := atomic.LoadInt32(&c.activeCall)
|
||||
if x&1 != 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(NoiseSession) Write",
|
||||
"reason": "session is closed",
|
||||
}).Error("session is closed")
|
||||
return 0, errors.New("session is closed")
|
||||
}
|
||||
if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
|
||||
defer atomic.AddInt32(&c.activeCall, -2)
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := c.RunClientHandshake(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
if !c.handshakeComplete {
|
||||
return 0, errors.New("internal error")
|
||||
}
|
||||
n, err := c.writePacketLocked(b)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (c *NoiseSession) writePacketLocked(data []byte) (int, error) {
|
||||
var n int
|
||||
if len(data) == 0 { //special case to answer when everything is ok during handshake
|
||||
if _, err := c.Conn.Write(make([]byte, 2)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
for len(data) > 0 {
|
||||
/*m := len(data)
|
||||
packet := c.InitializePacket()
|
||||
maxPayloadSize := c.maxPayloadSizeForWrite(packet)
|
||||
if m > int(maxPayloadSize) {
|
||||
m = int(maxPayloadSize)
|
||||
}
|
||||
if c.CipherState != nil {
|
||||
////fmt.Println("writing encrypted packet:", m)
|
||||
packet.reserve(uint16Size + uint16Size + m + macSize)
|
||||
packet.resize(uint16Size + uint16Size + m)
|
||||
copy(packet.data[uint16Size+uint16Size:], data[:m])
|
||||
binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m))
|
||||
//fmt.Println("encrypt size", uint16(m))
|
||||
} else {
|
||||
packet.resize(len(packet.data) + len(data))
|
||||
copy(packet.data[uint16Size:len(packet.data)], data[:m])
|
||||
binary.BigEndian.PutUint16(packet.data, uint16(len(data)))
|
||||
}
|
||||
b := c.encryptIfNeeded(packet)
|
||||
c.freeBlock(packet)
|
||||
////fmt.Println(hex.EncodeToString(b))
|
||||
if _, err := c.conn.Write(b); err != nil {
|
||||
return n, err
|
||||
}
|
||||
n += m
|
||||
data = data[m:]
|
||||
*/
|
||||
}
|
||||
return n, nil
|
||||
}
|
41
lib/transport/noise/handshake.go
Normal file
41
lib/transport/noise/handshake.go
Normal file
@ -0,0 +1,41 @@
|
||||
package noise
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_info"
|
||||
)
|
||||
|
||||
func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
session, err := c.GetSession(routerInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
if session.(*NoiseSession).handshakeComplete {
|
||||
return nil
|
||||
}
|
||||
if session.(*NoiseSession).Cond == nil {
|
||||
break
|
||||
}
|
||||
session.(*NoiseSession).Cond.Wait()
|
||||
}
|
||||
// Set handshakeCond to indicate that this goroutine is committing to
|
||||
// running the handshake.
|
||||
session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex)
|
||||
c.Mutex.Unlock()
|
||||
session.(*NoiseSession).Mutex.Lock()
|
||||
defer session.(*NoiseSession).Mutex.Unlock()
|
||||
c.Mutex.Lock()
|
||||
// if c.config.isClient {
|
||||
if err := session.(*NoiseSession).RunClientHandshake(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Wake any other goroutines that are waiting for this handshake to
|
||||
// complete.
|
||||
session.(*NoiseSession).Cond.Broadcast()
|
||||
session.(*NoiseSession).Cond = nil
|
||||
return nil
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package noise
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
cb "github.com/emirpasic/gods/queues/circularbuffer"
|
||||
"github.com/flynn/noise"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_info"
|
||||
@ -15,10 +19,47 @@ import (
|
||||
type NoiseSession struct {
|
||||
*cb.Queue
|
||||
router_info.RouterInfo
|
||||
net.Conn
|
||||
*noise.CipherState
|
||||
sync.Mutex
|
||||
*sync.Cond
|
||||
*NoiseTransport
|
||||
handshakeBuffer bytes.Buffer
|
||||
activeCall int32
|
||||
handshakeComplete bool
|
||||
Conn net.Conn
|
||||
}
|
||||
|
||||
// Read implements net.Conn
|
||||
func (*NoiseSession) Read(b []byte) (n int, err error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// RemoteAddr implements net.Conn
|
||||
func (*NoiseSession) RemoteAddr() net.Addr {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// SetDeadline implements net.Conn
|
||||
func (*NoiseSession) SetDeadline(t time.Time) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// SetReadDeadline implements net.Conn
|
||||
func (*NoiseSession) SetReadDeadline(t time.Time) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// SetWriteDeadline implements net.Conn
|
||||
func (*NoiseSession) SetWriteDeadline(t time.Time) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var exampleNoiseSession transport.TransportSession = &NoiseSession{}
|
||||
var ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession)
|
||||
|
||||
func (s *NoiseSession) LocalAddr() net.Addr {
|
||||
return s.Conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) {
|
||||
s.Queue.Enqueue(msg)
|
||||
|
@ -8,9 +8,10 @@ package noise
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/flynn/noise"
|
||||
"github.com/go-i2p/go-i2p/lib/common/data"
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_identity"
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_info"
|
||||
@ -19,13 +20,32 @@ import (
|
||||
)
|
||||
|
||||
type NoiseTransport struct {
|
||||
routerIdentity router_identity.RouterIdentity
|
||||
*noise.CipherState
|
||||
router_identity.RouterIdentity
|
||||
sync.Mutex
|
||||
Listener net.Listener
|
||||
peerConnections map[data.Hash]transport.TransportSession
|
||||
<<<<<<< HEAD
|
||||
netSocket net.Listener
|
||||
=======
|
||||
>>>>>>> 8d631239b7559bf5f65b5e1e6872219d156efa8b
|
||||
}
|
||||
|
||||
var exampleNoiseTransport transport.Transport = &NoiseTransport{}
|
||||
|
||||
// ExampleNoiseListener is not a real Noise Listener, do not use it.
|
||||
// It is exported so that it can be confirmed that the transport
|
||||
// implements net.Listener
|
||||
var ExampleNoiseListener net.Listener = exampleNoiseTransport
|
||||
|
||||
func (noopt *NoiseTransport) Accept() (net.Conn, error) {
|
||||
return noopt.Listener.Accept()
|
||||
}
|
||||
|
||||
func (noopt *NoiseTransport) Addr() net.Addr {
|
||||
return noopt.Listener.Addr()
|
||||
}
|
||||
|
||||
func (noopt *NoiseTransport) Name() string {
|
||||
return "noise"
|
||||
}
|
||||
@ -52,7 +72,6 @@ func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) (
|
||||
// returns an established TransportSession and nil on success
|
||||
// returns nil and an error on error
|
||||
func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
|
||||
var err error
|
||||
hash := routerInfo.IdentHash()
|
||||
if len(hash) == 0 {
|
||||
return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash")
|
||||
@ -60,10 +79,13 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran
|
||||
if t, ok := noopt.peerConnections[hash]; ok {
|
||||
return t, nil
|
||||
}
|
||||
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil {
|
||||
return noopt.peerConnections[hash], err
|
||||
conn, err := noopt.Accept()
|
||||
if err == nil {
|
||||
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo, conn); err != nil {
|
||||
return noopt.peerConnections[hash], err
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Unable to obtain transport session with %s", routerInfo.IdentHash())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Compatable return true if a routerInfo is compatable with this transport
|
||||
@ -83,7 +105,7 @@ func (noopt *NoiseTransport) Close() error {
|
||||
func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
|
||||
return &NoiseTransport{
|
||||
peerConnections: make(map[data.Hash]transport.TransportSession),
|
||||
netSocket: netSocket,
|
||||
Listener: netSocket,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_identity"
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_info"
|
||||
|
||||
@ -23,6 +25,11 @@ type TransportSession interface {
|
||||
}
|
||||
|
||||
type Transport interface {
|
||||
// Accept accepts an incoming session.
|
||||
Accept() (net.Conn, error)
|
||||
|
||||
// Addr returns an
|
||||
Addr() net.Addr
|
||||
|
||||
// Set the router identity for this transport.
|
||||
// will bind if the underlying socket is not already
|
||||
|
Reference in New Issue
Block a user