Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with Peer Locking Mechanism – Incorrect Disconnect Behavior When Third Peer Attempts to Connect #466

Open
1 task done
techteamyooli opened this issue Dec 6, 2024 · 0 comments

Comments

@techteamyooli
Copy link

Please, check for existing issues to avoid duplicates.

  • No similar issues found.

What happened?

I am implementing a peer-locking mechanism, aiming to prevent a third peer (p3) from communicating with peers p1 and p2 if they are already paired. However, when p3 attempts to connect to p1, who is already locked with p2, p1 is unexpectedly disconnected, and the connection behavior does not align with the intended functionality.

Code -

import { Injectable, Logger } from '@nestjs/common';
import { NestExpressApplication } from '@nestjs/platform-express';
import { ExpressPeerServer, PeerServerEvents, IClient, IMessage } from 'peer';

@Injectable()
export class ChannelService {
  private readonly logger = new Logger(ChannelService.name);
  private readonly lockedPeers = new Map<string, string>();

  public enablePeerServer(app: NestExpressApplication) {
    const peerServer = ExpressPeerServer(app.getHttpServer(), {
      path: '/channel',
      allow_discovery: true,
    });

    (peerServer as PeerServerEvents)
      .on('connection', (client: IClient) => {
        const peerId = client.getId();
        this.logger.log(`Client connected: ${peerId}`);
      })
      .on('message', (client: IClient, message: IMessage) => {
        const sourcePeerId = message.src;
        const targetPeerId = message.dst;

        if (sourcePeerId && targetPeerId) {
          if (
            this.isPeerLocked(sourcePeerId) ||
            this.isPeerLocked(targetPeerId)
          ) {
            this.logger.log(
              `Message from ${sourcePeerId} to ${targetPeerId} denied. One of the peers is already in a pair: ${message.type}`,
            );
            return client.send({
              type: 'ERROR',
              payload: 'One of the peers is locked in a pair.',
            });
          } else {
            if (message.type === 'ANSWER') {
              this.lockedPeers.set(sourcePeerId, targetPeerId);
              this.lockedPeers.set(targetPeerId, sourcePeerId);
              this.logger.log(
                `Pair ${sourcePeerId} and ${targetPeerId} locked after ANSWER.`,
              );
            }
          }
        } else {
          this.logger.log(`Message from ${sourcePeerId}: ${message.type}`);
        }

        if (message.type === 'LEAVE') {
          if (this.lockedPeers.delete(sourcePeerId)) {
            this.lockedPeers.delete(this.lockedPeers.get(sourcePeerId)!);
            this.logger.log(
              `Pair containing ${sourcePeerId} released after LEAVE.`,
            );
          }
        }
      })
      .on('disconnect', (client: IClient) => {
        const peerId = client.getId();
        this.lockedPeers.forEach((value, key) => {
          if (key === peerId || value === peerId) {
            this.lockedPeers.delete(key);
            this.logger.log(`Pair involving ${peerId} released on disconnect.`);
          }
        });
        this.logger.log(`Client disconnected: ${peerId}`);
      })
      .on('error', (error: Error) => {
        this.logger.error('PeerServer error:', error);
      });

    app.use(peerServer);
  }

  private isPeerLocked(peerId: string): boolean {
    return (
      Array.from(this.lockedPeers.keys()).includes(peerId) ||
      Array.from(this.lockedPeers.values()).includes(peerId)
    );
  }
}

Additional Context:
The disconnect event is being triggered when p3 attempts to connect to a peer already in an established pair, leading to p1’s disconnection. This issue might stem from the message with type error being returned. But I need it to throw an error when an individual peer tries to connect to paired peers.

How can we reproduce the issue?

  1. Start the peer server with the provided code, where the peer-locking mechanism is implemented.
  2. Connect three peer clients: p1, p2, and p3.
  3. Establish a connection between p1 and p2 (pair lock) and exchange a message (ANSWER).
  4. While p1 and p2 are connected, attempt to establish a connection from p3 to either p1 or p2.
  5. Observe p1 client as it loses connection and the logs, which show p1 being disconnected when p3 tries to connect.

What do you expected to happen?

Expected Behavior:
When p3 attempts to connect to either p1 or p2, p1 and p2 should remain connected, and p3 should not be able to establish a connection with either of them.

Actual Behavior:
When p3 attempts to connect to p1, the logs indicate that p1 is disconnected, despite the intention being to prevent communication between p3 and the locked peers, without disconnecting anyone.

Environment setup

  • OS: Zorin OS 12
  • Platform: Nodejs 20
  • Browser: Microsoft Edge v131.0.2903

Is this a regression?

No response

Anything else?

Logs:

3296 6/12/2024, 7:30:29 pm     LOG [NestFactory] Starting Nest application... +0ms  
3296 6/12/2024, 7:30:29 pm     LOG [InstanceLoader] ChannelModule dependencies initialized +12ms  
3296 6/12/2024, 7:30:29 pm     LOG [InstanceLoader] AppModule dependencies initialized +1ms  
3296 6/12/2024, 7:30:29 pm     LOG [RoutesResolver] AppController {/communication/api}: +9ms  
3296 6/12/2024, 7:30:29 pm     LOG [RouterExplorer] Mapped {/communication/api/status, GET} route +2ms  
3296 6/12/2024, 7:30:29 pm     LOG [NestApplication] Nest application successfully started +3ms  
3296 6/12/2024, 7:31:14 pm     LOG [ChannelService] Client connected: one_s864go37r8c +44s  
3296 6/12/2024, 7:31:14 pm     LOG [ChannelService] Client connected: two_h4ox542979a +600ms  
3296 6/12/2024, 7:31:16 pm     LOG [ChannelService] Client connected: two_v4flzxtxh7a +1s  
3296 6/12/2024, 7:31:19 pm     LOG [ChannelService] Message from one_s864go37r8c: HEARTBEAT +3s  
3296 6/12/2024, 7:31:19 pm     LOG [ChannelService] Message from two_h4ox542979a: HEARTBEAT +600ms  
3296 6/12/2024, 7:31:21 pm     LOG [ChannelService] Message from two_v4flzxtxh7a: HEARTBEAT +1s  
3296 6/12/2024, 7:31:24 pm     LOG [ChannelService] Pair one_s864go37r8c and two_h4ox542979a locked after ANSWER. +150ms  
3296 6/12/2024, 7:31:24 pm     LOG [ChannelService] Message from one_s864go37r8c to two_h4ox542979a denied. One of the peers is already in a pair: CANDIDATE +3ms  
3296 6/12/2024, 7:31:24 pm     LOG [ChannelService] Message from one_s864go37r8c to two_h4ox542979a denied. One of the peers is already in a pair: CANDIDATE +1ms  
3296 6/12/2024, 7:31:24 pm     LOG [ChannelService] Pair involving one_s864go37r8c released on disconnect. +4ms  
3296 6/12/2024, 7:31:24 pm     LOG [ChannelService] Client disconnected: one_s864go37r8c +0ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant