This commit is contained in:
Toby Woerthle 2018-01-07 14:06:56 -05:00
commit 01646644d1
22 changed files with 459 additions and 906 deletions

7
Daniel.txt Normal file
View File

@ -0,0 +1,7 @@
- add toggle button to action bar
- forget networks after discovery
- stop discovery after successful negotiation
- display states in frontend
- p2p discovery active -> stop button
- negotiation sockets active -> stop button
- refactor NegotiationClientTask and NegotiationServerTask ( -> common code base)

View File

@ -34,12 +34,8 @@
android:parentActivityName=".DesktopActivity" />
<service
android:name=".WiFiDirectBroadcastService"
android:name=".broadcast.WiFiDirectBroadcastService"
android:description="@string/wifi_direct" />
<service
android:name=".MessengerService"
android:process=":remote" />
<service android:name=".AccessPointService" />
<activity android:name=".DesktopActivity" />

View File

@ -12,10 +12,8 @@ import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
@ -27,6 +25,8 @@ import android.widget.Toast;
import java.net.InetAddress;
import java.util.ArrayList;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
public class ChatActivity extends AppCompatActivity {
@ -38,7 +38,7 @@ public class ChatActivity extends AppCompatActivity {
String address;
WiFiDirectBroadcastService mService;
AccessPointService apService;
//AccessPointService apService;
boolean mBound = false;
InetAddress groupOwnerAddress;
@ -65,8 +65,8 @@ public class ChatActivity extends AppCompatActivity {
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
// Bind to
Intent intent2 = new Intent(this, AccessPointService.class);
bindService(intent2, apConnection, Context.BIND_AUTO_CREATE);
//Intent intent2 = new Intent(this, AccessPointService.class);
//bindService(intent2, apConnection, Context.BIND_AUTO_CREATE);
}
private void updateUi(Intent intent) {
@ -132,7 +132,7 @@ public class ChatActivity extends AppCompatActivity {
public void onClick(final View view) {
addMessageRight(name, input.getText().toString());
// send the message to the peer
mService.sendMessageToSocketServer(groupOwnerAddress, input.getText().toString());
//mService.sendMessageToSocketServer(groupOwnerAddress, input.getText().toString());
}
});
@ -160,17 +160,17 @@ public class ChatActivity extends AppCompatActivity {
}
private void startHotspot() {
apService.startAP();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setImageResource(R.drawable.icon_tethering_on);
hotspot_running = true;
//apService.startAP();
//FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
//fab.setImageResource(R.drawable.icon_tethering_on);
//hotspot_running = true;
}
private void stopHotspot() {
apService.stopAP();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setImageResource(R.drawable.icon_tethering_off);
hotspot_running = false;
//apService.stopAP();
//FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
//fab.setImageResource(R.drawable.icon_tethering_off);
//hotspot_running = false;
}
public void addMessageLeft(String name, String text) {
@ -207,24 +207,4 @@ public class ChatActivity extends AppCompatActivity {
}
};
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection apConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
AccessPointService.LocalBinder binder = (AccessPointService.LocalBinder) service;
apService = binder.getService();
//apBound = true;
// start connection
connectToPeer(address);
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

View File

@ -1,57 +0,0 @@
package com.flashwifi.wifip2p;
import android.os.AsyncTask;
import android.util.Log;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
public class ClientTask extends AsyncTask<String, Void, String> {
private final static String TAG = "ClientTask";
@Override
protected String doInBackground(String... params) {
String host = params[0];
String message = params[1];
int port = 9999;
Socket socket = new Socket();
Log.d(TAG, "connectToSocketServer: socket created");
byte buf[] = new byte[1024];
try {
socket.bind(null);
Log.d(TAG, "connectToSocketServer: socket bind");
socket.connect((new InetSocketAddress(host, port)), 500);
Log.d(TAG, "connectToSocketServer: socket connected");
DataOutputStream DOS = new DataOutputStream(socket.getOutputStream());
DOS.writeUTF(message);
Log.d(TAG, "connectToSocketServer: utf written");
socket.close();
} catch (IOException e) {
//catch logic
Log.d(TAG, "connectToSocketServer: io exception");
} finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
//catch logic
}
}
}
}
return null;
}
@Override
protected void onPostExecute(String result) {}
@Override
protected void onPreExecute() {}
@Override
protected void onProgressUpdate(Void... values) {}
}

