Var/val should be lower camel case.

This commit is contained in:
Felix Ableitner 2015-02-09 23:47:23 +01:00
parent 4ca13ed3d9
commit 32fd7638e0
31 changed files with 129 additions and 131 deletions

View File

@ -32,7 +32,7 @@ class AddressTest extends AndroidTestCase {
} }
assertEquals(a1, new Address(a1Binary)) assertEquals(a1, new Address(a1Binary))
assertEquals(a1Binary.deep, a1.Bytes.deep) assertEquals(a1Binary.deep, a1.bytes.deep)
} }
} }

View File

@ -29,7 +29,7 @@ class MessageHeaderTest extends AndroidTestCase {
val bytes = h.write(0) val bytes = h.write(0)
val header = MessageHeader.read(bytes) val header = MessageHeader.read(bytes)
assertEquals(h, header) assertEquals(h, header)
assertEquals(bytes.length, header.Length) assertEquals(bytes.length, header.length)
} }
} }

View File

@ -11,7 +11,7 @@ class ResultAddContactTest extends AndroidTestCase {
val rac = new ResultAddContact(a) val rac = new ResultAddContact(a)
val bytes = rac.write val bytes = rac.write
val read = ResultAddContact.read(bytes) val read = ResultAddContact.read(bytes)
assertEquals(a, read.Accepted) assertEquals(a, read.accepted)
} }
} }

View File

