add 'help' and 'about' messages
[brisk.git] / web / spush / brisk-spush.php
1 #!/usr/bin/php
2 <?php
3 /*
4  *  brisk - spush/brisk-spush.php
5  *
6  *  Copyright (C) 2012 Matteo Nastasi
7  *                          mailto: nastasi@alternativeoutput.it 
8  *                                  matteo.nastasi@milug.org
9  *                          web: http://www.alternativeoutput.it
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details. You should have received a
20  * copy of the GNU General Public License along with this program; if
21  * not, write to the Free Software Foundation, Inc, 59 Temple Place -
22  * Suite 330, Boston, MA 02111-1307, USA.
23  *
24  * TODO
25  *   problema con getpeer (HOSTADDR)
26  *   setcookie (for tables only)
27  *   keepalive
28  *   chunked 
29  *   index_rd.php porting
30  *   index.php auth part
31  *   generic var management from internet
32  */
33
34 $G_base = "../";
35
36 require_once("./sac-a-push.phh");
37 require_once("./brisk-spush.phh");
38 require_once($G_base."Obj/brisk.phh");
39 require_once($G_base."Obj/auth.phh");
40 // require_once("../Obj/proxyscan.phh");
41 require_once($G_base."index.php");
42 require_once($G_base."index_wr.php");
43 require_once($G_base."index_rd_ifra.php");
44 require_once($G_base."briskin5/Obj/briskin5.phh");
45
46 define('SITE_PREFIX', '/brisk/');
47
48 class SPUser {
49     var $id;
50     var $sess;
51     var $cnt;
52     var $sock;
53     
54     function SPUser($id)
55     {
56         $this->id = $id;
57         $this->cnt = -1;
58         $this->sock = NULL;
59     }
60
61     function enable($sock, $sess)
62     {
63         $this->sess = $sess;
64         $this->cnt = 0;
65         $this->sock = $sock;
66
67         return ($this->id);
68     }
69
70     function disable()
71     {
72         $this->cnt = -1;
73         $this->sock = NULL;
74     }
75
76     function is_enable()
77     {
78         return ($this->cnt < 0 ? FALSE : TRUE);
79     }
80
81     function sock_get()
82     {
83         return $this->sock;
84     }
85
86     function sock_set($sock)
87     {
88         $this->sock = $sock;
89     }
90
91     function id_get()
92     {
93         return $this->id;
94     }
95     
96     function sess_get()
97     {
98         return $this->sess;
99     }
100
101     function cnt_get()
102     {
103         return $this->cnt;
104     }
105
106     function cnt_inc()
107     {
108         return $this->cnt++;
109     }
110 }
111
112 function user_get_free($user_arr)
113 {
114     foreach ($user_arr as $i => $user) {
115         if (!$user->is_enable()) {
116             return ($user);
117         }
118     }
119     return FALSE;
120 }
121
122 function user_get_sess($user_arr, $sess)
123 {
124     foreach ($user_arr as $i => $user) {
125         printf("SESS: [%s]  cur: [%s]\n", $user->sess_get(), $sess);
126         if ($user->sess_get() == $sess) {
127             return ($user);
128         }
129     }
130     return FALSE;
131 }
132
133 function headers_render($header)
134 {
135     
136     $s = "";
137     $s .= "HTTP/1.1 200 OK\r\n";
138     if (!isset($header['Date']))
139         $s .= sprintf("Date: %s\r\n", date(DATE_RFC822));
140     if (!isset($header['Connection']))
141         $s .= "Connection: close\r\n";
142     if (!isset($header['Content-Type']))
143         $s .= "Content-Type: text/html\r\n";
144     foreach($header as $key => $value) {
145         $s .= sprintf("%s: %s\r\n", $key, $value);
146     }
147     $s .= "Mop: was/here\r\n";
148     $s .= "\r\n";
149
150     return ($s);
151 }
152
153
154 /*
155  *  Caching system using ob php system to cache old style pages
156  *  to a var and than send it with more calm
157  */
158 $G_headers = "";
159
160 function shutta()
161 {
162   log_rd2("SHUTTA [".connection_status()."] !");
163 }
164
165 register_shutdown_function('shutta');
166
167 /*
168  *  MAIN
169  */
170 $shutdown = FALSE;
171
172 function main()
173 {
174     GLOBAL $G_headers;
175     GLOBAL $shutdown;
176     $main_loop = TRUE;
177
178     /*
179      *  INIT
180      */
181
182     $FILE_SOCKET = "/tmp/brisk.sock";
183     $UNIX_SOCKET = "unix://$FILE_SOCKET";
184     $debug = 0;
185     $fixed_fd = 2;
186     $socks = array();
187
188     $blocking_mode = 0; // 0 for non-blocking
189
190     if (($room = Room::create()) == FALSE) {
191         log_crit("load_data failed");
192         return FALSE;
193     }
194
195     $s2u  = array();
196
197     $rndstr = "";
198     for ($i = 0 ; $i < 4096 ; $i++) {
199         $rndstr .= chr(mt_rand(65, 90));
200     }
201
202     if (file_exists($FILE_SOCKET)) {
203         unlink($FILE_SOCKET);
204     }
205     
206     $old_umask = umask(0);
207     if (($list = stream_socket_server($UNIX_SOCKET, $err, $errs)) === FALSE) {
208         exit(11);
209     }
210     umask($old_umask);
211
212     if (($in = fopen("php://stdin", "r")) === FALSE) {
213         exit(11);
214     }
215
216     stream_set_blocking($list, $blocking_mode); # Set the stream to non-blocking
217
218     while ($main_loop) {
219         echo "IN LOOP\n";
220         /* Prepare the read array */
221         if ($shutdown) 
222             $read   = array_merge(array("$in" => $in), $socks);
223         else
224             $read   = array_merge(array("$list" => $list, "$in" => $in), $socks);
225
226         if ($debug > 1) {
227             printf("PRE_SELECT\n");
228             print_r($read);
229         }
230         $write  = NULL;
231         $except = NULL;
232         $num_changed_sockets = stream_select($read, $write, $except, 5);
233         
234         if ($num_changed_sockets === FALSE) {
235             printf("No data in 5 secs");
236         } 
237         else if ($num_changed_sockets > 0) {
238             printf("num sock %d num_of_socket: %d\n", $num_changed_sockets, count($read));
239             if ($debug > 1) {
240                 print_r($read);
241             }
242             /* At least at one of the sockets something interesting happened */
243             foreach ($read as $i => $sock) {
244                 if ($sock === $list) {
245                     printf("NUOVA CONNEX\n");
246                     $new_unix = stream_socket_accept($list);
247                     $stream_info = "";
248                     $method      = "";
249                     $get         = array();
250                     $post        = array();
251                     $cookie      = array();
252                     if (($new_socket = ancillary_getstream($new_unix, $stream_info)) !== FALSE) {
253                         printf("RECEIVED HEADER:\n%s", $stream_info);
254                         $path = spu_process_info($stream_info, $method, $header, $get, $post, $cookie);
255                         printf("PATH: [%s]\n", $path);
256                         printf("M: %s\nHEADER:\n", $method);
257                         print_r($header);
258                         printf("GET:\n");
259                         print_r($get);
260                         printf("POST:\n");
261                         print_r($post);
262                         printf("COOKIE:\n");
263                         print_r($cookie);
264
265                         switch ($path) {
266                         case SITE_PREFIX:
267                         case SITE_PREFIX."index.php":
268                             $header_out = array();
269                             ob_start();
270                             index_main($room, $header_out, $get, $post, $cookie);
271                             $content = ob_get_contents();
272                             ob_end_clean();
273                             // printf("OUT: [%s]\n", $G_content);
274                             fwrite($new_socket, headers_render($header_out).$content);
275                             fclose($new_socket);
276                             break;
277                         case SITE_PREFIX."index_wr.php":
278                             $G_headers = "";
279                             $addr = "";
280                             $ret = socket_getpeername($new_socket, $addr);
281                             // printf("RET: %d\n", $ret);
282                             // exit(123);
283                             ob_start();
284                             index_wr_main($room, $addr, $get, $post, $cookie);
285                             $content = ob_get_contents();
286                             ob_end_clean();
287                             
288                             // printf("OUT: [%s]\n", $G_content);
289                             fwrite($new_socket, headers_render($header_out).$content);
290                             fclose($new_socket);
291                             break;
292                         case SITE_PREFIX."index_rd_ifra.php":
293                             do {
294                                 if (!isset($cookie['sess'])) {
295                                     fclose($new_socket);
296                                     break;
297                                 }
298                                 if (($user = $room->get_user($cookie['sess'], $idx)) == FALSE) {
299                                     fclose($new_socket);
300                                     break;
301                                 }
302                                 if (($prev = $user->rd_socket_get()) != NULL) {
303                                     unset($s2u[intval($user->rd_socket_get())]);
304                                     unset($socks[intval($user->rd_socket_get())]);
305                                     fclose($user->rd_socket_get());
306                                     $user->rd_socket_set(NULL);
307                                 }
308
309                                 $header_out = array();
310                                 $body = "";
311                                 index_rd_ifra_init($room, $user, $header_out, $body, $get, $post, $cookie);
312                                 stream_set_blocking($new_socket, $blocking_mode); // Set the stream to non-blocking
313                                 fwrite($new_socket, headers_render($header_out).$body);
314                                 fflush($new_socket);
315
316                                 $s2u[intval($new_socket)] = $idx;
317                                 $socks[intval($new_socket)] = $new_socket;                                
318                                 $user->rd_socket_set($new_socket);
319                             } while (FALSE);
320
321                             break;
322                         }
323                             
324
325
326
327                         if (0 == 1) {
328                             /* TODO: here stuff to decide if it is old or new user */
329                             if (($user_cur = user_get_sess($user_a, $get['sess'])) != FALSE) {
330                                 /* close the previous socket */
331                                 unset($s2u[intval($user_cur->sock_get())]);
332                                 unset($socks[intval($user_cur->sock_get())]);
333                                 fclose($user_cur->sock_get());
334                                 /* assign the new socket */
335                                 $user_cur->sock_set($new_socket);
336                                 $id = $user_cur->id_get();
337                                 $s2u[intval($new_socket)] = $id;
338                                 $socks[intval($new_socket)] = $new_socket;
339                                 fwrite($new_socket, $rndstr);
340                                 fflush($new_socket);
341                             }
342                             else if (($user_cur = user_get_free($user_a)) != FALSE) {
343                                 stream_set_blocking($new_socket, $blocking_mode); // Set the stream to non-blocking
344                                 $socks[intval($new_socket)] = $new_socket;
345
346                                 $id = $user_cur->id_get();
347                                 $user_a[$id]->enable($new_socket, $get['sess']);
348                                 printf("s2u: ci passo %d\n", intval($new_socket));
349                                 $s2u[intval($new_socket)] = $id;
350
351                                 fwrite($new_socket, $rndstr);
352                                 fflush($new_socket);
353                             }
354                             else {
355                                 printf("Too many opened users\n");
356                                 fclose($new_socket);
357                             }
358                         }
359                     }
360                     else {
361                         printf("WARNING: ancillary_getstream failed\n");
362                     }
363                 }
364                 else {
365                     if (($buf = fread($sock, 512)) === FALSE) {
366                         printf("error read\n");
367                         exit(123);
368                     }
369                     else if (strlen($buf) === 0) {
370                         if ($sock === $list) {
371                             printf("Arrivati %d bytes da list\n", strlen($buf));
372                         }
373                         else if ($sock === $in) {
374                             printf("Arrivati %d bytes da stdin\n", strlen($buf));
375                         }
376                         else {
377                             // $user_a[$s2u[intval($sock)]]->disable();
378                             if ($room->user[$s2u[intval($sock)]]->rd_socket_get() != NULL) {
379                                 $room->user[$s2u[intval($sock)]]->rd_socket_set(NULL);
380                             }
381                             unset($socks[intval($sock)]);
382                             unset($s2u[intval($sock)]);
383                             fclose($sock);
384                         }
385                         if ($debug > 1) {
386                             printf("post unset\n");
387                             print_r($socks);
388                         }
389                     }
390                     else {
391                         if ($debug > 1) {
392                             print_r($read);
393                         }
394                         if ($sock === $list) {
395                             printf("Arrivati %d bytes da list\n", strlen($buf));
396                         }
397                         else if ($sock === $in) {
398                             printf("Arrivati %d bytes da stdin\n", strlen($buf));
399                         }
400                         else {
401                             $key = array_search("$sock", $socks);
402                             printf("Arrivati %d bytes dalla socket n. %d\n", strlen($buf), $key);
403                         }
404                     }
405                 }
406             }
407         }
408
409
410
411
412
413
414         foreach ($socks as $k => $sock) {
415             if (isset($s2u[intval($sock)])) {
416                 $body = "";
417                 
418
419                 $header_out = array();
420                 $body = "";
421                 index_rd_ifra_main($room, $room->user[$s2u[intval($sock)]], $body);
422                 echo "SPIA: [".substr($body, 0, 60)."...]\n";
423                 fwrite($sock, headers_render($header_out).$body);
424                 fflush($sock);
425             }
426         }
427     }
428     
429     exit(0);
430 }
431
432 main();
433 ?>