45 |
46 |
--------------------------------------------------------------------------------
/nad/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/util/Charsetfunctions.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.util;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.nio.ByteBuffer;
5 | import java.nio.charset.CharacterCodingException;
6 | import java.nio.charset.Charset;
7 | import java.nio.charset.CharsetDecoder;
8 | import java.nio.charset.CodingErrorAction;
9 |
10 | import org.java_websocket.exceptions.InvalidDataException;
11 | import org.java_websocket.framing.CloseFrame;
12 |
13 | public class Charsetfunctions {
14 |
15 | public static CodingErrorAction codingErrorAction = CodingErrorAction.REPORT;
16 |
17 | /*
18 | * @return UTF-8 encoding in bytes
19 | */
20 | public static byte[] utf8Bytes( String s ) {
21 | try {
22 | return s.getBytes( "UTF8" );
23 | } catch ( UnsupportedEncodingException e ) {
24 | throw new RuntimeException( e );
25 | }
26 | }
27 |
28 | /*
29 | * @return ASCII encoding in bytes
30 | */
31 | public static byte[] asciiBytes( String s ) {
32 | try {
33 | return s.getBytes( "ASCII" );
34 | } catch ( UnsupportedEncodingException e ) {
35 | throw new RuntimeException( e );
36 | }
37 | }
38 |
39 | public static String stringAscii( byte[] bytes ) {
40 | return stringAscii( bytes, 0, bytes.length );
41 | }
42 |
43 | public static String stringAscii( byte[] bytes, int offset, int length ){
44 | try {
45 | return new String( bytes, offset, length, "ASCII" );
46 | } catch ( UnsupportedEncodingException e ) {
47 | throw new RuntimeException( e );
48 | }
49 | }
50 |
51 | public static String stringUtf8( byte[] bytes ) throws InvalidDataException {
52 | return stringUtf8( ByteBuffer.wrap( bytes ) );
53 | }
54 |
55 | /*public static String stringUtf8( byte[] bytes, int off, int length ) throws InvalidDataException {
56 | CharsetDecoder decode = Charset.forName( "UTF8" ).newDecoder();
57 | decode.onMalformedInput( codingErrorAction );
58 | decode.onUnmappableCharacter( codingErrorAction );
59 | //decode.replaceWith( "X" );
60 | String s;
61 | try {
62 | s = decode.decode( ByteBuffer.wrap( bytes, off, length ) ).toString();
63 | } catch ( CharacterCodingException e ) {
64 | throw new InvalidDataException( CloseFrame.NO_UTF8, e );
65 | }
66 | return s;
67 | }*/
68 |
69 | public static String stringUtf8( ByteBuffer bytes ) throws InvalidDataException {
70 | CharsetDecoder decode = Charset.forName( "UTF8" ).newDecoder();
71 | decode.onMalformedInput( codingErrorAction );
72 | decode.onUnmappableCharacter( codingErrorAction );
73 | // decode.replaceWith( "X" );
74 | String s;
75 | try {
76 | bytes.mark();
77 | s = decode.decode( bytes ).toString();
78 | bytes.reset();
79 | } catch ( CharacterCodingException e ) {
80 | throw new InvalidDataException( CloseFrame.NO_UTF8, e );
81 | }
82 | return s;
83 | }
84 |
85 | public static void main( String[] args ) throws InvalidDataException {
86 | stringUtf8( utf8Bytes( "\0" ) );
87 | stringAscii( asciiBytes( "\0" ) );
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/org/java_websocket/util/Charsetfunctions.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.util;
2 |
3 | import org.java_websocket.exceptions.InvalidDataException;
4 | import org.java_websocket.framing.CloseFrame;
5 |
6 | import java.io.UnsupportedEncodingException;
7 | import java.nio.ByteBuffer;
8 | import java.nio.charset.CharacterCodingException;
9 | import java.nio.charset.Charset;
10 | import java.nio.charset.CharsetDecoder;
11 | import java.nio.charset.CodingErrorAction;
12 |
13 | public class Charsetfunctions {
14 |
15 | public static CodingErrorAction codingErrorAction = CodingErrorAction.REPORT;
16 |
17 | /*
18 | * @return UTF-8 encoding in bytes
19 | */
20 | public static byte[] utf8Bytes( String s ) {
21 | try {
22 | return s.getBytes( "UTF8" );
23 | } catch ( UnsupportedEncodingException e ) {
24 | throw new RuntimeException( e );
25 | }
26 | }
27 |
28 | /*
29 | * @return ASCII encoding in bytes
30 | */
31 | public static byte[] asciiBytes( String s ) {
32 | try {
33 | return s.getBytes( "ASCII" );
34 | } catch ( UnsupportedEncodingException e ) {
35 | throw new RuntimeException( e );
36 | }
37 | }
38 |
39 | public static String stringAscii( byte[] bytes ) {
40 | return stringAscii( bytes, 0, bytes.length );
41 | }
42 |
43 | public static String stringAscii( byte[] bytes, int offset, int length ){
44 | try {
45 | return new String( bytes, offset, length, "ASCII" );
46 | } catch ( UnsupportedEncodingException e ) {
47 | throw new RuntimeException( e );
48 | }
49 | }
50 |
51 | public static String stringUtf8( byte[] bytes ) throws InvalidDataException {
52 | return stringUtf8( ByteBuffer.wrap(bytes) );
53 | }
54 |
55 | /*public static String stringUtf8( byte[] bytes, int off, int length ) throws InvalidDataException {
56 | CharsetDecoder decode = Charset.forName( "UTF8" ).newDecoder();
57 | decode.onMalformedInput( codingErrorAction );
58 | decode.onUnmappableCharacter( codingErrorAction );
59 | //decode.replaceWith( "X" );
60 | String s;
61 | try {
62 | s = decode.decode( ByteBuffer.wrap( bytes, off, length ) ).toString();
63 | } catch ( CharacterCodingException e ) {
64 | throw new InvalidDataException( CloseFrame.NO_UTF8, e );
65 | }
66 | return s;
67 | }*/
68 |
69 | public static String stringUtf8( ByteBuffer bytes ) throws InvalidDataException {
70 | CharsetDecoder decode = Charset.forName("UTF8").newDecoder();
71 | decode.onMalformedInput( codingErrorAction );
72 | decode.onUnmappableCharacter( codingErrorAction );
73 | // decode.replaceWith( "X" );
74 | String s;
75 | try {
76 | bytes.mark();
77 | s = decode.decode( bytes ).toString();
78 | bytes.reset();
79 | } catch ( CharacterCodingException e ) {
80 | throw new InvalidDataException( CloseFrame.NO_UTF8, e );
81 | }
82 | return s;
83 | }
84 |
85 | public static void main( String[] args ) throws InvalidDataException {
86 | stringUtf8( utf8Bytes( "\0" ) );
87 | stringAscii( asciiBytes( "\0" ) );
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/framing/FramedataImpl1.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.framing;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.util.Arrays;
5 |
6 | import org.java_websocket.exceptions.InvalidDataException;
7 | import org.java_websocket.exceptions.InvalidFrameException;
8 | import org.java_websocket.util.Charsetfunctions;
9 |
10 | public class FramedataImpl1 implements FrameBuilder {
11 | protected static byte[] emptyarray = {};
12 | protected boolean fin;
13 | protected Opcode optcode;
14 | private ByteBuffer unmaskedpayload;
15 | protected boolean transferemasked;
16 |
17 | public FramedataImpl1() {
18 | }
19 |
20 | public FramedataImpl1( Opcode op ) {
21 | this.optcode = op;
22 | unmaskedpayload = ByteBuffer.wrap( emptyarray );
23 | }
24 |
25 | /**
26 | * Helper constructor which helps to create "echo" frames.
27 | * The new object will use the same underlying payload data.
28 | **/
29 | public FramedataImpl1( Framedata f ) {
30 | fin = f.isFin();
31 | optcode = f.getOpcode();
32 | unmaskedpayload = f.getPayloadData();
33 | transferemasked = f.getTransfereMasked();
34 | }
35 |
36 | @Override
37 | public boolean isFin() {
38 | return fin;
39 | }
40 |
41 | @Override
42 | public Opcode getOpcode() {
43 | return optcode;
44 | }
45 |
46 | @Override
47 | public boolean getTransfereMasked() {
48 | return transferemasked;
49 | }
50 |
51 | @Override
52 | public ByteBuffer getPayloadData() {
53 | return unmaskedpayload;
54 | }
55 |
56 | @Override
57 | public void setFin( boolean fin ) {
58 | this.fin = fin;
59 | }
60 |
61 | @Override
62 | public void setOptcode( Opcode optcode ) {
63 | this.optcode = optcode;
64 | }
65 |
66 | @Override
67 | public void setPayload( ByteBuffer payload ) throws InvalidDataException {
68 | unmaskedpayload = payload;
69 | }
70 |
71 | @Override
72 | public void setTransferemasked( boolean transferemasked ) {
73 | this.transferemasked = transferemasked;
74 | }
75 |
76 | @Override
77 | public void append( Framedata nextframe ) throws InvalidFrameException {
78 | ByteBuffer b = nextframe.getPayloadData();
79 | if( unmaskedpayload == null ) {
80 | unmaskedpayload = ByteBuffer.allocate( b.remaining() );
81 | b.mark();
82 | unmaskedpayload.put( b );
83 | b.reset();
84 | } else {
85 | b.mark();
86 | unmaskedpayload.position( unmaskedpayload.limit() );
87 | unmaskedpayload.limit( unmaskedpayload.capacity() );
88 |
89 | if( b.remaining() > unmaskedpayload.remaining() ) {
90 | ByteBuffer tmp = ByteBuffer.allocate( b.remaining() + unmaskedpayload.capacity() );
91 | unmaskedpayload.flip();
92 | tmp.put( unmaskedpayload );
93 | tmp.put( b );
94 | unmaskedpayload = tmp;
95 |
96 | } else {
97 | unmaskedpayload.put( b );
98 | }
99 | unmaskedpayload.rewind();
100 | b.reset();
101 | }
102 | fin = nextframe.isFin();
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return "Framedata{ optcode:" + getOpcode() + ", fin:" + isFin() + ", payloadlength:[pos:" + unmaskedpayload.position() + ", len:" + unmaskedpayload.remaining() + "], payload:" + Arrays.toString( Charsetfunctions.utf8Bytes( new String( unmaskedpayload.array() ) ) ) + "}";
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/org/java_websocket/framing/FramedataImpl1.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.framing;
2 |
3 | import org.java_websocket.exceptions.InvalidDataException;
4 | import org.java_websocket.exceptions.InvalidFrameException;
5 | import org.java_websocket.util.Charsetfunctions;
6 |
7 | import java.nio.ByteBuffer;
8 | import java.util.Arrays;
9 |
10 | public class FramedataImpl1 implements FrameBuilder {
11 | protected static byte[] emptyarray = {};
12 | protected boolean fin;
13 | protected Opcode optcode;
14 | private ByteBuffer unmaskedpayload;
15 | protected boolean transferemasked;
16 |
17 | public FramedataImpl1() {
18 | }
19 |
20 | public FramedataImpl1( Opcode op ) {
21 | this.optcode = op;
22 | unmaskedpayload = ByteBuffer.wrap(emptyarray);
23 | }
24 |
25 | /**
26 | * Helper constructor which helps to create "echo" frames.
27 | * The new object will use the same underlying payload data.
28 | **/
29 | public FramedataImpl1( Framedata f ) {
30 | fin = f.isFin();
31 | optcode = f.getOpcode();
32 | unmaskedpayload = f.getPayloadData();
33 | transferemasked = f.getTransfereMasked();
34 | }
35 |
36 | @Override
37 | public boolean isFin() {
38 | return fin;
39 | }
40 |
41 | @Override
42 | public Opcode getOpcode() {
43 | return optcode;
44 | }
45 |
46 | @Override
47 | public boolean getTransfereMasked() {
48 | return transferemasked;
49 | }
50 |
51 | @Override
52 | public ByteBuffer getPayloadData() {
53 | return unmaskedpayload;
54 | }
55 |
56 | @Override
57 | public void setFin( boolean fin ) {
58 | this.fin = fin;
59 | }
60 |
61 | @Override
62 | public void setOptcode( Opcode optcode ) {
63 | this.optcode = optcode;
64 | }
65 |
66 | @Override
67 | public void setPayload( ByteBuffer payload ) throws InvalidDataException {
68 | unmaskedpayload = payload;
69 | }
70 |
71 | @Override
72 | public void setTransferemasked( boolean transferemasked ) {
73 | this.transferemasked = transferemasked;
74 | }
75 |
76 | @Override
77 | public void append( Framedata nextframe ) throws InvalidFrameException {
78 | ByteBuffer b = nextframe.getPayloadData();
79 | if( unmaskedpayload == null ) {
80 | unmaskedpayload = ByteBuffer.allocate(b.remaining());
81 | b.mark();
82 | unmaskedpayload.put( b );
83 | b.reset();
84 | } else {
85 | b.mark();
86 | unmaskedpayload.position( unmaskedpayload.limit() );
87 | unmaskedpayload.limit( unmaskedpayload.capacity() );
88 |
89 | if( b.remaining() > unmaskedpayload.remaining() ) {
90 | ByteBuffer tmp = ByteBuffer.allocate(b.remaining() + unmaskedpayload.capacity());
91 | unmaskedpayload.flip();
92 | tmp.put( unmaskedpayload );
93 | tmp.put( b );
94 | unmaskedpayload = tmp;
95 |
96 | } else {
97 | unmaskedpayload.put( b );
98 | }
99 | unmaskedpayload.rewind();
100 | b.reset();
101 | }
102 | fin = nextframe.isFin();
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return "Framedata{ optcode:" + getOpcode() + ", fin:" + isFin() + ", payloadlength:[pos:" + unmaskedpayload.position() + ", len:" + unmaskedpayload.remaining() + "], payload:" + Arrays.toString(Charsetfunctions.utf8Bytes(new String(unmaskedpayload.array()))) + "}";
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/framing/CloseFrameBuilder.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.framing;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | import org.java_websocket.exceptions.InvalidDataException;
6 | import org.java_websocket.exceptions.InvalidFrameException;
7 | import org.java_websocket.util.Charsetfunctions;
8 |
9 | public class CloseFrameBuilder extends FramedataImpl1 implements CloseFrame {
10 |
11 | static final ByteBuffer emptybytebuffer = ByteBuffer.allocate( 0 );
12 |
13 | private int code;
14 | private String reason;
15 |
16 | public CloseFrameBuilder() {
17 | super( Opcode.CLOSING );
18 | setFin( true );
19 | }
20 |
21 | public CloseFrameBuilder( int code ) throws InvalidDataException {
22 | super( Opcode.CLOSING );
23 | setFin( true );
24 | setCodeAndMessage( code, "" );
25 | }
26 |
27 | public CloseFrameBuilder( int code , String m ) throws InvalidDataException {
28 | super( Opcode.CLOSING );
29 | setFin( true );
30 | setCodeAndMessage( code, m );
31 | }
32 |
33 | private void setCodeAndMessage( int code, String m ) throws InvalidDataException {
34 | if( m == null ) {
35 | m = "";
36 | }
37 | // CloseFrame.TLS_ERROR is not allowed to be transfered over the wire
38 | if( code == CloseFrame.TLS_ERROR ) {
39 | code = CloseFrame.NOCODE;
40 | m = "";
41 | }
42 | if( code == CloseFrame.NOCODE ) {
43 | if( 0 < m.length() ) {
44 | throw new InvalidDataException( PROTOCOL_ERROR, "A close frame must have a closecode if it has a reason" );
45 | }
46 | return;// empty payload
47 | }
48 |
49 | byte[] by = Charsetfunctions.utf8Bytes( m );
50 | ByteBuffer buf = ByteBuffer.allocate( 4 );
51 | buf.putInt( code );
52 | buf.position( 2 );
53 | ByteBuffer pay = ByteBuffer.allocate( 2 + by.length );
54 | pay.put( buf );
55 | pay.put( by );
56 | pay.rewind();
57 | setPayload( pay );
58 | }
59 |
60 | private void initCloseCode() throws InvalidFrameException {
61 | code = CloseFrame.NOCODE;
62 | ByteBuffer payload = super.getPayloadData();
63 | payload.mark();
64 | if( payload.remaining() >= 2 ) {
65 | ByteBuffer bb = ByteBuffer.allocate( 4 );
66 | bb.position( 2 );
67 | bb.putShort( payload.getShort() );
68 | bb.position( 0 );
69 | code = bb.getInt();
70 |
71 | if( code == CloseFrame.ABNORMAL_CLOSE || code == CloseFrame.TLS_ERROR || code == CloseFrame.NOCODE || code > 4999 || code < 1000 || code == 1004 ) {
72 | throw new InvalidFrameException( "closecode must not be sent over the wire: " + code );
73 | }
74 | }
75 | payload.reset();
76 | }
77 |
78 | @Override
79 | public int getCloseCode() {
80 | return code;
81 | }
82 |
83 | private void initMessage() throws InvalidDataException {
84 | if( code == CloseFrame.NOCODE ) {
85 | reason = Charsetfunctions.stringUtf8( super.getPayloadData() );
86 | } else {
87 | ByteBuffer b = super.getPayloadData();
88 | int mark = b.position();// because stringUtf8 also creates a mark
89 | try {
90 | b.position( b.position() + 2 );
91 | reason = Charsetfunctions.stringUtf8( b );
92 | } catch ( IllegalArgumentException e ) {
93 | throw new InvalidFrameException( e );
94 | } finally {
95 | b.position( mark );
96 | }
97 | }
98 | }
99 |
100 | @Override
101 | public String getMessage() {
102 | return reason;
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return super.toString() + "code: " + code;
108 | }
109 |
110 | @Override
111 | public void setPayload( ByteBuffer payload ) throws InvalidDataException {
112 | super.setPayload( payload );
113 | initCloseCode();
114 | initMessage();
115 | }
116 | @Override
117 | public ByteBuffer getPayloadData() {
118 | if( code == NOCODE )
119 | return emptybytebuffer;
120 | return super.getPayloadData();
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/org/java_websocket/framing/CloseFrameBuilder.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.framing;
2 |
3 | import org.java_websocket.exceptions.InvalidDataException;
4 | import org.java_websocket.exceptions.InvalidFrameException;
5 | import org.java_websocket.util.Charsetfunctions;
6 |
7 | import java.nio.ByteBuffer;
8 |
9 | public class CloseFrameBuilder extends FramedataImpl1 implements CloseFrame {
10 |
11 | static final ByteBuffer emptybytebuffer = ByteBuffer.allocate(0);
12 |
13 | private int code;
14 | private String reason;
15 |
16 | public CloseFrameBuilder() {
17 | super( Opcode.CLOSING );
18 | setFin( true );
19 | }
20 |
21 | public CloseFrameBuilder( int code ) throws InvalidDataException {
22 | super( Opcode.CLOSING );
23 | setFin( true );
24 | setCodeAndMessage( code, "" );
25 | }
26 |
27 | public CloseFrameBuilder( int code , String m ) throws InvalidDataException {
28 | super( Opcode.CLOSING );
29 | setFin( true );
30 | setCodeAndMessage( code, m );
31 | }
32 |
33 | private void setCodeAndMessage( int code, String m ) throws InvalidDataException {
34 | if( m == null ) {
35 | m = "";
36 | }
37 | // CloseFrame.TLS_ERROR is not allowed to be transfered over the wire
38 | if( code == CloseFrame.TLS_ERROR ) {
39 | code = CloseFrame.NOCODE;
40 | m = "";
41 | }
42 | if( code == CloseFrame.NOCODE ) {
43 | if( 0 < m.length() ) {
44 | throw new InvalidDataException( PROTOCOL_ERROR, "A close frame must have a closecode if it has a reason" );
45 | }
46 | return;// empty payload
47 | }
48 |
49 | byte[] by = Charsetfunctions.utf8Bytes( m );
50 | ByteBuffer buf = ByteBuffer.allocate(4);
51 | buf.putInt( code );
52 | buf.position( 2 );
53 | ByteBuffer pay = ByteBuffer.allocate(2 + by.length);
54 | pay.put( buf );
55 | pay.put( by );
56 | pay.rewind();
57 | setPayload( pay );
58 | }
59 |
60 | private void initCloseCode() throws InvalidFrameException {
61 | code = CloseFrame.NOCODE;
62 | ByteBuffer payload = super.getPayloadData();
63 | payload.mark();
64 | if( payload.remaining() >= 2 ) {
65 | ByteBuffer bb = ByteBuffer.allocate(4);
66 | bb.position( 2 );
67 | bb.putShort( payload.getShort() );
68 | bb.position( 0 );
69 | code = bb.getInt();
70 |
71 | if( code == CloseFrame.ABNORMAL_CLOSE || code == CloseFrame.TLS_ERROR || code == CloseFrame.NOCODE || code > 4999 || code < 1000 || code == 1004 ) {
72 | throw new InvalidFrameException( "closecode must not be sent over the wire: " + code );
73 | }
74 | }
75 | payload.reset();
76 | }
77 |
78 | @Override
79 | public int getCloseCode() {
80 | return code;
81 | }
82 |
83 | private void initMessage() throws InvalidDataException {
84 | if( code == CloseFrame.NOCODE ) {
85 | reason = Charsetfunctions.stringUtf8( super.getPayloadData() );
86 | } else {
87 | ByteBuffer b = super.getPayloadData();
88 | int mark = b.position();// because stringUtf8 also creates a mark
89 | try {
90 | b.position( b.position() + 2 );
91 | reason = Charsetfunctions.stringUtf8( b );
92 | } catch ( IllegalArgumentException e ) {
93 | throw new InvalidFrameException( e );
94 | } finally {
95 | b.position( mark );
96 | }
97 | }
98 | }
99 |
100 | @Override
101 | public String getMessage() {
102 | return reason;
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return super.toString() + "code: " + code;
108 | }
109 |
110 | @Override
111 | public void setPayload( ByteBuffer payload ) throws InvalidDataException {
112 | super.setPayload( payload );
113 | initCloseCode();
114 | initMessage();
115 | }
116 | @Override
117 | public ByteBuffer getPayloadData() {
118 | if( code == NOCODE )
119 | return emptybytebuffer;
120 | return super.getPayloadData();
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/NADClient/src/shared/MethodInfoOld.java:
--------------------------------------------------------------------------------
1 | package shared;
2 |
3 | import java.io.Serializable;
4 | import java.lang.reflect.Array;
5 | import java.lang.reflect.Method;
6 | import java.util.ArrayList;
7 |
8 | /**
9 | * Created by IEUser on 8/29/2015.
10 | */
11 | public class MethodInfoOld implements Serializable {
12 |
13 | private static final long serialVersionUID = 1300307475607848077L;
14 | String humanReadableDescription;
15 | String methodName;
16 | String className;
17 | /*
18 | ArrayList methodParameterTypes;
19 | ArrayList methodParameterValues;
20 | ArrayList hookableParamsIndex;
21 | */
22 | Class> methodReturnType;
23 | ArrayList methodParameters;
24 | transient Method mMethod;
25 |
26 | public MethodInfoOld(Method method)
27 | {
28 | mMethod = method;
29 | methodReturnType = method.getReturnType();
30 | methodName = method.getName();
31 | humanReadableDescription = createHumanReadableDescription();
32 | }
33 |
34 | private String createHumanReadableDescription()
35 | {
36 | String description = methodReturnType.getName() + " " + methodName + " (";
37 | for(Class> parameter:mMethod.getParameterTypes())
38 | {
39 | description+=parameter.getName();
40 | description+=", ";
41 | }
42 | if(mMethod.getParameterTypes().length > 0) {
43 | description = description.substring(0, description.length() - 2);
44 | }
45 | description += ")";
46 |
47 | return description;
48 | }
49 |
50 | public String getHumanReadableDescription() {
51 | return humanReadableDescription;
52 | }
53 |
54 | public void setHumanReadableDescription(String humanReadableDescription) {
55 | this.humanReadableDescription = humanReadableDescription;
56 | }
57 |
58 |
59 | public String getMethodName() {
60 | return methodName;
61 | }
62 |
63 | public void setMethodName(String methodName) {
64 | this.methodName = methodName;
65 | }
66 |
67 | public Class> getMethodReturnType() {
68 | return methodReturnType;
69 | }
70 |
71 | public void setMethodReturnType(Class> methodReturnType) {
72 | this.methodReturnType = methodReturnType;
73 | }
74 |
75 | public Method getmMethod() {
76 | return mMethod;
77 | }
78 |
79 | public void setmMethod(Method mMethod) {
80 | this.mMethod = mMethod;
81 | }
82 |
83 | public String getClassName() {
84 | return className;
85 | }
86 |
87 | public void setClassName(String className) {
88 | this.className = className;
89 | }
90 | /*
91 | public ArrayList getMethodParameterTypes() {
92 | return methodParameterTypes;
93 | }
94 |
95 | public void setMethodParameterTypes(ArrayList methodParameterTypes) {
96 | this.methodParameterTypes = methodParameterTypes;
97 | }
98 |
99 |
100 | public ArrayList getMethodParameterValues() {
101 | return methodParameterValues;
102 | }
103 |
104 | public void setMethodParameterValues(ArrayList methodParameterValues) {
105 | this.methodParameterValues = methodParameterValues;
106 | }
107 |
108 | public ArrayList getHookableParamsIndex() {
109 | return hookableParamsIndex;
110 | }
111 |
112 | public void setHookableParamsIndex(ArrayList hookableParamsIndex) {
113 | this.hookableParamsIndex = hookableParamsIndex;
114 | }
115 | */
116 |
117 | public ArrayList getMethodParameters() {
118 | return methodParameters;
119 | }
120 |
121 | public void setMethodParameters(ArrayList methodParameters) {
122 | this.methodParameters = methodParameters;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/NADClient/src/shared/MethodInfo.java:
--------------------------------------------------------------------------------
1 | package shared;
2 |
3 | import java.io.Serializable;
4 | import java.lang.reflect.Array;
5 | import java.lang.reflect.Method;
6 | import java.util.ArrayList;
7 |
8 | /**
9 | * Created by IEUser on 8/29/2015.
10 | */
11 | public class MethodInfo implements Serializable {
12 |
13 | private static final long serialVersionUID = 1300307475607848077L;
14 | public String humanReadableDescription;
15 | String methodName;
16 | String className;
17 | /*
18 | ArrayList methodParameterTypes;
19 | ArrayList methodParameterValues;
20 | ArrayList hookableParamsIndex;
21 | */
22 | //Class> methodReturnType;
23 | String methodReturnType;
24 | ArrayList methodParameters;
25 | //transient Method mMethod;
26 |
27 | public MethodInfo(Method method)
28 | {
29 | //mMethod = method;
30 | //methodReturnType = method.getReturnType();
31 | methodReturnType = method.getReturnType().getName();
32 | methodName = method.getName();
33 | humanReadableDescription = createHumanReadableDescription(method);
34 | }
35 |
36 | private String createHumanReadableDescription(Method method)
37 | {
38 | String description = methodReturnType + " " + methodName + " (";
39 | for(Class> parameter:method.getParameterTypes())
40 | {
41 | description+=parameter.getName();
42 | description+=", ";
43 | }
44 | if(method.getParameterTypes().length > 0) {
45 | description = description.substring(0, description.length() - 2);
46 | }
47 | description += ")";
48 |
49 | return description;
50 | }
51 |
52 | public String getHumanReadableDescription() {
53 | return humanReadableDescription;
54 | }
55 |
56 | public void setHumanReadableDescription(String humanReadableDescription) {
57 | this.humanReadableDescription = humanReadableDescription;
58 | }
59 |
60 |
61 | public String getMethodName() {
62 | return methodName;
63 | }
64 |
65 | public void setMethodName(String methodName) {
66 | this.methodName = methodName;
67 | }
68 |
69 | /*
70 | public Class> getMethodReturnType() {
71 | return methodReturnType;
72 | }
73 |
74 | public void setMethodReturnType(Class> methodReturnType) {
75 | this.methodReturnType = methodReturnType;
76 | }
77 | */
78 |
79 | /*
80 | public Method getmMethod() {
81 | return mMethod;
82 | }
83 |
84 | public void setmMethod(Method mMethod) {
85 | this.mMethod = mMethod;
86 | }
87 | */
88 |
89 | public String getClassName() {
90 | return className;
91 | }
92 |
93 | public void setClassName(String className) {
94 | this.className = className;
95 | }
96 | /*
97 | public ArrayList getMethodParameterTypes() {
98 | return methodParameterTypes;
99 | }
100 |
101 | public void setMethodParameterTypes(ArrayList methodParameterTypes) {
102 | this.methodParameterTypes = methodParameterTypes;
103 | }
104 |
105 |
106 | public ArrayList getMethodParameterValues() {
107 | return methodParameterValues;
108 | }
109 |
110 | public void setMethodParameterValues(ArrayList methodParameterValues) {
111 | this.methodParameterValues = methodParameterValues;
112 | }
113 |
114 | public ArrayList getHookableParamsIndex() {
115 | return hookableParamsIndex;
116 | }
117 |
118 | public void setHookableParamsIndex(ArrayList hookableParamsIndex) {
119 | this.hookableParamsIndex = hookableParamsIndex;
120 | }
121 | */
122 |
123 | public ArrayList getMethodParameters() {
124 | return methodParameters;
125 | }
126 |
127 | public void setMethodParameters(ArrayList methodParameters) {
128 | this.methodParameters = methodParameters;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/framing/CloseFrame.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.framing;
2 |
3 | import org.java_websocket.exceptions.InvalidDataException;
4 | import org.java_websocket.exceptions.InvalidFrameException;
5 |
6 | public interface CloseFrame extends Framedata {
7 | /**
8 | * indicates a normal closure, meaning whatever purpose the
9 | * connection was established for has been fulfilled.
10 | */
11 | public static final int NORMAL = 1000;
12 | /**
13 | * 1001 indicates that an endpoint is "going away", such as a server
14 | * going down, or a browser having navigated away from a page.
15 | */
16 | public static final int GOING_AWAY = 1001;
17 | /**
18 | * 1002 indicates that an endpoint is terminating the connection due
19 | * to a protocol error.
20 | */
21 | public static final int PROTOCOL_ERROR = 1002;
22 | /**
23 | * 1003 indicates that an endpoint is terminating the connection
24 | * because it has received a type of data it cannot accept (e.g. an
25 | * endpoint that understands only text data MAY send this if it
26 | * receives a binary message).
27 | */
28 | public static final int REFUSE = 1003;
29 | /*1004: Reserved. The specific meaning might be defined in the future.*/
30 | /**
31 | * 1005 is a reserved value and MUST NOT be set as a status code in a
32 | * Close control frame by an endpoint. It is designated for use in
33 | * applications expecting a status code to indicate that no status
34 | * code was actually present.
35 | */
36 | public static final int NOCODE = 1005;
37 | /**
38 | * 1006 is a reserved value and MUST NOT be set as a status code in a
39 | * Close control frame by an endpoint. It is designated for use in
40 | * applications expecting a status code to indicate that the
41 | * connection was closed abnormally, e.g. without sending or
42 | * receiving a Close control frame.
43 | */
44 | public static final int ABNORMAL_CLOSE = 1006;
45 | /**
46 | * 1007 indicates that an endpoint is terminating the connection
47 | * because it has received data within a message that was not
48 | * consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
49 | * data within a text message).
50 | */
51 | public static final int NO_UTF8 = 1007;
52 | /**
53 | * 1008 indicates that an endpoint is terminating the connection
54 | * because it has received a message that violates its policy. This
55 | * is a generic status code that can be returned when there is no
56 | * other more suitable status code (e.g. 1003 or 1009), or if there
57 | * is a need to hide specific details about the policy.
58 | */
59 | public static final int POLICY_VALIDATION = 1008;
60 | /**
61 | * 1009 indicates that an endpoint is terminating the connection
62 | * because it has received a message which is too big for it to
63 | * process.
64 | */
65 | public static final int TOOBIG = 1009;
66 | /**
67 | * 1010 indicates that an endpoint (client) is terminating the
68 | * connection because it has expected the server to negotiate one or
69 | * more extension, but the server didn't return them in the response
70 | * message of the WebSocket handshake. The list of extensions which
71 | * are needed SHOULD appear in the /reason/ part of the Close frame.
72 | * Note that this status code is not used by the server, because it
73 | * can fail the WebSocket handshake instead.
74 | */
75 | public static final int EXTENSION = 1010;
76 | /**
77 | * 1011 indicates that a server is terminating the connection because
78 | * it encountered an unexpected condition that prevented it from
79 | * fulfilling the request.
80 | **/
81 | public static final int UNEXPECTED_CONDITION = 1011;
82 | /**
83 | * 1015 is a reserved value and MUST NOT be set as a status code in a
84 | * Close control frame by an endpoint. It is designated for use in
85 | * applications expecting a status code to indicate that the
86 | * connection was closed due to a failure to perform a TLS handshake
87 | * (e.g., the server certificate can't be verified).
88 | **/
89 | public static final int TLS_ERROR = 1015;
90 |
91 | /** The connection had never been established */
92 | public static final int NEVER_CONNECTED = -1;
93 | public static final int BUGGYCLOSE = -2;
94 | public static final int FLASHPOLICY = -3;
95 |
96 | public int getCloseCode() throws InvalidFrameException;
97 | public String getMessage() throws InvalidDataException;
98 | }
99 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/org/java_websocket/framing/CloseFrame.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket.framing;
2 |
3 | import org.java_websocket.exceptions.InvalidDataException;
4 | import org.java_websocket.exceptions.InvalidFrameException;
5 |
6 | public interface CloseFrame extends Framedata {
7 | /**
8 | * indicates a normal closure, meaning whatever purpose the
9 | * connection was established for has been fulfilled.
10 | */
11 | public static final int NORMAL = 1000;
12 | /**
13 | * 1001 indicates that an endpoint is "going away", such as a server
14 | * going down, or a browser having navigated away from a page.
15 | */
16 | public static final int GOING_AWAY = 1001;
17 | /**
18 | * 1002 indicates that an endpoint is terminating the connection due
19 | * to a protocol error.
20 | */
21 | public static final int PROTOCOL_ERROR = 1002;
22 | /**
23 | * 1003 indicates that an endpoint is terminating the connection
24 | * because it has received a type of data it cannot accept (e.g. an
25 | * endpoint that understands only text data MAY send this if it
26 | * receives a binary message).
27 | */
28 | public static final int REFUSE = 1003;
29 | /*1004: Reserved. The specific meaning might be defined in the future.*/
30 | /**
31 | * 1005 is a reserved value and MUST NOT be set as a status code in a
32 | * Close control frame by an endpoint. It is designated for use in
33 | * applications expecting a status code to indicate that no status
34 | * code was actually present.
35 | */
36 | public static final int NOCODE = 1005;
37 | /**
38 | * 1006 is a reserved value and MUST NOT be set as a status code in a
39 | * Close control frame by an endpoint. It is designated for use in
40 | * applications expecting a status code to indicate that the
41 | * connection was closed abnormally, e.g. without sending or
42 | * receiving a Close control frame.
43 | */
44 | public static final int ABNORMAL_CLOSE = 1006;
45 | /**
46 | * 1007 indicates that an endpoint is terminating the connection
47 | * because it has received data within a message that was not
48 | * consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
49 | * data within a text message).
50 | */
51 | public static final int NO_UTF8 = 1007;
52 | /**
53 | * 1008 indicates that an endpoint is terminating the connection
54 | * because it has received a message that violates its policy. This
55 | * is a generic status code that can be returned when there is no
56 | * other more suitable status code (e.g. 1003 or 1009), or if there
57 | * is a need to hide specific details about the policy.
58 | */
59 | public static final int POLICY_VALIDATION = 1008;
60 | /**
61 | * 1009 indicates that an endpoint is terminating the connection
62 | * because it has received a message which is too big for it to
63 | * process.
64 | */
65 | public static final int TOOBIG = 1009;
66 | /**
67 | * 1010 indicates that an endpoint (client) is terminating the
68 | * connection because it has expected the server to negotiate one or
69 | * more extension, but the server didn't return them in the response
70 | * message of the WebSocket handshake. The list of extensions which
71 | * are needed SHOULD appear in the /reason/ part of the Close frame.
72 | * Note that this status code is not used by the server, because it
73 | * can fail the WebSocket handshake instead.
74 | */
75 | public static final int EXTENSION = 1010;
76 | /**
77 | * 1011 indicates that a server is terminating the connection because
78 | * it encountered an unexpected condition that prevented it from
79 | * fulfilling the request.
80 | **/
81 | public static final int UNEXPECTED_CONDITION = 1011;
82 | /**
83 | * 1015 is a reserved value and MUST NOT be set as a status code in a
84 | * Close control frame by an endpoint. It is designated for use in
85 | * applications expecting a status code to indicate that the
86 | * connection was closed due to a failure to perform a TLS handshake
87 | * (e.g., the server certificate can't be verified).
88 | **/
89 | public static final int TLS_ERROR = 1015;
90 |
91 | /** The connection had never been established */
92 | public static final int NEVER_CONNECTED = -1;
93 | public static final int BUGGYCLOSE = -2;
94 | public static final int FLASHPOLICY = -3;
95 |
96 | public int getCloseCode() throws InvalidFrameException;
97 | public String getMessage() throws InvalidDataException;
98 | }
99 |
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/WebSocketAdapter.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket;
2 |
3 | import java.net.InetSocketAddress;
4 |
5 | import org.java_websocket.drafts.Draft;
6 | import org.java_websocket.exceptions.InvalidDataException;
7 | import org.java_websocket.exceptions.InvalidHandshakeException;
8 | import org.java_websocket.framing.Framedata;
9 | import org.java_websocket.framing.Framedata.Opcode;
10 | import org.java_websocket.framing.FramedataImpl1;
11 | import org.java_websocket.handshake.ClientHandshake;
12 | import org.java_websocket.handshake.HandshakeImpl1Server;
13 | import org.java_websocket.handshake.ServerHandshake;
14 | import org.java_websocket.handshake.ServerHandshakeBuilder;
15 |
16 | /**
17 | * This class default implements all methods of the WebSocketListener that can be overridden optionally when advances functionalities is needed.
18 | **/
19 | public abstract class WebSocketAdapter implements WebSocketListener {
20 |
21 | /**
22 | * This default implementation does not do anything. Go ahead and overwrite it.
23 | *
24 | * @see org.java_websocket.WebSocketListener#onWebsocketHandshakeReceivedAsServer(WebSocket, Draft, ClientHandshake)
25 | */
26 | @Override
27 | public ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer( WebSocket conn, Draft draft, ClientHandshake request ) throws InvalidDataException {
28 | return new HandshakeImpl1Server();
29 | }
30 |
31 | @Override
32 | public void onWebsocketHandshakeReceivedAsClient( WebSocket conn, ClientHandshake request, ServerHandshake response ) throws InvalidDataException {
33 | }
34 |
35 | /**
36 | * This default implementation does not do anything which will cause the connections to always progress.
37 | *
38 | * @see org.java_websocket.WebSocketListener#onWebsocketHandshakeSentAsClient(WebSocket, ClientHandshake)
39 | */
40 | @Override
41 | public void onWebsocketHandshakeSentAsClient( WebSocket conn, ClientHandshake request ) throws InvalidDataException {
42 | }
43 |
44 | /**
45 | * This default implementation does not do anything. Go ahead and overwrite it
46 | *
47 | * @see org.java_websocket.WebSocketListener#onWebsocketMessageFragment(WebSocket, Framedata)
48 | */
49 | @Override
50 | public void onWebsocketMessageFragment( WebSocket conn, Framedata frame ) {
51 | }
52 |
53 | /**
54 | * This default implementation will send a pong in response to the received ping.
55 | * The pong frame will have the same payload as the ping frame.
56 | *
57 | * @see org.java_websocket.WebSocketListener#onWebsocketPing(WebSocket, Framedata)
58 | */
59 | @Override
60 | public void onWebsocketPing( WebSocket conn, Framedata f ) {
61 | FramedataImpl1 resp = new FramedataImpl1( f );
62 | resp.setOptcode( Opcode.PONG );
63 | conn.sendFrame( resp );
64 | }
65 |
66 | /**
67 | * This default implementation does not do anything. Go ahead and overwrite it.
68 | *
69 | * @see org.java_websocket.WebSocketListener#onWebsocketPong(WebSocket, Framedata)
70 | */
71 | @Override
72 | public void onWebsocketPong( WebSocket conn, Framedata f ) {
73 | }
74 |
75 | /**
76 | * Gets the XML string that should be returned if a client requests a Flash
77 | * security policy.
78 | *
79 | * The default implementation allows access from all remote domains, but
80 | * only on the port that this WebSocketServer is listening on.
81 | *
82 | * This is specifically implemented for gitime's WebSocket client for Flash:
83 | * http://github.com/gimite/web-socket-js
84 | *
85 | * @return An XML String that comforts to Flash's security policy. You MUST
86 | * not include the null char at the end, it is appended automatically.
87 | * @throws InvalidDataException thrown when some data that is required to generate the flash-policy like the websocket local port could not be obtained e.g because the websocket is not connected.
88 | */
89 | @Override
90 | public String getFlashPolicy( WebSocket conn ) throws InvalidDataException {
91 | InetSocketAddress adr = conn.getLocalSocketAddress();
92 | if(null == adr){
93 | throw new InvalidHandshakeException( "socket not bound" );
94 | }
95 |
96 | StringBuffer sb = new StringBuffer( 90 );
97 | sb.append( "\0" );
100 |
101 | return sb.toString();
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/org/java_websocket/WebSocketAdapter.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket;
2 |
3 | import org.java_websocket.drafts.Draft;
4 | import org.java_websocket.exceptions.InvalidDataException;
5 | import org.java_websocket.exceptions.InvalidHandshakeException;
6 | import org.java_websocket.framing.Framedata;
7 | import org.java_websocket.framing.Framedata.Opcode;
8 | import org.java_websocket.framing.FramedataImpl1;
9 | import org.java_websocket.handshake.ClientHandshake;
10 | import org.java_websocket.handshake.HandshakeImpl1Server;
11 | import org.java_websocket.handshake.ServerHandshake;
12 | import org.java_websocket.handshake.ServerHandshakeBuilder;
13 |
14 | import java.net.InetSocketAddress;
15 |
16 | /**
17 | * This class default implements all methods of the WebSocketListener that can be overridden optionally when advances functionalities is needed.
18 | **/
19 | public abstract class WebSocketAdapter implements WebSocketListener {
20 |
21 | /**
22 | * This default implementation does not do anything. Go ahead and overwrite it.
23 | *
24 | * @see org.java_websocket.WebSocketListener#onWebsocketHandshakeReceivedAsServer(WebSocket, Draft, ClientHandshake)
25 | */
26 | @Override
27 | public ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer( WebSocket conn, Draft draft, ClientHandshake request ) throws InvalidDataException {
28 | return new HandshakeImpl1Server();
29 | }
30 |
31 | @Override
32 | public void onWebsocketHandshakeReceivedAsClient( WebSocket conn, ClientHandshake request, ServerHandshake response ) throws InvalidDataException {
33 | }
34 |
35 | /**
36 | * This default implementation does not do anything which will cause the connections to always progress.
37 | *
38 | * @see org.java_websocket.WebSocketListener#onWebsocketHandshakeSentAsClient(WebSocket, ClientHandshake)
39 | */
40 | @Override
41 | public void onWebsocketHandshakeSentAsClient( WebSocket conn, ClientHandshake request ) throws InvalidDataException {
42 | }
43 |
44 | /**
45 | * This default implementation does not do anything. Go ahead and overwrite it
46 | *
47 | * @see org.java_websocket.WebSocketListener#onWebsocketMessageFragment(WebSocket, Framedata)
48 | */
49 | @Override
50 | public void onWebsocketMessageFragment( WebSocket conn, Framedata frame ) {
51 | }
52 |
53 | /**
54 | * This default implementation will send a pong in response to the received ping.
55 | * The pong frame will have the same payload as the ping frame.
56 | *
57 | * @see org.java_websocket.WebSocketListener#onWebsocketPing(WebSocket, Framedata)
58 | */
59 | @Override
60 | public void onWebsocketPing( WebSocket conn, Framedata f ) {
61 | FramedataImpl1 resp = new FramedataImpl1( f );
62 | resp.setOptcode( Opcode.PONG );
63 | conn.sendFrame( resp );
64 | }
65 |
66 | /**
67 | * This default implementation does not do anything. Go ahead and overwrite it.
68 | *
69 | * @see org.java_websocket.WebSocketListener#onWebsocketPong(WebSocket, Framedata)
70 | */
71 | @Override
72 | public void onWebsocketPong( WebSocket conn, Framedata f ) {
73 | }
74 |
75 | /**
76 | * Gets the XML string that should be returned if a client requests a Flash
77 | * security policy.
78 | *
79 | * The default implementation allows access from all remote domains, but
80 | * only on the port that this WebSocketServer is listening on.
81 | *
82 | * This is specifically implemented for gitime's WebSocket client for Flash:
83 | * http://github.com/gimite/web-socket-js
84 | *
85 | * @return An XML String that comforts to Flash's security policy. You MUST
86 | * not include the null char at the end, it is appended automatically.
87 | * @throws InvalidDataException thrown when some data that is required to generate the flash-policy like the websocket local port could not be obtained e.g because the websocket is not connected.
88 | */
89 | @Override
90 | public String getFlashPolicy( WebSocket conn ) throws InvalidDataException {
91 | InetSocketAddress adr = conn.getLocalSocketAddress();
92 | if(null == adr){
93 | throw new InvalidHandshakeException( "socket not bound" );
94 | }
95 |
96 | StringBuffer sb = new StringBuffer( 90 );
97 | sb.append( "\0" );
100 |
101 | return sb.toString();
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/com/nad/Util.java:
--------------------------------------------------------------------------------
1 | package com.nad;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.IOException;
7 | import java.io.ObjectOutputStream;
8 | import java.lang.reflect.Array;
9 | import java.lang.reflect.Member;
10 | import java.lang.reflect.Method;
11 | import java.util.ArrayList;
12 |
13 | /**
14 | * Created by Administrator on 4/19/2016.
15 | */
16 | public final class Util {
17 | // private constructor to avoid unnecessary instantiation of the class
18 | private Util() {
19 | }
20 |
21 | public static final String generateHRMD(Method method) {
22 | String methodName = method.getName();
23 | String className = method.getDeclaringClass().getCanonicalName();
24 | Class> methodReturnType = method.getReturnType();
25 |
26 | String description = methodReturnType.getName() + " " + methodName + " (";
27 | for(Class> parameter:method.getParameterTypes())
28 | {
29 | description+=parameter.getName();
30 | description+=", ";
31 | }
32 | if(method.getParameterTypes().length > 0) {
33 | description = description.substring(0, description.length() - 2);
34 | }
35 | description += ")";
36 |
37 | return description;
38 | }
39 |
40 | public static final String generateHRMD(Member method) {
41 | String methodName = method.getName();
42 | String className = method.getDeclaringClass().getCanonicalName();
43 | Class> methodReturnType = ((Method) method).getReturnType();
44 |
45 | String description = methodReturnType.getName() + " " + methodName + " (";
46 | for(Class> parameter:((Method) method).getParameterTypes())
47 | {
48 | description+=parameter.getName();
49 | description+=", ";
50 | }
51 | if(((Method) method).getParameterTypes().length > 0) {
52 | description = description.substring(0, description.length() - 2);
53 | }
54 | description += ")";
55 |
56 | return description;
57 | }
58 |
59 | public static final ArrayList getSerializableTypes()
60 | {
61 | /*
62 | Currently supported types that can be serialized and modified between android and normal Java
63 | */
64 |
65 | ArrayList serializableTypes = new ArrayList<>();
66 | serializableTypes.add("String");
67 | serializableTypes.add("Integer");
68 | serializableTypes.add("Boolean");
69 | serializableTypes.add("Int");
70 | serializableTypes.add("Long");
71 | serializableTypes.add("Float");
72 | serializableTypes.add("Double");
73 | serializableTypes.add("Short");
74 |
75 | return serializableTypes;
76 | }
77 |
78 | public static final Object getReconstructedObject (String type, Object ob)
79 | {
80 | Object object = new Object();
81 | switch (type) {
82 | case "String":
83 | object = ob.toString();
84 | break;
85 | case "Character":
86 | object = ob.toString().charAt(0);
87 | break;
88 | case "Byte":
89 | object = Byte.parseByte(ob.toString());
90 | break;
91 | case "Integer":
92 | object = Integer.parseInt(ob.toString());
93 | break;
94 | case "Long":
95 | object = Long.parseLong(ob.toString());
96 | break;
97 | case "Float":
98 | object = Float.valueOf(ob.toString());
99 | break;
100 | case "Double":
101 | object = Double.valueOf(ob.toString());
102 | break;
103 | case "Boolean":
104 | object = Boolean.valueOf(ob.toString());
105 | break;
106 | default:
107 | Log.v("diorand", "unknown type, strange this should not happen");
108 | break;
109 | }
110 |
111 | return object;
112 | }
113 |
114 | public static String byteArrayToHexString(byte[] byteArray)
115 | {
116 | StringBuffer hexString = new StringBuffer();
117 | for (int i=0; i
68 | * For more into on this frame type see http://tools.ietf.org/html/rfc6455#section-5.4
69 | *
70 | * If the first frame you send is also the last then it is not a fragmented frame and will received via onMessage instead of onFragmented even though it was send by this method.
71 | *
72 | * @param op
73 | * This is only important for the first frame in the sequence. Opcode.TEXT, Opcode.BINARY are allowed.
74 | * @param buffer
75 | * The buffer which contains the payload. It may have no bytes remaining.
76 | * @param fin
77 | * true means the current frame is the last in the sequence.
78 | **/
79 | public abstract void sendFragmentedFrame(Opcode op, ByteBuffer buffer, boolean fin);
80 |
81 | public abstract boolean hasBufferedData();
82 |
83 | /**
84 | * @return never returns null
85 | */
86 | public abstract InetSocketAddress getRemoteSocketAddress();
87 |
88 | /**
89 | * @return never returns null
90 | */
91 | public abstract InetSocketAddress getLocalSocketAddress();
92 |
93 | public abstract boolean isConnecting();
94 |
95 | public abstract boolean isOpen();
96 |
97 | public abstract boolean isClosing();
98 |
99 | /**
100 | * Returns true when no further frames may be submitted
101 | * This happens before the socket connection is closed.
102 | */
103 | public abstract boolean isFlushAndClose();
104 |
105 | /** Returns whether the close handshake has been completed and the socket is closed. */
106 | public abstract boolean isClosed();
107 |
108 | public abstract Draft getDraft();
109 |
110 | /**
111 | * Retrieve the WebSocket 'readyState'.
112 | * This represents the state of the connection.
113 | * It returns a numerical value, as per W3C WebSockets specs.
114 | *
115 | * @return Returns '0 = CONNECTING', '1 = OPEN', '2 = CLOSING' or '3 = CLOSED'
116 | */
117 | public abstract READYSTATE getReadyState();
118 |
119 | /**
120 | * Returns the HTTP Request-URI as defined by http://tools.ietf.org/html/rfc2616#section-5.1.2
121 | * If the opening handshake has not yet happened it will return null.
122 | **/
123 | public abstract String getResourceDescriptor();
124 | }
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/WebSocket.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket;
2 |
3 | import java.net.InetSocketAddress;
4 | import java.nio.ByteBuffer;
5 | import java.nio.channels.NotYetConnectedException;
6 |
7 | import org.java_websocket.drafts.Draft;
8 | import org.java_websocket.framing.Framedata;
9 | import org.java_websocket.framing.Framedata.Opcode;
10 |
11 | public interface WebSocket {
12 | public enum Role {
13 | CLIENT, SERVER
14 | }
15 |
16 | public enum READYSTATE {
17 | NOT_YET_CONNECTED, CONNECTING, OPEN, CLOSING, CLOSED;
18 | }
19 |
20 | /**
21 | * The default port of WebSockets, as defined in the spec. If the nullary
22 | * constructor is used, DEFAULT_PORT will be the port the WebSocketServer
23 | * is binded to. Note that ports under 1024 usually require root permissions.
24 | */
25 | public static final int DEFAULT_PORT = 80;
26 |
27 | public static final int DEFAULT_WSS_PORT = 443;
28 |
29 | /**
30 | * sends the closing handshake.
31 | * may be send in response to an other handshake.
32 | */
33 | public void close( int code, String message );
34 |
35 | public void close( int code );
36 |
37 | /** Convenience function which behaves like close(CloseFrame.NORMAL) */
38 | public void close();
39 |
40 | /**
41 | * This will close the connection immediately without a proper close handshake.
42 | * The code and the message therefore won't be transfered over the wire also they will be forwarded to onClose/onWebsocketClose.
43 | **/
44 | public abstract void closeConnection( int code, String message );
45 |
46 | /**
47 | * Send Text data to the other end.
48 | *
49 | * @throws IllegalArgumentException
50 | * @throws NotYetConnectedException
51 | */
52 | public abstract void send( String text ) throws NotYetConnectedException;
53 |
54 | /**
55 | * Send Binary data (plain bytes) to the other end.
56 | *
57 | * @throws IllegalArgumentException
58 | * @throws NotYetConnectedException
59 | */
60 | public abstract void send( ByteBuffer bytes ) throws IllegalArgumentException , NotYetConnectedException;
61 |
62 | public abstract void send( byte[] bytes ) throws IllegalArgumentException , NotYetConnectedException;
63 |
64 | public abstract void sendFrame( Framedata framedata );
65 |
66 | /**
67 | * Allows to send continuous/fragmented frames conveniently.
68 | * For more into on this frame type see http://tools.ietf.org/html/rfc6455#section-5.4
69 | *
70 | * If the first frame you send is also the last then it is not a fragmented frame and will received via onMessage instead of onFragmented even though it was send by this method.
71 | *
72 | * @param op
73 | * This is only important for the first frame in the sequence. Opcode.TEXT, Opcode.BINARY are allowed.
74 | * @param buffer
75 | * The buffer which contains the payload. It may have no bytes remaining.
76 | * @param fin
77 | * true means the current frame is the last in the sequence.
78 | **/
79 | public abstract void sendFragmentedFrame( Opcode op, ByteBuffer buffer, boolean fin );
80 |
81 | public abstract boolean hasBufferedData();
82 |
83 | /**
84 | * @return never returns null
85 | */
86 | public abstract InetSocketAddress getRemoteSocketAddress();
87 |
88 | /**
89 | * @return never returns null
90 | */
91 | public abstract InetSocketAddress getLocalSocketAddress();
92 |
93 | public abstract boolean isConnecting();
94 |
95 | public abstract boolean isOpen();
96 |
97 | public abstract boolean isClosing();
98 |
99 | /**
100 | * Returns true when no further frames may be submitted
101 | * This happens before the socket connection is closed.
102 | */
103 | public abstract boolean isFlushAndClose();
104 |
105 | /** Returns whether the close handshake has been completed and the socket is closed. */
106 | public abstract boolean isClosed();
107 |
108 | public abstract Draft getDraft();
109 |
110 | /**
111 | * Retrieve the WebSocket 'readyState'.
112 | * This represents the state of the connection.
113 | * It returns a numerical value, as per W3C WebSockets specs.
114 | *
115 | * @return Returns '0 = CONNECTING', '1 = OPEN', '2 = CLOSING' or '3 = CLOSED'
116 | */
117 | public abstract READYSTATE getReadyState();
118 |
119 | /**
120 | * Returns the HTTP Request-URI as defined by http://tools.ietf.org/html/rfc2616#section-5.1.2
121 | * If the opening handshake has not yet happened it will return null.
122 | **/
123 | public abstract String getResourceDescriptor();
124 | }
--------------------------------------------------------------------------------
/nad/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/nad/app/src/main/java/org/java_websocket/WebSocketListener.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket;
2 |
3 | import org.java_websocket.drafts.Draft;
4 | import org.java_websocket.exceptions.InvalidDataException;
5 | import org.java_websocket.framing.Framedata;
6 | import org.java_websocket.handshake.ClientHandshake;
7 | import org.java_websocket.handshake.Handshakedata;
8 | import org.java_websocket.handshake.ServerHandshake;
9 | import org.java_websocket.handshake.ServerHandshakeBuilder;
10 |
11 | import java.net.InetSocketAddress;
12 | import java.nio.ByteBuffer;
13 |
14 | /**
15 | * Implemented by WebSocketClient and WebSocketServer.
16 | * The methods within are called by WebSocket.
17 | * Almost every method takes a first parameter conn which represents the source of the respective event.
18 | */
19 | public interface WebSocketListener {
20 |
21 | /**
22 | * Called on the server side when the socket connection is first established, and the WebSocket
23 | * handshake has been received. This method allows to deny connections based on the received handshake.
24 | * By default this method only requires protocol compliance.
25 | *
26 | * @param conn
27 | * The WebSocket related to this event
28 | * @param draft
29 | * The protocol draft the client uses to connect
30 | * @param request
31 | * The opening http message send by the client. Can be used to access additional fields like cookies.
32 | * @return Returns an incomplete handshake containing all optional fields
33 | * @throws InvalidDataException
34 | * Throwing this exception will cause this handshake to be rejected
35 | */
36 | public ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer(WebSocket conn, Draft draft, ClientHandshake request) throws InvalidDataException;
37 |
38 | /**
39 | * Called on the client side when the socket connection is first established, and the WebSocketImpl
40 | * handshake response has been received.
41 | *
42 | * @param conn
43 | * The WebSocket related to this event
44 | * @param request
45 | * The handshake initially send out to the server by this websocket.
46 | * @param response
47 | * The handshake the server sent in response to the request.
48 | * @throws InvalidDataException
49 | * Allows the client to reject the connection with the server in respect of its handshake response.
50 | */
51 | public void onWebsocketHandshakeReceivedAsClient(WebSocket conn, ClientHandshake request, ServerHandshake response) throws InvalidDataException;
52 |
53 | /**
54 | * Called on the client side when the socket connection is first established, and the WebSocketImpl
55 | * handshake has just been sent.
56 | *
57 | * @param conn
58 | * The WebSocket related to this event
59 | * @param request
60 | * The handshake sent to the server by this websocket
61 | * @throws InvalidDataException
62 | * Allows the client to stop the connection from progressing
63 | */
64 | public void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) throws InvalidDataException;
65 |
66 | /**
67 | * Called when an entire text frame has been received. Do whatever you want
68 | * here...
69 | *
70 | * @param conn
71 | * The WebSocket instance this event is occurring on.
72 | * @param message
73 | * The UTF-8 decoded message that was received.
74 | */
75 | public void onWebsocketMessage(WebSocket conn, String message);
76 |
77 | /**
78 | * Called when an entire binary frame has been received. Do whatever you want
79 | * here...
80 | *
81 | * @param conn
82 | * The WebSocket instance this event is occurring on.
83 | * @param blob
84 | * The binary message that was received.
85 | */
86 | public void onWebsocketMessage(WebSocket conn, ByteBuffer blob);
87 |
88 | public void onWebsocketMessageFragment(WebSocket conn, Framedata frame);
89 |
90 | /**
91 | * Called after onHandshakeReceived returns true.
92 | * Indicates that a complete WebSocket connection has been established,
93 | * and we are ready to send/receive data.
94 | *
95 | * @param conn
96 | * The WebSocket instance this event is occuring on.
97 | */
98 | public void onWebsocketOpen(WebSocket conn, Handshakedata d);
99 |
100 | /**
101 | * Called after WebSocket#close is explicity called, or when the
102 | * other end of the WebSocket connection is closed.
103 | *
104 | * @param ws
105 | * The WebSocket instance this event is occuring on.
106 | */
107 | public void onWebsocketClose(WebSocket ws, int code, String reason, boolean remote);
108 |
109 | /** called as soon as no further frames are accepted */
110 | public void onWebsocketClosing(WebSocket ws, int code, String reason, boolean remote);
111 |
112 | /** send when this peer sends a close handshake */
113 | public void onWebsocketCloseInitiated(WebSocket ws, int code, String reason);
114 |
115 | /**
116 | * Called if an exception worth noting occurred.
117 | * If an error causes the connection to fail onClose will be called additionally afterwards.
118 | *
119 | * @param ex
120 | * The exception that occurred.
121 | * Might be null if the exception is not related to any specific connection. For example if the server port could not be bound.
122 | */
123 | public void onWebsocketError(WebSocket conn, Exception ex);
124 |
125 | /**
126 | * Called a ping frame has been received.
127 | * This method must send a corresponding pong by itself.
128 | *
129 | * @param f
130 | * The ping frame. Control frames may contain payload.
131 | */
132 | public void onWebsocketPing(WebSocket conn, Framedata f);
133 |
134 | /**
135 | * Called when a pong frame is received.
136 | **/
137 | public void onWebsocketPong(WebSocket conn, Framedata f);
138 |
139 | /**
140 | * Gets the XML string that should be returned if a client requests a Flash
141 | * security policy.
142 | * @throws InvalidDataException thrown when some data that is required to generate the flash-policy like the websocket local port could not be obtained.
143 | */
144 | public String getFlashPolicy(WebSocket conn) throws InvalidDataException;
145 |
146 | /** This method is used to inform the selector thread that there is data queued to be written to the socket. */
147 | public void onWriteDemand(WebSocket conn);
148 |
149 | public InetSocketAddress getLocalSocketAddress(WebSocket conn);
150 | public InetSocketAddress getRemoteSocketAddress(WebSocket conn);
151 | }
152 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Not-a-debugger
2 | An experiment into dynamic hooking and modification of Android application functions and return values.
3 |
4 | Summary
5 | --------
6 | Not a debugger (NAD) was created to perform run time analysis, tracing and tampering of Android application function input parameters and return values.
7 |
8 | NAD provides an user interface written in Java, which allows the user to connect to the accompanying Android application using their testing machine. This allows convenient manipulation of Android parameters and hooks.
9 |
10 | This application is built upon the Xposed Framework and it is necessary for this to work. This is just a POC so expect it to break, turn on logcat to view any error messages.
11 |
12 | Features
13 | --------
14 |
15 | ### Websocket Connection
16 | Turn on the switch on the accompanying Android application, enter the device's Ip address into the IP field and click "Connect" and you're done!
17 |
18 | ### Apps Tab
19 | The "Apps" tab lists all the applications that are installed on the device. The freetext search field allows easy searching of applications installed on the Android device to be hooked.
20 | 
21 |
22 | Selecting the application to analyze is as easy as double clicking on the package name on the list displayed and confirming your selection.
23 | 
24 |
25 | Note, ensure that the application you have selected to hook is not running in the background after selection. NAD only analyzes the application classes and methods of the application when it is starting up. If it is running, kill it with the task manager or something similar.
26 |
27 | ### Functions Tab
28 | After hooking using the "Apps" tab, launch the application and browse to the "Functions" tab, it will list out the functions within the application to be analyzed.
29 | 
30 |
31 | To hook a function, double click on the function and select what you would like to hook.
32 | 
33 |
34 | ***Hook Input Parameters Only***
35 | Choose this if you want to tamper only the input parameters of the function when the function is called. Note: Not all parameters are able to be edited. When such a parameter is encountered, that parameter will be skipped.
36 |
37 | ***Hook Return Value Only***
38 | Choose this only if you want to tamper with the return values of a function. Note that not all values are able to be edited, nor will it work on a function that returns a void (probably will crash).
39 |
40 | ***Hook Input and Return Values***
41 | Choose this if you want to hook and tamper with both the input parameters and the return values of that function.
42 |
43 | ***Remove Hook***
44 | Obviously, remove the hook.
45 |
46 | Example, we want to analyze the parameters and the result of the return value of the function "boolean a(android.content.Context, java.lang.String)". We select the "Hook Input and Return Values" option.
47 |
48 | We entered the string "Secret Password" on our target application and clicked on the "VERIFY PASSWORD" button that triggered the function. When the function is called, we get a prompt that shows us the String paramter as shown below, looks like our user input is passed into this function. Here we are free to modify the string in the prompt if we want to, perhaps bypass user input restrictions?
49 | 
50 |
51 | After we click on "OK", the function returns the boolean "false" (obviously as we did not enter the right password). Once again, as we selected the option to hook the return value as well, we are presented with the next prompt as shown below:
52 | 
53 |
54 | Here as this is a boolean, we get the option to make it return true or false. In this case the function returned "false", let's turn that into a true by editing it to "true" and we click "OK" again. Note that putting anything else than what the function expects will cause it to crash.
55 | 
56 |
57 | The application also supports custom objects that are passed around to functions:
58 | 
59 |
60 | Arrays are supported too!
61 | 
62 |
63 | ### Options Tab
64 | The "Options" tab offers the user 2 functions. Mainly "Trace mode", and also "Canary mode".
65 |
66 | The "Trace mode" toggle allows the user to turn on / off the trace mode. Turn this mode on, launch the application and mess around with it. Logcat will show a trace of all the functions of the application that were called.
67 | Options tab GUI:
68 | 
69 |
70 | Logcat output of the teamsik application:
71 | 
72 |
73 | The hooking function, trace mode and the canary mode (more details below) functions are exclusive, and can only work when the other is off. Remember to turn off the trace mode when you want to start hooking functions!
74 |
75 | The "Canary mode" toggle allows the user to define a unique canary token, in the screenshot above, the value of "deadbeef". In the demo application screenshot below, we enter the string "deadbeef" into the input text and we click the "VERIFY PASSWORD" button.
76 | 
77 |
78 | Any functions that receives a parameter with the value of the canary token will be printed out to logcat as shown in the screenshot below:
79 | 
80 |
81 | The "Canary mode" just like trace mode, works exclusively by itself. When in this mode, you will not be able to modify/hook on the fly.
82 |
83 | Upon connecting to the Android application with the client, if the canary mode is turned on, a prompt will alert you that canary mode is turned on.
84 | 
85 |
86 | ### Accompanying Android Application
87 | There is nothing fancy about the accompanying android application. Just an on/off switch.
88 | 
89 |
90 | ### TODO
91 | 1) Determine feasibility to perform analysis on the application when the user selects the application to hook instead of when the application starts
92 | 2) Determine feasibility to consolidate data files dropped on the target application
93 |
94 |
--------------------------------------------------------------------------------
/NADClient/src/org/java_websocket/WebSocketListener.java:
--------------------------------------------------------------------------------
1 | package org.java_websocket;
2 |
3 | import java.net.InetSocketAddress;
4 | import java.nio.ByteBuffer;
5 |
6 | import org.java_websocket.drafts.Draft;
7 | import org.java_websocket.exceptions.InvalidDataException;
8 | import org.java_websocket.framing.Framedata;
9 | import org.java_websocket.handshake.ClientHandshake;
10 | import org.java_websocket.handshake.Handshakedata;
11 | import org.java_websocket.handshake.ServerHandshake;
12 | import org.java_websocket.handshake.ServerHandshakeBuilder;
13 |
14 | /**
15 | * Implemented by WebSocketClient and WebSocketServer.
16 | * The methods within are called by WebSocket.
17 | * Almost every method takes a first parameter conn which represents the source of the respective event.
18 | */
19 | public interface WebSocketListener {
20 |
21 | /**
22 | * Called on the server side when the socket connection is first established, and the WebSocket
23 | * handshake has been received. This method allows to deny connections based on the received handshake.
24 | * By default this method only requires protocol compliance.
25 | *
26 | * @param conn
27 | * The WebSocket related to this event
28 | * @param draft
29 | * The protocol draft the client uses to connect
30 | * @param request
31 | * The opening http message send by the client. Can be used to access additional fields like cookies.
32 | * @return Returns an incomplete handshake containing all optional fields
33 | * @throws InvalidDataException
34 | * Throwing this exception will cause this handshake to be rejected
35 | */
36 | public ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer( WebSocket conn, Draft draft, ClientHandshake request ) throws InvalidDataException;
37 |
38 | /**
39 | * Called on the client side when the socket connection is first established, and the WebSocketImpl
40 | * handshake response has been received.
41 | *
42 | * @param conn
43 | * The WebSocket related to this event
44 | * @param request
45 | * The handshake initially send out to the server by this websocket.
46 | * @param response
47 | * The handshake the server sent in response to the request.
48 | * @throws InvalidDataException
49 | * Allows the client to reject the connection with the server in respect of its handshake response.
50 | */
51 | public void onWebsocketHandshakeReceivedAsClient( WebSocket conn, ClientHandshake request, ServerHandshake response ) throws InvalidDataException;
52 |
53 | /**
54 | * Called on the client side when the socket connection is first established, and the WebSocketImpl
55 | * handshake has just been sent.
56 | *
57 | * @param conn
58 | * The WebSocket related to this event
59 | * @param request
60 | * The handshake sent to the server by this websocket
61 | * @throws InvalidDataException
62 | * Allows the client to stop the connection from progressing
63 | */
64 | public void onWebsocketHandshakeSentAsClient( WebSocket conn, ClientHandshake request ) throws InvalidDataException;
65 |
66 | /**
67 | * Called when an entire text frame has been received. Do whatever you want
68 | * here...
69 | *
70 | * @param conn
71 | * The WebSocket instance this event is occurring on.
72 | * @param message
73 | * The UTF-8 decoded message that was received.
74 | */
75 | public void onWebsocketMessage( WebSocket conn, String message );
76 |
77 | /**
78 | * Called when an entire binary frame has been received. Do whatever you want
79 | * here...
80 | *
81 | * @param conn
82 | * The WebSocket instance this event is occurring on.
83 | * @param blob
84 | * The binary message that was received.
85 | */
86 | public void onWebsocketMessage( WebSocket conn, ByteBuffer blob );
87 |
88 | public void onWebsocketMessageFragment( WebSocket conn, Framedata frame );
89 |
90 | /**
91 | * Called after onHandshakeReceived returns true.
92 | * Indicates that a complete WebSocket connection has been established,
93 | * and we are ready to send/receive data.
94 | *
95 | * @param conn
96 | * The WebSocket instance this event is occuring on.
97 | */
98 | public void onWebsocketOpen( WebSocket conn, Handshakedata d );
99 |
100 | /**
101 | * Called after WebSocket#close is explicity called, or when the
102 | * other end of the WebSocket connection is closed.
103 | *
104 | * @param ws
105 | * The WebSocket instance this event is occuring on.
106 | */
107 | public void onWebsocketClose( WebSocket ws, int code, String reason, boolean remote );
108 |
109 | /** called as soon as no further frames are accepted */
110 | public void onWebsocketClosing( WebSocket ws, int code, String reason, boolean remote );
111 |
112 | /** send when this peer sends a close handshake */
113 | public void onWebsocketCloseInitiated( WebSocket ws, int code, String reason );
114 |
115 | /**
116 | * Called if an exception worth noting occurred.
117 | * If an error causes the connection to fail onClose will be called additionally afterwards.
118 | *
119 | * @param ex
120 | * The exception that occurred.
121 | * Might be null if the exception is not related to any specific connection. For example if the server port could not be bound.
122 | */
123 | public void onWebsocketError( WebSocket conn, Exception ex );
124 |
125 | /**
126 | * Called a ping frame has been received.
127 | * This method must send a corresponding pong by itself.
128 | *
129 | * @param f
130 | * The ping frame. Control frames may contain payload.
131 | */
132 | public void onWebsocketPing( WebSocket conn, Framedata f );
133 |
134 | /**
135 | * Called when a pong frame is received.
136 | **/
137 | public void onWebsocketPong( WebSocket conn, Framedata f );
138 |
139 | /**
140 | * Gets the XML string that should be returned if a client requests a Flash
141 | * security policy.
142 | * @throws InvalidDataException thrown when some data that is required to generate the flash-policy like the websocket local port could not be obtained.
143 | */
144 | public String getFlashPolicy( WebSocket conn ) throws InvalidDataException;
145 |
146 | /** This method is used to inform the selector thread that there is data queued to be written to the socket. */
147 | public void onWriteDemand( WebSocket conn );
148 |
149 | public InetSocketAddress getLocalSocketAddress( WebSocket conn );
150 | public InetSocketAddress getRemoteSocketAddress( WebSocket conn );
151 | }
152 |
--------------------------------------------------------------------------------
/NADClient/src/MethodInfoEditor.java:
--------------------------------------------------------------------------------
1 | import java.awt.BorderLayout;
2 | import java.awt.FlowLayout;
3 | import java.awt.GridBagConstraints;
4 | import java.awt.GridBagLayout;
5 | import java.awt.Insets;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.util.ArrayList;
9 |
10 | import javax.swing.JButton;
11 | import javax.swing.JDialog;
12 | import javax.swing.JPanel;
13 | import javax.swing.border.EmptyBorder;
14 |
15 | import shared.MethodInfo;
16 | import shared.ParameterInfo;
17 |
18 | import javax.swing.JLabel;
19 | import javax.swing.JScrollPane;
20 | import javax.swing.JTextArea;
21 | import javax.swing.JTextField;
22 |
23 | public class MethodInfoEditor extends JDialog implements ActionListener {
24 |
25 | private final JPanel contentPanel = new JPanel();
26 | //private ArrayList textFields = new ArrayList();
27 | private ArrayList textAreas = new ArrayList();
28 | private JButton okButton;
29 | private MethodInfo methodInfo;
30 | /**
31 | * Launch the application.
32 | */
33 | /*
34 | public static void main(String[] args) {
35 | try {
36 | MethodInfoEditor dialog = new MethodInfoEditor();
37 | dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
38 | dialog.setVisible(true);
39 | } catch (Exception e) {
40 | e.printStackTrace();
41 | }
42 | }
43 | */
44 |
45 | public MethodInfo getMethodInfo() {
46 | return methodInfo;
47 | }
48 | /**
49 | * Create the dialog.
50 | */
51 | public MethodInfoEditor(MethodInfo mi) {
52 | this.setModalityType(ModalityType.APPLICATION_MODAL);
53 | setBounds(100, 100, 450, 300);
54 | getContentPane().setLayout(new BorderLayout());
55 | contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
56 | getContentPane().add(contentPanel, BorderLayout.CENTER);
57 | contentPanel.setLayout(new BorderLayout());
58 | JLabel lblMethodDescription = null;
59 | this.methodInfo = mi;
60 | {
61 | lblMethodDescription = new JLabel("New label");
62 | lblMethodDescription.setBounds(10, 11, 414, 14);
63 | contentPanel.add(lblMethodDescription);
64 | }
65 | {
66 | JScrollPane scrollPane = new JScrollPane();
67 | scrollPane.setBounds(10, 35, 414, 183);
68 | JPanel panel = new JPanel(new GridBagLayout());
69 |
70 | /*
71 | for(int i=0; i< mi.getMethodParameterTypes().size(); i++)
72 | {
73 | JTextField textField = new JTextField(mi.getMethodParameterValues().get(i).toString(), 20);
74 | GridBagConstraints constraints = new GridBagConstraints();
75 | constraints.gridx = 1;
76 | constraints.gridy = i;
77 | constraints.insets = new Insets(10,10,10,10);
78 | panel.add(textField, constraints);
79 |
80 | textFields.add(textField);
81 |
82 | Class> tmpClass = (Class>) mi.getMethodParameterTypes().get(i);
83 | String simpleName = tmpClass.getSimpleName();
84 |
85 | JLabel label = null;
86 | if (mi.getHookableParamsIndex().get(i).toString().equals("-1"))
87 | label = new JLabel("[Return Value]");
88 | else
89 | label = new JLabel("[" + mi.getHookableParamsIndex().get(i).toString() +"] " + simpleName);
90 | constraints.gridx = 0;
91 | constraints.gridy = i;
92 | panel.add(label, constraints);
93 | }
94 | */
95 | lblMethodDescription.setText(mi.getClassName()+":"+mi.getHumanReadableDescription());
96 | System.out.println("debug size: " + mi.getMethodParameters().size());
97 | for(int i=0; i < mi.getMethodParameters().size(); i++)
98 | {
99 | ParameterInfo pi = mi.getMethodParameters().get(i);
100 | //System.out.println("debug: " + pi.getParameterValue().toString());
101 | //JTextField textField = new JTextField(pi.getParameterValue().toString(), 20);
102 | String string = pi.getParameterValue().toString();
103 | int rows = 1;
104 |
105 | if(string.contains("\n"))
106 | {
107 | for(int l=0; l valuesArray = new ArrayList