vinesmod 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/Gemfile +3 -0
  2. data/LICENSE +19 -0
  3. data/README.md +43 -0
  4. data/Rakefile +57 -0
  5. data/bin/vines +93 -0
  6. data/conf/certs/README +39 -0
  7. data/conf/certs/ca-bundle.crt +3366 -0
  8. data/conf/config.rb +149 -0
  9. data/lib/vines.rb +197 -0
  10. data/lib/vines/cluster.rb +246 -0
  11. data/lib/vines/cluster/connection.rb +26 -0
  12. data/lib/vines/cluster/publisher.rb +55 -0
  13. data/lib/vines/cluster/pubsub.rb +92 -0
  14. data/lib/vines/cluster/sessions.rb +125 -0
  15. data/lib/vines/cluster/subscriber.rb +108 -0
  16. data/lib/vines/command/bcrypt.rb +12 -0
  17. data/lib/vines/command/cert.rb +50 -0
  18. data/lib/vines/command/init.rb +68 -0
  19. data/lib/vines/command/register.rb +27 -0
  20. data/lib/vines/command/restart.rb +12 -0
  21. data/lib/vines/command/schema.rb +24 -0
  22. data/lib/vines/command/start.rb +28 -0
  23. data/lib/vines/command/stop.rb +18 -0
  24. data/lib/vines/command/unregister.rb +27 -0
  25. data/lib/vines/config.rb +213 -0
  26. data/lib/vines/config/host.rb +119 -0
  27. data/lib/vines/config/port.rb +132 -0
  28. data/lib/vines/config/pubsub.rb +108 -0
  29. data/lib/vines/contact.rb +111 -0
  30. data/lib/vines/daemon.rb +78 -0
  31. data/lib/vines/error.rb +150 -0
  32. data/lib/vines/jid.rb +95 -0
  33. data/lib/vines/kit.rb +35 -0
  34. data/lib/vines/log.rb +24 -0
  35. data/lib/vines/router.rb +179 -0
  36. data/lib/vines/stanza.rb +175 -0
  37. data/lib/vines/stanza/iq.rb +48 -0
  38. data/lib/vines/stanza/iq/auth.rb +18 -0
  39. data/lib/vines/stanza/iq/disco_info.rb +45 -0
  40. data/lib/vines/stanza/iq/disco_items.rb +29 -0
  41. data/lib/vines/stanza/iq/error.rb +16 -0
  42. data/lib/vines/stanza/iq/ping.rb +16 -0
  43. data/lib/vines/stanza/iq/private_storage.rb +83 -0
  44. data/lib/vines/stanza/iq/query.rb +10 -0
  45. data/lib/vines/stanza/iq/register.rb +42 -0
  46. data/lib/vines/stanza/iq/result.rb +16 -0
  47. data/lib/vines/stanza/iq/roster.rb +140 -0
  48. data/lib/vines/stanza/iq/session.rb +17 -0
  49. data/lib/vines/stanza/iq/vcard.rb +56 -0
  50. data/lib/vines/stanza/iq/version.rb +25 -0
  51. data/lib/vines/stanza/message.rb +43 -0
  52. data/lib/vines/stanza/presence.rb +156 -0
  53. data/lib/vines/stanza/presence/error.rb +23 -0
  54. data/lib/vines/stanza/presence/probe.rb +37 -0
  55. data/lib/vines/stanza/presence/subscribe.rb +42 -0
  56. data/lib/vines/stanza/presence/subscribed.rb +51 -0
  57. data/lib/vines/stanza/presence/unavailable.rb +15 -0
  58. data/lib/vines/stanza/presence/unsubscribe.rb +38 -0
  59. data/lib/vines/stanza/presence/unsubscribed.rb +38 -0
  60. data/lib/vines/stanza/pubsub.rb +22 -0
  61. data/lib/vines/stanza/pubsub/create.rb +39 -0
  62. data/lib/vines/stanza/pubsub/delete.rb +41 -0
  63. data/lib/vines/stanza/pubsub/publish.rb +66 -0
  64. data/lib/vines/stanza/pubsub/subscribe.rb +44 -0
  65. data/lib/vines/stanza/pubsub/unsubscribe.rb +30 -0
  66. data/lib/vines/storage.rb +188 -0
  67. data/lib/vines/storage/local.rb +165 -0
  68. data/lib/vines/storage/null.rb +39 -0
  69. data/lib/vines/storage/sql.rb +260 -0
  70. data/lib/vines/store.rb +94 -0
  71. data/lib/vines/stream.rb +247 -0
  72. data/lib/vines/stream/client.rb +84 -0
  73. data/lib/vines/stream/client/auth.rb +74 -0
  74. data/lib/vines/stream/client/auth_restart.rb +29 -0
  75. data/lib/vines/stream/client/bind.rb +72 -0
  76. data/lib/vines/stream/client/bind_restart.rb +24 -0
  77. data/lib/vines/stream/client/closed.rb +13 -0
  78. data/lib/vines/stream/client/ready.rb +17 -0
  79. data/lib/vines/stream/client/session.rb +210 -0
  80. data/lib/vines/stream/client/start.rb +27 -0
  81. data/lib/vines/stream/client/tls.rb +38 -0
  82. data/lib/vines/stream/component.rb +58 -0
  83. data/lib/vines/stream/component/handshake.rb +26 -0
  84. data/lib/vines/stream/component/ready.rb +23 -0
  85. data/lib/vines/stream/component/start.rb +19 -0
  86. data/lib/vines/stream/http.rb +157 -0
  87. data/lib/vines/stream/http/auth.rb +22 -0
  88. data/lib/vines/stream/http/bind.rb +32 -0
  89. data/lib/vines/stream/http/bind_restart.rb +37 -0
  90. data/lib/vines/stream/http/ready.rb +29 -0
  91. data/lib/vines/stream/http/request.rb +172 -0
  92. data/lib/vines/stream/http/session.rb +120 -0
  93. data/lib/vines/stream/http/sessions.rb +65 -0
  94. data/lib/vines/stream/http/start.rb +23 -0
  95. data/lib/vines/stream/parser.rb +78 -0
  96. data/lib/vines/stream/sasl.rb +92 -0
  97. data/lib/vines/stream/server.rb +150 -0
  98. data/lib/vines/stream/server/auth.rb +13 -0
  99. data/lib/vines/stream/server/auth_restart.rb +13 -0
  100. data/lib/vines/stream/server/final_restart.rb +21 -0
  101. data/lib/vines/stream/server/outbound/auth.rb +31 -0
  102. data/lib/vines/stream/server/outbound/auth_restart.rb +20 -0
  103. data/lib/vines/stream/server/outbound/auth_result.rb +32 -0
  104. data/lib/vines/stream/server/outbound/final_features.rb +28 -0
  105. data/lib/vines/stream/server/outbound/final_restart.rb +20 -0
  106. data/lib/vines/stream/server/outbound/start.rb +20 -0
  107. data/lib/vines/stream/server/outbound/tls.rb +30 -0
  108. data/lib/vines/stream/server/outbound/tls_result.rb +34 -0
  109. data/lib/vines/stream/server/ready.rb +24 -0
  110. data/lib/vines/stream/server/start.rb +13 -0
  111. data/lib/vines/stream/server/tls.rb +13 -0
  112. data/lib/vines/stream/state.rb +60 -0
  113. data/lib/vines/token_bucket.rb +55 -0
  114. data/lib/vines/user.rb +123 -0
  115. data/lib/vines/version.rb +5 -0
  116. data/lib/vines/xmpp_server.rb +43 -0
  117. data/vines.gemspec +36 -0
  118. data/web/404.html +51 -0
  119. data/web/apple-touch-icon.png +0 -0
  120. data/web/chat/coffeescripts/chat.coffee +362 -0
  121. data/web/chat/coffeescripts/init.coffee +15 -0
  122. data/web/chat/index.html +16 -0
  123. data/web/chat/javascripts/app.js +1 -0
  124. data/web/chat/stylesheets/chat.css +144 -0
  125. data/web/favicon.png +0 -0
  126. data/web/lib/coffeescripts/button.coffee +25 -0
  127. data/web/lib/coffeescripts/contact.coffee +32 -0
  128. data/web/lib/coffeescripts/filter.coffee +49 -0
  129. data/web/lib/coffeescripts/layout.coffee +30 -0
  130. data/web/lib/coffeescripts/login.coffee +68 -0
  131. data/web/lib/coffeescripts/logout.coffee +5 -0
  132. data/web/lib/coffeescripts/navbar.coffee +84 -0
  133. data/web/lib/coffeescripts/notification.coffee +14 -0
  134. data/web/lib/coffeescripts/router.coffee +40 -0
  135. data/web/lib/coffeescripts/session.coffee +229 -0
  136. data/web/lib/coffeescripts/transfer.coffee +106 -0
  137. data/web/lib/images/dark-gray.png +0 -0
  138. data/web/lib/images/default-user.png +0 -0
  139. data/web/lib/images/light-gray.png +0 -0
  140. data/web/lib/images/logo-large.png +0 -0
  141. data/web/lib/images/logo-small.png +0 -0
  142. data/web/lib/images/white.png +0 -0
  143. data/web/lib/javascripts/base.js +12 -0
  144. data/web/lib/javascripts/icons.js +110 -0
  145. data/web/lib/javascripts/jquery.cookie.js +91 -0
  146. data/web/lib/javascripts/jquery.js +4 -0
  147. data/web/lib/javascripts/raphael.js +6 -0
  148. data/web/lib/javascripts/strophe.js +1 -0
  149. data/web/lib/stylesheets/base.css +385 -0
  150. data/web/lib/stylesheets/login.css +68 -0
  151. metadata +423 -0
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Auth < Client::Auth
7
+ def initialize(stream, success=FinalRestart)
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class AuthRestart < Client::AuthRestart
7
+ def initialize(stream, success=Auth)
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class FinalRestart < State
7
+ def initialize(stream, success=Ready)
8
+ super
9
+ end
10
+
11
+ def node(node)
12
+ raise StreamErrors::NotAuthorized unless stream?(node)
13
+ stream.start(node)
14
+ stream.write('<stream:features/>')
15
+ stream.router << stream
16
+ advance
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class Auth < State
8
+ NS = NAMESPACES[:sasl]
9
+
10
+ def initialize(stream, success=AuthResult)
11
+ super
12
+ end
13
+
14
+ def node(node)
15
+ raise StreamErrors::NotAuthorized unless external?(node)
16
+ authzid = Base64.strict_encode64(stream.domain)
17
+ stream.write(%Q{<auth xmlns="#{NS}" mechanism="EXTERNAL">#{authzid}</auth>})
18
+ advance
19
+ end
20
+
21
+ private
22
+
23
+ def external?(node)
24
+ external = node.xpath("ns:mechanisms/ns:mechanism[text()='EXTERNAL']", 'ns' => NS).any?
25
+ node.name == 'features' && namespace(node) == NAMESPACES[:stream] && external
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class AuthRestart < State
8
+ def initialize(stream, success=Auth)
9
+ super
10
+ end
11
+
12
+ def node(node)
13
+ raise StreamErrors::NotAuthorized unless stream?(node)
14
+ advance
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class AuthResult < State
8
+ SUCCESS = 'success'.freeze
9
+ FAILURE = 'failure'.freeze
10
+
11
+ def initialize(stream, success=FinalRestart)
12
+ super
13
+ end
14
+
15
+ def node(node)
16
+ raise StreamErrors::NotAuthorized unless namespace(node) == NAMESPACES[:sasl]
17
+ case node.name
18
+ when SUCCESS
19
+ stream.start(node)
20
+ stream.reset
21
+ advance
22
+ when FAILURE
23
+ stream.close_connection
24
+ else
25
+ raise StreamErrors::NotAuthorized
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class FinalFeatures < State
8
+ def initialize(stream, success=Server::Ready)
9
+ super
10
+ end
11
+
12
+ def node(node)
13
+ raise StreamErrors::NotAuthorized unless empty_features?(node)
14
+ stream.router << stream
15
+ advance
16
+ stream.notify_connected
17
+ end
18
+
19
+ private
20
+
21
+ def empty_features?(node)
22
+ node.name == 'features' && namespace(node) == NAMESPACES[:stream] && node.elements.empty?
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class FinalRestart < State
8
+ def initialize(stream, success=FinalFeatures)
9
+ super
10
+ end
11
+
12
+ def node(node)
13
+ raise StreamErrors::NotAuthorized unless stream?(node)
14
+ advance
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class Start < State
8
+ def initialize(stream, success=TLS)
9
+ super
10
+ end
11
+
12
+ def node(node)
13
+ raise StreamErrors::NotAuthorized unless stream?(node)
14
+ advance
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class TLS < State
8
+ NS = NAMESPACES[:tls]
9
+
10
+ def initialize(stream, success=TLSResult)
11
+ super
12
+ end
13
+
14
+ def node(node)
15
+ raise StreamErrors::NotAuthorized unless tls?(node)
16
+ stream.write("<starttls xmlns='#{NS}'/>")
17
+ advance
18
+ end
19
+
20
+ private
21
+
22
+ def tls?(node)
23
+ tls = node.xpath('ns:starttls', 'ns' => NS).any?
24
+ node.name == 'features' && namespace(node) == NAMESPACES[:stream] && tls
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Outbound
7
+ class TLSResult < State
8
+ NS = NAMESPACES[:tls]
9
+ PROCEED = 'proceed'.freeze
10
+ FAILURE = 'failure'.freeze
11
+
12
+ def initialize(stream, success=AuthRestart)
13
+ super
14
+ end
15
+
16
+ def node(node)
17
+ raise StreamErrors::NotAuthorized unless namespace(node) == NS
18
+ case node.name
19
+ when PROCEED
20
+ stream.encrypt
21
+ stream.start(node)
22
+ stream.reset
23
+ advance
24
+ when FAILURE
25
+ stream.close_connection
26
+ else
27
+ raise StreamErrors::NotAuthorized
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Ready < State
7
+ def node(node)
8
+ stanza = to_stanza(node)
9
+ raise StreamErrors::UnsupportedStanzaType unless stanza
10
+ to, from = stanza.validate_to, stanza.validate_from
11
+ raise StreamErrors::ImproperAddressing unless to && from
12
+ raise StreamErrors::InvalidFrom unless from.domain == stream.remote_domain
13
+ raise StreamErrors::HostUnknown unless to.domain == stream.domain
14
+ stream.user = User.new(jid: from)
15
+ if stanza.local? || stanza.to_pubsub_domain?
16
+ stanza.process
17
+ else
18
+ stanza.route
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class Start < Client::Start
7
+ def initialize(stream, success=TLS)
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+ class Server
6
+ class TLS < Client::TLS
7
+ def initialize(stream, success=AuthRestart)
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ class Stream
5
+
6
+ # The base class of Stream state machines. States know how to process XML
7
+ # nodes and advance to their next valid state or fail the stream.
8
+ class State
9
+ include Nokogiri::XML
10
+ include Vines::Log
11
+
12
+ attr_accessor :stream
13
+
14
+ BODY = 'body'.freeze
15
+ STREAM = 'stream'.freeze
16
+
17
+ def initialize(stream, success=nil)
18
+ @stream, @success = stream, success
19
+ end
20
+
21
+ def node(node)
22
+ raise 'subclass must implement'
23
+ end
24
+
25
+ def ==(state)
26
+ self.class == state.class
27
+ end
28
+
29
+ def eql?(state)
30
+ state.is_a?(State) && self == state
31
+ end
32
+
33
+ def hash
34
+ self.class.hash
35
+ end
36
+
37
+ private
38
+
39
+ def advance
40
+ stream.advance(@success.new(stream))
41
+ end
42
+
43
+ def stream?(node)
44
+ node.name == STREAM && namespace(node) == NAMESPACES[:stream]
45
+ end
46
+
47
+ def body?(node)
48
+ node.name == BODY && namespace(node) == NAMESPACES[:http_bind]
49
+ end
50
+
51
+ def namespace(node)
52
+ node.namespace ? node.namespace.href : nil
53
+ end
54
+
55
+ def to_stanza(node)
56
+ Stanza.from_node(node, stream)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+
5
+ # The token bucket algorithm is useful for rate limiting.
6
+ # Before an operation can be completed, a token is taken from
7
+ # the bucket. If no tokens are available, the operation fails.
8
+ # The bucket is refilled with tokens at the maximum allowed rate
9
+ # of operations.
10
+ class TokenBucket
11
+
12
+ # Create a full bucket with `capacity` number of tokens to be filled
13
+ # at the given rate of tokens/second.
14
+ #
15
+ # capacity - The Fixnum maximum number of tokens the bucket can hold.
16
+ # rate - The Fixnum number of tokens per second at which the bucket is
17
+ # refilled.
18
+ def initialize(capacity, rate)
19
+ raise ArgumentError.new('capacity must be > 0') unless capacity > 0
20
+ raise ArgumentError.new('rate must be > 0') unless rate > 0
21
+ @capacity = capacity
22
+ @tokens = capacity
23
+ @rate = rate
24
+ @timestamp = Time.new
25
+ end
26
+
27
+ # Remove tokens from the bucket if it's full enough. There's no way, or
28
+ # need, to add tokens to the bucket. It refills over time.
29
+ #
30
+ # tokens - The Fixnum number of tokens to attempt to take from the bucket.
31
+ #
32
+ # Returns true if the bucket contains enough tokens to take, false if the
33
+ # bucket isn't full enough to satisy the request.
34
+ def take(tokens)
35
+ raise ArgumentError.new('tokens must be > 0') unless tokens > 0
36
+ tokens <= fill ? @tokens -= tokens : false
37
+ end
38
+
39
+ private
40
+
41
+ # Add tokens to the bucket at the `rate` provided in the constructor. This
42
+ # fills the bucket slowly over time.
43
+ #
44
+ # Returns the Fixnum number of tokens left in the bucket.
45
+ def fill
46
+ if @tokens < @capacity
47
+ now = Time.new
48
+ @tokens += (@rate * (now - @timestamp)).round
49
+ @tokens = @capacity if @tokens > @capacity
50
+ @timestamp = now
51
+ end
52
+ @tokens
53
+ end
54
+ end
55
+ end