$name = $modules[$modulename]['name']; $this->$id = $modulename; $this->$state = ($modules[$modulename]['enabled'])? Module::STATE_UNLOADED : Module::STATE_DISABLED; $this->$filename = $modules[$modulename]['filename']; $this->$classname = $modules[$modulename]['classname']; } protected function wait_answer($answer_type, &$buf) { if(is_string($answer_type)) $answer_type = array($answer_type); socket_set_block($this->$sock); $time = microtime(true); do { if(($answer = socket_read ($this->$sock, 1024, PHP_NORMAL_READ)) !== false) { if (trim($answer) == "") continue; $buf .= trim($answer) . "\n"; foreach ($answer_type as $answer_type_a) { $answer_array = explode(" ", trim($answer)); if ($answer_array[0] == $answer_type_a) return $answer_array; } } else if (socket_last_error() == 104) { $this->$state = Module::STATE_UNLOADED; $buf .= "Module " . $this->getName() . " crashed."; throw new Exception ($buf); } } while ((microtime(true) - $time) <3); $buf .= "Got no " . implode(", no ", $answer_type) . " answer from module " . $this->getName() . " in the 3 seconds timeout\n"; } public function getName() { return $this->$name; } public function getState() { return $this->$state; } public function setState(int $state_num) { switch ($state_num) { case Module::STATE_DISABLED: break; case Module::STATE_LOADING: case Module::STATE_LOADED: break; case Module::STATE_UNLOADING: case Module::STATE_UNLOADED: break; default: return -1; } } // Creates a pair socket, then split the processes, and stock them in this class private function load(&$messages = NULL) { $sockets = array(); $this->$state = STATE_LOADING; if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false) { log_debug("Error creating socket for loading module " . $this->getName()); $this->$state = Module::STATE_UNLOADED; throw new Exception("Error creating socket for loading module " . $this->getName() . ": " . socket_strerror(socket_last_error())); } $this->$sock = $sockets[1]; $this->$pid = pcntl_fork(); if ($this->$pid === -1) { $this->$state = Module::STATE_UNLOADED; throw new Exception("Failed forking child for module inclusion."); } else if ($this->$pid) { $answer = $this->wait_answer(array(Module::STATE_LOADED, Module::STATE_UNLOADED), $messages, $given_answer); switch ($given_answer) { case Module::STATE_LOADED: return $this->$state = Module::STATE_LOADED; case Module::STATE_UNLOADED: $this->$state = Module::STATE_UNLOADED; $msg .= "Module " . $this->getName() . " stopped."; throw new Exception ($msg); } return -1; } else { $this->$sock = $sockets[0]; require (MODULES_DIR . "/" . $this->$id . "/" . $filename); call_user_func(array($this->$classname, 'init')); socket_write($this->$sock, Module::STATE_LOADED . "\n"); // $this->listen(); } } protected function listen() { socket_set_block($this->$sock); } public function send_command($command) { if($this->$pid == 0) return; socket_write($this->$sock, $command . "\n"); socket_set_block($this->$sock); } private function unload() { call_user_func(array($this->$classname, 'stop')); } private function enable() { } private function disable() { } }