예제 #1
0
  private SendBuffer acquire(ChannelBuffer src) {
    final int size = src.readableBytes();
    if (size == 0) {
      return EMPTY_BUFFER;
    }

    if (src instanceof CompositeChannelBuffer && ((CompositeChannelBuffer) src).useGathering()) {
      return new GatheringSendBuffer(src.toByteBuffers());
    }

    if (src.isDirect()) {
      return new UnpooledSendBuffer(src.toByteBuffer());
    }
    if (src.readableBytes() > DEFAULT_PREALLOCATION_SIZE) {
      return new UnpooledSendBuffer(src.toByteBuffer());
    }

    Preallocation current = this.current;
    ByteBuffer buffer = current.buffer;
    int remaining = buffer.remaining();
    PooledSendBuffer dst;

    if (size < remaining) {
      int nextPos = buffer.position() + size;
      ByteBuffer slice = buffer.duplicate();
      buffer.position(align(nextPos));
      slice.limit(nextPos);
      current.refCnt++;
      dst = new PooledSendBuffer(current, slice);
    } else if (size > remaining) {
      this.current = current = getPreallocation();
      buffer = current.buffer;
      ByteBuffer slice = buffer.duplicate();
      buffer.position(align(size));
      slice.limit(size);
      current.refCnt++;
      dst = new PooledSendBuffer(current, slice);
    } else { // size == remaining
      current.refCnt++;
      this.current = getPreallocation0();
      dst = new PooledSendBuffer(current, current.buffer);
    }

    ByteBuffer dstbuf = dst.buffer;
    dstbuf.mark();
    src.getBytes(src.readerIndex(), dstbuf);
    dstbuf.reset();
    return dst;
  }
예제 #2
0
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    receivedMessages.mark();

    ChannelBuffer buffer = (ChannelBuffer) e.getMessage();

    byte[] readable = new byte[buffer.readableBytes()];
    buffer.toByteBuffer().get(readable, buffer.readerIndex(), buffer.readableBytes());

    GELFMessage msg = new GELFMessage(readable);

    switch (msg.getGELFType()) {
      case CHUNKED:
        dispatchedMessageChunk.mark();
        server.getGELFChunkManager().insert(msg);
        break;
      case ZLIB:
      case GZIP:
      case UNCOMPRESSED:
      case UNSUPPORTED:
        dispatchedUnchunkedMessage.mark();
        processor.messageReceived(msg);
        break;
    }
  }
예제 #3
0
  static void write(
      OioDatagramChannel channel,
      ChannelFuture future,
      Object message,
      SocketAddress remoteAddress) {
    try {
      ChannelBuffer buf = (ChannelBuffer) message;
      int length = buf.readableBytes();
      ByteBuffer nioBuf = buf.toByteBuffer();
      DatagramPacket packet;
      if (nioBuf.hasArray()) {
        // Avoid copy if the buffer is backed by an array.
        packet = new DatagramPacket(nioBuf.array(), nioBuf.arrayOffset(), length);
      } else {
        // Otherwise it will be expensive.
        byte[] arrayBuf = new byte[length];
        buf.getBytes(0, arrayBuf);
        packet = new DatagramPacket(arrayBuf, length);
      }

      if (remoteAddress != null) {
        packet.setSocketAddress(remoteAddress);
      }
      channel.socket.send(packet);
      fireWriteComplete(channel, length);
      future.setSuccess();
    } catch (Throwable t) {
      future.setFailure(t);
      fireExceptionCaught(channel, t);
    }
  }
예제 #4
0
  public void handleDownstream(final ChannelHandlerContext context, final ChannelEvent evt)
      throws Exception {
    if (evt instanceof ChannelStateEvent) {
      ChannelStateEvent e = (ChannelStateEvent) evt;
      switch (e.getState()) {
        case OPEN:
        case CONNECTED:
        case BOUND:
          if (Boolean.FALSE.equals(e.getValue()) || e.getValue() == null) {
            closeOutboundAndChannel(context, e);
            return;
          }
      }
    }
    if (!(evt instanceof MessageEvent)) {
      context.sendDownstream(evt);
      return;
    }

    MessageEvent e = (MessageEvent) evt;
    if (!(e.getMessage() instanceof ChannelBuffer)) {
      context.sendDownstream(evt);
      return;
    }

    // Do not encrypt the first write request if this handler is
    // created with startTLS flag turned on.
    if (startTls && sentFirstMessage.compareAndSet(false, true)) {
      context.sendDownstream(evt);
      return;
    }

    // Otherwise, all messages are encrypted.
    ChannelBuffer msg = (ChannelBuffer) e.getMessage();
    PendingWrite pendingWrite;

    if (msg.readable()) {
      pendingWrite =
          new PendingWrite(
              evt.getFuture(), msg.toByteBuffer(msg.readerIndex(), msg.readableBytes()));
    } else {
      pendingWrite = new PendingWrite(evt.getFuture(), null);
    }
    synchronized (pendingUnencryptedWrites) {
      boolean offered = pendingUnencryptedWrites.offer(pendingWrite);
      assert offered;
    }

    wrap(context, evt.getChannel());
  }
