]> git.mxchange.org Git - core.git/blob - framework/main/classes/listener/socket/class_SocketFileListener.php
Rewrite continued:
[core.git] / framework / main / classes / listener / socket / class_SocketFileListener.php
1 <?php
2 // Own namespace
3 namespace CoreFramework\Listener\Socket;
4
5 // Import framework stuff
6 use CoreFramework\Bootstrap\FrameworkBootstrap;
7 use CoreFramework\Factory\ObjectFactory;
8 use CoreFramework\Listener\Listenable;
9
10 /**
11  * A file-based socket listener
12  *
13  * @author              Roland Haeder <webmaster@ship-simu.org>
14  * @version             0.0.0
15  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
16  * @license             GNU GPL 3.0 or any newer version
17  * @link                http://www.ship-simu.org
18  *
19  * This program is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  */
32 class SocketFileListener extends BaseListener implements Listenable {
33         /**
34          * Protected constructor
35          *
36          * @return      void
37          */
38         protected function __construct () {
39                 // Call parent constructor
40                 parent::__construct(__CLASS__);
41
42                 // Set the protocol to file
43                 $this->setProtocolName('file');
44         }
45
46         /**
47          * Creates an instance of this class
48          *
49          * @return      $listenerInstance       An instance a prepared listener class
50          */
51         public final static function createSocketFileListener () {
52                 // Get new instance
53                 $listenerInstance = new SocketFileListener();
54
55                 // Return the prepared instance
56                 return $listenerInstance;
57         }
58
59         /**
60          * Initializes the listener by setting up the required socket server
61          *
62          * @return      void
63          */
64         public function initListener() {
65                 // Init socket
66                 $mainSocket = socket_create(AF_UNIX, SOCK_STREAM, 0);
67
68                 // Is the socket resource valid?
69                 if (!is_resource($mainSocket)) {
70                         // Something bad happened
71                         throw new InvalidSocketException(array($this, $mainSocket), BaseListener::EXCEPTION_INVALID_SOCKET);
72                 } // END - if
73
74                 // Get socket error code for verification
75                 $socketError = socket_last_error($mainSocket);
76
77                 // Check if there was an error else
78                 if ($socketError > 0) {
79                         // Handle this socket error with a faked recipientData array
80                         $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array('null', '0'));
81                 } // END - if
82
83                 // Create file name
84                 $socketFile = self::createTempPathForFile($this->getConfigInstance()->getConfigEntry('ipc_socket_file_name'));
85
86                 // Debug message
87                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: socketFile=' . $socketFile . ' ...');
88
89                 // File name must not be empty
90                 assert(!empty($socketFile));
91
92                 // Is the file there?
93                 if ((FrameworkBootstrap::isReachableFilePath($socketFile)) && (file_exists($socketFile))) {
94                         // Old socket found
95                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: WARNING: Old socket at ' . $socketFile . ' found. Will not start.');
96
97                         // Shutdown this socket
98                         $this->shutdownSocket($mainSocket);
99
100                         // Quit here
101                         exit;
102                 } // END - if
103
104                 // Debug message
105                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Binding to ' . $socketFile . ' ...');
106
107                 // Try to bind to it
108                 if (!socket_bind($mainSocket, $socketFile)) {
109                         // Handle error here
110                         $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array($socketFile, '0'));
111                         /*
112                         // Get socket error code for verification
113                         $socketError = socket_last_error($mainSocket);
114
115                         // Get error message
116                         $errorMessage = socket_strerror($socketError);
117
118                         // Shutdown this socket
119                         $this->shutdownSocket($mainSocket);
120
121                         // And throw again
122                         throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
123                         */
124                 } // END - if
125
126                 // Start listen for connections
127                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Listening for connections.');
128                 if (!socket_listen($mainSocket)) {
129                         // Handle this socket error with a faked recipientData array
130                         $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array($socketFile, '0'));
131                         /*
132                         // Get socket error code for verification
133                         $socketError = socket_last_error($mainSocket);
134
135                         // Get error message
136                         $errorMessage = socket_strerror($socketError);
137
138                         // Shutdown this socket
139                         $this->shutdownSocket($mainSocket);
140
141                         // And throw again
142                         throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
143                         */
144                 } // END - if
145
146                 // Now, we want non-blocking mode
147                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Setting non-blocking mode.');
148                 if (!socket_set_nonblock($mainSocket)) {
149                         // Handle this socket error with a faked recipientData array
150                         $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array($socketFile, '0'));
151                         /*
152                         // Get socket error code for verification
153                         $socketError = socket_last_error($mainSocket);
154
155                         // Get error message
156                         $errorMessage = socket_strerror($socketError);
157
158                         // Shutdown this socket
159                         $this->shutdownSocket($mainSocket);
160
161                         // And throw again
162                         throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
163                         */
164                 } // END - if
165
166                 // Set the main socket
167                 $this->registerServerSocketResource($mainSocket);
168
169                 // Initialize the peer pool instance
170                 $poolInstance = ObjectFactory::createObjectByConfiguredName('application_pool_class', array($this));
171
172                 // Add main socket
173                 $poolInstance->addPeer($mainSocket, BaseConnectionHelper::CONNECTION_TYPE_SERVER);
174
175                 // And add it to this listener
176                 $this->setPoolInstance($poolInstance);
177
178                 // Initialize iterator for listening on packages
179                 $iteratorInstance = ObjectFactory::createObjectByConfiguredName('socket_listen_iterator_class', array($poolInstance->getPoolEntriesInstance()));
180
181                 // Rewind it and remember it in this class
182                 $iteratorInstance->rewind();
183                 $this->setIteratorInstance($iteratorInstance);
184
185                 // Initialize the raw data handler
186                 $handlerInstance = ObjectFactory::createObjectByConfiguredName('socket_raw_data_handler_class');
187
188                 // Set it in this class
189                 $this->setHandlerInstance($handlerInstance);
190
191                 // Output message
192                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Socket listener now ready on socket ' . $socketFile . ' for service.');
193         }
194
195         /**
196          * "Listens" for incoming network packages
197          *
198          * @return      void
199          */
200         public function doListen() {
201                 // Call super method
202                 $this->doListenSocketSelect('');
203         }
204
205         /**
206          * Checks whether the listener would accept the given package data array
207          *
208          * @param       $packageData    Raw package data
209          * @return      $accepts                Whether this listener does accept
210          */
211         public function ifListenerAcceptsPackageData (array $packageData) {
212                 $this->partialStub('Need to implement this method.');
213         }
214
215         /**
216          * Monitors incoming raw data from the handler and transfers it to the
217          * given receiver instance.
218          *
219          * @return      void
220          */
221         public function monitorIncomingRawData () {
222                 $this->partialStub('Need to implement this method.');
223         }
224
225 }