em-simple_telnet 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- 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
|