View File

@ -9,37 +9,22 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ToggleButton;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import jota.IotaAPI;
import jota.dto.response.GetNodeInfoResponse;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
public class HotspotFragment extends Fragment {

View File

@ -1,134 +0,0 @@
package com.flashwifi.wifip2p;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.Toast;
import java.util.ArrayList;
public class MessengerService extends Service {
/** For showing and hiding our notification. */
NotificationManager mNM;
/** Keeps track of all current registered clients. */
static ArrayList<Messenger> mClients = new ArrayList<Messenger>();
/** Holds last value set by a client. */
static int mValue = 0;
/**
* Command to the service to register a client, receiving callbacks
* from the service. The Message's replyTo field must be a Messenger of
* the client where callbacks should be sent.
*/
static final int MSG_REGISTER_CLIENT = 1;
/**
* Command to the service to unregister a client, ot stop receiving callbacks
* from the service. The Message's replyTo field must be a Messenger of
* the client as previously given with MSG_REGISTER_CLIENT.
*/
static final int MSG_UNREGISTER_CLIENT = 2;
/**
* Command to service to set a new value. This can be sent to the
* service to supply a new value, and will be sent by the service to
* any registered clients with the new value.
*/
static final int MSG_SET_VALUE = 3;
/**
* Handler of incoming messages from clients.
*/
static class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_VALUE:
mValue = msg.arg1;
for (int i=mClients.size()-1; i>=0; i--) {
try {
mClients.get(i).send(Message.obtain(null,
MSG_SET_VALUE, mValue, 0));
} catch (RemoteException e) {
// The client is dead. Remove it from the list;
// we are going through the list from back to front
// so this is safe to do inside the loop.
mClients.remove(i);
}
}
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Display a notification about us starting.
showNotification();
}
@Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel(R.string.remote_service_started);
// Tell the user we stopped.
Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
}
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
/**
* Show a notification while this service is running.
*/
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.remote_service_started);
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, ChatActivity.class), 0);
// Set the info for the views that show in the notification panel.
Notification notification = new Notification.Builder(this)
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.local_service_label)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
// Send the notification.
// We use a string id because it is a unique number. We use it later to cancel.
mNM.notify(R.string.remote_service_started, notification);
}
}

View File

@ -1,273 +0,0 @@
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;
}
}

View File

