Compare commits

...

No commits in common. "main" and "verze3" have entirely different histories.
main ... verze3

124 changed files with 6959 additions and 3797 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
*.log

View File

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="jNetServer" default="default" basedir=".">
<description>Builds, tests, and runs the project jNetServer.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="jNetServer-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jnet</groupId>
<artifactId>jNetServer</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<finalName>jNetServer</finalName>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<shadedClassifierName>null</shadedClassifierName>
<transformers>
<transformer />
<transformer>
<mainClass>jnet.server.Server</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
<filter>
<artifact>jnet:jNetServer</artifact>
<excludes>
<exclude>db/**</exclude>
<exclude>assets/**</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/*.dtd</exclude>
<exclude>**/*.md</exclude>
<exclude>**/*.service</exclude>
<exclude>**/LICENSE</exclude>
<exclude>**/README</exclude>
<exclude>**/navod</exclude>
<exclude>**/INFO_BIN</exclude>
<exclude>**/INFO_SRC</exclude>
<exclude>**/CONTRIBUTING.md</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>${maven.compiler.release}</release>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<exec.mainClass>jnet.server.Server</exec.mainClass>
</properties>
</project>

72
log Normal file
View File

@ -0,0 +1,72 @@
27.08.26 18:45:51 I ---------------------------------------------
27.08.26 18:45:51 I jNet Server
27.08.26 18:45:51 I Version: 3 (Thu Aug 27 16:59:16 CEST 2026)
27.08.26 18:45:51 I ---------------------------------------------
27.08.26 18:45:51 I
27.08.26 18:45:51 I Loading config ...
27.08.26 18:45:52 I successfully
27.08.26 18:45:52 D Debug mode on
27.08.26 18:45:52 I Ugrade database ...
27.08.26 18:45:52 I Number of migrations performed: 0
27.08.26 18:45:52 I Connecting to database ...
27.08.26 18:45:53 I successfully
27.08.26 18:45:53 I Loading user list ...
27.08.26 18:45:53 I load 4 user(s)
27.08.26 18:45:53 I Loading node icon ...
27.08.26 18:45:53 I load 10 icon(s)
27.08.26 18:45:53 I Loading map and object list ...
27.08.26 18:45:53 I load 8 maps
27.08.26 18:45:53 I Loading events list ...
27.08.26 18:45:53 I load 436 events
27.08.26 18:45:53 I Loading SNMP profile list ...
27.08.26 18:45:53 I load 5 profile(s)
27.08.26 18:45:53 I Loading SNMP template list ...
27.08.26 18:45:53 I load 4 templates(s)
27.08.26 18:45:53 I Loading SNMP template value map list ...
27.08.26 18:45:53 I load 1 value map(s)
27.08.26 18:45:53 I Spoustim SNMP monitor (dotaz=5000ms, davka=2000ms)
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=3
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=5
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=6
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=7
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=8
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=9
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=10
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=11
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=12
27.08.26 18:45:53 I SNMP zarizeni pridano: ID=14
27.08.26 18:45:53 I Nacteno 10 monitoru, preskoceno 2
27.08.26 18:45:53 I Monitor spusten, interval=5000ms, zarizeni=10
27.08.26 18:45:53 I TrafficBatchDispatcher spusten, interval=2000ms
27.08.26 18:45:53 I SNMP monitor spusten, zarizeni=10
27.08.26 18:45:58 I Ping probe starting...
27.08.26 18:45:58 I Loaded 16 targets.
27.08.26 18:45:58 I OS is Windows - using PingEngine (subprocess ping)
27.08.26 18:45:58 I Targets set.
27.08.26 18:45:58 I Starting engine...
27.08.26 18:45:58 I Engine started successfully.
27.08.26 18:46:00 I Starting Netty on port 1225
27.08.26 18:46:01 I New client: /127.0.0.1:56938
27.08.26 18:46:01 D Received message ID: 501
27.08.26 18:46:01 D Received message ID: 502
27.08.26 18:46:02 I User: michal logged in (127.0.0.1)
27.08.26 18:47:40 D CHANGE: Node 25 (10.10.0.39) -> DOWN
27.08.26 18:47:48 D CHANGE: Node 25 (10.10.0.39) -> UP, odezva 2 ms
27.08.26 19:23:20 D CHANGE: Node 27 (10.10.0.254) -> DOWN
27.08.26 19:23:28 D CHANGE: Node 27 (10.10.0.254) -> UP, odezva 3 ms
27.08.26 20:12:00 D CHANGE: Node 27 (10.10.0.254) -> DOWN
27.08.26 20:12:08 D CHANGE: Node 27 (10.10.0.254) -> UP, odezva 2 ms
27.08.26 20:13:50 D CHANGE: Node 25 (10.10.0.39) -> DOWN
27.08.26 20:13:58 D CHANGE: Node 25 (10.10.0.39) -> UP, odezva 3 ms
27.08.26 21:3:40 D CHANGE: Node 27 (10.10.0.254) -> DOWN
27.08.26 21:3:48 D CHANGE: Node 27 (10.10.0.254) -> UP, odezva 2 ms
27.08.26 21:25:00 D CHANGE: Node 29 (10.0.0.219) -> DOWN
27.08.26 21:25:08 D CHANGE: Node 29 (10.0.0.219) -> UP, odezva 4 ms
27.08.26 21:27:30 D CHANGE: Node 4 (10.0.0.220) -> DOWN
27.08.26 21:27:38 D CHANGE: Node 4 (10.0.0.220) -> UP, odezva 5 ms
27.08.26 21:42:00 D CHANGE: Node 27 (10.10.0.254) -> DOWN
27.08.26 21:42:08 D CHANGE: Node 27 (10.10.0.254) -> UP, odezva 4 ms
27.08.26 21:58:00 D CHANGE: Node 25 (10.10.0.39) -> DOWN
27.08.26 21:58:08 D CHANGE: Node 25 (10.10.0.39) -> UP, odezva 2 ms
27.08.26 21:59:20 D CHANGE: Node 4 (10.0.0.220) -> DOWN
27.08.26 21:59:28 D CHANGE: Node 4 (10.0.0.220) -> UP, odezva 6 ms

60
log.log
View File

@ -1,60 +0,0 @@
13.02.25 18:7:16 I ---------------------------------------------
13.02.25 18:7:16 I jNet Server
13.02.25 18:7:16 I Version: 1 (Thu Feb 13 09:04:35 CET 2025)
13.02.25 18:7:16 I ---------------------------------------------
13.02.25 18:7:16 I
13.02.25 18:7:16 I Loading config ...
13.02.25 18:7:16 I successfully
13.02.25 18:7:16 D Debug mode on
13.02.25 18:7:16 I Connecting to a selected database ...
13.02.25 18:7:16 I successfully
13.02.25 18:7:16 I Loading user list ...
13.02.25 18:7:16 I load 2 user(s)
13.02.25 18:7:16 I Loading map list ...
13.02.25 18:7:16 I load 6 map(s)
13.02.25 18:7:16 I Loading object list ...
13.02.25 18:7:17 I load 8 object(s)
13.02.25 18:7:17 I Loading object type ...
13.02.25 18:7:17 I load 12 type(s)
13.02.25 18:7:17 I Loading SNMP profile ...
13.02.25 18:7:17 I load 2 profile(s)
13.02.25 18:7:17 I Loading events ...
13.02.25 18:7:17 I load 30 event(s)
13.02.25 18:7:17 I Ping probe start
13.02.25 18:7:17 I Server is ready and listening on port 1225
13.02.25 18:7:49 D -> Message type: 1
13.02.25 18:7:49 I Authorization request send (kubernetes.docker.internal)
13.02.25 18:7:49 D <- Message type: 3
13.02.25 18:7:49 D -> Message type: 4
13.02.25 18:7:49 I User: michal logged in (kubernetes.docker.internal)
13.02.25 18:7:49 D <- Message type: 5
13.02.25 18:7:49 D <- Message type: 9
13.02.25 18:7:49 D <- For all. Message type: 7
13.02.25 18:7:49 D <- Message type: 13
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 8
13.02.25 18:7:49 D <- Message type: 11
13.02.25 18:7:49 D <- Message type: 11
13.02.25 18:7:49 D <- Message type: 100
13.02.25 18:7:49 D <- Message type: 100
13.02.25 18:7:49 D <- Message type: 100
13.02.25 18:7:49 D <- Message type: 100
13.02.25 18:7:49 D <- Message type: 100
13.02.25 18:7:49 D <- Message type: 100
13.02.25 18:7:49 D <- Message type: 14
13.02.25 18:7:49 D <- Message type: 110
13.02.25 18:7:49 D <- Message type: 107
13.02.25 18:7:49 D <- Message type: 107
13.02.25 18:8:31 D -> Message type: 105
13.02.25 18:8:31 D <- For all. Message type: 105
13.02.25 18:8:31 D <- For all. Message type: 108

View File

@ -1,3 +0,0 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

55
nbactions.xml Normal file
View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action>
<actionName>run</actionName>
<packagings>
<packaging>jar</packaging>
</packagings>
<goals>
<goal>process-classes</goal>
<goal>org.codehaus.mojo:exec-maven-plugin:3.5.1:exec</goal>
</goals>
<properties>
<exec.vmArgs>-Dio.netty.noUnsafe=true -Dio.netty.tryUnsafe=false</exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.appArgs></exec.appArgs>
<exec.mainClass>${packageClassName}</exec.mainClass>
<exec.executable>java</exec.executable>
</properties>
</action>
<action>
<actionName>debug</actionName>
<packagings>
<packaging>jar</packaging>
</packagings>
<goals>
<goal>process-classes</goal>
<goal>org.codehaus.mojo:exec-maven-plugin:3.5.1:exec</goal>
</goals>
<properties>
<exec.vmArgs>-Dio.netty.noUnsafe=true -Dio.netty.tryUnsafe=false -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}</exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.appArgs></exec.appArgs>
<exec.mainClass>${packageClassName}</exec.mainClass>
<exec.executable>java</exec.executable>
<jpda.listen>true</jpda.listen>
</properties>
</action>
<action>
<actionName>profile</actionName>
<packagings>
<packaging>jar</packaging>
</packagings>
<goals>
<goal>process-classes</goal>
<goal>org.codehaus.mojo:exec-maven-plugin:3.5.1:exec</goal>
</goals>
<properties>
<exec.vmArgs>-Dio.netty.noUnsafe=true -Dio.netty.tryUnsafe=false</exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.mainClass>${packageClassName}</exec.mainClass>
<exec.executable>java</exec.executable>
<exec.appArgs></exec.appArgs>
</properties>
</action>
</actions>

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=36922983
build.xml.script.CRC32=49bb365f
build.xml.stylesheet.CRC32=f85dc8f2@1.113.0.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=36922983
nbproject/build-impl.xml.script.CRC32=233b34c8
nbproject/build-impl.xml.stylesheet.CRC32=12e0a6c2@1.113.0.48

View File

@ -1,120 +0,0 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=jNetServer
application.vendor=cucky
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.modulepath=\
${run.modulepath}
debug.test.classpath=\
${run.test.classpath}
debug.test.modulepath=\
${run.test.modulepath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/jNetServer.jar
dist.javadoc.dir=${dist.dir}/javadoc
dist.jlink.dir=${dist.dir}/jlink
dist.jlink.output=${dist.jlink.dir}/jNetServer
endorsed.classpath=
excludes=
file.reference.apache-commons-configuration2-2.9.0.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\apache-commons-configuration2-2.9.0.jar
file.reference.apache-commons-lang3-3.12.0.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\apache-commons-lang3-3.12.0.jar
file.reference.apache-commons-logging-1.2.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\apache-commons-logging-1.2.jar
file.reference.apache-commons-text-1.10.0.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\apache-commons-text-1.10.0.jar
file.reference.icmp4j-all.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\icmp4j-all.jar
file.reference.jna-5.3.1.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\jna-5.3.1.jar
file.reference.jna-platform-5.9.0.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\jna-platform-5.9.0.jar
file.reference.mysql-connector-java-8.0.15.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\mysql-connector-java-8.0.15.jar
file.reference.netty-all-4.1.68.Final.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\netty-all-4.1.68.Final.jar
file.reference.spring-security-crypto-5.8.0.jar=C:\\Users\\cucky\\Documents\\NetBeansProjects\\jar_files\\spring-security-crypto-5.8.0.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.mysql-connector-java-8.0.15.jar}:\
${reference.jNetLib.jar}:\
${file.reference.apache-commons-lang3-3.12.0.jar}:\
${file.reference.netty-all-4.1.68.Final.jar}:\
${file.reference.icmp4j-all.jar}:\
${file.reference.apache-commons-logging-1.2.jar}:\
${file.reference.apache-commons-text-1.10.0.jar}:\
${file.reference.jna-5.3.1.jar}:\
${file.reference.jna-platform-5.9.0.jar}:\
${file.reference.spring-security-crypto-5.8.0.jar}:\
${file.reference.apache-commons-configuration2-2.9.0.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.external.vm=true
javac.modulepath=
javac.processormodulepath=
javac.processorpath=\
${javac.classpath}
javac.source=23
javac.target=23
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.modulepath=\
${javac.modulepath}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.html5=false
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
# The jlink additional root modules to resolve
jlink.additionalmodules=
# The jlink additional command line parameters
jlink.additionalparam=
jlink.launcher=true
jlink.launcher.name=jNetServer
main.class=jnet.server.Server
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
project.jNetLib=../jNetLib
reference.jNetLib.jar=${project.jNetLib}/dist/jNetLib.jar
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.modulepath=\
${javac.modulepath}
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
run.test.modulepath=\
${javac.test.modulepath}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>jNetServer</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
<references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
<reference>
<foreign-project>jNetLib</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
</references>
</configuration>
</project>

164
pom.xml Normal file
View File

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jnet</groupId>
<artifactId>jNetServer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<exec.mainClass>jnet.server.Server</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.118.Final</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jNetLib</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>26.7.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.14.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>10.15.0</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
<version>10.15.0</version>
</dependency>
</dependencies>
<build>
<!-- Zakážeme standardní kopírování resources do target/classes -->
<resources>
<!-- prázdné -->
</resources>
<finalName>jNetServer</finalName>
<plugins>
<!-- Kopírování resources do target/ (vedle JARu) včetně podsložek -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Shade plugin – vytvoří fat JAR a vyloučí naše resources -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<shadedClassifierName>null</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>jnet.server.Server</mainClass>
</transformer>
</transformers>
<filters>
<!-- Vyřazení bezpečnostních podpisů ze všech artifactů -->
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
<!-- Vyloučení veškerých resources z našeho vlastního artifactu -->
<filter>
<artifact>jnet:jNetServer</artifact>
<excludes>
<!-- Celé složky -->
<exclude>db/**</exclude>
<exclude>assets/**</exclude>
<!-- Konkrétní soubory (a všechny s danou příponou) -->
<exclude>**/*.properties</exclude>
<exclude>**/*.dtd</exclude>
<exclude>**/*.md</exclude>
<exclude>**/*.service</exclude>
<exclude>**/LICENSE</exclude>
<exclude>**/README</exclude>
<exclude>**/navod</exclude>
<exclude>**/INFO_BIN</exclude>
<exclude>**/INFO_SRC</exclude>
<exclude>**/CONTRIBUTING.md</exclude>
<!-- Pokud máte další soubory, přidejte je sem -->
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<!-- Kompilátor -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>${maven.compiler.release}</release>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,709 +0,0 @@
package jnet.server;
import java.sql.Timestamp;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import jnet.lib.LogFile;
import jnet.lib.object.Event;
import jnet.lib.object.Map;
import jnet.lib.object.MapObject;
import jnet.lib.object.ObjectType;
import jnet.lib.object.SnmpProbe;
import jnet.lib.object.SnmpProfile;
import jnet.lib.object.User;
public class Database {
private static Connection connection = null;
private static String host;
private static String port;
private static String database;
private static String user;
private static String password;
public void connect(String host, String port, String database, String user, String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
connection = connect();
}
private static Connection connect() {
try {
LogFile.printInfo("Connecting to a selected database ...");
Connection connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + ""
+ "?useUnicode=true"
+ "&characterEncoding=UTF-8"
+ "&autoReconnect=true"
+ "&serverTimezone=UTC", user, password);
LogFile.printInfo(" successfully");
return connection;
} catch (SQLException ex) {
LogFile.printErr("MySQL connection exception: " + ex.getMessage());
LogFile.printErr("MySQL host: " + host + " port: " + port + " database: " + database + " user: " + user);
System.exit(0);
}
return null;
}
/**
* vrati aktualni spojeni
*
* @return
* @throws SQLException
*/
public static Connection getCurrentConnection() throws SQLException {
if (connection != null || connection.isClosed()) {
return connection;
} else {
connection = connect();
}
return null;
}
/**
* insert
*
* @param sql dotaz
* @return pri uspesnem vlozeni vrati posledni vlozeny id
*/
public static int insert(String sqlQuery) {
long id = -1;
try {
Statement statement = getCurrentConnection().createStatement();
statement.executeUpdate(sqlQuery, Statement.RETURN_GENERATED_KEYS);
PreparedStatement getLastInsertId = getCurrentConnection().prepareStatement("SELECT LAST_INSERT_ID()");
ResultSet rs = getLastInsertId.executeQuery();
if (rs.next()) {
id = rs.getLong("last_insert_id()");
}
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + " SQL: " + sqlQuery);
}
return (int) id;
}
/**
* update
*
* @param sql sql dotaz
*/
public static void update(String sql) {
try {
Statement statement = getCurrentConnection().createStatement();
statement.executeUpdate(sql);
statement.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + " SQL: " + sql);
}
}
/**
* smaze zaznam z tabulky
*
* @param table nazev tabulky
* @param id id rádku
* @return
*/
static boolean remove(String table, int id) {
try {
String sql = "DELETE FROM " + table + " WHERE id = ?";
PreparedStatement stmt = getCurrentConnection().prepareStatement(sql);
stmt.setInt(1, id);
int affectedRows = stmt.executeUpdate();
if (affectedRows > 0) {
return true;
} else {
return false;
}
} catch (SQLException ex) {
LogFile.printErr("Database error: " + ex.getMessage());
}
return false;
}
/**
* vytvoří tabulku
*
* @param sql string
*/
public static void createTable(String sql) {
try {
Statement statement = getCurrentConnection().createStatement();
statement.executeUpdate(sql);
} catch (SQLException e) {
System.out.println("An error has occured on Table Creation: " + e.getMessage());
}
}
/**
* vráti seznam vsech map
*
* @return ArrayList<Map>
*/
public static ArrayList<Map> getMapList() {
String sql = "SELECT * FROM maps";
ArrayList<Map> list = new ArrayList<Map>();
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
Map m = new Map(
rs.getInt("id"),
rs.getString("name"),
rs.getBoolean("locked"));
list.add(m);
}
rs.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + "query: " + sql);
}
return list;
}
/**
* vrati seznam objektu odpovidajici mape
*
* @param mapId id mapy
* @return ArrayList<MapObject>
*/
public static ArrayList<MapObject> getMapObject(int mapId) {
ArrayList<MapObject> list = new ArrayList<>();
String sql = "SELECT * FROM objects WHERE map = " + mapId;
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet r = statement.executeQuery(sql);
while (r.next()) {
int objId = r.getInt("id");
list.add(new MapObject(
objId,
r.getString("name"),
r.getInt("map"),
r.getInt("objectType"),
r.getString("ip"),
r.getInt("x"),
r.getInt("y"),
r.getString("user"),
r.getString("password"),
r.getString("description"),
r.getString("location"),
r.getInt("snmpProfile"),
getSnmpProbe(objId),
(boolean) (r.getInt("active") == 1),
(r.getInt("winbox") == 1),
r.getString("winboxPort"),
(boolean) (r.getInt("ssh") == 1),
r.getString("sshPort"),
(boolean) (r.getInt("web") == 1),
r.getString("webPort"),
r.getInt("webVerze"),
(boolean) (r.getInt("telnet") == 1),
r.getString("telnetPort"),
(boolean) (r.getInt("sms") == 1),
r.getString("smsPort"),
r.getInt("smsVerze")
));
}
r.close();
statement.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + "query: " + sql);
}
return list;
}
/**
* vrati seznam objektu
*
* @return ArrayList<MapObject>
*/
public static ArrayList<MapObject> getAllMapObject() {
ArrayList<MapObject> list = new ArrayList<>();
String sql = "SELECT * FROM objects";
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet r = statement.executeQuery(sql);
while (r.next()) {
int objId = r.getInt("id");
list.add(new MapObject(
objId,
r.getString("name"),
r.getInt("map"),
r.getInt("objectType"),
r.getString("ip"),
r.getInt("x"),
r.getInt("y"),
r.getString("user"),
r.getString("password"),
r.getString("description"),
r.getString("location"),
r.getInt("snmpProfile"),
getSnmpProbe(objId),
(boolean) (r.getInt("active") == 1),
(r.getInt("winbox") == 1),
r.getString("winboxPort"),
(boolean) (r.getInt("ssh") == 1),
r.getString("sshPort"),
(boolean) (r.getInt("web") == 1),
r.getString("webPort"),
r.getInt("webVerze"),
(boolean) (r.getInt("telnet") == 1),
r.getString("telnetPort"),
(boolean) (r.getInt("sms") == 1),
r.getString("smsPort"),
r.getInt("smsVerze")
));
}
r.close();
statement.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + "query: " + sql);
}
return list;
}
/**
* vrati seznam SNMP probe
*
* @return ArrayList<SnmpProbe>
*/
public static ArrayList<SnmpProbe> getSnmpProbe(int objId) {
ArrayList<SnmpProbe> list = new ArrayList<>();
String sql = "SELECT * FROM snmpProbe WHERE object = " + objId;
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet r = statement.executeQuery(sql);
while (r.next()) {
list.add(new SnmpProbe(
r.getInt("id"),
r.getString("name"),
r.getInt("object")
));
}
r.close();
statement.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + "query: " + sql);
}
return list;
}
/**
* vrati informace o uzivateli podle jmena
*
* @param username
* @return User
*/
static User getUserInfo(String username) {
User u = null;
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet r_con = statement.executeQuery("SELECT * FROM users WHERE username = '" + username + "'");
while (r_con.next()) {
u = new User(r_con.getInt("id"),
username,
r_con.getString("password"),
r_con.getBoolean("add_map"),
r_con.getBoolean("remove_map"),
r_con.getBoolean("edit_map"),
r_con.getBoolean("add_object"),
r_con.getBoolean("remove_object"),
r_con.getBoolean("edit_object"),
r_con.getBoolean("edit_server")
);
}
r_con.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage());
}
return u;
}
/**
* vrati seznam object type
*
* @return ArrayList<ObjectType>
*/
static ArrayList<ObjectType> getObjectType() {
ArrayList<ObjectType> objectType = new ArrayList<>();
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet so = statement.executeQuery("SELECT * FROM objectType");
while (so.next()) {
objectType.add(new ObjectType(
so.getInt("id"),
so.getString("name"),
so.getString("image")
));
}
so.close();
} catch (SQLException ex) {
System.out.println("MySQL exception: " + ex.getMessage());
}
return objectType;
}
/**
* vrati seznam uzivatelu
*
* @return ArrayList<User>
*/
static ArrayList<User> getUsers() {
ArrayList<User> users = new ArrayList<>();
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet su = statement.executeQuery("SELECT * FROM users");
while (su.next()) {
users.add(new User(
su.getInt("id"),
su.getString("username"),
"",
su.getBoolean("add_map"),
su.getBoolean("remove_map"),
su.getBoolean("edit_map"),
su.getBoolean("add_object"),
su.getBoolean("remove_object"),
su.getBoolean("edit_object"),
su.getBoolean("edit_server")
));
}
su.close();
} catch (SQLException ex) {
System.out.println("MySQL exception: " + ex.getMessage());
}
return users;
}
/**
* vrati snmp profily
*
* @return ArrayList<SnmpProfile>
*/
static ArrayList<SnmpProfile> getSnmpProfile() {
ArrayList<SnmpProfile> snmpProfile = new ArrayList<>();
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM snmpProfile");
while (rs.next()) {
snmpProfile.add(new SnmpProfile(
rs.getInt("id"),
rs.getString("name"),
rs.getInt("version"),
rs.getString("port"),
rs.getString("communityRead"),
rs.getString("communityRead")
));
}
rs.close();
} catch (SQLException ex) {
System.out.println("MySQL exception: " + ex.getMessage());
}
return snmpProfile;
}
/**
* vrati seznam udalosti
*
* @param
* @return ArrayList<Event>
*/
public static ArrayList<Event> getEvents() {
ArrayList<Event> list = new ArrayList<>();
String sql = "SELECT * FROM events";
try {
Statement statement = getCurrentConnection().createStatement();
ResultSet r = statement.executeQuery(sql);
while (r.next()) {
list.add(new Event(
r.getInt("id"),
r.getInt("object"),
r.getLong("start"),
r.getLong("finish"),
r.getString("description"),
r.getInt("type")
));
}
r.close();
statement.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + "query: " + sql);
}
return list;
}
/**
* pridá objekt
*
* @param mo MapObject
* @return
*/
static MapObject addMapObject(MapObject mo) {
String query = "INSERT INTO objects ("
+ "name,"
+ "ip,"
+ "x,"
+ "y,"
+ "map,"
+ "objectType,"
+ "active,"
+ "user,"
+ "password,"
+ "description,"
+ "location,"
+ "snmpProfile,"
+ "winbox,"
+ "winboxPort,"
+ "ssh,"
+ "sshPort,"
+ "web,"
+ "webPort,"
+ "webVerze,"
+ "telnet,"
+ "telnetPort,"
+ "sms,"
+ "smsPort,"
+ "smsVerze"
+ ") VALUES ("
+ "'" + mo.getName() + "',"
+ "'" + mo.getIp() + "',"
+ "'" + mo.getX() + "',"
+ "'" + mo.getY() + "',"
+ "'" + mo.getMap() + "',"
+ "'" + mo.getObjectType() + "',"
+ "'" + (mo.isActive() ? 1 : 0) + "',"
+ "'" + mo.getUser() + "',"
+ "'" + mo.getPassword() + "',"
+ "'" + mo.getDescription() + "',"
+ "'" + mo.getLocation() + "',"
+ "'" + mo.getSnmpProfile() + "',"
+ "'" + (mo.isWinbox() ? 1 : 0) + "',"
+ "'" + mo.getWinboxPort() + "',"
+ "'" + (mo.isSsh() ? 1 : 0) + "',"
+ "'" + mo.getSshPort() + "',"
+ "'" + (mo.isWeb() ? 1 : 0) + "',"
+ "'" + mo.getWebPort() + "',"
+ "'" + mo.getWebVerze() + "',"
+ "'" + (mo.isTelnet() ? 1 : 0) + "',"
+ "'" + mo.getTelnetPort() + "',"
+ "'" + (mo.isSms() ? 1 : 0) + "',"
+ "'" + mo.getSmsPort() + "',"
+ "'" + mo.getSmsVerze() + "'"
+ ")";
mo.setId(insert(query));
return mo;
}
/**
* nastaví stav zámku mapy
*
* @param state stav
* @param map map id
*/
static void mapLock(int state, int map) {
update("UPDATE maps SET locked='" + state + "' WHERE id=" + map);
}
/**
* pridá typ objektu
*
* @param ot ObjectType
* @return
*/
static int addObjectType(ObjectType ot) {
return insert("INSERT INTO objectType (name, image) VALUES ('" + ot.getName() + "', '" + ot.getImgStr() + "')");
}
/**
* odebere objekt z databaze
*
* @param id
*/
static void removeObject(int id) {
if (remove("objects", id)) {
LogFile.printInfo("Obejct ID " + id + " removed from database");
} else {
LogFile.printErr("Obejct ID " + id + " not removed from database");
}
}
/**
* odebere mapu z databaze
*
* @param id
*/
static void removeMap(int id) {
if (remove("maps", id)) {
LogFile.printInfo("Map ID " + id + " removed from database");
} else {
LogFile.printErr("Map ID " + id + " not removed from database");
}
}
/**
* pridani mapy
*
* @param name nazev mapy
* @return
*/
static int addMap(String name) {
return insert("INSERT INTO maps (name) VALUES ('" + name + "')");
}
/**
* zmeni pozici objektu
*
* @param id id objektu
* @param x pozice x
* @param y pozice y
*/
static void objectMove(int id, int x, int y) {
update("UPDATE objects SET x='" + x + "', y='" + y + "' WHERE id=" + id);
}
/**
* upravi object
*
* @param mo MapObject
*/
static void updateObject(MapObject mo) {
update("UPDATE objects SET "
+ "name='" + mo.getName() + "', "
+ "ip='" + mo.getIp() + "', "
+ "x='" + mo.getX() + "', "
+ "y='" + mo.getY() + "',"
+ "map='" + mo.getMap() + "', "
+ "objectType='" + mo.getObjectType() + "', "
+ "active='" + (mo.isActive() ? 1 : 0) + "', "
+ "user='" + mo.getUser() + "', "
+ "password='" + mo.getPassword() + "', "
+ "description='" + mo.getDescription() + "', "
+ "location='" + mo.getLocation() + "', "
+ "snmpProfile='" + mo.getSnmpProfile() + "', "
+ "winbox='" + (mo.isWinbox() ? 1 : 0) + "', "
+ "winboxPort='" + mo.getWinboxPort() + "', "
+ "ssh='" + (mo.isSsh() ? 1 : 0) + "', "
+ "sshPort='" + mo.getSshPort() + "', "
+ "web='" + (mo.isWeb() ? 1 : 0) + "', "
+ "webPort='" + mo.getWebPort() + "', "
+ "webVerze='" + mo.getWebVerze() + "', "
+ "telnet='" + (mo.isTelnet() ? 1 : 0) + "', "
+ "telnetPort='" + mo.getTelnetPort() + "', "
+ "sms='" + (mo.isSms() ? 1 : 0) + "', "
+ "smsPort='" + mo.getSmsPort() + "', "
+ "smsVerze='" + mo.getSmsVerze() + "' "
+ "WHERE id=" + mo.getId());
}
public static Event addEvent(int mo_id, String description, int type) {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Event event = new Event(mo_id,
timestamp.getTime(),
description,
type);
int id = insert("INSERT INTO events ("
+ "object, "
+ "start, "
+ "description, "
+ "type"
+ ") VALUES ("
+ "'" + event.getObject() + "',"
+ "'" + event.getStart() + "',"
+ "'" + event.getDescription() + "',"
+ "'" + event.getType() + "'"
+ ")");
event.setId(id);
return event;
}
public static Event endEvent(int objectId, int type) {
Event event = null;
try {
String select_query = "SELECT * FROM events WHERE object = '" + objectId + "' && type = '" + type + "' ORDER BY id DESC LIMIT 1";
PreparedStatement stmt = getCurrentConnection().prepareStatement(select_query);
ResultSet rs = stmt.executeQuery();
// Process the result
if (rs.next()) {
event = new Event(
objectId,
rs.getLong("start"),
rs.getString("description"),
type);
event.setId(rs.getInt("id"));
}
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
event.setEnd(timestamp.getTime());
String update_query = "UPDATE events SET finish='" + event.getEnd() + "' WHERE id=" + event.getId();
update(update_query);
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage());
}
return event;
}
static int addUser(User user) {
return insert("INSERT INTO users ("
+ "username, "
+ "password, "
+ "add_map, "
+ "remove_map, "
+ "edit_map, "
+ "add_object, "
+ "remove_object, "
+ "edit_object, "
+ "edit_server"
+ ") VALUES ("
+ "'"+user.getUsername()+"',"
+ "'"+user.getPassword()+"',"
+ "'"+(user.isAddMap()?1:0)+"',"
+ "'"+(user.isRemoveMap()?1:0)+"',"
+ "'"+(user.isEditMap()?1:0)+"',"
+ "'"+(user.isAddObject()?1:0)+"',"
+ "'"+(user.isRemoveObject()?1:0)+"',"
+ "'"+(user.isEditObject()?1:0)+"',"
+ "'"+(user.isEditServer()?1:0)+"'"
+ ")");
}
static void editUser(User ur) {
String sql = "UPDATE users SET "
+ "username='" + ur.getUsername() + "',"
+ "add_map='" + (ur.isAddMap() ? 1:0) + "',"
+ "remove_map='" + (ur.isRemoveMap() ? 1:0) + "',"
+ "edit_map='" + (ur.isEditMap() ? 1:0) + "',"
+ "add_object='" + (ur.isAddObject() ? 1:0) + "',"
+ "remove_object='" + (ur.isEditObject() ? 1:0) + "',"
+ "edit_object='" + (ur.isRemoveObject() ? 1:0) + "',"
+ "edit_server='" + (ur.isEditServer() ? 1:0) + "'"
+ "WHERE id='" + ur.getId() + "'";
update(sql);
}
static void deleteObjectLog(int objId) {
String sql = "DELETE FROM events WHERE object = " + objId;
try {
Statement statement = getCurrentConnection().createStatement();
statement.executeUpdate(sql);
statement.close();
} catch (SQLException ex) {
LogFile.printErr("MySQL exception: " + ex.getMessage() + " SQL: " + sql);
}
}
}

View File

@ -1,173 +0,0 @@
package jnet.server;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import jnet.lib.BuilddDate;
import jnet.lib.LogFile;
import jnet.lib.LogWindow;
import jnet.lib.OSValidator;
import jnet.lib.PropertiesManager;
import jnet.lib.object.Event;
import jnet.lib.object.Map;
import jnet.lib.object.MapObject;
import jnet.lib.object.ObjectType;
import jnet.lib.object.OnlineClients;
import jnet.lib.object.SnmpProbe;
import jnet.lib.object.SnmpProfile;
import jnet.lib.object.User;
import jnet.server.network.NettyServer;
import jnet.server.probe.NettyPing;
public class Server {
// verze serveru
public static final int SERVER_VERSION = 1;
// minimální verze klienta
public static final int MINIMAL_CLIENT_VERSION = 1;
public static PropertiesManager config;
public static List<Map> maps = new ArrayList<>();
public static ArrayList<MapObject> mapObject= new ArrayList<>();
public static ArrayList<OnlineClients> onlineClients = new ArrayList<>();
public static ArrayList<ObjectType> objectType = new ArrayList<>();
public static ArrayList<SnmpProfile> snmpProfile = new ArrayList<>();
public static ArrayList<SnmpProbe> snmpProbe = new ArrayList<>();
public static ArrayList<User> users = new ArrayList<>();
public static ArrayList<Event> events = new ArrayList<>();
public static void main(String[] args) {
// pokud je hostitelsky system windows otevre logovaci okno
if (OSValidator.isWindows()) {
new LogWindow();
}
LogFile.clear();
LogFile.setDebug(false);
LogFile.printInfo("---------------------------------------------");
LogFile.printInfo(" jNet Server ");
LogFile.printInfo(" Version: " + SERVER_VERSION + " (" + BuilddDate.get() + ")");
LogFile.printInfo("---------------------------------------------");
LogFile.printInfo("");
///
/// nahrani konfigurace
///
LogFile.printInfo("Loading config ...");
try {
// Načtení existující konfigurace, pokud soubor existuje
config = new PropertiesManager("config.properties");
config.load();
LogFile.printInfo(" successfully");
} catch (PropertiesManager.FileException | PropertiesManager.ConfigException ex) {
LogFile.printErr(" fail. " + ex.getMessage());
System.exit(0);
}
///
/// debug rezim ?
///
if (config.getBoolean("debug")) {
LogFile.setDebug(true);
LogFile.printDebug("Debug mode on");
}
///
/// pripojeni k databazi
///
new Database().connect(config.getString("mysql_server"),
config.getString("mysql_port"),
config.getString("mysql_database"),
config.getString("mysql_user"),
config.getString("mysql_password"));
///
/// konfigurace z databaze
///
LogFile.printInfo("Loading user list ...");
users = Database.getUsers();
LogFile.printInfo(" load " + users.size() + " user(s)");
LogFile.printInfo("Loading map list ...");
maps = Database.getMapList();
LogFile.printInfo(" load " + maps.size() + " map(s)");
LogFile.printInfo("Loading object list ...");
mapObject = Database.getAllMapObject();
LogFile.printInfo(" load " + mapObject.size() + " object(s)");
LogFile.printInfo("Loading object type ...");
objectType = Database.getObjectType();
LogFile.printInfo(" load " + objectType.size() + " type(s)");
LogFile.printInfo("Loading SNMP profile ...");
snmpProfile = Database.getSnmpProfile();
LogFile.printInfo(" load " + snmpProfile.size() + " profile(s)");
// LogFile.printInfo("Loading SNMP template ...");
// snmpProbe = Database.getSnmpProbe();
// LogFile.printInfo(" load " + snmpProbe.size() + " template(s)");
LogFile.printInfo("Loading events ...");
events = Database.getEvents();
LogFile.printInfo(" load " + events.size() + " event(s)");
///
/// spusteni serveru
///
NettyServer nettyserver = new NettyServer(config.getInt("server_port"));
nettyserver.start();
///
/// spusteni ping probe
///
/// spousete pro kazdou mapu samostatne ?
///
// Ping pp = new Ping();
// pp.start();
// Ping2 p2 = new Ping2();
// p2.start();
NettyPing np = new NettyPing();
np.start();
}
public static void restartServer() {
new Thread(() -> {
try {
Thread.sleep(5000);
try {
String java = System.getProperty("java.home") + "/bin/java";
File jarFile = new File(Server.class
.getProtectionDomain().getCodeSource().getLocation().getPath());
List<String> command = new ArrayList<>();
command.add(java);
command.add("-jar");
command.add(jarFile.getAbsolutePath());
new ProcessBuilder(command).start();
System.exit(0);
} catch (IOException ex) {
LogFile.printErr("Restart failed! " + ex.getMessage());
}
} catch (InterruptedException e) {
LogFile.printErr("Restart failed! " + e.getMessage());
}
}).start();
}
}

View File

@ -1,349 +0,0 @@
package jnet.server;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.lang.management.ManagementFactory;
import java.net.InetSocketAddress;
import java.util.ListIterator;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.PasswordHashing;
import jnet.lib.object.Event;
import jnet.lib.object.Map;
import jnet.lib.object.MapObject;
import jnet.lib.object.ObjectType;
import jnet.lib.object.OnlineClients;
import jnet.lib.object.ServerConfig;
import jnet.lib.object.SnmpProfile;
import jnet.lib.object.User;
public class ServerMessageParser {
private final Channel currentClient;
private static final ChannelGroup channels = new DefaultChannelGroup(
"containers", GlobalEventExecutor.INSTANCE);
public ServerMessageParser(Channel currentClient) {
this.currentClient = currentClient;
}
public void parse(Message msg) {
LogFile.printDebug("-> Message type: " + msg.getType());
ListIterator<Map> iteratorMap = Server.maps.listIterator();
ListIterator<MapObject> iteratorMapObject = Server.mapObject.listIterator();
switch (msg.getType()) {
case Message.CLIENT_VERSION:
int client_version = (int) msg.getMsg();
if (client_version < Server.MINIMAL_CLIENT_VERSION) {
LogFile.printInfo("Outdated client. Sent update request (" + ((InetSocketAddress) currentClient.remoteAddress()).getHostName() + ")");
send(new Message(Message.UPDATE, null));
} else {
LogFile.printInfo("Authorization request send (" + ((InetSocketAddress) currentClient.remoteAddress()).getHostName() + ")");
// oodeslat pozadavek na autorizacni udaje
send(new Message(Message.AUTH_REQUEST, null));
}
break;
case Message.AUTH:
String[] userData = (String[]) msg.getMsg();
String username = userData[0];
String password = userData[1];
int platform = Integer.parseInt(userData[2]);
User u = Database.getUserInfo(username);
if (PasswordHashing.verify(password, u.getPassword())) {
LogFile.printInfo("User: " + username + " logged in (" + ((InetSocketAddress) currentClient.remoteAddress()).getAddress().getHostName() + ")");
// odeslat informaci uzivateli o jeho uspesnem prihlaseni
send(new Message(Message.AUTH_SUCEFULL, null));
// pridani uzivatele mezi pripojene kanaly
channels.add(currentClient);
// vložit uživatele na seznam online uživatelů
InetSocketAddress socketAddress = (InetSocketAddress) currentClient.remoteAddress();
String clientIp = socketAddress.getAddress().getHostAddress();
String clientPort = String.valueOf(socketAddress.getPort());
Server.onlineClients.add(new OnlineClients(
String.valueOf(u.getId()),
u.getUsername(),
clientIp,
clientPort,
platform));
// odeslat informace o prihlasenem uzivateli, opravneni atd
send(new Message(Message.USER_INFO, u));
// odeslat vsem nový seznam pripojenych klientu
sendAll(new Message(Message.ONLINE_CLIENTS, Server.onlineClients));
// odeslat nastaveni serveru
ServerConfig sc = new ServerConfig(
Server.config.getInt("ping_repeat"),
Server.config.getInt("ping_attempt"),
Server.config.getInt("ping_timeout"),
Server.config.getInt("instability_attempt"),
Server.config.getInt("instability_limit"));
send(new Message(Message.SERVER_CONFIG, sc));
// odeslat typy objektu
for (ObjectType ot : Server.objectType) {
send(new Message(Message.OBJECT_TYPE, ot));
}
// odesila seznam uzivatelu
for (User us : Server.users) {
send(new Message(Message.USER, us));
}
// odeslat seznam map
for (Map i : Server.maps) {
send(new Message(Message.MAP, i));
}
// odeslat seznam objektu
send(Message.OBJECT_LIST, Server.mapObject);
// odeslat seznam udalosti
send(new Message(Message.EVENT_LIST, Server.events));
// odeslat seznam snmp profilů
for (SnmpProfile i : Server.snmpProfile) {
send(new Message(Message.SNMP_PROFILE, i));
}
} else {
LogFile.printInfo("Authorization failed (ser: " + username + " )");
}
break;
case Message.RESTART:
LogFile.printInfo("Prijat pozadavek na restart serveru");
Server.restartServer();
break;
case Message.UPTIME:
long uptime = ManagementFactory.getRuntimeMXBean().getUptime();
send(Message.UPTIME, uptime);
break;
case Message.NEW_OBJECT_TYPE:
ObjectType not = (ObjectType) msg.getMsg();
int id = Database.addObjectType(not);
not.setId(id);
Server.objectType.add(not);
sendAll(new Message(Message.OBJECT_TYPE, not));
break;
case Message.SET_MAP_LOCK:
int[] data_lock = (int[]) msg.getMsg();
while (iteratorMap.hasNext()) {
Map map = iteratorMap.next();
if (map.getId() == data_lock[0]) {
map.setLock((data_lock[1] == 1));
break;
}
}
// upravit informaci v databazi
Database.mapLock(data_lock[1], data_lock[0]);
// odeslani informace ostatnim
sendAll(new Message(Message.SET_MAP_LOCK, data_lock));
break;
case Message.ADD_OBJECT:
MapObject mo = Database.addMapObject((MapObject) msg.getMsg());
// pridat do seznamu
Server.mapObject.add(mo);
// odesle všem novy objekt
sendAll(new Message(Message.ADD_OBJECT, mo));
// prida event a odesle ho
Event event = Database.addEvent(mo.getId(), "Přidáno", Event.TYPE_INFO);
sendAll(new Message(Message.EVENT_NEW, event));
// pokud je object vypnuty prida log
if (!mo.isActive()) {
Event event_disable = Database.addEvent(mo.getId(), "Ping vypnut", Event.TYPE_PING_OFF);
sendAll(new Message(Message.EVENT_NEW, event_disable));
}
break;
case Message.REMOVE_OBJECT:
while (iteratorMapObject.hasNext()) {
MapObject obj = iteratorMapObject.next();
if (obj.getId() == (int) msg.getMsg()) {
// odebere z databaze
Database.removeObject(obj.getId());
// odesle informaci o odebrani objektu klientum
sendAll(new Message(Message.REMOVE_OBJECT, obj.getId()));
// odebere ze seznamu
iteratorMapObject.remove();
break;
}
}
break;
case Message.MAP_REMOVE:
while (iteratorMap.hasNext()) {
Map map = iteratorMap.next();
if (map.getId() == (int) msg.getMsg()) {
// odebere z databaze
Database.removeMap(map.getId());
// odesle informaci o odebrani objektu klientum
sendAll(new Message(Message.MAP_REMOVE, map.getId()));
// odebere ze seznamu
iteratorMap.remove();
break;
}
}
break;
case Message.MAP_ADD:
Map map = new Map((String) msg.getMsg());
// přidání mapy do databaze
map.setId(Database.addMap(map.getName()));
//odeslání mapy klientum
send(new Message(Message.MAP, map));
// pridani mapy do seznamu
iteratorMap.add(map);
break;
case Message.OBJECT_MOVE:
int[] data = (int[]) msg.getMsg();
// 0 = obj id
// 2 = x
// 2 = y
// zmenit v databázi
Database.objectMove(data[0], data[1], data[2]);
// zmenit v seznamu
while (iteratorMapObject.hasNext()) {
MapObject obj = iteratorMapObject.next();
if (obj.getId() == data[0]) {
// zmenit pozici
obj.setX(data[1]);
obj.setY(data[2]);
// zapsat zmenu do databaze
Database.objectMove(data[0], data[1], data[2]);
// preposlat zmenu klientum
sendAll(new Message(Message.UPDATE_OBJECT, obj));
break;
}
}
break;
case Message.UPDATE_OBJECT:
MapObject mo_u = (MapObject) msg.getMsg();
// zmenit v databazi
Database.updateObject(mo_u);
// zmenit v seznamu
while (iteratorMapObject.hasNext()) {
if (iteratorMapObject.next().getId() == mo_u.getId()) {
iteratorMapObject.set(mo_u);
break;
}
}
// preposlat zmenu klientum
sendAll(new Message(Message.UPDATE_OBJECT, mo_u));
break;
case Message.DELETE_LOG:
int objId = (int) msg.getMsg();
// vymaže logy v databazi
Database.deleteObjectLog(objId);
// vymaze logy v listu
ListIterator<Event> iterator = Server.events.listIterator();
while (iterator.hasNext()) {
if (iterator.next().getObject() == objId) {
iterator.remove();
break;
}
}
sendAll(new Message(Message.DELETE_LOG, objId));
break;
case Message.USER:
User user = (User) msg.getMsg();
user.setPassword(PasswordHashing.hash(user.getPassword()));
//pridáni do databáze a nastaveni id
user.setId(Database.addUser(user));
// přidání do seznamu
Server.users.add(user);
// odeslat klientum nového uživatele
send(new Message(Message.USER, user));
break;
case Message.USER_EDIT:
User ue = (User) msg.getMsg();
// upraveni v databázi
Database.editUser(ue);
// zmenit v seznamu
ListIterator<User> iteratorUser = Server.users.listIterator();
while (iteratorUser.hasNext()) {
User next = iteratorUser.next();
if (next.getId() == ue.getId()) {
iteratorUser.set(ue);
break;
}
}
// preposlat zmenu klientum
sendAll(new Message(Message.USER_EDIT, ue));
break;
case Message.SERVER_CONFIG:
ServerConfig sc = (ServerConfig) msg.getMsg();
// ulozeni
Server.config.setInt("ping_repeat", sc.getPingRepeat());
Server.config.setInt("ping_attempt", sc.getPingAttempt());
Server.config.setInt("ping_timeout", sc.getPingTimeout());
Server.config.setInt("instability_attempt", sc.getInstabilityAttempt());
Server.config.setInt("instability_limit", sc.getInstabilityLimit());
Server.config.save();
//odeslani vsem
sendAll(Message.SERVER_CONFIG, sc);
break;
default:
LogFile.printErr("Neznamy typ zpravy");
}
}
public void send(Message message) {
currentClient.writeAndFlush(message);
LogFile.printDebug("<- Message type: " + message.getType());
}
public void send(int type, Object obj) {
currentClient.writeAndFlush(new Message(type, obj));
LogFile.printDebug("<- Message type: " + type);
}
public static void sendAll(Message message) {
if (channels.isEmpty()) {
return;
}
channels.writeAndFlush(message);
LogFile.printDebug("<- For all. Message type: " + message.getType());
}
public static void sendAll(int type, Object obj) {
if (channels.isEmpty()) {
return;
}
channels.writeAndFlush(new Message(type, obj));
LogFile.printDebug("<- For all. Message type: " + type);
}
public static final void removeClient(Channel ch) {
// odebrani z připojenych kanalu
channels.remove(ch);
// odebrani ze seznamu klientu
InetSocketAddress socketAddress = (InetSocketAddress) ch.remoteAddress();
String clientIp = socketAddress.getAddress().getHostAddress();
String clientPort = String.valueOf(socketAddress.getPort());
for (OnlineClients oc : Server.onlineClients) {
if (oc.getIp().equals(clientIp) && oc.getPort().equals(clientPort)) {
Server.onlineClients.remove(oc);
System.err.println("Client removed");
break;
}
}
// odeslat vsem novy seznam klientu
sendAll(new Message(Message.ONLINE_CLIENTS, Server.onlineClients));
}
}

View File

@ -1,61 +0,0 @@
package jnet.server.network;
import jnet.lib.LogFile;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
/**
*
* @author cucky
*/
public class NettyServer extends Thread {
private int port;
public NettyServer(int port) {
this.port = port;
}
@Override
public void run() {
// Skupiny pro zpracování I/O operací
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// Vytvoření ServerBootstrap pro nastavení serveru
ServerBootstrap serverBootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
//.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast("decoder", new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(getClass().getClassLoader())));
ch.pipeline().addLast("encoder", new ObjectEncoder());
ch.pipeline().addLast(new ServerHandler()); // Vlastní handler pro zpracování zpráv
}
});
// Bind serveru na specifikovaný port (např. 8080)
Channel channel = serverBootstrap.bind(port).sync().channel();
LogFile.printInfo("Server is ready and listening on port " + port);
// Čekání na ukončení serveru
channel.closeFuture().sync();
} catch (Exception ex) {
LogFile.printErr("Server exception: " + ex);
} finally {
// Uvolnění prostředků
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}

View File

@ -1,40 +0,0 @@
package jnet.server.network;
import jnet.server.ServerMessageParser;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import jnet.lib.LogFile;
import jnet.lib.Message;
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof Message) {
Message m = (Message) msg;
new ServerMessageParser(ctx.channel()).parse((Message) msg);
}
if (msg instanceof String) {
System.out.println("Client message: " + msg);
}
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("Client connected");
Channel currentClient = ctx.channel();
currentClient.writeAndFlush(new Message(Message.CLIENT_VERSION, null));
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
LogFile.printInfo("Client disconnected");
ServerMessageParser.removeClient(ctx.channel());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
ctx.close();
}
}

View File

@ -1,88 +0,0 @@
package jnet.server.network;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLException;
/**
*
* @author cucky
*/
public class ServerSsl extends Thread {
private int port;
public ServerSsl(int port) {
this.port = port;
}
@Override
public void run() {
try {
// Načtení self-signed certifikátu a privátního klíče
//File certChainFile = new File("cert.pem");
//File privateKeyFile = new File("key.pem");
// Vytvoření SSL kontextu
//SslContext sslContext = SslContextBuilder.forServer(certChainFile, privateKeyFile).build();
// Self-signed certifikát pro server
SelfSignedCertificate ssc = new SelfSignedCertificate();
// SSL kontext pro server
SslContext sslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
.trustManager(InsecureTrustManagerFactory.INSTANCE) // Nepožadujeme důvěryhodné klientské certifikáty
.build();
// Skupiny pro zpracování I/O operací
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// Vytvoření ServerBootstrap pro nastavení serveru
ServerBootstrap serverBootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
//.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(sslContext.newHandler(ch.alloc())); // SSL handler
ch.pipeline().addLast(new StringDecoder()); // Dekóduje zprávy přijaté od klienta
ch.pipeline().addLast(new StringEncoder()); // Kóduje zprávy odeslané klientovi
ch.pipeline().addLast(new ServerHandler()); // Vlastní handler pro zpracování zpráv
}
});
// Bind serveru na specifikovaný port (např. 8080)
Channel channel = serverBootstrap.bind(port).sync().channel();
System.out.println("ssl Server is ready and listening on port " + port);
// Čekání na ukončení serveru
channel.closeFuture().sync();
} catch (Exception ex) {
Logger.getLogger(ServerSsl.class.getName()).log(Level.SEVERE, null, ex);
} finally {
// Uvolnění prostředků
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
} catch (SSLException ex) {
Logger.getLogger(ServerSsl.class.getName()).log(Level.SEVERE, null, ex);
} catch (CertificateException ex) {
Logger.getLogger(ServerSsl.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

View File

@ -1,85 +0,0 @@
package jnet.server.probe;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
import jnet.lib.LogFile;
import jnet.lib.Status;
import jnet.lib.object.MapObject;
import jnet.server.Server;
public class NettyPing extends Thread {
private static final HashedWheelTimer TIMER = new HashedWheelTimer(); // Netty časovač
public NettyPing() {
}
@Override
public void run() {
LogFile.printInfo("Ping probe start");
for (MapObject mapObject : Server.mapObject) {
schedulePing(mapObject);
}
}
private static void schedulePing(MapObject object) {
TIMER.newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) {
pingHost(object);
timeout.timer().newTimeout(this, Server.config.getInt("ping_repeat"), TimeUnit.SECONDS); // Opakuje každých x sekund
}
}, 0, TimeUnit.SECONDS);
}
private static void pingHost(MapObject object) {
try {
String command = System.getProperty("os.name").startsWith("Windows")
? "ping -n 1 -w " + String.valueOf((Server.config.getInt("ping_timeout")*1000)) + " " + object.getIp() // Timeout 2000 ms (Windows)
: "ping -c 1 -W " + String.valueOf(Server.config.getInt("ping_timeout")) + " " + object.getIp(); // Timeout 2 sec (Linux)
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
boolean success = false;
int timeMs = -1;
while ((line = reader.readLine()) != null) {
if (line.contains("TTL=") || line.contains("bytes from")) {
success = true;
timeMs = extractTime(line);
}
}
//System.out.println("Ping na " + object.getIp() + (success ? " uspesny! RTT: " + timeMs + " ms" : " selhal!"));
if (success) {
if (object.getStatus() != Status.OK) {
PingResult.stateOnline(object);
}
} else {
PingResult.stateOffline(object);
}
process.waitFor();
} catch (Exception e) {
PingResult.stateOffline(object);
LogFile.printErr("Chyba pri pingu na " + object.getIp() + " " + e.getMessage());
}
}
private static int extractTime(String line) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.contains("time=") || part.contains("čas=")) {
return Integer.parseInt(part.replaceAll("[^0-9]", ""));
}
}
return -1;
}
}

View File

@ -1,136 +0,0 @@
package jnet.server.probe;
import java.io.IOException;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.Status;
import jnet.lib.object.Event;
import jnet.lib.object.MapObject;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.ServerMessageParser;
public class Ping extends Thread {
// Perioda opakování v sekundách
private static final int PERIOD = 3;
// Timeout pro ping (v milisekundách)
private static final int TIMEOUT = 2000;
// pocet pokus pro nastaveni offline statusu
private static final int ATTEMPT = 3;
public Ping() {
}
@Override
public void start() {
init();
}
private void init() {
// ExecutorService pro paralelní provádění pingů
ExecutorService executorService = Executors.newCachedThreadPool();
// ScheduledExecutorService pro periodické provádění
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// Naplánování periodického provádění kontrol
scheduledExecutorService.scheduleAtFixedRate(() -> {
for (MapObject mo : Server.mapObject) {
if (mo.isActive()) {
// Vytvoření úkolu pro pingování každé IP adresy
executorService.submit(() -> {
try {
long responseTime = pingWithResponseTime(mo.getIp());
if (responseTime >= 0) {
isOnline(mo, responseTime);
} else {
isOffline(mo);
}
} catch (Exception e) {
LogFile.printDebug("Chyba pri pingovani " + mo.getIp() + ": " + e.getMessage());
}
});
}
}
}, 0, PERIOD, TimeUnit.SECONDS);
}
// Funkce pro kontrolu dostupnosti IP adresy s timeoutem a zobrazení času odezvy
private static long pingWithResponseTime(String ipAddress) throws IOException, InterruptedException {
InetAddress inet = InetAddress.getByName(ipAddress);
long startTime = System.currentTimeMillis(); // Začátek měření času
boolean reachable = inet.isReachable(TIMEOUT); // Timeout pro ping 5 sekund
long endTime = System.currentTimeMillis(); // Konec měření času
if (reachable) {
return endTime - startTime; // Vrátí dobu odezvy v milisekundách
} else {
return -1; // Pokud není dostupná, vrátí -1
}
}
private void isOnline(MapObject mo, long responseTime) {
// LogFile.printDebug(mo.getName() + "(" + mo.getIp() + ") online, latence: " + responseTime + " ms");
// pokud neni predchozi stav ok odesle novy stav
if (mo.getStatus() != Status.OK) {
// pokud byl predchozi stav offline ukonci event
if (mo.getStatus() == Status.OFFLINE) {
// zapise do logu konec udalosti
Event event = Database.endEvent(mo.getId(), Event.TYPE_PING);
for (int i = 0; i < Server.events.size(); i++) {
if (Server.events.get(i).getId() == event.getId()) {
Server.events.set(i, event);
ServerMessageParser.sendAll(new Message(Message.EVENT_UPDATE, (Event) event));
break;
}
}
// vynuluje počet pokusu o ping
mo.setPingAttemp(0);
// nastavi a odesle stav
setNewState(mo, Status.OK);
}
// pokud byl predchozi stav N/A
if (mo.getStatus() == Status.NA) {
// nastavi a odesle stav
setNewState(mo, Status.OK);
}
}
}
private void setNewState(MapObject mo, int state) {
mo.setStatus(state);
// odesle stav
int[] o = {mo.getId(), state};
ServerMessageParser.sendAll(new Message(Message.STATUS_UPDATE, o));
}
private void isOffline(MapObject mo) {
// zvysi pocet jiz probehlích pokusu o ping
mo.pingAttemp++;
// vyhodnoti
if (mo.getStatus() != Status.OFFLINE && mo.getPingAttemp() >= ATTEMPT) {
int[] o = {mo.getId(), Status.OFFLINE};
// nastavi objektu status
mo.setStatus(Status.OFFLINE);
// zapise do logu
// zapise do databaze
Event event = Database.addEvent(mo.getId(), "offline", Event.TYPE_PING);
Server.events.add(event);
//odesle stav a event klientum
ServerMessageParser.sendAll(new Message(Message.STATUS_UPDATE, o));
ServerMessageParser.sendAll(new Message(Message.EVENT_NEW, event));
}
}
}

View File

@ -1,66 +0,0 @@
package jnet.server.probe;
import jnet.lib.Message;
import jnet.lib.Status;
import jnet.lib.object.Event;
import jnet.lib.object.MapObject;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.ServerMessageParser;
public class PingResult {
private static final int POKUS = Server.config.getInt("ping_attempt");
public static void stateOnline(MapObject obj) {
// oveří jestli neni zarizeni vypnuto
if (obj.isActive() && obj.getStatus() != Status.OK) {
// vynuluje ping pokusy
obj.setPingAttemp(0);
// pokud byl předchozí stav offline ukončí event
if (obj.getStatus() == Status.OFFLINE) {
// aktualizace eventu
Event event = Database.endEvent(obj.getId(), Event.TYPE_PING);
for (int i = 0; i < Server.events.size(); i++) {
if (Server.events.get(i).getId() == event.getId()) {
Server.events.set(i, event);
}
}
// odeslani aktualizovaného eventu
ServerMessageParser.sendAll(Message.EVENT_UPDATE, event);
}
// nastavi status objektu
obj.setStatus(Status.OK);
// odesle informaci o novem stavu klientum
sendState(obj.getId(), Status.OK);
}
}
public static void stateOffline(MapObject obj) {
// oveří jestli neni zarizeni vypnuto
if (obj.isActive()) {
if (obj.getPingAttemp() >= POKUS && obj.getStatus() != Status.OFFLINE) {
System.err.println("objekt: " + obj.getName() + " pokus: " + obj.getPingAttemp());
// nastavi status objektu
obj.setStatus(Status.OFFLINE);
// odesle informaci o novem stavu klientum
sendState(obj.getId(), Status.OFFLINE);
// pridáni eventu
Event event = Database.addEvent(obj.getId(), "Offline", Event.TYPE_PING);
Server.events.add(event);
// Odeslani eventu klientum
ServerMessageParser.sendAll(new Message(Message.EVENT_NEW, event));
} else {
obj.pingAttemp++;
}
}
}
private static void sendState(int object, int state) {
int[] o = {object, state};
ServerMessageParser.sendAll(new Message(Message.STATUS_UPDATE, o));
}
}

View File

@ -0,0 +1,278 @@
package jnet.server;
import jnet.server.dao.SnmpDao;
import jnet.lib.LogFile;
import jnet.lib.object.*;
import jnet.server.dao.*;
import java.util.ArrayList;
import java.util.List;
/**
* Fasádní wrapper, který zachovává původní statické rozhraní třídy Database.
* Všechny metody delegují na odpovídající DAO instance.
*/
public final class Database {
private static final UserDao userDao = new UserDao();
private static final SiteDao siteDao = new SiteDao();
private static final NodeDao nodeDao = new NodeDao();
private static final EventDao eventDao = new EventDao();
private static final SnmpDao snmpDao = new SnmpDao();
private static final ObjectTypeDao objectTypeDao = new ObjectTypeDao();
private static final ConnectionDao connectionDao = new ConnectionDao();
private static final ProbeDao probeDao = new ProbeDao();
// Veřejný konstruktor pro případy, kdy je v kódu voláno new Database()
public Database() {}
///
/// -------- inicializace --------
///
public static void connect(String host, String port, String database, String user, String password) {
ConnectionManager.init(host, port, database, user, password);
}
///
/// -------- User --------
///
public static boolean verifyUser(String username, String password) {
return userDao.verifyUser(username, password);
}
public static User getUserInfo(String username) {
return userDao.getUserInfo(username);
}
public static ArrayList<User> getUsers() {
return new ArrayList<>(userDao.getUsers());
}
public static int addUser(User user) {
return userDao.addUser(user);
}
public static void editUser(User u) {
userDao.editUser(u);
}
public static void deleteUser(int userId) {
userDao.deleteUser(userId);
}
///
/// -------- ObjectType --------
///
public static ArrayList<DeviceType> getObjectType() {
return new ArrayList<>(objectTypeDao.getObjectTypes());
}
public static int addObjectType(DeviceType ot) {
return objectTypeDao.addObjectType(ot);
}
public static void deleteDeviceType(int id) {
objectTypeDao.deleteDeviceType(id);
}
///
/// -------- Site --------
///
public static ArrayList<Site> getSiteList() {
return new ArrayList<>(siteDao.getSiteList());
}
public static int addSite(String name) {
return siteDao.addSite(name);
}
public static void removeSite(int id) {
siteDao.removeSite(id);
}
public static void setSiteLock(boolean state, int map) {
siteDao.setSiteLock(state, map);
}
///
/// -------- Node --------
///
public static ArrayList<Node> getNodeList(int siteId) {
return new ArrayList<>(nodeDao.getNodesForSite(siteId));
}
public static int addNode(Node mo) {
return nodeDao.addNode(mo);
}
public static void removeNode(int id) {
nodeDao.removeNode(id);
}
public static void nodeUpdatePosition(int nodeId, int x, int y) {
nodeDao.updatePosition(nodeId, x, y);
}
public static void editNode(Node node) {
nodeDao.updateNode(node);
}
///
/// -------- NodeConnection (spojení) --------
///
public static List<NodeConnection> getNodeConnectionList(int nodeId) {
return connectionDao.getConnectionsForNode(nodeId);
}
public static List<NodeConnection> getSiteConnectionList(int siteId) {
return connectionDao.getConnectionsForSite(siteId);
}
public static int addNodeConnection(NodeConnection nc) {
return connectionDao.addConnection(nc);
}
public static void removeNodeConnection(int id) {
connectionDao.removeNodeConnection(id);
}
public static void editNodeconnection(NodeConnection connection) {
connectionDao.editNodeconnection(connection);
}
public static void deteleConnectionAfterNodeMove(int id) {
connectionDao.deteleConnectionAfterNodeMove(id);
}
///
/// -------- Event --------
///
public static long insertEvent(int nodeId, int status, long time) {
return eventDao.insertEvent(nodeId, status, time);
}
public static void endEvent(long eventId, long time) {
eventDao.endEvent(eventId, time);
}
public static List<Event> getAllEvents() {
return eventDao.getAllEvents();
}
///
/// -------- SNMP --------
///
public static List<SnmpProfile> getSnmpProfile() {
return snmpDao.getAllProfile();
}
public static int addSnmpProfile(SnmpProfile profile) {
return snmpDao.addSnmpProfile(profile);
}
public static void editSnmpProfile(SnmpProfile profile) {
snmpDao.editSnmpProfile(profile);
}
public static void removeSnmpProfile(int id){
snmpDao.removeSnmpProfile(id);
}
public static List<SnmpTemplate> getSnmpTemplate(){
return snmpDao.getSnmpTemplate();
}
public static List<SnmpValueMap> getSnmpValueMapList() {
return snmpDao.getSnmpValueMapList();
}
public static int addSnmpTemplate(SnmpTemplate template) {
return snmpDao.addSnmpTemplate(template);
}
public static void editSnmpTemplate(SnmpTemplate template) {
snmpDao.editSnmpTemplate(template);
}
public static void deleteSnmpTemplate(int id) {
snmpDao.deleteSnmpTemplate(id);
}
public static int addSnmpValueMap(String name) {
return snmpDao.addSnmpValueMap(name);
}
public static int addSnmpValueMapItem(int map_id, String raw_value, String mapedValue) {
return snmpDao.addSnmpValueMapItem(map_id, raw_value, mapedValue);
}
public static void deleteSnmpValueMap(int id) {
snmpDao.deleteSnmpValueMap(id);
}
public static void editSnmpValueMap(SnmpValueMap valueMap) {
snmpDao.editSnmpValueMap(valueMap);
}
public static void deleteSnmpValueMapItem(int id) {
snmpDao.deleteSnmpValueMapItem(id);
}
public static void editSnmpValueMapItem(int map_id, String raw_value, String mapedValue) {
snmpDao.editSnmpValueMapItem(map_id, raw_value, mapedValue);
}
///
/// -------- probe --------
///
public static int addNodeProbe(NodeProbe probe) {
return probeDao.addNodeProbe(probe);
}
public static void removeNodeProbe(int id) {
probeDao.removeNodeProbe(id);
}
public static void editNodeProbe(NodeProbe probe) {
probeDao.editNodeProbe(probe);
}
// -------- zachování zastaralých metod pro kompatibilitu --------
@Deprecated
public static void query(String sqlQuery) {
try {
siteDao.executeUpdate(sqlQuery); // používáme existující DAO instanci
} catch (Exception e) {
LogFile.printErr("MySQL exception: " + e.getMessage());
}
}
@Deprecated
public static int insert(String sqlQuery) {
return siteDao.insertAndGetId(sqlQuery);
}
@Deprecated
public static void update(String sql) {
try {
siteDao.executeUpdate(sql);
} catch (Exception e) {
LogFile.printErr("MySQL exception: " + e.getMessage() + " SQL: " + sql);
}
}
@Deprecated
static boolean remove(String table, int id) {
return siteDao.deleteById(table, id);
}
}

View File

@ -0,0 +1,40 @@
package jnet.server;
import jnet.lib.LogFile;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.output.MigrateResult;
public class DatabaseMigrator {
public static void migrate(String jdbcUrl, String username, String password) {
Flyway flyway = Flyway.configure()
.dataSource(jdbcUrl, username, password)
.locations("classpath:db/migration", "filesystem:db/migration")
.load();
// Kontrola, zda je vše v pořádku
flyway.validate();
// Provedení migrací
MigrateResult migrationsApplied = flyway.migrate();
}
static void migrate(String host, String port, String database, String username, String password) {
String jdbcUrl = "jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false&serverTimezone=UTC";
Flyway flyway = Flyway.configure()
.dataSource(jdbcUrl, username, password)
.locations("classpath:db/migration", "filesystem:db/migration")
.ignoreMigrationPatterns("*:pending")
.load();
// Kontrola, zda je vše v pořádku
flyway.validate();
// Provedení migrací
MigrateResult migrationsApplied = flyway.migrate();
int successfully = migrationsApplied.getSuccessfulMigrations().size();
int failed = migrationsApplied.getFailedMigrations().size();
LogFile.printInfo(" Number of migrations performed: " + successfully);
}
}

View File

@ -0,0 +1,49 @@
package jnet.server;
import java.util.HashMap;
import java.util.Map;
import jnet.lib.Message;
import jnet.lib.Status;
import jnet.lib.object.Event;
import jnet.server.networkserver.NettyServerManager;
import jnet.server.networkserver.ServerHandler;
public class EventManager {
private static final Map<Integer, Long> openEventIds = new HashMap<>();
static public void insertOfflineEvent(int nodeId) {
long now = System.currentTimeMillis();
long eventId = Database.insertEvent(nodeId, Status.OFFLINE, now);
if (eventId > 0) {
openEventIds.put(nodeId, eventId);
Event e = new Event(eventId, nodeId, Status.OFFLINE, now);
Server.events.add(e);
ServerHandler.sendAll(new Message(Message.EVENT_NEW, e));
}
}
static public void endEvent(int nodeId) {
Long eventId = openEventIds.get(nodeId);
if (eventId != null) {
long now = System.currentTimeMillis();
Database.endEvent(eventId, now);
openEventIds.remove(nodeId);
for (Event event : Server.events) {
if (event.getId() == eventId) {
event.setEnd(now);
ServerHandler.sendAll(new Message(Message.EVENT_UPDATE, event));
break;
}
}
}
}
}

View File

@ -0,0 +1,168 @@
package jnet.server;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import jnet.lib.ApacheConfig;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import jnet.lib.BuilddDate;
import jnet.lib.LogFile;
import jnet.lib.object.DeviceType;
import jnet.lib.object.Event;
import jnet.lib.object.OnlineClients;
import jnet.lib.object.Site;
import jnet.lib.object.SnmpProfile;
import jnet.lib.object.User;
import jnet.server.networkserver.NettyServerManager;
import jnet.server.probe.Ping;
import jnet.server.trafficmonitor.SnmpMonitorService;
import jnet.lib.object.SnmpTemplate;
import jnet.lib.object.SnmpValueMap;
import jnet.server.probe.snmp.SnmpBatchProcessor;
import jnet.server.probe.snmp.NodeProbeManager;
public class Server {
// verze serveru
public static final int VERSION = 3;
// minimální verze klienta
public static final int MINIMAL_CLIENT_VERSION = 1;
public static Configuration config;
public static Database database;
public static SnmpMonitorService trafficMonitorService;
public static NodeProbeManager snmpProbeManager;
public static List<OnlineClients> onlineClients = new ArrayList<>();
public static List<Site> site = new ArrayList<>();
public static List<DeviceType> devicType = new ArrayList<>();
public static List<SnmpProfile> snmpProfile = new ArrayList<>();
public static List<User> users = new ArrayList<>();
public static List<Event> events = new ArrayList<>();
public static List<SnmpTemplate> snmpTemplate = new ArrayList<>();
public static List<SnmpValueMap> snmpValueMap = new ArrayList<>();
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Prague"));
LogFile.clear();
LogFile.setDebug(false);
LogFile.printInfo("---------------------------------------------");
LogFile.printInfo(" jNet Server ");
LogFile.printInfo(" Version: " + VERSION + " (" + BuilddDate.get() + ")");
LogFile.printInfo("---------------------------------------------");
LogFile.printInfo("");
// Nahrani konfigurace
LogFile.printInfo("Loading config ...");
try {
config = ApacheConfig.loadProperties();
LogFile.printInfo(" successfully");
} catch (ConfigurationException ex) {
LogFile.printInfo(" fail: " + ex.getMessage());
System.exit(1);
}
// Debug mode
if (config.getBoolean("debug")) {
LogFile.setDebug(true);
LogFile.printDebug("Debug mode on");
}
// migrace databáze
LogFile.printInfo("Ugrade database ...");
DatabaseMigrator.migrate(
config.getString("mysql_server"),
config.getString("mysql_port"),
config.getString("mysql_database"),
config.getString("mysql_user"),
config.getString("mysql_password")
);
// Pripojeni k databazi
database = new Database();
database.connect(
config.getString("mysql_server"),
config.getString("mysql_port"),
config.getString("mysql_database"),
config.getString("mysql_user"),
config.getString("mysql_password")
);
// nacteni uzivatelu
LogFile.printInfo("Loading user list ...");
users = Database.getUsers();
LogFile.printInfo(" load " + users.size() + " user(s)");
// nacteni node icon
LogFile.printInfo("Loading node icon ...");
devicType = Database.getObjectType();
LogFile.printInfo(" load " + devicType.size() + " icon(s)");
// nacteni map a objektu z databaze
LogFile.printInfo("Loading map and object list ...");
site = Database.getSiteList();
LogFile.printInfo(" load " + site.size() + " maps");
// nacteni logu
LogFile.printInfo("Loading events list ...");
events = Database.getAllEvents();
LogFile.printInfo(" load " + events.size() + " events");
// nacteni SNMP profilu
LogFile.printInfo("Loading SNMP profile list ...");
snmpProfile = Database.getSnmpProfile();
LogFile.printInfo(" load " + snmpProfile.size() + " profile(s)");
// nacteni SNMP sablon
LogFile.printInfo("Loading SNMP template list ...");
snmpTemplate = Database.getSnmpTemplate();
LogFile.printInfo(" load " + snmpTemplate.size() + " templates(s)");
// nacteni SNMP sablon -value map
LogFile.printInfo("Loading SNMP template value map list ...");
snmpValueMap = Database.getSnmpValueMapList();
LogFile.printInfo(" load " + snmpValueMap.size() + " value map(s)");
// ============================================================
// 🆕 SPUŠTĚNÍ traffic SNMP MONITORU
// ============================================================
// Spustíme SNMP monitoring s intervalem z configu (např. 30 sekund)
int snmpInterval = config.getInt("traffic_interval", 30) * 1000; // default 30s
int batchInterval = config.getInt("traffic_batch_interval", 2) * 1000;
trafficMonitorService.start(snmpInterval, batchInterval);
// ============================================================
// Vytvoření SnmpProbeManager
snmpProbeManager = new NodeProbeManager();
// Vytvoření batch processoru s intervalem 5 sekund (lze z configu)
int batchSeconds = config.getInt("probe_batch_interval", 5);
SnmpBatchProcessor batchProcessor = new SnmpBatchProcessor(batchSeconds);
batchProcessor.init(snmpProbeManager); // zaregistruje se a spustí scheduler
// spustěni ping probe
Ping.start();
// Netty server vlákna
NettyServerManager nettyServer = new NettyServerManager();
nettyServer.start(config.getInt("server_port", 8443));
// Shutdown hook pro případ vypnutí z OS (Ctrl+C, kill/SIGTERM)
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
LogFile.printInfo("Shutdown signal received...");
// 🆕 Zastavení SNMP monitoru
trafficMonitorService.stop();
snmpProbeManager.close();
nettyServer.stop();
}));
}
}

View File

@ -0,0 +1,25 @@
package jnet.server;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.NodeState;
import jnet.lib.object.Site;
import jnet.server.networkserver.ServerHandler;
public class SiteOperation {
public static void updateNodeStatus(NodeState ns){
// zmení status v seznamu
for (Site site : Server.site) {
for (Node node : site.getNode()) {
if (node.getId() == ns.getId()) {
node.setStatus(ns.getState());
break; // ID je unikátní, po nalezení končíme
}
}
}
ServerHandler.sendAll(new Message(Message.NODE_STATUS_CHANGE, ns));
}
}

View File

@ -0,0 +1,102 @@
package jnet.server.dao;
import jnet.lib.LogFile;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractDao {
protected Connection getConnection() throws SQLException {
return ConnectionManager.getConnection();
}
// -------- veřejné helpery pro všechny potomky i fasádu --------
public int insertAndGetId(String sql, Object... params) {
try (PreparedStatement pstmt = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
setParameters(pstmt, params);
//System.err.println(pstmt.toString());
pstmt.executeUpdate();
try (ResultSet rs = pstmt.getGeneratedKeys()) {
if (rs.next()) {
return rs.getInt(1);
}
}
} catch (SQLException e) {
LogFile.printErr("Insert failed: " + e.getMessage() + " SQL: " + sql);
}
return -1;
}
public boolean deleteById(String table, int id) {
String sql = "DELETE FROM " + table + " WHERE id = ?";
try (PreparedStatement pstmt = getConnection().prepareStatement(sql)) {
pstmt.setInt(1, id);
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
LogFile.printErr("Delete failed: " + e.getMessage());
return false;
}
}
public void executeUpdate(String sql, Object... params) throws SQLException {
try (PreparedStatement pstmt = getConnection().prepareStatement(sql)) {
setParameters(pstmt, params);
pstmt.executeUpdate();
}
}
public boolean deleteConnectionsByNodeId(String table, int nodeId) {
String sql = "DELETE FROM " + table + " WHERE nodeFrom = ? OR nodeTo = ?";
try (PreparedStatement pstmt = getConnection().prepareStatement(sql)) {
pstmt.setInt(1, nodeId);
pstmt.setInt(2, nodeId);
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
LogFile.printErr("Delete connections failed: " + e.getMessage());
return false;
}
}
// -------- chráněné helpery pro query (zůstávají protected) --------
protected <T> T querySingle(String sql, ResultSetMapper<T> mapper, Object... params) {
try (PreparedStatement pstmt = getConnection().prepareStatement(sql)) {
setParameters(pstmt, params);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
return mapper.map(rs);
}
}
} catch (SQLException e) {
LogFile.printErr("Query failed: " + e.getMessage());
}
return null;
}
protected <T> List<T> queryList(String sql, ResultSetMapper<T> mapper, Object... params) {
List<T> list = new ArrayList<>();
try (PreparedStatement pstmt = getConnection().prepareStatement(sql)) {
setParameters(pstmt, params);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
list.add(mapper.map(rs));
}
}
} catch (SQLException e) {
LogFile.printErr("Query failed: " + e.getMessage());
}
return list;
}
private void setParameters(PreparedStatement pstmt, Object... params) throws SQLException {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
@FunctionalInterface
protected interface ResultSetMapper<T> {
T map(ResultSet rs) throws SQLException;
}
}

View File

