File: 0.04.30a/server/base/tests.inc.php (View as HTML)

  1: <?php // tests.inc.php
  2: /* -------------------------------------------------------------
  3: This file is part of FreeNATS
  4: 
  5: FreeNATS is (C) Copyright 2008 PurplePixie Systems
  6: 
  7: FreeNATS is free software: you can redistribute it and/or modify
  8: it under the terms of the GNU General Public License as published by
  9: the Free Software Foundation, either version 3 of the License, or
 10: (at your option) any later version.
 11: 
 12: FreeNATS is distributed in the hope that it will be useful,
 13: but WITHOUT ANY WARRANTY; without even the implied warranty of
 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15: GNU General Public License for more details.
 16: 
 17: You should have received a copy of the GNU General Public License
 18: along with FreeNATS.  If not, see www.gnu.org/licenses
 19: 
 20: For more information see www.purplepixie.org/freenats
 21: -------------------------------------------------------------- */
 22: 
 23: if (!isset($BaseDir)) $BaseDir="../base/"; // 
 24: require_once($BaseDir."timer.inc.php"); // just in case standalone
 25: 
 26: require($BaseDir."tests/mysql.inc.php");
 27: require($BaseDir."tests/imap.inc.php");
 28: require($BaseDir."tests/smtp.inc.php");
 29: require($BaseDir."tests/dns.inc.php");
 30: 
 31: function ip_lookup($hostname) // "safe" DNS lookup function to call with a hostname, URL or IP - returns 0 if unsuccessful
 32: {
 33: // Is it already an IP adress?
 34: $out=str_replace(".","",$hostname);
 35: if (is_numeric($out)) return $hostname; // yes it is
 36: 
 37: // No it is not
 38: $ip=@gethostbyname($hostname);
 39: if ($ip==$hostname) return 0; // unmodified host - lookup failed
 40: 
 41: return $ip;
 42: }
 43: 
 44: 
 45: function test_sleep()
 46: {
 47: global $NATS;
 48: if (!isset($NATS)) return false;
 49: $sleep=$NATS->Cfg->Get("test.interval",0);
 50: if ($sleep<=0) return false;
 51: $sleep=$sleep*1000000; // convert to usec
 52: usleep($sleep);
 53: return true;
 54: }
 55: 	
 56: function url_lookup($url)
 57: {
 58: // Sod regular expressions here as we'd have to do it twice or with cleverness I lack
 59: // Is it a URL?
 60: $colon=strpos($url,":");
 61: if ($colon != 0) // exists so it a URL
 62: 	{
 63: 	$out=preg_match("@^(?:http[s]*://)?([^/|\?|:]+)@i",$url,$matches);
 64: 	$hostname=$matches[1];
 65: 	}
 66: else $hostname=$url; // try direct
 67: 	
 68: return ip_lookup($hostname);
 69: }
 70: 	
 71: 	
 72: 
 73: 
 74: 
 75: 
 76: 
 77:  function icmpChecksum($data)
 78:     {
 79:     if (strlen($data)%2)
 80:     $data .= "\x00";
 81:     
 82:     $bit = unpack('n*', $data);
 83:     $sum = array_sum($bit);
 84:     
 85:     while ($sum >> 16)
 86:     $sum = ($sum >> 16) + ($sum & 0xffff);
 87:     
 88:     return pack('n*', ~$sum);
 89:     }
 90:    
 91: function PingTest($host,$ctimeout=-1)
 92: 	{
 93: 	global $NATS;
 94: 	$FreeNATS_Timer=new TFNTimer();
 95:     // Make Package
 96:     $type= "\x08";
 97:     $code= "\x00";
 98:     $checksum= "\x00\x00";
 99:     $identifier = "\x00\x00";
100:     $seqNumber = "\x00\x00";
101:     $data= "FreeNATS";
102:     $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
103:     $checksum = icmpChecksum($package); // Calculate the checksum
104:     $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
105:     
106:     // Return s or ms(s*1000)
107:     $returnsecs=true;
108:     if (isset($NATS))
109:     	{
110: 	    if ($NATS->Cfg->Get("test.icmp.returnms",0)==1) $returnsecs=false;
111:     	}
112: 
113: 	// Timeout Values
114:     if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.icmp.timeout",10);
115:     else $timeout=10;
116:     if ($ctimeout>0) $timeout=$ctimeout; // use custom timeout if passed
117:     if ($timeout<=0) $timeout=10; // catch-all for defaults bug
118:     
119:     // Create Socket
120:     $socket = @socket_create(AF_INET, SOCK_RAW, 1);
121:     	//or die(socket_strerror(socket_last_error()));
122:     if (!$socket) return 0;
123:     
124:     // Set Non-Blocking
125:     @socket_set_nonblock($socket);
126:     	
127:     // Connect Socket
128:     $sconn=@socket_connect($socket, $host, null);
129:     if (!$sconn) return 0;
130:     
131:     // Send Data
132:     @socket_send($socket, $package, strLen($package), 0);
133:         
134:     // Start Timer
135:     $FreeNATS_Timer->Start();
136:     $startTime = microtime(true); // need this for the looping section
137:     
138: 
139:     // Read Data
140:     $keepon=true;
141: 
142:     while( (!(@socket_read($socket, 255))) && $keepon)
143:     	{ // basically just kill time
144:     	// consider putting some sort of sleepy thing here to lower load but would f* with figures!
145:     	
146:     	if ( (microtime(true) - $startTime) > $timeout )
147:     		$keepon=false;
148: 		}
149:     	
150: 	if ($keepon) // didn't time out - read data
151:     	{
152: 	    $elapsed=$FreeNATS_Timer->Stop();
153: 	    if ($returnsecs) $elapsed=round($elapsed,4);
154: 	    else $elapsed=round( ($elapsed*1000),4 );
155: 	    @socket_close($socket);
156:     	// $ret=round(microtime(true) - $startTime, 4); -- old method
157:     	if ($elapsed<=0) $elapsed="0.0001"; // safety catch-all
158:     	return $elapsed;
159:     	/*
160:     	if ($ret==0) return "0.0001";
161:     	else 
162:     		{
163: 	    	if ($ret<=0) return "0.0001";
164: 	    	else return $ret;
165:     		}
166:     	*/
167:     	}
168:     	
169:     // Socket timed out
170:     @socket_close($socket);
171:     return 0;
172: 	}
173: 
174: function WebTest($url,$timeout=-1)
175: 	{
176: 	global $NATS;
177: 	if ($timeout<=0) // use NATS or env
178: 		{
179: 		if (isset($NATS))
180: 			{
181: 			$nto=$NATS->Cfg->Get("test.http.timeout",-1);
182: 			if ($nto>0) $timeout=$nto; // use NATS timeout
183: 			}
184: 		}
185: 	if ($timeout>0) // use the set timeout
186: 		$oldtimeout=ini_set("default_socket_timeout",$timeout);
187: 		
188: 	if (function_exists("curl_getinfo")) // use CURL if present
189: 		{
190: 		$ch=curl_init();
191: 		curl_setopt($ch,CURLOPT_URL,$url);
192: 		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
193: 		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
194: 		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
195: 		curl_setopt($ch,CURLOPT_HEADER,1);
196: 		if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
197: 		if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
198: 		if (!$output=curl_exec($ch))
199: 			{
200: 			$ctr=-1; // failed
201: 			}
202: 		else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
203: 		curl_close($ch);
204: 		
205: 		if ($ctr==0) $ctr="0.0001";
206: 		
207: 		}
208: 	else
209: 		{	// no CURL - use fopen()	
210: 		$fp=@fopen($url,"r");
211: 		if ($fp<=0)
212: 			{
213: 			if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
214: 			return -1;
215: 			}
216: 		$ctr=0;
217: 		while ($body=@fgets($fp,1024)) $ctr+=sizeof($body);
218: 		@fclose($fp);
219: 		}
220: 	
221: 	
222: 	
223: 	if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
224: 	return $ctr;
225: 	}
226: 	
227: function DoTest($test,$param,$hostname="",$timeout=-1,$params=0)
228: {
229: if (!is_array($params))
230: 	{
231: 	$params=array();
232: 	for ($a=0; $a<10; $a++) $params[$a]="";
233: 	}
234: 	
235: switch ($test)
236: 	{
237: 	case "web": case "wsize":
238: 		// Don't bother with pre-resolution as size only
239: 		return WebTest($param,$timeout);
240: 		break;
241: 	case "tcp": // nb TCP does not support timeouts currently
242: 		$ip=ip_lookup($hostname);
243: 		if ($ip=="0") return 0;
244: 		$fp=@fsockopen($ip,$param);
245: 		if ($fp<=0) return 0;
246: 		@fclose($fp);
247: 		return 1;
248: 		break;
249: 	case "wtime":
250: 		$timer=new TFNTimer();
251: 		// Do a pre-lookup
252: 		$ip=url_lookup($param);
253: 		if ($ip=="0") return -1; // dns lookup failed
254: 		$timer->Start();
255: 		$r=WebTest($param,$timeout);
256: 		$elapsedTime=$timer->Stop();
257: 		$elapsedTime=round($elapsedTime,4);
258: 		if ($r<0) return -1; // open failed
259: 		if ($r==0) return -2; // no chars shown as returned
260: 		if ($elapsedTime<=0) return 0.0001;
261: 		return $elapsedTime;
262: 		break;
263: 		
264: 	case "host":
265: 		$timer=new TFNTimer();
266: 		if (preg_match("/[a-zA-Z]/",$param)>0) $is_ip=false;
267: 		else $is_ip=true;
268: 		
269: 		$timer->Start();
270: 		if ($is_ip) $result=gethostbyaddr($param);
271: 		else $result=gethostbyname($param);
272: 		$elapsedTime=$timer->Stop();
273: 		
274: 		if ($result==$param) // lookup failed
275: 			return -1;
276: 			
277: 		if ($result=="")	// lookup failed
278: 			return -1;
279: 			
280: 		$elapsedTime=round($elapsedTime,4);
281: 		if ($elapsedTime<=0) return 0.0001;
282: 		return $elapsedTime;
283: 		break;
284: 		
285: 	case "dns":
286: 		$timer=new TFNTimer();
287: 		if ($param=="") $dnsserver=$hostname;
288: 		else $dnsserver=$param;
289: 		if ($dnsserver=="") return -3;
290: 		if ($timeout<=0) $timeout=60;
291: 		if ($params[4]==1) $udp=false; // use TCP
292: 		else $udp=true;
293: 		if (($params[3]=="")||($params[3]==0)) $port=53;
294: 		else $port=$params[3];
295: 		
296: 		$dns_query=new DNSQuery($dnsserver,$port,$timeout,$udp,false); // run with debug off
297: 		$type=$params[2];
298: 		$query=$params[1];
299: 		
300: 		$timer->Start();
301: 		$answer=$dns_query->Query($query,$type);
302: 		$elapsedTime=$timer->Stop();
303: 		
304: 		if ( ($answer===false) || ($dns_query->error) ) return -2; // query error
305: 		if ($answer->count<=0) return -1; // no records returned
306: 		
307: 		// otherwise we've got some results ok
308: 		$elapsedTime=round($elapsedTime,4);
309: 		if ($elapsedTime<=0) return 0.0001;
310: 		return $elapsedTime;
311: 		break;
312: 		
313: 	case "testloop":
314: 		return $param;
315: 		break;
316: 		
317: 	case "testrand":
318: 		mt_srand(microtime()*1000000);
319: 		if ( ($param=="") || ($param==0) ) $param=100;
320: 		return mt_rand(0,$param);
321: 		break;
322: 		
323: 	case "ping":
324: 		return PingTest($param,$timeout);
325: 		break;
326: 		
327: 	case "smtp":
328: 		$ip=ip_lookup($param);
329: 		if ($ip=="0") return -1;
330: 		return smtp_test_time($ip,$params[1],$timeout);
331: 		break;
332: 		
333: 	case "imap":
334: 		if ($params[5]==1) $ssl=true;
335: 		else $ssl=false;
336: 		
337: 		$ip=ip_lookup($param);
338: 		if ($ip=="0") return -1;
339: 		
340: 		return imap_test_time($ip,$params[1],$params[2],$timeout,$params[3],$params[4],$ssl);
341: 		break;
342: 		
343: 	case "mysql":
344: 		$ip=ip_lookup($param);
345: 		if ($ip=="0") return -1; // cache only as 127.0.0.1 is not the same connection as localhost for MySQL auth!
346: 
347: 		return mysql_test_time($param,$params[1],$params[2],$params[3],$timeout,$params[4]);
348: 		break;
349: 		
350: 	case "mysqlrows":
351: 		$ip=ip_lookup($param);
352: 		if ($ip=="0") return -1; // cache only - see above
353: 		return mysql_test_rows($param,$params[1],$params[2],$params[3],$timeout,$params[4]);
354: 		break;
355: 		
356: 		
357: 	}
358: return -1;
359: }
360: 
361: function SimpleEval($test,$result)
362: {
363: switch($test)
364: 	{
365: 	case "ping": // handles both types of simple evaluation (inbuilt ICMP and remote ping)
366: 		if ($result<=0) return 2;
367: 		return 0;
368: 	case "web": case "wsize":
369: 		if ($result<=0) return 2;
370: 		return 0;
371: 	case "tcp":
372: 		if ($result==1) return 0;
373: 		return 2;
374: 	case "wtime":
375: 		if ($result<0) return 2;
376: 		return 0;
377: 	
378: 	case "imap":
379: 		if ($result<=0) return 2;
380: 		return 0;
381: 	
382: 	case "smtp":
383: 		if ($result<=0) return 2;
384: 		return 0;
385: 		
386: 	case "mysql":
387: 		if ($result<=0) return 2;
388: 		return 0;
389: 		
390: 	case "mysqlrows":
391: 		if ($result<=0) return 2; // no rows returned or error
392: 		return 0;
393: 		
394: 	case "host": case "dns":
395: 		if ($result<=0) return 2; // no records returned or error
396: 		
397: 	case "testloop":
398: 		return 0;
399: 	case "testrand":
400: 		return 0;
401: 	}
402: return -1; // untested if we don't know WTF the result was
403: }
404: 
405: function aText($al)
406: {
407: return oText($al); // uses function in tests.inc.php with site config support	
408: /* -- depreciated
409: switch($al)
410: 	{
411: 	case -1: return "Untested";
412: 	case 0: return "Passed";
413: 	case 1: return "Warning";
414: 	case 2: return "Failed";
415: 	default: return "Unknown";
416: 	}
417: */
418: }
419: ?>