I wrote a server in java that is on port 4444.
Then I made a mysql connection with terminal to port 4444(my mysql real port is 3306)
Then with jpcap I captured the packet and changed the src port and ip to my server port and ip and also I changed destination port and id to mysql port and ip.
and I send the new packet with jpcapSender. The problem is that when I send the packet the length of that is 74. but when I capture that packet it is 60 bytes. I guessed it is because the dont_frag is false. But changing it didn't help.
package connection;
public class Bridge implements PacketReceiver {
NetworkInterface device;
static int DeviceName;
public Bridge(NetworkInterface device,int deviceName) throws IOException {
ServerSocket ss = new ServerSocket(4444);
this.device = device;
this.DeviceName=deviceName;
System.err.println(DeviceName);
JpcapCaptor jpcap;
jpcap = JpcapCaptor.openDevice(device, 2000, false, 20);
// System.err.println(jpcap.isNonBlockinMode());
jpcap.loopPacket(-1, new Bridge());
}
public Bridge() {
}
#Override
public void receivePacket(Packet p) {
if (p instanceof TCPPacket) {
TCPPacket myPacket = (TCPPacket) p;
if(myPacket.dst_port==3306 && myPacket.src_port==4444){
System.err.println("don't frag"+myPacket.len);
}
if (myPacket.dst_port == 4444) {
if(myPacket.syn==true){
System.err.println("connecting"+myPacket.len);
DatalinkPacket dlp=myPacket.datalink;
System.err.println(dlp.toString());
try {
Server.src_ip = myPacket.src_ip;
Server.src_port = myPacket.src_port;
myPacket.src_ip = InetAddress.getByName("127.0.0.1");// TODO
// variable
myPacket.src_port = 4444;
myPacket.dst_ip = InetAddress.getByName("127.0.0.1");// System.err.println("device"+this.DeviceName);
myPacket.dst_port = 3306;
sendPacket(myPacket);
} catch (UnknownHostException e) {
// Auto-generated catch block
e.printStackTrace();
}//
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (myPacket.syn = false ) {//
System.err.println("query request");
MySqlRequestParser parser = new MySqlRequestParser(
myPacket.data);
String query = parser.getQuery();
System.err.println(query);
// TODO get rules from db
// TODO check for rules
try {
Server.src_ip = myPacket.src_ip;
Server.src_port = myPacket.src_port;
// myPacket.src_ip = InetAddress.getByName("127.0.0.1");// TODO
// variable
//myPacket.src_port = 4444;
myPacket.dst_ip = InetAddress.getByName("127.0.0.1");// TODO
myPacket.dst_port = 3306;
sendPacket(myPacket);
} catch (UnknownHostException e) {
// Auto-generated catch block
e.printStackTrace();
}//
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if (myPacket.src_port == 3306) {
System.err.println("response"+myPacket.sequence);
if (myPacket.syn == false || myPacket.syn == true) {
System.err.println("response to query");
myPacket.dst_ip = Server.src_ip;
myPacket.dst_port = Server.src_port;
myPacket.src_port = 4444;// TODO about ip it's kinda
// fishiiii
try {
sendPacket(myPacket);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public void sendPacket(TCPPacket packet) throws IOException {
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
System.err.println("dev number"+DeviceName);
NetworkInterface dev=devices[DeviceName];
System.err.println("in sender packet src ip"
+ packet.src_ip.getHostAddress() + " dst ip "
+ packet.dst_ip.getHostAddress() + " src port "
+ packet.src_port + " dst port " + packet.dst_port+" len"+packet.len+" datalink:"+packet.datalink.toString());
JpcapSender sender = JpcapSender.openDevice(dev);
//TCPPacket tp=new TCPPacket(packet.src_port,packet.dst_port, packet.sequence, packet.ack_num, packet.urg, packet.ack, packet.psh, packet.rst, packet.syn, packet.fin, packet.rsv1, packet.rsv2, packet.window, packet.urgent_pointer);
System.err.println("open device"+packet.len);
boolean df=packet.dont_frag;
boolean mf=packet.more_frag;
boolean rf=packet.rsv_frag;
packet.dont_frag=true;
packet.offset=(short)(((packet.offset&0xFF)<<8)|((packet.offset&0xF00)>>8));
packet.offset=(short)((packet.offset|((mf?0x0020:0)|(df?0x0040:0)|(rf?0x0080:0))));
System.err.println("don't frag"+packet.dont_frag);
sender.sendPacket(packet);
System.err.println("packet sent");
sender.close();
}
public static void main(String[] arg) throws IOException {
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
int localIndex = 0;
for (int i = 0; i < devices.length; i++) {
if (devices[i].name.equals("lo")) {
localIndex = i;
}
}
System.err.println("lo:" + localIndex);
Bridge br = new Bridge(devices[localIndex],localIndex);
}
}
Related
First some Information regarding my Setup.
I have a S8 Cellphone, where i run this App, based upon the AR-Devkit demo from Google.
public void closeSocket(DatagramSocket socket) {
if (socket != null && socket.isConnected() ) {
while (!socket.isConnected()) {
socket.disconnect();
try {
Thread.sleep(SpringAR.TIME_OUT_IN_BROADCAST);
} catch (InterruptedException e) {
Log.d(SpringAR.protocollDebugLogPrefix, " Socket Closing interrupted");
e.printStackTrace();
}
}
}
if (socket != null && !socket.isClosed()) {
socket.close();
while (!socket.isClosed()) {
try {
Thread.sleep(SpringAR.TIME_OUT_IN_BROADCAST);
} catch (InterruptedException e) {
Log.d(SpringAR.protocollDebugLogPrefix, " Socket Closing interrupted");
e.printStackTrace();
}
}
}
}
public DatagramSocket createSocket(InetAddress ipAddress, int port) {
try {
DatagramSocket socket = new DatagramSocket(null);
InetSocketAddress address = new InetSocketAddress(ipAddress, port);
socket.setReuseAddress(true);
socket.bind(address);
return socket;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public DatagramSocket getBroadcastListenerSocket() throws IOException {
InetSocketAddress anyAdress = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 9000);
DatagramSocket socket = new DatagramSocket(null);
socket.setSoTimeout(30);
socket.setReuseAddress(true);
socket.bind(anyAdress);
return socket;
}
public DatagramSocket getBroadcastSenderSocket(DatagramSocket oldSocket) {
DatagramSocket socket = null;
try {
ARDeviceAddress = InetAddress.getByName(comonUtils.getIPAddress(true));
socket = getSocket(oldSocket, ARDeviceAddress, SpringAR.UDP_SERVER_PORT, null);
socket.setBroadcast(true);
socket.setSoTimeout(SpringAR.TIME_OF_FRAME_IN_MS);
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
public DatagramSocket getSocket(DatagramSocket oldSocket, InetAddress ipAddress, int port, InetAddress targetAddress) {
if (oldSocket != null ) {
closeSocket(oldSocket);
}
DatagramSocket socket = null;
try {
socket = createSocket(ipAddress, port);
socket.setBroadcast(false);
socket.setSoTimeout(SpringAR.TIME_OF_FRAME_IN_MS);
if (targetAddress != null)
socket.connect(targetAddress, port);
} catch (SocketException e) {
e.printStackTrace();
}
return socket;
}
public class DatagramReciever extends Thread {
private String datagramToSend = "";
private boolean newDatagramToSend = false;
private DatagramPacket snd_packet;
DatagramSocket senderSocket = null;
DatagramSocket listenerSocket = null;
private DatagramSocket broadCastListenerSocket;
//Buffer gettters and setters
private int writeBuffer = 0;
private SpringAR.comStates oldState;
int getReadBuffer() {
if (writeBuffer == 1) return 0;
return 1;
}
void switchBuffer() {
recieveByteIndex = 0;
writeBuffer = getReadBuffer();
}
public String dbg_message = "";
//Management Communication Headers
public void kill() {
closeSocket(senderSocket);
closeSocket(listenerSocket);
closeSocket(broadCastListenerSocket);
}
public void run() {
try {
initializeBroadcastConnection();
while (true) {
//Recieving Datagramm
DatagramPacket rcv_packet = new DatagramPacket(rcv_message[writeBuffer], rcv_message[writeBuffer].length);
boolean NewMessageArrived = true;
try {
listenerSocket.receive(rcv_packet);
} catch (SocketTimeoutException e) {
NewMessageArrived = false;
}
//Watchdog
handleWatchDogTimer(State);
//TODO Delete String conversion
if (NewMessageArrived) {
dbg_message = new String(rcv_message[writeBuffer], 0, rcv_packet.getLength(), "US-ASCII");
Log.d(SpringAR.dataDebugLogPrefix, "" + rcv_packet.getAddress().getHostAddress() + ": " + dbg_message.trim() + " of " + rcv_packet.getLength() + "length ");
}
if (validatePackageSender(rcv_packet)) {
connectionStateMachine(rcv_message, rcv_packet);
}
//Sending Datagram
if (newDatagramToSend && hostIpAddress != null) {
//Log.d(SpringAR.protocollDebugLogPrefix, "Server sending: " + datagramToSend);
byte[] snd_message = datagramToSend.getBytes();
try {
snd_packet = packSendPackageByState(snd_message);
assert (snd_packet != null);
senderSocket.send(snd_packet);
newDatagramToSend = false;
} catch (IOException e1) {
e1.printStackTrace();
//causes Caused by: android.system.ErrnoException: sendto failed: EINVAL (Invalid argument)
Log.e(SpringAR.protocollDebugLogPrefix, "Server Error in State: " + State.name());
break;
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
private void initializeBroadcastConnection() throws IOException {
ARDeviceAddress = InetAddress.getByName(comonUtils.getIPAddress(true));
senderSocket = getSocket(null, ARDeviceAddress, SpringAR.UDP_SERVER_PORT, null);
broadCastListenerSocket = getBroadcastListenerSocket();
listenerSocket = broadCastListenerSocket;
Log.d(SpringAR.protocollDebugLogPrefix, "initializeBroadcastConnection completed");
}
// handles management traffic like configurstion files
private void connectionStateMachine(byte[][] payload, DatagramPacket rcv_packet) throws IOException {
//Reset triggered by Host
if (comonUtils.indexOf(payload[writeBuffer], SpringAR.recieveResetHeaderByte) != SpringAR.STRING_NOT_FOUND) {
State = SpringAR.comStates.STATE_resetCommunication;
}
Log.d(SpringAR.protocollDebugLogPrefix, "ConnectionStateMachine: " + State.name());
switch (State) {
case STATE_resetCommunication: {
messageCounter = 0;
listenerSocket = broadCastListenerSocket;
hostIpAddress = comonUtils.getBroadcastAddress(context);
senderSocket = getBroadcastSenderSocket(senderSocket);
setSendToSpringMessage(SpringAR.sendResetHeader);
State = SpringAR.comStates.STATE_broadCastHeader;
return;
}
case STATE_broadCastHeader: {
if (comonUtils.indexOf(payload[writeBuffer], SpringAR.recieveHostReplyHeaderByte) != SpringAR.STRING_NOT_FOUND) {
Log.d(SpringAR.protocollDebugLogPrefix, " Host Reply Header recieved");
//Extract the hostIp
String hostIpAdressAsString = new String(payload[writeBuffer]);
hostIpAdressAsString = hostIpAdressAsString.replace(SpringAR.recieveHostReplyHeader, "").trim();
Log.d(SpringAR.dataDebugLogPrefix, hostIpAdressAsString);
hostIpAddress = InetAddress.getByName(hostIpAdressAsString);
//Set Connection from broadcast to target
ARDeviceAddress = InetAddress.getByName(comonUtils.getIPAddress(true));
Log.d(SpringAR.protocollDebugLogPrefix, " New Device Adress " + ARDeviceAddress);
senderSocket = getSocket(senderSocket, ARDeviceAddress, SpringAR.UDP_SERVER_PORT, hostIpAddress);
listenerSocket = senderSocket;
State = SpringAR.comStates.STATE_sendCFG;
return;
}
setSendToSpringMessage(SpringAR.sendBroadcasteHeader);
delayByMs(SpringAR.TIME_OUT_IN_BROADCAST);
return;
}
case STATE_sendCFG: {
if ( SpringAR.STRING_NOT_FOUND != comonUtils.indexOf(payload[writeBuffer], SpringAR.recieveCFGHeaderByte )) {
State = SpringAR.comStates.STATE_sendRecieveData;
return;
}
setSendToSpringMessage(SpringAR.formConfigurationMessage());
return;
}
case STATE_sendRecieveData: {
if ( SpringAR.STRING_NOT_FOUND != comonUtils.indexOf(payload[writeBuffer], SpringAR.recieveDataHeaderByte)) {
writeRecievedDataToBuffer(payload[writeBuffer], rcv_packet.getLength());
}
break;
}
default:
Log.d(SpringAR.protocollDebugLogPrefix, "Connection State Machine invalid state");
}
}
https://github.com/PicassoCT/arcore-android-sdk/blob/6c9b48a3d520e039cd48bc2af7354ccdec857736/arcore-android-sdk/samples/hello_ar/app/src/main/java/com/google/ar/core/examples/app/common/tcpClient/Server.java
All the testing is happening in a home-WiFi Setup, where the desktop with the host-application is directly attached to the WiFi-Router.
What is working thus far:
The device can broadcast its presence.
The host can broadcast its configuration.
The Device can not communicate from IP to IP on the host. Both sides have fixed IP set.
I can communicate with the App PacketSender with the host-Application, and ruled a failure on its part out.
I also built a smaller debug-loop, to only send udp-packets back and forth, which also worked.
Thank you for your time
Change this line:
socket.setSoTimeout(30);
to
socket.setSoTimeout(1000);
You've got a fairly complex state machine going here, and it's difficult to discern what is happening without having logs to look at. I would summarize your state machine like this:
Broadcast a configuration message
Spend 30ms listening for a response
If no response is received, block for SpringAR.TIME_OF_FRAME_IN_MS (not included in your code; I assume it is 1000ms), and loop back to #1
If a response was received, send a reply directly to the peer, and go to #2
#4 is the step that isn't happening. The likely reason (based on the Wireshark dump) is that it's taking 68ms for ARDevice's response to reach "Host". You only gave it 30ms. There could be a number of reasons it's taking so long, but that's beyond the scope of your question.
In a pice of code in which a class start a thread calling start method.
it throw an illegalstate exception. But if i call run() it gose well.
Can you expain me why ?
class A{
void methodA(){
T t = new T();
t.start(); // illegal state exception
t.run(); ///ok
}
}
class T extends Thread{
....
....
}
real code:
public class FileMultiServer
{
private static Logger _logger = Logger.getLogger("FileMultiServer");
public static void main(String[] args)
{
ServerSocket serverSocket = null;
boolean listening = true;
String host = "localhost";
int porta = 4444;
InetSocketAddress addr = null;
String archiveDir = System.getProperty("java.io.tmpdir");
Aes aes = new Aes();
Properties prop = new Properties();
//load a properties file
File propFile = new File("config.properties");
try {
System.out.println(propFile.getCanonicalPath());
prop.load(new FileInputStream("config.properties"));
} catch (Exception e1) {
// TODO Auto-generated catch block
System.out.println(e1);
}
DBConnector.dbName = prop.getProperty("database");
DBConnector.ipDb = prop.getProperty("urlDb");
DBConnector.dbPort = prop.getProperty("dbport");
DBConnector.userName = prop.getProperty("dbuser");
DBConnector.password = aes.DeCrypt(prop.getProperty("dbpassword"));
String agent_address = prop.getProperty("agent_ip");
String agent_port = prop.getProperty("agent_port");
try {
WDAgent m_agent = new WDAgent(agent_address, Integer.parseInt(agent_port));
m_agent.run();
} catch (NumberFormatException e1) {
// TODO Auto-generated catch block
System.out.println("errore nell'agent");
e1.printStackTrace();
} catch (Exception e1) {
// TODO Auto-generated catch block
StringWriter errors = new StringWriter();
e1.printStackTrace(new PrintWriter(errors));
_logger.debug(e1.getMessage());
_logger.debug(errors.toString());
System.out.println(e1.getMessage());
System.out.println(errors.toString());
}
String logCfg = System.getProperty("LOG");
if (logCfg != null) DOMConfigurator.configure(logCfg); else
DOMConfigurator.configure("log4j.xml");
try
{
if (args.length == 0) {
host = "localhost";
porta = 4444;
}
else if (args.length == 1) {
porta = Integer.parseInt(args[0]);
} else if (args.length == 2) {
host = args[0];
porta = Integer.parseInt(args[1]);
} else if (args.length == 3) {
host = args[0];
porta = Integer.parseInt(args[1]);
archiveDir = args[2];
} else {
_logger.info("usage: server <host> <port> | server [port] | server");
System.exit(88);
}
} catch (Exception e) {
_logger.error(e.getMessage());
_logger.info("enter a numer for argument or nothing....");
System.exit(88);
}
_logger.info("Allocating listen to: " + host + ":" + porta);
try
{
addr = new InetSocketAddress(host, porta);
serverSocket = new ServerSocket();
serverSocket.bind(addr);
} catch (Exception e) {
_logger.error(e.getMessage());
_logger.error("Could not listen on port: " + porta);
System.exit(-1);
}
_logger.info("Server listening on " + host + "-" + addr.getAddress().getHostAddress() + ":" + porta);
while (listening) {
try {
new FileMultiServerThread(serverSocket.accept(), archiveDir).start();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e);
}
}
try {
serverSocket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e);
}
}
}
class extends thread:
public class WDAgent extends Thread
{
private String _PID=null;
// *************************************************************************
// private - static final
// *************************************************************************
DatagramSocket socket;
boolean m_shutdown = false;
private static final Logger m_logger = Logger.getLogger(WDAgent.class);
private String getPID() {
try {
String ppid=System.getProperty("pid");
String match= "-Dpid="+ppid;
Runtime runtime = Runtime.getRuntime();
String cmd="/bin/ps -ef ";
Process process = runtime.exec(cmd);
InputStream is = process.getInputStream();
InputStreamReader osr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(osr);
String line;
while ((line = br.readLine()) != null) {
m_logger.info("line 0: "+line);
if(line.indexOf(match)!=-1 ) {
m_logger.info("line: "+line);
String[] cols=line.split(" ");
int count=0;
String val=null;
for (int k=0; k<cols.length; k++) {
if(cols[k].length()==0) continue;
count++;
if(count==3) {
// Good. I answerd the question
String pid = val;
m_logger.debug("pid processo: " + pid);
return pid;
}
val=cols[k];
}
}
}
}
catch (Exception err)
{
m_logger.error("Error retrieving PID....", err);
err.printStackTrace();
}
return null;
}
public WDAgent(String address, int port) throws IOException
{
InetSocketAddress isa = new InetSocketAddress(address, port);
socket = new DatagramSocket(isa);
m_logger.info("Agent started on (" + address + ":" + port + ")");
m_logger.info("Waiting for WD connection.");
this.start();
}
void Finalize() throws IOException
{
m_logger.info("Closing Agent.");
socket.close();
m_logger.info("Agent Closed");
}
public void Shutdown()
{
m_shutdown = true;
}
public void run()
{
byte[] buffer = new byte[1024];
int i;
while(!m_shutdown)
{
try {
String answer = "Agent PID=123456";
for (i=0; i<1024; i++)
buffer[i] = 0;
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
InetAddress client = packet.getAddress();
int client_port = packet.getPort();
m_logger.info("Received " + received + " from " + client);
if ((received.indexOf("PID") > 0) && (received.indexOf("ASK") > 0))
{
if(_PID==null) {
_PID=getPID();
}
if(_PID!=null) {
answer = "Agent PID=" + _PID;
m_logger.debug("risposta: " + answer);
DatagramPacket answ_packet = new DatagramPacket(answer.getBytes(), answer.getBytes().length, client, client_port);
socket.send(answ_packet);
} else {
m_logger.error("no PID per rispondere a watchdog .... sorry");
}
}
else
m_logger.warn("Command not recognized");
}
catch(IOException e)
{
m_logger.error(e.getMessage());
}
catch(Exception e)
{
m_logger.error(e.getMessage());
}
}
}
}
Well, if you call run(), you're just calling a method in your current thread. With start() you're attempting to start the Thread, and if it has for example already been started (or it has already stopped), you'll get an IllegalStateException.
ummm... you have already started the WDAgent Thread at constructor, so when you are trying to start again it thorws IllegalStateException.
You wanted to start it here:
...
try {
WDAgent m_agent = new WDAgent(agent_address, Integer.parseInt(agent_port));
m_agent.run(); // <-- Run that you wanted to be a start
} catch (NumberFormatException e1) {
...
But it was started in the constructor:
public WDAgent(String address, int port) throws IOException
{
InetSocketAddress isa = new InetSocketAddress(address, port);
socket = new DatagramSocket(isa);
m_logger.info("Agent started on (" + address + ":" + port + ")");
m_logger.info("Waiting for WD connection.");
this.start(); // <<----- It was already started here!!!!
}
You are running the run method twice, once in the new thread (you start it in the constructor) and one in the main thread by calling run.
t.start() is used to start the thread's execution. t.start() is used one time only. If you want to a run the thread again you will need to use t.run().
I have desktop and android applications, which connected by bluetooth(in desktop side I use Bluecove 2.1.1 library). Desktop application create bluetooth service then android application connects to it. I want to add logout functionality from both desktop and android sides. For example in desktop app user click disconnect, both desktop and android apps reset their connections and should be able to connect again. Here is bluetoothService code for desktop side:
public class BluetoothService
{
private static final String serviceName = "btspp://localhost:"
// + new UUID("0000110100001000800000805F9B34F7", false).toString()
// + new UUID("0000110100001000800000805F9B34F8", false).toString()
+ new UUID("0000110100001000800000805F9B34F9", false).toString()
+ ";name=serviceName";
private StreamConnectionNotifier m_service = null;
private ListenerThread m_listenerThread;
private DataOutputStream m_outStream;
public BluetoothService()
{
Open();
}
public void Open()
{
try
{
assert (m_service == null);
m_service = (StreamConnectionNotifier) Connector.open(serviceName);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void Start()
{
try
{
StreamConnection connection = (StreamConnection) m_service
.acceptAndOpen();
System.out.println("Connected");
m_listenerThread = new ListenerThread(connection);
Thread listener = new Thread(m_listenerThread);
listener.start();
m_outStream = new DataOutputStream(connection.openOutputStream());
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void Send(String message)
{
assert (m_listenerThread != null);
try
{
m_outStream.writeUTF(message);
m_outStream.flush();
System.out.println("Sent: " + message);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void Close()
{
try
{
m_service.close();
m_listenerThread.Stop();
m_listenerThread = null;
m_outStream.close();
m_outStream = null;
m_service = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
class ListenerThread implements Runnable
{
private DataInputStream m_inStream;
private boolean m_isRunning;
public ListenerThread(StreamConnection connection)
{
try
{
this.m_inStream = new DataInputStream(connection.openInputStream());
m_isRunning = true;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
;
}
public void run()
{
while (m_isRunning)
{
try
{
assert (m_inStream != null);
if (m_inStream.available() > 0)
{
String message = m_inStream.readUTF();
System.out.println("Received command: " + message);
CommandManager.getInstance().Parse(message);
}
}
catch (IOException e)
{
System.err.println(e.toString());
}
}
}
public void Stop()
{
m_isRunning = false;
try
{
m_inStream.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
for restarting service I do:
BluetoothService::Close();
BluetoothService::Open();
BluetoothService::Start();
but seems I cannot reconnect. Maybe I should create service with different name?
yet another java problem ...
got a client which should connect to a server via passive mode.
it seems to work fine, i get the ip adress and the port and the passivesocket says that it's ready.
but the passivesocket.getInputStream isn't ready at all - so i can't read from it and don't get the response to LIST.
can't figure out why, any suggestions?
public synchronized void getPasvCon() throws IOException, InterruptedException {
// Commands abholen
// IP Adresse holen
Thread.sleep(200);
String pasv = commands.lastElement();
String ipAndPort = pasv.substring(pasv.indexOf("(") + 1,
pasv.indexOf(")"));
StringTokenizer getIp = new StringTokenizer(ipAndPort);
// holt die IP
String ipNew = ""; // IP für den neuen Socket
for (int i = 0; i < 4; i++) {
if (i < 3) {
ipNew += (getIp.nextToken(",") + ".");
} else {
ipNew += (getIp.nextToken(","));
}
}
Integer portTemp1 = new Integer( getIp.nextToken(","));
Integer portTemp2 = new Integer (getIp.nextToken(","));
portNew = (portTemp1 << 8 )+ portTemp2;
System.out.println(">>>>> " + ipNew + ":" + portNew);
try {
pasvSocket = new Socket(ipNew, portNew);
System.out.println("Socket verbunden: "+ pasvSocket.isConnected());
} catch (UnknownHostException e) {
System.out.println("Host unbekannt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fromPasvServer = new BufferedReader(new InputStreamReader(
pasvSocket.getInputStream()));
Thread.sleep(2000);
System.out.println("Streams bereit: " + fromPasvServer.ready() + " | " );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
writePasvCommands = new PrintWriter(pasvSocket.getOutputStream(),
true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread.sleep(3000);
Thread pasvKonsole = new Thread(new PasvKonsole(this));
pasvKonsole.start();
}
public void LIST() throws IOException {
writeCommands.print("LIST\n");
writeCommands.flush();
}
public void run() {
try {
connect();
// getStatus();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
USER();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PASS();
try {
Thread.sleep(2000);
PASV();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
import java.io.IOException;
public class PasvKonsole extends Thread {
Client client;
public PasvKonsole(Client client) {
this.client = client;
}
public void run() {
System.out.println("========= PasvKonsole started");
while(true) {
try {
String lineP = client.fromPasvServer.readLine();
System.out.println("***" + lineP);
System.out.println("Ich bin da und tue auch was");
} catch (IOException e) {}
}
}
}
Added a Thread.Sleep and it works.
Due to a variety of reasons it became necessary to create our own proxy. Everything is working as it should through HTTP. As soon as we receive a CONNECT to tunnel through SSL is when everything goes wrong. What we do logically is take the CONNECT parse out the host and port so we know where we are sending future ssl requests and create a request to send back to the browser stating we have successfully made the ssl handshake like so:
HTTP/1.0 200 Connection established\r\nProxy-agent: test\r\n\r\n
What we expect to happen is that the browser once receiving this successful message will send us the next https request. However, instead we get sent another CONNECT request over and over.It is clear that is does not like the response we send back. The problem is that i'm not exactly sure why? Does the response back need to be sent back via an https socket? I just don't understand this process enough to move forward.
Here is my server class:
public class HttpServer extends Observable implements IWebServer, Runnable
{
int Port = -1;
int State = HttpState.IDLE;
ArrayList<WebTransactionEvent> History = new ArrayList<WebTransactionEvent>();
ArrayList<HttpService> myServices = new ArrayList<HttpService>();
SocketChannel myChannel = null;
boolean needResponse = false;
boolean shouldStop;
Logger logger = OpsToolsLogger.getLogger(HttpServer.class.getName());
Selector selector ;
static Hashtable<String, HttpServer> myInstances = new Hashtable<String, HttpServer>();
Hashtable<HttpTransaction, HttpService> myTaskTable = new Hashtable<HttpTransaction, HttpService>();
Vector<HttpTransaction> transactionQueue = new Vector<HttpTransaction>();
private HttpServer(){}
private HttpServer(int Port)
{
logger.log(Level.WARNING, "HttpServer: startup - listening to port: " + Port);
this.Port = Port;
shouldStop = false;
// Create the selector
try {
selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(Port));
this.registerSocket(serverChannel);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(this).start();
}
public static HttpServer getInstance(String port)
{
if( !myInstances.containsKey( port ) )
{
myInstances.put( port, new HttpServer(Integer.parseInt(port)));
}
return myInstances.get(port);
}
public int getState()
{
return State;
}
public void stop()
{
shouldStop = true;
}
public boolean needResponse()
{
return needResponse;
}
public HttpTransaction getNextTransaction()
{
if(transactionQueue.isEmpty())
{
return null;
}
//System.out.println("grabbing next trans");
HttpTransaction temp = transactionQueue.firstElement();
transactionQueue.remove(0);//pop trans from queue
return temp;
}
public void dropTransaction()
{
myTaskTable.clear();
needResponse = false;
}
public synchronized boolean respond(HttpTransaction transaction, IHttpResponse editedResponse, boolean closeConnection)
{
logger.log(Level.FINE, "HttpServer: responding ");
needResponse = false;
if(myTaskTable.isEmpty())
{
return false;
}
//see if there isn't a service object registered with that transaction
if(!myTaskTable.containsKey(transaction))
{
return false;
}
State = HttpState.SENDING_RESPONSE;
ManipulatedHttpTransaction myTrans = (ManipulatedHttpTransaction) transaction;
HttpResponse response = (HttpResponse) editedResponse;
myTrans.setManipulatedResponse( response );
HttpService serv = myTaskTable.get(transaction);
if(!serv.respond(myTrans.getManipulatedResponse(), closeConnection))
{
History.add( new WebTransactionEvent( myTrans, WebTransactionEvent.TRANSACTION_ERROR ) );
return false;
}
myTaskTable.remove(transaction);
History.add( new WebTransactionEvent( myTrans, WebTransactionEvent.TRANSACTION_COMPLETED ) );
needResponse = !myTaskTable.isEmpty();
return true;
}
public void registerSocket(ServerSocketChannel theSocket)
{
try {
theSocket.register(selector, SelectionKey.OP_ACCEPT);
} catch (ClosedChannelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run()
{
try {
while (!shouldStop ) {
// Wait for an event
selector.select();
// Get list of selection keys with pending events
Iterator it = selector.selectedKeys().iterator();
// Process each key
while (it.hasNext()) {
// Get the selection key
SelectionKey selKey = (SelectionKey)it.next();
// Remove it from the list to indicate that it is being processed
it.remove();
// Check if it's a connection request
if (selKey.isAcceptable()) {
// Get channel with connection request
ServerSocketChannel ssChannel = (ServerSocketChannel)selKey.channel();
SocketChannel theChannel = ssChannel.accept();
if(theChannel != null)
{
logger.log(Level.FINEST, "HttpServer: Connection established");
try
{
theChannel.configureBlocking(false);
}
catch(Exception e)
{
logger.log(Level.WARNING, "myChannel = null ( configureBlocking() )");
//bytesRead = -1;
}
myServices.add( new HttpService(this, theChannel ) );
needResponse = true;
}
//needResponse = !myTaskTable.isEmpty();
//System.out.println("need response: "+ needResponse);
}
}
}
} catch (IOException e) {
}
//shutdown
logger.log(Level.WARNING, "Server stopping - " + Port);
}
public ArrayList<WebTransactionEvent> getHistory()
{
return new ArrayList<WebTransactionEvent>(History);
}
public boolean switchServerToSSL()
{
//HttpService tempService = myTaskTable.get(PendingTransaction);
//tempService.useSSL = true;
return true;
}
/**
* Adds the transaction from browser to the transaction queue and also ties it to a service by adding it to myTasks map
* #param myTrans
* #param httpService
*/
public void addTransaction(ManipulatedHttpTransaction myTrans,
HttpService httpService) {
// TODO Auto-generated method stub
//ensure vector has room to add another transaction
if(transactionQueue.capacity() <= transactionQueue.size())
transactionQueue.ensureCapacity(transactionQueue.size() * 2);
transactionQueue.add(myTrans);//add transaction to queue
myTaskTable.put(myTrans, httpService);//tie the transaction toits service
// System.out.println("server notifying proxy: " + myTrans.getFullURL());
this.setChanged();
this.notifyObservers(myTrans);
}
}
Here is portion in proxy that handles a CONNECT:
if(tempTransaction.getOriginatingRequest().getMethod().contentEquals("CONNECT"))
{
/*tell the browser that the connection exists
*
* Each time you connect to an SSL-protected website, Burp generates a server certificate for that host, signed by the CA certificate
*
* The server certificates presented to the client (i.e. a web browser) are dynamically generated/signed by the proxy and contain most of the same fields as the original webserver certificate. The subject DN, serial number, validity dates, and extensions are preserved. However, the issuer DN is now set to the name of the proxy's self-signed
* certificate and the public/private keys of the proxy are used in creating the forged certificate. These forged certificates are cached (in memory) by the proxy, for better performance
*/
HttpResponse tunnelResponse = new HttpResponse("HTTP/1.0 200 Connection established\r\nProxy-agent: Ops Assistant\r\n\r\n");
tempTransaction.setResponse(tunnelResponse);
if(!finishResponse2(tempTransaction,tempTransaction.getResponse(), false));
{
//close the connection
}
myServer.switchServerToSSL();
}
Here is section sends request back to browser:
public boolean respond(IHttpResponse response, boolean closeConnection)
{
isCloseConnectionRequested = closeConnection;
try
{
if(useSSL)
{
ByteBuffer tmpBuffer = response.getData();
tmpBuffer.position(0);
myConnection.SecureWrite( tmpBuffer );
}
else
{
ByteBuffer tmpBuffer = response.getData();
tmpBuffer.position(0);
myConnection.Write(tmpBuffer);
}
if(closeConnection)
{
myChannel.close();
myChannel = null;
}
}
catch (Exception e)
{
isResponded = true;
return false;
}
isResponded = true;
return true;
}
Probably most important the socket class:
public class SocketConnection implements IConnection
{
public SocketChannel theSocketChannel;
public InetSocketAddress theRemoteAddress;
public int TimeoutThreshold;
private int TimeOutThreshold = 30;
private SSLEngine theSSLEngine;
private SSLContext theSSLContext;
private ByteBuffer inNetworkDataBuffer;
private ByteBuffer inAppDataBuffer;
private ByteBuffer outNetworkDataBuffer;
private ByteBuffer outAppDataBuffer;
//create outbound connection to host/port
public SocketConnection(String Host, int Port ) throws IOException
{
theRemoteAddress = new InetSocketAddress( Host, Port);
theSocketChannel = SocketChannel.open();
theSocketChannel.configureBlocking(false);
theSocketChannel.connect( theRemoteAddress );
theSocketChannel.finishConnect();
}
//use existing socket connection
public SocketConnection(SocketChannel existingChannel) throws IOException
{
theSocketChannel = existingChannel;
theSocketChannel.configureBlocking(false);
theRemoteAddress = new InetSocketAddress( existingChannel.socket().getInetAddress(), existingChannel.socket().getPort() );
}
public boolean setTimeOut(int newTimeOutThreshold)
{
TimeOutThreshold = newTimeOutThreshold;
return true;
}
public void waitForSocketToConnect() throws Exception
{
int i = 0;
while( !this.isConnected() )
{
this.finishConnect();
if(i>=3000)
{
throw new Exception();
}
i++;
try{Thread.sleep(10);}catch(Exception e){}
}
}
public boolean Write( ByteBuffer DataToSend )
{
try
{
//DataToSend.flip();
int numBytesWritten = theSocketChannel.write(DataToSend);
try
{
DataToSend.compact();
}
catch (ReadOnlyBufferException e)
{
DataToSend.rewind();
}
}
catch (IOException e)
{
// Connection may have been closed
}
return true;
}
public ByteBuffer Read()
{
ByteBuffer ResponseBytes = ByteBuffer.allocateDirect(0);
try
{
ByteBuffer netBuffer = ByteBuffer.wrap(new byte[10000]);
// Clear the buffer and read bytes from socket
netBuffer.clear();
int numBytesRead = theSocketChannel.read(netBuffer);
if(numBytesRead == -1)
return null; //-1 means we done return null as the flag
netBuffer.flip();
ByteBuffer tempBuffer = ByteBuffer.wrap(new byte[ ResponseBytes.limit() + netBuffer.limit() ]);
ResponseBytes.position(0);
netBuffer.position(0);
tempBuffer.put(ResponseBytes);
tempBuffer.put(netBuffer);
netBuffer.flip();
ResponseBytes = tempBuffer;
}
catch (IOException e)
{
// Connection may have been closed
e = e;
return ByteBuffer.wrap( e.getMessage().getBytes() );
}
return (ByteBuffer) ResponseBytes.flip();
}
public boolean SecureWrite( ByteBuffer DataToSend )
{
boolean writeSuccess = true;
try
{
//if we don't have a SSLEngine make one
if(theSSLEngine==null)
{
setupSSL();
}
//Convert Data
outAppDataBuffer.clear();
outAppDataBuffer.put(DataToSend);
outAppDataBuffer.flip();
SSLEngineResult sslResult = theSSLEngine.wrap(outAppDataBuffer, outNetworkDataBuffer);
outAppDataBuffer.compact();
//outNetworkDataBuffer.flip();
//int numBytesWritten = theSocketChannel.write(outNetworkDataBuffer);
if(sslResult.getStatus() == SSLEngineResult.Status.OK)
{
if(sslResult.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
{
// Write bytes
outNetworkDataBuffer.flip();
int numBytesWritten = theSocketChannel.write(outNetworkDataBuffer);
outNetworkDataBuffer.compact();
if(finishHandshake(sslResult))
{
DataToSend.rewind();
return SecureWrite(DataToSend);
}
else
{
return false;
}
}
else
{
// Write bytes
outNetworkDataBuffer.rewind();
Write(outNetworkDataBuffer);
}
}
else
{
}
}
catch(Exception e)
{
writeSuccess = false;
}
return writeSuccess;
}
public ByteBuffer SecureRead() throws ReadTimedOutException
{
int timeElapsed = 0;
ByteBuffer ResponseBytes = ByteBuffer.allocateDirect(0);
try
{
//if we don't have a SSLEngine make one
if(theSSLEngine==null)
{
setupSSL();
}
int consumedCount = 0;
SSLEngineResult sslResult;
do
{
//inNetworkDataBuffer.clear();
inNetworkDataBuffer.put( Read() );
inNetworkDataBuffer.flip();
sslResult = theSSLEngine.unwrap( inNetworkDataBuffer, inAppDataBuffer );
consumedCount += sslResult.bytesConsumed();
inNetworkDataBuffer.compact();
if( sslResult.getStatus() == SSLEngineResult.Status.OK )
{
if(sslResult.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
{
if(finishHandshake(sslResult))
{
return SecureRead();
}
else
{
return ByteBuffer.allocateDirect(0);
}
}
else
{
timeElapsed = 0;
inAppDataBuffer.flip();
ByteBuffer tempBuffer = ByteBuffer.wrap(new byte[ ResponseBytes.limit() + inAppDataBuffer.limit() ]);
ResponseBytes.position(0);
inAppDataBuffer.position(0);
tempBuffer.put(ResponseBytes);
tempBuffer.put(inAppDataBuffer);
inAppDataBuffer.flip();
ResponseBytes = tempBuffer;
ResponseBytes.flip();
}
}
else
{
//the status wasn't ok
timeElapsed++;
}
}while(consumedCount < inNetworkDataBuffer.limit() && sslResult.getStatus() != SSLEngineResult.Status.OK);
}
catch (Exception e)
{
System.out.println(e.toString());
}
if(timeElapsed>=TimeOutThreshold)
{
throw new ReadTimedOutException();
}
return ResponseBytes;
}
public boolean Disconnect()
{
try
{
theSocketChannel.close();
}
catch(Exception e)
{
return false;
}
return true;
}
public boolean isClosed()
{
return !theSocketChannel.isOpen();
}
#Override
public String getHost()
{
return theRemoteAddress.getHostName();
}
#Override
public int getPort()
{
return theRemoteAddress.getPort();
}
public boolean isConnected()
{
return theSocketChannel.isConnected();
}
#Override
public boolean hasSecure()
{
return true;
}
public boolean finishConnect() throws Exception
{
return theSocketChannel.finishConnect();
}
private void setupSSL() throws NoSuchAlgorithmException, KeyManagementException
{
//create a new SSLEngine instance
System.setProperty( "javax.net.debug", "ssl");
TrustManager[] tm = new TrustManager[] { new NaiveTrustManager() };
SSLContext theSSLContext = SSLContext.getInstance ("TLS");
theSSLContext.init( new KeyManager[0], tm, new SecureRandom( ) );
theSSLEngine = theSSLContext.createSSLEngine( theRemoteAddress.getHostName(), theRemoteAddress.getPort());
theSSLEngine.setUseClientMode(true);
inNetworkDataBuffer = ByteBuffer.wrap(new byte[theSSLEngine.getSession().getPacketBufferSize()]);
inAppDataBuffer = ByteBuffer.wrap(new byte[theSSLEngine.getSession().getApplicationBufferSize()]);
outNetworkDataBuffer = ByteBuffer.wrap(new byte[theSSLEngine.getSession().getPacketBufferSize()]);
outAppDataBuffer = ByteBuffer.wrap(new byte[theSSLEngine.getSession().getApplicationBufferSize()]);
}
private boolean finishHandshake(SSLEngineResult sslResult)
{
boolean bFinished = false;
while(sslResult.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED)
{
if( sslResult.getStatus() == SSLEngineResult.Status.CLOSED )
{
bFinished = false;
//break;
}
if(sslResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK)
{
Runnable task;
while ((task=theSSLEngine.getDelegatedTask()) != null)
{
task.run();
}
try
{
//outNetworkDataBuffer.flip();
sslResult = theSSLEngine.wrap(outAppDataBuffer, outNetworkDataBuffer);
//outNetworkDataBuffer.compact();
}
catch (SSLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(sslResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP)
{
try
{
outAppDataBuffer.flip();
sslResult = theSSLEngine.wrap(outAppDataBuffer, outNetworkDataBuffer);
outAppDataBuffer.compact();
} catch (SSLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if((sslResult.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) || (outNetworkDataBuffer.position() > 0))
{
try
{
outNetworkDataBuffer.flip();
int numBytesWritten = theSocketChannel.write(outNetworkDataBuffer);
outNetworkDataBuffer.compact();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
else if(sslResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)
{
try
{
int numBytes;
//read data from the socket into inNetworkBuffer
inNetworkDataBuffer.flip();
sslResult = theSSLEngine.unwrap( inNetworkDataBuffer, inAppDataBuffer );
inNetworkDataBuffer.compact();
if(theSSLEngine.isInboundDone())
{
}
else
{
numBytes = theSocketChannel.read(inNetworkDataBuffer);
numBytes = numBytes;
}
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
}
return true;
}
}
Anyone have any tips on how to best establish this handshake with the browser?
Have you read the Internet draft? The CONNECT is received in plaintext. You form the upstream connection and return the 'HTTP/1.0 200 Connection established' response. After that the proxy isn't processing requests and responses, it is just copying bytes in both directions, whatever they may happen to be. Specifically, the proxy isn't concerned with SSL in any way shape or form.