Commit ed55f418 authored by Leigh Stoller's avatar Leigh Stoller

Fixup capture/tip/power_rpc27 so that capture returns a positive

ack/nak for a connection so that the connecting process knows what the
hell is going on. Turned out to be necessary for power control since
we do that in parallel, and because it stays busy for 10 seconds on
each power control. I think we will end up revisiting this at some
point, adding blocking connections instead of connect/fail status.
parent 1f160215
......@@ -38,3 +38,15 @@ typedef struct {
int portnum;
secretkey_t key;
} whoami_t;
/*
* Return Status. Define a constant size return to ensure that the
* status is read as an independent block, distinct from any output
* that might be sent. An int is a reasonable thing to use.
*
* XXX: If you change this, be sure to change the PERL code!
*/
#define CAPOK 0
#define CAPBUSY 1
#define CAPNOPERM 2
typedef int capret_t;
......@@ -946,6 +946,7 @@ clientconnect()
int cc, length = sizeof(tipclient);
int newfd;
secretkey_t key;
capret_t capret;
newfd = accept(sockfd, (struct sockaddr *)&tipclient, &length);
if (newfd < 0)
......@@ -958,9 +959,15 @@ clientconnect()
* sounds horribly brutish!
*/
if (tipactive) {
close(newfd);
capret = CAPBUSY;
if ((cc = write(newfd, &capret, sizeof(capret))) <= 0) {
dolog(LOG_NOTICE, "%s refusing. error writing status",
inet_ntoa(tipclient.sin_addr));
}
dolog(LOG_NOTICE, "%s connecting, but tip is active",
inet_ntoa(tipclient.sin_addr));
close(newfd);
return 1;
}
ptyfd = newfd;
......@@ -979,6 +986,14 @@ clientconnect()
if (cc != sizeof(key) ||
key.keylen != strlen(key.key) ||
strncmp(secretkey.key, key.key, key.keylen)) {
/*
* Tell the other side that all is okay.
*/
capret = CAPNOPERM;
if ((cc = write(ptyfd, &capret, sizeof(capret))) <= 0) {
dolog(LOG_NOTICE, "%s connecting, error perm status",
inet_ntoa(tipclient.sin_addr));
}
close(ptyfd);
dolog(LOG_NOTICE,
"%s connecting, secret key does not match",
......@@ -990,6 +1005,16 @@ clientconnect()
dolog(LOG_INFO, "Key: %d: %s",
secretkey.keylen, secretkey.key);
#endif
/*
* Tell the other side that all is okay.
*/
capret = CAPOK;
if ((cc = write(ptyfd, &capret, sizeof(capret))) <= 0) {
close(ptyfd);
dolog(LOG_NOTICE, "%s connecting, error writing status",
inet_ntoa(tipclient.sin_addr));
return 1;
}
/*
* See Mike comments (use threads) above.
......
......@@ -69,18 +69,21 @@ sub rpc27ctrl {
#
$insync = 0;
for ($i = 0; $i < 10; $i++) {
for ($i = 0; $i < 20; $i++) {
my $line;
if (syswrite($TIP, "\r\n") == 0) {
print STDERR
"*** Power control sync failed ($controller/$outlet)\n";
"*** Power control sync write failed ($controller/$outlet)\n";
close($TIP);
return 1;
}
if (sysread($TIP, $line, 1024) == 0) {
last;
print STDERR
"*** Power control sync read failed ($controller/$outlet)\n";
close($TIP);
return 1;
}
if ($debug) {
print "Read: $line";
......@@ -121,7 +124,7 @@ sub rpc27ctrl {
#
sub tipconnect($) {
my($controller) = $_[0];
my($server, $portnum, $keylen, $keydata);
my($server, $portnum, $keylen, $keydata, $capreturn);
my($inetaddr, $paddr, $proto);
my(%powerid_row);
local *TIP;
......@@ -149,6 +152,7 @@ sub tipconnect($) {
# to make it look like the C struct.
#
my $secretkey = pack("iZ256", $keylen, $keydata);
my $capret = pack("i", 0);
#
# This stuff from the PERLIPC manpage.
......@@ -160,11 +164,7 @@ sub tipconnect($) {
$paddr = sockaddr_in($portnum, $inetaddr);
$proto = getprotobyname('tcp');
#
# We have no locking protocol in place for the tiplines. So, loop
# a small number of time, trying to form a proper connection.
#
for ($i = 0; $i < 10; $i++) {
for ($i = 0; $i < 20; $i++) {
if (! socket(TIP, PF_INET, SOCK_STREAM, $proto)) {
print STDERR "*** Cannot create socket.\n";
return 0;
......@@ -173,29 +173,42 @@ sub tipconnect($) {
if (! connect(TIP, $paddr)) {
print STDERR
"*** Cannot connect to $controller on $server($portnum)\n";
close(TIP);
return 0;
}
TIP->autoflush(1);
#
# If the connect succeeds, but the write fails, it means that the
# other end dropped the connection cause there was already a tip
# active (either a person on the tip line, or another power control).
#
# I'm not happy about this. We need a more positive action protocol.
#
if (syswrite(TIP, $secretkey) > 0) {
if (! syswrite(TIP, $secretkey)) {
print STDERR
"*** Cannot write to $controller on $server($portnum)\n";
close(TIP);
return 0;
}
if (! sysread(TIP, $capret, length($capret))) {
print STDERR
"*** Cannot read from $controller on $server($portnum)\n";
close(TIP);
return 0;
}
my $foo = unpack("i", $capret);
if ($debug) {
print "Capture returned $foo\n";
}
if ($foo == 0) {
return(*TIP);
}
print STDERR
"*** WARNING: Cannot write to $controller on $server($portnum)" .
" Power controller might be busy. Waiting a bit ...\n";
close(TIP);
if ($i > 5) {
printf STDERR
"*** WARNING: $controller on $server($portnum) is busy\n".
" Waiting a bit before trying again.\n";
}
sleep(5);
}
print STDERR
"*** Cannot connect to $controller on $server($portnum)\n";
"*** $controller on $server($portnum) was busy for too long\n";
return 0;
}
......
......@@ -36,7 +36,7 @@
static char sccsid[] = "@(#)hunt.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$Id: hunt.c,v 1.9 2001-08-20 15:26:06 stoller Exp $";
"$Id: hunt.c,v 1.10 2001-08-29 19:36:09 stoller Exp $";
#endif /* not lint */
#ifdef USESOCKETS
......@@ -153,7 +153,8 @@ socket_open(char *tipname)
char aclname[BUFSIZ];
char b1[256], b2[256];
secretkey_t key;
int port;
capret_t capret;
int port, cc;
char hostname[MAXHOSTNAMELEN];
FILE *fp;
struct hostent *he;
......@@ -226,11 +227,27 @@ socket_open(char *tipname)
/*
* Send the secretkey.
*/
if (write(sock, &key, sizeof(key)) != sizeof(key)) {
close(sock);
return -1;
}
if (write(sock, &key, sizeof(key)) != sizeof(key))
goto screwed;
/*
* Wait for the response.
*/
if ((cc = read(sock, &capret, sizeof(capret))) <= 0)
goto screwed;
if (capret != CAPOK) {
if (capret == CAPBUSY)
fprintf(stderr, "Tip line busy. Try again later?\n");
if (capret == CAPNOPERM)
fprintf(stderr, "You do not have permission!\n");
goto screwed;
}
return sock;
screwed:
close(sock);
deadfl = 1;
longjmp(deadline, 1);
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment