Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
947ee07
Starting Code of Application
ManavSarkar Jun 13, 2022
ec1114d
Merge branch 'main' into 'gsoc-2022'
Jun 14, 2022
693ffb2
Chat Message refresh fix
ManavSarkar Jun 14, 2022
d19b8d4
//WIP Reformatting to Stateful Widget
ManavSarkar Jun 21, 2022
fcaae6e
// WIP Send the last received message id
ManavSarkar Jun 21, 2022
8f2f319
Change the compile version
ManavSarkar Jul 2, 2022
791c09e
Rename subscription and conversations
ManavSarkar Jul 2, 2022
a3a1efe
Changed formatting and added some documentation
ManavSarkar Jul 2, 2022
a5b6f35
Added function to get the last message id
ManavSarkar Jul 2, 2022
f9e2107
Code formatting and documenting
ManavSarkar Jul 2, 2022
e12c2d9
Broadcasting last message id and comparing message ids
ManavSarkar Jul 2, 2022
b898186
Code formatting and UI fixes
ManavSarkar Jul 2, 2022
1c156b5
Code formatting
ManavSarkar Jul 2, 2022
bd28696
New plugins added
ManavSarkar Jul 2, 2022
5683469
Code formatting, check for updates and UI fixed
ManavSarkar Jul 2, 2022
381df4f
Implemented Save profile feature
ManavSarkar Jul 4, 2022
31ccb9f
HomeScreen manages the Tabs and initialises nearby connections
ManavSarkar Jul 11, 2022
33dd43a
Added Provider State Management for better state management and auto …
ManavSarkar Jul 11, 2022
e3d926a
Separated MessagePanel for sending messages separately
ManavSarkar Jul 11, 2022
18bde65
Added provider state management to related files
ManavSarkar Jul 11, 2022
bf36880
Removed the init code and moved to HomeScreen
ManavSarkar Jul 11, 2022
1f3c7bb
Added Date, Time in message component
ManavSarkar Jul 11, 2022
02d45ec
Fixed imports and removed unused code
ManavSarkar Jul 11, 2022
d7d65f6
Adding save profile feature
ManavSarkar Jul 29, 2022
cdd7b41
Date formatting
ManavSarkar Jul 29, 2022
c8ef41c
Settings button navigating to profile page
ManavSarkar Jul 29, 2022
71a8b86
Added global key to make context available to back-end for easier sta…
ManavSarkar Aug 7, 2022
e0d0eae
Removed unnecessary code commented.
ManavSarkar Aug 7, 2022
a7accbd
Separated Backend from frontend by moving broadcast code from homescr…
ManavSarkar Aug 7, 2022
d63bf6d
Implementing First Push then Pull protocol
ManavSarkar Aug 7, 2022
5632b0d
Fixing hybrid protocol context problems
ManavSarkar Aug 16, 2022
53f1fd4
Merge branch 'main' into 'gsoc-2022'
Sep 5, 2022
0df2f0b
Documenting Files
ManavSarkar Sep 7, 2022
a433efe
Updating gradle for new Flutter version
ManavSarkar Sep 7, 2022
53a4fdd
README updated and GSoC 2022 implementations attached
ManavSarkar Sep 7, 2022
3d7e023
Updated GSoC 2022 file.
ManavSarkar Sep 7, 2022
a9ffaac
Adding APK and Project links
ManavSarkar Sep 12, 2022
acfe97b
Moving to appropriate destination of GSOC Contributions folder.
ManavSarkar Sep 12, 2022
4e1fdd6
Merge branch 'main' into 'gsoc-2022'
ManavSarkar Jul 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions GSOC/2022/ManavSarkar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Peer to Peer Messaging application GSOC 2022

## Choosen Idea
1) Change the project Push Gossip Protocol to either Pull Protocol or Hybrid protocol
2) Updating the User Interface for the Application.

## Project Description
The Peer to Peer messaging application aims to build an application that does not rely on a central server governed by laws and influenced by third party users. Currently, we are relying on applications that are based on central server messaging that can use our private data for their benefit regardless of the privacy policies without knowing the user. We came across incidents of data breaches where the personal data of a large number of users was disclosed to hackers. Hence a solution would be to move the data from the central server to a distributed network. The distributed network will be able to provide better privacy, less dependence on the network, and freedom from central network laws.
The application will be hugely beneficial in disaster-prone areas or remote areas where the cellular connections are too weak to communicate through general messaging applications. In this case, this application would communicate through device networking capabilities. Hence the app is reliable and the project is working for a good cause. Hence I am motivated to develop and contribute to this project.

