merge with spawn branch
[brisk.git] / web / briskin5 / Obj / briskin5.phh
1 <?php
2 define(BRISKIN5_PLAYERS_N, 3);
3 define(BRISKIN5_MAX_PLAYERS, BRISKIN5_PLAYERS_N);
4 // define(BRISKIN5_SHM_MIN, (50000 * BRISKIN5_MAX_PLAYERS));
5 define(BRISKIN5_SHM_MIN, 32768);
6 define(BRISKIN5_SHM_MAX, (BRISKIN5_SHM_MIN + 1048576));
7 define(BRISKIN5_SHM_DLT, 32768);
8
9 class Briskin5 {
10   var $user;
11   var $table;
12   var $table_idx;
13   var $table_token;
14
15   var $comm; // commands for many people
16   var $step; // current step of the comm array
17   var $garbage_timeout;
18
19   var $the_end;
20   
21   var $tok;
22   var $shm_sz;
23
24   function Briskin5 (&$room, $table_idx, $table_token) {
25     $this->user = array();
26     $this->table = array();
27
28     $this->the_end = FALSE;
29     $this->shm_sz = BRISKIN5_SHM_MIN;
30     if (($this->tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
31       echo "FTOK FAILED";
32       exit;
33     }
34
35     $user  =& $room->user;
36     $table =& $room->table[$table_idx];
37
38     log_wr("Briskin5 constructor");
39
40     for ($i = 0 ; $i < $table->player_n ; $i++) {
41       $user[$table->player[$i]]->table_token = $table_token;
42       $this->user[$i] =& User::spawn(&$user[$table->player[$i]], 0, $i);
43     }
44     $this->table[0] =& Table::spawn(&$table);
45     $this->table_idx = $table_idx;
46     $this->table_token = $table_token;
47     $this->garbage_timeout = 0;
48     
49     log_wr("Briskin5 constructor end");
50   }
51
52
53   function &get_user($sess, &$idx)
54   {
55     GLOBAL $PHP_SELF, $G_false;
56
57     if (validate_sess($sess)) {
58       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
59         if (strcmp($sess, $this->user[$i]->sess) == 0) {
60           // find it
61           $idx = $i;
62           $ret = &$this->user[$i];
63           return ($ret);
64         }
65       }
66       log_main(sprintf("get_user: Wrong sess from page [%s]",$PHP_SELF));
67       // for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) 
68       // log_main(sprintf("get_user: Wrong sess compared with [%s]",$this->user[$i]->sess));
69     }
70     else {
71       log_main(sprintf("get_user: Wrong strlen [%s]",$sess));
72     }
73
74     return ($G_false);
75   }
76
77
78   function garbage_manager($force)
79   {
80     
81     /* Garbage collector degli utenti in timeout */
82     $ismod = FALSE;
83     $curtime = time();
84     if ($force || $this->garbage_timeout < $curtime) {
85       
86       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
87         $user_cur = &$this->user[$i];
88         if ($user_cur->sess == "" || 
89             ($user_cur->stat == 'table' && ($user_cur->subst == 'shutdowned' || $user_cur->subst == 'shutdowner')))
90           continue;
91         
92         if ($user_cur->lacc + EXPIRE_TIME_RD < $curtime) { // Auto logout dell'utente
93           log_rd2($user_cur->sess." bin5 AUTO LOGOUT.");
94
95           if ($user_cur->stat == 'table') {
96             log_auth($user_cur->sess," bin5 Autologout session.");
97
98             /* SI DELEGA AL garbage_manager principale LA RIMOZIONE DELL'UTENTE 
99
100             $tmp_sess = $user_cur->sess;
101             $user_cur->sess = "";
102             step_unproxy($tmp_sess);
103             $user_cur->name = "";
104             $user_cur->the_end = FALSE;
105             
106             */
107
108             $this->table_wakeup(&$user_cur);
109           }
110         }
111       }
112       log_rd2($user_cur->sess." GARBAGE UPDATED!");
113       
114       $this->garbage_timeout = $curtime + GARBAGE_TIMEOUT;
115       $ismod = TRUE;
116     }
117
118     return ($ismod);
119   }
120
121
122
123
124   //
125   //  static functions
126   //
127   function &load_data($table_idx, $table_token = "") 
128   {
129     GLOBAL $G_false, $sess;
130     $doexit = FALSE;
131     $shm = FALSE;
132
133     log_wr("TABLE_IDX ".FTOK_PATH."/table".$table_idx);
134     
135     do {
136       if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
137         log_main("ftok failed");
138         $doexit = TRUE;
139         break;
140       }
141
142       if (($shm_sz = sharedmem_sz($tok)) == -1) {
143         log_main("shmop_open failed");
144         break;
145       }
146         
147       if (($shm = shm_attach($tok, $shm_sz)) == FALSE)
148         break;
149
150       if (($bri = @shm_get_var($shm, $tok)) == FALSE) 
151         break;
152
153       if ($table_token != "" && $bri->table_token != $table_token) {
154         log_wr("bri->table_token: ".$bri->table_token."table_token: ".$table_token);
155         
156         break;
157       }
158       $bri->tok = $tok;
159
160       shm_detach($shm);
161         
162       $ret = &$bri;
163       return ($ret); 
164     } while (FALSE);
165
166     if ($shm != FALSE)
167       shm_detach($shm);
168
169     log_wr("briskin5 load_data failed");
170     if ($doexit)
171       exit();
172     
173     return ($G_false);
174   }
175   
176
177
178   function save_data(&$bri) 
179   {
180     GLOBAL $sess;
181     
182     $ret =   FALSE;
183     $shm =   FALSE;
184     
185     log_main("SAVE BRISKIN5 DATA");
186     
187     if (!isset($bri->tok))
188       return (FALSE);
189     
190     while ($bri->shm_sz < BRISKIN5_SHM_MAX) {
191       if (($shm = shm_attach($bri->tok, $bri->shm_sz)) == FALSE)
192         break;
193       
194       if (@shm_put_var($shm, $bri->tok, $bri) != FALSE) {
195         shm_detach($shm);
196         return (TRUE);
197       }
198       if (shm_remove($shm) === FALSE) {
199         log_only("REMOVE FALLITA");
200         break;
201       }
202       shm_detach($shm);
203       $bri->shm_sz += BRISKIN5_SHM_DLT;
204     } 
205
206     log_crit("save data failed!");
207
208     if ($shm)
209       shm_detach($shm);
210     
211     return ($ret);
212   }
213
214
215
216   function destroy_data($table_idx) 
217   {
218     GLOBAL $sess;
219
220     $ret =   FALSE;
221     $shm =   FALSE;
222     log_main("DESTROY BRISKIN5 DATA");
223     
224     do {
225       log_main("DESTROY2 BRISKIN5 DATA");
226
227       if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) 
228         break;
229
230       if (($shm = @shmop_open($tok, 'a', 0, 0)) == FALSE)
231         break;
232       
233       if (shmop_delete($shm) == 0) {
234         log_only("REMOVE FALLITA ");
235         break;
236       }
237    
238       $shm = FALSE;
239       log_main("DESTROY2 BRISKIN5 DATA SUCCESS");
240       
241       // log_main("QUI CI ARRIVA [".$bri->user[0]->name."]");
242       $ret = TRUE;
243     } while (0);
244     
245     if ($shm)
246       shm_detach($shm);
247     
248     return ($ret);
249   }
250
251   function lock_data($table_idx)
252   {
253     GLOBAL $sess; 
254     
255     log_wr("LOCK_DATA ".FTOK_PATH."/table".$table_idx);
256     //  echo "LOCK: ".FTOK_PATH."/main";
257     //  exit;
258     // WARNING monitor this step
259     if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
260       echo "FTOK FAILED";
261       exit;
262     }
263     // WARNING monitor this step
264     if (($res = @sem_get($tok)) == FALSE) {
265       echo "SEM_GET FAILED";
266       exit;
267     }
268     if (sem_acquire($res)) {   
269       log_lock("LOCK table ".$table_idx."[res: ".$res."]");
270       return ($res);
271     }
272     else {
273       log_lock("LOCK table ".$table_idx.":FAILED");
274       return (FALSE);
275     }
276   }
277   
278   function unlock_data($res)
279   {
280     GLOBAL $sess; 
281     
282     log_lock("UNLOCK table [res: ".$res."]");
283
284     return (sem_release($res));
285   }
286
287
288   function chatt_send(&$user, $mesg)
289   {
290     if ($user->stat == 'table') {
291       $table = &$this->table[$user->table];
292     }
293     
294     $user_mesg = substr($mesg,6);
295     
296     $curtime = time();
297     
298     $dt = date("H:i ", $curtime);
299     if (strncmp($user_mesg, "/nick ", 6) == 0) {
300       log_main($user->sess." chatt_send BEGIN");
301
302       if (($name_new = validate_name(substr($user_mesg, 6))) == FALSE) {
303           $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
304           $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Il nickname deve contenere almeno una lettera dell\'alfabeto o una cifra.");', $dt.NICKSERV);
305           $user->step_inc();
306
307           return;
308       }
309       $user_mesg = "COMMAND ".$user_mesg;
310       // Search dup name
311       // change
312       // update local graph
313       // update remote graphs
314       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
315         $user_cur = &$this->user[$i];
316         //      if ($user_cur->sess == '' || $user_cur->stat != 'room')
317         if ($user_cur->sess == '')
318           continue;
319         if ($user_cur->name == $name_new) {
320           $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
321           $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Nickname <b>%s</b> gi&agrave; in uso.");', $dt.NICKSERV, xcape($name_new));
322           $user->step_inc();
323           break;
324         }
325       }
326       if ($i == BRISKIN5_MAX_PLAYERS) {
327         $user->name = $name_new;
328
329       log_main($user->sess." chatt_send start set");
330         
331
332         for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
333           log_main($user->sess." chatt_send set loop");
334           
335           $user_cur = &$this->user[$i];
336           if ($user_cur->sess == '')
337             continue;
338           if ($user_cur->stat == 'room') {
339             if ($user->stat == 'room' && $user->subst == 'standup') {
340               $this->standup_update(&$user);
341             }
342             else if ($user->stat == 'room' && $user->subst == 'sitdown' ||
343                      $user->stat == 'table') {
344               log_main($user->sess." chatt_send pre table update");
345
346               $this->table_update(&$user);
347
348               log_main($user->sess." chatt_send post table update");
349             }
350           }
351           else if ($user_cur->stat == 'table' && $user_cur->table == $user->table) {
352             $table = &$this->table[$user->table];
353             
354             $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
355             $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('set_names(" %s", " %s", " %s", " %s", " %s"); ',
356                 xcape($this->user[$table->player[($user_cur->table_pos) % BRISKIN5_PLAYERS_N]]->name),
357                 xcape($this->user[$table->player[($user_cur->table_pos+1) % BRISKIN5_PLAYERS_N]]->name),
358                 xcape($this->user[$table->player[($user_cur->table_pos+2) % BRISKIN5_PLAYERS_N]]->name),
359                 (BRISKIN5_PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+3) % BRISKIN5_PLAYERS_N]]->name)),
360                 (BRISKIN5_PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+4) % BRISKIN5_PLAYERS_N]]->name)));
361             if ($user_cur == $user)
362               $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('$("myname").innerHTML = "<b>%s</b>";', 
363                                                                    xcape($user->name,ENT_COMPAT,"UTF-8"));
364             $user_cur->step_inc();
365           }
366         }
367       }
368     }
369     else {
370       for ($i = 0 ; $i < ($user->stat == 'room' ? BRISKIN5_MAX_PLAYERS : BRISKIN5_PLAYERS_N) ; $i++) {
371         if ($user->stat == 'room') {
372           $user_cur = &$this->user[$i];
373           if ($user_cur->sess == '' || $user_cur->stat != 'room')
374             continue;
375         }
376         else {
377           $user_cur = &$this->user[$table->player[$i]];
378         }
379         
380         $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
381         $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('chatt_sub("%s","%s");',
382                                                              $dt.xcape($user->name), xcape($user_mesg));
383         $user_cur->step_inc();
384       }
385       log_legal($curtime, $user->sess, $user->name, 
386                 ($user->stat == 'room' ? 'room' : 'table '.$user->table),$user_mesg);
387     }
388   }
389
390   function table_wakeup(&$user)
391   {
392     $table = &$this->table[0];
393
394     log_main("BRISKIN5_WAKEUP begin function table  stat: ".$user->stat."  subst: ".$user->subst);
395
396     $curtime = time();
397
398     log_main("BRISKIN5_WAKEUP from table [".$user->table."] nplayers_n: ".$this->table[$user->table]->player_n);
399     
400     for ($i = 0 ; $i < $table->player_n ; $i++) {
401       $user_cur = &$this->user[$i];
402       log_main("PREIMPOST INLOOP name: ".$user_cur->name);
403       
404       if ($user_cur == $user)
405         $user_cur->subst = "shutdowner";
406       else
407         $user_cur->subst = "shutdowned";
408       $user_cur->laccwr = $curtime;
409
410       $ret = "gst.st = ".($user_cur->step+1)."; ";
411       $ret .= 'gst.st_loc++; the_end=true; window.onunload = null; document.location.assign("../index.php");|';
412
413       log_wr($user_cur->sess." BRISKIN5_WAKEUP: ".$ret);
414       $user_cur->comm[$user_cur->step % COMM_N] = $ret;
415       $user_cur->step_inc();
416     }
417
418     $this->the_end = TRUE;
419   }
420   
421   /*
422    *  If all players are freezed the room garbage_manager clean up table and users.
423    */ 
424   function is_abandoned() 
425   {
426     $is_ab = TRUE;
427     $curtime = time();
428
429     $table = &$this->table[0];
430
431     for ($i = 0 ; $i < $table->player_n ; $i++) {
432       $user_cur = &$this->user[$i];
433
434       if ($user_cur->lacc + (EXPIRE_TIME_RD * 2) >= $curtime) { 
435         $is_ab = FALSE;
436         break;
437       }
438     }
439
440     return ($is_ab);
441   }
442 } // end class Briskin5
443
444 function locshm_exists($tok)
445 {
446   // return (TRUE);
447
448   if (($id = @shmop_open($tok,"a", 0, 0)) == FALSE) {
449     log_main($tok." SHM NOT exists");
450
451     return (FALSE);
452   }
453   else {
454     shmop_close($id);
455     log_main($tok." SHM exists");
456
457     return (TRUE);
458   }
459     
460 }
461
462
463 ?>