/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package remotep2p;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
*
* @author jasamer
*/
@ServerEndpoint("/connection/request/{sourcePeer}/{targetPeer}")
public class ConnectionRequestEndpoint {
/// Logger to write to server logs.
private static final Logger LOGGER = Logger.getLogger(DiscoveryEndpoint.class.getName());
private Session acceptingSession;
private Session requestingSession;
public Session getRequestingSession() {
return this.requestingSession;
}
public void setAcceptingSession(Session session) {
this.acceptingSession = session;
}
/**
* Called when a new RemotePeer opens a connection to the server
* @param session WebSocket session of the RemotePeer
* @param conf Contains all the information needed during the handshake process.
* @param sourcePeer
* @param targetPeer
* @throws java.io.IOException
*/
@OnOpen
public void onOpen(Session session, EndpointConfig conf, @PathParam("sourcePeer") String sourcePeer, @PathParam("targetPeer") String targetPeer) throws IOException {
LOGGER.log(Level.INFO, "onOpen called on data connection {0}", conf);
this.requestingSession = session;
ConnectionManager
.getInstance()
.requestConnection(
UUID.fromString(sourcePeer),
UUID.fromString(targetPeer),
this
);
}
@OnMessage
public void binaryMessage(byte[] data, Session session) throws IOException {
if (this.acceptingSession == null) {
LOGGER.log(Level.WARNING, "Could not send data, the accepting Session was not set yet.");
}
this.acceptingSession
.getBasicRemote()
.sendBinary(
ByteBuffer
.wrap(data)
.order(ByteOrder.LITTLE_ENDIAN)
);
}
/**
* Called when a RemotePeer closes the connection to the server.
* Informs other RemotePeers about the peer loss.
* @param session WebSocket session of the RemotePeer
* @param closeReason Reason why a web socket has been closed.
*/
@OnClose
public void onClose(Session session, CloseReason closeReason) {
LOGGER.log(Level.INFO, "Data connection closed {0}", closeReason);
try {
this.acceptingSession.close(closeReason);
} catch (IOException ex) {
Logger.getLogger(ConnectionAcceptEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}
@OnError
public void onError(Session session, Throwable t) {
LOGGER.log(Level.WARNING, "Error occured {0}", t);
try {
this.acceptingSession
.close(
new CloseReason(
CloseReason.CloseCodes.CLOSED_ABNORMALLY,
"An exception occured: "+t.toString()
)
);
} catch (IOException ex) {
Logger.getLogger(ConnectionAcceptEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}
ByteBuffer getConnectionConfirmationPacketData() {
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putInt(1);
byteBuffer.rewind();
return byteBuffer;
}
void confirmAccepted() {
this.requestingSession.getAsyncRemote().sendBinary(getConnectionConfirmationPacketData());
}
}