Example usage for io.netty.buffer ByteBuf writerIndex

List of usage examples for io.netty.buffer ByteBuf writerIndex

Introduction

In this page you can find the example usage for io.netty.buffer ByteBuf writerIndex.

Prototype

public abstract int writerIndex();

Source Link

Document

Returns the writerIndex of this buffer.

Usage

From source file:divconq.test.pgp.PGPWriter2.java

License:Open Source License

@SuppressWarnings("resource")
public void test2(String srcpath, String destpath, String keyring) throws Exception {
    Path src = Paths.get(srcpath);

    // file data 
    byte[] fileData = Files.readAllBytes(src);

    // dest//from w  w  w . java2s  .com
    OutputStream dest = new BufferedOutputStream(new FileOutputStream(destpath));

    // encryption key
    PGPPublicKey pubKey = null;

    InputStream keyIn = new BufferedInputStream(new FileInputStream(keyring));

    PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(
            org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());

    //
    // we just loop through the collection till we find a key suitable for encryption, in the real
    // world you would probably want to be a bit smarter about this.
    //

    @SuppressWarnings("rawtypes")
    Iterator keyRingIter = pgpPub.getKeyRings();

    while (keyRingIter.hasNext() && (pubKey == null)) {
        PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();

        @SuppressWarnings("rawtypes")
        Iterator keyIter = keyRing.getPublicKeys();

        while (keyIter.hasNext() && (pubKey == null)) {
            PGPPublicKey key = (PGPPublicKey) keyIter.next();

            if (key.isEncryptionKey())
                pubKey = key;
        }
    }

    if (pubKey == null)
        throw new IllegalArgumentException("Can't find encryption key in key ring.");

    String fileName = src.getFileName().toString();
    byte[] encName = Utf8Encoder.encode(fileName);
    long modificationTime = System.currentTimeMillis();

    SecureRandom rand = new SecureRandom();
    int algorithm = PGPEncryptedData.AES_256;

    Cipher cipher = null;

    ByteBuf leadingbuf = Hub.instance.getBufferAllocator().heapBuffer(1024 * 1024); // 1 mb
    ByteBuf encbuf = Hub.instance.getBufferAllocator().heapBuffer(1024 * 1024); // 1 mb

    // *******************************************************************
    // public key packet
    // *******************************************************************

    PGPKeyEncryptionMethodGenerator method = new JcePublicKeyKeyEncryptionMethodGenerator(pubKey);

    byte[] key = org.bouncycastle.openpgp.PGPUtil.makeRandomKey(algorithm, rand);

    byte[] sessionInfo = new byte[key.length + 3];

    // add algorithm
    sessionInfo[0] = (byte) algorithm;

    // add key
    System.arraycopy(key, 0, sessionInfo, 1, key.length);

    // add checksum 
    int check = 0;

    for (int i = 1; i != sessionInfo.length - 2; i++)
        check += sessionInfo[i] & 0xff;

    sessionInfo[sessionInfo.length - 2] = (byte) (check >> 8);
    sessionInfo[sessionInfo.length - 1] = (byte) (check);

    ContainedPacket packet1 = method.generate(algorithm, sessionInfo);

    byte[] encoded1 = packet1.getEncoded();

    leadingbuf.writeBytes(encoded1);

    // *******************************************************************
    // encrypt packet, add IV to encryption though
    // *******************************************************************

    leadingbuf.writeByte(0xC0 | PacketTags.SYM_ENC_INTEGRITY_PRO);

    this.writePacketLength(leadingbuf, 0); // 0 = we don't know

    leadingbuf.writeByte(1); // version number

    String cName = PGPUtil.getSymmetricCipherName(algorithm) + "/CFB/NoPadding";

    DefaultJcaJceHelper helper = new DefaultJcaJceHelper();

    cipher = helper.createCipher(cName);

    byte[] iv = new byte[cipher.getBlockSize()];

    cipher.init(Cipher.ENCRYPT_MODE, PGPUtil.makeSymmetricKey(algorithm, key), new IvParameterSpec(iv));

    // ******************** start encryption **********************

    // --- encrypt checksum for encrypt packet, part of the encrypted output --- 

    byte[] inLineIv = new byte[cipher.getBlockSize() + 2];

    rand.nextBytes(inLineIv);

    inLineIv[inLineIv.length - 1] = inLineIv[inLineIv.length - 3];
    inLineIv[inLineIv.length - 2] = inLineIv[inLineIv.length - 4];

    encbuf.writeBytes(inLineIv);

    System.out.println("bytes written a: " + encbuf.readableBytes());

    // --- data packet ---

    int chunkpos = 0;

    int headerlen = 1 // format
            + 1 // name length
            + encName.length // file name
            + 4; // time

    encbuf.writeByte(0xC0 | PacketTags.LITERAL_DATA);

    int packetsize = 512 - headerlen;

    if (fileData.length - chunkpos < packetsize) {
        packetsize = fileData.length - chunkpos;

        this.writePacketLength(encbuf, headerlen + packetsize);
    } else {
        encbuf.writeByte(0xE9); // 512 packet length
    }

    System.out.println("bytes written b: " + encbuf.readableBytes());

    encbuf.writeByte(PGPLiteralData.BINARY); // data format

    encbuf.writeByte((byte) encName.length); // file name

    encbuf.writeBytes(encName);

    encbuf.writeInt((int) (modificationTime / 1000)); // mod time

    System.out.println("bytes written c: " + encbuf.readableBytes());

    encbuf.writeBytes(fileData, chunkpos, packetsize);

    System.out.println("bytes written d: " + encbuf.readableBytes());

    chunkpos += packetsize;

    // write one or more literal packets
    while (chunkpos < fileData.length) {
        packetsize = 512;

        // check if this is the final packet
        if (fileData.length - chunkpos <= packetsize) {
            packetsize = fileData.length - chunkpos;

            this.writePacketLength(encbuf, packetsize);
        } else {
            encbuf.writeByte(0xE9); // full 512 packet length
        }

        encbuf.writeBytes(fileData, chunkpos, packetsize);

        chunkpos += packetsize;
    }

    // protection packet
    encbuf.writeByte(0xC0 | PacketTags.MOD_DETECTION_CODE);
    encbuf.writeByte(20); // packet length

    MessageDigest md = MessageDigest.getInstance("SHA-1");
    md.update(encbuf.array(), encbuf.arrayOffset(), encbuf.writerIndex());

    byte[] rv = md.digest();

    encbuf.writeBytes(rv);

    System.out.println("Pre-Encrypted Hex");

    this.hexDump(encbuf.array(), encbuf.arrayOffset(), encbuf.writerIndex());

    System.out.println();
    System.out.println();

    // ***** encryption data ready *********

    byte[] encdata = cipher.doFinal(encbuf.array(), encbuf.arrayOffset(), encbuf.writerIndex());

    // add encrypted data to main buffer
    leadingbuf.writeBytes(encdata);

    System.out.println("Final Hex");

    this.hexDump(leadingbuf.array(), leadingbuf.arrayOffset(), leadingbuf.writerIndex());

    System.out.println();
    System.out.println();

    // write to file
    dest.write(leadingbuf.array(), leadingbuf.arrayOffset(), leadingbuf.writerIndex());

    dest.flush();
    dest.close();
}

