Skip to content

Commit 4f3c759

Browse files
committed
Merge branch 'chrisvdg-adds-tls'
2 parents e095da8 + 61c5beb commit 4f3c759

File tree

3 files changed

+353
-8
lines changed

3 files changed

+353
-8
lines changed

README.md

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Installing
2525
go get -u github.com/tidwall/redcon
2626
```
2727

28-
Example
28+
Examples
2929
-------
3030

3131
Here's a full example of a Redis clone that accepts:
@@ -123,6 +123,136 @@ func main() {
123123
}
124124
```
125125

126+
The same example is also provided for serving redcon over TLS:
127+
128+
```sh
129+
go run example/tls/tls.go
130+
```
131+
132+
```go
133+
package main
134+
135+
import (
136+
"crypto/tls"
137+
"log"
138+
"strings"
139+
"sync"
140+
141+
"github.com/tidwall/redcon"
142+
)
143+
144+
const serverKey = `
145+
-----BEGIN EC PARAMETERS-----
146+
BggqhkjOPQMBBw==
147+
-----END EC PARAMETERS-----
148+
-----BEGIN EC PRIVATE KEY-----
149+
MHcCAQEEIHg+g2unjA5BkDtXSN9ShN7kbPlbCcqcYdDu+QeV8XWuoAoGCCqGSM49
150+
AwEHoUQDQgAEcZpodWh3SEs5Hh3rrEiu1LZOYSaNIWO34MgRxvqwz1FMpLxNlx0G
151+
cSqrxhPubawptX5MSr02ft32kfOlYbaF5Q==
152+
-----END EC PRIVATE KEY-----
153+
`
154+
155+
const serverCert = `
156+
-----BEGIN CERTIFICATE-----
157+
MIIB+TCCAZ+gAwIBAgIJAL05LKXo6PrrMAoGCCqGSM49BAMCMFkxCzAJBgNVBAYT
158+
AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn
159+
aXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNTEyMDgxNDAxMTNa
160+
Fw0yNTEyMDUxNDAxMTNaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0
161+
YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMM
162+
CWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHGaaHVod0hLOR4d
163+
66xIrtS2TmEmjSFjt+DIEcb6sM9RTKS8TZcdBnEqq8YT7m2sKbV+TEq9Nn7d9pHz
164+
pWG2heWjUDBOMB0GA1UdDgQWBBR0fqrecDJ44D/fiYJiOeBzfoqEijAfBgNVHSME
165+
GDAWgBR0fqrecDJ44D/fiYJiOeBzfoqEijAMBgNVHRMEBTADAQH/MAoGCCqGSM49
166+
BAMCA0gAMEUCIEKzVMF3JqjQjuM2rX7Rx8hancI5KJhwfeKu1xbyR7XaAiEA2UT7
167+
1xOP035EcraRmWPe7tO0LpXgMxlh2VItpc2uc2w=
168+
-----END CERTIFICATE-----
169+
`
170+
171+
var addr = ":6380"
172+
173+
func main() {
174+
cer, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
175+
if err != nil {
176+
log.Fatal(err)
177+
}
178+
config := &tls.Config{Certificates: []tls.Certificate{cer}}
179+
180+
var mu sync.RWMutex
181+
var items = make(map[string][]byte)
182+
183+
go log.Printf("started server at %s", addr)
184+
err = redcon.ListenAndServeTLS(addr,
185+
func(conn redcon.Conn, cmd redcon.Command) {
186+
switch strings.ToLower(string(cmd.Args[0])) {
187+
default:
188+
conn.WriteError("ERR unknown command '" + string(cmd.Args[0]) + "'")
189+
case "detach":
190+
hconn := conn.Detach()
191+
log.Printf("connection has been detached")
192+
go func() {
193+
defer hconn.Close()
194+
hconn.WriteString("OK")
195+
hconn.Flush()
196+
}()
197+
return
198+
case "ping":
199+
conn.WriteString("PONG")
200+
case "quit":
201+
conn.WriteString("OK")
202+
conn.Close()
203+
case "set":
204+
if len(cmd.Args) != 3 {
205+
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
206+
return
207+
}
208+
mu.Lock()
209+
items[string(cmd.Args[1])] = cmd.Args[2]
210+
mu.Unlock()
211+
conn.WriteString("OK")
212+
case "get":
213+
if len(cmd.Args) != 2 {
214+
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
215+
return
216+
}
217+
mu.RLock()
218+
val, ok := items[string(cmd.Args[1])]
219+
mu.RUnlock()
220+
if !ok {
221+
conn.WriteNull()
222+
} else {
223+
conn.WriteBulk(val)
224+
}
225+
case "del":
226+
if len(cmd.Args) != 2 {
227+
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
228+
return
229+
}
230+
mu.Lock()
231+
_, ok := items[string(cmd.Args[1])]
232+
delete(items, string(cmd.Args[1]))
233+
mu.Unlock()
234+
if !ok {
235+
conn.WriteInt(0)
236+
} else {
237+
conn.WriteInt(1)
238+
}
239+
}
240+
},
241+
func(conn redcon.Conn) bool {
242+
return true
243+
},
244+
func(conn redcon.Conn, err error) {
245+
},
246+
config,
247+
)
248+
249+
if err != nil {
250+
log.Fatal(err)
251+
}
252+
}
253+
```
254+
255+
126256
Benchmarks
127257
----------
128258

