Commit | Line | Data |
---|---|---|
54f4a22e D |
1 | <?php\r |
2 | \r | |
3 | /*\r | |
4 | * CASE: Page requested to start a session.\r | |
5 | * 1. Attempt connect to the server\r | |
6 | * Fail?\r | |
7 | * End session and send error to the client\r | |
8 | * Connected?\r | |
9 | * Create a listening UNIX socket and send OK to the client\r | |
10 | *\r | |
11 | * 2. Run the IRC client class as normal, while polling for connections\r | |
12 | * on the listening socket. Save any messages for the web client into\r | |
13 | * a buffer.\r | |
14 | * This is the normal running state.\r | |
15 | *\r | |
16 | * 3. Upon a connection on the UNIX socket, send the oldest message from\r | |
17 | * the buffer to the web client, FIFO style and close the connection.\r | |
18 | */\r | |
19 | \r | |
20 | // If -d has been sent to start this session, start in debug mode\r | |
21 | if(in_array('-d', $argv)){\r | |
22 | define('DEBUG', true);\r | |
23 | } else {\r | |
24 | define('DEBUG', false);\r | |
25 | }\r | |
26 | \r | |
27 | \r | |
28 | require(dirname(__FILE__).'/config.php');\r | |
29 | require(dirname(__FILE__).'/common.php');\r | |
30 | require(dirname(__FILE__).'/class_session.php');\r | |
31 | require(dirname(__FILE__).'/class_irc.php');\r | |
32 | require(dirname(__FILE__).'/class_ircconnection.php');\r | |
33 | require(dirname(__FILE__).'/ircd_profiles/hybrid.php');\r | |
34 | \r | |
35 | \r | |
36 | // Make sure a session id has been specified\r | |
37 | if(!isset($argv[1]) || empty($argv[1]))\r | |
38 | die('no_session');\r | |
39 | \r | |
40 | $session_id = $argv[1];\r | |
41 | $host_key = $argv[2]; // The remote host key in memcached\r | |
42 | \r | |
43 | // Process any arguments\r | |
44 | $app_args = array();\r | |
45 | foreach($argv as $a){\r | |
46 | $value = substr($a, 2);\r | |
47 | switch(substr($a, 0, 2)){\r | |
48 | case '-h':\r | |
49 | // Client host\r | |
50 | $app_args['remote_host'] = $value;\r | |
51 | break;\r | |
52 | }\r | |
53 | }\r | |
54 | \r | |
55 | \r | |
56 | // Start the unix session, and if it fails quit here\r | |
57 | $ipc_srv = SESSIONS::clStart($session_id);\r | |
58 | if($ipc_srv === false) die("fail '$session_id' '$host_key'");\r | |
59 | \r | |
60 | // Debug mode runs in terminal to see output\r | |
61 | if(!DEBUG){\r | |
62 | // See if we can fork our process..\r | |
63 | $pid = pcntl_fork();\r | |
64 | if($pid === -1){\r | |
65 | die('Forking error');\r | |
66 | }elseif($pid){\r | |
67 | // Parent process\r | |
68 | die('ok');\r | |
69 | }else{\r | |
70 | // Child process\r | |
71 | fclose(STDOUT);\r | |
72 | }\r | |
73 | }\r | |
74 | \r | |
75 | //posix_setsid();\r | |
76 | \r | |
77 | \r | |
78 | \r | |
79 | ############################################\r | |
80 | ## Main process\r | |
81 | ############################################\r | |
82 | \r | |
83 | $old_error_handler = set_error_handler("errorHandler");\r | |
84 | \r | |
85 | $bot = null; // The IRC connection\r | |
86 | $ipc = array(); // The IPC connections to the web clients\r | |
87 | $ipc_read = array(); // The IPC connections wanting to read the buffer\r | |
88 | $buffer = array(); // Messages to be sent to the web client\r | |
89 | $send_debug = false;\r | |
90 | \r | |
91 | deb("Starting $session_id");\r | |
92 | \r | |
93 | $timeout = time();\r | |
94 | $timeout_timer = 0;\r | |
95 | while(true){\r | |
96 | // If there are no webclients connected, start the timer to disconnect\r | |
97 | if(!count($ipc)){\r | |
98 | if($timeout == 0) $timeout = time();\r | |
99 | $timeout_timer = time() - $timeout;\r | |
100 | if($timeout_timer >= $config['timeout']) break;\r | |
101 | } else {\r | |
102 | $timeout = 0;\r | |
103 | }\r | |
104 | \r | |
105 | processClients();\r | |
106 | \r | |
107 | if($bot != null){\r | |
108 | // $bot handles the sleep time here\r | |
109 | $bot->Process();\r | |
110 | } else {\r | |
111 | usleep(5000);\r | |
112 | }\r | |
113 | }\r | |
114 | \r | |
115 | \r | |
116 | // We've quit, lower the counter for this host\r | |
117 | if($config['memcache_use']){\r | |
118 | @GLOB::$mc->decrement($host_key);\r | |
119 | }\r | |
120 | \r | |
121 | deb('Exiting client');\r | |
122 | \r | |
123 | \r | |
124 | ############################################\r | |
125 | ## Functions / Classes\r | |
126 | ############################################\r | |
127 | \r | |
128 | \r | |
129 | \r | |
130 | function processClients(){\r | |
131 | global $ipc_srv;\r | |
132 | global $ipc;\r | |
133 | global $ipc_read;\r | |
134 | global $buffer;\r | |
135 | global $timeout;\r | |
136 | \r | |
137 | // Check for any new web client connections...\r | |
138 | $read = array($ipc_srv);\r | |
139 | $write = $excep = array();\r | |
140 | $read_changed = stream_select($read, $write, $excep, 0);\r | |
141 | for($i=0; $i<$read_changed; $i++) {\r | |
142 | if($read[$i] === $ipc_srv){\r | |
143 | $ipc[] = stream_socket_accept($ipc_srv);\r | |
144 | deb("Connection...");\r | |
145 | }\r | |
146 | }\r | |
147 | \r | |
148 | \r | |
149 | // Check for any changed web clients..\r | |
150 | $read = $ipc;\r | |
151 | $read_changed = (count($read)) ? stream_select($read, $write, $excep, 0) : array();\r | |
152 | if($read_changed){\r | |
153 | foreach($read as $cl){\r | |
154 | $data = fread($cl, 1024);\r | |
155 | if(!$data){\r | |
156 | // Web client has disconnected\r | |
157 | deb("Removing closed socket..");\r | |
158 | $key = array_search($cl, $ipc);\r | |
159 | unset($ipc[$key]);\r | |
160 | \r | |
161 | $key = array_search($cl, $ipc_read);\r | |
162 | if($key !== false) unset($ipc_read[$key]);\r | |
163 | } else {\r | |
164 | //deb('Got data: '.$data);\r | |
165 | processClientMessage($data, $cl);\r | |
166 | }\r | |
167 | }\r | |
168 | }\r | |
169 | \r | |
170 | \r | |
171 | \r | |
172 | // Send the buffer messages to any connected web clients..\r | |
173 | // 1 message at a time...\r | |
174 | if(count($buffer) && count($ipc_read)){\r | |
175 | //deb(print_r($ipc_read, 1));\r | |
176 | $msg = array_shift($buffer);\r | |
177 | //deb("Sending '$msg' to ".count($ipc_read)." clients..");\r | |
178 | foreach($ipc_read as $cl){\r | |
179 | if($cl) fwrite($cl, $msg."\n");\r | |
180 | }\r | |
181 | }\r | |
182 | \r | |
183 | // The whole buffer at a time...\r | |
184 | /*\r | |
185 | while(count($buffer)){\r | |
186 | $msg = array_shift($buffer);\r | |
187 | foreach($ipc as $cl) frwite($cl, $msg);\r | |
188 | }\r | |
189 | */\r | |
190 | \r | |
191 | }\r | |
192 | \r | |
193 | \r | |
194 | function processClientMessage($data, $cl){\r | |
195 | global $config;\r | |
196 | global $buffer;\r | |
197 | global $bot, $ipc_read;\r | |
198 | global $timeout;\r | |
199 | global $send_debug;\r | |
200 | global $app_args;\r | |
201 | \r | |
202 | require('dev_processClientMessage.php');\r | |
203 | return true;\r | |
204 | }\r | |
205 | \r | |
206 | \r | |
207 | \r | |
208 | \r | |
209 | function errorHandler($errno, $errstr, $errfile, $errline){\r | |
210 | $ret = '';\r | |
211 | switch ($errno) {\r | |
212 | case E_USER_ERROR:\r | |
213 | $ret .= "USER [$errno] $errstr\n";\r | |
214 | $ret .= " Fatal error on line $errline in file $errfile";\r | |
215 | $ret .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")\n";\r | |
216 | $ret .= "Aborting...<br />\n";\r | |
217 | exit(1);\r | |
218 | break;\r | |
219 | \r | |
220 | case E_USER_WARNING:\r | |
221 | $ret .= "WARNING on line $errline in file $errfile: [$errno] $errstr\n";\r | |
222 | break;\r | |
223 | \r | |
224 | case E_USER_NOTICE:\r | |
225 | $ret .= "NOTICE on line $errline in file $errfile: [$errno] $errstr\n";\r | |
226 | break;\r | |
227 | \r | |
228 | default:\r | |
229 | $ret .= "UNKOWN ERR on line $errline in file $errfile: [$errno] $errstr\n";\r | |
230 | break;\r | |
231 | }\r | |
232 | \r | |
233 | if(!empty($ret)) deb($ret); \r | |
234 | \r | |
235 | \r | |
236 | /* Don't execute PHP internal error handler */\r | |
237 | return true;\r | |
238 | } |