//---------------------------------------------------------------------------- // // Copyright (C) Intel Corporation, 2006 - 2007. // // File: TunnelHandler.h // // Contents: Handles tunnel connection // // Notes: //---------------------------------------------------------------------------- #ifndef AMT_TUNNEL_HANDLER #define AMT_TUNNEL_HANDLER #include #include "APF.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include #include #include #include #include #include "ChannelManager.h" using namespace std; class Port_Address; // ============================================================================ // = TITLE // Handles reception of APF packet from Intel(R) AMT. // // = DESCRIPTION // Performs parsing on APF messages and acts accordingly. Intended to // run reactively, i.e., in one thread of control using a // Reactor for demuxing and dispatching. // ============================================================================ class AMT_Tunnel_Handler : public ACE_Svc_Handler { friend class AMT_Tunnel_Supplier; friend class AMT_Tunnel_Consumer; public: // = Initialization method. AMT_Tunnel_Handler (void); // = Destruction virtual ~AMT_Tunnel_Handler(void); enum Tunnel_State { // -- NOTE -- for new APF support SESSION_INIT = 1, // SESSION_OPENED, // AUTH_PENDING, // SESSION_AUTHENTICATED, // PFWD_OPEN, // DISCONNECTED // Handler is disconnected, but pending all notifications // in reactor to be dispatched. }; struct disconnectData { ACE_UINT32 _disconnect_reason; // APF Reason for disconnecting this tunnel bool _is_APF_send; //holds true iff we should send APF_DISCONNECT bool _is_consumer_hold_disconnect; //holds true iff consumer already holds a disconnect message PRIORITY _hangup_prio; //if PRIO_HIGH the hangup message will be enqueued to the head of the queue. disconnectData(): _disconnect_reason(APF_DISCONNECT_PROTOCOL_ERROR), _is_APF_send(false), _is_consumer_hold_disconnect(false), _hangup_prio(PRIO_LOW){} // default priority is low, so if no fatel error accured, (if so, we will change the priority to HIGH) // we want to send the messages in queue first, and only then handle the disconnect // (supporting half close connection) void setParams(ACE_UINT32 reason, bool is_APF_send, PRIORITY prio) { _disconnect_reason = reason; _is_APF_send = is_APF_send; _hangup_prio = prio; } void setParams(bool is_APF_send, PRIORITY prio) { _is_APF_send = is_APF_send; _hangup_prio = prio; } }; // = Set/get the current tunnel state. void tunnelState (int state) { tunnel_state_ = state;} int tunnelState (void) const { return tunnel_state_;} // Returns the underlying AMT_Tunnel_Supplier. AMT_Tunnel_Supplier *supplier (void) const { return supplier_;} // Returns the underlying AMT_Tunnel_Consumer. AMT_Tunnel_Consumer *consumer (void) const { return consumer_;} // Returns the underlying Channel_Mgr. Channel_Manager& channel_mgr (void) { return channel_mgr_;} // Handle reactor calls. virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE); virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask close_mask = ACE_Event_Handler::ALL_EVENTS_MASK); virtual int handle_timeout(const ACE_Time_Value ¤t_time, const void * arg = NULL); // Close functions void shutdown_tunnel(); // virtual from ACE_Svc_Handler<> virtual int open (void * pVoid); // int AMT_ID() {return AMT_ID_;} // void AMT_ID(int id) {AMT_ID_ = id;} //ACE_RW_Thread_Mutex& guard() {return tunnel_mutex_;} virtual const char* identifier() {return _identifier.c_str();} void set_identifier(const ACE_CString &str) { _identifier = str;} protected: ACE_CString _identifier; STATUS initiate_io (ACE_Reactor_Mask mask); STATUS cancel_io (ACE_Reactor_Mask mask); STATUS terminate_io (ACE_Reactor_Mask mask); int processReturnVal (int result); //------------------------------------------------------- // return true on the following cases: // (1) some other thread is currently handling this object message's // (so it will handle all messages currently in the queue) // (2) the object is in DISCONNECT state, but we are NOT the last dispacher // (it can happend whan some earlier thread handled several of messages, // so we dont have anything to do) //------------------------------------------------------- bool needReturnWithoutWorking(int* reply); //------------------------------------------------------- // NOTE: // you must take TunnelMgr mutex BEFORE calling this function //------------------------------------------------------- void removeTcpForwardConnection(Port_Address& addr); //------------------------------------------------------- // NOTE: // you must take TunnelMgr mutex BEFORE calling this function //------------------------------------------------------- void removeFromTunnelMgr(); //----------------------------------------------------------- // Disconnect this tunnel due to some error/or socket closed. // // NOTES: // (1) _mutex_disconnect MUST be taken before invoking this method! // This function should be called only ONCE on each tunnel // to make sure the consumer is still running. // (2) the disconnect uses the params in _disconnect_data. //----------------------------------------------------------- STATUS disconnect(); private: AMT_Tunnel_Supplier* supplier_; // Reference to this tunnel supplier AMT_Tunnel_Consumer* consumer_; // Reference to this tunnel consumer Channel_Manager channel_mgr_; // The channel manager int tunnel_state_; // This tunnel state int flg_mask_; // Mask that registers with the reactor ACE_CString full_addr_; ACE_Recursive_Thread_Mutex output_mutex_; ACE_UINT32 AMT_ID_; vector _tcp_forward_connections; //bool _is_consumer_hold_disconnect; // notification on queue ACE_Reactor_Notification_Strategy _notification_strategy; ACE_Recursive_Thread_Mutex _dispatch_output_counter_mutex; ACE_UINT32 _dispatch_output_counter; ACE_RW_Thread_Mutex _state_mutex; ACE_Recursive_Thread_Mutex _active_mutex; ACE_INT32 _active_counter; //bool _send_APF_disconnect; ACE_Recursive_Thread_Mutex _mutex_disconnect; ACE_Recursive_Thread_Mutex _close_mutex; //will be used only in handle_close disconnectData _disconnect_data; }; #endif // AMT_TUNNEL_HANDLER