Compare commits

...

56 Commits

Author SHA1 Message Date
Felix Hartmann (PEA3-Fe-FI)
e75385a69b fix typos 2021-09-24 10:08:04 +02:00
Felix Hartmann (PEA3-Fe-FI)
f5030c55c5 update README.md 2021-09-24 10:06:48 +02:00
Felix Hartmann (PEA3-Fe-FI)
2718864b5c add README.md 2021-09-24 10:04:56 +02:00
Felix Hartmann (PEA3-Fe-FI)
61cbd7fe74 Merge branch 'ConnectionController' 2021-09-24 09:15:02 +02:00
Felix Hartmann (PEA3-Fe-FI)
c00e4c6a01 merge master 2021-09-24 09:07:54 +02:00
Felix Hartmann (PEA3-Fe-FI)
125c908ef8 remove test code, add logo svg, add screenshots 2021-09-24 09:05:07 +02:00
Felix Hartmann (PEA3-Fe-FI)
ebaf831be7 set encryption keys 2021-09-24 09:05:04 +02:00
SCM6WE
1daaa52c36 Cleanup / Comments 2021-09-24 09:04:57 +02:00
Patrick Hellebrand
ba4d0b619e ChatMessages on THEEEEEEEEEEEEEEE RIGHT 2021-09-24 09:03:50 +02:00
Felix Hartmann (PEA3-Fe-FI)
31ffe86f04 remove unused variables 2021-09-24 09:03:48 +02:00
Felix Hartmann (PEA3-Fe-FI)
fd5cb984e2 dont open new chat window if client is already in list 2021-09-24 09:03:46 +02:00
Felix Hartmann (PEA3-Fe-FI)
f55c4a2b70 delete chat only on explicit button press, not on disconnect, dialog opening fixed 2021-09-24 09:03:38 +02:00
Patrick Hellebrand
ac67ff38c6 Message Alignment First Try 2021-09-24 08:59:59 +02:00
Patrick Hellebrand
5c4b4373d6 Added Themes + Toggle 2021-09-24 08:59:07 +02:00
Patrick Hellebrand
4c0413e7d8 removed ability to send empty messages 2021-09-24 08:59:05 +02:00
SCM6WE
5ce1316245 load chatlogs on newly created chat 2021-09-24 08:59:03 +02:00
SCM6WE
c3daaf8b00 Added method to delete userspeciffic logs. 2021-09-24 08:59:00 +02:00
SCM6WE
9141efd55a Propper file manager with encryption of files 2021-09-24 08:58:58 +02:00
Patrick Hellebrand
179ce2b1bb Dark Theme, added styling for messages 2021-09-24 08:58:57 +02:00
Patrick Hellebrand
59d4827965 removed test code for username reactivitiy 2021-09-24 08:58:55 +02:00
Felix Hartmann (PEA3-Fe-FI)
0d76ec30e2 only open dialog if there are no popups already open 2021-09-24 08:58:53 +02:00
SCM6WE
a8a07f44c3 brgin of encryption 2021-09-24 08:58:51 +02:00
SCM6WE
3cf0197672 stuff 2021-09-24 08:58:37 +02:00
Patrick Hellebrand
43d8b2919c Username change now dirty reactive in ui 2021-09-24 08:57:51 +02:00
Felix Hartmann (PEA3-Fe-FI)
7286b211bf tested build and deploy via apppackage, fixed typo in IP.cs 2021-09-24 08:57:49 +02:00
Patrick Hellebrand
c00a7ff379 Chats now only try to connect, if they are opened 2021-09-24 08:57:47 +02:00
SCM6WE
b12d3f3f4f quick 2021-09-24 08:57:40 +02:00
SCM6WE
e27141e013 fix connection establishment when loading files 2021-09-24 08:56:56 +02:00
Patrick Hellebrand
a953d34122 Removed timeStamp from SendMessage, added param Timestamp to savechat() 2021-09-24 08:54:59 +02:00
SCM6WE
eeea238398 Saving and loading but still has error(Pls fix) 2021-09-24 08:54:50 +02:00
Patrick Hellebrand
7e5883d761 Added BoardcastMessage, Username Changed event via Broadcast, remove json parsing from ChatMessage 2021-09-24 08:54:09 +02:00
Felix Hartmann (PEA3-Fe-FI)
fb098db63d fix ip in intial packet (send own ip, not foreign) 2021-09-24 08:54:07 +02:00
Felix Hartmann (PEA3-Fe-FI)
1b3d133657 allow deletion of chats which are not started by me 2021-09-24 08:54:05 +02:00
Felix Hartmann (PEA3-Fe-FI)
e1ea49bf71 stop connection if we are already connected 2021-09-24 08:53:57 +02:00
Patrick Hellebrand
92bc795aff Added OnIncomingMessages (for loading messages from json array) 2021-09-24 08:52:09 +02:00
Felix Hartmann (PEA3-Fe-FI)
55bd72b467 retry working, radiobuttons now triggering on every click, deleteChat Button working 2021-09-24 08:52:07 +02:00
Patrick Hellebrand
ea81547540 ConnectionFailedDialog -> Dialog for Success and Error Messages with heading, message and buttons/actions 2021-09-24 08:52:05 +02:00
Felix Hartmann (PEA3-Fe-FI)
e2de9f5917 add retry logic on disconnect, silently delete chat if disconnected after connect was succesfull 2021-09-24 08:52:03 +02:00
Patrick Hellebrand
6f2c442e94 small fix for correct ip display 2021-09-24 08:52:01 +02:00
Patrick Hellebrand
b42a2f9728 Fixed json formatting in SendMessage 2021-09-24 08:51:49 +02:00
Patrick Hellebrand
05e3e9e0c4 Added our default ip address, added ip as param to onMessage 2021-09-24 08:51:14 +02:00
Felix Hartmann (PEA3-Fe-FI)
e6e5bee4ef add outgoing connections to dict 2021-09-24 08:51:13 +02:00
Patrick Hellebrand
0f305a216e SendMessage is now Json 2021-09-24 08:51:02 +02:00
Felix Hartmann (PEA3-Fe-FI)
7135486810 add initial packet, close socket on disconnect, move server start to Controller.cs 2021-09-24 08:50:01 +02:00
Felix Hartmann (PEA3-Fe-FI)
0ef2158859 remove test code, add logo svg, add screenshots 2021-09-24 08:39:48 +02:00
Patrick Hellebrand
badbaf0b40 Merge branch 'ConnectionController' of https://sourcecode.socialcoding.bosch.com/scm/~hpl2fe/polychat into ConnectionController 2021-09-23 16:24:51 +02:00
Patrick Hellebrand
072e12d427 ChatMessages on THEEEEEEEEEEEEEEE RIGHT 2021-09-23 16:24:41 +02:00
Felix Hartmann (PEA3-Fe-FI)
f0d785cb13 set encryption keys 2021-09-23 16:22:38 +02:00
SCM6WE
0ca78d7861 Merge branch 'ConnectionController' of https://sourcecode.socialcoding.bosch.com/scm/~hpl2fe/polychat into ConnectionController 2021-09-23 16:07:50 +02:00
SCM6WE
323f4d5b5b Merge branch 'ConnectionController' of https://sourcecode.socialcoding.bosch.com/scm/~hpl2fe/polychat into ConnectionController
# Conflicts:
#	PolyChat/Controller.cs
2021-09-23 16:07:33 +02:00
Patrick Hellebrand
3b4ca6caa3 Merged Theming with AsyncDialogs 2021-09-23 16:06:55 +02:00
Patrick Hellebrand
0a1ff66e38 Message Alignment First Try 2021-09-23 16:05:20 +02:00
SCM6WE
88e5d3a329 Cleanup / Comments 2021-09-23 16:03:12 +02:00
Patrick Hellebrand
de2d135fdf Added Themes + Toggle 2021-09-23 15:31:30 +02:00
Patrick Hellebrand
15679951bc removed ability to send empty messages 2021-09-23 14:54:25 +02:00
SCM6WE
08325b1c65 Network debugging 2021-09-22 12:57:46 +02:00
16 changed files with 619 additions and 116 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -5,18 +5,10 @@ using System.Net;
using SocketIOSharp.Server;
using SocketIOSharp.Server.Client;
using PolyChat.Models;
using System.IO;
using System.Threading;
using System;
using System.Text;
using System.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
namespace PolyChat
{
// 10.1.211.26 Marc
// 10.1.218.90 Felix
// 10.4.141.77 Pat
@@ -37,13 +29,13 @@ namespace PolyChat
public Controller(MainPage uiController)
{
UIController = uiController;
fileManager = new FileManager(uiController);
fileManager = new FileManager(this);
fileManager.loadChats();
Serve();
// test
/*
UIController.OnIncomingConnection("1.1.1.1");
UIController.OnIncomingConnection("localhost");
UIController.OnIncomingConnection("1.2.3.4");
UIController.OnIncomingConnection("1.2.4.8");
*/
@@ -65,6 +57,9 @@ namespace PolyChat
}
/// <summary>
/// starts server for clients to connect to
/// </summary>
private void Serve()
{
Debug.WriteLine("--- Controller.Serve ---");
@@ -107,6 +102,12 @@ namespace PolyChat
}
}
/// <summary>
/// Sends message to given ip
/// </summary>
/// <param name="ip"></param>
/// <param name="type"></param>
/// <param name="content"></param>
public void SendMessage(string ip, string type, string content)
{
Debug.WriteLine("--- Controller.SendMessage ---");
@@ -122,6 +123,11 @@ namespace PolyChat
fileManager.saveChats(ip, json.ToString(), DateTime.Now);
}
/// <summary>
/// if We recieve a message this method gets triggert
/// </summary>
/// <param name="ip">ip from sender</param>
/// <param name="data">String that is send</param>
private void OnMessage(string ip, JToken[] data)
{
Debug.WriteLine("--- Controller.OnMessage ---");
@@ -135,6 +141,12 @@ namespace PolyChat
else Debug.WriteLine("Undefined: " + data);
}
/// <summary>
/// Closes chat connection
/// </summary>
/// <param name="IP">ip of user to be closed</param>
/// <param name="wasConnected"></param>
/// <param name="delete"></param>
public void CloseChat(string IP, bool wasConnected = true, bool delete = false)
{
Debug.WriteLine($"Deleting connection with IP:{IP}");
@@ -149,6 +161,17 @@ namespace PolyChat
fileManager.deleteChat(IP);
}
/// <summary>
/// sends incoming message to ui
/// </summary>
/// <param name="ip">ip of client that send the message</param>
/// <param name="jsonArr">the json array that is ti be displayed in th gui</param>
public void SendIncomingMessageUI(String ip, String jsonArr)
{
UIController.OnIncomingConnection(ip);
UIController.OnIncomingMessages(ip, jsonArr);
}
private void CloseChatUI(string IP, bool wasConnected = true, bool delete = false)
{
UIController.OnChatPartnerDeleted(IP);
@@ -166,6 +189,10 @@ namespace PolyChat
return Connections.ContainsKey(ip) && Connections[ip].IsConnected();
}
/// <summary>
/// returns your own ip that starts with 10. becuase that is our subnet
/// </summary>
/// <returns></returns>
public static string getIP()
{
IPHostEntry ipEntry = Dns.GetHostEntry(Dns.GetHostName());
@@ -180,11 +207,5 @@ namespace PolyChat
return null;
}
private void encode(string json)
{
String ecryptetText = FileManager.encrypt(json);
Debug.WriteLine(ecryptetText);
Debug.WriteLine(FileManager.decrypt(ecryptetText));
}
}
}

