package de.tudarmstadt.informatik.hostage.sync.wifi_direct; import android.net.wifi.p2p.WifiP2pDevice; import android.net.wifi.p2p.WifiP2pManager; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /** * Created by Julien on 07.01.2015. * * The Server Task. * * The Server task is waiting as long as a client is connecting to it. * As a result of this the main part and process will start after the client had send the first data. * * You never know how will become the host / server. * So you need to implement a strategy if you want do send just from one specific device to the other. * * * The server creates the object stream before the client can do it - to avoid a chicken and egg problem. */ public abstract class WiFiP2pServerTask extends BackgroundTask { private ServerSocket serverSocket; private WifiP2pDevice ownDevice; @Override public void interrupt(boolean b){ super.interrupt(b); if (b && this.serverSocket != null) { try { this.serverSocket.close(); } catch (IOException e) { Log.e("WiFiP2pServerTask", e.getMessage()); } } } public WiFiP2pServerTask( WifiP2pDevice ownDevice, BackgroundTaskCompletionListener l){ super(l); this.ownDevice = ownDevice; } @Override public boolean performInBackground(){ while (!this.isInterrupted()){ try { this.serverSocket = new ServerSocket(WiFiP2pClientTask.port()); Log.d("WiFiP2pServerTask", "Server: Socket opened"); Socket client = this.serverSocket.accept(); Log.d("WiFiP2pServerTask", "Server: connection done"); this.handleConnection(client, this.serverSocket); client.close(); serverSocket.close(); return true; } catch (ClassNotFoundException e){ e.printStackTrace(); Log.e("WiFiP2pServerTask", e.getMessage()); return false; } catch (IOException e) { e.printStackTrace(); Log.e("WiFiP2pServerTask", e.getMessage()); return false; } } return true; } /** * The server creates the object stream before the client can do it to avoid a chicken and egg problem. * @param client the client socket. * @param server the server socket. * @throws IOException * @throws ClassNotFoundException */ private void handleConnection(Socket client, ServerSocket server) throws IOException, ClassNotFoundException { OutputStream os = client.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); oos.flush(); InputStream is = client.getInputStream(); ObjectInputStream ois = new ObjectInputStream(is); Object obj = ois.readObject(); while (obj != null && obj instanceof WiFiP2pSerializableObject) { WiFiP2pSerializableObject receivedObj = ( WiFiP2pSerializableObject) obj; obj = null; WiFiP2pSerializableObject toSend = this.handleReceivedObject(receivedObj); if (toSend != null) { toSend.setActingDevice_IP_address(this.ownDevice.deviceAddress); oos.writeObject(toSend); oos.flush(); oos.reset(); } try { obj = ois.readObject(); }catch (IOException e){ // IF NULL WAS TRANSMITTED obj = null; } } oos.close(); os.close(); ois.close(); is.close(); } /** * This method will be called if the server receives data from the client. * Always return a WiFiP2pSerializableObject instance to give a simple response, otherwise the connection will be disconnected. * @param receivedObj WiFiP2pSerializableObject the clients request * @return WiFiP2pSerializableObject the response */ abstract public WiFiP2pSerializableObject handleReceivedObject(WiFiP2pSerializableObject receivedObj); }