xmpp4r 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/ChangeLog +12 -0
  2. data/Rakefile +2 -4
  3. data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +6 -6
  4. data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +3 -3
  5. data/data/doc/xmpp4r/examples/advanced/minimuc.rb +5 -5
  6. data/data/doc/xmpp4r/examples/advanced/xmpping.rb +17 -4
  7. data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +5 -0
  8. data/data/doc/xmpp4r/examples/basic/echo_threaded.rb +6 -2
  9. data/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +13 -0
  10. data/lib/xmpp4r.rb +0 -6
  11. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +6 -7
  12. data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +5 -6
  13. data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +3 -5
  14. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +1 -1
  15. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +10 -8
  16. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +3 -5
  17. data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +11 -17
  18. data/lib/xmpp4r/bytestreams/iq/si.rb +13 -32
  19. data/lib/xmpp4r/callbacks.rb +124 -0
  20. data/lib/xmpp4r/client.rb +2 -5
  21. data/lib/xmpp4r/command/helper/responder.rb +53 -0
  22. data/lib/xmpp4r/command/iq/command.rb +154 -0
  23. data/lib/xmpp4r/connection.rb +49 -12
  24. data/lib/xmpp4r/dataforms/x/data.rb +66 -29
  25. data/lib/xmpp4r/delay/x/delay.rb +2 -3
  26. data/lib/xmpp4r/discovery/iq/discoinfo.rb +20 -33
  27. data/lib/xmpp4r/discovery/iq/discoitems.rb +5 -28
  28. data/lib/xmpp4r/error.rb +5 -10
  29. data/lib/xmpp4r/feature_negotiation/iq/feature.rb +2 -20
  30. data/lib/xmpp4r/httpbinding.rb +5 -0
  31. data/lib/xmpp4r/httpbinding/client.rb +285 -0
  32. data/lib/xmpp4r/iq.rb +22 -41
  33. data/lib/xmpp4r/message.rb +8 -38
  34. data/lib/xmpp4r/muc.rb +2 -0
  35. data/lib/xmpp4r/muc/helper/mucclient.rb +50 -1
  36. data/lib/xmpp4r/muc/helper/simplemucclient.rb +2 -2
  37. data/lib/xmpp4r/muc/iq/mucowner.rb +11 -0
  38. data/lib/xmpp4r/muc/x/muc.rb +2 -30
  39. data/lib/xmpp4r/muc/x/mucuserinvite.rb +4 -2
  40. data/lib/xmpp4r/muc/x/mucuseritem.rb +4 -2
  41. data/lib/xmpp4r/presence.rb +7 -35
  42. data/lib/xmpp4r/pubsub.rb +1 -0
  43. data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +174 -0
  44. data/lib/xmpp4r/pubsub/helper/nodehelper.rb +153 -0
  45. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +326 -0
  46. data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  47. data/lib/xmpp4r/pubsub/stanzas/event.rb +49 -0
  48. data/lib/xmpp4r/pubsub/stanzas/item.rb +27 -0
  49. data/lib/xmpp4r/pubsub/stanzas/items.rb +35 -0
  50. data/lib/xmpp4r/pubsub/stanzas/subscription.rb +58 -0
  51. data/lib/xmpp4r/query.rb +4 -32
  52. data/lib/xmpp4r/rexmladdons.rb +7 -772
  53. data/lib/xmpp4r/roster/helper/roster.rb +29 -50
  54. data/lib/xmpp4r/roster/iq/roster.rb +6 -35
  55. data/lib/xmpp4r/roster/x/roster.rb +13 -30
  56. data/lib/xmpp4r/rpc.rb +2 -0
  57. data/lib/xmpp4r/rpc/helper/client.rb +114 -0
  58. data/lib/xmpp4r/rpc/helper/server.rb +75 -0
  59. data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +57 -0
  60. data/lib/xmpp4r/rpc/iq/rpc.rb +24 -0
  61. data/lib/xmpp4r/sasl.rb +1 -1
  62. data/lib/xmpp4r/semaphore.rb +38 -0
  63. data/lib/xmpp4r/stream.rb +104 -165
  64. data/lib/xmpp4r/streamparser.rb +2 -2
  65. data/lib/xmpp4r/vcard/iq/vcard.rb +5 -12
  66. data/lib/xmpp4r/version/helper/responder.rb +2 -1
  67. data/lib/xmpp4r/version/iq/version.rb +6 -18
  68. data/lib/xmpp4r/x.rb +20 -26
  69. data/lib/xmpp4r/xmpp4r.rb +1 -1
  70. data/lib/xmpp4r/xmppelement.rb +152 -0
  71. data/lib/xmpp4r/{xmlstanza.rb → xmppstanza.rb} +17 -29
  72. data/setup.rb +1 -0
  73. data/test/bytestreams/tc_ibb.rb +8 -8
  74. data/test/dataforms/tc_data.rb +81 -0
  75. data/test/lib/clienttester.rb +20 -17
  76. data/test/muc/tc_muc_mucclient.rb +48 -23
  77. data/test/muc/tc_muc_simplemucclient.rb +7 -4
  78. data/test/muc/tc_mucowner.rb +50 -0
  79. data/test/pubsub/tc_helper.rb +227 -0
  80. data/test/roster/tc_helper.rb +181 -55
  81. data/test/roster/tc_iqqueryroster.rb +33 -0
  82. data/test/roster/tc_xroster.rb +6 -3
  83. data/test/rpc/tc_helper.rb +84 -0
  84. data/test/tc_callbacks.rb +2 -1
  85. data/test/tc_class_names.rb +9 -1
  86. data/test/tc_error.rb +1 -0
  87. data/test/tc_iq.rb +13 -12
  88. data/test/tc_message.rb +1 -0
  89. data/test/tc_presence.rb +1 -0
  90. data/test/tc_rexml.rb +1 -1
  91. data/test/tc_stream.rb +147 -102
  92. data/test/tc_streamComponent.rb +94 -0
  93. data/test/tc_streamError.rb +67 -29
  94. data/test/tc_streamSend.rb +1 -1
  95. data/test/tc_xmppstanza.rb +125 -0
  96. data/test/ts_xmpp4r.rb +37 -28
  97. data/test/version/tc_helper.rb +14 -0
  98. data/test/version/tc_iqqueryversion.rb +4 -3
  99. metadata +163 -123
  100. data/data/doc/xmpp4r/examples/basic/echo_nonthreaded.rb +0 -32
  101. data/lib/callbacks.rb +0 -122
  102. data/test/tc_streamThreaded.rb +0 -168
  103. data/test/tc_xmlstanza.rb +0 -76
