# = Trisul Remote Protocol functions # # dependency = ruby_protobuf # # Akhil.M & Dhinesh.K (c) 2010 Unleash Networks require 'openssl' require 'socket' require 'time' # ==== TrisulRP::Protocol # Contains methods to help with common TRP tasks like # * creating connections # * interacting with Trisul via requests/responses # * helpers to create objects # # module TrisulRP::Protocol include TrisulRP::Guids # Establish a TLS connection to a Trisul instance # # [server] IP Address or hostname # [port] TRP port, typically 12001 (see trisulConfig.xml) # [client_cert_file] Client certificate file issued by admin # [client_key_file] Client key file issued by admin # # # ==== Returns # ==== Yields # a connection object that can be used in subsequent calls # # ==== On error # If a connection cannot be established, an exception is thrown which can point # to the actual cause. The most common causes are # # * Trisul is not running # * Trisul is not running in trp mode (see the docs for runmode) # * Using the wrong port ( check netstat to verify trisul remote protocol port - typically 12001) # * The Access Control List does not permit connections from client IP # def connect(server,port,client_cert_file,client_key_file) tcp_sock=TCPSocket.open(server,port) ctx = OpenSSL::SSL::SSLContext.new(:TLSv1) ctx.cert = OpenSSL::X509::Certificate.new(File.read(client_cert_file)) ctx.key = OpenSSL::PKey::RSA.new(File.read(client_key_file)) ssl_sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) ssl_sock.connect yield ssl_sock if block_given? return ssl_sock end # Dispatch request to server & get response # [conn] TRP connection previously opened via TrisulRP::Protocol::connect # [trp_request] a TRP request object, created directly or using the mk_request helper # # ==== Returns # ==== Yields # a response object, you can then inspect the fields in the response and spawn additional # requests if required # # ==== On error # raises an error if the server returns an ErrorResponse - this contains an error_message field # which can tell you what went wrong # def get_response(conn,trp_request) outbuf="" outbuf=trp_request.serialize_to_string conn.write([outbuf.length].pack("N*")) conn.write(outbuf) inbuf = conn.read(4) buflenarr=inbuf.unpack("N*") datalen=buflenarr[0] dataarray=conn.read(datalen) resp =TRP::Message.new resp.parse dataarray raise resp.error_response if resp.trp_command == TRP::Message::Command::ERROR_RESPONSE yield unwrap_response(resp) if block_given? return unwrap_response(resp) end # Query the total time window available in Trisul # # [conn] TRP connection previously opened via connect # # ==== Returns # returns an array of two Time objects [Time_from, Time_to] representing start and end time # # ==== Typical usage # # You pass the output of this method to mk_time_interval to get an object you can attach to a # TRP request. # # # # tmarr = TrisulRP::Protocol::get_avaiable_time(conn) # req =TrisulRP::Protocol.mk_request( :source_ip => target_ip,... # :time_interval => TrisulRP::Protocol::mk_time_interval(tm_arr)) # # # def get_available_time(conn) from_tm=to_tm=nil req=mk_request(TRP::Message::Command::COUNTER_GROUP_INFO_REQUEST, :counter_group => TrisulRP::Guids::CG_AGGREGATE) get_response(conn,req) do |resp| from_tm = Time.at(resp.group_details[0].time_interval.from.tv_sec) to_tm = Time.at(resp.group_details[0].time_interval.to.tv_sec) end return [from_tm,to_tm] end # Helper to create a TRP TimeInterval object # # [tmarr] An array of two Time objects representing a window # # ==== Returns # A TRP::TimeInterval object which can be attached to any :time_interval field of a TRP request # def mk_time_interval(tmarr) tint=TRP::TimeInterval.new tint.from=TRP::Timestamp.new(:tv_sec => tmarr[0].tv_sec, :tv_usec => 0) tint.to=TRP::Timestamp.new(:tv_sec => tmarr[1].tv_sec, :tv_usec => 0) return tint end # Helper to create a TRP request object # # Read the TRP documentation wiki for a description of each command. # # [cmd_id] The command ID. # [params] A hash containing command parameters # # ==== Typical usage # # # # # create a new command of type KeySessionActivityRequest # req = TrisulRP::Protocol.mk_request(TRP::Message::Command::KEY_SESS_ACTIVITY_REQUEST, # :key => target_key , # :time_interval => mk_time_interval(tmarr)) # # ... now you can use the req object ... # # # # You can also create the request objects directly, just a little too verbose for our liking # # # # # create a new command of type CounterItemRequest # req =TRP::Message.new(:trp_command => TRP::Message::Command::KEY_SESS_ACTIVITY_REQUEST ) # req.key_session_activity_request = TRP::KeySessionActivityRequest.new( # :key => target_key , # :time_interval => mk_time_interval(tmarr)) # # ... now you can use the req object ... # # # # def mk_request(cmd_id,params={}) req = TRP::Message.new(:trp_command => cmd_id) case cmd_id when TRP::Message::Command::HELLO_REQUEST req.hello_request = TRP::HelloRequest.new(params) when TRP::Message::Command::COUNTER_GROUP_REQUEST req.counter_group_request = TRP::CounterGroupRequest.new(params) when TRP::Message::Command::COUNTER_ITEM_REQUEST req.counter_item_request = TRP::CounterItemRequest.new(params) when TRP::Message::Command::RELEASE_RESOURCE_REQUEST req.release_resource_request = TRP::ReleaseResourceRequest.new(params) when TRP::Message::Command::CONTROLLED_COUNTER_GROUP_REQUEST req.controlled_counter_group_request = TRP::ControlledCounterGroupRequest.new(params) when TRP::Message::Command::FILTERED_DATAGRAMS_REQUEST req.filtered_datagram_request = TRP::FilteredDatagramRequest.new(params) when TRP::Message::Command::CONTROLLED_CONTEXT_REQUEST req.controlled_context_request = TRP::ControlledContextRequest.new(params) when TRP::Message::Command::SEARCH_KEYS_REQUEST req.search_keys_request = TRP::SearchKeysRequest.new(params) when TRP::Message::Command::BULK_COUNTER_ITEM_REQUEST req.bulk_counter_item_request = TRP::BulkCounterItemRequest.new(params) when TRP::Message::Command:: CGMONITOR_REQUEST req.cgmonitor_request = TRP::CgmonitorRequest.new(params) when TRP::Message::Command::TOPPER_SNAPSHOT_REQUEST req.topper_snapshot_request = TRP::TopperSnapshotRequest.new(params) when TRP::Message::Command::UPDATE_KEY_REQUEST req.update_key_request = TRP::UpdateKeyRequest.new(params) when TRP::Message::Command::RING_STATS_REQUEST req.ring_stats_request = TRP::RingStatsRequest.new(params) when TRP::Message::Command::SERVER_STATS_REQUEST req.server_stats_request = TRP::ServerStatsRequest.new(params) when TRP::Message::Command::SESSION_ITEM_REQUEST req.session_item_request = TRP::SessionItemRequest.new(params) when TRP::Message::Command::SESSION_GROUP_REQUEST req.session_group_request = TRP::SessionGroupRequest.new(params) when TRP::Message::Command::ALERT_ITEM_REQUEST req.alert_item_request = TRP::AlertItemRequest.new(params) when TRP::Message::Command::ALERT_GROUP_REQUEST req.alert_group_request = TRP::AlertGroupRequest.new(params) when TRP::Message::Command::RESOURCE_ITEM_REQUEST req.resource_item_request = TRP::ResourceItemRequest.new(params) when TRP::Message::Command::RESOURCE_GROUP_REQUEST req.resource_group_request = TRP::ResourceGroupRequest.new(params) when TRP::Message::Command::KEY_LOOKUP_REQUEST req.key_lookup_request = TRP::KeyLookupRequest.new(params) when TRP::Message::Command::COUNTER_GROUP_INFO_REQUEST req.counter_group_info_request = TRP::CounterGroupInfoRequest.new(params) when TRP::Message::Command::SESSION_TRACKER_REQUEST req.session_tracker_request = TRP::SessionTrackerRequest.new(params) when TRP::Message::Command::KEY_SESS_ACTIVITY_REQUEST req.key_session_activity_request = TRP::KeySessionActivityRequest.new(params) when TRP::Message::Command::GREP_REQUEST req.grep_request = TRP::GrepRequest.new(params) else raise "Unknown TRP command ID" end return req end # Helper to unwrap a response # # All protobuf messages used in TRP have a wrapper containing a command_id which identifies # the type of encapsulated message. This sometimes gets in the way because you have to write # stuff like # # # # response.counter_group_response.blah_blah # # instead of # # response.blah_blah # # # # Read the TRP documentation wiki for a description of each command. # # [resp] The response # # ==== Typical usage # # # # # create a new command of type KeySessionActivityRequest # req = TrisulRP::Protocol.get_response(...) do |resp| # # # here resp points to the inner response without the wrapper # # this allows you to write resp.xyz instead of resp.hello_response.xyz # # # end # # # # def unwrap_response(resp) case resp.trp_command when TRP::Message::Command::HELLO_RESPONSE resp.hello_response when TRP::Message::Command::COUNTER_GROUP_RESPONSE resp.counter_group_response when TRP::Message::Command::COUNTER_ITEM_RESPONSE resp.counter_item_response when TRP::Message::Command::OK_RESPONSE resp.ok_response when TRP::Message::Command::CONTROLLED_COUNTER_GROUP_RESPONSE resp.controlled_counter_group_response when TRP::Message::Command::FILTERED_DATAGRAMS_RESPONSE resp.filtered_datagram_response when TRP::Message::Command::CONTROLLED_CONTEXT_RESPONSE resp.controlled_context_response when TRP::Message::Command::SEARCH_KEYS_RESPONSE resp.search_keys_response when TRP::Message::Command::BULK_COUNTER_ITEM_RESPONSE resp.bulk_counter_item_response when TRP::Message::Command:: CGMONITOR_RESPONSE resp.cgmonitor_response when TRP::Message::Command::TOPPER_SNAPSHOT_RESPONSE resp.topper_snapshot_response when TRP::Message::Command::UPDATE_KEY_RESPONSE resp.update_key_response when TRP::Message::Command::RING_STATS_RESPONSE resp.ring_stats_response when TRP::Message::Command::SERVER_STATS_RESPONSE resp.server_stats_response when TRP::Message::Command::SESSION_ITEM_RESPONSE resp.session_item_response when TRP::Message::Command::SESSION_GROUP_RESPONSE resp.session_group_response when TRP::Message::Command::ALERT_ITEM_RESPONSE resp.alert_item_response when TRP::Message::Command::ALERT_GROUP_RESPONSE resp.alert_group_response when TRP::Message::Command::RESOURCE_ITEM_RESPONSE resp.resource_item_response when TRP::Message::Command::RESOURCE_GROUP_RESPONSE resp.resource_group_response when TRP::Message::Command::KEY_LOOKUP_RESPONSE resp.key_lookup_response when TRP::Message::Command::COUNTER_GROUP_INFO_RESPONSE resp.counter_group_info_response when TRP::Message::Command::SESSION_TRACKER_RESPONSE resp.session_tracker_response when TRP::Message::Command::KEY_SESS_ACTIVITY_RESPONSE resp.key_session_activity_response when TRP::Message::Command::GREP_RESPONSE resp.grep_response else raise "Unknown TRP command ID" end end end