Commits

Christian Fischer committed e97a9da

added functions for asynchronous connections

Comments (0)

Files changed (6)

src/net/wiesel/io/net/connection.cpp

 #include "connection.h"
 #include "connector.h"
 
+#include "connection_event_dispatcher.h"
+#include <wiesel/util/thread.h>
+
 #include <wiesel/module_registry.h>
 
 using namespace wiesel;
 
 
 
+
+class CreateConnectionAsyncTask : public IRunnable
+{
+public:
+	CreateConnectionAsyncTask(const std::string& address, ConnectionListener *listener) {
+		this->address	= address;
+		this->listener	= keep(listener);
+	}
+
+	virtual ~CreateConnectionAsyncTask() {
+		safe_release(listener);
+	}
+
+	virtual void run() {
+		ConnectionEventDispatcher::ConnectionListeners listeners;
+		listeners.push_back(listener);
+
+		Connection *connection = Connection::createConnection(address);
+
+		// attach the listener to a successfully created connection
+		if (connection) {
+			connection->addListener(listener);
+		}
+
+		ConnectionEventDispatcher::dispatch(
+							listeners,
+							connection
+								? ConnectionEventDispatcher::ConnectionEvent_Connected
+								: ConnectionEventDispatcher::ConnectionEvent_ConnectionFailed,
+							address,
+							connection
+		);
+
+		return;
+	}
+
+private:
+	std::string				address;
+	ConnectionListener*		listener;
+};
+
+
+
+
+
 Connection::Connection() {
 }
 
 }
 
 
+void Connection::createConnectionAsync(const std::string& address, ConnectionListener* listener) {
+	Thread *thread = new Thread(new CreateConnectionAsyncTask(address, listener));
+	thread->start();
+	thread->detach();
+
+	return;
+}
+
+
 void Connection::setCurrentAddress(const std::string& address) {
 	this->address = address;
 }

src/net/wiesel/io/net/connection.h

 		/**
 		 * @brief Creates a new connection to a specific address.
 		 * For TCP Connections, this address should be in the format host:port
+		 * @param address	The address to connect to.
 		 * @return A new \ref Connection object or \c NULL, when the connection was not successful.
 		 */
 		static Connection* createConnection(const std::string& address);
 
+		/**
+		 * @brief Tries to connect to the given address within a seperate thread.
+		 * @param address	The address to connect to.
+		 * @param listener	The listener which will receive the created connection on success
+		 *					or an onConnectionFailed event, when no connection could be established.
+		 *					When successful, the listener will be attached to the created connection.
+		 */
+		static void createConnectionAsync(const std::string& address, ConnectionListener *listener);
+
 	public:
 		/// alias type for data sent via network.
 		typedef uint8_t data_t;

src/net/wiesel/io/net/connection_event_dispatcher.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "connection_event_dispatcher.h"
+
+#include <wiesel/engine.h>
+
+using namespace wiesel;
+
+
+void ConnectionEventDispatcher::dispatch(
+			const ConnectionListeners&		listeners,
+			ConnectionEvent					event,
+			std::string						address,
+			Connection*						connection
+) {
+	ConnectionEventDispatcher *dispatcher = new ConnectionEventDispatcher(
+			listeners, event, address, connection
+	);
+
+	Engine::getInstance()->runOnMainThread(dispatcher);
+}
+
+
+ConnectionEventDispatcher::ConnectionEventDispatcher(
+			const ConnectionListeners&		listeners,
+			ConnectionEvent					event,
+			std::string						address,
+			Connection*						connection
+) :
+	listeners(listeners),
+	event(event),
+	address(address),
+	connection(connection)
+{
+	return;
+}
+
+ConnectionEventDispatcher::~ConnectionEventDispatcher() {
+	return;
+}
+
+
+void ConnectionEventDispatcher::run() {
+	switch(event) {
+		case ConnectionEvent_Connected: {
+			for(ConnectionListeners::iterator it=listeners.begin(); it!=listeners.end(); it++) {
+				(*it)->onConnected(address, connection);
+			}
+
+			break;
+		}
+
+		case ConnectionEvent_ConnectionFailed: {
+			for(ConnectionListeners::iterator it=listeners.begin(); it!=listeners.end(); it++) {
+				(*it)->onConnectionFailed(address);
+			}
+
+			break;
+		}
+
+		case ConnectionEvent_Disconnected: {
+			for(ConnectionListeners::iterator it=listeners.begin(); it!=listeners.end(); it++) {
+				(*it)->onDisconnected(address, connection);
+			}
+
+			break;
+		}
+	}
+
+	return;
+}
+

