@Override public void run() { try { ClientConnection cc = null; while (true) { // Accept client connections Socket socket = serverSocket.accept(); // Clean up old connection if (oldSocket != null) { try { oldSocket.close(); } catch (IOException e) { // Ignore } } if (cc != null) { // Close old worker cc.close(); } oldSocket = socket; cc = new ClientConnection(handler, privateKey, socket); cc.start(); } } catch (Exception e) { e.printStackTrace(); } gui.exit(); }
/** * Process a touch point birth by getting the groupID and gestures for the touch point. NULL * touchpoint means we have a driver failure * * @param touchPoint The new touch point. * @return whether a client has claimed this touchPoint as its own. */ private boolean processBirth(TouchPoint touchPoint) { List<ClientConnection> clients_to_remove = null; boolean isClaimed = false; for (int i = 0; i < main._clients.size(); i++) { ClientConnection client = main._clients.get(i); // Return if the client claims the touch point try { if (touchPoint == null) client.processError(EventType.DRIVER_NONE); else isClaimed = client.processBirth(touchPoint); if (isClaimed) break; } catch (IOException e) { // This occurs if there is a communication error // with the client. In this case, we will want // to remove the client. if (clients_to_remove == null) clients_to_remove = new ArrayList<ClientConnection>(); clients_to_remove.add(client); } } if (clients_to_remove != null) for (int i = 0; i < clients_to_remove.size(); i++) { main._clients.remove(clients_to_remove.get(i)); Logger.info("[GestureServer] Client Disconnected"); } return isClaimed; }
private synchronized void connect() { if (!connecting) { // We defer actual connection until the first part of body is written or end is called // This gives the user an opportunity to set an exception handler before connecting so // they can capture any exceptions on connection client.getConnection( port, host, conn -> { synchronized (this) { if (exceptionOccurred) { // The request already timed out before it has left the pool waiter queue // So return it conn.close(); } else if (!conn.isClosed()) { connected(conn); } else { // The connection has been closed - closed connections can be in the pool // Get another connection - Note that we DO NOT call connectionClosed() on the pool // at this point // that is done asynchronously in the connection closeHandler() connect(); } } }, exceptionHandler, vertx.getOrCreateContext()); connecting = true; } }
private void connected(ClientConnection conn) { checkThread(); conn.setCurrentRequest(this); this.conn = conn; // If anything was written or the request ended before we got the connection, then // we need to write it now if (pendingMaxSize != -1) { conn.setWriteQueueMaxSize(pendingMaxSize); } if (pendingChunks != null || writeHead || completed) { writeHead(); headWritten = true; } if (pendingChunks != null) { for (PendingChunk chunk : pendingChunks) { sendChunk(chunk.chunk, chunk.doneHandler); } } if (completed) { if (chunked) { writeEndChunk(); } conn.endRequest(); } }
private void sendChunk(ChannelBuffer buff, Handler<Void> doneHandler) { Object write = chunked ? new DefaultHttpChunk(buff) : buff; ChannelFuture writeFuture = conn.write(write); if (doneHandler != null) { conn.addFuture(doneHandler, writeFuture); } }
// This method is called when a request has been made to close a client connection public synchronized void disconnectClient(ClientConnection clientConnection) { // Ensures this connection exists (a necessary check when this is being called from outside of a // clientConnection) if (clientConnection != null && clientConnection.isConnected() && clientSocketList.get(clientSocketList.indexOf(clientConnection)) != null) { // Send the client a message telling it to close its socket clientConnection.xmitMessage(ClientConnection.QUIT); // Then close that socket...the user really doesn't have a choice. We're just asking to be // nice. clientSocketList.get(clientSocketList.indexOf(clientConnection)).closeSocket(); parent.updateStatusBox( clientSocketList.indexOf(clientConnection) + " " + "Forcing disconnection of client " + clientConnection.id + " on port " + port + "..."); } else { // If this thread is NOT connected, it may be stuck, so let's send an interrupt to wake it up clientThreadList.get(clientSocketList.indexOf(clientConnection)).interrupt(); parent.updateStatusBox("Closing listen socket on port " + port + "..."); } }
/** @return String with all connected users. */ public String getConnectedUsernamesMessage() { String s = Messages.CONNECTED_USERS; for (ClientConnection client : clients) { s += " " + client.getUsername(); } return s; }
@Override public void clientDisconnected(String userId, String clientId) { ClientConnection connection = getConnectionByClientId(userId, clientId); _connectionsByClientId.remove(clientId); _changeManager.removeChangeListener(connection); _masterChangeManager.removeChangeListener(connection); _longPollingConnectionManager.disconnect(clientId); connection.disconnect(); }
private void writeHeadWithContent(ByteBuf buf, boolean end) { prepareHeaders(); if (end) { conn.writeToChannel(new AssembledFullHttpRequest(request, buf)); } else { conn.writeToChannel(new AssembledHttpRequest(request, buf)); } headWritten = true; }
// THIS IS WHERE THE MAGIC HAPPENS -- on the server side at least // This method sends some given message to ALL connected clients by creating an iterator from // clientSocketList // and executing the xmitMessage method for each element in that iterator public synchronized void broadcastMsg(String message) { Iterator<ClientConnection> clientIterator = clientSocketList.iterator(); ClientConnection clientConnection; while (clientIterator.hasNext()) { clientConnection = clientIterator.next(); clientConnection.xmitMessage(message); } }
/** * @param socket * @throws IOException */ private void acceptClientConnection(Socket socket) throws IOException { Logger.info("[GestureServer] Client connection accepted"); ClientConnection cc = new ClientConnection(socket); main._clients.add(cc); if (main.ic == null) { cc.processError(EventType.DRIVER_NONE); } else { main.myState |= JmolGestureServerInterface.HAS_CLIENT; } }
@Override public void close() { checkClosed(); pool.close(); for (ClientConnection conn : connectionMap.values()) { conn.close(); } actualCtx.removeCloseHook(closeHook); closed = true; }
private void write(ByteBuf buff, boolean end) { int readableBytes = buff.readableBytes(); if (readableBytes == 0 && !end) { // nothing to write to the connection just return return; } if (end) { completed = true; } if (!end && !chunked && !contentLengthSet()) { throw new IllegalStateException( "You must set the Content-Length header to be the total size of the message " + "body BEFORE sending any data if you are not using HTTP chunked encoding."); } written += buff.readableBytes(); if (conn == null) { if (pendingChunks == null) { pendingChunks = buff; } else { CompositeByteBuf pending; if (pendingChunks instanceof CompositeByteBuf) { pending = (CompositeByteBuf) pendingChunks; } else { pending = Unpooled.compositeBuffer(); pending.addComponent(pendingChunks).writerIndex(pendingChunks.writerIndex()); pendingChunks = pending; } pending.addComponent(buff).writerIndex(pending.writerIndex() + buff.writerIndex()); } connect(); } else { if (!headWritten) { writeHeadWithContent(buff, end); } else { if (end) { if (buff.isReadable()) { conn.writeToChannel(new DefaultLastHttpContent(buff, false)); } else { conn.writeToChannel(LastHttpContent.EMPTY_LAST_CONTENT); } } else { conn.writeToChannel(new DefaultHttpContent(buff)); } } if (end) { conn.reportBytesWritten(written); if (respHandler != null) { conn.endRequest(); } } } }
@Override public HttpClientRequest drainHandler(Handler<Void> handler) { synchronized (getLock()) { checkComplete(); this.drainHandler = handler; if (conn != null) { conn.getContext().runOnContext(v -> conn.handleInterestedOpsChanged()); } return this; } }
/** * Returns the {@link ClientConnection} that owns a viewport. * * @param userId The ID of the user who owns the connection * @param viewportId The ID of the viewport * @return The connection * @throws DataNotFoundException If there is no viewport with the specified ID, the connection * doesn't own viewport, the user ID is invalid or if the client connection isn't owned by the * specified user. */ private ClientConnection getConnectionByViewportId(String userId, String viewportId) { ClientConnection connection = _connectionsByViewportId.get(viewportId); if (connection == null) { throw new DataNotFoundException("Unknown viewport ID: " + viewportId); } if (!Objects.equal(userId, connection.getUserId())) { throw new DataNotFoundException( "User ID " + userId + " is not associated with viewport " + viewportId); } return connection; }
private void doResume() { if (hasPausedEnd) { if (pausedChunk != null) { final Buffer theChunk = pausedChunk; conn.getContext().runOnContext(v -> handleChunk(theChunk)); pausedChunk = null; } final LastHttpContent theTrailer = pausedTrailer; conn.getContext().runOnContext(v -> handleEnd(theTrailer)); hasPausedEnd = false; pausedTrailer = null; } }
/** * Returns the {@link ClientConnection} corresponding to a client ID. * * @param userId The ID of the user who owns the connection * @param clientId The client ID * @return The connection * @throws DataNotFoundException If there is no connection for the specified ID, the user ID is * invalid or if the client and user IDs don't correspond */ private ClientConnection getConnectionByClientId(String userId, String clientId) { // TODO user logins // ArgumentChecker.notEmpty(userId, "userId"); ArgumentChecker.notEmpty(clientId, "clientId"); ClientConnection connection = _connectionsByClientId.get(clientId); if (connection == null) { throw new DataNotFoundException("Unknown client ID: " + clientId); } if (!Objects.equal(userId, connection.getUserId())) { throw new DataNotFoundException( "User ID " + userId + " is not associated with client ID " + clientId); } return connection; }
@Override protected void doMessageReceived(ClientConnection conn, ChannelHandlerContext ctx, Object msg) { if (conn == null || conn.isClosed()) { return; } boolean valid = false; if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; conn.handleResponse(response); valid = true; } if (msg instanceof HttpContent) { HttpContent chunk = (HttpContent) msg; if (chunk.content().isReadable()) { Buffer buff = new Buffer(chunk.content().slice()); conn.handleResponseChunk(buff); } if (chunk instanceof LastHttpContent) { conn.handleResponseEnd((LastHttpContent) chunk); } valid = true; } else if (msg instanceof WebSocketFrame) { WebSocketFrame frame = (WebSocketFrame) msg; switch (frame.getType()) { case BINARY: case TEXT: conn.handleWsFrame(frame); break; case PING: // Echo back the content of the PING frame as PONG frame as specified in RFC 6455 // Section 5.5.2 ctx.writeAndFlush( new DefaultWebSocketFrame(WebSocketFrame.FrameType.PONG, frame.getBinaryData())); break; case CLOSE: if (!closeFrameSent) { // Echo back close frame and close the connection once it was written. // This is specified in the WebSockets RFC 6455 Section 5.4.1 ctx.writeAndFlush(frame).addListener(ChannelFutureListener.CLOSE); closeFrameSent = true; } break; } valid = true; } if (!valid) { throw new IllegalStateException("Invalid object " + msg); } }
private void processMessage(ClientConnection clientConnection, String message) { clientConnection.lastMessagetime = System.currentTimeMillis(); if (message.equals("ping")) { return; } if (message.equals("disconnect")) { clientConnection.alive = false; return; } if (message.startsWith("createGame ")) { distribution.createGame(clientConnection.connectionId, message); return; } distribution.messageFromClient(clientConnection.connectionId, message); }
@Override public boolean writeQueueFull() { synchronized (getLock()) { checkComplete(); return conn != null && conn.isNotWritable(); } }
public void perform() { while (isRunning) { while (dataStack.size() > 0) { DataPackage dataPackage = dataStack.elementAt(0); dataStack.removeElementAt(0); try { byte[] data = dataPackage.getAllData(); // log.info("Send data len: " + data.length); os.writeInt(data.length); os.write(data); os.flush(); lastTimeSend = System.currentTimeMillis(); } catch (IOException e) { log.warn( "ERROR: WriterThread: IOException when try to write data which has header: " + dataPackage.getHeader()); client.detroy(); return; } catch (Throwable ex) { log.warn("ERROR: WriterThread : faltal exception:", ex); } } try { sleep(20); } catch (InterruptedException e) { } } }
/** * Updates a contact in SQL and refreshes the table with the new information. * * @param contact The changed contact * @param selectedRow The contacts row in the table */ public void updateContact(IContact contact, int selectedRow) { commandObject = new CommandObject("update contact", contact); serverConnection.sendCommand(commandObject); contacts.set(selectedRow, contact); contacts.get(selectedRow).incrementVersion(); }
/** * Deletes a contact in SQL and sets new tableData. * * @param contact Contact to be deleted. */ public void deleteContact(int selectedRow) { IContact contact = getContact(selectedRow); commandObject = new CommandObject("delete contact", contact); serverConnection.sendCommand(commandObject); contacts.remove(selectedRow); refreshGUI(); }
/** * Creates a new contact in SQL and in the locally stored list, the updates the table. * * @param contact The new contact */ public void newContact(Contact contact) { commandObject = new CommandObject("new contact", contact); int id = (Integer) serverConnection.sendAndGet(commandObject); contact.setId(id); contacts.add(contact); refreshGUI(); }
@Override public void createViewport( String userId, String clientId, ViewportDefinition viewportDefinition, String viewportId, String dataUrl, String gridStructureUrl) { if (clientId == null) { _viewportFactory.createViewport(viewportId, viewportDefinition); } else { ClientConnection connection = getConnectionByClientId(userId, clientId); connection.createViewport(viewportDefinition, viewportId, dataUrl, gridStructureUrl); _connectionsByViewportId.put(viewportId, connection); } }
void returnConnection(final ClientConnection conn) { if (!conn.keepAlive) { // Close it conn.internalClose(); } else { pool.returnConnection(conn); } }
/** * If the amount of data that is currently queued is greater than the write queue max size see * {@link #setWriteQueueMaxSize(int)} then the request queue is considered full. * * <p>Data can still be written to the request even if the write queue is deemed full, however it * should be used as indicator to stop writing and push back on the source of the data, otherwise * you risk running out of available RAM. * * <p>This method is used by the {@link org.vertx.java.core.streams.Pump} class to pump data * between different streams and perform flow control. * * @return {@code true} if the write queue is full, {@code false} otherwise */ public boolean writeQueueFull() { check(); if (conn != null) { return conn.writeQueueFull(); } else { return false; } }
/** * Data is queued until it is actually sent. To set the point at which the queue is considered * "full" call this method specifying the {@code maxSize} in bytes. * * <p>This method is used by the {@link org.vertx.java.core.streams.Pump} class to pump data * between different streams and perform flow control. */ public void setWriteQueueMaxSize(int maxSize) { check(); if (conn != null) { conn.setWriteQueueMaxSize(maxSize); } else { pendingMaxSize = maxSize; } }
/** * This method sets a drain handler {@code handler} on the request. The drain handler will be * called when write queue is no longer full and it is safe to write to it again. * * <p>The drain handler is actually called when the write queue size reaches <b>half</b> the write * queue max size to prevent thrashing. This method is used as part of a flow control strategy, * e.g. it is used by the {@link org.vertx.java.core.streams.Pump} class to pump data between * different streams. * * @param handler */ public void drainHandler(Handler<Void> handler) { check(); this.drainHandler = handler; if (conn != null) { conn.handleInterestedOpsChanged(); // If the channel is already drained, we want to call it // immediately } }
@Override public NetSocket netSocket() { synchronized (conn) { if (netSocket == null) { netSocket = conn.createNetSocket(); } return netSocket; } }