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 private function __construct () {
40 // Call parent constructor
41 parent::constructor(__CLASS__);
44 $this->setPartDescr("Hub-Connector");
47 $this->createUniqueID();
50 $this->removeSystemArray();
51 $this->removeNumberFormaters();
55 * Creates an instance based on the (IP) address and port number of this
56 * class. Next it tries to connect to the specified peer and communicates
59 * @param $address The peer's IP address
60 * @param $port The peer's port number
61 * @param $hubInstance An instance of a HubCoreLoop class
62 * @return $connector An instance of this class
63 * @throws HubHelloException If HELLO retries reached maximum
65 public final static function createHubConnectorByAddressPort ($address, $port, HubCoreLoop $hubInstance) {
66 // Get a new instance of this class
67 $connector = new HubConnector();
69 // Connect to the given address and IP number
70 $connector->aquireConnectionToAddress($address, $port);
73 $hubInstance->getOutputInstance()->output(sprintf("[%s] Sending %s request to hub %s:%d...",
75 $connector->getConfigInstance()->readConfig("hub_peer_hello"),
80 // Get a HubPeer instance
81 $peerInstance = HubPeer::createHubPeerBySocket($connector->getSocketResource(), $hubInstance);
83 // Send a HELLO to the master hub
84 $helloed = 0; $retries = 0;
85 while (!$peerInstance->ifHelloReplied()) {
87 if ((time() - $helloed) >= $connector->getConfigInstance()->readConfig("hub_hello_timeout")) {
88 // Send HELLOs out in periodic times
89 $peerInstance->sendMessage($connector->getConfigInstance()->readConfig("hub_peer_hello"));
90 $helloed = time(); $retries++;
91 if ($retries == $connector->getConfigInstance()->readConfig("hub_hello_retires")) {
92 // Maximum retries reached
93 throw new HubHelloException(
96 'peer' => $peerInstance
97 ), HubCoreLoop::EXCEPTION_HELLO_TIMED_OUT
103 // Set the peer instance
104 $connector->setPeerInstance($peerInstance);
106 // Return the instance
111 * Aquires a socket link to a specified IP address and port number. It
112 * throws subclasses of SocketException-s if the peer is down or not
113 * responding. If the connection is up it writes it's resource into
114 * the attribute $socketResource and waits for incoming data packages.
116 * @param $address The peer's IP address
117 * @param $port The peer's port number
119 * @throws SocketCreationException If creation of the socket wents wrong
120 * @throws SocketConnectException If the connection was not established
122 public function aquireConnectionToAddress ($address, $port) {
123 // Create a socket for binding to the address
124 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
127 if (!is_resource($socket)) {
129 throw new SocketCreationException(
132 'code' => socket_last_error()
133 ), HubCoreLoop::EXCEPTION_SOCKET_PROBLEM
137 // Now connect to the peer
138 if (@socket_connect($socket, $address, $port) === false) {
139 // Something wents wrong!
140 throw new SocketConnectException (
143 'code' => socket_last_error()
144 ), HubCoreLoop::EXCEPTION_SOCKET_PROBLEM
148 // Set non-blocking mode
149 @socket_set_nonblock($socket);
152 $this->socketResource = $socket;
156 * Getter for current socket
158 * @return $socketResource The current socket resource or null if not set
160 public final function getSocketResource() {
161 return $this->socketResource;
165 * Setter for a HubPeer instance
167 * @param $peerInstance An instance of a HubPeer class
170 public final function setPeerInstance (HubPeer $peerInstance) {
171 $this->peerInstance = $peerInstance;
175 * Handles any incoming master requests
179 public function handleMasterRequests () {
180 // Just ask the peer instance
181 $command = $this->peerInstance->handleMasterRequests();