Network/ignored_for_now/discovery/server/BroadcastServer.java

156 lines
5.2 KiB
Java

/*
* Copyright 2018 dorkbox, llc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.network.other.discovery.server;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import dorkbox.network.Server;
import dorkbox.network.connection.EndPoint;
import dorkbox.network.other.discovery.MagicBytes;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.socket.DatagramPacket;
/**
* Manages the response to broadcast events
*/
public
class BroadcastServer {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Server.class.getSimpleName());
private final int tcpPort;
private final int udpPort;
private final int bufferSize;
public
BroadcastServer() {
this.bufferSize = 0;
this.tcpPort = 0;
this.udpPort = 0;
}
public
BroadcastServer(final int tcpPort, final int udpPort) {
this.tcpPort = tcpPort;
this.udpPort = udpPort;
// either it will be TCP or UDP, or BOTH
if (tcpPort > 0 ^ udpPort > 0) {
// TCP or UDP
// ID + TCP or UDP ID + TCP or UDP port
bufferSize = 4;
}
else {
// BOTH
// ID + TCP and UDP ID + TCP and UDP port
bufferSize = 6;
}
}
/**
* @return true if the broadcast was responded to, false if it was not a broadcast (and there was no response)
*/
public boolean isDiscoveryRequest(final Channel channel, ByteBuf byteBuf, final InetSocketAddress localAddress, InetSocketAddress remoteAddress) {
if (byteBuf.readableBytes() == 1) {
// this is a BROADCAST discovery event. Don't read the byte unless it is...
if (byteBuf.getByte(0) == MagicBytes.broadcastID) {
byteBuf.readByte(); // read the byte to consume it (now that we verified it is a broadcast byte)
// absolutely MUST send packet > 0 across, otherwise netty will think it failed to write to the socket, and keep trying.
// (this bug was fixed by netty, however we are keeping this code)
ByteBuf directBuffer = channel.alloc()
.ioBuffer(bufferSize);
directBuffer.writeByte(MagicBytes.broadcastResponseID);
// now output the port information for TCP/UDP so the broadcast client knows which port to connect to
// either it will be TCP or UDP, or BOTH
int enabledFlag = 0;
if (tcpPort > 0) {
enabledFlag |= MagicBytes.HAS_TCP;
}
if (udpPort > 0) {
enabledFlag |= MagicBytes.HAS_UDP;
}
directBuffer.writeByte(enabledFlag);
// TCP is always first
if (tcpPort > 0) {
directBuffer.writeShort(tcpPort);
}
if (udpPort > 0) {
directBuffer.writeShort(udpPort);
}
channel.writeAndFlush(new DatagramPacket(directBuffer, remoteAddress, localAddress));
logger.info("Responded to host discovery from [{}]", EndPoint.Companion.getHostDetails(remoteAddress));
byteBuf.release();
return true;
}
}
return false;
}
/**
* @return true if this is a broadcast response, false if it was not a broadcast response
*/
public static
boolean isDiscoveryResponse(ByteBuf byteBuf, final InetAddress remoteAddress, final Channel channel) {
if (byteBuf.readableBytes() <= MagicBytes.maxPacketSize) {
// this is a BROADCAST discovery RESPONSE event. Don't read the byte unless it is...
if (byteBuf.getByte(0) == MagicBytes.broadcastResponseID) {
byteBuf.readByte(); // read the byte to consume it (now that we verified it is a broadcast byte)
// either it will be TCP or UDP, or BOTH
int typeID = byteBuf.readByte();
int tcpPort = 0;
int udpPort = 0;
// TCP is always first
if ((typeID & MagicBytes.HAS_TCP) == MagicBytes.HAS_TCP) {
tcpPort = byteBuf.readUnsignedShort();
}
if ((typeID & MagicBytes.HAS_UDP) == MagicBytes.HAS_UDP) {
udpPort = byteBuf.readUnsignedShort();
}
channel.attr(ClientDiscoverHostHandler.STATE)
.set(new BroadcastResponse(remoteAddress, tcpPort, udpPort));
byteBuf.release();
return true;
}
}
return false;
}
}