Add multiple channel pipeline handlers in SwiftNIO similarly as Java Netty












0















I am exploring how to add multiple handlers in channel pipelines in SwiftNIO. In Java Netty, I have the following code:



@Component
public class NettyClientFilter extends ChannelInitializer<SocketChannel> {

@Autowired
private NettyClientHandler nettyClientHandler;

@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline ph = ch.pipeline();

ph.addLast(new IdleStateHandler(20, 10, 0));
ph.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));

ph.addLast(new ProtobufDecoder(IMessage.getDefaultInstance()));

ph.addLast(new LengthFieldPrepender(4));
ph.addLast(new ProtobufEncoder());
ph.addLast("nettyClientHandler",nettyClientHandler);

}
}


In the SwiftNIO, seems there are no similar classes as "LengthFieldBasedFrameDecoder", "ProtobufDecoder", "LengthFieldPrepender", "ProtobufEncoder". How can I get those ones in SwiftNIO?










share|improve this question



























    0















    I am exploring how to add multiple handlers in channel pipelines in SwiftNIO. In Java Netty, I have the following code:



    @Component
    public class NettyClientFilter extends ChannelInitializer<SocketChannel> {

    @Autowired
    private NettyClientHandler nettyClientHandler;

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline ph = ch.pipeline();

    ph.addLast(new IdleStateHandler(20, 10, 0));
    ph.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));

    ph.addLast(new ProtobufDecoder(IMessage.getDefaultInstance()));

    ph.addLast(new LengthFieldPrepender(4));
    ph.addLast(new ProtobufEncoder());
    ph.addLast("nettyClientHandler",nettyClientHandler);

    }
    }


    In the SwiftNIO, seems there are no similar classes as "LengthFieldBasedFrameDecoder", "ProtobufDecoder", "LengthFieldPrepender", "ProtobufEncoder". How can I get those ones in SwiftNIO?










    share|improve this question

























      0












      0








      0


      1






      I am exploring how to add multiple handlers in channel pipelines in SwiftNIO. In Java Netty, I have the following code:



      @Component
      public class NettyClientFilter extends ChannelInitializer<SocketChannel> {

      @Autowired
      private NettyClientHandler nettyClientHandler;

      @Override
      protected void initChannel(SocketChannel ch) throws Exception {
      ChannelPipeline ph = ch.pipeline();

      ph.addLast(new IdleStateHandler(20, 10, 0));
      ph.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));

      ph.addLast(new ProtobufDecoder(IMessage.getDefaultInstance()));

      ph.addLast(new LengthFieldPrepender(4));
      ph.addLast(new ProtobufEncoder());
      ph.addLast("nettyClientHandler",nettyClientHandler);

      }
      }


      In the SwiftNIO, seems there are no similar classes as "LengthFieldBasedFrameDecoder", "ProtobufDecoder", "LengthFieldPrepender", "ProtobufEncoder". How can I get those ones in SwiftNIO?










      share|improve this question














      I am exploring how to add multiple handlers in channel pipelines in SwiftNIO. In Java Netty, I have the following code:



      @Component
      public class NettyClientFilter extends ChannelInitializer<SocketChannel> {

      @Autowired
      private NettyClientHandler nettyClientHandler;

      @Override
      protected void initChannel(SocketChannel ch) throws Exception {
      ChannelPipeline ph = ch.pipeline();

      ph.addLast(new IdleStateHandler(20, 10, 0));
      ph.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));

      ph.addLast(new ProtobufDecoder(IMessage.getDefaultInstance()));

      ph.addLast(new LengthFieldPrepender(4));
      ph.addLast(new ProtobufEncoder());
      ph.addLast("nettyClientHandler",nettyClientHandler);

      }
      }


      In the SwiftNIO, seems there are no similar classes as "LengthFieldBasedFrameDecoder", "ProtobufDecoder", "LengthFieldPrepender", "ProtobufEncoder". How can I get those ones in SwiftNIO?







      ios swift swift-nio






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 22 '18 at 12:13









      Rui HuangRui Huang

      1721111




      1721111
























          1 Answer
          1






          active

          oldest

          votes


















          2














          Right, let me go through all the handlers you add to your pipeline in Netty:





          • IdleStateHandler: available with import NIO from the swift-nio package


          • LengthFieldBasedFrameDecoder: right now in a PR but will be available shortly through import NIOExtras from the swift-nio-extras package


          • ProtobufDecoder, LengthFieldPrepender, ProtobufEncoder: all currently unavailable but straightforward to implement:


          LengthFieldPrepender:



              final class LengthFieldPrepender<IntType: FixedWidthInteger>: ChannelOutboundHandler {
          // we send send and receive ByteBuffers
          typealias OutboundIn = ByteBuffer
          typealias OutboundOut = ByteBuffer

          private let endianness: Endianness
          private var buf: ByteBuffer?

          init(type: IntType.Type = IntType.self, endianness: Endianness = .big) {
          self.endianness = endianness
          }

          func handlerAdded(ctx: ChannelHandlerContext) {
          self.buf = ctx.channel.allocator.buffer(capacity: 8)
          }

          func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
          let incomingData = self.unwrapOutboundIn(data)

          // we cache `self.buf` so we might get lucky and save an allocation here if the previous buffer has been fully written already
          self.buf!.clear()
          // write the length as the right type
          self.buf!.write(integer: IntType(incomingData.readableBytes), endianness: self.endianness)
          ctx.write(self.wrapOutboundOut(self.buf!), promise: nil)
          // write the actual data
          ctx.write(data, promise: promise)
          }
          }


          ProtobufDecoder:



              import SwiftProtobuf
          import NIOFoundationCompat // for ByteBuffer.readData

          final class ProtobufDecoder<Msg: SwiftProtobuf.Message>: ChannelInboundHandler {
          typealias InboundIn = ByteBuffer
          typealias InboundOut = Msg

          func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
          var buffer = self.unwrapInboundIn(data)
          let data = buffer.readData(length: buffer.readableBytes)!
          do {
          // pretty straightforward here, just call the message type's initialiser
          let req = try Msg(serializedData: data)
          ctx.fireChannelRead(self.wrapInboundOut(req))
          } catch {
          ctx.fireErrorCaught(error)
          }
          }
          }


          ProtobufEncoder:



              import NIOFoundationCompat
          import SwiftProtobuf

          final class ProtobufEncoder<Msg: SwiftProtobuf.Message>: ChannelOutboundHandler {
          typealias OutboundIn = Msg
          typealias OutboundOut = ByteBuffer

          private var buf: ByteBuffer?

          func handlerAdded(ctx: ChannelHandlerContext) {
          self.buf = ctx.channel.allocator.buffer(capacity: 4096)
          }

          func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
          let msg = self.unwrapOutboundIn(data)
          self.buf!.clear()
          do {
          // just use SwiftProtobuf's nice encoder
          self.buf!.write(bytes: try msg.serializedData())
          ctx.write(self.wrapOutboundOut(self.buf!), promise: promise)
          } catch {
          ctx.fireErrorCaught(error)
          }
          }
          }





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53430784%2fadd-multiple-channel-pipeline-handlers-in-swiftnio-similarly-as-java-netty%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            Right, let me go through all the handlers you add to your pipeline in Netty:





            • IdleStateHandler: available with import NIO from the swift-nio package


            • LengthFieldBasedFrameDecoder: right now in a PR but will be available shortly through import NIOExtras from the swift-nio-extras package


            • ProtobufDecoder, LengthFieldPrepender, ProtobufEncoder: all currently unavailable but straightforward to implement:


            LengthFieldPrepender:



                final class LengthFieldPrepender<IntType: FixedWidthInteger>: ChannelOutboundHandler {
            // we send send and receive ByteBuffers
            typealias OutboundIn = ByteBuffer
            typealias OutboundOut = ByteBuffer

            private let endianness: Endianness
            private var buf: ByteBuffer?

            init(type: IntType.Type = IntType.self, endianness: Endianness = .big) {
            self.endianness = endianness
            }

            func handlerAdded(ctx: ChannelHandlerContext) {
            self.buf = ctx.channel.allocator.buffer(capacity: 8)
            }

            func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
            let incomingData = self.unwrapOutboundIn(data)

            // we cache `self.buf` so we might get lucky and save an allocation here if the previous buffer has been fully written already
            self.buf!.clear()
            // write the length as the right type
            self.buf!.write(integer: IntType(incomingData.readableBytes), endianness: self.endianness)
            ctx.write(self.wrapOutboundOut(self.buf!), promise: nil)
            // write the actual data
            ctx.write(data, promise: promise)
            }
            }


            ProtobufDecoder:



                import SwiftProtobuf
            import NIOFoundationCompat // for ByteBuffer.readData

            final class ProtobufDecoder<Msg: SwiftProtobuf.Message>: ChannelInboundHandler {
            typealias InboundIn = ByteBuffer
            typealias InboundOut = Msg

            func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
            var buffer = self.unwrapInboundIn(data)
            let data = buffer.readData(length: buffer.readableBytes)!
            do {
            // pretty straightforward here, just call the message type's initialiser
            let req = try Msg(serializedData: data)
            ctx.fireChannelRead(self.wrapInboundOut(req))
            } catch {
            ctx.fireErrorCaught(error)
            }
            }
            }


            ProtobufEncoder:



                import NIOFoundationCompat
            import SwiftProtobuf

            final class ProtobufEncoder<Msg: SwiftProtobuf.Message>: ChannelOutboundHandler {
            typealias OutboundIn = Msg
            typealias OutboundOut = ByteBuffer

            private var buf: ByteBuffer?

            func handlerAdded(ctx: ChannelHandlerContext) {
            self.buf = ctx.channel.allocator.buffer(capacity: 4096)
            }

            func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
            let msg = self.unwrapOutboundIn(data)
            self.buf!.clear()
            do {
            // just use SwiftProtobuf's nice encoder
            self.buf!.write(bytes: try msg.serializedData())
            ctx.write(self.wrapOutboundOut(self.buf!), promise: promise)
            } catch {
            ctx.fireErrorCaught(error)
            }
            }
            }





            share|improve this answer




























              2














              Right, let me go through all the handlers you add to your pipeline in Netty:





              • IdleStateHandler: available with import NIO from the swift-nio package


              • LengthFieldBasedFrameDecoder: right now in a PR but will be available shortly through import NIOExtras from the swift-nio-extras package


              • ProtobufDecoder, LengthFieldPrepender, ProtobufEncoder: all currently unavailable but straightforward to implement:


              LengthFieldPrepender:



                  final class LengthFieldPrepender<IntType: FixedWidthInteger>: ChannelOutboundHandler {
              // we send send and receive ByteBuffers
              typealias OutboundIn = ByteBuffer
              typealias OutboundOut = ByteBuffer

              private let endianness: Endianness
              private var buf: ByteBuffer?

              init(type: IntType.Type = IntType.self, endianness: Endianness = .big) {
              self.endianness = endianness
              }

              func handlerAdded(ctx: ChannelHandlerContext) {
              self.buf = ctx.channel.allocator.buffer(capacity: 8)
              }

              func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
              let incomingData = self.unwrapOutboundIn(data)

              // we cache `self.buf` so we might get lucky and save an allocation here if the previous buffer has been fully written already
              self.buf!.clear()
              // write the length as the right type
              self.buf!.write(integer: IntType(incomingData.readableBytes), endianness: self.endianness)
              ctx.write(self.wrapOutboundOut(self.buf!), promise: nil)
              // write the actual data
              ctx.write(data, promise: promise)
              }
              }


              ProtobufDecoder:



                  import SwiftProtobuf
              import NIOFoundationCompat // for ByteBuffer.readData

              final class ProtobufDecoder<Msg: SwiftProtobuf.Message>: ChannelInboundHandler {
              typealias InboundIn = ByteBuffer
              typealias InboundOut = Msg

              func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
              var buffer = self.unwrapInboundIn(data)
              let data = buffer.readData(length: buffer.readableBytes)!
              do {
              // pretty straightforward here, just call the message type's initialiser
              let req = try Msg(serializedData: data)
              ctx.fireChannelRead(self.wrapInboundOut(req))
              } catch {
              ctx.fireErrorCaught(error)
              }
              }
              }


              ProtobufEncoder:



                  import NIOFoundationCompat
              import SwiftProtobuf

              final class ProtobufEncoder<Msg: SwiftProtobuf.Message>: ChannelOutboundHandler {
              typealias OutboundIn = Msg
              typealias OutboundOut = ByteBuffer

              private var buf: ByteBuffer?

              func handlerAdded(ctx: ChannelHandlerContext) {
              self.buf = ctx.channel.allocator.buffer(capacity: 4096)
              }

              func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
              let msg = self.unwrapOutboundIn(data)
              self.buf!.clear()
              do {
              // just use SwiftProtobuf's nice encoder
              self.buf!.write(bytes: try msg.serializedData())
              ctx.write(self.wrapOutboundOut(self.buf!), promise: promise)
              } catch {
              ctx.fireErrorCaught(error)
              }
              }
              }





              share|improve this answer


























                2












                2








                2







                Right, let me go through all the handlers you add to your pipeline in Netty:





                • IdleStateHandler: available with import NIO from the swift-nio package


                • LengthFieldBasedFrameDecoder: right now in a PR but will be available shortly through import NIOExtras from the swift-nio-extras package


                • ProtobufDecoder, LengthFieldPrepender, ProtobufEncoder: all currently unavailable but straightforward to implement:


                LengthFieldPrepender:



                    final class LengthFieldPrepender<IntType: FixedWidthInteger>: ChannelOutboundHandler {
                // we send send and receive ByteBuffers
                typealias OutboundIn = ByteBuffer
                typealias OutboundOut = ByteBuffer

                private let endianness: Endianness
                private var buf: ByteBuffer?

                init(type: IntType.Type = IntType.self, endianness: Endianness = .big) {
                self.endianness = endianness
                }

                func handlerAdded(ctx: ChannelHandlerContext) {
                self.buf = ctx.channel.allocator.buffer(capacity: 8)
                }

                func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
                let incomingData = self.unwrapOutboundIn(data)

                // we cache `self.buf` so we might get lucky and save an allocation here if the previous buffer has been fully written already
                self.buf!.clear()
                // write the length as the right type
                self.buf!.write(integer: IntType(incomingData.readableBytes), endianness: self.endianness)
                ctx.write(self.wrapOutboundOut(self.buf!), promise: nil)
                // write the actual data
                ctx.write(data, promise: promise)
                }
                }


                ProtobufDecoder:



                    import SwiftProtobuf
                import NIOFoundationCompat // for ByteBuffer.readData

                final class ProtobufDecoder<Msg: SwiftProtobuf.Message>: ChannelInboundHandler {
                typealias InboundIn = ByteBuffer
                typealias InboundOut = Msg

                func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
                var buffer = self.unwrapInboundIn(data)
                let data = buffer.readData(length: buffer.readableBytes)!
                do {
                // pretty straightforward here, just call the message type's initialiser
                let req = try Msg(serializedData: data)
                ctx.fireChannelRead(self.wrapInboundOut(req))
                } catch {
                ctx.fireErrorCaught(error)
                }
                }
                }


                ProtobufEncoder:



                    import NIOFoundationCompat
                import SwiftProtobuf

                final class ProtobufEncoder<Msg: SwiftProtobuf.Message>: ChannelOutboundHandler {
                typealias OutboundIn = Msg
                typealias OutboundOut = ByteBuffer

                private var buf: ByteBuffer?

                func handlerAdded(ctx: ChannelHandlerContext) {
                self.buf = ctx.channel.allocator.buffer(capacity: 4096)
                }

                func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
                let msg = self.unwrapOutboundIn(data)
                self.buf!.clear()
                do {
                // just use SwiftProtobuf's nice encoder
                self.buf!.write(bytes: try msg.serializedData())
                ctx.write(self.wrapOutboundOut(self.buf!), promise: promise)
                } catch {
                ctx.fireErrorCaught(error)
                }
                }
                }





                share|improve this answer













                Right, let me go through all the handlers you add to your pipeline in Netty:





                • IdleStateHandler: available with import NIO from the swift-nio package


                • LengthFieldBasedFrameDecoder: right now in a PR but will be available shortly through import NIOExtras from the swift-nio-extras package


                • ProtobufDecoder, LengthFieldPrepender, ProtobufEncoder: all currently unavailable but straightforward to implement:


                LengthFieldPrepender:



                    final class LengthFieldPrepender<IntType: FixedWidthInteger>: ChannelOutboundHandler {
                // we send send and receive ByteBuffers
                typealias OutboundIn = ByteBuffer
                typealias OutboundOut = ByteBuffer

                private let endianness: Endianness
                private var buf: ByteBuffer?

                init(type: IntType.Type = IntType.self, endianness: Endianness = .big) {
                self.endianness = endianness
                }

                func handlerAdded(ctx: ChannelHandlerContext) {
                self.buf = ctx.channel.allocator.buffer(capacity: 8)
                }

                func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
                let incomingData = self.unwrapOutboundIn(data)

                // we cache `self.buf` so we might get lucky and save an allocation here if the previous buffer has been fully written already
                self.buf!.clear()
                // write the length as the right type
                self.buf!.write(integer: IntType(incomingData.readableBytes), endianness: self.endianness)
                ctx.write(self.wrapOutboundOut(self.buf!), promise: nil)
                // write the actual data
                ctx.write(data, promise: promise)
                }
                }


                ProtobufDecoder:



                    import SwiftProtobuf
                import NIOFoundationCompat // for ByteBuffer.readData

                final class ProtobufDecoder<Msg: SwiftProtobuf.Message>: ChannelInboundHandler {
                typealias InboundIn = ByteBuffer
                typealias InboundOut = Msg

                func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
                var buffer = self.unwrapInboundIn(data)
                let data = buffer.readData(length: buffer.readableBytes)!
                do {
                // pretty straightforward here, just call the message type's initialiser
                let req = try Msg(serializedData: data)
                ctx.fireChannelRead(self.wrapInboundOut(req))
                } catch {
                ctx.fireErrorCaught(error)
                }
                }
                }


                ProtobufEncoder:



                    import NIOFoundationCompat
                import SwiftProtobuf

                final class ProtobufEncoder<Msg: SwiftProtobuf.Message>: ChannelOutboundHandler {
                typealias OutboundIn = Msg
                typealias OutboundOut = ByteBuffer

                private var buf: ByteBuffer?

                func handlerAdded(ctx: ChannelHandlerContext) {
                self.buf = ctx.channel.allocator.buffer(capacity: 4096)
                }

                func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
                let msg = self.unwrapOutboundIn(data)
                self.buf!.clear()
                do {
                // just use SwiftProtobuf's nice encoder
                self.buf!.write(bytes: try msg.serializedData())
                ctx.write(self.wrapOutboundOut(self.buf!), promise: promise)
                } catch {
                ctx.fireErrorCaught(error)
                }
                }
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 22 '18 at 15:12









                Johannes WeissJohannes Weiss

                39.4k1483120




                39.4k1483120
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53430784%2fadd-multiple-channel-pipeline-handlers-in-swiftnio-similarly-as-java-netty%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                    Alcedinidae

                    Origin of the phrase “under your belt”?