diff --git a/app/src/main/java/io/xeres/app/xrs/service/turtle/TurtleRsService.java b/app/src/main/java/io/xeres/app/xrs/service/turtle/TurtleRsService.java index 3822e7e39..78ab0911d 100644 --- a/app/src/main/java/io/xeres/app/xrs/service/turtle/TurtleRsService.java +++ b/app/src/main/java/io/xeres/app/xrs/service/turtle/TurtleRsService.java @@ -64,13 +64,15 @@ public class TurtleRsService extends RsService implements RsServiceMaster turtleClients = new ArrayList<>(); - private final IdentityGroupItem ownIdentity; + private final IdentityRsService identityRsService; + + private IdentityGroupItem ownIdentity; protected TurtleRsService(RsServiceRegistry rsServiceRegistry, PeerConnectionManager peerConnectionManager, IdentityRsService identityRsService) { super(rsServiceRegistry); this.peerConnectionManager = peerConnectionManager; - ownIdentity = identityRsService.getOwnIdentity(); + this.identityRsService = identityRsService; } @Override @@ -85,6 +87,12 @@ public void addRsSlave(TurtleRsClient client) turtleClients.add(client); } + @Override + public void initialize() + { + ownIdentity = identityRsService.getOwnIdentity(); + } + @Override public void handleItem(PeerConnection sender, Item item) { @@ -135,8 +143,9 @@ private void handleTunnelRequest(PeerConnection sender, TurtleTunnelRequestItem if (client.isPresent()) { - var resultItem = new TurtleTunnelResultItem(item.getRequestId(), generateTunnelId(item, false)); - + var resultItem = new TurtleTunnelResultItem(item.getRequestId(), generateTunnelId(item, tunnelProbability.getBias(), false)); + peerConnectionManager.writeItem(sender, resultItem, this); + // XXX: store the opened tunnel somewhere! also we added a distant peer, etc... return; } @@ -152,24 +161,23 @@ private void handleTunnelRequest(PeerConnection sender, TurtleTunnelRequestItem } } - private int generateTunnelId(TurtleTunnelRequestItem item, boolean symetrical) + int generateTunnelId(TurtleTunnelRequestItem item, int bias, boolean symetrical) { - // XXX: test this, compare with RS var buf = item.getFileHash().toString() + ownIdentity.getGxsId().toString(); - int result = tunnelProbability.getBias(); + int result = bias; int decal = 0; for (int i = 0; i < buf.length(); i++) { - result += 7 * buf.charAt(i) + decal; + result += (int) (7 * buf.charAt(i) + Integer.toUnsignedLong(decal)); if (symetrical) { - decal = decal * 44497 + 15641 + (result % 86243); + decal = (int) (Integer.toUnsignedLong(decal) * 44497 + 15641 + (Integer.toUnsignedLong(result) % 86243)); } else { - decal = decal * 86243 + 15649 + (result % 44497); + decal = (int) (Integer.toUnsignedLong(decal) * 86243 + 15649 + (Integer.toUnsignedLong(result) % 44497)); } } return item.getPartialTunnelId() ^ result; diff --git a/app/src/test/java/io/xeres/app/xrs/service/turtle/TurtleRsServiceTest.java b/app/src/test/java/io/xeres/app/xrs/service/turtle/TurtleRsServiceTest.java new file mode 100644 index 000000000..5351e9073 --- /dev/null +++ b/app/src/test/java/io/xeres/app/xrs/service/turtle/TurtleRsServiceTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 by David Gerber - https://zapek.com + * + * This file is part of Xeres. + * + * Xeres is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Xeres is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Xeres. If not, see . + */ + +package io.xeres.app.xrs.service.turtle; + +import io.xeres.app.database.model.gxs.IdentityGroupItemFakes; +import io.xeres.app.xrs.service.identity.IdentityRsService; +import io.xeres.app.xrs.service.turtle.item.TurtleTunnelRequestItem; +import io.xeres.common.id.Id; +import io.xeres.common.id.Sha1Sum; +import io.xeres.testutils.IdFakes; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(SpringExtension.class) +class TurtleRsServiceTest +{ + @Mock + private IdentityRsService identityRsService; + + @InjectMocks + private TurtleRsService turtleRsService; + + @Test + void TurtleRsService_GenerateTunnelId_OK() + { + // Values have been taken directly from Retroshare to make sure there's no signed/unsigned bugs + var ownIdentity = IdentityGroupItemFakes.createIdentityGroupItem(IdFakes.createGxsId(Id.toBytes("d3b9c7ceb75c7c68b5e3c6446259c8e7")), "Test"); + + when(identityRsService.getOwnIdentity()).thenReturn(ownIdentity); + turtleRsService.initialize(); + + var item = mock(TurtleTunnelRequestItem.class); + when(item.getFileHash()).thenReturn(new Sha1Sum(Id.toBytes("ac39b8f761465b1460948973e8fe754f4e101700"))); + var result = turtleRsService.generateTunnelId(item, 1_833_303_450, true); + + assertEquals(3_280_770_886L, Integer.toUnsignedLong(result)); + } +} \ No newline at end of file diff --git a/common/src/testFixtures/java/io/xeres/testutils/IdFakes.java b/common/src/testFixtures/java/io/xeres/testutils/IdFakes.java index b880fb42e..3d943babe 100644 --- a/common/src/testFixtures/java/io/xeres/testutils/IdFakes.java +++ b/common/src/testFixtures/java/io/xeres/testutils/IdFakes.java @@ -35,6 +35,11 @@ public static GxsId createGxsId() return new GxsId(RandomUtils.nextBytes(GxsId.LENGTH)); } + public static GxsId createGxsId(byte[] gxsId) + { + return new GxsId(gxsId); + } + public static MessageId createMessageId() { return new MessageId(RandomUtils.nextBytes(MessageId.LENGTH));