Включаем и выключаем порты на свичах Dlink, SNR, QSW скрипт на Python

Задача: считать текущий статус порта, и в зависимости от него или выключить порт, или включить.

Решение: скрипт на python

# coding=utf-8
from pysnmp.hlapi import *
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto import rfc1902

def GetPortStatus(ip,comm,oid):
 rez=None	    
 try:
    errorIndication, errorStatus, errorIndex, varBinds = next(
       getCmd(SnmpEngine(),
	      CommunityData(comm),
	      UdpTransportTarget(
		  (ip, 161), timeout=2.0, retries=0
	      ),
	      ContextData(),
	      ObjectType(ObjectIdentity(oid)))
    )

    if errorIndication:
       print(errorIndication)
       return rez
    elif errorStatus:
       print('%s at %s' % (errorStatus.prettyPrint(),
			   errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
       return rez			
    else:
       for varBind in varBinds:      
	 if str(varBind).find("up")>0: rez=1;
	 if str(varBind).find("down")>0: rez=2;
	 if rez==None:
	   zx=str(varBind).split("=");
	   rez=zx[1].replace(" ","");      
 except:	       
     rez=None   
 return rez

def SetPortStatus(ip,comm,oid,status):
 rez=None	          
 try:
    cmdGen = cmdgen.CommandGenerator()
    errorIndication, errorStatus, errorIndex, varBinds = cmdGen.setCmd(
       cmdgen.CommunityData(comm,mpModel=1),
       cmdgen.UdpTransportTarget((ip, 161)),
	(oid, rfc1902.Integer(status)),    
    )
    # Check for errors and print out results
    if errorIndication:
       print(errorIndication)
    else:
       if errorStatus:
	   print('%s at %s' % (
	       errorStatus.prettyPrint(),
	       errorIndex and varBinds[int(errorIndex)-1] or '?'
	       )
	   )
	   rez=None
       else:
	   for name, val in varBinds:
	       print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))    
	       rez=True
 except:	       
     rez=None
 return rez
#снимает статус порта	
#dlink
# oid=1.3.6.1.2.1.2.2.1.8.x
# x - номер порта
rz=GetPortStatus('12.1.14.6','XFiles','1.3.6.1.2.1.2.2.1.8.9')	
print "Dlink: ",rz
#snr
rz=GetPortStatus('72.1.14.201','X-Files','1.3.6.1.2.1.2.2.1.8.3')	
print "SNR: ",rz
#qsw
rz=GetPortStatus('72.1.114.201','X-Files','1.3.6.1.2.1.2.2.1.8.3')	
print "QSW: ",rz

#устанавливаем статус порта
#up=1,down=2
#oid=1.3.6.1.2.1.2.2.1.7.9.x
# x - номер порта
#Dlink
rz=SetPortStatus('72.8.114.4','X-Files','1.3.6.1.2.1.2.2.1.7.9',1)
print rz;
#SNR
rz=SetPortStatus('72.7.114.196','X-Files','1.3.6.1.2.1.2.2.1.7.8',1)
print rz;
#QSR
rz=SetPortStatus('12.1.114.100','X-Files','1.3.6.1.2.1.2.2.1.7.3',1)
print rz;

 

Работаем на python с протоколом snmp

Есть несколько модулей, которые помогают работать с snmp на python. Гугл в помощь какие. Наиболее популярный: pysnmp. В Ubuntu ставится как:

pip install pysnmp

Напишем на Python аналог команды из консоли, которая получает  список мак адресов на портах свичей Dlink:

snmpwalk -v2c -c XFiles 172.18.114.6 1.3.6.1.2.1.17.7.1.2.2.1.2

Снимок экрана из 2016-05-20 10-05-50

Код:

from pysnmp.entity.rfc3413.oneliner import cmdgen

cmdGen = cmdgen.CommandGenerator()

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
    cmdgen.CommunityData('XFiles'),
    cmdgen.UdpTransportTarget(('172.18.114.6', 161)),
    '1.3.6.1.2.1.17.7.1.2.2.1.2'    
)

if errorIndication:
    print(errorIndication)
else:
    if errorStatus:
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
            )
        )
    else:
        for varBindTableRow in varBindTable:
            for name, val in varBindTableRow:
                print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))

Снимок экрана из 2016-05-20 10-07-41

Синхронная загрузка ajax при использовании jQuery

Задача: строго последоватально подгрузить код на страницу.

Решение:

  $.ajax({
        url: "controller/server/lanbilling/listgrp.php?blibaseid="+blibaseid,        
        async: false                
    }).done(function(data) {	    
	    $("#grpd").html(data);            	
    });

Конечно это считается не правильным подходом, т.к. в целом замедляет загрузку страницы. Однако в некоторых случая это просто необходимо. Например, когда нужно получить некое значение из загружаемого участка, а участок не понятно, уже подгрузился или еще нет.

Потоковое видео rtsp на сайте

Задача: есть IP камера вещающая по протоколу rtsp. В html5 стандарте, этот протокол не поддерживается. Ни один флеш и javascript плеер, его так-же не воспроизводят. С плагинами в браузер — бред.

Решение: при помощи ngnix конвертируем видео в удобовариваемый формат. Решение стырено с: http://conture.by/post/1552#more-1552

Для начала необходимые пакеты:

apt-get install libpcre3 libpcre3-dev libssl-dev gcc build-essential unzip rtmpdump

Устанавливать nginx надо не через apt-get, а из исходников.

wget http://conture.by/wp-content/uploads/2015/06/nginx-1.8.0.tar.gz
tar -xzvf nginx-1.8.0.tar.gz
wget http://conture.by/wp-content/uploads/2015/06/nginx-rtmp-module-master.zip
unzip nginx-rtmp-module-master.zip -d nginx-rtmp-module-master
wget http://conture.by/wp-content/uploads/2015/06/ffmpeg_nginx.zip
unzip ffmpeg_nginx.zip -d /bin
chmod 777 /bin/ffmpeg_nginx
cd nginx-1.8.0
./configure --prefix=/usr --add-module=../nginx-rtmp-module-master/arut-nginx-rtmp-module-f62a083/ --pid-path=/var/run/nginx.pid --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_ssl_module
make
make install
cp ../nginx-rtmp-module-master/arut-nginx-rtmp-module-f62a083/stat.xsl /etc/nginx/stat.xsl

Далее открываем конфиг nginx расположенный /etc/nginx/nginx.conf и правим под себя. У меня он следующий…

user www-data;
worker_processes 4; # воркеры по количеству ядер процессора
pid /run/nginx.pid;
error_log  /var/log/nginx/nginx_error.log debug;
env PATH;
events {
    worker_connections 768;
}

http {
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 88;

        # rtmp stat

        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            # you can move stat.xsl to a different location
            root /etc/nginx/;
        }

        location / {
            rtmp_control all;
        }


        error_page   500 502 503 504  /50x.html;

        location = /50x.html {
            root   html;
        }
    }
}

# RTMP proxy
rtmp {
    access_log /var/log/nginx/rtmp_access.log;
    server {
        listen 1935;
        ping 30s;
        notify_method get;
        # ретрансляция без звука
        application camera_1 {
            live on;
            exec_pull ffmpeg_nginx -i http://192.168.2.40:8000/71-camera1 -vcodec copy -f flv -an rtmp://localhost:1935/camera_1/live 2>>/var/log/nginx/ffmpeg_camera_1.log;
       }
       # конвертируем в меньшее разрешение без звука
        application cam_1 {
            live on;
            exec_pull ffmpeg_nginx -i http://192.168.2.40:8000/71-camera1 -threads 2 -f flv -r 25 -s 800x600 -an rtmp://localhost:1935/cam_1/live 2>>/var/log/nginx/ffmpeg_cam1.log;
       }
       # и ещё один поток...
        application infochan {
           live on;
           exec_pull ffmpeg_nginx -i http://192.168.2.40:8000/70-infokanal -threads 2 -f flv -r 25 -s 800x600 -an rtmp://localhost:1935/infochan/live 2>>/var/log/nginx/ffmpeg_infochan.log;
      }
    }
}

Проверяем корректность нашего конфига nginx:

root@kubuntu:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@kubuntu:~#

Если всё ок, то запускаем nginx:

service nginx start

Проверяем льётся ли что-нибудь на порт 1935. Выхлоп должен идти прямо в консоль.

rtmpdump -r "rtmp://127.0.0.1:1935/camera_1/live" -v
rtmpdump -r "rtmp://127.0.0.1:1935/cam_1/live" -v
rtmpdump -r "rtmp://127.0.0.1:1935/infochan/live" -v

Если есть выхлоп, то гуд. Приступаем к установке Flash-плеера на сайт. Качаем и распаковываем папку архива на сайт.
Содержимое html-страницы где будет встроен плеер должно иметь следующую структуру:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script src="/jwplayer/jwplayer.js" type="text/javascript"></script>
<div id="contain">Loading the player ...</div>
<script>
jwplayer("contain").setup({
  autostart:!0,
  height:600,
  width:800,
  modes:[{
   type:"flash",
   src:"/jwplayer/player.swf",
   config:{file:"live",streamer:"rtmp://внешний_ip_сервера_rtmp/infochan",provider:"rtmp"}
  }]
});
</script>

 

Простой сервер websockets на php

Фактически это каркас, для создания «чего-то поинтереснее» . Чисто логика, ничего лишнего.

javascript клиент:

<!DOCTYPE html>
<!--
(с) 2011-2015 Грибов Павел
http://грибовы.рф
Если исходный код найден в сети - значит лицензия GPL v.3
-->
<html>
    <head>
	<title>TODO supply a title</title>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
	<div>TODO write content</div>
	<script>
	    var socket = new WebSocket("ws://localhost:8000");
	    socket.onopen = function() {
	      console.log("Соединение установлено.");
	    };

	    socket.onclose = function(event) {
	      if (event.wasClean) {
		console.log('Соединение закрыто чисто');
	      } else {
		console.log('Обрыв соединения'); // например, "убит" процесс сервера
	      }
	      alert('Код: ' + event.code + ' причина: ' + event.reason);
	    };

	    socket.onmessage = function(event) {
	      console.log("Получены данные " + event.data);
	    };

	    socket.onerror = function(error) {
	      console.log("Ошибка " + error.message);
	    };	    
	    var timerId = setInterval(function() {
	      socket.send("тик!");
	    }, 2000);	    
	</script>
    </body>
</html>

php server:

#!/usr/bin/php
<?php

$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);

if (!$socket) {
    die("$errstr ($errno)\n");
}

$connects = array();
while (true) {
    //формируем массив прослушиваемых сокетов:
    $read = $connects;
    $read []= $socket;
    $write = $except = null;

    if (!stream_select($read, $write, $except, null)) {//ожидаем сокеты доступные для чтения (без таймаута)
        break;
    }

    if (in_array($socket, $read)) {//есть новое соединение
        //принимаем новое соединение и производим рукопожатие:
        if (($connect = stream_socket_accept($socket, -1)) && $info = handshake($connect)) {
            $connects[] = $connect;//добавляем его в список необходимых для обработки
            onOpen($connect, $info);//вызываем пользовательский сценарий
        }
        unset($read[ array_search($socket, $read) ]);
    }

    foreach($read as $connect) {//обрабатываем все соединения
        $data = fread($connect, 100000);

        if (!$data) { //соединение было закрыто
            fclose($connect);
            unset($connects[ array_search($connect, $connects) ]);
            onClose($connect);//вызываем пользовательский сценарий
            continue;
        }

        onMessage($connect, $data,$info);//вызываем пользовательский сценарий
    }
}

fclose($server);

