Browse Source

Release

master
ocsnetworks 5 months ago
commit
62ba6ee1e4
  1. 40
      .gitignore
  2. 96
      Build/Build.ps1
  3. BIN
      Home_Screenshot.png
  4. BIN
      Home_about2012.png
  5. 21
      LICENSE
  6. 31
      Libraries/Plugins/NAudio-license.txt
  7. 1
      Libraries/Plugins/Readme.txt
  8. 9
      Libraries/Speex/libspeex-license.txt
  9. BIN
      Libraries/Speex/libspeexdsp.dll
  10. 25
      Readme.md
  11. 1
      Scripts/ConnectionString.txt
  12. 87
      Scripts/SquiggleHistory.sql
  13. 5
      Shared/AssemblyInfo.ApiVersion.cs
  14. 11
      Shared/AssemblyInfo.Copyright.cs
  15. 5
      Shared/AssemblyInfo.Version.cs
  16. 28
      Squiggle.Bridge/App.config
  17. 144
      Squiggle.Bridge/BridgeHost.cs
  18. 41
      Squiggle.Bridge/Configuration/BridgeConfiguration.cs
  19. 45
      Squiggle.Bridge/Configuration/PresenceBinding.cs
  20. 30
      Squiggle.Bridge/Configuration/Target.cs
  21. 32
      Squiggle.Bridge/Configuration/TargetCollection.cs
  22. 17
      Squiggle.Bridge/Message.cs
  23. 15
      Squiggle.Bridge/Messages/ForwardChatMessage.cs
  24. 31
      Squiggle.Bridge/Messages/ForwardPresenceMessage.cs
  25. 45
      Squiggle.Bridge/PresenceMessageInspector.cs
  26. 20
      Squiggle.Bridge/Program.cs
  27. 60
      Squiggle.Bridge/ProjectInstaller.Designer.cs
  28. 14
      Squiggle.Bridge/ProjectInstaller.cs
  29. 129
      Squiggle.Bridge/ProjectInstaller.resx
  30. 26
      Squiggle.Bridge/Properties/AssemblyInfo.cs
  31. 58
      Squiggle.Bridge/RouteTable.cs
  32. 135
      Squiggle.Bridge/Squiggle.Bridge.csproj
  33. 194
      Squiggle.Bridge/SquiggleBridge.cs
  34. 40
      Squiggle.Bridge/SquiggleBridgeService.Designer.cs
  35. 62
      Squiggle.Bridge/SquiggleBridgeService.cs
  36. 123
      Squiggle.Bridge/SquiggleBridgeService.resx
  37. 4
      Squiggle.Bridge/packages.config
  38. 15
      Squiggle.Client/Activities/IFileTransferHandler.cs
  39. 16
      Squiggle.Client/Activities/IVoiceChatHandler.cs
  40. 24
      Squiggle.Client/Activities/SquiggleActivities.cs
  41. 154
      Squiggle.Client/BroadcastChat.cs
  42. 125
      Squiggle.Client/Buddy.cs
  43. 136
      Squiggle.Client/BuddyList.cs
  44. 281
      Squiggle.Client/Chat.cs
  45. 105
      Squiggle.Client/ChatBuddies.cs
  46. 274
      Squiggle.Client/ChatClient.cs
  47. 26
      Squiggle.Client/Properties/AssemblyInfo.cs
  48. 140
      Squiggle.Client/Squiggle.Client.csproj
  49. 224
      Squiggle.Core/Chat/Activity/ActivityExecutor.cs
  50. 72
      Squiggle.Core/Chat/Activity/ActivitySession.cs
  51. 98
      Squiggle.Core/Chat/ChatService.cs
  52. 382
      Squiggle.Core/Chat/ChatSession.cs
  53. 77
      Squiggle.Core/Chat/ChatSessionCollection.cs
  54. 241
      Squiggle.Core/Chat/Transport/Host/ChatHost.cs
  55. 95
      Squiggle.Core/Chat/Transport/Host/ChatHostExtensions.cs
  56. 43
      Squiggle.Core/Chat/Transport/Message.cs
  57. 13
      Squiggle.Core/Chat/Transport/Messages/ActivityCancelMessage.cs
  58. 15
      Squiggle.Core/Chat/Transport/Messages/ActivityDataMessage.cs
  59. 13
      Squiggle.Core/Chat/Transport/Messages/ActivityInviteAcceptMessage.cs
  60. 24
      Squiggle.Core/Chat/Transport/Messages/ActivityInviteMessage.cs
  61. 13
      Squiggle.Core/Chat/Transport/Messages/BuzzMessage.cs
  62. 20
      Squiggle.Core/Chat/Transport/Messages/ChatInviteMessage.cs
  63. 13
      Squiggle.Core/Chat/Transport/Messages/ChatJoinMessage.cs
  64. 13
      Squiggle.Core/Chat/Transport/Messages/ChatLeaveMessage.cs
  65. 13
      Squiggle.Core/Chat/Transport/Messages/GiveSessionInfoMessage.cs
  66. 12
      Squiggle.Core/Chat/Transport/Messages/IMessageHasParticipants.cs
  67. 20
      Squiggle.Core/Chat/Transport/Messages/SessionInfoMessage.cs
  68. 40
      Squiggle.Core/Chat/Transport/Messages/TextMessage.cs
  69. 17
      Squiggle.Core/Chat/Transport/Messages/UpdateTextMessage.cs
  70. 13
      Squiggle.Core/Chat/Transport/Messages/UserTypingMessage.cs
  71. 16
      Squiggle.Core/DefaultValues.cs
  72. 11
      Squiggle.Core/OperationFailedException.cs
  73. 113
      Squiggle.Core/Presence/BuddyProperties.cs
  74. 163
      Squiggle.Core/Presence/KeepAliveService.cs
  75. 144
      Squiggle.Core/Presence/PresenceService.cs
  76. 17
      Squiggle.Core/Presence/PresenceServiceOptions.cs
  77. 47
      Squiggle.Core/Presence/Transport/Message.cs
  78. 18
      Squiggle.Core/Presence/Transport/Messages/GiveUserInfoMessage.cs
  79. 16
      Squiggle.Core/Presence/Transport/Messages/HelloMessage.cs
  80. 13
      Squiggle.Core/Presence/Transport/Messages/HiMessage.cs
  81. 10
      Squiggle.Core/Presence/Transport/Messages/KeepAliveMessage.cs
  82. 10
      Squiggle.Core/Presence/Transport/Messages/LoginMessage.cs
  83. 10
      Squiggle.Core/Presence/Transport/Messages/LogoutMessage.cs
  84. 71
      Squiggle.Core/Presence/Transport/Messages/PresenceMessage.cs
  85. 18
      Squiggle.Core/Presence/Transport/Messages/UserInfoMessage.cs
  86. 10
      Squiggle.Core/Presence/Transport/Messages/UserUpdateMessage.cs
  87. 15
      Squiggle.Core/Presence/Transport/Multicast/IMulticastService.cs
  88. 32
      Squiggle.Core/Presence/Transport/Multicast/Tcp/Message.cs
  89. 16
      Squiggle.Core/Presence/Transport/Multicast/Tcp/Messages/MulticastMessage.cs
  90. 13
      Squiggle.Core/Presence/Transport/Multicast/Tcp/Messages/RegisterMessage.cs
  91. 13
      Squiggle.Core/Presence/Transport/Multicast/Tcp/Messages/UnregisterMessage.cs
  92. 62
      Squiggle.Core/Presence/Transport/Multicast/Tcp/MulticastHost.cs
  93. 66
      Squiggle.Core/Presence/Transport/Multicast/Tcp/TcpMulticastService.cs
  94. 89
      Squiggle.Core/Presence/Transport/Multicast/UdpMulticastService.cs
  95. 106
      Squiggle.Core/Presence/Transport/PresenceChannel.cs
  96. 55
      Squiggle.Core/Presence/Transport/PresenceHost.cs
  97. 216
      Squiggle.Core/Presence/UserDiscovery.cs
  98. 70
      Squiggle.Core/Presence/UserInfo.cs
  99. 26
      Squiggle.Core/Properties/AssemblyInfo.cs
  100. 15
      Squiggle.Core/ServiceNames.cs
  101. Some files were not shown because too many files have changed in this diff Show More

