File: BaseConnection.h

package info (click to toggle)
eris 1.2.1-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,360 kB
  • ctags: 1,348
  • sloc: sh: 8,289; cpp: 7,576; perl: 287; ansic: 172; makefile: 143
file content (125 lines) | stat: -rw-r--r-- 4,237 bytes parent folder | download
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
124
125
#ifndef ERIS_BASE_CONNECTION_H
#define ERIS_BASE_CONNECTION_H

#include <sigc++/object.h>
#include <sigc++/signal.h>

#include <iostream>

// Forward declarations
namespace Atlas {
	class Bridge;
	template <class Stream> class Codec;
	namespace Objects { class Encoder; }
	namespace Net { class StreamConnect; }
	namespace Message { class Encoder; }
}	

// Forward declaration of the skstream type
class tcp_socket_stream;

namespace Eris
{

// Forward declarations 
class Timeout;	
	
/// Underlying Atlas connection, providing a send interface, and receive (dispatch) system
class BaseConnection : 
	virtual public SigC::Object
{
public:
	/// destructor, will perform a hard disconnect if necessary
	virtual ~BaseConnection();

	/** open a connection to the specified host/port; invokes the failure handler if
	the connection could not be opened. */
	virtual void connect(const std::string &host, short port);

	/// possible states for the connection
	typedef enum {
		INVALID_STATUS = 0,	///< indicates an illegal state
		NEGOTIATE,		///< Atlas negotiation in progress
		CONNECTING,		///< stream / socket connection in progress
		CONNECTED,		///< connection fully established
		DISCONNECTED,		///< finished disconnection
		DISCONNECTING,		///< clean disconnection in progress
		
		// doesn't really belong here, but enums aren't subclassable
		QUERY_GET		///< meta-query performing GET operation
	} Status;

	/// get the current status of the connection
	Status getStatus() const
	{ return _status; }
	
	/// Ascertain whether or not the connection is usable for transport
	bool isConnected() const
	{ return (_status == CONNECTED) || (_status == DISCONNECTING);}
	
	/** get the underlyinmg file descriptor (socket). This is so GUI / widget libraries which steal
	the main-loop, but can monitor file-decriptors work. The obvious examples being Gtk+/-- and
	Qt */
	int getFileDescriptor();
	
	/// sent on successful negotiation of a game server connection
	SigC::Signal0<void> Connected;
	
	/// final disconnect (or hard disocnnect) notifcation
	SigC::Signal0<void> Disconnected;
protected:
	/// create an unconnected instance
	/** Create a new connection, with the client-name  string specified. The client-name
	is sent during Atlas negotiation of the connection. Id is a unique string to identify
	timeouts created by the connection (and potentially errors in the future) */
	BaseConnection(const std::string &cnm, const std::string &id, Atlas::Bridge *br);	

	/// perform a blocking read from the underlying socket
	void recv();

	/// update the connection status and generate signals
	virtual void setStatus(Status sc);

	/// derived-class notification when connection and negotiation is completed
	virtual void onConnect();

	/// derived-class notification when a failure occurs
	virtual void handleFailure(const std::string &msg) = 0;

	/// hook for derived classes to install a signal handler onto the timeout
	virtual void bindTimeout(Timeout &t, Status sc) = 0;

	/// performs and instant disconnection from the server
	/// @emit specified whether the change of state should be signalled
	void hardDisconnect(bool emit);

    /// complete the connection state and start negotiation
    void nonblockingConnect();

	/// track negotation of the Atlas codecs / stream
	void pollNegotiation();

	Atlas::Objects::Encoder* _encode;	///< the objects encoder, bound to _codec
	Atlas::Message::Encoder* _msgEncode;	///< the message encoder, again bound to _codec
	Atlas::Net::StreamConnect* _sc;		///< negotiation object (NULL after connection!)
	Atlas::Codec<std::iostream>* _codec;		///< the underlying codec object

	Status _status;			///< current status of the connection
	const std::string _id;	///< a unique identifier for this connection
	
	tcp_socket_stream* _stream;		///< the underlying iostream channel
	std::string _clientName;		///< the client identified used during connection
	
	/** the connection bridge (i.e something implementing objectArrived()) : this can be the derived
	class itself, or any other object */
	Atlas::Bridge* _bridge;	
	Timeout* _timeout;		///< network level timeouts	
	
    std::string _host;	///< the host name we're connected to
    short _port;	///< the port we're connected to
};
		
}	

#endif