From e7d27884a897d9366eb18cbb7eac629a9862e86b Mon Sep 17 00:00:00 2001 From: moodler Date: Thu, 12 Aug 2004 12:31:38 +0000 Subject: [PATCH] Some cleanups from Jon ... beeps now work --- mod/chat/chatd.php | 152 +++++++++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 60 deletions(-) diff --git a/mod/chat/chatd.php b/mod/chat/chatd.php index 76c7125c0e..a0c30bcff6 100755 --- a/mod/chat/chatd.php +++ b/mod/chat/chatd.php @@ -34,28 +34,22 @@ function chat_empty_connection() { } class ChatConnection { - var $sid = NULL; - var $handle = NULL; - var $ip = NULL; - var $port = NULL; - var $groupid = NULL; - var $lastmessages = array(); - var $lastmsgindex = 0; - var $type = NULL; -} + // Chat-related info + var $sid = NULL; + var $type = NULL; + //var $groupid = NULL; -class ChatMessage { - var $chatid = NULL; - var $userid = NULL; - var $groupid = NULL; - var $system = NULL; - var $message = NULL; - var $timestamp = NULL; + // PHP-level info + var $handle = NULL; - var $text_ = ''; - var $html_ = ''; - var $beep_ = false; + // TCP/IP + var $ip = NULL; + var $port = NULL; + function ChatConnection($resource) { + $this->handle = $resource; + socket_getpeername($this->handle, &$this->ip, &$this->port); + } } class ChatDaemon { @@ -150,8 +144,9 @@ class ChatDaemon { echo ""; echo "

"; echo fullname($userinfo['user'])."
"; - echo "$str->idle: ".format_time($lastping, $str).""; - //echo " id&groupid=$groupid\">$str->beep"; + echo "$str->idle: ".format_time($lastping, $str)." "; + echo ''.$str->beep."\n"; echo "

"; echo ""; } @@ -178,6 +173,7 @@ class ChatDaemon { return true; } 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']); unset($this->conn_side[$sessionid][$sideid]); } @@ -188,6 +184,44 @@ class ChatDaemon { global $CFG; 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: /* //$x = pusers($this->sets_info[$sessionid]['chatid'], $this->sets_info[$sessionid]['groupid']); @@ -250,7 +284,7 @@ class ChatDaemon { break; case CHAT_SIDEKICK_MESSAGE: // Incoming message - $msg = &New ChatMessage; + $msg = &New stdClass; $msg->chatid = $this->sets_info[$sessionid]['chatid']; $msg->userid = $this->sets_info[$sessionid]['userid']; $msg->groupid = $this->sets_info[$sessionid]['groupid']; @@ -356,11 +390,11 @@ class ChatDaemon { $this->dismiss_half($sessionid, false); 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 - $msg = &New ChatMessage; + $msg = &New stdClass; $msg->chatid = $chatuser->chatid; $msg->userid = $chatuser->userid; $msg->groupid = 0; @@ -379,7 +413,7 @@ class ChatDaemon { return false; } 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? if($type & CHAT_SIDEKICK) { @@ -402,11 +436,12 @@ class ChatDaemon { if($type & CHAT_CONNECTION) { // This forces a new connection right now... + trace('Incoming connection from '.$ufo->ip.':'.$ufo->port); // Do we have such a connection active? if(isset($this->conn_sets[$sessionid])) { // 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); return false; } @@ -425,14 +460,6 @@ class ChatDaemon { 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; @@ -444,8 +471,8 @@ class ChatDaemon { } if($disconnect) { foreach($this->conn_half[$sessionid] as $handle) { - socket_shutdown($handle); - socket_close($handle); + @socket_shutdown($handle); + @socket_close($handle); } } unset($this->conn_half[$sessionid]); @@ -453,13 +480,12 @@ class ChatDaemon { } function dismiss_set($sessionid) { - if(!isset($this->conn_sets[$sessionid])) { - return false; - } - foreach($this->conn_sets[$sessionid] as $handle) { - // Since we want to dismiss this, don't generate any errors if it's dead already - @socket_shutdown($handle); - @socket_close($handle); + if(!empty($this->conn_sets[$sessionid])) { + foreach($this->conn_sets[$sessionid] as $handle) { + // Since we want to dismiss this, don't generate any errors if it's dead already + @socket_shutdown($handle); + @socket_close($handle); + } } unset($this->conn_sets[$sessionid]); unset($this->sets_info[$sessionid]); @@ -472,7 +498,7 @@ class ChatDaemon { return false; } foreach($this->conn_ufo as $id => $ufo) { - if($ufo == $handle) { + if($ufo->handle == $handle) { unset($this->conn_ufo[$id]); if($disconnect) { chat_socket_write($handle, "You don't seem to be a valid client.\n"); @@ -491,21 +517,18 @@ class ChatDaemon { return false; } - $newconn = &New ChatConnection; - $newconn->handle = $handle; - socket_getpeername($newconn->handle, &$newconn->ip, &$newconn->port); - + $newconn = &New ChatConnection($handle); $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) { $monitor = array(); if(!empty($this->conn_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. delete_records('chat_users', 'sid', $sessionid); - $msg = &New ChatMessage; + $msg = &New stdClass; $msg->chatid = $info['chatid']; $msg->userid = $info['userid']; $msg->groupid = 0; @@ -585,12 +608,13 @@ define('CHAT_SIDEKICK', 0x20); // Sidekicks: Incrementing sequence, 0x21 to 0x2f define('CHAT_SIDEKICK_USERS', 0x21); define('CHAT_SIDEKICK_MESSAGE', 0x22); +define('CHAT_SIDEKICK_BEEP', 0x23); $DAEMON = New ChatDaemon; $DAEMON->socket_active = false; $DAEMON->trace_level = E_ALL; -$DAEMON->socketserver_refresh = 10; +$DAEMON->socketserver_refresh = 20; $DAEMON->can_daemonize = function_exists('pcntl_fork'); $DAEMON->beepsoundsrc = $CFG->wwwroot.'/mod/chat/beep.wav'; $DAEMON->live_data_update_threshold = 30; @@ -649,13 +673,10 @@ if(!socket_bind($DAEMON->listen_socket, $CFG->chat_serverip, $CFG->chat_serverpo $DAEMON->last_error = socket_last_error(); 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 - // This is EXPERIMENTAL code! - if($DAEMON->last_error == 98) { - trace('experimental fix kicks in'); - socket_close($DAEMON->listen_socket); + if($DAEMON->last_error != 98) { + die(); } - die(); + } if(!socket_listen($DAEMON->listen_socket, $CFG->chat_servermax)) { // Failed to get socket to listen @@ -743,7 +764,7 @@ while(true) { 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 trace('UFO with '.$handle.': Request with malformed data; connection closed', E_USER_WARNING); $DAEMON->dismiss_ufo($handle); @@ -763,6 +784,17 @@ while(true) { case 'users': $type = CHAT_SIDEKICK_USERS; 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': $type = CHAT_SIDEKICK_MESSAGE; if(!ereg('chat_message=([^&]*)[& ]', $data, $info)) { -- 2.39.5