├── .github
└── workflows
│ └── dotnet.yml
├── .gitignore
├── .vscode
├── launch.json
└── tasks.json
├── I2CP
├── I2CP.csproj
├── I2CP
│ ├── I2CPHost.cs
│ ├── I2CPSession.cs
│ ├── Messages
│ │ ├── CreateLeaseSet2Message.cs
│ │ ├── CreateLeaseSetMessage.cs
│ │ ├── CreateSessionMessage.cs
│ │ ├── DestLookupMessage.cs
│ │ ├── DestReplyMessage.cs
│ │ ├── DestroySessionMessage.cs
│ │ ├── GetDateMessage.cs
│ │ ├── HostLookupMessage.cs
│ │ ├── HostReplyMessage.cs
│ │ ├── Message.cs
│ │ ├── MessagePayloadMessage.cs
│ │ ├── MessageStatusMessage.cs
│ │ ├── ReceiveMessageEndMessage.cs
│ │ ├── ReconfigureSessionMessage.cs
│ │ ├── RequestLeaseSetMessage.cs
│ │ ├── RequestVariableLeaseSetMessage.cs
│ │ ├── SendMessageExpiresMessage.cs
│ │ ├── SendMessageMessage.cs
│ │ ├── SessionStatusMessage.cs
│ │ └── SetDateMessage.cs
│ └── States
│ │ ├── EstablishedState.cs
│ │ ├── I2CPState.cs
│ │ └── WaitGetDateState.cs
├── Streaming
│ └── Messages
│ │ └── StreamingPacket.cs
└── packages.config
├── I2P.code-workspace
├── I2PCore.NTests
├── BufRefTest.cs
├── ElGamalTest.cs
├── GarlicTest.cs
├── I2NPMessagesTest.cs
├── I2PCore.NTests.csproj
├── I2PTypesTest.cs
├── SignatureTest.cs
├── StoreTest.cs
├── TransportTest.cs
├── TunnelDataFragmentationTest.cs
├── TunnelDataMessageTest.cs
├── UtilsTest.cs
└── packages.config
├── I2PCore
├── ChecksumFailureException.cs
├── Contrib
│ └── Certificates
│ │ └── Reseed
│ │ ├── backup_at_mail.i2p.crt
│ │ ├── bugme_at_mail.i2p.crt
│ │ ├── creativecowpat_at_mail.i2p.crt
│ │ ├── echelon_at_mail.i2p.crt
│ │ ├── hottuna_at_mail.i2p.crt
│ │ ├── igor_at_novg.net.crt
│ │ ├── lazygravy_at_mail.i2p.crt
│ │ ├── meeh_at_mail.i2p.crt
│ │ └── r4sas-reseed_at_mail.i2p.crt
├── Data
│ ├── DatabaseLookupKeyInfo.cs
│ ├── I2PCertificate.cs
│ ├── I2PConstants.cs
│ ├── I2PDate.cs
│ ├── I2PDateShort.cs
│ ├── I2PDestination.cs
│ ├── I2PDestinationInfo.cs
│ ├── I2PHashSHA256.cs
│ ├── I2PIdentHash.cs
│ ├── I2PIdentHashComparer.cs
│ ├── I2PKeyType.cs
│ ├── I2PKeysAndCert.cs
│ ├── I2PLease.cs
│ ├── I2PLease2.cs
│ ├── I2PLeaseSet.cs
│ ├── I2PLeaseSet2.cs
│ ├── I2PLeaseSet2Header.cs
│ ├── I2PMapping.cs
│ ├── I2PMessagePayload.cs
│ ├── I2POfflineSignature.cs
│ ├── I2PPrivateKey.cs
│ ├── I2PPublicKey.cs
│ ├── I2PRawData.cs
│ ├── I2PRouterAddress.cs
│ ├── I2PRouterIdentity.cs
│ ├── I2PRouterInfo.cs
│ ├── I2PRoutingKey.cs
│ ├── I2PSU3Header.cs
│ ├── I2PSessionConfig.cs
│ ├── I2PSessionKey.cs
│ ├── I2PSessionTag.cs
│ ├── I2PSignature.cs
│ ├── I2PSigningKey.cs
│ ├── I2PSigningPrivateKey.cs
│ ├── I2PSigningPublicKey.cs
│ ├── I2PString.cs
│ ├── I2PStringComparer.cs
│ ├── I2PStringEqualityComparer.cs
│ ├── I2PTunnelId.cs
│ ├── I2PType.cs
│ ├── ILease.cs
│ └── ILeaseSet.cs
├── EndOfStreamEncounteredException.cs
├── FailedToConnectException.cs
├── I2PCore.csproj
├── NetDb
│ ├── Bootstrap.cs
│ ├── CertificatesDb.cs
│ ├── FloodfillUpdater.cs
│ ├── IdentResolver.cs
│ ├── NetDb.Query.cs
│ ├── NetDb.Reports.cs
│ ├── NetDb.RouterEntry.cs
│ ├── NetDb.Store.cs
│ ├── NetDb.cs
│ ├── PublishedBandwidth.cs
│ ├── RouterStatistics.cs
│ └── RoutersStatistics.cs
├── RouterUnresolvable.cs
├── SessionLayer
│ ├── ClientDestination.IClient.cs
│ ├── ClientDestination.Leases.cs
│ ├── ClientDestination.RecvGarlic.cs
│ ├── ClientDestination.Send.cs
│ ├── ClientDestination.Tunnels.cs
│ ├── ClientDestination.cs
│ ├── ElGamal-AES
│ │ ├── EGAESDecryptReceivedSessions.cs
│ │ └── EGAESSessionKeyOrigin.cs
│ ├── IClient.cs
│ ├── Router.cs
│ ├── RouterContext.IPV4.cs
│ ├── RouterContext.cs
│ ├── Session.cs
│ ├── SessionManager.cs
│ └── Watchdog.cs
├── SignatureCheckFailureException.cs
├── TransportLayer
│ ├── DecayingIPBlockFilter.cs
│ ├── ITransport.cs
│ ├── ITransportProtocol.cs
│ ├── LookupDestination.cs
│ ├── NTCP
│ │ ├── DHHandshakeContext.cs
│ │ ├── NTCPClient.cs
│ │ ├── NTCPClientIncoming.cs
│ │ ├── NTCPClientOutgoing.cs
│ │ ├── NTCPHost.cs
│ │ ├── NTCPReader.cs
│ │ ├── NTCPRunningContext.cs
│ │ ├── SessionConfirmA.cs
│ │ ├── SessionConfirmB.cs
│ │ ├── SessionCreated.cs
│ │ └── SessionRequest.cs
│ ├── SSU
│ │ ├── Data
│ │ │ ├── DataFragment.cs
│ │ │ ├── DataMessage.cs
│ │ │ ├── IntroducerInfo.cs
│ │ │ ├── PeerTest.cs
│ │ │ ├── RelayIntro.cs
│ │ │ ├── RelayResponse.cs
│ │ │ ├── SSUHeader.cs
│ │ │ ├── SessionCreated.cs
│ │ │ └── SessionRequest.cs
│ │ ├── DataDefragmenter.cs
│ │ ├── DataFragmenter.cs
│ │ ├── EndpointStatistic.cs
│ │ ├── EndpointStatistics.cs
│ │ ├── FragmentedMessage.cs
│ │ ├── PeerTestState.cs
│ │ ├── RebuildI2NPMessage.cs
│ │ ├── SSUHost.Introducers.cs
│ │ ├── SSUHost.NetDB.cs
│ │ ├── SSUHost.PeerTest.cs
│ │ ├── SSUHost.Sessions.cs
│ │ ├── SSUHost.Sockets.cs
│ │ ├── SSUHost.Utilities.cs
│ │ ├── SSUHost.cs
│ │ ├── SSUSession.cs
│ │ ├── SendBufferPool.cs
│ │ └── States
│ │ │ ├── EstablishedState.cs
│ │ │ ├── IdleState.cs
│ │ │ ├── RelayRequestState.cs
│ │ │ ├── SSUState.cs
│ │ │ ├── SessionCreatedState.cs
│ │ │ ├── SessionRequestState.SessionConfirmed.cs
│ │ │ └── SessionRequestState.cs
│ ├── TransportProtocolAttribute.cs
│ ├── TransportProvider.cs
│ ├── UnknownRouterQueue.cs
│ └── UnresolvableRouters.cs
├── TunnelLayer
│ ├── ClientTunnelProvider.cs
│ ├── EndpointTunnel.cs
│ ├── ExplorationTunnelProvider.cs
│ ├── GatewayTunnel.cs
│ ├── I2NP
│ │ ├── Data
│ │ │ ├── AesEGBuildRequestRecord.cs
│ │ │ ├── BuildRequestRecord.cs
│ │ │ ├── BuildResponseRecord.cs
│ │ │ ├── EGBuildRequestRecord.cs
│ │ │ ├── Garlic.cs
│ │ │ ├── GarlicAESBlock.cs
│ │ │ ├── GarlicClove.cs
│ │ │ ├── GarlicCloveDelivery.cs
│ │ │ ├── HopInfo.cs
│ │ │ ├── I2NPHeader.cs
│ │ │ ├── I2NPHeader16.cs
│ │ │ └── TunnelInfo.cs
│ │ ├── I2NPUtil.cs
│ │ └── Messages
│ │ │ ├── DataMessage.cs
│ │ │ ├── DatabaseLookupMessage.cs
│ │ │ ├── DatabaseSearchReplyMessage.cs
│ │ │ ├── DatabaseStoreMessage.cs
│ │ │ ├── DeliveryStatusMessage.cs
│ │ │ ├── GarlicMessage.cs
│ │ │ ├── I2NPMessage.cs
│ │ │ ├── TunnelBuildMessage.cs
│ │ │ ├── TunnelBuildReplyMessage.cs
│ │ │ ├── TunnelDataFragment.cs
│ │ │ ├── TunnelDataFragmentCreation.cs
│ │ │ ├── TunnelDataMessage.cs
│ │ │ ├── TunnelGatewayMessage.cs
│ │ │ ├── TunnelMessage.cs
│ │ │ ├── VariableTunnelBuildMessage.cs
│ │ │ └── VariableTunnelBuildReplyMessage.cs
│ ├── ITunnelOwner.cs
│ ├── InboundTunnel.cs
│ ├── OutboundTunnel.cs
│ ├── TransitTunnel.cs
│ ├── TransitTunnelProvider.cs
│ ├── Tunnel.cs
│ ├── TunnelBuildRequestDecrypt.cs
│ ├── TunnelConfig.cs
│ ├── TunnelDataFragmentReassembly.cs
│ ├── TunnelIdSubsriptions.cs
│ ├── TunnelProvider.cs
│ ├── TunnelQuality.cs
│ ├── TunnelSettings.cs
│ ├── TunnelTester.cs
│ └── ZeroHopTunnel.cs
├── Utils
│ ├── Bandwidth.cs
│ ├── BandwidthLimiter.cs
│ ├── BandwidthStatistics.cs
│ ├── BufRef.cs
│ ├── BufRefStream.cs
│ ├── BufUtils.cs
│ ├── ElGamalCrypto.cs
│ ├── FreenetBase64.cs
│ ├── HashedItemGroup.cs
│ ├── I2PHMACMD5Digest.cs
│ ├── IPAddressMask.cs
│ ├── ItemFilterWindow.cs
│ ├── LZUtils.cs
│ ├── Logging
│ │ ├── FileLogStore.cs
│ │ ├── ILogStore.cs
│ │ ├── Logging.cs
│ │ └── StreamLogStore.cs
│ ├── MurMurHash3.cs
│ ├── PeriodicAction.cs
│ ├── PeriodicLogger.cs
│ ├── RefPair.cs
│ ├── RouletteSelection.cs
│ ├── RunBatchWait.cs
│ ├── Store.cs
│ ├── StreamUtils.cs
│ ├── SuccessRatio.cs
│ ├── TickCounter.cs
│ ├── TimeWindowDictionary.cs
│ └── UPnp.cs
└── packages.config
├── LICENCE.txt
├── Nuget.config
├── README.md
├── Samples
├── I2PDemo
│ ├── App.config
│ ├── I2PDemo.csproj
│ ├── Program.cs
│ └── packages.config
├── I2PEchoClient
│ ├── App.config
│ ├── I2PEchoClient.csproj
│ ├── Program.cs
│ └── packages.config
├── I2PEchoServer
│ ├── App.config
│ ├── I2PEchoServer.csproj
│ ├── Program.cs
│ └── packages.config
└── I2PRouter
│ ├── App.config
│ ├── I2PRouter.csproj
│ └── Program.cs
└── i2p.sln
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET
2 |
3 | on:
4 | push:
5 | branches: [ github-master ]
6 | pull_request:
7 | branches: [ github-master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Setup .NET
17 | uses: actions/setup-dotnet@v1
18 | with:
19 | dotnet-version: 5.0.x
20 | - name: Restore dependencies
21 | run: dotnet restore
22 | - name: Build
23 | run: dotnet build --no-restore
24 | - name: Test
25 | run: dotnet test --no-build --verbosity normal
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .vscode/*
3 | !.vscode/settings.json
4 | !.vscode/tasks.json
5 | !.vscode/launch.json
6 | !.vscode/extensions.jsons
7 |
8 | # User-specific files
9 | *.suo
10 | *.user
11 | *.userosscache
12 | *.sln.docstates
13 |
14 | Thumbs.db
15 | *.obj
16 | *.exe
17 | *.pdb
18 | *.aps
19 | *.pch
20 | *.vspscc
21 | *_i.c
22 | *_p.c
23 | *.ncb
24 | *.suo
25 | *.tlb
26 | *.tlh
27 | *.bak
28 | *.cache
29 | *.ilk
30 | *.log
31 | [Bb]in
32 | [Dd]ebug*/
33 | *.lib
34 | *.sbr
35 | obj/
36 | [Rr]elease*/
37 | _ReSharper*/
38 | [Tt]est[Rr]esult*
39 | .vs
40 | /Backup
41 | /packages
42 | *.kate-swp
43 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | // Use IntelliSense to find out which attributes exist for C# debugging
6 | // Use hover for the description of the existing attributes
7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
8 | "name": "I2PDemo (console)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "builddemo",
12 | // If you have changed target frameworks, make sure to update the program path.
13 | "program": "${workspaceFolder}/Samples/I2PDemo/bin/Debug/net5.0/I2PDemo.dll",
14 | "args": [],
15 | "cwd": "${workspaceFolder}/Samples/I2PDemo",
16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
17 | "console": "internalConsole",
18 | "stopAtEntry": false
19 | },
20 | {
21 | "name": "I2PRouter (console)",
22 | "type": "coreclr",
23 | "request": "launch",
24 | "preLaunchTask": "buildrouter",
25 | "program": "${workspaceFolder}/Samples/I2PRouter/bin/Debug/net5.0/I2PRouter.dll",
26 | "args": [],
27 | "cwd": "${workspaceFolder}/Samples/I2PRouter",
28 | "console": "internalConsole",
29 | "stopAtEntry": false
30 | },
31 | {
32 | "name": "I2PEchoServer (console)",
33 | "type": "coreclr",
34 | "request": "launch",
35 | "preLaunchTask": "buildeserver",
36 | "program": "${workspaceFolder}/Samples/I2PEchoServer/bin/Debug/net5.0/I2PEchoServer.dll",
37 | "args": [],
38 | "cwd": "${workspaceFolder}/Samples/I2PEchoServer",
39 | "console": "internalConsole",
40 | "stopAtEntry": false
41 | },
42 | {
43 | "name": "I2PEchoClient (console)",
44 | "type": "coreclr",
45 | "request": "launch",
46 | "preLaunchTask": "buildeclient",
47 | "program": "${workspaceFolder}/Samples/I2PEchoClient/bin/Debug/net5.0/I2PEchoClient.dll",
48 | "args": [],
49 | "cwd": "${workspaceFolder}/Samples/I2PEchoClient",
50 | "console": "internalConsole",
51 | "stopAtEntry": false
52 | },
53 | {
54 | "name": ".NET Core Attach",
55 | "type": "coreclr",
56 | "request": "attach",
57 | "processId": "${command:pickProcess}"
58 | }
59 | ]
60 | }
--------------------------------------------------------------------------------
/I2CP/I2CP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/CreateLeaseSet2Message.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 | using Org.BouncyCastle.Math;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class CreateLeaseSet2Message: I2CPMessage
12 | {
13 | public ushort SessionId;
14 | public I2PSigningPrivateKey DSAPrivateSigningKey;
15 | public IList PrivateKeys;
16 | public I2PLeaseSet Leases;
17 | public I2PLeaseSet2 Leases2;
18 |
19 | public CreateLeaseSet2Message( BufRef reader, I2CPSession session )
20 | : base( ProtocolMessageType.CreateLeaseSet2Message )
21 | {
22 | SessionId = reader.ReadFlip16();
23 |
24 | var lstype = reader.Read8();
25 | switch( lstype )
26 | {
27 | case 1: // LS
28 | Leases = new I2PLeaseSet( reader );
29 | break;
30 |
31 | case 3: // LS2
32 | Leases2 = new I2PLeaseSet2( reader );
33 | break;
34 |
35 | case 5: // Enc LS2
36 | throw new NotImplementedException();
37 |
38 | case 7: // Meta LS2
39 | throw new NotImplementedException();
40 | }
41 |
42 | PrivateKeys = new List();
43 | var privkeycount = reader.Read8();
44 | for( int i = 0; i < privkeycount; ++i )
45 | {
46 | var etype = (I2PPublicKey.KeyTypes)reader.ReadFlip16();
47 | var keylen = reader.ReadFlip16();
48 | PrivateKeys.Add( new I2PPrivateKey( reader, new I2PCertificate( etype, keylen ) ) );
49 | }
50 | }
51 |
52 | public override void Write( BufRefStream dest )
53 | {
54 | throw new NotImplementedException();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/CreateLeaseSetMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 | using Org.BouncyCastle.Math;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class CreateLeaseSetMessage: I2CPMessage
12 | {
13 | public ushort SessionId;
14 | public BufLen DSAPrivateSigningKey;
15 | public I2PPrivateKey PrivateKey;
16 | public I2PLeaseSet Leases;
17 |
18 | public CreateLeaseSetMessage(
19 | I2PDestination dest,
20 | ushort sessionid,
21 | I2PLeaseSet ls,
22 | List leases ): base( ProtocolMessageType.CreateLS )
23 | {
24 | SessionId = sessionid;
25 | Leases = ls;
26 | }
27 |
28 | public CreateLeaseSetMessage( BufRef reader, I2CPSession session )
29 | : base( ProtocolMessageType.CreateLS )
30 | {
31 | SessionId = reader.ReadFlip16();
32 |
33 | var cert = session.SessionIds[SessionId].Config.Destination.Certificate;
34 |
35 | DSAPrivateSigningKey = reader.ReadBufLen( 20 );
36 |
37 | PrivateKey = new I2PPrivateKey( reader, cert );
38 | Leases = new I2PLeaseSet( reader );
39 | }
40 |
41 | static readonly byte[] TwentyBytes = { 0, 0, 0, 0, 0, 0, 0, 0,
42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
43 |
44 | public override void Write( BufRefStream dest )
45 | {
46 | dest.Write( (BufRefLen)BufUtils.Flip16BL( SessionId ) );
47 | dest.Write( TwentyBytes );
48 | PrivateKey.Write( dest );
49 | Leases.Write( dest );
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/CreateSessionMessage.cs:
--------------------------------------------------------------------------------
1 | using I2PCore.Data;
2 | using I2PCore.Utils;
3 |
4 | namespace I2P.I2CP.Messages
5 | {
6 | public class CreateSessionMessage: I2CPMessage
7 | {
8 | public I2PSessionConfig Config;
9 |
10 | public CreateSessionMessage( I2PSessionConfig cfg ): base( ProtocolMessageType.CreateSession )
11 | {
12 | Config = cfg;
13 | }
14 |
15 | public CreateSessionMessage( BufRef reader ) : base( ProtocolMessageType.CreateSession )
16 | {
17 | Config = new I2PSessionConfig( reader );
18 | }
19 |
20 | public override void Write( BufRefStream dest )
21 | {
22 | Config.Write( dest );
23 | }
24 |
25 | public override string ToString()
26 | {
27 | return Config?.ToString();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/DestLookupMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class DestLookupMessage: I2CPMessage
12 | {
13 | public I2PIdentHash Ident;
14 |
15 | public DestLookupMessage( I2PIdentHash hash )
16 | : base( ProtocolMessageType.DestLookup )
17 | {
18 | Ident = hash;
19 | }
20 |
21 | public DestLookupMessage( BufRefLen reader )
22 | : base( ProtocolMessageType.DestLookup )
23 | {
24 | Ident = new I2PIdentHash( reader );
25 | }
26 |
27 | public override void Write( BufRefStream dest )
28 | {
29 | Ident.Write( dest );
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/DestReplyMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class DestReplyMessage : I2CPMessage
12 | {
13 | public I2PDestination Destination;
14 | public I2PIdentHash Ident;
15 |
16 | // Success
17 | public DestReplyMessage( I2PDestination dest )
18 | : base( ProtocolMessageType.DestReply )
19 | {
20 | Destination = dest;
21 | }
22 |
23 | // Failure
24 | public DestReplyMessage( I2PIdentHash hash )
25 | : base( ProtocolMessageType.DestReply )
26 | {
27 | Ident = hash;
28 | }
29 |
30 | public DestReplyMessage( BufRefLen reader )
31 | : base( ProtocolMessageType.DestReply )
32 | {
33 | Destination = null;
34 | Ident = null;
35 |
36 | if ( reader.Length == 0 ) return;
37 | if ( reader.Length == 32 )
38 | {
39 | Ident = new I2PIdentHash( reader );
40 | }
41 | else
42 | {
43 | Destination = new I2PDestination( reader );
44 | }
45 | }
46 |
47 | public override void Write( BufRefStream dest )
48 | {
49 | if ( Destination != null )
50 | {
51 | Destination.Write( dest );
52 | return;
53 | }
54 |
55 | Ident.Write( dest );
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/DestroySessionMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2P.I2CP.Messages
8 | {
9 | public class DestroySessionMessage : I2CPMessage
10 | {
11 | public ushort SessionId;
12 |
13 | public DestroySessionMessage( ushort sessid )
14 | : base( ProtocolMessageType.DestroySession )
15 | {
16 | SessionId = sessid;
17 | }
18 |
19 | public DestroySessionMessage( BufRef reader )
20 | : base( ProtocolMessageType.DestroySession )
21 | {
22 | SessionId = reader.ReadFlip16();
23 | }
24 |
25 | public override void Write( BufRefStream dest )
26 | {
27 | dest.Write( (BufRefLen)BufUtils.Flip16BL( SessionId ) );
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/GetDateMessage.cs:
--------------------------------------------------------------------------------
1 | using I2PCore.Data;
2 | using I2PCore.Utils;
3 |
4 | namespace I2P.I2CP.Messages
5 | {
6 | public class GetDateMessage: I2CPMessage
7 | {
8 | public I2PString Version;
9 | public I2PMapping Mapping;
10 |
11 | public GetDateMessage( string ver, I2PMapping map )
12 | : base( ProtocolMessageType.GetDate )
13 | {
14 | Version = new I2PString( ver );
15 | Mapping = map;
16 | }
17 |
18 | public GetDateMessage( BufRefLen reader )
19 | : base( ProtocolMessageType.GetDate )
20 | {
21 | Version = new I2PString( reader );
22 |
23 | // As of release 0.9.11, the authentication [Mapping] may be included, with the keys i2cp.username and i2cp.password.
24 | if ( reader.Length > 0 )
25 | {
26 | Mapping = new I2PMapping( reader );
27 | }
28 | }
29 |
30 | public override void Write( BufRefStream dest )
31 | {
32 | Version.Write( dest );
33 |
34 | if ( Mapping != null )
35 | {
36 | Mapping.Write( dest );
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/HostLookupMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class HostLookupMessage : I2CPMessage
12 | {
13 | public enum HostLookupTypes: byte { Hash = 0, HostName = 1 }
14 |
15 | public ushort SessionId;
16 | public uint RequestId;
17 | public uint TimeoutMilliseconds;
18 | public HostLookupTypes RequestType;
19 | public I2PIdentHash Hash;
20 | public I2PString HostName;
21 |
22 | public HostLookupMessage( BufRefLen reader )
23 | : base( ProtocolMessageType.HostLookup )
24 | {
25 | SessionId = reader.ReadFlip16();
26 | RequestId = reader.ReadFlip32();
27 | TimeoutMilliseconds = reader.ReadFlip32();
28 | RequestType = (HostLookupTypes)reader.Read8();
29 |
30 | switch ( RequestType )
31 | {
32 | case HostLookupTypes.Hash:
33 | Hash = new I2PIdentHash( reader );
34 | break;
35 |
36 | case HostLookupTypes.HostName:
37 | HostName = new I2PString( reader );
38 | break;
39 | }
40 | }
41 |
42 | public override void Write( BufRefStream dest )
43 | {
44 | throw new NotImplementedException();
45 | }
46 |
47 | public override string ToString()
48 | {
49 | return $"{GetType().Name} {SessionId} {RequestId} {Hash?.Id32Short} {HostName}";
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/HostReplyMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class HostReplyMessage : I2CPMessage
12 | {
13 | public enum HostLookupResults: byte
14 | {
15 | Success = 0,
16 | Failure = 1,
17 | LookupPasswordRequired = 2,
18 | PrivateKeyRequired = 3,
19 | LookupPasswordAndPrivateKeyRequired = 4,
20 | LeasesetDecryptionFailure = 5,
21 | }
22 |
23 | public ushort SessionId;
24 | public uint RequestId;
25 | public HostLookupResults ResultCode;
26 | public I2PDestination Destination;
27 |
28 | public HostReplyMessage( ushort sessid, uint reqid, HostLookupResults rescode )
29 | : base( ProtocolMessageType.HostLookupReply )
30 | {
31 | SessionId = sessid;
32 | RequestId = reqid;
33 | ResultCode = rescode;
34 | }
35 |
36 | public HostReplyMessage( ushort sessid, uint reqid, I2PDestination dest )
37 | : base( ProtocolMessageType.HostLookupReply )
38 | {
39 | SessionId = sessid;
40 | RequestId = reqid;
41 | ResultCode = HostLookupResults.Success;
42 | Destination = dest;
43 | }
44 |
45 | public override void Write( BufRefStream dest )
46 | {
47 | var header = new byte[7];
48 | var writer = new BufRefLen( header );
49 | writer.WriteFlip16( SessionId );
50 | writer.WriteFlip32( RequestId );
51 | writer.Write8( (byte)ResultCode );
52 | dest.Write( header );
53 |
54 | if ( ResultCode == HostLookupResults.Success )
55 | {
56 | Destination.Write( dest );
57 | }
58 | }
59 |
60 | public override string ToString()
61 | {
62 | return $"{GetType().Name} {SessionId} {RequestId} {ResultCode} {Destination}";
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/Message.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.IO;
6 | using I2PCore.Utils;
7 | using I2PCore.Data;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public abstract class I2CPMessage
12 | {
13 | public enum PayloadFormat : byte
14 | {
15 | Streaming = 6,
16 | Datagram = 17,
17 | Raw = 18,
18 | };
19 |
20 | public enum ProtocolMessageType : byte
21 | {
22 | CreateSession = 1,
23 | ReconfigSession = 2,
24 | DestroySession = 3,
25 | CreateLS = 4,
26 | SendMessage = 5,
27 | RecvMessageBegin = 6,
28 | RecvMessageEnd = 7,
29 | GetBWLimits = 8,
30 | SessionStatus = 20,
31 | RequestLS = 21,
32 | MessageStatus = 22,
33 | BWLimits = 23,
34 | ReportAbuse = 29,
35 | Disconnect = 30,
36 | MessagePayload = 31,
37 | GetDate = 32,
38 | SetDate = 33,
39 | DestLookup = 34,
40 | DestReply = 35,
41 | SendMessageExpires = 36,
42 | RequestVarLS = 37,
43 | HostLookup = 38,
44 | HostLookupReply = 39,
45 | CreateLeaseSet2Message_Deprecated = 40,
46 | CreateLeaseSet2Message = 41,
47 | }
48 |
49 | public readonly ProtocolMessageType MessageType;
50 |
51 | protected I2CPMessage( ProtocolMessageType msgtype )
52 | {
53 | MessageType = msgtype;
54 | }
55 |
56 | public abstract void Write( BufRefStream dest );
57 |
58 | /*
59 | public void WriteMessage( BufRefStream dest, params I2PType[] fields )
60 | {
61 | var buf = new BufRefStream();
62 | foreach ( var field in fields ) field.Write( buf );
63 |
64 | dest.Write( BufUtils.Flip32B( (uint)buf.Length ) );
65 | dest.Write( (byte)MessageType );
66 | dest.Write( buf );
67 | }
68 | */
69 |
70 | public byte[] ToByteArray()
71 | {
72 | var buf = new BufRefStream();
73 | Write( buf );
74 | return buf.ToArray();
75 | }
76 |
77 | public override string ToString()
78 | {
79 | return GetType().Name;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/MessagePayloadMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 |
8 | namespace I2P.I2CP.Messages
9 | {
10 | public class MessagePayloadMessage: I2CPMessage
11 | {
12 | public ushort SessionId;
13 | public uint MessageId;
14 | public BufLen Payload;
15 |
16 | public MessagePayloadMessage( ushort sessionid, uint msgid, BufLen data )
17 | : base( ProtocolMessageType.MessagePayload )
18 | {
19 | SessionId = sessionid;
20 | MessageId = msgid;
21 | Payload = data;
22 | }
23 |
24 | public override void Write( BufRefStream dest )
25 | {
26 | var header = new byte[10];
27 | var writer = new BufRefLen( header );
28 | writer.WriteFlip16( SessionId );
29 | writer.WriteFlip32( MessageId );
30 | writer.WriteFlip32( (uint)Payload.Length );
31 |
32 | dest.Write( header );
33 | dest.Write( (BufRefLen)Payload );
34 | }
35 |
36 | public override string ToString()
37 | {
38 | return $"{GetType().Name} {SessionId} {MessageId} {Payload}";
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/MessageStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2P.I2CP.Messages
8 | {
9 | public class MessageStatusMessage: I2CPMessage
10 | {
11 | public ushort SessionId;
12 | public uint MessageId;
13 | public uint AvailableMessageSize;
14 | public uint ClientNonce;
15 |
16 | public enum MessageStatatuses : byte
17 | {
18 | Available = 0,
19 | Accepted = 1,
20 | BestEffortSuccess = 2,
21 | BestEffortFailure = 3,
22 | GuaranteedSuccess = 4,
23 | GuaranteedFailure = 5,
24 | LocalSuccess = 6,
25 | LocalFailure = 7,
26 | RouterFailure = 8,
27 | NetworkFailure = 9,
28 | BadSession = 10,
29 | BadMessage = 11,
30 | BadOptions = 12,
31 | OverflowFailure = 13,
32 | MessageExpired = 14,
33 | BadLocalLeaseset = 15,
34 | NoLocalTunnels = 16,
35 | UnsupportedEncryption = 17,
36 | BadDestination = 18,
37 | BadLeaseset = 19,
38 | ExpiredLeaseset = 20,
39 | NoLeaseset = 21,
40 | }
41 | public MessageStatatuses MessageStatus;
42 |
43 | public MessageStatusMessage(
44 | ushort sessionid,
45 | uint messageid,
46 | MessageStatatuses messagestatus,
47 | uint availablemessagesize,
48 | uint clientnonce
49 | ) : base( ProtocolMessageType.MessageStatus )
50 | {
51 | SessionId = sessionid;
52 | MessageId = messageid;
53 | MessageStatus = messagestatus;
54 | AvailableMessageSize = availablemessagesize;
55 | ClientNonce = clientnonce;
56 | }
57 |
58 | public MessageStatusMessage( BufRef reader )
59 | : base( ProtocolMessageType.MessageStatus )
60 | {
61 | throw new NotImplementedException();
62 | }
63 |
64 | public override void Write( BufRefStream dest )
65 | {
66 | var header = new byte[15];
67 | var writer = new BufRefLen( header );
68 | writer.WriteFlip16( SessionId );
69 | writer.WriteFlip32( MessageId );
70 | writer.Write8( (byte)MessageStatus );
71 | writer.WriteFlip32( AvailableMessageSize );
72 | writer.WriteFlip32( ClientNonce );
73 | dest.Write( header );
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/ReceiveMessageEndMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class ReceiveMessageEndMessage: I2CPMessage
12 | {
13 | public ushort SessionId;
14 | public uint MessageId;
15 |
16 | public ReceiveMessageEndMessage( ushort sessionid, uint msgid )
17 | : base( ProtocolMessageType.RecvMessageEnd )
18 | {
19 | SessionId = sessionid;
20 | MessageId = msgid;
21 | }
22 |
23 | public ReceiveMessageEndMessage( BufRefLen reader )
24 | : base( ProtocolMessageType.RecvMessageEnd )
25 | {
26 | SessionId = reader.ReadFlip16();
27 | MessageId = reader.ReadFlip32();
28 | }
29 |
30 | public override void Write( BufRefStream dest )
31 | {
32 | var header = new byte[6];
33 | var writer = new BufRefLen( header );
34 | writer.WriteFlip16( SessionId );
35 | writer.WriteFlip32( MessageId );
36 | dest.Write( header );
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/ReconfigureSessionMessage.cs:
--------------------------------------------------------------------------------
1 | using I2PCore.Data;
2 | using I2PCore.Utils;
3 |
4 | namespace I2P.I2CP.Messages
5 | {
6 | public class ReconfigureSessionMessage: I2CPMessage
7 | {
8 | public ushort SessionId;
9 | public I2PSessionConfig Config;
10 |
11 | public ReconfigureSessionMessage( I2PSessionConfig cfg ): base( ProtocolMessageType.ReconfigSession )
12 | {
13 | Config = cfg;
14 | }
15 |
16 | public ReconfigureSessionMessage( BufRef reader ) : base( ProtocolMessageType.ReconfigSession )
17 | {
18 | SessionId = reader.ReadFlip16();
19 | Config = new I2PSessionConfig( reader );
20 | }
21 |
22 | public override void Write( BufRefStream dest )
23 | {
24 | dest.Write( BufUtils.Flip16B( SessionId ) );
25 | Config.Write( dest );
26 | }
27 |
28 | public override string ToString()
29 | {
30 | return Config?.ToString();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/RequestLeaseSetMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 |
8 | namespace I2P.I2CP.Messages
9 | {
10 | public class RequestLeaseSetMessage: I2CPMessage
11 | {
12 | public ushort SessionId;
13 | public List Leases = new List();
14 |
15 | public RequestLeaseSetMessage( ushort sessionid, IEnumerable leases )
16 | : base( ProtocolMessageType.RequestLS )
17 | {
18 | SessionId = sessionid;
19 | Leases.AddRange( leases );
20 | }
21 |
22 | public RequestLeaseSetMessage( BufRef reader )
23 | : base( ProtocolMessageType.RequestLS )
24 | {
25 | SessionId = reader.ReadFlip16();
26 | var leases = reader.Read8();
27 | for ( int i = 0; i < leases; ++i )
28 | {
29 | Leases.Add( new I2PLease( reader ) );
30 | }
31 | }
32 |
33 | public override void Write( BufRefStream dest )
34 | {
35 | var buf = new byte[3];
36 | var writer = new BufRefLen( buf );
37 | writer.WriteFlip16( SessionId );
38 | writer.Write8( (byte)Leases.Count );
39 | dest.Write( buf );
40 |
41 | for ( int i = 0; i < Leases.Count; ++i )
42 | {
43 | Leases[i].TunnelGw.Write( dest );
44 | Leases[i].TunnelId.Write( dest );
45 | }
46 | new I2PDate( DateTime.UtcNow.AddMinutes( 9 ) ).Write( dest );
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/RequestVariableLeaseSetMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 |
8 | namespace I2P.I2CP.Messages
9 | {
10 | public class RequestVariableLeaseSetMessage: I2CPMessage
11 | {
12 | public ushort SessionId;
13 | public List Leases = new List();
14 |
15 | public RequestVariableLeaseSetMessage( ushort sessionid, IEnumerable leases )
16 | : base( ProtocolMessageType.RequestVarLS )
17 | {
18 | SessionId = sessionid;
19 | Leases.AddRange( leases );
20 | }
21 |
22 | public RequestVariableLeaseSetMessage( BufRef reader )
23 | : base( ProtocolMessageType.RequestVarLS )
24 | {
25 | SessionId = reader.ReadFlip16();
26 | var leases = reader.Read8();
27 | for ( int i = 0; i < leases; ++i )
28 | {
29 | Leases.Add( new I2PLease( reader ) );
30 | }
31 | }
32 |
33 | public override void Write( BufRefStream dest )
34 | {
35 | var header = new byte[3];
36 | var writer = new BufRefLen( header );
37 | writer.WriteFlip16( SessionId );
38 | writer.Write8( (byte)Leases.Count );
39 | dest.Write( header );
40 |
41 | foreach( var ls in Leases )
42 | {
43 | ls.TunnelGw.Write( dest );
44 | ls.TunnelId.Write( dest );
45 | new I2PDate( ls.Expire ).Write( dest );
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/SendMessageExpiresMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class SendMessageExpiresMessage : I2CPMessage
12 | {
13 | public ushort SessionId;
14 | public I2PDestination Destination;
15 | public BufLen Payload;
16 | public uint Nonce;
17 |
18 | // Ignored
19 | private BufLen Flags;
20 | private DateTime Expiration;
21 |
22 | public SendMessageExpiresMessage( BufRefLen reader )
23 | : base( ProtocolMessageType.SendMessageExpires )
24 | {
25 | SessionId = reader.ReadFlip16();
26 | Destination = new I2PDestination( reader );
27 | var len = reader.ReadFlip32();
28 | Payload = reader.ReadBufLen( (int)len );
29 | Nonce = reader.ReadFlip32();
30 | }
31 |
32 | public override void Write( BufRefStream dest )
33 | {
34 | throw new NotImplementedException();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/SendMessageMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class SendMessageMessage : I2CPMessage
12 | {
13 | public ushort SessionId;
14 | public I2PDestination Destination;
15 | public BufLen Payload;
16 | public uint Nonce;
17 |
18 | public SendMessageMessage( BufRefLen reader )
19 | : base( ProtocolMessageType.SendMessage )
20 | {
21 | SessionId = reader.ReadFlip16();
22 | Destination = new I2PDestination( reader );
23 | var len = reader.ReadFlip32();
24 | Payload = reader.ReadBufLen( (int)len );
25 | Nonce = reader.ReadFlip32();
26 | }
27 |
28 | public override void Write( BufRefStream dest )
29 | {
30 | throw new NotImplementedException();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/SessionStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2P.I2CP.Messages
8 | {
9 | public class SessionStatusMessage: I2CPMessage
10 | {
11 | public ushort SessionId;
12 |
13 | public enum SessionStates : byte { Destroyed = 0, Created = 1, Updated = 2, Invalid = 3, Refused = 4, NoLeaseSet = 21 }
14 | public SessionStates SessionState;
15 |
16 | public SessionStatusMessage( ushort sessid, SessionStates state )
17 | : base( ProtocolMessageType.SessionStatus )
18 | {
19 | SessionId = sessid;
20 | SessionState = state;
21 | }
22 |
23 | public SessionStatusMessage( BufRef reader )
24 | : base( ProtocolMessageType.SessionStatus )
25 | {
26 | SessionId = reader.ReadFlip16();
27 | SessionState = (SessionStates)reader.Read8();
28 | }
29 |
30 | public override void Write( BufRefStream dest )
31 | {
32 | var header = new byte[3];
33 | var writer = new BufRefLen( header );
34 | writer.WriteFlip16( SessionId );
35 | writer.Write8( (byte)SessionState );
36 | dest.Write( header );
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/I2CP/I2CP/Messages/SetDateMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2P.I2CP.Messages
10 | {
11 | public class SetDateMessage: I2CPMessage
12 | {
13 | public I2PDate Date;
14 | public I2PString Version;
15 |
16 | public SetDateMessage( I2PDate date, I2PString ver )
17 | : base( ProtocolMessageType.SetDate )
18 | {
19 | Date = date;
20 | Version = ver;
21 | }
22 |
23 | public SetDateMessage( BufRef data )
24 | : base( ProtocolMessageType.SetDate )
25 | {
26 | Date = new I2PDate( data );
27 | Version = new I2PString( data );
28 | }
29 |
30 | public override void Write( BufRefStream dest )
31 | {
32 | Date.Write( dest );
33 | Version.Write( dest );
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/I2CP/I2CP/States/I2CPState.cs:
--------------------------------------------------------------------------------
1 | using I2PCore;
2 | using I2PCore.Utils;
3 | using I2P.I2CP.Messages;
4 |
5 | namespace I2P.I2CP.States
6 | {
7 | public abstract class I2CPState
8 | {
9 | public static readonly TickSpan InactivityTimeout = TickSpan.Minutes( 20 );
10 | public static readonly TickSpan HandshakeTimeout = TickSpan.Seconds( 30 );
11 | public static readonly TickSpan EstablishedDestinationTimeout = TickSpan.Seconds( 150 );
12 |
13 | public TickCounter Created = TickCounter.Now;
14 | public TickCounter LastAction = TickCounter.Now;
15 | public int Retries = 0;
16 |
17 | protected I2CPSession Session;
18 |
19 | protected I2CPState( I2CPSession sess )
20 | {
21 | Session = sess;
22 | }
23 |
24 | protected bool Timeout( TickSpan timeout ) { return LastAction.DeltaToNow > timeout; }
25 | protected void DataSent() { LastAction.SetNow(); }
26 |
27 | internal virtual I2CPState Run()
28 | {
29 | if ( Timeout( HandshakeTimeout ) )
30 | {
31 | throw new FailedToConnectException( $"{this} WaitProtVer {Session.DebugId} Failed to connect. Timeout." );
32 | }
33 |
34 | return this;
35 | }
36 |
37 | internal abstract I2CPState MessageReceived( I2CPMessage msg );
38 |
39 | public override string ToString()
40 | {
41 | return $"{Session} {GetType().Name}";
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/I2CP/I2CP/States/WaitGetDateState.cs:
--------------------------------------------------------------------------------
1 | using I2P.I2CP.Messages;
2 | using I2PCore.Data;
3 | using I2CP.I2CP.States;
4 |
5 | namespace I2P.I2CP.States
6 | {
7 | internal class WaitGetDateState: I2CPState
8 | {
9 | internal WaitGetDateState( I2CPSession sess ): base( sess ) { }
10 |
11 | internal override I2CPState MessageReceived( I2CPMessage msg )
12 | {
13 | if ( msg is GetDateMessage gdm )
14 | {
15 | //var reply = new SetDateMessage( I2PDate.Now, new I2PString( "0.9.15" ) );
16 | var reply = new SetDateMessage( I2PDate.Now, gdm.Version );
17 | Session.Send( reply );
18 | return new EstablishedState( Session );
19 | }
20 | return this;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/I2CP/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/I2P.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {
8 | "dotnet-test-explorer.testProjectPath": "**/*Tests.csproj"
9 | }
10 | }
--------------------------------------------------------------------------------
/I2PCore.NTests/I2PCore.NTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/I2PCore.NTests/SignatureTest.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using I2PCore.Data;
3 | using I2PCore.Utils;
4 | using Org.BouncyCastle.Math;
5 | using I2PCore.TunnelLayer.I2NP.Data;
6 | using System.Text;
7 | using System.Linq;
8 | using System.Globalization;
9 |
10 | namespace I2PTests
11 | {
12 | [TestFixture]
13 | public class SignatureTest
14 | {
15 | public SignatureTest()
16 | {
17 | }
18 |
19 | public void TestCert( I2PCertificate certificate )
20 | {
21 | var privskey = new I2PSigningPrivateKey( certificate );
22 | var pubskey = new I2PSigningPublicKey( privskey );
23 |
24 | var data = new BufLen( BufUtils.RandomBytes( 500 ) );
25 | var sign = new I2PSignature( new BufRefLen( I2PSignature.DoSign( privskey, data ) ), certificate );
26 |
27 | Assert.IsTrue( I2PSignature.DoVerify( pubskey, sign, data ) );
28 | }
29 |
30 | [Test]
31 | public void TestEdDSASHA512Ed25519()
32 | {
33 | TestCert( new I2PCertificate( I2PSigningKey.SigningKeyTypes.EdDSA_SHA512_Ed25519 ) );
34 | }
35 |
36 | [Test]
37 | public void TestDSASHA1()
38 | {
39 | TestCert( new I2PCertificate( I2PSigningKey.SigningKeyTypes.DSA_SHA1 ) );
40 | }
41 |
42 | [Test]
43 | public void TestECDSASHA256P256()
44 | {
45 | TestCert( new I2PCertificate( I2PSigningKey.SigningKeyTypes.ECDSA_SHA256_P256 ) );
46 | }
47 |
48 | [Test]
49 | public void TestECDSASHA384P384()
50 | {
51 | TestCert( new I2PCertificate( I2PSigningKey.SigningKeyTypes.ECDSA_SHA384_P384 ) );
52 | }
53 |
54 | [Test]
55 | public void TestECDSASHA512P521()
56 | {
57 | TestCert( new I2PCertificate( I2PSigningKey.SigningKeyTypes.ECDSA_SHA512_P521 ) );
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/I2PCore.NTests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/I2PCore/ChecksumFailureException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore
7 | {
8 | public class ChecksumFailureException: Exception
9 | {
10 | public ChecksumFailureException() : base() { }
11 | public ChecksumFailureException( string msg ) : base( msg ) { }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/backup_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFfTCCA2WgAwIBAgIEOprmhjANBgkqhkiG9w0BAQ0FADBvMQswCQYDVQQGEwJY
3 | WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
4 | b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEYMBYGA1UEAwwPYmFja3VwQG1haWwu
5 | aTJwMB4XDTEzMTAxMzEzNDQ1NVoXDTIzMTAxMzEzNDQ1NVowbzELMAkGA1UEBhMC
6 | WFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255
7 | bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGDAWBgNVBAMMD2JhY2t1cEBtYWls
8 | LmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIoAkobXwk/Enf1d
9 | roHyqCyvcJfZJVTwb/LgYWAvCBMCr+RGqlSgtk3g69Y3I0xU08fD2kGt3r5Pwsbr
10 | omXIbJAcccyLqmQ5QX6QgL+X9VpMDp9C4h2RogCrqLBAWw4cuZ4RS9VCpP1Yis7H
11 | uejYqENP86p7BsRnuW/4cYnfunAdMpss4LpRGQXt1nTX+kfgCYgnKFbFqwAHt7yV
12 | Ds+Pe6FuBHPlp+sc1amKRcUnSvhXLsv43VicnT7xYL/kUsN83wrtHA3B4aGDx3aA
13 | 3/EzuRmIXQB0BlTZILMEyYwG/nc4OsW82QYrvEZ9BIg9A4lF/wS/KZCICPxLF2zo
14 | dGjnmlgkiA4s8eO+va/ElHyELjckVXqmG1eXHhSkEsDvOQJy01IUuwLinvq7cUbJ
15 | HfJBZJllEg+sLDCv3FkEqN+XjBNFfQN4oNew4w6IPY6YH1INVB9LL0Cmdu4DudLv
16 | TY8OcI8eSfez3hmm+pYQ23PJRYYnvRDnRECyIWBegkckWRh8U/WvZUYUvETK6EDl
17 | /0KpTtfzX6MqHA5D6bTAB8Y3ijGMLrZ/B5vj5yCoZbLiGme9X2moR2k1LEhdhtzV
18 | exsqezCpg6dn48FTX7mHjvR5/r4kz2jqBGmdPUWIIxnjFUzDUK3llVQiHihleHpe
19 | jL4LqnhBGKWFRTaVwaIkBG4zAfIzAgMBAAGjITAfMB0GA1UdDgQWBBQNkfW7bSMl
20 | 1/4KDbgwrkf9x1Zu/TANBgkqhkiG9w0BAQ0FAAOCAgEAGg3a3rTf0EznQocmio0T
21 | 5gCoL0n8h6yKW/PyPAIELrd9wiYjhJFcWvMTcJJJnVqmAL5vpvhaAFVtAfx70MGa
22 | 0DZ7FvytK5hEfF4IqOFDyEEVGJR5rIpVK4MeI1nmwEsxdbW+FhODjtRzgYO8XBME
23 | Xj4aY1FWg9vxc3reUj6PSFsZtsB0aLiRgL9JDovJIiRw0Uqr1v2wXBte5yVCxDge
24 | vTREZtpK4cKetoOa68pwSXI32JwKE18j6bfdKVBCcYQKlKP/3gHGduaDrQv3w32S
25 | DRym5s6MREeTUOtAw4wq46KpdOX8yyAqJPrCfMwS6ORd3t+egqOw0PUnsqb97w4O
26 | lUtrRYvb2cOj60SmRx4vJvItyuHbKqIK7o2e1RcUZPXYoAVx2ww4XB2Wk4D7LSAs
27 | cS7nLj8yAqzJ2qqtBzxu+zILJtkVa12dKF0xmS0BxBp4sCYiBtmAVE8AWQqEuSHA
28 | FrMWqoXcjcfdvvyX487FFWWUE7ZBIn0hee2sK9J9+SPtqczJaN7TF3K3nzo65WJG
29 | 1epltmq2Ugjb67Gz7v4y7H23DJ/qhm8yLtCHTj69HTta5I08j6Kut924WLZaiMO/
30 | 4YoEL5AE63X0sxYibKFQiq7FW5nUJA280GRlY3xSMFzlB2ggazrUV3YAWVDhfdnI
31 | flpzWXkFM2D36OUaubfe9YY=
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/bugme_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
31 | wpBgPyAFAwouPy1whmnx
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/creativecowpat_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
34 | Hz8KWVkHZg==
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/echelon_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
31 | JNJOWTH/Vas1W6XlwGcOOAARTQ==
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/hottuna_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
33 | -----END CERTIFICATE-----
34 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/igor_at_novg.net.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
33 | -----END CERTIFICATE-----
34 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/lazygravy_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
33 | +g==
34 | -----END CERTIFICATE-----
35 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/meeh_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
31 | o3eNsanvTU+TIFBh2Q==
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/I2PCore/Contrib/Certificates/Reseed/r4sas-reseed_at_mail.i2p.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFiTCCA3GgAwIBAgIEY2XeQjANBgkqhkiG9w0BAQ0FADB1MQswCQYDVQQGEwJY
3 | WDELMAkGA1UECAwCWFgxHjAcBgNVBAcMFUkyUCBBbm9ueW1vdXMgTmV0d29yazEL
4 | MAkGA1UECgwCWFgxDDAKBgNVBAsMA0kyUDEeMBwGA1UEAwwVcjRzYXMtcmVzZWVk
5 | QG1haWwuaTJwMB4XDTE3MDYyMjEwNTQ1NFoXDTI3MDYyMDEwNTQ1NFowdTELMAkG
6 | A1UEBhMCWFgxCzAJBgNVBAgMAlhYMR4wHAYDVQQHDBVJMlAgQW5vbnltb3VzIE5l
7 | dHdvcmsxCzAJBgNVBAoMAlhYMQwwCgYDVQQLDANJMlAxHjAcBgNVBAMMFXI0c2Fz
8 | LXJlc2VlZEBtYWlsLmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
9 | ANgsj5LhF4uGG4RDueShqYQZsG5Rz6XUAtK9sVGFdmdJTDZirUMZcCGCGZP/Harz
10 | QaZU9EYxOCztnpLCQksSCpdRsij56MURS0tW/1x7LHIDUOi911Of57jgIHH+3E5n
11 | 6tuRxEk6J/9Ji3PI+89kl0sPKMVFMyKkINprVTA5zr/keyYEG0p6HSEYYiJkQH78
12 | 8uoOCAmlk9mxkJFb+zviCk6jsYwdH+ofD6Lw5ueOlYUbeZ9Nd7jfSdf20XM7ofIw
13 | W2COtsbq3J7vNrQJMV7HkHxVx/7OqmjQF02OahZFZREVZqbHpL501iTn9Iqd5qKq
14 | IsxYjk7ZnP4UUCBk8NOU5TuWsy0qNw+TJDI9s55Fi4KPtXWf47HIl6CdpM5y/D5L
15 | eufCojSwPKlrD6x9gTyJdBggBZRIyplXdKffo/95hUhEkv86yfsVVR7Gu1uy0O8T
16 | Gtb8Da/oi5eEZBHWonLVicLPei5jeo+1gbR09PQ6s41uMZlOhMe4RSgiIQj/7UVo
17 | ffKdl1MPNKr1u2fgVj8kxqg8ZivWKQ2taEgimU2EkQcNcE96M9yQlNNpNvqSAQVk
18 | wYXlHt0AN6A1A8u1pItxaTwXnbmx+OBJZoKl4ZQeaC8wtKjTgAgVXp+g5iot2gir
19 | LjxCRx1WLG1c8vRg1W8CDZII8Swc8EWpMhI+0hPv7/4/AgMBAAGjITAfMB0GA1Ud
20 | DgQWBBTN5sKbrNzwE8sgMGDekfOPgX8/JDANBgkqhkiG9w0BAQ0FAAOCAgEAjLaB
21 | bHqvFTs0ikAtesk9r8+8XVIsP5FR57zZCek2vxkHcCQWw8Uqs3ndInRX4FirKSLT
22 | WRb4aSwFCkrmwueecTpXN/RBC+fZj+POCfdILEsA+FGreAM2q5ZXv/Q0jyIXOXEM
23 | +KL0JZXnNS0/dqR3IYbC7f39CL6Sf40gRGTwTWWGg3KnynoS0v1zQcZLTMhHBD2X
24 | tgdIPbroq9t4gXa7Dhm0egYfQOI/7re2wiZT7UWVVwEpYqKf6JApFHa1nNOFMrLF
25 | 45JHQIHArkoxpQdfSe9HBoyJiB5vz398rHZeqbJaF3PIg9rxWWY/NvvOVuIk8U5z
26 | 0jExhg29a88B32U7ndvQJqIuGiQghzCiLxC/y1+wAdpeDSbD3OAOHqplvMj3BUn9
27 | yhDSLSjtfBJjnXKxtEcWLR0edHCGEk5mAcL7q1WNxDpxaICwGGpNZN53CtFx7amb
28 | egYil448DmiqoQTCTE9pBz8YjwiVfCYLYv17O0NJyYM9Efy/wL3rFlsPJniWHMuH
29 | imZybVU4ukjvfOZ+LY4COTwz6w4sfA7a+i+2mOynC7eKX8Yg6i1nXlcY1Z8ykNgi
30 | 7B3kz1T/DV56CIm6QUWtepfuKTYq4C6QrBBIXLk1d5g95aWA21u1LRqNZ9GLH+eA
31 | gfvIm7v+cELj8a53EQY0LafzZqNC5kQAp916coU=
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/I2PCore/Data/DatabaseLookupKeyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | using I2PCore.Utils;
3 |
4 | public class DatabaseLookupKeyInfo
5 | {
6 | public bool EncryptionFlag { get; set; }
7 | public bool ECIESFlag { get; set; }
8 | public BufLen ReplyKey { get; set; }
9 | public BufLen[] Tags { get; set; }
10 | }
--------------------------------------------------------------------------------
/I2PCore/Data/I2PDate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using System.IO;
7 |
8 | namespace I2PCore.Data
9 | {
10 | public class I2PDate : I2PType, IComparable, IComparable
11 | {
12 | public static readonly I2PDate Zero = new I2PDate( 0 );
13 |
14 | ulong DateMilliseconds;
15 |
16 | private I2PDate()
17 | {
18 | }
19 |
20 | ///
21 | /// Set value explicitly.
22 | ///
23 | /// Milliseconds since Jan 1st 1970.
24 | public I2PDate( UInt64 val )
25 | {
26 | DateMilliseconds = val;
27 | }
28 | public I2PDate( BufRef reader )
29 | {
30 | DateMilliseconds = reader.ReadFlip64();
31 | }
32 | public I2PDate( I2PDate date )
33 | {
34 | DateMilliseconds = date.DateMilliseconds;
35 | }
36 |
37 | public static readonly DateTime RefDate = new DateTime( 1970, 1, 1 );
38 |
39 | public I2PDate( DateTime dt )
40 | {
41 | DateMilliseconds = (UInt64)( dt - RefDate ).TotalMilliseconds;
42 | }
43 |
44 | public void Write( BufRefStream dest )
45 | {
46 | dest.Write( BufUtils.Flip64B( DateMilliseconds ) );
47 | }
48 |
49 | public void Write( BufRef dest )
50 | {
51 | dest.WriteFlip64( DateMilliseconds );
52 | }
53 |
54 | public void Poke( BufBase dest, int offset )
55 | {
56 | dest.PokeFlip64( DateMilliseconds, offset );
57 | }
58 |
59 | public ulong Nudge()
60 | {
61 | return ++DateMilliseconds;
62 | }
63 |
64 | public override string ToString()
65 | {
66 | return ( RefDate + new TimeSpan( (long)DateMilliseconds * 10000 ) ).ToString();
67 | }
68 |
69 | public static explicit operator DateTime( I2PDate date )
70 | {
71 | return RefDate + TimeSpan.FromMilliseconds( date.DateMilliseconds );
72 | }
73 |
74 | public static explicit operator ulong( I2PDate date )
75 | {
76 | return date.DateMilliseconds;
77 | }
78 |
79 | public int CompareTo( object obj )
80 | {
81 | if ( obj is null ) return 1;
82 | var other = obj as I2PDate;
83 | if ( other is null ) return 1;
84 | if ( DateMilliseconds == other.DateMilliseconds ) return 0;
85 | return DateMilliseconds > other.DateMilliseconds ? 1 : -1;
86 | }
87 |
88 | public int CompareTo( I2PDate other )
89 | {
90 | if ( other is null ) return 1;
91 | if ( DateMilliseconds == other.DateMilliseconds ) return 0;
92 | return DateMilliseconds > other.DateMilliseconds ? 1 : -1;
93 | }
94 |
95 | public static I2PDate Now
96 | {
97 | get
98 | {
99 | return new I2PDate( DateTime.UtcNow );
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PDateShort.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.Utils;
3 |
4 | namespace I2PCore.Data
5 | {
6 | public class I2PDateShort : I2PType
7 | {
8 | public static readonly I2PDateShort Zero = new I2PDateShort( 0 );
9 |
10 | uint DateSeconds;
11 |
12 | private I2PDateShort()
13 | {
14 | }
15 |
16 | public I2PDateShort( uint val )
17 | {
18 | DateSeconds = val;
19 | }
20 |
21 | public I2PDateShort( BufRef reader )
22 | {
23 | DateSeconds = reader.ReadFlip32();
24 | }
25 | public I2PDateShort( I2PDateShort date )
26 | {
27 | DateSeconds = date.DateSeconds;
28 | }
29 |
30 | public I2PDateShort( I2PDate date )
31 | {
32 | DateSeconds = (uint)( (ulong)date / 1000 );
33 | }
34 |
35 | public static readonly DateTime RefDate = new DateTime( 1970, 1, 1 );
36 |
37 | public I2PDateShort( DateTime dt )
38 | {
39 | DateSeconds = (uint)( dt - RefDate ).TotalSeconds;
40 | }
41 |
42 | public void Write( BufRefStream dest )
43 | {
44 | dest.Write( BufUtils.Flip32B( DateSeconds ) );
45 | }
46 |
47 | public static explicit operator DateTime( I2PDateShort ds )
48 | {
49 | return RefDate + TimeSpan.FromSeconds( ds.DateSeconds );
50 | }
51 |
52 | public static explicit operator uint( I2PDateShort ds )
53 | {
54 | return ds.DateSeconds;
55 | }
56 |
57 | public override string ToString()
58 | {
59 | return ( RefDate + new TimeSpan( (long)DateSeconds * 10000000 ) ).ToString();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PDestination.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.IO;
6 | using Org.BouncyCastle.Math;
7 | using Org.BouncyCastle.Security;
8 | using I2PCore.Utils;
9 |
10 | namespace I2PCore.Data
11 | {
12 | public class I2PDestination : I2PKeysAndCert
13 | {
14 | public I2PDestination( I2PPublicKey pubkey, I2PSigningPublicKey signkey ) : base( pubkey, signkey ) { }
15 |
16 | public I2PDestination( BufRef buf ) : base( buf ) { }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PDestinationInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Org.BouncyCastle.Math;
6 | using Org.BouncyCastle.Security;
7 | using I2PCore.Utils;
8 |
9 | namespace I2PCore.Data
10 | {
11 | public class I2PDestinationInfo
12 | {
13 | public readonly I2PPrivateKey PrivateKey;
14 | public readonly I2PSigningPrivateKey PrivateSigningKey;
15 |
16 | public readonly I2PDestination Destination;
17 |
18 | public I2PDestinationInfo( I2PSigningKey.SigningKeyTypes signkeytype )
19 | {
20 | var certificate = new I2PCertificate( signkeytype );
21 |
22 | var keys = I2PPrivateKey.GetNewKeyPair();
23 |
24 | PrivateKey = keys.PrivateKey;
25 | PrivateSigningKey = new I2PSigningPrivateKey( certificate );
26 |
27 | Destination = new I2PDestination(
28 | keys.PublicKey,
29 | new I2PSigningPublicKey( PrivateSigningKey ) );
30 | }
31 |
32 | public I2PDestinationInfo( BufRef reader )
33 | {
34 | Destination = new I2PDestination( reader );
35 | PrivateKey = new I2PPrivateKey( reader, Destination.Certificate );
36 | PrivateSigningKey = new I2PSigningPrivateKey( reader, Destination.Certificate );
37 | }
38 |
39 | public I2PDestinationInfo( string base64 )
40 | : this( new BufRefLen( FreenetBase64.Decode( base64 ) ) )
41 | {
42 | }
43 |
44 | public byte[] ToByteArray()
45 | {
46 | return BufUtils.ToByteArray( Destination, PrivateKey, PrivateSigningKey );
47 | }
48 |
49 | public string ToBase64()
50 | {
51 | return FreenetBase64.Encode( new BufLen( ToByteArray() ) );
52 | }
53 |
54 | public override string ToString()
55 | {
56 | return $"{Destination}";
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PIdentHashComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.Data
8 | {
9 | public class I2PIdentHashComparer: IEqualityComparer
10 | {
11 | public bool Equals( I2PIdentHash x, I2PIdentHash y )
12 | {
13 | return BufUtils.Equals( x.Hash, y.Hash );
14 | }
15 |
16 | public int GetHashCode( I2PIdentHash x )
17 | {
18 | return x.GetHashCode();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PLease.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.Utils;
3 |
4 | namespace I2PCore.Data
5 | {
6 | public class I2PLease : I2PType, ILease
7 | {
8 | public static readonly TickSpan LeaseLifetime = TickSpan.Minutes( 10 );
9 |
10 | public I2PIdentHash TunnelGw { get; private set; }
11 | public I2PTunnelId TunnelId { get; private set; }
12 | public I2PDate EndDate { get; private set; }
13 |
14 | public I2PLease( I2PIdentHash tunnelgw, I2PTunnelId tunnelid, I2PDate enddate )
15 | {
16 | TunnelGw = tunnelgw;
17 | TunnelId = tunnelid;
18 | EndDate = enddate;
19 | }
20 |
21 | public I2PLease( I2PIdentHash tunnelgw, I2PTunnelId tunnelid )
22 | {
23 | TunnelGw = tunnelgw;
24 | TunnelId = tunnelid;
25 | EndDate = new I2PDate(
26 | DateTime.UtcNow
27 | + TimeSpan.FromSeconds( LeaseLifetime.ToSeconds ) );
28 | }
29 |
30 | public I2PLease( BufRef reader )
31 | {
32 | TunnelGw = new I2PIdentHash( reader );
33 | TunnelId = new I2PTunnelId( reader );
34 |
35 | EndDate = new I2PDate( reader );
36 | }
37 |
38 | public void Write( BufRefStream dest )
39 | {
40 | TunnelGw.Write( dest );
41 | TunnelId.Write( dest );
42 | EndDate.Write( dest );
43 | }
44 |
45 | // ILease
46 | public DateTime Expire { get => (DateTime)EndDate; }
47 |
48 | public override string ToString()
49 | {
50 | return $"I2PLease GW {TunnelGw.Id32Short}, Id {TunnelId}, Exp {EndDate}";
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PLease2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.Utils;
3 |
4 | namespace I2PCore.Data
5 | {
6 | public class I2PLease2 : I2PType, ILease
7 | {
8 | public const int DefaultLeaseLifetimeSeconds = 10 * 60;
9 |
10 | public I2PIdentHash TunnelGw { get; private set; }
11 | public I2PTunnelId TunnelId { get; private set; }
12 | public I2PDateShort EndDate { get; private set; }
13 |
14 | public I2PLease2( I2PIdentHash tunnelgw, I2PTunnelId tunnelid, I2PDateShort enddate )
15 | {
16 | TunnelGw = tunnelgw;
17 | TunnelId = tunnelid;
18 | EndDate = enddate;
19 | }
20 |
21 | public I2PLease2( I2PIdentHash tunnelgw, I2PTunnelId tunnelid )
22 | {
23 | TunnelGw = tunnelgw;
24 | TunnelId = tunnelid;
25 | EndDate = new I2PDateShort(
26 | DateTime.UtcNow
27 | + TimeSpan.FromSeconds( DefaultLeaseLifetimeSeconds ) );
28 | }
29 |
30 | public I2PLease2( BufRef reader )
31 | {
32 | TunnelGw = new I2PIdentHash( reader );
33 | TunnelId = new I2PTunnelId( reader );
34 |
35 | EndDate = new I2PDateShort( reader );
36 | }
37 |
38 | public void Write( BufRefStream dest )
39 | {
40 | TunnelGw.Write( dest );
41 | TunnelId.Write( dest );
42 | EndDate.Write( dest );
43 | }
44 |
45 | // ILease
46 | public DateTime Expire { get => (DateTime)EndDate; }
47 |
48 | public override string ToString()
49 | {
50 | return $"I2PLease2 GW {TunnelGw.Id32Short}, Id {TunnelId}, Exp {EndDate}";
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PLeaseSet2Header.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using I2PCore.Utils;
4 |
5 | namespace I2PCore.Data
6 | {
7 | public class I2PLeaseSet2Header: I2PType
8 | {
9 | [Flags]
10 | public enum HeaderFlagTypes : ushort
11 | {
12 | None = 0x00,
13 | Invalid = ushort.MaxValue,
14 | OfflineKey = 0x01,
15 | Unpublished = 0x02,
16 | Blinded = 0x04,
17 | }
18 |
19 | public I2PDestination Destination { get; set; }
20 | public I2PDateShort Published { get; set; }
21 | public ushort ExpiresSeconds { get; set; }
22 | public HeaderFlagTypes Flags { get; set; }
23 | public I2POfflineSignature OfflineSignature { get; set; }
24 | public I2PLeaseSet2Header(
25 | I2PDestination dest,
26 | I2PDateShort published,
27 | HeaderFlagTypes flags,
28 | ushort expiresseconds = I2PLease2.DefaultLeaseLifetimeSeconds )
29 | {
30 | if ( dest is null || published is null )
31 | {
32 | throw new ArgumentException( "Null argument not supported" );
33 | }
34 | Destination = dest;
35 | Published = published;
36 | Flags = flags;
37 | ExpiresSeconds = expiresseconds;
38 | }
39 | public I2PLeaseSet2Header( BufRef reader )
40 | {
41 | Destination = new I2PDestination( reader );
42 | Published = new I2PDateShort( reader );
43 | ExpiresSeconds = reader.ReadFlip16();
44 | Flags = (HeaderFlagTypes)reader.ReadFlip16();
45 | if ( Flags.HasFlag( HeaderFlagTypes.OfflineKey ) )
46 | {
47 | OfflineSignature = new I2POfflineSignature( reader, Destination.Certificate );
48 | }
49 | }
50 | public void Write( BufRefStream dest )
51 | {
52 | Destination.Write( dest );
53 | Published.Write( dest );
54 | dest.Write( BufUtils.Flip16B( ExpiresSeconds ) );
55 | dest.Write( BufUtils.Flip16B( (ushort)Flags ) );
56 | if ( Flags.HasFlag( HeaderFlagTypes.OfflineKey ) )
57 | {
58 | OfflineSignature?.Write( dest );
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PMessagePayload.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.IO.Compression;
6 | using System.IO;
7 | using I2PCore.Utils;
8 |
9 | namespace I2PCore.Data
10 | {
11 | public class I2PMessagePayload: I2PType
12 | {
13 | public ushort SessionId;
14 | public uint MessageId;
15 | public byte[] Payload;
16 |
17 | public void Compress( byte[] data )
18 | {
19 | using ( var ms = new MemoryStream() )
20 | {
21 | using ( var gs = new GZipStream( ms, CompressionMode.Compress ) )
22 | {
23 | gs.Write( data, 0, data.Length );
24 | gs.Flush();
25 | }
26 | Payload = ms.ToArray();
27 | }
28 | }
29 |
30 | public byte[] GetBytes
31 | {
32 | get
33 | {
34 | using ( var ms = new MemoryStream() )
35 | {
36 | ms.Write( Payload, 0, Payload.Length );
37 | ms.Position = 0;
38 |
39 | using ( var gs = new GZipStream( ms, CompressionMode.Decompress ) )
40 | {
41 | var result = new List();
42 | var buf = new byte[32768];
43 |
44 | int len;
45 | while ( ( len = gs.Read( buf, 0, buf.Length ) ) > 0 )
46 | {
47 | result.AddRange( buf.Take( len ) );
48 | }
49 |
50 | return result.ToArray();
51 | }
52 | }
53 | }
54 | }
55 |
56 | public void Write( BufRefStream dest )
57 | {
58 | throw new NotImplementedException();
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2POfflineSignature.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using I2PCore.Utils;
4 | using static I2PCore.Data.I2PSigningKey;
5 |
6 | namespace I2PCore.Data
7 | {
8 | public class I2POfflineSignature: I2PType
9 | {
10 | public I2PDateShort Expires { get; set; }
11 | public SigningKeyTypes SignatureType { get; set; }
12 | public I2PSigningPublicKey TransientPublicKey { get; set; }
13 | public I2PSignature Signature { get; set; }
14 | public I2POfflineSignature( BufRef reader, I2PCertificate cert )
15 | {
16 | Expires = new I2PDateShort( reader.ReadFlip32() );
17 | SignatureType = (SigningKeyTypes)reader.ReadFlip16();
18 |
19 | TransientPublicKey = new I2PSigningPublicKey(
20 | reader,
21 | new I2PCertificate( SignatureType ) );
22 |
23 | Signature = new I2PSignature( reader, cert );
24 | }
25 | public void Write( BufRefStream dest )
26 | {
27 | Expires.Write( dest );
28 | dest.Write( BufUtils.Flip16B( (ushort)SignatureType ) );
29 | TransientPublicKey.Write( dest );
30 | Signature.Write( dest );
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PPublicKey.cs:
--------------------------------------------------------------------------------
1 | using Org.BouncyCastle.Math;
2 | using I2PCore.Utils;
3 | using System;
4 |
5 | namespace I2PCore.Data
6 | {
7 | public class I2PPublicKey : I2PKeyType
8 | {
9 | public I2PPublicKey( I2PPrivateKey priv ): base( priv.Certificate )
10 | {
11 | switch( Certificate.PublicKeyType )
12 | {
13 | case KeyTypes.ElGamal2048:
14 | Key = new BufLen( I2PConstants
15 | .ElGamalG.ModPow(
16 | priv.ToBigInteger(),
17 | I2PConstants.ElGamalP )
18 | .ToByteArrayUnsigned() );
19 | break;
20 |
21 | default:
22 | throw new NotImplementedException();
23 | }
24 | }
25 |
26 | public I2PPublicKey( BufRef buf, I2PCertificate cert ) : base( buf, cert ) { }
27 |
28 | public I2PPublicKey( BigInteger pubkey, I2PCertificate cert ): base( cert )
29 | {
30 | Key = new BufLen( pubkey.ToByteArrayUnsigned() );
31 | }
32 |
33 | public override int KeySizeBytes { get { return Certificate.PublicKeyLength; } }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PRawData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.Data
8 | {
9 | public class I2PRawData: I2PType
10 | {
11 | public byte[] Data;
12 |
13 | public I2PRawData( int bytes, bool random )
14 | {
15 | Data = random ? BufUtils.RandomBytes( bytes ): new byte[bytes];
16 | }
17 |
18 | public I2PRawData( byte b )
19 | {
20 | Data = new byte[] { b };
21 | }
22 |
23 | public I2PRawData( ushort ui )
24 | {
25 | Data = BitConverter.GetBytes( ui );
26 | }
27 |
28 | public I2PRawData( uint ui )
29 | {
30 | Data = BitConverter.GetBytes( ui );
31 | }
32 |
33 | public I2PRawData( byte[] buf, bool copy )
34 | {
35 | Data = copy ? buf.Copy( 0, buf.Length ): buf;
36 | }
37 |
38 | public I2PRawData( I2PRawData src, bool copy )
39 | {
40 | Data = copy ? src.Data.Copy( 0, src.Data.Length ) : src.Data;
41 | }
42 |
43 | public I2PRawData( BufRef reader, int size )
44 | {
45 | Data = new byte[size];
46 | Array.Copy( reader.BaseArray, reader.BaseArrayOffset, Data, 0, size );
47 | reader.Seek( size );
48 | }
49 |
50 | public void Write( BufRefStream dest )
51 | {
52 | dest.Write( Data );
53 | }
54 |
55 | public override string ToString()
56 | {
57 | var result = new StringBuilder();
58 |
59 | result.AppendLine( "I2PRawData" );
60 |
61 | if ( Data == null )
62 | {
63 | result.AppendLine( "Data: (null)" );
64 | }
65 |
66 | return result.ToString();
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PRouterIdentity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.Data
8 | {
9 | public class I2PRouterIdentity : I2PKeysAndCert
10 | {
11 | public I2PRouterIdentity( I2PPublicKey pubkey, I2PSigningPublicKey signkey ) : base( pubkey, signkey ) { }
12 | public I2PRouterIdentity( BufRef data ) : base( data ) { }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PRoutingKey.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using I2PCore.Utils;
4 |
5 | namespace I2PCore.Data
6 | {
7 | public class I2PRoutingKey: I2PType
8 | {
9 | private readonly I2PIdentHash Identity;
10 |
11 | public I2PRoutingKey( I2PIdentHash ident )
12 | {
13 | Identity = ident;
14 | }
15 |
16 | BufLen HashCache;
17 | DateTime HashCacheDay = DateTime.MinValue;
18 |
19 | public BufLen Hash
20 | {
21 | get
22 | {
23 | var daynow = DateTime.UtcNow.Date;
24 | if ( HashCache != null && HashCacheDay == daynow ) return HashCache;
25 |
26 | HashCache = new BufLen( I2PHashSHA256.GetHash( Identity.Hash, new BufLen( GenerateDTBuf() ) ) );
27 | HashCacheDay = daynow;
28 |
29 | return HashCache;
30 | }
31 | }
32 |
33 | static byte[] DTBufCache = null;
34 | static DateTime DTBufCacheDay = DateTime.MinValue;
35 |
36 | private static byte[] GenerateDTBuf()
37 | {
38 | var daynow = DateTime.UtcNow.Date;
39 | if ( DTBufCache != null && DTBufCacheDay == daynow ) return DTBufCache;
40 |
41 | DTBufCache = Encoding.ASCII.GetBytes( $"{daynow:yyyyMMdd}" );
42 | DTBufCacheDay = daynow;
43 |
44 | return DTBufCache;
45 | }
46 |
47 | public void Write( BufRefStream dest )
48 | {
49 | throw new NotImplementedException();
50 | }
51 |
52 | public override string ToString()
53 | {
54 | var hc = HashCache != null ? FreenetBase64.Encode( new BufLen( HashCache ) ): "";
55 | return $"I2PRoutingKey: HashCacheDay {HashCacheDay}, HashCache: {hc}.";
56 | }
57 |
58 | public byte this[int ix]
59 | {
60 | get { return Hash[ix]; }
61 | }
62 |
63 |
64 | ///
65 | /// Distance definitions is always between as stored floodfill IdentHash and a searched RoutingKey.
66 | /// Not between two routing keys.
67 | ///
68 | ///
69 | public static BufLen operator ^( I2PIdentHash left, I2PRoutingKey right )
70 | {
71 | var result = new byte[32];
72 | var lhash = left.Hash;
73 | var rhash = right.Hash;
74 | for ( int i = 0; i < 32; ++i )
75 | {
76 | result[i] = (byte)( lhash[i] ^ rhash[i] );
77 | }
78 | return new BufLen( result );
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PSU3Header.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using I2PCore.Utils;
4 |
5 | namespace I2PCore.Data
6 | {
7 | public class I2PSU3Header: I2PType
8 | {
9 | public const string SU3_MAGIC_NUMBER = "I2Psu3";
10 | public enum SU3FileTypes : byte { Zip = 0x00 }
11 | public enum SU3ContentTypes : byte { SeedData = 0x03 }
12 |
13 | public I2PSU3Header( BufRef src )
14 | {
15 | Read( src );
16 | }
17 |
18 | public byte FileVersion { get; private set; }
19 | public ushort SignatureType { get; private set; }
20 | public ushort SignatureLength { get; private set; }
21 | public byte VersionLength { get; private set; }
22 | public BufLen Version { get; private set; }
23 | public byte SignerIdLength { get; private set; }
24 | public ulong ContentLength { get; private set; }
25 | public SU3FileTypes FileType { get; private set; }
26 | public SU3ContentTypes ContentType { get; private set; }
27 | public string SignerID { get; private set; }
28 |
29 | public void Read( BufRef reader )
30 | {
31 | // magic number and zero byte 6
32 | var magic = reader.ReadBufLen( 6 );
33 | _ = reader.Read8();
34 | var magicstr = magic.ToEncoding( Encoding.UTF8 );
35 |
36 | if ( magicstr != SU3_MAGIC_NUMBER )
37 | {
38 | throw new ArgumentException( "Not SU3 data." );
39 | }
40 |
41 | // su3 file format version
42 | FileVersion = reader.Read8();
43 |
44 | SignatureType = reader.ReadFlip16();
45 | SignatureLength = reader.ReadFlip16();
46 | _ = reader.Read8();
47 | VersionLength = reader.Read8();
48 | _ = reader.Read8();
49 | SignerIdLength = reader.Read8();
50 | ContentLength = reader.ReadFlip64();
51 | _ = reader.Read8();
52 | FileType = (SU3FileTypes)reader.Read8();
53 | _ = reader.Read8();
54 | ContentType = (SU3ContentTypes)reader.Read8();
55 | reader.Seek( 12 );
56 | Version = reader.ReadBufLen( VersionLength );
57 | SignerID = reader.ReadBufLen( SignerIdLength )
58 | .ToEncoding( Encoding.UTF8 ) ;
59 | }
60 |
61 | public void Write( BufRefStream dest )
62 | {
63 | throw new NotImplementedException();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PSessionTag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.Utils;
3 |
4 | namespace I2PCore.Data
5 | {
6 | public class I2PSessionTag : I2PType, IEquatable
7 | {
8 | public const int TagLength = 32;
9 |
10 | // Session tag lifespan.
11 | // "The session tags delivered successfully are remembered for a brief period (15 minutes currently)"
12 | // https://geti2p.net/en/docs/how/elgamal-aes
13 | public static readonly TickSpan TagLifetime = TickSpan.Minutes( 15 );
14 | public readonly TickCounter Created = TickCounter.Now;
15 |
16 | public readonly BufLen Value;
17 |
18 | public I2PSessionTag()
19 | {
20 | Value = new BufLen( BufUtils.RandomBytes( TagLength ) );
21 | }
22 |
23 | public I2PSessionTag( BufRef buf )
24 | {
25 | Value = buf.ReadBufLen( TagLength );
26 | }
27 |
28 | public void Write( BufRefStream dest )
29 | {
30 | Value.WriteTo( dest );
31 | }
32 |
33 | public bool Equals( I2PSessionTag other )
34 | {
35 | if ( other is null ) return false;
36 | return Value == other.Value;
37 | }
38 |
39 | public override int GetHashCode()
40 | {
41 | return Value.GetHashCode();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PSigningPrivateKey.cs:
--------------------------------------------------------------------------------
1 | using Org.BouncyCastle.Math;
2 | using I2PCore.Utils;
3 |
4 | namespace I2PCore.Data
5 | {
6 | public class I2PSigningPrivateKey : I2PSigningKey
7 | {
8 | public override int KeySizeBytes { get { return Certificate.SigningPrivateKeyLength; } }
9 |
10 | public I2PSigningPrivateKey( I2PCertificate cert )
11 | : base( new BufLen( BufUtils.RandomBytes( cert.SigningPrivateKeyLength ) ), cert )
12 | {
13 | if ( cert.SignatureType == SigningKeyTypes.ECDSA_SHA512_P521 )
14 | {
15 | Key[0] &= 0x01;
16 | }
17 | }
18 |
19 | public I2PSigningPrivateKey( BufRef reader, I2PCertificate cert ) : base( reader, cert )
20 | {
21 | }
22 |
23 | public I2PSigningPrivateKey( BigInteger key, I2PCertificate cert ) : base( key, cert )
24 | {
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PSigningPublicKey.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Org.BouncyCastle.Math;
3 | using I2PCore.Utils;
4 | using Org.BouncyCastle.Asn1.Nist;
5 | using Org.BouncyCastle.Crypto.Parameters;
6 |
7 | namespace I2PCore.Data
8 | {
9 | public class I2PSigningPublicKey : I2PSigningKey
10 | {
11 | public override int KeySizeBytes { get { return Certificate.SigningPublicKeyLength; } }
12 |
13 | public I2PSigningPublicKey( BigInteger key, I2PCertificate cert ) : base( key, cert ) { }
14 |
15 | public I2PSigningPublicKey( I2PSigningPrivateKey privkey )
16 | : base( privkey.Certificate )
17 | {
18 | switch ( Certificate.SignatureType )
19 | {
20 | case SigningKeyTypes.DSA_SHA1:
21 | Key = new BufLen( I2PConstants.DsaG.ModPow( privkey.ToBigInteger(), I2PConstants.DsaP ).ToByteArrayUnsigned() );
22 | break;
23 |
24 | case I2PSigningKey.SigningKeyTypes.ECDSA_SHA256_P256:
25 | {
26 | var param = NistNamedCurves.GetByName( "P-256" );
27 | var domain = new ECDomainParameters( param.Curve, param.G, param.N, param.H );
28 |
29 | var q = domain.G.Multiply( privkey.ToBigInteger() );
30 | var publicparam = new ECPublicKeyParameters( q, domain );
31 | Key = new BufLen( publicparam.Q.GetEncoded() );
32 | }
33 | break;
34 |
35 | case I2PSigningKey.SigningKeyTypes.ECDSA_SHA384_P384:
36 | {
37 | var param = NistNamedCurves.GetByName( "P-384" );
38 | var domain = new ECDomainParameters( param.Curve, param.G, param.N, param.H );
39 |
40 | var q = domain.G.Multiply( privkey.ToBigInteger() );
41 | var publicparam = new ECPublicKeyParameters( q, domain );
42 | Key = new BufLen( publicparam.Q.GetEncoded() );
43 | }
44 | break;
45 |
46 | case I2PSigningKey.SigningKeyTypes.ECDSA_SHA512_P521:
47 | {
48 | var param = NistNamedCurves.GetByName( "P-521" );
49 | var domain = new ECDomainParameters( param.Curve, param.G, param.N, param.H );
50 |
51 | var q = domain.G.Multiply( privkey.ToBigInteger() );
52 | var publicparam = new ECPublicKeyParameters( q, domain );
53 | Key = new BufLen( publicparam.Q.GetEncoded() );
54 | }
55 | break;
56 |
57 | case SigningKeyTypes.EdDSA_SHA512_Ed25519:
58 | Key = new BufLen( new Ed25519PrivateKeyParameters( privkey.Key.BaseArray, privkey.Key.BaseArrayOffset ).GeneratePublicKey().GetEncoded() );
59 | break;
60 |
61 | default:
62 | throw new NotImplementedException();
63 | }
64 | }
65 |
66 | public I2PSigningPublicKey( BufRef buf, I2PCertificate cert ): base( cert )
67 | {
68 | Key = buf.ReadBufLen( KeySizeBytes );
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PString.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.IO;
6 | using I2PCore.Utils;
7 | using System.Collections;
8 |
9 | namespace I2PCore.Data
10 | {
11 | public class I2PString : I2PType
12 | {
13 | readonly String Str = "";
14 |
15 | public I2PString()
16 | {
17 | }
18 |
19 | public I2PString( I2PString src )
20 | {
21 | Str = src.Str;
22 | }
23 |
24 | public I2PString( String src )
25 | {
26 | Str = src;
27 | }
28 |
29 | public I2PString( Stream src, char[] skipchars )
30 | {
31 | Read( src, skipchars );
32 | }
33 |
34 | public I2PString( BufRef buf )
35 | {
36 | var len = buf.Read8();
37 | Str = System.Text.Encoding.UTF8.GetString( buf.BaseArray, buf.BaseArrayOffset, len );
38 | buf.Seek( len );
39 | }
40 |
41 | internal int CompareTo( I2PString other )
42 | {
43 | return string.CompareOrdinal( Str, other.Str );
44 | }
45 |
46 | public byte[] GetBytes
47 | {
48 | get
49 | {
50 | return System.Text.Encoding.UTF8.GetBytes( Str );
51 | }
52 | }
53 |
54 | public void Write( BufRefStream dest )
55 | {
56 | var l = (byte)Math.Min( 255, Str.Length );
57 | var v = new byte[System.Text.Encoding.UTF8.GetMaxByteCount( l ) + 1];
58 | v[0] = l;
59 | var bytes = System.Text.Encoding.UTF8.GetBytes( Str, 0, l, v, 1 );
60 | dest.Write( v, 0, bytes + 1 );
61 | }
62 |
63 | public void Read( Stream src, char[] skipchars )
64 | {
65 | var len = (int)StreamUtils.ReadInt8( src );
66 | while ( skipchars != null && skipchars.Any( c => len == (long)c ) ) len = (int)StreamUtils.ReadInt8( src );
67 |
68 | var buf = new byte[len];
69 | var read = src.Read( buf, 0, len );
70 | if ( read != len ) throw new EndOfStreamEncounteredException();
71 | System.Text.Encoding.UTF8.GetString( buf );
72 | }
73 |
74 | public override string ToString()
75 | {
76 | return Str ?? "[I2PString]";
77 | }
78 |
79 | public static bool operator ==( I2PString stl, string str )
80 | {
81 | return StringComparer.InvariantCulture.Compare( stl?.Str, str ) == 0;
82 | }
83 |
84 | public static bool operator !=( I2PString stl, string str )
85 | {
86 | return StringComparer.InvariantCulture.Compare( stl?.Str, str ) != 0;
87 | }
88 |
89 | public override bool Equals( object obj )
90 | {
91 | if ( obj is I2PString ) return Str == ( (I2PString)obj )?.Str;
92 | if ( obj is string ) return this == (string)obj;
93 | return false;
94 | }
95 |
96 | public override int GetHashCode()
97 | {
98 | return Str.GetHashCode();
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PStringComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Data
7 | {
8 | public class I2PStringComparer: IComparer
9 | {
10 | int IComparer.Compare( I2PString x, I2PString y )
11 | {
12 | return x.CompareTo( y );
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PStringEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Data
7 | {
8 | class I2PStringEqualityComparer: IEqualityComparer
9 | {
10 | bool IEqualityComparer.Equals( I2PString x, I2PString y )
11 | {
12 | return x.Equals( y );
13 | }
14 |
15 | int IEqualityComparer.GetHashCode( I2PString obj )
16 | {
17 | return obj.GetHashCode();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PTunnelId.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.Data
8 | {
9 | public class I2PTunnelId : I2PType
10 | {
11 | public static readonly I2PTunnelId Zero = new I2PTunnelId( (uint)0 );
12 |
13 | ///
14 | /// Not flipped as it is just a tag.
15 | ///
16 | uint Id;
17 |
18 | public I2PTunnelId()
19 | {
20 | Id = BufUtils.RandomUint();
21 | }
22 |
23 | public I2PTunnelId( UInt32 id )
24 | {
25 | Id = id;
26 | }
27 |
28 | public I2PTunnelId( I2PTunnelId src )
29 | {
30 | Id = src.Id;
31 | }
32 |
33 | public I2PTunnelId( BufRef buf )
34 | {
35 | Id = buf.Read32();
36 | }
37 |
38 | public void Write( BufRefStream dest )
39 | {
40 | dest.Write( BitConverter.GetBytes( Id ) );
41 | }
42 |
43 | public void Write( BufRef dest )
44 | {
45 | dest.Write32( Id );
46 | }
47 |
48 | public override string ToString()
49 | {
50 | return $"I2PTunnelId: {Id}";
51 | }
52 |
53 | public static bool operator ==( I2PTunnelId left, I2PTunnelId right )
54 | {
55 | if ( left is null && right is null ) return true;
56 | if ( left is null || right is null ) return false;
57 | return left.Id == right.Id;
58 | }
59 |
60 | public static bool operator !=( I2PTunnelId left, I2PTunnelId right )
61 | {
62 | if ( left is null && right is null ) return true;
63 | if ( left is null || right is null ) return false;
64 | return left.Id != right.Id;
65 | }
66 |
67 | public override bool Equals( object obj )
68 | {
69 | if ( obj is null ) return false;
70 | if ( !( obj is I2PTunnelId ) ) return false;
71 | return this == (I2PTunnelId)obj;
72 | }
73 |
74 | public override int GetHashCode()
75 | {
76 | return (int)Id;
77 | }
78 |
79 | public static implicit operator uint( I2PTunnelId tid )
80 | {
81 | return tid.Id;
82 | }
83 |
84 | public static implicit operator I2PTunnelId( uint tid )
85 | {
86 | return new I2PTunnelId( tid );
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/I2PCore/Data/I2PType.cs:
--------------------------------------------------------------------------------
1 | using I2PCore.Utils;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace I2PCore.Data
8 | {
9 | ///
10 | /// Can be byte serialized according to specification.
11 | ///
12 | public interface I2PType
13 | {
14 | void Write( BufRefStream dest );
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/I2PCore/Data/ILease.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace I2PCore.Data
5 | {
6 | public interface ILease
7 | {
8 | I2PIdentHash TunnelGw { get; }
9 | I2PTunnelId TunnelId { get; }
10 | DateTime Expire { get; }
11 | }
12 | }
--------------------------------------------------------------------------------
/I2PCore/Data/ILeaseSet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using I2PCore.TunnelLayer.I2NP.Messages;
4 |
5 | namespace I2PCore.Data
6 | {
7 | public interface ILeaseSet
8 | {
9 | DatabaseStoreMessage.MessageContent MessageType { get; }
10 | I2PDestination Destination { get; }
11 | IEnumerable Leases { get; }
12 | DateTime Expire { get; }
13 | IEnumerable PublicKeys { get; }
14 |
15 | void RemoveExpired();
16 |
17 | byte[] ToByteArray();
18 | }
19 | }
--------------------------------------------------------------------------------
/I2PCore/EndOfStreamEncounteredException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore
7 | {
8 | public class EndOfStreamEncounteredException: Exception
9 | {
10 | public EndOfStreamEncounteredException() : base() { }
11 | public EndOfStreamEncounteredException( string text ) : base( text ) { }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/I2PCore/FailedToConnectException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore
7 | {
8 | public class FailedToConnectException: Exception
9 | {
10 | public FailedToConnectException( string text ) : base( text ) { }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/I2PCore/I2PCore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | NOLOG_ALL_TUNNEL_TRANSFER;NOLOG_ALL_IDENT_LOOKUPS;NOLOG_MUCH_TRANSPORT;NOLOG_ALL_LEASE_MGMT,NOLOG_TUNNEL_SELECTION,NOLOG_ROUTER_SELECTION_HISTORY
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/I2PCore/NetDb/CertificatesDb.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Security.Cryptography.X509Certificates;
5 |
6 | namespace I2PCore
7 | {
8 | public static class CertificatesDb
9 | {
10 | private const string DefaultCertificatesDir = "Contrib?Certificates";
11 | public static string DefaultCertificatesDirectory
12 | {
13 | get
14 | {
15 | return Path.GetFullPath( DefaultCertificatesDir
16 | .Replace( '?', Path.DirectorySeparatorChar ) );
17 | }
18 | }
19 |
20 | public static X509Certificate2[] GetCertificates()
21 | {
22 | var files = Directory.GetFiles(
23 | DefaultCertificatesDirectory,
24 | "*.crt",
25 | SearchOption.AllDirectories );
26 |
27 | var result = new List();
28 | foreach( var file in files )
29 | {
30 | var cert = new X509Certificate2( file );
31 | result.Add( cert );
32 | }
33 | return result.ToArray();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/I2PCore/NetDb/NetDb.RouterEntry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.Data;
3 | using I2PCore.Utils;
4 |
5 | namespace I2PCore
6 | {
7 | public partial class NetDb
8 | {
9 | protected class RouterEntry
10 | {
11 | public I2PRouterInfo Router { get; protected set; }
12 | public RouterInfoMeta Meta { get; protected set; }
13 |
14 | public RouterEntry( I2PRouterInfo info, RouterInfoMeta meta )
15 | {
16 | Router = info;
17 | Meta = meta;
18 | }
19 |
20 | private TickCounter ScoreAge = null;
21 | private RouterStatistics CachedStatisticsField;
22 | public RouterStatistics CachedStatistics
23 | {
24 | get
25 | {
26 | if ( ScoreAge is null || ScoreAge.DeltaToNow > TickSpan.Minutes( 5 ) )
27 | {
28 | ScoreAge = TickCounter.Now;
29 | CachedStatisticsField = NetDb.Inst.Statistics[Router.Identity.IdentHash];
30 | }
31 | return CachedStatisticsField;
32 | }
33 | }
34 |
35 | public bool IsFloodfill
36 | {
37 | get
38 | {
39 | return Router.Options["caps"].IndexOf( 'f' ) >= 0;
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/I2PCore/NetDb/PublishedBandwidth.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore
7 | {
8 | public class PublishedBandwidth
9 | {
10 | public class BandwidthRange
11 | {
12 | public int MinKBps;
13 | public int MaxKBps;
14 | }
15 |
16 | public class BandwithLetter
17 | {
18 | public BandwidthRange Range;
19 | public char Letter;
20 | }
21 |
22 | /*
23 | K: Under 12 KBps shared bandwidth
24 | L: 12 - 48 KBps shared bandwidth (default)
25 | M: 48 - 64 KBps shared bandwidth
26 | N: 64 - 128 KBps shared bandwidth
27 | O: 128 - 256 KBps shared bandwidth
28 | P: 256 - 2000 KBps shared bandwidth (as of release 0.9.20)
29 | X: Over 2000 KBps shared bandwidth (as of release 0.9.20)
30 | */
31 | public static BandwithLetter[] DefinedBandwidths = new BandwithLetter[]
32 | {
33 | new BandwithLetter() { Letter = 'K', Range = new BandwidthRange() { MinKBps = 0, MaxKBps = 11 } },
34 | new BandwithLetter() { Letter = 'L', Range = new BandwidthRange() { MinKBps = 12, MaxKBps = 47 } },
35 | new BandwithLetter() { Letter = 'M', Range = new BandwidthRange() { MinKBps = 48, MaxKBps = 63 } },
36 | new BandwithLetter() { Letter = 'N', Range = new BandwidthRange() { MinKBps = 64, MaxKBps = 127 } },
37 | new BandwithLetter() { Letter = 'O', Range = new BandwidthRange() { MinKBps = 128, MaxKBps = 255 } },
38 | new BandwithLetter() { Letter = 'P', Range = new BandwidthRange() { MinKBps = 256, MaxKBps = 1999 } },
39 | new BandwithLetter() { Letter = 'X', Range = new BandwidthRange() { MinKBps = 2000, MaxKBps = int.MaxValue } },
40 | };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/I2PCore/RouterUnresolvable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore
7 | {
8 | public class RouterUnresolvableException: Exception
9 | {
10 | public RouterUnresolvableException() : base() { }
11 | public RouterUnresolvableException( string text ) : base( text ) { }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/I2PCore/SessionLayer/ClientDestination.Tunnels.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using I2PCore.Data;
4 | using I2PCore.TunnelLayer;
5 | using I2PCore.Utils;
6 | using System.Collections.Generic;
7 |
8 | namespace I2PCore.SessionLayer
9 | {
10 | public partial class ClientDestination : IClient
11 | {
12 | internal InboundTunnel SelectInboundTunnel()
13 | {
14 | return TunnelProvider.SelectTunnel( InboundEstablishedPool.Keys, 5 );
15 | }
16 |
17 | internal OutboundTunnel SelectOutboundTunnel()
18 | {
19 | return TunnelProvider.SelectTunnel( OutboundEstablishedPool.Keys, 5 );
20 | }
21 |
22 | public static ILease SelectLease( IEnumerable ls )
23 | {
24 | return ls
25 | .Where( l => l.Expire > DateTime.UtcNow )
26 | .RandomWeighted( l => l.Expire.ToFileTime(), 4 );
27 | }
28 |
29 | void RemovePendingTunnel( Tunnel tunnel )
30 | {
31 | if ( tunnel is OutboundTunnel ot )
32 | {
33 | OutboundPending.TryRemove( ot, out _ );
34 | }
35 |
36 | if ( tunnel is InboundTunnel it )
37 | {
38 | InboundPending.TryRemove( it, out _ );
39 | }
40 | }
41 |
42 | void RemovePoolTunnel( Tunnel tunnel, RemovalReason reason )
43 | {
44 | if ( tunnel is OutboundTunnel ot )
45 | {
46 | OutboundEstablishedPool.TryRemove( ot, out _ );
47 | }
48 |
49 | if ( tunnel is InboundTunnel it )
50 | {
51 | var removed = InboundEstablishedPool.TryRemove( it, out _ );
52 | RemoveTunnelFromEstablishedLeaseSet( (InboundTunnel)tunnel );
53 |
54 | if ( removed && reason != RemovalReason.Expired )
55 | {
56 | UpdateSignedLeases();
57 | }
58 | }
59 | }
60 |
61 | void InboundTunnel_TunnelShutdown( Tunnel tunnel )
62 | {
63 | tunnel.TunnelShutdown -= InboundTunnel_TunnelShutdown;
64 |
65 | if ( tunnel is InboundTunnel )
66 | {
67 | ((InboundTunnel)tunnel).GarlicMessageReceived -= InboundTunnel_GarlicMessageReceived;
68 | }
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/I2PCore/SessionLayer/IClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.TunnelLayer;
3 |
4 | namespace I2PCore.SessionLayer
5 | {
6 | internal enum RemovalReason { BuildFailed, Expired, Failed }
7 | internal interface IClient
8 | {
9 | int InboundTunnelHopCount { get; }
10 | int OutboundTunnelHopCount { get; }
11 |
12 | int TargetInboundTunnelCount { get; }
13 | int TargetOutboundTunnelCount { get; }
14 |
15 | int InboundTunnelsNeeded { get; }
16 | int OutboundTunnelsNeeded { get; }
17 |
18 | bool ClientTunnelsStatusOk { get; }
19 |
20 | void AddOutboundPending( OutboundTunnel tunnel );
21 | void AddInboundPending( InboundTunnel tunnel );
22 | void TunnelEstablished( Tunnel tunnel );
23 | void RemoveTunnel( Tunnel tunnel, RemovalReason reason );
24 |
25 | void Execute();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/I2PCore/SignatureCheckFailureException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore
7 | {
8 | public class SignatureCheckFailureException: Exception
9 | {
10 | public SignatureCheckFailureException() : base() { }
11 | public SignatureCheckFailureException( string msg ) : base( msg ) { }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/ITransport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.SessionLayer;
7 | using System.Net;
8 | using I2PCore.TunnelLayer.I2NP.Messages;
9 | using I2PCore.TunnelLayer.I2NP.Data;
10 |
11 | namespace I2PCore.TransportLayer
12 | {
13 | public interface ITransport
14 | {
15 | event Action ConnectionException;
16 | event Action ConnectionShutDown;
17 |
18 | ///
19 | /// Protocol initial handshake is finished, and data can be sent.
20 | ///
21 | event Action ConnectionEstablished;
22 |
23 | event Action DataBlockReceived;
24 |
25 | void Connect();
26 |
27 | void Send( I2NPMessage msg );
28 |
29 | void Terminate();
30 | bool IsTerminated { get; }
31 |
32 | ///
33 | /// Called by TransportProvider if a DatabaseStoreMessage for this transport was received.
34 | ///
35 | void DatabaseStoreMessageReceived( DatabaseStoreMessage dsm );
36 |
37 | I2PKeysAndCert RemoteRouterIdentity { get; }
38 | IPAddress RemoteAddress { get; }
39 |
40 | long BytesSent { get; }
41 | long BytesReceived { get; }
42 |
43 | ///
44 | /// Instance unique identifier for debugging.
12 | PeerTest-------------------->
13 | <-------------------PeerTest
14 | <-------------------PeerTest
15 | <------------------------------------------PeerTest
16 | PeerTest------------------------------------------>
17 | <------------------------------------------PeerTest
18 |
19 | * https://geti2p.net/en/docs/transport/ssu
20 | */
21 |
22 | internal enum PeerTestRole { Alice, Bob, Charlie }
23 |
24 | internal class PeerTestState
25 | {
26 | internal const int PeerTestNonceLifetimeMilliseconds = 20000;
27 |
28 | SSUHost Host;
29 | I2PRouterInfo Router;
30 |
31 | SSUSession Session;
32 |
33 | enum TestState { Start, GotReplyFromBob, GotReplyFromBobCharlie, GotReplyFromCharlie };
34 | TestState State = TestState.Start;
35 |
36 | internal int BobPeerTestsSent = 0;
37 | internal int CharliePeerTestsSent = 0;
38 |
39 | internal PeerTestState()
40 | {
41 | }
42 |
43 | private PeerTestState( SSUHost host, I2PRouterInfo router )
44 | {
45 | Host = host;
46 | Router = router;
47 |
48 | Session = (SSUSession)Host.AddSession( router );
49 | //Session.StartPeerTest( this );
50 | }
51 |
52 | internal bool OurTestNonce( I2PCore.Utils.BufLen bufLen )
53 | {
54 | return false;
55 | }
56 |
57 | internal void CharlieDirectResponseReceived( PeerTest msg )
58 | {
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/SSU/SSUHost.PeerTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.TransportLayer.SSU
8 | {
9 | internal class PeerTestNonceInfo
10 | {
11 | public TickCounter Created = new TickCounter();
12 | public PeerTestRole Role;
13 |
14 | public PeerTestNonceInfo( PeerTestRole role )
15 | {
16 | Role = role;
17 | }
18 | }
19 |
20 | public partial class SSUHost
21 | {
22 | internal PeerTestState PeerTestInstance = new PeerTestState();
23 | Dictionary KnownPeerTestNonces = new Dictionary();
24 |
25 | internal PeerTestNonceInfo GetNonceInfo( uint nonce )
26 | {
27 | PeerTestNonceInfo nonceinfo;
28 |
29 | lock ( KnownPeerTestNonces )
30 | {
31 | var remove = KnownPeerTestNonces.Where( p => p.Value.Created.DeltaToNowMilliseconds > PeerTestState.PeerTestNonceLifetimeMilliseconds ).
32 | Select( p => p.Key ).ToArray();
33 | foreach ( var key in remove ) KnownPeerTestNonces.Remove( key );
34 |
35 | if ( !KnownPeerTestNonces.TryGetValue( nonce, out nonceinfo ) ) nonceinfo = null;
36 | }
37 |
38 | return nonceinfo;
39 | }
40 |
41 | internal void SetNonceInfo( uint nonce, PeerTestRole role )
42 | {
43 | lock ( KnownPeerTestNonces )
44 | {
45 | KnownPeerTestNonces[nonce] = new PeerTestNonceInfo( role );
46 | }
47 | }
48 |
49 | internal void SendFirstPeerTestToCharlie( PeerTest msg )
50 | {
51 | if ( Sessions.Count > 0 ) Sessions.Random().Value.SendFirstPeerTestToCharlie( msg );
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/SSU/SSUHost.Utilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net;
4 | using I2PCore.Data;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.TransportLayer.SSU
8 | {
9 | public partial class SSUHost
10 | {
11 | static readonly DateTime SSURefDateTime = new DateTime( 1970, 1, 1 );
12 | public static uint SSUTime( DateTime dt ) { return (uint)( ( dt - SSURefDateTime ).TotalSeconds ); }
13 | public static DateTime SSUDateTime( uint sec ) { return SSURefDateTime.AddSeconds( sec ); }
14 |
15 | class EPComparer : IEqualityComparer
16 | {
17 | public bool Equals( IPEndPoint x, IPEndPoint y )
18 | {
19 | if ( x == null && y == null ) return false;
20 | if ( x == null || y == null ) return false;
21 | if ( ReferenceEquals( x, y ) ) return true;
22 | return ( BufUtils.Equal( x.Address.GetAddressBytes(), y.Address.GetAddressBytes() ) && x.Port == y.Port );
23 | }
24 |
25 | public int GetHashCode( IPEndPoint obj )
26 | {
27 | return obj.Address.GetAddressBytes().ComputeHash() ^ obj.Port;
28 | }
29 | }
30 |
31 | #if DEBUG
32 | internal SuccessRatio SignatureChecks = new SuccessRatio();
33 | #endif
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/SSU/SendBufferPool.cs:
--------------------------------------------------------------------------------
1 | using I2PCore.Utils;
2 |
3 | namespace I2PCore.TransportLayer.SSU
4 | {
5 | internal class SendBufferPool
6 | {
7 | const int MaxBufferSize = 1500;
8 | const int MaxNumberOfSendBuffers = 300;
9 |
10 | System.Buffers.ArrayPool Buffers = System.Buffers.ArrayPool.Create( MaxBufferSize, MaxNumberOfSendBuffers );
11 |
12 | internal SendBufferPool()
13 | {
14 | }
15 |
16 | internal BufLen Pop( int size )
17 | {
18 | return new BufLen( Buffers.Rent( size ), 0, size );
19 | }
20 |
21 | internal void Push( BufLen buf )
22 | {
23 | Buffers.Return( buf.BaseArray );
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/SSU/States/IdleState.cs:
--------------------------------------------------------------------------------
1 | using I2PCore.Utils;
2 | using I2PCore.SessionLayer;
3 |
4 | namespace I2PCore.TransportLayer.SSU
5 | {
6 | public class IdleState : SSUState
7 | {
8 | protected override BufLen CurrentMACKey => RouterContext.Inst.IntroKey;
9 |
10 | protected override BufLen CurrentPayloadKey => RouterContext.Inst.IntroKey;
11 |
12 | internal IdleState( SSUSession sess ): base( sess )
13 | {
14 | }
15 |
16 | public override SSUState Run()
17 | {
18 | return this;
19 | }
20 |
21 | public override SSUState HandleMessage( SSUHeader header, BufRefLen reader )
22 | {
23 | return this;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/TransportProtocolAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace I2PCore.TransportLayer
3 | {
4 | ///
5 | /// Add to classes that implement ITransportProtocol and should be instanced
6 | /// to accept incomming and outgoing connections.
7 | /// The class decorated with this attribute must have a default constructor
8 | /// with no aruments.
9 | ///
10 | [AttributeUsage( AttributeTargets.Class, AllowMultiple = false )]
11 | public class TransportProtocolAttribute: Attribute
12 | {
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/I2PCore/TransportLayer/UnresolvableRouters.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.TunnelLayer.I2NP.Messages;
7 | using I2PCore.Utils;
8 |
9 | namespace I2PCore.TransportLayer
10 | {
11 | internal class UnresolvableRouters
12 | {
13 | const int UnresolvableDecayMinutes = 60 * 2;
14 |
15 | Dictionary CurrentlyUnresolvableRouters = new Dictionary();
16 |
17 | internal void Add( I2PIdentHash dest )
18 | {
19 | Logging.LogDebug( $"UnresolvableAddresses: {dest.Id32Short} marked as unresolvable." );
20 | lock ( CurrentlyUnresolvableRouters )
21 | {
22 | CurrentlyUnresolvableRouters[dest] = TickCounter.Now;
23 | }
24 | }
25 |
26 | internal bool Contains( I2PIdentHash dest )
27 | {
28 | lock ( CurrentlyUnresolvableRouters )
29 | {
30 | var remove = CurrentlyUnresolvableRouters.Where( d => d.Value.DeltaToNow.ToMinutes > UnresolvableDecayMinutes ).Select( m => m.Key ).ToArray();
31 | foreach ( var one in remove ) CurrentlyUnresolvableRouters.Remove( one );
32 |
33 | return CurrentlyUnresolvableRouters.ContainsKey( dest );
34 | }
35 | }
36 |
37 | internal int Count { get { return CurrentlyUnresolvableRouters.Count; } }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/AesEGBuildRequestRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using Org.BouncyCastle.Crypto;
7 | using Org.BouncyCastle.Crypto.Modes;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Data
10 | {
11 | public class AesEGBuildRequestRecord
12 | {
13 | public const int Length = 528;
14 |
15 | public BufLen Data;
16 |
17 | // Might be readable, or encrypted
18 | public BufLen ToPeer16 { get { return new BufLen( Data, 0, 16 ); } }
19 |
20 | public AesEGBuildRequestRecord( BufRef buf )
21 | {
22 | Data = buf.ReadBufLen( Length );
23 | }
24 |
25 | public AesEGBuildRequestRecord( BufLen dest, EGBuildRequestRecord src, BufferedBlockCipher cipher )
26 | {
27 | Data = dest;
28 | cipher.ProcessBytes( src.Data.BaseArray, src.Data.BaseArrayOffset, src.Data.Length, Data.BaseArray, Data.BaseArrayOffset );
29 | }
30 |
31 | public AesEGBuildRequestRecord( EGBuildRequestRecord src, BufferedBlockCipher cipher )
32 | {
33 | Data = new BufLen( cipher.ProcessBytes( src.Data.BaseArray, src.Data.BaseArrayOffset, src.Data.Length ) );
34 | }
35 |
36 | public AesEGBuildRequestRecord Clone()
37 | {
38 | return new AesEGBuildRequestRecord( (BufRefLen)Data.Clone() );
39 | }
40 |
41 | public void Process( BufferedBlockCipher cipher )
42 | {
43 | cipher.ProcessBytes( Data );
44 | }
45 |
46 | public void Process( CbcBlockCipher cipher )
47 | {
48 | cipher.ProcessBytes( Data );
49 | }
50 |
51 | public override string ToString()
52 | {
53 | var result = new StringBuilder();
54 | result.AppendLine( "EGAesBuildRequestRecord " + BufUtils.ToBase32String( ToPeer16 ) );
55 | return result.ToString();
56 | }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/BuildResponseRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 | using Org.BouncyCastle.Utilities.Encoders;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Data
10 | {
11 | public class BuildResponseRecord: I2PType
12 | {
13 | public enum RequestResponse : byte { Accept = 0, ProbabalisticReject = 10, TransientOverload = 20, Bandwidth = 30, Critical = 50 }
14 | public const RequestResponse DefaultErrorReply = RequestResponse.Bandwidth;
15 |
16 | public int Length { get => 528; }
17 | BufLen Data;
18 |
19 | public BuildResponseRecord( BufRef buf )
20 | {
21 | Data = buf.ReadBufLen( Length );
22 | }
23 |
24 | public BuildResponseRecord( BufLen src )
25 | {
26 | if ( src.Length != Length ) throw new ArgumentException( "BuildResponseRecord needs a 528 byte record!" );
27 | Data = src;
28 | }
29 |
30 | public BuildResponseRecord( EGBuildRequestRecord request )
31 | {
32 | // Replace it
33 | Data = request.Data;
34 | Data.Randomize();
35 | }
36 |
37 | public BuildResponseRecord( AesEGBuildRequestRecord request )
38 | {
39 | // Reuse it
40 | Data = request.Data;
41 | }
42 |
43 | public RequestResponse Reply
44 | {
45 | get { return (RequestResponse)Data[527]; }
46 | set { Data[527] = (byte)value; }
47 | }
48 |
49 | public BufLen Payload
50 | {
51 | get { return new BufLen( Data, 0, Length ); }
52 | }
53 |
54 | public BufLen Hash
55 | {
56 | get { return new BufLen( Data, 0, 32 ); }
57 | }
58 |
59 | public BufLen HashedArea
60 | {
61 | get { return new BufLen( Data, 32, 496 ); }
62 | }
63 |
64 | public bool CheckHash()
65 | {
66 | var hash = I2PHashSHA256.GetHash( HashedArea );
67 | return Hash.Equals( hash );
68 | }
69 |
70 | public void UpdateHash()
71 | {
72 | var hash = I2PHashSHA256.GetHash( HashedArea );
73 | Hash.Poke( new BufLen( hash ), 0 );
74 | }
75 |
76 | public bool IsDestination( I2PIdentHash comp )
77 | {
78 | return comp.Hash16 == Data;
79 | }
80 |
81 | public void Write( BufRefStream dest )
82 | {
83 | Data.WriteTo( dest );
84 | }
85 |
86 | public override string ToString()
87 | {
88 | return Data == null
89 | ? "BuildResponseRecord Content: (null)"
90 | : $"BuildResponseRecord Content: Reply: {Reply}";
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/EGBuildRequestRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.Data;
7 | using Org.BouncyCastle.Math;
8 | using Org.BouncyCastle.Security;
9 | using I2PCore.SessionLayer;
10 |
11 | namespace I2PCore.TunnelLayer.I2NP.Data
12 | {
13 | public class EGBuildRequestRecord: I2PType
14 | {
15 | public const int Length = 528;
16 |
17 | public BufLen Data;
18 |
19 | public BufLen ToPeer16 { get { return new BufLen( Data, 0, 16 ); } }
20 | public BufLen EncryptedData { get { return new BufLen( Data, 16, Length - 16 ); } }
21 |
22 | public EGBuildRequestRecord( BufRef buf )
23 | {
24 | Data = buf.ReadBufLen( Length );
25 | }
26 |
27 | // The AesEGBuildRequestRecord has been decrypted to the degree ToPeer16 is readable.
28 | public EGBuildRequestRecord( AesEGBuildRequestRecord src )
29 | {
30 | Data = src.Data;
31 | }
32 |
33 | public EGBuildRequestRecord( BufLen dest, BuildRequestRecord src, I2PIdentHash topeer, I2PPublicKey key )
34 | {
35 | Data = dest;
36 | var writer = new BufRefLen( Data );
37 |
38 | writer.Write( topeer.Hash16 );
39 |
40 | var datastart = new BufLen( writer );
41 | ElGamalCrypto.Encrypt( writer, src.Data, key, false );
42 | }
43 |
44 | public EGBuildRequestRecord( BuildRequestRecord src, I2PIdentHash topeer, I2PPublicKey key ):
45 | this( new BufLen( new byte[Length] ), src, topeer, key )
46 | {
47 | }
48 |
49 | public BuildRequestRecord Decrypt( I2PPrivateKey pkey )
50 | {
51 | return new BuildRequestRecord( new BufRef( ElGamalCrypto.Decrypt( EncryptedData, pkey, false ) ) );
52 | }
53 |
54 | public override string ToString()
55 | {
56 | var result = new StringBuilder();
57 |
58 | result.AppendLine( "EGBuildRequestRecord" );
59 | result.AppendLine( "ToPeer16 : " + BufUtils.ToBase32String( ToPeer16 ) );
60 |
61 | return result.ToString();
62 | }
63 |
64 | void I2PType.Write( BufRefStream dest )
65 | {
66 | Data.WriteTo( dest );
67 | }
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/GarlicClove.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.Data;
7 | using I2PCore.TunnelLayer.I2NP.Messages;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Data
10 | {
11 | public class GarlicClove : I2PType
12 | {
13 | public GarlicCloveDelivery Delivery;
14 | public uint CloveId;
15 | public I2PDate Expiration;
16 | public I2NPMessage Message;
17 |
18 | public GarlicClove( BufRefLen reader )
19 | {
20 | Delivery = GarlicCloveDelivery.CreateGarlicCloveDelivery( reader );
21 | Message = I2NPMessage.ReadHeader16( reader ).Message;
22 | CloveId = reader.ReadFlip32();
23 | Expiration = new I2PDate( reader );
24 | reader.Seek( 3 ); // Cert
25 | }
26 |
27 | public GarlicClove( GarlicCloveDelivery delivery, I2PDate exp )
28 | {
29 | Delivery = delivery;
30 | Message = delivery.Message;
31 | CloveId = BufUtils.RandomUint();
32 | Expiration = exp;
33 | }
34 |
35 | public GarlicClove( GarlicCloveDelivery delivery )
36 | {
37 | Delivery = delivery;
38 | Message = delivery.Message;
39 | CloveId = BufUtils.RandomUint();
40 | Expiration = new I2PDate( DateTime.UtcNow + TimeSpan.FromMinutes( 5 ) );
41 | }
42 |
43 | static readonly byte[] ThreeZero = new byte[] { 0, 0, 0 };
44 |
45 | public void Write( BufRefStream dest )
46 | {
47 | Delivery.Write( dest );
48 | dest.Write( (BufRefLen)BufUtils.Flip32BL( CloveId ) );
49 | Expiration.Write( dest );
50 | dest.Write( ThreeZero );
51 | }
52 |
53 | public override string ToString()
54 | {
55 | return $"{CloveId} {Delivery} {Message?.MessageType}";
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/HopInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.TunnelLayer.I2NP.Messages;
7 |
8 | namespace I2PCore.TunnelLayer.I2NP.Data
9 | {
10 | public class HopInfo
11 | {
12 | public readonly I2PKeysAndCert Peer;
13 | public readonly I2PTunnelId TunnelId;
14 |
15 | public I2PSessionKey IVKey;
16 | public I2PSessionKey LayerKey;
17 |
18 | public VariableTunnelBuildMessage.ReplyProcessingInfo ReplyProcessing;
19 |
20 | public HopInfo( I2PKeysAndCert dest, I2PTunnelId id )
21 | {
22 | Peer = dest;
23 | TunnelId = id;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/I2NPHeader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.TunnelLayer.I2NP.Messages;
6 | using I2PCore.Data;
7 | using I2PCore.Utils;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Data
10 | {
11 | public interface II2NPHeader
12 | {
13 | I2NPMessage.MessageTypes MessageType { get; set; }
14 | I2PDate Expiration { get; set; }
15 | BufLen HeaderAndPayload { get; }
16 | int Length { get; }
17 |
18 | I2NPMessage Message { get; }
19 |
20 | string ToString();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Data/TunnelInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 | using Org.BouncyCastle.Crypto;
8 | using Org.BouncyCastle.Crypto.Modes;
9 | using Org.BouncyCastle.Crypto.Engines;
10 | using Org.BouncyCastle.Crypto.Parameters;
11 | using I2PCore.TunnelLayer.I2NP.Messages;
12 | using I2PCore.SessionLayer;
13 |
14 | namespace I2PCore.TunnelLayer.I2NP.Data
15 | {
16 | public class TunnelInfo
17 | {
18 | public readonly List Hops;
19 |
20 | public TunnelInfo( List hops )
21 | {
22 | Hops = hops;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/DataMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.Data;
7 | using I2PCore.TunnelLayer.I2NP.Messages;
8 | using I2PCore.TunnelLayer.I2NP.Data;
9 |
10 | namespace I2PCore.TunnelLayer.I2NP.Messages
11 | {
12 | public class DataMessage : I2NPMessage
13 | {
14 | public override MessageTypes MessageType { get { return MessageTypes.Data; } }
15 |
16 | public DataMessage( BufRef reader )
17 | {
18 | var start = new BufRef( reader );
19 | reader.Seek( (int)reader.ReadFlip32() );
20 | SetBuffer( start, reader );
21 | }
22 |
23 | public DataMessage( BufLen data )
24 | {
25 | AllocateBuffer( 4 + data.Length );
26 | Payload.PokeFlip32( (uint)data.Length, 0 );
27 | Payload.Poke( data, 4 );
28 | }
29 |
30 | public uint DataMessagePayloadLength
31 | {
32 | get
33 | {
34 | return Payload.PeekFlip32( 0 );
35 | }
36 | set
37 | {
38 | Payload.PokeFlip32( value, 0 );
39 | }
40 | }
41 |
42 | public BufLen DataMessagePayload
43 | {
44 | get
45 | {
46 | return new BufLen( Payload, 4, (int)DataMessagePayloadLength );
47 | }
48 | }
49 |
50 | public override string ToString()
51 | {
52 | var result = new StringBuilder();
53 |
54 | result.AppendLine( $"DataMessage bytes: {Payload.Length}" );
55 |
56 | return result.ToString();
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/DatabaseSearchReplyMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.Data;
7 | using I2PCore.TunnelLayer.I2NP.Messages;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Messages
10 | {
11 | public class DatabaseSearchReplyMessage : I2NPMessage
12 | {
13 | public override MessageTypes MessageType { get { return MessageTypes.DatabaseSearchReply; } }
14 |
15 | public readonly I2PIdentHash Key;
16 | public readonly List Peers = new List();
17 | public readonly I2PIdentHash From;
18 |
19 | public DatabaseSearchReplyMessage( BufRef reader )
20 | {
21 | var start = new BufRef( reader );
22 |
23 | Key = new I2PIdentHash( reader );
24 |
25 | var peercount = reader.Read8();
26 | for ( int i = 0; i < peercount; ++i )
27 | {
28 | Peers.Add( new I2PIdentHash( reader ) );
29 | }
30 |
31 | From = new I2PIdentHash( reader );
32 |
33 | SetBuffer( start, reader );
34 | }
35 |
36 | public override string ToString()
37 | {
38 | var result = new StringBuilder();
39 |
40 | result.AppendLine( "DatabaseSearchReplyMessage" );
41 | result.AppendLine( "Peer count : " + ( Peers == null ? "(null)" : Peers.Count.ToString() ) );
42 |
43 | foreach ( var one in Peers )
44 | {
45 | result.AppendLine( one.ToString() );
46 | }
47 |
48 | return result.ToString();
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/DeliveryStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.TunnelLayer.I2NP.Messages;
6 | using I2PCore.Utils;
7 | using I2PCore.Data;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Data
10 | {
11 | public sealed class DeliveryStatusMessage : I2NPMessage
12 | {
13 | public override MessageTypes MessageType { get { return MessageTypes.DeliveryStatus; } }
14 |
15 | public uint StatusMessageId
16 | {
17 | get
18 | {
19 | return Payload.Peek32( 0 );
20 | }
21 | set
22 | {
23 | Payload.Poke32( value, 0 );
24 | }
25 | }
26 |
27 | public I2PDate Timestamp { get { return new I2PDate( new BufRefLen( Payload, 4 ) ); } set { value.Poke( Payload, 4 ); } }
28 |
29 | public DeliveryStatusMessage()
30 | {
31 | AllocateBuffer( 12 );
32 | var writer = new BufRefLen( Payload );
33 | Timestamp = new I2PDate( DateTime.UtcNow );
34 | StatusMessageId = I2NPMessage.GenerateMessageId();
35 | }
36 |
37 | public DeliveryStatusMessage( uint msgid )
38 | {
39 | AllocateBuffer( 12 );
40 | var writer = new BufRefLen( Payload );
41 | Timestamp = new I2PDate( DateTime.UtcNow );
42 | StatusMessageId = msgid;
43 | }
44 |
45 | public DeliveryStatusMessage( ulong networkid )
46 | {
47 | AllocateBuffer( 12 );
48 | var writer = new BufRefLen( Payload );
49 | writer.PokeFlip64( networkid, 4 );
50 | StatusMessageId = BufUtils.RandomUint();
51 | }
52 |
53 | public DeliveryStatusMessage( BufRef reader )
54 | {
55 | var start = new BufRef( reader );
56 | reader.Seek( 12 );
57 | SetBuffer( start, reader );
58 | }
59 |
60 | public bool IsNetworkId( ulong networkid )
61 | {
62 | return Payload.PeekFlip64( 4 ) == networkid;
63 | }
64 |
65 | public override string ToString()
66 | {
67 | var result = new StringBuilder();
68 |
69 | result.AppendFormat( "DeliveryStatus MessageId: {0}, Timestamp: {1}.", StatusMessageId, Timestamp );
70 |
71 | return result.ToString();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/GarlicMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Data;
6 | using I2PCore.Utils;
7 | using I2PCore.TunnelLayer.I2NP.Data;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Messages
10 | {
11 | public class GarlicMessage : I2NPMessage
12 | {
13 | public override MessageTypes MessageType { get { return MessageTypes.Garlic; } }
14 |
15 | public BufLen EGData
16 | {
17 | get
18 | {
19 | return new BufLen( Payload, 4 );
20 | }
21 | }
22 |
23 | public GarlicMessage( BufRef reader )
24 | {
25 | var start = new BufRef( reader );
26 | var len = (int)reader.PeekFlip32( 0 );
27 | reader.Seek( len + 4 );
28 | SetBuffer( start, reader );
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/TunnelBuildMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.TunnelLayer.I2NP.Data;
7 |
8 | namespace I2PCore.TunnelLayer.I2NP.Messages
9 | {
10 | public class TunnelBuildMessage: I2NPMessage
11 | {
12 | public override MessageTypes MessageType { get { return MessageTypes.TunnelBuild; } }
13 |
14 | public List Records = new List();
15 |
16 | public TunnelBuildMessage( BufRef reader )
17 | {
18 | var start = new BufRef( reader );
19 | for ( int i = 0; i < 8; ++i )
20 | {
21 | var r = new AesEGBuildRequestRecord( reader );
22 | Records.Add( r );
23 | }
24 | SetBuffer( start, reader );
25 | }
26 |
27 | // Clones records
28 | public TunnelBuildMessage( IEnumerable records )
29 | {
30 | var hops = (byte)records.Count();
31 | if ( hops > 8 ) throw new ArgumentException( "TunnelBuildMessage can only contain 8 records" );
32 |
33 | AllocateBuffer( 1 + 8 * AesEGBuildRequestRecord.Length );
34 | var writer = new BufRefLen( Payload );
35 | foreach ( var rec in records )
36 | {
37 | Records.Add( rec );
38 | writer.Write( rec.Data );
39 | }
40 | }
41 |
42 | private TunnelBuildMessage()
43 | {
44 | AllocateBuffer( 1 + 8 * AesEGBuildRequestRecord.Length );
45 | var writer = new BufRefLen( Payload );
46 | for ( int i = 0; i < 8; ++i ) Records.Add( new AesEGBuildRequestRecord( writer ) );
47 | }
48 |
49 | public override string ToString()
50 | {
51 | var result = new StringBuilder();
52 |
53 | result.AppendLine( "TunnelBuild" );
54 | for ( int i = 0; i < Records.Count; ++i )
55 | {
56 | result.Append( Records[i].ToString() );
57 | }
58 |
59 | return result.ToString();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/TunnelBuildReplyMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.TunnelLayer.I2NP.Data;
6 | using I2PCore.Utils;
7 |
8 | namespace I2PCore.TunnelLayer.I2NP.Messages
9 | {
10 | public class TunnelBuildReplyMessage: I2NPMessage
11 | {
12 | public override MessageTypes MessageType { get { return MessageTypes.TunnelBuildReply; } }
13 |
14 | public BuildResponseRecord[] ResponseRecords;
15 |
16 | public TunnelBuildReplyMessage( BufRef reader )
17 | {
18 | var start = new BufRef( reader );
19 | ResponseRecords = new BuildResponseRecord[8];
20 |
21 | for ( int i = 0; i < 8; ++i ) ResponseRecords[i] = new BuildResponseRecord( reader );
22 | SetBuffer( start, reader );
23 | }
24 |
25 | public override string ToString()
26 | {
27 | var result = new StringBuilder();
28 |
29 | result.AppendLine( "TunnelBuildReply" );
30 |
31 | if ( ResponseRecords == null )
32 | {
33 | result.AppendLine( "Content: (null)" );
34 | }
35 | else
36 | {
37 | for ( int i = 0; i < 8; ++i )
38 | {
39 | result.AppendLine( "ResponseRecords[" + i.ToString() + "]" );
40 | result.AppendLine( ResponseRecords[i].ToString() );
41 | }
42 | }
43 |
44 | return result.ToString();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/TunnelGatewayMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.Data;
7 | using I2PCore.TunnelLayer.I2NP.Data;
8 |
9 | namespace I2PCore.TunnelLayer.I2NP.Messages
10 | {
11 | public class TunnelGatewayMessage : I2NPMessage
12 | {
13 | public override MessageTypes MessageType { get { return MessageTypes.TunnelGateway; } }
14 |
15 | public TunnelGatewayMessage( BufRef reader )
16 | {
17 | var start = new BufRef( reader );
18 | reader.Seek( 6 + reader.PeekFlip16( 4 ) );
19 | SetBuffer( start, reader );
20 | }
21 |
22 | public TunnelGatewayMessage( I2NPMessage message, I2PTunnelId outtunnel )
23 | {
24 | var msg = message.CreateHeader16.HeaderAndPayload;
25 | AllocateBuffer( 6 + msg.Length );
26 |
27 | TunnelId = outtunnel;
28 | GatewayMessageLength = (ushort)msg.Length;
29 | // TODO: Remove mem copy
30 | Payload.Poke( msg, 6 );
31 | }
32 |
33 | public uint TunnelId
34 | {
35 | get
36 | {
37 | return Payload.Peek32( 0 );
38 | }
39 | set
40 | {
41 | Payload.Poke32( value, 0 );
42 | }
43 | }
44 |
45 | public ushort GatewayMessageLength
46 | {
47 | get
48 | {
49 | return Payload.PeekFlip16( 4 );
50 | }
51 | set
52 | {
53 | Payload.PokeFlip16( value, 4 );
54 | }
55 | }
56 |
57 | public BufLen GatewayMessage
58 | {
59 | get
60 | {
61 | return new BufLen( Payload, 6, GatewayMessageLength );
62 | }
63 | }
64 |
65 | protected MessageTypes GatewayMessageType
66 | {
67 | get
68 | {
69 | return (I2NPMessage.MessageTypes)GatewayMessage.Peek8( 0 );
70 | }
71 | }
72 |
73 | public override string ToString()
74 | {
75 | var result = new StringBuilder();
76 |
77 | result.AppendLine( "TunnelGateway" );
78 | result.AppendLine( "TunnelId: : " + TunnelId.ToString() );
79 | result.AppendLine( "GatewayMessageType : " + GatewayMessageType.ToString() + " ( " + GatewayMessageLength.ToString() + " bytes )" );
80 |
81 | return result.ToString();
82 | }
83 |
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/I2NP/Messages/VariableTunnelBuildReplyMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.Utils;
6 | using I2PCore.TunnelLayer.I2NP.Data;
7 |
8 | namespace I2PCore.TunnelLayer.I2NP.Messages
9 | {
10 | public class VariableTunnelBuildReplyMessage: I2NPMessage
11 | {
12 | public override MessageTypes MessageType { get { return MessageTypes.VariableTunnelBuildReply; } }
13 |
14 | public List ResponseRecords;
15 |
16 | public VariableTunnelBuildReplyMessage( BufRef reader )
17 | {
18 | var start = new BufRef( reader );
19 | ResponseRecords = new List();
20 |
21 | byte count = reader.Read8();
22 | for ( int i = 0; i < count; ++i ) ResponseRecords.Add( new BuildResponseRecord( reader ) );
23 | SetBuffer( start, reader );
24 | }
25 |
26 | public VariableTunnelBuildReplyMessage( IEnumerable recs, uint msgid )
27 | {
28 | AllocateBuffer( 1 + recs.Count() * EGBuildRequestRecord.Length );
29 | ResponseRecords = new List( recs );
30 |
31 | MessageId = msgid;
32 |
33 | // TODO: Remove mem copy
34 | var writer = new BufRefLen( Payload );
35 | writer.Write8( (byte)recs.Count() );
36 | foreach ( var rec in ResponseRecords ) writer.Write( rec.Payload );
37 | }
38 |
39 | public override string ToString()
40 | {
41 | var result = new StringBuilder();
42 |
43 | result.AppendLine( "VariableTunnelBuildReply" );
44 | if ( ResponseRecords != null )
45 | {
46 | foreach ( var one in ResponseRecords )
47 | {
48 | result.AppendLine( one.ToString() );
49 | }
50 | }
51 |
52 | return result.ToString();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/ITunnelOwner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace I2PCore.TunnelLayer
3 | {
4 | public interface ITunnelOwner
5 | {
6 | void TunnelBuildFailed( Tunnel tunnel, bool timeout );
7 | void TunnelEstablished( Tunnel tunnel );
8 | void TunnelFailed( Tunnel tunnel );
9 | void TunnelExpired( Tunnel tunnel );
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/TunnelBuildRequestDecrypt.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using I2PCore.Data;
4 | using I2PCore.TunnelLayer.I2NP.Data;
5 | using System.Linq;
6 | using I2PCore.Utils;
7 | using Org.BouncyCastle.Crypto.Modes;
8 | using Org.BouncyCastle.Crypto.Engines;
9 |
10 | namespace I2PCore.TunnelLayer
11 | {
12 | public class TunnelBuildRequestDecrypt
13 | {
14 | readonly IEnumerable RecordsField;
15 | readonly I2PIdentHash Me;
16 | private readonly I2PPrivateKey Key;
17 | private readonly AesEGBuildRequestRecord ToMeField;
18 | private readonly EGBuildRequestRecord MyRecord;
19 | private readonly BuildRequestRecord DecryptedRecord;
20 |
21 | public TunnelBuildRequestDecrypt(
22 | IEnumerable records,
23 | I2PIdentHash me,
24 | I2PPrivateKey key )
25 | {
26 | RecordsField = records;
27 | Me = me;
28 | Key = key;
29 |
30 | ToMeField = RecordsField.FirstOrDefault( rec => Me.Hash16 == rec.ToPeer16 );
31 |
32 | if ( ToMeField != null )
33 | {
34 | MyRecord = new EGBuildRequestRecord( ToMeField );
35 | DecryptedRecord = MyRecord.Decrypt( key );
36 | }
37 | }
38 |
39 | public TunnelBuildRequestDecrypt Clone()
40 | {
41 | return new TunnelBuildRequestDecrypt(
42 | Records.Select( r => r.Clone() ),
43 | Me,
44 | Key );
45 | }
46 |
47 | public AesEGBuildRequestRecord ToMe()
48 | {
49 | return ToMeField;
50 | }
51 |
52 | public BuildRequestRecord Decrypted => DecryptedRecord;
53 | public IEnumerable Records => RecordsField;
54 |
55 | public IEnumerable CreateTunnelBuildReplyRecords(
56 | BuildResponseRecord.RequestResponse response )
57 | {
58 | var newrecords = new List(
59 | Records.Select( r => r.Clone() )
60 | );
61 |
62 | var tmp = new TunnelBuildRequestDecrypt( newrecords, Me, Key );
63 |
64 | tmp.ToMeField.Data.Randomize();
65 | var responserec = new BuildResponseRecord( tmp.ToMeField.Data )
66 | {
67 | Reply = response
68 | };
69 | responserec.UpdateHash();
70 |
71 | var cipher = new CbcBlockCipher( new AesEngine() );
72 | cipher.Init( true, Decrypted.ReplyKeyBuf.ToParametersWithIV( Decrypted.ReplyIV ) );
73 |
74 | foreach ( var one in newrecords )
75 | {
76 | cipher.Reset();
77 | one.Process( cipher );
78 | }
79 |
80 | return newrecords;
81 | }
82 |
83 |
84 | public override string ToString()
85 | {
86 | return $"{GetType().Name} {Decrypted}";
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/TunnelConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using I2PCore.TunnelLayer.I2NP.Data;
6 |
7 | namespace I2PCore.TunnelLayer
8 | {
9 | public class TunnelConfig
10 | {
11 | public enum TunnelDirection { Outbound, Inbound };
12 | public enum TunnelPool { Initial, Client, Exploratory, External }
13 |
14 | public TunnelInfo Info;
15 | public TunnelDirection Direction;
16 | public TunnelPool Pool;
17 |
18 | public TunnelConfig( TunnelDirection dir, TunnelPool pool, TunnelInfo hops )
19 | {
20 | Direction = dir;
21 | Pool = pool;
22 | Info = hops;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/TunnelIdSubsriptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using I2PCore.Utils;
6 |
7 | namespace I2PCore.TunnelLayer
8 | {
9 | public class TunnelIdSubsriptions
10 | {
11 | ConcurrentDictionary> TunnelIds
12 | = new ConcurrentDictionary>();
13 |
14 | public void Add( uint id, Tunnel tunnel )
15 | {
16 | Logging.LogDebug( $"TunnelIdSubsriptions: Added {id} to {tunnel}" );
17 |
18 | var tunnels = TunnelIds.GetOrAdd( id, new HashSet() );
19 | tunnels.Add( tunnel );
20 | }
21 |
22 | public Tunnel Remove( uint id, Tunnel tunnel )
23 | {
24 | if ( !TunnelIds.TryGetValue( id, out var tunnels ) ) return null;
25 |
26 | tunnels.Remove( tunnel );
27 | if ( !tunnels.Any() ) TunnelIds.TryRemove( id, out _ );
28 |
29 | return tunnel;
30 | }
31 |
32 | public IEnumerable FindTunnelFromTunnelId( uint tunnelid )
33 | {
34 | if ( TunnelIds.TryGetValue( tunnelid, out var tunnels ) )
35 | return tunnels.ToArray();
36 |
37 | return Enumerable.Empty();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/TunnelQuality.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using I2PCore.Utils;
3 |
4 | namespace I2PCore.TunnelLayer
5 | {
6 | public class TunnelQuality
7 | {
8 | public TickSpan MinLatencyMeasured { set; get; }
9 |
10 | public void UpdateMinLatency( TickSpan delta )
11 | {
12 | if ( MinLatencyMeasured == null || MinLatencyMeasured > delta )
13 | {
14 | MinLatencyMeasured = delta;
15 | }
16 | }
17 |
18 | public bool PassedTunnelTest { get; set; }
19 |
20 | public TickSpan BuildTimePerHop { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/TunnelSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.TunnelLayer
7 | {
8 | internal class TunnelSettings
9 | {
10 | internal float OutboundTunnelBitrateLimit = 0f;
11 | internal float InboundTunnelBitrateLimit = 0f;
12 |
13 | ///
14 | /// 0.0f (share nothing) -> 1.0f (only share)
15 | ///
16 | internal float BandwidthShareRatio = 0.5f;
17 |
18 | internal const float EndpointTunnelBitrateLimit = 500f * 1024f;
19 | internal const float GatewayTunnelBitrateLimit = 500f * 1024f;
20 | internal const float TransitTunnelBitrateLimit = 500f * 1024f;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/I2PCore/TunnelLayer/ZeroHopTunnel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using I2PCore.Data;
4 | using I2PCore.Utils;
5 |
6 | namespace I2PCore.TunnelLayer
7 | {
8 | public class ZeroHopTunnel: InboundTunnel
9 | {
10 | public override TickSpan Lifetime => TickSpan.Minutes( 5 );
11 |
12 | public override TickSpan TunnelEstablishmentTimeout => TickSpan.Seconds( 100 );
13 |
14 | public override bool NeedsRecreation => false;
15 |
16 | public ZeroHopTunnel( ITunnelOwner owner, TunnelConfig config, I2PIdentHash remotegateway )
17 | : base( owner, config, remotegateway )
18 | {
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/I2PCore/Utils/BandwidthLimiter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Utils
7 | {
8 | public class BandwidthLimiter
9 | {
10 | Bandwidth BandwidthMeasurement;
11 | float MaxKbPS;
12 |
13 | const float StartDiscardingLimitFactor = 0.9f;
14 | float StartDiscardingLimit;
15 | float ProbabilityWindow;
16 |
17 | public BandwidthLimiter( Bandwidth bwref, float maxkbps )
18 | {
19 | BandwidthMeasurement = bwref;
20 |
21 | MaxKbPS = maxkbps;
22 | StartDiscardingLimit = MaxKbPS * StartDiscardingLimitFactor;
23 | ProbabilityWindow = MaxKbPS - StartDiscardingLimit;
24 | }
25 |
26 | Random Rnd = new Random();
27 |
28 | public bool DropMessage()
29 | {
30 | var br = BandwidthMeasurement.Bitrate;
31 | if ( MaxKbPS <= 0f || br < StartDiscardingLimit ) return false;
32 |
33 | var probability = ( br - StartDiscardingLimit ) / ProbabilityWindow;
34 | return Rnd.NextDouble() < probability;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/I2PCore/Utils/BandwidthStatistics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using static I2PCore.Utils.BufUtils;
6 |
7 | namespace I2PCore.Utils
8 | {
9 | public class BandwidthStatistics
10 | {
11 | public Bandwidth ReceiveBandwidth = new Bandwidth();
12 | public Bandwidth SendBandwidth = new Bandwidth();
13 | readonly DateTime StartTime = DateTime.Now;
14 |
15 | public event Action OnDataReceived;
16 | public event Action OnDataSent;
17 |
18 | public BandwidthStatistics()
19 | {
20 | }
21 |
22 | public BandwidthStatistics( BandwidthStatistics aggregate )
23 | {
24 | OnDataReceived += aggregate.DataReceived;
25 | OnDataSent += aggregate.DataSent;
26 | }
27 |
28 | public void DataReceived( int size )
29 | {
30 | ReceiveBandwidth.Measure( size );
31 | OnDataReceived?.Invoke( size );
32 | }
33 |
34 | public void DataSent( int size )
35 | {
36 | SendBandwidth.Measure( size );
37 | OnDataSent?.Invoke( size );
38 | }
39 |
40 | public override string ToString()
41 | {
42 | return $"send / recv: {SendBandwidth.Bitrate/1024f,8:0.00} /" +
43 | $"{ReceiveBandwidth.Bitrate/1024f,8:0.00} kbps " +
44 | $"{BytesToReadable( SendBandwidth.DataBytes ),12} /" +
45 | $"{BytesToReadable( ReceiveBandwidth.DataBytes ),12} ";
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/I2PCore/Utils/HashedItemGroup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Utils
7 | {
8 |
9 | class HashedItemGroup : IEquatable
10 | {
11 | int Hash;
12 |
13 | public HashedItemGroup( params object[] objs )
14 | {
15 | int result = 0;
16 | foreach ( var obj in objs ) if ( obj != null )
17 | {
18 | result ^= obj.GetHashCode();
19 | }
20 | Hash = result;
21 | }
22 |
23 | public bool Equals( HashedItemGroup other )
24 | {
25 | if ( other == null ) return false;
26 | return other.Hash == Hash;
27 | }
28 |
29 | public override bool Equals( object obj )
30 | {
31 | if ( obj == null ) return false;
32 | var other = (HashedItemGroup)obj;
33 | if ( other == null ) return false;
34 | return other.Hash == Hash;
35 | }
36 |
37 | public override int GetHashCode()
38 | {
39 | return Hash;
40 | }
41 | }
42 |
43 | class OrderedHashedItemGroup : HashedItemGroup
44 | {
45 | int Hash;
46 |
47 | public OrderedHashedItemGroup( params object[] objs )
48 | {
49 | int result = 0;
50 | foreach ( var obj in objs ) if ( obj != null )
51 | {
52 | result = ( result << 1 ) | ( result >> -1 );
53 | result ^= obj.GetHashCode();
54 | }
55 | Hash = result;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/I2PCore/Utils/IPAddressMask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 |
5 | namespace I2PCore.Utils
6 | {
7 | public class IPAddressMask
8 | {
9 | public IPAddress Address { get; protected set; }
10 | public IPAddress Mask { get; protected set; }
11 | public IPAddressMask( string mask )
12 | {
13 | if ( !mask.Contains( '/' ) )
14 | throw new ArgumentException( "Mask needs to contain address and netmask" );
15 |
16 | var split = mask.Split( '/', StringSplitOptions.RemoveEmptyEntries );
17 |
18 | if ( split.Length != 2 )
19 | throw new ArgumentException( "Address/Mask needed" );
20 |
21 | var isbitcount = true;
22 |
23 | if ( mask.Contains( "//" ) )
24 | {
25 | isbitcount = false;
26 | }
27 |
28 | Address = IPAddress.Parse( split[0] );
29 |
30 | if ( isbitcount )
31 | {
32 | var bits = int.Parse( split[1] );
33 | var maxbits = Address.AddressFamily == AddressFamily.InterNetwork ? 32 : 128;
34 | if ( bits < 0 || bits > maxbits )
35 | throw new ArgumentException( $"Mask bits must be in the rage 0 -> {maxbits}" );
36 |
37 | var maskbits = new byte[Address.AddressFamily == AddressFamily.InterNetwork ? 4 : 16];
38 | var ix = 0;
39 | while ( bits >= 8 )
40 | {
41 | maskbits[ix++] = 0xff;
42 | bits -= 8;
43 | }
44 |
45 | for( int i = 0; i < bits; ++i ) maskbits[ix] = (byte)( ( maskbits[ix] >> 1 ) | 0x80 );
46 |
47 | Mask = new IPAddress( maskbits );
48 | }
49 | else
50 | {
51 | Mask = IPAddress.Parse( split[1] );
52 |
53 | if ( Address.AddressFamily != Mask.AddressFamily )
54 | throw new ArgumentException( "Address and Mask must belong to the same AddressFamily" );
55 | }
56 | }
57 |
58 | public static byte[] Combine( IPAddress a, IPAddress b, Func op )
59 | {
60 | if ( a.AddressFamily != b.AddressFamily )
61 | throw new ArgumentException( "Addresses must belong to the same AddressFamily" );
62 |
63 | var ab = a.GetAddressBytes();
64 | var bb = b.GetAddressBytes();
65 | var result = new byte[ab.Length];
66 |
67 | for ( int i = 0; i < ab.Length; ++i )
68 | {
69 | result[i] = op( ab[i], bb[i] );
70 | }
71 |
72 | return result;
73 | }
74 | public static byte[] And( IPAddress a, IPAddress b )
75 | {
76 | return Combine( a, b, ( ab, bb ) => (byte)( ab & bb ) );
77 | }
78 | public static byte[] Xor( IPAddress a, IPAddress b )
79 | {
80 | return Combine( a, b, ( ab, bb ) => (byte)( ab ^ bb ) );
81 | }
82 | public bool BelongsTo( IPAddress addr )
83 | {
84 | var mysubnet = And( Address, Mask );
85 | var addrsubnet = And( addr, Mask );
86 |
87 | return new BufLen( mysubnet ) == new BufLen( addrsubnet );
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/I2PCore/Utils/Logging/ILogStore.cs:
--------------------------------------------------------------------------------
1 | namespace I2PCore.Utils
2 | {
3 | public interface ILogStore
4 | {
5 | string Name { set; get; }
6 | void Log( string text );
7 | void CheckStoreRotation();
8 | void Close();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/I2PCore/Utils/Logging/StreamLogStore.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Threading;
5 |
6 | namespace I2PCore.Utils
7 | {
8 | public class StreamLogStore : ILogStore
9 | {
10 | protected StreamWriter LogFile { get; private set; } = null;
11 |
12 | public Stream Stream
13 | {
14 | set
15 | {
16 | Close();
17 | LogFile = new StreamWriter( value );
18 | }
19 | }
20 |
21 | public virtual string Name
22 | {
23 | get
24 | {
25 | return null;
26 | }
27 |
28 | set
29 | {
30 | }
31 | }
32 |
33 | public virtual void CheckStoreRotation()
34 | {
35 | }
36 |
37 | public void Close()
38 | {
39 | if ( LogFile != null )
40 | {
41 | LogFile.Close();
42 | LogFile.Dispose();
43 | }
44 | LogFile = null;
45 | }
46 |
47 | public virtual void Log( string text )
48 | {
49 | LogFile.Write( $"{text}\r\n" );
50 | LogFile.Flush();
51 | LogFile.BaseStream.Flush();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/I2PCore/Utils/PeriodicAction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Utils
7 | {
8 | public class PeriodicAction
9 | {
10 | public delegate void PerformAction();
11 |
12 | TickSpan mFrequency;
13 | TickSpan mOriginalFrequency = null;
14 |
15 | public TickSpan Frequency
16 | {
17 | get
18 | {
19 | return mFrequency;
20 | }
21 | set
22 | {
23 | mOriginalFrequency = value;
24 | mFrequency = value;
25 | }
26 | }
27 |
28 | public TickCounter LastAction { get; protected set; }
29 | public TickSpan TimeToAction
30 | {
31 | get => ( LastAction + mFrequency ).DeltaToNow;
32 | set
33 | {
34 | if ( mOriginalFrequency is null )
35 | {
36 | mOriginalFrequency = mFrequency;
37 | }
38 |
39 | LastAction = TickCounter.Now;
40 | mFrequency = value;
41 | }
42 | }
43 |
44 | public bool Autotrigger { get; protected set; }
45 |
46 | public PeriodicAction( TickSpan freq, bool hastimedout = false )
47 | {
48 | mFrequency = freq;
49 | Autotrigger = hastimedout;
50 | LastAction = TickCounter.Now;
51 | }
52 |
53 | public void Reset()
54 | {
55 | LastAction = TickCounter.Now;
56 | }
57 |
58 | public void Start()
59 | {
60 | if ( LastAction == null )
61 | LastAction = new TickCounter();
62 | else
63 | LastAction.SetNow();
64 | }
65 |
66 | public void Stop()
67 | {
68 | LastAction = null;
69 | }
70 |
71 | public void Do( PerformAction action )
72 | {
73 | if ( LastAction == null ) return;
74 |
75 | if ( Autotrigger || LastAction.DeltaToNow > mFrequency )
76 | {
77 | LastAction.SetNow();
78 | Autotrigger = false;
79 | if ( mOriginalFrequency != null )
80 | {
81 | mFrequency = mOriginalFrequency;
82 | mOriginalFrequency = null;
83 | }
84 |
85 | action();
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/I2PCore/Utils/PeriodicLogger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Utils
7 | {
8 | public class PeriodicLogger
9 | {
10 | PeriodicAction LogAction;
11 | readonly Logging.LogLevels LogLevel;
12 |
13 | public PeriodicLogger( int freqsec )
14 | {
15 | LogAction = new PeriodicAction( TickSpan.Seconds( freqsec ) );
16 | LogLevel = Logging.LogLevels.DebugData;
17 | }
18 |
19 | public PeriodicLogger( Logging.LogLevels level, int freqsec )
20 | {
21 | LogLevel = level;
22 | LogAction = new PeriodicAction( TickSpan.Seconds( freqsec ) );
23 | }
24 |
25 | public void Log( Func maker )
26 | {
27 | LogAction.Do( () => Logging.Log( LogLevel, maker() ) );
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/I2PCore/Utils/RefPair.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace I2PCore.Utils
7 | {
8 | public class RefPair
9 | {
10 | public L Left { get; set; }
11 | public R Right { get; set; }
12 |
13 | public RefPair( L l, R r ) { Left = l; Right = r; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/I2PCore/Utils/RunBatchWait.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 |
7 | namespace I2PCore.Utils
8 | {
9 | public class RunBatchWait
10 | {
11 | int InitialCount;
12 | int Counter;
13 | ManualResetEvent Finished;
14 |
15 | public RunBatchWait( int count )
16 | {
17 | InitialCount = count;
18 | Interlocked.Exchange( ref Counter, InitialCount );
19 | Finished = new ManualResetEvent( count == 0 );
20 | }
21 |
22 | public void Reset()
23 | {
24 | Interlocked.Exchange( ref Counter, InitialCount );
25 | Finished.Reset();
26 | }
27 |
28 | public void Set()
29 | {
30 | if ( Interlocked.Decrement( ref Counter ) == 0 )
31 | {
32 | Finished.Set();
33 | }
34 | }
35 |
36 | public bool WaitOne( int waitms )
37 | {
38 | return Finished.WaitOne( waitms );
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/I2PCore/Utils/SuccessRatio.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Threading;
3 |
4 | namespace I2PCore.Utils
5 | {
6 | public class SuccessRatio
7 | {
8 | long SuccessCountField;
9 | long FailureCountField;
10 |
11 | public long SuccessCount { get => Interlocked.Read( ref SuccessCountField ); }
12 | public long FailureCount { get => Interlocked.Read( ref FailureCountField ); }
13 |
14 | public long Success( bool succ ) => succ ? Success() : Failure();
15 | public long Success() => Interlocked.Increment( ref SuccessCountField );
16 |
17 | public long Failure() => Interlocked.Increment( ref FailureCountField );
18 |
19 | public double Ratio { get => (double)SuccessCountField / FailureCountField; }
20 | public double Percent { get => ( 100.0 * SuccessCountField ) / ( SuccessCountField + FailureCountField ); }
21 |
22 | public override string ToString()
23 | {
24 | return $"Succ: {SuccessCountField}, Fail: {FailureCountField}, Ratio: {Ratio:F2}, {Percent:F2}%";
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/I2PCore/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/LICENCE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Peter Zander
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # i2p-cs
2 |
3 | See https://github.com/PeterZander/i2p-cs/wiki
4 |
--------------------------------------------------------------------------------
/Samples/I2PDemo/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Samples/I2PDemo/I2PDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net5.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Samples/I2PDemo/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/I2PEchoClient/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Samples/I2PEchoClient/I2PEchoClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net5.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Samples/I2PEchoClient/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/I2PEchoServer/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Samples/I2PEchoServer/I2PEchoServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net5.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Samples/I2PEchoServer/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/I2PRouter/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Samples/I2PRouter/I2PRouter.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net5.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------