@@ -0,0 +1,57 @@
1
+ require "xmlrpc/parser"
2
+ require "xmlrpc/create"
3
+ require "xmlrpc/config"
4
+ require "xmlrpc/utils" # ParserWriterChooseMixin
5
+
6
+
7
+ module XMLRPC
8
+ class Create
9
+ ##
10
+ # create a Method Call
11
+ # name:: [String] name of the method
12
+ # params:: [Array] params of the method as a array
13
+ def methodCall(name, *params)
14
+ name = name.to_s
15
+
16
+ if name !~ /[a-zA-Z0-9_.:\/]+/
17
+ raise ArgumentError, "Wrong XML-RPC method-name"
18
+ end
19
+
20
+ parameter = params.collect { |param|
21
+ @writer.ele("param", conv2value(param))
22
+ }
23
+
24
+ tree = @writer.document(
25
+ @writer.ele("methodCall",
26
+ @writer.tag("methodName", name),
27
+ @writer.ele("params", *parameter)
28
+ )
29
+ )
30
+
31
+ @writer.document_to_str(tree) + "\n"
32
+ end
33
+ ##
34
+ # create a response to a method call
35
+ # is_ret:: [TrueClass] is this a return (true) or a error (false)
36
+ # params:: [Array] a array of params
37
+
38
+ def methodResponse(is_ret, *params)
39
+
40
+ if is_ret
41
+ resp = params.collect do |param|
42
+ @writer.ele("param", conv2value(param))
43
+ end
44
+
45
+ resp = [@writer.ele("params", *resp)]
46
+ else
47
+ if params.size != 1 or params[0] === XMLRPC::FaultException
48
+ raise ArgumentError, "no valid fault-structure given"
49
+ end
50
+ resp = @writer.ele("fault", conv2value(params[0].to_h))
51
+ end
52
+
53
+ tree = @writer.document(@writer.ele("methodResponse", resp))
54
+ @writer.document_to_str(tree) + "\n"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,24 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ require 'xmpp4r/query'
6
+
7
+ module Jabber
8
+ module RPC
9
+ class IqQueryRPC < IqQuery
10
+ NS_RPC = 'jabber:iq:rpc'
11
+ name_xmlns 'query', NS_RPC
12
+
13
+ # TODO: Is typed_add with a String right here?
14
+ def typed_add(e)
15
+ if e.kind_of? String
16
+ typed_add(REXML::Document.new(e).root)
17
+ else
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
@@ -57,7 +57,7 @@ module Jabber
57
57
  def auth(password)
