em-simple_telnet 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/em-simple_telnet.rb +78 -71
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aac1cbb2de2d9e9285a27c2e36f9c255e00f6c13
|
4
|
+
data.tar.gz: 2491898f33c8cf1933ca7389296fb50d6d977b5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa352be4b89435b9c8f2ae773c80dab83a1f6ffba98175c147d9adbaf0eac5497f67418806f5b26bf155c84b702e08effabf763891664974ea95fafe2bae3cf9
|
7
|
+
data.tar.gz: 73b705b35ad35d862000dd2218c4c968ab1200997cce3698cc11c1b4a505d5d79570a0ae5de777846e72ec3e6ccf98dab9a63aa2d6274dcd69c0ae23d1c6f780
|
data/lib/em-simple_telnet.rb
CHANGED
@@ -2,6 +2,9 @@ require "fiber"
|
|
2
2
|
require 'timeout' # for Timeout::Error
|
3
3
|
require "socket" # for SocketError
|
4
4
|
require "eventmachine"
|
5
|
+
require "logger"
|
6
|
+
|
7
|
+
module EventMachine
|
5
8
|
|
6
9
|
##
|
7
10
|
# Provides the facility to connect to telnet servers using EventMachine. The
|
@@ -25,7 +28,7 @@ require "eventmachine"
|
|
25
28
|
# Because of being event-driven, it performs quite well and can handle a lot
|
26
29
|
# of connections concurrently.
|
27
30
|
#
|
28
|
-
class
|
31
|
+
class Protocols::SimpleTelnet < Connection
|
29
32
|
|
30
33
|
# :stopdoc:
|
31
34
|
IAC = 255.chr # "\377" # "\xff" # interpret as command
|
@@ -161,6 +164,16 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
161
164
|
# the root fiber
|
162
165
|
RootFiber = Fiber.current
|
163
166
|
|
167
|
+
# SimpleTelnet.logger
|
168
|
+
@logger = Logger.new($stderr)
|
169
|
+
@logger.progname = "SimpleTelnet"
|
170
|
+
@logger.level = Logger::INFO
|
171
|
+
@logger.level = Logger::DEBUG if $DEBUG
|
172
|
+
|
173
|
+
# @!attribute [r]
|
174
|
+
# the logger instance for SimpleTelnet
|
175
|
+
def self.logger() @logger end
|
176
|
+
|
164
177
|
class << self
|
165
178
|
|
166
179
|
##
|
@@ -193,7 +206,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
193
206
|
end
|
194
207
|
|
195
208
|
if EventMachine.reactor_running? and Fiber.current == RootFiber
|
196
|
-
|
209
|
+
logger.debug "EventMachine reactor had been started " +
|
197
210
|
"independently. Won't stop it automatically."
|
198
211
|
fiber.resume
|
199
212
|
|
@@ -376,7 +389,8 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
376
389
|
@input_rest = ""
|
377
390
|
@wait_time_timer = nil
|
378
391
|
@check_input_buffer_timer = nil
|
379
|
-
@recently_received_data = ""
|
392
|
+
@recently_received_data = ""
|
393
|
+
@logger = opts[:logger] || EventMachine::Protocols::SimpleTelnet.logger
|
380
394
|
|
381
395
|
setup_logging
|
382
396
|
end
|
@@ -384,10 +398,10 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
384
398
|
# Last command that was executed in this telnet session
|
385
399
|
attr_reader :last_command
|
386
400
|
|
387
|
-
#
|
401
|
+
# connection specific logger used to log output
|
388
402
|
attr_reader :output_logger
|
389
403
|
|
390
|
-
#
|
404
|
+
# connection specific logger used to log commands
|
391
405
|
attr_reader :command_logger
|
392
406
|
|
393
407
|
# used telnet options Hash
|
@@ -396,8 +410,11 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
396
410
|
# the callback executed again and again to resume this connection's Fiber
|
397
411
|
attr_accessor :fiber_resumer
|
398
412
|
|
413
|
+
# logger for connection activity (messages from SimpleTelnet)
|
414
|
+
attr_accessor :logger
|
415
|
+
|
416
|
+
# @deprecated use {#fiber_resumer} instead
|
399
417
|
def connection_state_callback
|
400
|
-
warn "#connection_state_callback deprecated. use #fiber_resumer instead"
|
401
418
|
fiber_resumer
|
402
419
|
end
|
403
420
|
|
@@ -471,7 +488,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
471
488
|
end
|
472
489
|
else
|
473
490
|
if seconds
|
474
|
-
warn "
|
491
|
+
logger.warn "Use #timeout= to set the timeout."
|
475
492
|
end
|
476
493
|
@telnet_options[:timeout]
|
477
494
|
end
|
@@ -504,7 +521,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
504
521
|
# #log_output. Then calls #process_payload.
|
505
522
|
#
|
506
523
|
def receive_data data
|
507
|
-
@recently_received_data << data if
|
524
|
+
@recently_received_data << data if logger.debug?
|
508
525
|
if @telnet_options[:telnet_mode]
|
509
526
|
c = @input_rest + data
|
510
527
|
se_pos = c.rindex(/#{IAC}#{SE}/no) || 0
|
@@ -532,10 +549,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
532
549
|
buf = @input_rest + data
|
533
550
|
@input_rest.clear
|
534
551
|
unless @telnet_options[:bin_mode]
|
535
|
-
if
|
536
|
-
buf = buf[0 ... pt_pos]
|
537
|
-
@input_rest = buf[pt_pos .. -1]
|
538
|
-
end
|
552
|
+
buf.chop! if buf =~ /\r\z/no
|
539
553
|
buf.gsub!(/#{EOL}/no, "\n")
|
540
554
|
end
|
541
555
|
end
|
@@ -543,7 +557,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
543
557
|
# in case only telnet sequences were received
|
544
558
|
return if buf.empty?
|
545
559
|
|
546
|
-
log_output(buf
|
560
|
+
log_output(buf)
|
547
561
|
process_payload(buf)
|
548
562
|
end
|
549
563
|
|
@@ -600,10 +614,9 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
600
614
|
when :listening
|
601
615
|
@fiber_resumer.(buf)
|
602
616
|
when :connected, :sleeping
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
end
|
617
|
+
logger.debug "#{node}: Discarding data that was received " +
|
618
|
+
"while not waiting " +
|
619
|
+
"for data (state = #{@connection_state.inspect}): #{buf.inspect}"
|
607
620
|
else
|
608
621
|
raise "Don't know what to do with received data while being in " +
|
609
622
|
"connection state #{@connection_state.inspect}"
|
@@ -695,20 +708,18 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
695
708
|
result = nil
|
696
709
|
while result == nil
|
697
710
|
# measure how long Fiber is paused
|
698
|
-
if
|
711
|
+
if logger.debug?
|
699
712
|
before_pause = Time.now
|
700
713
|
result = Fiber.yield
|
701
714
|
pause_duration = Time.now - before_pause
|
702
715
|
|
703
|
-
|
704
|
-
"is resumed with: #{result.inspect}"
|
705
|
-
result.nil? ? warn(m.red) : warn(m)
|
716
|
+
logger.debug "#{node}: Fiber was paused for " +
|
717
|
+
"#{pause_duration * 1000}ms and is resumed with: #{result.inspect}"
|
706
718
|
else
|
707
719
|
result = Fiber.yield
|
708
720
|
end
|
709
721
|
end
|
710
722
|
|
711
|
-
|
712
723
|
raise result if result.is_a? Exception
|
713
724
|
return result
|
714
725
|
end
|
@@ -740,14 +751,14 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
740
751
|
end
|
741
752
|
|
742
753
|
# Raises Errno::ENOTCONN in case the connection is closed (#unbind has been
|
743
|
-
# called before).
|
754
|
+
# called before).
|
744
755
|
def send_data(s)
|
745
|
-
|
746
|
-
|
747
|
-
end
|
756
|
+
raise Errno::ENOTCONN,
|
757
|
+
"Can't send data: Connection is already closed." if closed?
|
748
758
|
@last_sent_data = Time.now
|
749
|
-
|
750
|
-
|
759
|
+
log_recently_received_data if logger.debug?
|
760
|
+
logger.debug "#{node}: Sending #{s.inspect}"
|
761
|
+
log_output(s)
|
751
762
|
super
|
752
763
|
end
|
753
764
|
|
@@ -821,8 +832,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
821
832
|
# #print is used to send the command to the host instead of #puts.
|
822
833
|
#
|
823
834
|
def cmd command, opts={}
|
824
|
-
command = command.to_s
|
825
|
-
@last_command = command
|
835
|
+
@last_command = command = command.to_s
|
826
836
|
|
827
837
|
# log the command
|
828
838
|
log_command(opts[:hide] ? "<hidden command>" : command)
|
@@ -921,13 +931,9 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
921
931
|
# Finally, the <tt>@connection_state</tt> is set to +closed+.
|
922
932
|
#
|
923
933
|
def unbind(reason)
|
924
|
-
@unbound_at = Time.now
|
925
934
|
prev_conn_state = @connection_state
|
926
935
|
self.connection_state = :closed
|
927
|
-
|
928
|
-
warn "#{node}: unbinding because of: " + reason.inspect.red.bold
|
929
|
-
end
|
930
|
-
@@unbound_at[node] = [ Time.now, prev_conn_state ]
|
936
|
+
logger.debug "#{node}: Unbinding because of: " + reason.inspect
|
931
937
|
@@_telnet_connection_count -= 1
|
932
938
|
close_logs
|
933
939
|
|
@@ -950,17 +956,11 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
950
956
|
when :connecting
|
951
957
|
@fiber_resumer.(ConnectionFailed.new)
|
952
958
|
else
|
953
|
-
|
959
|
+
logger.error "#{node}: bad connection state #{prev_conn_state.inspect} " +
|
954
960
|
"while unbinding"
|
955
|
-
warn m.red
|
956
|
-
debugger
|
957
961
|
end
|
958
962
|
end
|
959
963
|
|
960
|
-
@@unbound_at = {}
|
961
|
-
|
962
|
-
def self.unbound_at() @@unbound_at end
|
963
|
-
|
964
964
|
##
|
965
965
|
# Called by EventMachine after the connection is successfully established.
|
966
966
|
#
|
@@ -968,20 +968,12 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
968
968
|
self.connection_state = :connected
|
969
969
|
@fiber_resumer.(:connection_completed)
|
970
970
|
|
971
|
-
#
|
972
|
-
if
|
973
|
-
EventMachine.add_periodic_timer(0.5) {
|
971
|
+
# log received data in a more readable way
|
972
|
+
if logger.debug?
|
973
|
+
EventMachine.add_periodic_timer(0.5) { log_recently_received_data }
|
974
974
|
end
|
975
975
|
end
|
976
976
|
|
977
|
-
# Prints recently received data (@recently_received), if there's any, and
|
978
|
-
# empties that buffer afterwards.
|
979
|
-
def print_recently_received_data
|
980
|
-
return if @recently_received_data.empty?
|
981
|
-
warn "#{node}: Received: #{@recently_received_data.inspect}".cyan
|
982
|
-
@recently_received_data = ""
|
983
|
-
end
|
984
|
-
|
985
977
|
##
|
986
978
|
# Redefine this method to execute some logout command like +exit+ or
|
987
979
|
# +logout+ before the connection is closed. Don't forget: The command will
|
@@ -1007,6 +999,25 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
1007
999
|
|
1008
1000
|
private
|
1009
1001
|
|
1002
|
+
# Prints recently received data (@recently_received), if there's any, and
|
1003
|
+
# empties that buffer afterwards.
|
1004
|
+
#
|
1005
|
+
# The goal is to log data in a more readable way, by periodically log what
|
1006
|
+
# has recently been received, as opposed to each single character in case of
|
1007
|
+
# a slowly answering telnet server.
|
1008
|
+
def log_recently_received_data
|
1009
|
+
return if @recently_received_data.empty?
|
1010
|
+
logger.debug "#{node}: Received: #{@recently_received_data.inspect}"
|
1011
|
+
@recently_received_data = ""
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
# Returns +true+ if recently received data should be logged.
|
1015
|
+
# @see #log_recently_received_data
|
1016
|
+
# @return [Boolean]
|
1017
|
+
def should_log_recently_received_data?
|
1018
|
+
true & logger.debug?
|
1019
|
+
end
|
1020
|
+
|
1010
1021
|
# Sets the @connection_state to _new_state_. Raises if current (old) state is
|
1011
1022
|
# :closed, because that can't be changed.
|
1012
1023
|
def connection_state=(new_state)
|
@@ -1021,36 +1032,31 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
1021
1032
|
# Sets up output and command logging.
|
1022
1033
|
#
|
1023
1034
|
def setup_logging
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1035
|
+
@output_logger = @command_logger = nil
|
1036
|
+
|
1037
|
+
if file = @telnet_options[:output_log]
|
1038
|
+
@output_logger = Logger.new(file)
|
1039
|
+
log_output "# Starting telnet output log at #{Time.now}\n"
|
1028
1040
|
end
|
1029
1041
|
|
1030
|
-
if @telnet_options[:command_log]
|
1031
|
-
@command_logger = Logger.new
|
1042
|
+
if file = @telnet_options[:command_log]
|
1043
|
+
@command_logger = Logger.new(file)
|
1032
1044
|
end
|
1033
1045
|
end
|
1034
1046
|
|
1035
1047
|
##
|
1036
|
-
# Logs _output_ to output log.
|
1037
|
-
#
|
1048
|
+
# Logs _output_ to output log. Appends a newline if +output+ doesn't end in
|
1049
|
+
# one. To supress this behavior, set +exact+ to +true+.
|
1038
1050
|
#
|
1039
|
-
def log_output output
|
1040
|
-
|
1041
|
-
if exact
|
1042
|
-
@output_logger.print output
|
1043
|
-
else
|
1044
|
-
@output_logger.puts output
|
1045
|
-
end
|
1051
|
+
def log_output output
|
1052
|
+
@output_logger and @output_logger << output
|
1046
1053
|
end
|
1047
1054
|
|
1048
1055
|
##
|
1049
1056
|
# Logs _command_ to command log.
|
1050
1057
|
#
|
1051
1058
|
def log_command command
|
1052
|
-
|
1053
|
-
@command_logger.info command
|
1059
|
+
@command_logger and @command_logger.info command
|
1054
1060
|
end
|
1055
1061
|
|
1056
1062
|
##
|
@@ -1064,7 +1070,7 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
1064
1070
|
string = string.gsub(/#{CR}#{NULL}/no, CR) if telnet_mode?
|
1065
1071
|
|
1066
1072
|
# combine EOL into "\n"
|
1067
|
-
string = string.gsub(/#{EOL}/no,
|
1073
|
+
string = string.gsub(/#{EOL}/no, LF) unless bin_mode?
|
1068
1074
|
|
1069
1075
|
# remove NULL
|
1070
1076
|
string = string.gsub(/#{NULL}/no, '') unless bin_mode?
|
@@ -1119,3 +1125,4 @@ class EventMachine::Protocols::SimpleTelnet < EventMachine::Connection
|
|
1119
1125
|
end
|
1120
1126
|
end
|
1121
1127
|
end
|
1128
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-simple_telnet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrik Wenger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|