vines 0.1.0

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 (119) hide show
  1. data/LICENSE +19 -0
  2. data/README +34 -0
  3. data/Rakefile +55 -0
  4. data/bin/vines +95 -0
  5. data/conf/certs/README +32 -0
  6. data/conf/certs/ca-bundle.crt +3987 -0
  7. data/conf/config.rb +114 -0
  8. data/lib/vines.rb +155 -0
  9. data/lib/vines/command/bcrypt.rb +12 -0
  10. data/lib/vines/command/cert.rb +49 -0
  11. data/lib/vines/command/init.rb +58 -0
  12. data/lib/vines/command/ldap.rb +35 -0
  13. data/lib/vines/command/restart.rb +12 -0
  14. data/lib/vines/command/schema.rb +24 -0
  15. data/lib/vines/command/start.rb +28 -0
  16. data/lib/vines/command/stop.rb +18 -0
  17. data/lib/vines/config.rb +191 -0
  18. data/lib/vines/contact.rb +99 -0
  19. data/lib/vines/daemon.rb +78 -0
  20. data/lib/vines/error.rb +150 -0
  21. data/lib/vines/jid.rb +56 -0
  22. data/lib/vines/kit.rb +23 -0
  23. data/lib/vines/router.rb +125 -0
  24. data/lib/vines/stanza.rb +55 -0
  25. data/lib/vines/stanza/iq.rb +50 -0
  26. data/lib/vines/stanza/iq/auth.rb +18 -0
  27. data/lib/vines/stanza/iq/disco_info.rb +25 -0
  28. data/lib/vines/stanza/iq/disco_items.rb +23 -0
  29. data/lib/vines/stanza/iq/error.rb +16 -0
  30. data/lib/vines/stanza/iq/ping.rb +16 -0
  31. data/lib/vines/stanza/iq/query.rb +10 -0
  32. data/lib/vines/stanza/iq/result.rb +16 -0
  33. data/lib/vines/stanza/iq/roster.rb +153 -0
  34. data/lib/vines/stanza/iq/session.rb +22 -0
  35. data/lib/vines/stanza/iq/vcard.rb +58 -0
  36. data/lib/vines/stanza/message.rb +41 -0
  37. data/lib/vines/stanza/presence.rb +119 -0
  38. data/lib/vines/stanza/presence/error.rb +23 -0
  39. data/lib/vines/stanza/presence/probe.rb +38 -0
  40. data/lib/vines/stanza/presence/subscribe.rb +66 -0
  41. data/lib/vines/stanza/presence/subscribed.rb +64 -0
  42. data/lib/vines/stanza/presence/unavailable.rb +15 -0
  43. data/lib/vines/stanza/presence/unsubscribe.rb +57 -0
  44. data/lib/vines/stanza/presence/unsubscribed.rb +50 -0
  45. data/lib/vines/storage.rb +216 -0
  46. data/lib/vines/storage/couchdb.rb +119 -0
  47. data/lib/vines/storage/ldap.rb +59 -0
  48. data/lib/vines/storage/local.rb +66 -0
  49. data/lib/vines/storage/redis.rb +108 -0
  50. data/lib/vines/storage/sql.rb +174 -0
  51. data/lib/vines/store.rb +51 -0
  52. data/lib/vines/stream.rb +198 -0
  53. data/lib/vines/stream/client.rb +131 -0
  54. data/lib/vines/stream/client/auth.rb +94 -0
  55. data/lib/vines/stream/client/auth_restart.rb +33 -0
  56. data/lib/vines/stream/client/bind.rb +58 -0
  57. data/lib/vines/stream/client/bind_restart.rb +25 -0
  58. data/lib/vines/stream/client/closed.rb +13 -0
  59. data/lib/vines/stream/client/ready.rb +15 -0
  60. data/lib/vines/stream/client/start.rb +27 -0
  61. data/lib/vines/stream/client/tls.rb +37 -0
  62. data/lib/vines/stream/component.rb +53 -0
  63. data/lib/vines/stream/component/handshake.rb +25 -0
  64. data/lib/vines/stream/component/ready.rb +24 -0
  65. data/lib/vines/stream/component/start.rb +19 -0
  66. data/lib/vines/stream/http.rb +111 -0
  67. data/lib/vines/stream/http/http_request.rb +22 -0
  68. data/lib/vines/stream/http/http_state.rb +139 -0
  69. data/lib/vines/stream/http/http_states.rb +53 -0
  70. data/lib/vines/stream/parser.rb +78 -0
  71. data/lib/vines/stream/server.rb +126 -0
  72. data/lib/vines/stream/server/auth.rb +13 -0
  73. data/lib/vines/stream/server/auth_restart.rb +19 -0
  74. data/lib/vines/stream/server/final_restart.rb +20 -0
  75. data/lib/vines/stream/server/outbound/auth.rb +31 -0
  76. data/lib/vines/stream/server/outbound/auth_restart.rb +20 -0
  77. data/lib/vines/stream/server/outbound/auth_result.rb +28 -0
  78. data/lib/vines/stream/server/outbound/final_features.rb +27 -0
  79. data/lib/vines/stream/server/outbound/final_restart.rb +20 -0
  80. data/lib/vines/stream/server/outbound/start.rb +20 -0
  81. data/lib/vines/stream/server/outbound/tls.rb +30 -0
  82. data/lib/vines/stream/server/outbound/tls_result.rb +31 -0
  83. data/lib/vines/stream/server/ready.rb +20 -0
  84. data/lib/vines/stream/server/start.rb +13 -0
  85. data/lib/vines/stream/server/tls.rb +13 -0
  86. data/lib/vines/stream/state.rb +55 -0
  87. data/lib/vines/token_bucket.rb +46 -0
  88. data/lib/vines/user.rb +124 -0
  89. data/lib/vines/version.rb +5 -0
  90. data/lib/vines/xmpp_server.rb +25 -0
  91. data/test/config_test.rb +396 -0
  92. data/test/error_test.rb +59 -0
  93. data/test/ext/nokogiri.rb +14 -0
  94. data/test/jid_test.rb +71 -0
  95. data/test/kit_test.rb +21 -0
  96. data/test/router_test.rb +60 -0
  97. data/test/stanza/iq/roster_test.rb +198 -0
  98. data/test/stanza/iq/session_test.rb +30 -0
  99. data/test/stanza/iq/vcard_test.rb +159 -0
  100. data/test/stanza/message_test.rb +124 -0
  101. data/test/stanza/presence/subscribe_test.rb +75 -0
  102. data/test/storage/couchdb_test.rb +102 -0
  103. data/test/storage/ldap_test.rb +207 -0
  104. data/test/storage/local_test.rb +54 -0
  105. data/test/storage/redis_test.rb +75 -0
  106. data/test/storage/sql_test.rb +55 -0
  107. data/test/storage/storage_tests.rb +134 -0
  108. data/test/storage_test.rb +90 -0
  109. data/test/stream/client/auth_test.rb +127 -0
  110. data/test/stream/client/ready_test.rb +47 -0
  111. data/test/stream/component/handshake_test.rb +46 -0
  112. data/test/stream/component/ready_test.rb +105 -0
  113. data/test/stream/component/start_test.rb +41 -0
  114. data/test/stream/parser_test.rb +121 -0
  115. data/test/stream/server/outbound/auth_test.rb +77 -0
  116. data/test/stream/server/ready_test.rb +100 -0
  117. data/test/token_bucket_test.rb +24 -0
  118. data/test/user_test.rb +64 -0
  119. metadata +318 -0
