diff --git a/.idea/modules.xml b/.idea/modules.xml index 4c9d0f4..b36e3f6 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,10 +3,7 @@ - - - \ No newline at end of file diff --git a/app/src/androidTest/java/ch/ethz/inf/vs/fstreun/payapp/DataServiceTest.java b/app/src/androidTest/java/ch/ethz/inf/vs/fstreun/payapp/DataServiceTest.java index e362d8c..40f5e8a 100644 --- a/app/src/androidTest/java/ch/ethz/inf/vs/fstreun/payapp/DataServiceTest.java +++ b/app/src/androidTest/java/ch/ethz/inf/vs/fstreun/payapp/DataServiceTest.java @@ -40,7 +40,7 @@ public class DataServiceTest { @ClassRule public static final ServiceTestRule mServiceRule = new ServiceTestRule(); - private static DataService.LocalBinder binder; + private static DataService.DataServiceBinder binder; private static UUID userID; @@ -61,7 +61,7 @@ public static void setBinder() throws TimeoutException { DataService.class); // Bind the service and grab a reference to the binder. - binder = (DataService.LocalBinder) mServiceRule.bindService(serviceIntent); + binder = (DataService.DataServiceBinder) mServiceRule.bindService(serviceIntent); } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2448c70..f1544cd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -45,18 +45,18 @@ android:parentActivityName=".MainActivity" /> - - + + expected = new HashMap<>(); + JSONArray jsonMap = object.getJSONArray(NetworkKeys.LENGTHMAP); + + for (int i = 0; i < jsonMap.length(); i++) { + JSONObject item = (JSONObject) jsonMap.get(i); + UUID mUUid = UUID.fromString( item.getString(NetworkKeys.DEVICEID)); + Integer mLength = Integer.valueOf(item.getString(NetworkKeys.LENGHT)); + expected.put(mUUid, mLength); + } + + // save data + mSessionAccess.putData(data, expected); + + } catch (JSONException e) { + // response body is not json + Log.e(TAG, "Response body handling failed, due to JSONException", e); + } + + + } + + + private String generateRequest(String host, int port, String body) { + String path = "/dataSync"; + String accept = "text/plain"; + String connect = "Closed"; + + + return "GET " + path + " HTTP/1.1\r\n" + + "Host: " + host + ":" + port + "\r\n" + + "Accept: " + accept + "\r\n" + + "Connection: " + connect + "\r\n\r\n" + + body + "\r\n" + + "\r\n"; + } + + + private String generateRequestBody() throws JSONException { + + // get data for request (UUID sessionId, Map start) + UUID sessionId = mSessionAccess.getSessionID(); + Map mData = mSessionAccess.getLength(); + + // create json request + JSONObject jsonRequest = new JSONObject(); + jsonRequest.put(NetworkKeys.SESSIONID, sessionId.toString()); + jsonRequest.put(NetworkKeys.COMMAND, "start"); + JSONArray mJsonMap = new JSONArray(); + + for (Map.Entry item : mData.entrySet()) { + UUID deviceId = item.getKey(); + Integer length = item.getValue(); + + JSONObject mJsonItem = new JSONObject(); + mJsonItem.put(NetworkKeys.DEVICEID, deviceId.toString()); + mJsonItem.put(NetworkKeys.LENGHT, length.toString()); + mJsonMap.put(mJsonItem); + } + + jsonRequest.put(NetworkKeys.LENGTHMAP, mJsonMap); + + return jsonRequest.toString(); + } +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSyncSubscribeService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Client/DataSyncSubscribeService.java similarity index 56% rename from app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSyncSubscribeService.java rename to app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Client/DataSyncSubscribeService.java index 4f256b3..4d463e3 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSyncSubscribeService.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Client/DataSyncSubscribeService.java @@ -1,4 +1,4 @@ -package ch.ethz.inf.vs.fstreun.network; +package ch.ethz.inf.vs.fstreun.network.DataSync.Client; import android.app.Service; import android.content.ComponentName; @@ -11,28 +11,18 @@ import android.os.IBinder; import android.util.Log; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; import java.util.Set; import java.util.UUID; import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; /** - * Created by Kaan on 30.11.17. + * Created by fstreun on 25.12.17. * */ @@ -48,7 +38,7 @@ public class DataSyncSubscribeService extends Service { private Set mServiceInfos = new HashSet<>(); - DataService.LocalBinder dataServiceBinder; + DataService.DataServiceBinder dataServiceBinder; boolean bound = false; @Override @@ -87,7 +77,7 @@ public void onDestroy() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (name.getClassName().equals(DataService.class.getName())){ - dataServiceBinder = (DataService.LocalBinder) service; + dataServiceBinder = (DataService.DataServiceBinder) service; bound = true; Log.d(TAG, "onServiceConnected: " + name.getClassName()); } @@ -200,7 +190,7 @@ public void onServiceFound(NsdServiceInfo service) { public void onServiceLost(NsdServiceInfo service) { // When the network service is no longer available. // Internal bookkeeping code goes here. - Log.e(TAG, "service lost" + service); + Log.d(TAG, "service lost: " + service); } }; } @@ -259,16 +249,20 @@ private class ClientThread implements Runnable { public void run() { - Log.i(TAG, "run()"); + Log.d(TAG, "run()"); + for (Iterator iterator = mServiceInfos.iterator(); iterator.hasNext();){ NsdServiceInfo serviceInfo = iterator.next(); InetAddress address = serviceInfo.getHost(); int port = serviceInfo.getPort(); - Socket socket = null; try { - socket = new Socket(address, port); + Socket socket = new Socket(address, port); socket.setSoTimeout(1000); - handleSocket(socket); + + DataSyncSubscribe dataSyncSubscribe = new DataSyncSubscribe(mSessionAccess, socket); + // execute not concurrent + dataSyncSubscribe.run(); + } catch (IOException e) { Log.e(TAG, "new Socket Creation exception.", e); iterator.remove(); @@ -278,162 +272,9 @@ public void run() { // call that data is updated mCallback.dataUpdated(); - Log.i(TAG, "run finished"); - } - - private void handleSocket(Socket socket){ - try { - - JSONObject requestBody = generateRequestBody(); - - String get_message = generateRequest(socket.getInetAddress().toString(), socket.getPort(), "/dataSync", requestBody.toString()); - - Log.d(TAG, "request: " + get_message); - - OutputStream mOutputStream = socket.getOutputStream(); - - PrintWriter wtr = new PrintWriter(mOutputStream); - wtr.print(get_message); - //mOutputStream.write(get_message.getBytes()); - wtr.flush(); - - BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - String result = parseResponseForBody(input); - - Log.d(TAG, "response: " + result); - - JSONObject responseBody = new JSONObject(result); - - handleResponse(responseBody); - - socket.close(); - return; - } catch (IOException e) { - e.printStackTrace(); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - private void handleResponse(JSONObject body){ - try { - UUID sessionId = UUID.fromString(body.getString(NetworkKeys.SESSIONID)); - if (!sessionId.equals(mSessionAccess.getSessionID())){ - // data not supposed to be for this session - return; - } - JSONObject data = body.getJSONObject(NetworkKeys.DATA); - - Map expected = new HashMap<>(); - JSONArray jsonMap = body.getJSONArray(NetworkKeys.LENGTHMAP); - - for (int i = 0; i < jsonMap.length(); i++) { - JSONObject item = (JSONObject) jsonMap.get(i); - UUID mUUid = UUID.fromString( item.getString(NetworkKeys.DEVICEID)); - Integer mLength = Integer.valueOf(item.getString(NetworkKeys.LENGHT)); - expected.put(mUUid, mLength); - } - - // save data - mSessionAccess.putData(data, expected); - }catch (JSONException e){ - Log.e(TAG, "JSONException in handleResponse.", e); - } - } - - private JSONObject generateRequestBody() { - - JSONObject mJsonRequest = null; - - try { - // get data for request (sessionId, Map start - UUID sessionId = mSessionAccess.getSessionID(); - Map mData = mSessionAccess.getLength(); - - // create json request - mJsonRequest = new JSONObject(); - mJsonRequest.put(NetworkKeys.SESSIONID, sessionId.toString()); - mJsonRequest.put(NetworkKeys.COMMAND, "start"); - JSONArray mJsonMap = new JSONArray(); - - for (Map.Entry item : mData.entrySet()) { - UUID deviceId = item.getKey(); - Integer length = item.getValue(); - - JSONObject mJsonItem = new JSONObject(); - mJsonItem.put(NetworkKeys.DEVICEID, deviceId.toString()); - mJsonItem.put(NetworkKeys.LENGHT, length.toString()); - mJsonMap.put(mJsonItem); - } - mJsonRequest.put(NetworkKeys.LENGTHMAP, mJsonMap); - } catch (JSONException e) { - Log.e(TAG, "JSONException in generateRequestBody.", e); - } - - return mJsonRequest; + Log.d(TAG, "run finished"); } - public String generateRequest(String host, int port, String path, String body) { - String accept = "text/plain"; - String connect = "Closed"; - - - String request = "GET " + path + " HTTP/1.1\r\n" - + "Host: " + host + ":" + port + "\r\n" - + "Accept: " + accept + "\r\n" - + "Connection: " + connect + "\r\n\r\n" - + body + "\r\n" - + "\r\n"; - - return request; - } - - private String parseResponseForBody(BufferedReader input) { - // parse all header fields - - try { - String statusLine = input.readLine(); - if (statusLine == null || statusLine.isEmpty()) { - return ""; - } - - String lengthLine = input.readLine(); - if (lengthLine == null || lengthLine.isEmpty()) { - return ""; - } - - String typeLine = input.readLine(); - if (typeLine == null || typeLine.isEmpty()) { - return ""; - } - - String connectionLine = input.readLine(); - if (connectionLine == null || connectionLine.isEmpty()) { - return ""; - } - - String emptyLine = input.readLine(); - if (emptyLine == null || !emptyLine.isEmpty()){ - return ""; - } - - StringBuilder result = new StringBuilder(); - String line; - - while ((line = input.readLine()) != null){ - if (line.isEmpty()){ - break; - }else { - result.append(line).append("\r\n"); - } - } - return result.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - return ""; - } } } diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Server/DataSyncPublish.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Server/DataSyncPublish.java new file mode 100644 index 0000000..0e36420 --- /dev/null +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Server/DataSyncPublish.java @@ -0,0 +1,159 @@ +package ch.ethz.inf.vs.fstreun.network.DataSync.Server; + +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import ch.ethz.inf.vs.fstreun.network.HttpParser; +import ch.ethz.inf.vs.fstreun.network.NetworkKeys; +import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; + +/** + * Created by fabio on 12/25/17. + * + */ + +public class DataSyncPublish implements Runnable{ + + private final String TAG = "DataSyncPublish"; + + private final DataService.DataServiceBinder mServiceBinder; + private final Socket mSocket; + + DataSyncPublish(DataService.DataServiceBinder serviceBinder, Socket socket){ + mServiceBinder = serviceBinder; + mSocket = socket; + } + + @Override + public void run() { + try { + handleCommunication(); + } catch (IOException e) { + Log.e(TAG, "handleCommunication throws IOException", e); + } + + if (mSocket != null){ + try { + mSocket.close(); + Log.d(TAG, "closed socket"); + } catch (IOException e) { + Log.e(TAG, "failed closing socket"); + } + } + } + + private void handleCommunication() throws IOException { + + // get input buffer + BufferedReader input = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); + + // parser http request + HttpParser httpParser = new HttpParser(input); + Log.d(TAG, "request: " + httpParser); + + if (httpParser.isError()){ + // error occurred during http parsing. + Log.e(TAG, "HTTP Parsing error occurred"); + + input.close(); + return; + } + + // get http body + String bodyString = httpParser.getBody(); + + // get output buffer + BufferedWriter output = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())); + PrintWriter wtr = new PrintWriter(output); + + // Create Here Response String + String responseBody = generateResponseBody(bodyString); + + Log.d(TAG, "response: " + responseBody); + + wtr.print(generateResponse(responseBody)); + wtr.flush(); + wtr.close(); + + input.close(); + } + + private String generateResponse(String body) { + + return "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.length() + "\r\n" + + "Content-Type: application/json\r\n" + + "Connection: Closed\r\n\r\n" + body+ "\r\n\r\n"; + } + + private String generateResponseBody(String requestBody) { + + if (mServiceBinder == null) { + // service not available + return "{\"" + NetworkKeys.SUCCESS + "\": false}"; + } + + JSONObject json; + try { + json = new JSONObject(requestBody); + + return generateResponseBody(json).toString(); + + } catch (JSONException e) { + // requestBody is not a JSON + return "{\"" + NetworkKeys.SUCCESS + "\": false}"; + } + + } + + private JSONObject generateResponseBody(JSONObject requestBody) throws JSONException { + JSONObject jsonResponse = new JSONObject(); + + // get requested sessionID + UUID sessionID = UUID.fromString(requestBody.getString(NetworkKeys.SESSIONID)); + + // get access to session + DataService.SessionNetworkAccess sessionAccess = mServiceBinder.getSessionNetworkAccess(sessionID); + if (sessionAccess == null){ + // no such session available + Log.d(TAG, "Session not available on this device."); + jsonResponse.put(NetworkKeys.SUCCESS, false); + return jsonResponse; + } + + // get start map + JSONArray jsonMap = requestBody.getJSONArray(NetworkKeys.LENGTHMAP); + Map start = new HashMap<>(jsonMap.length()); + for (int i = 0; i < jsonMap.length(); i++){ + JSONObject jsonItem = jsonMap.getJSONObject(i); + UUID deviceID = UUID.fromString(jsonItem.getString(NetworkKeys.DEVICEID)); + Integer length = Integer.valueOf(jsonItem.getString(NetworkKeys.LENGHT)); + start.put(deviceID, length); + } + + // get data after start + JSONObject data = sessionAccess.getData(start); + + // put data. + jsonResponse.put(NetworkKeys.SESSIONID, sessionID.toString()); + jsonResponse.put(NetworkKeys.LENGTHMAP, jsonMap); + jsonResponse.put(NetworkKeys.DATA, data); + jsonResponse.put(NetworkKeys.SUCCESS, true); + + return jsonResponse; + } +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Server/DataSyncPublishService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Server/DataSyncPublishService.java new file mode 100644 index 0000000..83508b5 --- /dev/null +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSync/Server/DataSyncPublishService.java @@ -0,0 +1,199 @@ +package ch.ethz.inf.vs.fstreun.network.DataSync.Server; + +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.nsd.NsdManager; +import android.net.nsd.NsdServiceInfo; +import android.os.IBinder; +import android.util.Log; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; + +import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; + +/** + * Created by fstreun on 25.12.17. + * + */ + +public class DataSyncPublishService extends Service { + + String TAG = "DataSyncPublishService"; + String SERVICE_TYPE = "_http._tcp."; + String SERVICE_NAME = "DataSyncPublisher"; + private NsdManager mNsdManager; + private NsdServiceInfo mServiceInfo; + private String mServiceName; + private ServerSocket mServerSocket = null; + private int mLocalPort; + private NsdManager.RegistrationListener mRegistrationListener; + + DataService.DataServiceBinder dataServiceBinder; + boolean bound = false; + + @Override + public void onCreate() { + super.onCreate(); + // start server Socket + initializeServerSocket(); + // Bind DataService + Intent intent = new Intent(this, DataService.class); + bindService(intent, connection, BIND_AUTO_CREATE); + } + + public void initializeServerSocket() { + // Initialize a server socket on the next available port. + if (mServerSocket == null) { + try { + mServerSocket = new ServerSocket(0); + // start master network thread + new Thread(new ServerMasterThread()).start(); + } catch (IOException e) { + e.printStackTrace(); + } + + // Store the chosen port. + mLocalPort = mServerSocket.getLocalPort(); + } + } + + + @Override + public void onDestroy() { + super.onDestroy(); + // unregister service + if (mNsdManager != null) { + mNsdManager.unregisterService(mRegistrationListener); + } + mNsdManager = null; + + // stop ServerSocket + if (mServerSocket != null){ + try { + mServerSocket.close(); + } catch (IOException e) { + Log.e(TAG, "failed to close ServerSocket"); + } + } + + // Unbind from service + if (bound){ + unbindService(connection); + bound = false; + } + } + + ServiceConnection connection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if (name.getClassName().equals(DataService.class.getName())){ + dataServiceBinder = (DataService.DataServiceBinder) service; + bound = true; + Log.d(TAG, "onServiceConnected: " + name.getClassName()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Log.e(TAG, "onServiceDisconnected"); + bound = false; + } + }; + + + + @Override + public IBinder onBind(Intent intent) { + // TODO: Return the communication channel to the service. + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + initializeRegistrationListener(); + registerService(mLocalPort); + return super.onStartCommand(intent, flags, startId); + } + + + + public void registerService(int port) { + // Create the NsdServiceInfo object, and populate it. + mServiceInfo = new NsdServiceInfo(); + + // The name is subject to change based on conflicts + // with other services advertised on the same network. + mServiceInfo.setServiceName(SERVICE_NAME); + mServiceInfo.setServiceType(SERVICE_TYPE); + mServiceInfo.setPort(port); + + mNsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE); + + mNsdManager.registerService(mServiceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener); + } + + + public void initializeRegistrationListener() { + mRegistrationListener = new NsdManager.RegistrationListener() { + + @Override + public void onRegistrationFailed(NsdServiceInfo nsdServiceInfo, int errorCode) { + Log.d(TAG, "Registration Failed: " + errorCode); + } + + @Override + public void onUnregistrationFailed(NsdServiceInfo nsdServiceInfo, int errorCode) { + Log.d(TAG, "Unregistration Failed: " + errorCode); + } + + @Override + public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) { + mServiceName = mServiceInfo.getServiceName(); + Log.d(TAG, "onServiceRegistered: " + mServiceName); + } + + @Override + public void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) { + Log.d(TAG, "onServiceUnregistered: " + nsdServiceInfo.getServiceName()); + } + }; + } + + class ServerMasterThread implements Runnable { + + private final static String TAG = "ServerMasterThread"; + + public void run() { + Log.i("ServerMasterThread", "run()"); + while (mServerSocket != null && !mServerSocket.isClosed()) { + + try { + Log.i(TAG, "run() - open RequestThread"); + Socket socket = mServerSocket.accept(); + socket.setSoTimeout(1000); + + // start slave thread + DataSyncPublish slaveThread = new DataSyncPublish(dataServiceBinder, socket); + + // run not concurrent + slaveThread.run(); + + + } catch (SocketException e) { + // socket closed + Log.e(TAG, "socket exception, probably closed.", e); + } catch (IOException e) { + Log.e(TAG, "io excepted.", e); + } + } + } + } + +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSyncPublishService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSyncPublishService.java deleted file mode 100644 index 93f876c..0000000 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/DataSyncPublishService.java +++ /dev/null @@ -1,373 +0,0 @@ -package ch.ethz.inf.vs.fstreun.network; - -import android.app.Service; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.net.nsd.NsdManager; -import android.net.nsd.NsdServiceInfo; -import android.os.IBinder; -import android.util.Log; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import ch.ethz.inf.vs.fstreun.payapp.R; -import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; - -/** - * Created by Kaan on 30.11.17. - * - */ - -public class DataSyncPublishService extends Service { - - String TAG = "DataSyncPublishService"; - String SERVICE_TYPE = "_http._tcp."; - String SERVICE_NAME = "DataSyncPublisher"; - private NsdManager mNsdManager; - private NsdServiceInfo mServiceInfo; - private String mServiceName; - private ServerSocket mServerSocket = null; - private int mLocalPort; - private NsdManager.RegistrationListener mRegistrationListener; - - DataService.LocalBinder dataServiceBinder; - boolean bound = false; - - private boolean registered; - - @Override - public void onCreate() { - super.onCreate(); - // start server Socket - initializeServerSocket(); - // Bind DataService - Intent intent = new Intent(this, DataService.class); - bindService(intent, connection, BIND_AUTO_CREATE); - } - - public void initializeServerSocket() { - // Initialize a server socket on the next available port. - if (mServerSocket == null) { - try { - mServerSocket = new ServerSocket(0); - // start master network thread - new Thread(new ServerMasterThread()).start(); - } catch (IOException e) { - e.printStackTrace(); - } - - // Store the chosen port. - mLocalPort = mServerSocket.getLocalPort(); - } - } - - - @Override - public void onDestroy() { - super.onDestroy(); - - // Unbind from service - if (bound){ - unbindService(connection); - bound = false; - } - - // unregister service - if (mNsdManager != null) { - mNsdManager.unregisterService(mRegistrationListener); - } - //registered = false; - mNsdManager = null; - - // stop ServerSocket - if (mServerSocket != null){ - try { - mServerSocket.close(); - } catch (IOException e) { - Log.e(TAG, "failed to close ServerSocket"); - } - } - - - } - - ServiceConnection connection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - if (name.getClassName().equals(DataService.class.getName())){ - dataServiceBinder = (DataService.LocalBinder) service; - bound = true; - Log.d(TAG, "onServiceConnected: " + name.getClassName()); - } - } - - @Override - public void onServiceDisconnected(ComponentName name) { - Log.e(TAG, "onServiceDisconnected"); - bound = false; - } - }; - - - - @Override - public IBinder onBind(Intent intent) { - // TODO: Return the communication channel to the service. - throw new UnsupportedOperationException("Not yet implemented"); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.d(TAG, "onStartCommand. registered: " + registered); - //if (!registered) { - initializeRegistrationListener(); - registerService(mLocalPort); - //} - return super.onStartCommand(intent, flags, startId); - } - - - - public void registerService(int port) { - // Create the NsdServiceInfo object, and populate it. - mServiceInfo = new NsdServiceInfo(); - - // The name is subject to change based on conflicts - // with other services advertised on the same network. - mServiceInfo.setServiceName(SERVICE_NAME); - mServiceInfo.setServiceType(SERVICE_TYPE); - mServiceInfo.setPort(port); - - mNsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE); - - mNsdManager.registerService(mServiceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener); - - registered = true; - } - - - public void initializeRegistrationListener() { - mRegistrationListener = new NsdManager.RegistrationListener() { - - @Override - public void onRegistrationFailed(NsdServiceInfo nsdServiceInfo, int errorCode) { - Log.d(TAG, "Registration Failed: " + errorCode); - } - - @Override - public void onUnregistrationFailed(NsdServiceInfo nsdServiceInfo, int errorCode) { - Log.d(TAG, "Unregistration Failed: " + errorCode); - } - - @Override - public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) { - mServiceName = mServiceInfo.getServiceName(); - Log.d(TAG, "onServiceRegistered: " + mServiceName); - } - - @Override - public void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) { - Log.d(TAG, "onServiceUnregistered: " + nsdServiceInfo.getServiceName()); - } - }; - } - - class ServerMasterThread implements Runnable { - - private final static String TAG = "ServerMasterThread"; - - public void run() { - Log.i("ServerMasterThread", "run()"); - while (mServerSocket != null && !mServerSocket.isClosed()) { - - try { - Log.i(TAG, "run() - open RequestThread"); - Socket socket = mServerSocket.accept(); - socket.setSoTimeout(1000); - // start slave thread - ServerSlaveThread slaveThread = new ServerSlaveThread(socket); - slaveThread.run(); - - - } catch (SocketException e) { - // socket closed - Log.e(TAG, "socket exception, probably closed.", e); - } catch (IOException e) { - Log.e(TAG, "io excepted.", e); - } - } - } - } - - class ServerSlaveThread implements Runnable{ - - private final static String TAG = "ServerSlaveThread"; - - private final Socket mSocket; - - ServerSlaveThread(Socket socket) { - this.mSocket = socket; - } - - @Override - public void run() { - - try { - Log.d(TAG, "run"); - if (!bound){ - // session access service not available - mSocket.close(); - return; - } - - BufferedReader input = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); - - String jsonBodyString = parseRequestForBody(input); - - Log.d(TAG, "request: " + jsonBodyString); - - JSONObject jsonBody = new JSONObject(jsonBodyString); - - - BufferedWriter output = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())); - - PrintWriter wtr = new PrintWriter(output); - - // Create Here Response String (favourably JSON) - JSONObject responseBody = generateResponseBody(jsonBody); - String stringBody = ""; - if (responseBody != null){ - stringBody = responseBody.toString(); - } - Log.d(TAG, "response: " + stringBody); - - wtr.print(generateResponse(stringBody)); - wtr.flush(); - wtr.close(); - - Log.d(TAG, "run finished without exception"); - }catch (IOException e){ - e.printStackTrace(); - }catch (JSONException e){ - e.printStackTrace(); - } - } - - private String generateResponse(String body) { - String response = "HTTP/1.1 200 OK\r\n" + - "Content-Length: " + body.length() + "\r\n" + - "Content-Type: application/json\r\n" + - "Connection: Closed\r\n\r\n" + body+ "\r\n\r\n"; - return response; - } - - private JSONObject generateResponseBody(JSONObject requestBody){ - JSONObject jsonResponse = null; - try { - UUID sessionID = UUID.fromString(requestBody.getString(NetworkKeys.SESSIONID)); - - DataService.SessionNetworkAccess sessionAccess = dataServiceBinder.getSessionNetworkAccess(sessionID); - if (sessionAccess == null){ - // no such session available - Log.d(TAG, "Session not available on this device."); - return null; - } - - String command = requestBody.getString(NetworkKeys.COMMAND); - - - JSONArray jsonMap = requestBody.getJSONArray(NetworkKeys.LENGTHMAP); - - Map start = new HashMap<>(jsonMap.length()); - - for (int i = 0; i < jsonMap.length(); i++){ - JSONObject jsonItem = jsonMap.getJSONObject(i); - UUID deviceID = UUID.fromString(jsonItem.getString(NetworkKeys.DEVICEID)); - Integer length = Integer.valueOf(jsonItem.getString(NetworkKeys.LENGHT)); - start.put(deviceID, length); - } - - JSONObject data = sessionAccess.getData(start); - - jsonResponse = new JSONObject(); - jsonResponse.put(NetworkKeys.SESSIONID, sessionID.toString()); - jsonResponse.put(NetworkKeys.LENGTHMAP, jsonMap); - jsonResponse.put(NetworkKeys.DATA, data); - - }catch (JSONException e){ - Log.e(TAG, "JSONException in generateResponseBody.", e); - return null; - } - return jsonResponse; - } - - private String parseRequestForBody(BufferedReader input) { - // parse all header fields - - try { - String requestLine = input.readLine(); - - if (requestLine == null || requestLine.isEmpty()) { - return ""; - } - - String hostLine = input.readLine(); - if (hostLine == null || hostLine.isEmpty()) { - return ""; - } - - String acceptLine = input.readLine(); - if (acceptLine == null || acceptLine.isEmpty()) { - return ""; - } - - String connectionLine = input.readLine(); - if (connectionLine == null || connectionLine.isEmpty()) { - return ""; - } - - String emptyLine = input.readLine(); - if (emptyLine == null || !emptyLine.isEmpty()){ - return ""; - } - - StringBuilder result = new StringBuilder(); - String line; - - while ((line = input.readLine()) != null){ - if (line.isEmpty()){ - Log.d(TAG, result.toString()); - break; - }else { - result.append(line).append("\r\n"); - } - } - return result.toString(); - } catch (IOException e) { - Log.e(TAG, "IOException in parseRequestForBody"); - } - return ""; - } - - - } -} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/HttpParser.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/HttpParser.java new file mode 100644 index 0000000..4c085d7 --- /dev/null +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/HttpParser.java @@ -0,0 +1,255 @@ +package ch.ethz.inf.vs.fstreun.network; + +import android.support.annotation.NonNull; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by fabio on 12/23/17. + * Parses HTTP requests. + * Body is only read if Content-Length is available + */ + +public class HttpParser { + + private final String TAG = "HTTPPARSER"; + + // BufferedReader given in the constructor and used by the parser. + public final BufferedReader bufferedReader; + + private String requestLine; + private String requestMethod; + private String requestURI; + private String requestHTTPVersion; + + private String head = ""; + private Map headerFields = new HashMap<>(); + + private String body = ""; + + private boolean error; + private List exceptions = new ArrayList<>(); + + public HttpParser(@NonNull BufferedReader bufferedReader){ + + this.bufferedReader = bufferedReader; + + try { + + // parse first line + String firstLine = bufferedReader.readLine(); + if (firstLine == null || firstLine.isEmpty()){ + error = true; + exceptions.add(new IOException("HTTP Parser Error: could not read from buffered reader!")); + return; + } + + try { + // might throw IOException if format is wrong + parserRequestLine(firstLine); + }catch (IOException e){ + // wrong format of request line. + error = true; + exceptions.add(new IOException("HTTP Parser Error: wrong request line format.", e)); + } + + + // parse all header fields + String headerLine; + while ((headerLine = bufferedReader.readLine()) != null){ + if (headerLine.isEmpty()){ + // end of header + break; + }else { + try { + + // might throw IOException if format is wrong + parseHeaderFields(headerLine); + }catch (IOException e){ + error = true; + exceptions.add(new IOException("HTTP Parser Error: wrong header line format.", e)); + } + } + } + + + // get content length header field. + String contentLength = getHeaderFieldValue("Content-Length"); + Integer maxLength = null; + + if (contentLength != null){ + // header field is available + try{ + maxLength = Integer.parseInt(contentLength); + }catch (NumberFormatException e){ + // unsuccessful parsing of integer + error = true; + exceptions.add(new IOException("HTTP Parser Error: Failed to parser Content-Length header value: " + contentLength, e)); + } + } + + + if (maxLength != null) { + // read body char by char + StringBuilder bodyLine = new StringBuilder(maxLength); + int c; + for (int i = 0; i < maxLength; i++) { + c = bufferedReader.read(); + bodyLine.append((char) c); + } + + parseBody(bodyLine.toString()); + } + + } catch (IOException e) { + e.printStackTrace(); + error = true; + exceptions.add(new IOException("Http Parser Error", e)); + } + } + + + /** + * Parses the request line of a http request + * @param line has to contain at most three parameters split by a space + * @throws IOException if to many many parameters are there + */ + private void parserRequestLine(@NonNull String line) throws IOException { + String[] parts = line.split(" ", -1); + + requestLine = line; + + if (parts.length < 3){ + throw new IOException("Illegal request line format: " + line); + } + + // TODO: distinguish between response and request... + + if (parts[0].startsWith("HTTP")){ + // it is a response + + }else{ + // it is a request + if (parts.length != 3){ + throw new IOException("Illegal request line format: " + line); + } + + requestMethod = parts[0]; + requestURI = parts[1]; + requestHTTPVersion = parts[2]; + } + + } + + /** + * Parses header fields of a http request. + * Appends line to the string head. + * Case-insensitive and appends values of the same header field with a comma to each other. + * @param line contains a header key ending with a ':' and followed by values. + * @throws IOException if format is not fulfilled + */ + private void parseHeaderFields(@NonNull String line) throws IOException { + + // check header line format + int endOfKey = line.indexOf(':'); + if (endOfKey < 0){ + throw new IOException("Following character is missing: ':' in the line: " + line); + } + + // append line to head string + head += line + "\n"; + + // add line to header map + String fieldKey = line.substring(0, endOfKey); + String fieldValue = line.substring(endOfKey + 2); + if (headerFields.containsKey(fieldKey)){ + // field key already parsed. Append new values with an comma. + fieldValue = headerFields.get(fieldKey) + ", " + fieldValue; + } + headerFields.put(fieldKey.toLowerCase(), fieldValue.toLowerCase()); + } + + /** + * parses the body of a http request. + * @param line to be append to the already parsed body + */ + private void parseBody(@NonNull String line){ + body += line; + } + + + /** + * + * @return the parsed requestLine + */ + public String getRequestLine(){ + return requestLine; + } + + /** + * + * @return the parsed request method. + */ + public String getRequestMethod() { + return requestMethod; + } + + /** + * + * @return the parsed request URI + */ + public String getRequestURI() { + return requestURI; + } + + /** + * + * @return the parsed request HTTP Version + */ + public String getRequestHTTPVersion() { + return requestHTTPVersion; + } + + /** + * + * @param fieldKey (case-insensitive) + * @return header field value or null if not parsed + */ + public String getHeaderFieldValue(String fieldKey){ + return headerFields.get(fieldKey.toLowerCase()); + } + + /** + * + * @return the parsed body of the http request + */ + public String getBody(){ + return body; + } + + /** + * + * @return true if an error occurred during parsing. + */ + public boolean isError() {return error;} + + /** + * + * @return a copy of the exception list. + */ + public List getExceptions() { + return new ArrayList<>(exceptions); + } + + + @Override + public String toString() { + return error ? "Error occurred during http parsing" : + requestLine + "\n" + head + "\n" + body; + } +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/NetworkKeys.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/NetworkKeys.java index 849f720..e1e6d86 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/NetworkKeys.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/NetworkKeys.java @@ -4,15 +4,20 @@ * Created by fabio on 12/12/17. */ -final class NetworkKeys { - static final String SESSIONID = "sessionID"; +public final class NetworkKeys { + public static final String SUCCESS = "success"; - static final String LENGTHMAP = "lengthmap"; - static final String DEVICEID = "deviceID"; - static final String LENGHT = "length"; + public static final String SECRET = "secret"; + public static final String GROUP = "group"; - static final String DATA = "data"; + public static final String SESSIONID = "sessionID"; - static final String COMMAND = "command"; + public static final String LENGTHMAP = "lengthmap"; + public static final String DEVICEID = "deviceID"; + public static final String LENGHT = "length"; + + public static final String DATA = "data"; + + public static final String COMMAND = "command"; } diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Client/GroupSubscribe.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Client/GroupSubscribe.java new file mode 100644 index 0000000..0b1369a --- /dev/null +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Client/GroupSubscribe.java @@ -0,0 +1,152 @@ +package ch.ethz.inf.vs.fstreun.network.SessionPublish.Client; + +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; + +import ch.ethz.inf.vs.fstreun.network.HttpParser; +import ch.ethz.inf.vs.fstreun.network.NetworkKeys; + +/** + * Created by fabio on 12/25/17. + * + */ + +public class GroupSubscribe implements Runnable{ + + private final String TAG = "GroupSubscribe"; + + private final Callback mCallback; + private final Socket mSocket; + + GroupSubscribe(Callback callback, Socket socket){ + mCallback = callback; + mSocket = socket; + } + + @Override + public void run() { + try { + if (mCallback != null) { + handleCommunication(); + } + } catch (IOException e) { + Log.e(TAG, "handleCommunication throws IOException", e); + } + + if (mSocket != null){ + try { + mSocket.close(); + Log.d(TAG, "closed socket"); + } catch (IOException e) { + Log.e(TAG, "failed closing socket"); + } + } + } + + private void handleCommunication() throws IOException { + + String requestBody; + try { + requestBody = generateRequestBody(); + } catch (JSONException e) { + // generation of Request failed + Log.e(TAG, "Request generation failed!"); + return; + } + + String request = generateRequest(mSocket.getInetAddress().toString(), mSocket.getPort(), requestBody); + Log.d(TAG, "Request: " + request); + + // get output stream and print writer + OutputStream outputStream = mSocket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + + printWriter.print(request); + printWriter.flush(); + + // get input buffer + BufferedReader input = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); + + // parse http response + HttpParser httpParser = new HttpParser(input); + Log.d(TAG, "request: " + httpParser); + + if (httpParser.isError()){ + // error occurred druing http parsing. + Log.e(TAG, "HTTP Parsing error occurred"); + + input.close(); + printWriter.close(); + return; + } + + // get http body + String bodyString = httpParser.getBody(); + + handleResponse(bodyString); + + // clean up streams and buffers + input.close(); + printWriter.close(); + + } + + private void handleResponse(String responseBody) { + + try { + JSONObject object = new JSONObject(responseBody); + + Boolean success = object.getBoolean(NetworkKeys.SUCCESS); + if (!success){ + // not successfull or wrong format + return; + } + + String secret = object.getString(NetworkKeys.SECRET); + String group = object.getString(NetworkKeys.GROUP); + + mCallback.groupFound(group, secret); + + } catch (JSONException e) { + // response body is not json + Log.e(TAG, "Response body handling failed, due to JSONException", e); + } + } + + private String generateRequest(String host, int port, String body) { + String path = "/joinGroup"; + String accept = "text/plain"; + String connect = "Closed"; + + + return "GET " + path + " HTTP/1.1\r\n" + + "Host: " + host + ":" + port + "\r\n" + + "Accept: " + accept + "\r\n" + + "Connection: " + connect + "\r\n\r\n" + + body + "\r\n" + + "\r\n"; + } + + + private String generateRequestBody() throws JSONException { + + JSONObject jsonRequest = new JSONObject(); + jsonRequest.put(NetworkKeys.SECRET, mCallback.getSecret()); + + return jsonRequest.toString(); + } + + public interface Callback{ + String getSecret(); + void groupFound(String simpleGroup, String secret); + } +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Client/GroupSubscribeService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Client/GroupSubscribeService.java new file mode 100644 index 0000000..14d724f --- /dev/null +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Client/GroupSubscribeService.java @@ -0,0 +1,151 @@ +package ch.ethz.inf.vs.fstreun.network.SessionPublish.Client; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.net.nsd.NsdManager; +import android.net.nsd.NsdServiceInfo; +import android.os.IBinder; +import android.util.Log; + +import java.io.IOException; +import java.net.Socket; + +import ch.ethz.inf.vs.fstreun.payapp.JoinGroupActivity; + +public class GroupSubscribeService extends Service { + + String TAG = "## GroupSubscribeService"; + String SERVICE_TYPE = "_http._tcp."; + String SERVICE_NAME = "SessionSubscriber"; + + private NsdManager mNsdManager; + private NsdServiceInfo mService; + private NsdManager.DiscoveryListener mDiscoveryListener; + + @Override + public IBinder onBind(Intent intent) { + // TODO: Return the communication channel to the service. + throw new UnsupportedOperationException("Not yet implemented"); + } + + + @Override + public void onCreate() { + super.onCreate(); + // initialize listener + initializeDiscoveryListener(); + mNsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + mNsdManager.stopServiceDiscovery(mDiscoveryListener); + + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + if (mNsdManager == null){ + Log.e(TAG, "FATAL ERRO: NSD Manager has not been properly initialized."); + stopSelf(); + return START_STICKY; + } + + mNsdManager.discoverServices( + SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); + + return super.onStartCommand(intent, flags, startId); + } + + + public void initializeDiscoveryListener() { + // Instantiate a new DiscoveryListener + mDiscoveryListener = new NsdManager.DiscoveryListener() { + + @Override + public void onStartDiscoveryFailed(String s, int errorCode ) { + Log.e(TAG, "Discovery failed: Error code:" + errorCode); + mNsdManager.stopServiceDiscovery(mDiscoveryListener); + } + + @Override + public void onStopDiscoveryFailed(String s, int errorCode) { + Log.e(TAG, "Discovery failed: Error code:" + errorCode); + mNsdManager.stopServiceDiscovery(mDiscoveryListener); + } + + @Override + public void onDiscoveryStarted(String s) { + Log.d(TAG, "Service discovery started: " + s); + } + + @Override + public void onDiscoveryStopped(String serviceType) { + Log.i(TAG, "Discovery stopped: " + serviceType); + } + + @Override + public void onServiceLost(NsdServiceInfo service) { + // When the network service is no longer available. + // Internal bookkeeping code goes here. + Log.e(TAG, "service lost" + service); + } + + @Override + public void onServiceFound(NsdServiceInfo service) { + // A service was found! Do something with it. + + Log.d(TAG, "onServiceFound: " + service); + + if (!service.getServiceType().equals(SERVICE_TYPE)) { + // Service type is the string containing the protocol and + // transport layer for this service. + Log.d(TAG, "Unknown Service Type: " + service.getServiceType()); + } else if (service.getServiceName().equals(SERVICE_NAME)) { + // The name of the service tells the user what they'd be + // connecting to. It could be "Bob's Chat App". + Log.d(TAG, "Same machine: " + SERVICE_NAME); + } else if (service.getServiceName().contains("SessionPublisher")){ + Log.d(TAG, "Resolve service: "); + mNsdManager.resolveService(service, new MyResolveListener()); + } + } + }; + } + + class MyResolveListener implements NsdManager.ResolveListener { + + + @Override + public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int errorCode) { + // Called when the resolve fails. Use the error code to debug. + Log.w(TAG, "Resolve failed" + errorCode); + } + + @Override + public void onServiceResolved(NsdServiceInfo serviceInfo) { + Log.w(TAG, "Resolve Succeeded. " + serviceInfo); + + if (serviceInfo.getServiceName().equals(SERVICE_NAME)) { + Log.i(TAG, "Same IP."); + return; + } + mService = serviceInfo; + Socket socket = null; + try { + socket = new Socket(mService.getHost(), mService.getPort()); + } catch (IOException e) { + Log.e(TAG, "onServiceResolved failed due to socket creation failure.", e); + return; + } + + GroupSubscribe groupSubscribe = new GroupSubscribe(JoinGroupActivity.instance, socket); + new Thread(groupSubscribe).start(); + } + } + +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Server/GroupPublish.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Server/GroupPublish.java new file mode 100644 index 0000000..de1691f --- /dev/null +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Server/GroupPublish.java @@ -0,0 +1,131 @@ +package ch.ethz.inf.vs.fstreun.network.SessionPublish.Server; + +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.Map; + +import ch.ethz.inf.vs.fstreun.network.HttpParser; +import ch.ethz.inf.vs.fstreun.network.NetworkKeys; + +/** + * Created by fabio on 12/25/17. + * + */ + +public class GroupPublish implements Runnable { + + private final String TAG = "GroupPublish"; + + private final Map mGroups; + private final Socket mSocket; + + GroupPublish(Map groups, Socket socket){ + mGroups = groups; + mSocket = socket; + } + + @Override + public void run() { + try { + handleCommunication(); + } catch (IOException e) { + Log.e(TAG, "handleCommunication throws IOException", e); + } + + if (mSocket != null){ + try { + mSocket.close(); + Log.d(TAG, "closed socket"); + } catch (IOException e) { + Log.e(TAG, "failed closing socket"); + } + } + } + + private void handleCommunication() throws IOException { + + // get input buffer + BufferedReader input = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); + + // parser http request + HttpParser httpParser = new HttpParser(input); + Log.d(TAG, "request: " + httpParser); + + if (httpParser.isError()){ + // error occurred during http parsing. + Log.e(TAG, "HTTP Parsing error occurred"); + + input.close(); + return; + } + + // get http body + String bodyString = httpParser.getBody(); + + // get output buffer + BufferedWriter output = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())); + PrintWriter wtr = new PrintWriter(output); + + // Create Here Response String + String responseBody = generateResponseBody(bodyString); + + Log.d(TAG, "response: " + responseBody); + + wtr.print(generateResponse(responseBody)); + wtr.flush(); + wtr.close(); + + input.close(); + } + + private String generateResponse(String body) { + + return "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + body.length() + "\r\n" + + "Content-Type: application/json\r\n" + + "Connection: Closed\r\n\r\n" + body+ "\r\n\r\n"; + } + + private String generateResponseBody(String requestBody) { + + try { + JSONObject json = new JSONObject(requestBody); + + return generateResponseBody(json).toString(); + + } catch (JSONException e) { + // requestBody is not a JSON + return "{\"" + NetworkKeys.SUCCESS + "\": false}"; + } + + } + + private JSONObject generateResponseBody(JSONObject requestBody) throws JSONException { + JSONObject jsonResponse = new JSONObject(); + + String secret = requestBody.getString(NetworkKeys.SECRET); + + String groupString = mGroups.get(secret); + + if (groupString != null){ + jsonResponse.put(NetworkKeys.GROUP, groupString); + jsonResponse.put(NetworkKeys.SECRET, secret); + jsonResponse.put(NetworkKeys.SUCCESS, true); + }else { + jsonResponse.put(NetworkKeys.SUCCESS, false); + } + return jsonResponse; + } + + +} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublishService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Server/GroupPublishService.java similarity index 57% rename from app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublishService.java rename to app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Server/GroupPublishService.java index 7aaed56..eb45e1a 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublishService.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionPublish/Server/GroupPublishService.java @@ -1,34 +1,24 @@ -package ch.ethz.inf.vs.fstreun.network; +package ch.ethz.inf.vs.fstreun.network.SessionPublish.Server; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.os.Binder; import android.os.IBinder; import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; -import java.net.SocketException; - -import ch.ethz.inf.vs.fstreun.payapp.R; +import java.util.HashMap; +import java.util.Map; -public class SessionPublishService extends Service { +public class GroupPublishService extends Service { - String TAG = "## SessionPublishService"; + String TAG = "## GroupPublishService"; String SERVICE_TYPE = "_http._tcp."; String SERVICE_NAME = "SessionPublisher"; @@ -45,7 +35,7 @@ public class SessionPublishService extends Service { private String secret; private String groupJsonString; - public SessionPublishService() {} + public GroupPublishService() {} @Override public IBinder onBind(Intent intent) { @@ -58,16 +48,16 @@ public IBinder onBind(Intent intent) { public class LocalBinder extends Binder { public void setSecretGroup(String secret, String groupJSON){ - SessionPublishService.this.secret = secret; - SessionPublishService.this.groupJsonString = groupJSON; + GroupPublishService.this.secret = secret; + GroupPublishService.this.groupJsonString = groupJSON; Log.d(TAG, "setSecretGroup: " + secret + "\n" + groupJSON); } } @Override public boolean onUnbind(Intent intent) { - SessionPublishService.this.secret = ""; - SessionPublishService.this.groupJsonString = ""; + GroupPublishService.this.secret = ""; + GroupPublishService.this.groupJsonString = ""; return super.onUnbind(intent); } @@ -208,8 +198,11 @@ public void run() { Log.i(TAG, "ServerMainThread accepted socket"); socket.setSoTimeout(1000); - ServerSlaveThread slaveThread = new ServerSlaveThread(socket); + Map groups = new HashMap<>(1); + groups.put(secret, groupJsonString); + GroupPublish slaveThread = new GroupPublish(groups, socket); new Thread(slaveThread).start(); + } catch (IOException e) { Log.d(TAG, "ServerMainThread exception occured", e); } @@ -217,106 +210,4 @@ public void run() { } } - class ServerSlaveThread implements Runnable { - - private final Socket socket; - - ServerSlaveThread(Socket socket){ - this.socket = socket; - } - - @Override - public void run() { - - try { - - BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - String jsonBodyString = parseRequestForBody(input); - - JSONObject mJson = null; - String key = ""; - mJson = new JSONObject(jsonBodyString); - key = mJson.getString("secret"); - - JSONObject response = new JSONObject(); - if (key.equals(secret)) { - response.put("result", true); - response.put("group", groupJsonString); - } else { - response.put("result", false); - } - - BufferedWriter output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); - - PrintWriter wtr = new PrintWriter(output); - wtr.print(generateResponse(response.toString())); - wtr.flush(); - wtr.close(); - - } catch (SocketException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - private String generateResponse(String body) { - String response = "HTTP/1.1 200 OK\r\n" + - "Content-Length: " + body.length() + "\r\n" + - "Content-Type: application/json\r\n" + - "Connection: Closed\r\n\r\n" + body + "\r\n\r\n"; - return response; - } - - private String parseRequestForBody(BufferedReader input) { - // parse all header fields - - try { - String requestLine = input.readLine(); - - if (requestLine == null || requestLine.isEmpty()) { - return ""; - } - - String hostLine = input.readLine(); - if (hostLine == null || hostLine.isEmpty()) { - return ""; - } - - String acceptLine = input.readLine(); - if (acceptLine == null || acceptLine.isEmpty()) { - return ""; - } - - String connectionLine = input.readLine(); - if (connectionLine == null || connectionLine.isEmpty()) { - return ""; - } - - String emptyLine = input.readLine(); - if (emptyLine == null || !emptyLine.isEmpty()){ - return ""; - } - - StringBuilder result = new StringBuilder(); - String line; - - while ((line = input.readLine()) != null){ - if (line.isEmpty()){ - Log.w(TAG, result.toString()); - break; - }else { - result.append(line).append("\r\n"); - } - } - return result.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - return ""; - } - } } diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionSubscribeService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionSubscribeService.java deleted file mode 100644 index 0333d50..0000000 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/network/SessionSubscribeService.java +++ /dev/null @@ -1,308 +0,0 @@ -package ch.ethz.inf.vs.fstreun.network; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.net.nsd.NsdManager; -import android.net.nsd.NsdServiceInfo; -import android.os.AsyncTask; -import android.os.IBinder; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.net.Socket; - -import ch.ethz.inf.vs.fstreun.payapp.JoinGroupActivity; - -public class SessionSubscribeService extends Service { - - String TAG = "## SessionSubscribeService"; - String SERVICE_TYPE = "_http._tcp."; - String SERVICE_NAME = "SessionSubscriber"; - - private NsdManager mNsdManager; - private NsdServiceInfo mService; - private NsdManager.DiscoveryListener mDiscoveryListener; - - private String secret; - - private JoinGroupActivity activity; - - public SessionSubscribeService(){} - - - @Override - public IBinder onBind(Intent intent) { - // TODO: Return the communication channel to the service. - throw new UnsupportedOperationException("Not yet implemented"); - } - - - @Override - public void onCreate() { - super.onCreate(); - // initialize listener - initializeDiscoveryListener(); - mNsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - mNsdManager.stopServiceDiscovery(mDiscoveryListener); - - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - - if (mNsdManager == null){ - Log.e(TAG, "FATAL ERRO: NSD Manager has not been properly initialized."); - stopSelf(); - return START_STICKY; - } - - secret = intent.getStringExtra("SECRET"); - activity = JoinGroupActivity.instance; - - - mNsdManager.discoverServices( - SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); - - return super.onStartCommand(intent, flags, startId); - } - - - public void initializeDiscoveryListener() { - // Instantiate a new DiscoveryListener - mDiscoveryListener = new NsdManager.DiscoveryListener() { - - @Override - public void onStartDiscoveryFailed(String s, int errorCode ) { - Log.e(TAG, "Discovery failed: Error code:" + errorCode); - mNsdManager.stopServiceDiscovery(mDiscoveryListener); - } - - @Override - public void onStopDiscoveryFailed(String s, int errorCode) { - Log.e(TAG, "Discovery failed: Error code:" + errorCode); - mNsdManager.stopServiceDiscovery(mDiscoveryListener); - } - - @Override - public void onDiscoveryStarted(String s) { - Log.d(TAG, "Service discovery started: " + s); - } - - @Override - public void onDiscoveryStopped(String serviceType) { - Log.i(TAG, "Discovery stopped: " + serviceType); - } - - @Override - public void onServiceLost(NsdServiceInfo service) { - // When the network service is no longer available. - // Internal bookkeeping code goes here. - Log.e(TAG, "service lost" + service); - } - - @Override - public void onServiceFound(NsdServiceInfo service) { - // A service was found! Do something with it. - - Log.d(TAG, "onServiceFound: " + service); - - if (!service.getServiceType().equals(SERVICE_TYPE)) { - // Service type is the string containing the protocol and - // transport layer for this service. - Log.d(TAG, "Unknown Service Type: " + service.getServiceType()); - } else if (service.getServiceName().equals(SERVICE_NAME)) { - // The name of the service tells the user what they'd be - // connecting to. It could be "Bob's Chat App". - Log.d(TAG, "Same machine: " + SERVICE_NAME); - } else if (service.getServiceName().contains("SessionPublisher")){ - Log.d(TAG, "Resolve service: "); - mNsdManager.resolveService(service, new MyResolveListener()); - } - } - }; - } - - class MyResolveListener implements NsdManager.ResolveListener { - - - @Override - public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int errorCode) { - // Called when the resolve fails. Use the error code to debug. - Log.w(TAG, "Resolve failed" + errorCode); - } - - @Override - public void onServiceResolved(NsdServiceInfo serviceInfo) { - Log.w(TAG, "Resolve Succeeded. " + serviceInfo); - - if (serviceInfo.getServiceName().equals(SERVICE_NAME)) { - Log.i(TAG, "Same IP."); - return; - } - mService = serviceInfo; - Socket socket = null; - try { - socket = new Socket(mService.getHost(), mService.getPort()); - } catch (IOException e) { - Log.e(TAG, "onServiceResolved failed due to socket creation failure.", e); - return; - } - - NetworkTask networkTask = new NetworkTask(); - networkTask.execute(socket); - } - } - - /** - * Have to use AsyncTask since UI Thread is needed to access the group list! - */ - class NetworkTask extends AsyncTask{ - - private Socket mSocket; - - - @Override - protected JSONObject doInBackground(Socket... sockets) { - mSocket = sockets[0]; - if (mSocket == null){ - return null; - } - Log.i("ClientThread", "run()"); - try { - //String get_message = generateRequest(mHost.getHostAddress(), mPort, "/joinGroup", secret); - String get_message = generateRequest(mSocket.getInetAddress().toString(), mSocket.getPort(), "/joinGroup", secret); - - OutputStream mOutputStream = mSocket.getOutputStream(); - - PrintWriter wtr = new PrintWriter(mOutputStream); - wtr.print(get_message); - wtr.flush(); - - BufferedReader input = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); - - String result = parseResponseForBody(input); - - JSONObject response = new JSONObject(result); - boolean success = response.getBoolean("result"); - if (success) { - Log.w(TAG, "Success response: " + result); - if (activity != null) { - // we are calling here activity's method - return new JSONObject(response.getString("group")); - } - } else { - // do nothing - Log.w(TAG, "Failure response: " + result); - return null; - } - return null; - } catch (IOException e) { - e.printStackTrace(); - } catch (JSONException e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void onPostExecute(JSONObject simpleGroup) { - if (mSocket != null && !mSocket.isClosed()){ - try { - mSocket.close(); - } catch (IOException e) { - Log.e(TAG, "Failed to close socket"); - } - } - - if (simpleGroup != null) { - activity.addGroupToList(simpleGroup); - } - super.onPostExecute(simpleGroup); - } - - private String parseResponseForBody(BufferedReader input) { - // parse all header fields - - try { - String statusLine = input.readLine(); - - if (statusLine == null || statusLine.isEmpty()) { - return ""; - } - - String lengthLine = input.readLine(); - if (lengthLine == null || lengthLine.isEmpty()) { - return ""; - } - - String typeLine = input.readLine(); - if (typeLine == null || typeLine.isEmpty()) { - return ""; - } - - String connectionLine = input.readLine(); - if (connectionLine == null || connectionLine.isEmpty()) { - return ""; - } - - String emptyLine = input.readLine(); - if (emptyLine == null || !emptyLine.isEmpty()){ - return ""; - } - - StringBuilder result = new StringBuilder(); - String line; - - while ((line = input.readLine()) != null){ - if (line.isEmpty()){ - Log.w(TAG, result.toString()); - break; - }else { - result.append(line).append("\r\n"); - } - } - return result.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - return ""; - } - - private String generateRequest(String host, int port, String path, String secret) { - String accept = "application/json"; - String connect = "Closed"; - - JSONObject requestBody = new JSONObject(); - try { - requestBody.put("secret", secret); - } catch (JSONException e) { - e.printStackTrace(); - } - - - String request = "GET " + path + " HTTP/1.1\r\n" - + "Host: " + host + ":" + port + "\r\n" - + "Accept: " + accept + "\r\n" - + "Connection: " + connect + "\r\n\r\n" - + requestBody.toString() + "\r\n" - + "\r\n"; - - return request; - } - } - -} diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/CreateGroupActivity.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/CreateGroupActivity.java index 1f34868..419f076 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/CreateGroupActivity.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/CreateGroupActivity.java @@ -74,7 +74,7 @@ protected void onStop() { public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance - DataService.LocalBinder binder = (DataService.LocalBinder) service; + DataService.DataServiceBinder binder = (DataService.DataServiceBinder) service; mService = binder.getService(); mBound = true; } diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/GroupActivity.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/GroupActivity.java index 055a597..0755948 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/GroupActivity.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/GroupActivity.java @@ -40,7 +40,7 @@ import ch.ethz.inf.vs.fstreun.finance.Participant; import ch.ethz.inf.vs.fstreun.finance.SimpleGroup; import ch.ethz.inf.vs.fstreun.finance.Transaction; -import ch.ethz.inf.vs.fstreun.network.DataSyncSubscribeService; +import ch.ethz.inf.vs.fstreun.network.DataSync.Client.DataSyncSubscribeService; import ch.ethz.inf.vs.fstreun.payapp.ListAdapters.ListParticipantsAdapter; import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; import ch.ethz.inf.vs.fstreun.payapp.filemanager.FileHelper; @@ -276,7 +276,7 @@ protected void onStop() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (name.getClassName().equals(DataService.class.getName())){ - DataService.LocalBinder binder = (DataService.LocalBinder) service; + DataService.DataServiceBinder binder = (DataService.DataServiceBinder) service; sessionAccess = binder.getSessionClientAccess(mSimpleGroup.sessionID); if (sessionAccess == null){ diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/JoinGroupActivity.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/JoinGroupActivity.java index adadd65..841ac6b 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/JoinGroupActivity.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/JoinGroupActivity.java @@ -7,6 +7,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; +import android.os.Handler; import android.os.IBinder; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; @@ -30,25 +31,28 @@ import ch.ethz.inf.vs.fstreun.finance.Group; import ch.ethz.inf.vs.fstreun.finance.SimpleGroup; -import ch.ethz.inf.vs.fstreun.network.SessionSubscribeService; +import ch.ethz.inf.vs.fstreun.network.SessionPublish.Client.GroupSubscribe; +import ch.ethz.inf.vs.fstreun.network.SessionPublish.Client.GroupSubscribeService; import ch.ethz.inf.vs.fstreun.payapp.ListAdapters.ListSimpleGroupAdapter; import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; import ch.ethz.inf.vs.fstreun.payapp.filemanager.FileHelper; -public class JoinGroupActivity extends AppCompatActivity { +public class JoinGroupActivity extends AppCompatActivity implements GroupSubscribe.Callback{ + + private String TAG = "JoinGroupActivity"; public static JoinGroupActivity instance; DataService mService; - private String TAG = "JoinGroupActivity"; boolean mBound; private Intent intentSessionSubscribeService; public static final String KEY_SIMPLEGROUP = "simple_group"; - EditText editTextGroupSecret; + private EditText editTextGroupSecret; + private String currentSecret; - List groupList = new ArrayList(); - ListSimpleGroupAdapter adapter; + private List groupList = new ArrayList(); + private ListSimpleGroupAdapter adapter; private SharedPreferences sharedPref; @Override @@ -61,6 +65,7 @@ protected void onCreate(Bundle savedInstanceState) { sharedPref = getSharedPreferences(prefName, Context.MODE_PRIVATE); editTextGroupSecret = findViewById(R.id.edittext_group_secret); + currentSecret = null; adapter = new ListSimpleGroupAdapter(this, groupList); ListView listViewFoundGroup = findViewById(R.id.listView_foundGroups); @@ -73,18 +78,17 @@ public void onItemClick(AdapterView parent, View view, int position, long id) } }); - final Button buttonJoin = findViewById(R.id.button_search); - buttonJoin.setOnClickListener(new View.OnClickListener() { + final Button buttonSearch = findViewById(R.id.button_search); + buttonSearch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - buttonJoinClicked(); + buttonSearchClicked(); } }); // for reference in service instance = this; - // Bind to LocalService Intent intent = new Intent(this, DataService.class); bindService(intent, mConnection, BIND_AUTO_CREATE); @@ -133,7 +137,7 @@ protected void onDestroy() { public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance - DataService.LocalBinder binder = (DataService.LocalBinder) service; + DataService.DataServiceBinder binder = (DataService.DataServiceBinder) service; mService = binder.getService(); mBound = true; } @@ -145,9 +149,7 @@ public void onServiceDisconnected(ComponentName arg0) { }; - - - private void buttonJoinClicked(){ + private void buttonSearchClicked(){ // end running try { stopService(intentSessionSubscribeService); @@ -155,30 +157,35 @@ private void buttonJoinClicked(){ } + currentSecret = editTextGroupSecret.getText().toString(); + groupList.clear(); adapter.notifyDataSetChanged(); - String groupHint = editTextGroupSecret.getText().toString(); - - intentSessionSubscribeService = new Intent(this, SessionSubscribeService.class); - intentSessionSubscribeService.putExtra("SECRET", groupHint); + intentSessionSubscribeService = new Intent(this, GroupSubscribeService.class); startService(intentSessionSubscribeService); } - public void addGroupToList(JSONObject groupJSON){ - Log.d(TAG, "SimpleGroup addGroupToList: " + groupJSON); - SimpleGroup group = null; - try { - group = new SimpleGroup(groupJSON); - Log.d(TAG, "SimpleGroup added: " + group.toJSON().toString()); - } catch (JSONException e) { - Log.e(TAG, "Failed to create SimpleGroup from JSON.", e); - return; - } - if (group != null) { - groupList.add(group); - adapter.notifyDataSetChanged(); + public void addGroupToList(String secret, String groupString){ + if (secret.equals(getSecret())){ + // still same secret + + Log.d(TAG, "SimpleGroup addGroupToList: " + groupString); + SimpleGroup group = null; + try { + JSONObject groupJSON = new JSONObject(groupString); + group = new SimpleGroup(groupJSON); + Log.d(TAG, "SimpleGroup added: " + group.toJSON().toString()); + } catch (JSONException e) { + Log.e(TAG, "Failed to create SimpleGroup from JSON.", e); + return; + } + if (group != null) { + groupList.add(group); + adapter.notifyDataSetChanged(); + } + } } @@ -291,4 +298,27 @@ private List loadGroups(){ } return groups; } + + + + @Override + public String getSecret() { + return currentSecret; + } + + @Override + public void groupFound(final String simpleGroup, final String secret) { + Log.d(TAG, "groupFound callback"); + + // Get a handler that can be used to post to the main thread + Handler mainHandler = new Handler(this.getMainLooper()); + + Runnable myRunnable = new Runnable() { + @Override + public void run() { + addGroupToList(secret, simpleGroup); + } // This is your code + }; + mainHandler.post(myRunnable); + } } diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/MainActivity.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/MainActivity.java index c90b4a8..591f520 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/MainActivity.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/MainActivity.java @@ -32,8 +32,8 @@ import java.util.Set; import ch.ethz.inf.vs.fstreun.finance.SimpleGroup; -import ch.ethz.inf.vs.fstreun.network.DataSyncPublishService; -import ch.ethz.inf.vs.fstreun.network.DataSyncSubscribeService; +import ch.ethz.inf.vs.fstreun.network.DataSync.Server.DataSyncPublishService; +import ch.ethz.inf.vs.fstreun.network.DataSync.Client.DataSyncSubscribeService; import ch.ethz.inf.vs.fstreun.payapp.ListAdapters.ListGroupAdapter; import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; @@ -124,7 +124,7 @@ protected void onDestroy() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (name.getClassName().equals(DataService.class.getName())){ - DataService.LocalBinder binder = (DataService.LocalBinder) service; + DataService.DataServiceBinder binder = (DataService.DataServiceBinder) service; dataService = binder.getService(); bound = true; Log.d(TAG, "onServiceConnected: " + name.getClassName()); diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/PublishGroupActivity.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/PublishGroupActivity.java index 34edb2d..29d1223 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/PublishGroupActivity.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/PublishGroupActivity.java @@ -17,12 +17,12 @@ import java.util.Random; import ch.ethz.inf.vs.fstreun.finance.SimpleGroup; -import ch.ethz.inf.vs.fstreun.network.SessionPublishService; +import ch.ethz.inf.vs.fstreun.network.SessionPublish.Server.GroupPublishService; public class PublishGroupActivity extends AppCompatActivity { boolean bound; - SessionPublishService.LocalBinder serviceBind; + GroupPublishService.LocalBinder serviceBind; private String TAG = "PublishGroupActivity"; public final static String KEY_SIMPLEGROUP = "key_group"; @@ -57,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { Log.i(TAG, "start service"); // bind service with simplegroup (secret is set with bound service) - intentSessionPublishService = new Intent(this, SessionPublishService.class); + intentSessionPublishService = new Intent(this, GroupPublishService.class); startService(intentSessionPublishService); bindService(intentSessionPublishService, connection, BIND_AUTO_CREATE); } @@ -69,8 +69,8 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "Service bound: " + name.getClassName()); - if (name.getClassName().equals(SessionPublishService.class.getName())){ - serviceBind = (SessionPublishService.LocalBinder) service; + if (name.getClassName().equals(GroupPublishService.class.getName())){ + serviceBind = (GroupPublishService.LocalBinder) service; bound = true; // create random 4 digit number diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/TransactionListActivity.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/TransactionListActivity.java index 720e364..1da175b 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/TransactionListActivity.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/TransactionListActivity.java @@ -35,7 +35,7 @@ import ch.ethz.inf.vs.fstreun.finance.Group; import ch.ethz.inf.vs.fstreun.finance.SimpleGroup; import ch.ethz.inf.vs.fstreun.finance.Transaction; -import ch.ethz.inf.vs.fstreun.network.DataSyncSubscribeService; +import ch.ethz.inf.vs.fstreun.network.DataSync.Client.DataSyncSubscribeService; import ch.ethz.inf.vs.fstreun.payapp.ListAdapters.ListTransactionAdapter; import ch.ethz.inf.vs.fstreun.payapp.filemanager.DataService; import ch.ethz.inf.vs.fstreun.payapp.filemanager.FileHelper; @@ -355,7 +355,7 @@ protected void onDestroy() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (name.getClassName().equals(DataService.class.getName())){ - DataService.LocalBinder binder = (DataService.LocalBinder) service; + DataService.DataServiceBinder binder = (DataService.DataServiceBinder) service; sessionAccess = binder.getSessionClientAccess(group.getSessionID()); if(sessionAccess != null) { diff --git a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/filemanager/DataService.java b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/filemanager/DataService.java index 85b0f96..6f1d6af 100644 --- a/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/filemanager/DataService.java +++ b/app/src/main/java/ch/ethz/inf/vs/fstreun/payapp/filemanager/DataService.java @@ -107,13 +107,13 @@ private void storeSessionIDs(Set sessionIDs){ */ // Binder given to clients - private final IBinder mBinder = new LocalBinder(); + private final IBinder mBinder = new DataServiceBinder(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ - public class LocalBinder extends Binder { + public class DataServiceBinder extends Binder { /** * Return this instance of LocalService so clients can call public methods diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml new file mode 100644 index 0000000..affc7ba --- /dev/null +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_join_group.xml b/app/src/main/res/layout/activity_join_group.xml index 192f38a..c4b4e12 100644 --- a/app/src/main/res/layout/activity_join_group.xml +++ b/app/src/main/res/layout/activity_join_group.xml @@ -12,28 +12,41 @@ android:padding="8dp" android:text="Search group with secret." /> - - -