github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/network/agent.go (about) 1 package network 2 3 import ( 4 "context" 5 "github.com/15mga/kiwi" 6 "math" 7 "net" 8 "sync" 9 10 "github.com/15mga/kiwi/ds" 11 12 "github.com/15mga/kiwi/util" 13 ) 14 15 const ( 16 _PacketMaxCap int = math.MaxUint32 17 _PacketMinCap int = 1 << 11 18 ) 19 20 func newAgent(addr string, receiver kiwi.FnAgentBytes, opts ...kiwi.AgentOption) agent { 21 opt := &kiwi.AgentOpt{ 22 PacketMaxCap: _PacketMaxCap, 23 PacketMinCap: _PacketMinCap, 24 HeadLen: 4, 25 } 26 for _, action := range opts { 27 action(opt) 28 } 29 a := agent{ 30 id: addr, 31 addr: addr, 32 option: opt, 33 enable: util.NewEnable(), 34 receiver: receiver, 35 bytesLink: ds.NewLink[[]byte](), 36 onConnected: ds.NewFnLink1[kiwi.IAgent](), 37 onDisconnected: ds.NewFnLink2[kiwi.IAgent, *util.Err](), 38 head: util.M{}, 39 cache: util.M{}, 40 mtx: &sync.RWMutex{}, 41 } 42 a.head.Set("addr", addr) 43 return a 44 } 45 46 type agent struct { 47 option *kiwi.AgentOpt 48 onClose func() error 49 id string 50 addr string 51 ctx context.Context 52 cancel context.CancelFunc 53 writeSignCh chan struct{} 54 enable *util.Enable 55 receiver kiwi.FnAgentBytes 56 bytesLink *ds.Link[[]byte] 57 onConnected *ds.FnLink1[kiwi.IAgent] 58 onDisconnected *ds.FnLink2[kiwi.IAgent, *util.Err] 59 head util.M 60 cache util.M 61 mtx *sync.RWMutex 62 } 63 64 func (a *agent) onStart(_ []any) { 65 a.writeSignCh = make(chan struct{}, 1) 66 go a.onConnected.Invoke(a) 67 } 68 69 func (a *agent) start(ctx context.Context) { 70 a.ctx, a.cancel = context.WithCancel(ctx) 71 _ = a.enable.Enable(a.onStart) 72 } 73 74 func (a *agent) SetHead(key string, val any) { 75 a.mtx.Lock() 76 a.head[key] = val 77 a.mtx.Unlock() 78 } 79 80 func (a *agent) SetHeads(m util.M) { 81 a.mtx.Lock() 82 for key, val := range m { 83 a.head[key] = val 84 } 85 a.mtx.Unlock() 86 } 87 88 func (a *agent) GetHead(key string) (val any, exist bool) { 89 a.mtx.RLock() 90 val, exist = a.head[key] 91 a.mtx.RUnlock() 92 return 93 } 94 95 func (a *agent) DelHead(keys ...string) { 96 a.mtx.Lock() 97 for _, key := range keys { 98 delete(a.head, key) 99 } 100 a.mtx.Unlock() 101 } 102 103 func (a *agent) CopyHead(m util.M) { 104 if m == nil { 105 return 106 } 107 a.mtx.Lock() 108 for key, val := range a.head { 109 m[key] = val 110 } 111 a.mtx.Unlock() 112 } 113 114 func (a *agent) SetCache(key string, val any) { 115 a.mtx.Lock() 116 a.cache[key] = val 117 a.mtx.Unlock() 118 } 119 120 func (a *agent) SetCaches(m util.M) { 121 a.mtx.Lock() 122 for key, val := range m { 123 a.cache[key] = val 124 } 125 a.mtx.Unlock() 126 } 127 128 func (a *agent) GetCache(key string) (val any, exist bool) { 129 a.mtx.RLock() 130 val, exist = a.cache[key] 131 a.mtx.RUnlock() 132 return 133 } 134 135 func (a *agent) DelCache(keys ...string) { 136 a.mtx.Lock() 137 for _, key := range keys { 138 delete(a.cache, key) 139 } 140 a.mtx.Unlock() 141 } 142 143 func (a *agent) CopyCache(m util.M) { 144 a.mtx.Lock() 145 for key, val := range a.cache { 146 m[key] = val 147 } 148 a.mtx.Unlock() 149 } 150 151 func (a *agent) Id() (id string) { 152 a.mtx.RLock() 153 id = a.id 154 a.mtx.RUnlock() 155 return id 156 } 157 158 func (a *agent) SetId(id string) { 159 a.mtx.Lock() 160 a.id = id 161 a.mtx.Unlock() 162 } 163 164 func (a *agent) Addr() string { 165 return a.addr 166 } 167 168 func (a *agent) Host() string { 169 host, _, _ := net.SplitHostPort(a.addr) 170 return host 171 } 172 173 func (a *agent) Enable() *util.Enable { 174 return a.enable 175 } 176 177 func (a *agent) Dispose() { 178 a.cancel() 179 } 180 181 func (a *agent) Send(bytes []byte) *util.Err { 182 if bytes == nil { 183 return util.NewErr(util.EcEmpty, nil) 184 } 185 l := len(bytes) 186 if l == 0 { 187 return util.NewErr(util.EcEmpty, nil) 188 } 189 if l > a.option.PacketMaxCap { 190 return util.NewErr(util.EcTooLong, util.M{ 191 "length": l, 192 }) 193 } 194 return a.enable.WAction(agentPushByte, a, bytes) 195 } 196 197 func agentPushByte(params []any) { 198 a, bytes := util.SplitSlc2[*agent, []byte](params) 199 a.bytesLink.Push(bytes) 200 select { 201 case a.writeSignCh <- struct{}{}: 202 default: 203 } 204 } 205 206 func (a *agent) BindConnected(fn kiwi.FnAgent) { 207 a.onConnected.Push(fn) 208 } 209 210 func (a *agent) BindDisconnected(fn kiwi.FnAgentErr) { 211 a.onDisconnected.Push(fn) 212 } 213 214 func (a *agent) close(err *util.Err) { 215 a.enable.Disable(agentClose, a, err) 216 } 217 218 func agentClose(params []any) { 219 a, err := util.SplitSlc2[*agent, *util.Err](params) 220 close(a.writeSignCh) 221 _ = a.onClose() 222 go a.onDisconnected.Invoke(a, err) 223 }