## Proposal Detailed Approach
I intend to propose an approach to transfer the messaging protocol of the application from the naive push protocol. The push protocol has many disadvantages and so we need to migrate to either pull protocol or hybrid protocol. The hybrid model that is used in this project is the First-Push-Then-Pull protocol.

### Hybrid Protocol Implementation
Hybrid protocol comprises both the Push protocol and Pull protocol. The approach for this protocol is First Push and then Pull. It works on the following principle.
- As we know, the push protocol has better performance in the initial rounds. So we first take the use of the push protocol and propagate the message until some rounds.
- Next, we will apply the pull protocol where the devices will start asking for updates.
- In this way, we will achieve the propagation time of O(log(log N)), which is much better than O(log N) for the push protocol.

**Determination of transition period**We cannot change from push protocol to pull protocol randomly. We need a definite round where the nodes will change from push to pull protocol.
1) First the Pull protocol works as it asks the connected devices that if there is new message with the help of method UPDATE that is being implemented.
2) The pull protocol continues until the application is on.
3) Now when a new message is being sent from a device, it pushes to the connected devices. The rest of devices receive the message with the help of Pull Protocol.
4) In this way, we achieve First Push and Then Pull protocol.

## Implementations in GSoC 2022
- The app previously required to enter the name every time the app launches.
Now the application saves the user name and unique id(automatically generated) into the Shared Preferences that is being removed only when the app is installed. It is a key-value form of data storing way. So when the app is launched again, the app directly opens the Home Page.
- Home Page - It contains two tabs. The tabs are created and managed by default tab controller of the Flutter.
- Tab 1: Contains List of Connected and Disconnected but in network devices.
- Tab2: List of devices conversed with previously.
- Provider State Management - Previously when viewing the chat page, if new message arrived from the person whom with we are chatting, the message was saved in Database but not displayed until relaunching the ChatPage. Hence the state management was required which ensured that when a new message arrived, it will be displayed instantly. This also improved the overall speed of the application as common details where available globally rather being transferring from one screen to other.
- Hybrid Protocol as discussed previously - First Push Then Pull (FPTP) Protocol.
- Updated the UI

## App Flow
- ***(If first launched)*** - The app asks for the username and a random string is added to their name, to make sure its unique.
- Then the user is taken to the HomePage.
- One first tab, it contains the devices with whom he/she can connect with and chat.
- On second tab, it contains the devices with which devices it has chatted previously.
- On clicking any device name from the list, it can chat with the devices in realtime or if there is no connection, it is delivered when the app comes on network.

## Merge Requests
- https://gitlab.com/aossie/p2p-messaging-flutter/-/merge_requests/18
- https://gitlab.com/aossie/p2p-messaging-flutter/-/merge_requests/19
- https://gitlab.com/aossie/p2p-messaging-flutter/-/merge_requests/20

## App Working Video
Here is the video for the working application.

https://drive.google.com/file/d/1Egv-RhbZmwLcs0yskrFm4Ym8IX44D1qg/view?usp=sharing

## APK Link
https://drive.google.com/file/d/1fBfJO6akTe_-GXhvtEcr_qd59W7Ah5YG/view?usp=sharing

## Project Link
https://gitlab.com/aossie/p2p-messaging-flutter

## GSOC 2022 Branch Link
https://gitlab.com/aossie/p2p-messaging-flutter/-/tree/gsoc-2022
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,49 @@ There are 6 main parts the above idea can be broken into,
- use the 'hopping message' architecture to relay messages
- offline storage of undelivered messages

# Peer to Peer Messaging application GSOC 2022

## Choosen Idea
1) Change the project Push Gossip Protocol to either Pull Protocol or Hybrid protocol
2) Updating the User Interface for the Application.

## Project Description
The Peer to Peer messaging application aims to build an application that does not rely on a central server governed by laws and influenced by third party users. Currently, we are relying on applications that are based on central server messaging that can use our private data for their benefit regardless of the privacy policies without knowing the user. We came across incidents of data breaches where the personal data of a large number of users was disclosed to hackers. Hence a solution would be to move the data from the central server to a distributed network. The distributed network will be able to provide better privacy, less dependence on the network, and freedom from central network laws.
The application will be hugely beneficial in disaster-prone areas or remote areas where the cellular connections are too weak to communicate through general messaging applications. In this case, this application would communicate through device networking capabilities. Hence the app is reliable and the project is working for a good cause. Hence I am motivated to develop and contribute to this project.

