Add multiple channel pipeline handlers in SwiftNIO similarly as Java Netty
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
add a comment |
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
add a comment |
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
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
ios swift swift-nio
asked Nov 22 '18 at 12:13
Rui HuangRui Huang
1721111
1721111
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Right, let me go through all the handlers you add to your pipeline in Netty:
IdleStateHandler
: available withimport NIO
from theswift-nio
package
LengthFieldBasedFrameDecoder
: right now in a PR but will be available shortly throughimport NIOExtras
from theswift-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)
}
}
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Right, let me go through all the handlers you add to your pipeline in Netty:
IdleStateHandler
: available withimport NIO
from theswift-nio
package
LengthFieldBasedFrameDecoder
: right now in a PR but will be available shortly throughimport NIOExtras
from theswift-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)
}
}
}
add a comment |
Right, let me go through all the handlers you add to your pipeline in Netty:
IdleStateHandler
: available withimport NIO
from theswift-nio
package
LengthFieldBasedFrameDecoder
: right now in a PR but will be available shortly throughimport NIOExtras
from theswift-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)
}
}
}
add a comment |
Right, let me go through all the handlers you add to your pipeline in Netty:
IdleStateHandler
: available withimport NIO
from theswift-nio
package
LengthFieldBasedFrameDecoder
: right now in a PR but will be available shortly throughimport NIOExtras
from theswift-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)
}
}
}
Right, let me go through all the handlers you add to your pipeline in Netty:
IdleStateHandler
: available withimport NIO
from theswift-nio
package
LengthFieldBasedFrameDecoder
: right now in a PR but will be available shortly throughimport NIOExtras
from theswift-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)
}
}
}
answered Nov 22 '18 at 15:12
Johannes WeissJohannes Weiss
39.4k1483120
39.4k1483120
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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