public BaseRTMPTConnection(String type) { super(type); this.buffer = IoBuffer.allocate(0).setAutoExpand(true); }
@Override public void initialize(XMPPServer server) { super.initialize(server); // Check if we need to configure MINA to use Direct or Heap Buffers // Note: It has been reported that heap buffers are 50% faster than direct buffers if (JiveGlobals.getBooleanProperty("xmpp.socket.heapBuffer", true)) { IoBuffer.setUseDirectBuffer(false); IoBuffer.setAllocator(new SimpleBufferAllocator()); } }
/** * Generates response for non-versioned connections, such as those before FP9. * * @param input * incoming RTMP bytes * @return outgoing handshake */ private IoBuffer generateUnversionedHandshake(byte[] input) { log.debug("Using old style (un-versioned) handshake"); IoBuffer output = IoBuffer.allocate((Constants.HANDSHAKE_SIZE * 2) + 1); // 3073 // non-encrypted output.put(RTMPConnection.RTMP_NON_ENCRYPTED); // set server uptime in seconds output.putInt((int) Red5.getUpTime() / 1000); //0x01 output.position(Constants.HANDSHAKE_SIZE + 1); output.put(input); output.flip(); // fill S1 with handshake data (nearly all 0's) output.mark(); output.position(1); output.get(s1); output.reset(); return output; }
buf.mark(); int msgPos = savedBuf.position(); // carry on from previous buffer boolean seenNewline = false; while (!seenNewline && buf.hasRemaining() && msgPos < maxLineLength) { curByte = buf.get(); int end = buf.position(); buf.reset(); int start = buf.position(); if (savedBuf.position() > 0) { buf.get(tmp); savedBuf.put(tmp); int len = savedBuf.position() - 1; savedBuf.flip(); parsedBuf.buffer = savedBuf.getSlice(len); savedBuf.clear(); } else { parsedBuf.buffer = buf.getSlice(end - start - 1); buf.get(); // throw away newline int end = buf.position(); buf.reset(); int start = buf.position();
/** {@inheritDoc} */ @Override public void messageReceived(NextFilter next, IoSession session, Object message) throws Exception { if (message instanceof IoBuffer) { IoBuffer out = (IoBuffer) message; if (headers != null) { IoBuffer header = IoBuffer.allocate(12); header.putLong(System.currentTimeMillis()); header.putInt(out.limit() - out.position()); header.flip(); headers.write(header.buf()); } if (raw != null) { raw.write(out.asReadOnlyBuffer().buf()); } } next.messageReceived(session, message); }
/** {@inheritDoc} */ @Override public void messageReceived(NextFilter next, IoSession session, Object message) throws Exception { // Create forwarding IO session IoSession forward = (IoSession) session.getAttribute(FORWARD_KEY); if (forward != null && forward.isConnected()) { if (message instanceof IoBuffer) { final IoBuffer buf = (IoBuffer) message; if (log.isDebugEnabled()) { log.debug("[{}] RAW >> {}", name, buf.getHexDump()); } IoBuffer copy = IoBuffer.allocate(buf.limit()); int limit = buf.limit(); copy.put(buf); copy.flip(); forward.write(copy); buf.flip(); buf.position(0); buf.limit(limit); } } next.messageReceived(session, message); }
/** * Decode data sent by the client. * * @param data * the data to decode * @return a list of decoded objects */ public List<?> decode(IoBuffer data) { log.debug("decode"); if (closing || state.getState() == RTMP.STATE_DISCONNECTED) { // connection is being closed, don't decode any new packets return Collections.EMPTY_LIST; } if (log.isTraceEnabled()) { log.trace("Current bytes read at decode: {}", data.limit()); } buffer.put(data); buffer.flip(); return decoder.decodeBuffer(this, buffer); }
/** * Skip data sent by the client. * * @param req * Servlet request * @throws IOException * I/O exception */ protected void skipData(HttpServletRequest req) throws IOException { log.trace("skipData {}", req); int length = req.getContentLength(); log.trace("Skipping {} bytes", length); IoBuffer data = IoBuffer.allocate(length); ServletUtils.copy(req, data.asOutputStream()); data.flip(); data.free(); data = null; log.trace("Skipped {} bytes", length); }
@Override public void encode(IoSession session, Object message, ProtocolEncoderOutput out) { IoBuffer buf = IoBuffer.allocate( 1024 ); DnsMessage dnsMessage = (DnsMessage) message; encoder.encode(buf, dnsMessage); for (ResourceRecord record: dnsMessage.getAnswerRecords()) { // This is a hack to allow to also test for AAAA resolution as DnsMessageEncoder does not support it and it // is hard to extend, because the interesting methods are private... // In case of RecordType.AAAA we need to encode the RecordType by ourself if (record.getRecordType() == RecordType.AAAA) { try { recordEncoder.put(buf, record); } catch (IOException e) { // Should never happen throw new IllegalStateException(e); } } } buf.flip(); out.write( buf ); } };
@Override public void sessionCreated(IoSession session) { logger.info("Session created: {}", session); // Allocate saved buffer when session is created. // This allows us to parse an incomplete message and use it on // the next request. session.setAttribute(SAVED_BUF, IoBuffer.allocate(maxEventSize, false)); }
@Override protected void putResourceRecordData(IoBuffer ioBuffer, ResourceRecord resourceRecord) { if (!resourceRecord.get(DnsAttribute.IP_ADDRESS).equals("::1")) { throw new IllegalStateException("Only supposed to be used with IPV6 address of ::1"); } // encode the ::1 ioBuffer.put(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}); } }
/** * Take a message from this buffer. The message count decreases. * * @return <tt>null</tt> if buffer is empty. */ public RTMPMessage takeMessage() { RTMPMessage message = messageQueue.poll(); if (message != null) { IRTMPEvent body = message.getBody(); if (!(body instanceof IStreamData)) { throw new RuntimeException("Expected IStreamData but got " + body); } messageSize -= ((IStreamData<?>) body).getData().limit(); } return message; }
@Override public void write(Object encodedMessage) { IoBuffer buf = (IoBuffer) encodedMessage; if (buf.hasRemaining()) { SocketAddress destination = writeRequest.getDestination(); WriteRequest writeRequest = new DefaultWriteRequest(encodedMessage, null, destination); nextFilter.filterWrite(session, writeRequest); } else { throw new IllegalArgumentException("encodedMessage is empty. Forgot to call flip?"); } }
/** {@inheritDoc} */ @Override public void close() { closing = true; if (pendingOutMessages.size() > 0) { if (log.isTraceEnabled()) { log.trace("Clearing pending messages out: {}", pendingOutMessages.size()); } pendingOutMessages.clear(); } // clean up buffer if (buffer != null) { buffer.free(); buffer = null; } super.close(); }
@Override public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { if (message == null) { LOGGER.error("Message is null"); return; } if (!(message instanceof RemotingCommand)) { LOGGER.error("{} is not instanceof RemotingCommand", message); return; } RemotingCommand remotingCommand = (RemotingCommand) message; try { ByteBuffer byteBuffer = codec.encode(remotingCommand); IoBuffer ioBuffer = bufferAllocator.wrap(byteBuffer); out.write(ioBuffer); out.flush(); } catch (Exception e) { Channel channel = new MinaChannel(session); LOGGER.error("encode exception, addr={}, remotingCommand={}", RemotingHelper.parseChannelRemoteAddr(channel), remotingCommand.toString(), e); RemotingHelper.closeChannel(channel); } } };
/** * Put a message into this buffer. * * @param message * RTMP message * @return <tt>true</tt> indicates success and <tt>false</tt> indicates buffer is full. */ public boolean putMessage(RTMPMessage message) { IRTMPEvent body = message.getBody(); if (!(body instanceof IStreamData)) { throw new RuntimeException("Expected IStreamData but got " + body); } int size = ((IStreamData<?>) body).getData().limit(); if (messageSize + size > capacity) { return false; } messageSize += size; messageQueue.offer(message); return true; }
@Override protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { // Get the XML light parser from the IoSession XMLLightweightParser parser = (XMLLightweightParser) session.getAttribute(ConnectionHandler.XML_PARSER); // Parse as many stanzas as possible from the received data parser.read(in); if (parser.areThereMsgs()) { for (String stanza : parser.getMsgs()) { out.write(stanza); } } return !in.hasRemaining(); } }
@Override public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { if (message == null) { LOGGER.error("Message is null"); return; } if (!(message instanceof RemotingCommand)) { LOGGER.error("{} is not instanceof RemotingCommand", message); return; } RemotingCommand remotingCommand = (RemotingCommand) message; try { ByteBuffer byteBuffer = codec.encode(remotingCommand); IoBuffer ioBuffer = bufferAllocator.wrap(byteBuffer); out.write(ioBuffer); out.flush(); } catch (Exception e) { Channel channel = new MinaChannel(session); LOGGER.error("encode exception, addr={}, remotingCommand={}", RemotingHelper.parseChannelRemoteAddr(channel), remotingCommand.toString(), e); RemotingHelper.closeChannel(channel); } } };