40
.gitignore vendored

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
/Squiggle.UI/obj
/Squiggle.UI/bin
/Squiggle.Bridge/bin
/Squiggle.Bridge/obj
/Squiggle.Client/bin
/Squiggle.Client/obj
/Squiggle.Core/obj
/Squiggle.Core/bin
/Squiggle.Utilities/bin
/Squiggle.Utilities/obj
/Squiggle.Translate/obj
/Squiggle.Translate/bin
/Squiggle.Multicast/bin
/Squiggle.Multicast/obj
/Squiggle.History/bin
/Squiggle.History/obj
/Squiggle.VoiceChat/bin
/Squiggle.VoiceChat/obj
/Squiggle.FileTransfer/bin
/Squiggle.FileTransfer/obj
/Squiggle.Screenshot/bin
/Squiggle.Screenshot/obj
/Squiggle.Infrastructure/bin
/Squiggle.Infrastructure/obj
/Squiggle.Setup/obj
/Squiggle.Setup/bin
/Libraries/Plugins/NAudio.dll
/Libraries/Plugins/Squiggle.FileTransfer.dll
/Libraries/Plugins/Squiggle.VoiceChat.dll
/Libraries/Plugins/Squiggle.Screenshot.dll
/Libraries/Plugins/libspeex-license.txt
/Libraries/Plugins/libspeexdsp.dll
/Build/*.zip
/Build/*.log
/Build/*.msi
*.user
*.suo
*.ncrunch*
packages

96
Build/Build.ps1

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
$scriptDir = Split-Path $script:MyInvocation.MyCommand.Path
$releasePath = "bin"
$version = (Select-String $scriptDir\..\Shared\AssemblyInfo.Version.cs -pattern 'AssemblyVersion[(]"((\d\.\d)\.\d\.\d)').Matches[0]
$longVersion = $version.Groups[1].Value
$shortVersion = $version.Groups[2].Value
function Main()
{
rm *.zip,*.msi
Write-Host ------------- Building Squiggle $shortVersion -----------------------
Build-Squiggle
Write-Host ------------- Updating config -------------------------
Update-Config
Write-Host ------------- Creating setup ---------------------------
Create-Setup
Write-Host ------------- Packaging ---------------------------
Package-All
Write-Host ------------- Done ------------------------------------
}
function Package-All()
{
Package Squiggle.UI\$releasePath Client $shortVersion
copy "$scriptDir\..\Squiggle.Setup\$releasePath\Squiggle.Setup.msi" "$scriptDir\Squiggle-$shortVersion Client.msi"
Package Squiggle.Bridge\$releasePath Bridge $shortVersion
Package Squiggle.Multicast\$releasePath Multicast $shortVersion
Package Scripts Scripts $shortVersion
}
function Package()
{
del ("$scriptDir\..\{0}\*.pdb" -f $args[0])
$target = ("{0}\Squiggle-{1} {2}.zip" -f $scriptDir, $args[2], $args[1])
$source = ("{0}\..\{1}\*.*" -f $scriptDir, $args[0])
Create-Archive $target $source
}
function Create-Setup()
{
$productName = "Squiggle $shortVersion"
Change-Setup-Product-Name "Squiggle" $productName
Change-Setup-Version "1.0.0.0" $longVersion
Build "Squiggle.Setup\Squiggle.Setup.wixproj"
Change-Setup-Version $longVersion "1.0.0.0"
Change-Setup-Product-Name $productName "Squiggle"
}
function Update-Config()
{
$gitHash = git rev-parse HEAD
$configPath = "$scriptDir\..\Squiggle.UI\$releasePath\Squiggle.exe.config"
Replace-In-File $configPath "GitHash`" value=`"`"" "GitHash`" value=`"$gitHash`""
}
function Build-Squiggle()
{
Build Squiggle.sln
}
function Change-Setup-Product-Name($from, $to)
{
Replace-In-File "$scriptDir\..\Squiggle.Setup\Product.wxs" "Name=`"$from" "Name=`"$to"
}
function Change-Setup-Version($from, $to)
{
Replace-In-File "$scriptDir\..\Squiggle.Setup\Product.wxs" "Version=`"$from" "Version=`"$to"
}
function Replace-In-File($filePath, $find, $replace)
{
(get-content $filePath) -replace $find, $replace | set-content $filePath
}
function Create-Archive($target, $source)
{
& "${Env:ProgramFiles}\7-Zip\7z" a -r -tzip $target $source
}
function Build($file)
{
& "${Env:WINDIR}\Microsoft.NET\Framework\v4.0.30319\msbuild" "$scriptDir\..\$file" "/p:Configuration=Release" "/t:Clean,Build" "/v:M" "/fl" "/nr:false"
if (!$?) {
#last command (msbuild) failed
exit
}
}
Main

BIN
Home_Screenshot.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

BIN
Home_about2012.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

21
LICENSE

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Muhammad Hasan Khan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

31
Libraries/Plugins/NAudio-license.txt

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
Microsoft Public License (Ms-PL)
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.

1
Libraries/Plugins/Readme.txt

@ -0,0 +1 @@ @@ -0,0 +1 @@
This is where plugins shipped with Squiggle are kept.

9
Libraries/Speex/libspeex-license.txt

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
© 2002-2003, Jean-Marc Valin/Xiph.Org Foundation
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
This software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the foundation or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

BIN
Libraries/Speex/libspeexdsp.dll

Binary file not shown.

25
Readme.md

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
Squiggle is a free server-less peer to peer LAN messenger.
Just download and run it and you're ready to talk to everyone on your LAN.
**Key Features:**
* Server-less peer to peer LAN chat, No installation required. Just download, unzip and run
* Group chat, Broadcast chat and Private chat
* Bridge for connecting two LANs across subnets or WAN.
* Supports localization i.e. you can replace the translation file to use Squiggle in your native language.
* Fast (multiple) file transfer
* Spell Check, Buzz, Emoticons, Audio Alerts, Tray Popups
* Contact groups, Display message, Display Pic, Chat commands, Message aliases
* Chat history, Status history
* **Voice Chat**
![](Home_Screenshot.png)
Server-less LAN Chat software that is easy to use and has a nice UI.
![Finalist of About.com Best Enterprise IM Award 2012](Home_about2012.png)
[System Requirements](https://github.com/hasankhan/Squiggle/wiki/System-Requirements)
Follow us on twitter [http://twitter.com/overroot](http://twitter.com/overroot)
[http://www.overroot.com](http://www.overroot.com)

1
Scripts/ConnectionString.txt

@ -0,0 +1 @@ @@ -0,0 +1 @@
<add name="HistoryContext" connectionString="Server=.;Database=SquiggleHistory;Trusted_Connection=true;" providerName="System.Data.SqlClient" />

87
Scripts/SquiggleHistory.sql

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
USE [SquiggleHistory]
GO
/****** Object: Table [dbo].[Events] Script Date: 11/3/2012 12:06:01 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Events](
[Id] [uniqueidentifier] NOT NULL,
[SessionId] [uniqueidentifier] NOT NULL,
[TypeCode] [int] NOT NULL,
[SenderId] [uniqueidentifier] NOT NULL,
[SenderName] [nvarchar](max) NULL,
[Data] [nvarchar](max) NULL,
[Stamp] [datetime] NOT NULL,
CONSTRAINT [PK_dbo.Events] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
/****** Object: Table [dbo].[Participants] Script Date: 11/3/2012 12:06:01 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Participants](
[Id] [uniqueidentifier] NOT NULL,
[SessionId] [uniqueidentifier] NOT NULL,
[ContactId] [uniqueidentifier] NOT NULL,
[ContactName] [nvarchar](max) NULL,
CONSTRAINT [PK_dbo.Participants] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
/****** Object: Table [dbo].[Sessions] Script Date: 11/3/2012 12:06:01 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Sessions](
[Id] [uniqueidentifier] NOT NULL,
[ContactId] [uniqueidentifier] NOT NULL,
[ContactName] [nvarchar](max) NULL,
[Start] [datetime] NOT NULL,
[End] [datetime] NULL,
CONSTRAINT [PK_dbo.Sessions] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
/****** Object: Table [dbo].[StatusUpdates] Script Date: 11/3/2012 12:06:01 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[StatusUpdates](
[Id] [uniqueidentifier] NOT NULL,
[ContactId] [uniqueidentifier] NOT NULL,
[ContactName] [nvarchar](max) NULL,
[StatusCode] [int] NOT NULL,
[Stamp] [datetime] NOT NULL,
CONSTRAINT [PK_dbo.StatusUpdates] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Events] WITH CHECK ADD CONSTRAINT [FK_dbo.Events_dbo.Sessions_SessionId] FOREIGN KEY([SessionId])
REFERENCES [dbo].[Sessions] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Events] CHECK CONSTRAINT [FK_dbo.Events_dbo.Sessions_SessionId]
GO
ALTER TABLE [dbo].[Participants] WITH CHECK ADD CONSTRAINT [FK_dbo.Participants_dbo.Sessions_SessionId] FOREIGN KEY([SessionId])
REFERENCES [dbo].[Sessions] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Participants] CHECK CONSTRAINT [FK_dbo.Participants_dbo.Sessions_SessionId]
GO

5
Shared/AssemblyInfo.ApiVersion.cs

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyVersion("3.4.0.0")]

11
Shared/AssemblyInfo.Copyright.cs

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Overroot")]
[assembly: AssemblyProduct("Squiggle Messenger")]
[assembly: AssemblyCopyright("Copyright © 2010 Overroot")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

5
Shared/AssemblyInfo.Version.cs

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyVersion("3.4.4.0")]

28
Squiggle.Bridge/App.config

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="BridgeConfiguration" type="Squiggle.Bridge.Configuration.BridgeConfiguration, Squiggle.Bridge, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<BridgeConfiguration>
<InternalServiceBinding IP="" Port=""/>
<ExternalServiceBinding IP="" Port=""/>
<PresenceBinding MulticastIP="224.10.11.12" MulticastPort="9998" ServicePort="9997" CallbackPort="9996"/>
<Targets>
<add IP="" Port=""/>
</Targets>
</BridgeConfiguration>
<system.diagnostics>
<!--
<trace autoflush="true" >
<listeners>
<add name="FileListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="Squiggle.Bridge.log" />
</listeners>
</trace>
-->
</system.diagnostics>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
</startup>
</configuration>

144
Squiggle.Bridge/BridgeHost.cs

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using Squiggle.Core;
using Squiggle.Core.Chat;
using Squiggle.Core.Chat.Transport.Host;
using Squiggle.Core.Presence;
using Squiggle.Utilities.Net.Pipe;
using Squiggle.Utilities.Serialization;
using Squiggle.Bridge.Messages;
using Squiggle.Utilities;
namespace Squiggle.Bridge
{
public class PresenceMessageForwardedEventArgs: EventArgs
{
public IPEndPoint BridgeEndPoint { get; set; }
public Squiggle.Core.Presence.Transport.Message Message {get; set; }
public bool IsBroadcast
{
get { return Message.Recipient == null; }
}
public PresenceMessageForwardedEventArgs(Squiggle.Core.Presence.Transport.Message message, IPEndPoint bridgeEdnpoint)
{
this.Message = message;
this.BridgeEndPoint = bridgeEdnpoint;
}
}
public class ChatMessageReceivedEventArgs : EventArgs
{
public Squiggle.Core.Chat.Transport.Message Message { get; set; }
}
public class BridgeHost: IDisposable
{
IPEndPoint externalEndPoint;
IPEndPoint internalEndPoint;
UnicastMessagePipe bridgePipe;
SquiggleBridge bridge;
UnicastMessagePipe chatPipe;
public event EventHandler<PresenceMessageForwardedEventArgs> PresenceMessageForwarded = delegate { };
public event EventHandler<ChatMessageReceivedEventArgs> ChatMessageReceived = delegate { };
internal BridgeHost(SquiggleBridge bridge, IPEndPoint externalEndPoint, IPEndPoint internalEndPoint)
{
this.bridge = bridge;
this.externalEndPoint = externalEndPoint;
this.internalEndPoint = internalEndPoint;
}
public void Start()
{
bridgePipe = new UnicastMessagePipe(externalEndPoint);
bridgePipe.MessageReceived += bridgePipe_MessageReceived;
bridgePipe.Open();
chatPipe = new UnicastMessagePipe(internalEndPoint);
chatPipe.MessageReceived += chatPipe_MessageReceived;
chatPipe.Open();
}
void chatPipe_MessageReceived(object sender,Utilities.Net.Pipe.MessageReceivedEventArgs e)
{
OnChatMessage(e.Message);
}
void bridgePipe_MessageReceived(object sender, Utilities.Net.Pipe.MessageReceivedEventArgs e)
{
SerializationHelper.Deserialize<Message>(e.Message, msg =>
{
OnMessageReceived(msg);
}, "bridge message");
}
void OnMessageReceived(Message message)
{
if (message is ForwardPresenceMessage)
OnPresenceMessage((ForwardPresenceMessage)message);
else if (message is ForwardChatMessage)
OnChatMessage(((ForwardChatMessage)message).Message);
}
void OnPresenceMessage(ForwardPresenceMessage message)
{
SerializationHelper.Deserialize<Squiggle.Core.Presence.Transport.Message>(message.Message, msg =>
{
var args = new PresenceMessageForwardedEventArgs(msg, message.BridgeEndPoint);
PresenceMessageForwarded(this, args);
}, "presence message");
}
void OnChatMessage(byte[] data)
{
SerializationHelper.Deserialize<Squiggle.Core.Chat.Transport.Message>(data, msg =>
{
var args = new ChatMessageReceivedEventArgs() { Message = msg };
ChatMessageReceived(this, args);
}, "chat message");
}
public void Dispose()
{
if (bridgePipe != null)
{
bridgePipe.Dispose();
bridgePipe = null;
}
if (chatPipe != null)
{
chatPipe.Dispose();
chatPipe = null;
}
}
public void SendChatMessage(bool local, IPEndPoint target, Core.Chat.Transport.Message message)
{
byte[] data = SerializationHelper.Serialize(message);
if (local)
chatPipe.Send(target, data);
else
Send(target, new ForwardChatMessage() { Message = data });
}
public void SendPresenceMessage(IPEndPoint target, byte[] message)
{
Validator.IsNotNull(target, "target");
Validator.IsNotNull(message, "message");
Send(target, new ForwardPresenceMessage() { BridgeEndPoint = externalEndPoint, Message = message});
}
void Send(IPEndPoint target, Message message)
{
bridgePipe.Send(target, SerializationHelper.Serialize(message));
}
}
}

41
Squiggle.Bridge/Configuration/BridgeConfiguration.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
using System.Configuration;
namespace Squiggle.Bridge.Configuration
{
class BridgeConfiguration : ConfigurationSection
{
public static BridgeConfiguration GetConfig()
{
return (BridgeConfiguration)ConfigurationManager.GetSection("BridgeConfiguration") ?? new BridgeConfiguration();
}
[ConfigurationProperty("ExternalServiceBinding")]
public Target ExternalServiceBinding
{
get { return (Target)this["ExternalServiceBinding"] ?? new Target(); }
}
[ConfigurationProperty("InternalServiceBinding")]
public Target InternalServiceBinding
{
get { return (Target)this["InternalServiceBinding"] ?? new Target(); }
}
[ConfigurationProperty("PresenceBinding")]
public PresenceBinding PresenceBinding
{
get { return (PresenceBinding)this["PresenceBinding"] ?? new PresenceBinding(); }
}
[ConfigurationProperty("Targets")]
public TargetCollection Targets
{
get
{
return (TargetCollection)this["Targets"] ??
new TargetCollection();
}
}
}
}

45
Squiggle.Bridge/Configuration/PresenceBinding.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text;
namespace Squiggle.Bridge.Configuration
{
class PresenceBinding : ConfigurationElement
{
[ConfigurationProperty("MulticastIP", IsRequired = true)]
public string IP
{
get { return this["MulticastIP"] as string; }
}
[ConfigurationProperty("MulticastPort", IsRequired = true)]
public int MulticastPort
{
get { return Convert.ToInt32(this["MulticastPort"]); }
}
[ConfigurationProperty("ServicePort", IsRequired = true)]
public int ServicePort
{
get { return Convert.ToInt32(this["ServicePort"]); }
}
[ConfigurationProperty("CallbackPort", IsRequired = true)]
public int CallbackPort
{
get { return Convert.ToInt32(this["CallbackPort"]); }
}
public IPEndPoint MulticastEndPoint
{
get
{
var ip = IPAddress.Parse(IP);
return new IPEndPoint(ip, MulticastPort);
}
}
}
}

30
Squiggle.Bridge/Configuration/Target.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
using System;
using System.Configuration;
using System.Net;
namespace Squiggle.Bridge.Configuration
{
class Target : ConfigurationElement
{
[ConfigurationProperty("IP", IsRequired = true)]
public string IP
{
get { return this["IP"] as string; }
}
[ConfigurationProperty("Port", IsRequired = true)]
public int Port
{
get { return Convert.ToInt32(this["Port"]); }
}
public IPEndPoint EndPoint
{
get
{
var ip = IPAddress.Parse(IP);
return new IPEndPoint(ip, Port);
}
}
}
}

32
Squiggle.Bridge/Configuration/TargetCollection.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
using System.Configuration;
namespace Squiggle.Bridge.Configuration
{
class TargetCollection : ConfigurationElementCollection
{
public Target this[int index]
{
get
{
return base.BaseGet(index) as Target;
}
set
{
if (base.BaseGet(index) != null)
base.BaseRemoveAt(index);
this.BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new Target();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((Target)element).IP;
}
}
}

17
Squiggle.Bridge/Message.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using Squiggle.Utilities.Serialization;
using Squiggle.Bridge.Messages;
namespace Squiggle.Bridge
{
[ProtoContract]
[ProtoInclude(50, typeof(ForwardPresenceMessage))]
[ProtoInclude(51, typeof(ForwardChatMessage))]
public abstract class Message
{
}
}

15
Squiggle.Bridge/Messages/ForwardChatMessage.cs

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
namespace Squiggle.Bridge.Messages
{
[ProtoContract]
class ForwardChatMessage: Message
{
[ProtoMember(1)]
public byte[] Message { get; set; }
}
}

31
Squiggle.Bridge/Messages/ForwardPresenceMessage.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using Squiggle.Core;
using System.Net;
namespace Squiggle.Bridge.Messages
{
[ProtoContract]
class ForwardPresenceMessage : Message
{
[ProtoMember(1)]
public byte[] Message { get; set; }
[ProtoMember(2)]
IPAddress IP { get; set; }
[ProtoMember(3)]
int Port { get; set; }
public IPEndPoint BridgeEndPoint
{
get { return new IPEndPoint(IP, Port); }
set
{
IP = value.Address;
Port = value.Port;
}
}
}
}

45
Squiggle.Bridge/PresenceMessageInspector.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Squiggle.Core;
using Squiggle.Core.Presence.Transport;
using Squiggle.Core.Presence.Transport.Messages;
namespace Squiggle.Bridge
{
class PresenceMessageInspector
{
RouteTable routeTable;
IPEndPoint bridgePresenceEndPoint;
IPEndPoint bridgeChatEndPoint;
public PresenceMessageInspector(RouteTable routeTable, IPEndPoint bridgePresenceEndPoint, IPEndPoint bridgeChatEndPoint)
{
this.routeTable = routeTable;
this.bridgePresenceEndPoint = bridgePresenceEndPoint;
this.bridgeChatEndPoint = bridgeChatEndPoint;
}
public void InspectForeignPresenceMessage(Squiggle.Core.Presence.Transport.Message message, IPEndPoint bridge)
{
routeTable.AddRemoteClient(message.Sender.ClientID, bridge);
ReplaceSenderWithBridgeEndPoints(message);
}
public void InspectLocalPresenceMessage(Squiggle.Core.Presence.Transport.Message message)
{
routeTable.AddLocalPresenceEndPoint(message.Sender);
if (message is PresenceMessage)
routeTable.AddLocalChatEndPoint(message.Sender.ClientID, ((PresenceMessage)message).ChatEndPoint);
}
void ReplaceSenderWithBridgeEndPoints(Squiggle.Core.Presence.Transport.Message message)
{
message.Sender = new SquiggleEndPoint(message.Sender.ClientID, bridgePresenceEndPoint);
if (message is PresenceMessage)
((PresenceMessage)message).ChatEndPoint = bridgeChatEndPoint;
}
}
}

20
Squiggle.Bridge/Program.cs

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
using System;
using System.Configuration.Install;
using System.Diagnostics;
using System.Reflection;
using System.ServiceProcess;
using Squiggle.Utilities;
namespace Squiggle.Bridge
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
ConsoleService.Run<SquiggleBridgeService>(args);
}
}
}

60
Squiggle.Bridge/ProjectInstaller.Designer.cs generated

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
namespace Squiggle.Bridge
{
partial class ProjectInstaller
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller1
//
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
//
// serviceInstaller1
//
this.serviceInstaller1.Description = "Bridges two squiggle nets across WAN and subnets";
this.serviceInstaller1.DisplayName = "Squiggle Bridge";
this.serviceInstaller1.ServiceName = "SquiggleBridge";
this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
//
// ProjectInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller1,
this.serviceInstaller1});
}
#endregion
private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
private System.ServiceProcess.ServiceInstaller serviceInstaller1;
}
}

14
Squiggle.Bridge/ProjectInstaller.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
using System.ComponentModel;
namespace Squiggle.Bridge
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
}
}

129
Squiggle.Bridge/ProjectInstaller.resx

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="serviceProcessInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>19, 18</value>
</metadata>
<metadata name="serviceInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>196, 17</value>
</metadata>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

26
Squiggle.Bridge/Properties/AssemblyInfo.cs

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Squiggle Bridge")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d45c2419-53b1-44c0-a7d2-af63b6642fb8")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

58
Squiggle.Bridge/RouteTable.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Squiggle.Core;
namespace Squiggle.Bridge
{
class RouteTable
{
Dictionary<string, IPEndPoint> remoteClientBridgeMap = new Dictionary<string, IPEndPoint>();
Dictionary<string, IPEndPoint> localPresenceEndPoints = new Dictionary<string, IPEndPoint>();
Dictionary<string, IPEndPoint> localChatEndPoints = new Dictionary<string, IPEndPoint>();
public void AddRemoteClient(string clientId, IPEndPoint bridge)
{
lock (remoteClientBridgeMap)
remoteClientBridgeMap[clientId] = bridge;
}
public IPEndPoint GetLocalPresenceEndPoint(string clientId)
{
IPEndPoint endpoint;
lock (localPresenceEndPoints)
localPresenceEndPoints.TryGetValue(clientId, out endpoint);
return endpoint;
}
public void AddLocalPresenceEndPoint(ISquiggleEndPoint localPresenceEndPoint)
{
lock (localPresenceEndPoints)
localPresenceEndPoints[localPresenceEndPoint.ClientID] = localPresenceEndPoint.Address;
}
public void AddLocalChatEndPoint(string clientId, IPEndPoint endpoint)
{
lock (localChatEndPoints)
localChatEndPoints[clientId] = endpoint;
}
public IPEndPoint GetLocalChatEndPoint(string clientId)
{
IPEndPoint endpoint;
lock (localChatEndPoints)
localChatEndPoints.TryGetValue(clientId, out endpoint);
return endpoint;
}
public IPEndPoint FindBridge(string clientID)
{
IPEndPoint bridge;
lock (remoteClientBridgeMap)
remoteClientBridgeMap.TryGetValue(clientID, out bridge);
return bridge;
}
}
}

135
Squiggle.Bridge/Squiggle.Bridge.csproj

@ -0,0 +1,135 @@ @@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D832B3DB-16CF-463A-8C80-1DBD581183A2}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Squiggle.Bridge</RootNamespace>
<AssemblyName>Squiggle.Bridge</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisLogFile>bin\Debug\Squiggle.Bridge.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisLogFile>bin\Release\Squiggle.Bridge.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="protobuf-net">
<HintPath>..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="..\Shared\AssemblyInfo.Copyright.cs">
<Link>Properties\AssemblyInfo.Copyright</Link>
</Compile>
<Compile Include="..\Shared\AssemblyInfo.Version.cs">
<Link>Properties\AssemblyInfo.Version</Link>
</Compile>
<Compile Include="BridgeHost.cs" />
<Compile Include="Configuration\BridgeConfiguration.cs" />
<Compile Include="Configuration\PresenceBinding.cs" />
<Compile Include="Configuration\Target.cs" />
<Compile Include="Configuration\TargetCollection.cs" />
<Compile Include="Messages\ForwardChatMessage.cs" />
<Compile Include="Messages\ForwardPresenceMessage.cs" />
<Compile Include="Message.cs" />
<Compile Include="PresenceMessageInspector.cs" />
<Compile Include="ProjectInstaller.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ProjectInstaller.Designer.cs">
<DependentUpon>ProjectInstaller.cs</DependentUpon>
</Compile>
<Compile Include="RouteTable.cs" />
<Compile Include="SquiggleBridge.cs" />
<Compile Include="SquiggleBridgeService.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="SquiggleBridgeService.Designer.cs">
<DependentUpon>SquiggleBridgeService.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ProjectInstaller.resx">
<DependentUpon>ProjectInstaller.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SquiggleBridgeService.resx">
<DependentUpon>SquiggleBridgeService.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Squiggle.Core\Squiggle.Core.csproj">
<Project>{CCC71193-64AA-4B92-80C9-7BC688C7FAE3}</Project>
<Name>Squiggle.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Squiggle.Infrastructure\Squiggle.Infrastructure.csproj">
<Project>{CC6D9F53-D00B-4554-8642-218AEA987D20}</Project>
<Name>Squiggle.Infrastructure</Name>
</ProjectReference>
<ProjectReference Include="..\Squiggle.Utilities\Squiggle.Utilities.csproj">
<Project>{8B57850B-FA7F-4F96-A4A0-BF81BF24E710}</Project>
<Name>Squiggle.Utilities</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

194
Squiggle.Bridge/SquiggleBridge.cs

@ -0,0 +1,194 @@ @@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Squiggle.Core;
using Squiggle.Core.Chat.Transport.Host;
using Squiggle.Core.Chat.Transport.Messages;
using Squiggle.Core.Presence.Transport;
using Squiggle.Core.Presence.Transport.Messages;
using Squiggle.Utilities;
using Squiggle.Utilities.Serialization;
namespace Squiggle.Bridge
{
class TargetBridge
{
public IPEndPoint EndPoint { get; set; }
}
delegate void RouteAction(bool local, IPEndPoint target, SquiggleEndPoint sender, SquiggleEndPoint recipient);
class SquiggleBridge
{
BridgeHost bridgeHost;
IPEndPoint presenceServiceEndPoint;
IPEndPoint bridgeEndPointInternal;
IPEndPoint bridgeEndPointExternal;
IPEndPoint multicastEndPoint;
IPEndPoint multicastReceiveEndPoint;
PresenceChannel presenceChannel;
PresenceMessageInspector messageInspector;
List<IPEndPoint> targetBridges = new List<IPEndPoint>();
RouteTable routeTable;
public SquiggleBridge(IPEndPoint bridgeEndPointInternal,
IPEndPoint bridgeEndPointExternal,
IPEndPoint multicastEndPoint,
IPEndPoint multicastReceiveEndPoint,
IPEndPoint presenceServiceEndPoint)
{
this.bridgeEndPointInternal = bridgeEndPointInternal;
this.bridgeEndPointExternal = bridgeEndPointExternal;
this.multicastEndPoint = multicastEndPoint;
this.multicastReceiveEndPoint = multicastReceiveEndPoint;
this.presenceServiceEndPoint = presenceServiceEndPoint;
}
public void AddTarget(IPEndPoint target)
{
targetBridges.Add(target);
}
public void Start()
{
bridgeHost = new BridgeHost(this, bridgeEndPointExternal, bridgeEndPointInternal);
bridgeHost.PresenceMessageForwarded += bridgeHost_PresenceMessageForwarded;
bridgeHost.ChatMessageReceived += bridgeHost_ChatMessageReceived;
bridgeHost.Start();
routeTable = new RouteTable();
messageInspector = new PresenceMessageInspector(routeTable, presenceServiceEndPoint, bridgeEndPointInternal);
presenceChannel = new PresenceChannel(multicastEndPoint, multicastReceiveEndPoint, presenceServiceEndPoint);
presenceChannel.Start();
presenceChannel.MessageReceived += presenceChannel_MessageReceived;
}
public void Stop()
{
bridgeHost.Dispose();
presenceChannel.Stop();
}
void bridgeHost_PresenceMessageForwarded(object sender, PresenceMessageForwardedEventArgs e)
{
if (e.Message.ChannelID == presenceChannel.ChannelID)
return; // my own message
if (!targetBridges.Contains(e.BridgeEndPoint)) // not coming from a target bridge list
return;
messageInspector.InspectForeignPresenceMessage(e.Message, e.BridgeEndPoint);
Trace.WriteLine("Replay: " + e.Message.GetType().Name);
if (e.IsBroadcast)
ExceptionMonster.EatTheException(() =>
{
presenceChannel.MulticastMessage(e.Message);
}, "replaying presence message to local clients");
else
ExceptionMonster.EatTheException(() =>
{
IPEndPoint endpoint = routeTable.GetLocalPresenceEndPoint(e.Message.Recipient.ClientID);
if (endpoint != null)
{
e.Message.Recipient = new SquiggleEndPoint(e.Message.Recipient.ClientID, endpoint);
presenceChannel.SendMessage(e.Message);
}
}, "routing presence message to local user");
}
void bridgeHost_ChatMessageReceived(object sender, ChatMessageReceivedEventArgs e)
{
if (e.Message is IMessageHasParticipants)
{
var msg = (IMessageHasParticipants)e.Message;
msg.Participants = ConvertChatEndPointsForRecipient(msg.Participants, e.Message.Recipient).ToList();
}
RouteChatMessageToLocalOrRemoteUser((local, target, newSender, newRecipient) =>
{
e.Message.Sender = newSender;
e.Message.Recipient = newRecipient;
bridgeHost.SendChatMessage(local, target, e.Message);
}, e.Message.Sender, e.Message.Recipient);
}
void presenceChannel_MessageReceived(object sender, Squiggle.Core.Presence.Transport.MessageReceivedEventArgs e)
{
ExceptionMonster.EatTheException(() =>
{
messageInspector.InspectLocalPresenceMessage(e.Message);
byte[] message = SerializationHelper.Serialize(e.Message);
if (e.IsBroadcast)
{
foreach (IPEndPoint target in targetBridges)
bridgeHost.SendPresenceMessage(target, message);
}
else
{
IPEndPoint bridge = routeTable.FindBridge(e.Message.Recipient.ClientID);
bridgeHost.SendPresenceMessage(bridge, message);
}
Trace.WriteLine("Forward: " + e.Message.GetType().Name);
}, "forwarding presence message to bridge(s)");
}
void RouteChatMessageToLocalOrRemoteUser(RouteAction action, SquiggleEndPoint sender, SquiggleEndPoint recipient)
{
if (IsLocalChatEndpoint(recipient))
RouteChatMessageToLocalUser(action, sender, recipient);
else
RouteMessageToRemoteUser((local, target, s, r) => action(local, target, s, r), sender, recipient);
}
IEnumerable<SquiggleEndPoint> ConvertChatEndPointsForRecipient(IEnumerable<SquiggleEndPoint> endpoints, SquiggleEndPoint recipient)
{
if (IsLocalChatEndpoint(recipient))
return endpoints.Select(ep => new SquiggleEndPoint(ep.ClientID, bridgeEndPointInternal)).ToList();
return endpoints;
}
bool IsLocalChatEndpoint(ISquiggleEndPoint recipient)
{
return routeTable.GetLocalChatEndPoint(recipient.ClientID) != null;
}
void RouteMessageToRemoteUser(RouteAction action, SquiggleEndPoint sender, SquiggleEndPoint recipient)
{
ExceptionMonster.EatTheException(() =>
{
IPEndPoint bridge = routeTable.FindBridge(recipient.ClientID);
if (bridge != null)
action(false, bridge, sender, recipient);
}, "routing message to remote user");
}
void RouteChatMessageToLocalUser(RouteAction action, SquiggleEndPoint sender, SquiggleEndPoint recipient)
{
ExceptionMonster.EatTheException(() =>
{
sender = new SquiggleEndPoint(sender.ClientID, bridgeEndPointInternal);
IPEndPoint endpoint = routeTable.GetLocalChatEndPoint(recipient.ClientID);
action(true, endpoint, sender, new SquiggleEndPoint(recipient.ClientID, endpoint));
}, "routing chat message to local user");
}
IPEndPoint FindBridge(IPEndPoint bridgeEndPoint)
{
IPEndPoint bridge = targetBridges.FirstOrDefault(t => t.Equals(bridgeEndPoint));
return bridge;
}
}
}

40
Squiggle.Bridge/SquiggleBridgeService.Designer.cs generated

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
namespace Squiggle.Bridge
{
partial class SquiggleBridgeService
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}