src/net/wiesel/io/net/connection_event_dispatcher.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_IO_NET_CONNECTION_EVENT_DISPATCHER_H__
+#define	__WIESEL_IO_NET_CONNECTION_EVENT_DISPATCHER_H__
+
+#include "connection.h"
+#include "wiesel/util/thread.h"
+
+#include <list>
+
+namespace wiesel {
+
+	/**
+	 * @brief Utility class for dispatching connection events to the mainthread.
+	 */
+	class ConnectionEventDispatcher : public IRunnable
+	{
+	public:
+		typedef std::list<ConnectionListener*> ConnectionListeners;
+
+		enum ConnectionEvent {
+			ConnectionEvent_Connected,
+			ConnectionEvent_ConnectionFailed,
+			ConnectionEvent_Disconnected,
+		};
+
+
+		static void dispatch(
+				const ConnectionListeners&	listeners,
+				ConnectionEvent				event,
+				std::string					address,
+				Connection*					connection
+		);
+
+		ConnectionEventDispatcher(
+				const ConnectionListeners&	listeners,
+				ConnectionEvent				event,
+				std::string					address,
+				Connection*					connection
+		);
+
+		virtual ~ConnectionEventDispatcher();
+
+	public:
+		virtual void run();
+
+	private:
+		ConnectionListeners		listeners;
+		ConnectionEvent			event;
+		std::string				address;
+		ref<Connection>			connection;
+	};
+
+
+}
+
+#endif // __WIESEL_IO_NET_CONNECTION_EVENT_DISPATCHER_H__
+

src/net/wiesel/io/net/message_dispatcher.cpp

  * Boston, MA 02110-1301 USA
  */
 #include "message_dispatcher.h"
+#include "connection_event_dispatcher.h"
 #include "wiesel/util/log.h"
 #include "wiesel/engine.h"
 
 using namespace wiesel;
 
 
-
-enum ConnectionEvent {
-	ConnectionEvent_Connected,
-	ConnectionEvent_ConnectionFailed,
-	ConnectionEvent_Disconnected,
-};
-
-
-class ConnectionEventDispatcher : public IRunnable
-{
-public:
-	ConnectionEventDispatcher(
-			MessageDispatcher::Listeners	listeners,
-			ConnectionEvent					event,
-			std::string						address,
-			Connection*						connection
-	) :
-		listeners(listeners),
-		event(event),
-		address(address),
-		connection(connection)
-	{
-		return;
-	}
-
-	virtual ~ConnectionEventDispatcher() {
-		return;
-	}
-
-public:
-	virtual void run() {
-		switch(event) {
-			case ConnectionEvent_Connected: {
-				for(MessageDispatcher::Listeners::iterator it=listeners.begin(); it!=listeners.end(); it++) {
-					(*it)->onConnected(address, connection);
-				}
-
-				break;
-			}
-
-			case ConnectionEvent_ConnectionFailed: {
-				for(MessageDispatcher::Listeners::iterator it=listeners.begin(); it!=listeners.end(); it++) {
-					(*it)->onConnectionFailed(address);
-				}
-
-				break;
-			}
-
-			case ConnectionEvent_Disconnected: {
-				for(MessageDispatcher::Listeners::iterator it=listeners.begin(); it!=listeners.end(); it++) {
-					(*it)->onDisconnected(address, connection);
-				}
-
-				break;
-			}
-		}
-
-		return;
-	}
-
-private:
-	MessageDispatcher::Listeners	listeners;
-	ConnectionEvent					event;
-	std::string						address;
-	ref<Connection>					connection;
-};
-
-
-
-
 MessageDispatcher::IMessage::IMessage() {
 	return;
 }
 	do {
 		// delete connection, when interrupted
 		if (connection && (connection->isConnected() == false)) {
-			Engine::getInstance()->runOnMainThread(new ConnectionEventDispatcher(
+			ConnectionEventDispatcher::dispatch(
 					*(this->getListeners()),
-					ConnectionEvent_Disconnected,
+					ConnectionEventDispatcher::ConnectionEvent_Disconnected,
 					this->address,
 					connection
-			));
+			);
 
 			// release the object (we're creating a new one)
 			safe_release(connection);
 
 			// notify, when the connection was successful
 			if (connection) {
-				Engine::getInstance()->runOnMainThread(new ConnectionEventDispatcher(
+				ConnectionEventDispatcher::dispatch(
 						*(this->getListeners()),
-						ConnectionEvent_Connected,
+						ConnectionEventDispatcher::ConnectionEvent_Connected,
 						this->address,
 						connection
-				));
+				);
 			}
 			else {
-				Engine::getInstance()->runOnMainThread(new ConnectionEventDispatcher(
+				ConnectionEventDispatcher::dispatch(
 						*(this->getListeners()),
-						ConnectionEvent_ConnectionFailed,
+						ConnectionEventDispatcher::ConnectionEvent_ConnectionFailed,
 						this->address,
 						NULL
-				));
+				);
 			}
 		}
 

src/net/wiesel/io/net/socket_connection.cpp

 
 	hostent* he = gethostbyname(host.c_str());
 	if (he == NULL) {
+		releaseSocket();
+		fireOnConnectionFailed();
+
 		return false;
 	}
 
 
 		int result = ::connect(socket_handle, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
 		if (result == -1) {
-			disconnect();
 			continue;
 		}