@ -1,311 +0,0 @@
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.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class NegotiationServerTask extends AsyncTask<String, Void, String> {
private static final String TAG = "NegServerTask";
private boolean running = true;
private ServerSocket serverSocket;
private Socket socket;
private State server_state;
private NegotiationClientTask.State client_state;
private boolean isClient = false;
BufferedReader in;
PrintWriter out;
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);
}
public void writeError(int code, String msg) {
sendLine(String.format("err_code: %s msg: %s", Integer.toString(code), msg));
}
private boolean runServer(boolean isClient, String macAddress) {
boolean success = false;
try {
serverSocket = new ServerSocket(9898);
// set the timeout for the negotiation protocol to 1 second
// ToDo: make this a variable
int timeout = 1000;
serverSocket.setSoTimeout(timeout);
server_state = State.INITIAL;
Log.d(TAG, "doInBackground: Server is waiting for connection");
socket = serverSocket.accept();
socket.setSoTimeout(timeout);
// get ip and port of client
InetAddress addr = socket.getInetAddress();
int port = socket.getPort();
// ToDo: clear this problem
macAddress = addr.getHostAddress();
// set up the stream reader and writer
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// WAIT FOR CLIENT
server_state = State.WAIT_FOR_CLIENT;
String hello = getLine();
// Check: Is the peer in the same role as we are?
// server and server or client and client MAKES NO SENSE
// we have to check this because we can't control it
if (hello.contains("SERVER") && !isClient || hello.contains("CLIENT") && isClient) {
Log.d(TAG, "doInBackground: Pairing roles are broken.");
server_state = State.ERROR;
socket.close();
return false;
}
// If we are the server
if (!isClient) {
success = runServerProtocol(macAddress);
} else {
// we are the client
success = runClientProtocol(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();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return success;
}
@Override
protected String doInBackground(String... params) {
String return_string = null;
String isClientString = params[0];
if (isClientString.equals("True")) {
isClient = true;
}
String macAddress = params[1];
boolean success = false;
while (!success) {
success = runServer(isClient, macAddress);
}
return return_string;
}
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_CLIENT,
CHECK_CLIENT_REQUEST,
WAIT_FOR_ANSWER,
CHECK_ANSWER,
CHECK_ITP,
GENERATE_PASSWORD,
WAIT_FOR_OK,
CREATE_HOTSPOT,
SUCCESS,
ERROR;
}
}

View File

@ -11,11 +11,7 @@ import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
@ -33,6 +29,8 @@ import com.flashwifi.wifip2p.datastore.PeerStore;
import java.net.InetAddress;
import java.util.ArrayList;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
/**
* Fragment that appears in the "content_frame", shows a planet
*/
@ -222,10 +220,10 @@ public class SearchFragment extends Fragment {
startNegotiationProtocol(address);
Intent intent = new Intent(getActivity(), ChatActivity.class);
/*Intent intent = new Intent(getActivity(), ChatActivity.class);
intent.putExtra("address", address);
intent.putExtra("name", name);
startActivity(intent);
startActivity(intent);*/
}
public void onRefreshButtonClick() {

View File

@ -1,46 +0,0 @@
package com.flashwifi.wifip2p;
import android.os.AsyncTask;
import android.util.Log;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerTask extends AsyncTask<String, Void, String> {
private boolean running = true;
@Override
protected String doInBackground(String... params) {
try {
String msg_received = null;
while (running) {
ServerSocket serverSocket = new ServerSocket(9999);
Socket client = serverSocket.accept();
Log.d("ServerTask", "doInBackground: openend");
DataInputStream DIS = new DataInputStream(client.getInputStream());
msg_received = DIS.readUTF();
Log.d(">>>>>", msg_received);
serverSocket.close();
}
return msg_received;
} catch (IOException e) {
Log.d("", e.getMessage());
return null;
}
}
@Override
protected void onPostExecute(String result) {}
@Override
protected void onPreExecute() {}
@Override
protected void onProgressUpdate(Void... values) {}
}

View File

@ -1,9 +1,7 @@
package com.flashwifi.wifip2p;
package com.flashwifi.wifip2p.accesspoint;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

View File

@ -1,4 +1,4 @@
package com.flashwifi.wifip2p;
package com.flashwifi.wifip2p.accesspoint;
import android.content.Context;
import android.net.wifi.WifiConfiguration;

View File

@ -1,4 +1,4 @@
package com.flashwifi.wifip2p;
package com.flashwifi.wifip2p.broadcast;
import android.content.BroadcastReceiver;
import android.content.Context;

View File

@ -1,7 +1,4 @@
package com.flashwifi.wifip2p;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
package com.flashwifi.wifip2p.broadcast;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -15,9 +12,9 @@ import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Binder;
import android.os.IBinder;
import android.support.design.widget.Snackbar;
import android.util.Log;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.ArrayList;
@ -28,8 +25,6 @@ public class WiFiDirectBroadcastService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
private boolean setup = false;
@ -47,7 +42,6 @@ public class WiFiDirectBroadcastService extends Service {
ArrayList<String> receivedMessages = new ArrayList<>();
// socket stuff
NegotiationServerTask negotiationServerTask;
boolean serverRuns;
private String currentDeviceConnected = null;
@ -60,18 +54,16 @@ public class WiFiDirectBroadcastService extends Service {
//negotiationServerTask = new NegotiationServerTask();
//negotiationServerTask.execute();
String isClientString = (isClient) ? "True" : "False";
new NegotiationServerTask().execute(isClientString, macAddress);
// ToDo: rewire this
// new NegotiationServerTask().execute(isClientString, macAddress);
}
public void startNegotiationClient(InetAddress address, boolean isClient, String macAddress) {
Log.d("", "startSocketClient: ");
String isClientString = (isClient) ? "True" : "False";
String ipaddr = address.getHostAddress();
new NegotiationClientTask().execute(isClientString, ipaddr, macAddress);
}
public void sendMessageToSocketServer(InetAddress address, String message) {
new ClientTask().execute(address.getHostAddress(), message);
// ToDo: use the Negotiator here
// new NegotiationClientTask().execute(isClientString, ipaddr, macAddress);
}
public WifiP2pInfo getP2p_info() {
@ -136,7 +128,7 @@ public class WiFiDirectBroadcastService extends Service {
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
WiFiDirectBroadcastService getService() {
public WiFiDirectBroadcastService getService() {
// Return this instance of LocalService so clients can call public methods
return WiFiDirectBroadcastService.this;
}

View File

@ -65,7 +65,15 @@ public class PeerInformation {
this.latestFinalization = latestFinalization;
}
public String getIpAddress() {
return ipAddress;
}
public NegotiationFinalization getLatestFinalization() {
return latestFinalization;
}
public void setIPAddress(String IPAddress) {
this.ipAddress = IPAddress;
}
}

View File

@ -1,6 +1,7 @@
package com.flashwifi.wifip2p.datastore;
import android.content.Context;
import android.net.wifi.p2p.WifiP2pDevice;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -8,6 +9,7 @@ import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.flashwifi.wifip2p.R;
import com.flashwifi.wifip2p.protocol.NegotiationOffer;
import java.util.List;
@ -38,15 +40,30 @@ public class PeerListAdapter extends ArrayAdapter<PeerInformation> {
TextView tt1 = (TextView) v.findViewById(R.id.deviceName);
TextView tt2 = (TextView) v.findViewById(R.id.categoryId);
TextView tt3 = (TextView) v.findViewById(R.id.description);
TextView tt4 = (TextView) v.findViewById(R.id.ipAddr);
TextView tt5 = (TextView) v.findViewById(R.id.iotaPrice);
if (tt1 != null) {
tt1.setText(p.getWifiP2pDevice().deviceName);
WifiP2pDevice device = p.getWifiP2pDevice();
if (device != null) {
if (tt1 != null) {
tt1.setText(p.getWifiP2pDevice().deviceName);
}
if (tt2 != null) {
tt2.setText(p.getWifiP2pDevice().deviceAddress);
}
}
if (tt2 != null) {
tt2.setText(p.getWifiP2pDevice().deviceAddress);
NegotiationOffer offer = p.getLatestNegotiationOffer();
if (offer != null) {
tt5.setText(Integer.toString(offer.getIotaPerMegabyte()));
}
if (p.getIpAddress() != null) {
tt4.setText(p.getIpAddress());
}
if (tt3 != null)
tt3.setText(String.format("%s", Integer.toString(p.getAge())));
}

View File

@ -91,4 +91,8 @@ public class PeerStore {
public void setLatestFinalization(String macAddress, NegotiationFinalization finalization) {
getOrCreatePeer(macAddress).setLatestFinalization(finalization);
}
public void setIPAddress(String macAddress, InetAddress IPAddress) {
getOrCreatePeer(macAddress).setIPAddress(IPAddress.getHostAddress());
}
}

View File

@ -0,0 +1,292 @@
package com.flashwifi.wifip2p.negotiation;
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.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Negotiator {
private static final String TAG = "Negotiator";
private static final int PORT = 9898;
private static final int timeoutMillis = 1000;
private SocketWrapper socketWrapper;
private HotspotState hotspot_state;
private ConsumerState consumer_state;
// client as in client-server
private boolean isClient;
// consumer as in consumer-hotspot
private boolean isConsumer;
private Gson gson;
public enum ConsumerState {
INITIAL,
WAIT_FOR_OFFER,
CHECK_OFFER,
WAIT_FOR_PASSWORD,
SUCCESS,
ERROR
}
public enum HotspotState {
INITIAL,
WAIT_FOR_CLIENT,
CHECK_CLIENT_REQUEST,
WAIT_FOR_ANSWER,
CHECK_ANSWER,
CHECK_ITP,
GENERATE_PASSWORD,
WAIT_FOR_OK,
CREATE_HOTSPOT,
SUCCESS,
ERROR
}
public Negotiator(boolean isConsumer) {
this.isConsumer = isConsumer;
gson = new GsonBuilder().create();
}
public boolean workAsClient(String serverIPAddress) {
this.isClient = true;
boolean success = false;
Socket socket = null;
try {
// create client socket that connects to server
socket = new Socket(serverIPAddress, PORT);
socket.setSoTimeout(timeoutMillis);
Log.d(TAG, "workAsClient: client socket created");
// wrap the socket
socketWrapper = new SocketWrapper(socket);
// send Client Request
String hello = isConsumer ? "HELLO I AM CLIENT" : "HELLO I AM SERVER";
socketWrapper.sendLine(hello);
// Whether we want to provide a hotspot or use one
if (isConsumer) {
success = runConsumerProtocol(serverIPAddress);
} else {
success = runHotspotProtocol(serverIPAddress);
}
} catch (SocketTimeoutException ste) {
Log.d(TAG, "workAsServer: ### 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;
}
public boolean workAsServer() {
// this device is the socket server
this.isClient = false;
boolean success = false;
ServerSocket serverSocket = null;
Socket socket = null;
try {
// use the port to start
serverSocket = new ServerSocket(PORT);
serverSocket.setSoTimeout(timeoutMillis);
Log.d(TAG, "doInBackground: Server is waiting for connection");
// accept one connection
socket = serverSocket.accept();
socket.setSoTimeout(timeoutMillis);
// wrap the socket
socketWrapper = new SocketWrapper(socket);
// WAIT FOR CLIENT
String hello = socketWrapper.getLine();
// Check: Is the peer in the same role as we are
// server and server or client and client MAKES NO SENSE
if (hello.contains("SERVER") && !isClient || hello.contains("CLIENT") && isClient) {
error(1, "Pairing roles are broken");
return false;
}
// Whether we want to provide a hotspot or use one
if (isConsumer) {
success = runConsumerProtocol(socketWrapper.getClientAddress().getHostAddress());
} else {
success = runHotspotProtocol(socketWrapper.getClientAddress().getHostAddress());
}
} catch (SocketTimeoutException ste) {
Log.d(TAG, "workAsServer: ### Timed out after 1 seconds");
} catch (IOException e) {
Log.d("", e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return success;
}
private boolean runConsumerProtocol(String ipAddress) throws IOException {
consumer_state = ConsumerState.WAIT_FOR_OFFER;
// RECEIVE OFFER
String offerString = socketWrapper.getLine();
if (offerString == null) {
error(2, "No offer received");
return false;
}
// CHECK OFFER
consumer_state = ConsumerState.CHECK_OFFER;
NegotiationOffer offer = gson.fromJson(offerString, NegotiationOffer.class);
// Write offer to the PeerStore
PeerStore.getInstance().setLatestOffer(ipAddress, offer);
// ToDo: implement accept or deny logic
if (!true) {
error(3, "Offer not acceptable");
return false;
}
// SEND NegotiationAnswer
// ToDo: where shall the input come from?
NegotiationOfferAnswer answer = new NegotiationOfferAnswer(true, 10);
String answerString = gson.toJson(answer);
socketWrapper.sendLine(answerString);
// WAIT FOR PASSWORD and hostname
consumer_state = ConsumerState.WAIT_FOR_PASSWORD;
String finalizationString = socketWrapper.getLine();
if (finalizationString == null) {
error(4, "No finalization received");
return false;
}
NegotiationFinalization finalization = gson.fromJson(finalizationString, NegotiationFinalization.class);
// Write offer to the PeerStore
PeerStore.getInstance().setLatestFinalization(ipAddress, finalization);
// Send OK
socketWrapper.sendLine("OK from Client");
consumer_state = ConsumerState.SUCCESS;
// End
socketWrapper.close();
return true;
}
private boolean runHotspotProtocol(String ipAddress) throws IOException {
// CHECK_CLIENT_REQUEST
hotspot_state = HotspotState.CHECK_CLIENT_REQUEST;
// send offer
NegotiationOffer offer = new NegotiationOffer(1, 100, 0);
String offerString = gson.toJson(offer);
socketWrapper.sendLine(offerString);
// WAIT_FOR_ANSWER
hotspot_state = HotspotState.WAIT_FOR_ANSWER;
String answerString = socketWrapper.getLine();
// Parse the answer
NegotiationOfferAnswer answer = gson.fromJson(answerString, NegotiationOfferAnswer.class);
PeerStore.getInstance().setLatestOfferAnswer(ipAddress, answer);
// CHECK_ANSWER
hotspot_state = HotspotState.CHECK_ANSWER;
if (!answer.isAgreeToConditions()) {
error(5, "Client does not agree to conditions");
return false;
}
// CHECK_ITP
// server_state = NegotiationServerTask.State.CHECK_ITP;
// if (!true) {
// writeError(0, "");
// server_state = NegotiationServerTask.State.ERROR;
// // ToDo: Error handling
// }
// GENERATE_PASSWORD
// ToDo: Don't mock this
hotspot_state = HotspotState.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);
socketWrapper.sendLine(finalizationString);
// WAIT_FOR_OK
hotspot_state = HotspotState.WAIT_FOR_OK;
String ok = socketWrapper.getLine();
// CREATE_HOTSPOT
hotspot_state = HotspotState.CREATE_HOTSPOT;
// now close the socket and leave
hotspot_state = HotspotState.SUCCESS;
socketWrapper.close();
return true;
}
// ------------------------
// HELPER METHODS BELOW
// ------------------------
private void error(int code, String msg) throws IOException {
Log.d(TAG, "error: " + msg);
if (isConsumer) {
consumer_state = ConsumerState.ERROR;
} else {
hotspot_state = HotspotState.ERROR;
}
socketWrapper.close();
}
}

View File

@ -0,0 +1,48 @@
package com.flashwifi.wifip2p.negotiation;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class SocketWrapper {
private static final String TAG = "SocketWrapper";
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public SocketWrapper(Socket socket) throws IOException {
this.socket = socket;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
}
public String getLine() {
String response;
try {
response = in.readLine();
} catch (IOException ex) {
response = "Error: " + ex;
}
Log.d(TAG, "getLine: " + response);
return response;
}
public void sendLine(String line) {
out.println(line);
Log.d(TAG, "sendLine: " + line);
}
public void close() throws IOException {
socket.close();
}
public InetAddress getClientAddress() {
return socket.getInetAddress();
}
}

View File

@ -13,4 +13,20 @@ public class NegotiationOffer {
this.maxMinutes = maxMinutes;
this.iotaPerMegabyte = iotaPerMegabyte;
}
public String getType() {
return type;
}
public int getMinMinutes() {
return minMinutes;
}
public int getMaxMinutes() {
return maxMinutes;
}
public int getIotaPerMegabyte() {
return iotaPerMegabyte;
}
}

View File

@ -18,6 +18,17 @@
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.NoActionBar.PopupOverlay" />
<!-- <ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="right"
android:textOn="WiFi P2P"
android:textOff="WiFi P2P"
android:text="WiFi P2P"
android:visibility="invisible"
android:id="@+id/wifip2pToggle"/>-->
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />

View File

@ -39,5 +39,27 @@
android:text="description"
android:height="20sp" />
</TableRow>
<TableRow android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView android:textColor="#000000"
android:id="@+id/ipAddr"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="ipAddr"
android:layout_weight="1"
android:height="20sp" />
<TextView android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:textColor="#000000"
android:gravity="right"
android:id="@+id/iotaPrice"
android:text="iotaPrice"
android:height="20sp" />
</TableRow>
</TableLayout>