@ -0,0 +1,165 @@
package jnet.server.dao;
import java.sql.SQLException;
import jnet.lib.object.NodeConnection;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jnet.lib.LogFile;
import jnet.lib.object.Node;
public class ConnectionDao extends AbstractDao {
public static final String TABLE = "connection";
/**
* Pro daný seznam uzlů vrátí všechna jejich spojení (bez duplicit).
*/
public List<NodeConnection> getConnectionsForNodes(List<Node> nodes) {
return getUniqueConnectionsForNodes(nodes);
}
/**
* Vrátí všechna spojení, do kterých daný uzel vstupuje nebo z nich
* vystupuje.
*/
public List<NodeConnection> getConnectionsForNode(int nodeId) {
String sql = "SELECT DISTINCT * FROM " + TABLE + " WHERE nodeFrom = ? OR nodeTo = ?";
return queryList(sql, rs -> new NodeConnection(
rs.getInt("id"),
rs.getInt("siteId"),
rs.getInt("nodeFrom"),
rs.getInt("nodeTo"),
rs.getInt("typeConnection"),
rs.getBoolean("readTraffic"),
rs.getInt("trafficNode"),
rs.getInt("trafficIface")
), nodeId, nodeId);
}
/**
* Vrátí všechna spojení, která mají alespoň jeden konec v seznamu uzlů.
* Používá se pro efektivní načtení všech spojení na mapě najednou.
*/
public List<NodeConnection> getConnectionsForNodeList(List<Integer> nodeIds) {
if (nodeIds == null || nodeIds.isEmpty()) {
return new ArrayList<>();
}
// Sestavíme dynamický IN dotaz
StringBuilder sql = new StringBuilder("SELECT DISTINCT * FROM " + TABLE + " WHERE nodeFrom IN (");
for (int i = 0; i < nodeIds.size(); i++) {
sql.append("?");
if (i < nodeIds.size() - 1) {
sql.append(",");
}
}
sql.append(") OR nodeTo IN (");
for (int i = 0; i < nodeIds.size(); i++) {
sql.append("?");
if (i < nodeIds.size() - 1) {
sql.append(",");
}
}
sql.append(")");
// Parametry: dvakrát stejný seznam
List<Object> params = new ArrayList<>();
params.addAll(nodeIds);
params.addAll(nodeIds);
return queryList(sql.toString(), rs -> new NodeConnection(
rs.getInt("id"),
rs.getInt("siteId"),
rs.getInt("nodeFrom"),
rs.getInt("nodeTo"),
rs.getInt("typeConnection"),
rs.getBoolean("readTraffic"),
rs.getInt("trafficNode"),
rs.getInt("trafficIface")
), params.toArray());
}
/**
* Vrátí unikátní spojení pro daný seznam uzlů podle node ID (bez duplicit).
*/
public List<NodeConnection> getUniqueConnectionsForNodes(List<Node> nodes) {
List<Integer> ids = new ArrayList<>();
for (Node n : nodes) {
ids.add(n.getId());
}
List<NodeConnection> all = getConnectionsForNodeList(ids);
// odstranění duplicit podle id
Set<Integer> seen = new HashSet<>();
List<NodeConnection> unique = new ArrayList<>();
for (NodeConnection nc : all) {
if (seen.add(nc.getId())) {
unique.add(nc);
}
}
return unique;
}
public int addConnection(NodeConnection nc) {
String sql = "INSERT INTO " + TABLE + " (siteId, nodeFrom, nodeTo, typeConnection, readTraffic, trafficNode, trafficIface) "
+ "VALUES (?,?,?,?,?,?,?)";
return insertAndGetId(sql,
nc.getSite(),
nc.getNodeFrom(),
nc.getNodeTo(),
nc.getType(),
(nc.isReadTraffic() ? 1:0),
nc.getTrafficNode(),
nc.getTrafficIface()
);
}
/**
* Vrátí unikátní spojení pro danou site
*/
public List<NodeConnection> getConnectionsForSite(int siteId) {
String sql = "SELECT * FROM " + TABLE + " WHERE siteId = ?";
return queryList(sql, rs -> new NodeConnection(
rs.getInt("id"),
rs.getInt("siteId"),
rs.getInt("nodeFrom"),
rs.getInt("nodeTo"),
rs.getInt("typeConnection"),
rs.getBoolean("readTraffic"),
rs.getInt("trafficNode"),
rs.getInt("trafficIface")
), siteId);
}
public void removeNodeConnection(int id) {
if (deleteById(TABLE, id)) {
LogFile.printInfo("Node connection ID " + id + " removed from database");
} else {
LogFile.printErr("Node connection ID " + id + " not removed from database");
}
}
public void editNodeconnection(NodeConnection connection) {
try {
executeUpdate(
"UPDATE " + TABLE + " SET typeConnection=?, readTraffic=?, trafficNode=?, trafficIface=? WHERE id=?",
connection.getType(),
(connection.isReadTraffic() ? 1:0),
connection.getTrafficNode(),
connection.getTrafficIface(),
connection.getId() // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci connection: " + e.getMessage());
}
}
public void deteleConnectionAfterNodeMove(int id) {
if (deleteConnectionsByNodeId(TABLE, id)) {
LogFile.printInfo("Node connection ID " + id + " removed from database");
} else {
LogFile.printErr("Node connection ID " + id + " not removed from database");
}
}
}

View File

@ -0,0 +1,57 @@
package jnet.server.dao;
import jnet.lib.LogFile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public final class ConnectionManager {
private static final int VALIDATION_TIMEOUT = 2;
private static String host;
private static String port;
private static String database;
private static String user;
private static String password;
private static Connection connection = null;
private ConnectionManager() {}
public static void init(String host, String port, String database, String user, String password) {
ConnectionManager.host = host;
ConnectionManager.port = port;
ConnectionManager.database = database;
ConnectionManager.user = user;
ConnectionManager.password = password;
connection = createConnection();
}
private static Connection createConnection() {
try {
String url = String.format(
"jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Europe/Prague",
host, port, database
);
LogFile.printInfo("Connecting to database ...");
Connection conn = DriverManager.getConnection(url, user, password);
LogFile.printInfo(" successfully");
return conn;
} catch (SQLException ex) {
LogFile.printErr("MySQL connection exception: " + ex.getMessage());
System.exit(1);
return null;
}
}
/**
* Vrátí platné spojení – pokud je staré uzavřené (timeout), automaticky ho obnoví.
*/
public static Connection getConnection() throws SQLException {
if (connection == null || !connection.isValid(VALIDATION_TIMEOUT)) {
LogFile.printInfo("Database connection lost, reconnecting...");
connection = createConnection();
}
return connection;
}
}

View File

@ -0,0 +1,42 @@
package jnet.server.dao;
import jnet.lib.LogFile;
import jnet.lib.object.Event;
import java.sql.Timestamp;
import java.util.List;
public class EventDao extends AbstractDao {
public static final String TABLE = "events";
public long insertEvent(int nodeId, int status, long time) {
String sql = "INSERT INTO " + TABLE + " (node, status, start) VALUES (?, ?, ?)";
return insertAndGetId(sql, nodeId, status, new Timestamp(time));
}
public void endEvent(long eventId, long time) {
try {
executeUpdate("UPDATE events SET end = ? WHERE id = ?", new Timestamp(time), eventId);
} catch (Exception e) {
LogFile.printErr("MySQL exception: " + e.getMessage());
}
}
public List<Event> getAllEvents() {
String sql = "SELECT * FROM " + TABLE;
return queryList(sql, rs -> {
Timestamp start = rs.getTimestamp("start");
Timestamp end = rs.getTimestamp("end");
long startMillis = start.getTime();
Long endMillis = (end != null) ? end.getTime() : 0L;
return new Event(
rs.getLong("id"),
rs.getInt("node"),
rs.getInt("status"),
startMillis,
endMillis,
rs.getInt("duration")
);
});
}
}

View File

@ -0,0 +1,127 @@
package jnet.server.dao;
import jnet.lib.LogFile;
import jnet.lib.Status;
import jnet.lib.object.Node;
import jnet.lib.object.NodeProbe;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
public class NodeDao extends AbstractDao {
public static final String TABLE = "node";
public List<Node> getNodesForSite(int siteId) {
String sql = "SELECT * FROM " + TABLE + " WHERE siteId = ?";
return queryList(sql, this::mapNode, siteId);
}
public int addNode(Node node) {
String sql = "INSERT INTO " + TABLE + " (name, ip, x, y, type, siteId, icon, ping, user, password, "
+ "description, location, snmpProfile, winbox, winboxPort, ssh, sshPort, web, "
+ "webPort, webVerze, telnet, telnetPort, sms, smsPort, smsVerze) "
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
return insertAndGetId(sql,
node.getName(), node.getIp(), node.getX(), node.getY(),
node.getType(), node.getSiteId(), node.getIcon(), node.isPing(),
node.getUser(), node.getPassword(), node.getDescription(),
node.getLocation(), node.getSnmpProfile(),
node.isWinbox(), node.getWinboxPort(),
node.isSsh(), node.getSshPort(),
node.isWeb(), node.getWebPort(), node.getWebVerze(),
node.isTelnet(), node.getTelnetPort(),
node.isSms(), node.getSmsPort(), node.getSmsVerze()
);
}
public void removeNode(int id) {
if (deleteById(TABLE, id)) {
LogFile.printInfo("Node ID " + id + " removed from database");
} else {
LogFile.printErr("Node ID " + id + " not removed from database");
}
}
public void updatePosition(int nodeId, int x, int y) {
try {
executeUpdate("UPDATE " + TABLE + " SET x = ?, y = ? WHERE id = ?", x, y, nodeId);
} catch (SQLException e) {
LogFile.printErr("MySQL exception: " + e.getMessage());
}
}
private Node mapNode(ResultSet rs) throws SQLException {
return new Node(
rs.getInt("id"),
rs.getString("name"),
rs.getInt("siteId"),
rs.getInt("x"),
rs.getInt("y"),
rs.getInt("type"),
rs.getInt("icon"),
rs.getString("ip"),
rs.getString("user"),
rs.getString("password"),
rs.getString("description"),
rs.getString("location"),
rs.getInt("snmpProfile"),
Status.NA,
rs.getBoolean("ping"),
rs.getInt("winbox") == 1,
rs.getString("winboxPort"),
rs.getInt("ssh") == 1,
rs.getString("sshPort"),
rs.getInt("web") == 1,
rs.getString("webPort"),
rs.getInt("webVerze"),
rs.getInt("telnet") == 1,
rs.getString("telnetPort"),
rs.getInt("sms") == 1,
rs.getString("smsPort"),
rs.getInt("smsVerze"),
rs.getInt("siteLink"),
new ProbeDao().getNodeProbe(rs.getInt("id"))
);
}
public void updateNode(Node node) {
try {
executeUpdate(
"UPDATE " + TABLE + " SET name=?, siteId=?, type=?, x=?, y=?, ip=?, ping=?, icon=?, user=?, password=?, description=?, location=?, snmpProfile=?, winbox=?, winboxPort=?, ssh=?, sshPort=?, web=?, webPort=?, webVerze=?, telnet=?, telnetPort=?, sms=?, smsPort=?, smsVerze=?, siteLink=? WHERE id=?",
node.getName(),
node.getSiteId(),
node.getType(),
node.getX(),
node.getY(),
node.getIp(),
(node.isPing() ? 1 : 0),
node.getIcon(), // může být null
node.getUser(),
node.getPassword(),
node.getDescription(), // může být null
node.getLocation(), // může být null
node.getSnmpProfile(), // může být null
(node.isWinbox() ? 1 : 0), // může být null
node.getWinboxPort(), // může být null
(node.isSsh() ? 1 : 0), // může být null
node.getSshPort(), // může být null
(node.isWeb() ? 1 : 0), // může být null
node.getWebPort(), // může být null
node.getWebVerze(), // může být null
(node.isTelnet() ? 1 : 0), // může být null
node.getTelnetPort(), // může být null
(node.isSms() ? 1 : 0), // může být null
node.getSmsPort(), // může být null
node.getSmsVerze(), // může být null
node.getSiteLink(), // může být null
node.getId() // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci uzlu: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,32 @@
package jnet.server.dao;
import jnet.lib.object.DeviceType;
import java.util.List;
import jnet.lib.LogFile;
public class ObjectTypeDao extends AbstractDao {
public static final String TABLE = "objectType";
public List<DeviceType> getObjectTypes() {
String sql = "SELECT * FROM " + TABLE;
return queryList(sql, rs -> new DeviceType(
rs.getInt("id"),
rs.getString("name"),
rs.getString("image")
));
}
public int addObjectType(DeviceType ot) {
String sql = "INSERT INTO " + TABLE + " (name, image) VALUES (?, ?)";
return insertAndGetId(sql, ot.getName(), ot.getImgStr());
}
public void deleteDeviceType(int id) {
if (deleteById(TABLE, id)) {
LogFile.printInfo("Device type ID " + id + " removed from database");
} else {
LogFile.printErr("Device type ID " + id + " not removed from database");
}
}
}

View File

@ -0,0 +1,80 @@
package jnet.server.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import jnet.lib.LogFile;
import jnet.lib.object.NodeProbe;
public class ProbeDao extends AbstractDao {
public static final String TABLE = "nodeProbe";
public List<NodeProbe> getNodeProbe(int nodeId) {
String sql = "SELECT * FROM " + TABLE + " WHERE node_id = ?";
return queryList(sql, this::mapNodeProbe, nodeId);
}
private NodeProbe mapNodeProbe(ResultSet rs) throws SQLException {
return new NodeProbe(rs.getInt("id"),
rs.getString("name"),
rs.getString("oid"),
rs.getInt("snmp_data_type"),
rs.getString("conversion_type"),
rs.getDouble("conversion_value"),
rs.getString("conversion_expression"),
rs.getString("unit"),
rs.getInt("value_map_id"),
rs.getInt("interval_time"),
(rs.getInt("view_on_map") == 1 ? true:false)
);
}
public void removeNodeProbe(int id) {
if (deleteById(TABLE, id)) {
LogFile.printInfo("Node probe ID " + id + " removed from database");
} else {
LogFile.printErr("Node probe ID " + id + " not removed from database");
}
}
public void editNodeProbe(NodeProbe probe) {
try {
executeUpdate(
"UPDATE " + TABLE + " SET name=?, oid=?, snmp_data_type=?, conversion_type=?, conversion_value=?, conversion_expression=?, value_map_id=?, unit=?, interval_time=?, view_on_map=? WHERE id=?",
probe.getName(),
probe.getOid(),
probe.getDataType(),
probe.getConversionType(),
probe.getConversionValue(),
probe.getConversionExpression(),
probe.getValueMap(),
probe.getUnit(),
probe.getInterval(),
(probe.isViewOnMap() ? 1:0),
probe.getId() // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci uzlu: " + e.getMessage());
}
}
public int addNodeProbe(NodeProbe probe) {
String sql = "INSERT INTO " + TABLE + " (name, node_id, oid, snmp_data_type, conversion_type, conversion_value, conversion_expression, value_map_id, unit, interval_time, view_on_map) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
return insertAndGetId(
sql,
probe.getName(),
probe.getNodeId(),
probe.getOid(),
probe.getDataType(),
probe.getConversionType(),
probe.getConversionValue(),
probe.getConversionExpression(),
probe.getValueMap(),
probe.getUnit(),
probe.getInterval(),
(probe.isViewOnMap() ? 1 : 0)
);
}
}

View File

@ -0,0 +1,49 @@
package jnet.server.dao;
import java.sql.SQLException;
import jnet.lib.LogFile;
import jnet.lib.object.Node;
import jnet.lib.object.NodeConnection;
import jnet.lib.object.Site;
import java.util.List;
public class SiteDao extends AbstractDao {
public static final String TABLE = "site";
public List<Site> getSiteList() {
String sql = "SELECT * FROM " + TABLE;
return queryList(sql, rs -> {
int siteId = rs.getInt("id");
List<Node> nodes = new NodeDao().getNodesForSite(siteId);
List<NodeConnection> connections = new ConnectionDao().getConnectionsForSite(siteId);
return new Site(
siteId,
rs.getString("name"),
rs.getBoolean("locked"),
nodes,
connections
);
});
}
public int addSite(String name) {
return insertAndGetId("INSERT INTO " + TABLE + " (name) VALUES (?)", name);
}
public void removeSite(int id) {
if (deleteById("site", id)) {
LogFile.printInfo("Site ID " + id + " removed from database");
} else {
LogFile.printErr("Site ID " + id + " not removed from database");
}
}
public void setSiteLock(boolean locked, int siteId) {
try {
executeUpdate("UPDATE " + TABLE + " SET locked = ? WHERE id = ?", locked, siteId);
} catch (SQLException e) {
LogFile.printErr("MySQL exception: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,204 @@
package jnet.server.dao;
import java.sql.SQLException;
import java.util.List;
import jnet.lib.LogFile;
import jnet.lib.object.SnmpProfile;
import jnet.lib.object.SnmpTemplate;
import jnet.lib.object.SnmpValueMap;
import jnet.lib.object.SnmpValueMapItem;
public class SnmpDao extends AbstractDao {
public static final String TABLE_PROFILE = "snmpProfile";
public static final String TABLE_TEMPLATE = "snmp_oid_template";
public static final String TABLE_VALUE_MAP = "snmp_value_map";
public static final String TABLE_VALUE_MAP_ITEM = "snmp_value_map_item";
public List<SnmpProfile> getAllProfile() {
String sql = "SELECT * FROM " + TABLE_PROFILE;
return queryList(sql, rs -> {
return new SnmpProfile(
rs.getInt("id"),
rs.getString("name"),
rs.getInt("version"),
rs.getString("port"),
rs.getString("communityRead")
);
});
}
public List<SnmpTemplate> getSnmpTemplate() {
String sql = "SELECT * FROM " + TABLE_TEMPLATE;
return queryList(sql, rs -> {
return new SnmpTemplate(
rs.getInt("id"),
rs.getInt("device_type"),
rs.getString("name"),
rs.getString("oid"),
rs.getInt("snmp_data_type"),
rs.getString("conversion_type"),
rs.getDouble("conversion_value"),
rs.getString("conversion_expression"),
rs.getString("unit"),
rs.getInt("value_map_id"),
rs.getString("description")
);
});
}
public List<SnmpValueMap> getSnmpValueMapList() {
String sql = "SELECT * FROM " + TABLE_VALUE_MAP;
return queryList(sql, rs -> new SnmpValueMap(
rs.getInt("id"),
rs.getString("name"),
getSnmpValueMapItem(rs.getInt("id"))
));
}
private List<SnmpValueMapItem> getSnmpValueMapItem(int id) {
String sql = "SELECT * FROM " + TABLE_VALUE_MAP_ITEM + " WHERE map_id = ?";
return queryList(sql, rs -> new SnmpValueMapItem(
rs.getInt("id"),
rs.getString("raw_value"),
rs.getString("mapped_value")
), id);
}
public int addSnmpProfile(SnmpProfile profile) {
String sql = "INSERT INTO " + TABLE_PROFILE + " (name, communityRead, port, version) VALUES (?, ?, ?, ?)";
return insertAndGetId(
sql,
profile.getName(),
profile.getCommunityRead(),
profile.getPort(),
profile.getVersion()
);
}
public void editSnmpProfile(SnmpProfile profile) {
try {
executeUpdate(
"UPDATE " + TABLE_PROFILE + " SET name=?, communityRead=?, port=?, version=? WHERE id=?",
profile.getName(),
profile.getCommunityRead(),
profile.getPort(),
profile.getVersion(),
profile.getId() // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci SNMP profilu: " + e.getMessage());
}
}
public void removeSnmpProfile(int id) {
if (deleteById(TABLE_PROFILE, id)) {
LogFile.printInfo("SNMP profile ID " + id + " removed from database");
} else {
LogFile.printErr("SNMP profile ID " + id + " not removed from database");
}
}
public int addSnmpTemplate(SnmpTemplate template) {
String sql = "INSERT INTO " + TABLE_TEMPLATE + " (name, device_type, oid, snmp_data_type, conversion_type, conversion_value, conversion_expression, value_map_id, unit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
return insertAndGetId(
sql,
template.getName(),
template.getDeviceType(),
template.getOid(),
template.getDataType(),
template.getConversionType(),
template.getConversionValue(),
template.getConversionExpression(),
template.getValueMap(),
template.getUnit()
);
}
public void editSnmpTemplate(SnmpTemplate template) {
try {
executeUpdate(
"UPDATE " + TABLE_TEMPLATE + " SET name=?, device_type=?, oid=?, snmp_data_type=?, conversion_type=?, conversion_value=?, conversion_expression=?, value_map_id=?, unit=? WHERE id=?",
template.getName(),
template.getDataType(),
template.getOid(),
template.getDataType(),
template.getConversionType(),
template.getConversionValue(),
template.getConversionExpression(),
template.getValueMap(),
template.getUnit(),
template.getId() // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci SNMP template: " + e.getMessage());
}
}
public void deleteSnmpTemplate(int id) {
if (deleteById(TABLE_TEMPLATE, id)) {
LogFile.printInfo("SNMP template ID " + id + " removed from database");
} else {
LogFile.printErr("SNMP template ID " + id + " not removed from database");
}
}
public int addSnmpValueMap(String name) {
String sql = "INSERT INTO " + TABLE_VALUE_MAP + " (name) VALUES (?)";
return insertAndGetId(
sql,
name
);
}
public int addSnmpValueMapItem(int map_id, String raw_value, String mapedValue) {
String sql = "INSERT INTO " + TABLE_VALUE_MAP_ITEM + " (map_id, raw_value, mapped_value) VALUES (?, ?, ?)";
return insertAndGetId(
sql,
map_id,
raw_value,
mapedValue
);
}
public void deleteSnmpValueMap(int id) {
if (deleteById(TABLE_VALUE_MAP, id)) {
LogFile.printInfo("SNMP Value Map ID " + id + " removed from database");
} else {
LogFile.printErr("SNMP Value Map ID " + id + " not removed from database");
}
}
public void editSnmpValueMap(SnmpValueMap valueMap) {
try {
executeUpdate(
"UPDATE " + TABLE_VALUE_MAP + " SET name=? WHERE id=?",
valueMap.getName(),
valueMap.getId() // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci SNMP Value Map: " + e.getMessage());
}
}
public void deleteSnmpValueMapItem(int id) {
if (deleteById(TABLE_VALUE_MAP_ITEM, id)) {
LogFile.printInfo("SNMP Value Map Item ID " + id + " removed from database");
} else {
LogFile.printErr("SNMP Value Map Item ID " + id + " not removed from database");
}
}
public void editSnmpValueMapItem(int map_id, String raw_value, String mapedValue) {
try {
executeUpdate(
"UPDATE " + TABLE_VALUE_MAP_ITEM + " SET map_id=?, raw_value=?, mapped_value=? WHERE id=?",
raw_value,
mapedValue,
map_id // poslední parametr pro WHERE
);
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci SNMP Value Map: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,107 @@
package jnet.server.dao;
import java.sql.SQLException;
import jnet.lib.PasswordHashing;
import jnet.lib.object.User;
import java.util.List;
import jnet.lib.LogFile;
public class UserDao extends AbstractDao {
public static final String TABLE = "users";
public boolean verifyUser(String username, String plainPassword) {
String sql = "SELECT password FROM " + TABLE + " WHERE username = ?";
String storedHash = querySingle(sql, rs -> rs.getString("password"), username);
return storedHash != null && PasswordHashing.verify(plainPassword, storedHash);
}
public User getUserInfo(String username) {
String sql = "SELECT * FROM " + TABLE + " WHERE username = ?";
return querySingle(sql, rs -> new User(
rs.getInt("id"),
rs.getString("username"),
rs.getString("password"),
rs.getBoolean("add_map"),
rs.getBoolean("remove_map"),
rs.getBoolean("edit_map"),
rs.getBoolean("add_object"),
rs.getBoolean("remove_object"),
rs.getBoolean("edit_object"),
rs.getBoolean("edit_server")
), username);
}
public List<User> getUsers() {
String sql = "SELECT * FROM " + TABLE;
return queryList(sql, rs -> new User(
rs.getInt("id"),
rs.getString("username"),
"",
rs.getBoolean("add_map"),
rs.getBoolean("remove_map"),
rs.getBoolean("edit_map"),
rs.getBoolean("add_object"),
rs.getBoolean("remove_object"),
rs.getBoolean("edit_object"),
rs.getBoolean("edit_server")
));
}
public int addUser(User user) {
String sql = "INSERT INTO " + TABLE + " (username, password, add_map, remove_map, edit_map, "
+ "add_object, remove_object, edit_object, edit_server) VALUES (?,?,?,?,?,?,?,?,?)";
return insertAndGetId(sql,
user.getUsername(), user.getPassword(),
user.isAddMap(), user.isRemoveMap(), user.isEditMap(),
user.isAddObject(), user.isRemoveObject(), user.isEditObject(),
user.isEditServer()
);
}
public void editUser(User u) {
try {
if (u.getPassword() == null) {
executeUpdate(
//edit bez zmeny hesla
"UPDATE " + TABLE + " SET username=?, add_map=?, remove_map=?, edit_map=?, add_object=?, remove_object=?, edit_object=?, edit_server=? WHERE id=?",
u.getUsername(),
(u.isAddMap() ? 1 : 0),
(u.isRemoveMap() ? 1 : 0),
(u.isEditMap() ? 1 : 0),
(u.isAddObject() ? 1 : 0),
(u.isRemoveObject() ? 1 : 0),
(u.isEditObject() ? 1 : 0),
(u.isEditServer() ? 1 : 0),
u.getId() // poslední parametr pro WHERE
);
} else {
executeUpdate(
// edit se zmenou hesla
"UPDATE " + TABLE + " SET username=?, password=?, add_map=?, remove_map=?, edit_map=?, add_object=?, remove_object=?, edit_object=?, edit_server=? WHERE id=?",
u.getUsername(),
u.getPassword(),
(u.isAddMap() ? 1 : 0),
(u.isRemoveMap() ? 1 : 0),
(u.isEditMap() ? 1 : 0),
(u.isAddObject() ? 1 : 0),
(u.isRemoveObject() ? 1 : 0),
(u.isEditObject() ? 1 : 0),
(u.isEditServer() ? 1 : 0),
u.getId() // poslední parametr pro WHERE
);
}
} catch (SQLException e) {
LogFile.printErr("Chyba při aktualizaci uzlu: " + e.getMessage());
}
}
public void deleteUser(int userId) {
if (deleteById(TABLE, userId)) {
LogFile.printInfo("User ID " + userId + " removed from database");
} else {
LogFile.printErr("User ID " + userId + " not removed from database");
}
}
}

View File

@ -0,0 +1,61 @@
package jnet.server.message;
import java.util.HashMap;
import java.util.Map;
import jnet.lib.Message;
public class MessageRegister {
private final Map<Integer, Register> register = new HashMap<>();
// Konstruktor - při vytvoření registru se sám naplní
public MessageRegister() {
register.put(Message.CLIENT_TYPE, new RegisterClientVersion());
register.put(Message.AUTH_DATA, new RegisterClientAuth());
register.put(Message.SITE_ADD, new RegisterSiteAdd());
register.put(Message.NODE_ICON_NEW, new RegisterNodeIconNew());
register.put(Message.USER_ADD, new RegisterUserAdd());
register.put(Message.SITE_DELETE, new RegisterSideDelete());
register.put(Message.NODE_POSITION_CHANGE, new RegisterNodePositionChange());
register.put(Message.NODE_ADD, new RegisterNodeAdd());
register.put(Message.SITE_SET_LOCK, new RegisterSiteSetLock());
register.put(Message.NODE_DELETE, new RegisterNodeDelete());
register.put(Message.NODE_CHANGE, new RegisterNodeChange());
register.put(Message.SNMP_TEST, new RegisterSnmpTest());
register.put(Message.SERVER_RESTART, new RegisterServerRestart());
register.put(Message.SERVER_UPTIME, new RegisterServerUptime());
register.put(Message.USER_EDIT, new RegisterUserEdit());
register.put(Message.NODE_SNMP_INFO, new RegisterSnmpNodeInfo());
register.put(Message.NODE_SNMP_INTERFACE, new RegisterSnmpNodeInterface());
register.put(Message.NODE_MOVE_TO_SITE, new RegisterNodeMoveToSite());
register.put(Message.NODE_CONNECTION_NEW, new RegisterNodeConnectionNew());
register.put(Message.NODE_CONNECTION_EDIT, new RegisterNodeConnectionEdit());
register.put(Message.NODE_CONNECTION_SNMP_INTERFACE, new RegisterNodeConnectionSnmpInterface());
register.put(Message.NODE_PROBE_NEW, new RegisterNodeProbeNew());
register.put(Message.NODE_CONNECTION_DELETE, new RegisterNodeConnectionDelete());
register.put(Message.SNMP_PROFILE_NEW, new RegisterSnmpProfileNew());
register.put(Message.SNMP_PROFILE_EDIT, new RegisterSnmpProfileEdit());
register.put(Message.SNMP_PROFILE_DELETE, new RegisterSnmpProfileDelete());
register.put(Message.NODE_PROBE_EDIT, new RegisterNodeProbeEdit());
register.put(Message.NODE_PROBE_DELETE, new RegisterNodeProbeDelete());
register.put(Message.SNMP_TEMPLATE_NEW, new RegisterSnmpTemplateNew());
register.put(Message.SNMP_TEMPLATE_EDIT, new RegisterSnmpTemplateEdit());
register.put(Message.SNMP_TEMPLATE_DELETE, new RegisterSnmpTemplateDelete());
register.put(Message.DEVICE_TYPE_DELETE, new RegisterDeviceTypeDelete());
register.put(Message.USER_DELETE, new RegisterUserDelete());
register.put(Message.USER_PING_START, new RegisterUserPingStart());
register.put(Message.USER_PING_STOP, new RegisterUserPingStop());
register.put(Message.SERVER_LOG, new RegisterServerLog());
register.put(Message.SERVER_CONFIG_EDIT, new RegisterServerEdit());
register.put(Message.VALUE_MAP_NEW, new RegisterValueMapNew());
register.put(Message.VALUE_MAP_EDIT, new RegisterValueMapEdit());
register.put(Message.VALUE_MAP_DELETE, new RegisterValueMapDelete());
}
public Register getRegister(int typ) {
return register.get(typ);
}
}

View File

@ -0,0 +1,10 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
public interface Register {
void processing(ChannelHandlerContext ctx, Message msg);
}

View File

@ -0,0 +1,83 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.net.InetSocketAddress;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.object.OnlineClients;
import jnet.lib.object.ServerConfig;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterClientAuth implements Register {
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
String[] userData = (String[]) msg.getMsg();
String username = userData[0];
String password = userData[1];
InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
String ip = remoteAddress.getAddress().getHostAddress();
int port = remoteAddress.getPort(); // 54321
int platform = Integer.parseInt(userData[2]);
if (Database.verifyUser(username, password)) {
LogFile.printInfo("User: " + username + " logged in (" + ip + ")");
// odeslani potvreni autorizace
ctx.writeAndFlush(new Message(Message.AUTH_OK, null));
// odeslat informace o prihlasenem uzivateli, opravneni atd
ctx.writeAndFlush(new Message(Message.USER_INFO, Database.getUserInfo(username)));
// pridani uzivatele mezi pripojene kanaly
ServerHandler.addChannel(ctx);
// pridat do seznamu klientu
Server.onlineClients.add(new OnlineClients(
String.valueOf(ctx.channel().id()),
username, // username
remoteAddress.getAddress().getHostName(), // ip adresa
String.valueOf(port), // port
platform));
// odeslat vsem nový seznam pripojenych klientu
ServerHandler.sendAll(new Message(Message.ONLINE_CLIENTS, Server.onlineClients));
// odeslat nastaveni serveru
ctx.writeAndFlush(new Message(Message.SERVER_CONFIG, getServerConfig()));
// odeslat seznam uzivatelu
ctx.writeAndFlush(new Message(Message.USER_LIST, Server.users));
// odeslat seznam icon
ctx.writeAndFlush(new Message(Message.NODE_ICON_LIST, Server.devicType));
// odeslat seznam udalosti
ctx.writeAndFlush(new Message(Message.EVENT_LIST, Server.events));
// odeslat seznam site
ctx.writeAndFlush(new Message(Message.SITE_LIST, Server.site));
// odeslat seznam snmp profilu
ctx.writeAndFlush(new Message(Message.SNMP_PROFILE_LIST, Server.snmpProfile));
// odeslat seznam snmp sablon
ctx.writeAndFlush(new Message(Message.SNMP_TEMPLATE_LIST, Server.snmpTemplate));
// odeslat seznam snmp value map
ctx.writeAndFlush(new Message(Message.SNMP_TEMPLATE_VALUE_MAP_LIST, Server.snmpValueMap));
} else {
LogFile.printErr("User:" + username + " has not been logged in - Incorrect user data (" + ip + ")");
// odeslání selhani autorizace
ctx.writeAndFlush(new Message(Message.AUTH_FAIL, null));
}
}
private ServerConfig getServerConfig() {
ServerConfig sc = new ServerConfig(
Server.config.getInt("ping_repeat"),
Server.config.getInt("ping_attempt"),
Server.config.getInt("ping_timeout"),
Server.config.getInt("instability_attempt"),
Server.config.getInt("instability_limit"),
Server.config.getInt("traffic_interval"),
Server.config.getInt("traffic_batch_interval"),
Server.config.getInt("probe_batch_interval"),
Server.config.getBoolean("debug"));
return sc;
}
}

View File

@ -0,0 +1,22 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Server;
class RegisterClientVersion implements Register {
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int clientVersion = (int) msg.getMsg();
if (clientVersion < Server.MINIMAL_CLIENT_VERSION) {
// verze klienta je mensi nez pozadovana -> vyzadat aktualizaci klienta
ctx.writeAndFlush(new Message(Message.CLIENT_UPDATE, null));
} else {
// verze klienta je ok -> vyzadat aktualizaci
ctx.writeAndFlush(new Message(Message.AUTH_REQUEST, null));
}
}
}

View File

@ -0,0 +1,27 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterDeviceTypeDelete implements Register{
public RegisterDeviceTypeDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int id = (int) msg.getMsg();
Database.deleteDeviceType(id);
// odebere ze seznamu
Server.devicType.removeIf(obj -> obj.getId() == id);
ServerHandler.sendAll(Message.DEVICE_TYPE_DELETE_RESULT, id);
}
}

View File

@ -0,0 +1,41 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.server.probe.Ping;
public class RegisterNodeAdd implements Register {
public RegisterNodeAdd() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Node node = (Node) msg.getMsg();
// vlozi do databaze a získa id
int id = Database.addNode(node);
node.setId(id);
// vlozi do seznamu
for (Site site : Server.site) {
if (site.getId() == node.getSiteId()) {
site.getNode().add(node);
break;
}
}
// odesle novy node klientum
ServerHandler.sendAll(new Message(Message.NODE_NEW, node));
// pokud je povolen ping zaradí ke sledovani
if (node.isPing()) {
Ping.addOrUpdateTarget(node.getId(), node.getIp());
}
}
}

View File

@ -0,0 +1,45 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.util.List;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.server.probe.Ping;
public class RegisterNodeChange implements Register {
public RegisterNodeChange() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Node newNode = (Node) msg.getMsg();
for (Site site : Server.site) {
List<Node> nodes = site.getNode(); // nebo použijte rozhraní
for (int i = 0; i < nodes.size(); i++) {
if (nodes.get(i).getId() == newNode.getId()) {
// nahradi node v seznamu
nodes.set(i, newNode);
// aktualizuje v databazi
Database.editNode(newNode);
// aktualizuje ping
if (newNode.isPing()) {
// aktualizuje
Ping.addOrUpdateTarget(newNode.getId(), newNode.getIp());
} else {
// odebere target z pingu
Ping.removeTarget(newNode.getId());
}
// odesle zmenu klientum
ServerHandler.sendAll(Message.NODE_UPDATE, newNode);
return;
}
}
}
}
}

View File

@ -0,0 +1,36 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.server.probe.Ping;
public class RegisterNodeConnectionDelete implements Register {
public RegisterNodeConnectionDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int id = (int) msg.getMsg();
// smazani z lokalniho seznamu
for (Site site : Server.site) {
// odebere ze seznamu
site.getNodeConnection().removeIf(nodeConnection -> nodeConnection.getId() == id);
// odebere z databaze
Database.removeNodeConnection(id);
// smazani z traffic monitoru
Server.trafficMonitorService.removeDevice(id);
// odesle informaci vsem
ServerHandler.sendAll(Message.NODE_CONNECTION_REMOVE, id);
break;
}
}
}

View File

@ -0,0 +1,56 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.util.List;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.NodeConnection;
import jnet.lib.object.Site;
import jnet.lib.object.SnmpProfile;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterNodeConnectionEdit implements Register {
public RegisterNodeConnectionEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
NodeConnection nc = (NodeConnection) msg.getMsg();
for (Site site : Server.site) {
List<NodeConnection> connection = site.getNodeConnection(); // nebo použijte rozhraní
for (int i = 0; i < connection.size(); i++) {
if (connection.get(i).getId() == nc.getId()) {
// nahradi node v seznamu
connection.set(i, nc);
// aktualizuje v databazi
Database.editNodeconnection(nc);
// odebere traffic monitor
Server.trafficMonitorService.removeDevice(nc.getId());
// a pokud je zapnute cteni znovu ho prida
if (nc.isReadTraffic()) {
// ziska info o node
Node node = site.getNode().stream()
.filter(n -> n.getId() == nc.getTrafficNode())
.findFirst()
.orElse(null);
// ziska info o profilu
SnmpProfile profile = Server.snmpProfile.stream()
.filter(p -> p.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
// prida ke čtení
Server.trafficMonitorService.addDevice(nc.getId(), node.getIp(), profile.getPort(), profile.getCommunityRead(), profile.getVersion(), nc.getTrafficIface());
// odesle infomaci o zmene
ServerHandler.sendAll(Message.NODE_CONNECTION_CHANGE, nc);
}
}
}
}
}
}

View File

@ -0,0 +1,60 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.NodeConnection;
import jnet.lib.object.Site;
import jnet.lib.object.SnmpProfile;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterNodeConnectionNew implements Register {
private Node node = null;
public RegisterNodeConnectionNew() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
NodeConnection nc = (NodeConnection) msg.getMsg();
// ulozeni do databaze
int id = Database.addNodeConnection(nc);
// vlozen id
nc.setId(id);
// ulozeni do mistniho seznamu
for (Site site : Server.site) {
if (site.getId() == nc.getSite()) {
site.getNodeConnection().add(nc);
// je-li zapnuto cteni trafficu
if (nc.isReadTraffic()) {
node = site.getNode().stream()
.filter(n -> n.getId() == nc.getTrafficNode())
.findFirst()
.orElse(null);
}
break;
}
}
// odeslani zmeny site
ServerHandler.sendAll(Message.NODE_CONNECTION_ADD, nc);
// je-li zapnuto cteni trafficu
if (nc.isReadTraffic() && node != null) {
SnmpProfile profile = Server.snmpProfile.stream()
.filter(p -> p.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
Server.trafficMonitorService.addDevice(nc.getId(), node.getIp(), profile.getPort(), profile.getCommunityRead(), profile.getVersion(), nc.getTrafficIface());
}
}
}

View File

@ -0,0 +1,50 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException;
import java.util.List;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.object.Interface;
import jnet.lib.object.Node;
import jnet.lib.object.SnmpProfile;
import jnet.server.Server;
import jnet.server.snmp.SNMPInterfaceScanner;
public class RegisterNodeConnectionSnmpInterface implements Register {
public RegisterNodeConnectionSnmpInterface() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
try {
Object[] data = (Object[]) msg.getMsg();
String frame = (String) data[0];
Node node = (Node) data[1];
// zjistit snmp profile
SnmpProfile snmpProfile = Server.snmpProfile.stream()
.filter(profile -> profile.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
if (snmpProfile != null) {
// odeslat pozadavek
SNMPInterfaceScanner scanner = new SNMPInterfaceScanner(
node.getIp(),
snmpProfile.getPort(),
snmpProfile.getCommunityRead(),
snmpProfile.getVersion()
);
List<Interface> ifaces = scanner.scanInterfaces();
Object[] result = {frame, ifaces};
ctx.writeAndFlush(new Message(Message.NODE_CONNECTION_SNMP_INTERFACE_RESULT, result));
}
} catch (IOException ex) {
LogFile.printErr("SNMP interface scan error: " + ex.getMessage());
}
}
}

View File

@ -0,0 +1,36 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.util.Objects;
import jnet.lib.Message;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.server.probe.Ping;
public class RegisterNodeDelete implements Register{
public RegisterNodeDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int nodeId = (int) msg.getMsg();
for (Site site : Server.site) {
// odebere ze seznamu
site.getNode().removeIf(node -> node.getId() == nodeId);
// odebere z databaze
Database.removeNode(nodeId);
// odebere target z pingu
Ping.removeTarget(nodeId);
// odesle informaci vsem
ServerHandler.sendAll(Message.NODE_REMOVE, nodeId);
break;
}
// smazat z eventu
Server.events.removeIf(event -> Objects.equals(event.getNode(), nodeId));
}
}

View File

@ -0,0 +1,31 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.DeviceType;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterNodeIconNew implements Register {
public RegisterNodeIconNew() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
DeviceType not = (DeviceType) msg.getMsg();
// ulozit do databaze
int id = Database.addObjectType(not);
// pridat do seznamu
not.setId(id);
Server.devicType.add(not);
// odeslat vsem novy seznam
ServerHandler.sendAll(new Message(Message.NODE_ICON_LIST, Server.devicType));
// klientovi odeslat pokyn k aktualizaci tabulky
ctx.writeAndFlush(new Message(Message.NODE_ICON_REFRESH, null));
}
}

View File

@ -0,0 +1,64 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterNodeMoveToSite implements Register {
public RegisterNodeMoveToSite() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int[] data = (int[]) msg.getMsg();
int nodeId = data[0];
int targetSiteId = data[1];
int newX = data[2];
int newY = data[3];
Node node = new Node();
for (Site site : Server.site) { // Server.site je List<Site>
for (Node n : site.getNode()) {
if (n.getId() == nodeId) {
// najdeme node v puvodni mape a ulozime si ho
node = n;
// odebereme z puvodni site
site.getNode().remove(n);
break;
}
}
}
// nastavime nové hodnoty x a y
node.setX(newX);
node.setY(newY);
node.setSiteId(targetSiteId);
// najdeme cilovou site a vlozime do ni node
for (Site site : Server.site) { // Server.site je List<Site>
if (site.getId() == targetSiteId) {
site.getNode().add(node);
break;
}
}
// smazat connection
Database.deteleConnectionAfterNodeMove(node.getId());
// upravime v databazi
Database.editNode(node);
// odesleme delete z puvodni site klientum
ServerHandler.sendAll(Message.NODE_REMOVE, nodeId);
// odesleme klientum node do nove site
ServerHandler.sendAll(Message.NODE_NEW, node);
}
}

View File

@ -0,0 +1,47 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterNodePositionChange implements Register {
public RegisterNodePositionChange() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int[] data = (int[]) msg.getMsg();
int nodeId = data[0];
int x = data[1];
int y = data[2];
// najit node v seznamu a upravit mu pozici
boolean changed = false;
for (Site site : Server.site) {
for (Node node : site.getNode()) {
if (node.getId() == nodeId) {
// zmenit v seznamu
node.setX(x);
node.setY(y);
// zmenit v databazi
Database.nodeUpdatePosition(nodeId, x, y);
// odeslat novou pozici klientum
ServerHandler.sendAll(new Message(Message.NODE_CHANGE_POSITION, msg.getMsg()));
changed = true;
break;
}
}
if (changed) {
break;
}
}
}
}

View File

@ -0,0 +1,41 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterNodeProbeDelete implements Register {
public RegisterNodeProbeDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] obj = (Object[]) msg.getMsg();
int probeId = (int) obj[0];
String frame = (String) obj[1];
// odebere ze seznamu
for (Site site : Server.site) {
for (Node node : site.getNode()) {
node.getProbe().removeIf(probe -> probe.getId() == probeId);
}
}
// odebere z databaze
Database.removeNodeProbe(probeId);
// odebere ze sledovani
Server.snmpProbeManager.removeTask(probeId);
// odesle informaci vsem
Object[] reply = {probeId, frame};
ServerHandler.sendAll(Message.NODE_PROBE_DELETE_RESULT, reply);
}
}

View File

@ -0,0 +1,65 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.NodeProbe;
import jnet.lib.object.Site;
import jnet.lib.object.SnmpProfile;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.server.probe.snmp.MonitorConfig;
public class RegisterNodeProbeEdit implements Register {
public RegisterNodeProbeEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] obj = (Object[]) msg.getMsg();
NodeProbe probe = (NodeProbe) obj[0];
String frame = (String) obj[1];
// upravit v lokalnim seznamu
for (Site site : Server.site) {
for (Node node : site.getNode()) {
for (int i = 0; i < node.getProbe().size(); i++) {
if (node.getProbe().get(i).getId() == probe.getId()) {
node.getProbe().set(i, probe);
// upravit monitor
runMonitor(node, probe);
}
}
}
}
// uprvait v databazi
Database.editNodeProbe(probe);
// odeslat zmenu klientum
Object[] reply = {probe, frame};
ServerHandler.sendAll(Message.NODE_PROBE_EDIT_RESULT, reply);
}
private void runMonitor(Node node, NodeProbe probe) {
SnmpProfile profile = Server.snmpProfile.stream()
.filter(p -> p.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
// nejdriv odebrat
Server.snmpProbeManager.removeTask(probe.getId());
// pak znovu přidat
Server.snmpProbeManager.addTask(new MonitorConfig(
probe.getId(),
node.getIp(),
profile.getCommunityRead(),
profile.getPort(),
profile.getVersion(),
probe.getOid(),
probe.getInterval()
));
}
}

View File

@ -0,0 +1,62 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Node;
import jnet.lib.object.NodeProbe;
import jnet.lib.object.Site;
import jnet.lib.object.SnmpProfile;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.server.probe.snmp.MonitorConfig;
public class RegisterNodeProbeNew implements Register {
public RegisterNodeProbeNew() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] obj = (Object[]) msg.getMsg();
NodeProbe probe = (NodeProbe) obj[0];
String frame = (String) obj[1];
// vlozeni do databaze
int id = Database.addNodeProbe(probe);
probe.setId(id);
// vlozeni do lokalniho seznamu
for (Site site : Server.site) {
for (Node node : site.getNode()) {
if (node.getId() == probe.getNodeId()) {
node.getProbe().add(probe);
// spustit snmp dotazovani
runMonitor(node, probe);
break;
}
}
}
// odeslat zmenu klientum
Object[] reply = {probe, frame};
ServerHandler.sendAll(Message.NODE_PROBE_NEW_RESULT, reply);
}
private void runMonitor(Node node, NodeProbe probe) {
SnmpProfile profile = Server.snmpProfile.stream()
.filter(p -> p.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
Server.snmpProbeManager.addTask(new MonitorConfig(
probe.getId(),
node.getIp(),
profile.getCommunityRead(),
profile.getPort(),
profile.getVersion(),
probe.getOid(),
probe.getInterval()
));
}
}

View File

@ -0,0 +1,39 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.ApacheConfig;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.object.ServerConfig;
import jnet.server.Server;
import org.apache.commons.configuration2.ex.ConfigurationException;
public class RegisterServerEdit implements Register {
public RegisterServerEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
ServerConfig sc = (ServerConfig) msg.getMsg();
Server.config.setProperty("debug", sc.isDebug());
Server.config.setProperty("ping_repeat", sc.getPingRepeat());
Server.config.setProperty("ping_timeout", sc.getPingTimeout());
Server.config.setProperty("ping_attempt", sc.getPingAttempt());
Server.config.setProperty("instability_attempt", sc.getInstabilityAttempt());
Server.config.setProperty("instability_limit", sc.getInstabilityLimit());
Server.config.setProperty("traffic_interval", sc.getTrafficInterval());
Server.config.setProperty("traffic_batch_interval", sc.getTrafficBatchInterval());
Server.config.setProperty("probe_batch_interval", sc.getProbeBatchInterval());
try {
ApacheConfig.saveProperties(Server.config);
LogFile.printInfo("Nastavení uloženo.");
} catch (ConfigurationException ex) {
LogFile.printErr("Nastavení nebylo uloženo. " + ex.getMessage());
}
}
}

View File

@ -0,0 +1,34 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import jnet.lib.Message;
import jnet.server.networkserver.ServerHandler;
public class RegisterServerLog implements Register{
public RegisterServerLog() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
try {
// Načtení všech řádků souboru do List<String>
List<String> lines = Files.readAllLines(Paths.get("log"));
// Převod na String[]
String[] logRecords = lines.toArray(new String[0]);
ctx.writeAndFlush(new Message(Message.SERVER_LOG_RESULT, logRecords));
} catch (IOException e) {
// Ošetření chyby – např. logování nebo zaslání chybové zprávy
e.printStackTrace();
// případně ctx.writeAndFlush(...)
}
}
}