@@ -168,4 +298,3 @@ Josh Baker [@tidwall](http://twitter.com/tidwall)
168298
License
169299
-------
170300
Redcon source code is available under the MIT [License](/LICENSE).
171-

example/tls/tls.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package main
2+
3+
import (
4+
"crypto/tls"
5+
"log"
6+
"strings"
7+
"sync"
8+
9+
"github.com/tidwall/redcon"
10+
)
11+
12+
const serverKey = `-----BEGIN EC PARAMETERS-----
13+
BggqhkjOPQMBBw==
14+
-----END EC PARAMETERS-----
15+
-----BEGIN EC PRIVATE KEY-----
16+
MHcCAQEEIHg+g2unjA5BkDtXSN9ShN7kbPlbCcqcYdDu+QeV8XWuoAoGCCqGSM49
17+
AwEHoUQDQgAEcZpodWh3SEs5Hh3rrEiu1LZOYSaNIWO34MgRxvqwz1FMpLxNlx0G
18+
cSqrxhPubawptX5MSr02ft32kfOlYbaF5Q==
19+
-----END EC PRIVATE KEY-----
20+
`
21+
22+
const serverCert = `-----BEGIN CERTIFICATE-----
23+
MIIB+TCCAZ+gAwIBAgIJAL05LKXo6PrrMAoGCCqGSM49BAMCMFkxCzAJBgNVBAYT
24+
AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn
25+
aXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNTEyMDgxNDAxMTNa
26+
Fw0yNTEyMDUxNDAxMTNaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0
27+
YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMM
28+
CWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHGaaHVod0hLOR4d
29+
66xIrtS2TmEmjSFjt+DIEcb6sM9RTKS8TZcdBnEqq8YT7m2sKbV+TEq9Nn7d9pHz
30+
pWG2heWjUDBOMB0GA1UdDgQWBBR0fqrecDJ44D/fiYJiOeBzfoqEijAfBgNVHSME
31+
GDAWgBR0fqrecDJ44D/fiYJiOeBzfoqEijAMBgNVHRMEBTADAQH/MAoGCCqGSM49
32+
BAMCA0gAMEUCIEKzVMF3JqjQjuM2rX7Rx8hancI5KJhwfeKu1xbyR7XaAiEA2UT7
33+
1xOP035EcraRmWPe7tO0LpXgMxlh2VItpc2uc2w=
34+
-----END CERTIFICATE-----
35+
`
36+
37+
var addr = ":6380"
38+
39+
func main() {
40+
cer, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
41+
if err != nil {
42+
log.Fatal(err)
43+
}
44+
config := &tls.Config{Certificates: []tls.Certificate{cer}}
45+
46+
var mu sync.RWMutex
47+
var items = make(map[string][]byte)
48+
49+
go log.Printf("started server at %s", addr)
50+
err = redcon.ListenAndServeTLS(addr,
51+
func(conn redcon.Conn, cmd redcon.Command) {
52+
switch strings.ToLower(string(cmd.Args[0])) {
53+
default:
54+
conn.WriteError("ERR unknown command '" + string(cmd.Args[0]) + "'")
55+
case "detach":
56+
hconn := conn.Detach()
57+
log.Printf("connection has been detached")
58+
go func() {
59+
defer hconn.Close()
60+
hconn.WriteString("OK")
61+
hconn.Flush()
62+
}()
63+
return
64+
case "ping":
65+
conn.WriteString("PONG")
66+
case "quit":
67+
conn.WriteString("OK")
68+
conn.Close()
69+
case "set":
70+
if len(cmd.Args) != 3 {
71+
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
72+
return
73+
}
74+
mu.Lock()
75+
items[string(cmd.Args[1])] = cmd.Args[2]
76+
mu.Unlock()
77+
conn.WriteString("OK")
78+
case "get":
79+
if len(cmd.Args) != 2 {
80+
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
81+
return
82+
}
83+
mu.RLock()
84+
val, ok := items[string(cmd.Args[1])]
85+
mu.RUnlock()
86+
if !ok {
87+
conn.WriteNull()
88+
} else {
89+
conn.WriteBulk(val)
90+
}
91+
case "del":
92+
if len(cmd.Args) != 2 {
93+
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
94+
return
95+
}
96+
mu.Lock()
97+
_, ok := items[string(cmd.Args[1])]
98+
delete(items, string(cmd.Args[1]))
99+
mu.Unlock()
100+
if !ok {
101+
conn.WriteInt(0)
102+
} else {
103+
conn.WriteInt(1)
104+
}
105+
}
106+
},
107+
func(conn redcon.Conn) bool {
108+
return true
109+
},
110+
func(conn redcon.Conn, err error) {
111+
},
112+
config,
113+
)
114+
115+
if err != nil {
116+
log.Fatal(err)
117+
}
118+
}

0 commit comments

Comments
 (0)