Improve P2P connectivity

This commit is contained in:
Daniel Pollithy 2018-01-08 00:49:52 +01:00
parent 01646644d1
commit eb7f131171
10 changed files with 207 additions and 56 deletions

View File

@ -103,22 +103,7 @@ public class ChatActivity extends AppCompatActivity {
private void connectToPeer(String address) {
if (mBound) {
mService.connect(address, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(getApplicationContext(), "Connected to peer", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reason) {
Toast.makeText(getApplicationContext(), "Error connecting to peer", Toast.LENGTH_SHORT).show();
}
});
} else {
Toast.makeText(getApplicationContext(), "Service not available", Toast.LENGTH_SHORT).show();
}
}
private void initUI() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

View File

@ -21,6 +21,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.flashwifi.wifip2p.datastore.PeerInformation;
import com.flashwifi.wifip2p.datastore.PeerListAdapter;
@ -45,6 +46,9 @@ public class SearchFragment extends Fragment {
ArrayList<String> arrayList;
PeerListAdapter peerListAdapter;
View view;
private boolean busy = false;
public SearchFragment() {
// Empty constructor required for fragment subclasses
@ -89,11 +93,15 @@ public class SearchFragment extends Fragment {
return f;
}
private void updateUi(Intent intent) {
private void updateList() {
peerListAdapter.notifyDataSetInvalidated();
peerListAdapter.clear();
peerListAdapter.addAll(PeerStore.getInstance().getPeerArrayList());
peerListAdapter.notifyDataSetChanged();
}
private void updateUi(Intent intent) {
updateList();
String what = intent.getStringExtra("what");
Log.d(">>>>>>>>>>>>", "updateUi: " + what);
@ -176,6 +184,8 @@ public class SearchFragment extends Fragment {
Intent intent = new Intent(getActivity(), WiFiDirectBroadcastService.class);
getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
view = getActivity().findViewById(R.id.main_view);
initUI();
}
@ -205,20 +215,39 @@ public class SearchFragment extends Fragment {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
PeerInformation peer = PeerStore.getInstance().getPeerArrayList().get(i);
if (!busy) {
busy = true;
PeerInformation peer = PeerStore.getInstance().getPeerArrayList().get(i);
String address = peer.getWifiP2pDevice().deviceAddress;
String name = peer.getWifiP2pDevice().deviceName;
peer.setSelected(true);
updateList();
startChat(address, name);
String address = peer.getWifiP2pDevice().deviceAddress;
String name = peer.getWifiP2pDevice().deviceName;
startChat(address, name);
} else {
Toast.makeText(view.getContext(), "Busy", Toast.LENGTH_SHORT).show();
}
}
});
}
public void startChat(String address, String name) {
// start the socket for the negotiation
startNegotiationProtocol(address);
public void startChat(final String address, String name) {
mService.connect(address, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(view.getContext(), "Connected to peer", Toast.LENGTH_SHORT).show();
// start the protocol
startNegotiationProtocol(address);
busy = false;
}
@Override
public void onFailure(int reason) {
Toast.makeText(view.getContext(), "Error connecting to peer", Toast.LENGTH_SHORT).show();
busy = false;
}
});
/*Intent intent = new Intent(getActivity(), ChatActivity.class);
intent.putExtra("address", address);
@ -227,7 +256,7 @@ public class SearchFragment extends Fragment {
}
public void onRefreshButtonClick() {
final View view = getActivity().findViewById(R.id.main_view);
if (mBound) {
mService.getPeerList(new WifiP2pManager.ActionListener() {
@Override

View File

@ -5,19 +5,28 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.p2p.WifiP2pConfig;
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.AsyncTask;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import com.flashwifi.wifip2p.WalletAddressAndBalanceChecker;
import com.flashwifi.wifip2p.negotiation.Negotiator;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class WiFiDirectBroadcastService extends Service {
@ -49,21 +58,74 @@ public class WiFiDirectBroadcastService extends Service {
// discovery mode
private boolean discoveryModeActive = false;
public void startNegotiationServer(boolean isClient, String macAddress) {
Log.d("", "startSocketServer: ");
//negotiationServerTask = new NegotiationServerTask();
//negotiationServerTask.execute();
String isClientString = (isClient) ? "True" : "False";
// ToDo: rewire this
// new NegotiationServerTask().execute(isClientString, macAddress);
public String getWFDMacAddress(){
try {
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface ntwInterface : interfaces) {
if (ntwInterface.getName().equalsIgnoreCase("p2p0")) {
byte[] byteMac = ntwInterface.getHardwareAddress();
if (byteMac==null){
return null;
}
StringBuilder strBuilder = new StringBuilder();
for (int i=0; i<byteMac.length; i++) {
strBuilder.append(String.format("%02X:", byteMac[i]));
}
if (strBuilder.length()>0){
strBuilder.deleteCharAt(strBuilder.length()-1);
}
return strBuilder.toString();
}
}
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
return null;
}
public void startNegotiationClient(InetAddress address, boolean isClient, String macAddress) {
Log.d("", "startSocketClient: ");
String isClientString = (isClient) ? "True" : "False";
String ipaddr = address.getHostAddress();
// ToDo: use the Negotiator here
// new NegotiationClientTask().execute(isClientString, ipaddr, macAddress);
public void startNegotiationServer(final boolean isClient, String macAddress) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
Negotiator negotiator = new Negotiator(isClient, getWFDMacAddress());
// ToDo: run as long as this group is connected
while (true) {
negotiator.workAsServer();
deletePersistentGroups();
sendUpdateUIBroadcast();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
public void startNegotiationClient(final InetAddress address, final boolean isClient, String macAddress) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
Negotiator negotiator = new Negotiator(isClient, getWFDMacAddress());
// ToDo: run as long as this group is connected
while (true) {
negotiator.workAsClient(address.getHostAddress());
deletePersistentGroups();
sendUpdateUIBroadcast();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
public WifiP2pInfo getP2p_info() {

View File

@ -16,6 +16,7 @@ public class PeerInformation {
private WifiP2pInfo p2pInfo;
private WifiP2pDevice wifiP2pDevice;
private Date lastUpdate;
private boolean selected;
// age stores how long it has been since the last signal from this peer
// it is not stored in seconds but in update cycles
@ -26,6 +27,7 @@ public class PeerInformation {
private NegotiationFinalization latestFinalization;
public PeerInformation() {
selected = false;
age = 0;
}
@ -76,4 +78,12 @@ public class PeerInformation {
public void setIPAddress(String IPAddress) {
this.ipAddress = IPAddress;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}

View File

@ -6,6 +6,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TableRow;
import android.widget.TextView;
import com.flashwifi.wifip2p.R;
@ -42,6 +43,15 @@ public class PeerListAdapter extends ArrayAdapter<PeerInformation> {
TextView tt3 = (TextView) v.findViewById(R.id.description);
TextView tt4 = (TextView) v.findViewById(R.id.ipAddr);
TextView tt5 = (TextView) v.findViewById(R.id.iotaPrice);
TableRow row = (TableRow) v.findViewById(R.id.talkingRow);
if (row != null) {
if (p.isSelected()) {
row.setVisibility(View.VISIBLE);
} else {
row.setVisibility(View.INVISIBLE);
}
}
WifiP2pDevice device = p.getWifiP2pDevice();
if (device != null) {
@ -69,6 +79,8 @@ public class PeerListAdapter extends ArrayAdapter<PeerInformation> {
}
return v;
}

View File

@ -37,16 +37,18 @@ public class PeerStore {
*/
public boolean updateOrCreate(PeerInformation peer) {
String macAddress = peer.getWifiP2pDevice().deviceAddress;
boolean created = peers.containsKey(macAddress);
boolean exists = peers.containsKey(macAddress);
if (!created) {
if (exists) {
// Temp store for the important values
peer.setSelected(peers.get(macAddress).isSelected());
}
// overwrite or insert
peers.put(macAddress, peer);
return created;
return !exists;
}
public ArrayList<PeerInformation> getPeerArrayList() {
@ -71,6 +73,7 @@ public class PeerStore {
}
private PeerInformation getOrCreatePeer(String address_) {
address_ = address_.toLowerCase();
if (peers.containsKey(address_)) {
return peers.get(address_);
}

View File

@ -19,7 +19,9 @@ 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 static final int clientTimeoutMillis = 100000;
private static final int serverTimeoutMillis = 100000;
private final String ownMacAddress;
private SocketWrapper socketWrapper;
@ -56,9 +58,11 @@ public class Negotiator {
ERROR
}
public Negotiator(boolean isConsumer) {
public Negotiator(boolean isConsumer, String ownMacAddress) {
this.isConsumer = isConsumer;
gson = new GsonBuilder().create();
this.ownMacAddress = ownMacAddress;
Log.d(TAG, "Negotiator: " + ownMacAddress);
}
public boolean workAsClient(String serverIPAddress) {
@ -70,14 +74,14 @@ public class Negotiator {
try {
// create client socket that connects to server
socket = new Socket(serverIPAddress, PORT);
socket.setSoTimeout(timeoutMillis);
socket.setSoTimeout(clientTimeoutMillis);
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";
String hello = isClient ? "HELLO I AM CLIENT" : "HELLO I AM SERVER";
socketWrapper.sendLine(hello);
// Whether we want to provide a hotspot or use one
@ -113,12 +117,12 @@ public class Negotiator {
try {
// use the port to start
serverSocket = new ServerSocket(PORT);
serverSocket.setSoTimeout(timeoutMillis);
//serverSocket.setSoTimeout(serverTimeoutMillis);
Log.d(TAG, "doInBackground: Server is waiting for connection");
// accept one connection
socket = serverSocket.accept();
socket.setSoTimeout(timeoutMillis);
//socket.setSoTimeout(serverTimeoutMillis);
// wrap the socket
socketWrapper = new SocketWrapper(socket);
@ -126,9 +130,14 @@ public class Negotiator {
// WAIT FOR CLIENT
String hello = socketWrapper.getLine();
if (hello == null) {
error(0, "no hello received");
return false;
}
// 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) {
if (hello.contains("SERVER") && !isClient || hello.contains("CLIENT") && isClient){
error(1, "Pairing roles are broken");
return false;
}
@ -176,8 +185,9 @@ public class Negotiator {
// CHECK OFFER
consumer_state = ConsumerState.CHECK_OFFER;
NegotiationOffer offer = gson.fromJson(offerString, NegotiationOffer.class);
String otherMac = offer.getHotspotMac();
// Write offer to the PeerStore
PeerStore.getInstance().setLatestOffer(ipAddress, offer);
PeerStore.getInstance().setLatestOffer(otherMac, offer);
// ToDo: implement accept or deny logic
if (!true) {
@ -187,7 +197,7 @@ public class Negotiator {
// SEND NegotiationAnswer
// ToDo: where shall the input come from?
NegotiationOfferAnswer answer = new NegotiationOfferAnswer(true, 10);
NegotiationOfferAnswer answer = new NegotiationOfferAnswer(true, 10, ownMacAddress);
String answerString = gson.toJson(answer);
socketWrapper.sendLine(answerString);
@ -202,7 +212,7 @@ public class Negotiator {
NegotiationFinalization finalization = gson.fromJson(finalizationString, NegotiationFinalization.class);
// Write offer to the PeerStore
PeerStore.getInstance().setLatestFinalization(ipAddress, finalization);
PeerStore.getInstance().setLatestFinalization(otherMac, finalization);
// Send OK
@ -220,7 +230,8 @@ public class Negotiator {
hotspot_state = HotspotState.CHECK_CLIENT_REQUEST;
// send offer
NegotiationOffer offer = new NegotiationOffer(1, 100, 0);
int iotaPerMegabyte = (int) (Math.random() * (1000 - 10)) + 10;
NegotiationOffer offer = new NegotiationOffer(1, 100, iotaPerMegabyte, ownMacAddress);
String offerString = gson.toJson(offer);
socketWrapper.sendLine(offerString);
@ -228,9 +239,15 @@ public class Negotiator {
hotspot_state = HotspotState.WAIT_FOR_ANSWER;
String answerString = socketWrapper.getLine();
if (answerString == null) {
error(8, "No answer received");
return false;
}
// Parse the answer
NegotiationOfferAnswer answer = gson.fromJson(answerString, NegotiationOfferAnswer.class);
PeerStore.getInstance().setLatestOfferAnswer(ipAddress, answer);
String otherMac = answer.getConsumerMac();
PeerStore.getInstance().setLatestOfferAnswer(otherMac, answer);
// CHECK_ANSWER
hotspot_state = HotspotState.CHECK_ANSWER;

View File

@ -6,12 +6,14 @@ public class NegotiationOffer {
private int minMinutes;
private int maxMinutes;
private int iotaPerMegabyte;
private String hotspotMac;
public NegotiationOffer(int minMinutes, int maxMinutes, int iotaPerMegabyte) {
public NegotiationOffer(int minMinutes, int maxMinutes, int iotaPerMegabyte, String hotspotMac) {
this.type = "offer";
this.minMinutes = minMinutes;
this.maxMinutes = maxMinutes;
this.iotaPerMegabyte = iotaPerMegabyte;
this.hotspotMac = hotspotMac;
}
public String getType() {
@ -29,4 +31,8 @@ public class NegotiationOffer {
public int getIotaPerMegabyte() {
return iotaPerMegabyte;
}
public String getHotspotMac() {
return hotspotMac;
}
}

View File

@ -5,11 +5,13 @@ public class NegotiationOfferAnswer {
private String type;
private boolean agreeToConditions;
private int duranceInMinutes;
private String consumerMac;
public NegotiationOfferAnswer(boolean agreeToConditions, int duranceInMinutes) {
public NegotiationOfferAnswer(boolean agreeToConditions, int duranceInMinutes, String consumerMac) {
this.type = "answerToOffer";
this.agreeToConditions = agreeToConditions;
this.duranceInMinutes = duranceInMinutes;
this.consumerMac = consumerMac;
}
public String getType() {
@ -23,4 +25,8 @@ public class NegotiationOfferAnswer {
public int getDuranceInMinutes() {
return duranceInMinutes;
}
public String getConsumerMac() {
return consumerMac;
}
}

View File

@ -61,5 +61,26 @@
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
android:id="@+id/talkingRow">
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="63dp"
android:layout_height="match_parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Stop Talking" />
</TableRow>
</TableLayout>