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.bootstrap.client; 12 13 import collie.channel; 14 import collie.net; 15 import collie.utils.memory; 16 17 import collie.bootstrap.exception; 18 import collie.net.client.linklogInfo; 19 public import kiss.net.TcpStream; 20 import kiss.event.task; 21 22 final class ClientBootstrap(PipeLine) : PipelineManager 23 { 24 alias ConnCallBack = void delegate(PipeLine); 25 alias LinklogInfo = TLinklogInfo!ConnCallBack; 26 alias ClientCreatorCallBack = void delegate(TcpStream); 27 28 this(EventLoop loop) 29 { 30 _loop = loop; 31 } 32 33 ~this() 34 { 35 if (_timer) 36 _timer.destroy; 37 if(_logInfo.client) 38 _logInfo.client.destroy; 39 } 40 41 void setClientCreatorCallBack(ClientCreatorCallBack cback) 42 { 43 _oncreator = cback; 44 } 45 46 auto pipelineFactory(shared PipelineFactory!PipeLine pipeFactory) 47 { 48 _pipelineFactory = pipeFactory; 49 return this; 50 } 51 52 /// time is s 53 auto heartbeatTimeOut(uint second) 54 { 55 _timeOut = second * 1000; 56 return this; 57 } 58 59 void connect(Address to, ConnCallBack cback = null) 60 { 61 if (_pipelineFactory is null) 62 throw new NeedPipeFactoryException( 63 "Pipeline must be not null! Please set Pipeline frist!"); 64 if (_logInfo.client) 65 throw new ConnectedException("This Socket is Connected! Please close before connect!"); 66 _logInfo.addr = to; 67 _logInfo.tryCount = 0; 68 _logInfo.cback = cback; 69 _loop.postTask(newTask(&doConnect)); 70 } 71 72 void close() 73 { 74 if (_logInfo.client is null) 75 return; 76 _logInfo.client.close(); 77 } 78 79 @property EventLoop eventLoop() 80 { 81 return _loop; 82 } 83 84 @property auto pipeLine() 85 { 86 if(_logInfo.client is null) 87 return null; 88 return _pipe; 89 } 90 91 @property tryCount(){return _tryCount;} 92 @property tryCount(uint count){_tryCount = count;} 93 94 protected: 95 void doConnect() 96 { 97 _logInfo.client = new TcpStream(_loop,_logInfo.addr.addressFamily); 98 if(_oncreator) 99 _oncreator(_logInfo.client); 100 _logInfo.client.setCloseHandle(&closeCallBack); 101 _logInfo.client.setConnectHandle(&connectCallBack); 102 _logInfo.client.setReadHandle(&readCallBack); 103 _logInfo.client.connect(_logInfo.addr); 104 } 105 106 void closeCallBack() nothrow @trusted 107 { 108 catchAndLogException((){ 109 if (_timer) 110 _timer.stop(); 111 if(_pipe) 112 _pipe.transportInactive(); 113 }()); 114 } 115 116 void connectCallBack(bool isconnect) nothrow @trusted 117 { 118 catchAndLogException((){ 119 if (isconnect) 120 { 121 if (_timeOut > 0) 122 { 123 if (_timer is null) 124 { 125 logDebug("new timer!"); 126 _timer = new Timer(_loop); 127 _timer.setTimerHandle(&onTimeOut); 128 } 129 if(!_timer.watched) { 130 131 bool rv = _timer.start(_timeOut); 132 logDebug("start timer! : ", rv); 133 } 134 } 135 _logInfo.tryCount = 0; 136 _pipe = _pipelineFactory.newPipeline(_logInfo.client); 137 if(_logInfo.cback) 138 _logInfo.cback(_pipe); 139 _pipe.finalize(); 140 _pipe.pipelineManager(this); 141 _pipe.transportActive(); 142 }else if(_logInfo.tryCount < _tryCount){ 143 _logInfo.client = null; 144 _logInfo.tryCount ++; 145 doConnect(); 146 } else { 147 if(_logInfo.cback) 148 _logInfo.cback(null); 149 _logInfo.client = null; 150 _logInfo.cback = null; 151 _logInfo.addr = null; 152 _pipe = null; 153 } 154 }()); 155 } 156 157 void readCallBack(in ubyte[] buffer) nothrow @trusted 158 { 159 catchAndLogException(_pipe.read(cast(ubyte[])buffer)); 160 } 161 /// Client Time out is not refresh! 162 void onTimeOut() nothrow @trusted 163 { 164 catchAndLogException((){ 165 if(_pipe) 166 _pipe.timeOut(); 167 }()); 168 } 169 170 override void deletePipeline(PipelineBase pipeline) 171 { 172 if (_timer) 173 _timer.stop(); 174 gcFree(_logInfo.client); 175 _logInfo.client = null; 176 pipeline.pipelineManager(null); 177 _pipe = null; 178 } 179 180 override void refreshTimeout() 181 { 182 } 183 184 private: 185 EventLoop _loop; 186 PipeLine _pipe; 187 shared PipelineFactory!PipeLine _pipelineFactory; 188 Timer _timer = null; 189 uint _timeOut = 0; 190 uint _tryCount; 191 192 LinklogInfo _logInfo; 193 ClientCreatorCallBack _oncreator; 194 }