Skip to content

Commit df26c23

Browse files
committed
numerous fixes to ssh2 use, plus some renaming
1 parent 90e9b44 commit df26c23

File tree

1 file changed

+39
-53
lines changed

1 file changed

+39
-53
lines changed

src/cloud/social/provider.ts

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export class CloudSocialProvider {
203203
if (invite.host in this.clients_) {
204204
log.debug('closing old connection to %1', invite.host);
205205
this.clients_[invite.host].then((connection: Connection) => {
206-
connection.close();
206+
connection.end();
207207
});
208208
}
209209

@@ -353,7 +353,7 @@ export class CloudSocialProvider {
353353
log.debug('logout');
354354
for (let address in this.clients_) {
355355
this.clients_[address].then((connection: Connection) => {
356-
connection.close();
356+
connection.end();
357357
});
358358
}
359359
return Promise.resolve<void>();
@@ -430,10 +430,10 @@ class Connection {
430430

431431
private state_ = ConnectionState.NEW;
432432

433-
private client_ = new Client();
433+
private connection_ = new Client();
434434

435435
// The tunneled connection, i.e. secure link to Zork.
436-
private stream_ :ssh2.Channel;
436+
private tunnel_ :ssh2.Channel;
437437

438438
constructor(
439439
private invite_: Invite,
@@ -467,23 +467,22 @@ class Connection {
467467
}
468468

469469
return new Promise<void>((F, R) => {
470-
this.client_.on('ready', () => {
470+
this.connection_.on('ready', () => {
471471
// TODO: set a timeout here, too
472472
this.setState_(ConnectionState.ESTABLISHING_TUNNEL);
473-
this.client_.forwardOut(
473+
this.connection_.forwardOut(
474474
// TODO: since we communicate using the stream, what does this mean?
475475
'127.0.0.1', 0,
476-
ZORK_HOST, ZORK_PORT, (e: Error, stream: ssh2.Channel) => {
476+
ZORK_HOST, ZORK_PORT, (e: Error, tunnel: ssh2.Channel) => {
477477
if (e) {
478-
this.close();
478+
this.end();
479479
R({
480480
message: 'error establishing tunnel: ' + e.message
481481
});
482482
return;
483483
}
484-
this.setState_(ConnectionState.WAITING_FOR_PING);
485484

486-
this.stream_ = stream;
485+
this.setState_(ConnectionState.WAITING_FOR_PING);
487486

488487
var bufferQueue = new queue.Queue<ArrayBuffer, void>();
489488
new linefeeder.LineFeeder(bufferQueue).setSyncHandler((reply: string) => {
@@ -494,7 +493,7 @@ class Connection {
494493
this.setState_(ConnectionState.ESTABLISHED);
495494
F();
496495
} else {
497-
this.close();
496+
this.end();
498497
R({
499498
message: 'did not receive ping from server on login: ' + reply
500499
});
@@ -511,54 +510,36 @@ class Connection {
511510
default:
512511
log.warn('%1: did not expect message in state %2: %3',
513512
this.name_, ConnectionState[this.state_], reply);
514-
this.close();
513+
this.end();
515514
}
516515
});
517516

518-
// TODO: add error handler for stream
519-
stream.on('data', (buffer: Buffer) => {
517+
this.tunnel_ = tunnel;
518+
tunnel.on('data', (buffer: Buffer) => {
520519
bufferQueue.handle(arraybuffers.bufferToArrayBuffer(buffer));
521-
}).on('error', (e: Error) => {
522-
// This occurs when:
523-
// - host cannot be reached, e.g. non-existant hostname
524-
// TODO: does this occur outside of startup, i.e. should it always reject?
525-
log.warn('%1: tunnel error: %2', this.name_, e);
526-
this.close();
527-
R({
528-
message: 'could not establish tunnel: ' + e.message
529-
});
530520
}).on('end', () => {
531-
// Occurs when the stream is "over" for any reason, including
532-
// failed connection.
533521
log.debug('%1: tunnel end', this.name_);
534-
this.close();
535522
}).on('close', (hadError: boolean) => {
536-
// TODO: when does this occur? don't see it on normal close or failure
537-
log.debug('%1: tunnel close: %2', this.name_, hadError);
538-
this.close();
523+
log.debug('%1: tunnel close, with%2 error', this.name_, (hadError ? '' : 'out'));
539524
});
540525

541-
stream.write('ping\n');
526+
tunnel.write('ping\n');
542527
});
543528
}).on('error', (e: Error) => {
544529
// This occurs when:
545530
// - user supplies the wrong username or password
546531
// - host cannot be reached, e.g. non-existant hostname
547-
// TODO: does this occur outside of startup, i.e. should it always reject?
548532
log.warn('%1: connection error: %2', this.name_, e);
549-
this.close();
533+
this.setState_(ConnectionState.TERMINATED);
550534
R({
551535
message: 'could not login: ' + e.message
552536
});
553537
}).on('end', () => {
554-
// Occurs when the connection is "over" for any reason, including
555-
// failed connection.
556-
log.debug('%1: connection ended', this.name_);
557-
this.close();
538+
log.debug('%1: connection end', this.name_);
539+
this.setState_(ConnectionState.TERMINATED);
558540
}).on('close', (hadError: boolean) => {
559-
// TODO: when does this occur? don't see it on normal close or failure
560-
log.debug('%1: connection close: %2', this.name_, hadError);
561-
this.close();
541+
log.debug('%1: connection close, with%1 error', this.name_, (hadError ? '' : 'out'));
542+
this.setState_(ConnectionState.TERMINATED);
562543
}).connect(connectConfig);
563544
});
564545
}
@@ -567,17 +548,14 @@ class Connection {
567548
if (this.state_ !== ConnectionState.ESTABLISHED) {
568549
throw new Error('can only connect in ESTABLISHED state');
569550
}
570-
this.stream_.write(s + '\n');
551+
this.tunnel_.write(s + '\n');
571552
}
572553

573-
public close = (): void => {
554+
public end = (): void => {
574555
log.debug('%1: close', this.name_);
575-
if (this.state_ === ConnectionState.TERMINATED) {
576-
log.debug('%1: already closed', this.name_);
577-
} else {
556+
if (this.state_ !== ConnectionState.TERMINATED) {
578557
this.setState_(ConnectionState.TERMINATED);
579-
this.client_.end();
580-
// TODO: what about the stream?
558+
this.connection_.end();
581559
}
582560
}
583561

@@ -596,21 +574,29 @@ class Connection {
596574
// Executes a command, fulfilling with the command's stdout
597575
// or rejecting if output is received on stderr.
598576
private exec_ = (command:string): Promise<string> => {
577+
log.debug('%1: execute command: %2', this.name_, command);
599578
if (this.state_ !== ConnectionState.ESTABLISHED) {
600579
return Promise.reject(new Error('can only execute commands in ESTABLISHED state'));
601580
}
602581
return new Promise<string>((F, R) => {
603-
this.client_.exec(command, (e: Error, stream: ssh2.Channel) => {
582+
this.connection_.exec(command, (e: Error, stream: ssh2.Channel) => {
604583
if (e) {
605-
R(e);
584+
R({
585+
message: 'failed to execute command: ' + e.message
586+
});
606587
return;
607588
}
608-
stream.on('data', function(data: Buffer) {
589+
590+
// TODO: There is a close event with a return code which
591+
// is probably a better indication of success.
592+
stream.on('data', (data: Buffer) => {
609593
F(data.toString());
610-
}).stderr.on('data', function(data: Buffer) {
611-
R(new Error(data.toString()));
612-
}).on('close', function(code: any, signal: any) {
613-
log.debug('exec stream closed');
594+
}).stderr.on('data', (data: Buffer) => {
595+
R({
596+
message: 'command output to STDERR: ' + data.toString()
597+
});
598+
}).on('end', (code: any, signal: any) => {
599+
log.debug('%1: exec stream end', this.name_);
614600
});
615601
});
616602
});

0 commit comments

Comments
 (0)