Skip to content

Commit

Permalink
The whole thing compiles now, writing tests and fixing bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
wkoomson committed Mar 11, 2018
1 parent d9ca45d commit 15798f4
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 83 deletions.
37 changes: 21 additions & 16 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ type RouterInfo struct {

type Client struct {
logger *LoggerCallbacks // TODO idk wat this is for
callbacks ClientCallBacks
callbacks *ClientCallBacks
properties [NR_OF_I2CP_CLIENT_PROPERTIES]string
tcp *Tcp
tcp Tcp
outputStream *Stream
messageStream *Stream
router RouterInfo
Expand All @@ -98,17 +98,18 @@ type Client struct {
var defaultConfigFile = "/.i2cp.conf"

// NewClient creates a new i2p client with the specified callbacks
func NewClient(callbacks ClientCallBacks) (c *Client) {
func NewClient(callbacks *ClientCallBacks) (c *Client) {
c = new(Client)
c.callbacks = callbacks
LogInit(nil, ERROR)
c.outputStream = bytes.NewBuffer(make([]byte, 0, I2CP_MESSAGE_SIZE))
c.messageStream = bytes.NewBuffer(make([]byte, 0, I2CP_MESSAGE_SIZE))
c.outputStream = NewStream(make([]byte, 0, I2CP_MESSAGE_SIZE))
c.messageStream = NewStream(make([]byte, 0, I2CP_MESSAGE_SIZE))
c.setDefaultProperties()
c.lookup = make(map[string]uint32, 1000)
c.lookupReq = make(map[uint32]LookupEntry, 1000)
c.sessions = make(map[uint16]*Session)
c.outputQueue = make([]*Stream, 0)
c.tcp.Init()
return
}

Expand Down Expand Up @@ -267,20 +268,21 @@ func (c *Client) onMsgPayload(stream *Stream) {
var protocol uint8
var sessionId, srcPort, destPort uint16
var messageId, payloadSize uint32
var out Stream
var err error
var ret int
Debug(TAG|PROTOCOL, "Received PayloadMessage message")
sessionId, err = stream.ReadUint16()
messageId, err = stream.ReadUint32()
_ = messageId // currently unused
session, ok := c.sessions[sessionId]
if !ok {
Fatal(TAG|FATAL, "Session id %d does not match any of our currently initiated sessions by %p", sessionId, c)
}
payloadSize, err = stream.ReadUint32()
_ = payloadSize // currently unused
// validate gzip header
var msgStream = bytes.NewBuffer(stream.Bytes())
ret, err = stream.Read(testHeader[:])
_, err = stream.Read(testHeader[:])
if testHeader != gzipHeader {
Warning(TAG, "Payload validation failed, skipping payload")
return
Expand All @@ -298,9 +300,10 @@ func (c *Client) onMsgPayload(stream *Stream) {
destPort, err = stream.ReadUint16()
_, err = stream.ReadByte()
protocol, err = stream.ReadByte()
session.dispatchMessage(protocol, srcPort, destPort, payload)
session.dispatchMessage(protocol, srcPort, destPort, &Stream{payload})
}

_ = err // currently unused
_ = ret // currently unused
}
func (c *Client) onMsgStatus(stream *Stream) {
var status uint8
Expand All @@ -313,6 +316,7 @@ func (c *Client) onMsgStatus(stream *Stream) {
status, err = stream.ReadByte()
size, err = stream.ReadUint32()
nonce, err = stream.ReadUint32()
_ = err // currently unused
Debug(TAG|PROTOCOL, "Message status; session id %d, message id %d, status %d, size %d, nonce %d", sessionId, messageId, status, size, nonce)
}
func (c *Client) onMsgDestReply(stream *Stream) {
Expand Down Expand Up @@ -354,7 +358,8 @@ func (c *Client) onMsgSessionStatus(stream *Stream) {
Debug(TAG|PROTOCOL, "Received SessionStatus message.")
sessionID, err = stream.ReadUint16()
sessionStatus, err = stream.ReadByte()
if sessionStatus == I2CP_SESSION_STATUS_CREATED {
_ = err // currently unused
if SessionStatus(sessionStatus) == I2CP_SESSION_STATUS_CREATED {
if c.currentSession == nil {
Error(TAG, "Received session status created without waiting for it %p", c)
return
Expand All @@ -367,11 +372,10 @@ func (c *Client) onMsgSessionStatus(stream *Stream) {
if sess == nil {
Fatal(TAG|FATAL, "Session with id %d doesn't exists in client instance %p.", sessionID, c)
} else {
sess.dispatchStatus(sessionStatus)
sess.dispatchStatus(SessionStatus(sessionStatus))
}
}
func (c *Client) onMsgReqVariableLease(stream *Stream) {
var t int
var sessionId uint16
var tunnels uint8
var sess *Session
Expand All @@ -386,9 +390,10 @@ func (c *Client) onMsgReqVariableLease(stream *Stream) {
}
leases = make([]*Lease, tunnels)
for i := uint8(0); i < tunnels; i++ {
leases[i] = NewLeaseFromStream(stream)
leases[i], err = NewLeaseFromStream(stream)
}
c.msgCreateLeaseSet(sess, tunnels, leases, true)
_ = err // currently unused
}
func (c *Client) onMsgHostReply(stream *Stream) {
var result uint8
Expand All @@ -407,6 +412,7 @@ func (c *Client) onMsgHostReply(stream *Stream) {
if err != nil {
Fatal(TAG|FATAL, "Failed to construct destination from stream.")
}
dest = &dst
}
sess = c.sessions[sessionId]
if sess == nil {
Expand All @@ -415,6 +421,7 @@ func (c *Client) onMsgHostReply(stream *Stream) {
lup = c.lookupReq[requestId]
delete(c.lookupReq, requestId)
sess.dispatchDestination(requestId, lup.address, dest)
_ = err // currently unused
}

func (c *Client) configFileParseCallback(name, value string) {
Expand Down Expand Up @@ -571,7 +578,6 @@ func (c *Client) Connect() {
}

func (c *Client) CreateSession(sess *Session) {
var config *SessionConfig
if c.n_sessions == I2CP_MAX_SESSIONS_PER_CLIENT {
Warning(TAG, "Maximum number of session per client connection reached.")
return
Expand Down Expand Up @@ -621,8 +627,7 @@ func (c *Client) DestinationLookup(session *Session, address string) (requestId
Debug(TAG, "Lookup of b32 address detected, decode and use hash for faster lookup.")
host := address[:strings.Index(address, ".")]
in.Write([]byte(host))
dout, _ := GetCryptoInstance().DecodeStream(CODEC_BASE32, in)
out = &dout
out, _ = GetCryptoInstance().DecodeStream(CODEC_BASE32, in)
if out.Len() == 0 {
Warning(TAG, "Failed to decode hash of address '%s'", address)
}
Expand Down
11 changes: 11 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package go_i2cp

import (
"testing"
)

func TestClient(t *testing.T) {
client := NewClient(nil)
client.Connect()
client.Disconnect()
}
23 changes: 21 additions & 2 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"crypto/sha256"
"encoding/base32"
"encoding/base64"
"errors"
"hash"
"io"
"math/big"
Expand Down Expand Up @@ -171,6 +172,19 @@ func (c *Crypto) SignatureKeyPairFromStream(stream *Stream) (sgk SignatureKeyPai
return
}

func (c *Crypto) PublicKeyFromStream(keyType uint32, stream *Stream) (key *big.Int, err error) {
if keyType == DSA_SHA1 {
key = &big.Int{}
keyBytes := make([]byte, 128)
_, err = stream.Read(keyBytes)
key.SetBytes(keyBytes)
return key, err
} else {
Fatal(CRYPTO, "Unknown signature algorithm")
return nil, errors.New("Unknown signature algorithm")
}
}

// Generate a signature keypair
func (c *Crypto) SignatureKeygen(algorithmTyp uint32) (sgk SignatureKeyPair, err error) {
var pkey dsa.PrivateKey
Expand All @@ -193,22 +207,27 @@ func (c *Crypto) HashStream(algorithmTyp uint8, src *Stream) *Stream {
return NewStream(c.sh256.Sum(src.Bytes()))
} else {
Fatal(tAG|FATAL, "Request of unsupported hash algorithm.")
return nil
}
}
func (c *Crypto) EncodeStream(algorithmTyp uint8, src *Stream) (dst Stream) {
func (c *Crypto) EncodeStream(algorithmTyp uint8, src *Stream) (dst *Stream) {
switch algorithmTyp {
case CODEC_BASE32:
dst = NewStream(make([]byte, c.b32.EncodedLen(src.Len())))
c.b32.Encode(dst.Bytes(), src.Bytes())
case CODEC_BASE64:
dst = NewStream(make([]byte, c.b64.EncodedLen(src.Len())))
c.b64.Encode(dst.Bytes(), src.Bytes())
}
return
}
func (c *Crypto) DecodeStream(algorithmTyp uint8, src *Stream) (dst Stream, err error) {
func (c *Crypto) DecodeStream(algorithmTyp uint8, src *Stream) (dst *Stream, err error) {
switch algorithmTyp {
case CODEC_BASE32:
dst = NewStream(make([]byte, c.b32.DecodedLen(src.Len())))
_, err = c.b32.Decode(dst.Bytes(), src.Bytes())
case CODEC_BASE64:
dst = NewStream(make([]byte, c.b64.DecodedLen(src.Len())))
_, err = c.b64.Decode(dst.Bytes(), src.Bytes())
}
return
Expand Down
60 changes: 39 additions & 21 deletions destination.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package go_i2cp

import (
"errors"
"fmt"
"math/big"
"os"
"strings"
Expand All @@ -16,7 +17,7 @@ type Destination struct {
cert *Certificate
sgk SignatureKeyPair
signPubKey *big.Int
pubKey []byte
pubKey [PUB_KEY_SIZE]byte
digest [DIGEST_SIZE]byte
b32 string
b64 string
Expand All @@ -26,21 +27,29 @@ func NewDestination() (dest Destination, err error) {
nullCert := NewCertificate(CERTIFICATE_NULL)
dest.cert = &nullCert
dest.sgk, err = GetCryptoInstance().SignatureKeygen(DSA_SHA1)
dest.signPubKey = dest.sgk.pub.Y
dest.generateB32()
dest.generateB64()
return
}

// TODO ensure that this function not setting dest.sgk is the right thing to do
func NewDestinationFromMessage(stream *Stream) (dest Destination, err error) {
signPubKey := make([]byte, 128)
pubKey := make([]byte, PUB_KEY_SIZE)
_, err = stream.Read(pubKey)
_, err = stream.Read(signPubKey)
dest.pubKey = pubKey
dest.signPubKey.SetBytes(signPubKey)
_, err = stream.Read(dest.pubKey[:])
if err != nil {
return
}
dest.signPubKey, err = GetCryptoInstance().PublicKeyFromStream(DSA_SHA1, stream)
if err != nil {
return
}
dest.sgk = SignatureKeyPair{}
dest.sgk.priv.Y = dest.signPubKey
dest.sgk.pub.Y = dest.signPubKey
var cert Certificate
cert, err = NewCertificateFromMessage(stream)
if err != nil {
return
}
dest.cert = &cert
dest.generateB32()
dest.generateB64()
Expand All @@ -57,9 +66,7 @@ func NewDestinationFromStream(stream *Stream) (dest Destination, err error) {
if pubKeyLen != PUB_KEY_SIZE {
Fatal(tag, "Failed to load pub key len, %d != %d", pubKeyLen, PUB_KEY_SIZE)
}
pubKey := make([]byte, PUB_KEY_SIZE)
_, err = stream.Read(pubKey)
dest.pubKey = pubKey
_, err = stream.Read(dest.pubKey[:])
dest.generateB32()
dest.generateB64()
return
Expand All @@ -79,9 +86,9 @@ func NewDestinationFromBase64(base64 string) (dest Destination, err error) {
replaced = strings.Replace(base64, "~", "/", -1)
replaced = strings.Replace(replaced, "-", "+", -1)
stream := NewStream([]byte(replaced))
var decoded Stream
var decoded *Stream
decoded, err = GetCryptoInstance().DecodeStream(CODEC_BASE64, stream)
return NewDestinationFromMessage(&decoded)
return NewDestinationFromMessage(decoded)
}

func NewDestinationFromFile(file *os.File) (dest Destination, err error) {
Expand All @@ -92,56 +99,67 @@ func NewDestinationFromFile(file *os.File) (dest Destination, err error) {
func (dest *Destination) Copy() (newDest Destination) {
newDest.cert = dest.cert
newDest.signPubKey = dest.signPubKey
copy(newDest.pubKey, dest.pubKey)
newDest.pubKey = dest.pubKey
newDest.sgk = dest.sgk
newDest.b32 = dest.b32
newDest.b64 = dest.b64
newDest.digest = dest.digest
return
}
func (dest *Destination) WriteToFile(filename string) (err error) {
stream := NewStream(make([]byte, DEST_SIZE))
stream := NewStream(make([]byte, 0, DEST_SIZE))
dest.WriteToStream(stream)
var file *os.File
file, err = os.Open(filename)
stream.WriteTo(file)
file.Close()
return
}
func (dest *Destination) WriteToMessage(stream *Stream) (err error) {
_, err = stream.Write(dest.pubKey)
lena := len(dest.pubKey)
_ = lena
_, err = stream.Write(dest.pubKey[:])
_, err = stream.Write(dest.signPubKey.Bytes()) //GetCryptoInstance().WriteSignatureToStream(&dest.sgk, stream)
err = dest.cert.WriteToMessage(stream)
lenb := stream.Len()
_ = lenb
return
}
func (dest *Destination) WriteToStream(stream *Stream) (err error) {
err = dest.cert.WriteToStream(stream)
err = GetCryptoInstance().WriteSignatureToStream(&dest.sgk, stream)
err = stream.WriteUint16(PUB_KEY_SIZE)
_, err = stream.Write(dest.pubKey)
_, err = stream.Write(dest.pubKey[:])
return
}

//Doesn't seem to be used anywhere??
func (dest *Destination) Verify() (verified bool, err error) {
stream := NewStream(make([]byte, DEST_SIZE))
stream := NewStream(make([]byte, 0, DEST_SIZE))
dest.WriteToMessage(stream)
stream.Write(dest.digest[:])
return GetCryptoInstance().VerifyStream(&dest.sgk, stream)
}

func (dest *Destination) generateB32() {
stream := NewStream(make([]byte, DEST_SIZE))
stream := NewStream(make([]byte, 0, DEST_SIZE))
dest.WriteToMessage(stream)
cpt := GetCryptoInstance()
hash := cpt.HashStream(HASH_SHA256, stream)
b32 := cpt.EncodeStream(CODEC_BASE32, hash)
dest.b32 = string(b32.Bytes()) + ".b32.i2p"
length := b32.Len()
_ = length
dest.b32 = string(b32.Bytes())
dest.b32 += ".b32.i2p"
Debug(tag, "New destination %s", dest.b32)
}
func (dest *Destination) generateB64() {
stream := NewStream(make([]byte, DEST_SIZE))
stream := NewStream(make([]byte, 0, DEST_SIZE))
dest.WriteToMessage(stream)
cpt := GetCryptoInstance()
if stream.Len() > 0 {
fmt.Printf("Stream len %d \n", stream.Len())
}
b64B := cpt.EncodeStream(CODEC_BASE64, stream)
replaced := strings.Replace(string(b64B.Bytes()), "/", "~", -1)
replaced = strings.Replace(replaced, "/", "~", -1)
Expand Down
Loading

0 comments on commit 15798f4

Please sign in to comment.