3 * A class for making socket connections to other hubs including the master hub
5 * @author Roland Haeder <webmaster@ship-simu.org>
7 * @copyright Copyright(c) 2007, 2008 Roland Haeder, this is free software
8 * @license GNU GPL 3.0 or any newer version
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 class HubConnector extends BaseFrameworkSystem {
25 * The socket we shall use for communication
27 private $socketResource = null;
30 * The peer instance (HubPeer class)
32 private $peerInstance = null;
35 * The private constructor
39 protected function __construct () {
40 // Call parent constructor
41 parent::__construct(__CLASS__);
44 $this->removeSystemArray();
45 $this->removeNumberFormaters();
49 * Creates an instance based on the (IP) address and port number of this
50 * class. Next it tries to connect to the specified peer and communicates
53 * @param $address The peer's IP address
54 * @param $port The peer's port number
55 * @param $hubInstance An instance of a HubCoreLoop class
56 * @return $connector An instance of this class
57 * @throws HubHelloException If HELLO retries reached maximum
59 public final static function createHubConnectorByAddressPort ($address, $port, HubCoreLoop $hubInstance) {
60 // Get a new instance of this class
61 $connector = new HubConnector();
63 // Connect to the given address and IP number
64 $connector->aquireConnectionToAddress($address, $port);
67 $hubInstance->getOutputInstance()->output(sprintf("[%s] Sending %s request to hub %s:%d...",
69 $connector->getConfigInstance()->readConfig("hub_peer_hello"),
74 // Get a HubPeer instance
75 $peerInstance = HubPeer::createHubPeerBySocket($connector->getSocketResource(), $hubInstance);
77 // Send a HELLO to the master hub
78 $helloed = 0; $retries = 0;
79 while (!$peerInstance->ifHelloReplied()) {
81 if ((time() - $helloed) >= $connector->getConfigInstance()->readConfig("hub_hello_timeout")) {
82 // Send HELLOs out in periodic times
83 $peerInstance->sendMessage($connector->getConfigInstance()->readConfig("hub_peer_hello"));
84 $helloed = time(); $retries++;
85 if ($retries == $connector->getConfigInstance()->readConfig("hub_hello_retires")) {
86 // Maximum retries reached
87 throw new HubHelloException(
90 'peer' => $peerInstance
91 ), HubCoreLoop::EXCEPTION_HELLO_TIMED_OUT
97 // Set the peer instance
98 $connector->setPeerInstance($peerInstance);
100 // Return the instance
105 * Aquires a socket link to a specified IP address and port number. It
106 * throws subclasses of SocketException-s if the peer is down or not
107 * responding. If the connection is up it writes it's resource into
108 * the attribute $socketResource and waits for incoming data packages.
110 * @param $address The peer's IP address
111 * @param $port The peer's port number
113 * @throws SocketCreationException If creation of the socket wents wrong
114 * @throws SocketConnectException If the connection was not established
116 public function aquireConnectionToAddress ($address, $port) {
117 // Create a socket for binding to the address
118 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
121 if (!is_resource($socket)) {
123 throw new SocketCreationException(
126 'code' => socket_last_error()
127 ), HubCoreLoop::EXCEPTION_SOCKET_PROBLEM
131 // Now connect to the peer
132 if (@socket_connect($socket, $address, $port) === false) {
133 // Something wents wrong!
134 throw new SocketConnectException (
137 'code' => socket_last_error()
138 ), HubCoreLoop::EXCEPTION_SOCKET_PROBLEM
142 // Set non-blocking mode
143 @socket_set_nonblock($socket);
146 $this->socketResource = $socket;
150 * Getter for current socket
152 * @return $socketResource The current socket resource or null if not set
154 public final function getSocketResource() {
155 return $this->socketResource;
159 * Setter for a HubPeer instance
161 * @param $peerInstance An instance of a HubPeer class
164 public final function setPeerInstance (HubPeer $peerInstance) {
165 $this->peerInstance = $peerInstance;
169 * Handles any incoming master requests
173 public function handleMasterRequests () {
174 // Just ask the peer instance
175 $command = $this->peerInstance->handleMasterRequests();