SPORTS
Change-Id: Ic272cba9811948aac3ac2b4713ed61ebf73955d4
diff --git a/runtime/internal/flow/conn/grpc/conn.go b/runtime/internal/flow/conn/grpc/conn.go
new file mode 100644
index 0000000..5ce7b6a
--- /dev/null
+++ b/runtime/internal/flow/conn/grpc/conn.go
@@ -0,0 +1,88 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package grpc
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "time"
+
+ "golang.org/x/crypto/nacl/box"
+)
+
+// Implements net.Conn. Encrypts messages using keys negotioated via NaCl.
+// TODO: blessings
+// TODO: discharges and caveats
+// TODO: ensuer that all 5 of these are set. Constructor?
+// TODO: do I need to check the message size as in box_coipher.Seal?
+// TODO: make all these keys not pointers?
+type conn struct {
+ rawConn net.Conn
+ publicKey *[32]byte
+ secretKey *[32]byte
+ sharedKey *[32]byte
+ binding []byte
+ nonce [24]byte
+ counter uint64 // Why is this so weirdly handled in advanceNonce?
+}
+
+func (c *conn) Read(b []byte) (n int, err error) {
+ return 0, nil
+}
+
+// TODO: all this casting is gross
+func (c *conn) Write(b []byte) (n int, err error) {
+ tmp := make([]byte, len(b)+box.Overhead) // TODO: is this enough? Also, why do we need both of tmp and out?
+ out := box.SealAfterPrecomputation(tmp, b, c.currentNonce(), c.sharedKey)
+ c.advanceNonce()
+ bytesCopied, err := io.Copy(c.rawConn, bytes.NewReader(out))
+ if err != nil {
+ return int(bytesCopied), err
+ }
+ if bytesCopied != int64(len(out)) {
+ errMsg := fmt.Sprintf("Did not write entire message. Expected to write %d bytes but wrote %d.", len(out), bytesCopied)
+ return -1, errors.New(errMsg)
+ }
+ return int(bytesCopied), nil
+}
+
+// TODO: cover these up with an interface?
+func (c *conn) Close() error {
+ return c.rawConn.Close()
+}
+
+func (c *conn) LocalAddr() net.Addr {
+ return c.rawConn.LocalAddr()
+}
+
+func (c *conn) RemoteAddr() net.Addr {
+ return c.rawConn.RemoteAddr()
+}
+
+func (c *conn) SetDeadline(t time.Time) error {
+ return c.rawConn.SetDeadline(t)
+}
+
+func (c *conn) SetReadDeadline(t time.Time) error {
+ return c.rawConn.SetReadDeadline(t)
+}
+
+func (c *conn) SetWriteDeadline(t time.Time) error {
+ return c.rawConn.SetWriteDeadline(t)
+}
+
+// TODO: should I just collapse current and advance?
+func (c *conn) currentNonce() *[24]byte {
+ return &c.nonce
+}
+
+func (c *conn) advanceNonce() {
+ c.counter++
+ binary.LittleEndian.PutUint64(c.nonce[:], c.counter)
+}