Comment déterminer un port libre pour le démon d'un plugin

Bonjour,

Comment faite vous dans vos plugins (tiers ou officiels) pour déterminer quel port utiliser par le démon?
J’ai vu plusieurs cas ou c’était simplement codé en dur (avec éventuellement une config pour le changer).
Ce que j’ai fait et manque de pot, j’avais pris le même que le plugin rfPlayer (que je n’ai pas), pas très grave, nouvelle version sortie avec un autre port.

J’hésite à mettre en place un check pour déterminer un port libre via un script bash par exemple et je me dis que cela serait mieux si c’était connu par, enregistré et donc attribué par le core: en gros le plugin demanderait l’allocation d’un port au core qui se chargerait de la distribution.

Laurent

Si tu parle d’un port pour une socket j’ai mis ca dans un plugin

private $min_port = 5065;
private $max_port = 5265;
private $lock_file = ‹ /tmp/PhpSIP.lock ›;
private function getPort(){
if ($this->src_port){
return true;
}
if ($this->min_port > $this->max_port){
log::add(‹ clientSIP ›,‹ error ›,« Min port is bigger than max port. »);
die();
}
$fp = @fopen($this->lock_file, ‹ a+ ›);
if (!$fp) {
log::add(‹ clientSIP ›,‹ error ›,« Failed to open lock file « .$this->lock_file);
die();
}
$canWrite = flock($fp, LOCK_EX);
if (!$canWrite) {
log::add(‹ clientSIP ›,‹ error ›,« Failed to lock a file in 1000 ms. »);
die();
}
clearstatcache();
$size = filesize($this->lock_file);
if ($size){
$contents = fread($fp, $size);
$ports = explode( », »,$contents);
}else{
$ports = false;
}
ftruncate($fp, 0);
rewind($fp);
if (!$ports){
// we are the first one to run, initialize « PID » => « port number » array
if (!fwrite($fp, $this->min_port)){
log::add(‹ clientSIP ›,‹ error ›,« Fail to write data to a lock file. »);
die();
}
$this->src_port = $this->min_port;
}else{
// there are other programs running now
$src_port = null;
for ($i = $this->min_port; $i <= $this->max_port; $i++) {
if (!in_array($i,$ports)) {
$src_port = $i;
break;
}
}
if (!$src_port) {
log::add(‹ clientSIP ›,‹ error ›,« No more ports left to bind. »);
die();
}
$ports = $src_port;
if (!fwrite($fp, implode(« , »,$ports))) {
log::add(‹ clientSIP ›,‹ error ›,« Failed to write data to lock file. »);
die();
}
$this->src_port = $src_port;
}
if (!fclose($fp)){
log::add(‹ clientSIP ›,‹ error ›,« Failed to close lock_file »);
die();
}
}

Je parle du port pour un socket tcp effectivement; qu’un démon (python) ouvre pour le plus souvent écouter les commandes envoyées par le code php.
Type plugin zwave, rfx, rfplayer, blea

Je vais regarde ce code pour voir si je peux y trouver une inspiration :wink:

edit: si j’ai bien suivi: ici tu gères un « pool » de port que ton plugin utilise car tu as potentiellement plusieurs « programs » qui tournent.
Moi je parlais du conflit d’utilisation avec d’autres plugin dont je ne connais même pas l’existence.

Oui effectivement j’ai pas pris le bon plugin

Sur un autre plugin j’ai mis ca mais pas encore eu le temps de tester

public function getPort(){
	$port = 8001;
	$max_port = 9000;
	while($port <= $max_port){
		$connection = @fsockopen('localhost', $port);
		if (is_resource($connection)){
			return $port;
		}
		$port++;
	}
}

Oui, c’était plus ou moins mon idée mais pas encore implémentée. C’est plutot quand y réfléchissant car pourrait faire partie du core ou d’un lib « utils » même si le core ne conserve pas l’info.

sinon j’imagine que ca devrait plutot être if (! is_resource … vu qu’on veut trouver un port libre :wink:

		if (! is_resource($connection)){
			return $port;
		}

merci pour ta réponse

Cette fonction que je n’utilisais pas je l’ai mis en beta.
Chez moi elle me retourne bien le port, mais je la machine de dev il n’y a pas beaucoup port utilisé.