]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Commit this stuff somewhere before I delete it accidentally
authorPeter Palfrader <peter@palfrader.org>
Mon, 8 Oct 2007 23:40:52 +0000 (23:40 +0000)
committerPeter Palfrader <peter@palfrader.org>
Mon, 8 Oct 2007 23:40:52 +0000 (23:40 +0000)
svn:r11794

contrib/auto-naming/build-approved-routers [new file with mode: 0755]
contrib/auto-naming/create-db.sql [new file with mode: 0644]
contrib/auto-naming/db-config.rb [new file with mode: 0644]
contrib/auto-naming/db.rb [new file with mode: 0644]
contrib/auto-naming/process-consensus [new file with mode: 0755]
contrib/auto-naming/update-named-status.rb [new file with mode: 0755]

diff --git a/contrib/auto-naming/build-approved-routers b/contrib/auto-naming/build-approved-routers
new file mode 100755 (executable)
index 0000000..dcc597e
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/ruby
+
+require "yaml"
+
+require 'db'
+require 'db-config'
+
+verbose = ARGV.first == "-v"
+
+db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
+
+db.transaction_begin
+named = db.query2("
+               SELECT fingerprint, router_id, nickname_id, nick, first_seen, last_seen
+               FROM router NATURAL JOIN router_claims_nickname NATURAL JOIN nickname
+               WHERE named")
+while (n=named.next) do
+       puts "# (r##{n['router_id']},n##{n['nickname_id']}); first_seen: #{n['first_seen']}, last_seen: #{n['last_seen']}"
+       fpr = n['fingerprint'].split(/(....)/).delete_if{|x| x=="" }.join(' ')
+       puts "#{n['nick']} #{fpr}}"
+end
+db.transaction_commit
diff --git a/contrib/auto-naming/create-db.sql b/contrib/auto-naming/create-db.sql
new file mode 100644 (file)
index 0000000..6377be3
--- /dev/null
@@ -0,0 +1,29 @@
+
+CREATE TABLE router (
+       router_id       SERIAL PRIMARY KEY,
+       fingerprint     CHAR(40)                NOT NULL,
+       UNIQUE(fingerprint)
+);
+-- already created implicitly due to unique contraint
+-- CREATE INDEX router_fingerprint ON router(fingerprint);
+
+CREATE TABLE nickname (
+       nickname_id     SERIAL PRIMARY KEY,
+       nick            VARCHAR(30)             NOT NULL,
+       UNIQUE(nick)
+);
+-- already created implicitly due to unique contraint
+-- CREATE INDEX nickname_nick ON nickname(nick);
+
+CREATE TABLE router_claims_nickname (
+       router_id       INTEGER         NOT NULL        REFERENCES router(router_id) ON DELETE CASCADE,
+       nickname_id     INTEGER         NOT NULL        REFERENCES nickname(nickname_id) ON DELETE CASCADE,
+       first_seen      TIMESTAMP WITH TIME ZONE        NOT NULL        DEFAULT CURRENT_TIMESTAMP,
+       last_seen       TIMESTAMP WITH TIME ZONE        NOT NULL        DEFAULT CURRENT_TIMESTAMP,
+       named           BOOLEAN                         NOT NULL        DEFAULT 'false',
+       UNIQUE(router_id, nickname_id)
+);
+CREATE INDEX router_claims_nickname_router_id ON router_claims_nickname(router_id);
+CREATE INDEX router_claims_nickname_nickname_id ON router_claims_nickname(nickname_id);
+CREATE INDEX router_claims_nickname_first_seen ON router_claims_nickname(first_seen);
+CREATE INDEX router_claims_nickname_last_seen ON router_claims_nickname(last_seen);
diff --git a/contrib/auto-naming/db-config.rb b/contrib/auto-naming/db-config.rb
new file mode 100644 (file)
index 0000000..3cf2dbe
--- /dev/null
@@ -0,0 +1,6 @@
+$CONFIG             = {} unless $CONFIG
+$CONFIG['database'] = {} unless $CONFIG['database']
+
+$CONFIG['database']['dbname'] = 'tornaming';
+$CONFIG['database']['user'] = 'tornaming';
+$CONFIG['database']['password'] = 'x';
diff --git a/contrib/auto-naming/db.rb b/contrib/auto-naming/db.rb
new file mode 100644 (file)
index 0000000..706e81c
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/ruby
+
+require "dbi"
+
+class WeaselDbQueryHandle
+       def initialize(sth)
+               @sth = sth
+       end
+
+       def next()
+               row = @sth.fetch_hash
+               if row
+                       return row
+               else
+                       @sth.finish
+                       return nil
+               end
+       end
+end
+
+class Db
+       def initialize(database, user, password)
+               @dbh = DBI.connect("dbi:Pg:#{database}:localhost", user, password);
+               @dbh['AutoCommit'] = false
+               @transaction = false
+               @pre_initial_transaction=true
+       end
+
+       def do(query,*args)
+               @dbh.do(query,*args)
+       end
+       def transaction_begin()
+               @dbh.do("BEGIN") unless @pre_initial_transaction
+               @transaction = true
+               @pre_initial_transaction=false
+       end
+       def transaction_commit()
+               @dbh.do("COMMIT")
+               @transaction = false
+       end
+       def transaction_rollback()
+               @dbh.do("ROLLBACK")
+       end
+       def get_primarykey_name(table);
+               #return 'ref';
+               return table+'_id';
+       end
+
+       def update(table, values, keys)
+               cols = []
+               vals = []
+               values.each_pair{ |k,v|
+                       cols << "#{k}=?"
+                       vals << v
+               }
+
+               wheres = []
+               keys.each_pair{ |k,v|
+                       wheres << "#{k}=?"
+                       vals << v
+               }
+
+               throw "update value set empty" unless cols.size > 0
+               throw "where clause empty" unless wheres.size > 0
+
+               query = "UPDATE #{table} SET #{cols.join(',')} WHERE #{wheres.join(' AND ')}"
+               transaction_begin unless transaction_before=@transaction
+               r = @dbh.do(query, *vals)
+               transaction_commit unless transaction_before
+               return r
+       end
+
+       def update_row(table, values)
+               pk_name = get_primarykey_name(table);
+               throw "Ref not defined" unless values[pk_name]
+               return update(table, values.clone.delete_if{|k,v| k == pk_name}, { pk_name => values[pk_name] });
+       end
+       def insert(table, values)
+               cols = values.keys
+               vals = values.values
+               qmarks = values.values.collect{ '?' }
+
+               query = "INSERT INTO #{table} (#{cols.join(',')}) VALUES (#{qmarks.join(',')})"
+               transaction_begin unless transaction_before=@transaction
+               @dbh.do(query, *vals)
+               transaction_commit unless transaction_before
+       end
+
+       def insert_row(table, values)
+               pk_name = get_primarykey_name(table);
+               if values[pk_name]
+                       insert(table, values)
+               else
+                       transaction_begin unless transaction_before=@transaction
+                       row = query_row("SELECT nextval(pg_get_serial_sequence('#{table}', '#{pk_name}')) AS newref");
+                       throw "No newref?" unless row['newref']
+                       values[pk_name] = row['newref']
+                       insert(table, values);
+                       transaction_commit unless transaction_before
+               end
+       end
+       def delete_row(table, ref)
+               pk_name = get_primarykey_name(table);
+               query = "DELETE FROM #{table} WHERE #{pk_name}=?"
+               transaction_begin unless transaction_before=@transaction
+               @dbh.do(query, ref)
+               transaction_commit unless transaction_before
+       end
+       def query(query, *params)
+               sth = @dbh.execute(query, *params)
+               while row = sth.fetch_hash
+                       yield row
+               end
+               sth.finish
+       end
+       # nil if no results
+       # hash if one match
+       # throw otherwise
+       def query_row(query, *params)
+               sth = @dbh.execute(query, *params)
+
+               row = sth.fetch_hash
+               if row == nil
+                       sth.finish
+                       return nil
+               elsif sth.fetch_hash != nil
+                       sth.finish
+                       throw "More than one result when querying for #{query}"
+               else
+                       sth.finish
+                       return row
+               end
+       end
+       def query_all(query, *params)
+               sth = @dbh.execute(query, *params)
+
+               rows = sth.fetch_all
+               return nil if rows.size == 0
+               return rows
+       end
+       def query2(query, *params)
+               sth = @dbh.execute(query, *params)
+               return WeaselDbQueryHandle.new(sth)
+       end
+end
diff --git a/contrib/auto-naming/process-consensus b/contrib/auto-naming/process-consensus
new file mode 100755 (executable)
index 0000000..321b64d
--- /dev/null
@@ -0,0 +1,94 @@
+#!/usr/bin/ruby
+
+require "yaml"
+
+require 'db'
+require 'db-config'
+require 'update-named-status'
+
+$db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
+
+$router_cache = {}
+$nickname_cache = {}
+
+def parse_consensus consensus
+       ts = nil
+       routers = []
+       consensus.each do |line|
+               (key, value) = line.split(' ',2)
+               case key
+                       when "valid-after", "published": ts = DateTime.parse(value)
+                       when "r":
+                               (nick, fpr, _) = value.split(' ', 3)
+                               nick.downcase!
+                               next if nick == 'unnamed'
+                               routers << {
+                                       'nick' => nick,
+                                       'fingerprint' => (fpr+'=').unpack('m').first.unpack('H*').first
+                                       }
+               end
+       end
+       throw "Did not find a timestamp" unless ts
+       throw "Did not find any routers" unless routers.size > 0
+       return ts, routers
+end
+
+def insert_routers_into_db(router, table, field, value)
+       pk = table+'_id'
+       row = $db.query_row("SELECT #{pk} FROM #{table} WHERE #{field}=?", value)
+       if row
+               return row[pk]
+       else
+               r = { field => value }
+               $db.insert_row( table, r )
+               return r[pk]
+       end
+end
+
+def handle_one_consensus(c)
+       puts "parsing..." if $verbose
+       timestamp, routers = parse_consensus c
+       puts "storing..." if $verbose
+
+       routers.each do |router|
+               fpr = router['fingerprint']
+               nick = router['nick']
+               $router_cache[fpr] = router_id = ($router_cache[fpr] or insert_routers_into_db(router, 'router', 'fingerprint', router['fingerprint']))
+               $nickname_cache[nick] = nickname_id = ($nickname_cache[nick] or insert_routers_into_db(router, 'nickname', 'nick', router['nick']))
+
+               row = $db.update(
+                       'router_claims_nickname',
+                       { 'last_seen' => timestamp.to_s },
+                       { 'router_id' => router_id, 'nickname_id' => nickname_id} )
+               case row
+                       when 0:
+                               $db.insert('router_claims_nickname',
+                                       {
+                                               'first_seen' => timestamp.to_s,
+                                               'last_seen' => timestamp.to_s,
+                                               'router_id' => router_id, 'nickname_id' => nickname_id} )
+                       when 1:
+                       else
+                               throw "Update of router_claims_nickname returned unexpected number of affected rows(#{row})"
+               end
+       end
+end
+
+$db.transaction_begin
+if ARGV.first == '-v'
+       $verbose = true
+       ARGV.shift
+end
+
+if ARGV.size == 0
+       handle_one_consensus STDIN.readlines
+       do_update true
+else
+       ARGV.each do |filename|
+               puts filename if $verbose
+               handle_one_consensus File.new(filename).readlines
+               puts "updating..." if $verbose
+               do_update $verbose
+       end
+end
+$db.transaction_commit
diff --git a/contrib/auto-naming/update-named-status.rb b/contrib/auto-naming/update-named-status.rb
new file mode 100755 (executable)
index 0000000..8ff60ca
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/ruby
+
+require "yaml"
+
+require 'db'
+require 'db-config'
+
+def do_update verbose
+       now = "TIMESTAMP '" + $db.query_row("SELECT max(last_seen) AS max FROM router_claims_nickname")['max'].to_s + "'"
+
+       denamed = $db.do("
+                       UPDATE router_claims_nickname
+                       SET named=false
+                       WHERE named
+                         AND last_seen < #{now} - INTERVAL '6 months'")
+       puts "de-named: #{denamed}" if verbose
+
+       named = $db.do("
+                       UPDATE router_claims_nickname
+                       SET named=true
+                       WHERE NOT named
+                         AND first_seen < #{now} - INTERVAL '2 weeks'
+                         AND last_seen  > #{now} - INTERVAL '2 days'
+                         AND NOT EXISTS (SELECT *
+                              FROM router_claims_nickname AS innertable
+                              WHERE named
+                                AND router_claims_nickname.nickname_id=innertable.nickname_id) "+ # if that nickname is already named, we lose.
+                       " AND NOT EXISTS (SELECT *
+                              FROM router_claims_nickname AS innertable
+                              WHERE router_claims_nickname.nickname_id=innertable.nickname_id
+                                AND router_claims_nickname.router_id <> innertable.router_id
+                                AND last_seen > #{now} - INTERVAL '1 month') ") # if nobody else wanted that nickname in the last month we are set
+       puts "named: #{named}" if verbose
+end
+
+if __FILE__ == $0
+       $db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
+       verbose = ARGV.first == "-v"
+
+       $db.transaction_begin
+       do_update verbose
+       $db.transaction_commit
+end