예제 #5
0
  public void addToHead(BytesReference content) throws IOException {
    if (content == null) {
      return;
    }

    int written = 0;
    ChannelBuffer channelBuffer = content.toChannelBuffer();
    int readableBytes = channelBuffer.readableBytes();
    assert readableBytes + headSize.get() <= headLength : "Got too many bytes in addToHead()";

    ByteBuffer byteBuffer = channelBuffer.toByteBuffer();
    while (written < readableBytes) {
      updateDigest(byteBuffer);
      written += headFileChannel.write(byteBuffer);
    }
    headSize.addAndGet(written);
    if (headSize.get() == headLength) {
      headCatchedUpLatch.countDown();
    }
  }
예제 #6
0
  private void addContent(ChannelBuffer buffer, boolean last) throws IOException {
    if (buffer != null) {
      int readableBytes = buffer.readableBytes();
      ByteBuffer byteBuffer = buffer.toByteBuffer();
      if (file == null) {
        file = createTmpFile();
      }
      if (fileChannel == null) {
        FileOutputStream outputStream = new FileOutputStream(file);
        fileChannel = outputStream.getChannel();
      }

      int written = 0;
      do {
        if (headLength == 0) {
          updateDigest(byteBuffer);
        }
        written += fileChannel.write(byteBuffer);
      } while (written < readableBytes);
      size += readableBytes;
      buffer.readerIndex(buffer.readerIndex() + written);
      chunks++;
    }
    if (last) {
      if (file == null) {
        file = createTmpFile();
      }
      if (fileChannel == null) {
        FileOutputStream outputStream = new FileOutputStream(file);
        fileChannel = outputStream.getChannel();
      }
      fileChannel.force(false);
      fileChannel.close();
      fileChannel = null;
    } else {
      if (buffer == null) {
        throw new NullPointerException("buffer");
      }
    }
  }
예제 #7
0
  private ChannelBuffer unwrap(
      ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, int offset, int length)
      throws SSLException {
    ByteBuffer inNetBuf = buffer.toByteBuffer(offset, length);
    ByteBuffer outAppBuf = bufferPool.acquire();

    try {
      boolean needsWrap = false;
      loop:
      for (; ; ) {
        SSLEngineResult result;
        synchronized (handshakeLock) {
          if (!handshaken
              && !handshaking
              && !engine.getUseClientMode()
              && !engine.isInboundDone()
              && !engine.isOutboundDone()) {
            handshake();
          }

          try {
            result = engine.unwrap(inNetBuf, outAppBuf);
          } catch (SSLException e) {
            throw e;
          }

          final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
          handleRenegotiation(handshakeStatus);
          switch (handshakeStatus) {
            case NEED_UNWRAP:
              if (inNetBuf.hasRemaining() && !engine.isInboundDone()) {
                break;
              } else {
                break loop;
              }
            case NEED_WRAP:
              wrapNonAppData(ctx, channel);
              break;
            case NEED_TASK:
              runDelegatedTasks();
              break;
            case FINISHED:
              setHandshakeSuccess(channel);
              needsWrap = true;
              break loop;
            case NOT_HANDSHAKING:
              needsWrap = true;
              break loop;
            default:
              throw new IllegalStateException("Unknown handshake status: " + handshakeStatus);
          }
        }
      }

      if (needsWrap) {
        // wrap() acquires pendingUnencryptedWrites first and then
        // handshakeLock.  If handshakeLock is already hold by the
        // current thread, calling wrap() will lead to a dead lock
        // i.e. pendingUnencryptedWrites -> handshakeLock vs.
        //      handshakeLock -> pendingUnencryptedLock -> handshakeLock
        //
        // There is also a same issue between pendingEncryptedWrites
        // and pendingUnencryptedWrites.
        if (!Thread.holdsLock(handshakeLock)
            && !pendingEncryptedWritesLock.isHeldByCurrentThread()) {
          wrap(ctx, channel);
        }
      }

      outAppBuf.flip();

      if (outAppBuf.hasRemaining()) {
        ChannelBuffer frame = ChannelBuffers.buffer(outAppBuf.remaining());
        frame.writeBytes(outAppBuf.array(), 0, frame.capacity());
        return frame;
      } else {
        return null;
      }
    } catch (SSLException e) {
      setHandshakeFailure(channel, e);
      throw e;
    } finally {
      bufferPool.release(outAppBuf);
    }
  }
