├── .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 | 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 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 | --------------------------------------------------------------------------------