Browse Source

Fix cross-namespace broadcast happens on single ns

Given mutable nature of Packet object and a fact that single Packet
instance is created in BroadcastOperations before sending it all
clients, when event is emitted to room where clients with different
namespaces are joined, then all of them will receive that event on
single namespace.

By using withNs method, Packet copy will be created, effectively, solving
the issue
master
Volodymyr Masliy 6 years ago
parent
commit
75d08d405d
  1. 22
      src/main/java/com/corundumstudio/socketio/protocol/Packet.java
  2. 4
      src/main/java/com/corundumstudio/socketio/transport/NamespaceClient.java
  3. 61
      src/test/java/com/corundumstudio/socketio/protocol/PacketTest.java

22
src/main/java/com/corundumstudio/socketio/protocol/Packet.java

@ -77,6 +77,28 @@ public class Packet implements Serializable {
return (T)data;
}
/**
* Creates a copy of #{@link Packet} with new namespace set
* if it differs from current namespace.
* Otherwise, returns original object unchanged
*/
public Packet withNsp(String namespace) {
if (this.nsp.equalsIgnoreCase(namespace)) {
return this;
} else {
Packet newPacket = new Packet(this.type);
newPacket.setAckId(this.ackId);
newPacket.setData(this.data);
newPacket.setDataSource(this.dataSource);
newPacket.setName(this.name);
newPacket.setSubType(this.subType);
newPacket.setNsp(namespace);
newPacket.attachments = this.attachments;
newPacket.attachmentsCount = this.attachmentsCount;
return newPacket;
}
}
public void setNsp(String endpoint) {
this.nsp = endpoint;
}

4
src/main/java/com/corundumstudio/socketio/transport/NamespaceClient.java

@ -104,8 +104,8 @@ public class NamespaceClient implements SocketIOClient {
if (!isConnected()) {
return;
}
packet.setNsp(namespace.getName());
baseClient.send(packet);
baseClient.send(packet.withNsp(namespace.getName()));
}
public void onDisconnect() {

61
src/test/java/com/corundumstudio/socketio/protocol/PacketTest.java

@ -0,0 +1,61 @@
package com.corundumstudio.socketio.protocol;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import io.netty.buffer.Unpooled;
import org.junit.Test;
public class PacketTest {
@Test
public void packetCopyIsCreatedWhenNamespaceDiffers() {
Packet oldPacket = createPacket();
String newNs = "new";
Packet newPacket = oldPacket.withNsp(newNs);
assertEquals(newNs, newPacket.getNsp());
assertPacketCopied(oldPacket, newPacket);
}
@Test
public void packetCopyIsCreatedWhenNewNamespaceDiffersAndIsNull() {
Packet packet = createPacket();
Packet newPacket = packet.withNsp(null);
assertNull(newPacket.getNsp());
assertPacketCopied(packet, newPacket);
}
@Test
public void originalPacketReturnedIfNamespaceIsTheSame() {
Packet packet = new Packet(PacketType.MESSAGE);
assertSame(packet, packet.withNsp(""));
}
private void assertPacketCopied(Packet oldPacket, Packet newPacket) {
assertNotSame(newPacket, oldPacket);
assertEquals(oldPacket.getName(), newPacket.getName());
assertEquals(oldPacket.getType(), newPacket.getType());
assertEquals(oldPacket.getSubType(), newPacket.getSubType());
assertEquals(oldPacket.getAckId(), newPacket.getAckId());
assertEquals(oldPacket.getAttachments().size(), newPacket.getAttachments().size());
assertSame(oldPacket.getAttachments(), newPacket.getAttachments());
assertEquals(oldPacket.getData(), newPacket.getData());
assertSame(oldPacket.getDataSource(), newPacket.getDataSource());
}
private Packet createPacket() {
Packet packet = new Packet(PacketType.MESSAGE);
packet.setSubType(PacketType.EVENT);
packet.setName("packetName");
packet.setData("data");
packet.setAckId(1L);
packet.setNsp("old");
packet.setDataSource(Unpooled.wrappedBuffer(new byte[]{10}));
packet.initAttachments(1);
packet.addAttachment(Unpooled.wrappedBuffer(new byte[]{20}));
return packet;
}
}
Loading…
Cancel
Save