summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Langley <agl@golang.org>2009-11-05 16:43:29 -0800
committerAdam Langley <agl@golang.org>2009-11-05 16:43:29 -0800
commitb0af6c8cdc22eb04696e0008fe02313e5b380274 (patch)
tree0324fd1fdd422bca6522362f6a99da3d62bdced4
parentc4434decd053e77bd5d06b5d0c127f39cf8dd4b9 (diff)
downloadgolang-b0af6c8cdc22eb04696e0008fe02313e5b380274.tar.gz
crypto/tls (part 4/5)
R=rsc CC=go-dev http://go/go-review/1019002
-rw-r--r--src/pkg/crypto/tls/Makefile19
-rw-r--r--src/pkg/crypto/tls/tls.go172
2 files changed, 191 insertions, 0 deletions
diff --git a/src/pkg/crypto/tls/Makefile b/src/pkg/crypto/tls/Makefile
new file mode 100644
index 000000000..dd3df2957
--- /dev/null
+++ b/src/pkg/crypto/tls/Makefile
@@ -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
index 000000000..13d8fd70b
--- /dev/null
+++ b/src/pkg/crypto/tls/tls.go
@@ -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;
+}