eventmachine 0.12.6-x86-mswin32-60 → 0.12.8-x86-mswin32-60

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.
Files changed (116) hide show
  1. data/{docs/README → README} +21 -13
  2. data/Rakefile +14 -4
  3. data/docs/DEFERRABLES +0 -5
  4. data/docs/INSTALL +2 -4
  5. data/docs/LEGAL +1 -1
  6. data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
  7. data/docs/PURE_RUBY +0 -2
  8. data/docs/RELEASE_NOTES +0 -2
  9. data/docs/SMTP +0 -7
  10. data/docs/SPAWNED_PROCESSES +0 -4
  11. data/docs/TODO +0 -2
  12. data/eventmachine.gemspec +41 -32
  13. data/examples/ex_channel.rb +43 -0
  14. data/examples/ex_queue.rb +2 -0
  15. data/examples/helper.rb +2 -0
  16. data/ext/cmain.cpp +685 -586
  17. data/ext/cplusplus.cpp +15 -6
  18. data/ext/ed.cpp +1732 -1522
  19. data/ext/ed.h +407 -380
  20. data/ext/em.cpp +2263 -1937
  21. data/ext/em.h +223 -186
  22. data/ext/eventmachine.h +111 -98
  23. data/ext/eventmachine_cpp.h +1 -0
  24. data/ext/extconf.rb +4 -0
  25. data/ext/kb.cpp +81 -82
  26. data/ext/pipe.cpp +349 -351
  27. data/ext/project.h +21 -0
  28. data/ext/rubymain.cpp +1047 -847
  29. data/ext/ssl.cpp +38 -1
  30. data/ext/ssl.h +5 -1
  31. data/java/src/com/rubyeventmachine/Application.java +7 -3
  32. data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
  33. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
  34. data/lib/{protocols → em}/buftok.rb +16 -5
  35. data/lib/em/callback.rb +26 -0
  36. data/lib/em/channel.rb +57 -0
  37. data/lib/em/connection.rb +505 -0
  38. data/lib/em/deferrable.rb +144 -165
  39. data/lib/em/file_watch.rb +54 -0
  40. data/lib/em/future.rb +24 -25
  41. data/lib/em/messages.rb +1 -1
  42. data/lib/em/process_watch.rb +44 -0
  43. data/lib/em/processes.rb +119 -113
  44. data/lib/em/protocols.rb +35 -0
  45. data/lib/em/protocols/header_and_content.rb +138 -0
  46. data/lib/em/protocols/httpclient.rb +263 -0
  47. data/lib/em/protocols/httpclient2.rb +582 -0
  48. data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
  49. data/lib/em/protocols/linetext2.rb +160 -0
  50. data/lib/{protocols → em/protocols}/memcache.rb +37 -7
  51. data/lib/em/protocols/object_protocol.rb +39 -0
  52. data/lib/em/protocols/postgres3.rb +247 -0
  53. data/lib/em/protocols/saslauth.rb +175 -0
  54. data/lib/em/protocols/smtpclient.rb +331 -0
  55. data/lib/em/protocols/smtpserver.rb +547 -0
  56. data/lib/em/protocols/stomp.rb +200 -0
  57. data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
  58. data/lib/em/queue.rb +61 -0
  59. data/lib/em/spawnable.rb +53 -56
  60. data/lib/em/streamer.rb +92 -74
  61. data/lib/em/timers.rb +55 -0
  62. data/lib/em/version.rb +3 -0
  63. data/lib/eventmachine.rb +1636 -1926
  64. data/lib/evma.rb +1 -1
  65. data/lib/jeventmachine.rb +106 -101
  66. data/lib/pr_eventmachine.rb +47 -36
  67. data/tasks/project.rake +2 -1
  68. data/tests/client.crt +31 -0
  69. data/tests/client.key +51 -0
  70. data/tests/test_attach.rb +18 -0
  71. data/tests/test_basic.rb +285 -231
  72. data/tests/test_channel.rb +63 -0
  73. data/tests/test_connection_count.rb +2 -2
  74. data/tests/test_epoll.rb +162 -163
  75. data/tests/test_errors.rb +36 -36
  76. data/tests/test_exc.rb +22 -25
  77. data/tests/test_file_watch.rb +49 -0
  78. data/tests/test_futures.rb +77 -93
  79. data/tests/test_hc.rb +2 -2
  80. data/tests/test_httpclient.rb +55 -52
  81. data/tests/test_httpclient2.rb +153 -155
  82. data/tests/test_inactivity_timeout.rb +30 -0
  83. data/tests/test_kb.rb +8 -9
  84. data/tests/test_ltp2.rb +274 -277
  85. data/tests/test_next_tick.rb +135 -109
  86. data/tests/test_object_protocol.rb +37 -0
  87. data/tests/test_process_watch.rb +48 -0
  88. data/tests/test_processes.rb +128 -95
  89. data/tests/test_proxy_connection.rb +92 -0
  90. data/tests/test_pure.rb +1 -5
  91. data/tests/test_queue.rb +44 -0
  92. data/tests/test_running.rb +9 -14
  93. data/tests/test_sasl.rb +32 -34
  94. data/tests/test_send_file.rb +175 -176
  95. data/tests/test_servers.rb +37 -41
  96. data/tests/test_smtpserver.rb +47 -55
  97. data/tests/test_spawn.rb +284 -291
  98. data/tests/test_ssl_args.rb +1 -1
  99. data/tests/test_ssl_methods.rb +1 -1
  100. data/tests/test_ssl_verify.rb +82 -0
  101. data/tests/test_timers.rb +81 -88
  102. data/tests/test_ud.rb +0 -7
  103. data/tests/testem.rb +1 -1
  104. metadata +52 -36
  105. data/lib/em/eventable.rb +0 -39
  106. data/lib/eventmachine_version.rb +0 -31
  107. data/lib/protocols/header_and_content.rb +0 -129
  108. data/lib/protocols/httpcli2.rb +0 -803
  109. data/lib/protocols/httpclient.rb +0 -270
  110. data/lib/protocols/linetext2.rb +0 -161
  111. data/lib/protocols/postgres.rb +0 -261
  112. data/lib/protocols/saslauth.rb +0 -179
  113. data/lib/protocols/smtpclient.rb +0 -308
  114. data/lib/protocols/smtpserver.rb +0 -556
  115. data/lib/protocols/stomp.rb +0 -153
  116. data/tests/test_eventables.rb +0 -77