View File

@ -0,0 +1,72 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.server.Server;
public class RegisterServerRestart implements Register {
public RegisterServerRestart() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
restartService();
}
public static void restartService() {
try {
ProcessBuilder builder = new ProcessBuilder(
"sudo", "systemctl", "restart", "jnetserver.service"
);
builder.inheritIO(); // pro viditelnost výstupu v konzoli
builder.start();
// Po zavolání restartu službu ukončíme
// systemd službu automaticky znovu spustí
//System.exit(0);
} catch (IOException e) {
LogFile.printErr("Restart error: " +e.getLocalizedMessage());
}
}
public static void restartServer() {
try {
// Získání cesty k aktuálnímu JAR souboru
String jarPath = new File(Server.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI())
.getAbsolutePath();
// Získání původních argumentů (pokud byly použity)
String[] originalArgs = System.getProperty("sun.java.command").split(" ");
// Sestavení příkazu
List<String> command = new ArrayList<>();
command.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
command.add("-jar");
command.add(jarPath);
command.addAll(Arrays.asList(originalArgs)); // přidání původních argumentů
// Spuštění nového procesu
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.inheritIO(); // převzetí stdout/stderr
processBuilder.start();
// Ukončení aktuálního procesu
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
// Chyba - nelze restartovat
}
}
}

View File

@ -0,0 +1,19 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.lang.management.ManagementFactory;
import jnet.lib.Message;
public class RegisterServerUptime implements Register {
public RegisterServerUptime() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
long uptime = ManagementFactory.getRuntimeMXBean().getUptime();
ctx.writeAndFlush(new Message(Message.SERVER_UPTIME_RESULT, uptime));
}
}

View File

@ -0,0 +1,25 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSideDelete implements Register {
public RegisterSideDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int id = (int) msg.getMsg();
// odebere ze seznamu
Server.site.removeIf(site -> site.getId() == id);
// odebere z databaze
Database.removeSite(id);
// odessle novy seznam map
ServerHandler.sendAll(new Message(Message.SITE_LIST, Server.site));
}
}

View File

@ -0,0 +1,29 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSiteAdd implements Register {
public RegisterSiteAdd() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
String name = (String) msg.getMsg();
// vlozeni do databaze a ziskani id vlozeneho radku
int siteId = Database.addSite(name);
// priprava Site objektu
Site site= new Site(siteId, name);
// pridání do seznamu na serveru
Server.site.add(site);
// odeslani nove mapy vsem klientum
ServerHandler.sendAll(new Message(Message.SITE_NEW, site));
}
}

View File

@ -0,0 +1,33 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.Site;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSiteSetLock implements Register{
public RegisterSiteSetLock() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] data = (Object[]) msg.getMsg();
for (Site site : Server.site) {
if (site.getId() == (int) data[0]) {
// zamknout v lokalnim seznamu
site.setLock((boolean) data[1]);
// zamknout v databazi
Database.setSiteLock((boolean) data[1], (int) data[0]);
// odeslat informaci klientum
ServerHandler.sendAll(new Message(Message.SITE_LOCK, data));
}
}
}
}

View File

@ -0,0 +1,44 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.object.DeviceInfo;
import jnet.lib.object.Node;
import jnet.lib.object.SnmpProfile;
import jnet.server.Server;
import jnet.server.snmp.SNMPDeviceInfo;
public class RegisterSnmpNodeInfo implements Register {
public RegisterSnmpNodeInfo() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
new Thread(() -> {
try {
Object[] data = (Object[]) msg.getMsg();
String frame = (String) data[0];
Node node = (Node) data[1];
// zjistit snmp profile
SnmpProfile snmpProfile = Server.snmpProfile.stream()
.filter(profile -> profile.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
if (snmpProfile != null) {
// odeslat pozadavek
SNMPDeviceInfo snmp = new SNMPDeviceInfo(node.getIp(), snmpProfile.getPort(), snmpProfile.getCommunityRead(), snmpProfile.getVersion());
DeviceInfo info = snmp.getDeviceInfo(); // spojení se automaticky uzavře
Object[] result = {frame, info};
ctx.writeAndFlush(new Message(Message.NODE_SNMP_INFO_RESULT, result));
}
} catch (IOException ex) {
LogFile.printErr("SNMP info error: " + ex.getMessage());
}
}).start();
}
}

View File

@ -0,0 +1,51 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException;
import java.util.List;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.object.Interface;
import jnet.lib.object.Node;
import jnet.lib.object.SnmpProfile;
import jnet.server.Server;
import jnet.server.snmp.SNMPInterfaceScanner;
public class RegisterSnmpNodeInterface implements Register {
public RegisterSnmpNodeInterface() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
new Thread(() -> {
try {
Object[] data = (Object[]) msg.getMsg();
String frame = (String) data[0];
Node node = (Node) data[1];
// zjistit snmp profile
SnmpProfile snmpProfile = Server.snmpProfile.stream()
.filter(profile -> profile.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
if (snmpProfile != null) {
// odeslat pozadavek
SNMPInterfaceScanner scanner = new SNMPInterfaceScanner(
node.getIp(),
snmpProfile.getPort(),
snmpProfile.getCommunityRead(),
snmpProfile.getVersion()
);
List<Interface> ifaces = scanner.scanInterfaces();
Object[] result = {frame, ifaces};
ctx.writeAndFlush(new Message(Message.NODE_SNMP_INTERFACE_RESULT, result));
}
} catch (IOException ex) {
LogFile.printErr("SNMP interface scan error: " + ex.getMessage());
}
}).start();
}
}

View File

@ -0,0 +1,27 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSnmpProfileDelete implements Register {
public RegisterSnmpProfileDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int profileId = (int) msg.getMsg();
// odebere ze seznamu
Server.snmpProfile.removeIf(snmpProfile -> snmpProfile.getId() == profileId);
// odebere z databaze
Database.removeSnmpProfile(profileId);
// odesle informaci vsem
ServerHandler.sendAll(Message.SNMP_PROFILE_DELETE_RESULT, profileId);
}
}

View File

@ -0,0 +1,35 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.SnmpProfile;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSnmpProfileEdit implements Register {
public RegisterSnmpProfileEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
SnmpProfile profile = (SnmpProfile) msg.getMsg();
// upravit v databazi
Database.editSnmpProfile(profile);
// upravit v lokalnim seznamu
for (int i = 0; i < Server.snmpProfile.size(); i++) {
if (Server.snmpProfile.get(i).getId() == profile.getId()) {
// nahradi node v seznamu
Server.snmpProfile.set(i, profile);
break;
}
}
System.out.println("jnet.server.message.RegisterSnmpProfileEdit.processing()");
ServerHandler.sendAll(Message.SNMP_PROFILE_EDIT_RESULT, profile);
}
}

View File

@ -0,0 +1,30 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.SnmpProfile;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSnmpProfileNew implements Register {
public RegisterSnmpProfileNew() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
SnmpProfile profile = (SnmpProfile) msg.getMsg();
int id = Database.addSnmpProfile(profile);
profile.setId(id);
Server.snmpProfile.add(profile);
ServerHandler.sendAll(Message.SNMP_PROFILE_NEW_RESULT, profile);
}
}

View File

@ -0,0 +1,26 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSnmpTemplateDelete implements Register {
public RegisterSnmpTemplateDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int id = (int) msg.getMsg();
Database.deleteSnmpTemplate(id);
Server.snmpTemplate.removeIf(template -> template.getId() == id);
ServerHandler.sendAll(Message.SNMP_TEMPLATE_DELETE_RESULT, id);
}
}

View File

@ -0,0 +1,32 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.SnmpTemplate;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSnmpTemplateEdit implements Register {
public RegisterSnmpTemplateEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
SnmpTemplate template = (SnmpTemplate) msg.getMsg();
Database.editSnmpTemplate(template);
for (int i = 0; i < Server.snmpTemplate.size(); i++) {
if (Server.snmpTemplate.get(i).getId() == template.getId()) {
Server.snmpTemplate.set(i, template);
break;
}
}
ServerHandler.sendAll(Message.SNMP_TEMPLATE_EDIT_RESULT, template);
}
}

View File

@ -0,0 +1,29 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.SnmpTemplate;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterSnmpTemplateNew implements Register {
public RegisterSnmpTemplateNew() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
SnmpTemplate template = (SnmpTemplate) msg.getMsg();
int id = Database.addSnmpTemplate(template);
template.setId(id);
Server.snmpTemplate.add(template);
ServerHandler.sendAll(Message.SNMP_TEMPLATE_NEW_RESULT, template);
}
}

View File

@ -0,0 +1,98 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
public class RegisterSnmpTest implements Register {
public RegisterSnmpTest() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] data = (Object[]) msg.getMsg();
String ip = (String) data[0];
String port = (String) data[1];
int version = (int) data[2];
String communityRead = (String) data[3];
String frame = (String) data[4];
String result = testSnmpGet(ip, port, communityRead, ".1.3.6.1.2.1.1.1.0", version, 5*1000);
if (result.startsWith("ERROR:")) {
Object[] reply = {frame, false};
ctx.writeAndFlush(new Message(Message.SNMP_TEST_RESULT, reply));
} else {
Object[] reply = {frame, true};
ctx.writeAndFlush(new Message(Message.SNMP_TEST_RESULT, reply));
}
}
/**
* Otestuje SNMP GET na zadaném zařízení.
*
* @param ip IP adresa (např. "192.168.1.100")
* @param community Komunitní řetězec (např. "public")
* @param oid OID ve tvaru ".1.3.6.1.2.1.1.1.0" nebo "1.3.6.1.2.1.1.1.0"
* @param timeoutMs Timeout v milisekundách (např. 3000)
* @return String s hodnotou OID, nebo zpráva začínající "ERROR: " při chybě
*/
public static String testSnmpGet(String ip, String port, String community, String oid,
int version, int timeoutMs) {
try (TransportMapping<?> transport = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transport)) {
transport.listen();
Address targetAddress = GenericAddress.parse("udp:" + ip + "/"+port);
Target target;
if (version == 1 || version == 2) {
// SNMPv1 nebo v2c
CommunityTarget ct = new CommunityTarget();
ct.setCommunity(new OctetString(community));
ct.setVersion(version == 1 ? SnmpConstants.version1 : SnmpConstants.version2c);
target = ct;
} else if (version == 3) {
// SNMPv3 – vyžaduje další údaje (uživatel, auth, priv)
// Zde je potřeba předat i jméno, hesla – proto raději udělejte přetíženou verzi
return "ERROR: Pro SNMPv3 použijte speciální funkci s parametry auth/priv.";
} else {
return "ERROR: Neznámá verze SNMP (povoleno 1, 2, 3)";
}
target.setAddress(targetAddress);
target.setTimeout(timeoutMs);
target.setRetries(1);
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(oid)));
pdu.setType(PDU.GET);
ResponseEvent event = snmp.send(pdu, target);
PDU response = event.getResponse();
if (response == null) {
return "ERROR: Žádná odpověď (timeout)";
}
VariableBinding vb = response.get(0);
return (vb == null) ? "ERROR: Prázdná odpověď" : vb.getVariable().toString();
} catch (Exception e) {
return "ERROR: " + e.getMessage();
}
}
}

View File

@ -0,0 +1,31 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.PasswordHashing;
import jnet.lib.object.User;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterUserAdd implements Register {
public RegisterUserAdd() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
User u = (User) msg.getMsg();
u.setPassword(PasswordHashing.hash(u.getPassword()));
//pridáni do databáze a nastaveni id
u.setId(Database.addUser(u));
// přidání do seznamu
Server.users.add(u);
// odeslat klientum novy seznam uzivatelu
ServerHandler.sendAll(new Message(Message.USER_LIST, Server.users));
// odeslat klientovi infomraci o pridani a aktualizaci tabulky
ctx.writeAndFlush(new Message(Message.USER_REFRESH, null));
}
}

View File

@ -0,0 +1,27 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterUserDelete implements Register {
public RegisterUserDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int userId = (int) msg.getMsg();
Database.deleteUser(userId);
Server.users.removeIf(user -> user.getId() == userId);
// odessle novy seznam map
ServerHandler.sendAll(new Message(Message.USER_DELETE, userId));
}
}

View File

@ -0,0 +1,39 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.PasswordHashing;
import jnet.lib.object.User;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterUserEdit implements Register {
public RegisterUserEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
User u = (User) msg.getMsg();
// bude se editovat heslo ?
if (u.getPassword() != null) {
u.setPassword(PasswordHashing.hash(u.getPassword()));
}
// ulozeni do databaze
Database.editUser(u);
// aktualizace v seznamu
for (int i = 0; i < Server.users.size(); i++) {
if (Server.users.get(i).getId() == u.getId()) {
// nahradi node v seznamu
Server.users.set(i, u);
break;
}
}
// odeslat klientum novy seznam uzivatelu
ServerHandler.sendAll(new Message(Message.USER_LIST, Server.users));
// odeslat klientovi infomraci o pridani a aktualizaci tabulky
ctx.writeAndFlush(new Message(Message.USER_REFRESH, null));
}
}

View File

