1package mssql
2
3import (
4	"fmt"
5	"net"
6	"time"
7)
8
9type timeoutConn struct {
10	c             net.Conn
11	timeout       time.Duration
12}
13
14func newTimeoutConn(conn net.Conn, timeout time.Duration) *timeoutConn {
15	return &timeoutConn{
16		c:       conn,
17		timeout: timeout,
18	}
19}
20
21func (c *timeoutConn) Read(b []byte) (n int, err error) {
22	if c.timeout > 0 {
23		err = c.c.SetDeadline(time.Now().Add(c.timeout))
24		if err != nil {
25			return
26		}
27	}
28	return c.c.Read(b)
29}
30
31func (c *timeoutConn) Write(b []byte) (n int, err error) {
32	if c.timeout > 0 {
33		err = c.c.SetDeadline(time.Now().Add(c.timeout))
34		if err != nil {
35			return
36		}
37	}
38	return c.c.Write(b)
39}
40
41func (c timeoutConn) Close() error {
42	return c.c.Close()
43}
44
45func (c timeoutConn) LocalAddr() net.Addr {
46	return c.c.LocalAddr()
47}
48
49func (c timeoutConn) RemoteAddr() net.Addr {
50	return c.c.RemoteAddr()
51}
52
53func (c timeoutConn) SetDeadline(t time.Time) error {
54	panic("Not implemented")
55}
56
57func (c timeoutConn) SetReadDeadline(t time.Time) error {
58	panic("Not implemented")
59}
60
61func (c timeoutConn) SetWriteDeadline(t time.Time) error {
62	panic("Not implemented")
63}
64
65// this connection is used during TLS Handshake
66// TDS protocol requires TLS handshake messages to be sent inside TDS packets
67type tlsHandshakeConn struct {
68	buf *tdsBuffer
69	packetPending bool
70	continueRead  bool
71}
72
73func (c *tlsHandshakeConn) Read(b []byte) (n int, err error) {
74	if c.packetPending {
75		c.packetPending = false
76		err = c.buf.FinishPacket()
77		if err != nil {
78			err = fmt.Errorf("Cannot send handshake packet: %s", err.Error())
79			return
80		}
81		c.continueRead = false
82	}
83	if !c.continueRead {
84		var packet packetType
85		packet, err = c.buf.BeginRead()
86		if err != nil {
87			err = fmt.Errorf("Cannot read handshake packet: %s", err.Error())
88			return
89		}
90		if packet != packPrelogin {
91			err = fmt.Errorf("unexpected packet %d, expecting prelogin", packet)
92			return
93		}
94		c.continueRead = true
95	}
96	return c.buf.Read(b)
97}
98
99func (c *tlsHandshakeConn) Write(b []byte) (n int, err error) {
100	if !c.packetPending {
101		c.buf.BeginPacket(packPrelogin, false)
102		c.packetPending = true
103	}
104	return c.buf.Write(b)
105}
106
107func (c *tlsHandshakeConn) Close() error {
108	panic("Not implemented")
109}
110
111func (c *tlsHandshakeConn) LocalAddr() net.Addr {
112	panic("Not implemented")
113}
114
115func (c *tlsHandshakeConn) RemoteAddr() net.Addr {
116	panic("Not implemented")
117}
118
119func (c *tlsHandshakeConn) SetDeadline(t time.Time) error {
120	panic("Not implemented")
121}
122
123func (c *tlsHandshakeConn) SetReadDeadline(t time.Time) error {
124	panic("Not implemented")
125}
126
127func (c *tlsHandshakeConn) SetWriteDeadline(t time.Time) error {
128	panic("Not implemented")
129}
130
131// this connection just delegates all methods to it's wrapped connection
132// it also allows switching underlying connection on the fly
133// it is needed because tls.Conn does not allow switching underlying connection
134type passthroughConn struct {
135	c net.Conn
136}
137
138func (c passthroughConn) Read(b []byte) (n int, err error) {
139	return c.c.Read(b)
140}
141
142func (c passthroughConn) Write(b []byte) (n int, err error) {
143	return c.c.Write(b)
144}
145
146func (c passthroughConn) Close() error {
147	return c.c.Close()
148}
149
150func (c passthroughConn) LocalAddr() net.Addr {
151	panic("Not implemented")
152}
153
154func (c passthroughConn) RemoteAddr() net.Addr {
155	panic("Not implemented")
156}
157
158func (c passthroughConn) SetDeadline(t time.Time) error {
159	panic("Not implemented")
160}
161
162func (c passthroughConn) SetReadDeadline(t time.Time) error {
163	panic("Not implemented")
164}
165
166func (c passthroughConn) SetWriteDeadline(t time.Time) error {
167	panic("Not implemented")
168}
169