shlist

share and manage lists between multiple people
Log | Files | Refs

commit 53b59e98e0fca52a7bc550043d3cbfc229969a43
parent d67aabff3e4f1d033d689249316ebeb3b0314e8d
Author: kyle <kyle@getaddrinfo.net>
Date:   Sat, 13 Feb 2016 19:16:11 -0700

sl: move logger and database classes into their own files

- sl is getting close to 1000 lines so start splitting out functionality

Diffstat:
Aserver/database.pm | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aserver/logger.pm | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mserver/sl | 255+++----------------------------------------------------------------------------
3 files changed, 258 insertions(+), 248 deletions(-)

diff --git a/server/database.pm b/server/database.pm @@ -0,0 +1,203 @@ +package database; + +use DBI; +use File::Temp; + +sub new { + my $class = shift; + my $db_file = shift; + + my $self = {}; + bless ($self, $class); + + $self->{dbh} = DBI->connect( + "dbi:SQLite:dbname=$db_file", + "", "", + { + RaiseError => 1, + sqlite_unicode => 1, + } + ) or die $DBI::errstr; + + $self->{dbh}->do("PRAGMA foreign_keys = ON"); + $self->{dbh}->{AutoCommit} = 1; + + return $self; +} + +sub create_tables { + my ($self) = @_; + + my $db_handle = $self->{dbh}; + $db_handle->begin_work; + + $db_handle->do(qq{ + create table if not exists lists ( + num integer primary key, + name text not null, + date int, + created int not null, + last_updated int not null) + }); + + $db_handle->do(qq{ + create table if not exists devices ( + num integer primary key, + id text not null, + phone_num text not null, + os text, + push_token text, + seen_first int not null, + seen_last int not null) + }); + + $db_handle->do(qq{ + create table if not exists friends ( + device integer not null, + friend text not null, + primary key(device, friend), + foreign key(device) references devices(num)) + }); + + $db_handle->do(qq{ + create table if not exists mutual_friends ( + device integer not null, + mutual_friend integer not null, + primary key(device, mutual_friend), + foreign key(device) references devices(num), + foreign key(mutual_friend) references devices(num)) + }); + + $db_handle->do(qq{ + create table if not exists list_members ( + list integer, + device integer, + joined int not null, + primary key(list, device), + foreign key(list) references lists(num), + foreign key(device) references devices(num)) + }); + + $db_handle->do(qq{ + create table if not exists list_data ( + num integer primary key, + list integer, + name text, + owner integer, + status int not null default 0, + quantity, + created int not null, + last_updated int not null, + foreign key(list) references lists(num), + foreign key(owner) references devices(num)) + }); + + $db_handle->commit; + $self->{dbh}->disconnect(); + $self->{dbh} = undef; +} + +sub prepare_stmt_handles { + my ($self) = @_; + + my $dbh = $self->{dbh}; + my $sql; + + # list table queries + $sql = 'select * from lists where num = ?'; + $self->{list_select} = $dbh->prepare($sql); + + $sql = 'insert into lists (name, date, created, last_updated) values (?, ?, ?, ?)'; + $self->{new_list} = $dbh->prepare($sql); + + $sql = qq{update lists set name = coalesce(?, name), + date = coalesce(?, date), last_updated = ? where num = ?}; + $self->{update_list} = $dbh->prepare($sql); + + $sql = 'delete from lists where num = ?'; + $self->{delete_list} = $dbh->prepare($sql); + + # devices table queries + $sql = 'insert into devices (id, phone_num, os, push_token, seen_first, seen_last) values (?, ?, ?, ?, ?, ?)'; + $self->{new_device} = $dbh->prepare($sql); + + $sql = 'select * from devices where phone_num = ?'; + $self->{ph_num_exists} = $dbh->prepare($sql); + + $sql = 'select * from devices where id = ?'; + $self->{select_device_id} = $dbh->prepare($sql); + + $sql = 'update devices set push_token = coalesce(?, push_token) where num = ?'; + $self->{update_device} = $dbh->prepare($sql); + + # friends table queries + $sql = 'insert or replace into friends (device, friend) values (?, ?)'; + $self->{friends_insert} = $dbh->prepare($sql); + + $sql = 'select * from friends where device = ? and friend = ?'; + $self->{friends_select} = $dbh->prepare($sql); + + $sql = 'delete from friends where device = ? and friend = ?'; + $self->{friends_delete} = $dbh->prepare($sql); + + # mutual_friends table queries + $sql = 'insert or replace into mutual_friends (device, mutual_friend) values (?, ?)'; + $self->{mutual_friend_insert} = $dbh->prepare($sql); + + $sql = qq{select devices.num, devices.phone_num, devices.os, devices.push_token + from devices, mutual_friends + where devices.num = mutual_friends.mutual_friend + and mutual_friends.device = ?}; + $self->{mutual_friend_select} = $dbh->prepare($sql); + + $sql = qq{select devices.os, devices.push_token from devices, mutual_friends + where devices.num = mutual_friends.mutual_friend + and mutual_friends.device = ? and devices.push_token is not null}; + $self->{mutual_friend_notify_select} = $dbh->prepare($sql); + + $sql = 'delete from mutual_friends where device = ? and mutual_friend = ?'; + $self->{mutual_friends_delete} = $dbh->prepare($sql); + + # lists/list_members compound queries + $sql = qq{select lists.num, lists.name, lists.date from lists, list_members where + lists.num = list_members.list and list_members.device = ?}; + $self->{get_lists} = $dbh->prepare($sql); + + $sql = qq{select devices.phone_num from devices, list_members + where devices.num = list_members.device and list_members.list = ?}; + $self->{list_members_phnums} = $dbh->prepare($sql); + + $sql = qq{select devices.os, devices.push_token from devices, list_members + where devices.num = list_members.device and list_members.list = ? + and list_members.device != ?}; + $self->{select_list_members} = $dbh->prepare($sql); + + # list_members table queries + $sql = 'select device from list_members where list = ?'; + $self->{get_list_members} = $dbh->prepare($sql); + + $sql = 'insert into list_members (list, device, joined) values (?, ?, ?)'; + $self->{new_list_member} = $dbh->prepare($sql); + + $sql = 'delete from list_members where list = ? and device = ?'; + $self->{remove_list_member} = $dbh->prepare($sql); + + $sql = 'select device from list_members where list = ? and device = ?'; + $self->{check_list_member} = $dbh->prepare($sql); + + $sql = qq{select list from list_members where device = ? except + select list from list_members where device = ?}; + $self->{get_other_lists} = $dbh->prepare($sql); + + # list_data table queries + $sql = 'delete from list_data where list = ?'; + $self->{delete_list_data} = $dbh->prepare($sql); + + $sql = 'select * from list_data where list = ?'; + $self->{get_list_items} = $dbh->prepare($sql); + + $sql = 'insert into list_data (list, name, quantity, status, owner, last_updated) values (?, ?, ?, ?, ?, ?)'; + $self->{new_list_item} = $dbh->prepare($sql); +} + +1; diff --git a/server/logger.pm b/server/logger.pm @@ -0,0 +1,48 @@ +package logger; +use POSIX; + +sub new { + my $class = shift; + + my $self = {}; + bless ($self, $class); + + $self->{addr} = ''; + $self->{port} = ''; + $self->{msg_type} = ''; + return $self; +} + +sub set_peer_host_port { + my ($self, $sock) = @_; + ($self->{addr}, $self->{port}) = ($sock->peerhost(), $sock->peerport()); +} + +sub set_msg { + my ($self, $msg_type) = @_; + + if ($msg_type ne '') { + $self->{msg_type} = "$msg_type: "; + } else { + $self->{msg_type} = ''; + } +} + +sub print { + my ($self, @args) = @_; + + my $ftime = strftime("%F %T", localtime); + printf "%s %-15s %-5s> %s", $ftime, $self->{addr}, $self->{port}, $self->{msg_type}; + # we print potentially unsafe strings here, don't use printf + print @args; +} + +sub print_bare { + my ($self, @args) = @_; + + my $ftime = strftime("%F %T", localtime); + printf "%s> ", $ftime; + printf @args; +} + +1; diff --git a/server/sl b/server/sl @@ -4,7 +4,6 @@ use strict; use BSD::arc4random qw(arc4random_bytes arc4random_stir); use Digest::SHA qw(sha256_base64); -use DBI; use File::Temp; use Getopt::Std; use IO::Socket::SSL; @@ -13,19 +12,24 @@ use JSON::XS; use Scalar::Util qw(looks_like_number); use Try::Tiny; +use logger; +use database; + require "msgs.pl"; our (%msg_num, @msg_str, @msg_func, $protocol_ver); my %args; getopts("p:t", \%args); +# This is used by the parent to create the database if it doesn't already +# exist, and then each child connects to this db to do queries my $db_file = "db"; $db_file = File::Temp->new(SUFFIX => '.db', EXLOCK => 0) if ($args{t}); my $log = logger->new(); $log->print_bare("using database '$db_file'\n"); -my $db = database->new(); +my $db = database->new($db_file); $db->create_tables(); my $server_socket = new IO::Socket::INET ( @@ -74,7 +78,7 @@ while (my $client_socket = $server_socket->accept()) { my $ssl_cipher = $client_socket->get_cipher(); $log->print("ssl ok, ver = '$ssl_ver' cipher = '$ssl_cipher'\n"); - my $db = database->new(); + my $db = database->new($db_file); $db->prepare_stmt_handles(); while (1) { @@ -746,248 +750,3 @@ sub device_id_valid { $log->print("unknown device '$device_id'\n"); return ('the client sent an unknown device id'); } - -package database; - -sub new { - my $class = shift; - - my $self = {}; - bless ($self, $class); - - $self->{dbh} = DBI->connect( - "dbi:SQLite:dbname=$db_file", - "", "", - { - RaiseError => 1, - sqlite_unicode => 1, - } - ) or die $DBI::errstr; - - $self->{dbh}->do("PRAGMA foreign_keys = ON"); - $self->{dbh}->{AutoCommit} = 1; - - return $self; -} - -sub create_tables { - my ($self) = @_; - - my $db_handle = $self->{dbh}; - $db_handle->begin_work; - - $db_handle->do(qq{ - create table if not exists lists ( - num integer primary key, - name text not null, - date int, - created int not null, - last_updated int not null) - }); - - $db_handle->do(qq{ - create table if not exists devices ( - num integer primary key, - id text not null, - phone_num text not null, - os text, - push_token text, - seen_first int not null, - seen_last int not null) - }); - - $db_handle->do(qq{ - create table if not exists friends ( - device integer not null, - friend text not null, - primary key(device, friend), - foreign key(device) references devices(num)) - }); - - $db_handle->do(qq{ - create table if not exists mutual_friends ( - device integer not null, - mutual_friend integer not null, - primary key(device, mutual_friend), - foreign key(device) references devices(num), - foreign key(mutual_friend) references devices(num)) - }); - - $db_handle->do(qq{ - create table if not exists list_members ( - list integer, - device integer, - joined int not null, - primary key(list, device), - foreign key(list) references lists(num), - foreign key(device) references devices(num)) - }); - - $db_handle->do(qq{ - create table if not exists list_data ( - num integer primary key, - list integer, - name text, - owner integer, - status int not null default 0, - quantity, - created int not null, - last_updated int not null, - foreign key(list) references lists(num), - foreign key(owner) references devices(num)) - }); - - $db_handle->commit; - $self->{dbh}->disconnect(); - $self->{dbh} = undef; -} - -sub prepare_stmt_handles { - my ($self) = @_; - - my $dbh = $self->{dbh}; - my $sql; - - # list table queries - $sql = 'select * from lists where num = ?'; - $self->{list_select} = $dbh->prepare($sql); - - $sql = 'insert into lists (name, date, created, last_updated) values (?, ?, ?, ?)'; - $self->{new_list} = $dbh->prepare($sql); - - $sql = qq{update lists set name = coalesce(?, name), - date = coalesce(?, date), last_updated = ? where num = ?}; - $self->{update_list} = $dbh->prepare($sql); - - $sql = 'delete from lists where num = ?'; - $self->{delete_list} = $dbh->prepare($sql); - - # devices table queries - $sql = 'insert into devices (id, phone_num, os, push_token, seen_first, seen_last) values (?, ?, ?, ?, ?, ?)'; - $self->{new_device} = $dbh->prepare($sql); - - $sql = 'select * from devices where phone_num = ?'; - $self->{ph_num_exists} = $dbh->prepare($sql); - - $sql = 'select * from devices where id = ?'; - $self->{select_device_id} = $dbh->prepare($sql); - - $sql = 'update devices set push_token = coalesce(?, push_token) where num = ?'; - $self->{update_device} = $dbh->prepare($sql); - - # friends table queries - $sql = 'insert or replace into friends (device, friend) values (?, ?)'; - $self->{friends_insert} = $dbh->prepare($sql); - - $sql = 'select * from friends where device = ? and friend = ?'; - $self->{friends_select} = $dbh->prepare($sql); - - $sql = 'delete from friends where device = ? and friend = ?'; - $self->{friends_delete} = $dbh->prepare($sql); - - # mutual_friends table queries - $sql = 'insert or replace into mutual_friends (device, mutual_friend) values (?, ?)'; - $self->{mutual_friend_insert} = $dbh->prepare($sql); - - $sql = qq{select devices.num, devices.phone_num, devices.os, devices.push_token - from devices, mutual_friends - where devices.num = mutual_friends.mutual_friend - and mutual_friends.device = ?}; - $self->{mutual_friend_select} = $dbh->prepare($sql); - - $sql = qq{select devices.os, devices.push_token from devices, mutual_friends - where devices.num = mutual_friends.mutual_friend - and mutual_friends.device = ? and devices.push_token is not null}; - $self->{mutual_friend_notify_select} = $dbh->prepare($sql); - - $sql = 'delete from mutual_friends where device = ? and mutual_friend = ?'; - $self->{mutual_friends_delete} = $dbh->prepare($sql); - - # lists/list_members compound queries - $sql = qq{select lists.num, lists.name, lists.date from lists, list_members where - lists.num = list_members.list and list_members.device = ?}; - $self->{get_lists} = $dbh->prepare($sql); - - $sql = qq{select devices.phone_num from devices, list_members - where devices.num = list_members.device and list_members.list = ?}; - $self->{list_members_phnums} = $dbh->prepare($sql); - - $sql = qq{select devices.os, devices.push_token from devices, list_members - where devices.num = list_members.device and list_members.list = ? - and list_members.device != ?}; - $self->{select_list_members} = $dbh->prepare($sql); - - # list_members table queries - $sql = 'select device from list_members where list = ?'; - $self->{get_list_members} = $dbh->prepare($sql); - - $sql = 'insert into list_members (list, device, joined) values (?, ?, ?)'; - $self->{new_list_member} = $dbh->prepare($sql); - - $sql = 'delete from list_members where list = ? and device = ?'; - $self->{remove_list_member} = $dbh->prepare($sql); - - $sql = 'select device from list_members where list = ? and device = ?'; - $self->{check_list_member} = $dbh->prepare($sql); - - $sql = qq{select list from list_members where device = ? except - select list from list_members where device = ?}; - $self->{get_other_lists} = $dbh->prepare($sql); - - # list_data table queries - $sql = 'delete from list_data where list = ?'; - $self->{delete_list_data} = $dbh->prepare($sql); - - $sql = 'select * from list_data where list = ?'; - $self->{get_list_items} = $dbh->prepare($sql); - - $sql = 'insert into list_data (list, name, quantity, status, owner, last_updated) values (?, ?, ?, ?, ?, ?)'; - $self->{new_list_item} = $dbh->prepare($sql); -} - -package logger; -use POSIX; - -sub new { - my $class = shift; - - my $self = {}; - bless ($self, $class); - - $self->{addr} = ''; - $self->{port} = ''; - $self->{msg_type} = ''; - return $self; -} - -sub set_peer_host_port { - my ($self, $sock) = @_; - ($self->{addr}, $self->{port}) = ($sock->peerhost(), $sock->peerport()); -} - -sub set_msg { - my ($self, $msg_type) = @_; - - if ($msg_type ne '') { - $self->{msg_type} = "$msg_type: "; - } else { - $self->{msg_type} = ''; - } -} - -sub print { - my ($self, @args) = @_; - - my $ftime = strftime("%F %T", localtime); - printf "%s %-15s %-5s> %s", $ftime, $self->{addr}, $self->{port}, $self->{msg_type}; - # we print potentially unsafe strings here, don't use printf - print @args; -} - -sub print_bare { - my ($self, @args) = @_; - - my $ftime = strftime("%F %T", localtime); - printf "%s> ", $ftime; - printf @args; -}