transportshim/transportshim.go (71 lines of code) (raw):

// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package transportshim implements the net.Conn interface. Used for to enable // the `crypto/tls` package to implement TLS over any transport layer. package transportshim import ( "net" "time" ) // In the event that more data is written to sendBuf than the underlying // TLS implementation can read at once, the sendBuf channel will need to // buffer multiple byte slices. In initial testing, the TLS implementation // can read somewhere between 2KB to 8KB per call, and the largest vTPM // attestation is on the order of 32KB, so we set the size of the channel // to 100 to accommodate for this. const sendBufLen = 100 // Allow 1 MB of bytes to be buffered through the receiveBuf channel. const receiveBufLen = 1024 * 1024 // TransportShim handles shuttling data. // When used on the server side, receiveBuf holds records sent from the client // and sendBuf is for records generated by the server to be sent to the client. // When used on the client side, receiveBuf holds records sent from the server // and sendBuf is for records generated by the client to be sent to the server. type TransportShim struct { sendBuf chan []byte receiveBuf chan byte } // NewTransportShim initializes and returns the transport shim. func NewTransportShim() ShimInterface { t := &TransportShim{} t.sendBuf = make(chan []byte, sendBufLen) t.receiveBuf = make(chan byte, receiveBufLen) return t } // QueueReceiveBuf inputs data received from the counterparty, to be read. func (shim *TransportShim) QueueReceiveBuf(buf []byte) { for _, b := range buf { shim.receiveBuf <- b } } func (shim *TransportShim) Read(b []byte) (n int, err error) { if len(b) == 0 { return 0, nil } // Block until we can read at least one byte, as per https://pkg.go.dev/io#Reader. b[0] = <-shim.receiveBuf // Read as many remaining bytes from `receiveBuf` as available, stopping if // we have read len(b) bytes, noting that we are starting at the 2nd byte. for i := range b[1:] { select { case b[i+1] = <-shim.receiveBuf: default: // Nothing left to read from channel. return i + 1, nil } } return len(b), nil } // DrainSendBuf returns records from `sendBuf` to be sent to the counterparty // (over some transport, i.e., gRPC). Will block until Write is invoked with // data to be sent to the counterparty. func (shim *TransportShim) DrainSendBuf() []byte { // Block until at least one slice of bytes is available in the sendBuf channel. ret := <-shim.sendBuf // Then, exhaust the remainder of the channel. for { select { case b := <-shim.sendBuf: ret = append(ret, b...) default: return ret } } } func (shim *TransportShim) Write(b []byte) (n int, err error) { buf := make([]byte, len(b)) copy(buf, b) shim.sendBuf <- buf return len(buf), nil } // Close not implemented func (shim *TransportShim) Close() error { panic("Close not implemented") } // LocalAddr not implemented func (shim *TransportShim) LocalAddr() net.Addr { panic("LocalAddr not implemented") } // RemoteAddr not implemented func (shim *TransportShim) RemoteAddr() net.Addr { panic("RemoteAddr not implemented") } // SetDeadline not implemented func (shim *TransportShim) SetDeadline(t time.Time) error { panic("SetDeadline not implemented") } // SetReadDeadline not implemented func (shim *TransportShim) SetReadDeadline(t time.Time) error { panic("SetReadDeadline not implemented") } // SetWriteDeadline not implemented func (shim *TransportShim) SetWriteDeadline(t time.Time) error { panic("SetWriteDeadline not implemented") }