summaryrefslogtreecommitdiff
path: root/lib/agi_server.rb
blob: 29c06c466be2082327d78ba81f61802723de6130 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
module AGIServer
  DEFAULT_AGI_SERVER_HOST = nil
  DEFAULT_AGI_SERVER_PORT = 4573

  def self.log_debug(message)
      puts "DEBUG-AGI-Server: #{message.to_s}"
      #Rails.logger.debug "AGI-Server: #{message}"
  end

  def self.log_error(message)
      puts "ERROR-AGI-Server: #{message.to_s}"
      #Rails.logger.error "AGI-Server: #{message}"
  end

  class Client
    AGI_AVAILABLE_METHODS = ['directory_lookup']
    @client  = nil
    @options = nil

    def set_variable(variable_name, variable_value)
      if !@client
        return false
      end
      @client.puts "SET VARIABLE #{variable_name.to_s} \"#{variable_value.to_s}\""
    end

    def directory_lookup
      number = @options['agi_arg_1'].to_s.gsub(/[^0-9A-Za-z\*_-]/, '')
      number_type = @options['agi_arg_3'].to_s
      client_id = @options['agi_arg_2'].to_i

      if number.blank?
        number = @options['agi_dnid'].to_s.gsub(/[^0-9A-Za-z\*_-]/, '')
        number_type = "unknown"
        client_id = 1
      end

      if client_id > 0
        if number != ""
          phone_number = PhoneNumber.where(:number => number, :phone_numberable_type => "SipAccount").first
          if phone_number.blank?
            set_variable(:directory_status, 'unknown')
            set_variable(:directory_message, 'Number not found in directory')
            return nil
          end

          set_variable(:directory_status, 'exact_match')
          set_variable(:directory_message, 'Exact match')
          set_variable(:directory_number_type, phone_number.phone_numberable_type)
          set_variable(:directory_number_destination, phone_number.phone_numberable.to_s)
          set_variable(:directory_number_host, "1")
          set_variable(:directory_number_name, phone_number.name)
          set_variable(:directory_number_number, phone_number.number)
          set_variable(:directory_number_country_code, phone_number.country_code)
          set_variable(:directory_number_area_code, phone_number.area_code)
          set_variable(:directory_number_central_office_code, phone_number.central_office_code)
          set_variable(:directory_number_subscriber_number, phone_number.subscriber_number)
          set_variable(:directory_number_extension, phone_number.extension)

          if phone_number.phone_numberable_type == "SipAccount"
            set_variable(:directory_caller_name, phone_number.phone_numberable.caller_name)             
          end
        else
          set_variable(:directory_status, 'error')
          set_variable(:directory_message, 'No number specified')
        end
      else
        set_variable(:directory_status, 'error')
        set_variable(:directory_message, 'No ID')
      end
    end

    def handler(client)
      @client = client
      @options = Hash.new
      while @client
        buffer = @client.gets().strip
        if buffer == ""
          if @options['agi_network_script'] && AGI_AVAILABLE_METHODS.include?(@options['agi_network_script'].to_s.downcase)
            self.send(@options['agi_network_script'].to_s.downcase)
          end
          break
        elsif buffer =~ /^.*:\s/
          key, value = buffer.split(': ')
          @options[key]= value
        end
      end
      @client.close
    end
  end

  def self.server( host = DEFAULT_AGI_SERVER_HOST, port = DEFAULT_AGI_SERVER_PORT )

    log_debug("Starting server process.")
    require 'socket'
    server = TCPServer.open(4573)
    if server
      run_server = true
    end

    client_handler_id = 0
    while run_server
      log_debug("Server listening on: #{server.local_address.ip_address}:#{server.local_address.ip_port}")
      
      Thread.start(server.accept) do |client|
        remote_ip   = client.remote_address.ip_address
        remote_port = client.remote_address.ip_port
        
        begin
          client_handler = Client.new
          client_handler_id = client_handler.object_id
          log_debug("[#{client_handler_id}] Connection opened: #{remote_ip}:#{remote_port}")
          client_handler.handler(client)
          log_debug("[#{client_handler_id}] Connection closed: #{remote_ip}:#{remote_port}")
        rescue => e
          log_error("[#{client_handler_id}] #{e.class.to_s}: #{e.to_s},  closing connection: #{remote_ip}:#{remote_port}")
        ensure
          client.close()
        end
      end
    end
  end
end