## Proposal Detailed Approach
I intend to propose an approach to transfer the messaging protocol of the application from the naive push protocol. The push protocol has many disadvantages and so we need to migrate to either pull protocol or hybrid protocol. The hybrid model that is used in this project is the First-Push-Then-Pull protocol.

### Hybrid Protocol Implementation
Hybrid protocol comprises both the Push protocol and Pull protocol. The approach for this protocol is First Push and then Pull. It works on the following principle.
- As we know, the push protocol has better performance in the initial rounds. So we first take the use of the push protocol and propagate the message until some rounds.
- Next, we will apply the pull protocol where the devices will start asking for updates.
- In this way, we will achieve the propagation time of O(log(log N)), which is much better than O(log N) for the push protocol.

**Determination of transition period**We cannot change from push protocol to pull protocol randomly. We need a definite round where the nodes will change from push to pull protocol.
1) First the Pull protocol works as it asks the connected devices that if there is new message with the help of method UPDATE that is being implemented.
2) The pull protocol continues until the application is on.
3) Now when a new message is being sent from a device, it pushes to the connected devices. The rest of devices receive the message with the help of Pull Protocol.
4) In this way, we achieve First Push and Then Pull protocol.

## Implementations in GSoC 2022
- The app previously required to enter the name every time the app launches.
Now the application saves the user name and unique id(automatically generated) into the Shared Preferences that is being removed only when the app is installed. It is a key-value form of data storing way. So when the app is launched again, the app directly opens the Home Page.
- Home Page - It contains two tabs. The tabs are created and managed by default tab controller of the Flutter.
- Tab 1: Contains List of Connected and Disconnected but in network devices.
- Tab2: List of devices conversed with previously.
- Provider State Management - Previously when viewing the chat page, if new message arrived from the person whom with we are chatting, the message was saved in Database but not displayed until relaunching the ChatPage. Hence the state management was required which ensured that when a new message arrived, it will be displayed instantly. This also improved the overall speed of the application as common details where available globally rather being transferring from one screen to other.
- Hybrid Protocol as discussed previously - First Push Then Pull (FPTP) Protocol.
- Updated the UI

## App Flow
- ***(If first launched)*** - The app asks for the username and a random string is added to their name, to make sure its unique.
- Then the user is taken to the HomePage.
- One first tab, it contains the devices with whom he/she can connect with and chat.
- On second tab, it contains the devices with which devices it has chatted previously.
- On clicking any device name from the list, it can chat with the devices in realtime or if there is no connection, it is delivered when the app comes on network.

## Merge Requests
- https://gitlab.com/aossie/p2p-messaging-flutter/-/merge_requests/18
- https://gitlab.com/aossie/p2p-messaging-flutter/-/merge_requests/19
- https://gitlab.com/aossie/p2p-messaging-flutter/-/merge_requests/20
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 30
compileSdkVersion 33

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand Down
6 changes: 2 additions & 4 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
<application android:name="${applicationName}"
android:label="flutter_nearby_connections_example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
<activity android:name="io.flutter.embedding.android.FlutterActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
Expand Down
3 changes: 0 additions & 3 deletions android/app/src/main/kotlin/com/aossie/p2p/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
package com.aossie.p2p

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.5.10'
ext.kotlin_version = '1.6.10'
repositories {
google()
jcenter()
Expand Down
70 changes: 61 additions & 9 deletions lib/classes/Global.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,76 @@
/// It the Global state management class.
/// This is used over all the application.

import 'dart:async';
import 'package:pointycastle/api.dart' as crypto;
import 'package:flutter/material.dart';
import 'package:flutter_nearby_connections/flutter_nearby_connections.dart';
import 'Payload.dart';

import 'package:flutter_nearby_connections_example/p2p/AdhocHousekeeping.dart';
import '../database/DatabaseHelper.dart';
import 'Msg.dart';

class Global {
static List<Device> devices = [];
static List<Device> connectedDevices = [];
class Global extends ChangeNotifier {
List<Device> devices = [];
List<Device> connectedDevices = [];
static NearbyService? nearbyService;
static StreamSubscription? subscription;
static StreamSubscription? deviceSubscription;

static StreamSubscription? receivedDataSubscription;
static List<Msg> messages = [
Msg("1", "test", "sent", '2'),
Msg("2", "test2", "sent", '4')
];
static Map<String, String> publicKeys = Map();
static Map<String,Map<String, Msg>> conversations =
Map(); //converser mapped to conversation
Map<String, Map<String, Msg>> conversations = Map();
static String myName = '';
static Map<String, dynamic> cache = Map();
static final GlobalKey<ScaffoldState> scaffoldKey =
GlobalKey<ScaffoldState>();
// Global({
// this.conversations = Map,
// });
void sentToConversations(Msg msg, String converser,
{bool addToTable = true}) {
if (conversations[converser] == null) {
conversations[converser] = {};
}
conversations[converser]![msg.id] = msg;
if (addToTable) {
insertIntoConversationsTable(msg, converser);
}
notifyListeners();
// First push the new message for one time when new message is sent
broadcast(scaffoldKey.currentContext!);
}

void receivedToConversations(dynamic decodedMessage, BuildContext context) {
if (conversations[decodedMessage['sender']] == null) {
conversations[decodedMessage['sender']] = Map();
}
if (conversations[decodedMessage['sender']] != null &&
!(conversations[decodedMessage['sender']]!
.containsKey(decodedMessage['id']))) {
conversations[decodedMessage['sender']]![decodedMessage["id"]] = Msg(
decodedMessage['message'],
"received",
decodedMessage['Timestamp'],
decodedMessage["id"],
);
insertIntoConversationsTable(
Msg(decodedMessage['message'], "received",
decodedMessage['Timestamp'], decodedMessage["id"]),
decodedMessage['sender']);
}

notifyListeners();
}

void updateDevices(List<Device> devices) {
this.devices = devices;
notifyListeners();
}

void updateConnectedDevices(List<Device> devices) {
this.connectedDevices = devices;
notifyListeners();
}
}
6 changes: 3 additions & 3 deletions lib/classes/Msg.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

/// Message model

class Msg {
String message;
String msgtype; //sent or received
String timestamp;
String ack='false';
String ack = 'false';
String id;
Msg(this.message, this.msgtype,this.timestamp,this.id);
Msg(this.message, this.msgtype, this.timestamp, this.id);
}
31 changes: 15 additions & 16 deletions lib/classes/Payload.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@

class Payload{
String id='';
String sender='';
String receiver='';
String message='';
String timestamp='';
bool broadcast=true;
String type='Payload';
Payload(this.id,this.sender,this.receiver,this.message,this.timestamp);

/// This is the model to transfer the message from one device to another.
class Payload {
String id = '';
String sender = '';
String receiver = '';
String message = '';
String timestamp = '';
bool broadcast = true;
String type = 'Payload';
Payload(this.id, this.sender, this.receiver, this.message, this.timestamp);
}
class Ack{
String id='';
String type="Ack";
Ack(this.id);

}
class Ack {
String id = '';
String type = "Ack";
Ack(this.id);
}
74 changes: 74 additions & 0 deletions lib/components/message_panel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/// This component is used in the ChatPage.
/// It is the message bar where the message is typed on and sent to
/// connected devices.
import 'package:flutter/material.dart';
import 'package:nanoid/nanoid.dart';
import 'package:provider/provider.dart';

import '../classes/Global.dart';
import '../classes/Msg.dart';
import '../classes/Payload.dart';
import '../database/DatabaseHelper.dart';

class MessagePanel extends StatefulWidget {
const MessagePanel({Key? key, required this.converser}) : super(key: key);
final String converser;

@override
State<MessagePanel> createState() => _MessagePanelState();
}

class _MessagePanelState extends State<MessagePanel> {
TextEditingController myController = TextEditingController();
@override
Widget build(BuildContext context) {
return TextFormField(
controller: myController,
decoration: InputDecoration(
icon: Icon(Icons.person),
hintText: 'Send Message?',
labelText: 'Send Message ',
suffixIcon: IconButton(
onPressed: () {
var msgId = nanoid(21);
var data = {
"sender": "$Global.myName",
"receiver": "$widget.device.deviceName",
"message": "$myController.text",
"id": "$msgId",
"Timestamp": "${DateTime.now().toUtc().toString()}",
"type": "Payload"
};
Global.cache[msgId] = Payload(
msgId,
Global.myName,
widget.converser,
myController.text,
DateTime.now().toUtc().toString(),
);
insertIntoMessageTable(
Payload(
msgId,
Global.myName,
widget.converser,
myController.text,
DateTime.now().toUtc().toString(),
),
);

Provider.of<Global>(context, listen: false).sentToConversations(
Msg(myController.text, "sent", data["Timestamp"]!, msgId),
widget.converser,
);

// refreshMessages();
myController.clear();
},
icon: Icon(
Icons.send,
),
),
),
);
}
}
Loading