View File

@@ -6,17 +6,18 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:PolyChat.Models"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" RequestedTheme="Dark">
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="224"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- LEFT SIDE -->
<Grid Grid.Column="0" Margin="16">
<Grid Grid.Column="0" Padding="16" Background="{ThemeResource SystemChromeMediumColor}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- CONNECTION HEADER -->
<StackPanel HorizontalAlignment="Stretch" Spacing="8" Margin="0 0 0 8">
@@ -37,7 +38,7 @@
<TextBlock Text="Connect to" Foreground="{ThemeResource SystemColorDisabledTextColor}"/>
<TextBlock x:Name="ipAddress" Grid.Column="1"/>
</Grid>
<Border BorderThickness="1" BorderBrush="{ThemeResource AppBarBorderThemeBrush}"/>
<Border BorderThickness="1" BorderBrush="{ThemeResource SystemControlBackgroundListLowBrush}"/>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@@ -55,12 +56,8 @@
<DataTemplate x:DataType="models:ChatPartner">
<RadioButton GroupName="chatSelect" Tag="{x:Bind Code}" HorizontalAlignment="Stretch" Height="64" Click="OnChatPartnerSelected">
<StackPanel x:Name="ChatPartner" VerticalAlignment="Center" HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Name}"/>
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text=" ("/>
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text="{x:Bind Code}"/>
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text=")"/>
</StackPanel>
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Name}"/>
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text="{x:Bind Code}"/>
<!--
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Messages.Last().toString()}"/>
@@ -73,6 +70,7 @@
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
<Button Grid.Row="2" Click="OnToggleTheme" Content="Toggle Theme"/>
</Grid>
<TextBlock x:Name="textNoChatSelected" Grid.Column="1" Text="No Chat Selected" Foreground="{ThemeResource SystemColorDisabledTextColor}" FontSize="24" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!-- RIGHT SIDE -->
@@ -98,12 +96,16 @@
<!-- CHAT -->
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
<ListView x:Name="listViewMessages" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="4 16">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:ChatMessage">
<StackPanel x:Name="Message" MaxWidth="320" Margin="0 4" Padding="16 8" CornerRadius="4" Background="{ThemeResource SystemAccentColor}">
<TextBlock Text="{x:Bind Content}" Foreground="{ThemeResource SystemAltHighColor}" TextWrapping="WrapWholeWords" FontSize="14"/>
<TextBlock Text="{x:Bind TimeStamp.ToString()}" Foreground="{ThemeResource SystemAltMediumColor}"/>
<TextBlock Text="{x:Bind Foreign}" Foreground="{ThemeResource SystemAltMediumLowColor}" FontStyle="Italic" />
<StackPanel HorizontalAlignment="{x:Bind Align}" x:Name="Message" MaxWidth="320" Margin="0 4" Padding="16 8" CornerRadius="4" Background="{ThemeResource SystemAccentColor}">
<TextBlock Text="{x:Bind Content}" Foreground="{ThemeResource SystemAltHighColor}" TextWrapping="WrapWholeWords" FontSize="14"/>
<TextBlock Text="{x:Bind TimeStamp.ToString()}" Foreground="{ThemeResource SystemAltMediumColor}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>

View File

@@ -26,6 +26,7 @@ namespace PolyChat
private ObservableCollection<ChatPartner> Partners;
private ChatPartner selectedPartner = null;
private string username;
private static ElementTheme Theme = ElementTheme.Light;
public MainPage()
{
@@ -35,6 +36,9 @@ namespace PolyChat
// ui variables
ipAddress.Text = IP.GetCodeFromIP(Controller.getIP());
Partners = new ObservableCollection<ChatPartner>();
// theming
RequestedTheme = Theme;
// updated placeholder
updateNoChatsPlaceholder();
updateNoUsernamePlaceholder();
updateNoChatSelected();
@@ -74,7 +78,7 @@ namespace PolyChat
public void OnSendMessage(object sender = null, RoutedEventArgs e = null)
{
selectedPartner.AddMessage(new ChatMessage(username, "message", inputSend.Text));
selectedPartner.AddMessage(new ChatMessage(username, "message", inputSend.Text, DateTime.Now, false));
Controller.SendMessage(selectedPartner.Code, "message", inputSend.Text);
// clear input
inputSend.Text = "";
@@ -85,10 +89,10 @@ namespace PolyChat
// test
/*
OnIncomingMessage(
"1.1.1.1",
"localhost",
new JObject(
new JProperty("type", "username"),
new JProperty("content", "Cloudflare")
new JProperty("type", "message"),
new JProperty("content", "Test")
).ToString(),
DateTime.Now
);
@@ -159,7 +163,7 @@ namespace PolyChat
Partners.Insert(index, sendingPartner);
break;
default:
sendingPartner.AddMessage(new ChatMessage(origin, type, content, timeStamp));
sendingPartner.AddMessage(new ChatMessage(origin, type, content, timeStamp, true));
break;
}
});
@@ -176,15 +180,15 @@ namespace PolyChat
new ChatMessage(
origin,
item["type"].ToString(),
item["content"].ToString()//,
//DateTime.Parse(item["timestamp"].ToString())
item["content"].ToString(),
DateTime.Parse(item["timestamp"].ToString()),
false // TODO: FIX !!!!
)
);
}
});
}
private void OnDeleteChat(object sender = null, RoutedEventArgs e = null)
{
Controller.CloseChat(selectedPartner.Code,delete: true);
@@ -213,35 +217,31 @@ namespace PolyChat
if (!Controller.IsConnected(code)) Controller.Connect(code);
}
public void OnToggleTheme(object sender, RoutedEventArgs e)
{
Theme = Theme == ElementTheme.Light ? ElementTheme.Dark : ElementTheme.Light;
RequestedTheme = Theme;
}
private void OnKeyUp(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
{
updateSendButtonEnabled();
if (e.Key == Windows.System.VirtualKey.Enter)
if (buttonSend.IsEnabled && e.Key == Windows.System.VirtualKey.Enter)
{
OnSendMessage();
}
}
public static IAsyncOperation<ContentDialogResult> SafelyOpenDialog(Dialog d)
public static IAsyncOperation<ContentDialogResult> SafelyOpenDialog(ContentDialog d)
{
if(VisualTreeHelper.GetOpenPopups(Window.Current).Count == 0)
return d.ShowAsync();
return null;
}
public static IAsyncOperation<ContentDialogResult> SafelyOpenDialog(NewChatDialog d)
{
if (VisualTreeHelper.GetOpenPopups(Window.Current).Count == 0)
return d.ShowAsync();
return null;
}
// GETTERS
public static IAsyncOperation<ContentDialogResult> SafelyOpenDialog(EditUsernameDialog d)
{
if (VisualTreeHelper.GetOpenPopups(Window.Current).Count == 0)
return d.ShowAsync();
return null;
}
public static ElementTheme GetTheme() => Theme;
// UPDATE FUNCTIONS FOR UI PLACEHOLDERS

View File

@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Text.Json;
using Windows.UI.Xaml;
namespace PolyChat.Models
{
@@ -10,38 +11,23 @@ namespace PolyChat.Models
public string Type;
public string Content;
public DateTime TimeStamp;
public readonly bool Foreign;
public HorizontalAlignment Align;
private bool Foreign;
/// <summary>
/// Create own Message (directly sent)
/// </summary>
/// <param name="origin">My IP</param>
/// <param name="type">Message Type</param>
/// <param name="content">Message Content (not JSON)</param>
public ChatMessage(string origin, string type, string content)
{
Origin = origin;
TimeStamp = DateTime.Now;
Type = type;
Content = content;
// TODO
Foreign = false;
Debug.WriteLine("Created Message: " + ToString());
}
/// <summary>
/// Create Message loaded with timestamp
/// Create Message
/// </summary>
/// <param name="origin">Origin IP</param>
/// <param name="type">Message Type, usually "message"</param>
/// <param name="content">Message Content, usually plain text</param>
/// <param name="timeStamp">Parsed DateTime</param>
public ChatMessage(string origin, string type, string content, DateTime timeStamp, bool foreign = false)
public ChatMessage(string origin, string type, string content, DateTime timeStamp, bool foreign)
{
Origin = origin;
TimeStamp = timeStamp;
Type = type;
Content = content;
Align = foreign ? HorizontalAlignment.Right : HorizontalAlignment.Left;
Foreign = foreign;
Debug.WriteLine("Created Loaded Message: " + ToString());
}

156
PolyChat/Models/Client.cs Normal file
View File

@@ -0,0 +1,156 @@
using System;
using SocketIOSharp.Common;
using SocketIOSharp.Client;
using SocketIOSharp.Server.Client;
using Json.Net;
using System.Threading;
using PolyChat.Models.Exceptions;
using System.Diagnostics;
namespace PolyChat.Models
{
class Client
{
private SocketIOClient connection_client = null;
private SocketIOSocket connection_server = null;
private Boolean connected = true;
private String ipSelf;
public Client(SocketIOClient connection, String ip, MainPage uiController)
{
this.ipSelf = ip;
this.connection_client = connection;
InitEventHandlers(this, connection, uiController);
}
/// <summary>
/// Called when socket accepts client
/// </summary>
/// <param name="connection"></param>
/// <param name="ip"></param>
/// <param name="uiController"></param>
public Client(SocketIOSocket connection, String ip, MainPage uiController)
{
Debug.WriteLine("New Client Saved!!!!(Clinent[34])");
this.ipSelf = ip;
this.connection_server = connection;
InitEventHandlers(this, connection, uiController);
}
//Sending
//===================================================================================
/// <summary>
/// converts String message into json file and sends it to the server.
/// </summary>
/// <remarks>
/// gets called by gui if someone wants to send Message
/// </remarks>
/// <param name="sender">Sender of Message</param>
/// <param name="chatMessage">the accual text the user wants to send</param>
/// <param name="timestamp">current time</param>
public void sendMessage(SendCode code, String chatMessage)
{
new Thread(() =>
{
Debug.WriteLine($"connected is {connected}");
//create msg
Message msg = new Message(chatMessage, false, ipSelf);
//convert msg
String petJson = JsonNet.Serialize(msg);
//wait if not connected and send msg
int i=0;
int sleeptimer = 2000;
while(!this.connected)
{
Thread.Sleep(sleeptimer);
i++;
if(i>=10)
{
throw new MessageTimedOutException(i*sleeptimer);
}
}
if (connection_client != null)
{
connection_client.Emit(code.ToString(), petJson);
}else if (connection_server != null)
{
connection_server.Emit(code.ToString(), petJson);
}
}).Start();
}
//==================================================================================
//EventHandeling
//===================================================================================
/// <summary>
/// handles all events of client
/// </summary>
/// <param name="client">self</param>
/// <param name="connection"></param>
private static void InitEventHandlers(Client client, SocketIOClient connection, MainPage uiController)
{
connection.On(SendCode.Message.ToString(), (Data) =>
{
//Message msg = new Message(Data[0]);
Debug.WriteLine("Normal Message Recieved!!!!");
Message msg = JsonNet.Deserialize<Message>(Data[0].ToString());
uiController.OnIncomingMessage(msg);
//TODO: send message to GUI
});
connection.On(SendCode.Command.ToString(), (Data) =>
{
Console.WriteLine("Command recieved!" + Data[0]);
});
connection.On(SocketIOEvent.CONNECTION, () =>
{
client.connected = true;
});
}
/// <summary>
/// handles all events of server
/// </summary>
/// <param name="client">self</param>
/// <param name="connection"></param>
private static void InitEventHandlers(Client client, SocketIOSocket connection, MainPage uiController)
{
connection.On(SendCode.Message.ToString(), (Data) =>
{
Debug.WriteLine("Normal Message Recieved!!!!");
Message msg = JsonNet.Deserialize<Message>(Data[0].ToString());
//Message msg = new Message(Data[0]);
uiController.OnIncomingMessage(msg);
//TODO: send message to GUI
});
connection.On(SendCode.Command.ToString(), (Data) =>
{
Console.WriteLine("Command recieved!" + Data[0]);
});
client.connected = true;
}
//==================================================================================
//Getter and Setter
//==================================================================================
public String getIP()
{
return this.ipSelf;
}
public Boolean isConnected()
{
return this.connected;
}
}
}

View File

@@ -14,13 +14,21 @@ namespace PolyChat.Models
class FileManager
{
// Controller
private readonly MainPage UIController;
private readonly Controller controller;
public FileManager(MainPage uiController)
//===============================================================================================================================================
//Constructor
//===============================================================================================================================================
public FileManager(Controller controller)
{
UIController = uiController;
this.controller = controller;
}
//===============================================================================================================================================
// editing save files
//===============================================================================================================================================
/// <summary>
/// deletes chatlog of one speciffic user
/// </summary>
@@ -59,14 +67,13 @@ namespace PolyChat.Models
if (File.Exists($"U:\\PolyChat\\Saves\\{ip}.txt"))
{
String jsonArr = decrypt(File.ReadAllText($"U:\\PolyChat\\Saves\\{ip}.txt"));
UIController.OnIncomingConnection(ip);
UIController.OnIncomingMessages(ip, jsonArr);
controller.SendIncomingMessageUI(ip, jsonArr);
}
}
}
/// <summary>
/// sends chatlogs as json array to uiController wit corrosponding ip
/// sends chatlogs as json array to uiController with corrosponding ip
///
/// in ui when chat is clicked connection gets established
/// </summary>
@@ -97,22 +104,18 @@ namespace PolyChat.Models
ip = ip.Substring(0, ip.Length - 4);
Debug.WriteLine($"-{ip}");
Debug.WriteLine(jsonArr);
UIController.OnIncomingConnection(ip);
UIController.OnIncomingMessages(ip, jsonArr);
controller.SendIncomingMessageUI(ip, jsonArr);
}
}
}
/// <summary>
/// Saves incoming chat message to
/// Saves incoming chat message to U:\PolyChat\Saves\ip.txt
/// </summary>
/// <param name="ip"></param>
/// <param name="json"></param>
public void saveChats(string ip, string json, DateTime timeStamp)
{
//Vielleicht noch so machen dass die mit gleicher ip nacheinander gemacht
//werden damit es nicht zu überschreibungen kommt vielleicth auch ganz oben oder am ende ne
//writing flag setzen oder auch in der datei selbst ne flag setzen
new Thread(() =>
{
//breaking if namechange
@@ -120,39 +123,39 @@ namespace PolyChat.Models
if (!obj["type"].ToString().Equals("username"))
{
//adding timestamp
obj = JObject.Parse(json);
obj.Add(new JProperty("timestamp", timeStamp));
json = obj.ToString();
if (File.Exists($"U:\\PolyChat\\Saves\\{ip}.txt"))
{
Debug.WriteLine("--File allready exists--");
//check for integraty of file
string output = decrypt(File.ReadAllText($"U:\\PolyChat\\Saves\\{ip}.txt"));
Debug.WriteLine($"---{output}---");
if (output.Substring(0, 1).Equals("[") && output.Substring(output.Length - 1, 1).Equals("]"))
{
Debug.WriteLine("--adding new chatmessage--");
//structure intact
//save new chat
String saved = output.Substring(0, output.Length - 1);
output = saved + ", " + json + " ]";
Debug.WriteLine("--adding new chatmessage--");
output = output.Substring(0, output.Length - 1) + ", " + json + " ]"; //rip appart and put file back together
File.Delete($"U:\\PolyChat\\Saves\\{ip}.txt");
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt(output));
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt(output)); //encrypt and save to textfile
}
else
{
Debug.WriteLine("--Structure not intact--");
Debug.WriteLine("--redoing file--");
//structure not intact
//redo file
Debug.WriteLine("--Structure not intact--");
Debug.WriteLine("--redoing file--");
File.Delete($"U:\\PolyChat\\Saves\\{ip}.txt");
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt($"[ {json} ]"));
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt($"[ {json} ]")); //encrypt and write to file
}
}
else
{
Debug.WriteLine("--Creating new File--");
//setup file
Debug.WriteLine("--Creating new File--");
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt($"[ {json} ]"));
}
}
@@ -160,28 +163,35 @@ namespace PolyChat.Models
}
//---------------------------------------------------------------------------------------------------
//security
//---------------------------------------------------------------------------------------------------
private void genKeys()
{
//===============================================================================================================================================
// Encryption
//===============================================================================================================================================
/// <summary>
/// generates keypair [public, privte] (100% secure, trust me)
/// </summary>
/// <returns></returns>
private String[] genKeys()
{
return new String[] {"12345678", "12345678" };
}
/// <summary>
/// does exactly what it says. XD
///
/// encrypts given string and returns unreadable string
/// </summary>
/// <param name="toEncrypt"></param>
/// <returns></returns>
public static String encrypt(String toEncrypt)
private String encrypt(String toEncrypt)
{
try
{
string textToEncrypt = toEncrypt;
string ToReturn = "";
string publickey = "santhosh";
string secretkey = "engineer";
string publickey = genKeys()[0];
string secretkey = genKeys()[1];
byte[] secretkeyByte = { };
secretkeyByte = System.Text.Encoding.UTF8.GetBytes(secretkey);
byte[] publickeybyte = { };
@@ -203,22 +213,23 @@ namespace PolyChat.Models
{
throw new Exception(ex.Message, ex.InnerException);
}
}
/// <summary>
/// does exactly what it says. XD
///
/// takes in unreadable string and returns infirmation
/// </summary>
/// <param name="toEncrypt"></param>
/// <returns></returns>
public static String decrypt(String toDecrypt)
private String decrypt(String toDecrypt)
{
try
{
string textToDecrypt = toDecrypt;
string ToReturn = "";
string publickey = "santhosh";
string privatekey = "engineer";
string publickey = genKeys()[0];
string privatekey = genKeys()[1];
byte[] privatekeyByte = { };
privatekeyByte = System.Text.Encoding.UTF8.GetBytes(privatekey);
byte[] publickeybyte = { };
@@ -244,10 +255,4 @@ namespace PolyChat.Models
}
}
}
}

View File

@@ -0,0 +1,62 @@
using Json.Net;
using Newtonsoft.Json.Linq;
using System;
namespace PolyChat.Models
{
public class Message
{
public readonly string Sender;
public readonly DateTime Timestamp = new DateTime(1970, 01, 01);
public readonly string Msg = "empty";
public readonly string Ip;
public readonly bool Foreign;
public readonly string StringTimeStamp;
/// <summary>
/// create new Message object from parameters
/// </summary>
/// <param name="Msg"></param>
/// <param name="Foreign"></param>
/// <param name="Sender"></param>
/// <param name="Ip"></param>
public Message(string Msg = "", bool Foreign = true, string Sender= "Unknown", string Ip = "127.0.0.1")
{
this.Sender = Sender;
this.Timestamp = DateTime.Now;
StringTimeStamp = Timestamp.ToString();
this.Msg = Msg;
this.Foreign = Foreign;
this.Ip = Ip;
}
/// <summary>
/// create new Message object from JToken (json)
/// </summary>
/// <param name="data"></param>
public Message(JToken data)
{
Message m = (Message) data.ToObject<Message>();
Sender = m.Sender;
Timestamp = m.Timestamp;
StringTimeStamp = Timestamp.ToString();
Msg = m.Msg;
Ip = m.Ip;
Foreign = m.Foreign;
}
public Message()
{
}
override
public string ToString()
{
string prefix = Foreign ? "Other" : "Me";
return $"{prefix}: {Msg}({Sender})";
}
}
}

View File

@@ -0,0 +1,127 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
using SocketIOSharp.Client;
using EngineIOSharp.Common.Enum;
using System.Net;
using PolyChat.Models.Exceptions;
//dependencies for server functionality
using SocketIOSharp.Server;
using SocketIOSharp.Server.Client;
using Newtonsoft.Json.Linq;
using System.Threading;
using Json.Net;
namespace PolyChat.Models
{
class NetworkingController
{
public List<Client> clients = new List<Client>();
private String ownName = "";
private IPAddress ownIP;
private readonly ushort Port;
private SocketIOServer Server;
private readonly MainPage uiController;
public NetworkingController (MainPage uiController, ushort Port = 8050)
{
this.uiController = uiController;
this.Port = Port;
ownIP = getIP();
startServer();
}
//EXTERNAL METHODS
//=========================================================================================================================================================================================
/// <summary>
/// connects self to server with given ip
/// </summary>
/// <param name="ip"> server to connect to </param>
public void connectNewClient(String ip)
{
SocketIOClient connection = new SocketIOClient(new SocketIOClientOption(EngineIOScheme.http, ip, 8050));
connection.Connect();
clients.Add(new Client(connection, ip, uiController));
}
/// <summary>
/// handle incomming connection
/// </summary>
/// <param name="ip"> server to connect to </param>
private void connectNewClient(SocketIOSocket socket)
{
socket.On(SendCode.Initial.ToString(), (JToken[] Data) =>
{
Debug.WriteLine("Client connected and Initial Message Recieved!!!!!!!!!!!!!!!!!");
Message msg = JsonNet.Deserialize<Message>(Data[0].ToString());
clients.Add(new Client(socket,msg.Ip, uiController));
});
}
/// <summary>
/// sends Message to given ip
/// </summary>
/// <param name="ip"> partner to send to </param>
/// <param name="msg"> to send </param>
public void sendMessage(String ip, String msg)
{
this.getClient(ip).sendMessage(SendCode.Message, msg);
}
/// <summary>
/// returns own ip adress
/// </summary>
/// <returns></returns>
public IPAddress getIP()
{
IPHostEntry ipEntry = Dns.GetHostEntry(Dns.GetHostName());
IPAddress[] addrList = ipEntry.AddressList;
for (short i = 0; i < addrList.Length; i++)
{
if (addrList[i].ToString().Substring(0, 3).Equals("10."))
{
return addrList[i];
}
}
return null;
}
public MainPage getUIController()
{
return this.uiController;
}
//=========================================================================================================================================================================================
//INTERNAL METHODS
//=========================================================================================================================================================================================
private void startServer()
{
Server = new SocketIOServer(new SocketIOServerOption(Port));
Server.OnConnection((socket) => connectNewClient(socket));
Server.Start();
Debug.WriteLine($"Your ip is: {ownIP}");
Debug.WriteLine($"Server started, binding to port {Port}, waiting for connection...");
}
/// <summary>
/// returns client that fit to ip address
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
private Client getClient(String ip)
{
foreach (Client cl in clients)
{
if (cl.getIP().Equals(ip))
{
return cl;
}
}
return null;
}
}
}

View File

@@ -5,7 +5,11 @@
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
IgnorableNamespaces="uap mp uap3">
xmlns:uap6="http://schemas.microsoft.com/appx/manifest/uap/windows10/6"
xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
IgnorableNamespaces="uap mp uap3 uap6 iot uap4 uap2">
<Identity
Name="ee2ef4f2-e61b-497a-8f0e-9fa7c90234b1"
@@ -45,7 +49,42 @@
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<Capability Name="internetClientServer"/>
<Capability Name="allJoyn"/>
<uap:Capability Name="appointments"/>
<uap3:Capability Name="backgroundMediaPlayback"/>
<uap:Capability Name="blockedChatMessages"/>
<uap:Capability Name="chat"/>
<Capability Name="codeGeneration"/>
<uap:Capability Name="contacts"/>
<uap:Capability Name="enterpriseAuthentication"/>
<uap6:Capability Name="graphicsCapture"/>
<iot:Capability Name="lowLevelDevices"/>
<uap:Capability Name="musicLibrary"/>
<uap:Capability Name="objects3D"/>
<uap4:Capability Name="offlineMapsManagement"/>
<uap:Capability Name="phoneCall"/>
<uap2:Capability Name="phoneCallHistoryPublic"/>
<uap:Capability Name="picturesLibrary"/>
<Capability Name="privateNetworkClientServer"/>
<uap3:Capability Name="remoteSystem"/>
<uap:Capability Name="removableStorage"/>
<uap:Capability Name="sharedUserCertificates"/>
<uap2:Capability Name="spatialPerception"/>
<iot:Capability Name="systemManagement"/>
<uap:Capability Name="userAccountInformation"/>
<uap3:Capability Name="userNotificationListener"/>
<uap:Capability Name="videosLibrary"/>
<uap:Capability Name="voipCall"/>
<uap4:Capability Name="userDataTasks"/>
<DeviceCapability Name="bluetooth"/>
<DeviceCapability Name="gazeInput"/>
<DeviceCapability Name="lowLevel"/>
<DeviceCapability Name="microphone"/>
<DeviceCapability Name="location"/>
<DeviceCapability Name="pointOfService"/>
<DeviceCapability Name="proximity"/>
<DeviceCapability Name="webcam"/>
</Capabilities>
</Package>

View File

@@ -34,6 +34,7 @@ namespace PolyChat.Views
// TODO: use event handlers and asign actions here
Primary = primary.Action;
Secondary = secondary.Action;
RequestedTheme = MainPage.GetTheme();
}
private void setType(string type, string message)

View File

@@ -22,6 +22,7 @@ namespace PolyChat.Views
if (initialValue == null || initialValue.Length == 0) IsSecondaryButtonEnabled = false;
else input.Text = initialValue;
validate();
RequestedTheme = MainPage.GetTheme();
}
public string getValue()

View File

@@ -20,6 +20,7 @@ namespace PolyChat.Views
{
this.InitializeComponent();
IsPrimaryButtonEnabled = false;
RequestedTheme = MainPage.GetTheme();
}
public string getValue()

20
README.md Normal file
View File

@@ -0,0 +1,20 @@
# Polychat
![Logo](PolyChat/Assets/polychat_logo.svg "Logo")
serverless chat app written in c# using [`SocketIOSharp`](https://github.com/uhm0311/SocketIOSharp) & `UWP`
### Features:
- chat is not dependent on server, every client can be a server
- chatpartner discovery over ip address
- set username to be shown to chatpartners
- save chat history to local disk (encrypted)
- dark mode ;)
### Implentation:
- network connection via the library [`SocketIOSharp`](https://github.com/uhm0311/SocketIOSharp)
- graphical user interface uses `UWP` (Universal Windows App)
- messages are sent via json
- chat history gets saved as json after encryption
### Screenshots:
![light mode](screenshots/polychat_light.PNG "light mode")
![dark mode](screenshots/polychat_dark.PNG "dark mode")

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB