Initial commit.
This commit is contained in:
commit
a97b32c9d4
30
.gitignore
vendored
Normal file
30
.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Built files
|
||||||
|
out/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/
|
||||||
|
nbbuild/
|
||||||
|
dist/
|
||||||
|
nbdist/
|
||||||
|
.nb-gradle/
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
10
.idea/artifacts/calmnettest_jar.xml
Normal file
10
.idea/artifacts/calmnettest_jar.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<component name="ArtifactManager">
|
||||||
|
<artifact type="jar" build-on-make="true" name="calmnettest:jar">
|
||||||
|
<output-path>$PROJECT_DIR$/out/artifacts/calmnettest_jar</output-path>
|
||||||
|
<root id="archive" name="calmnettest.jar">
|
||||||
|
<element id="module-output" name="calmnettest" />
|
||||||
|
<element id="library" level="application" name="calmnetlib" />
|
||||||
|
<element id="library" level="application" name="calmstdcrypt" />
|
||||||
|
</root>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
1
.idea/description.html
Normal file
1
.idea/description.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<html>Simple <b>Java</b> application that includes a class with <code>main()</code> method</html>
|
7
.idea/discord.xml
Normal file
7
.idea/discord.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DiscordProjectSettings">
|
||||||
|
<option name="show" value="PROJECT_FILES" />
|
||||||
|
<option name="description" value="" />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/encodings.xml
Normal file
6
.idea/encodings.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="PROJECT" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
12
.idea/misc.xml
Normal file
12
.idea/misc.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="EntryPointsManager">
|
||||||
|
<entry_points version="2.0" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectKey">
|
||||||
|
<option name="state" value="project://e2804f05-5315-4fc6-a121-c522a6c26470" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/calmnettest.iml" filepath="$PROJECT_DIR$/calmnettest.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
3
.idea/project-template.xml
Normal file
3
.idea/project-template.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<input-field default="com.company">IJ_BASE_PACKAGE</input-field>
|
||||||
|
</template>
|
124
.idea/uiDesigner.xml
Normal file
124
.idea/uiDesigner.xml
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Palette2">
|
||||||
|
<group name="Swing">
|
||||||
|
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Button" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="RadioButton" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="CheckBox" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Label" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||||
|
<preferred-size width="-1" height="20" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
</group>
|
||||||
|
</component>
|
||||||
|
</project>
|
29
LICENSE
Normal file
29
LICENSE
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2022, Captain ALM
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Captain ALM Network Library Tester (Java)
|
||||||
|
|
||||||
|
This is the tester for the [calmnetlib](https://code.mrmelon54.xyz/alfred/calmnetlib) java library.
|
||||||
|
|
||||||
|
There is a keystore file with the password keystore containing a self-signed localhost certificate for testing.
|
||||||
|
|
||||||
|
This application targets Java 8.
|
||||||
|
|
||||||
|
(C) Captain ALM 2022 - Under the BSD 3-Clause License
|
13
calmnettest.iml
Normal file
13
calmnettest.iml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="calmstdcrypt" level="application" />
|
||||||
|
<orderEntry type="library" name="calmnetlib" level="application" />
|
||||||
|
</component>
|
||||||
|
</module>
|
BIN
keystore.jks
Normal file
BIN
keystore.jks
Normal file
Binary file not shown.
3
src/META-INF/MANIFEST.MF
Normal file
3
src/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: com.captainalm.test.calmnet.Main
|
||||||
|
|
66
src/com/captainalm/test/calmnet/AKNPacket.java
Normal file
66
src/com/captainalm/test/calmnet/AKNPacket.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.packet.IPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketException;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketProtocolInformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides the acknowledgement packet.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public class AKNPacket implements IPacket {
|
||||||
|
private static final PacketProtocolInformation protocol = new PacketProtocolInformation((byte) 1, (byte) 3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the packet is valid.
|
||||||
|
*
|
||||||
|
* @return Is the packet valid?
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the protocol information.
|
||||||
|
*
|
||||||
|
* @return The protocol information.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PacketProtocolInformation getProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the protocol information statically.
|
||||||
|
*
|
||||||
|
* @return The protocol information.
|
||||||
|
*/
|
||||||
|
public static PacketProtocolInformation getTheProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the packet payload to a byte array.
|
||||||
|
*
|
||||||
|
* @return The packet payload data.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] savePayload() throws PacketException {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the packet payload from save data.
|
||||||
|
*
|
||||||
|
* @param packetData The packet payload data.
|
||||||
|
* @throws NullPointerException The new store data is null.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadPayload(byte[] packetData) throws PacketException {
|
||||||
|
if (packetData == null) throw new NullPointerException("packetData is null");
|
||||||
|
}
|
||||||
|
}
|
141
src/com/captainalm/test/calmnet/DataPacket.java
Normal file
141
src/com/captainalm/test/calmnet/DataPacket.java
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.packet.IPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketException;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketProtocolInformation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the data packet to store a byte array that can be backed to a file.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public class DataPacket implements IPacket {
|
||||||
|
private static final PacketProtocolInformation protocol = new PacketProtocolInformation((byte) 1, (byte) 1);
|
||||||
|
|
||||||
|
protected File backingFile;
|
||||||
|
protected byte[] backedData;
|
||||||
|
protected final Object slock = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new DataPacket with initial data.
|
||||||
|
*
|
||||||
|
* @param dataIn The data to initially use.
|
||||||
|
*/
|
||||||
|
public DataPacket(byte[] dataIn) {
|
||||||
|
backedData = dataIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new DataPacket backed by a specified {@link Path}.
|
||||||
|
*
|
||||||
|
* @param path The path to back to.
|
||||||
|
*/
|
||||||
|
public DataPacket(Path path) {
|
||||||
|
if (path != null) backingFile = path.toFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the backing file.
|
||||||
|
*
|
||||||
|
* @return The backing file or null.
|
||||||
|
*/
|
||||||
|
public File getBackingFile() {
|
||||||
|
return backingFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the packet is valid.
|
||||||
|
*
|
||||||
|
* @return Is the packet valid?
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
synchronized (slock) {
|
||||||
|
return (backingFile == null) || (backedData != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the protocol information.
|
||||||
|
*
|
||||||
|
* @return The protocol information.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PacketProtocolInformation getProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the protocol information statically.
|
||||||
|
*
|
||||||
|
* @return The protocol information.
|
||||||
|
*/
|
||||||
|
public static PacketProtocolInformation getTheProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads the stored data.
|
||||||
|
*/
|
||||||
|
public void unload() {
|
||||||
|
synchronized (slock) {
|
||||||
|
backedData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the packet payload to a byte array.
|
||||||
|
*
|
||||||
|
* @return The packet payload data.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] savePayload() throws PacketException {
|
||||||
|
synchronized (slock) {
|
||||||
|
return internalSavePayload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] internalSavePayload() throws PacketException {
|
||||||
|
if (backedData == null && backingFile != null) {
|
||||||
|
try {
|
||||||
|
backedData = Files.readAllBytes(backingFile.toPath());
|
||||||
|
} catch (IOException | SecurityException e) {
|
||||||
|
throw new PacketException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (backedData == null) throw new PacketException("no data");
|
||||||
|
return backedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the packet payload from save data.
|
||||||
|
*
|
||||||
|
* @param packetData The packet payload data.
|
||||||
|
* @throws NullPointerException The new store data is null.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadPayload(byte[] packetData) throws PacketException {
|
||||||
|
if (packetData == null) throw new NullPointerException("dataIn is null");
|
||||||
|
synchronized (slock) {
|
||||||
|
internalLoadPayload(packetData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void internalLoadPayload(byte[] packetData) throws PacketException {
|
||||||
|
backedData = packetData;
|
||||||
|
if (backingFile != null) {
|
||||||
|
try {
|
||||||
|
Files.write(backingFile.toPath(), backedData);
|
||||||
|
} catch (IOException | SecurityException | UnsupportedOperationException e) {
|
||||||
|
throw new PacketException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
458
src/com/captainalm/test/calmnet/Main.java
Normal file
458
src/com/captainalm/test/calmnet/Main.java
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.SSLUtilities;
|
||||||
|
import com.captainalm.lib.calmnet.SSLUtilityException;
|
||||||
|
import com.captainalm.lib.calmnet.packet.IPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketException;
|
||||||
|
import com.captainalm.lib.calmnet.packet.core.NetworkSSLUpgradePacket;
|
||||||
|
import com.captainalm.utils.Console;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLServerSocket;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
public final class Main {
|
||||||
|
private static NetworkRuntime runtime;
|
||||||
|
private static Thread recvThread;
|
||||||
|
private static boolean akned = false;
|
||||||
|
private final static Queue<DataPacket> packetQueue = new LinkedList<>();
|
||||||
|
|
||||||
|
private static SSLContext sslContext;
|
||||||
|
private static boolean isClient;
|
||||||
|
private static String sslHost;
|
||||||
|
|
||||||
|
private static int sendLoopsRemainingSetting;
|
||||||
|
|
||||||
|
private static int sendLoopWaitTime;
|
||||||
|
private static final Object slock = new Object();
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
header();
|
||||||
|
help();
|
||||||
|
boolean shouldExecuting = true;
|
||||||
|
while (shouldExecuting) {
|
||||||
|
char opt = Console.readCharacter();
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case '0':
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
case 'i':
|
||||||
|
info();
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
case 's':
|
||||||
|
start();
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
case 'd':
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
case 'm':
|
||||||
|
message();
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
case 'f':
|
||||||
|
send();
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
case 'p':
|
||||||
|
process();
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
case 'x':
|
||||||
|
sslSetup();
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
case 'u':
|
||||||
|
upgrade();
|
||||||
|
break;
|
||||||
|
case '9':
|
||||||
|
case 'a':
|
||||||
|
header();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shouldExecuting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void start() {
|
||||||
|
if (runtime != null && runtime.isProcessing()) return;
|
||||||
|
Console.writeLine("Socket Setup:");
|
||||||
|
Console.writeLine("IP Address:");
|
||||||
|
InetAddress address = null;
|
||||||
|
try {
|
||||||
|
address = InetAddress.getByName(Console.readString());
|
||||||
|
Console.writeLine("Done ! ; Setting To: " + address.getHostAddress());
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
Console.writeLine("Ignored! ; Setting To: null");
|
||||||
|
}
|
||||||
|
Console.writeLine("Port:");
|
||||||
|
Integer port = Console.readInt();
|
||||||
|
if (port == null || port < 0 || port > 65535) {
|
||||||
|
port = 0;
|
||||||
|
Console.writeLine("Ignored! ; Setting To: 0");
|
||||||
|
}
|
||||||
|
Console.writeLine("Use Fragmentation (Y/OTHER):");
|
||||||
|
char fopt = Console.readCharacter();
|
||||||
|
|
||||||
|
boolean fragmentation = (fopt == 'Y' || fopt == 'y');
|
||||||
|
boolean fverifyp = false;
|
||||||
|
if (fragmentation) {
|
||||||
|
Console.writeLine("Verify Fragment Payloads (Y/OTHER)");
|
||||||
|
fopt = Console.readCharacter();
|
||||||
|
|
||||||
|
fverifyp = (fopt == 'Y' || fopt == 'y');
|
||||||
|
}
|
||||||
|
Console.writeLine("Select Socket Mode:");
|
||||||
|
Console.writeLine("0) TCP Listen");
|
||||||
|
Console.writeLine("1) TCP Client");
|
||||||
|
Console.writeLine("2) UDP Listen");
|
||||||
|
Console.writeLine("3) UDP Client");
|
||||||
|
Console.writeLine("4) UDP Broadcast");
|
||||||
|
Console.writeLine("5) UDP Loopback Client");
|
||||||
|
Console.writeLine("6) UDP Loopback Broadcast");
|
||||||
|
Console.writeLine("7) SSL TCP Listen");
|
||||||
|
Console.writeLine("8) SSL TCP Client");
|
||||||
|
Console.writeLine("OTHER) Cancel");
|
||||||
|
char opt = Console.readCharacter();
|
||||||
|
|
||||||
|
Console.writeLine("Starting Socket...");
|
||||||
|
runtime = null;
|
||||||
|
switch (opt) {
|
||||||
|
case '0':
|
||||||
|
sendLoopsRemainingSetting = 1;
|
||||||
|
sendLoopWaitTime = 50;
|
||||||
|
try (ServerSocket serverSocket = new ServerSocket(port, 1, address)) {
|
||||||
|
Socket socket = serverSocket.accept();
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp);
|
||||||
|
isClient = false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
sendLoopsRemainingSetting = 1;
|
||||||
|
sendLoopWaitTime = 50;
|
||||||
|
try {
|
||||||
|
Socket socket = new Socket(address, port);
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp);
|
||||||
|
isClient = true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
requestSendSettings();
|
||||||
|
try {
|
||||||
|
DatagramSocket socket = new DatagramSocket(port, address);
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp, null, -1);
|
||||||
|
isClient = false;
|
||||||
|
} catch (SocketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
requestSendSettings();
|
||||||
|
try {
|
||||||
|
DatagramSocket socket = new DatagramSocket();
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp, address, port);
|
||||||
|
isClient = true;
|
||||||
|
} catch (SocketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
requestSendSettings();
|
||||||
|
try {
|
||||||
|
MulticastSocket socket = new MulticastSocket(port);
|
||||||
|
if (!socket.getLoopbackMode()) socket.setLoopbackMode(true);
|
||||||
|
socket.joinGroup(address);
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp, address, port);
|
||||||
|
isClient = false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
requestSendSettings();
|
||||||
|
try {
|
||||||
|
DatagramSocket socket = new DatagramSocket(port, address);
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp, address, port);
|
||||||
|
isClient = true;
|
||||||
|
} catch (SocketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
requestSendSettings();
|
||||||
|
try {
|
||||||
|
MulticastSocket socket = new MulticastSocket(port);
|
||||||
|
if (socket.getLoopbackMode()) socket.setLoopbackMode(false);
|
||||||
|
socket.joinGroup(address);
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp, address, port);
|
||||||
|
isClient = false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
sendLoopsRemainingSetting = 1;
|
||||||
|
sendLoopWaitTime = 50;
|
||||||
|
if (sslContext == null) break;
|
||||||
|
try (SSLServerSocket serverSocket = SSLUtilities.getSSLServerSocket(sslContext, port, 1, address)) {
|
||||||
|
Socket socket = serverSocket.accept();
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp);
|
||||||
|
isClient = false;
|
||||||
|
} catch (IOException | SSLUtilityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
sendLoopsRemainingSetting = 1;
|
||||||
|
sendLoopWaitTime = 50;
|
||||||
|
if (sslContext == null) break;
|
||||||
|
try {
|
||||||
|
Socket socket = SSLUtilities.getSSLClientSocket(sslContext, sslHost, port);
|
||||||
|
runtime = new NetworkRuntime(socket, fragmentation, fverifyp);
|
||||||
|
isClient = true;
|
||||||
|
} catch (SSLUtilityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (runtime == null) {
|
||||||
|
Console.writeLine("!FAILED TO START!");
|
||||||
|
} else {
|
||||||
|
while (runtime.notReadyToSend()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createAndStartRecvThread();
|
||||||
|
Console.writeLine("Socket Started.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void requestSendSettings() {
|
||||||
|
Console.writeLine("Enter number of send retries:");
|
||||||
|
Integer num = Console.readInt();
|
||||||
|
if (num == null || num < 0) num = 0;
|
||||||
|
Console.writeLine("Send Retires set to: " + num);
|
||||||
|
sendLoopsRemainingSetting = num + 1;
|
||||||
|
Console.writeLine("Enter timeout before send retry (Milliseconds) :");
|
||||||
|
num = Console.readInt();
|
||||||
|
if (num == null || num < 50) num = 50;
|
||||||
|
Console.writeLine("Retry Send Timeout set to: " + num);
|
||||||
|
sendLoopWaitTime = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createAndStartRecvThread() {
|
||||||
|
recvThread = new Thread(() -> {
|
||||||
|
PacketType nextType = null;
|
||||||
|
Path nextPath = null;
|
||||||
|
while (runtime != null && runtime.isProcessing()) {
|
||||||
|
IPacket packet;
|
||||||
|
while ((packet = runtime.receiveLastPacket()) != null) {
|
||||||
|
if (!packet.isValid()) continue;
|
||||||
|
if (packet instanceof TypePacket && nextType == null) {
|
||||||
|
nextType = ((TypePacket) packet).type;
|
||||||
|
runtime.sendPacket(new AKNPacket(), false);
|
||||||
|
}
|
||||||
|
if (packet instanceof DataPacket && nextType == PacketType.Message) {
|
||||||
|
nextType = null;
|
||||||
|
synchronized (slock) {
|
||||||
|
packetQueue.add((DataPacket) packet);
|
||||||
|
}
|
||||||
|
runtime.sendPacket(new AKNPacket(), false);
|
||||||
|
}
|
||||||
|
if (packet instanceof DataPacket && nextType == PacketType.Name) {
|
||||||
|
nextType = null;
|
||||||
|
try {
|
||||||
|
nextPath = new File(new String(packet.savePayload(), StandardCharsets.UTF_8)).toPath();
|
||||||
|
} catch (PacketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
runtime.sendPacket(new AKNPacket(), false);
|
||||||
|
}
|
||||||
|
if (packet instanceof StreamedDataPacket && nextType == PacketType.Data && nextPath != null) {
|
||||||
|
nextType = null;
|
||||||
|
try (FileOutputStream outputStream = new FileOutputStream(nextPath.toFile())) {
|
||||||
|
((StreamedDataPacket) packet).readData(outputStream);
|
||||||
|
synchronized (slock) {
|
||||||
|
DataPacket p = new DataPacket(("Received File: " + nextPath.toAbsolutePath()).getBytes(StandardCharsets.UTF_8));
|
||||||
|
packetQueue.add(p);
|
||||||
|
}
|
||||||
|
} catch (IOException | PacketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
nextPath = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (packet instanceof NetworkSSLUpgradePacket && sslContext != null) {
|
||||||
|
if (((NetworkSSLUpgradePacket) packet).isAcknowledgement()) {
|
||||||
|
runtime.sslUpgrade(sslContext, sslHost, isClient);
|
||||||
|
} else {
|
||||||
|
runtime.sendPacket(new NetworkSSLUpgradePacket(true), true);
|
||||||
|
runtime.sslUpgrade(sslContext, sslHost, isClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "main_recv_thread");
|
||||||
|
recvThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void stop() {
|
||||||
|
if (runtime == null || !runtime.isProcessing()) return;
|
||||||
|
Console.writeLine("Socket Stopping...");
|
||||||
|
runtime.stopProcessing();
|
||||||
|
try {
|
||||||
|
recvThread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
runtime = null;
|
||||||
|
isClient = false;
|
||||||
|
Console.writeLine("Socket Stopped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean waitForAKN(IPacket packet) {
|
||||||
|
if (packet instanceof AKNPacket && packet.isValid()) {
|
||||||
|
akned = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doAKNWait(IPacket packet) {
|
||||||
|
akned = false;
|
||||||
|
runtime.setPacketReceiveCallback(Main::waitForAKN);
|
||||||
|
int i = 0;
|
||||||
|
while (!akned) {
|
||||||
|
runtime.sendPacket(packet, false);
|
||||||
|
try {
|
||||||
|
Thread.sleep(sendLoopWaitTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
if (++i >= sendLoopsRemainingSetting) akned = true;
|
||||||
|
}
|
||||||
|
runtime.setPacketReceiveCallback(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void message() {
|
||||||
|
if (runtime == null || !runtime.isProcessing()) return;
|
||||||
|
Console.writeLine("Message To Send:");
|
||||||
|
String message = Console.readString();
|
||||||
|
doAKNWait(new TypePacket(PacketType.Message));
|
||||||
|
DataPacket packet = new DataPacket(message.getBytes(StandardCharsets.UTF_8));
|
||||||
|
doAKNWait(packet);
|
||||||
|
Console.writeLine("!Message Sent!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void send() {
|
||||||
|
if (runtime == null || !runtime.isProcessing()) return;
|
||||||
|
Console.writeLine("Path of File To Send:");
|
||||||
|
File file = new File(Console.readString());
|
||||||
|
if (file.exists()) {
|
||||||
|
doAKNWait(new TypePacket(PacketType.Name));
|
||||||
|
DataPacket packet = new DataPacket(file.getName().getBytes(StandardCharsets.UTF_8));
|
||||||
|
doAKNWait(packet);
|
||||||
|
Console.writeLine("!Name Sent!");
|
||||||
|
doAKNWait(new TypePacket(PacketType.Data));
|
||||||
|
packet = new StreamedDataPacket(file.toPath(), true);
|
||||||
|
doAKNWait(packet);
|
||||||
|
Console.writeLine("!File Sent!");
|
||||||
|
} else {
|
||||||
|
Console.writeLine("!File does not Exist!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void process() {
|
||||||
|
Console.writeLine("Received Messages:");
|
||||||
|
synchronized (slock) {
|
||||||
|
int i = 1;
|
||||||
|
while (packetQueue.size() > 0) {
|
||||||
|
DataPacket packet = packetQueue.poll();
|
||||||
|
Console.writeLine("Message ("+ i++ +"):");
|
||||||
|
try {
|
||||||
|
Console.writeLine(new String(packet.savePayload(), StandardCharsets.UTF_8));
|
||||||
|
} catch (PacketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sslSetup() {
|
||||||
|
if (runtime != null && runtime.isSSLUpgraded()) return;
|
||||||
|
Console.writeLine("SSL Setup:");
|
||||||
|
Console.writeLine("SSL Host Name (Enter empty to set to null):");
|
||||||
|
sslHost = Console.readString();
|
||||||
|
if (sslHost.equals("")) sslHost = null;
|
||||||
|
Console.writeLine("SSL Keystore Path:");
|
||||||
|
String kpath = Console.readString();
|
||||||
|
Console.writeLine("SSL Keystore Password:");
|
||||||
|
String kpass = Console.readString();
|
||||||
|
if (kpass.equals("")) kpass = "changeit";
|
||||||
|
try {
|
||||||
|
sslContext = SSLUtilities.getSSLContext(null, SSLUtilities.loadKeyStore(null, new File(kpath), kpass), kpass.toCharArray());
|
||||||
|
Console.writeLine("SSL Setup Complete!");
|
||||||
|
} catch (SSLUtilityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Console.writeLine("SSL Setup Failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void upgrade() {
|
||||||
|
if (runtime == null || !runtime.isProcessing() || sslContext == null) return;
|
||||||
|
Console.writeLine("Upgrading Connection to SSL...");
|
||||||
|
runtime.sendPacket(new NetworkSSLUpgradePacket(false), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void info() {
|
||||||
|
Console.writeLine("INFORMATION:");
|
||||||
|
Console.writeLine("Local Socket: " + ((runtime != null && runtime.isProcessing()) ? runtime.getLocalAddress() + ":" + runtime.getLocalPort() : ":"));
|
||||||
|
Console.writeLine("Remote Socket: " + ((runtime != null && runtime.isProcessing()) ? runtime.getTargetAddress() + ":" + runtime.getTargetPort() : ":"));
|
||||||
|
Console.writeLine("Is Active: " + ((runtime != null && runtime.isProcessing()) ? "Yes" : "No"));
|
||||||
|
Console.writeLine("Number Of Packets To Process: " + (((runtime == null) ? 0 : runtime.numberOfQueuedReceivedPackets()) + packetQueue.size()));
|
||||||
|
Console.writeLine("SSL Upgrade Status: " + ((runtime != null && runtime.isSSLUpgraded()) ? "Upgraded" : "Not Upgraded"));
|
||||||
|
Console.writeLine("SSL Host Name: " + ((sslHost == null) ? "<null>" : sslHost));
|
||||||
|
Console.writeLine("SSL Context Status: " + ((sslContext == null) ? "Unavailable" : "Available"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void header() {
|
||||||
|
Console.writeLine("C-ALM Net Test (C) Captain ALM 2022");
|
||||||
|
Console.writeLine("Under The BSD 3-Clause License");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void help() {
|
||||||
|
Console.writeLine("HELP:");
|
||||||
|
Console.writeLine("KEY) Action");
|
||||||
|
Console.writeLine("0/h) This Help Message");
|
||||||
|
Console.writeLine("1/i) Information State");
|
||||||
|
Console.writeLine("2/s) Start Connection");
|
||||||
|
Console.writeLine("3/d) Stop Connection");
|
||||||
|
Console.writeLine("4/m) Send Message");
|
||||||
|
Console.writeLine("5/f) Send File");
|
||||||
|
Console.writeLine("6/p) Process Incoming Packets");
|
||||||
|
Console.writeLine("7/x) SSL Settings");
|
||||||
|
Console.writeLine("8/u) SSL Upgrade");
|
||||||
|
Console.writeLine("9/a) Show the About Header");
|
||||||
|
Console.writeLine("OTHER) Quit");
|
||||||
|
}
|
||||||
|
}
|
71
src/com/captainalm/test/calmnet/MyPacketFactory.java
Normal file
71
src/com/captainalm/test/calmnet/MyPacketFactory.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.packet.*;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class creates packets.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public final class MyPacketFactory extends CALMNETPacketFactory {
|
||||||
|
private Path targetPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Instance of CALMNETPacketFactory with the specified {@link PacketLoader}.
|
||||||
|
*
|
||||||
|
* @param loader The packet loader to use.
|
||||||
|
* @throws NullPointerException loader is null.
|
||||||
|
*/
|
||||||
|
public MyPacketFactory(PacketLoader loader) {
|
||||||
|
super(true ,loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Instance of CALMNETPacketFactory with the specified {@link PacketLoader} and {@link IPacketFactory}.
|
||||||
|
*
|
||||||
|
* @param loader The packet loader to use.
|
||||||
|
* @param factory The packet factory to use or null (null signifies to use the same instance).
|
||||||
|
* @throws NullPointerException loader is null.
|
||||||
|
*/
|
||||||
|
public MyPacketFactory(PacketLoader loader, IPacketFactory factory) {
|
||||||
|
super(true ,loader, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link IPacket} of the protocol specified by the passed {@link PacketProtocolInformation} instance.
|
||||||
|
*
|
||||||
|
* @param information The protocol information to use.
|
||||||
|
* @return The constructed packet or null.
|
||||||
|
* @throws NullPointerException The information is null.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IPacket getPacket(PacketProtocolInformation information) {
|
||||||
|
if (information == null) throw new NullPointerException("information is null");
|
||||||
|
|
||||||
|
if (information.equals(AKNPacket.getTheProtocol())) return new AKNPacket();
|
||||||
|
if (information.equals(TypePacket.getTheProtocol())) return new TypePacket(null);
|
||||||
|
if (information.equals(DataPacket.getTheProtocol())) return (streamPreferred) ? new StreamedDataPacket(targetPath, true) : new DataPacket(targetPath);
|
||||||
|
|
||||||
|
return super.getPacket(information);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target path for {@link DataPacket}s.
|
||||||
|
*
|
||||||
|
* @return The target path or null.
|
||||||
|
*/
|
||||||
|
public Path getTargetPath() {
|
||||||
|
return targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the target path for {@link DataPacket}s.
|
||||||
|
*
|
||||||
|
* @param path The target path or null.
|
||||||
|
*/
|
||||||
|
public void setTargetPath(Path path) {
|
||||||
|
targetPath = path;
|
||||||
|
}
|
||||||
|
}
|
449
src/com/captainalm/test/calmnet/NetworkRuntime.java
Normal file
449
src/com/captainalm/test/calmnet/NetworkRuntime.java
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.SSLUtilities;
|
||||||
|
import com.captainalm.lib.calmnet.SSLUtilityException;
|
||||||
|
import com.captainalm.lib.calmnet.packet.*;
|
||||||
|
import com.captainalm.lib.calmnet.packet.core.NetworkSSLUpgradePacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.fragment.FragmentAllocationPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.fragment.FragmentPIDPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.fragment.FragmentSendStopPacket;
|
||||||
|
import com.captainalm.lib.calmnet.stream.NetworkInputStream;
|
||||||
|
import com.captainalm.lib.calmnet.stream.NetworkOutputStream;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the network runtime class.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public final class NetworkRuntime {
|
||||||
|
public final MyPacketFactory factory = new MyPacketFactory(new PacketLoader());
|
||||||
|
private NetworkInputStream inputStream;
|
||||||
|
private NetworkOutputStream outputStream;
|
||||||
|
private FragmentReceiver fragmentReceiver;
|
||||||
|
private final HashMap<Integer, LocalDateTime> fragmentRMM = new HashMap<>();
|
||||||
|
private FragmentSender fragmentSender;
|
||||||
|
private final HashMap<Integer, LocalDateTime> fragmentSMM = new HashMap<>();
|
||||||
|
private boolean processing = true;
|
||||||
|
|
||||||
|
private InetAddress targetAddress;
|
||||||
|
private int targetPort = -1;
|
||||||
|
|
||||||
|
private final Queue<IPacket> packetQueue = new LinkedList<>();
|
||||||
|
private Function<IPacket, Boolean> packetReceiveCallback;
|
||||||
|
private final Object slock = new Object();
|
||||||
|
private final Object slocksend = new Object();
|
||||||
|
private final Object slockfmon = new Object();
|
||||||
|
private final Object slockupg = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new NetworkRuntime with the specified parameters.
|
||||||
|
*
|
||||||
|
* @param socketIn The socket to use.
|
||||||
|
* @param useFragmentation If fragmentation should be used.
|
||||||
|
* @param verifyFragmentPayloads If a fragment payload should be verified.
|
||||||
|
*/
|
||||||
|
public NetworkRuntime(Socket socketIn, boolean useFragmentation, boolean verifyFragmentPayloads) {
|
||||||
|
inputStream = new NetworkInputStream(socketIn);
|
||||||
|
outputStream = new NetworkOutputStream(socketIn);
|
||||||
|
init(useFragmentation, verifyFragmentPayloads);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new NetworkRuntime with the specified parameters.
|
||||||
|
*
|
||||||
|
* @param socketIn The datagram socket to use.
|
||||||
|
* @param useFragmentation If fragmentation should be used.
|
||||||
|
* @param verifyFragmentPayloads If a fragment payload should be verified.
|
||||||
|
* @param address The target address (Can be null).
|
||||||
|
* @param port The target port.
|
||||||
|
*/
|
||||||
|
public NetworkRuntime(DatagramSocket socketIn, boolean useFragmentation, boolean verifyFragmentPayloads, InetAddress address, int port) {
|
||||||
|
inputStream = new NetworkInputStream(socketIn);
|
||||||
|
outputStream = new NetworkOutputStream(socketIn);
|
||||||
|
targetAddress = address;
|
||||||
|
targetPort = port;
|
||||||
|
if (address != null && port >= 0) {
|
||||||
|
try {
|
||||||
|
outputStream.setDatagramTarget(address, port);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
outputStream.setDatagramBufferSize(65535);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
init(useFragmentation, verifyFragmentPayloads);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(boolean useFragmentation, boolean verifyFragmentPayloads) {
|
||||||
|
fragmentReceiver = (useFragmentation) ? new FragmentReceiver(factory.getPacketLoader(), factory) : null;
|
||||||
|
if (fragmentReceiver != null) fragmentReceiver.setResponseVerification(verifyFragmentPayloads);
|
||||||
|
fragmentSender = (useFragmentation) ? new FragmentSender(factory.getPacketLoader()) : null;
|
||||||
|
if (fragmentSender != null) fragmentSender.setResponseVerification(verifyFragmentPayloads);
|
||||||
|
receiveThread.start();
|
||||||
|
if (useFragmentation) {
|
||||||
|
fragmentMonitorThread.start();
|
||||||
|
fragmentFinishRecvMonitorThread.start();
|
||||||
|
fragmentFinishSendMonitorThread.start();
|
||||||
|
fragmentReceiveThread.start();
|
||||||
|
fragmentSendThread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Thread receiveThread = new Thread(() -> {
|
||||||
|
while (processing) {
|
||||||
|
try {
|
||||||
|
IPacket packet = factory.getPacketLoader().readStreamedPacket(inputStream, factory, null);
|
||||||
|
if (packet == null) continue;
|
||||||
|
if (inputStream.getDatagramSocket() != null && (targetAddress == null || targetPort < 0)) {
|
||||||
|
targetAddress = inputStream.getAddress();
|
||||||
|
targetPort = inputStream.getPort();
|
||||||
|
if (targetAddress != null && targetPort >= 0) {
|
||||||
|
try {
|
||||||
|
outputStream.setDatagramTarget(targetAddress, targetPort);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fragmentReceiver != null) {
|
||||||
|
updateMState(fragmentRMM, packet);
|
||||||
|
fragmentReceiver.receivePacket(packet);
|
||||||
|
}
|
||||||
|
if (fragmentSender != null) {
|
||||||
|
updateMState(fragmentSMM, packet);
|
||||||
|
fragmentSender.receivePacket(packet);
|
||||||
|
}
|
||||||
|
synchronized (slock) {
|
||||||
|
if (packetReceiveCallback == null || packetReceiveCallback.apply(packet)) packetQueue.add(packet);
|
||||||
|
}
|
||||||
|
if (packet.isValid() && packet instanceof NetworkSSLUpgradePacket) {
|
||||||
|
synchronized (slockupg) {
|
||||||
|
int timeout = 4;
|
||||||
|
while (!isSSLUpgraded() && inputStream.getDatagramSocket() == null && timeout-- > 0) slockupg.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
synchronized (slocksend) {
|
||||||
|
slocksend.notifyAll();
|
||||||
|
}
|
||||||
|
} catch (PacketException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
stopProcessing();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "recv_thread");
|
||||||
|
|
||||||
|
private final Thread fragmentReceiveThread = new Thread(() -> {
|
||||||
|
while (processing) {
|
||||||
|
try {
|
||||||
|
IPacket packet = fragmentReceiver.receivePacket();
|
||||||
|
if (packet == null) continue;
|
||||||
|
synchronized (slock) {
|
||||||
|
if (packetReceiveCallback == null || packetReceiveCallback.apply(packet)) packetQueue.add(packet);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "frag_recv_thread");
|
||||||
|
|
||||||
|
private final Thread fragmentSendThread = new Thread(() -> {
|
||||||
|
while (processing) {
|
||||||
|
try {
|
||||||
|
synchronized (slocksend) {
|
||||||
|
slocksend.wait();
|
||||||
|
IPacket[] packets = fragmentSender.sendPacket();
|
||||||
|
for (IPacket c : packets) if (c != null) {
|
||||||
|
updateMState(fragmentSMM, c);
|
||||||
|
factory.getPacketLoader().writePacket(outputStream, c, true);
|
||||||
|
}
|
||||||
|
packets = fragmentReceiver.sendPacket();
|
||||||
|
for (IPacket c : packets) if (c != null) {
|
||||||
|
updateMState(fragmentRMM, c);
|
||||||
|
factory.getPacketLoader().writePacket(outputStream, c, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PacketException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
stopProcessing();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "frag_send_thread");
|
||||||
|
|
||||||
|
private final Thread fragmentMonitorThread = new Thread(() -> {
|
||||||
|
while (processing) {
|
||||||
|
int id = -1;
|
||||||
|
synchronized (slockfmon) {
|
||||||
|
for (int c : fragmentRMM.keySet()) {
|
||||||
|
if (!fragmentRMM.get(c).plusSeconds(29).isAfter(LocalDateTime.now())) {
|
||||||
|
fragmentRMM.remove(id);
|
||||||
|
fragmentReceiver.deletePacketFromRegistry(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int c : fragmentSMM.keySet()) {
|
||||||
|
if (!fragmentSMM.get(c).plusSeconds(29).isAfter(LocalDateTime.now())) {
|
||||||
|
fragmentSMM.remove(id);
|
||||||
|
fragmentSender.deletePacketFromRegistry(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(30000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "frag_mntr_thread");
|
||||||
|
|
||||||
|
private final Thread fragmentFinishRecvMonitorThread = new Thread(() -> {
|
||||||
|
while (processing) {
|
||||||
|
int id = -1;
|
||||||
|
try {
|
||||||
|
while ((id = fragmentReceiver.getLastIDFinished()) != -1) synchronized (slockfmon) {
|
||||||
|
fragmentRMM.remove(id);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "frag_fin_recv_mntr_thread");
|
||||||
|
|
||||||
|
private final Thread fragmentFinishSendMonitorThread = new Thread(() -> {
|
||||||
|
while (processing) {
|
||||||
|
int id = -1;
|
||||||
|
try {
|
||||||
|
while ((id = fragmentSender.getLastIDFinished()) != -1) synchronized (slockfmon) {
|
||||||
|
fragmentSMM.remove(id);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "frag_fin_send_mntr_thread");
|
||||||
|
|
||||||
|
private void updateMState(HashMap<Integer, LocalDateTime> mm, IPacket packet) {
|
||||||
|
if (packet == null || !packet.isValid()) return;
|
||||||
|
synchronized (slockfmon) {
|
||||||
|
if (packet instanceof FragmentAllocationPacket) {
|
||||||
|
mm.put(((FragmentAllocationPacket) packet).getPacketID(), LocalDateTime.now());
|
||||||
|
} else if (packet instanceof FragmentPIDPacket && !(packet instanceof FragmentSendStopPacket)) {
|
||||||
|
if (mm.containsKey(((FragmentPIDPacket) packet).getPacketID()))
|
||||||
|
mm.put(((FragmentPIDPacket) packet).getPacketID(), LocalDateTime.now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current remote endpoint address or null.
|
||||||
|
*
|
||||||
|
* @return The remote address or null.
|
||||||
|
*/
|
||||||
|
public InetAddress getTargetAddress() {
|
||||||
|
if (!processing) return null;
|
||||||
|
return (targetAddress == null) ? inputStream.getAddress() : targetAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current target port or -1.
|
||||||
|
*
|
||||||
|
* @return The target port or -1.
|
||||||
|
*/
|
||||||
|
public int getTargetPort() {
|
||||||
|
if (!processing) return -1;
|
||||||
|
return (targetPort < 0) ? inputStream.getPort() : targetPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current remote endpoint address or null.
|
||||||
|
*
|
||||||
|
* @return The remote address or null.
|
||||||
|
*/
|
||||||
|
public InetAddress getLocalAddress() {
|
||||||
|
if (!processing) return null;
|
||||||
|
return inputStream.getLocalAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current local port or -1.
|
||||||
|
*
|
||||||
|
* @return The local port or -1.
|
||||||
|
*/
|
||||||
|
public int getLocalPort() {
|
||||||
|
if (!processing) return -1;
|
||||||
|
return inputStream.getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an SSL Upgrade on a TCP Connection.
|
||||||
|
*
|
||||||
|
* @param context The SSL Context to use.
|
||||||
|
* @param host The host to check the remote certificate using (Set to null on server).
|
||||||
|
* @param isClientSide If the caller is directly connected (Not using an accepted socket).
|
||||||
|
*/
|
||||||
|
public void sslUpgrade(SSLContext context, String host, boolean isClientSide) {
|
||||||
|
if (!processing || inputStream.getSocket() == null || inputStream.getSocket() instanceof SSLSocket) return;
|
||||||
|
synchronized (slock) {
|
||||||
|
synchronized (slocksend) {
|
||||||
|
synchronized (slockupg) {
|
||||||
|
Socket original = inputStream.getSocket();
|
||||||
|
try {
|
||||||
|
inputStream.setSocket(SSLUtilities.upgradeClientSocketToSSL(context, inputStream.getSocket(), host, inputStream.getPort(), true, isClientSide));
|
||||||
|
outputStream.setSocket(inputStream.getSocket());
|
||||||
|
} catch (SSLUtilityException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
try {
|
||||||
|
inputStream.setSocket(original);
|
||||||
|
outputStream.setSocket(original);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slockupg.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the runtime SSL Upgraded.
|
||||||
|
*
|
||||||
|
* @return If the runtime is upgraded.
|
||||||
|
*/
|
||||||
|
public boolean isSSLUpgraded() {
|
||||||
|
if (!processing) return false;
|
||||||
|
return inputStream.getSocket() instanceof SSLSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a packet.
|
||||||
|
*
|
||||||
|
* @param packet The packet to send.
|
||||||
|
* @param forceNormalSend Forces a normal send operation without fragmentation.
|
||||||
|
*/
|
||||||
|
public void sendPacket(IPacket packet, boolean forceNormalSend) {
|
||||||
|
if (packet == null || notReadyToSend()) return;
|
||||||
|
synchronized (slocksend) {
|
||||||
|
if (fragmentSender == null || forceNormalSend) {
|
||||||
|
try {
|
||||||
|
factory.getPacketLoader().writePacket(outputStream, packet, true);
|
||||||
|
slocksend.notifyAll();
|
||||||
|
} catch (IOException | PacketException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
stopProcessing();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fragmentSender.sendPacket(packet);
|
||||||
|
slocksend.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives the last packet.
|
||||||
|
*
|
||||||
|
* @return Receives the last packet.
|
||||||
|
*/
|
||||||
|
public IPacket receiveLastPacket() {
|
||||||
|
if (!processing) return null;
|
||||||
|
synchronized (slock) {
|
||||||
|
return packetQueue.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of queued received packets.
|
||||||
|
*
|
||||||
|
* @return The number of queued received packets.
|
||||||
|
*/
|
||||||
|
public int numberOfQueuedReceivedPackets() {
|
||||||
|
synchronized (slock) {
|
||||||
|
return packetQueue.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packet receive callback.
|
||||||
|
* The return value of the passed function is whether to add the packet to the receive queue.
|
||||||
|
*
|
||||||
|
* @return The packet receive callback.
|
||||||
|
*/
|
||||||
|
public Function<IPacket, Boolean> getPacketReceiveCallback() {
|
||||||
|
return packetReceiveCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the packet receive callback.
|
||||||
|
* The return value of the passed function is whether to add the packet to the receive queue.
|
||||||
|
*
|
||||||
|
* @param callback The new packet receive callback.
|
||||||
|
*/
|
||||||
|
public void setPacketReceiveCallback(Function<IPacket, Boolean> callback) {
|
||||||
|
synchronized (slock) {
|
||||||
|
packetReceiveCallback = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the runtime not ready to send.
|
||||||
|
*
|
||||||
|
* @return Cannot send.
|
||||||
|
*/
|
||||||
|
public boolean notReadyToSend() {
|
||||||
|
return !processing || ((outputStream.getSocket() == null) && (outputStream.getDatagramSocket() == null || targetAddress == null || targetPort < 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the runtime is processing.
|
||||||
|
*
|
||||||
|
* @return Is the runtime processing.
|
||||||
|
*/
|
||||||
|
public boolean isProcessing() {
|
||||||
|
return processing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops processing.
|
||||||
|
*/
|
||||||
|
public void stopProcessing() {
|
||||||
|
if (processing) {
|
||||||
|
processing = false;
|
||||||
|
if (Thread.currentThread() != fragmentSendThread && fragmentSendThread.isAlive()) fragmentSendThread.interrupt();
|
||||||
|
if (Thread.currentThread() != fragmentReceiveThread && fragmentReceiveThread.isAlive()) fragmentReceiveThread.interrupt();
|
||||||
|
if (Thread.currentThread() != fragmentMonitorThread && fragmentMonitorThread.isAlive()) fragmentMonitorThread.interrupt();
|
||||||
|
if (Thread.currentThread() != fragmentFinishRecvMonitorThread && fragmentFinishRecvMonitorThread.isAlive()) fragmentFinishRecvMonitorThread.interrupt();
|
||||||
|
if (Thread.currentThread() != fragmentFinishSendMonitorThread && fragmentFinishSendMonitorThread.isAlive()) fragmentFinishSendMonitorThread.interrupt();
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
inputStream = null;
|
||||||
|
try {
|
||||||
|
outputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
outputStream = null;
|
||||||
|
if (fragmentSender != null) {
|
||||||
|
fragmentSender.clearLastIDFinished();
|
||||||
|
fragmentSender.clearRegistry();
|
||||||
|
fragmentSender.clearWaitingPackets();
|
||||||
|
fragmentSender = null;
|
||||||
|
fragmentSMM.clear();
|
||||||
|
}
|
||||||
|
if (fragmentReceiver != null) {
|
||||||
|
fragmentReceiver.clearLastIDFinished();
|
||||||
|
fragmentReceiver.clearRegistry();
|
||||||
|
fragmentReceiver.clearWaitingPackets();
|
||||||
|
fragmentReceiver = null;
|
||||||
|
fragmentRMM.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
src/com/captainalm/test/calmnet/PacketType.java
Normal file
44
src/com/captainalm/test/calmnet/PacketType.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a type of packet.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public enum PacketType {
|
||||||
|
Message(0),
|
||||||
|
Name(1),
|
||||||
|
Data(2);
|
||||||
|
int value;
|
||||||
|
PacketType(int i) {
|
||||||
|
value = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the integer value of the packet type.
|
||||||
|
*
|
||||||
|
* @return The integer value of the packet type.
|
||||||
|
*/
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packet type given the integer value.
|
||||||
|
*
|
||||||
|
* @param i The integer value.
|
||||||
|
* @return The packet type or null.
|
||||||
|
*/
|
||||||
|
public static PacketType getPacketType(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return Message;
|
||||||
|
case 1:
|
||||||
|
return Name;
|
||||||
|
case 2:
|
||||||
|
return Data;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
152
src/com/captainalm/test/calmnet/StreamedDataPacket.java
Normal file
152
src/com/captainalm/test/calmnet/StreamedDataPacket.java
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.packet.IStreamedPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketException;
|
||||||
|
import com.captainalm.lib.calmnet.stream.LengthClampedInputStream;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the data packet to store a byte array that can be backed to a file that is stream stored.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public class StreamedDataPacket extends DataPacket implements IStreamedPacket {
|
||||||
|
protected static final int transferBufferSize = 2048;
|
||||||
|
protected boolean passThroughStream = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new StreamedDataPacket with initial data.
|
||||||
|
*
|
||||||
|
* @param dataIn The data to initially use.
|
||||||
|
*/
|
||||||
|
public StreamedDataPacket(byte[] dataIn) {
|
||||||
|
super(dataIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new stream data packet backed by a specified {@link Path}.
|
||||||
|
*
|
||||||
|
* @param path The path to back to.
|
||||||
|
* @param passThroughStream If the backing array should not be used.
|
||||||
|
*/
|
||||||
|
public StreamedDataPacket(Path path, boolean passThroughStream) {
|
||||||
|
super(path);
|
||||||
|
this.passThroughStream = passThroughStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the backing array is not used when using {@link IStreamedPacket} methods.
|
||||||
|
* The backing array is always used when the store is not file backed.
|
||||||
|
*
|
||||||
|
* @return If the backing array is not used.
|
||||||
|
*/
|
||||||
|
public boolean isStreamPassedThrough() {
|
||||||
|
return passThroughStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the backing array is not used when using {@link IStreamedPacket} methods.
|
||||||
|
* The backing array is always used when the store is not file backed.
|
||||||
|
*
|
||||||
|
* @param passThroughStream If the backing array should not be used.
|
||||||
|
*/
|
||||||
|
public void setStreamPassedThrough(boolean passThroughStream) {
|
||||||
|
synchronized (slock) {
|
||||||
|
this.passThroughStream = passThroughStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the packet is valid.
|
||||||
|
*
|
||||||
|
* @return Is the packet valid?
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
boolean toret = super.isValid();
|
||||||
|
synchronized (slock) {
|
||||||
|
return toret || passThroughStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads payload data to an {@link OutputStream}.
|
||||||
|
*
|
||||||
|
* @param outputStream The output stream to read data to.
|
||||||
|
* @throws NullPointerException outputStream is null.
|
||||||
|
* @throws IOException An IO Exception has occurred.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void readData(OutputStream outputStream) throws IOException, PacketException {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (passThroughStream && backingFile != null) {
|
||||||
|
try (InputStream streamIn = new FileInputStream(backingFile)) {
|
||||||
|
int length;
|
||||||
|
byte[] transferBuffer = new byte[transferBufferSize];
|
||||||
|
while ((length = streamIn.read(transferBuffer)) != -1)
|
||||||
|
outputStream.write(transferBuffer, 0, length);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
throw new PacketException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outputStream.write(internalSavePayload());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes payload data from an {@link InputStream}.
|
||||||
|
*
|
||||||
|
* @param inputStream The input stream to write data from.
|
||||||
|
* @param size The size of the input payload in bytes.
|
||||||
|
* @throws NullPointerException inputStream is null.
|
||||||
|
* @throws IllegalArgumentException size is less than 0.
|
||||||
|
* @throws IOException An IO Exception has occurred.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void writeData(InputStream inputStream, int size) throws IOException, PacketException {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (passThroughStream && backingFile != null) {
|
||||||
|
try (OutputStream streamOut = new FileOutputStream(backingFile); LengthClampedInputStream linputStream = new LengthClampedInputStream(inputStream, size)) {
|
||||||
|
int length;
|
||||||
|
byte[] transferBuffer = new byte[transferBufferSize];
|
||||||
|
while ((length = linputStream.read(transferBuffer)) != -1)
|
||||||
|
streamOut.write(transferBuffer, 0, length);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
throw new PacketException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
byte[] dataIn = new byte[size];
|
||||||
|
int offset = 0;
|
||||||
|
int slen;
|
||||||
|
while (offset < size) if ((slen = inputStream.read(dataIn, offset, size - offset)) != -1) offset += slen; else throw new IOException("inputStream end of stream");
|
||||||
|
internalLoadPayload(dataIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the output data.
|
||||||
|
*
|
||||||
|
* @return The size of the output data in bytes.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getSize() throws PacketException {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (passThroughStream) {
|
||||||
|
try {
|
||||||
|
return Math.toIntExact(backingFile.length());
|
||||||
|
} catch (ArithmeticException | SecurityException e){
|
||||||
|
throw new PacketException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (backedData == null) return 0; else return backedData.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
src/com/captainalm/test/calmnet/TypePacket.java
Normal file
83
src/com/captainalm/test/calmnet/TypePacket.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package com.captainalm.test.calmnet;
|
||||||
|
|
||||||
|
import com.captainalm.lib.calmnet.packet.IPacket;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketException;
|
||||||
|
import com.captainalm.lib.calmnet.packet.PacketProtocolInformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This packet provides the ability to send {@link PacketType}s.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public class TypePacket implements IPacket {
|
||||||
|
private static final PacketProtocolInformation protocol = new PacketProtocolInformation((byte) 1, (byte) 2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This field holds the {@link PacketType} (Can be null).
|
||||||
|
*/
|
||||||
|
public PacketType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of type packet using the specified {@link PacketType}.
|
||||||
|
*
|
||||||
|
* @param packetType The packet type or null.
|
||||||
|
*/
|
||||||
|
public TypePacket(PacketType packetType) {
|
||||||
|
type = packetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the packet is valid.
|
||||||
|
*
|
||||||
|
* @return Is the packet valid?
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return (type != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the protocol information.
|
||||||
|
*
|
||||||
|
* @return The protocol information.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PacketProtocolInformation getProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the protocol information statically.
|
||||||
|
*
|
||||||
|
* @return The protocol information.
|
||||||
|
*/
|
||||||
|
public static PacketProtocolInformation getTheProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the packet payload to a byte array.
|
||||||
|
*
|
||||||
|
* @return The packet payload data.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] savePayload() throws PacketException {
|
||||||
|
if (type == null) throw new PacketException("no data");
|
||||||
|
return new byte[] {(byte) type.getValue()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the packet payload from save data.
|
||||||
|
*
|
||||||
|
* @param packetData The packet payload data.
|
||||||
|
* @throws NullPointerException The new store data is null.
|
||||||
|
* @throws PacketException An Exception has occurred.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadPayload(byte[] packetData) throws PacketException {
|
||||||
|
if (packetData == null) throw new NullPointerException("packetData is null");
|
||||||
|
if (packetData.length != 1) throw new PacketException("packetData length is not 1");
|
||||||
|
type = PacketType.getPacketType(packetData[0]);
|
||||||
|
}
|
||||||
|
}
|
84
src/com/captainalm/utils/Console.java
Normal file
84
src/com/captainalm/utils/Console.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package com.captainalm.utils;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a console wrapper for standard stream.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public class Console {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes to {@link System#out}.
|
||||||
|
*
|
||||||
|
* @param dataOut The string to write.
|
||||||
|
*/
|
||||||
|
public static void write(String dataOut) {
|
||||||
|
System.out.print(dataOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes to {@link System#out} terminated by a new line.
|
||||||
|
*
|
||||||
|
* @param dataOut The string to write.
|
||||||
|
*/
|
||||||
|
public static void writeLine(String dataOut) {
|
||||||
|
System.out.println(dataOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a string from {@link System#in} terminated by a new line.
|
||||||
|
*
|
||||||
|
* @return The read string.
|
||||||
|
*/
|
||||||
|
public static String readString() {
|
||||||
|
if (System.console() != null) return System.console().readLine(); else {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
String line = "";
|
||||||
|
try {
|
||||||
|
line = reader.readLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a character from {@link System#in}.
|
||||||
|
*
|
||||||
|
* @return The read character.
|
||||||
|
*/
|
||||||
|
public static char readCharacter() {
|
||||||
|
char[] chars = readString().toCharArray();
|
||||||
|
return (chars.length > 0) ? chars[0] : (char) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an integer from {@link System#in} terminated by a new line.
|
||||||
|
*
|
||||||
|
* @return The integer or null.
|
||||||
|
*/
|
||||||
|
public static Integer readInt() {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(readString());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a long from {@link System#in} terminated by a new line.
|
||||||
|
*
|
||||||
|
* @return The long or null.
|
||||||
|
*/
|
||||||
|
public static Long readLong() {
|
||||||
|
try {
|
||||||
|
return Long.parseLong(readString());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
src/com/captainalm/utils/ObjectToString.java
Normal file
79
src/com/captainalm/utils/ObjectToString.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package com.captainalm.utils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the ability to output an object with all its fields.
|
||||||
|
*
|
||||||
|
* @author Captain ALM
|
||||||
|
*/
|
||||||
|
public class ObjectToString {
|
||||||
|
/**
|
||||||
|
* Gets the string representation of the passed object with its non-static fields.
|
||||||
|
*
|
||||||
|
* @param objectIn The object to output.
|
||||||
|
* @return The string representation.
|
||||||
|
*/
|
||||||
|
public static String toStringAllNonStatic(Object objectIn) {
|
||||||
|
if (objectIn == null) return "null";
|
||||||
|
StringBuilder b = new StringBuilder(objectIn + " [");
|
||||||
|
for (Field f : objectIn.getClass().getFields())
|
||||||
|
{
|
||||||
|
if (!Modifier.isStatic(f.getModifiers()))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object obj = f.get(objectIn);
|
||||||
|
b.append(f.getName()).append("=").append((obj == null) ? "null" : obj.toString()).append(" ");
|
||||||
|
} catch (IllegalAccessException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.append(']');
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the string representation of the passed object with its non-static getters.
|
||||||
|
*
|
||||||
|
* @param objectIn The object to output.
|
||||||
|
* @return The string representation.
|
||||||
|
*/
|
||||||
|
public static String toStringAllNonStaticGetters(Object objectIn) {
|
||||||
|
StringBuilder b = new StringBuilder(objectIn + " [");
|
||||||
|
for (Method m : objectIn.getClass().getMethods())
|
||||||
|
{
|
||||||
|
if (!Modifier.isStatic(m.getModifiers()) && m.getReturnType() != void.class && m.getParameterCount() == 0) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object obj = m.invoke(objectIn);
|
||||||
|
b.append(m.getName()).append("()=").append((obj == null) ? "null" : obj.toString()).append(" ");
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.append(']');
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the string representation of the passed object with its non-static getters that return integers or booleans.
|
||||||
|
*
|
||||||
|
* @param objectIn The object to output.
|
||||||
|
* @return The string representation.
|
||||||
|
*/
|
||||||
|
public static String toStringAllNonStaticIntBoolGetters(Object objectIn) {
|
||||||
|
StringBuilder b = new StringBuilder(objectIn + " [");
|
||||||
|
for (Method m : objectIn.getClass().getMethods())
|
||||||
|
{
|
||||||
|
if (!Modifier.isStatic(m.getModifiers()) && (m.getReturnType() == int.class || m.getReturnType() == Integer.class || m.getReturnType() == boolean.class || m.getReturnType() == Boolean.class) && m.getParameterCount() == 0) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object obj = m.invoke(objectIn);
|
||||||
|
b.append(m.getName()).append("()=").append((obj == null) ? "null" : obj.toString()).append(" ");
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.append(']');
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user