tcpmessenger.java
来自「JXTA™ is a set of open, generalize」· Java 代码 · 共 1,127 行 · 第 1/3 页
JAVA
1,127 行
/** * parses a welcome from a buffer * * @param buffer the buffer to parse, if successful the state is set to HEADER * @return true if successfully parsed */ private boolean processWelcome(ByteBuffer buffer) { try { if (itsWelcome == null) { itsWelcome = new WelcomeMessage(); } if (!itsWelcome.read(buffer)) { return false; } // The correct value for dstAddr: that of the other party. dstAddress = itsWelcome.getPublicAddress(); if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine("Creating a logical address from : " + itsWelcome.getWelcomeString()); } fullDstAddress = dstAddress; logicalDestAddress = new EndpointAddress("jxta", itsWelcome.getPeerID().getUniqueValue().toString(), null, null); if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine("Hello from " + itsWelcome.getPublicAddress() + " [" + itsWelcome.getPeerID() + "] "); } if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine("Registering Messenger from " + socketChannel.socket().getInetAddress().getHostAddress() + ":"+ socketChannel.socket().getPort()); } try { // announce this messenger by connection address tcpTransport.messengerReadyEvent(this, getConnectionAddress()); } catch (Throwable all) { if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) { LOG.log(Level.SEVERE, "Uncaught Throwable in thread :" + Thread.currentThread().getName(), all); } IOException failure = new IOException("Failure announcing messenger."); failure.initCause(all); throw failure; } } catch (IOException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Error while parsing the welcome message", e); } closeImpl(); return false; } return true; } /** * parses a header from a buffer * * @param buffer the buffer to parse, if successful the state is set to BODY * @return true if successfully parsed */ private boolean processHeader(ByteBuffer buffer) { if (null == header) { header = new MessagePackageHeader(); } if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} Processing message package header, buffer stats:{1}", Thread.currentThread(), buffer.toString())); } try { if (!header.readHeader(buffer)) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} maintaining current state at header, buffer stats :{1}", Thread.currentThread(), buffer.toString())); } return false; } } catch (IOException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Error while parsing the message header", e); } if (!socketChannel.isConnected()) { // defunct connection close the messenger if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine("SocketChannel closed. Closing the messenger"); } closeImpl(); } } if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} setting current state to body, Buffer stats :{1}, remaining elements {2}:", Thread.currentThread(), buffer.toString(), buffer.remaining())); } return true; } private Message processMessage(ByteBuffer buffer, MessagePackageHeader header) throws IOException { // TODO 20020730 bondolo@jxta.org Do something with content-coding here. MimeMediaType msgMime = header.getContentTypeHeader(); return WireFormatMessageFactory.fromBuffer(buffer, msgMime, null); } /** * {@inheritDoc} * <p/> * This is what gets run by the Executor. It reads whatever is available, * processes it and then goes back to the selector waiting for more IO */ public void run() { try { while (read()) { List<Message> msgs = processBuffer(); for (Message msg : msgs) { // Use the group's threadpool to process the message tcpTransport.executor.execute(new MessageProcessor(msg)); } } // resets the interestOPS and wakeup the selector if (socketChannel != null) { tcpTransport.register(socketChannel, this); } } catch (Throwable all) { if (Logging.SHOW_SEVERE) { LOG.log(Level.SEVERE, "Uncaught Throwable", all); } } } /** * @return true to indicate read maybe required */ private boolean read() { if (closed || socketChannel == null) { return false; } if (!socketChannel.isConnected()) { closeImpl(); return false; } try { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} State before read(): {1}, buffer stats : {2}, remaining :{3}", Thread.currentThread(), state.get(), buffer.toString(), buffer.remaining())); } int read = socketChannel.read(buffer); if (read < 0) { if (!socketChannel.isConnected() || read < 0) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} Closing due to EOF", Thread.currentThread())); } closeImpl(); } return false; } else if (read == 0) { return false; } tcpTransport.incrementBytesReceived(read); // prepare the buffer for reading buffer.flip(); if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} SocketChannel.read() == {1} bytes. Buffer stats:{2}, remaining {3}", Thread.currentThread(), read, buffer.toString(), buffer.remaining())); } return true; } catch (ClosedChannelException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Channel closed while reading data", e); } closeImpl(); return false; } catch (InterruptedIOException woken) { // Framing is maintained within this object, therefore a read maybe interrupted then resumed if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) { LOG.warning(MessageFormat.format("tcp receive - interrupted : read() {0} {1}:{2}", woken.bytesTransferred, inetAddress.getHostAddress(), port)); } } catch (IOException ioe) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "IOException occured while reading data", ioe); } closeImpl(); return false; } catch (Throwable e) { if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, MessageFormat.format("tcp receive - Error on connection {0}:{1}", inetAddress.getHostAddress(), port), e); } closingDueToFailure = true; closeImpl(); return false; } // if the channel has a valid read ops return true, otherwise false return (socketChannel.validOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ; } /** * processes the input byte buffer * @return the list of messages present in the buffer */ @SuppressWarnings("fallthrough") public List<Message> processBuffer() { List<Message> msgs = new ArrayList<Message>(); boolean done = false; while (!done) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} processBuffer({1}). Buffer stats:{2}, elements remaining {3}", Thread.currentThread(), state.getClass(), buffer.toString(), buffer.remaining())); } switch (state.get()) { case WELCOME: // Parse Welcome message boolean wseen = processWelcome(buffer); if (wseen) { state.set(readState.HEADER); } done = true; break; case HEADER: // process the message header boolean hseen = processHeader(buffer); if (!hseen) { done = true; break; } receiveBeginTime = TimeUtils.timeNow(); // todo add a check for MTU size if (header.getContentLengthHeader() > buffer.capacity()) { ByteBuffer src = buffer; // create an array backed buffer if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} Reallocating a new buffer of size {1} to replace :{2}", Thread.currentThread(), header.getContentLengthHeader(), buffer.toString())); } // This implementation limits the message size to the MTU which is always < 2GB buffer = ByteBuffer.allocate((int) header.getContentLengthHeader()); buffer.put(src); buffer.flip(); } state.set(readState.BODY); /* FALLSTHROUGH */ case BODY: // process the message body if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format(" {0} Proccessing Message Body. expecting {1}, {2} elements remaining {3}", Thread.currentThread(), header.getContentLengthHeader(), buffer.toString(), buffer.remaining())); } if (buffer.remaining() >= (int) header.getContentLengthHeader()) { Message msg; try { msg = processMessage(buffer, header); } catch (IOException io) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Failed to parse a message from buffer. closing connection", io); } closeImpl(); done = true; break; } if (TransportMeterBuildSettings.TRANSPORT_METERING && (transportBindingMeter != null)) { transportBindingMeter.messageReceived(initiator, msg, TimeUtils.timeNow() - receiveBeginTime, header.getContentLengthHeader()); } tcpTransport.incrementMessagesReceived(); setLastUsed(TimeUtils.timeNow()); state.set(readState.HEADER); header = null; msgs.add(msg); } else { done = true; break; } } } // while loop // prepare the buffer for more data buffer.compact(); return msgs; } /** * A small class for processing individual messages. */ private class MessageProcessor implements Runnable { private Message msg; MessageProcessor(Message msg) { this.msg = msg; } public void run() { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(MessageFormat.format("{0} calling EndpointService.demux({1})", Thread.currentThread(), msg, inetAddress.getHostAddress(), port)); } tcpTransport.endpoint.demux(msg); } } /** * return the current connection status. * * @return true if there is an active connection to the remote peer, otherwise false. */ private boolean isConnected() { return !closed; } /** * Return the absolute time in milliseconds at which this Connection was last used. * * @return absolute time in milliseconds. */ private long getLastUsed() { return lastUsed; } /** * Set the last used time for this connection in absolute milliseconds. * * @param time absolute time in milliseconds. */ private void setLastUsed(long time) { lastUsed = time; } /** * Returns the metering object for this tcpTransport * * @return the metering object for this tcpTransport */ TransportBindingMeter getTransportBindingMeter() { return transportBindingMeter; } /** * Returns the remote address * * @return the remote address */ private EndpointAddress getConnectionAddress() { // Somewhat confusing but destinationAddress is the name of that thing // for the welcome message. return itsWelcome.getDestinationAddress(); } /** * Returns Remote PeerID * * @return Remote PeerID */ private ID getDestinationPeerID() { return itsWelcome.getPeerID(); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?