58
58
  auth_text = "#{@stream.jid.strip}\x00#{@stream.jid.node}\x00#{password}"
59
59
  error = nil
60
- @stream.send(generate_auth('PLAIN', Base64::encode64(auth_text).strip)) { |reply|
60
+ @stream.send(generate_auth('PLAIN', Base64::encode64(auth_text).gsub(/\s/, ''))) { |reply|
61
61
  if reply.name != 'success'
62
62
  error = reply.first_element(nil).name
63
63
  end
@@ -0,0 +1,38 @@
1
+ # =XMPP4R - XMPP Library for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/xmpp4r/
4
+
5
+ module Jabber
6
+ ##
7
+ # This class implements semaphore for threads synchronization.
8
+ class Semaphore
9
+
10
+ ##
11
+ # Initialize new semaphore
12
+ #
13
+ # val:: [Integer] number of threads, that can enter to section
14
+ def initialize(val=0)
15
+ @tickets = val
16
+ @lock = Mutex.new
17
+ @cond = ConditionVariable.new
18
+ end
19
+
20
+ ##
21
+ # Waits until are available some free tickets
22
+ def wait
23
+ @lock.synchronize {
24
+ @cond.wait(@lock) while !(@tickets > 0)
25
+ @tickets -= 1
26
+ }
27
+ end
28
+
29
+ ##
30
+ # Unlocks guarded section, increments number of free tickets
31
+ def run
32
+ @lock.synchronize {
33
+ @tickets += 1
34
+ @cond.signal
35
+ }
36
+ end
37
+ end
38
+ end
@@ -2,10 +2,10 @@
2
2
  # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
3
  # Website::http://home.gna.org/xmpp4r/
4
4
 
5
- require 'callbacks'
5
+ require 'xmpp4r/callbacks'
6
6
  require 'socket'
7
7
  require 'thread'
8
- Thread::abort_on_exception = true
8
+ require 'xmpp4r/semaphore'
9
9
  require 'xmpp4r/streamparser'
10
10
  require 'xmpp4r/presence'
11
11
  require 'xmpp4r/message'
@@ -40,6 +40,9 @@ module Jabber
40
40
  # Create a new stream
41
41
  # (just initializes)
42
42
  def initialize(threaded = true)
43
+ unless threaded
44
+ raise "Non-threaded mode was removed from XMPP4R."
45
+ end
43
46
  @fd = nil
44
47
  @status = DISCONNECTED
45
48
  @xmlcbs = CallbackList::new
@@ -47,20 +50,15 @@ module Jabber
47
50
  @messagecbs = CallbackList::new
48
51
  @iqcbs = CallbackList::new
49
52
  @presencecbs = CallbackList::new
50
- unless threaded
51
- $stderr.puts "Non-threaded mode is currently broken, re-enabling threaded"
52
- threaded = true
53
- end
54
- @threaded = threaded
55
- @stanzaqueue = []
56
- @stanzaqueue_lock = Mutex::new
53
+ @send_lock = Mutex.new
54
+ @last_send = Time.now
57
55
  @exception_block = nil
58
56
  @threadblocks = []
59
- # @pollCounter = 10
60
- @waiting_thread = nil
61
57
  @wakeup_thread = nil
62
58
  @streamid = nil
63
- @features_lock = Mutex.new
59
+ @streamns = 'jabber:client'
60
+ @features_sem = Semaphore.new
61
+ @parser_thread = nil
64
62
  end
65
63
 
66
64
  ##
@@ -71,36 +69,42 @@ module Jabber
71
69
 
72
70
  @fd = fd
73
71
  @parser = StreamParser.new(@fd, self)
74
- @parserThread = Thread.new do
72
+ @parser_thread = Thread.new do
73
+ Thread.current.abort_on_exception = true
75
74
  begin
76
75
  @parser.parse
76
+ Jabber::debuglog("DISCONNECTED\n")
77
+
78
+ if @exception_block
79
+ Thread.new { close!; @exception_block.call(nil, self, :disconnected) }
80
+ else
81
+ close!
82
+ end
77
83
  rescue Exception => e
78
84
  Jabber::debuglog("EXCEPTION:\n#{e.class}\n#{e.message}\n#{e.backtrace.join("\n")}")
79
85
 
80
86
  if @exception_block
81
- Thread.new { close; @exception_block.call(e, self, :start) }
87
+ Thread.new do
88
+ Thread.current.abort_on_exception = true
89
+ close
90
+ @exception_block.call(e, self, :start)
91
+ end
82
92
  else
83
- puts "Exception caught in Parser thread!"
84
- close
93
+ if Jabber::debug
94
+ puts "Exception caught in Parser thread! (#{e.class})"
95
+ puts e.backtrace
96
+ end
97
+ close!
85
98
  raise
86
99
  end
87
100
  end
88
101
  end
89
- # @pollThread = Thread.new do
90
- # begin
91
- # poll
92
- # rescue
93
- # puts "Exception caught in Poll thread, dumping backtrace and" +
94
- # " exiting...\n" + $!.exception + "\n"
95
- # puts $!.backtrace
96
- # exit
97
- # end
98
- # end
102
+
99
103
  @status = CONNECTED
100
104
  end
101
105
 
102
106
  def stop
103
- @parserThread.kill
107
+ @parser_thread.kill
104
108
  @parser = nil
105
109
  end
106
110
 
@@ -126,10 +130,11 @@ module Jabber
126
130
  # to commit suicide(???)
127
131
  if @exception_block
128
132
  # New thread, because close will kill the current thread
129
- Thread.new {
133
+ Thread.new do
134
+ Thread.current.abort_on_exception = true
130
135
  close
131
136
  @exception_block.call(e, self, :parser)
132
- }
137
+ end
133
138
  else
134
139
  puts "Stream#parse_failure was called by XML parser. Dumping " +
135
140
  "backtrace...\n" + e.exception + "\n"
@@ -143,10 +148,11 @@ module Jabber
143
148
  # This method is called by the parser upon receiving <tt></stream:stream></tt>
144
149
  def parser_end
145
150
  if @exception_block
146
- Thread.new {
151
+ Thread.new do
152
+ Thread.current.abort_on_exception = true
147
153
  close
148
154
  @exception_block.call(nil, self, :close)
149
- }
155
+ end
150
156
  else
151
157
  close
152
158
  end
@@ -171,30 +177,31 @@ module Jabber
171
177
  # Processes a received REXML::Element and executes
172
178
  # registered thread blocks and filters against it.
173
179
  #
174
- # If in threaded mode, a new thread will be spawned
175
- # for the call to receive_nonthreaded.
176
180
  # element:: [REXML::Element] The received element
177
181
  def receive(element)
178
- if @threaded
179
- # Don't spawn a new thread here. An implicit feature
180
- # of XMPP is constant order of stanzas.
181
- receive_nonthreaded(element)
182
- else
183
- receive_nonthreaded(element)
184
- end
185
- end
186
-
187
- def receive_nonthreaded(element)
188
182
  Jabber::debuglog("RECEIVED:\n#{element.to_s}")
183
+
184
+ if element.namespace('').to_s == '' # REXML namespaces are always strings
185
+ element.add_namespace(@streamns)
186
+ end
187
+
189
188
  case element.prefix
190
189
  when 'stream'
191
190
  case element.name
192
191
  when 'stream'
193
192
  stanza = element
194
193
  @streamid = element.attributes['id']
194
+ @streamns = element.namespace('') if element.namespace('')
195
+
196
+ # Hack: component streams are basically client streams.
197
+ # Someday we may want to create special stanza classes
198
+ # for components/s2s deriving from normal stanzas but
199
+ # posessing these namespaces
200
+ @streamns = 'jabber:client' if @streamns == 'jabber:component:accept'
201
+
195
202
  unless element.attributes['version'] # isn't XMPP compliant, so
196
203
  Jabber::debuglog("FEATURES: server not XMPP compliant, will not wait for features")
197
- @features_lock.unlock # don't wait for <stream:features/>
204
+ @features_sem.run # don't wait for <stream:features/>
198
205
  end
199
206
  when 'features'
200
207
  stanza = element
@@ -208,20 +215,16 @@ module Jabber
208
215
  end
209
216
  }
210
217
  Jabber::debuglog("FEATURES: received")
211
- @features_lock.unlock
218
+ @features_sem.run
212
219
  else
213
220
  stanza = element
214
221
  end
215
222
  else
216
- case element.name
217
- when 'message'
218
- stanza = Message::import(element)
219
- when 'iq'
220
- stanza = Iq::import(element)
221
- when 'presence'
222
- stanza = Presence::import(element)
223
- else
224
- stanza = element
223
+ # Any stanza, classes are registered by XMPPElement::name_xmlns
224
+ begin
225
+ stanza = XMPPStanza::import(element)
226
+ rescue NoNameXmlnsRegistered
227
+ stanza = element
225
228
  end
226
229
  end
227
230
 
@@ -251,23 +254,7 @@ module Jabber
251
254
  end
252
255
  }
