1 # A Perl module for communicating with the MO Submit Server
2 # (c) 2007 Martin Mares <mj@ucw.cz>
10 use IO::Socket::SSL; # qw(debug3);
15 my $user = $ENV{"USER"} or die "Environment variable USER not set\n";
16 my $home = $ENV{"HOME"} or die "Environment variable HOME not set\n";
18 my $root = $ENV{"MO_ROOT"} or die "Environment variable MO_ROOT not set\n";
20 "Contest" => "CEOI 2007",
21 "Server" => "ceoi-gamma:8888",
22 "Key" => "$mo/key.pem", # Keys and certificates
23 "Cert" => "$mo/cert.pem",
24 "CACert" => "$mo/ca-cert.pem",
25 "Trace" => defined $ENV{"MO_SUBMIT_TRACE"},
26 "Checks" => 1, # Run `check' before submitting
27 "AllowOverride" => 1, # Allow overriding a failed check
28 "History" => "$home/.history", # Keep submission history in this directory
29 "RefreshTimer" => 60000, # How often GUI sends STATUS commands [ms]
44 my ($self, $msg) = @_;
45 print STDERR "SUBMIT: $msg\n" if $self->{"Trace"};
49 my ($self, $msg) = @_;
50 print STDERR "ERROR: $msg\n" if $self->{"Trace"};
51 $self->{"error"} = $msg;
57 return defined $self->{"sk"};
62 if ($self->is_connected) {
64 $self->{"sk"} = undef;
65 $self->log("Disconnected");
73 $self->log("Connecting to submit server");
74 my $sk = new IO::Socket::INET(
75 PeerAddr => $self->{"Server"},
79 $self->err("Cannot connect to server: $!");
84 $self->err("Server failed to send a welcome message");
90 $self->err("Server rejected the connection: $z");
95 $self->log("Starting TLS");
96 $sk = IO::Socket::SSL->start_SSL(
98 SSL_version => 'TLSv1',
100 SSL_key_file => $self->{"Key"},
101 SSL_cert_file => $self->{"Cert"},
102 SSL_ca_file => $self->{"CACert"},
103 SSL_verify_mode => 3,
106 $self->err("Cannot establish TLS connection: " . IO::Socket::SSL::errstr());
113 $self->log("Logging in");
114 my $req = new Sherlock::Object("U" => $self->{"user"});
115 my $reply = $self->request($req);
116 my $err = $reply->get("-");
118 $self->err("Cannot log in: $err");
122 $self->log("Connected");
127 my ($self, $obj) = @_;
128 my $sk = $self->{"sk"};
129 local $SIG{'PIPE'} = 'ignore';
134 $self->err("Connection broken");
141 my ($self, $obj) = @_;
142 my $sk = $self->{"sk"};
143 my $reply = new Sherlock::Object;
144 if ($reply->read($sk)) {
147 $self->err("Connection broken");
153 my ($self, $fh, $size) = @_;
154 my $sk = $self->{"sk"};
155 local $SIG{'PIPE'} = 'ignore';
157 my $l = ($size < 4096 ? $size : 4096);
159 if ($fh->read($buf, $l) != $l) {
160 $self->err("File shrunk during upload");
163 $sk->write($buf, $l);
165 $self->err("Connection broken");
173 sub write_history($$$$$) {
174 my ($self, $task, $part, $ext, $filename) = @_;
175 my $hist = $self->{"History"};
176 -d $hist or mkdir $hist or return "Unable to create $hist: $!";
177 my $now = POSIX::strftime("%H:%M:%S", localtime(time));
178 my $maybe_part = ($part eq $task) ? "" : ":$part";
179 my $name = "$hist/$now-$task$maybe_part.$ext";
180 $self->log("Backing up to $name");
181 `cp "$filename" "$name"`;
182 return "Unable to back up $filename as $name" if $?;