Initial commit

back_recharge
mashiyu 2018-12-27 17:54:23 +08:00
commit ea5bab62c6
173 changed files with 8194 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,2 @@
#Thu Dec 13 11:30:27 CST 2018
gradle.version=4.8

Binary file not shown.

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel>
<module name="jieling-server_main" target="1.8" />
<module name="jieling-server_test" target="1.8" />
</bytecodeTargetLevel>
</component>
</project>

21
.idea/gradle.xml 100644
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/common" />
<option value="$PROJECT_DIR$/hotfix" />
<option value="$PROJECT_DIR$/netty" />
<option value="$PROJECT_DIR$/serverlogic" />
</set>
</option>
<option name="useAutoImport" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>

7
.idea/misc.xml 100644
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View 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>

6
.idea/vcs.xml 100644
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

2272
.idea/workspace.xml 100644

File diff suppressed because it is too large Load Diff

15
build.gradle 100644
View File

@ -0,0 +1,15 @@
buildscript {
repositories {
maven { url "http://repo.spring.io/libs-release" }
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.4.RELEASE")
}
}

View File

@ -0,0 +1,25 @@
plugins {
id 'java'
}
group 'com.ljsd'
version '1.0.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
jar {
baseName = 'common'
version = '1.0.0'
manifest {
attributes 'Main-Class': 'com.ljsd.jieling.CommonApplication'
}
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.ljsd.jieling.CommonApplication

View File

@ -0,0 +1,128 @@
<configuration scan="true" scanPeriod="60 seconds">
<contextName>Jieling_Logging</contextName>
<property name="tip" value="INFO"/>
<!-- 定义日志文件 输入位置 -->
<property name="log_dir" value="/data/logs"/>
<!-- 日志最大的历史 30天 -->
<property name="maxHistory" value="30"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="UTF-8">
<pattern>[%level] - %d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %logger{0}#%line - ${tip}:%msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
</appender>
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<Encoding>UTF-8</Encoding>-->
<!-- 过滤器只记录WARN级别的日志 -->
<encoder charset="UTF-8">
<pattern>[%level] - %d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %logger{0}#%line - ${tip}:%msg%n</pattern>
</encoder>
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>-->
<!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志输出位置 可相对、和绝对路径 -->
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/corelog%i.log</fileNamePattern>
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6
则只保存最近6个月的文件删除之前的旧文件。注意删除旧文件是那些为了归档而创建的目录也会被删除-->
<maxHistory>${maxHistory}</maxHistory>
<maxFileSize>200MB</maxFileSize>
</rollingPolicy>
<!-- 按照固定窗口模式生成日志文件当文件大于20MB时生成新的日志文件。窗口大小是1到3当保存了3个归档文件后将覆盖最早的日志。
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy> -->
<!-- 查看当前活动文件的大小如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5KB</maxFileSize>
</triggeringPolicy>-->
</appender>
<!--
<appender name="AllLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/all/%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%level] - %d{yyyy-MM-dd- HH:mm:ss.SSS} - ${tip}:%msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
-->
<!-- ERROR级别日志 -->
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<Encoding>UTF-8</Encoding>-->
<!-- 过滤器只记录WARN级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志输出位置 可相对、和绝对路径 -->
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/error-log.log</fileNamePattern>
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6
则只保存最近6个月的文件删除之前的旧文件。注意删除旧文件是那些为了归档而创建的目录也会被删除-->
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<!-- 按照固定窗口模式生成日志文件当文件大于20MB时生成新的日志文件。窗口大小是1到3当保存了3个归档文件后将覆盖最早的日志。
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy> -->
<!-- 查看当前活动文件的大小如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy> -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="INFO"/>
<root level="INFO">
<!-- 控制台输出 -->
<appender-ref ref="console"/>
<appender-ref ref="file_console"/>
<!-- 文件输出 -->
<!--<appender-ref ref="AllLog" />-->
<appender-ref ref="ERROR"/>
<!--<appender-ref ref="TRACE" />-->
</root>
</configuration>

BIN
gradle/wrapper/gradle-wrapper.jar vendored 100644

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Mon Dec 17 14:08:44 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip

172
gradlew vendored 100644
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
gradlew.bat vendored 100644
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,26 @@
plugins {
id 'java'
}
group 'com.ljsd'
version '1.0.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
jar {
manifest{
attributes 'Manifest-Version':'1.0'
attributes 'Premain-Class':'com.ljsd.jieling.hotfix.JavaAgent'
attributes 'Agent-Class':'com.ljsd.jieling.hotfix.JavaAgent'
attributes 'Can-Retransform-Classes':true
attributes 'Can-Redefine-Classes':true
}
}

Binary file not shown.

View File

@ -0,0 +1,6 @@
Manifest-Version: 1.0
Premain-Class: com.ljsd.jieling.hotfix.JavaAgent
Agent-Class: com.ljsd.jieling.hotfix.JavaAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

View File

@ -0,0 +1,8 @@
package com.ljsd.jieling.hotfix;
public class DynamicClassLoader extends ClassLoader {
public Class<?> findClass(byte[] b) throws ClassNotFoundException {
return defineClass(null, b, 0, b.length);
}
}

View File

@ -0,0 +1,8 @@
package com.ljsd.jieling.hotfix;
public class HotFixApplication {
public static void main(String[] arg){
}
}

View File

@ -0,0 +1,96 @@
package com.ljsd.jieling.hotfix;
import java.io.*;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.text.SimpleDateFormat;
import java.util.Date;
public class JavaAgent {
private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
private static final Object object = new Object();
private static String logFileName = "hotfix.log";
private static SimpleDateFormat getDateFormat(String pattern)
throws RuntimeException {
SimpleDateFormat dateFormat = threadLocal.get();
if (dateFormat == null) {
synchronized (object) {
dateFormat = new SimpleDateFormat(pattern);
dateFormat.setLenient(false);
threadLocal.set(dateFormat);
}
}
dateFormat.applyPattern(pattern);
return dateFormat;
}
public static String getStrDateYMD() {
Date currentTime = new Date();
SimpleDateFormat formatter = getDateFormat("yyyyMMdd");
String dateString = formatter.format(currentTime);
return dateString;
}
public static String getStrDateYMDHMS() {
Date currentTime = new Date();
SimpleDateFormat formatter = getDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
return dateString;
}
private static void writeLog(Exception e){
try {
String fname = "../logs/" + getStrDateYMD() + "_" + logFileName;
File file = new File(fname);
OutputStream fos=new FileOutputStream(file, true);
PrintStream out = new PrintStream(fos);
writeLog(e.getMessage());
e.printStackTrace(out);
out.close();
} catch(Exception e1){
e.printStackTrace();
e1.printStackTrace();
}
}
private static void writeLog(String line){
try {
String fname = "../logs/" + getStrDateYMD() + "_" + logFileName;
File file = new File(fname);
OutputStream fos=new FileOutputStream(file, true);
PrintStream out = new PrintStream(fos);
line = "[" + getStrDateYMDHMS() + "][" + Thread.currentThread().getId() + "]:" + line + "\n";
out.print(line);
out.close();
} catch(Exception e){
e.printStackTrace();
}
}
//该方法支持在JVM 启动后再启动代理对应清单的Agent-Class:属性
public static void agentmain(String args,Instrumentation inst){
try{
writeLog("args=:[" + args + "]");
File f = new File(args);
byte[] targetClassFile = new byte[(int)f.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(f));
dis.readFully(targetClassFile);
dis.close();
DynamicClassLoader myLoader = new DynamicClassLoader();
Class targetClazz = myLoader.findClass(targetClassFile);
writeLog("class name is:["+targetClazz.getName() + "]");
Class<?> clz = Class.forName(targetClazz.getName());
writeLog("clz-->Class.forName:(\""+targetClazz.getName() + "\")");
ClassDefinition clazzDef = new ClassDefinition(clz, targetClassFile);
writeLog("ClassDefinition");
inst.redefineClasses(clazzDef);
writeLog("redefineClasses "+args+" finish!");
}catch(Exception e){
writeLog(e);
}
}
}

30
netty/build.gradle 100644
View File

@ -0,0 +1,30 @@
plugins {
id 'java'
}
group 'com.ljsd'
version '1.0.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile("org.javassist:javassist:3.18.2-GA")
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compile("io.netty:netty-all:4.0.21.Final")
compile("com.google.protobuf:protobuf-java:2.5.0")
compile 'com.google.guava:guava:23.5-android'
}
jar {
baseName = 'netty'
version = '1.0.0'
manifest {
attributes 'Main-Class': 'com.ljsd.jieling.NettyApplication'
}
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.ljsd.jieling.NettyApplication

View File

@ -0,0 +1,8 @@
package com.ljsd.jieling;
public class NettyApplication {
public static void main(String[] args) {
System.out.println("netty server ...");
}
}

View File

@ -0,0 +1,111 @@
package com.ljsd.jieling.netty;
import com.ljsd.jieling.session.GameSession;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class NettyGameSession implements GameSession {
protected Logger logger = LoggerFactory.getLogger(NettyGameSession.class);
private int uid;
private int areaId;
private int offlineType; // 0:正常下线1被踢下线
private long userLoginTime ;
private volatile ChannelHandlerContext ctx;
@Override
public boolean isOnline() {
return (this.ctx != null) && (this.ctx.channel().isActive());
}
@Override
public void write(Object msg) {
ChannelHandlerContext localCtx = this.ctx;
if ((localCtx != null) && (localCtx.channel() != null) && (localCtx.channel().isOpen())
&& (localCtx.channel().isActive()) && (localCtx.channel().isWritable())) {
localCtx.write(msg).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
} else {
logger.info("write,uid=>{}, write fail,localCtx={}",uid, localCtx);
}
}
public void writeAndFlush(Object msg) {
ChannelHandlerContext localCtx = this.ctx;
if ((localCtx != null) && (localCtx.channel() != null) && (localCtx.channel().isOpen())
&& (localCtx.channel().isActive()) && (localCtx.channel().isWritable())) {
localCtx.writeAndFlush(msg).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
} else {
logger.info("writeAndFlush, uid=>{},writeAndFlush fail, localCtx is {}", uid, localCtx);
}
}
@Override
public void close() {
if (this.ctx != null) {
this.ctx.channel().close();
}
}
public String getIp() {
if ((this.ctx != null) && (this.ctx.channel() != null)) {
String ip = this.ctx.channel().remoteAddress().toString();
if (!ip.equals("")) {
ip = ip.substring(1, ip.length() - 6);
}
return ip;
}
return "";
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
public ChannelHandlerContext getCtx() {
return ctx;
}
public void setCtx(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
public int getOfflineType() {
return offlineType;
}
public void setOfflineType(int offlineType) {
this.offlineType = offlineType;
}
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public long getUserLoginTime() {
return userLoginTime;
}
public void setUserLoginTime(long userLoginTime) {
this.userLoginTime = userLoginTime;
}
}

View File

@ -0,0 +1,10 @@
package com.ljsd.jieling.netty;
public class PackageConstant {
public static final int LENGTH_FIELD_LEN = 2; //网络包的前两个字节是有效数据的长度
public static final int UID_FIELD_LEN = 4; //从其他服务器回包到gateway时长度后的四个字节是玩家ID
public static final int MSG_ID_FIELD_LEN = 4; // 跟网络消息的消息号
public static final int RESULT_LEN = 4;//请求结果
public static final int TOKEN_LEN = 4;//token长度
public static final int INDEX_FIELD_LEN = 4;
}

View File

@ -0,0 +1,35 @@
package com.ljsd.jieling.netty.cocdex;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
public class BaseDecoder extends ByteToMessageDecoder {
private static final Logger LOGGER = LoggerFactory.getLogger(BaseDecoder.class);
public BaseDecoder(){
}
public short readLean(ByteBuf in){
in.markReaderIndex();
final byte[] buf = new byte[2];
for (int i = 0; i < buf.length; i ++) {
if (!in.isReadable()) {
in.resetReaderIndex();
return -1;
}
buf[i] = in.readByte();
}
int length = Tea.byteToShort(buf, 0);
return (short) length;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
}
}

View File

@ -0,0 +1,41 @@
package com.ljsd.jieling.netty.cocdex;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
public class ByteBufDecoder extends BaseDecoder {
private static final Logger LOGGER = LoggerFactory.getLogger(ByteBufDecoder.class);
public ByteBufDecoder() {
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
String secret_key = "";
try {
int length = readLean(in);
int encodeLen = (length +7) / 8 * 8;
if(length == 0){
LOGGER.debug("decode->receive empty heartbeat parackage");
return;
}
if (in.readableBytes() < encodeLen){
in.resetReaderIndex();
return;
} else {
ByteBuf message = in.readBytes(encodeLen);
int[] secretKey = Tea.KEY;
byte[] packetNetData = Tea.decrypt2(message.array(), length,0, secretKey);
out.add(packetNetData);
}
} catch (Exception e) {
LOGGER.error("decode->secret_key={},emsg={}", secret_key, e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,26 @@
package com.ljsd.jieling.netty.cocdex;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ChannelHandler.Sharable
public class ByteBufEncoder extends MessageToByteEncoder<byte[]> {
private static final Logger LOGGER = LoggerFactory.getLogger(ByteBufDecoder.class);
public ByteBufEncoder(){
}
@Override
protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) {
try {
//不加密
// out.writeShort((short) msg.length);
out.writeBytes(msg, 0, msg.length);
} catch (Exception e){
LOGGER.error("encode->emsg={}", e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,43 @@
package com.ljsd.jieling.netty.cocdex;
public class ClientDate {
//包长2 uid 4 msgid 4 result 4 index4
private byte[] clientDate;
public int getMsgId() {
return Tea.byteToInt(clientDate, 4);
}
public int getUid() {
return Tea.byteToInt(clientDate, 0);
}
public int getResult() {
return Tea.byteToInt(clientDate, 8);
}
public int getIndex() {
return Tea.byteToInt(clientDate, 12);
}
/**
*
*
* @return
*/
public byte[] parseProtoNetData() {
byte[] data = new byte[clientDate.length - 16];
System.arraycopy(clientDate, 16, data, 0, data.length);
return data;
}
public byte[] getClientDate() {
return clientDate;
}
public void setClientDate(byte[] clientDate) {
this.clientDate = clientDate;
}
}

View File

@ -0,0 +1,79 @@
package com.ljsd.jieling.netty.cocdex;
import com.ljsd.jieling.tools.DESHelper;
import com.ljsd.jieling.tools.Utils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import java.util.List;
/**
*
*
* int) + GameMessage
* 4int
* Sharable,广
*/
public class Int32FrameDecoder extends ByteToMessageDecoder {
private static final Logger LOGGER = LoggerFactory.getLogger(Int32FrameDecoder.class);
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
// LOGGER.info("receieve the pack");
String secret_key = "";
try {
in.markReaderIndex();
final byte[] buf = new byte[4];
for (int i = 0; i < buf.length; i ++) {
if (!in.isReadable()) {
in.resetReaderIndex();
return;
}
buf[i] = in.readByte();
}
int length = Utils.bytesToInt(buf, 0);
if (in.readableBytes() < length){
in.resetReaderIndex();
// LOGGER.info("receieve fail pack");
return;
}else{
ByteBuf message = in.readBytes(length);
secret_key = ctx.channel().attr(DESHelper.LOGIN_ENCRYPTION_KEY).get();
byte[] key = null;
if (secret_key == null || secret_key.equals("")){
key = new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY);
}else {
key = new BASE64Decoder().decodeBuffer(secret_key);
}
byte[] decodeMsg = null;
try {
decodeMsg = DESHelper.des3DecodeCBC(key, DESHelper.keyiv, message.array());
}catch (Exception e){
LOGGER.error("decode->secret_key={},msg={}", secret_key, e.getMessage(), e);
decodeMsg = DESHelper.des3DecodeCBC(new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY), DESHelper.keyiv, message.array());
}
ByteBuf byteBuf = Unpooled.wrappedBuffer(decodeMsg);
out.add(byteBuf);
return;
}
}catch (Exception e){
LOGGER.error("decode->secret_key={},msg={}", secret_key, e.getMessage(), e);
}
// Couldn't find the byte whose MSB is off.
// throw new CorruptedFrameException("length wider than 32-bit");
}
}

View File

@ -0,0 +1,52 @@
package com.ljsd.jieling.netty.cocdex;
import com.ljsd.jieling.tools.DESHelper;
import com.ljsd.jieling.tools.Utils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import sun.misc.BASE64Decoder;
/**
*
* (4)
*/
@ChannelHandler.Sharable
public class Int32LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
String secret_key = ctx.channel().attr(DESHelper.LOGIN_ENCRYPTION_KEY).get();
String new_Secret_key = ctx.channel().attr(DESHelper.IS_NEW_KEY).getAndRemove();
byte[] key = null;
if (secret_key == null || secret_key.equals("")){
key = new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY);
// LOGGER.info("encode loginEncryptionKey..."+DESHelper.SECRET_KEY);
}else {
if (new_Secret_key!=null){
key = new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY);
// LOGGER.info("###encode loginEncryptionKey..."+DESHelper.SECRET_KEY);
}else {
key = new BASE64Decoder().decodeBuffer(secret_key);
// LOGGER.info("encode loginEncryptionKey..."+secret_key);
}
}
byte[] encodeMsg = DESHelper.des3EncodeCBC(key, DESHelper.keyiv, msg.array());
ByteBuf byteBuf = Unpooled.wrappedBuffer(encodeMsg);
int bodyLen = byteBuf.readableBytes();
int headerLen = 4;
out.ensureWritable(headerLen + bodyLen);
byte[] headerByte = Utils.intToBytes(bodyLen);
out.writeBytes(headerByte, 0, headerLen);
out.writeBytes(byteBuf, byteBuf.readerIndex(), bodyLen);
}
}

View File

@ -0,0 +1,49 @@
package com.ljsd.jieling.netty.cocdex;
public class NetData {
private int routerId;
private byte routerType;
private int msgId;
private int index;
private byte[] content;
public int getRouterId() {
return routerId;
}
public void setRouterId(int routerId) {
this.routerId = routerId;
}
public byte getRouterType() {
return routerType;
}
public void setRouterType(byte routerType) {
this.routerType = routerType;
}
public int getMsgId() {
return msgId;
}
public void setMsgId(int requestType) {
this.msgId = requestType;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
}

View File

@ -0,0 +1,62 @@
package com.ljsd.jieling.netty.cocdex;
public class PacketNetData {
//
private byte[] packetData;
public PacketNetData(byte[] packetData) {
this.packetData = packetData;
}
public void setPacketData(byte[] packetData) {
this.packetData = packetData;
}
public int getUserId() {
return Tea.byteToInt(packetData, 0);
}
public int getToken() {
return Tea.byteToInt(packetData, 4);
}
public int getMsgId() {
return Tea.byteToInt(packetData, 8);
}
public int getIndex() {
return Tea.byteToInt(packetData, 12);
}
public int getResult() {
return Tea.byteToInt(packetData, 16);
}
/**
*
*
* @return
*/
public byte[] parseClientProtoNetData() {
byte[] data = new byte[packetData.length - 16];
System.arraycopy(packetData, 16, data, 0, data.length);
return data;
}
public byte[] parseServerProtoNetData() {
byte[] data = new byte[packetData.length - 20];
System.arraycopy(packetData, 20, data, 0, data.length);
return data;
}
/**
*
*
* @return
*/
public byte[] getPacketData() {
return packetData;
}
}

View File

@ -0,0 +1,206 @@
package com.ljsd.jieling.netty.cocdex; /** */
import java.util.Random;
/**
* Tea
* 8
* KEY16,4intint[]int4
* 864
*/
public class Tea {
public static int[] KEY = new int[]{//加密解密所用的KEY
0x789f5645, 0xf68bd5a4,
0x81963ffa, 0x458fac58
};
private static int TIMES = 32;
public static int[] generateSecretKey() {
Random rand = new Random();
int[] secretKey = new int[4];
for (int i = 0; i < 4; i++) {
secretKey[i] = rand.nextInt();
}
return secretKey;
}
//若某字节被解释成负的则需将其转成无符号正数
private static int transform(byte temp) {
int tempInt = (int) temp;
if (tempInt < 0) {
tempInt += 256;
}
return tempInt;
}
public static int byteToInt(byte[] content, int offset) {
int result = transform(content[offset + 3]) | transform(content[offset + 2]) << 8 |
transform(content[offset + 1]) << 16 | (int) content[offset] << 24;
return result;
}
public static void intToByte(byte[] bys, int offset, int content) {
bys[offset + 3] = (byte) (content & 0xff);
bys[offset + 2] = (byte) ((content >> 8) & 0xff);
bys[offset + 1] = (byte) ((content >> 16) & 0xff);
bys[offset] = (byte) ((content >> 24) & 0xff);
}
//byte[]型数据转成int[]型数据
private static int[] byteToIntArray(byte[] content, int offset) {
int[] result = new int[content.length >> 2]; //除以2的n次方 == 右移n位 即 content.length / 4 == content.length >> 2
for (int i = 0, j = offset; j < content.length; i++, j += 4) {
result[i] = byteToInt(content, j);
}
return result;
}
//int[]型数据转成byte[]型数据
private static byte[] intArrayToByte(int[] content, int offset) {
byte[] result = new byte[content.length << 2]; //乘以2的n次方 == 左移n位 即 content.length * 4 == content.length << 2
for (int i = 0, j = offset; j < result.length; i++, j += 4) {
intToByte(result, j, content[i]);
}
return result;
}
//加密
public static byte[] encrypt(byte[] content, int offset, int[] key, int times) {//times为加密轮数
int[] tempInt = byteToIntArray(content, offset);
int y = tempInt[0], z = tempInt[1], sum = 0, i;
int delta = 0x9e3779b9; //这是算法标准给的值
int a = key[0], b = key[1], c = key[2], d = key[3];
for (i = 0; i < times; i++) {
sum += delta;
y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
}
tempInt[0] = y;
tempInt[1] = z;
return intArrayToByte(tempInt, 0);
}
//解密
public static byte[] decrypt(byte[] encryptContent, int offset, int[] key, int times) {
int[] tempInt = byteToIntArray(encryptContent, offset);
int y = tempInt[0], z = tempInt[1], sum = 0xC6EF3720, i;
int delta = 0x9e3779b9; //这是算法标准给的值
int a = key[0], b = key[1], c = key[2], d = key[3];
for (i = 0; i < times; i++) {
z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
sum -= delta;
}
tempInt[0] = y;
tempInt[1] = z;
return intArrayToByte(tempInt, 0);
}
public static void shortToByte(byte[] bys, int offset, int content) {
bys[offset + 1] = (byte) (content & 0xff);
bys[offset] = (byte) ((content >> 8) & 0xff);
}
public static int byteToShort(byte[] content, int offset) {
int result = transform(content[offset + 1]) | transform(content[offset]) << 8;
return result;
}
public static byte[] encrypt2(byte[] content, int[] key) {
byte[] bys = content;
if (bys.length % 8 != 0) {
bys = new byte[(bys.length + 7) / 8 * 8];
System.arraycopy(content, 0, bys, 0, content.length);
}
byte[] encryptContent = encrypt(bys, 0, key, TIMES);
byte[] result = new byte[encryptContent.length + 2];
shortToByte(result, 0, content.length);
System.arraycopy(encryptContent, 0, result, 2, encryptContent.length);
return result;
}
public static byte[] decrypt2(byte[] encryptContent, int len, int offset, int[] key) {
byte[] decryptContent = decrypt(encryptContent, offset, key, TIMES);
if (len == decryptContent.length) {
return decryptContent;
}
byte[] bys = new byte[len];
System.arraycopy(decryptContent, 0, bys, 0, len);
return bys;
}
// public static byte[] encrypt3(NetData netData, int[] key) {
// //4:routerId, 1:routerType+reqestType
// //取8的整数倍长度
// int length = netData.getContent().length + 19;
// byte[] plainText = new byte[length];
//
// intToByte(plainText, 0, netData.getRouterId());
// plainText[4] = netData.getRouterType();
// intToByte(plainText, 5, netData.getMsgId());
// System.arraycopy(netData.getContent(), 0, plainText, 19, netData.getContent().length);
// return encrypt2(plainText, key);
// }
//
// public static PacketNetData decrypt3(int length, byte[] encryptContent, int offset, int[] key) {
// byte[] decryptContent = decrypt2(encryptContent, length, offset, key);
// PacketNetData packetNetData = new PacketNetData(decryptContent);
// return packetNetData;
// }
// public static void main(String[] args) {
// String plainStr = "123";
// byte[] encryptBys = encrypt2(plainStr.getBytes(), KEY);
// int length = byteToShort(encryptBys, 0);
// byte[] decodeBys = decrypt2(encryptBys, length, 2, KEY);
// String decryptStr = new String(decodeBys);
// System.out.println("decryptStr=" + decryptStr);
//
// NetData netData = new NetData();
// long startTime = System.currentTimeMillis();
// netData.setContent(new byte[50]);
// for (int i = 0; i < netData.getContent().length; i++) {
// netData.getContent()[i] = (byte) i;
// }
// netData.setRouterId(1);
// netData.setRouterType((byte) 2);
// netData.setMsgId(3);
// for (int i = 0; i < 100000; i++) {
// byte[] secretInfo = encrypt3(netData, KEY);
// length = byteToShort(secretInfo, 0);
// PacketNetData packetNetData = decrypt3(length, secretInfo, 2, KEY);
//
// if (netData.getRouterId() != packetNetData.getRouterId()) {
// System.out.println("netData.routerId != netData2.routerId");
// return;
// }
// if (netData.getRouterType() != packetNetData.getRouterType()) {
// System.out.println("netData.routerType != netData2.routerType");
// return;
// }
//
// byte[] data = packetNetData.getMsgIdAndPBData();
// if (netData.getContent().length != data.length) {
// System.out.println("netData.content.length != netData2.content.length");
// return;
// }
// int j;
// for (j = 0; j < netData.getContent().length; j++) {
// if (netData.getContent()[j] != data[j]) {
// System.out.println("decryptInfo[j] != info[j]");
// return;
// }
// }
// }
// long endTime = System.currentTimeMillis();
// //加解密10万用时91毫秒
// System.out.println("加解密10万用时" + (endTime - startTime) + "毫秒");
// }
}

View File

@ -0,0 +1,51 @@
package com.ljsd.jieling.netty.cocdex;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
public class TeaDecoder extends ByteToMessageDecoder {
private static final Logger LOGGER = LoggerFactory.getLogger(TeaDecoder.class);
public TeaDecoder(){
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
String secret_key = "";
try {
in.markReaderIndex();
final byte[] buf = new byte[2];
for (int i = 0; i < buf.length; i ++) {
if (!in.isReadable()) {
in.resetReaderIndex();
return;
}
buf[i] = in.readByte();
}
int length = Tea.byteToShort(buf, 0);
int encodeLen = (length +7) / 8 * 8;
if(length == 0){
LOGGER.debug("decode->receive empty heartbeat parackage");
return;
}
if (in.readableBytes() < encodeLen){
in.resetReaderIndex();
return;
}else{
ByteBuf message = in.readBytes(encodeLen);
// int[] secretKey = SessionManager.getSecretKey(ctx);
int[] secretKey = Tea.KEY;
byte[] packetNetData = Tea.decrypt2( message.array(), length,0, secretKey);
out.add(packetNetData);
}
}catch (Exception e){
LOGGER.error("decode->secret_key={},emsg={}", secret_key, e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,34 @@
package com.ljsd.jieling.netty.cocdex;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ChannelHandler.Sharable
public class TeaEncoder extends MessageToByteEncoder<byte[]> {
private static final Logger LOGGER = LoggerFactory.getLogger(TeaDecoder.class);
public TeaEncoder(){
}
@Override
protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) {
try {
int[] secretKey;
// if (CtxUtil.isFirstPacket(ctx)) {
// secretKey = Tea.KEY;
// } else {
// secretKey = SessionManager.getSecretKey(ctx);
// }
// out.writeShort((short) msg.length);
out.writeBytes(msg, 0, msg.length);
// System.out.println(out.array());
} catch (Exception e){
LOGGER.error("decode->emsg={}", e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,90 @@
package com.ljsd.jieling.netty.handler;
import com.ljsd.jieling.netty.NettyGameSession;
import com.ljsd.jieling.protocol.ProtocolsAbstract;
import com.ljsd.jieling.session.GameSession;
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.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class GameMessageHandler<T extends GameSession> extends SimpleChannelInboundHandler<Object> {
private static final Logger LOGGER = LoggerFactory.getLogger(GameMessageHandler.class);
public static Map<Integer, NettyGameSession> currentSessions = new ConcurrentHashMap<>();
public static ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
static final AttributeKey<GameSession> DEBUG_SESSION_KEY = AttributeKey.valueOf("DEBUG_SESSION_KEY");
private final T session;
private final ProtocolsAbstract protocols;
public GameMessageHandler(T session, ProtocolsAbstract protocols) {
this.session = session;
this.protocols = protocols;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
LOGGER.info("seission"+this.session+"channelActive: " + ctx.channel().remoteAddress()+" ,uid: "+
((NettyGameSession) this.session).getUid() +" ,areaId: "+ ((NettyGameSession) this.session).getAreaId());
ctx.channel().attr(DEBUG_SESSION_KEY).set(this.session);
((NettyGameSession) this.session).setCtx(ctx);
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
LOGGER.info("channelInactive->uid={},seission={},remoteAddress={}",
((NettyGameSession) this.session).getUid(), this.session, ctx.channel().remoteAddress());
protocols.offLine(this.session);
((NettyGameSession) this.session).setCtx(null);
ctx.channel().attr(DEBUG_SESSION_KEY).remove();
ctx.flush();
ctx.close();
super.channelInactive(ctx);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
LOGGER.info("111111111111");
protocols.processMessage(this.session, msg);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt);
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
if (e.state() == IdleState.READER_IDLE) {
protocols.readIdel(this.session);
}
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
//ctx.writeAndFlush(Unpooled.EMPTY_BUFFER);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// cause.printStackTrace();
// LOGGER.debug("client have disconnected:-->"+cause.getMessage()+" IP:"+ctx.channel().remoteAddress());
cause.printStackTrace();
ctx.close();
}
}

View File

@ -0,0 +1,68 @@
package com.ljsd.jieling.netty.handler;
import com.google.protobuf.MessageLite;
import com.ljsd.jieling.protocol.ProtocolsAbstract;
import com.ljsd.jieling.session.GameSession;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*
*/
public class ServerResponseMessageHandler<T extends GameSession> extends SimpleChannelInboundHandler<MessageLite> {
private static final Logger LOGGER = LoggerFactory.getLogger(ServerResponseMessageHandler.class);
private volatile Channel channel;
private final T session;
private final ProtocolsAbstract protocols;
public ServerResponseMessageHandler(T session, ProtocolsAbstract protocols) {
this.session = session;
this.protocols = protocols;
}
public Channel getChannel() {
return channel;
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) {
channel = ctx.channel();
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
LOGGER.info("userEventTriggered->evt=" + evt);
if (evt instanceof IdleStateEvent) {
// 不管是读事件空闲还是写事件空闲都向服务器发送心跳包
protocols.readIdel(this.session);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
LOGGER.info("exceptionCaught->remoteAddress={}" +
ctx.channel().remoteAddress().toString());
cause.printStackTrace();
ctx.close();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
LOGGER.info("channelInactive->run");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
LOGGER.info("channelReadComplete->run");
super.channelReadComplete(ctx);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, MessageLite msg) throws Exception {
LOGGER.info("channelRead0->run");
}
}

View File

@ -0,0 +1,101 @@
package com.ljsd.jieling.netty.server;
import com.google.protobuf.MessageLite;
import com.ljsd.jieling.netty.cocdex.Int32FrameDecoder;
import com.ljsd.jieling.netty.cocdex.Int32LengthFieldPrepender;
import com.ljsd.jieling.netty.handler.ServerResponseMessageHandler;
import com.ljsd.jieling.protocol.ProtocolsAbstract;
import com.ljsd.jieling.session.GameSession;
import com.ljsd.jieling.session.GameSessionFactory;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class NettyGameClient<T extends GameSession> {
private static final Logger LOGGER = LoggerFactory.getLogger(NettyGameClient.class);
private static Bootstrap bootstrap = null;
//key位IP+Port的组合
private static Map<String, Channel> channels = new ConcurrentHashMap<>();
private final int readTimeout;
private final int writeTimeout;
private final int allTimeout;
private final MessageLite gameMessage;
private final ProtocolsAbstract protocols;
private final GameSessionFactory<T> sessionFactory;
public NettyGameClient(int readTimeout, int writeTimeout,
int allTimeout, MessageLite gameMessage, ProtocolsAbstract protocols, GameSessionFactory<T> sessionFactory) {
this.readTimeout = readTimeout;
this.writeTimeout = writeTimeout;
this.allTimeout = allTimeout;
this.gameMessage = gameMessage;
this.protocols = protocols;
this.sessionFactory = sessionFactory;
}
public void start() {
try {
EventLoopGroup group = new NioEventLoopGroup(1);
bootstrap = new Bootstrap();
bootstrap.group(group)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.option(ChannelOption.SO_LINGER, 0)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer() {
@SuppressWarnings("unchecked")
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new Int32FrameDecoder());
p.addLast(new ProtobufDecoder(gameMessage));
// 心跳检测处理
p.addLast(new IdleStateHandler(readTimeout, writeTimeout, allTimeout, TimeUnit.SECONDS));
p.addLast(new Int32LengthFieldPrepender());
p.addLast(new ProtobufEncoder());
p.addLast(new ServerResponseMessageHandler(sessionFactory.createGameSession(), protocols));
}
});
} catch (Exception e) {
LOGGER.error("start->msg={}", e.getMessage(), e);
}
}
public static Channel getChannel(String serverIp, int port) {
try {
String key = serverIp + ":" + port;
Channel channel = channels.get(key);
if(channel == null || !channel.isOpen() || !channel.isActive()) {
channel = bootstrap.connect(serverIp, port).sync().channel();
channels.put(key, channel);
}
return channel;
} catch (Exception e) {
LOGGER.error("getChannel->serverIp={},port={},msg={}", serverIp, port, e.getMessage(), e);
}
return null;
}
public static Channel getChannel(String serverIpPort) {
String strs[] = serverIpPort.split(":");
return getChannel(strs[0], Integer.parseInt(strs[1]));
}
}

View File

@ -0,0 +1,94 @@
package com.ljsd.jieling.netty.server;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.ljsd.jieling.netty.cocdex.TeaDecoder;
import com.ljsd.jieling.netty.cocdex.TeaEncoder;
import com.ljsd.jieling.netty.handler.GameMessageHandler;
import com.ljsd.jieling.protocol.ProtocolsAbstract;
import com.ljsd.jieling.session.GameSession;
import com.ljsd.jieling.session.GameSessionFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public class NettyGameServer<T extends GameSession> {
private final int tcpPort;
private final int readTimeout;
private final int writeTimeout;
private final int allTimeout;
// private final MessageLite gameMessage;
private final ProtocolsAbstract protocols;
private final GameSessionFactory<T> sessionFactory;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
public NettyGameServer(int tcpPort, int readTimeout, int writeTimeout,
int allTimeout, ProtocolsAbstract protocols, GameSessionFactory<T> sessionFactory) {
this.tcpPort = tcpPort;
this.readTimeout = readTimeout;
this.writeTimeout = writeTimeout;
this.allTimeout = allTimeout;
// this.gameMessage = gameMessage;
this.protocols = protocols;
this.sessionFactory = sessionFactory;
}
// @SuppressWarnings("unused")
// private ChannelFuture channelFuture = null;
@SuppressWarnings("rawtypes")
public void start() throws Exception {
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("netty-%d").build();
bossGroup = new NioEventLoopGroup(0, factory);
workerGroup = new NioEventLoopGroup(16, factory);
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_LINGER, 0)
.handler(new LoggingHandler(LogLevel.DEBUG))
.childHandler(new ChannelInitializer() {
@SuppressWarnings("unchecked")
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
// 心跳检测处理
p.addLast(new IdleStateHandler(readTimeout, writeTimeout, allTimeout, TimeUnit.SECONDS));
p.addLast(new TeaDecoder());
p.addLast(new TeaEncoder());
p.addLast(new GameMessageHandler(NettyGameServer.this.sessionFactory.createGameSession(), protocols));
}
});
try {
serverBootstrap.bind(tcpPort).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
}
}
public void stop() throws Exception {
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
}
}

View File

@ -0,0 +1,15 @@
package com.ljsd.jieling.protocol;
import com.google.protobuf.InvalidProtocolBufferException;
import com.ljsd.jieling.session.GameSession;
public interface ProtocolsAbstract {
void processMessage(GameSession gameSession, final Object gameMessage) throws InvalidProtocolBufferException;
void offLine(GameSession gameSession);
void readIdel(GameSession gameSession);
}

View File

@ -0,0 +1,12 @@
package com.ljsd.jieling.session;
public interface GameSession {
boolean isOnline();
void write(Object paramObject);
void close();
void postClose();
}

View File

@ -0,0 +1,7 @@
package com.ljsd.jieling.session;
public interface GameSessionFactory<T extends GameSession> {
T createGameSession();
}

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