function handshake($connect) {
    $info = array();

    $line = fgets($connect);
    $header = explode(' ', $line);
    $info['method'] = $header[0];
    $info['uri'] = $header[1];

    //считываем заголовки из соединения
    while ($line = rtrim(fgets($connect))) {
        if (preg_match('/\A(\S+): (.*)\z/', $line, $matches)) {
            $info[$matches[1]] = $matches[2];
        } else {
            break;
        }
    }

    $address = explode(':', stream_socket_get_name($connect, true)); //получаем адрес клиента
    $info['ip'] = $address[0];
    $info['port'] = $address[1];

    if (empty($info['Sec-WebSocket-Key'])) {
        return false;
    }

    //отправляем заголовок согласно протоколу вебсокета
    $SecWebSocketAccept = base64_encode(pack('H*', sha1($info['Sec-WebSocket-Key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
        "Upgrade: websocket\r\n" .
        "Connection: Upgrade\r\n" .
        "Sec-WebSocket-Accept:$SecWebSocketAccept\r\n\r\n";
    fwrite($connect, $upgrade);

    return $info;
}

function encode($payload, $type = 'text', $masked = false){
    $frameHead = array();
    $payloadLength = strlen($payload);

    switch ($type) {
        case 'text':
            // first byte indicates FIN, Text-Frame (10000001):
            $frameHead[0] = 129;
            break;

        case 'close':
            // first byte indicates FIN, Close Frame(10001000):
            $frameHead[0] = 136;
            break;

        case 'ping':
            // first byte indicates FIN, Ping frame (10001001):
            $frameHead[0] = 137;
            break;

        case 'pong':
            // first byte indicates FIN, Pong frame (10001010):
            $frameHead[0] = 138;
            break;
    }

    // set mask and payload length (using 1, 3 or 9 bytes)
    if ($payloadLength > 65535) {
        $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
        $frameHead[1] = ($masked === true) ? 255 : 127;
        for ($i = 0; $i < 8; $i++) {
            $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
        }
        // most significant bit MUST be 0
        if ($frameHead[2] > 127) {
            return array('type' => '', 'payload' => '', 'error' => 'frame too large (1004)');
        }
    } elseif ($payloadLength > 125) {
        $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
        $frameHead[1] = ($masked === true) ? 254 : 126;
        $frameHead[2] = bindec($payloadLengthBin[0]);
        $frameHead[3] = bindec($payloadLengthBin[1]);
    } else {
        $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
    }

    // convert frame-head to string:
    foreach (array_keys($frameHead) as $i) {
        $frameHead[$i] = chr($frameHead[$i]);
    }
    if ($masked === true) {
        // generate a random mask:
        $mask = array();
        for ($i = 0; $i < 4; $i++) {
            $mask[$i] = chr(rand(0, 255));
        }

        $frameHead = array_merge($frameHead, $mask);
    }
    $frame = implode('', $frameHead);

    // append payload to frame:
    for ($i = 0; $i < $payloadLength; $i++) {
        $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
    }

    return $frame;
}

function decode($data){
    $unmaskedPayload = '';
    $decodedData = array();

    // estimate frame type:
    $firstByteBinary = sprintf('%08b', ord($data[0]));
    $secondByteBinary = sprintf('%08b', ord($data[1]));
    $opcode = bindec(substr($firstByteBinary, 4, 4));
    $isMasked = ($secondByteBinary[0] == '1') ? true : false;
    $payloadLength = ord($data[1]) & 127;

    // unmasked frame is received:
    if (!$isMasked) {
        return array('type' => '', 'payload' => '', 'error' => 'protocol error (1002)');
    }

    switch ($opcode) {
        // text frame:
        case 1:
            $decodedData['type'] = 'text';
            break;

        case 2:
            $decodedData['type'] = 'binary';
            break;

        // connection close frame:
        case 8:
            $decodedData['type'] = 'close';
            break;

        // ping frame:
        case 9:
            $decodedData['type'] = 'ping';
            break;

        // pong frame:
        case 10:
            $decodedData['type'] = 'pong';
            break;

        default:
            return array('type' => '', 'payload' => '', 'error' => 'unknown opcode (1003)');
    }

    if ($payloadLength === 126) {
        $mask = substr($data, 4, 4);
        $payloadOffset = 8;
        $dataLength = bindec(sprintf('%08b', ord($data[2])) . sprintf('%08b', ord($data[3]))) + $payloadOffset;
    } elseif ($payloadLength === 127) {
        $mask = substr($data, 10, 4);
        $payloadOffset = 14;
        $tmp = '';
        for ($i = 0; $i < 8; $i++) {
            $tmp .= sprintf('%08b', ord($data[$i + 2]));
        }
        $dataLength = bindec($tmp) + $payloadOffset;
        unset($tmp);
    } else {
        $mask = substr($data, 2, 4);
        $payloadOffset = 6;
        $dataLength = $payloadLength + $payloadOffset;
    }

    /**
     * We have to check for large frames here. socket_recv cuts at 1024 bytes
     * so if websocket-frame is > 1024 bytes we have to wait until whole
     * data is transferd.
     */
    if (strlen($data) < $dataLength) {
        return false;
    }

    if ($isMasked) {
        for ($i = $payloadOffset; $i < $dataLength; $i++) {
            $j = $i - $payloadOffset;
            if (isset($data[$i])) {
                $unmaskedPayload .= $data[$i] ^ $mask[$j % 4];
            }
        }
        $decodedData['payload'] = $unmaskedPayload;
    } else {
        $payloadOffset = $payloadOffset - 4;
        $decodedData['payload'] = substr($data, $payloadOffset);
    }

    return $decodedData;
}

//пользовательские сценарии:

function onOpen($connect, $info) {
    echo "open\n";
    var_dump($info);
    fwrite($connect, encode('Соединение установлено!'));
}

function onClose($connect) {
    echo "close\n";
}

function onMessage($connect, $data,$info) {
    var_dump($info);
    echo decode($data)['payload'] . "\n";
    fwrite($connect, encode('так'));
}

По мотивам: https://habrahabr.ru/post/209864/ и https://learn.javascript.ru/websockets

Жизнь замечательных грибов