eventmachine 0.4.5 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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_
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: project.h 2381 2006-04-24 13:33:03Z francis $
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
 
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: libmain.cpp 2309 2006-04-15 15:37:53Z francis $
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 << 1) | 1, rb_str_new(A3,A4));
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);
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: sigs.cpp 2291 2006-04-14 03:56:18Z francis $
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
- static bool bInstalled = false;
53
- if (!bInstalled) {
54
- bInstalled = true;
55
- signal (SIGINT, SigtermHandler);
56
- signal (SIGTERM, SigtermHandler);
57
- signal (SIGPIPE, SIG_IGN);
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 2291 2006-04-14 03:56:18Z francis $
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
 
@@ -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
+