From source file:divconq.test.pgp.PGPWriter2.java

License:Open Source License

@SuppressWarnings("resource")
public void test1(String srcpath, String destpath, String keyring) throws Exception {
    Path src = Paths.get(srcpath);

    // file data 
    byte[] story = Files.readAllBytes(src);

    // dest/*ww  w.  j av  a 2  s .c o  m*/
    OutputStream dest = new BufferedOutputStream(new FileOutputStream(destpath));

    // encryption key
    PGPPublicKey pubKey = null;

    InputStream keyIn = new BufferedInputStream(new FileInputStream(keyring));

    PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(
            org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());

    //
    // we just loop through the collection till we find a key suitable for encryption, in the real
    // world you would probably want to be a bit smarter about this.
    //

    @SuppressWarnings("rawtypes")
    Iterator keyRingIter = pgpPub.getKeyRings();

    while (keyRingIter.hasNext() && (pubKey == null)) {
        PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();

        @SuppressWarnings("rawtypes")
        Iterator keyIter = keyRing.getPublicKeys();

        while (keyIter.hasNext() && (pubKey == null)) {
            PGPPublicKey key = (PGPPublicKey) keyIter.next();

            if (key.isEncryptionKey())
                pubKey = key;
        }
    }

    if (pubKey == null)
        throw new IllegalArgumentException("Can't find encryption key in key ring.");

    String fileName = src.getFileName().toString();
    byte[] encName = Utf8Encoder.encode(fileName);
    long modificationTime = System.currentTimeMillis();

    SecureRandom rand = new SecureRandom();
    int algorithm = PGPEncryptedData.AES_256;

    Cipher cipher = null;

    ByteBuf leadingbuf = Hub.instance.getBufferAllocator().heapBuffer(1024 * 1024); // 1 mb
    ByteBuf encbuf = Hub.instance.getBufferAllocator().heapBuffer(1024 * 1024); // 1 mb

    // *******************************************************************
    // public key packet
    // *******************************************************************

    PGPKeyEncryptionMethodGenerator method = new JcePublicKeyKeyEncryptionMethodGenerator(pubKey);

    byte[] key = org.bouncycastle.openpgp.PGPUtil.makeRandomKey(algorithm, rand);

    byte[] sessionInfo = new byte[key.length + 3];

    // add algorithm
    sessionInfo[0] = (byte) algorithm;

    // add key
    System.arraycopy(key, 0, sessionInfo, 1, key.length);

    // add checksum 
    int check = 0;

    for (int i = 1; i != sessionInfo.length - 2; i++)
        check += sessionInfo[i] & 0xff;

    sessionInfo[sessionInfo.length - 2] = (byte) (check >> 8);
    sessionInfo[sessionInfo.length - 1] = (byte) (check);

    ContainedPacket packet1 = method.generate(algorithm, sessionInfo);

    byte[] encoded1 = packet1.getEncoded();

    leadingbuf.writeBytes(encoded1);

    // *******************************************************************
    // encrypt packet, add IV to 
    // *******************************************************************

    String cName = PGPUtil.getSymmetricCipherName(algorithm) + "/CFB/NoPadding";

    DefaultJcaJceHelper helper = new DefaultJcaJceHelper();

    cipher = helper.createCipher(cName);

    byte[] iv = new byte[cipher.getBlockSize()];

    cipher.init(Cipher.ENCRYPT_MODE, PGPUtil.makeSymmetricKey(algorithm, key), new IvParameterSpec(iv));

    // ******************** start encryption **********************

    // --- encrypt checksum for encrypt packet, part of the encrypted output --- 

    byte[] inLineIv = new byte[cipher.getBlockSize() + 2];

    rand.nextBytes(inLineIv);

    inLineIv[inLineIv.length - 1] = inLineIv[inLineIv.length - 3];
    inLineIv[inLineIv.length - 2] = inLineIv[inLineIv.length - 4];

    encbuf.writeBytes(inLineIv);

    // --- data packet ---

    encbuf.writeByte(0xC0 | PacketTags.LITERAL_DATA);

    this.writePacketLength(encbuf, 1 // format
            + 1 // name length
            + encName.length // file name
            + 4 // time
            + story.length // data
    );

    encbuf.writeByte(PGPLiteralData.BINARY);

    encbuf.writeByte((byte) encName.length);

    encbuf.writeBytes(encName);

    encbuf.writeInt((int) (modificationTime / 1000));

    encbuf.writeBytes(story);

    // protection packet
    encbuf.writeByte(0xC0 | PacketTags.MOD_DETECTION_CODE);
    encbuf.writeByte(20); // packet length

    MessageDigest md = MessageDigest.getInstance("SHA-1");
    md.update(encbuf.array(), encbuf.arrayOffset(), encbuf.writerIndex());

    byte[] rv = md.digest();

    encbuf.writeBytes(rv);

    System.out.println("Encrypted Hex");

    this.hexDump(encbuf.array(), encbuf.arrayOffset(), encbuf.writerIndex());

    System.out.println();
    System.out.println();

    // ***** encryption data ready *********

    byte[] encdata = cipher.doFinal(encbuf.array(), encbuf.arrayOffset(), encbuf.writerIndex());

    leadingbuf.writeByte(0xC0 | PacketTags.SYM_ENC_INTEGRITY_PRO);

    /*
    this.writePacketLength(leadingbuf, 
     1      // version 
     + encdata.length       // encrypted data
       );
       */

    this.writePacketLength(leadingbuf, 0); // 0 = we don't know

    leadingbuf.writeByte(1); // version number

    // add encrypted data to main buffer
    leadingbuf.writeBytes(encdata);

    System.out.println("Final Hex");

    this.hexDump(leadingbuf.array(), leadingbuf.arrayOffset(), leadingbuf.writerIndex());

    System.out.println();
    System.out.println();

    // write to file
    dest.write(leadingbuf.array(), leadingbuf.arrayOffset(), leadingbuf.writerIndex());

    dest.flush();
    dest.close();
}