@@ -1,4 +1,4 @@
1
- # $Id$
1
+ #--
2
2
  #
3
3
  # Author:: Francis Cianfrocca (gmail: blackhedd)
4
4
  # Homepage:: http://rubyeventmachine.com
@@ -23,7 +23,7 @@
23
23
  #
24
24
  #
25
25
  #
26
- require File.dirname(__FILE__) + '/buftok'
26
+ require File.dirname(__FILE__) + '/../buftok'
27
27
 
28
28
  module EventMachine
29
29
  module Protocols
@@ -0,0 +1,160 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 15 November 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ module EventMachine
27
+ module Protocols
28
+ # In the grand, time-honored tradition of re-inventing the wheel, we offer
29
+ # here YET ANOTHER protocol that handles line-oriented data with interspersed
30
+ # binary text. This one trades away some of the performance optimizations of
31
+ # EventMachine::Protocols::LineAndTextProtocol in order to get better correctness
32
+ # with regard to binary text blocks that can switch back to line mode. It also
33
+ # permits the line-delimiter to change in midstream.
34
+ # This was originally written to support Stomp.
35
+ module LineText2
36
+ # TODO! We're not enforcing the limits on header lengths and text-lengths.
37
+ # When we get around to that, call #receive_error if the user defined it, otherwise
38
+ # throw exceptions.
39
+
40
+ MaxLineLength = 16*1024
41
+ MaxBinaryLength = 32*1024*1024
42
+
43
+ #--
44
+ # Will be called recursively until there's no data to read.
45
+ # That way the user-defined handlers we call can modify the
46
+ # handling characteristics on a per-token basis.
47
+ #
48
+ def receive_data data
49
+ return unless (data and data.length > 0)
50
+
51
+ # Do this stuff in lieu of a constructor.
52
+ @lt2_mode ||= :lines
53
+ @lt2_delimiter ||= "\n"
54
+ @lt2_linebuffer ||= []
55
+
56
+ if @lt2_mode == :lines
57
+ if ix = data.index( @lt2_delimiter )
58
+ @lt2_linebuffer << data[0...ix]
59
+ ln = @lt2_linebuffer.join
60
+ @lt2_linebuffer.clear
61
+ if @lt2_delimiter == "\n"
62
+ ln.chomp!
63
+ end
64
+ receive_line ln
65
+ receive_data data[(ix+@lt2_delimiter.length)..-1]
66
+ else
67
+ @lt2_linebuffer << data
68
+ end
69
+ elsif @lt2_mode == :text
70
+ if @lt2_textsize
71
+ needed = @lt2_textsize - @lt2_textpos
72
+ will_take = if data.length > needed
73
+ needed
74
+ else
75
+ data.length
76
+ end
77
+
78
+ @lt2_textbuffer << data[0...will_take]
79
+ tail = data[will_take..-1]
80
+
81
+ @lt2_textpos += will_take
82
+ if @lt2_textpos >= @lt2_textsize
83
+ # Reset line mode (the default behavior) BEFORE calling the
84
+ # receive_binary_data. This makes it possible for user code
85
+ # to call set_text_mode, enabling chains of text blocks
86
+ # (which can possibly be of different sizes).
87
+ set_line_mode
88
+ receive_binary_data @lt2_textbuffer.join
89
+ receive_end_of_binary_data
90
+ end
91
+
92
+ receive_data tail
93
+ else
94
+ receive_binary_data data
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ def set_delimiter delim
101
+ @lt2_delimiter = delim.to_s
102
+ end
103
+
104
+ # Called internally but also exposed to user code, for the case in which
105
+ # processing of binary data creates a need to transition back to line mode.
106
+ # We support an optional parameter to "throw back" some data, which might
107
+ # be an umprocessed chunk of the transmitted binary data, or something else
108
+ # entirely.
109
+ def set_line_mode data=""
110
+ @lt2_mode = :lines
111
+ (@lt2_linebuffer ||= []).clear
112
+ receive_data data.to_s
113
+ end
114
+
115
+ def set_text_mode size=nil
116
+ if size == 0
117
+ set_line_mode
118
+ else
119
+ @lt2_mode = :text
120
+ (@lt2_textbuffer ||= []).clear
121
+ @lt2_textsize = size # which can be nil, signifying no limit
122
+ @lt2_textpos = 0
123
+ end
124
+ end
125
+
126
+ # Alias for #set_text_mode, added for back-compatibility with LineAndTextProtocol.
127
+ def set_binary_mode size=nil
128
+ set_text_mode size
129
+ end
130
+
131
+ # In case of a dropped connection, we'll send a partial buffer to user code
132
+ # when in sized text mode. User overrides of #receive_binary_data need to
133
+ # be aware that they may get a short buffer.
134
+ def unbind
135
+ if @lt2_mode == :text and @lt2_textpos > 0
136
+ receive_binary_data @lt2_textbuffer.join
137
+ end
138
+ end
139
+
140
+ # Stub. Should be subclassed by user code.
141
+ def receive_line ln
142
+ # no-op
143
+ end
144
+
145
+ # Stub. Should be subclassed by user code.
146
+ def receive_binary_data data
147
+ # no-op
148
+ end
149
+
150
+ # Stub. Should be subclassed by user code.
151
+ # This is called when transitioning internally from text mode
152
+ # back to line mode. Useful when client code doesn't want
153
+ # to keep track of how much data it's received.
154
+ def receive_end_of_binary_data
155
+ # no-op
156
+ end
157
+ end
158
+ end
159
+ end
160
+
@@ -32,6 +32,7 @@ module EventMachine
32
32
  ##
