<?php

/*
 * rino-SNMP-agent - SNMP agent for RINOTel (http://www.rinotel.com) gateway hardware
 *
 * Copyright (C) 2013 Volnikov Ivan
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 220 Lenin Avenue 82, Obninsk, Kaluga region, Russia.
 *
 * Report bugs to:  ivan@rinotel.com
 */

//$fd = fopen('c:/usr/tmp/terminal-agent.log', 'a');
$fh = fopen('php://stdin', 'r');
$fo = fopen('php://stdout', 'w');
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, '127.0.0.1', 39038);

/*
function logDUMP($MSG)
{
    global $fd;
    fwrite($fd,$MSG);
}
*/

function doAnswer($MSG)
{
    global $fo;
    fwrite($fo,$MSG."\n");
}


function getDataFromAgent($oid,$method,&$res)
{
	global $sock;
	//logDUMP("getDataFromAgent <".$oid."> command [mode=".$method."] - Enter\n");
	$msg = $oid.'|'.$method;
	socket_sendto($sock, $msg, strlen($msg), 0, '127.0.0.1', 39039);	
	$read   = array($sock);
	$write  = NULL;
	$except = NULL;
	$num_changed_sockets = socket_select($read, $write, $except, 3);

	if ($num_changed_sockets === false) {
		/* Error handling */
		//logDUMP("getDataFromAgent - Leave [Fail to select answer]\n");
	} else if ($num_changed_sockets > 0) {
		//there is answer
		$from_addr = '127.0.0.1';
		$from_port = 39039;
		if (socket_recvfrom($sock, $buf,4096,0, $from_addr, $from_port)>0)
		{
			list($oid_res,$oid_type,$oid_value) = explode("|",$buf);			
			if ($oid_res==="NONE")
			{
				//logDUMP("getDataFromAgent - Leave [Answer: No oid found]\n");
				return false;
			}else
			{
				$res['oid'] = $oid_res;
				$res['type'] = $oid_type;
				$res['value'] = $oid_value;
				//logDUMP("getDataFromAgent - Leave [Answer: oid=<$oid_res>, type=<$oid_type>, value=<$oid_value>]\n");
			}
			return true;
		}
		//logDUMP("getDataFromAgent - Leave [Fail to get data from agent]\n");
	}
	return false;
}

if (isset($fh)) {
    //logDUMP("Stdin is open!\n");
}else
{
    //logDUMP("Can not open stdin!"."\n");
    exit(1);
}

//main cycle

$mode = "command";
$command = "WORK";
do {
	//logDUMP("Try read data from stdin..."."\n");
	$buffer = rtrim(fgets($fh));
	//logDUMP("Data from stdin received [".$buffer."]\n");
	switch ($mode) {
		case "command":
			switch ($buffer) {
				case "PING":
				case "ping":
					// this is for startup handshake
					doAnswer("PONG");
					break;
				case "QUIT":
				case "quit":
					// this is for telnet-tests ;-)
					$command = "QUIT";
					//echo "Terminating.\n";
					break;
				case "getnext":
				case "GETNEXT":
					$mode = "getnext";
					break;
				case "get":
				case "GET":
					$mode = "get";					
					break;
				case "set":
				case "SET":
					$mode = "set";
					break;
				default:
					$command = "QUIT";
					break;
			}
			//logDUMP("Receive <".$buffer."> command [mode=".$mode."]\n");
			break;
		case "getnext":
		case "get":
			$oid=$buffer;
			//logDUMP("Process <".$mode."> command [oid=".$oid."]\n");
			$res = array();
			if (getDataFromAgent($oid,$mode,$res))
			{
				doAnswer($res["oid"]);
				doAnswer($res["type"]);
				doAnswer($res["value"]);
			}else
			{
				doAnswer("NONE");
			}

			$mode = "command";

			break;
		case "set":
			$mode = "set2";
			break;
		case "set2":
			$mode = "set3";
			break;
		case "set3":
			$mode = "command";
			doAnswer("not-writable");
			break;
		default:
			//logDUMP("Process <".$mode."> command - IGNORE \n");
			$mode = "command";
			doAnswer("NONE");
			break;
	}
} while ( $command != "QUIT" );

fclose($fh);
//logDUMP("Stdin is close!\n");

//fclose($fd);

?>
