Skip to content

Commit

Permalink
Courier Sync
Browse files Browse the repository at this point in the history
  • Loading branch information
sdsantos committed Jul 1, 2020
1 parent d3d9eee commit 8e1fdce
Show file tree
Hide file tree
Showing 45 changed files with 1,115 additions and 25 deletions.
6 changes: 5 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ dependencies {

// Relaynet
implementation 'tech.relaycorp:relaynet:1.15.6'
implementation 'tech.relaycorp:relaynet-cogrpc:1.0.2'
implementation 'tech.relaycorp:relaynet-cogrpc:1.1.0'

// Android TLS support for Netty
implementation "io.netty:netty-handler:4.1.50.Final"
implementation 'org.conscrypt:conscrypt-android:2.4.0'

// ORM
def room_version = "2.2.5"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,87 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "f4d34def0a467a21b391ecb53e2175d2",
"identityHash": "9ddb31ac692f375edbe5f934ce68bf51",
"entities": [
{
"tableName": "Message",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"tableName": "Parcel",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`recipientAddress` TEXT NOT NULL, `senderAddress` TEXT NOT NULL, `messageId` TEXT NOT NULL, `creationTimeUtc` INTEGER NOT NULL, `expirationTimeUtc` INTEGER NOT NULL, `storagePath` TEXT NOT NULL, `size` INTEGER NOT NULL, PRIMARY KEY(`senderAddress`, `messageId`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"fieldPath": "recipientAddress",
"columnName": "recipientAddress",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "senderAddress",
"columnName": "senderAddress",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "messageId",
"columnName": "messageId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "creationTimeUtc",
"columnName": "creationTimeUtc",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "expirationTimeUtc",
"columnName": "expirationTimeUtc",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "storagePath",
"columnName": "storagePath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "size",
"columnName": "size",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
"senderAddress",
"messageId"
],
"autoGenerate": false
},
"indices": [],
"indices": [
{
"name": "index_Parcel_recipientAddress",
"unique": false,
"columnNames": [
"recipientAddress"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_Parcel_recipientAddress` ON `${TABLE_NAME}` (`recipientAddress`)"
},
{
"name": "index_Parcel_expirationTimeUtc",
"unique": false,
"columnNames": [
"expirationTimeUtc"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_Parcel_expirationTimeUtc` ON `${TABLE_NAME}` (`expirationTimeUtc`)"
}
],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f4d34def0a467a21b391ecb53e2175d2')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9ddb31ac692f375edbe5f934ce68bf51')"
]
}
}
13 changes: 13 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"
package="tech.relaycorp.gateway">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<application
android:name=".App"
android:allowBackup="false"
Expand All @@ -14,13 +18,22 @@
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".ui.main.MainActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.Gateway.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.sync.CourierConnectionActivity"
android:label="@string/sync_courier"
android:screenOrientation="portrait" />
<activity
android:name=".ui.sync.CourierSyncActivity"
android:label="@string/sync_courier"
android:screenOrientation="portrait" />
</application>

</manifest>
7 changes: 7 additions & 0 deletions app/src/main/java/tech/relaycorp/gateway/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package tech.relaycorp.gateway
import android.app.Application
import android.os.Build
import android.os.StrictMode
import org.conscrypt.Conscrypt
import tech.relaycorp.gateway.common.Logging
import tech.relaycorp.gateway.common.di.AppComponent
import tech.relaycorp.gateway.common.di.DaggerAppComponent
import java.security.Security
import java.util.logging.Level
import java.util.logging.LogManager

Expand All @@ -29,6 +31,7 @@ class App : Application() {
override fun onCreate() {
super.onCreate()
component.inject(this)
setupTLSProvider()
setupLogger()
setupStrictMode()
}
Expand Down Expand Up @@ -74,5 +77,9 @@ class App : Application() {
}
}

private fun setupTLSProvider() {
Security.insertProviderAt(Conscrypt.newProvider(), 1)
}

enum class Mode { Normal, Test }
}
10 changes: 10 additions & 0 deletions app/src/main/java/tech/relaycorp/gateway/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tech.relaycorp.gateway

import android.content.Context
import android.content.res.Resources
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import dagger.Module
import dagger.Provides

Expand All @@ -21,4 +23,12 @@ class AppModule(

@Provides
fun resources(): Resources = app.resources

@Provides
fun connectivityManager() =
app.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

@Provides
fun wifiManager() =
app.getSystemService(Context.WIFI_SERVICE) as WifiManager
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package tech.relaycorp.gateway.background

import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.wifi.WifiManager
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CourierConnectionObserver
@Inject constructor(
connectivityManager: ConnectivityManager,
wifiManager: WifiManager
) {

private val state =
MutableStateFlow<CourierConnectionState>(CourierConnectionState.Disconnected)

private val networkRequest =
NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build()

private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
// TODO: check if there's an actual courier server listening at the right port
val hotspotSourceIpAddress =
wifiManager.dhcpInfo?.serverAddress?.toIpAddressString()

state.value =
hotspotSourceIpAddress
?.let { CourierConnectionState.ConnectedWithCourier("https://$it:21473") }
?: CourierConnectionState.ConnectedWithUnknown
}

override fun onUnavailable() {
state.value = CourierConnectionState.Disconnected
}

override fun onLost(network: Network) {
state.value = CourierConnectionState.Disconnected
}
}

init {
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}

fun observe(): Flow<CourierConnectionState> = state

private fun Int.toIpAddressString() =
String.format(
"%d.%d.%d.%d",
this and 0xff,
this shr 8 and 0xff,
this shr 16 and 0xff,
this shr 24 and 0xff
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tech.relaycorp.gateway.background

sealed class CourierConnectionState {
data class ConnectedWithCourier(val address: String) : CourierConnectionState()
object ConnectedWithUnknown : CourierConnectionState()
object Disconnected : CourierConnectionState()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package tech.relaycorp.gateway.common.di

import dagger.Subcomponent
import tech.relaycorp.gateway.ui.main.MainActivity
import tech.relaycorp.gateway.ui.sync.CourierConnectionActivity
import tech.relaycorp.gateway.ui.sync.CourierSyncActivity

@PerActivity
@Subcomponent
interface ActivityComponent {

// Activities

fun inject(activity: CourierConnectionActivity)
fun inject(activity: CourierSyncActivity)
fun inject(activity: MainActivity)
}
9 changes: 9 additions & 0 deletions app/src/main/java/tech/relaycorp/gateway/data/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import dagger.Module
import dagger.Provides
import tech.relaycorp.gateway.App
import tech.relaycorp.gateway.data.database.AppDatabase
import tech.relaycorp.relaynet.cogrpc.client.CogRPCClient
import javax.inject.Named
import javax.inject.Singleton

Expand All @@ -23,6 +24,11 @@ class DataModule {
Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
}.build()

@Provides
@Singleton
fun storedParcelDao(database: AppDatabase) =
database.parcelRepository()

@Provides
@Named("preferences_name")
fun preferencesName(appMode: App.Mode) =
Expand All @@ -37,4 +43,7 @@ class DataModule {
@Named("preferences_name") preferencesName: String
): SharedPreferences =
context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE)

@Provides
fun cogRPCClientBuilder(): CogRPCClient.Builder = CogRPCClient.Builder
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ package tech.relaycorp.gateway.data.database

import androidx.room.Database
import androidx.room.RoomDatabase
import tech.relaycorp.gateway.data.model.ExampleModel
import androidx.room.TypeConverters
import tech.relaycorp.gateway.data.model.StoredParcel
import tech.relaycorp.gateway.data.repos.ParcelRepository

@Database(
entities = [ExampleModel::class],
entities = [StoredParcel::class],
version = 1
)
abstract class AppDatabase : RoomDatabase()
@TypeConverters(
value = [
DateConverter::class,
MessageConverter::class,
StorageSizeConverter::class
]
)
abstract class AppDatabase : RoomDatabase(){
abstract fun parcelRepository(): ParcelRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package tech.relaycorp.gateway.data.database

import androidx.room.TypeConverter
import java.util.Date

class DateConverter {
@TypeConverter
fun toDate(dateLong: Long) = Date(dateLong)

@TypeConverter
fun fromDate(date: Date) = date.time
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package tech.relaycorp.gateway.data.database

import androidx.room.TypeConverter
import tech.relaycorp.gateway.data.model.MessageAddress
import tech.relaycorp.gateway.data.model.MessageId
import tech.relaycorp.gateway.data.model.PrivateMessageAddress
import tech.relaycorp.gateway.data.model.PublicMessageAddress

class MessageConverter {
@TypeConverter
fun toAddress(value: String) = MessageAddress.of(value)

@TypeConverter
fun fromAddress(address: MessageAddress) = address.value

@TypeConverter
fun toPrivateAddress(value: String) = PrivateMessageAddress(value)

@TypeConverter
fun fromPrivateAddress(address: PrivateMessageAddress) = address.value

@TypeConverter
fun toPublicAddress(value: String) = PublicMessageAddress(value)

@TypeConverter
fun fromPublicAddress(address: PublicMessageAddress) = address.value

@TypeConverter
fun toId(value: String) = MessageId(value)

@TypeConverter
fun fromId(id: MessageId) = id.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package tech.relaycorp.gateway.data.database

import androidx.room.TypeConverter
import tech.relaycorp.gateway.data.model.StorageSize

class StorageSizeConverter {
@TypeConverter
fun toStorageSize(value: Long) = StorageSize(value)

@TypeConverter
fun fromStorageSize(size: StorageSize) = size.bytes
}
Loading

0 comments on commit 8e1fdce

Please sign in to comment.