33
33
  # constants
34
34
 
35
+ # :stopdoc:
35
36
  unless defined? Cempty
36
37
  Cstored = 'STORED'.freeze
37
38
  Cend = 'END'.freeze
@@ -42,10 +43,16 @@ module EventMachine
42
43
  Cempty = ''.freeze
43
44
  Cdelimiter = "\r\n".freeze
44
45
  end
46
+ # :startdoc:
45
47
 
46
48
  ##
47
49
  # commands
48
50
 
51
+ # Get the value associated with one or multiple keys
52
+ #
53
+ # cache.get(:a){ |v| p v }
54
+ # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
55
+ #
49
56
  def get *keys
50
57
  raise ArgumentError unless block_given?
51
58
 
@@ -58,6 +65,11 @@ module EventMachine
58
65
  }
59
66
  end
60
67
 
68
+ # Set the value for a given key
69
+ #
70
+ # cache.set :a, 'hello'
71
+ # cache.set(:missing, 'abc'){ puts "stored the value!" }
72
+ #
61
73
  def set key, val, exptime = 0, &cb
62
74
  callback{
63
75
  val = val.to_s
@@ -68,6 +80,10 @@ module EventMachine
68
80
  }
69
81
  end
70
82
 
83
+ # Gets multiple values as a hash
84
+ #
85
+ # cache.get_hash(:a, :b, :c, :d){ |h| puts h[:a] }
86
+ #
71
87
  def get_hash *keys
