process-consensus 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/usr/bin/ruby
  2. # process-consensus - read a current consensus document, inserting the
  3. # information into a database then calling
  4. # update-named-status.rb to update the name-binding
  5. # flags
  6. #
  7. # Copyright (c) 2007 Peter Palfrader
  8. #
  9. # Permission is hereby granted, free of charge, to any person obtaining a copy
  10. # of this software and associated documentation files (the "Software"), to deal
  11. # in the Software without restriction, including without limitation the rights
  12. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. # copies of the Software, and to permit persons to whom the Software is
  14. # furnished to do so, subject to the following conditions:
  15. #
  16. # The above copyright notice and this permission notice shall be included in
  17. # all copies or substantial portions of the Software.
  18. #
  19. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  25. # SOFTWARE.
  26. require "yaml"
  27. require 'db'
  28. require 'db-config'
  29. require 'update-named-status'
  30. $db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
  31. $router_cache = {}
  32. $nickname_cache = {}
  33. def parse_consensus consensus
  34. ts = nil
  35. routers = []
  36. consensus.each do |line|
  37. (key, value) = line.split(' ',2)
  38. case key
  39. when "valid-after", "published": ts = DateTime.parse(value)
  40. when "r":
  41. (nick, fpr, _) = value.split(' ', 3)
  42. nick.downcase!
  43. next if nick == 'unnamed'
  44. routers << {
  45. 'nick' => nick,
  46. 'fingerprint' => (fpr+'=').unpack('m').first.unpack('H*').first
  47. }
  48. end
  49. end
  50. throw "Did not find a timestamp" unless ts
  51. throw "Did not find any routers" unless routers.size > 0
  52. return ts, routers
  53. end
  54. def insert_routers_into_db(router, table, field, value)
  55. pk = table+'_id'
  56. row = $db.query_row("SELECT #{pk} FROM #{table} WHERE #{field}=?", value)
  57. if row
  58. return row[pk]
  59. else
  60. r = { field => value }
  61. $db.insert_row( table, r )
  62. return r[pk]
  63. end
  64. end
  65. def handle_one_consensus(c)
  66. puts "parsing..." if $verbose
  67. timestamp, routers = parse_consensus c
  68. puts "storing..." if $verbose
  69. routers.each do |router|
  70. fpr = router['fingerprint']
  71. nick = router['nick']
  72. $router_cache[fpr] = router_id = ($router_cache[fpr] or insert_routers_into_db(router, 'router', 'fingerprint', router['fingerprint']))
  73. $nickname_cache[nick] = nickname_id = ($nickname_cache[nick] or insert_routers_into_db(router, 'nickname', 'nick', router['nick']))
  74. row = $db.update(
  75. 'router_claims_nickname',
  76. { 'last_seen' => timestamp.to_s },
  77. { 'router_id' => router_id, 'nickname_id' => nickname_id} )
  78. case row
  79. when 0:
  80. $db.insert('router_claims_nickname',
  81. {
  82. 'first_seen' => timestamp.to_s,
  83. 'last_seen' => timestamp.to_s,
  84. 'router_id' => router_id, 'nickname_id' => nickname_id} )
  85. when 1:
  86. else
  87. throw "Update of router_claims_nickname returned unexpected number of affected rows(#{row})"
  88. end
  89. end
  90. end
  91. $db.transaction_begin
  92. if ARGV.first == '-v'
  93. $verbose = true
  94. ARGV.shift
  95. end
  96. if ARGV.size == 0
  97. handle_one_consensus STDIN.readlines
  98. do_update $verbose
  99. else
  100. ARGV.each do |filename|
  101. puts filename if $verbose
  102. handle_one_consensus File.new(filename).readlines
  103. puts "updating..." if $verbose
  104. do_update $verbose
  105. end
  106. end
  107. $db.transaction_commit