@ -0,0 +1,34 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.userping.PingManager;
public class RegisterUserPingStart implements Register {
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] data = (Object[]) msg.getMsg();
if (data == null || data.length < 2) {
ctx.writeAndFlush(new Message(Message.USER_PING_STARTED, "ERR: Missing IP or frameName"));
return;
}
String ip = data[0].toString();
String frameName = data[1].toString();
if (ip.trim().isEmpty() || frameName.trim().isEmpty()) {
ctx.writeAndFlush(new Message(Message.USER_PING_STARTED, "ERR: Empty IP or frameName"));
return;
}
// Sender pro odesílání odpovědí – každý řádek pošleme s frameName
java.util.function.Consumer<String> sender = (line) -> {
if (ctx.channel().isActive()) {
ctx.writeAndFlush(new Message(Message.USER_PING_RESPONSE, new Object[]{frameName, line}));
}
};
String pingId = PingManager.startPing(ctx.channel(), ip.trim(), frameName, sender);
ctx.writeAndFlush(new Message(Message.USER_PING_STARTED, "Ping started for " + ip + " frame " + frameName + " (ID: " + pingId + ")"));
}
}

View File

@ -0,0 +1,23 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.userping.PingManager;
public class RegisterUserPingStop implements Register {
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
Object[] data = (Object[]) msg.getMsg();
if (data == null || data.length < 2) {
ctx.writeAndFlush(new Message(Message.USER_PING_STOPPED, "ERR: Missing IP or frameName"));
return;
}
String ip = data[0].toString();
String frameName = data[1].toString();
String pingId = ip + ":" + frameName;
PingManager.stopPing(ctx.channel(), pingId);
ctx.writeAndFlush(new Message(Message.USER_PING_STOPPED, "Ping stopped for " + pingId));
}
}

View File

@ -0,0 +1,27 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterValueMapDelete implements Register {
public RegisterValueMapDelete() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
int id = (int) msg.getMsg();
Database.deleteSnmpValueMap(id);
// odebere ze seznamu
Server.snmpValueMap.removeIf(vm -> vm.getId() == id);
ServerHandler.sendAll(Message.VALUE_MAP_DELETE_RESULT, id);
}
}

View File

@ -0,0 +1,49 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.SnmpValueMap;
import jnet.lib.object.SnmpValueMapItem;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterValueMapEdit implements Register {
public RegisterValueMapEdit() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
SnmpValueMap vm = (SnmpValueMap) msg.getMsg();
Database.editSnmpValueMap(vm);
// nejprve smazat stare itemy mapovani
SnmpValueMap oldValueMap = Server.snmpValueMap.stream()
.filter(p -> p.getId() == vm.getId())
.findFirst()
.orElse(null);
for (SnmpValueMapItem oldItem : oldValueMap.getItem()) {
Database.deleteSnmpValueMapItem(oldItem.getId());
}
// vlozit nové itemy mapovani
for (SnmpValueMapItem item : vm.getItem()) {
int itemID = Database.addSnmpValueMapItem(vm.getId(), item.getRawValue(), item.getMappedValue());
item.setId(itemID);
}
// upravit v lokalnim seznamu
for (int i = 0; i < Server.snmpValueMap.size(); i++) {
if (Server.snmpValueMap.get(i).getId() == vm.getId()) {
Server.snmpValueMap.set(i, vm);
}
}
// odeslat klientum
ServerHandler.sendAll(Message.VALUE_MAP_EDIT_RESULT, vm);
}
}

View File

@ -0,0 +1,37 @@
package jnet.server.message;
import io.netty.channel.ChannelHandlerContext;
import jnet.lib.Message;
import jnet.lib.object.SnmpValueMap;
import jnet.lib.object.SnmpValueMapItem;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
public class RegisterValueMapNew implements Register {
public RegisterValueMapNew() {
}
@Override
public void processing(ChannelHandlerContext ctx, Message msg) {
SnmpValueMap vm = (SnmpValueMap) msg.getMsg();
// zapsat do databaze a ulozit prirazene id
int idValueMap = Database.addSnmpValueMap(vm.getName());
vm.setId(idValueMap);
for (SnmpValueMapItem item : vm.getItem()) {
int itemID = Database.addSnmpValueMapItem(idValueMap, item.getRawValue(), item.getMappedValue());
item.setId(itemID);
}
// pridat do lokalniho seznamu
Server.snmpValueMap.add(vm);
// odeslat klientum
ServerHandler.sendAll(Message.VALUE_MAP_NEW_RESULT, vm);
}
}

View File

@ -0,0 +1,60 @@
package jnet.server.networkserver;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import jnet.lib.LogFile;
public class NettyServerManager {
private EventLoopGroup boss;
private EventLoopGroup worker;
private ChannelFuture serverChannelFuture;
public void start(int port) {
Thread serverThread = new Thread(() -> {
boss = new NioEventLoopGroup(1);
worker = new NioEventLoopGroup();
try {
SslContext sslCtx = SslUtil.createServerSslContext();
ServerBootstrap b = new ServerBootstrap();
b.group(boss, worker)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInitializer(sslCtx))
.childOption(ChannelOption.SO_KEEPALIVE, true);
LogFile.printInfo("Starting Netty on port " + port);
serverChannelFuture = b.bind(port).sync();
// Čeká na uzavření kanálu
serverChannelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
LogFile.printInfo("Netty server interrupted.");
Thread.currentThread().interrupt();
} catch (Exception e) {
LogFile.printInfo("Netty error: " + e.getMessage());
} finally {
stop();
}
}, "Netty-Server-Thread");
serverThread.start();
}
public synchronized void stop() {
if (boss != null && !boss.isShuttingDown()) {
LogFile.printInfo("Shutting down Netty gracefully...");
// Gracefully uzavře kanály, počká na dokončení probíhajících zápisů a ukončí vlákna
boss.shutdownGracefully();
worker.shutdownGracefully();
LogFile.printInfo("Netty stopped.");
}
}
}

View File

@ -0,0 +1,31 @@
package jnet.server.networkserver;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
public class SecureServer {
public static void main(String[] args) throws Exception {
SslContext sslCtx = SslUtil.createServerSslContext();
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(boss, worker)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInitializer(sslCtx))
.childOption(ChannelOption.SO_KEEPALIVE, true);
b.bind(8443).sync().channel().closeFuture().sync();
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,85 @@
package jnet.server.networkserver;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.server.Server;
import jnet.server.message.MessageRegister;
import jnet.server.message.Register;
import jnet.server.userping.PingManager;
public class ServerHandler extends SimpleChannelInboundHandler<Object> {
private final MessageRegister messageRegistr = new MessageRegister();
private static final ChannelGroup allChannels
= new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void channelActive(ChannelHandlerContext ctx) {
LogFile.printInfo("New client: " + ctx.channel().remoteAddress());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
LogFile.printInfo("Client: " + ctx.channel().remoteAddress() + " disconnected");
// odebere kanal
allChannels.remove(ctx.channel());
// odebere ze seznamu klientu
Server.onlineClients.removeIf(onlineClient
-> onlineClient.getId().equals(String.valueOf(ctx.channel().id()))
);
// odesle zmenu stavajicim klientum
sendAll(new Message(Message.ONLINE_CLIENTS, Server.onlineClients));
// Zastavíme všechny pingy pro tohoto klienta
PingManager.stopAllPings(ctx.channel());
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof Message) {
Message message = (Message) msg;
LogFile.printDebug("Received message ID: " + message.getType());
Register register = messageRegistr.getRegister(message.getType());
if (register != null) {
register.processing(ctx, message);
}
} else {
LogFile.printDebug("Unknown message received");
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (cause instanceof java.net.SocketException && cause.getMessage().contains("Connection reset")) {
LogFile.printInfo("Client abruptly disconnected: " + ctx.channel().remoteAddress());
} else {
cause.printStackTrace();
}
ctx.close();
}
public static void addChannel(ChannelHandlerContext ctx) {
allChannels.add(ctx.channel());
}
public static ChannelGroup getAllChannels() {
return allChannels;
}
public static void sendAll(Message msq) {
getAllChannels().writeAndFlush(msq);
}
public static void sendAll(int type, Object msg) {
getAllChannels().writeAndFlush(new Message(type, msg));
}
}

View File

@ -0,0 +1,29 @@
package jnet.server.networkserver;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.ssl.SslContext;
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
private final SslContext sslCtx;
public ServerInitializer(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline()
.addLast("ssl", sslCtx.newHandler(ch.alloc()))
// ObjectDecoder používá LengthFieldBasedFrameDecoder automaticky
//.addLast("objectDecoder", new ObjectDecoder(ClassResolvers.cacheDisabled(null)))
//.addLast("objectEncoder", new ObjectEncoder())
.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)))
.addLast(new ObjectEncoder())
.addLast("handler", new ServerHandler());
}
}

View File

@ -0,0 +1,13 @@
package jnet.server.networkserver;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
public class SslUtil {
public static SslContext createServerSslContext() throws Exception {
SelfSignedCertificate ssc = new SelfSignedCertificate();
return SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
}
}

View File

@ -0,0 +1,125 @@
package jnet.server.probe;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import jnet.lib.LogFile;
import jnet.lib.OSDetector;
import jnet.lib.Status;
import jnet.lib.object.Node;
import jnet.lib.object.NodeState;
import jnet.lib.object.Site;
import jnet.server.EventManager;
import jnet.server.Server;
import jnet.server.SiteOperation;
import jnet.server.probe.ping.MonitorEngine;
import jnet.server.probe.ping.PingEngine;
import jnet.server.probe.ping.RawIcmpPingEngine;
public class Ping {
private static MonitorEngine engine;
public static void start() {
try {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.schedule(() -> {
run();
}, 5, TimeUnit.SECONDS);
scheduler.shutdown();
scheduler.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
LogFile.printErr("Failed runing ping probe: " + ex.getMessage());
}
}
private static void run() {
LogFile.printInfo("Ping probe starting...");
// Vytvoření mapy nodeId -> IP
Map<String, String> nodeIdToIp = new HashMap<>();
for (Site site : Server.site) {
for (Node node : site.getNode()) {
if (node.getType() == 1 && node.isPing()) {
// prida jen kdyz je typ=1 (zarizeni) a ping je zapnut
nodeIdToIp.put(String.valueOf(node.getId()), node.getIp());
}
}
}
LogFile.printInfo("Loaded " + nodeIdToIp.size() + " targets.");
if (nodeIdToIp.isEmpty()) {
LogFile.printInfo("No targets to monitor, exiting.");
return;
}
if (OSDetector.isWindows()) {
LogFile.printInfo("OS is Windows - using PingEngine (subprocess ping)");
// OPRAVA: cyklus každých 10 sekund, timeout 2 sekundy
engine = new PingEngine(10, 10, 2);
} else if (OSDetector.isDebian()) {
LogFile.printInfo("OS is Debian - using RawIcmpPingEngine");
engine = new RawIcmpPingEngine(10, 3000, 2);
} else {
LogFile.printInfo("OS is undefined - ping not running");
return;
}
engine.setTargets(nodeIdToIp);
LogFile.printInfo("Targets set.");
// Listener pro změny stavu
engine.addListener(event -> {
// Sestavíme text s latencí
String latencyText = event.up() ? event.latencyMs() + " ms" : "N/A";
// Toto se vypíše při každé kontrole (i když není změna)
// Detailní výpis všech informací
// LogFile.printDebug("Listener: node=" + event.nodeId() +
// ", ip=" + event.ip() +
// ", up=" + event.up() +
// ", latency=" + latencyText +
// ", firstReport=" + event.firstReport() +
// ", stateChanged=" + event.stateChanged());
//
NodeState nodeState = null;
if (event.firstReport()) {
if (event.up()) {
nodeState = new NodeState(Integer.parseInt(event.nodeId()), Status.OK);
} else {
EventManager.insertOfflineEvent(Integer.parseInt(event.nodeId()));
nodeState = new NodeState(Integer.parseInt(event.nodeId()), Status.OFFLINE);
}
SiteOperation.updateNodeStatus(nodeState);
} else if (event.stateChanged()) {
LogFile.printDebug("CHANGE: " + event.describe());
if (event.up()) {
EventManager.endEvent(Integer.parseInt(event.nodeId()));
nodeState = new NodeState(Integer.parseInt(event.nodeId()), Status.OK);
} else {
EventManager.insertOfflineEvent(Integer.parseInt(event.nodeId()));
nodeState = new NodeState(Integer.parseInt(event.nodeId()), Status.OFFLINE);
}
SiteOperation.updateNodeStatus(nodeState);
}
});
LogFile.printInfo("Starting engine...");
try {
engine.start();
LogFile.printInfo("Engine started successfully.");
} catch (Exception e) {
LogFile.printErr("Failed to start engine: " + e.getMessage());
}
}
public static void addOrUpdateTarget(int nodeId, String ip) {
engine.addOrUpdateTarget(String.valueOf(nodeId), ip);
}
public static void removeTarget(int nodeId) {
engine.removeTarget(String.valueOf(nodeId));
}
}

View File

@ -0,0 +1,36 @@
package jnet.server.probe.ping;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
/**
* Mapovani vybranych funkci standardni C knihovny (libc) pres JNA.
* Umoznuje otevrit RAW ICMP socket, coz standardni java.net API neumoznuje.
*
* DULEZITE: otevreni SOCK_RAW socketu vyzaduje bud beh pod rootem, nebo
* capability CAP_NET_RAW nastavenou na java binarce:
*
* sudo setcap cap_net_raw+ep $(readlink -f $(which java))
*
* (Pozor: setcap se musi nastavit na *skutecny* java binary, ne na symlink
* spravovany update-alternatives, ktery se muze pri aktualizaci JDK zmenit -
* pouzijte radeji plnou cestu k danemu JDK, viz README.)
*/
public interface CLibrary extends Library {
CLibrary INSTANCE = Native.load("c", CLibrary.class);
int socket(int domain, int type, int protocol);
int close(int fd);
int sendto(int sockfd, byte[] buf, int len, int flags, SockAddrIn destAddr, int addrlen);
int recvfrom(int sockfd, byte[] buf, int len, int flags, Pointer srcAddr, Pointer addrlen);
int setsockopt(int sockfd, int level, int optname, Timeval optval, int optlen);
int setsockopt(int sockfd, int level, int optname, IntByReference optval, int optlen);
}

View File

@ -0,0 +1,90 @@
package jnet.server.probe.ping;
import java.util.Arrays;
/**
* Sestaveni/parsovani ICMP paketu (RFC 792) na bajtove urovni.
*/
public final class IcmpPacketBuilder {
private static final int ICMP_ECHO_REQUEST = 8;
private static final int ICMP_ECHO_REPLY = 0;
private IcmpPacketBuilder() {
}
/**
* Sestavi ICMP echo request packet (hlavicka + payload) vcetne spocitaneho checksumu.
*/
public static byte[] buildEchoRequest(int identifier, int sequence, byte[] payload) {
byte[] packet = new byte[8 + payload.length];
packet[0] = (byte) ICMP_ECHO_REQUEST;
packet[1] = 0; // code
packet[2] = 0; // checksum - doplnime az po spocitani
packet[3] = 0;
packet[4] = (byte) ((identifier >> 8) & 0xFF);
packet[5] = (byte) (identifier & 0xFF);
packet[6] = (byte) ((sequence >> 8) & 0xFF);
packet[7] = (byte) (sequence & 0xFF);
System.arraycopy(payload, 0, packet, 8, payload.length);
int checksum = checksum(packet);
packet[2] = (byte) ((checksum >> 8) & 0xFF);
packet[3] = (byte) (checksum & 0xFF);
return packet;
}
/**
* Standardni 16-bitovy jednickovy doplnkovy soucet (one's complement checksum)
* pouzivany ICMP i IP hlavickami.
*/
static int checksum(byte[] buf) {
int sum = 0;
int i = 0;
int length = buf.length;
while (length > 1) {
int word = ((buf[i] << 8) & 0xFF00) | (buf[i + 1] & 0xFF);
sum += word;
if ((sum & 0xFFFF0000) != 0) {
sum &= 0xFFFF;
sum += 1;
}
i += 2;
length -= 2;
}
if (length > 0) {
sum += (buf[i] << 8) & 0xFF00;
if ((sum & 0xFFFF0000) != 0) {
sum &= 0xFFFF;
sum += 1;
}
}
return (~sum) & 0xFFFF;
}
/**
* Rozparsuje surova prijata data z raw socketu (obsahuji IP hlavicku + ICMP zpravu)
* a vrati identifier/sequence z ICMP echo reply, nebo null, pokud to neni echo reply.
*/
public static ParsedReply parseEchoReply(byte[] buf, int length) {
if (length < 20) return null; // min. delka IP hlavicky
int ihl = (buf[0] & 0x0F) * 4; // Internet Header Length v bajtech
if (length < ihl + 8) return null;
int type = buf[ihl] & 0xFF;
if (type != ICMP_ECHO_REPLY) return null;
int identifier = ((buf[ihl + 4] & 0xFF) << 8) | (buf[ihl + 5] & 0xFF);
int sequence = ((buf[ihl + 6] & 0xFF) << 8) | (buf[ihl + 7] & 0xFF);
byte[] sourceAddress = Arrays.copyOfRange(buf, 12, 16);
return new ParsedReply(identifier, sequence, sourceAddress);
}
public record ParsedReply(int identifier, int sequence, byte[] sourceAddress) {
}
}

View File

@ -0,0 +1,29 @@
package jnet.server.probe.ping;
import java.time.LocalDateTime;
/**
* Reprezentuje jeden monitorovany cil - IP adresu se jejim aktualnim stavem.
* Pole jsou volatile/atomicka, protoze do nich zapisuji paralelni ping-vlakna
* a zaroven se z nich cte pri generovani web dashboardu.
*/
public class IpTarget {
public final String nodeId; // unikátní identifikátor (primární klíč)
public volatile String ip; // IP adresa (může se měnit, volatile pro viditelnost)
public volatile boolean up = false;
public volatile boolean everChecked = false;
public volatile long lastLatencyMs = -1;
public volatile LocalDateTime lastChange;
public volatile LocalDateTime lastCheck;
public volatile int consecutiveFails = 0;
public volatile int consecutiveOk = 0;
public IpTarget(String nodeId, String ip) {
this.nodeId = nodeId;
this.ip = ip;
}
}

View File

@ -0,0 +1,28 @@
package jnet.server.probe.ping;
import java.util.Collection;
import java.util.Map;
/**
* Spolecne rozhrani pro monitorovaci engine - umoznuje mit vice implementaci
* (subprocess ping vs. raw ICMP socket) se stejnym verejnym API, takze zbytek
* aplikace (napr. napojeni na Netty) neni na konkretni implementaci zavisly.
*/
public interface MonitorEngine {
void addOrUpdateTarget(String nodeId, String ip);
void removeTarget(String nodeId);
void setTargets(Map<String, String> nodeIdToIp); // nodeId -> IP
Collection<IpTarget> getTargets();
void addListener(StatusListener listener);
void removeListener(StatusListener listener);
void start();
void stop();
}

View File

@ -0,0 +1,201 @@
package jnet.server.probe.ping;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import jnet.lib.LogFile;
public class PingEngine implements MonitorEngine {
private final ConcurrentHashMap<String, IpTarget> targets = new ConcurrentHashMap<>();
private final CopyOnWriteArrayList<StatusListener> listeners = new CopyOnWriteArrayList<>();
private final ExecutorService pingPool;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private final int cycleIntervalSeconds;
private final int pingTimeoutSeconds;
private ScheduledFuture<?> cycleHandle;
private Path watchedFile;
private long watchedFileLastModified = -1;
public PingEngine(int threadPoolSize, int cycleIntervalSeconds, int pingTimeoutSeconds) {
this.pingPool = Executors.newFixedThreadPool(threadPoolSize);
this.cycleIntervalSeconds = cycleIntervalSeconds;
this.pingTimeoutSeconds = pingTimeoutSeconds;
}
@Override
public void addOrUpdateTarget(String nodeId, String ip) {
//LogFile.printDebug("ADD ping target (node: " + nodeId + " ip: " + ip + ")");
targets.compute(nodeId, (k, existing) -> {
if (existing == null) {
return new IpTarget(nodeId, ip);
} else {
if (!existing.ip.equals(ip)) {
existing.ip = ip;
}
return existing;
}
});
}
@Override
public void removeTarget(String nodeId) {
targets.remove(nodeId);
}
@Override
public void setTargets(Map<String, String> nodeIdToIp) {
targets.keySet().retainAll(nodeIdToIp.keySet());
for (Map.Entry<String, String> entry : nodeIdToIp.entrySet()) {
addOrUpdateTarget(entry.getKey(), entry.getValue());
}
}
@Override
public Collection<IpTarget> getTargets() {
return targets.values();
}
@Override
public void addListener(StatusListener listener) {
listeners.add(listener);
}
@Override
public void removeListener(StatusListener listener) {
listeners.remove(listener);
}
public void enableFileWatch(Path file) {
this.watchedFile = file;
reloadFromFileIfChanged();
}
private void reloadFromFileIfChanged() {
if (watchedFile == null) {
return;
}
try {
File f = watchedFile.toFile();
if (!f.exists()) {
return;
}
long modified = f.lastModified();
if (modified == watchedFileLastModified) {
return;
}
watchedFileLastModified = modified;
Set<String> seen = new HashSet<>();
List<String> lines = Files.readAllLines(watchedFile);
for (String raw : lines) {
String line = raw.trim();
if (line.isEmpty() || line.startsWith("#")) {
continue;
}
String[] parts = line.split(",", 2);
String nodeId = parts[0].trim();
String ip = parts.length > 1 ? parts[1].trim() : nodeId;
if (nodeId.isEmpty() || ip.isEmpty()) {
continue;
}
seen.add(nodeId);
addOrUpdateTarget(nodeId, ip);
}
targets.keySet().retainAll(seen);
} catch (IOException e) {
System.err.println("Chyba při načítání " + watchedFile + ": " + e.getMessage());
}
}
@Override
public void start() {
cycleHandle = scheduler.scheduleAtFixedRate(
this::runCycle, 0, cycleIntervalSeconds, TimeUnit.SECONDS);
}
@Override
public void stop() {
if (cycleHandle != null) {
cycleHandle.cancel(true);
}
scheduler.shutdownNow();
pingPool.shutdownNow();
}
private void runCycle() {
reloadFromFileIfChanged();
for (IpTarget target : targets.values()) {
CompletableFuture
.supplyAsync(() -> PingUtil.ping(target.ip, pingTimeoutSeconds), pingPool)
.thenAccept(latencyMs -> handleResult(target, latencyMs))
.exceptionally(ex -> {
System.err.println("Chyba při pingu " + target.ip + ": " + ex.getMessage());
return null;
});
}
}
// ==================== OPRAVENÁ METODA ====================
private void handleResult(IpTarget target, long latencyMs) {
boolean nowUp = latencyMs >= 0;
LocalDateTime now = LocalDateTime.now();
boolean everCheckedBefore = target.everChecked;
// ULOŽÍME STARÝ STAV PŘED PŘEPSÁNÍM
boolean previouslyReportedUp = target.up;
target.up = nowUp;
target.lastLatencyMs = nowUp ? latencyMs : -1;
target.lastCheck = now;
target.everChecked = true;
if (nowUp) {
target.consecutiveOk++;
target.consecutiveFails = 0;
} else {
target.consecutiveFails++;
target.consecutiveOk = 0;
}
// POROVNÁVÁME S ULOŽENÝM STARÝM STAVEM
boolean stateChanged = everCheckedBefore && (nowUp != previouslyReportedUp);
if (stateChanged) {
target.lastChange = now;
}
boolean firstReport = !everCheckedBefore;
StatusEvent event = new StatusEvent(
target.nodeId,
target.ip,
nowUp,
target.lastLatencyMs,
stateChanged,
firstReport,
now
);
for (StatusListener listener : listeners) {
listener.onUpdate(event);
}
}
}

View File