253
256
 
254
- if @threaded
255
- process_one(stanza)
256
- else
257
- # stanzaqueue will be read when the user call process
258
- @stanzaqueue_lock.lock
259
- @stanzaqueue.push(stanza)
260
- @stanzaqueue_lock.unlock
261
- @waiting_thread.wakeup if @waiting_thread
262
- end
263
- end
264
- private :receive_nonthreaded
265
-
266
- ##
267
- # Process |element| until it is consumed. Returns element.consumed?
268
- # element The element to process
269
- def process_one(stanza)
270
- Jabber::debuglog("PROCESSING:\n#{stanza.to_s}")
257
+ Jabber::debuglog("PROCESSING:\n#{stanza.to_s} (#{stanza.class})")
271
258
  return true if @xmlcbs.process(stanza)
272
259
  return true if @stanzacbs.process(stanza)
273
260
  case stanza
@@ -279,61 +266,6 @@ module Jabber
279
266
  return true if @presencecbs.process(stanza)
280
267
  end
281
268
  end
282
- private :process_one
283
-
284
- ##
285
- # Process |max| XML stanzas and call listeners for all of them.
286
- #
287
- # max:: [Integer] the number of stanzas to process (nil means process
288
- # all available)
289
- def process(max = nil)
290
- n = 0
291
- @stanzaqueue_lock.lock
292
- while @stanzaqueue.size > 0 and (max == nil or n < max)
293
- e = @stanzaqueue.shift
294
- @stanzaqueue_lock.unlock
295
- process_one(e)
296
- n += 1
297
- @stanzaqueue_lock.lock
298
- end
299
- @stanzaqueue_lock.unlock
300
- n
301
- end
302
-
303
- ##
304
- # Process an XML stanza and call the listeners for it. If no stanza is
305
- # currently available, wait for max |time| seconds before returning.
306
- #
307
- # time:: [Integer] time to wait in seconds. If nil, wait infinitely.
308
- # all available)
309
- def wait_and_process(time = nil)
310
- if time == 0
311
- return process(1)
312
- end
313
- @stanzaqueue_lock.lock
314
- if @stanzaqueue.size > 0
315
- e = @stanzaqueue.shift
316
- @stanzaqueue_lock.unlock
317
- process_one(e)
318
- return 1
319
- end
320
-
321
- @waiting_thread = Thread.current
322
- @wakeup_thread = Thread.new { sleep time ; @waiting_thread.wakeup if @waiting_thread }
323
- @waiting_thread.stop
324
- @wakeup_thread.kill if @wakeup_thread
325
- @wakeup_thread = nil
326
- @waiting_thread = nil
327
-
328
- @stanzaqueue_lock.lock
329
- if @stanzaqueue.size > 0
330
- e = @stanzaqueue.shift
331
- @stanzaqueue_lock.unlock
332
- process_one(e)
333
- return 1
334
- end
335
- return 0
336
- end
337
269
 
