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.
@@ -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
+