telnet.pm 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #!/usr/bin/perl
  2. use Modern::Perl;
  3. use experimental qw/smartmatch/;
  4. package telnet;
  5. use AnyEvent::Handle qw/connect/;
  6. use Mojo::Promise;
  7. use Data::Dumper;
  8. sub new
  9. {
  10. my $class = shift;
  11. my $ip = shift;
  12. return bless {ip => $ip},"telnet";
  13. }
  14. sub connect
  15. {
  16. my $self = shift;
  17. my $promise = new Mojo::Promise;
  18. $self->{handle} = new AnyEvent::Handle
  19. connect => [$self->{ip}, 23],
  20. on_prepare => sub { 30 }, # time-out
  21. on_connect => sub { $promise->resolve },
  22. on_connect_error => sub { $promise->reject("$self->{ip}: " . $_[1]) },
  23. on_rtimeout => sub
  24. {
  25. if ($self->{promise})
  26. {
  27. $self->{promise}->reject("$self->{ip}: read timeout");
  28. }
  29. else
  30. {
  31. say "telnet error: timeout";
  32. }
  33. },
  34. on_error => sub {
  35. my ($hdl, $fatal, $msg) = @_;
  36. $hdl->destroy;
  37. if ($self->{promise})
  38. {
  39. $self->{promise}->reject("$self->{ip}: $msg");
  40. }
  41. else
  42. {
  43. say "telnet error: $msg";
  44. }
  45. };
  46. return $promise;
  47. }
  48. sub print
  49. {
  50. my $self = shift;
  51. my $line = shift;
  52. say STDERR ">>> $line" if $self->{debug};
  53. $self->{handle}->push_write("$line\r\n");
  54. }
  55. sub _new_promise
  56. {
  57. my $self = shift;
  58. $self->{promise} = new Mojo::Promise;
  59. }
  60. sub _wait_for
  61. {
  62. my $self = shift;
  63. my $re = shift;
  64. say STDERR "### waiting for ", $re if $self->{debug};
  65. $self->{handle}->rtimeout(60);
  66. $self->{handle}->push_read(regex => $re, sub
  67. {
  68. my ($h, $text) = @_;
  69. $h->rtimeout(0);
  70. my @lines = split(/\n/, $text);
  71. if ($self->{debug})
  72. {
  73. say "<<< $_" for @lines;
  74. }
  75. shift(@lines);
  76. @lines = map { s/\r//g; $_ } @lines;
  77. $self->{promise}->resolve(@lines) if $self->{promise};
  78. });
  79. return $self->{promise};
  80. }
  81. sub waitfor
  82. {
  83. my $self = shift;
  84. my $re = shift;
  85. $self->_new_promise;
  86. return $self->_wait_for($re);
  87. }
  88. sub prompt
  89. {
  90. my $self = shift;
  91. my $re = shift;
  92. $self->{prompt} = $re;
  93. }
  94. sub cmd
  95. {
  96. my $self = shift;
  97. my $line = shift;
  98. $self->_new_promise;
  99. $self->print($line);
  100. return $self->_wait_for($self->{prompt});
  101. }
  102. sub reply
  103. {
  104. my $self = shift;
  105. my $re = shift;
  106. my $line = shift;
  107. $self->_new_promise;
  108. return $self->_wait_for($re)->then(sub
  109. {
  110. $self->print($line);
  111. });
  112. }
  113. sub close
  114. {
  115. my $self = shift;
  116. undef $self->{handle};
  117. }
  118. sub debug
  119. {
  120. my $self = shift;
  121. my $flag = shift;
  122. $self->{debug} = $flag;
  123. }
  124. 1;