From source file:divconq.web.http.ServerHandler.java

License:Open Source License

public void handleHttpRequest(ChannelHandlerContext ctx, HttpObject httpobj) throws Exception {
    if (httpobj instanceof HttpContent) {
        this.context.offerContent((HttpContent) httpobj);
        return;/*from   w w w  . j ava2  s.  c o  m*/
    }

    if (!(httpobj instanceof HttpRequest)) {
        this.context.sendRequestBad();
        return;
    }

    HttpRequest httpreq = (HttpRequest) httpobj;

    this.context.load(ctx, httpreq);

    // Handle a bad request.
    if (!httpreq.getDecoderResult().isSuccess()) {
        this.context.sendRequestBad();
        return;
    }

    Request req = this.context.getRequest();
    Response resp = this.context.getResponse();

    // to avoid lots of unused sessions
    if (req.pathEquals("/favicon.ico") || req.pathEquals("/robots.txt")) {
        this.context.sendNotFound();
        return;
    }

    // make sure we don't have a leftover task context
    OperationContext.clear();

    String origin = "http:" + NetUtil.formatIpAddress((InetSocketAddress) ctx.channel().remoteAddress());

    // TODO use X-Forwarded-For  if available, maybe a plug in approach to getting client's IP?

    DomainInfo dinfo = this.context.getSiteman().resolveDomainInfo(req.getHeader("Host"));

    if (dinfo == null) {
        this.context.sendForbidden();
        return;
    }

    WebDomain wdomain = this.context.getSiteman().getDomain(dinfo.getId());

    // check into url re-routing
    String reroute = wdomain.route(req, (SslHandler) ctx.channel().pipeline().get("ssl"));

    if (StringUtil.isNotEmpty(reroute)) {
        this.context.getResponse().setStatus(HttpResponseStatus.FOUND);
        this.context.getResponse().setHeader("Location", reroute);
        this.context.send();
        return;
    }

    Cookie sesscookie = req.getCookie("SessionId");
    Session sess = null;

    if (sesscookie != null) {
        String v = sesscookie.getValue();
        String sessionid = v.substring(0, v.lastIndexOf('_'));
        String accesscode = v.substring(v.lastIndexOf('_') + 1);

        sess = Hub.instance.getSessions().lookupAuth(sessionid, accesscode);
    }

    if (sess == null) {
        sess = Hub.instance.getSessions().create(origin, dinfo.getId());

        Logger.info("Started new session: " + sess.getId() + " on " + req.getPath() + " for " + origin);

        // TODO if ssl set client key on user context
        //req.getSecuritySession().getPeerCertificates();

        sess.setAdatper(new ISessionAdapter() {
            protected volatile ListStruct msgs = new ListStruct();

            @Override
            public void stop() {
                ServerHandler.this.context.close();
            }

            @Override
            public ListStruct popMessages() {
                ListStruct ret = this.msgs;
                this.msgs = new ListStruct();
                return ret;
            }

            @Override
            public void deliver(Message msg) {
                // keep no more than 100 messages - this is not a "reliable" approach, just basic comm help               
                while (this.msgs.getSize() > 99)
                    this.msgs.removeItem(0);

                this.msgs.addItem(msg);
            }
        });

        Cookie sk = new DefaultCookie("SessionId", sess.getId() + "_" + sess.getKey());
        sk.setPath("/");
        sk.setHttpOnly(true);

        resp.setCookie(sk);
    }

    this.context.setSession(sess);

    sess.touch();

    OperationContext tc = sess.setContext(origin);

    tc.info("Web request for host: " + req.getHeader("Host") + " url: " + req.getPath() + " by: " + origin
            + " session: " + sess.getId());

    /*
    System.out.println("sess proto: " + ((SslHandler)ctx.channel().pipeline().get("ssl")).engine().getSession().getProtocol());
    System.out.println("sess suite: " + ((SslHandler)ctx.channel().pipeline().get("ssl")).engine().getSession().getCipherSuite());
    */

    try {
        if (req.pathEquals(ServerHandler.BUS_PATH)) {
            // Allow only GET methods.
            if (req.getMethod() != HttpMethod.GET) {
                this.context.sendForbidden();
                return;
            }

            // Handshake
            WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                    ServerHandler.getWebSocketLocation(
                            "True".equals(this.context.getConfig().getAttribute("Secure")), httpreq),
                    null, false);

            this.handshaker = wsFactory.newHandshaker(httpreq);

            if (this.handshaker == null)
                WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
            else {
                DefaultFullHttpRequest freq = new DefaultFullHttpRequest(httpreq.getProtocolVersion(),
                        httpreq.getMethod(), httpreq.getUri());

                freq.headers().add(httpreq.headers());

                this.handshaker.handshake(ctx.channel(), freq);

                return;
            }

            this.context.sendForbidden();
            return;
        }

        // "upload" is it's own built-in extension.  
        if ((req.getPath().getNameCount() == 3) && req.getPath().getName(0).equals(ServerHandler.UPLOAD_PATH)) {
            if (!Hub.instance.isRunning()) { // only allow uploads when running
                this.context.sendRequestBad();
                return;
            }

            // currently only supporting POST/PUT of pure binary - though support for form uploads can be restored, see below
            // we cannot rely on content type being meaningful
            //if (!"application/octet-stream".equals(req.getContentType().getPrimary())) {
            //    this.context.sendRequestBad();
            //    return;
            //}

            // TODO add CORS support if needed

            if ((req.getMethod() != HttpMethod.PUT) && (req.getMethod() != HttpMethod.POST)) {
                this.context.sendRequestBad();
                return;
            }

            final String cid = req.getPath().getName(1);
            final String op = req.getPath().getName(2);

            final DataStreamChannel dsc = sess.getChannel(cid);

            if (dsc == null) {
                this.context.sendRequestBad();
                return;
            }

            dsc.setDriver(new IStreamDriver() {
                @Override
                public void cancel() {
                    Logger.error("Transfer canceled on channel: " + cid);
                    dsc.complete();
                    ServerHandler.this.context.sendRequestBad(); // TODO headers?
                }

                @Override
                public void nextChunk() {
                    Logger.debug("Continue on channel: " + cid);
                    ServerHandler.this.context.sendRequestOk();
                }

                @Override
                public void message(StreamMessage msg) {
                    if (msg.isFinal()) {
                        Logger.debug("Final on channel: " + cid);
                        dsc.complete();
                        ServerHandler.this.context.sendRequestOk();
                    }
                }
            });

            //if (req.getMethod() == HttpMethod.PUT) {
            this.context.setDecoder(new IContentDecoder() {
                protected boolean completed = false;
                protected int seq = 0;

                @Override
                public void release() {
                    // trust that http connection is closing or what ever needs to happen, we just need to deal with datastream

                    Logger.debug("Releasing data stream");

                    // if not done with request then something went wrong, kill data channel
                    if (!this.completed)
                        dsc.abort();
                }

                @Override
                public void offer(HttpContent chunk) {
                    boolean finalchunk = (chunk instanceof LastHttpContent);

                    //System.out.println("Chunk: " + finalchunk);

                    ByteBuf buffer = chunk.content();

                    if (!dsc.isClosed()) {
                        int size = buffer.readableBytes();

                        //System.out.println("Chunk size: " + size);

                        dsc.touch(); // TODO try to set progress on dsc

                        // TODO set hint in netty as to where this buffer was handled and sent

                        if (size > 0) {
                            buffer.retain(); // we will be using a reference up during send

                            StreamMessage b = new StreamMessage("Block", buffer);
                            b.setField("Sequence", this.seq);

                            //System.out.println("Buffer ref cnt a: " + buffer.refCnt());

                            OperationResult or = dsc.send(b);

                            //System.out.println("Buffer ref cnt b: " + buffer.refCnt());

                            // indicate we have read the buffer?
                            buffer.readerIndex(buffer.writerIndex());

                            if (or.hasErrors()) {
                                dsc.close();
                                return;
                            }

                            this.seq++;
                        }

                        // if last buffer of last block then mark the upload as completed
                        if (finalchunk) {
                            if ("Final".equals(op))
                                dsc.send(MessageUtil.streamFinal());
                            else
                                dsc.getDriver().nextChunk();
                        }
                    }

                    // means this block is completed, not necessarily entire file uploaded
                    if (finalchunk)
                        this.completed = true;
                }
            });

            //return;
            //}

            /* old approach that supported multipart posts TODO review/remove
            if (req.getMethod() == HttpMethod.POST) {
               StreamingDataFactory sdf = new StreamingDataFactory(dsc, op);
                       
               // TODO consider supporting non-multipart?
               final HttpPostMultipartRequestDecoder prd = new HttpPostMultipartRequestDecoder(sdf, httpreq); 
                    
                 this.context.setDecoder(new IContentDecoder() {               
                 @Override
                 public void release() {
             // trust that http connection is closing or what ever needs to happen, we just need to deal with datastream
                     
             // if not done with request then something went wrong, kill data channel
             if ((prd.getStatus() != MultiPartStatus.EPILOGUE) && (prd.getStatus() != MultiPartStatus.PREEPILOGUE))
                dsc.kill();
                 }
                         
                 @Override
                 public void offer(HttpContent chunk) {
             //the only thing we care about is the file, the file will stream to dsc - the rest can disappear
             prd.offer(chunk);      
                 }
              });
                         
                  return;
            }                         
            */

            //this.context.sendRequestBad();
            return;
        }

        // "download" is it's own built-in extension.  
        if ((req.getPath().getNameCount() == 2)
                && req.getPath().getName(0).equals(ServerHandler.DOWNLOAD_PATH)) {
            if (!Hub.instance.isRunning()) { // only allow downloads when running
                this.context.sendRequestBad();
                return;
            }

            if (req.getMethod() != HttpMethod.GET) {
                this.context.sendRequestBad();
                return;
            }

            String cid = req.getPath().getName(1);

            final DataStreamChannel dsc = sess.getChannel(cid);

            if (dsc == null) {
                this.context.sendRequestBad();
                return;
            }

            dsc.setDriver(new IStreamDriver() {
                //protected long amt = 0;
                protected long seq = 0;

                @Override
                public void cancel() {
                    dsc.complete();
                    ServerHandler.this.context.close();
                }

                @Override
                public void nextChunk() {
                    // meaningless in download
                }

                @Override
                public void message(StreamMessage msg) {
                    int seqnum = (int) msg.getFieldAsInteger("Sequence", 0);

                    if (seqnum != this.seq) {
                        this.error(1, "Bad sequence number: " + seqnum);
                        return;
                    }

                    if (msg.hasData()) {
                        //this.amt += msg.getData().readableBytes();
                        HttpContent b = new DefaultHttpContent(Unpooled.copiedBuffer(msg.getData())); // TODO not copied
                        ServerHandler.this.context.sendDownload(b);
                    }

                    this.seq++;

                    // TODO update progress

                    if (msg.isFinal()) {
                        ServerHandler.this.context.sendDownload(new DefaultLastHttpContent());
                        ServerHandler.this.context.close();
                        dsc.complete();
                    }
                }

                public void error(int code, String msg) {
                    dsc.send(MessageUtil.streamError(code, msg));
                    ServerHandler.this.context.close();
                }
            });

            // for some reason HyperSession is sending content. 
            this.context.setDecoder(new IContentDecoder() {
                @Override
                public void release() {
                }

                @Override
                public void offer(HttpContent chunk) {
                    if (!(chunk instanceof LastHttpContent))
                        Logger.error("Unexplained and unwanted content during download: " + chunk);
                }
            });

            // tell the client that chunked content is coming
            this.context.sendDownloadHeaders(dsc.getPath() != null ? dsc.getPath().getFileName() : null,
                    dsc.getMime());

            // get the data flowing
            dsc.send(new StreamMessage("Start"));

            return;
        }

        if ((req.getPath().getNameCount() == 1) && req.getPath().getName(0).equals(ServerHandler.STATUS_PATH)) {
            if (Hub.instance.getState() == HubState.Running)
                this.context.sendRequestOk();
            else
                this.context.sendRequestBad();

            return;
        }

        // "rpc" is it's own built-in extension.  all requests to rpc are routed through
        // DivConq bus, if the request is valid
        if (req.pathEquals(ServerHandler.RPC_PATH)) {
            if (req.getMethod() != HttpMethod.POST) {
                this.context.sendRequestBad();
                return;
            }

            //System.out.println("looks like we have a rpc message");

            // max 4MB of json? -- TODO is that max chunk size or max total?  we don't need 4MB chunk... 
            this.context.setDecoder(new HttpBodyRequestDecoder(4096 * 1024, new RpcHandler(this.context)));
            return;
        }

        // otherwise we need to figure out which extension is being called
        // "local" is also used to mean default extension
        String ext = req.pathEquals("/") ? "local" : req.getPath().getName(0);

        IWebExtension ex = "local".equals(ext) ? this.context.getSiteman().getDefaultExtension()
                : this.context.getSiteman().getExtension(ext);

        // still cannot figure it out, use default
        if (ex == null)
            ex = this.context.getSiteman().getDefaultExtension();

        // then have extension handle it
        if (ex != null) {
            //OperationResult res = new OperationResult();  

            OperationResult res = ex.handle(sess, this.context);
            //resp.addBody("Hello");
            //this.context.send();

            // no errors starting page processing, return 
            if (!res.hasErrors())
                return;

            resp.setHeader("X-dcResultCode", res.getCode() + "");
            resp.setHeader("X-dcResultMesage", res.getMessage());
            this.context.sendNotFound();
            return;
        }
    } catch (Exception x) {
        this.context.sendInternalError();
        return;
    }

    this.context.sendNotFound();
}

