flashwifi/app/src/main/java/com/flashwifi/wifip2p/NegotiationClientTask.java
Daniel Pollithy d99b7437b7 Stabilize socket messaging
Add GSON
Begin to implement negotiation protocol
2018-01-07 00:24:47 +01:00

274 lines
7.8 KiB
Java

package com.flashwifi.wifip2p;
import android.os.AsyncTask;
import android.util.Log;
import com.flashwifi.wifip2p.datastore.PeerStore;
import com.flashwifi.wifip2p.protocol.NegotiationFinalization;
import com.flashwifi.wifip2p.protocol.NegotiationOffer;
import com.flashwifi.wifip2p.protocol.NegotiationOfferAnswer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class NegotiationClientTask extends AsyncTask<String, Void, String> {
private static final String TAG = "NegClientTask";
private boolean running = true;
private Socket socket;
private NegotiationServerTask.State server_state;
private NegotiationClientTask.State client_state;
BufferedReader in;
PrintWriter out;
private boolean isClient = false;
public String getLine() {
String response;
try {
response = in.readLine();
} catch (IOException ex) {
response = "Error: " + ex;
}
Log.d(TAG, "getLine: " + response);
return response;
}
private void sendLine(String line) {
out.println(line);
Log.d(TAG, "sendLine: " + line);
}
public void writeError(int code, String msg) {
sendLine(String.format("err_code: %s msg: %s", Integer.toString(code), msg));
}
private boolean runClient(String ipAddressString, boolean isClient, String macAddress) {
boolean success = false;
try {
client_state = State.INITIAL;
// create socket
socket = new Socket(ipAddressString, 9898);
// set the socket timeout to 1 second
// ToDo: make this a variable
socket.setSoTimeout(1000);
Log.d(TAG, "doInBackground: client socket created");
// set up the stream reader and writer
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// send Client Request
String hello = isClient ? "HELLO I AM CLIENT" : "HELLO I AM SERVER";
sendLine(hello);
if (isClient) {
success = runClientProtocol(macAddress);
} else {
success = runServerProtocol(macAddress);
}
} catch (SocketTimeoutException ste) {
System.out.println("### Timed out after 1 seconds");
} catch (IOException e) {
Log.d("", e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return success;
}
@Override
protected String doInBackground(String... params) {
String isClientString = params[0];
if (isClientString.equals("True")) {
isClient = true;
}
String ipAddressString = params[1];
String macAddress = params[2];
boolean success = false;
while (!success){
success = runClient(ipAddressString, isClient, macAddress);
}
return null;
}
private void closeConnection() throws IOException {
socket.close();
}
private boolean runClientProtocol(String macAddress) throws IOException {
Gson gson = new Gson();
// WAIT FOR OFFER
client_state = NegotiationClientTask.State.WAIT_FOR_OFFER;
String offerString = getLine();
if (offerString == null) {
closeConnection();
return false;
}
// CHECK OFFER
client_state = NegotiationClientTask.State.CHECK_OFFER;
// Get offer
NegotiationOffer offer = gson.fromJson(offerString, NegotiationOffer.class);
// Write offer to the PeerStore
PeerStore.getInstance().setLatestOffer(macAddress, offer);
// ToDo: implement accept or deny logic
if (!true) {
client_state = NegotiationClientTask.State.ERROR;
writeError(1, "Offer not acceptable");
// ToDo: Error handling
return false;
}
// SEND NegotiationAnswer
NegotiationOfferAnswer answer = new NegotiationOfferAnswer(true, 10);
String answerString = gson.toJson(answer);
sendLine(answerString);
// WAIT FOR PASSWORD and hostname
client_state = NegotiationClientTask.State.WAIT_FOR_PASSWORD;
String finalizationString = getLine();
if (finalizationString == null) {
closeConnection();
return false;
}
NegotiationFinalization finalization = gson.fromJson(finalizationString, NegotiationFinalization.class);
// Write offer to the PeerStore
PeerStore.getInstance().setLatestFinalization(macAddress, finalization);
// Send OK
sendLine("OK from Client");
client_state = NegotiationClientTask.State.SUCCESS;
socket.close();
return true;
}
private boolean runServerProtocol(String macAddress) throws IOException {
// Json serializer
Gson gson = new GsonBuilder().create();
// CHECK_CLIENT_REQUEST
server_state = NegotiationServerTask.State.CHECK_CLIENT_REQUEST;
if (!true) {
writeError(0, "");
server_state = NegotiationServerTask.State.ERROR;
// ToDo: Error handling
}
// send offer
NegotiationOffer offer = new NegotiationOffer(1, 100, 0);
String offerString = gson.toJson(offer);
sendLine(offerString);
// WAIT_FOR_ANSWER
server_state = NegotiationServerTask.State.WAIT_FOR_ANSWER;
String answerString = getLine();
// Parse the answer
NegotiationOfferAnswer answer = gson.fromJson(answerString, NegotiationOfferAnswer.class);
PeerStore.getInstance().setLatestOfferAnswer(macAddress, answer);
// CHECK_ANSWER
server_state = NegotiationServerTask.State.CHECK_ANSWER;
if (!answer.isAgreeToConditions()) {
writeError(0, "Client does not agree to conditions");
server_state = NegotiationServerTask.State.ERROR;
return false;
// ToDo: Error handling
}
// CHECK_ITP
// server_state = NegotiationServerTask.State.CHECK_ITP;
// if (!true) {
// writeError(0, "");
// server_state = NegotiationServerTask.State.ERROR;
// // ToDo: Error handling
// }
// GENERATE_PASSWORD
server_state = NegotiationServerTask.State.GENERATE_PASSWORD;
String password = "123456789";
String hotspotName = "Iotify-123";
// send password and hotspot name
NegotiationFinalization finalization = new NegotiationFinalization(hotspotName, password,
"Address", 0, 0, "");
String finalizationString = gson.toJson(finalization);
sendLine(finalizationString);
// WAIT_FOR_OK
server_state = NegotiationServerTask.State.WAIT_FOR_OK;
String ok = getLine();
// CREATE_HOTSPOT
server_state = NegotiationServerTask.State.CREATE_HOTSPOT;
// now close the socket and leave
server_state = NegotiationServerTask.State.SUCCESS;
socket.close();
return true;
}
@Override
protected void onPostExecute(String result) {}
@Override
protected void onPreExecute() {}
@Override
protected void onProgressUpdate(Void... values) {}
public enum State {
INITIAL,
WAIT_FOR_OFFER,
CHECK_OFFER,
WAIT_FOR_PASSWORD,
SUCCESS,
ERROR;
}
}