Sean Roach wrote:
... Something to consider. If anyone of the distributed remailers is removed from a ring, the messages that need to travel across that ring can no longer do that. This makes the loop only as strong as its most at risk remailer. The star approach has already been seen in action, the trouble here is a single choke point. Full interconnectability is only feasible in a small net, but I would advise this at first. Check for the x-loop to see if another one got it first. If none, add one and send it on down the line. A disjointed mess, if the remailers are given first access to the list, could work quite well as long as that x-loop remained to point to who sent the message, and the x-loop contained an unalterable message number, and the remailers could eliminate duplications, probably based on message number. This should work as the net grows and would only be as weak as the strongest two connected remailers. Sounds like the internet.
I'd suggest a simplier solution: to connect each server with a couple, or maybe three, other servers. This scheme is rather robust, does not consume too much CPU time and bandwidth, and is easy to implement. - Igor.
Igor Chudov <ichudov@algebra.com> writes:
I'd suggest a simplier solution: to connect each server with a couple, or maybe three, other servers. This scheme is rather robust, does not consume too much CPU time and bandwidth, and is easy to implement.
I'm not sure what the architecture you are suggesting is, but this is what I suggest as the simplest to set up. Have one main majordomo. Have many mail-exploders. You subscribe to the main majordomo request address, and it forwards your subscription request to a random mail-exploder. You unsubscribe to the main majordomo request address, and it forwards your subscription to all the mail-exploders request addresses (unsubscribe traffic is low anyway, keeping track of who is subscribed where at the main major domo doesn't seem worth it). Each person who wishes to run an exploder is subscribed (manually) to the main majordomo. You submit articles to the main majordomo, and it sends copies of the articles to it's subscribers (the mail-exploders). The mail-exploders send mail to the address on their subscriber lists. (John Gilmore suggested this architecture, as a simpler alternative). Adam -- print pack"C*",split/\D+/,`echo "16iII*o\U@{$/=$z;[(pop,pop,unpack"H*",<> )]}\EsMsKsN0[lN*1lK[d2%Sa2/d0<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<J]dsJxp"|dc`
Maybe you have some use for the appended perl script. I created it for a list setup quite similar to what is currently being discussed on cypherpunks. It has never ever been used in production; you'll notice yourself that the code is not too nice. The script currently tries to handle majordomo and SmartList exploders; at least SmartList needs to be hacked a little bit to avoid daily subscription approvals to people being moved between different sub-lists. Distribute and use this script freely; credit is appreciated. tlr ------------------------------ #!/usr/bin/perl ############################################################ # # $Id: distlist.pl,v 1.2 1997/01/24 17:20:38 roessler Exp $ # # # Handle distributed mailing lists. # require 'getopts.pl'; $c_sublists='lists'; # Data about the sublists $c_distfile='dist'; # A list of mail addresses $c_datafile='dist.data'; # _Our_ list of addresses $c_contact='roessler@sobolev.rhein.de'; # Whom to contact in case of problems $sendmail="| /usr/sbin/sendmail -t -odq"; $debug=0; # Debugging output. Can also be # turned on by using the -x switch. $signature="-- \nThis mail has been generated automatically by the distlist\n". "program. Please contact $c_contact in case of problems.\n"; @sublists=(); @newsubs=(); # # Command line processing # &dprint (1, 'Processing the command line...\n'); &Getopts('s:d:D:c:x:'); $c_sublists=$opt_s if $opt_s; $c_distfile=$opt_d if $opt_d; $c_datafile=$opt_D if $opt_D; $c_contact=$opt_c if $opt_c; $debug=$opt_x if $opt_x; # # Read the data and config files, perform various checks. # # # sublists # &dprint(1, "Reading $c_sublists..."); # format: addr:maxsubscr:listtype:password:adminrequest:maintainer open(SUBLISTS, $c_sublists) || die("Can't open $c_sublists"); SUBLIST: while(<SUBLISTS>) { next SUBLIST if /^#/ || /^$/; chop; ($addr, $maxsubscr, $listtype, $password, $admin, $maintainer) = split(/:/, $_); $s_maxsubscr{$addr}=$maxsubscr; $s_listtype{$addr}=$listtype; $s_password{$addr}=$password; $s_admin{$addr}=$admin; $s_maintainer{$addr}=$maintainer; $s_onlist{$addr}=0; $s_addem{$addr}=""; $s_delem{$addr}=""; &dprint(3,"Parsed list $addr: maximum $maxsubscr people; listtype $listtype; password $password.; administrative address $admin; maintainer $maintainer"); @sublists=(@sublists, $addr); } close(SUBLISTS); # In addition, we define a special list for people to be redistributed later. $s_maxsubscr{'later'}=100000; # Very big. ;) $s_listtype{'later'}=""; $s_password{'later'}=""; $s_onlist{'later'}=0; $s_addem{'later'}=""; $s_delem{'later'}=""; # # Read our dist file # # format: user:list if(open(DATAFILE, $c_datafile)) { &dprint(1, "Reading $c_datafile..."); USERLINE: while(<DATAFILE>) { next USERLINE if /^#/ || /^$/; chop; ($user, $list) = split(/:/, $_); # Check if the list exists; handle user. if(! $s_maxsubscr{$list}) { &dprint(2, "While checking user $user: $list does no longer exist."); $list="later"; } elsif( $s_onlist{$list} >= $s_maxsubscr{$list} ) { &dprint(2, "Warning: $list is full. Redistributing people later."); $s_delem{$list}=join(':',$user,$s_delem{$list}); $list="later"; } $s_onlist{$list}++; $u_list{$user}=$list; $deletem{$user}=$user; } close(DATAFILE); &dprint(1,"$c_datafile finished."); } else { &dprint(1, "Warning: Can't read $c_datafile."); } # # Now, read the real distribution file. # &dprint(1, "Reading $c_distfile..."); open(DISTFILE, $c_distfile) || die("Can't open $c_distfile"); DISTLINE: while(<DISTFILE>) { next DISTLINE if /^#/ || /^$/ || /^\(/; chop; if(!$u_list{$_}) { # A new member. &dprint(2, "Found a new member: $_."); @newsubs=($_, @newsubs); } else { # We know him. &dprint(3, "Well-known: $_."); delete $deletem{$_}; } } close(DISTFILE); # # Handle deletions. # foreach $user (keys %deletem) { $list=$u_list{$user}; delete $u_list{$user}; $s_onlist{$list}--; $s_delem{$list}=join(':', $s_delem{$list}, $user); &dprint(3, "Removing $user from sublist $list."); } # # Handle postponed subscriptions: The later list. # foreach (keys %u_list) { next unless $u_list{$_} eq "later"; @newsubs=($_, @newsubs); delete $u_list{$_}; &dprint(3, "Adding $_ to the list of new subscriptions. Was postponed."); } &dprint(1, "Distributing new subscriptions..."); NEWSUBS: foreach $user (@newsubs) { $avg=0.0; foreach $l (@sublists) { $avg += $s_onlist{$l}/$s_maxsubscr{$l}; } $avg = $avg / ($#sublists + 1.0); if ($avg >= 1) { &dprint(2, "Warning: All sublists are full while trying to insert $user."); } undef $possible; foreach $l (@sublists) { if($s_onlist{$l} <= $avg*$s_maxsubscr{$l}) { $possible=$l; } if($s_onlist{$l} < $avg*$s_maxsubscr{$l}) { last; } } if($possible) { $l = $possible; } $s_addem{$l}=join(':', $s_addem{$l}, $user); $s_onlist{$l}++; $u_list{$user}=$l; } # # Write our own data file. # if(open(DATAFILE, ">$c_datafile")) { foreach (keys %u_list) { printf DATAFILE "%s:%s\n", $_, $u_list{$_}; } close(DATAFILE); } else { &dprint(1, "Warning: Can't write $c_datafile."); } # # The lists have been put together. Commit the changes. # &dprint(1, "Committing the changes..."); foreach $l (@sublists) { if($s_listtype{$l} eq "majordomo") { &commit_majordomo($l); } elsif ($s_listtype{$l} eq "smartlist") { &commit_smartlist($l); } else { &dprint(1, "While trying to commit changes for $l:"); &dprint(1, "Unknown list type $s_listtype{$l}.\n"); } } # # To be done: Print out some statistics. # print "Distlist results:\n"; print "-----------------\n"; print "\n"; printf "There are currently %d subscribers on %d sublists.\n\n", scalar(keys %u_list), $#sublists+1; $full_lists=0; printf "%-40s on max\n", "Name"; printf "----------------------------------------------------\n"; foreach $l (@sublists) { printf "%-40s %4d %4d", $l, $s_onlist{$l}, $s_maxsubscr{$l}; if($s_onlist{$l} >= $s_maxsubscr{$l}) { print " *** This list is full ***"; $full_lists++; } print "\n"; } if($full_lists) { print "\n$full_lists of the sublists are *full*. Please get in touch\n"; print "with the maintainers.\n"; } print "\n\n"; print $signature; ############################################################ # # Some helper functions. # # Print out diagnostics. sub dprint { if($_[0] <= $debug) { printf STDERR "%s\n", $_[1]; } } sub commit_majordomo { my $list=$_[0]; my @bla; my $ll; my $user; &dprint(2, "Committing changes to majordomo list $list"); &dprint(3, "to be added: $s_addem{$list}"); &dprint(3, "to be deleted: $s_delem{$list}"); ($ll, @bla)=split(/@/, $list); if(!open(SENDMAIL, $sendmail)) { &dprint(1, "Warning: Can't start sendmail when committing changes to $list"); } print SENDMAIL "To: $s_admin{$list}\n"; print SENDMAIL "From: $c_contact\n"; print SENDMAIL "\n\n"; foreach $user (@bla=split(/:/, $s_addem{$list})) { print SENDMAIL "approve $s_password{$list} subscribe $ll $user\n" if $u_list{$user}; } foreach $user (@bla=split(/:/, $s_delem{$list})) { print SENDMAIL "approve $s_password{$list} unsubscribe $ll $user\n" unless $u_list{$user} eq $list; } print SENDMAIL $signature; close(SENDMAIL); } sub smartlist_xcommand { my ($list, $to, $passwd, $command, $maintainer) = @_; if(!open(SENDMAIL, $sendmail)) { &dprint(1, "Can't start sendmail when committing changes for $list"); } print SENDMAIL "To: $to\n"; print SENDMAIL "From: $c_contact\n"; print SENDMAIL "X-Command: $maintainer $passwd $command\n"; print SENDMAIL "\n\n"; print SENDMAIL $signature; close SENDMAIL; } sub commit_smartlist { my $list=$_[0]; my @bla; my $user; &dprint(2, "Committing changes to smartlist list $list"); foreach $user (@bla=split(/:/, $s_addem{$list})) { &smartlist_xcommand($list, $s_admin{$list}, $s_password{$list}, "subscribe $user", $s_maintainer{$list}) if $u_list{$user}; } foreach $user (@bla=split(/:/, $s_delem{$list})) { &smartlist_xcommand($list, $s_admin{$list}, $s_password{$list}, "unsubscribe $user", $s_maintainer{$list}) unless $u_list{$user} eq $list; } }
participants (3)
-
Adam Back
-
ichudov@algebra.com
-
Thomas Roessler