From source file:dorkbox.network.connection.KryoExtra.java

License:Apache License

/**
 * This is NOT ENCRYPTED (and is only done on the loopback connection!)
 *//*from  w  w w. ja v a2s .co m*/
public synchronized void writeCompressed(final Connection_ connection, final ByteBuf buffer,
        final Object message) throws IOException {
    // required by RMI and some serializers to determine which connection wrote (or has info about) this object
    this.rmiSupport = connection.rmiSupport();

    ByteBuf objectOutputBuffer = this.tempBuffer;
    objectOutputBuffer.clear(); // always have to reset everything

    // write the object to a TEMP buffer! this will be compressed
    writer.setBuffer(objectOutputBuffer);

    writeClassAndObject(writer, message);

    // save off how much data the object took + magic byte
    int length = objectOutputBuffer.writerIndex();

    // NOTE: compression and encryption MUST work with byte[] because they use JNI!
    // Realistically, it is impossible to get the backing arrays out of a Heap Buffer once they are resized and begin to use
    // sliced. It's lame that there is a "double copy" of bytes here, but I don't know how to avoid it...
    // see:   https://stackoverflow.com/questions/19296386/netty-java-getting-data-from-bytebuf

    byte[] inputArray;
    int inputOffset;

    // Even if a ByteBuf has a backing array (i.e. buf.hasArray() returns true), the using it isn't always possible because
    // the buffer might be a slice of other buffer or a pooled buffer:
    //noinspection Duplicates
    if (objectOutputBuffer.hasArray() && objectOutputBuffer.array()[0] == objectOutputBuffer.getByte(0)
            && objectOutputBuffer.array().length == objectOutputBuffer.capacity()) {

        // we can use it...
        inputArray = objectOutputBuffer.array();
        inputArrayLength = -1; // this is so we don't REUSE this array accidentally!
        inputOffset = objectOutputBuffer.arrayOffset();
    } else {
        // we can NOT use it.
        if (length > inputArrayLength) {
            inputArrayLength = length;
            inputArray = new byte[length];
            this.inputArray = inputArray;
        } else {
            inputArray = this.inputArray;
        }

        objectOutputBuffer.getBytes(objectOutputBuffer.readerIndex(), inputArray, 0, length);
        inputOffset = 0;
    }

    ////////// compressing data
    // we ALWAYS compress our data stream -- because of how AES-GCM pads data out, the small input (that would result in a larger
    // output), will be negated by the increase in size by the encryption

    byte[] compressOutput = this.compressOutput;

    int maxLengthLengthOffset = 4; // length is never negative, so 4 is OK (5 means it's negative)
    int maxCompressedLength = compressor.maxCompressedLength(length);

    // add 4 so there is room to write the compressed size to the buffer
    int maxCompressedLengthWithOffset = maxCompressedLength + maxLengthLengthOffset;

    // lazy initialize the compression output buffer
    if (maxCompressedLengthWithOffset > compressOutputLength) {
        compressOutputLength = maxCompressedLengthWithOffset;
        compressOutput = new byte[maxCompressedLengthWithOffset];
        this.compressOutput = compressOutput;
    }

    // LZ4 compress. output offset max 4 bytes to leave room for length of tempOutput data
    int compressedLength = compressor.compress(inputArray, inputOffset, length, compressOutput,
            maxLengthLengthOffset, maxCompressedLength);

    // bytes can now be written to, because our compressed data is stored in a temp array.

    final int lengthLength = OptimizeUtilsByteArray.intLength(length, true);

    // correct input.  compression output is now buffer input
    inputArray = compressOutput;
    inputOffset = maxLengthLengthOffset - lengthLength;

    // now write the ORIGINAL (uncompressed) length to the front of the byte array (this is NOT THE BUFFER!). This is so we can use the FAST decompress version
    OptimizeUtilsByteArray.writeInt(inputArray, length, true, inputOffset);

    // have to copy over the orig data, because we used the temp buffer. Also have to account for the length of the uncompressed size
    buffer.writeBytes(inputArray, inputOffset, compressedLength + lengthLength);
}

