mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 08:56:36 +02:00
Some cleanups from Jon ... beeps now work
This commit is contained in:
parent
e7a80e32c9
commit
e7d27884a8
1 changed files with 92 additions and 60 deletions
|
@ -34,28 +34,22 @@ function chat_empty_connection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatConnection {
|
class ChatConnection {
|
||||||
|
// Chat-related info
|
||||||
var $sid = NULL;
|
var $sid = NULL;
|
||||||
|
var $type = NULL;
|
||||||
|
//var $groupid = NULL;
|
||||||
|
|
||||||
|
// PHP-level info
|
||||||
var $handle = NULL;
|
var $handle = NULL;
|
||||||
|
|
||||||
|
// TCP/IP
|
||||||
var $ip = NULL;
|
var $ip = NULL;
|
||||||
var $port = NULL;
|
var $port = NULL;
|
||||||
var $groupid = NULL;
|
|
||||||
var $lastmessages = array();
|
function ChatConnection($resource) {
|
||||||
var $lastmsgindex = 0;
|
$this->handle = $resource;
|
||||||
var $type = NULL;
|
socket_getpeername($this->handle, &$this->ip, &$this->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessage {
|
|
||||||
var $chatid = NULL;
|
|
||||||
var $userid = NULL;
|
|
||||||
var $groupid = NULL;
|
|
||||||
var $system = NULL;
|
|
||||||
var $message = NULL;
|
|
||||||
var $timestamp = NULL;
|
|
||||||
|
|
||||||
var $text_ = '';
|
|
||||||
var $html_ = '';
|
|
||||||
var $beep_ = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatDaemon {
|
class ChatDaemon {
|
||||||
|
@ -151,7 +145,8 @@ class ChatDaemon {
|
||||||
echo "<p><font size=1>";
|
echo "<p><font size=1>";
|
||||||
echo fullname($userinfo['user'])."<br />";
|
echo fullname($userinfo['user'])."<br />";
|
||||||
echo "<font color=\"#888888\">$str->idle: ".format_time($lastping, $str)."</font> ";
|
echo "<font color=\"#888888\">$str->idle: ".format_time($lastping, $str)."</font> ";
|
||||||
//echo " <a href=\"users.php?chat_sid=$chat_sid&beep=$chatuser->id&groupid=$groupid\">$str->beep</a>";
|
echo '<a target="empty" href="http://'.$CFG->chat_serverhost.':'.$CFG->chat_serverport.'/?win=beep&beep='.$userinfo['user']->id.
|
||||||
|
'&chat_sid='.$sessionid.'&groupid='.$this->sets_info[$sessionid]['groupid'].'">'.$str->beep."</a>\n";
|
||||||
echo "</font></p>";
|
echo "</font></p>";
|
||||||
echo "<td></tr>";
|
echo "<td></tr>";
|
||||||
}
|
}
|
||||||
|
@ -178,6 +173,7 @@ class ChatDaemon {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
foreach($this->conn_side[$sessionid] as $sideid => $sidekick) {
|
foreach($this->conn_side[$sessionid] as $sideid => $sidekick) {
|
||||||
|
// TODO: is this late-dispatch working correctly?
|
||||||
$this->dispatch_sidekick($sidekick['handle'], $sidekick['type'], $sessionid, $sidekick['customdata']);
|
$this->dispatch_sidekick($sidekick['handle'], $sidekick['type'], $sessionid, $sidekick['customdata']);
|
||||||
unset($this->conn_side[$sessionid][$sideid]);
|
unset($this->conn_side[$sessionid][$sideid]);
|
||||||
}
|
}
|
||||||
|
@ -188,6 +184,44 @@ class ChatDaemon {
|
||||||
global $CFG;
|
global $CFG;
|
||||||
|
|
||||||
switch($type) {
|
switch($type) {
|
||||||
|
case CHAT_SIDEKICK_BEEP:
|
||||||
|
// Incoming beep
|
||||||
|
$msg = &New stdClass;
|
||||||
|
$msg->chatid = $this->sets_info[$sessionid]['chatid'];
|
||||||
|
$msg->userid = $this->sets_info[$sessionid]['userid'];
|
||||||
|
$msg->groupid = $this->sets_info[$sessionid]['groupid'];
|
||||||
|
$msg->system = 0;
|
||||||
|
$msg->message = 'beep '.$customdata['beep'];
|
||||||
|
$msg->timestamp = time();
|
||||||
|
|
||||||
|
// Commit to DB
|
||||||
|
insert_record('chat_messages', $msg);
|
||||||
|
|
||||||
|
// OK, now push it out to all users
|
||||||
|
$this->message_broadcast($msg, $this->sets_info[$sessionid]['user']);
|
||||||
|
|
||||||
|
// Update that user's lastmessageping
|
||||||
|
$this->update_lastmessageping($sessionid, $msg->timestamp);
|
||||||
|
|
||||||
|
// We did our work, but before slamming the door on the poor browser
|
||||||
|
// show the courtesy of responding to the HTTP request. Otherwise, some
|
||||||
|
// browsers decide to get vengeance by flooding us with repeat requests.
|
||||||
|
|
||||||
|
$header = "HTTP/1.1 200 OK\n";
|
||||||
|
$header .= "Connection: close\n";
|
||||||
|
$header .= "Date: ".date('r')."\n";
|
||||||
|
$header .= "Server: Moodle\n";
|
||||||
|
$header .= "Content-Type: text/html\n";
|
||||||
|
$header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n";
|
||||||
|
$header .= "Cache-Control: no-cache, must-revalidate\n";
|
||||||
|
$header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n";
|
||||||
|
$header .= "\n";
|
||||||
|
|
||||||
|
// That's enough headers for one lousy dummy response
|
||||||
|
chat_socket_write($handle, $header);
|
||||||
|
// All done
|
||||||
|
break;
|
||||||
|
|
||||||
case CHAT_SIDEKICK_USERS:
|
case CHAT_SIDEKICK_USERS:
|
||||||
/*
|
/*
|
||||||
//$x = pusers($this->sets_info[$sessionid]['chatid'], $this->sets_info[$sessionid]['groupid']);
|
//$x = pusers($this->sets_info[$sessionid]['chatid'], $this->sets_info[$sessionid]['groupid']);
|
||||||
|
@ -250,7 +284,7 @@ class ChatDaemon {
|
||||||
break;
|
break;
|
||||||
case CHAT_SIDEKICK_MESSAGE:
|
case CHAT_SIDEKICK_MESSAGE:
|
||||||
// Incoming message
|
// Incoming message
|
||||||
$msg = &New ChatMessage;
|
$msg = &New stdClass;
|
||||||
$msg->chatid = $this->sets_info[$sessionid]['chatid'];
|
$msg->chatid = $this->sets_info[$sessionid]['chatid'];
|
||||||
$msg->userid = $this->sets_info[$sessionid]['userid'];
|
$msg->userid = $this->sets_info[$sessionid]['userid'];
|
||||||
$msg->groupid = $this->sets_info[$sessionid]['groupid'];
|
$msg->groupid = $this->sets_info[$sessionid]['groupid'];
|
||||||
|
@ -356,11 +390,11 @@ class ChatDaemon {
|
||||||
|
|
||||||
$this->dismiss_half($sessionid, false);
|
$this->dismiss_half($sessionid, false);
|
||||||
chat_socket_write($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $CHAT_HTMLHEAD_JS);
|
chat_socket_write($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $CHAT_HTMLHEAD_JS);
|
||||||
trace('Finalized client: sid: '.$sessionid.' uid: '.$chatuser->userid.' gid: '.intval($groupid));
|
trace('Connection accepted: '.$this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL].', SID: '.$sessionid.' UID: '.$chatuser->userid.' GID: '.intval($groupid));
|
||||||
|
|
||||||
// Finally, broadcast the "entered the chat" message
|
// Finally, broadcast the "entered the chat" message
|
||||||
|
|
||||||
$msg = &New ChatMessage;
|
$msg = &New stdClass;
|
||||||
$msg->chatid = $chatuser->chatid;
|
$msg->chatid = $chatuser->chatid;
|
||||||
$msg->userid = $chatuser->userid;
|
$msg->userid = $chatuser->userid;
|
||||||
$msg->groupid = 0;
|
$msg->groupid = 0;
|
||||||
|
@ -379,7 +413,7 @@ class ChatDaemon {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach($this->conn_ufo as $id => $ufo) {
|
foreach($this->conn_ufo as $id => $ufo) {
|
||||||
if($ufo == $handle) {
|
if($ufo->handle == $handle) {
|
||||||
// OK, got the id of the UFO, but what is it?
|
// OK, got the id of the UFO, but what is it?
|
||||||
|
|
||||||
if($type & CHAT_SIDEKICK) {
|
if($type & CHAT_SIDEKICK) {
|
||||||
|
@ -402,11 +436,12 @@ class ChatDaemon {
|
||||||
|
|
||||||
if($type & CHAT_CONNECTION) {
|
if($type & CHAT_CONNECTION) {
|
||||||
// This forces a new connection right now...
|
// This forces a new connection right now...
|
||||||
|
trace('Incoming connection from '.$ufo->ip.':'.$ufo->port);
|
||||||
|
|
||||||
// Do we have such a connection active?
|
// Do we have such a connection active?
|
||||||
if(isset($this->conn_sets[$sessionid])) {
|
if(isset($this->conn_sets[$sessionid])) {
|
||||||
// Yes, so regrettably we cannot promote you
|
// Yes, so regrettably we cannot promote you
|
||||||
trace('UFO #'.$id.' with '.$ufo.' cannot be promoted: session '.$sessionid.' is already final');
|
trace('Connection rejected: session '.$sessionid.' is already final');
|
||||||
$this->dismiss_ufo($handle);
|
$this->dismiss_ufo($handle);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -425,14 +460,6 @@ class ChatDaemon {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// It's the first one for that sessionid, so it will start an incomplete connection
|
|
||||||
$this->conn_half[$sessionid] = array($type => $handle);
|
|
||||||
unset($this->conn_ufo[$id]);
|
|
||||||
trace('UFO #'.$id.': identified session '.$sessionid.' wintype '.$type);
|
|
||||||
return true;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -444,8 +471,8 @@ class ChatDaemon {
|
||||||
}
|
}
|
||||||
if($disconnect) {
|
if($disconnect) {
|
||||||
foreach($this->conn_half[$sessionid] as $handle) {
|
foreach($this->conn_half[$sessionid] as $handle) {
|
||||||
socket_shutdown($handle);
|
@socket_shutdown($handle);
|
||||||
socket_close($handle);
|
@socket_close($handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($this->conn_half[$sessionid]);
|
unset($this->conn_half[$sessionid]);
|
||||||
|
@ -453,14 +480,13 @@ class ChatDaemon {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismiss_set($sessionid) {
|
function dismiss_set($sessionid) {
|
||||||
if(!isset($this->conn_sets[$sessionid])) {
|
if(!empty($this->conn_sets[$sessionid])) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach($this->conn_sets[$sessionid] as $handle) {
|
foreach($this->conn_sets[$sessionid] as $handle) {
|
||||||
// Since we want to dismiss this, don't generate any errors if it's dead already
|
// Since we want to dismiss this, don't generate any errors if it's dead already
|
||||||
@socket_shutdown($handle);
|
@socket_shutdown($handle);
|
||||||
@socket_close($handle);
|
@socket_close($handle);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
unset($this->conn_sets[$sessionid]);
|
unset($this->conn_sets[$sessionid]);
|
||||||
unset($this->sets_info[$sessionid]);
|
unset($this->sets_info[$sessionid]);
|
||||||
return true;
|
return true;
|
||||||
|
@ -472,7 +498,7 @@ class ChatDaemon {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach($this->conn_ufo as $id => $ufo) {
|
foreach($this->conn_ufo as $id => $ufo) {
|
||||||
if($ufo == $handle) {
|
if($ufo->handle == $handle) {
|
||||||
unset($this->conn_ufo[$id]);
|
unset($this->conn_ufo[$id]);
|
||||||
if($disconnect) {
|
if($disconnect) {
|
||||||
chat_socket_write($handle, "You don't seem to be a valid client.\n");
|
chat_socket_write($handle, "You don't seem to be a valid client.\n");
|
||||||
|
@ -491,21 +517,18 @@ class ChatDaemon {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$newconn = &New ChatConnection;
|
$newconn = &New ChatConnection($handle);
|
||||||
$newconn->handle = $handle;
|
|
||||||
socket_getpeername($newconn->handle, &$newconn->ip, &$newconn->port);
|
|
||||||
|
|
||||||
$id = $this->new_ufo_id();
|
$id = $this->new_ufo_id();
|
||||||
//trace('UFO #'.$id.': connection from '.$newconn->ip.' on port '.$newconn->port.', '.$newconn->handle);
|
$this->conn_ufo[$id] = $newconn;
|
||||||
|
|
||||||
$this->conn_ufo[$id] = $newconn->handle;
|
//trace('UFO #'.$id.': connection from '.$newconn->ip.' on port '.$newconn->port.', '.$newconn->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
function conn_activity_ufo (&$handles) {
|
function conn_activity_ufo (&$handles) {
|
||||||
$monitor = array();
|
$monitor = array();
|
||||||
if(!empty($this->conn_ufo)) {
|
if(!empty($this->conn_ufo)) {
|
||||||
foreach($this->conn_ufo as $ufoid => $ufo) {
|
foreach($this->conn_ufo as $ufoid => $ufo) {
|
||||||
$monitor[$ufoid] = $ufo;
|
$monitor[$ufoid] = $ufo->handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,7 +568,7 @@ class ChatDaemon {
|
||||||
// and THEN broadcast a message to all others... otherwise, infinite recursion.
|
// and THEN broadcast a message to all others... otherwise, infinite recursion.
|
||||||
|
|
||||||
delete_records('chat_users', 'sid', $sessionid);
|
delete_records('chat_users', 'sid', $sessionid);
|
||||||
$msg = &New ChatMessage;
|
$msg = &New stdClass;
|
||||||
$msg->chatid = $info['chatid'];
|
$msg->chatid = $info['chatid'];
|
||||||
$msg->userid = $info['userid'];
|
$msg->userid = $info['userid'];
|
||||||
$msg->groupid = 0;
|
$msg->groupid = 0;
|
||||||
|
@ -585,12 +608,13 @@ define('CHAT_SIDEKICK', 0x20);
|
||||||
// Sidekicks: Incrementing sequence, 0x21 to 0x2f
|
// Sidekicks: Incrementing sequence, 0x21 to 0x2f
|
||||||
define('CHAT_SIDEKICK_USERS', 0x21);
|
define('CHAT_SIDEKICK_USERS', 0x21);
|
||||||
define('CHAT_SIDEKICK_MESSAGE', 0x22);
|
define('CHAT_SIDEKICK_MESSAGE', 0x22);
|
||||||
|
define('CHAT_SIDEKICK_BEEP', 0x23);
|
||||||
|
|
||||||
|
|
||||||
$DAEMON = New ChatDaemon;
|
$DAEMON = New ChatDaemon;
|
||||||
$DAEMON->socket_active = false;
|
$DAEMON->socket_active = false;
|
||||||
$DAEMON->trace_level = E_ALL;
|
$DAEMON->trace_level = E_ALL;
|
||||||
$DAEMON->socketserver_refresh = 10;
|
$DAEMON->socketserver_refresh = 20;
|
||||||
$DAEMON->can_daemonize = function_exists('pcntl_fork');
|
$DAEMON->can_daemonize = function_exists('pcntl_fork');
|
||||||
$DAEMON->beepsoundsrc = $CFG->wwwroot.'/mod/chat/beep.wav';
|
$DAEMON->beepsoundsrc = $CFG->wwwroot.'/mod/chat/beep.wav';
|
||||||
$DAEMON->live_data_update_threshold = 30;
|
$DAEMON->live_data_update_threshold = 30;
|
||||||
|
@ -649,14 +673,11 @@ if(!socket_bind($DAEMON->listen_socket, $CFG->chat_serverip, $CFG->chat_serverpo
|
||||||
$DAEMON->last_error = socket_last_error();
|
$DAEMON->last_error = socket_last_error();
|
||||||
echo "Error: socket_bind() failed: ". socket_strerror(socket_last_error($DAEMON->last_error)).' ['.$DAEMON->last_error."]\n";
|
echo "Error: socket_bind() failed: ". socket_strerror(socket_last_error($DAEMON->last_error)).' ['.$DAEMON->last_error."]\n";
|
||||||
|
|
||||||
// If $DAEMON->last_error == 98 (Success), maybe we need to try cleaning up a bit before dying
|
if($DAEMON->last_error != 98) {
|
||||||
// This is EXPERIMENTAL code!
|
|
||||||
if($DAEMON->last_error == 98) {
|
|
||||||
trace('experimental fix kicks in');
|
|
||||||
socket_close($DAEMON->listen_socket);
|
|
||||||
}
|
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if(!socket_listen($DAEMON->listen_socket, $CFG->chat_servermax)) {
|
if(!socket_listen($DAEMON->listen_socket, $CFG->chat_servermax)) {
|
||||||
// Failed to get socket to listen
|
// Failed to get socket to listen
|
||||||
$DAEMON->last_error = socket_last_error();
|
$DAEMON->last_error = socket_last_error();
|
||||||
|
@ -743,7 +764,7 @@ while(true) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ereg('win=(chat|users|message).*&chat_sid=([a-zA-Z0-9]*)&groupid=([0-9]*) HTTP', $data, $info)) {
|
if(!ereg('win=(chat|users|message|beep).*&chat_sid=([a-zA-Z0-9]*)&groupid=([0-9]*) HTTP', $data, $info)) {
|
||||||
// Malformed data
|
// Malformed data
|
||||||
trace('UFO with '.$handle.': Request with malformed data; connection closed', E_USER_WARNING);
|
trace('UFO with '.$handle.': Request with malformed data; connection closed', E_USER_WARNING);
|
||||||
$DAEMON->dismiss_ufo($handle);
|
$DAEMON->dismiss_ufo($handle);
|
||||||
|
@ -763,6 +784,17 @@ while(true) {
|
||||||
case 'users':
|
case 'users':
|
||||||
$type = CHAT_SIDEKICK_USERS;
|
$type = CHAT_SIDEKICK_USERS;
|
||||||
break;
|
break;
|
||||||
|
case 'beep':
|
||||||
|
$type = CHAT_SIDEKICK_BEEP;
|
||||||
|
if(!ereg('beep=([^&]*)[& ]', $data, $info)) {
|
||||||
|
trace('Beep sidekick did not contain a valid userid', E_USER_WARNING);
|
||||||
|
$DAEMON->dismiss_ufo($handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$customdata = array('beep' => intval($info[1]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'message':
|
case 'message':
|
||||||
$type = CHAT_SIDEKICK_MESSAGE;
|
$type = CHAT_SIDEKICK_MESSAGE;
|
||||||
if(!ereg('chat_message=([^&]*)[& ]', $data, $info)) {
|
if(!ereg('chat_message=([^&]*)[& ]', $data, $info)) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue