1 /* 2 * Collie - An asynchronous event-driven network framework using Dlang development 3 * 4 * Copyright (C) 2015-2017 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: putao's Dlang team 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 module collie.channel.handler; 12 13 import std.traits; 14 15 import collie.channel.pipeline; 16 import collie.channel.handlercontext; 17 public import kiss.net.struct_; 18 19 abstract class HandlerBase(Context) 20 { 21 22 ~this() 23 { 24 } 25 26 void attachPipeline(Context /*ctx*/ ) 27 { 28 } 29 30 void detachPipeline(Context /*ctx*/ ) 31 { 32 } 33 34 final @property Context context() 35 { 36 if (_attachCount != 1) 37 { 38 return null; 39 } 40 assert(_ctx); 41 return _ctx; 42 } 43 44 protected: 45 ulong _attachCount = 0; 46 Context _ctx; 47 } 48 /// Rin : the Handle will read type 49 /// Rout : Next Handle will Read Type 50 /// Win : the Handle will Write type 51 /// Wout : Next Handle will write type 52 53 abstract class Handler(Rin, Rout = Rin, Win = Rout, Wout = Rin) : HandlerBase!( 54 HandlerContext!(Rout, Wout)) 55 { 56 alias TheCallBack = void delegate(Win, size_t); 57 alias Context = HandlerContext!(Rout, Wout); 58 59 alias rin = Rin; 60 alias rout = Rout; 61 alias win = Win; 62 alias wout = Wout; 63 64 static enum dir = HandlerDir.BOTH; 65 66 void read(Context ctx, Rin msg); 67 68 void timeOut(Context ctx) 69 { 70 ctx.fireTimeOut(); 71 } 72 73 void transportActive(Context ctx) 74 { 75 ctx.fireTransportActive(); 76 } 77 78 void transportInactive(Context ctx) 79 { 80 ctx.fireTransportInactive(); 81 } 82 83 void write(Context ctx, Win msg, TheCallBack cback = null); 84 85 void close(Context ctx) 86 { 87 ctx.fireClose(); 88 } 89 } 90 91 /// Rin : the Handle will read type 92 /// Rout : Next Handle will Read Type 93 abstract class InboundHandler(Rin, Rout = Rin) : HandlerBase!(InboundHandlerContext!Rout) 94 { 95 public: 96 static enum dir = HandlerDir.IN; 97 98 alias Context = InboundHandlerContext!Rout; 99 alias rin = Rin; 100 alias rout = Rout; 101 alias win = uint; 102 alias wout = uint; 103 104 void read(Context ctx, Rin msg); 105 106 void timeOut(Context ctx) 107 { 108 ctx.fireTimeOut(); 109 } 110 111 void transportActive(Context ctx) 112 { 113 ctx.fireTransportActive(); 114 } 115 116 void transportInactive(Context ctx) 117 { 118 ctx.fireTransportInactive(); 119 } 120 121 } 122 123 /// Win : the Handle will Write type 124 /// Wout : Next Handle will write type 125 abstract class OutboundHandler(Win, Wout = Win) : HandlerBase!(OutboundHandlerContext!Wout) 126 { 127 public: 128 static enum dir = HandlerDir.OUT; 129 130 alias Context = OutboundHandlerContext!Wout; 131 alias OutboundHandlerCallBack = void delegate(Win, size_t); 132 133 alias rin = uint; 134 alias rout = uint; 135 alias win = Win; 136 alias wout = Wout; 137 138 void write(Context ctx, Win msg, OutboundHandlerCallBack cback = null); 139 140 void close(Context ctx) 141 { 142 return ctx.fireClose(); 143 } 144 } 145 146 class HandlerAdapter(R, W = R) : Handler!(R, R, W, W) 147 { 148 alias Context = Handler!(R, R, W, W).Context; 149 alias TheCallBack = Handler!(R, R, W, W).TheCallBack; 150 151 override void read(Context ctx, R msg) 152 { 153 ctx.fireRead((msg)); 154 } 155 156 override void write(Context ctx, W msg, TheCallBack cback) 157 { 158 ctx.fireWrite(msg, cback); 159 } 160 } 161 162 abstract class PipelineContext 163 { 164 public: 165 ~this() 166 { 167 // writeln("PipelineContext ~ this"); 168 } 169 170 void attachPipeline(); 171 void detachPipeline(); 172 173 pragma(inline) 174 final void attachContext(H, HandlerContext)(H handler, HandlerContext ctx) 175 { 176 if (++handler._attachCount == 1) 177 { 178 handler._ctx = ctx; 179 } 180 else 181 { 182 handler._ctx = null; 183 } 184 } 185 186 void setNextIn(PipelineContext ctx); 187 void setNextOut(PipelineContext ctx); 188 189 HandlerDir getDirection(); 190 } 191 192 package: 193 194 interface InboundLink(In) 195 { 196 void read(In msg); 197 void timeOut(); 198 void transportActive(); 199 void transportInactive(); 200 } 201 202 interface OutboundLink(Out) 203 { 204 alias OutboundLinkCallBack = void delegate(Out, size_t); 205 void write(Out msg, OutboundLinkCallBack cback = null); 206 void close(); 207 }