72
88
  raise ArgumentError unless block_given?
73
89
 
@@ -76,6 +92,11 @@ module EventMachine
76
92
  end
77
93
  end
78
94
 
95
+ # Delete the value associated with a key
96
+ #
97
+ # cache.del :a
98
+ # cache.del(:b){ puts "deleted the value!" }
99
+ #
79
100
  def delete key, expires = 0, &cb
80
101
  callback{
81
102
  send_data "delete #{key} #{expires}#{cb ? '' : ' noreply'}\r\n"
@@ -84,7 +105,14 @@ module EventMachine
84
105
  end
85
106
  alias del delete
86
107
 
87
- def send_cmd cmd, key, flags = 0, exptime = 0, bytes = 0, noreply = false
108
+ # Connect to a memcached server (must support NOREPLY, memcached >= 1.2.4)
109
+ def self.connect host = 'localhost', port = 11211
110
+ EM.connect host, port, self, host, port
111
+ end
112
+
113
+ # :stopdoc:
114
+
115
+ def send_cmd cmd, key, flags = 0, exptime = 0, bytes = 0, noreply = false # :nodoc:
88
116
  send_data "#{cmd} #{key} #{flags} #{exptime} #{bytes}#{noreply ? ' noreply' : ''}\r\n"
89
117
  end
90
118
  private :send_cmd
@@ -92,15 +120,12 @@ module EventMachine
92
120
  ##
93
121
  # errors
94
122
 
95
- class ParserError < StandardError; end
123
+ class ParserError < StandardError
124
+ end
96
125
 
97
126
  ##
98
127
  # em hooks
99
128
 
100
- def self.connect host = 'localhost', port = 11211
101
- EM.connect host, port, self, host, port
102
- end
103
-
104
129
  def initialize host, port = 11211
105
130
  @host, @port = host, port
106
131
  end
@@ -119,6 +144,7 @@ module EventMachine
119
144
  # set_line_mode
120
145
  end
121
146
 
147
+ #--
122
148
  # 19Feb09 Switched to a custom parser, LineText2 is recursive and can cause
123
149
  # stack overflows when there is too much data.
124
150
  # include EM::P::LineText2
@@ -136,6 +162,7 @@ module EventMachine
136
162
  end
137
163
  end
138
164
 
165
+ #--
139
166
  # def receive_line line
140
167
  def process_cmd line
141
168
  case line.strip
@@ -177,6 +204,7 @@ module EventMachine
177
204
  end
178
205
  end
179
206
 
207
+ #--
180
208
  # def receive_binary_data data
181
209
  # @values[@cur_key] = data[0..-3]
182
210
  # end
@@ -191,6 +219,8 @@ module EventMachine
191
219
  raise 'Unable to connect to memcached server'
192
220
  end
193
221
  end
222
+
223
+ # :startdoc:
194
224
  end
195
225
  end
196
226
  end
@@ -199,7 +229,7 @@ if __FILE__ == $0
199
229
  # ruby -I ext:lib -r eventmachine -rubygems lib/protocols/memcache.rb
200
230
  require 'em/spec'
201
231
 
202
- class TestConnection
232
+ class TestConnection # :nodoc:
203
233
  include EM::P::Memcache
204
234
  def send_data data
205
235
  sent_data << data
@@ -0,0 +1,39 @@
1
+ module EventMachine
2
+ module Protocols
3
+ # ObjectProtocol allows for easy communication using marshaled ruby objects
4
+ #
5
+ # module RubyServer
6
+ # include EM::P::ObjectProtocol
7
+ #
8
+ # def receive_object obj
9
+ # send_object({'you said' => obj})
10
+ # end
11
+ # end
12
+ #
13
+ module ObjectProtocol
14
+ def receive_data data # :nodoc:
15
+ (@buf ||= '') << data
16
+
17
+ while @buf.size >= 4
18
+ if @buf.size >= 4+(size=@buf.unpack('N').first)
19
+ @buf.slice!(0,4)
20
+ receive_object Marshal.load(@buf.slice!(0,size))
21
+ else
22
+ break
23
+ end
24
+ end
25
+ end
26
+
27
+ # Invoked with ruby objects received over the network
28
+ def receive_object obj
29
+ # stub
30
+ end
31
+
32
+ # Sends a ruby object over the network
33
+ def send_object obj
34
+ data = Marshal.dump(obj)
35
+ send_data [data.respond_to?(:bytesize) ? data.bytesize : data.size, data].pack('Na*')
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,247 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 15 November 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-08 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+ #
26
+
27
+ require 'readbytes'
28
+ require 'postgres-pr/message'
29
+ require 'postgres-pr/connection'
30
+ require 'stringio'
31
+
32
+ class StringIO # :nodoc:
33
+ # Reads exactly +n+ bytes.
34
+ #
35
+ # If the data read is nil an EOFError is raised.
36
+ #
37
+ # If the data read is too short a TruncatedDataError is raised and the read
38
+ # data is obtainable via its #data method.
39
+ def readbytes(n)
40
+ str = read(n)
41
+ if str == nil
42
+ raise EOFError, "End of file reached"
43
+ end
44
+ if str.size < n
45
+ raise TruncatedDataError.new("data truncated", str)
46
+ end
47
+ str
48
+ end
49
+ alias read_exactly_n_bytes readbytes
50
+ end
51
+
52
+
53
+ module EventMachine
54
+ module Protocols
55
+ # PROVISIONAL IMPLEMENTATION of an evented Postgres client.
56
+ # This implements version 3 of the Postgres wire protocol, which will work
57
+ # with any Postgres version from roughly 7.4 onward.
58
+ #
59
+ # Objective: we want to access Postgres databases without requiring threads.
60
+ # Until now this has been a problem because the Postgres client implementations
61
+ # have all made use of blocking I/O calls, which is incompatible with a
62
+ # thread-free evented model.
63
+ #
64
+ # But rather than re-implement the Postgres Wire3 protocol, we're taking advantage
65
+ # of the existing postgres-pr library, which was originally written by Michael
66
+ # Neumann but (at this writing) appears to be no longer maintained. Still, it's
67
+ # in basically a production-ready state, and the wire protocol isn't that complicated
68
+ # anyway.
69
+ #
70
+ # We need to monkeypatch StringIO because it lacks the #readbytes method needed
71
+ # by postgres-pr.
72
+ #
73
+ # We're tucking in a bunch of require statements that may not be present in garden-variety
74
+ # EM installations. Until we find a good way to only require these if a program
75
+ # requires postgres, this file will need to be required explicitly.
76
+ #
77
+ # The StringIO monkeypatch is lifted verbatim from the standard library readbytes.rb,
78
+ # which adds method #readbytes directly to class IO. But StringIO is not a subclass of IO.
79
+ #
80
+ # We cloned the handling of postgres messages from lib/postgres-pr/connection.rb
81
+ # in the postgres-pr library, and modified it for event-handling.
82
+ #
83
+ # TODO: The password handling in dispatch_conn_message is totally incomplete.
84
+ #
85
+ #
86
+ # We return Deferrables from the user-level operations surfaced by this interface.
87
+ # Experimentally, we're using the pattern of always returning a boolean value as the
88
+ # first argument of a deferrable callback to indicate success or failure. This is
89
+ # instead of the traditional pattern of calling Deferrable#succeed or #fail, and
90
+ # requiring the user to define both a callback and an errback function.
91
+ #
92
+ # === Usage
93
+ # EM.run {
94
+ # db = EM.connect_unix_domain( "/tmp/.s.PGSQL.5432", EM::P::Postgres3 )
95
+ # db.connect( dbname, username, psw ).callback do |status|
96
+ # if status
97
+ # db.query( "select * from some_table" ).callback do |status, result, errors|
98
+ # if status
99
+ # result.rows.each do |row|
100
+ # p row
101
+ # end
102
+ # end
103
+ # end
104
+ # end
105
+ # end
106
+ # }
107
+ class Postgres3 < EventMachine::Connection
108
+ include PostgresPR
109
+
110
+ def initialize
111
+ @data = ""
112
+ @params = {}
113
+ end
114
+
115
+ def connect db, user, psw=nil
116
+ d = EM::DefaultDeferrable.new
117
+ d.timeout 15
118
+
119
+ if @pending_query || @pending_conn
120
+ d.succeed false, "Operation already in progress"
121
+ else
122
+ @pending_conn = d
123
+ prms = {"user"=>user, "database"=>db}
124
+ @user = user
125
+ if psw
126
+ @password = psw
127
+ #prms["password"] = psw
128
+ end
129
+ send_data PostgresPR::StartupMessage.new( 3 << 16, prms ).dump
130
+ end
131
+
132
+ d
133
+ end
134
+
135
+ def query sql
136
+ d = EM::DefaultDeferrable.new
137
+ d.timeout 15
138
+
139
+ if @pending_query || @pending_conn
140
+ d.succeed false, "Operation already in progress"
141
+ else
142
+ @r = PostgresPR::Connection::Result.new
143
+ @e = []
144
+ @pending_query = d
145
+ send_data PostgresPR::Query.dump(sql)
146
+ end
147
+
148
+ d
149
+ end
150
+
151
+
152
+ def receive_data data
153
+ @data << data
154
+ while @data.length >= 5
155
+ pktlen = @data[1...5].unpack("N").first
156
+ if @data.length >= (1 + pktlen)
157
+ pkt = @data.slice!(0...(1+pktlen))
158
+ m = StringIO.open( pkt, "r" ) {|io| PostgresPR::Message.read( io ) }
159
+ if @pending_conn
160
+ dispatch_conn_message m
161
+ elsif @pending_query
162
+ dispatch_query_message m
163
+ else
164
+ raise "Unexpected message from database"
165
+ end
166
+ else
167
+ break # very important, break out of the while
168
+ end
169
+ end
170
+ end
171
+
172
+
173
+ def unbind
174
+ if o = (@pending_query || @pending_conn)
175
+ o.succeed false, "lost connection"
176
+ end
177
+ end
178
+
179
+ # Cloned and modified from the postgres-pr.
180
+ def dispatch_conn_message msg
181
+ case msg
182
+ when AuthentificationClearTextPassword
183
+ raise ArgumentError, "no password specified" if @password.nil?
184
+ send_data PasswordMessage.new(@password).dump
185
+
186
+ when AuthentificationCryptPassword
187
+ raise ArgumentError, "no password specified" if @password.nil?
188
+ send_data PasswordMessage.new(@password.crypt(msg.salt)).dump
189
+
190
+ when AuthentificationMD5Password
191
+ raise ArgumentError, "no password specified" if @password.nil?
192
+ require 'digest/md5'
193
+
194
+ m = Digest::MD5.hexdigest(@password + @user)
195
+ m = Digest::MD5.hexdigest(m + msg.salt)
196
+ m = 'md5' + m
197
+ send_data PasswordMessage.new(m).dump
198
+
199
+ when AuthentificationKerberosV4, AuthentificationKerberosV5, AuthentificationSCMCredential
200
+ raise "unsupported authentification"
201
+
202
+ when AuthentificationOk
203
+ when ErrorResponse
204
+ raise msg.field_values.join("\t")
205
+ when NoticeResponse
206
+ @notice_processor.call(msg) if @notice_processor
207
+ when ParameterStatus
208
+ @params[msg.key] = msg.value
209
+ when BackendKeyData
210
+ # TODO
211
+ #p msg
212
+ when ReadyForQuery
213
+ # TODO: use transaction status
214
+ pc,@pending_conn = @pending_conn,nil
215
+ pc.succeed true
216
+ else
217
+ raise "unhandled message type"
218
+ end
219
+ end
220
+
221
+ # Cloned and modified from the postgres-pr.
222
+ def dispatch_query_message msg
223
+ case msg
224
+ when DataRow
225
+ @r.rows << msg.columns
226
+ when CommandComplete
227
+ @r.cmd_tag = msg.cmd_tag
228
+ when ReadyForQuery
229
+ pq,@pending_query = @pending_query,nil
230
+ pq.succeed true, @r, @e
231
+ when RowDescription
232
+ @r.fields = msg.fields
233
+ when CopyInResponse
234
+ when CopyOutResponse
235
+ when EmptyQueryResponse
236
+ when ErrorResponse
237
+ # TODO
238
+ @e << msg
239
+ when NoticeResponse
240
+ @notice_processor.call(msg) if @notice_processor
241
+ else
242
+ # TODO
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end