em-synchrony-moped 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # EM-Synchrony-Moped
2
+
3
+ EM-Synchrony-Moped is a [Moped](https://github.com/mongoid/mongoid) driver patch for [EM-Synchrony](http://github.com/igrigorik/em-synchrony). Moped is the MongoDB driver for the [Mongoid](http://github.com/mongoid/mongoid).
4
+
5
+ * Supports SSL connections
6
+
7
+ ## Usage
8
+
9
+ In order to use this driver in an EM-Synchrony environment, simply include the driver.
10
+
11
+ ```ruby
12
+ require "em-synchrony/moped"
13
+
14
+ ```
15
+
16
+ To use SSL:
17
+ ```ruby
18
+ require "em-synchrony/moped"
19
+
20
+ ```
21
+
22
+
23
+ # License
24
+
25
+ The MIT License - Copyright (c) 2013 Adam Lebsack
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ task :default => [:spec]
8
+ task :test => [:spec]
9
+
10
+ desc "Run all RSpec tests"
11
+ RSpec::Core::RakeTask.new(:spec)
12
+
13
+
14
+ rescue LoadError
15
+ # silent failure for when rspec is not installed (production mode)
16
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'em-synchrony-moped'
5
+ s.version = "0.9.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Adam Lebsack"]
9
+ s.email = ["alebsack@gmail.com"]
10
+
11
+ s.summary = %q{Moped driver for EM-Synchrony}
12
+ s.description = %q{EM-Synchrony-Moped is a Moped driver patch for EM-Synchtony, allowing your asynchronous application use non-blocking connections to MongoDB. Moped is the MongoDB driver for the Mongoid ORM.}
13
+ s.email = %q{alebsack@gmail.com}
14
+
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency 'eventmachine'
22
+ s.add_runtime_dependency 'em-synchrony', '~> 1.0'
23
+ s.add_runtime_dependency 'moped', '~> 1.4.5'
24
+
25
+ s.add_development_dependency 'rspec', '~> 2.12.0'
26
+
27
+ end
@@ -0,0 +1,118 @@
1
+ require "moped/connection"
2
+
3
+ silence_warnings {
4
+
5
+ module Moped
6
+ class Cluster
7
+ def sleep(seconds)
8
+ EM::Synchrony.sleep(seconds)
9
+ end
10
+ end
11
+
12
+ class Connection
13
+ def connect
14
+ @sock = if !!options[:ssl]
15
+ Sockets::SSL.connect(host, port, timeout, options)
16
+ else
17
+ Sockets::TCP.connect(host, port, timeout, options)
18
+ end
19
+ end
20
+ end
21
+
22
+ Sockets.send(:remove_const, :TCP)
23
+ Sockets.send(:remove_const, :SSL)
24
+ module Sockets
25
+ module Connectable
26
+ attr_accessor :options
27
+
28
+ def alive?
29
+ !closed?
30
+ end
31
+
32
+ module ClassMethods
33
+
34
+ def connect(host, port, timeout, options={})
35
+ socket = EM.connect(host, port, self) do |c|
36
+ c.pending_connect_timeout = timeout
37
+ c.comm_inactivity_timeout = timeout
38
+ c.options = options.merge(:host => host)
39
+ end
40
+ # In TCPSocket, new against a closed port raises Errno::ECONNREFUSED.
41
+ # In EM, connect against a closed port result in a call to unbind with
42
+ # a reason param of Errno::ECONNREFUSED as a class, not an instance.
43
+ unless socket.sync(:in) # wait for connection
44
+ raise socket.unbind_reason.new if socket.unbind_reason.is_a? Class
45
+ raise SocketError, socket.unbind_reason
46
+ end
47
+ socket
48
+
49
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EPIPE, Errno::ECONNRESET, Errno::ETIMEDOUT, IOError => error
50
+ raise Errors::ConnectionFailure, "#{host}:#{port}: #{error.class.name} (#{error.errno}): #{error.message}"
51
+ rescue SocketError => error
52
+ raise Errors::ConnectionFailure, "#{host}:#{port}: #{error.class.name}: #{error.message}"
53
+ rescue OpenSSL::SSL::SSLError => error
54
+ raise Errors::ConnectionFailure, "#{host}:#{port}: #{error.class.name} (#{error.errno}): #{error.message}"
55
+ end
56
+
57
+
58
+ end
59
+ end
60
+
61
+ class TCP < EventMachine::Synchrony::TCPSocket
62
+ include Connectable
63
+ end
64
+
65
+ class SSL < EventMachine::Synchrony::TCPSocket
66
+ include Connectable
67
+
68
+ def connection_completed
69
+ @verified = false
70
+ if @options[:ssl].is_a?(Hash)
71
+ start_tls(@options[:ssl])
72
+ else
73
+ start_tls
74
+ end
75
+ end
76
+
77
+ def ssl_verify_peer(pem)
78
+ unless cert_store = @options[:ssl][:cert_store]
79
+ cert_store = OpenSSL::X509::Store.new
80
+ cert_store.add_file(@options[:ssl][:verify_cert])
81
+ end
82
+
83
+ if cert = OpenSSL::X509::Certificate.new(pem) rescue nil
84
+ if cert_store.verify(cert)
85
+
86
+ cert.extensions.each do |e|
87
+ if e.oid == 'basicConstraints' && e.value == 'CA:TRUE'
88
+ return true
89
+ end
90
+ end
91
+
92
+ host = @options[:ssl][:verify_host] || @options[:host]
93
+ if OpenSSL::SSL.verify_certificate_identity(cert, host)
94
+ @verified = true
95
+ return true
96
+ end
97
+ end
98
+ end
99
+
100
+ true
101
+ rescue => e
102
+ unbind "Failed to verify SSL certificate of peer"
103
+ false
104
+ end
105
+
106
+ def ssl_handshake_completed
107
+ if @options[:ssl][:verify_peer] && !@verified
108
+ unbind "Failed to verify SSL certificate of peer"
109
+ else
110
+ @opening = false
111
+ @in_req.succeed self
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+ end
118
+ }
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ require 'moped'
4
+ require 'em-synchrony/moped'
5
+
6
+ describe "em-synchrony/moped" do
7
+
8
+ def new_node(options={})
9
+ options.merge!(:timeout => 1)
10
+ host = options.delete(:host) || 'localhost'
11
+ Moped::Node.new("#{host}:#{FakeMongodHelper::BASE_PORT}", options)
12
+ end
13
+
14
+ context "without ssl" do
15
+
16
+ it "should connect" do
17
+ EventMachine.synchrony do
18
+ start_mongod
19
+
20
+ node = new_node
21
+ node.refresh
22
+ node.should be_primary
23
+ EM.stop
24
+ end
25
+ end
26
+
27
+
28
+ it "should raise a connection error on timeout" do
29
+ lambda {
30
+ EventMachine.synchrony do
31
+ start_mongod
32
+
33
+ # google.com seems timeout for my tests...
34
+ node = new_node(:host => "google.com")
35
+ node.refresh
36
+
37
+ EM.stop
38
+ end
39
+ }.should raise_exception(Moped::Errors::ConnectionFailure, /ETIMEDOUT/)
40
+ end
41
+
42
+ it "should raise a connection error on connection refused" do
43
+ lambda {
44
+ EventMachine.synchrony do
45
+ new_node.refresh
46
+ EM.stop
47
+ end
48
+ }.should raise_exception(Moped::Errors::ConnectionFailure, /ECONNREFUSED/)
49
+ end
50
+ end
51
+
52
+ context "without ssl" do
53
+ it "should connect and not verify peer" do
54
+ EventMachine.synchrony do
55
+ start_mongod(
56
+ :ssl => {
57
+ :private_key_file => "#{SSL_DIR}/server.key",
58
+ :cert_chain_file => "#{SSL_DIR}/server.crt",
59
+ :verify_peer => false
60
+ }
61
+ )
62
+
63
+ node = new_node(:ssl => {:verify_peer => false})
64
+ node.refresh
65
+ node.should be_primary
66
+
67
+ EM.stop
68
+ end
69
+ end
70
+
71
+ it "should connect and verify peer" do
72
+ EventMachine.synchrony do
73
+ start_mongod(
74
+ :ssl => {
75
+ :private_key_file => "#{SSL_DIR}/server.key",
76
+ :cert_chain_file => "#{SSL_DIR}/server.crt",
77
+ :verify_peer => false
78
+ }
79
+ )
80
+
81
+ node = new_node(:ssl => {
82
+ :verify_peer => true,
83
+ :verify_cert => "#{SSL_DIR}/ca_cert.pem",
84
+ :verify_host => "localhost"
85
+ })
86
+ node.refresh
87
+ node.should be_primary
88
+
89
+ EM.stop
90
+ end
91
+ end
92
+
93
+
94
+ it "should connect and fail to verify peer" do
95
+ lambda {
96
+
97
+ EventMachine.synchrony do
98
+ start_mongod(
99
+ :ssl => {
100
+ :private_key_file => "#{SSL_DIR}/untrusted.key",
101
+ :cert_chain_file => "#{SSL_DIR}/untrusted.crt",
102
+ :verify_peer => false
103
+ }
104
+ )
105
+
106
+ node = new_node(:ssl => {
107
+ :verify_peer => true,
108
+ :verify_cert => "#{SSL_DIR}/ca_cert.pem",
109
+ :verify_host => "localhost"
110
+ })
111
+
112
+ node.refresh
113
+ node.should be_primary
114
+
115
+ EM.stop
116
+ end
117
+ }.should raise_exception(Moped::Errors::ConnectionFailure, /Failed to verify SSL certificate of peer/)
118
+ end
119
+
120
+
121
+ end
122
+
123
+
124
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ require "rspec"
5
+
6
+ require 'em-synchrony'
7
+
8
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
9
+
10
+ SSL_DIR = File.expand_path("../ssl", __FILE__)
11
+
12
+ RSpec.configure do |config|
13
+
14
+
15
+ end
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDODCCAiCgAwIBAgIBATALBgkqhkiG9w0BAQswQjEQMA4GA1UEAwwHVGVzdCBD
3
+ QTELMAkGA1UEBhMCVVMxITAfBgkqhkiG9w0BCQEWEmFsZWJzYWNrQGdtYWlsLmNv
4
+ bTAeFw0xMzA0MjgyMjAwMzBaFw0yMzA0MjYyMjAwMzBaMEIxEDAOBgNVBAMMB1Rl
5
+ c3QgQ0ExCzAJBgNVBAYTAlVTMSEwHwYJKoZIhvcNAQkBFhJhbGVic2Fja0BnbWFp
6
+ bC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFWoHcCntUnNpD
7
+ qBSZqx5LyrvIHqXOo1a/vKP6OE2uBRVGA8M2V8OPJfFJA6rvNMwU9Hd6Ft7znN+G
8
+ Nrtoagl4w2Fr+DoaUQdjUbg8T5e1kAhcOXrqzQMv70ig+hispU2JgbX7ixHu0vC8
9
+ PEDPLWmrb8fSWnF8APhamFOL5efEzL0vI1HlVfTKN52Twc5obHzmRXyxER13dQit
10
+ HBrxB69uN7M9deozmpu34/Pjw7OMBQTAs+r7nWTvX8rQaf15PXkwYb+PQrWZp8bd
11
+ HKpqr/R9E4k+J9QA6CLNMXeeZwoJ5TRz8dHXHCS2xctJnC84+Q92EnM2i8cwWA95
12
+ YpIPI/o9AgMBAAGjOzA5MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKE
13
+ MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBm8A8M
14
+ 49WMsWyowvao7psT/b1qe41uI7IfqCx8Mjh4+TRyk5/+zZtME+GWM0iRt0JMGomc
15
+ lhKjM9Q7S7kuE6oaMvwhFrrjtdMGlB+uQRG05AQaeDifYKsCACg+/1lRCbavGEvm
16
+ GqNSG5/jLoPE9ekuDsanz1ZxcfBTd1qhYfI9TW+7rpbpY+nGhkNpURA4WjeKSq7X
17
+ I2xTQhbSSiQYNwvSOEH8V2PP+6F2IEv//wCu7S5r/gPWp/B7JocvFK2oprAqgvm+
18
+ ZMkrYM4r2Mi96KUtmlPvNF4u7F3/FVPtoNmvw9nqM7ODIrKudNf5OJRC6C4FwpV4
19
+ 5Mud2Jw9mvbcZzNT
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDRTCCAi2gAwIBAgIBAjALBgkqhkiG9w0BAQswQjEQMA4GA1UEAwwHVGVzdCBD
3
+ QTELMAkGA1UEBhMCVVMxITAfBgkqhkiG9w0BCQEWEmFsZWJzYWNrQGdtYWlsLmNv
4
+ bTAeFw0xMzA0MjgyMjA2MjVaFw0yMzA0MjYyMjA2MjVaMEQxEjAQBgNVBAMMCWxv
5
+ Y2FsaG9zdDELMAkGA1UEBhMCVVMxITAfBgkqhkiG9w0BCQEWEmFsZWJzYWNrQGdt
6
+ YWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOrW1F5LzzR6
7
+ L+UnzTamxPZIIACBlyymkPA8TVlFKSu1tITSzAyHiNoP6y3tig1l+R1LxT+eY26Z
8
+ eAgwbXznvY1dJfKo7sH38IgL2cNsC3DCe/b1Ue15H5SLa+uDHTXUaybfve/dwCXO
9
+ 9oq0yHhrC9+4zppnLWXQekemW35WtRAX1Rds0pZNwxfanj8wy7+qfGIUPqQ11JiV
10
+ lJ1jx2Th+3IxvPFmoNZ5HFTgudNK76hzYjVq7SZb0fH/YwGt1uVR2qI7NW1GooCm
11
+ lK46SGAT3VDQqyNrXmNk5CSoID+4GqFuruLEK/KFgE6U30/8haWPrVQ5cNp/EoXA
12
+ Wp/q+Q/dSnkCAwEAAaNGMEQwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoG
13
+ CCsGAQUFBwMBMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0B
14
+ AQsFAAOCAQEAnm7sxj9bYLLa2t5aLQU3drUKX8FaEcA2TUTWFNvSt7tnLhL+5tVO
15
+ KGN8Xh9q97MWE3jSaJwaZvV+dKp1coH6IxS7jiSeGcLlyLdvW8qoou11LWSR2W4a
16
+ V71LaBgBkaLDupFLGrC9OKuJH2TfV0lII4Rp4w9OQNyPGDd1QTd57JV1IzvByarQ
17
+ X8bSI3VKp2mSzw5z75+zfjC0tjwuJ2uPNEhcrWE1Q46gxH77ucbfqfm2kSr4JXVT
18
+ f8U9R3ee/ReQuk94dC13/lPyj+RMBvgtGoozQR5dG74ZNiG3YTEcl9JmFTCaoM3/
19
+ qV/886MaDQ2weg/1+y4RoZipssK7wBnGtg==
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,31 @@
1
+ Bag Attributes
2
+ friendlyName: localhost
3
+ localKeyID: 15 89 76 85 F8 5E 3F E6 0F B0 4D 0B 06 A9 90 39 1B 32 8A A0
4
+ Key Attributes: <No Attributes>
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIIEpAIBAAKCAQEA6tbUXkvPNHov5SfNNqbE9kggAIGXLKaQ8DxNWUUpK7W0hNLM
7
+ DIeI2g/rLe2KDWX5HUvFP55jbpl4CDBtfOe9jV0l8qjuwffwiAvZw2wLcMJ79vVR
8
+ 7XkflItr64MdNdRrJt+9793AJc72irTIeGsL37jOmmctZdB6R6Zbfla1EBfVF2zS
9
+ lk3DF9qePzDLv6p8YhQ+pDXUmJWUnWPHZOH7cjG88Wag1nkcVOC500rvqHNiNWrt
10
+ JlvR8f9jAa3W5VHaojs1bUaigKaUrjpIYBPdUNCrI2teY2TkJKggP7gaoW6u4sQr
11
+ 8oWATpTfT/yFpY+tVDlw2n8ShcBan+r5D91KeQIDAQABAoIBACL5G2dvoswN5lQa
12
+ OVWKQIrs8tcgdYMQy0T7tgk1Y4w+40NkoT68cIUJGd0dIxIbvZ2/SwDOdcBi2p1d
13
+ mPChEnmbBau9vNDmO8wG98dCr/F7BTsiDbFv+GQG32uTeyYpHEwNxhuSyqrWx6Cg
14
+ i7pjNsF6pEoaU4h2I7/H5phKEWzz1p+XWutIhww/Z2LcH3Pfp0sJGx5jxQW27zcK
15
+ oqq4F4hsa9otZp4UjTNYM3QtBHRpVofq1RECfDHbX2cNOK37CdgI68X5ssZr9b1b
16
+ ercZylqR6rSHWWqE5+CIN3Vvw/fttJazsvxs+zagJXV4eppeGzW75IPfHTDbLB6v
17
+ lefd0AECgYEA94Zd4xdGScIbGYYUYh0WHGxtf2B2pGruv8cLjsVtLNcWaUP9HiJb
18
+ lp4h5rR+lBn5VFPz3OJiEE5UL3xNhEZ7Sh4hiuQGFlsxmYvUMbbbJz8q89dVpmey
19
+ pCtseslfuglcYYxSW/PA9JjLyTDFc7hdndhUPAaFfr0ucpsPxjEPgBECgYEA8uFE
20
+ zCyu3KwIBsMXUN/gCufKrXEZv3UaHKeArLtKx+CrKYl/UAqxylU9YymyiAEa69q2
21
+ 7s0CpJFsoxcXToyx2QnnNKMg168kgS9ga8lrCKFF5HPmWYIJDyYirRPz1DjDE06s
22
+ T/3t5JYDGpdLocynALHYxFyxXaWEjl7HWosxC+kCgYEA5kxuLkwJabbf3++QJ3lI
23
+ iUmY11q5CGE1odlgN4YY/g9hGq/XYaI19P1MLYrh+onwITW7P1iiROmcClJtDRVG
24
+ wL8oFkHyJ/rROzuOQnMPlISBQj6nwhvZakW8uMGD/2OWQGx+dG9mqC1B7f8it3hi
25
+ IeqU9QRcUH9UJ+19z7j14wECgYEA77FbOPhb9ZGdNjcwenMGYxzPy41TsLv7cg3o
26
+ kg8gRNO3d32ndDGpthmbRJKxC0Gz9NFbOZ5/HjQad3VhXfbByYTZdPwMfG7vYsKD
27
+ sLwNcm3eURAEY49OK3IiRJbtSiJeel5o9WSPcsiM9aAcVuhmY+wgFeG4dMfVYr+s
28
+ k/HMDIkCgYAf++B1I76Z6XdMt29wOP6bRk+oSTh/9bJ8KSD8PAq7DYdBAZRPqw72
29
+ cvx+iGbxcA2Erzag0mseOJkyEJmd8UypjtE/uw1VetjS0iBkKqRetBURTHDNt6Ef
30
+ Qv4Nr9OBhlcGKe8hVQ6ArN4JJk8pJ1PE7t2aCWds891ooN7dcsTKSw==
31
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,25 @@
1
+ Bag Attributes
2
+ friendlyName: localhost
3
+ localKeyID: 47 6A C5 CA E0 0D 13 B6 6B 84 F0 20 18 E9 F7 40 00 E7 EC E9
4
+ subject=/CN=localhost/C=US/emailAddress=alebsack@gmail.com
5
+ issuer=/CN=localhost/C=US/emailAddress=alebsack@gmail.com
6
+ -----BEGIN CERTIFICATE-----
7
+ MIIDRzCCAi+gAwIBAgIBATALBgkqhkiG9w0BAQswRDESMBAGA1UEAwwJbG9jYWxo
8
+ b3N0MQswCQYDVQQGEwJVUzEhMB8GCSqGSIb3DQEJARYSYWxlYnNhY2tAZ21haWwu
9
+ Y29tMB4XDTEzMDQyODIyMzQyOFoXDTIzMDQyNjIyMzQyOFowRDESMBAGA1UEAwwJ
10
+ bG9jYWxob3N0MQswCQYDVQQGEwJVUzEhMB8GCSqGSIb3DQEJARYSYWxlYnNhY2tA
11
+ Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvErl6uVq
12
+ op8gvmABuF/3MaLnqBqZEZ45okxM7XPw9zeJeVNvJ7+19rhV0tH44FbRVhOtAB/+
13
+ 1fbEa5DxGTfwWPEMDLEy8DIfXU513xPzCYU9AUSYOGiDDMKaoWKXC2HjjWXtcZMI
14
+ eZ5QG17/TWy4ElkrbxS3opROPcNQLrs810+4uvwOWibFEvHCGNCGnMm94Df2LqU+
15
+ y1s9Pj5FMo35kMYeJMWeLXmA8KCac2rOpBYUPgyVfXsjBgiEZFls8lBqpI4tOztQ
16
+ ZFyhqRfyqpdQ8IMHIELx39+9ydF85eYAb+bGgy8L1w9DZxAPc9Hcujctnd+F4KZi
17
+ qjA1oAwJOTOmrQIDAQABo0YwRDAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAww
18
+ CgYIKwYBBQUHAwEwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3
19
+ DQEBCwUAA4IBAQC7TWaKJFnIpaugXkyHWdMvzd9A/KbegOXzN107FgQ/7oyEFUL9
20
+ Mss3MN2lfnRy5WDFLkIWNivKoTBVEJ1b8cHp4CJmA8IcsFSvJw308H9MZoxhyRQ0
21
+ Ud4ezhXxmzKtwbwCaKmGzx63DtpsdC/uXPCYix4M2CvXmvUKbzSIBR3hD9UL4W9k
22
+ Rpe5tCRYJQHATlrW4e4W8Xg4+bszDb29LHCl8e8dAazmMl94j91BkmFBwodrLwVm
23
+ 5ss8SRpNxkGIX1VeL140sWlMGg9Cqk+Fj8zaeTUB85YYMkNF7RNolaGumMv0rmou
24
+ T6kYq7wNK/xm0P9WhSosvH+n/Xx3y/aalwgr
25
+ -----END CERTIFICATE-----
@@ -0,0 +1,31 @@
1
+ Bag Attributes
2
+ friendlyName: localhost
3
+ localKeyID: 47 6A C5 CA E0 0D 13 B6 6B 84 F0 20 18 E9 F7 40 00 E7 EC E9
4
+ Key Attributes: <No Attributes>
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIIEogIBAAKCAQEAvErl6uVqop8gvmABuF/3MaLnqBqZEZ45okxM7XPw9zeJeVNv
7
+ J7+19rhV0tH44FbRVhOtAB/+1fbEa5DxGTfwWPEMDLEy8DIfXU513xPzCYU9AUSY
8
+ OGiDDMKaoWKXC2HjjWXtcZMIeZ5QG17/TWy4ElkrbxS3opROPcNQLrs810+4uvwO
9
+ WibFEvHCGNCGnMm94Df2LqU+y1s9Pj5FMo35kMYeJMWeLXmA8KCac2rOpBYUPgyV
10
+ fXsjBgiEZFls8lBqpI4tOztQZFyhqRfyqpdQ8IMHIELx39+9ydF85eYAb+bGgy8L
11
+ 1w9DZxAPc9Hcujctnd+F4KZiqjA1oAwJOTOmrQIDAQABAoIBAGrg2MEMmArW6G8n
12
+ b9KIJng2T+hLsLcfaPeG9+OQ/CZXj+EeSun1GASDfbO9G9e7b/e8E2cOwkgRWkz0
13
+ aOY3qmXR7VUHADL3QHZmIuININc2mfouRXk/WaPUkpEotTPwzIlmYfEl1Jm0EyR2
14
+ N9Rq8dD4bH8Q82uFYyQLyWe9QDu2O5Hw+gwwjt3t2buOKX+pzymqH8LpKNlTBTol
15
+ 1qG1xp3lZKU7QmNOsznBSSdRV13WK3b+tD+iFSVrsQIX0r3Rh4UVw4QAqyT/8tjY
16
+ Aqb8qv9ccOdU2mKGSEhe0imqJcMBL/Ksh4e+tP0m8eJF/v6QpuqJw56iJ9kzsfY3
17
+ 1AH7QgECgYEA3hxQ9vgA9F4otI7jA/eq+m8D/Ecx2IKZRsOfZvA6J0a4KqXe/auN
18
+ gH4vjMJnTgcWVOheF8WctUf+F89f9Zh0xus6wBJrD6ichWAYUGzFafvpFSe0yNhW
19
+ UIvEhe5UYQp7pQMj4Oi9/PFVQT/zKroOZWY3Y37mkeIzhyEFdpLJ7ikCgYEA2QWk
20
+ gzK6fpOOM+bN3+vJU/1OVk4CdVoSrnz3f9hRj96BxEvr+EXn4f/J4+bItsq16U4f
21
+ 0xAhq+bGVV1PNOrXFqFzhMPtG14xW20mM89/MqBtke5ixB7D0cei29J87SbUX5MB
22
+ oNOg58vAbXb7NFYn3Q+SrQ89LvSASxxpfTjAPOUCgYAb8IvuxTu5ga61J9Q+x4Tm
23
+ g9iIf5wxlBwb3rfKhyWJk0fPdZYbat0d8MGif0HnetTAUYqkiuMvmqLH8/oqNsdZ
24
+ znVRe/+jtJ4b2P61/zjGID4tvxTqvuv8rdhG0LgkjOEI3OBChoR/sQv8bUL1ePoe
25
+ n0EQbwIqD75TnT/GrqhgIQKBgHNJsxZbWYUqX82km9OLj31FwFrKwDWVLv1wt447
26
+ 3UA/ZNJhvq46fK+rUZX3IMMyNqcE8JUQKcMHKm9ozU4AP1jvVc2+w3PZewDln/jA
27
+ DwNXBD4U1HT5Hu+PTS3XyLO2//TxxFiqc/0PWV8NaO9poW2m+zViNg9+pbTBGC0E
28
+ e+MdAoGAeLHx2ftPjj2+/6Zu/p4jzMcMDJurVJLWaHpaSfBAxggMKOHeXeaLCoGd
29
+ mcei57mVOK1udZTnjtFRDLz198pwk1ht2DzzjDSHYQDuOMAekeY0+MfbFzMGha5c
30
+ cUtmdCGOBYbbGnB3oqv6XNSY6cM8EvnVP/VV67fSoxy+DV8La/g=
31
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,142 @@
1
+ require 'eventmachine'
2
+
3
+ require 'moped/protocol/message'
4
+ module Moped
5
+ module Protocol
6
+
7
+ # This patch is so we can parse a query as a server
8
+ module Message
9
+ module ClassMethods
10
+
11
+ alias_method :_old_cstring, :cstring
12
+ def cstring(name)
13
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
14
+ def deserialize_#{name}(buffer)
15
+ str = ''
16
+ while c = buffer.getc
17
+ break if c == '\0'
18
+ str << c
19
+ end
20
+ self.#{name} = str
21
+ end
22
+ RUBY
23
+ _old_cstring(name)
24
+ end
25
+
26
+ alias_method :_old_document, :document
27
+ def document(name, options = {})
28
+ if options[:optional]
29
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
30
+ def deserialize_#{name}(buffer)
31
+ # noop for now
32
+ end
33
+ RUBY
34
+ else
35
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
36
+ def deserialize_#{name}(buffer)
37
+ self.#{name} = BSON::Document.deserialize(buffer)
38
+ end
39
+ RUBY
40
+ end
41
+ _old_document(name, options)
42
+ end
43
+ end
44
+ end
45
+
46
+ # now that the class DSL is patched, load the message classes we need to patch further
47
+
48
+ # This patch is so we can parse a query as a server
49
+ require 'moped/protocol/query'
50
+ class Query
51
+ class << self
52
+ def deserialize(buffer)
53
+ reply = allocate
54
+ fields.each do |field|
55
+ reply.__send__ :"deserialize_#{field}", buffer
56
+ end
57
+ reply
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ # This patch is so we can create a Reply object as a server
64
+ require 'moped/protocol/reply'
65
+ class Reply
66
+ def initialize(documents, options = {})
67
+ @documents = documents
68
+ @request_id = options[:request_id]
69
+ @response_to = options[:response_to]
70
+ @flags = options[:flags] || []
71
+ @count = documents.length
72
+ @op_code = 1
73
+ end
74
+ end
75
+
76
+
77
+ end
78
+ end
79
+
80
+
81
+ class FakeMongod < EventMachine::Connection
82
+ def initialize(options)
83
+ @options = options
84
+ @request_id = 0
85
+ end
86
+
87
+ def post_init
88
+ if @options[:ssl]
89
+ start_tls(@options[:ssl])
90
+ end
91
+ end
92
+
93
+ def receive_data(data)
94
+ query = Moped::Protocol::Query.deserialize(StringIO.new(data))
95
+ if query.full_collection_name == 'admin.$cmd'
96
+ if query.selector == {'ismaster' => 1}
97
+ send_reply(query,
98
+ :ok => 1,
99
+ :ismaster => 1
100
+ )
101
+ elsif query.selector == {'listDatabases' => 1}
102
+ send_reply(query,
103
+ :ok => 1,
104
+ :databases => [{
105
+ :name => 'test_db'
106
+ }]
107
+ )
108
+ end
109
+ end
110
+ end
111
+
112
+ def send_reply(query, *documents)
113
+ @request_id += 1
114
+ reply = Moped::Protocol::Reply.new(
115
+ documents,
116
+ :request_id => @request_ud,
117
+ :response_to => query.request_id
118
+ )
119
+ send_data reply.serialize
120
+ end
121
+
122
+ end
123
+
124
+ module FakeMongodHelper
125
+
126
+ BASE_PORT = 37017
127
+
128
+ def start_mongod(options={})
129
+ @server = EventMachine.start_server('127.0.0.1', BASE_PORT, FakeMongod, options)
130
+ end
131
+
132
+
133
+ def stop_mongod
134
+ EventMachine.stop_server(@server)
135
+ end
136
+
137
+ end
138
+
139
+ RSpec.configure do |config|
140
+ config.include FakeMongodHelper
141
+
142
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-synchrony-moped
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Adam Lebsack
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: em-synchrony
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: moped
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.4.5
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.4.5
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 2.12.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.12.0
78
+ description: EM-Synchrony-Moped is a Moped driver patch for EM-Synchtony, allowing
79
+ your asynchronous application use non-blocking connections to MongoDB. Moped is
80
+ the MongoDB driver for the Mongoid ORM.
81
+ email: alebsack@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - README.md
89
+ - Rakefile
90
+ - em-synchrony-moped.gemspec
91
+ - lib/em-synchrony/moped.rb
92
+ - spec/moped_spec.rb
93
+ - spec/spec_helper.rb
94
+ - spec/ssl/ca_cert.pem
95
+ - spec/ssl/server.crt
96
+ - spec/ssl/server.key
97
+ - spec/ssl/untrusted.crt
98
+ - spec/ssl/untrusted.key
99
+ - spec/support/simulated_mongod.rb
100
+ homepage:
101
+ licenses: []
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.25
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Moped driver for EM-Synchrony
124
+ test_files:
125
+ - spec/moped_spec.rb
126
+ - spec/spec_helper.rb
127
+ - spec/ssl/ca_cert.pem
128
+ - spec/ssl/server.crt
129
+ - spec/ssl/server.key
130
+ - spec/ssl/untrusted.crt
131
+ - spec/ssl/untrusted.key
132
+ - spec/support/simulated_mongod.rb
133
+ has_rdoc: