commit
62ba6ee1e4
455 changed files with 33654 additions and 0 deletions
@ -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 |
@ -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 |
After Width: | Height: | Size: 175 KiB |
After Width: | Height: | Size: 28 KiB |
@ -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. |
@ -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. |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
This is where plugins shipped with Squiggle are kept. |
@ -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. |
Binary file not shown.
@ -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** |
||||
|
||||
 |
||||
|
||||
Server-less LAN Chat software that is easy to use and has a nice UI. |
||||
|
||||
 |
||||
|
||||
[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) |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
<add name="HistoryContext" connectionString="Server=.;Database=SquiggleHistory;Trusted_Connection=true;" providerName="System.Data.SqlClient" /> |
@ -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 |
@ -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")] |
@ -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("")] |
@ -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")] |
@ -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> |
@ -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)); |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
||||
} |
@ -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 |
||||
{ |
||||
} |
||||
} |
@ -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; } |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
} |
@ -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> |
@ -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.*")]
|
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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> |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||