338
270
  ##
339
271
  # This is used by Jabber::Stream internally to
@@ -341,18 +273,32 @@ module Jabber
341
273
  # Stream#send.
342
274
  class ThreadBlock
343
275
  def initialize(block)
344
- @thread = Thread.current
345
276
  @block = block
277
+ @waiter = Semaphore.new
278
+ @exception = nil
346
279
  end
347
280
  def call(*args)
348
281
  @block.call(*args)
349
282
  end
283
+ def wait
284
+ @waiter.wait
285
+ raise @exception if @exception
286
+ end
350
287
  def wakeup
351
288
  # TODO: Handle threadblock removal if !alive?
352
- @thread.wakeup if @thread.alive?
289
+ @waiter.run
353
290
  end
354
291
  def raise(exception)
355
- @thread.raise(exception) if @thread.alive?
292
+ @exception = exception
293
+ @waiter.run
294
+ end
295
+ end
296
+
297
+ def send_data(data)
298
+ @send_lock.synchronize do
299
+ @last_send = Time.now
300
+ @fd << data
301
+ @fd.flush
356
302
  end
357
303
  end
358
304
 
@@ -368,31 +314,46 @@ module Jabber
368
314
  # &block:: [Block] The optional block
369
315
  def send(xml, &block)
370
316
  Jabber::debuglog("SENDING:\n#{xml}")
371
- @threadblocks.unshift(ThreadBlock.new(block)) if block
372
- Thread.critical = true # we don't want to be interupted before we stop!
317
+ @threadblocks.unshift(threadblock = ThreadBlock.new(block)) if block
373
318
  begin
374
- @fd << xml.to_s
375
- @fd.flush
319
+ # Temporarily remove stanza's namespace to
320
+ # reduce bandwidth consumption
321
+ if xml.kind_of? XMPPStanza and xml.namespace == 'jabber:client'
322
+ xml.delete_namespace
323
+ send_data(xml.to_s)
324
+ xml.add_namespace(@streamns)
325
+ else
326
+ send_data(xml.to_s)
327
+ end
376
328
  rescue Exception => e
377
329
  Jabber::debuglog("EXCEPTION:\n#{e.class}\n#{e.message}\n#{e.backtrace.join("\n")}")
378
330
 
379
- if @exception_block
380
- Thread.new { close!; @exception_block.call(e, self, :sending) }
331
+ if @exception_block
332
+ Thread.new do
333
+ Thread.current.abort_on_exception = true
334
+ close!
335
+ @exception_block.call(e, self, :sending)
336
+ end
381
337
  else
382
- puts "Exception caught while sending!"
338
+ if Jabber::debug
339
+ puts "Exception caught while sending! (#{e.class})"
340
+ puts e.backtrace
341
+ end
383
342
  close!
384
343
  raise
385
344
  end
386
345
  end
387
- Thread.critical = false
388
346
  # The parser thread might be running this (think of a callback running send())
389
347
  # If this is the case, we mustn't stop (or we would cause a deadlock)
390
- Thread.stop if block and Thread.current != @parserThread
391
- @pollCounter = 10
348
+ if block and Thread.current != @parser_thread
349
+ threadblock.wait
350
+ elsif block
351
+ Jabber::debuglog("WARNING:\nCannot stop current thread in Jabber::Stream#send because it is the parser thread!")
352
+ end
392
353
  end
393
354
 
394
355
  ##
395
- # Send an XMMP stanza with an Jabber::XMLStanza#id. The id will be
356
+ # Send an XMMP stanza with an Jabber::XMPPStanza#id. The id will be
396
357
  # generated by Jabber::IdGenerator if not already set.
397
358
  #
398
359
  # The block will be called once: when receiving a stanza with the
@@ -407,7 +368,7 @@ module Jabber
407
368
  # Please see Stream#send for some implementational details.
408
369
  #
409
370
  # Please read the note about nesting at Stream#send
410
- # xml:: [XMLStanza]
371
+ # xml:: [XMPPStanza]
411
372
  def send_with_id(xml, &block)
412
373
  if xml.id.nil?
413
374
  xml.id = Jabber::IdGenerator.instance.generate_id
@@ -416,7 +377,7 @@ module Jabber
416
377
  res = nil
417
378
  error = nil
418
379
  send(xml) do |received|
419
- if received.kind_of? XMLStanza and received.id == xml.id
380
+ if received.kind_of? XMPPStanza and received.id == xml.id
420
381
  if received.type == :error
421
382
  error = (received.error ? received.error : Error.new)
422
383
  true
@@ -436,27 +397,6 @@ module Jabber
436
397
  res
437
398
  end
438
399
 
439
- ##
440
- # Starts a polling thread to send "keep alive" data to prevent
441
- # the Jabber connection from closing for inactivity.
442
- #
443
- # Currently not working!
444
- def poll
445
- sleep 10
446
- while true
447
- sleep 2
448
- # @pollCounter = @pollCounter - 1
449
- # if @pollCounter < 0
450
- # begin
451
- # send(" \t ")
452
- # rescue
453
- # Thread.new {@exception_block.call if @exception_block}
454
- # break
455
- # end
456
- # end
457
- end
458
- end
459
-
460
400
  ##
461
401
  # Adds a callback block to process received XML messages
462
402
  #
@@ -554,8 +494,7 @@ module Jabber
554
494
  end
555
495
 
556
496
  def close!
557
- @parserThread.kill if @parserThread
558
- # @pollThread.kill
497
+ @parser_thread.kill if @parser_thread
559
498
  @fd.close if @fd and !@fd.closed?
560
499
  @status = DISCONNECTED
561
500
  end