@ -40,20 +40,20 @@ class DatabaseTest extends AndroidTestCase {
} }
def testMessageCount(): Unit = { def testMessageCount(): Unit = {
val msg1 = database.getMessages(m1.Header.Origin, 1) val msg1 = database.getMessages(m1.Header.origin, 1)
assertEquals(1, msg1.size) assertEquals(1, msg1.size)
val msg2 = database.getMessages(m1.Header.Origin, 3) val msg2 = database.getMessages(m1.Header.origin, 3)
assertEquals(2, msg2.size) assertEquals(2, msg2.size)
} }
def testMessageOrder(): Unit = { def testMessageOrder(): Unit = {
val msg = database.getMessages(m1.Header.Target, 1) val msg = database.getMessages(m1.Header.target, 1)
assertTrue(msg.contains(m3)) assertTrue(msg.contains(m3))
} }
def testMessageSelect(): Unit = { def testMessageSelect(): Unit = {
val msg = database.getMessages(m1.Header.Target, 2) val msg = database.getMessages(m1.Header.target, 2)
assertTrue(msg.contains(m1)) assertTrue(msg.contains(m1))
assertTrue(msg.contains(m3)) assertTrue(msg.contains(m3))
} }
@ -62,7 +62,7 @@ class DatabaseTest extends AndroidTestCase {
database.addContact(UserTest.u1) database.addContact(UserTest.u1)
val contacts = database.getContacts val contacts = database.getContacts
assertEquals(1, contacts.size) assertEquals(1, contacts.size)
assertEquals(Some(UserTest.u1), database.getContact(UserTest.u1.Address)) assertEquals(Some(UserTest.u1), database.getContact(UserTest.u1.address))
} }
def testAddContactCallback(): Unit = { def testAddContactCallback(): Unit = {
@ -76,8 +76,8 @@ class DatabaseTest extends AndroidTestCase {
def testGetContact(): Unit = { def testGetContact(): Unit = {
database.addContact(UserTest.u2) database.addContact(UserTest.u2)
assertTrue(database.getContact(UserTest.u1.Address).isEmpty) assertTrue(database.getContact(UserTest.u1.address).isEmpty)
val c = database.getContact(UserTest.u2.Address) val c = database.getContact(UserTest.u2.address)
assertTrue(c.nonEmpty) assertTrue(c.nonEmpty)
assertEquals(Some(UserTest.u2), c) assertEquals(Some(UserTest.u2), c)
} }

View File

@ -48,9 +48,9 @@ class AddContactsActivity extends EnsiChatActivity with ChatService.OnConnection
*/ */
override def onItemClick(parent: AdapterView[_], view: View, position: Int, id: Long): Unit = { override def onItemClick(parent: AdapterView[_], view: View, position: Int, id: Long): Unit = {
val contact = adapter.getItem(position) val contact = adapter.getItem(position)
service.sendTo(contact.Address, new RequestAddContact()) service.sendTo(contact.address, new RequestAddContact())
val intent = new Intent(this, classOf[ConfirmAddContactDialog]) val intent = new Intent(this, classOf[ConfirmAddContactDialog])
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, contact.Address.toString) intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, contact.address.toString)
startActivity(intent) startActivity(intent)
} }

View File

@ -55,11 +55,11 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
val remoteTitle = view.findViewById(R.id.remote_identicon_title).asInstanceOf[TextView] val remoteTitle = view.findViewById(R.id.remote_identicon_title).asInstanceOf[TextView]
local.setImageBitmap(IdenticonGenerator.generate(Crypto.getLocalAddress(this), (150, 150), this)) local.setImageBitmap(IdenticonGenerator.generate(Crypto.getLocalAddress(this), (150, 150), this))
remote.setImageBitmap(IdenticonGenerator.generate(user.Address, (150, 150), this)) remote.setImageBitmap(IdenticonGenerator.generate(user.address, (150, 150), this))
remoteTitle.setText(getString(R.string.remote_fingerprint_title, user.Name)) remoteTitle.setText(getString(R.string.remote_fingerprint_title, user.name))
new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme)) new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme))
.setTitle(getString(R.string.add_contact_dialog, user.Name)) .setTitle(getString(R.string.add_contact_dialog, user.name))
.setView(view) .setView(view)
.setCancelable(false) .setCancelable(false)
.setPositiveButton(android.R.string.yes, this) .setPositiveButton(android.R.string.yes, this)
@ -78,7 +78,7 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
finish() finish()
false false
} }
service.sendTo(user.Address, new ResultAddContact(result)) service.sendTo(user.address, new ResultAddContact(result))
} }
/** /**
@ -88,8 +88,8 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
if (localConfirmed && remoteConfirmed) { if (localConfirmed && remoteConfirmed) {
Log.i(Tag, "Adding new contact " + user.toString) Log.i(Tag, "Adding new contact " + user.toString)
// Get the user again, in case it was updated in the mean time. // Get the user again, in case it was updated in the mean time.
service.database.addContact(service.getUser(user.Address)) service.database.addContact(service.getUser(user.address))
Toast.makeText(this, getString(R.string.contact_added, user.Name), Toast.LENGTH_SHORT) Toast.makeText(this, getString(R.string.contact_added, user.name), Toast.LENGTH_SHORT)
.show() .show()
finish() finish()
} }
@ -102,12 +102,12 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
* the user is in this activity. * the user is in this activity.
*/ */
override def onMessageReceived(msg: Message): Unit = { override def onMessageReceived(msg: Message): Unit = {
if (msg.Header.Origin != user.Address || msg.Header.Target != Crypto.getLocalAddress(this)) if (msg.Header.origin != user.address || msg.Header.target != Crypto.getLocalAddress(this))
return return
msg.Body match { msg.Body match {
case m: ResultAddContact => case m: ResultAddContact =>
if (m.Accepted) { if (m.accepted) {
Log.i(Tag, user.toString + " accepted us as a contact, updating state") Log.i(Tag, user.toString + " accepted us as a contact, updating state")
remoteConfirmed = true remoteConfirmed = true
addContactIfBothConfirmed() addContactIfBothConfirmed()

View File

@ -38,7 +38,7 @@ class EnsiChatActivity extends Activity with ServiceConnection {
*/ */
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = { override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
val binder = iBinder.asInstanceOf[ChatServiceBinder] val binder = iBinder.asInstanceOf[ChatServiceBinder]
chatService = Option(binder.Service) chatService = Option(binder.service)
listeners.foreach(_()) listeners.foreach(_())
listeners = Set.empty listeners = Set.empty
} }

View File

@ -65,7 +65,7 @@ class MainActivity extends EnsiChatActivity {
override def onSaveInstanceState(outState: Bundle): Unit = { override def onSaveInstanceState(outState: Bundle): Unit = {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
getFragmentManager.putFragment(outState, classOf[ContactsFragment].getName, contactsFragment) getFragmentManager.putFragment(outState, classOf[ContactsFragment].getName, contactsFragment)
currentChat.collect{case c => outState.putByteArray("current_chat", c.Bytes)} currentChat.collect{case c => outState.putByteArray("current_chat", c.bytes)}
} }
/** /**

View File

@ -26,7 +26,7 @@ object BluetoothInterface {
/** /**
* Handles all Bluetooth connectivity. * Handles all Bluetooth connectivity.
*/ */
class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends InterfaceHandler { class BluetoothInterface(service: ChatService, crypto: Crypto) extends InterfaceHandler {
private val Tag = "BluetoothInterface" private val Tag = "BluetoothInterface"
@ -37,7 +37,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
private var connections = new HashMap[Device.ID, TransferThread]() private var connections = new HashMap[Device.ID, TransferThread]()
private lazy val listenThread = private lazy val listenThread =
new ListenThread(Service.getString(R.string.app_name), btAdapter, onConnectionOpened) new ListenThread(service.getString(R.string.app_name), btAdapter, onConnectionOpened)
private var cancelDiscovery = false private var cancelDiscovery = false
@ -49,11 +49,11 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
* Initializes and starts discovery and listening. * Initializes and starts discovery and listening.
*/ */
override def create(): Unit = { override def create(): Unit = {
Service.registerReceiver(DeviceDiscoveredReceiver, service.registerReceiver(DeviceDiscoveredReceiver,
new IntentFilter(BluetoothDevice.ACTION_FOUND)) new IntentFilter(BluetoothDevice.ACTION_FOUND))
Service.registerReceiver(BluetoothStateReceiver, service.registerReceiver(BluetoothStateReceiver,
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)) new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
Service.registerReceiver(DiscoveryFinishedReceiver, service.registerReceiver(DiscoveryFinishedReceiver,
new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
startBluetoothConnections() startBluetoothConnections()
} }
@ -64,9 +64,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
override def destroy(): Unit = { override def destroy(): Unit = {
listenThread.cancel() listenThread.cancel()
cancelDiscovery = true cancelDiscovery = true
Service.unregisterReceiver(DeviceDiscoveredReceiver) service.unregisterReceiver(DeviceDiscoveredReceiver)
Service.unregisterReceiver(BluetoothStateReceiver) service.unregisterReceiver(BluetoothStateReceiver)
Service.unregisterReceiver(DiscoveryFinishedReceiver) service.unregisterReceiver(DiscoveryFinishedReceiver)
} }
/** /**
@ -90,9 +90,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
btAdapter.startDiscovery() btAdapter.startDiscovery()
} }
val scanInterval = PreferenceManager.getDefaultSharedPreferences(Service) val scanInterval = PreferenceManager.getDefaultSharedPreferences(service)
.getString("scan_interval_seconds", "15").toInt * 1000 .getString("scan_interval_seconds", "15").toInt * 1000
Service.MainHandler.postDelayed(new Runnable { service.MainHandler.postDelayed(new Runnable {
override def run(): Unit = discover() override def run(): Unit = discover()
}, scanInterval) }, scanInterval)
} }
@ -111,10 +111,10 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
*/ */
private val DiscoveryFinishedReceiver = new BroadcastReceiver() { private val DiscoveryFinishedReceiver = new BroadcastReceiver() {
override def onReceive(context: Context, intent: Intent): Unit = { override def onReceive(context: Context, intent: Intent): Unit = {
discovered.filterNot(d => connections.keySet.contains(d.Id)) discovered.filterNot(d => connections.keySet.contains(d.id))
.foreach { d => .foreach { d =>
new ConnectThread(d, onConnectionOpened).start() new ConnectThread(d, onConnectionOpened).start()
devices += (d.Id -> d) devices += (d.id -> d)
} }
discovered = Set[Device]() discovered = Set[Device]()
} }
@ -127,7 +127,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
override def onReceive(context: Context, intent: Intent): Unit = { override def onReceive(context: Context, intent: Intent): Unit = {
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) match { intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) match {
case BluetoothAdapter.STATE_ON => case BluetoothAdapter.STATE_ON =>
if (Crypto.localKeysExist) if (crypto.localKeysExist)
startBluetoothConnections() startBluetoothConnections()
case BluetoothAdapter.STATE_TURNING_OFF => case BluetoothAdapter.STATE_TURNING_OFF =>
Log.i(Tag, "Bluetooth disabled, stopping connectivity") Log.i(Tag, "Bluetooth disabled, stopping connectivity")
@ -144,20 +144,20 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
* Initiates data transfer with device. * Initiates data transfer with device.
*/ */
def onConnectionOpened(device: Device, socket: BluetoothSocket): Unit = { def onConnectionOpened(device: Device, socket: BluetoothSocket): Unit = {
devices += (device.Id -> device) devices += (device.id -> device)
connections += (device.Id -> connections += (device.id ->
new TransferThread(device, socket, this, Crypto, onReceiveMessage)) new TransferThread(device, socket, this, crypto, onReceiveMessage))
connections(device.Id).start() connections(device.id).start()
} }
/** /**
* Removes device from active connections. * Removes device from active connections.
*/ */
def onConnectionClosed(device: Device, socket: BluetoothSocket): Unit = { def onConnectionClosed(device: Device, socket: BluetoothSocket): Unit = {
devices -= device.Id devices -= device.id
connections -= device.Id connections -= device.id
Service.callConnectionListeners() service.callConnectionListeners()
addressDeviceMap.inverse().remove(device.Id) addressDeviceMap.inverse().remove(device.id)
} }
/** /**
@ -170,13 +170,13 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
*/ */
private def onReceiveMessage(msg: Message, device: Device.ID): Unit = msg.Body match { private def onReceiveMessage(msg: Message, device: Device.ID): Unit = msg.Body match {
case info: ConnectionInfo => case info: ConnectionInfo =>
val address = Crypto.calculateAddress(info.key) val address = crypto.calculateAddress(info.key)
// Service.onConnectionOpened sends message, so mapping already needs to be in place. // Service.onConnectionOpened sends message, so mapping already needs to be in place.
addressDeviceMap.put(address, device) addressDeviceMap.put(address, device)
if (!Service.onConnectionOpened(msg)) if (!service.onConnectionOpened(msg))
addressDeviceMap.remove(address) addressDeviceMap.remove(address)
case _ => case _ =>
Service.onMessageReceived(msg) service.onMessageReceived(msg)
} }
/** /**

View File

@ -32,7 +32,7 @@ class ConnectThread(device: Device, onConnected: (Device, BluetoothSocket) => Un
return return
} }
Log.i(Tag, "Successfully connected to device " + device.Name) Log.i(Tag, "Successfully connected to device " + device.name)
onConnected(new Device(device.bluetoothDevice, true), socket) onConnected(new Device(device.bluetoothDevice, true), socket)
} }

View File

@ -7,13 +7,13 @@ private[bluetooth] object Device {
/** /**
* Holds bluetooth device IDs, which are just wrapped addresses (used for type safety). * Holds bluetooth device IDs, which are just wrapped addresses (used for type safety).
* *
* @param Id A bluetooth device address. * @param id A bluetooth device address.
*/ */
case class ID(private val Id: String) { case class ID(private val id: String) {
require(Id.matches("([A-Z0-9][A-Z0-9]:){5}[A-Z0-9][A-Z0-9]"), "Invalid device ID format") require(id.matches("([A-Z0-9][A-Z0-9]:){5}[A-Z0-9][A-Z0-9]"), "Invalid device ID format")
override def toString = Id override def toString = id
} }
@ -22,7 +22,7 @@ private[bluetooth] object Device {
/** /**
* Holds information about a remote bluetooth device. * Holds information about a remote bluetooth device.
*/ */
private[bluetooth] case class Device(Id: Device.ID, Name: String, Connected: Boolean, private[bluetooth] case class Device(id: Device.ID, name: String, connected: Boolean,
btDevice: Option[BluetoothDevice] = None) { btDevice: Option[BluetoothDevice] = None) {
def this(btDevice: BluetoothDevice, connected: Boolean) = { def this(btDevice: BluetoothDevice, connected: Boolean) = {

View File

@ -52,7 +52,7 @@ class TransferThread(device: Device, socket: BluetoothSocket, Handler: Bluetooth
if (inStream.available() > 0) { if (inStream.available() > 0) {
val msg = Message.read(inStream) val msg = Message.read(inStream)
onReceive(msg, device.Id) onReceive(msg, device.id)
Log.v(Tag, "Receiving " + msg) Log.v(Tag, "Receiving " + msg)
} }
} catch { } catch {

View File

@ -48,7 +48,7 @@ class ChatFragment extends ListFragment with OnClickListener
chatService = activity.service chatService = activity.service
chatService.database.getContact(address) chatService.database.getContact(address)
.foreach(c => getActivity.setTitle(c.Name)) .foreach(c => getActivity.setTitle(c.name))
// Read local device ID from service, // Read local device ID from service,
adapter = new MessagesAdapter(getActivity, address) adapter = new MessagesAdapter(getActivity, address)
@ -90,7 +90,7 @@ class ChatFragment extends ListFragment with OnClickListener
override def onSaveInstanceState(outState: Bundle): Unit = { override def onSaveInstanceState(outState: Bundle): Unit = {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putByteArray("device", address.Bytes) outState.putByteArray("device", address.bytes)
} }
/** /**
@ -110,7 +110,7 @@ class ChatFragment extends ListFragment with OnClickListener
* Displays new messages in UI. * Displays new messages in UI.
*/ */
override def onMessageReceived(msg: Message): Unit = { override def onMessageReceived(msg: Message): Unit = {
if (Set(msg.Header.Origin, msg.Header.Target).contains(address)) if (Set(msg.Header.origin, msg.Header.target).contains(address))
adapter.add(msg) adapter.add(msg)
} }

View File

@ -60,7 +60,7 @@ class ContactsFragment extends ListFragment with OnContactsUpdatedListener {
* Opens a chat with the clicked device. * Opens a chat with the clicked device.
*/ */
override def onListItemClick(l: ListView, v: View, position: Int, id: Long): Unit = override def onListItemClick(l: ListView, v: View, position: Int, id: Long): Unit =
getActivity.asInstanceOf[MainActivity].openChat(adapter.getItem(position).Address) getActivity.asInstanceOf[MainActivity].openChat(adapter.getItem(position).address)
override def onContactsUpdated(): Unit = { override def onContactsUpdated(): Unit = {
getActivity.runOnUiThread(new Runnable { getActivity.runOnUiThread(new Runnable {

View File

@ -48,7 +48,7 @@ class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListene
if (preference.getKey == KeyUserName) { if (preference.getKey == KeyUserName) {
val service = getActivity.asInstanceOf[EnsiChatActivity].service val service = getActivity.asInstanceOf[EnsiChatActivity].service
service.database.getContacts service.database.getContacts
.foreach(c => service.sendTo(c.Address, new UserName(newValue.toString))) .foreach(c => service.sendTo(c.address, new UserName(newValue.toString)))
} }
preference.setSummary(newValue.toString) preference.setSummary(newValue.toString)
true true

View File

@ -21,23 +21,23 @@ object Address {
/** /**
* Holds a device address and provides conversion methods. * Holds a device address and provides conversion methods.
* *
* @param Bytes SHA-256 hash of the node's public key. * @param bytes SHA-256 hash of the node's public key.
*/ */
case class Address(Bytes: Array[Byte]) { case class Address(bytes: Array[Byte]) {
require(Bytes.length == Address.Length, "Invalid address length (was " + Bytes.length + ")") require(bytes.length == Address.Length, "Invalid address length (was " + bytes.length + ")")
def this(base16: String) { def this(base16: String) {
this(BaseEncoding.base16().decode(base16)) this(BaseEncoding.base16().decode(base16))
} }
override def hashCode = util.Arrays.hashCode(Bytes) override def hashCode = util.Arrays.hashCode(bytes)
override def equals(a: Any) = a match { override def equals(a: Any) = a match {
case o: Address => Bytes.deep == o.Bytes.deep case o: Address => bytes.deep == o.bytes.deep
case _ => false case _ => false
} }
override def toString = BaseEncoding.base16().encode(Bytes) override def toString = BaseEncoding.base16().encode(bytes)
} }

View File

@ -17,7 +17,6 @@ import com.nutomic.ensichat.util.Database
import scala.collection.mutable import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future import scala.concurrent.Future
import scala.ref.WeakReference
object ChatService { object ChatService {
@ -151,10 +150,10 @@ class ChatService extends Service {
* Decrypts and verifies incoming messages, forwards valid ones to [[onNewMessage()]]. * Decrypts and verifies incoming messages, forwards valid ones to [[onNewMessage()]].
*/ */
def onMessageReceived(msg: Message): Unit = { def onMessageReceived(msg: Message): Unit = {
if (msg.Header.Target == Crypto.getLocalAddress(this)) { if (msg.Header.target == Crypto.getLocalAddress(this)) {
val decrypted = crypto.decrypt(msg) val decrypted = crypto.decrypt(msg)
if (!crypto.verify(decrypted)) { if (!crypto.verify(decrypted)) {
Log.i(Tag, "Ignoring message with invalid signature from " + msg.Header.Origin) Log.i(Tag, "Ignoring message with invalid signature from " + msg.Header.origin)
return return
} }
onNewMessage(decrypted) onNewMessage(decrypted)
@ -168,25 +167,25 @@ class ChatService extends Service {
*/ */
private def onNewMessage(msg: Message): Unit = msg.Body match { private def onNewMessage(msg: Message): Unit = msg.Body match {
case name: UserName => case name: UserName =>
val contact = new User(msg.Header.Origin, name.Name) val contact = new User(msg.Header.origin, name.name)
knownUsers += contact knownUsers += contact
if (database.getContact(msg.Header.Origin).nonEmpty) if (database.getContact(msg.Header.origin).nonEmpty)
database.changeContactName(contact) database.changeContactName(contact)
callConnectionListeners() callConnectionListeners()
case _: RequestAddContact => case _: RequestAddContact =>
if (msg.Header.Origin == Crypto.getLocalAddress(this)) if (msg.Header.origin == Crypto.getLocalAddress(this))
return return
Log.i(Tag, "Remote device " + msg.Header.Origin + Log.i(Tag, "Remote device " + msg.Header.origin +
" wants to add us as a contact, showing notification") " wants to add us as a contact, showing notification")
val intent = new Intent(this, classOf[ConfirmAddContactDialog]) val intent = new Intent(this, classOf[ConfirmAddContactDialog])
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, msg.Header.Origin.toString) intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, msg.Header.origin.toString)
val pi = PendingIntent.getActivity(this, 0, intent, val pi = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)
val notification = new Notification.Builder(this) val notification = new Notification.Builder(this)
.setContentTitle(getString(R.string.notification_friend_request, getUser(msg.Header.Origin))) .setContentTitle(getString(R.string.notification_friend_request, getUser(msg.Header.origin)))
.setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pi) .setContentIntent(pi)
.setAutoCancel(true) .setAutoCancel(true)
@ -259,6 +258,6 @@ class ChatService extends Service {
btInterface.getConnections btInterface.getConnections
def getUser(address: Address) = def getUser(address: Address) =
knownUsers.find(_.Address == address).getOrElse(new User(address, address.toString)) knownUsers.find(_.address == address).getOrElse(new User(address, address.toString))
} }

View File

@ -2,4 +2,4 @@ package com.nutomic.ensichat.protocol
import android.os.Binder import android.os.Binder
case class ChatServiceBinder (Service: ChatService) extends Binder case class ChatServiceBinder (service: ChatService) extends Binder

View File

@ -141,11 +141,11 @@ class Crypto(Context: Context) {
def verify(msg: Message, key: PublicKey = null): Boolean = { def verify(msg: Message, key: PublicKey = null): Boolean = {
val publicKey = val publicKey =
if (key != null) key if (key != null) key
else loadKey(msg.Header.Origin.toString, classOf[PublicKey]) else loadKey(msg.Header.origin.toString, classOf[PublicKey])
val sig = Signature.getInstance(SignAlgorithm) val sig = Signature.getInstance(SignAlgorithm)
sig.initVerify(publicKey) sig.initVerify(publicKey)
sig.update(msg.Body.write) sig.update(msg.Body.write)
sig.verify(msg.Crypto.Signature.get) sig.verify(msg.Crypto.signature.get)
} }
/** /**
@ -229,7 +229,7 @@ class Crypto(Context: Context) {
private def keyFolder = new File(Context.getFilesDir, "keys") private def keyFolder = new File(Context.getFilesDir, "keys")
def encrypt(msg: Message, key: PublicKey = null): Message = { def encrypt(msg: Message, key: PublicKey = null): Message = {
assert(msg.Crypto.Signature.isDefined, "Message must be signed before encryption") assert(msg.Crypto.signature.isDefined, "Message must be signed before encryption")
// Symmetric encryption of data // Symmetric encryption of data
val secretKey = makeSecretKey() val secretKey = makeSecretKey()
@ -240,25 +240,25 @@ class Crypto(Context: Context) {
// Asymmetric encryption of secret key // Asymmetric encryption of secret key
val publicKey = val publicKey =
if (key != null) key if (key != null) key
else loadKey(msg.Header.Target.toString, classOf[PublicKey]) else loadKey(msg.Header.target.toString, classOf[PublicKey])
val asymmetricCipher = Cipher.getInstance(KeyAlgorithm) val asymmetricCipher = Cipher.getInstance(KeyAlgorithm)
asymmetricCipher.init(Cipher.WRAP_MODE, publicKey) asymmetricCipher.init(Cipher.WRAP_MODE, publicKey)
new Message(msg.Header, new Message(msg.Header,
new CryptoData(msg.Crypto.Signature, Option(asymmetricCipher.wrap(secretKey))), encrypted) new CryptoData(msg.Crypto.signature, Option(asymmetricCipher.wrap(secretKey))), encrypted)
} }
def decrypt(msg: Message): Message = { def decrypt(msg: Message): Message = {
// Asymmetric decryption of secret key // Asymmetric decryption of secret key
val asymmetricCipher = Cipher.getInstance(KeyAlgorithm) val asymmetricCipher = Cipher.getInstance(KeyAlgorithm)
asymmetricCipher.init(Cipher.UNWRAP_MODE, loadKey(PrivateKeyAlias, classOf[PrivateKey])) asymmetricCipher.init(Cipher.UNWRAP_MODE, loadKey(PrivateKeyAlias, classOf[PrivateKey]))
val key = asymmetricCipher.unwrap(msg.Crypto.Key.get, SymmetricKeyAlgorithm, Cipher.SECRET_KEY) val key = asymmetricCipher.unwrap(msg.Crypto.key.get, SymmetricKeyAlgorithm, Cipher.SECRET_KEY)
// Symmetric decryption of data // Symmetric decryption of data
val symmetricCipher = Cipher.getInstance(SymmetricCipherAlgorithm) val symmetricCipher = Cipher.getInstance(SymmetricCipherAlgorithm)
symmetricCipher.init(Cipher.DECRYPT_MODE, key) symmetricCipher.init(Cipher.DECRYPT_MODE, key)
val decrypted = copyThroughCipher(symmetricCipher, msg.Body.asInstanceOf[EncryptedBody].Data) val decrypted = copyThroughCipher(symmetricCipher, msg.Body.asInstanceOf[EncryptedBody].data)
val body = msg.Header.MessageType match { val body = msg.Header.messageType match {
case RequestAddContact.Type => RequestAddContact.read(decrypted) case RequestAddContact.Type => RequestAddContact.read(decrypted)
case ResultAddContact.Type => ResultAddContact.read(decrypted) case ResultAddContact.Type => ResultAddContact.read(decrypted)
case Text.Type => Text.read(decrypted) case Text.Type => Text.read(decrypted)

View File

@ -10,7 +10,7 @@ class Router(activeConnections: () => Set[Address], send: (Address, Message) =>
private var messageSeen = Set[(Address, Int)]() private var messageSeen = Set[(Address, Int)]()
def onReceive(msg: Message): Unit = { def onReceive(msg: Message): Unit = {
val info = (msg.Header.Origin, msg.Header.SeqNum) val info = (msg.Header.origin, msg.Header.seqNum)
if (messageSeen.contains(info)) if (messageSeen.contains(info))
return return

View File

@ -1,4 +1,3 @@
package com.nutomic.ensichat.protocol package com.nutomic.ensichat.protocol
case class User(address: Address, name: String)
case class User(Address: Address, Name: String)

View File

@ -36,11 +36,11 @@ object CryptoData {
/** /**
* Holds the signature and (optional) key that are stored in a message. * Holds the signature and (optional) key that are stored in a message.
*/ */
case class CryptoData(Signature: Option[Array[Byte]], Key: Option[Array[Byte]]) { case class CryptoData(signature: Option[Array[Byte]], key: Option[Array[Byte]]) {
override def equals(a: Any): Boolean = a match { override def equals(a: Any): Boolean = a match {
case o: CryptoData => util.Arrays.equals(Signature.orNull, o.Signature.orNull) && case o: CryptoData => util.Arrays.equals(signature.orNull, o.signature.orNull) &&
util.Arrays.equals(Key.orNull, o.Key.orNull) util.Arrays.equals(key.orNull, o.key.orNull)
case _ => false case _ => false
} }
@ -49,15 +49,15 @@ case class CryptoData(Signature: Option[Array[Byte]], Key: Option[Array[Byte]])
*/ */
def write: Array[Byte] = { def write: Array[Byte] = {
val b = ByteBuffer.allocate(length) val b = ByteBuffer.allocate(length)
BufferUtils.putUnsignedShort(b, Signature.get.length) BufferUtils.putUnsignedShort(b, signature.get.length)
BufferUtils.putUnsignedShort(b, keyLength) BufferUtils.putUnsignedShort(b, keyLength)
b.put(Signature.get) b.put(signature.get)
if (Key.nonEmpty) b.put(Key.get) if (key.nonEmpty) b.put(key.get)
b.array() b.array()
} }
def length = 4 + Signature.get.length + keyLength def length = 4 + signature.get.length + keyLength
private def keyLength = if (Key.isDefined) Key.get.length else 0 private def keyLength = if (key.isDefined) key.get.length else 0
} }

View File

@ -3,11 +3,11 @@ package com.nutomic.ensichat.protocol.messages
/** /**
* Represents the data in an encrypted message body. * Represents the data in an encrypted message body.
*/ */
case class EncryptedBody(Data: Array[Byte]) extends MessageBody { case class EncryptedBody(data: Array[Byte]) extends MessageBody {
override def messageType = -1 override def messageType = -1
def write = Data def write = data
override def length = Data.length override def length = data.length
} }

View File

@ -26,7 +26,7 @@ object Message {
stream.read(headerBytes, 0, MessageHeader.Length) stream.read(headerBytes, 0, MessageHeader.Length)
val header = MessageHeader.read(headerBytes) val header = MessageHeader.read(headerBytes)
val contentLength = (header.Length - MessageHeader.Length).toInt val contentLength = (header.length - MessageHeader.Length).toInt
val contentBytes = new Array[Byte](contentLength) val contentBytes = new Array[Byte](contentLength)
var numRead = 0 var numRead = 0
do { do {
@ -36,7 +36,7 @@ object Message {
val (crypto, remaining) = CryptoData.read(contentBytes) val (crypto, remaining) = CryptoData.read(contentBytes)
val body = val body =
header.MessageType match { header.messageType match {
case ConnectionInfo.Type => ConnectionInfo.read(remaining) case ConnectionInfo.Type => ConnectionInfo.read(remaining)
case _ => new EncryptedBody(remaining) case _ => new EncryptedBody(remaining)
} }

View File

@ -45,13 +45,13 @@ object MessageHeader {
/** /**
* First part of any message, used for routing. * First part of any message, used for routing.
*/ */
case class MessageHeader(MessageType: Int, case class MessageHeader(messageType: Int,
HopLimit: Int, hopLimit: Int,
Origin: Address, origin: Address,
Target: Address, target: Address,
SeqNum: Int, seqNum: Int,
Length: Long = -1, length: Long = -1,
HopCount: Int = 0) { hopCount: Int = 0) {
/** /**
* Writes the header to byte array. * Writes the header to byte array.
@ -59,16 +59,16 @@ case class MessageHeader(MessageType: Int,
def write(contentLength: Int): Array[Byte] = { def write(contentLength: Int): Array[Byte] = {
val b = ByteBuffer.allocate(MessageHeader.Length) val b = ByteBuffer.allocate(MessageHeader.Length)
val versionAndType = (MessageHeader.Version << 12) | MessageType val versionAndType = (MessageHeader.Version << 12) | messageType
BufferUtils.putUnsignedShort(b, versionAndType) BufferUtils.putUnsignedShort(b, versionAndType)
BufferUtils.putUnsignedByte(b, HopLimit) BufferUtils.putUnsignedByte(b, hopLimit)
BufferUtils.putUnsignedByte(b, HopCount) BufferUtils.putUnsignedByte(b, hopCount)
BufferUtils.putUnsignedInt(b, MessageHeader.Length + contentLength) BufferUtils.putUnsignedInt(b, MessageHeader.Length + contentLength)
b.put(Origin.Bytes) b.put(origin.bytes)
b.put(Target.Bytes) b.put(target.bytes)
BufferUtils.putUnsignedShort(b, SeqNum) BufferUtils.putUnsignedShort(b, seqNum)
BufferUtils.putUnsignedShort(b, 0) BufferUtils.putUnsignedShort(b, 0)
b.array() b.array()
@ -76,11 +76,11 @@ case class MessageHeader(MessageType: Int,
override def equals(a: Any): Boolean = a match { override def equals(a: Any): Boolean = a match {
case o: MessageHeader => case o: MessageHeader =>
MessageType == o.MessageType && messageType == o.messageType &&
HopLimit == o.HopLimit && hopLimit == o.hopLimit &&
Origin == o.Origin && origin == o.origin &&
Target == o.Target && target == o.target &&
HopCount == o.HopCount hopCount == o.hopCount
// Don't compare length as it may be unknown (when header was just created without a body). // Don't compare length as it may be unknown (when header was just created without a body).
case _ => false case _ => false
} }

View File

@ -23,13 +23,13 @@ object ResultAddContact {
/** /**
* Contains the result of a [[RequestAddContact]] message. * Contains the result of a [[RequestAddContact]] message.
*/ */
case class ResultAddContact(Accepted: Boolean) extends MessageBody { case class ResultAddContact(accepted: Boolean) extends MessageBody {
override def messageType = ResultAddContact.Type override def messageType = ResultAddContact.Type
override def write: Array[Byte] = { override def write: Array[Byte] = {
val b = ByteBuffer.allocate(length) val b = ByteBuffer.allocate(length)
BufferUtils.putUnsignedByte(b, if (Accepted) 0x80 else 0) BufferUtils.putUnsignedByte(b, if (accepted) 0x80 else 0)
(0 to 1).foreach(_ => BufferUtils.putUnsignedByte(b, 0)) (0 to 1).foreach(_ => BufferUtils.putUnsignedByte(b, 0))
b.array() b.array()
} }

View File

@ -24,18 +24,18 @@ object UserName {
/** /**
* Holds the display name of the sender. * Holds the display name of the sender.
*/ */
case class UserName(Name: String) extends MessageBody { case class UserName(name: String) extends MessageBody {
override def messageType = UserName.Type override def messageType = UserName.Type
override def write: Array[Byte] = { override def write: Array[Byte] = {
val b = ByteBuffer.allocate(length) val b = ByteBuffer.allocate(length)
val bytes = Name.getBytes(Message.Charset) val bytes = name.getBytes(Message.Charset)
BufferUtils.putUnsignedInt(b, bytes.length) BufferUtils.putUnsignedInt(b, bytes.length)
b.put(bytes) b.put(bytes)
b.array() b.array()
} }
override def length = 4 + Name.getBytes(Message.Charset).length override def length = 4 + name.getBytes(Message.Charset).length
} }

View File

@ -82,8 +82,8 @@ class Database(context: Context)
override def onMessageReceived(msg: Message): Unit = msg.Body match { override def onMessageReceived(msg: Message): Unit = msg.Body match {
case text: Text => case text: Text =>
val cv = new ContentValues() val cv = new ContentValues()
cv.put("origin", msg.Header.Origin.toString) cv.put("origin", msg.Header.origin.toString)
cv.put("target", msg.Header.Target.toString) cv.put("target", msg.Header.target.toString)
// toString used as workaround for compile error with Long. // toString used as workaround for compile error with Long.
cv.put("date", text.time.getTime.toString) cv.put("date", text.time.getTime.toString)
cv.put("text", text.text) cv.put("text", text.text)
@ -130,16 +130,16 @@ class Database(context: Context)
*/ */
def addContact(contact: User): Unit = { def addContact(contact: User): Unit = {
val cv = new ContentValues() val cv = new ContentValues()
cv.put("address", contact.Address.toString) cv.put("address", contact.address.toString)
cv.put("name", contact.Name.toString) cv.put("name", contact.name.toString)
getWritableDatabase.insert("contacts", null, cv) getWritableDatabase.insert("contacts", null, cv)
contactsUpdatedListeners.foreach(_.onContactsUpdated() ) contactsUpdatedListeners.foreach(_.onContactsUpdated() )
} }
def changeContactName(contact: User): Unit = { def changeContactName(contact: User): Unit = {
val cv = new ContentValues() val cv = new ContentValues()
cv.put("name", contact.Name.toString) cv.put("name", contact.name.toString)
getWritableDatabase.update("contacts", cv, "address = ?", Array(contact.Address.toString)) getWritableDatabase.update("contacts", cv, "address = ?", Array(contact.address.toString))
contactsUpdatedListeners.foreach(_.onContactsUpdated()) contactsUpdatedListeners.foreach(_.onContactsUpdated())
} }

View File

@ -25,7 +25,7 @@ object IdenticonGenerator {
* @param size The size of the bitmap returned. * @param size The size of the bitmap returned.
*/ */
def generate(address: Address, size: (Int, Int), context: Context): Bitmap = { def generate(address: Address, size: (Int, Int), context: Context): Bitmap = {
val hash = address.Bytes val hash = address.bytes
// Create base image and colors. // Create base image and colors.
var identicon = Bitmap.createBitmap(Width, Height, Config.ARGB_8888) var identicon = Bitmap.createBitmap(Width, Height, Config.ARGB_8888)

View File

@ -26,7 +26,7 @@ class MessagesAdapter(context: Context, remoteAddress: Address) extends
val lp = new RelativeLayout.LayoutParams(tv.getLayoutParams) val lp = new RelativeLayout.LayoutParams(tv.getLayoutParams)
val margin = (MessageMargin * context.getResources.getDisplayMetrics.density).toInt val margin = (MessageMargin * context.getResources.getDisplayMetrics.density).toInt
if (getItem(position).Header.Origin != remoteAddress) { if (getItem(position).Header.origin != remoteAddress) {
view.setGravity(Gravity.RIGHT) view.setGravity(Gravity.RIGHT)
lp.setMargins(margin, 0, 0, 0) lp.setMargins(margin, 0, 0, 0)
} else { } else {

View File

@ -15,7 +15,7 @@ class UsersAdapter(context: Context) extends
override def getView(position: Int, convertView: View, parent: ViewGroup): View = { override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
val view = super.getView(position, convertView, parent) val view = super.getView(position, convertView, parent)
val title: TextView = view.findViewById(android.R.id.text1).asInstanceOf[TextView] val title: TextView = view.findViewById(android.R.id.text1).asInstanceOf[TextView]
title.setText(getItem(position).Name) title.setText(getItem(position).name)
view view
} }