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 }