]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls (part 4/5)
authorAdam Langley <agl@golang.org>
Fri, 6 Nov 2009 00:43:29 +0000 (16:43 -0800)
committerAdam Langley <agl@golang.org>
Fri, 6 Nov 2009 00:43:29 +0000 (16:43 -0800)
R=rsc
CC=go-dev
http://go/go-review/1019002

src/pkg/crypto/tls/Makefile [new file with mode: 0644]
src/pkg/crypto/tls/tls.go [new file with mode: 0644]

diff --git a/src/pkg/crypto/tls/Makefile b/src/pkg/crypto/tls/Makefile
new file mode 100644 (file)
index 0000000..dd3df29
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG=crypto/tls
+GOFILES=\
+       alert.go\
+       common.go\
+       handshake_messages.go\
+       handshake_server.go\
+       prf.go\
+       record_process.go\
+       record_read.go\
+       record_write.go\
+       tls.go\
+
+include $(GOROOT)/src/Make.pkg
diff --git a/src/pkg/crypto/tls/tls.go b/src/pkg/crypto/tls/tls.go
new file mode 100644 (file)
index 0000000..13d8fd7
--- /dev/null
@@ -0,0 +1,172 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
+package tls
+
+import (
+       "bytes";
+       "io";
+       "os";
+       "net";
+       "time";
+)
+
+// A Conn represents a secure connection.
+type Conn struct {
+       net.Conn;
+       writeChan                       chan<- []byte;
+       readChan                        <-chan []byte;
+       requestChan                     chan<- interface{};
+       readBuf                         []byte;
+       eof                             bool;
+       readTimeout, writeTimeout       int64;
+}
+
+func timeout(c chan<- bool, nsecs int64) {
+       time.Sleep(nsecs);
+       c <- true;
+}
+
+func (tls *Conn) Read(p []byte) (int, os.Error) {
+       if len(tls.readBuf) == 0 {
+               if tls.eof {
+                       return 0, os.EOF;
+               }
+
+               var timeoutChan chan bool;
+               if tls.readTimeout > 0 {
+                       timeoutChan = make(chan bool);
+                       go timeout(timeoutChan, tls.readTimeout);
+               }
+
+               select {
+               case b := <-tls.readChan:
+                       tls.readBuf = b;
+               case <-timeoutChan:
+                       return 0, os.EAGAIN;
+               }
+
+               // TLS distinguishes between orderly closes and truncations. An
+               // orderly close is represented by a zero length slice.
+               if closed(tls.readChan) {
+                       return 0, io.ErrUnexpectedEOF;
+               }
+               if len(tls.readBuf) == 0 {
+                       tls.eof = true;
+                       return 0, os.EOF;
+               }
+       }
+
+       n := bytes.Copy(p, tls.readBuf);
+       tls.readBuf = tls.readBuf[n:len(tls.readBuf)];
+       return n, nil;
+}
+
+func (tls *Conn) Write(p []byte) (int, os.Error) {
+       if tls.eof || closed(tls.readChan) {
+               return 0, os.EOF;
+       }
+
+       var timeoutChan chan bool;
+       if tls.writeTimeout > 0 {
+               timeoutChan = make(chan bool);
+               go timeout(timeoutChan, tls.writeTimeout);
+       }
+
+       select {
+       case tls.writeChan <- p:
+       case <-timeoutChan:
+               return 0, os.EAGAIN;
+       }
+
+       return len(p), nil;
+}
+
+func (tls *Conn) Close() os.Error {
+       close(tls.writeChan);
+       close(tls.requestChan);
+       tls.eof = true;
+       return nil;
+}
+
+func (tls *Conn) SetTimeout(nsec int64) os.Error {
+       tls.readTimeout = nsec;
+       tls.writeTimeout = nsec;
+       return nil;
+}
+
+func (tls *Conn) SetReadTimeout(nsec int64) os.Error {
+       tls.readTimeout = nsec;
+       return nil;
+}
+
+func (tls *Conn) SetWriteTimeout(nsec int64) os.Error {
+       tls.writeTimeout = nsec;
+       return nil;
+}
+
+func (tls *Conn) GetConnectionState() ConnectionState {
+       replyChan := make(chan ConnectionState);
+       tls.requestChan <- getConnectionState{replyChan};
+       return <-replyChan;
+}
+
+// Server establishes a secure connection over the given connection and acts
+// as a TLS server.
+func Server(conn net.Conn, config *Config) *Conn {
+       tls := new(Conn);
+       tls.Conn = conn;
+
+       writeChan := make(chan []byte);
+       readChan := make(chan []byte);
+       requestChan := make(chan interface{});
+
+       tls.writeChan = writeChan;
+       tls.readChan = readChan;
+       tls.requestChan = requestChan;
+
+       handshakeWriterChan := make(chan interface{});
+       processorHandshakeChan := make(chan interface{});
+       handshakeProcessorChan := make(chan interface{});
+       readerProcessorChan := make(chan *record);
+
+       go new(recordWriter).loop(conn, writeChan, handshakeWriterChan);
+       go recordReader(readerProcessorChan, conn);
+       go new(recordProcessor).loop(readChan, requestChan, handshakeProcessorChan, readerProcessorChan, processorHandshakeChan);
+       go new(serverHandshake).loop(handshakeWriterChan, handshakeProcessorChan, processorHandshakeChan, config);
+
+       return tls;
+}
+
+type Listener struct {
+       listener        net.Listener;
+       config          *Config;
+}
+
+func (l Listener) Accept() (c net.Conn, err os.Error) {
+       c, err = l.listener.Accept();
+       if err != nil {
+               return;
+       }
+
+       c = Server(c, l.config);
+       return;
+}
+
+func (l Listener) Close() os.Error {
+       return l.listener.Close();
+}
+
+func (l Listener) Addr() net.Addr {
+       return l.listener.Addr();
+}
+
+// NewListener creates a Listener which accepts connections from an inner
+// Listener and wraps each connection with Server.
+func NewListener(listener net.Listener, config *Config) (l Listener) {
+       l.listener = listener;
+       l.config = config;
+       return;
+}