From source file:dorkbox.network.connection.KryoExtra.java

License:Apache License

public synchronized void writeCrypto(final Connection_ connection, final ByteBuf buffer, final Object message)
        throws IOException {
    // required by RMI and some serializers to determine which connection wrote (or has info about) this object
    this.rmiSupport = connection.rmiSupport();

    ByteBuf objectOutputBuffer = this.tempBuffer;
    objectOutputBuffer.clear(); // always have to reset everything

    // write the object to a TEMP buffer! this will be compressed
    writer.setBuffer(objectOutputBuffer);

    writeClassAndObject(writer, message);

    // save off how much data the object took
    int length = objectOutputBuffer.writerIndex();

    // NOTE: compression and encryption MUST work with byte[] because they use JNI!
    // Realistically, it is impossible to get the backing arrays out of a Heap Buffer once they are resized and begin to use
    // sliced. It's lame that there is a "double copy" of bytes here, but I don't know how to avoid it...
    // see:   https://stackoverflow.com/questions/19296386/netty-java-getting-data-from-bytebuf

    byte[] inputArray;
    int inputOffset;

    // Even if a ByteBuf has a backing array (i.e. buf.hasArray() returns true), the using it isn't always possible because
    // the buffer might be a slice of other buffer or a pooled buffer:
    //noinspection Duplicates
    if (objectOutputBuffer.hasArray() && objectOutputBuffer.array()[0] == objectOutputBuffer.getByte(0)
            && objectOutputBuffer.array().length == objectOutputBuffer.capacity()) {

        // we can use it...
        inputArray = objectOutputBuffer.array();
        inputArrayLength = -1; // this is so we don't REUSE this array accidentally!
        inputOffset = objectOutputBuffer.arrayOffset();
    } else {//from   w ww .j a  v a  2s  .c  o m
        // we can NOT use it.
        if (length > inputArrayLength) {
            inputArrayLength = length;
            inputArray = new byte[length];
            this.inputArray = inputArray;
        } else {
            inputArray = this.inputArray;
        }

        objectOutputBuffer.getBytes(objectOutputBuffer.readerIndex(), inputArray, 0, length);
        inputOffset = 0;
    }

    ////////// compressing data
    // we ALWAYS compress our data stream -- because of how AES-GCM pads data out, the small input (that would result in a larger
    // output), will be negated by the increase in size by the encryption

    byte[] compressOutput = this.compressOutput;

    int maxLengthLengthOffset = 4; // length is never negative, so 4 is OK (5 means it's negative)
    int maxCompressedLength = compressor.maxCompressedLength(length);

    // add 4 so there is room to write the compressed size to the buffer
    int maxCompressedLengthWithOffset = maxCompressedLength + maxLengthLengthOffset;

    // lazy initialize the compression output buffer
    if (maxCompressedLengthWithOffset > compressOutputLength) {
        compressOutputLength = maxCompressedLengthWithOffset;
        compressOutput = new byte[maxCompressedLengthWithOffset];
        this.compressOutput = compressOutput;
    }

    // LZ4 compress. output offset max 4 bytes to leave room for length of tempOutput data
    int compressedLength = compressor.compress(inputArray, inputOffset, length, compressOutput,
            maxLengthLengthOffset, maxCompressedLength);

    // bytes can now be written to, because our compressed data is stored in a temp array.

    final int lengthLength = OptimizeUtilsByteArray.intLength(length, true);

    // correct input.  compression output is now encryption input
    inputArray = compressOutput;
    inputOffset = maxLengthLengthOffset - lengthLength;

    // now write the ORIGINAL (uncompressed) length to the front of the byte array. This is so we can use the FAST decompress version
    OptimizeUtilsByteArray.writeInt(inputArray, length, true, inputOffset);

    // correct length for encryption
    length = compressedLength + lengthLength; // +1 to +4 for the uncompressed size bytes

    /////// encrypting data.
    final long nextGcmSequence = connection.getNextGcmSequence();

    // this is a threadlocal, so that we don't clobber other threads that are performing crypto on the same connection at the same time
    final ParametersWithIV cryptoParameters = connection.getCryptoParameters();
    BigEndian.Long_.toBytes(nextGcmSequence, cryptoParameters.getIV(), 4); // put our counter into the IV

    final GCMBlockCipher aes = this.aesEngine;
    aes.reset();
    aes.init(true, cryptoParameters);

    byte[] cryptoOutput;

    // lazy initialize the crypto output buffer
    int cryptoSize = length + 16; // from:  aes.getOutputSize(length);

    // 'output' is the temp byte array
    if (cryptoSize > cryptoOutputLength) {
        cryptoOutputLength = cryptoSize;
        cryptoOutput = new byte[cryptoSize];
        this.cryptoOutput = cryptoOutput;
    } else {
        cryptoOutput = this.cryptoOutput;
    }

    int encryptedLength = aes.processBytes(inputArray, inputOffset, length, cryptoOutput, 0);

    try {
        // authentication tag for GCM
        encryptedLength += aes.doFinal(cryptoOutput, encryptedLength);
    } catch (Exception e) {
        throw new IOException("Unable to AES encrypt the data", e);
    }

    // write out our GCM counter
    OptimizeUtilsByteBuf.writeLong(buffer, nextGcmSequence, true);

    // have to copy over the orig data, because we used the temp buffer
    buffer.writeBytes(cryptoOutput, 0, encryptedLength);
}

From source file:dorkbox.network.pipeline.ByteBufInput.java

License:Apache License

/**
 * Returns true if enough bytes are available to read an int with {@link #readInt(boolean)}.
 *///  ww w  . j a v  a  2  s .  c om
@Override
public boolean canReadInt() throws KryoException {
    ByteBuf buffer = byteBuf;
    int limit = buffer.writerIndex();

    if (limit - buffer.readerIndex() >= 5) {
        return true;
    }

    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    return true;
}

From source file:dorkbox.network.pipeline.ByteBufInput.java

License:Apache License

/**
 * Returns true if enough bytes are available to read a long with {@link #readLong(boolean)}.
 *//*from   w  w  w  .  java 2 s.c  o m*/
@Override
public boolean canReadLong() throws KryoException {
    ByteBuf buffer = byteBuf;
    int limit = buffer.writerIndex();

    if (limit - buffer.readerIndex() >= 9) {
        return true;
    }

    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    if ((buffer.readByte() & 0x80) == 0) {
        return true;
    }
    if (buffer.readerIndex() == limit) {
        return false;
    }
    return true;
}

From source file:dorkbox.network.pipeline.ByteBufOutput.java

License:Apache License

public final void setBuffer(ByteBuf byteBuf) {
    this.byteBuf = byteBuf;

    if (byteBuf != null) {
        this.byteBuf.readerIndex(0);
        startIndex = byteBuf.writerIndex();
    } else {/*from  ww w  .  ja va2s.  c  o m*/
        startIndex = 0;
    }
}