@@ -0,0 +1,28 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ module Command
5
+ class Start
6
+ def run(opts)
7
+ raise 'vines [--pid FILE] start' unless opts[:args].size == 0
8
+ require opts[:config]
9
+ server = XmppServer.new(Config.instance)
10
+ daemonize(opts) if opts[:daemonize]
11
+ server.start
12
+ end
13
+
14
+ private
15
+
16
+ def daemonize(opts)
17
+ daemon = Daemon.new(:pid => opts[:pid], :stdout => opts[:log],
18
+ :stderr => opts[:log])
19
+ if daemon.running?
20
+ raise "Vines is running as process #{daemon.pid}"
21
+ else
22
+ puts "Vines has started"
23
+ daemon.start
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ module Command
5
+ class Stop
6
+ def run(opts)
7
+ raise 'vines [--pid FILE] stop' unless opts[:args].size == 0
8
+ daemon = Daemon.new(:pid => opts[:pid])
9
+ if daemon.running?
10
+ daemon.stop
11
+ puts 'Vines has been shutdown'
12
+ else
13
+ puts 'Vines is not running'
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,191 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+
5
+ # A Config object is passed to the stream handlers to give them access
6
+ # to server configuration information like virtual host names, storage
7
+ # systems, etc. This class provides the DSL methods used in the
8
+ # config/vines.rb file.
9
+ class Config
10
+ LOG_LEVELS = %w[debug info warn error fatal].freeze
11
+
12
+ attr_reader :vhosts
13
+
14
+ @@instance = nil
15
+ def self.configure(&block)
16
+ @@instance = self.new(&block)
17
+ end
18
+
19
+ def self.instance
20
+ @@instance
21
+ end
22
+
23
+ def initialize(&block)
24
+ @vhosts, @ports = {}, {}
25
+ instance_eval(&block)
26
+ raise "must define at least one virtual host" if @vhosts.empty?
27
+ end
28
+
29
+ def host(*names, &block)
30
+ names = names.flatten.map {|name| name.downcase }
31
+ dupes = names.uniq.size != names.size || (@vhosts.keys & names).any?
32
+ raise "one host definition per domain allowed" if dupes
33
+ names.each do |name|
34
+ @vhosts.merge! Host.new(name, &block).to_hash
35
+ end
36
+ end
37
+
38
+ %w[client server http component].each do |name|
39
+ define_method(name) do |*args, &block|
40
+ port = Vines::Config.const_get("#{name.capitalize}Port")
41
+ raise "one #{name} port definition allowed" if @ports[name.to_sym]
42
+ @ports[name.to_sym] = port.new(self, *args) do
43
+ instance_eval(&block) if block
44
+ end
45
+ end
46
+ end
47
+
48
+ def log(level)
49
+ const = Logger.const_get(level.to_s.upcase) rescue nil
50
+ unless LOG_LEVELS.include?(level.to_s) && const
51
+ raise "log level must be one of: #{LOG_LEVELS.join(', ')}"
52
+ end
53
+ Class.new.extend(Vines::Log).log.level = const
54
+ end
55
+
56
+ def ports
57
+ @ports.values
58
+ end
59
+
60
+ def vhost?(domain)
61
+ @vhosts.key?(domain)
62
+ end
63
+
64
+ # Returns true if server-to-server connections are allowed with the
65
+ # given domain.
66
+ def s2s?(domain)
67
+ @ports[:server] && @ports[:server].hosts.include?(domain)
68
+ end
69
+
70
+ # Retrieve the Port subclass with this name:
71
+ # [:client, :server, :http, :component]
72
+ def [](name)
73
+ @ports[name] or raise ArgumentError.new("no port named #{name}")
74
+ end
75
+
76
+ class Host
77
+ def initialize(name, &block)
78
+ @name, @storage, @ldap = name, nil, nil
79
+ instance_eval(&block)
80
+ end
81
+
82
+ def storage(name, &block)
83
+ raise "one storage mechanism per host allowed" if @storage
84
+ @storage = Storage.from_name(name, &block)
85
+ @storage.ldap = @ldap
86
+ end
87
+
88
+ def ldap(host='localhost', port=636, &block)
89
+ @ldap = Storage::Ldap.new(host, port, &block)
90
+ @storage.ldap = @ldap if @storage
91
+ end
92
+
93
+ def to_hash
94
+ raise "storage required for #{@name}" unless @storage
95
+ {@name => @storage}
96
+ end
97
+ end
98
+
99
+ class Port
100
+ include Vines::Log
101
+
102
+ attr_reader :config, :stream
103
+
104
+ %w[host port].each do |name|
105
+ define_method(name) do
106
+ @settings[name.to_sym]
107
+ end
108
+ end
109
+
110
+ def initialize(config, host, port, &block)
111
+ @config, @settings = config, {}
112
+ instance_eval(&block) if block
113
+ defaults = {:host => host, :port => port,
114
+ :max_resources_per_account => 5, :max_stanza_size => 128 * 1024}
115
+ @settings = defaults.merge(@settings)
116
+ end
117
+
118
+ def max_stanza_size(max=nil)
119
+ if max
120
+ # rfc 6120 section 13.12
121
+ @settings[:max_stanza_size] = [10000, max].max
122
+ else
123
+ @settings[:max_stanza_size]
124
+ end
125
+ end
126
+
127
+ def start
128
+ type = stream.name.split('::').last.downcase
129
+ log.info("Accepting #{type} connections on #{host}:#{port}")
130
+ EventMachine::start_server(host, port, stream, config)
131
+ end
132
+ end
133
+
134
+ class ClientPort < Port
135
+ def initialize(config, host='0.0.0.0', port=5222, &block)
136
+ @stream = Vines::Stream::Client
137
+ super(config, host, port, &block)
138
+ end
139
+
140
+ def max_resources_per_account(max=nil)
141
+ if max
142
+ @settings[:max_resources_per_account] = max
143
+ else
144
+ @settings[:max_resources_per_account]
145
+ end
146
+ end
147
+ end
148
+
149
+ class ServerPort < Port
150
+ def initialize(config, host='0.0.0.0', port=5269, &block)
151
+ @hosts, @stream = [], Vines::Stream::Server
152
+ super(config, host, port, &block)
153
+ end
154
+
155
+ def hosts(*hosts)
156
+ if hosts.any?
157
+ @hosts << hosts
158
+ @hosts.flatten!
159
+ else
160
+ @hosts
161
+ end
162
+ end
163
+ end
164
+
165
+ class HttpPort < Port
166
+ def initialize(config, host='0.0.0.0', port=5280, &block)
167
+ @stream = Vines::Stream::Http
168
+ super(config, host, port, &block)
169
+ end
170
+ end
171
+
172
+ class ComponentPort < Port
173
+ def initialize(config, host='0.0.0.0', port=5347, &block)
174
+ @components, @stream = {}, Vines::Stream::Component
175
+ super(config, host, port, &block)
176
+ end
177
+
178
+ def components(options=nil)
179
+ if options
180
+ @components = options
181
+ else
182
+ @components
183
+ end
184
+ end
185
+
186
+ def password(component)
187
+ @components[component]
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,99 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Contact
5
+ include Comparable
6
+
7
+ attr_accessor :name, :subscription, :ask, :groups
8
+ attr_reader :jid
9
+
10
+ def initialize(args={})
11
+ @jid = JID.new(args[:jid]).bare
12
+ raise ArgumentError, 'invalid jid' unless @jid.node && !@jid.domain.empty?
13
+ @name = args[:name]
14
+ @subscription = args[:subscription] || 'none'
15
+ @ask = args[:ask]
16
+ @groups = args[:groups] || []
17
+ end
18
+
19
+ def <=>(contact)
20
+ self.jid.to_s <=> contact.jid.to_s
21
+ end
22
+
23
+ def eql?(contact)
24
+ contact.is_a?(Contact) && self == contact
25
+ end
26
+
27
+ def hash
28
+ jid.to_s.hash
29
+ end
30
+
31
+ def update_from(contact)
32
+ @name = contact.name
33
+ @subscription = contact.subscription
34
+ @ask = contact.ask
35
+ @groups = contact.groups.clone
36
+ end
37
+
38
+ # Returns true if this contact is in a state that allows the user
39
+ # to subscribe to their presence updates.
40
+ def can_subscribe?
41
+ @ask == 'subscribe' && %w[none from].include?(@subscription)
42
+ end
43
+
44
+ def subscribe_to
45
+ @subscription = (@subscription == 'none') ? 'to' : 'both'
46
+ @ask = nil
47
+ end
48
+
49
+ def unsubscribe_to
50
+ @subscription = (@subscription == 'both') ? 'from' : 'none'
51
+ end
52
+
53
+ def subscribe_from
54
+ @subscription = (@subscription == 'none') ? 'from' : 'both'
55
+ @ask = nil
56
+ end
57
+
58
+ def unsubscribe_from
59
+ @subscription = (@subscription == 'both') ? 'to' : 'none'
60
+ end
61
+
62
+ # Returns true if the user is subscribed to this contact's
63
+ # presence updates.
64
+ def subscribed_to?
65
+ %w[to both].include?(@subscription)
66
+ end
67
+
68
+ # Returns true if the user has a presence subscription from
69
+ # this contact. The contact is subscribed to this user's presence.
70
+ def subscribed_from?
71
+ %w[from both].include?(@subscription)
72
+ end
73
+
74
+ # Returns a hash of this contact's attributes suitable for persisting in
75
+ # a document store.
76
+ def to_h
77
+ {
78
+ 'name' => @name,
79
+ 'subscription' => @subscription,
80
+ 'ask' => @ask,
81
+ 'groups' => @groups.sort!
82
+ }
83
+ end
84
+
85
+ # Returns this contact as an xmpp <item> element.
86
+ def to_roster_xml
87
+ doc = Nokogiri::XML::Document.new
88
+ doc.create_element('item') do |el|
89
+ el['ask'] = @ask unless @ask.nil? || @ask.empty?
90
+ el['jid'] = @jid.bare.to_s
91
+ el['name'] = @name unless @name.nil? || @name.empty?
92
+ el['subscription'] = @subscription
93
+ @groups.sort!.each do |group|
94
+ el << doc.create_element('group', group)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,78 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+
5
+ # Fork the current process into the background and manage pid
6
+ # files so we can kill the process later.
7
+ class Daemon
8
+
9
+ # Configure a new daemon process. Arguments hash can include the following
10
+ # keys: :pid (pid file name, required),
11
+ # :stdin, :stdout, :stderr (default to /dev/null)
12
+ def initialize(args)
13
+ @pid = args[:pid]
14
+ raise ArgumentError.new('pid file is required') unless @pid
15
+ raise ArgumentError.new('pid must be a file name') if File.directory?(@pid)
16
+ raise ArgumentError.new('pid file must be writable') unless File.writable?(File.dirname(@pid))
17
+ @stdin, @stdout, @stderr = [:stdin, :stdout, :stderr].map {|k| args[k] || '/dev/null' }
18
+ end
19
+
20
+ # Fork the current process into the background to start the
21
+ # daemon. Do nothing if the daemon is already running.
22
+ def start
23
+ daemonize unless running?
24
+ end
25
+
26
+ # Use the pid stored in the pid file created from a previous
27
+ # call to start to send a TERM signal to the process. Do nothing
28
+ # if the daemon is not running.
29
+ def stop
30
+ 10.times do
31
+ break unless running?
32
+ Process.kill('TERM', pid)
33
+ sleep(0.1)
34
+ end
35
+ end
36
+
37
+ # Returns true if the process is running as determined by the numeric
38
+ # pid stored in the pid file created by a previous call to start.
39
+ def running?
40
+ begin
41
+ pid && Process.kill(0, pid)
42
+ rescue Errno::ESRCH
43
+ delete_pid
44
+ false
45
+ rescue Errno::EPERM
46
+ true
47
+ end
48
+ end
49
+
50
+ # Returns the numeric process ID from the pid file.
51
+ # If the pid file does not exist, returns nil.
52
+ def pid
53
+ File.read(@pid).to_i if File.exists?(@pid)
54
+ end
55
+
56
+ private
57
+
58
+ def delete_pid
59
+ File.delete(@pid) if File.exists?(@pid)
60
+ end
61
+
62
+ # Fork process into background twice to release it from
63
+ # the controlling tty. Point open file descriptors shared
64
+ # with the parent process to separate destinations (e.g. /dev/null).
65
+ def daemonize
66
+ exit if fork
67
+ Process.setsid
68
+ exit if fork
69
+ Dir.chdir('/')
70
+ $stdin.reopen(@stdin)
71
+ $stdout.reopen(@stdout, 'a').sync = true
72
+ $stderr.reopen(@stderr, 'a').sync = true
73
+ File.open(@pid, 'w') {|f| f.write(Process.pid) }
74
+ at_exit { delete_pid }
75
+ trap('TERM') { exit }
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,150 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class XmppError < StandardError
5
+ include Nokogiri::XML
6
+
7
+ # Returns the XML element name based on the exception class name.
8
+ # For example, Vines::BadFormat becomes bad-format.
9
+ def element_name
10
+ name = self.class.name.split('::').last
11
+ name.gsub(/([A-Z])/, '-\1').downcase[1..-1]
12
+ end
13
+ end
14
+
15
+ class SaslError < XmppError
16
+ NAMESPACE = 'urn:ietf:params:xml:ns:xmpp-sasl'.freeze
17
+
18
+ def initialize(text=nil)
19
+ @text = text
20
+ end
21
+
22
+ def to_xml
23
+ doc = Document.new
24
+ doc.create_element('failure') do |node|
25
+ node.add_namespace(nil, NAMESPACE)
26
+ node << doc.create_element(element_name)
27
+ if @text
28
+ node << doc.create_element('text') do |text|
29
+ text['xml:lang'] = 'en'
30
+ text.content = @text
31
+ end
32
+ end
33
+ end.to_xml(:indent => 0).gsub(/\n/, '')
34
+ end
35
+ end
36
+
37
+ class StreamError < XmppError
38
+ NAMESPACE = 'urn:ietf:params:xml:ns:xmpp-streams'.freeze
39
+
40
+ def initialize(text=nil)
41
+ @text = text
42
+ end
43
+
44
+ def to_xml
45
+ doc = Document.new
46
+ doc.create_element('stream:error') do |el|
47
+ el << doc.create_element(element_name, 'xmlns' => NAMESPACE)
48
+ if @text
49
+ el << doc.create_element('text', @text, 'xmlns' => NAMESPACE, 'xml:lang' => 'en')
50
+ end
51
+ end.to_xml(:indent => 0).gsub(/\n/, '')
52
+ end
53
+ end
54
+
55
+ class StanzaError < XmppError
56
+ TYPES = %w[auth cancel continue modify wait].freeze
57
+ KINDS = %w[message presence iq].freeze
58
+ NAMESPACE = 'urn:ietf:params:xml:ns:xmpp-stanzas'.freeze
59
+
60
+ def initialize(el, type, text=nil)
61
+ raise "type must be one of: %s" % TYPES.join(', ') unless TYPES.include?(type)
62
+ raise "stanza must be one of: %s" % KINDS.join(', ') unless KINDS.include?(el.name)
63
+ @stanza_kind, @type, @text = el.name, type, text
64
+ @id, @from, @to = %w[id from to].map {|a| el[a] }
65
+ end
66
+
67
+ def to_xml
68
+ doc = Document.new
69
+ doc.create_element(@stanza_kind) do |el|
70
+ el['from'] = @to if @to
71
+ el['id'] = @id if @id
72
+ el['to'] = @from if @from
73
+ el['type'] = 'error'
74
+ el << doc.create_element('error', 'type' => @type) do |error|
75
+ error << doc.create_element(element_name, 'xmlns' => NAMESPACE)
76
+ if @text
77
+ error << doc.create_element('text', @text, 'xmlns' => NAMESPACE, 'xml:lang' => 'en')
78
+ end
79
+ end
80
+ end.to_xml(:indent => 0).gsub(/\n/, '')
81
+ end
82
+ end
83
+
84
+ module SaslErrors
85
+ class Aborted < SaslError; end
86
+ class AccountDisabled < SaslError; end
87
+ class CredentialsExpired < SaslError; end
88
+ class EncryptionRequired < SaslError; end
89
+ class IncorrectEncoding < SaslError; end
90
+ class InvalidAuthzid < SaslError; end
91
+ class InvalidMechanism < SaslError; end
92
+ class MalformedRequest < SaslError; end
93
+ class MechanismTooWeak < SaslError; end
94
+ class NotAuthorized < SaslError; end
95
+ class TemporaryAuthFailure < SaslError; end
96
+ end
97
+
98
+ module StreamErrors
99
+ class BadFormat < StreamError; end
100
+ class BadNamespacePrefix < StreamError; end
101
+ class Confict < StreamError; end
102
+ class ConnectionTimeout < StreamError; end
103
+ class HostGone < StreamError; end
104
+ class HostUnknown < StreamError; end
105
+ class ImproperAddressing < StreamError; end
106
+ class InternalServerError < StreamError; end
107
+ class InvalidFrom < StreamError; end
108
+ class InvalidNamespace < StreamError; end
109
+ class InvalidXml < StreamError; end
110
+ class NotAuthorized < StreamError; end
111
+ class NotWellFormed < StreamError; end
112
+ class PolicyViolation < StreamError; end
113
+ class RemoteConnectionFailed < StreamError; end
114
+ class Reset < StreamError; end
115
+ class ResourceConstraint < StreamError; end
116
+ class RestrictedXml < StreamError; end
117
+ class SeeOtherHost < StreamError; end
118
+ class SystemShutdown < StreamError; end
119
+ class UndefinedCondition < StreamError; end
120
+ class UnsupportedEncoding < StreamError; end
121
+ class UnsupportedFeature < StreamError; end
122
+ class UnsupportedStanzaType < StreamError; end
123
+ class UnsupportedVersion < StreamError; end
124
+ end
125
+
126
+ module StanzaErrors
127
+ class BadRequest < StanzaError; end
128
+ class Conflict < StanzaError; end
129
+ class FeatureNotImplemented < StanzaError; end
130
+ class Forbidden < StanzaError; end
131
+ class Gone < StanzaError; end
132
+ class InternalServerError < StanzaError; end
133
+ class ItemNotFound < StanzaError; end
134
+ class JidMalformed < StanzaError; end
135
+ class NotAcceptable < StanzaError; end
136
+ class NotAllowed < StanzaError; end
137
+ class NotAuthorized < StanzaError; end
138
+ class PolicyViolation < StanzaError; end
139
+ class RecipientUnavailable < StanzaError; end
140
+ class Redirect < StanzaError; end
141
+ class RegistrationRequired < StanzaError; end
142
+ class RemoteServerNotFound < StanzaError; end
143
+ class RemoteServerTimeout < StanzaError; end
144
+ class ResourceConstraint < StanzaError; end
145
+ class ServiceUnavailable < StanzaError; end
146
+ class SubscriptionRequired < StanzaError; end
147
+ class UndefinedCondition < StanzaError; end
148
+ class UnexpectedRequest < StanzaError; end
149
+ end
150
+ end