예제 #8
0
  @Override
  protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg)
      throws Exception {

    ChannelBuffer buf = (ChannelBuffer) msg;

    buf.skipBytes(2); // header
    int type = buf.readUnsignedByte();
    buf.readUnsignedShort(); // size

    if (type == MSG_ON_DEMAND
        || type == MSG_POSITION_UPLOAD
        || type == MSG_POSITION_REUPLOAD
        || type == MSG_ALARM
        || type == MSG_REPLY
        || type == MSG_PERIPHERAL) {

      // Create new position
      Position position = new Position();
      position.setProtocol(getProtocolName());

      // Device identification
      if (!identify(readSerialNumber(buf), channel)) {
        return null;
      }
      position.setDeviceId(getDeviceId());

      // Date and time
      Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
      time.clear();
      time.set(Calendar.YEAR, 2000 + ChannelBufferTools.readHexInteger(buf, 2));
      time.set(Calendar.MONTH, ChannelBufferTools.readHexInteger(buf, 2) - 1);
      time.set(Calendar.DAY_OF_MONTH, ChannelBufferTools.readHexInteger(buf, 2));
      time.set(Calendar.HOUR_OF_DAY, ChannelBufferTools.readHexInteger(buf, 2));
      time.set(Calendar.MINUTE, ChannelBufferTools.readHexInteger(buf, 2));
      time.set(Calendar.SECOND, ChannelBufferTools.readHexInteger(buf, 2));
      position.setTime(time.getTime());

      // Location
      position.setLatitude(ChannelBufferTools.readCoordinate(buf));
      position.setLongitude(ChannelBufferTools.readCoordinate(buf));
      position.setSpeed(UnitsConverter.knotsFromKph(ChannelBufferTools.readHexInteger(buf, 4)));
      position.setCourse(ChannelBufferTools.readHexInteger(buf, 4));

      // Flags
      int flags = buf.readUnsignedByte();
      position.setValid((flags & 0x80) != 0);

      if (type == MSG_ALARM) {

        buf.skipBytes(2);

      } else {

        // Odometer
        position.set(Event.KEY_ODOMETER, buf.readUnsignedMedium());

        // Status
        buf.skipBytes(4);

        // Other
        buf.skipBytes(8);
      }

      // TODO: parse extra data
      return position;
    } else if (type == MSG_LOGIN && channel != null) {

      buf.skipBytes(4); // serial number
      buf.readByte(); // reserved

      ChannelBuffer response = ChannelBuffers.dynamicBuffer();
      response.writeByte(0x29);
      response.writeByte(0x29); // header
      response.writeByte(MSG_CONFIRMATION);
      response.writeShort(5); // size
      response.writeByte(buf.readUnsignedByte());
      response.writeByte(type);
      response.writeByte(0); // reserved
      response.writeByte(Crc.xorChecksum(response.toByteBuffer()));
      response.writeByte(0x0D); // ending
      channel.write(response);
    }

    return null;
  }
예제 #9
0
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
      if (!readingChunks) {
        HttpResponse response = (HttpResponse) e.getMessage();

        StringBuilder sb = new StringBuilder();
        if (LOG.isDebugEnabled()) {
          sb.append("STATUS: ")
              .append(response.getStatus())
              .append(", VERSION: ")
              .append(response.getProtocolVersion())
              .append(", HEADER: ");
        }
        if (!response.getHeaderNames().isEmpty()) {
          for (String name : response.getHeaderNames()) {
            for (String value : response.getHeaders(name)) {
              if (LOG.isDebugEnabled()) {
                sb.append(name + " = " + value);
              }
              if (this.length == -1 && name.equals("Content-Length")) {
                this.length = Long.valueOf(value);
              }
            }
          }
        }
        if (LOG.isDebugEnabled()) {
          LOG.debug(sb.toString());
        }

        if (response.getStatus() == HttpResponseStatus.NO_CONTENT) {
          LOG.info("There are no data corresponding to the request");
          return;
        }

        this.raf = new RandomAccessFile(file, "rw");
        this.fc = raf.getChannel();

        if (response.isChunked()) {
          readingChunks = true;
        } else {
          ChannelBuffer content = response.getContent();
          if (content.readable()) {
            fc.write(content.toByteBuffer());
          }
        }
      } else {
        HttpChunk chunk = (HttpChunk) e.getMessage();
        if (chunk.isLast()) {
          readingChunks = false;
          long fileLength = fc.position();
          fc.close();
          raf.close();
          if (fileLength == length) {
            LOG.info("Data fetch is done (total received bytes: " + fileLength + ")");
          } else {
            LOG.info(
                "Data fetch is done, but cannot get all data "
                    + "(received/total: "
                    + fileLength
                    + "/"
                    + length
                    + ")");
          }
        } else {
          fc.write(chunk.getContent().toByteBuffer());
        }
      }
    }