]> git.mxchange.org Git - hub.git/blob - application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php
'public static final' is the right thing, some variables renamed to make clear what...
[hub.git] / application / hub / main / helper / connection / tcp / class_TcpConnectionHelper.php
1 <?php
2 /**
3  * A TCP connection helper class
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009, 2010 Core Developer Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  * @todo                Find an interface for hub helper
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  */
25 class TcpConnectionHelper extends BaseConnectionHelper {
26         /**
27          * Protected constructor
28          *
29          * @return      void
30          */
31         protected function __construct () {
32                 // Call parent constructor
33                 parent::__construct(__CLASS__);
34
35                 // Set protocol
36                 $this->setProtocol('tcp');
37         }
38
39         /**
40          * Creates a socket resource ("connection") for given recipient in package data
41          *
42          * @param       $packageData            Raw package data
43          * @return      $socketResource         Socket resource
44          * @throws      InvalidSocketException  If the socket is invalid
45          */
46         public static function createConnectionFromPackageData (array $packageData) {
47                 // Create an instance
48                 $helperInstance = new TcpConnectionHelper();
49
50                 // Create a socket instance
51                 $socketResource = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
52
53                 // Is the socket resource valid?
54                 if (!is_resource($socketResource)) {
55                         // Something bad happened
56                         throw new InvalidSocketException(array($helperInstance, gettype($socketResource), 0, 'invalid'), BaseListener::EXCEPTION_INVALID_SOCKET);
57                 } // END - if
58
59                 // Get socket error code for verification
60                 $socketError = socket_last_error($socketResource);
61
62                 // Check if there was an error else
63                 if ($socketError > 0) {
64                         // Then throw again
65                         throw new InvalidSocketException(array($helperInstance, gettype($socketResource), $socketError, socket_strerror($socketError)), BaseListener::EXCEPTION_INVALID_SOCKET);
66                 } // END - if
67
68                 // Set the option to reuse the port
69                 if (!socket_set_option($socketResource, SOL_SOCKET, SO_REUSEADDR, 1)) {
70                         // Get socket error code for verification
71                         $socketError = socket_last_error($socketResource);
72
73                         // Get error message
74                         $errorMessage = socket_strerror($socketError);
75
76                         // Shutdown this socket
77                         $helperInstance->shutdownSocket($socketResource);
78
79                         // And throw again
80                         throw new InvalidSocketException(array($helperInstance, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
81                 } // END - if
82
83                 // Now, we want non-blocking mode
84                 if (!socket_set_nonblock($socketResource)) {
85                         // Get socket error code for verification
86                         $socketError = socket_last_error($socketResource);
87
88                         // Get error message
89                         $errorMessage = socket_strerror($socketError);
90
91                         // Shutdown this socket
92                         $helperInstance->shutdownSocket($socketResource);
93
94                         // And throw again
95                         throw new InvalidSocketException(array($helperInstance, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
96                 } // END - if
97
98                 // Set the resource
99                 $helperInstance->setSocketResource($socketResource);
100
101                 // Resolve any session ids; 0 = IP, 1 = Port
102                 $recipientData = explode(':', HubTools::resolveSessionId($packageData['recipient']));
103
104                 // Set ip/port
105                 $helperInstance->setAddress($recipientData[0]);
106                 $helperInstance->setPort($recipientData[1]);
107
108                 // Debug message
109                 $helperInstance->debugOutput('CONNECTION: Connecting to ' . $recipientData[0] . ':' . $recipientData[1]);
110
111                 // Now connect to it
112                 if (!@socket_connect($socketResource, $recipientData[0], $recipientData[1])) {
113                         // Get socket error code for verification
114                         $socketError = socket_last_error($socketResource);
115
116                         // And throw again, but not for 'Operation now in progress', we should wait a little
117                         if ($socketError != 115) {
118                                 // Get error message
119                                 $errorMessage = socket_strerror($socketError);
120
121                                 // Shutdown this socket
122                                 $helperInstance->shutdownSocket($socketResource);
123
124                                 // Throw it again
125                                 throw new InvalidSocketException(array($helperInstance, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
126                         } else {
127                                 // Debug output
128                                 $helperInstance->debugOutput('CONNECTION: Operation is in progress, this usual for non-blocking connections.');
129                         }
130                 } // END - if
131
132                 // Okay, that should be it. So return it...
133                 return $socketResource;
134         }
135
136         /**
137          * Do the shutdown sequence for TCP connections
138          *
139          * @todo        We may want to implement a filter for ease notification of other objects like our pool
140          * @return      void
141          * @throws      SocketShutdownException         If the current socket could not be shut down
142          */
143         public function doShutdown () {
144                 // Clear any previous errors
145                 socket_clear_error($this->getSocketResource());
146
147                 // Call the shutdown function on the currently set socket
148                 if (!@socket_shutdown($this->getSocketResource())) {
149                         // Could not shutdown socket, this is fine if e.g. the other side is not connected, so analyse it
150                         if (socket_last_error($this->getSocketResource()) != 107) {
151                                 // Something bad happened while we shutdown a socket
152                                 throw new SocketShutdownException($this, BaseListener::EXCEPTION_INVALID_SOCKET);
153                         } // END - if
154                 } // END - if
155
156                 // Mark this connection as shutted down
157                 $this->markConnectionShutdown();
158         }
159 }
160
161 // [EOF]
162 ?>