Skip to content

Commit a84434b

Browse files
committed
Implement UdpNetCat and test for it
1 parent 620cf98 commit a84434b

File tree

4 files changed

+243
-243
lines changed

4 files changed

+243
-243
lines changed

netcat/src/main/java/com/github/dddpaul/netcat/TcpNetCat.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public boolean isConnected()
6464
return socket != null && socket.isConnected();
6565
}
6666

67-
public class NetCatTask extends NetCat.Task
67+
public class NetCatTask extends Task
6868
{
6969
@Override
7070
protected Result doInBackground( String... params )
@@ -131,6 +131,7 @@ protected Result doInBackground( String... params )
131131
if( isListening() ) {
132132
stopListening();
133133
}
134+
break;
134135
}
135136
} catch( Exception e ) {
136137
e.printStackTrace();

netcat/src/main/java/com/github/dddpaul/netcat/UdpNetCat.java

Lines changed: 25 additions & 240 deletions
Original file line numberDiff line numberDiff line change
@@ -3,100 +3,24 @@
33
import android.os.AsyncTask;
44
import android.util.Log;
55

6-
import java.io.BufferedReader;
7-
import java.io.ByteArrayOutputStream;
8-
import java.io.Closeable;
96
import java.io.IOException;
10-
import java.io.InputStream;
11-
import java.io.InputStreamReader;
12-
import java.io.OutputStream;
13-
import java.io.PrintWriter;
147
import java.net.DatagramPacket;
158
import java.net.DatagramSocket;
169
import java.net.InetSocketAddress;
17-
import java.net.Socket;
18-
import java.nio.channels.AsynchronousCloseException;
19-
import java.nio.channels.ServerSocketChannel;
20-
import java.nio.channels.SocketChannel;
21-
22-
import javax.inject.Inject;
23-
24-
import de.greenrobot.event.EventBus;
25-
import events.ActivityEvent;
2610

2711
import static com.github.dddpaul.netcat.NetCater.State.CONNECTED;
2812
import static com.github.dddpaul.netcat.NetCater.State.IDLE;
29-
import static com.github.dddpaul.netcat.NetCater.State.LISTENING;
3013

3114
public class UdpNetCat extends NetCat
3215
{
3316
private final String CLASS_NAME = getClass().getSimpleName();
3417

3518
private NetCatTask task;
36-
private NetCatListener listener;
37-
private ServerSocketChannel serverChannel;
38-
private Closeable socket;
39-
private InputStream input;
40-
private OutputStream output;
41-
42-
/**
43-
* Needs for NetCatModule
44-
*/
45-
@Inject
46-
public UdpNetCat() {}
19+
private DatagramSocket socket;
4720

4821
public UdpNetCat( NetCatListener listener )
4922
{
50-
this.listener = listener;
51-
}
52-
53-
@Override
54-
public void setListener( NetCatListener listener )
55-
{
56-
this.listener = listener;
57-
}
58-
59-
@Override
60-
public void setInput( InputStream input )
61-
{
62-
this.input = input;
63-
}
64-
65-
@Override
66-
public void createOutput()
67-
{
68-
this.output = new ByteArrayOutputStream();
69-
}
70-
71-
@Override
72-
public void closeOutput()
73-
{
74-
try {
75-
output.flush();
76-
output.close();
77-
} catch( IOException e ) {
78-
Log.e( CLASS_NAME, e.getMessage() );
79-
}
80-
output = null;
81-
}
82-
83-
@Override
84-
public OutputStream getOutput()
85-
{
86-
return output;
87-
}
88-
89-
/**
90-
* Strip last CR+LF
91-
*/
92-
@Override
93-
public String getOutputString()
94-
{
95-
String s = output.toString();
96-
if( s.endsWith( "\n" )) {
97-
s = s.substring( 0, s.length() - 1 );
98-
}
99-
return s;
23+
super( listener );
10024
}
10125

10226
@Override
@@ -121,36 +45,20 @@ public void executeParallel( String... params )
12145
task.executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR, params );
12246
}
12347

124-
/**
125-
* If isListening = true, then isConnected() = true/false
126-
*/
12748
@Override
12849
public boolean isListening()
12950
{
130-
return serverChannel != null || (( socket instanceof DatagramSocket) && ((DatagramSocket) socket).isBound() );
51+
return socket != null && socket.isBound();
13152
}
13253

133-
/**
134-
* If isConnected = true, then isListening() = true
135-
*/
13654
@Override
13755
public boolean isConnected()
13856
{
139-
if( socket != null ) {
140-
if( socket instanceof Socket ) return ( (Socket) socket ).isConnected();
141-
if( socket instanceof DatagramSocket ) return ( (DatagramSocket) socket ).isConnected();
142-
}
143-
return false;
57+
return socket != null && socket.isConnected();
14458
}
14559

146-
public class NetCatTask extends AsyncTask<String, String, Result>
60+
public class NetCatTask extends Task
14761
{
148-
@Override
149-
protected void onPreExecute()
150-
{
151-
listener.netCatIsStarted();
152-
}
153-
15462
@Override
15563
protected Result doInBackground( String... params )
15664
{
@@ -165,86 +73,46 @@ protected Result doInBackground( String... params )
16573
String host = params[2];
16674
port = Integer.parseInt( params[3] );
16775
Log.d( CLASS_NAME, String.format( "Connecting to %s:%d (%s)", host, port, proto ) );
168-
if( proto == Proto.TCP ) {
169-
socket = new Socket();
170-
( (Socket) socket).connect( new InetSocketAddress( host, port ), 3000 );
171-
} else if( proto == Proto.UDP ) {
172-
socket = new DatagramSocket();
173-
( (DatagramSocket) socket).connect( new InetSocketAddress( host, port ) );
174-
}
76+
socket = new DatagramSocket();
77+
socket.connect( new InetSocketAddress( host, port ) );
17578
publishProgress( CONNECTED.toString() );
17679
result.object = socket;
17780
break;
17881
case LISTEN:
17982
proto = Proto.valueOf( params[1] );
18083
port = Integer.parseInt( params[2] );
18184
Log.d( CLASS_NAME, String.format( "Listening on %d (%s)", port, proto ) );
182-
if( proto == Proto.TCP ) {
183-
serverChannel = ServerSocketChannel.open();
184-
serverChannel.configureBlocking( false );
185-
serverChannel.socket().bind( new InetSocketAddress( port ) );
186-
publishProgress( LISTENING.toString() );
187-
while( !task.isCancelled() ) {
188-
SocketChannel channel = serverChannel.accept();
189-
Thread.sleep( 100 );
190-
if( channel != null ) {
191-
socket = channel.socket();
192-
result.object = socket;
193-
publishProgress( CONNECTED.toString() );
194-
break;
195-
}
196-
}
197-
if( task.isCancelled() ) {
198-
stopListening();
199-
result.exception = new Exception( "Listening task is cancelled" );
200-
}
201-
} else if( proto == Proto.UDP ) {
202-
socket = new DatagramSocket( port );
203-
result.object = socket;
204-
}
85+
socket = new DatagramSocket( port );
86+
result.object = socket;
20587
break;
20688
case RECEIVE:
207-
if( isConnected() && socket instanceof Socket ) {
208-
Log.d( CLASS_NAME, String.format( "Receiving from %s", getSocketRemoteString( socket )));
209-
receiveFromSocket( (Socket) socket );
210-
}
211-
if( isListening() && socket instanceof DatagramSocket ) {
89+
if( isListening() ) {
21290
// Connect after receive is necessary for further sending
213-
DatagramPacket packet = receiveFromDatagramSocket( (DatagramSocket) socket );
91+
DatagramPacket packet = receiveFromDatagramSocket();
21492
Log.d( CLASS_NAME, String.format( "Received data from %s (UDP)", packet.getSocketAddress() ) );
215-
( (DatagramSocket) socket ).connect( packet.getSocketAddress() );
93+
socket.connect( packet.getSocketAddress() );
21694
Log.d( CLASS_NAME, String.format( "Connected to %s (UDP)", packet.getSocketAddress() ) );
21795
}
21896
break;
21997
case SEND:
220-
if( isConnected() && socket instanceof Socket ) {
221-
Log.d( CLASS_NAME, String.format( "Sending to %s", getSocketRemoteString( socket ) ) );
222-
sendToSocket( (Socket) socket );
223-
}
224-
if( isListening() && socket instanceof DatagramSocket ) {
225-
Log.d( CLASS_NAME, String.format( "Sending on %d (UDP)", ( (DatagramSocket) socket ).getLocalPort() ) );
226-
sendToDatagramSocket( (DatagramSocket) socket );
98+
if( isConnected() ) {
99+
Log.d( CLASS_NAME, String.format( "Sending to %s (UDP)", socket.getRemoteSocketAddress() ) );
100+
sendToDatagramSocket();
227101
}
228102
break;
229103
case DISCONNECT:
230104
if( isConnected() ) {
231-
Log.d( CLASS_NAME, String.format( "Disconnecting from %s", getSocketRemoteString( socket )));
232-
if( socket instanceof Socket ) {
233-
( (Socket) socket).shutdownOutput();
234-
( (Socket) socket).close();
235-
} else {
236-
( (DatagramSocket) socket).close();
237-
}
238-
socket = null;
239-
publishProgress( IDLE.toString() );
105+
Log.d( CLASS_NAME, String.format( "Disconnecting from %s (UDP)", socket.getRemoteSocketAddress() ) );
240106
}
241107
if( isListening() ) {
242-
if( serverChannel != null ) {
243-
stopListening();
244-
} else {
245-
stopDatagramListening();
246-
}
108+
Log.d( CLASS_NAME, String.format( "Stop listening on %d (UDP)", socket.getLocalPort() ) );
247109
}
110+
if( isConnected() || isListening() ) {
111+
socket.close();
112+
socket = null;
113+
publishProgress( IDLE.toString() );
114+
}
115+
break;
248116
}
249117
} catch( Exception e ) {
250118
e.printStackTrace();
@@ -253,60 +121,7 @@ protected Result doInBackground( String... params )
253121
return result;
254122
}
255123

256-
@Override
257-
protected void onProgressUpdate( String... values )
258-
{
259-
State state = State.valueOf( String.valueOf( values[0] ) );
260-
EventBus.getDefault().post( new ActivityEvent( state ) );
261-
}
262-
263-
@Override
264-
protected void onPostExecute( Result result )
265-
{
266-
if( result.exception == null ) {
267-
Log.d( CLASS_NAME, String.format( "%s operation is completed", result.op ) );
268-
listener.netCatIsCompleted( result );
269-
} else {
270-
Log.e( CLASS_NAME, result.getErrorMessage() );
271-
listener.netCatIsFailed( result );
272-
}
273-
}
274-
275-
@Override
276-
protected void onCancelled( Result result )
277-
{
278-
listener.netCatIsFailed( result );
279-
}
280-
281-
private void receiveFromSocket( Socket socket ) throws IOException
282-
{
283-
BufferedReader reader = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
284-
PrintWriter writer = new PrintWriter( output );
285-
transferStreams( reader, writer );
286-
}
287-
288-
private void sendToSocket( Socket socket ) throws IOException
289-
{
290-
BufferedReader reader = new BufferedReader( new InputStreamReader( input ) );
291-
PrintWriter writer = new PrintWriter( socket.getOutputStream() );
292-
transferStreams( reader, writer );
293-
}
294-
295-
private void transferStreams( BufferedReader reader, PrintWriter writer ) throws IOException
296-
{
297-
try {
298-
String line;
299-
while( ( line = reader.readLine() ) != null ) {
300-
writer.println( line );
301-
writer.flush();
302-
}
303-
} catch( AsynchronousCloseException e ) {
304-
// This exception is thrown when socket for receiver thread is closed by netcat
305-
Log.w( CLASS_NAME, e.toString() );
306-
}
307-
}
308-
309-
private DatagramPacket receiveFromDatagramSocket( DatagramSocket socket ) throws IOException
124+
private DatagramPacket receiveFromDatagramSocket() throws IOException
310125
{
311126
byte[] buf = new byte[1024];
312127
DatagramPacket packet = new DatagramPacket( buf, buf.length );
@@ -315,7 +130,7 @@ private DatagramPacket receiveFromDatagramSocket( DatagramSocket socket ) throws
315130
return packet;
316131
}
317132

318-
private void sendToDatagramSocket( DatagramSocket socket ) throws IOException
133+
private void sendToDatagramSocket() throws IOException
319134
{
320135
byte[] buf = new byte[1024];
321136
int bytesRead = input.read( buf, 0, buf.length );
@@ -324,35 +139,5 @@ private void sendToDatagramSocket( DatagramSocket socket ) throws IOException
324139
socket.send( packet );
325140
}
326141
}
327-
328-
private void stopListening() throws IOException
329-
{
330-
Log.d( CLASS_NAME, String.format( "Stop listening on %d (TCP)", serverChannel.socket().getLocalPort() ) );
331-
serverChannel.close();
332-
serverChannel = null;
333-
}
334-
335-
private void stopDatagramListening() throws IOException
336-
{
337-
DatagramSocket udpSocket = ( (DatagramSocket) socket );
338-
Log.d( CLASS_NAME, String.format( "Stop listening on %d (UDP)", udpSocket.getLocalPort() ) );
339-
socket.close();
340-
socket = null;
341-
}
342-
343-
private String getSocketRemoteString( Closeable socket )
344-
{
345-
if( socket instanceof Socket ) {
346-
Socket tcpSocket = (Socket) socket;
347-
return tcpSocket.getInetAddress().getHostAddress() + ":" + tcpSocket.getPort();
348-
349-
}
350-
if( socket instanceof DatagramSocket ) {
351-
DatagramSocket udpSocket = (DatagramSocket) socket;
352-
return udpSocket.getInetAddress().getHostAddress() + ":" + udpSocket.getPort();
353-
354-
}
355-
return "";
356-
}
357142
}
358143
}

netcat/src/test/java/com/github/dddpaul/netcat/TcpNetCatTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public void send() throws InterruptedException, IOException
185185
do {
186186
line = b.readLine();
187187
Log.i( CLASS_NAME, line );
188-
} while( !inputFromTest.equals( line ) );
188+
} while( !TestUtils.INPUT_TEST.equals( line ) );
189189
}
190190

191191
public void receive() throws IOException, InterruptedException
@@ -209,6 +209,6 @@ public void receive() throws IOException, InterruptedException
209209
assertThat( result.op, is( RECEIVE ));
210210
String line = netCat.getOutputString();
211211
Log.i( CLASS_NAME, line );
212-
assertThat( line, is( inputFromProcess ));
212+
assertThat( line, is( TestUtils.INPUT_NC ));
213213
}
214214
}

0 commit comments

Comments
 (0)