fix #62
fix #61
This commit is contained in:
Daniel Pollithy 2018-01-25 01:02:06 +01:00
parent 6cb3842798
commit c22f758940
7 changed files with 263 additions and 97 deletions

101
README.md
View File

@ -1,52 +1,77 @@
# flashwifi
## What is this?
Share remaining data from your android phone as a hotspot and get paid in iota.
[WiFiota](https://tobywoerthle.github.io/flashWiFiSite/)
[WiFiota promotion website](https://tobywoerthle.github.io/flashWiFiSite/)
## ToDos
# How does it work?
Iota stuff: 2.5d
- [x] Address generation TOBY
- [ ] Address storage TOBY
- [x] Withdrawal and deposit for the internal wallet 0.75d TOBY
- [ ] Attach/close flash channel to tangle (deposit to root of tree) -> "api.sendTransfer" 0.75d DANIEL
- [x] UI 1.0d TOBY
## Iota setup
Flash channel: 1d WLAD
- [x] J2V8 interfaces… 1d WLAD
- [ ] overwrite flash object 0.25d WLAD
- [ ] close channel 0.25d WLAD
- [x] Create flash channel 0.75d WLAD
- [ ] integrate into repo 0.5d WLAD
The app creates a seed for every user and stores it with a password in SharedEncryptedPreferences.
There is a withdraw and deposit view which can be used to interact with the seed.
Billing protocol: 2d DANIEL
- [ ] general stuff 0.5d DANIEL
- [ ] integrate flash channel 0.5d DANIEL
- [ ] UI 1.0 d DANIEL
So far everything runs on a testnode but a live node can be set.
Network monitoring: 2d TOBY
- [ ] Client and server measure data usage TOBY
- [ ] Build sweet graph TOBY
## Discovery
WiFi direct discovery: 1d
- [ ] Negotiation protocol 0.5d DANIEL
- [ ] Password generation, open hotspot, close hotspot on timeout etc. 0.5d DANIEL
Happens with WiFi P2P. The consumer selects a peer manually so far (-> in the future automatic service discovery)
Two devices then open a wifi direct group and start the **Negotiation Protocol**
## Negotiation Protocol
The devices talk about each others, how much data they want to share or consume and
whether they could agree on a price and time.
* If so the future hotspot generates a random SSID like "Iotidy-<random number>".
* And generates a random number which is used as the password
* The hotspot sends it to the consumer and now they start the Billing Protocol
ToDo: Add full protocol
## Billing Protocol
The hotspot is created and the device proving the hotspot starts a new ServerSocket.
Once the consumer is connected to the hotspot he tries to connect to the gateway and
start the Billing Protocol.
* "Hello I am Client and I am in state NOT_PAIRED"
* "Hello, Client! I am Hotspot and I am in state NOT_PAIRED"
...
(ToDo: add full protocol)
### Payment
Every minute a bill is exchanged which contains information about used megabytes and durances.
A **IOTA FLASH CHANNEL** is established between the two (-> in the future more than two parties).
Every minute can be associated with a token transfer in the channel.
* Signing a transfer signifies agreement to the the bill
* The funding of the channel results in shared risk on both parties so they have no incentive to leave earlier
* Time guards track whether timing constraints weren't fulfilled (channel not funded, no peers...)
### End
Every bill can contain a "closeAfterwards" flag. Which ends the whole process with a short
exchange of data for the consumer.
The hotspot still has to attach the flash channel to the tangle.
# Good to know
The WiFi P2P roles in a WiFi group are not fixed. So each time either the future hotspot or consumer act as server and client.
We wrapped the iota.flash.js with additional javascript bridges and connect them to the **Jota - iota java lib**. The javascript code for the flash channel is executed within J2V8.
# Next big steps
* [ ] Implement an automatic Wifiota hotspot discovery
* [ ] Implement iota.flash.js in Java
* [ ] Build a hardware prototype for Wifiota hotspot (Raspy + data plan + battery)
* [ ] Extend the protocol to multiple parties, endless roaming and backoffice functions to close conflicts after physical contacts isn't possible anymore
Frontends: 6.5d
- [ ] Initial setup view (seed generation, set password): 0.5d DANIEL
<!-- - [ ] Pricing calculation view (input data plan and price => select Iota/Mb) 0.5d WLAD -->
- [ ] Settings (security, hotspot price per megabyte, client max price per megabyte, tangle attachment timeout, make new setup, change password) 1.5d TOBY
- [ ] Search hotspot: 0.5d DANIEL
- [x] Start hotspot: 0.5d DANIEL
- [x] Fund wallet: 1d TOBY
- [x] Withdraw from wallet (+QR code) 0.5 d TOBY
- [ ] Tethering status (-> fixed Notification with stop button) 1d WLAD
- [ ] UI bugs (back button) 1d
Other stuff 2.5d
- [ ] Videos: 2d WLAD + TOBY + DANIEL
- [ ] Website: 0.5d WLAD
Total: 17d

View File

@ -104,7 +104,7 @@ public class RoamingActivity extends AppCompatActivity {
apConnected.setChecked(true);
mService.resetBillingState();
// when the AP is setup we can start the server
startBillingProtocol();
startBillingProtocol(5000);
} else if (message.equals("AP FAILED")) {
apConnected.setChecked(false);
Toast.makeText(getApplicationContext(), "Could not create Access point", Toast.LENGTH_LONG).show();
@ -192,8 +192,15 @@ public class RoamingActivity extends AppCompatActivity {
}
private void startBillingProtocol() {
private void startBillingProtocol(int milliseconds_sleep) {
// setup the flash channel etc...
try {
Log.d(TAG, "startBillingProtocol: wait for some milliseconds");
Thread.sleep(milliseconds_sleep);
Log.d(TAG, "startBillingProtocol: now let's go");
} catch (InterruptedException e) {
e.printStackTrace();
}
if (mService.isInRoleHotspot()) {
mService.startBillingServer(address);
} else {

View File

@ -2,6 +2,7 @@ package com.flashwifi.wifip2p.accesspoint;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@ -58,29 +59,69 @@ public class ConnectTask extends AsyncTask<Object, Void, String> {
int netId = wifiManager.addNetwork(wifiConfig);
boolean connected = false;
int max_tries = 10;
while (!connected) {
while (!connected && max_tries > 0) {
max_tries--;
Log.d(TAG, "doInBackground: try to find the network");
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
WifiInfo wifiInfo;
for( WifiConfiguration i : list ) {
if(i.SSID != null && i.SSID.equals("\"" + ssid + "\"")) {
Log.d(TAG, "doInBackground: found it!!!");
wifiManager.disconnect();
wifiManager.disableNetwork(old_network_id);
wifiManager.reconnect();
boolean worked = wifiManager.enableNetwork(i.networkId, true);
if (worked) {
Log.d(TAG, "doInBackground: WORKED enableNetwork");
sendUpdateUIBroadcastWithMessage("AP SUCCESS");
connected = true;
boolean connected_to_it = false;
String new_ssid;
Log.d(TAG, "New network added!");
int max_seconds = 10;
boolean wrong_network = false;
while (!connected_to_it && max_seconds > 0 && !wrong_network) {
Log.d(TAG, "try to connect to hotspot");
wifiInfo = wifiManager.getConnectionInfo();
if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
new_ssid = wifiInfo.getSSID();
if (new_ssid.contains(ssid)) {
connected_to_it = true;
Log.d(TAG, "doInBackground: WORKED enableNetwork");
sendUpdateUIBroadcastWithMessage("AP SUCCESS");
} else {
Log.d(TAG, "WRONG NETWORK");
sendUpdateUIBroadcastWithMessage("AP FAILED");
wrong_network = true;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
max_seconds--;
if (max_seconds == 0) {
Log.d(TAG, "TRIED TOO LONG TO CONNECT TO HOTSPOT -> stop");
connected = false;
sendUpdateUIBroadcastWithMessage("AP FAILED");
}
}
} else {
Log.d(TAG, "doInBackground: Error connecting to the network");
sendUpdateUIBroadcastWithMessage("AP FAILED");
Log.d(TAG, "doInBackground: Let's try it again");
//sendUpdateUIBroadcastWithMessage("AP FAILED");
}
wifiManager.reconnect();
connected = true;
break;
}
}
if (max_tries == 0) {
Log.d(TAG, "doInBackground: Error connecting to the network");
Log.d(TAG, "doInBackground: THIS WAS THE LAST TRY");
sendUpdateUIBroadcastWithMessage("AP FAILED");
}
}
/*Log.d(TAG, "doInBackground: now wait");

View File

@ -3,6 +3,8 @@ package com.flashwifi.wifip2p.billing;
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.text.format.Formatter;
import android.util.Log;
import com.flashwifi.wifip2p.datastore.PeerInformation;
@ -21,9 +23,14 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import static android.content.Context.WIFI_SERVICE;
/**
* 1) This class keeps the socket connection alive.
@ -65,17 +72,24 @@ public class BillingClient {
public void start(String serverIPAddress) {
public void start(String serverIPAddress, InetAddress inetAddress) {
int error_count = 0;
while (state != State.CLOSED && state != State.ERROR) {
try {
// create client socket that connects to server
socket = new Socket(serverIPAddress, PORT);
Log.d(TAG, "try to connect to 192.168.43.1 PORT " + Integer.toString(PORT));
socket = new Socket("192.168.43.1", PORT);
socket.setSoTimeout(clientTimeoutMillis);
Log.d(TAG, "connection is established");
// wrap the socket
socketWrapper = new SocketWrapper(socket);
Log.d(TAG, "socket wrapped");
Log.d(TAG, "We are in state: " + state);
if (state == State.NOT_PAIRED) {
// send current state
@ -87,10 +101,11 @@ public class BillingClient {
// ask the hotspot to open the flash channel
// get the negotiated data
// get the necessary values
NegotiationOffer offer = PeerStore.getInstance().getLatestNegotiationOffer(mac);
NegotiationOfferAnswer answer = PeerStore.getInstance().getLatestNegotiationOfferAnswer(mac);
NegotiationFinalization finalization = PeerStore.getInstance().getLatestFinalization(mac);
// get the necessary values
// ToDo: replace magic number with setting
int totalMegabytes = 100;
int treeDepth = 8;
@ -179,6 +194,9 @@ public class BillingClient {
sendUpdateUIBroadcastWithMessage("IOException");
e.printStackTrace();
error_count++;
} catch (Exception e) {
e.printStackTrace();
error_count++;
} finally {
if (socket != null) {
try {

View File

@ -26,10 +26,12 @@ import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import static android.content.Context.WIFI_SERVICE;
@ -70,6 +72,8 @@ public class BillingServer {
this.context = context;
this.mac = mac;
Log.d(TAG, "BillingServer: MAC of other part: " + mac);
// get the negotiated data
NegotiationOffer offer = PeerStore.getInstance().getLatestNegotiationOffer(mac);
NegotiationOfferAnswer answer = PeerStore.getInstance().getLatestNegotiationOfferAnswer(mac);
@ -79,7 +83,7 @@ public class BillingServer {
int totalMegabytes = 100;
int treeDepth = 8;
this.digests = new String[]{"1234", "2345", "3456"};
int timeoutMinutesServer = 20 * 60 * 1000;
int timeoutMinutesServer = 2 * 60 * 1000;
this.hotspotRefundAddress = finalization.getHotspotRefundAddress();
this.channelRootAddress = finalization.getDepositAddressFlashChannel();
@ -102,7 +106,8 @@ public class BillingServer {
Log.d(TAG, "start: Billing server has been started");
// ToDo: receive end of roaming broadcast
int max_errors = 1;
int errors = 0;
while (state != State.CLOSED) {
try {
@ -238,10 +243,21 @@ public class BillingServer {
}
state = State.FULLY_ATTACHED;
}
} catch (SocketException e) {
e.printStackTrace();
sendUpdateUIBroadcastWithMessage("Socket exception");
errors++;
} catch (IOException e) {
e.printStackTrace();
sendUpdateUIBroadcastWithMessage("IOException");
errors++;
} catch (InterruptedException e) {
sendUpdateUIBroadcastWithMessage("InterruptedException");
e.printStackTrace();
errors++;
} catch (Exception e) {
e.printStackTrace();
errors++;
} finally {
try {
if (socketWrapper != null) {
@ -258,6 +274,11 @@ public class BillingServer {
}
}
if (errors >= max_errors) {
Log.d(TAG, "start: error count too high");
state = State.ERROR;
sendUpdateUIBroadcastWithMessage("Exit");
}
}
}

View File

@ -53,6 +53,7 @@ import org.apache.commons.lang3.ArrayUtils;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
@ -109,6 +110,7 @@ public class WiFiDirectBroadcastService extends Service {
boolean apRuns = false;
ConnectTask connectTask;
private boolean negotiatorRunning = false;
private String ownMacAddressStore = null;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@ -237,6 +239,7 @@ public class WiFiDirectBroadcastService extends Service {
byte[] myIPAddress = BigInteger.valueOf(dhcp.gateway).toByteArray();
ArrayUtils.reverse(myIPAddress);
InetAddress myInetIP = null;
Inet6Address myInet6IP = null;
String routerIP = null;
try {
myInetIP = InetAddress.getByAddress(myIPAddress);
@ -246,7 +249,7 @@ public class WiFiDirectBroadcastService extends Service {
routerIP = "192.168.43.1";
}
Log.d(TAG, "DHCP gateway: " + routerIP);
billingClient.start(routerIP);
billingClient.start(routerIP, myInetIP);
// ToDo: handle billingServer EXIT CODES
// -> close the roaming etc.
}
@ -294,32 +297,38 @@ public class WiFiDirectBroadcastService extends Service {
}
public String getWFDMacAddress(){
Log.d(TAG, "getWFDMacAddress: GET MAC ADRESS =========================");
if (ownMacAddressStore != null) {
return ownMacAddressStore;
}
try {
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface ntwInterface : interfaces) {
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);
}
Log.d(TAG, "getWFDMacAddress: " + strBuilder.toString());
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();
this.ownMacAddressStore = strBuilder.toString();
}
}
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
return null;
return this.ownMacAddressStore;
}
private void stopAllTasks() {
@ -374,6 +383,7 @@ public class WiFiDirectBroadcastService extends Service {
NegotiationFinalization negFin = PeerStore.getInstance().getLatestFinalization(peer_mac_address);
String ssid = negFin.getHotspotName();
String key = negFin.getHotspotPassword();
Log.d(TAG, "YYY: " + peer_mac_address);
sendStartRoamingBroadcast(peer_mac_address, ssid, key);
} else if (peer_mac_address != null) {
PeerStore.getInstance().unselectAll();
@ -443,6 +453,7 @@ public class WiFiDirectBroadcastService extends Service {
NegotiationFinalization negFin = PeerStore.getInstance().getLatestFinalization(peer_mac_address);
String ssid = negFin.getHotspotName();
String key = negFin.getHotspotPassword();
Log.d(TAG, "ZZZ: " + peer_mac_address);
sendStartRoamingBroadcast(peer_mac_address, ssid, key);
} else {
Log.d(TAG, "run: could not start roaming");
@ -585,13 +596,21 @@ public class WiFiDirectBroadcastService extends Service {
NegotiationOffer offer = PeerStore.getInstance().getLatestNegotiationOffer(address);
NegotiationOfferAnswer offerAnser = PeerStore.getInstance().getLatestNegotiationOfferAnswer(address);
NegotiationFinalization finalization = PeerStore.getInstance().getLatestFinalization(address);
BillingOpenChannel openChannel = PeerStore.getInstance().getPeer(address).getBillingOpenChannel();
BillingOpenChannelAnswer openChannelAnswer = PeerStore.getInstance().getPeer(address).getBillingOpenChannelAnswer();
BillingOpenChannel openChannel = PeerStore.getInstance().getLatestBillingOpenChannel(address);
BillingOpenChannelAnswer openChannelAnswer = PeerStore.getInstance().getLatestBillingOpenChannelAnswer(address);
String multisigAddress = finalization.getDepositAddressFlashChannel();
int timeoutClientSeconds, timeoutHotspotSeconds;
int timeoutClientSeconds = openChannel.getTimeoutMinutesClient();
int timeoutHotspotSeconds = openChannelAnswer.getTimeoutMinutesHotspot() * 60;
// ToDo: Fix this bug!
// openChannel should not be null here
if (openChannel != null) {
timeoutClientSeconds = openChannel.getTimeoutMinutesClient();
timeoutHotspotSeconds = openChannelAnswer.getTimeoutMinutesHotspot() * 60;
} else {
timeoutClientSeconds = 3;
timeoutHotspotSeconds = 3 * 60;
}
int timeout = (isInRoleHotspot()) ? timeoutHotspotSeconds : timeoutClientSeconds;
int clientDeposit = finalization.getDepositClientFlashChannelInIota();

View File

@ -1,5 +1,7 @@
package com.flashwifi.wifip2p.datastore;
import android.util.Log;
import com.flashwifi.wifip2p.protocol.BillingCloseChannel;
import com.flashwifi.wifip2p.protocol.BillingCloseChannelAnswer;
import com.flashwifi.wifip2p.protocol.BillingOpenChannel;
@ -22,7 +24,20 @@ public class PeerStore {
private HashMap<String, PeerInformation> peers = new HashMap<String, PeerInformation>();
public static PeerStore getInstance() {
private NegotiationOffer storedNegotiationOffer = null;
private NegotiationOfferAnswer storedNegotiationOfferAnswer = null;
private NegotiationFinalization storedNegotiationFinalization = null;
private BillingOpenChannel storedBillingOpenChannel = null;
private BillingOpenChannelAnswer storedBillingOpenChannelAnswer = null;
private boolean debug = true;
private String lastMAC = null;
public static synchronized PeerStore getInstance() {
return ourInstance;
}
@ -30,7 +45,7 @@ public class PeerStore {
// ToDo: load and store stuff in SQLite or gson JSON
}
public void clear() {
public synchronized void clear() {
peers.clear();
}
@ -39,7 +54,7 @@ public class PeerStore {
*
* @return was the peer created?
*/
public boolean updateOrCreate(PeerInformation peer) {
public synchronized boolean updateOrCreate(PeerInformation peer) {
String macAddress = peer.getWifiP2pDevice().deviceAddress;
boolean exists = peers.containsKey(macAddress);
@ -55,7 +70,7 @@ public class PeerStore {
return !exists;
}
public ArrayList<PeerInformation> getPeerArrayList() {
public synchronized ArrayList<PeerInformation> getPeerArrayList() {
ArrayList<PeerInformation> ary = new ArrayList<>(peers.values());
Collections.sort(ary, new Comparator<PeerInformation>() {
@Override
@ -70,13 +85,13 @@ public class PeerStore {
/**
* This sets an old flag to all the peers
*/
public void makeNewGeneration() {
public synchronized void makeNewGeneration() {
for (PeerInformation peer : peers.values()) {
peer.incrementAge();
}
}
private PeerInformation getOrCreatePeer(String address_) {
private synchronized PeerInformation getOrCreatePeer(String address_) {
address_ = address_.toLowerCase();
if (peers.containsKey(address_)) {
return peers.get(address_);
@ -87,74 +102,94 @@ public class PeerStore {
return temp;
}
public void setLatestOffer(String macAddress, NegotiationOffer offer) {
public synchronized void setLatestOffer(String macAddress, NegotiationOffer offer) {
storedNegotiationOffer = offer;
getOrCreatePeer(macAddress.toLowerCase()).setLatestOffer(offer);
}
public void setErrorMessage(String macAddress, String msg) {
public synchronized void setErrorMessage(String macAddress, String msg) {
getOrCreatePeer(macAddress.toLowerCase()).setErrorMessage(msg);
}
public void setSelected(String macAddress, boolean selected) {
public synchronized void setSelected(String macAddress, boolean selected) {
getOrCreatePeer(macAddress.toLowerCase()).setSelected(selected);
}
public void unselectAll() {
public synchronized void unselectAll() {
for (PeerInformation p: peers.values()) {
p.setSelected(false);
}
}
public void setLatestOfferAnswer(String macAddress, NegotiationOfferAnswer answer) {
public synchronized void setLatestOfferAnswer(String macAddress, NegotiationOfferAnswer answer) {
storedNegotiationOfferAnswer = answer;
getOrCreatePeer(macAddress.toLowerCase()).setLatestOfferAnswer(answer);
}
public void setLatestFinalization(String macAddress, NegotiationFinalization finalization) {
public synchronized void setLatestFinalization(String macAddress, NegotiationFinalization finalization) {
lastMAC = macAddress;
storedNegotiationFinalization = finalization;
getOrCreatePeer(macAddress.toLowerCase()).setLatestFinalization(finalization);
}
public NegotiationFinalization getLatestFinalization(String macAddress) {
public synchronized NegotiationFinalization getLatestFinalization(String macAddress) {
if (peers.containsKey(macAddress.toLowerCase())) {
return peers.get(macAddress.toLowerCase()).getLatestFinalization();
}
return null;
return storedNegotiationFinalization;
}
public NegotiationOffer getLatestNegotiationOffer(String macAddress) {
public synchronized NegotiationOffer getLatestNegotiationOffer(String macAddress) {
if (peers.containsKey(macAddress.toLowerCase())) {
return peers.get(macAddress.toLowerCase()).getLatestNegotiationOffer();
}
return null;
return storedNegotiationOffer;
}
public NegotiationOfferAnswer getLatestNegotiationOfferAnswer(String macAddress) {
public synchronized NegotiationOfferAnswer getLatestNegotiationOfferAnswer(String macAddress) {
if (peers.containsKey(macAddress.toLowerCase())) {
return peers.get(macAddress.toLowerCase()).getLatestOfferAnswer();
}
return null;
return storedNegotiationOfferAnswer;
}
public void setIPAddress(String macAddress, InetAddress IPAddress) {
public synchronized void setIPAddress(String macAddress, InetAddress IPAddress) {
getOrCreatePeer(macAddress.toLowerCase()).setIPAddress(IPAddress.getHostAddress());
}
public void setLatestBillingOpenChannel(String macAddress, BillingOpenChannel o) {
public synchronized void setLatestBillingOpenChannel(String macAddress, BillingOpenChannel o) {
storedBillingOpenChannel = o;
getOrCreatePeer(macAddress.toLowerCase()).setBillingOpenChannel(o);
}
public void setLatestBillingOpenChannelAnswer(String macAddress, BillingOpenChannelAnswer o) {
public synchronized void setLatestBillingOpenChannelAnswer(String macAddress, BillingOpenChannelAnswer o) {
storedBillingOpenChannelAnswer = o;
getOrCreatePeer(macAddress.toLowerCase()).setBillingOpenChannelAnswer(o);
}
public void setLatestBillingCloseChannel(String macAddress, BillingCloseChannel o) {
public synchronized BillingOpenChannel getLatestBillingOpenChannel(String macAddress) {
if (peers.containsKey(macAddress.toLowerCase())) {
return peers.get(macAddress.toLowerCase()).getBillingOpenChannel();
}
return storedBillingOpenChannel;
}
public synchronized BillingOpenChannelAnswer getLatestBillingOpenChannelAnswer(String macAddress) {
if (peers.containsKey(macAddress.toLowerCase())) {
return peers.get(macAddress.toLowerCase()).getBillingOpenChannelAnswer();
}
return storedBillingOpenChannelAnswer;
}
public synchronized void setLatestBillingCloseChannel(String macAddress, BillingCloseChannel o) {
getOrCreatePeer(macAddress.toLowerCase()).setBillingCloseChannel(o);
}
public void setLatestBillingCloseChannelAnswer(String macAddress, BillingCloseChannelAnswer o) {
public synchronized void setLatestBillingCloseChannelAnswer(String macAddress, BillingCloseChannelAnswer o) {
getOrCreatePeer(macAddress.toLowerCase()).setBillingCloseChannelAnswer(o);
}
public PeerInformation getPeer(String address) {
public synchronized PeerInformation getPeer(String address) {
address = address.toLowerCase();
if (peers.containsKey(address)) {
return peers.get(address);