Top Level Namespace

Defined Under Namespace

Modules: Softwear Classes: ErrorReportMailer

Instance Method Summary collapse

Instance Method Details

#address_of(socket) ⇒ Object

Send Format: =======

One line strings: “#command #arg1 #arg2 #etc” The last argument, depending on the command, may contain spaces (but usually does not need to)

Receive Format: =====

Usually one string, like “yes”, or “no”. Returns “denied” if an unauthorized command was attempted. Returns “invalid” if an invalid command was attempted. Returns “sorry” if an error was raised while processing the command. Can be a json argument, often following “yes ”.



32
33
34
35
36
37
38
39
# File 'lib/softwear/library/tcp_server.rb', line 32

def address_of(socket)
  _family, port, name, host = socket.addr
  if host == name
    "#{host}:#{port}"
  else
    "#{name}(#{host}):#{port}"
  end
end

#dev_log(*a) ⇒ Object



11
12
13
# File 'lib/softwear/library/tcp_server.rb', line 11

def dev_log(*a)
  $stdout.puts(*a) if Rails.env.development?
end

#log(*a) ⇒ Object



15
16
17
# File 'lib/softwear/library/tcp_server.rb', line 15

def log(*a)
  $stdout.puts(*a) unless Rails.env.test?
end

#report_error(client, whole_command, error) ⇒ Object



5
6
7
8
9
# File 'lib/softwear/library/tcp_server.rb', line 5

def report_error(client, whole_command, error)
  $stderr.puts "=== ERROR WHILE PROCESSING THE COMMAND \"#{whole_command}\" ===\n"\
    "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}"
  client.puts "sorry"
end

#split(string, limit = nil) ⇒ Object



1
2
3
# File 'lib/softwear/library/tcp_server.rb', line 1

def split(string, limit = nil)
  string.split(/\s+/, limit)
end

#start_server!(*args) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/softwear/library/tcp_server.rb', line 41

def start_server!(*args)
  log "Connecting...!"
  
  if args.size > 1
    port = args.first
  else
    port = ENV['port'] || ENV['PORT'] || 2900
  end

  server = TCPServer.new port
  log "Ready! Using \"#{ActiveRecord::Base.connection.current_database}\" database"

  client_count = 0
  commands = args.last

  loop do
    Thread.start(server.accept) do |client|
      client_count += 1
      dev_log "New client! ##{client_count} #{address_of client}"

      if Rails.env.development?
        response_logger = Module.new do
          def puts(s)
            $stdout.puts "==> #{s}"
            super
          end
        end
        client.singleton_class.send :include, response_logger
      end

      while line_in = client.gets.chomp
        log "Processing \"#{line_in}\"" if Rails.env.test?

        command, rest_of_command = split(line_in, 2)

        before = Time.now
        begin
          command = commands[command.downcase.to_sym]

          if command.nil?
            log "SOMEONE attempted invalid command: \"#{line_in}\""
          else
            dev_log "<== #{line_in}"
            ActiveRecord::Base.connection_pool.with_connection do
              command.call(client, rest_of_command)
            end
          end

        rescue StandardError => e
          report_error(client, line_in, e)
        rescue Exception => e
          report_error(client, line_in, e)
          break
        end
        after = Time.now

        ms = (after - before) * 1000
        dev_log %((#{'%.2f' % ms}ms) from #{address_of(client)})
        dev_log ""
      end

      client_count -= 1
      client.close rescue nil
      dev_log "Client disconnected. #{address_of client}"
    end
  end
end