195 lines
6.7 KiB
C++

//----------------------------------------------------------------------------
//
// Copyright (C) Intel Corporation, 2006 - 2007.
//
// File: TunnelHandler.h
//
// Contents: Handles tunnel connection
//
// Notes:
//----------------------------------------------------------------------------
#ifndef AMT_TUNNEL_HANDLER
#define AMT_TUNNEL_HANDLER
#include <ace/ACE.h>
#include "APF.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include <ace/Svc_Handler.h>
#include <ace/SOCK_Stream.h>
#include <ace/Recursive_Thread_Mutex.h>
#include <ace/Reactor_Notification_Strategy.h>
#include <vector>
#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<ACE_SOCK_STREAM, ACE_MT_SYNCH>
{
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 &current_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<Port_Address> _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