From source file:dorkbox.network.pipeline.ByteBufOutput.java

License:Apache License

/** Writes the length and string, or null. Short strings are checked and if ASCII they are written more efficiently, else they
 * are written as UTF8. If a string is known to be ASCII, {@link #writeAscii(String)} may be used. The string can be read using
 * {@link ByteBufInput#readString()} or {@link ByteBufInput#readStringBuilder()}.
 * @param value May be null. *///w  w w .  ja v  a  2s  . c  o m
@Override
public void writeString(String value) throws KryoException {
    if (value == null) {
        writeByte(0x80); // 0 means null, bit 8 means UTF8.
        return;
    }
    int charCount = value.length();
    if (charCount == 0) {
        writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8.
        return;
    }
    // Detect ASCII.
    boolean ascii = false;
    if (charCount > 1 && charCount < 64) { // only snoop 64 chars in
        ascii = true;
        for (int i = 0; i < charCount; i++) {
            int c = value.charAt(i);
            if (c > 127) {
                ascii = false;
                break;
            }
        }
    }

    ByteBuf buffer = byteBuf;
    if (buffer.writableBytes() < charCount) {
        buffer.capacity(buffer.capacity() + charCount + 1);
    }

    if (!ascii) {
        writeUtf8Length(charCount + 1);
    }

    int charIndex = 0;
    // Try to write 8 bit chars.
    for (; charIndex < charCount; charIndex++) {
        int c = value.charAt(charIndex);
        if (c > 127) {
            break; // whoops! detect ascii. have to continue with a slower method!
        }
        buffer.writeByte((byte) c);
    }
    if (charIndex < charCount) {
        writeString_slow(value, charCount, charIndex);
    } else if (ascii) {
        // specify it's ASCII
        int i = buffer.writerIndex() - 1;
        buffer.setByte(i, buffer.getByte(i) | 0x80); // Bit 8 means end of ASCII.
    }
}