@ -0,0 +1,84 @@
package jnet.server.probe.ping;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Provadi ICMP ping pomoci systemoveho prikazu "ping".
*
* Proc systemovy prikaz a ne InetAddress.isReachable()?
* - isReachable() potrebuje bezet pod rootem, aby pouzil skutecne ICMP echo,
* jinak casto padne zpet na TCP echo (port 7), coz na vetsine cilu neprojde.
* - Systemovy binarni "ping" na Linuxu ma nastaveny setuid bit, takze funguje
* spolehlive i pod beznym uzivatelem.
*/
/**
* Provádí ICMP ping pomocí systemového příkazu "ping".
* Detekuje OS a používá správnou syntaxi (Windows vs. Linux).
*/
public class PingUtil {
// Regex pro Linux: time=1.23 ms nebo time<1 ms
private static final Pattern LINUX_TIME_PATTERN = Pattern.compile("time[=<]\\s*([0-9.]+)");
// Regex pro Windows: čas=1ms nebo time=1ms (anglická lokalizace) nebo doba=1ms
private static final Pattern WINDOWS_TIME_PATTERN = Pattern.compile("(?:čas|time|doba)[=<]\\s*([0-9.]+)");
/**
* Odešle jeden ICMP echo request.
*
* @param ip cílová IP adresa nebo hostname
* @param timeoutSeconds timeout pro odpověď v sekundách
* @return latenci v ms, nebo -1 pokud cil neodpověděl
*/
public static long ping(String ip, int timeoutSeconds) {
try {
ProcessBuilder pb;
if (isWindows()) {
// Windows: ping -n 1 -w timeoutMs ip
int timeoutMs = timeoutSeconds * 1000;
pb = new ProcessBuilder("ping", "-n", "1", "-w", String.valueOf(timeoutMs), ip);
} else {
// Linux/Unix: ping -c 1 -W timeoutSeconds ip
pb = new ProcessBuilder("ping", "-c", "1", "-W", String.valueOf(timeoutSeconds), ip);
}
pb.redirectErrorStream(true);
Process proc = pb.start();
String lastTimeMatch = null;
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(proc.getInputStream()))) {
String line;
Pattern pattern = isWindows() ? WINDOWS_TIME_PATTERN : LINUX_TIME_PATTERN;
while ((line = reader.readLine()) != null) {
Matcher m = pattern.matcher(line);
if (m.find()) {
lastTimeMatch = m.group(1);
}
}
}
boolean finished = proc.waitFor(timeoutSeconds + 2L, TimeUnit.SECONDS);
if (!finished) {
proc.destroyForcibly();
return -1;
}
int exitCode = proc.exitValue();
// Na Windows je exit code 0 při úspěchu, na Linuxu také
if (exitCode == 0 && lastTimeMatch != null) {
return Math.round(Double.parseDouble(lastTimeMatch));
}
return -1;
} catch (Exception e) {
return -1;
}
}
private static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}
}

View File

@ -0,0 +1,276 @@
package jnet.server.probe.ping;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class RawIcmpPingEngine implements MonitorEngine {
private static final int AF_INET = 2;
private static final int SOCK_RAW = 3;
private static final int IPPROTO_ICMP = 1;
private static final int SOL_SOCKET = 1;
private static final int SO_RCVTIMEO = 20;
private static final int SO_RCVBUF = 8;
private final ConcurrentHashMap<String, IpTarget> targets = new ConcurrentHashMap<>();
private final CopyOnWriteArrayList<StatusListener> listeners = new CopyOnWriteArrayList<>();
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private final ExecutorService receiveExecutor = Executors.newSingleThreadExecutor();
private final int cycleIntervalSeconds;
private final int replyWaitMillis;
private final int downThreshold;
private final int identifier;
private final ConcurrentHashMap<Integer, IpTarget> sequenceToTarget = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, Long> sequenceSentAtNanos = new ConcurrentHashMap<>();
private final AtomicInteger sequenceCounter = new AtomicInteger(0);
private int socketFd = -1;
private volatile boolean running = false;
private ScheduledFuture<?> cycleHandle;
public RawIcmpPingEngine(int cycleIntervalSeconds, int replyWaitMillis) {
this(cycleIntervalSeconds, replyWaitMillis, 2);
}
public RawIcmpPingEngine(int cycleIntervalSeconds, int replyWaitMillis, int downThreshold) {
this.cycleIntervalSeconds = cycleIntervalSeconds;
this.replyWaitMillis = replyWaitMillis;
this.downThreshold = Math.max(1, downThreshold);
this.identifier = (int) (ProcessHandle.current().pid() & 0xFFFF);
}
@Override
public void addOrUpdateTarget(String nodeId, String ip) {
targets.compute(nodeId, (k, existing) -> {
if (existing == null) {
return new IpTarget(nodeId, ip);
} else {
if (!existing.ip.equals(ip)) {
existing.ip = ip;
}
return existing;
}
});
}
@Override
public void removeTarget(String nodeId) {
targets.remove(nodeId);
}
@Override
public void setTargets(Map<String, String> nodeIdToIp) {
targets.keySet().retainAll(nodeIdToIp.keySet());
for (Map.Entry<String, String> entry : nodeIdToIp.entrySet()) {
addOrUpdateTarget(entry.getKey(), entry.getValue());
}
}
@Override
public Collection<IpTarget> getTargets() {
return targets.values();
}
@Override
public void addListener(StatusListener listener) {
listeners.add(listener);
}
@Override
public void removeListener(StatusListener listener) {
listeners.remove(listener);
}
@Override
public void start() {
openSocket();
running = true;
receiveExecutor.submit(this::receiveLoop);
cycleHandle = scheduler.scheduleAtFixedRate(this::runCycle, 0, cycleIntervalSeconds, TimeUnit.SECONDS);
}
@Override
public void stop() {
running = false;
if (cycleHandle != null) cycleHandle.cancel(true);
scheduler.shutdownNow();
receiveExecutor.shutdownNow();
closeSocket();
}
private void openSocket() {
socketFd = CLibrary.INSTANCE.socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (socketFd < 0) {
throw new IllegalStateException(
"Nepodařilo se otevřít RAW ICMP socket (errno=" + Native.getLastError() + "). "
+ "Běžte program jako root, nebo nastavte capability: "
+ "sudo setcap cap_net_raw+ep <cesta-k-java-binarce>");
}
Timeval tv = new Timeval();
tv.tv_sec = new NativeLong(0);
tv.tv_usec = new NativeLong(200_000);
CLibrary.INSTANCE.setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, tv, tv.size());
setReceiveBufferSize(1 << 20);
}
private void setReceiveBufferSize(int bytes) {
com.sun.jna.ptr.IntByReference size = new com.sun.jna.ptr.IntByReference(bytes);
CLibrary.INSTANCE.setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, size, 4);
}
private void closeSocket() {
if (socketFd >= 0) {
CLibrary.INSTANCE.close(socketFd);
socketFd = -1;
}
}
private void runCycle() {
try {
runCycleInternal();
} catch (Throwable t) {
System.err.println("runCycle selhal, cyklus VŠAK pokračuje dál:");
t.printStackTrace();
}
}
private void runCycleInternal() {
Set<Integer> sequencesThisCycle = new HashSet<>();
for (IpTarget target : targets.values()) {
int seq = sequenceCounter.updateAndGet(v -> (v + 1) & 0xFFFF);
sequencesThisCycle.add(seq);
sequenceToTarget.put(seq, target);
SockAddrIn addr = new SockAddrIn();
addr.sin_family = AF_INET;
try {
addr.sin_addr = InetAddress.getByName(target.ip).getAddress();
} catch (Exception e) {
sequenceToTarget.remove(seq);
continue;
}
byte[] payload = new byte[32];
byte[] packet = IcmpPacketBuilder.buildEchoRequest(identifier, seq, payload);
sequenceSentAtNanos.put(seq, System.nanoTime());
int sent = CLibrary.INSTANCE.sendto(socketFd, packet, packet.length, 0, addr, addr.size());
if (sent < 0) {
System.err.println("sendto selhal pro " + target.ip + " (errno=" + Native.getLastError() + ")");
}
}
scheduler.schedule(() -> evaluateTimeouts(sequencesThisCycle), replyWaitMillis, TimeUnit.MILLISECONDS);
}
private void receiveLoop() {
byte[] buffer = new byte[1024];
while (running) {
try {
int received = CLibrary.INSTANCE.recvfrom(socketFd, buffer, buffer.length, 0, Pointer.NULL, Pointer.NULL);
if (received > 0) {
IcmpPacketBuilder.ParsedReply reply = IcmpPacketBuilder.parseEchoReply(buffer, received);
if (reply != null && reply.identifier() == identifier) {
handleReply(reply.sequence());
}
}
} catch (Throwable t) {
System.err.println("receiveLoop selhal, pokračuje dál:");
t.printStackTrace();
}
}
}
private void handleReply(int sequence) {
IpTarget target = sequenceToTarget.remove(sequence);
Long sentAtNanos = sequenceSentAtNanos.remove(sequence);
if (target == null || sentAtNanos == null) return;
long latencyMs = Math.max(0, (System.nanoTime() - sentAtNanos) / 1_000_000);
updateTarget(target, true, latencyMs);
}
private void evaluateTimeouts(Set<Integer> sequencesFromThisCycle) {
for (Integer seq : sequencesFromThisCycle) {
IpTarget target = sequenceToTarget.remove(seq);
sequenceSentAtNanos.remove(seq);
if (target != null) {
updateTarget(target, false, -1);
}
}
}
// ==================== UPRAVENÁ METODA ====================
private void updateTarget(IpTarget target, boolean rawUp, long latencyMs) {
LocalDateTime now = LocalDateTime.now();
boolean previouslyReportedUp = target.up;
boolean everCheckedBefore = target.everChecked;
if (rawUp) {
target.consecutiveOk++;
target.consecutiveFails = 0;
} else {
target.consecutiveFails++;
target.consecutiveOk = 0;
}
boolean reportedUp;
if (rawUp) {
reportedUp = true;
} else if (!everCheckedBefore) {
reportedUp = false;
} else {
reportedUp = previouslyReportedUp && target.consecutiveFails < downThreshold;
}
boolean stateChanged = everCheckedBefore && (reportedUp != previouslyReportedUp);
boolean firstReport = !everCheckedBefore;
target.up = reportedUp;
if (rawUp) {
target.lastLatencyMs = latencyMs;
} else if (!reportedUp) {
target.lastLatencyMs = -1;
}
target.lastCheck = now;
target.everChecked = true;
if (stateChanged) target.lastChange = now;
StatusEvent event = new StatusEvent(
target.nodeId,
target.ip,
reportedUp,
target.lastLatencyMs,
stateChanged,
firstReport,
now
);
for (StatusListener listener : listeners) {
listener.onUpdate(event);
}
}
}

View File

@ -0,0 +1,27 @@
package jnet.server.probe.ping;
import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;
/**
* Odpovida C strukture "struct sockaddr_in" (viz <netinet/in.h>).
* sin_addr drzime primo jako 4 bajty (presne v poradi, v jakem je vraci
* InetAddress.getAddress() - tedy uz ve "network byte order"), abychom se
* vyhnuli zamene endianity pri prevodu na/z int.
*
* DULEZITE: trida MUSI byt public, jinak na ni JNA nemuze sahat reflexi
* z jineho balicku (IllegalAccessException i pres public pole uvnitr).
*/
public class SockAddrIn extends Structure {
public short sin_family;
public short sin_port;
public byte[] sin_addr = new byte[4];
public byte[] sin_zero = new byte[8];
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("sin_family", "sin_port", "sin_addr", "sin_zero");
}
}

View File

@ -0,0 +1,5 @@
package jnet.server.probe.ping;
public interface StatusChangeListener {
void onStatusChanged(String ip, String newStatus);
}

View File

@ -0,0 +1,32 @@
package jnet.server.probe.ping;
import java.time.LocalDateTime;
/**
* Jedna udalost o vysledku kontroly konkretni IP adresy.
* Predava se registrovanym listenerum (napr. pro broadcast pres Netty).
*
* @param ip IP adresa / hostname
* @param id id cile
* @param up true = cil odpovedel, false = neodpovedel (timeout)
* @param latencyMs latence v ms, pokud up == true; pokud up == false, je vzdy -1
* @param stateChanged true, pokud se stav zmenil oproti predchozi kontrole (UP<->DOWN)
* @param timestamp cas kontroly
*/
public record StatusEvent(
String nodeId,
String ip,
boolean up,
long latencyMs,
boolean stateChanged,
boolean firstReport, // true pro první hlášení po kontrole
LocalDateTime timestamp
) {
public String describe() {
if (up) {
return "Node " + nodeId + " (" + ip + ") -> UP, odezva " + latencyMs + " ms";
} else {
return "Node " + nodeId + " (" + ip + ") -> DOWN";
}
}
}

View File

@ -0,0 +1,17 @@
package jnet.server.probe.ping;
/**
* Implementujte toto rozhrani, abyste dostavali vysledky kontrol.
* Volano asynchronne z interniho ping-poolu po KAZDE kontrole (nejen pri
* zmene stavu) - v StatusEvent.stateChanged() poznate, jestli doslo ke zmene.
*
* Typicke pouziti: v implementaci rozeslat zpravu vsem pripojenym Netty
* klientum (napr. pres ChannelGroup.writeAndFlush(...)).
*
* Implementace by mela byt rychla a neblokujici - vola se primo z vlakna
* ping-poolu.
*/
@FunctionalInterface
public interface StatusListener {
void onUpdate(StatusEvent event);
}

View File

@ -0,0 +1,24 @@
package jnet.server.probe.ping;
import com.sun.jna.NativeLong;
import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;
/**
* Odpovida C strukture "struct timeval" (viz <sys/time.h>), pouzivane pro
* nastaveni SO_RCVTIMEO (timeout na recvfrom).
*
* DULEZITE: trida MUSI byt public, jinak na ni JNA nemuze sahat reflexi
* z jineho balicku (IllegalAccessException i pres public pole uvnitr).
*/
public class Timeval extends Structure {
public NativeLong tv_sec;
public NativeLong tv_usec;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("tv_sec", "tv_usec");
}
}

View File

@ -0,0 +1,24 @@
package jnet.server.probe.snmp;
public class MonitorConfig {
public int id; // unikátní ID, které si uživatel zvolí
public String ip;
public String community;
public String port = "161";
public int version;
public String oid;
public int interval; // v sekundách
public MonitorConfig() {}
public MonitorConfig(int id, String ip, String community, String port, int version, String oid, int interval) {
this.id = id;
this.ip = ip;
this.community = community;
this.port = port;
this.version = version;
this.oid = oid;
this.interval = interval;
}
}

View File

@ -0,0 +1,151 @@
package jnet.server.probe.snmp;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import jnet.lib.object.Node;
import jnet.lib.object.NodeProbe;
import jnet.lib.object.Site;
import jnet.lib.object.SnmpProfile;
import jnet.server.Server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import jnet.lib.LogFile;
public class NodeProbeManager implements AutoCloseable {
private Snmp snmp = null;
private ScheduledExecutorService scheduler = null;
private final ConcurrentHashMap<Integer, TaskEntry> tasks = new ConcurrentHashMap<>();
private final List<SnmpResultListener> listeners = new CopyOnWriteArrayList<>();
private static class TaskEntry {
final MonitorConfig config;
final ScheduledFuture<?> future;
final SnmpMonitorTask task;
TaskEntry(MonitorConfig config, ScheduledFuture<?> future, SnmpMonitorTask task) {
this.config = config;
this.future = future;
this.task = task;
}
}
public NodeProbeManager() {
try {
TransportMapping<?> transport = new DefaultUdpTransportMapping();
transport.listen();
this.snmp = new Snmp(transport);
this.scheduler = Executors.newScheduledThreadPool(10);
} catch (Exception ex) {
LogFile.printDebug("[NodeProbeManager] Error: " + ex.getMessage());
}
loadTask();
}
public void loadTask() {
for (Site site : Server.site) {
for (Node node : site.getNode()) {
SnmpProfile profile = Server.snmpProfile.stream()
.filter(p -> p.getId() == node.getSnmpProfile())
.findFirst()
.orElse(null);
for (NodeProbe nodeProbe : node.getProbe()) {
MonitorConfig mc = new MonitorConfig(
nodeProbe.getId(),
node.getIp(),
profile.getCommunityRead(),
profile.getPort(),
profile.getVersion(),
nodeProbe.getOid(),
nodeProbe.getInterval()
);
addTask(mc);
}
}
}
}
/**
* Přidá úlohu s ID z config.id. Pokud už ID existuje, vyhodí výjimku.
*/
public synchronized void addTask(MonitorConfig cfg) {
if (tasks.containsKey(cfg.id)) {
throw new IllegalArgumentException("Task s ID " + cfg.id + " již existuje.");
}
CommunityTarget target = createTarget(cfg);
OID oid = new OID(cfg.oid);
String identifier = cfg.ip + ":" + cfg.oid;
SnmpMonitorTask task = new SnmpMonitorTask(cfg.id, snmp, target, oid, identifier, listeners);
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task, 0, cfg.interval, TimeUnit.SECONDS);
tasks.put(cfg.id, new TaskEntry(cfg, future, task));
LogFile.printDebug("[NodeProbe Manager] Přidána úloha ID " + cfg.id);
}
/**
* Odebere úlohu podle ID.
*/
public synchronized boolean removeTask(int id) {
TaskEntry entry = tasks.remove(id);
if (entry != null) {
entry.future.cancel(false);
LogFile.printDebug("[NodeProbe Manager] Odebrána úloha ID " + id);
return true;
}
return false;
}
/**
* Vrátí kopii seznamu aktivních úloh.
*/
public synchronized List<MonitorConfig> getTasks() {
List<MonitorConfig> list = new ArrayList<>();
for (TaskEntry e : tasks.values()) {
list.add(e.config);
}
return list;
}
// --- Listener registrace ---
public void addListener(SnmpResultListener listener) {
listeners.add(listener);
}
public void removeListener(SnmpResultListener listener) {
listeners.remove(listener);
}
// --- pomocné ---
private CommunityTarget createTarget(MonitorConfig cfg) {
CommunityTarget target = new CommunityTarget();
target.setAddress(new UdpAddress(cfg.ip + "/" + cfg.port));
target.setCommunity(new OctetString(cfg.community));
target.setVersion(SnmpConstants.version2c);
target.setTimeout(3000);
target.setRetries(1);
return target;
}
@Override
public void close() {
LogFile.printInfo("[NodeProbe Manager] Ukončuji...");
try { snmp.close(); } catch (IOException e) { LogFile.printErr("[NodeProbe Manager] Error: " + e.getMessage()); }
scheduler.shutdownNow();
}
}

View File

@ -0,0 +1,115 @@
package jnet.server.probe.snmp;
import jnet.lib.object.Node;
import jnet.lib.object.NodeProbe;
import jnet.lib.object.Site;
import jnet.server.Server;
import jnet.server.networkserver.ServerHandler;
import jnet.lib.Message;
import org.snmp4j.smi.Variable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import jnet.lib.object.SnmpResult;
/**
* Zpracovává výsledky SNMP dotazů: - ihned aktualizuje lokální cache
* (NodeProbe.value) - ukládá výsledky/chyby do fronty - každých N sekund odešle
* dávku všem klientům
*/
public class SnmpBatchProcessor implements SnmpResultListener, AutoCloseable {
private final BlockingQueue<SnmpResult> queue = new LinkedBlockingQueue<>();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private final int batchIntervalSeconds;
private NodeProbeManager manager;
public SnmpBatchProcessor(int batchIntervalSeconds) {
this.batchIntervalSeconds = batchIntervalSeconds;
}
/**
* Inicializuje procesor: zaregistruje se jako listener a spustí periodické
* odesílání.
*
* @param manager SnmpProbeManager, ke kterému se připojí
*/
public void init(NodeProbeManager manager) {
this.manager = manager;
manager.addListener(this);
start();
}
/**
* Spustí periodické odesílání dávek.
*/
private void start() {
scheduler.scheduleAtFixedRate(this::flushBatch, batchIntervalSeconds, batchIntervalSeconds, TimeUnit.SECONDS);
}
/**
* Zastaví periodickou úlohu, odešle zbylé položky a odregistruje se z
* manageru.
*/
@Override
public void close() {
scheduler.shutdownNow();
// odešle zbylé položky
flushBatch();
if (manager != null) {
manager.removeListener(this);
}
}
// --- Implementace SnmpResultListener ---
@Override
public void onResult(int taskId, String oid, Variable value) {
queue.offer(new SnmpResult(taskId, oid, value, null, true));
}
@Override
public void onError(int taskId, String oid, String error) {
// Chyby také zařadíme do fronty (pro informování klientů)
queue.offer(new SnmpResult(taskId, oid, null, error, false));
}
// --- interní metody ---
/**
* Vybere všechny položky z fronty a odešle je jako jednu dávku.
*/
private void flushBatch() {
List<SnmpResult> batch = new ArrayList<>();
queue.drainTo(batch);
if (!batch.isEmpty()) {
// 1. Ihned aktualizovat lokální cache (NodeProbe)
for (SnmpResult snmpResult : batch) {
updateNodeProbeValue(snmpResult.getTaskId(), snmpResult.getValue());
}
// 2. Odeslat
ServerHandler.sendAll(Message.SNMP_PROBE_VALUE, batch);
}
}
/**
* Najde NodeProbe podle taskId a nastaví mu hodnotu. (Převzato z původního
* listeneru v Server.java)
*/
private void updateNodeProbeValue(int idProbe, Object value) {
for (Site site : Server.site) {
for (Node node : site.getNode()) {
for (NodeProbe nodeProbe : node.getProbe()) {
if (nodeProbe.getId() == idProbe) {
nodeProbe.setValue((Variable) value);
return; // nalezeno
}
}
}
}
}
}

View File

@ -0,0 +1,86 @@
package jnet.server.probe.snmp;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.snmp4j.smi.Variable;
public class SnmpMonitorTask implements Runnable {
private final int taskId;
private final Snmp snmp;
private final CommunityTarget target;
private final OID oid;
private final String identifier;
private final List<SnmpResultListener> listeners;
public SnmpMonitorTask(int taskId, Snmp snmp, CommunityTarget target, OID oid,
String identifier, List<SnmpResultListener> listeners) {
this.taskId = taskId;
this.snmp = snmp;
this.target = target;
this.oid = oid;
this.identifier = identifier;
this.listeners = listeners;
}
@Override
public void run() {
try {
PDU pdu = new PDU();
pdu.add(new VariableBinding(oid));
pdu.setType(PDU.GET);
ResponseEvent event = snmp.send(pdu, target);
if (event == null) {
notifyError("Žádná odpověď (timeout)");
return;
}
PDU response = event.getResponse();
if (response == null) {
notifyError("Timeout / agent nedostupný");
return;
}
int errorStatus = response.getErrorStatus();
if (errorStatus != PDU.noError) {
notifyError("SNMP chyba: " + response.getErrorStatusText());
return;
}
VariableBinding vb = response.get(0);
if (vb != null) {
Variable value = vb.getVariable();
notifyResult(value);
// také log
// System.out.println("[" + getCurrentTime() + "] [Task " + taskId + "] " + identifier + " = " + value);
} else {
notifyError("Prázdná odpověď");
}
} catch (Exception e) {
notifyError("Výjimka: " + e.getMessage());
}
}
private void notifyResult(Variable value) {
for (SnmpResultListener l : listeners) {
try { l.onResult(taskId, oid.toString(), value); } catch (Exception ignored) {}
}
}
private void notifyError(String error) {
for (SnmpResultListener l : listeners) {
try { l.onError(taskId, oid.toString(), error); } catch (Exception ignored) {}
}
}
private String getCurrentTime() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}

Some files were not shown because too many files have changed in this diff Show More