eventmachine 0.4.5 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/RELEASE_NOTES +17 -1
- data/ext/binder.cpp +17 -1
- data/ext/binder.h +1 -1
- data/ext/cmain.cpp +15 -1
- data/ext/ed.cpp +206 -28
- data/ext/ed.h +18 -1
- data/ext/em.cpp +65 -19
- data/ext/em.h +1 -1
- data/ext/eventmachine.h +2 -1
- data/ext/extconf.rb +52 -3
- data/ext/page.cpp +114 -0
- data/ext/page.h +58 -0
- data/ext/project.h +30 -1
- data/ext/rubymain.cpp +89 -2
- data/ext/sigs.cpp +44 -8
- data/ext/sigs.h +5 -1
- data/ext/ssl.cpp +377 -0
- data/ext/ssl.h +92 -0
- data/lib/eventmachine.rb +39 -7
- metadata +6 -2
data/ext/page.h
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id: page.h 2421 2006-04-29 23:48:49Z francis $
|
4
|
+
|
5
|
+
File: page.h
|
6
|
+
Date: 30Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: garbagecat20
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU General Public License as published by
|
13
|
+
the Free Software Foundation; either version 2 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU General Public License
|
22
|
+
along with this program; if not, write to the Free Software
|
23
|
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
24
|
+
|
25
|
+
*****************************************************************************/
|
26
|
+
|
27
|
+
|
28
|
+
#ifndef __PageManager__H_
|
29
|
+
#define __PageManager__H_
|
30
|
+
|
31
|
+
|
32
|
+
/**************
|
33
|
+
class PageList
|
34
|
+
**************/
|
35
|
+
|
36
|
+
class PageList
|
37
|
+
{
|
38
|
+
struct Page {
|
39
|
+
Page (const char *b, size_t s): Buffer(b), Size(s) {}
|
40
|
+
const char *Buffer;
|
41
|
+
size_t Size;
|
42
|
+
};
|
43
|
+
|
44
|
+
public:
|
45
|
+
PageList();
|
46
|
+
virtual ~PageList();
|
47
|
+
|
48
|
+
void Push (const char*, int);
|
49
|
+
bool HasPages();
|
50
|
+
void Front (const char**, int*);
|
51
|
+
void PopFront();
|
52
|
+
|
53
|
+
private:
|
54
|
+
deque<Page> Pages;
|
55
|
+
};
|
56
|
+
|
57
|
+
|
58
|
+
#endif // __PageManager__H_
|
data/ext/project.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id: project.h
|
3
|
+
$Id: project.h 2452 2006-05-05 03:57:39Z francis $
|
4
4
|
|
5
5
|
File: project.h
|
6
6
|
Date: 06Apr06
|
@@ -29,6 +29,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
29
29
|
#define __Project__H_
|
30
30
|
|
31
31
|
|
32
|
+
#ifdef OS_WIN32
|
33
|
+
#pragma warning(disable:4786)
|
34
|
+
#endif
|
35
|
+
|
32
36
|
#include <iostream>
|
33
37
|
#include <map>
|
34
38
|
#include <vector>
|
@@ -36,6 +40,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
36
40
|
#include <string>
|
37
41
|
#include <sstream>
|
38
42
|
#include <stdexcept>
|
43
|
+
|
44
|
+
|
45
|
+
#ifdef OS_UNIX
|
39
46
|
#include <signal.h>
|
40
47
|
#include <netdb.h>
|
41
48
|
#include <sys/types.h>
|
@@ -47,14 +54,36 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
47
54
|
#include <netinet/in.h>
|
48
55
|
#include <netinet/tcp.h>
|
49
56
|
#include <arpa/inet.h>
|
57
|
+
typedef int SOCKET;
|
58
|
+
#define closesocket close
|
59
|
+
#define INVALID_SOCKET -1
|
60
|
+
#define SOCKET_ERROR -1
|
61
|
+
#endif
|
62
|
+
|
63
|
+
|
64
|
+
#ifdef OS_WIN32
|
65
|
+
#define WIN32_LEAN_AND_MEAN
|
66
|
+
#include <windows.h>
|
67
|
+
#include <winsock.h>
|
68
|
+
#include <rpc.h>
|
69
|
+
#include <fcntl.h>
|
70
|
+
#include <assert.h>
|
71
|
+
typedef int socklen_t;
|
72
|
+
#endif
|
73
|
+
|
74
|
+
|
50
75
|
using namespace std;
|
51
76
|
|
77
|
+
#include <openssl/ssl.h>
|
78
|
+
#include <openssl/err.h>
|
52
79
|
|
53
80
|
|
54
81
|
#include "binder.h"
|
55
82
|
#include "em.h"
|
56
83
|
#include "sigs.h"
|
57
84
|
#include "ed.h"
|
85
|
+
#include "page.h"
|
86
|
+
#include "ssl.h"
|
58
87
|
|
59
88
|
|
60
89
|
|
data/ext/rubymain.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id:
|
3
|
+
$Id: rubymain.cpp 2416 2006-04-29 02:02:16Z francis $
|
4
4
|
|
5
5
|
File: libmain.cpp
|
6
6
|
Date: 06Apr06
|
@@ -36,6 +36,8 @@ Statics
|
|
36
36
|
|
37
37
|
static VALUE EmModule;
|
38
38
|
static int SyncSockets [2];
|
39
|
+
static int Pipe1[2];
|
40
|
+
static int Pipe2[2];
|
39
41
|
static bool UseThreads;
|
40
42
|
|
41
43
|
static const char *A1;
|
@@ -52,10 +54,19 @@ t_event_callback
|
|
52
54
|
static void event_callback (const char *a1, int a2, const char *a3, int a4)
|
53
55
|
{
|
54
56
|
if (UseThreads) {
|
57
|
+
#ifdef OS_UNIX
|
55
58
|
A1 = a1; A2 = a2; A3 = a3; A4 = a4;
|
56
59
|
write (SyncSockets[1], "+", 1);
|
57
60
|
char g;
|
58
61
|
read (SyncSockets[1], &g, 1);
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#ifdef OS_WIN32
|
65
|
+
A1 = a1; A2 = a2; A3 = a3; A4 = a4;
|
66
|
+
write (Pipe1[1], "+", 1);
|
67
|
+
char g;
|
68
|
+
read (Pipe2[0], &g, 1);
|
69
|
+
#endif
|
59
70
|
}
|
60
71
|
else {
|
61
72
|
rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4));
|
@@ -67,12 +78,24 @@ static void event_callback (const char *a1, int a2, const char *a3, int a4)
|
|
67
78
|
TRunEvma
|
68
79
|
********/
|
69
80
|
|
81
|
+
#ifdef OS_UNIX
|
70
82
|
void *TRunEvma (void *v)
|
71
83
|
{
|
72
84
|
evma_run_machine();
|
73
85
|
write (SyncSockets[1], "$", 1);
|
74
86
|
return NULL;
|
75
87
|
}
|
88
|
+
#endif
|
89
|
+
|
90
|
+
#ifdef OS_WIN32
|
91
|
+
unsigned int __stdcall TRunEvma (void *v)
|
92
|
+
{
|
93
|
+
evma_run_machine();
|
94
|
+
write (Pipe1[1], "$", 1);
|
95
|
+
return NULL;
|
96
|
+
}
|
97
|
+
#endif
|
98
|
+
|
76
99
|
|
77
100
|
|
78
101
|
/**************************
|
@@ -105,6 +128,7 @@ t_run_machine
|
|
105
128
|
|
106
129
|
static VALUE t_run_machine (VALUE self)
|
107
130
|
{
|
131
|
+
#ifdef OS_UNIX
|
108
132
|
UseThreads = true;
|
109
133
|
|
110
134
|
int sp = socketpair (AF_LOCAL, SOCK_STREAM, 0, SyncSockets);
|
@@ -135,7 +159,7 @@ static VALUE t_run_machine (VALUE self)
|
|
135
159
|
");
|
136
160
|
|
137
161
|
if (v == 3) {
|
138
|
-
rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(A1), (A2
|
162
|
+
rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(A1), INT2NUM(A2), rb_str_new(A3,A4));
|
139
163
|
write (SyncSockets[0], "", 1);
|
140
164
|
}
|
141
165
|
else if (v == 5) {
|
@@ -149,6 +173,57 @@ static VALUE t_run_machine (VALUE self)
|
|
149
173
|
close (SyncSockets[1]);
|
150
174
|
|
151
175
|
return Qnil;
|
176
|
+
#endif
|
177
|
+
|
178
|
+
#ifdef OS_WIN32
|
179
|
+
UseThreads = true;
|
180
|
+
|
181
|
+
int sp1 = _pipe (Pipe1, 4096, _O_BINARY);
|
182
|
+
int sp2 = _pipe (Pipe2, 4096, _O_BINARY);
|
183
|
+
if (sp1 || sp2)
|
184
|
+
throw std::runtime_error ("no socket pair");
|
185
|
+
|
186
|
+
char buf [100];
|
187
|
+
snprintf (buf, sizeof(buf), "@io________pipe = IO.new( %d, \"r\")", Pipe1[0]);
|
188
|
+
rb_eval_string (buf);
|
189
|
+
|
190
|
+
unsigned tid;
|
191
|
+
HANDLE h = (HANDLE) _beginthreadex (NULL, 0, TRunEvma, NULL, 0, &tid);
|
192
|
+
CloseHandle (h);
|
193
|
+
|
194
|
+
while (true) {
|
195
|
+
VALUE v = rb_eval_string ("\
|
196
|
+
if s=select([@io________pipe]) and s=s.shift and s=s.shift\n\
|
197
|
+
r = s.read(1)\n\
|
198
|
+
if r == '+'\n\
|
199
|
+
1\n\
|
200
|
+
elsif r == '$'\n\
|
201
|
+
2\n\
|
202
|
+
else\n\
|
203
|
+
0\n\
|
204
|
+
end\n\
|
205
|
+
else\n\
|
206
|
+
0\n\
|
207
|
+
end\n\
|
208
|
+
");
|
209
|
+
|
210
|
+
if (v == 3) {
|
211
|
+
rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(A1), INT2NUM(A2), rb_str_new(A3,A4));
|
212
|
+
write (Pipe2[1], "", 1);
|
213
|
+
}
|
214
|
+
else if (v == 5) {
|
215
|
+
break;
|
216
|
+
}
|
217
|
+
|
218
|
+
}
|
219
|
+
|
220
|
+
close (Pipe1[0]);
|
221
|
+
close (Pipe1[1]);
|
222
|
+
close (Pipe2[0]);
|
223
|
+
close (Pipe2[1]);
|
224
|
+
|
225
|
+
return Qnil;
|
226
|
+
#endif
|
152
227
|
}
|
153
228
|
|
154
229
|
|
@@ -190,6 +265,17 @@ static VALUE t_send_data (VALUE self, VALUE signature, VALUE data, VALUE data_le
|
|
190
265
|
}
|
191
266
|
|
192
267
|
|
268
|
+
/***********
|
269
|
+
t_start_tls
|
270
|
+
***********/
|
271
|
+
|
272
|
+
static VALUE t_start_tls (VALUE self, VALUE signature)
|
273
|
+
{
|
274
|
+
evma_start_tls (StringValuePtr (signature));
|
275
|
+
return Qnil;
|
276
|
+
}
|
277
|
+
|
278
|
+
|
193
279
|
/***************
|
194
280
|
t_send_datagram
|
195
281
|
***************/
|
@@ -275,6 +361,7 @@ extern "C" void Init_rubyeventmachine()
|
|
275
361
|
rb_define_module_function (EmModule, "run_machine_without_threads", (VALUE(*)(...))t_run_machine_without_threads, 0);
|
276
362
|
rb_define_module_function (EmModule, "add_oneshot_timer", (VALUE(*)(...))t_add_oneshot_timer, 1);
|
277
363
|
rb_define_module_function (EmModule, "start_tcp_server", (VALUE(*)(...))t_start_server, 2);
|
364
|
+
rb_define_module_function (EmModule, "start_tls", (VALUE(*)(...))t_start_tls, 1);
|
278
365
|
rb_define_module_function (EmModule, "send_data", (VALUE(*)(...))t_send_data, 3);
|
279
366
|
rb_define_module_function (EmModule, "send_datagram", (VALUE(*)(...))t_send_datagram, 5);
|
280
367
|
rb_define_module_function (EmModule, "close_connection", (VALUE(*)(...))t_close_connection, 2);
|
data/ext/sigs.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id: sigs.cpp
|
3
|
+
$Id: sigs.cpp 2456 2006-05-05 13:54:33Z francis $
|
4
4
|
|
5
5
|
File: sigs.cpp
|
6
6
|
Date: 06Apr06
|
@@ -49,12 +49,48 @@ InstallSignalHandlers
|
|
49
49
|
|
50
50
|
void InstallSignalHandlers()
|
51
51
|
{
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
#ifdef OS_UNIX
|
53
|
+
static bool bInstalled = false;
|
54
|
+
if (!bInstalled) {
|
55
|
+
bInstalled = true;
|
56
|
+
signal (SIGINT, SigtermHandler);
|
57
|
+
signal (SIGTERM, SigtermHandler);
|
58
|
+
signal (SIGPIPE, SIG_IGN);
|
59
|
+
}
|
60
|
+
#endif
|
59
61
|
}
|
60
62
|
|
63
|
+
|
64
|
+
|
65
|
+
/*******************
|
66
|
+
WintelSignalHandler
|
67
|
+
*******************/
|
68
|
+
|
69
|
+
#ifdef OS_WIN32
|
70
|
+
BOOL WINAPI WintelSignalHandler (DWORD control)
|
71
|
+
{
|
72
|
+
if (control == CTRL_C_EVENT)
|
73
|
+
gTerminateSignalReceived = true;
|
74
|
+
return TRUE;
|
75
|
+
}
|
76
|
+
#endif
|
77
|
+
|
78
|
+
/************
|
79
|
+
HookControlC
|
80
|
+
************/
|
81
|
+
|
82
|
+
#ifdef OS_WIN32
|
83
|
+
void HookControlC (bool hook)
|
84
|
+
{
|
85
|
+
if (hook) {
|
86
|
+
// INSTALL hook
|
87
|
+
SetConsoleCtrlHandler (WintelSignalHandler, TRUE);
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
// UNINSTALL hook
|
91
|
+
SetConsoleCtrlHandler (WintelSignalHandler, FALSE);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
#endif
|
95
|
+
|
96
|
+
|
data/ext/sigs.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id: sigs.h
|
3
|
+
$Id: sigs.h 2456 2006-05-05 13:54:33Z francis $
|
4
4
|
|
5
5
|
File: sigs.h
|
6
6
|
Date: 06Apr06
|
@@ -31,5 +31,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
31
31
|
void InstallSignalHandlers();
|
32
32
|
extern bool gTerminateSignalReceived;
|
33
33
|
|
34
|
+
#ifdef OS_WIN32
|
35
|
+
void HookControlC (bool);
|
36
|
+
#endif
|
37
|
+
|
34
38
|
#endif // __Signals__H_
|
35
39
|
|
data/ext/ssl.cpp
ADDED
@@ -0,0 +1,377 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id: ssl.cpp 2458 2006-05-05 17:07:17Z francis $
|
4
|
+
|
5
|
+
File: ssl.cpp
|
6
|
+
Date: 30Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: garbagecat20
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU General Public License as published by
|
13
|
+
the Free Software Foundation; either version 2 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU General Public License
|
22
|
+
along with this program; if not, write to the Free Software
|
23
|
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
24
|
+
|
25
|
+
*****************************************************************************/
|
26
|
+
|
27
|
+
|
28
|
+
#include "project.h"
|
29
|
+
|
30
|
+
|
31
|
+
bool SslContext_t::bLibraryInitialized = false;
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
static void InitializeDefaultCredentials();
|
36
|
+
static EVP_PKEY *DefaultPrivateKey = NULL;
|
37
|
+
static X509 *DefaultCertificate = NULL;
|
38
|
+
|
39
|
+
static char PrivateMaterials[] = {"\
|
40
|
+
-----BEGIN RSA PRIVATE KEY-----\n\
|
41
|
+
MIICXAIBAAKBgQDCYYhcw6cGRbhBVShKmbWm7UVsEoBnUf0cCh8AX+MKhMxwVDWV\n\
|
42
|
+
Igdskntn3cSJjRtmgVJHIK0lpb/FYHQB93Ohpd9/Z18pDmovfFF9nDbFF0t39hJ/\n\
|
43
|
+
AqSzFB3GiVPoFFZJEE1vJqh+3jzsSF5K56bZ6azz38VlZgXeSozNW5bXkQIDAQAB\n\
|
44
|
+
AoGALA89gIFcr6BIBo8N5fL3aNHpZXjAICtGav+kTUpuxSiaym9cAeTHuAVv8Xgk\n\
|
45
|
+
H2Wbq11uz+6JMLpkQJH/WZ7EV59DPOicXrp0Imr73F3EXBfR7t2EQDYHPMthOA1D\n\
|
46
|
+
I9EtCzvV608Ze90hiJ7E3guGrGppZfJ+eUWCPgy8CZH1vRECQQDv67rwV/oU1aDo\n\
|
47
|
+
6/+d5nqjeW6mWkGqTnUU96jXap8EIw6B+0cUKskwx6mHJv+tEMM2748ZY7b0yBlg\n\
|
48
|
+
w4KDghbFAkEAz2h8PjSJG55LwqmXih1RONSgdN9hjB12LwXL1CaDh7/lkEhq0PlK\n\
|
49
|
+
PCAUwQSdM17Sl0Xxm2CZiekTSlwmHrtqXQJAF3+8QJwtV2sRJp8u2zVe37IeH1cJ\n\
|
50
|
+
xXeHyjTzqZ2803fnjN2iuZvzNr7noOA1/Kp+pFvUZUU5/0G2Ep8zolPUjQJAFA7k\n\
|
51
|
+
xRdLkzIx3XeNQjwnmLlncyYPRv+qaE3FMpUu7zftuZBnVCJnvXzUxP3vPgKTlzGa\n\
|
52
|
+
dg5XivDRfsV+okY5uQJBAMV4FesUuLQVEKb6lMs7rzZwpeGQhFDRfywJzfom2TLn\n\
|
53
|
+
2RdJQQ3dcgnhdVDgt5o1qkmsqQh8uJrJ9SdyLIaZQIc=\n\
|
54
|
+
-----END RSA PRIVATE KEY-----\n\
|
55
|
+
-----BEGIN CERTIFICATE-----\n\
|
56
|
+
MIID6TCCA1KgAwIBAgIJANm4W/Tzs+s+MA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD\n\
|
57
|
+
VQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMRYw\n\
|
58
|
+
FAYDVQQKEw1TdGVhbWhlYXQubmV0MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEdMBsG\n\
|
59
|
+
A1UEAxMUb3BlbmNhLnN0ZWFtaGVhdC5uZXQxKDAmBgkqhkiG9w0BCQEWGWVuZ2lu\n\
|
60
|
+
ZWVyaW5nQHN0ZWFtaGVhdC5uZXQwHhcNMDYwNTA1MTcwNjAzWhcNMjQwMjIwMTcw\n\
|
61
|
+
NjAzWjCBqjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQH\n\
|
62
|
+
EwhOZXcgWW9yazEWMBQGA1UEChMNU3RlYW1oZWF0Lm5ldDEUMBIGA1UECxMLRW5n\n\
|
63
|
+
aW5lZXJpbmcxHTAbBgNVBAMTFG9wZW5jYS5zdGVhbWhlYXQubmV0MSgwJgYJKoZI\n\
|
64
|
+
hvcNAQkBFhllbmdpbmVlcmluZ0BzdGVhbWhlYXQubmV0MIGfMA0GCSqGSIb3DQEB\n\
|
65
|
+
AQUAA4GNADCBiQKBgQDCYYhcw6cGRbhBVShKmbWm7UVsEoBnUf0cCh8AX+MKhMxw\n\
|
66
|
+
VDWVIgdskntn3cSJjRtmgVJHIK0lpb/FYHQB93Ohpd9/Z18pDmovfFF9nDbFF0t3\n\
|
67
|
+
9hJ/AqSzFB3GiVPoFFZJEE1vJqh+3jzsSF5K56bZ6azz38VlZgXeSozNW5bXkQID\n\
|
68
|
+
AQABo4IBEzCCAQ8wHQYDVR0OBBYEFPJvPd1Fcmd8o/Tm88r+NjYPICCkMIHfBgNV\n\
|
69
|
+
HSMEgdcwgdSAFPJvPd1Fcmd8o/Tm88r+NjYPICCkoYGwpIGtMIGqMQswCQYDVQQG\n\
|
70
|
+
EwJVUzERMA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMRYwFAYD\n\
|
71
|
+
VQQKEw1TdGVhbWhlYXQubmV0MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEdMBsGA1UE\n\
|
72
|
+
AxMUb3BlbmNhLnN0ZWFtaGVhdC5uZXQxKDAmBgkqhkiG9w0BCQEWGWVuZ2luZWVy\n\
|
73
|
+
aW5nQHN0ZWFtaGVhdC5uZXSCCQDZuFv087PrPjAMBgNVHRMEBTADAQH/MA0GCSqG\n\
|
74
|
+
SIb3DQEBBQUAA4GBAC1CXey/4UoLgJiwcEMDxOvW74plks23090iziFIlGgcIhk0\n\
|
75
|
+
Df6hTAs7H3MWww62ddvR8l07AWfSzSP5L6mDsbvq7EmQsmPODwb6C+i2aF3EDL8j\n\
|
76
|
+
uw73m4YIGI0Zw2XdBpiOGkx2H56Kya6mJJe/5XORZedh1wpI7zki01tHYbcy\n\
|
77
|
+
-----END CERTIFICATE-----\n"};
|
78
|
+
|
79
|
+
/* These private materials were made with:
|
80
|
+
* openssl req -new -x509 -keyout cakey.pem -out cacert.pem -nodes -days 6500
|
81
|
+
* TODO: We need a full-blown capability to work with user-supplied
|
82
|
+
* keypairs and properly-signed certificates.
|
83
|
+
*/
|
84
|
+
|
85
|
+
|
86
|
+
/*****************
|
87
|
+
builtin_passwd_cb
|
88
|
+
*****************/
|
89
|
+
|
90
|
+
extern "C" static int builtin_passwd_cb (char *buf, int bufsize, int rwflag, void *userdata)
|
91
|
+
{
|
92
|
+
strcpy (buf, "kittycat");
|
93
|
+
return 8;
|
94
|
+
}
|
95
|
+
|
96
|
+
/****************************
|
97
|
+
InitializeDefaultCredentials
|
98
|
+
****************************/
|
99
|
+
|
100
|
+
static void InitializeDefaultCredentials()
|
101
|
+
{
|
102
|
+
BIO *bio = BIO_new_mem_buf (PrivateMaterials, -1);
|
103
|
+
assert (bio);
|
104
|
+
|
105
|
+
if (DefaultPrivateKey) {
|
106
|
+
// we may come here in a restart.
|
107
|
+
EVP_PKEY_free (DefaultPrivateKey);
|
108
|
+
DefaultPrivateKey = NULL;
|
109
|
+
}
|
110
|
+
PEM_read_bio_PrivateKey (bio, &DefaultPrivateKey, builtin_passwd_cb, 0);
|
111
|
+
|
112
|
+
if (DefaultCertificate) {
|
113
|
+
// we may come here in a restart.
|
114
|
+
X509_free (DefaultCertificate);
|
115
|
+
DefaultCertificate = NULL;
|
116
|
+
}
|
117
|
+
PEM_read_bio_X509 (bio, &DefaultCertificate, NULL, 0);
|
118
|
+
|
119
|
+
BIO_free (bio);
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
/**************************
|
125
|
+
SslContext_t::SslContext_t
|
126
|
+
**************************/
|
127
|
+
|
128
|
+
SslContext_t::SslContext_t (bool is_server):
|
129
|
+
pCtx (NULL),
|
130
|
+
PrivateKey (NULL),
|
131
|
+
Certificate (NULL)
|
132
|
+
{
|
133
|
+
if (!bLibraryInitialized) {
|
134
|
+
bLibraryInitialized = true;
|
135
|
+
SSL_library_init();
|
136
|
+
OpenSSL_add_ssl_algorithms();
|
137
|
+
OpenSSL_add_all_algorithms();
|
138
|
+
SSL_load_error_strings();
|
139
|
+
ERR_load_crypto_strings();
|
140
|
+
|
141
|
+
InitializeDefaultCredentials();
|
142
|
+
}
|
143
|
+
|
144
|
+
bIsServer = is_server;
|
145
|
+
pCtx = SSL_CTX_new (is_server ? SSLv23_server_method() : SSLv23_client_method());
|
146
|
+
if (!pCtx)
|
147
|
+
throw std::runtime_error ("no SSL context");
|
148
|
+
|
149
|
+
SSL_CTX_set_options (pCtx, SSL_OP_ALL);
|
150
|
+
//SSL_CTX_set_options (pCtx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3));
|
151
|
+
|
152
|
+
if (is_server) {
|
153
|
+
// The SSL_CTX calls here do NOT allocate memory.
|
154
|
+
int e;
|
155
|
+
e = SSL_CTX_use_PrivateKey (pCtx, DefaultPrivateKey);
|
156
|
+
assert (e > 0);
|
157
|
+
e = SSL_CTX_use_certificate (pCtx, DefaultCertificate);
|
158
|
+
assert (e > 0);
|
159
|
+
}
|
160
|
+
|
161
|
+
SSL_CTX_set_cipher_list (pCtx, "ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH");
|
162
|
+
|
163
|
+
if (is_server) {
|
164
|
+
SSL_CTX_sess_set_cache_size (pCtx, 128);
|
165
|
+
SSL_CTX_set_session_id_context (pCtx, (unsigned char*)"eventmachine", 12);
|
166
|
+
}
|
167
|
+
|
168
|
+
}
|
169
|
+
|
170
|
+
/***************************
|
171
|
+
SslContext_t::~SslContext_t
|
172
|
+
***************************/
|
173
|
+
|
174
|
+
SslContext_t::~SslContext_t()
|
175
|
+
{
|
176
|
+
if (pCtx)
|
177
|
+
SSL_CTX_free (pCtx);
|
178
|
+
if (PrivateKey)
|
179
|
+
EVP_PKEY_free (PrivateKey);
|
180
|
+
if (Certificate)
|
181
|
+
X509_free (Certificate);
|
182
|
+
}
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
/******************
|
187
|
+
SslBox_t::SslBox_t
|
188
|
+
******************/
|
189
|
+
|
190
|
+
SslBox_t::SslBox_t (bool is_server):
|
191
|
+
bIsServer (is_server),
|
192
|
+
pSSL (NULL),
|
193
|
+
pbioRead (NULL),
|
194
|
+
pbioWrite (NULL)
|
195
|
+
{
|
196
|
+
Context = new SslContext_t (bIsServer);
|
197
|
+
assert (Context);
|
198
|
+
|
199
|
+
pbioRead = BIO_new (BIO_s_mem());
|
200
|
+
assert (pbioRead);
|
201
|
+
|
202
|
+
pbioWrite = BIO_new (BIO_s_mem());
|
203
|
+
assert (pbioWrite);
|
204
|
+
|
205
|
+
pSSL = SSL_new (Context->pCtx);
|
206
|
+
assert (pSSL);
|
207
|
+
SSL_set_bio (pSSL, pbioRead, pbioWrite);
|
208
|
+
|
209
|
+
if (!bIsServer)
|
210
|
+
SSL_connect (pSSL);
|
211
|
+
}
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
/*******************
|
216
|
+
SslBox_t::~SslBox_t
|
217
|
+
*******************/
|
218
|
+
|
219
|
+
SslBox_t::~SslBox_t()
|
220
|
+
{
|
221
|
+
// Freeing pSSL will also free the associated BIOs, so DON'T free them separately.
|
222
|
+
if (pSSL) {
|
223
|
+
if (SSL_get_shutdown (pSSL) & SSL_RECEIVED_SHUTDOWN)
|
224
|
+
SSL_shutdown (pSSL);
|
225
|
+
else
|
226
|
+
SSL_clear (pSSL);
|
227
|
+
SSL_free (pSSL);
|
228
|
+
}
|
229
|
+
|
230
|
+
delete Context;
|
231
|
+
}
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
/***********************
|
236
|
+
SslBox_t::PutCiphertext
|
237
|
+
***********************/
|
238
|
+
|
239
|
+
bool SslBox_t::PutCiphertext (const char *buf, int bufsize)
|
240
|
+
{
|
241
|
+
assert (buf && (bufsize > 0));
|
242
|
+
|
243
|
+
assert (pbioRead);
|
244
|
+
int n = BIO_write (pbioRead, buf, bufsize);
|
245
|
+
|
246
|
+
return (n == bufsize) ? true : false;
|
247
|
+
}
|
248
|
+
|
249
|
+
|
250
|
+
/**********************
|
251
|
+
SslBox_t::GetPlaintext
|
252
|
+
**********************/
|
253
|
+
|
254
|
+
int SslBox_t::GetPlaintext (char *buf, int bufsize)
|
255
|
+
{
|
256
|
+
if (!SSL_is_init_finished (pSSL)) {
|
257
|
+
int e = bIsServer ? SSL_accept (pSSL) : SSL_connect (pSSL);
|
258
|
+
if (e < 0) {
|
259
|
+
int er = SSL_get_error (pSSL, e);
|
260
|
+
if (er != SSL_ERROR_WANT_READ) {
|
261
|
+
// Return -1 for a nonfatal error, -2 for an error that should force the connection down.
|
262
|
+
return (er == SSL_ERROR_SSL) ? (-2) : (-1);
|
263
|
+
}
|
264
|
+
else
|
265
|
+
return 0;
|
266
|
+
}
|
267
|
+
// If handshake finished, FALL THROUGH and return the available plaintext.
|
268
|
+
}
|
269
|
+
|
270
|
+
if (!SSL_is_init_finished (pSSL)) {
|
271
|
+
// We can get here if a browser abandons a handshake.
|
272
|
+
// The user can see a warning dialog and abort the connection.
|
273
|
+
cerr << "<SSL_incomp>";
|
274
|
+
return 0;
|
275
|
+
}
|
276
|
+
|
277
|
+
//cerr << "CIPH: " << SSL_get_cipher (pSSL) << endl;
|
278
|
+
|
279
|
+
int n = SSL_read (pSSL, buf, bufsize);
|
280
|
+
if (n >= 0) {
|
281
|
+
return n;
|
282
|
+
}
|
283
|
+
else {
|
284
|
+
if (SSL_get_error (pSSL, n) == SSL_ERROR_WANT_READ) {
|
285
|
+
return 0;
|
286
|
+
}
|
287
|
+
else {
|
288
|
+
return -1;
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|
292
|
+
return 0;
|
293
|
+
}
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
/**************************
|
298
|
+
SslBox_t::CanGetCiphertext
|
299
|
+
**************************/
|
300
|
+
|
301
|
+
bool SslBox_t::CanGetCiphertext()
|
302
|
+
{
|
303
|
+
assert (pbioWrite);
|
304
|
+
return BIO_pending (pbioWrite) ? true : false;
|
305
|
+
}
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
/***********************
|
310
|
+
SslBox_t::GetCiphertext
|
311
|
+
***********************/
|
312
|
+
|
313
|
+
int SslBox_t::GetCiphertext (char *buf, int bufsize)
|
314
|
+
{
|
315
|
+
assert (pbioWrite);
|
316
|
+
assert (buf && (bufsize > 0));
|
317
|
+
|
318
|
+
return BIO_read (pbioWrite, buf, bufsize);
|
319
|
+
}
|
320
|
+
|
321
|
+
|
322
|
+
|
323
|
+
/**********************
|
324
|
+
SslBox_t::PutPlaintext
|
325
|
+
**********************/
|
326
|
+
|
327
|
+
int SslBox_t::PutPlaintext (const char *buf, int bufsize)
|
328
|
+
{
|
329
|
+
// The caller will interpret the return value as the number of bytes written.
|
330
|
+
// WARNING WARNING WARNING, are there any situations in which a 0 or -1 return
|
331
|
+
// from SSL_write means we should immediately retry? The socket-machine loop
|
332
|
+
// will probably wait for a time-out cycle (perhaps a second) before re-trying.
|
333
|
+
// THIS WOULD CAUSE A PERCEPTIBLE DELAY!
|
334
|
+
|
335
|
+
/* We internally queue any outbound plaintext that can't be dispatched
|
336
|
+
* because we're in the middle of a handshake or something.
|
337
|
+
* When we get called, try to send any queued data first, and then
|
338
|
+
* send the caller's data (or queue it). We may get called with no outbound
|
339
|
+
* data, which means we try to send the outbound queue and that's all.
|
340
|
+
*
|
341
|
+
* Return >0 if we wrote any data, 0 if we didn't, and <0 for a fatal error.
|
342
|
+
* Note that if we return 0, the connection is still considered live
|
343
|
+
* and we are signalling that we have accepted the outbound data (if any).
|
344
|
+
*/
|
345
|
+
|
346
|
+
OutboundQ.Push (buf, bufsize);
|
347
|
+
|
348
|
+
bool fatal = false;
|
349
|
+
bool did_work = false;
|
350
|
+
|
351
|
+
while (OutboundQ.HasPages()) {
|
352
|
+
const char *page;
|
353
|
+
int length;
|
354
|
+
OutboundQ.Front (&page, &length);
|
355
|
+
assert (page && (length > 0));
|
356
|
+
int n = SSL_write (pSSL, page, length);
|
357
|
+
if (n > 0) {
|
358
|
+
did_work = true;
|
359
|
+
OutboundQ.PopFront();
|
360
|
+
}
|
361
|
+
else {
|
362
|
+
int er = SSL_get_error (pSSL, n);
|
363
|
+
if ((er != SSL_ERROR_WANT_READ) && (er != SSL_ERROR_WANT_WRITE))
|
364
|
+
fatal = true;
|
365
|
+
break;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
|
369
|
+
|
370
|
+
if (did_work)
|
371
|
+
return 1;
|
372
|
+
else if (fatal)
|
373
|
+
return -1;
|
374
|
+
else
|
375
|
+
return 0;
|
376
|
+
}
|
377
|
+
|