From source file:dorkbox.network.pipeline.ByteBufOutput.java

License:Apache License

/** Writes a string that is known to contain only ASCII characters. Non-ASCII strings passed to this method will be corrupted.
 * Each byte is a 7 bit character with the remaining byte denoting if another character is available. This is slightly more
 * efficient than {@link #writeString(String)}. The string can be read using {@link ByteBufInput#readString()} or
 * {@link ByteBufInput#readStringBuilder()}.
 * @param value May be null. *//*from   w  ww  .j a v  a 2s . c  o m*/
@Override
public void writeAscii(String value) throws KryoException {
    if (value == null) {
        writeByte(0x80); // 0 means null, bit 8 means UTF8.
        return;
    }
    int charCount = value.length();
    if (charCount == 0) {
        writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8.
        return;
    }

    ByteBuf buffer = byteBuf;
    if (buffer.writableBytes() < charCount) {
        buffer.capacity(buffer.capacity() + charCount + 1);
    }

    int charIndex = 0;
    // Try to write 8 bit chars.
    for (; charIndex < charCount; charIndex++) {
        int c = value.charAt(charIndex);
        buffer.writeByte((byte) c);
    }
    // specify it's ASCII
    int i = buffer.writerIndex() - 1;
    buffer.setByte(i, buffer.getByte(i) | 0x80); // Bit 8 means end of ASCII.
}