| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package ssh
- import (
- "context"
- ssh_util "yunion.io/x/onecloud/pkg/util/ssh"
- )
- type epClientSet struct {
- cc ssh_util.ClientConfig
- clients []*Client
- mark bool
- }
- func (epcs *epClientSet) clearMark() {
- epcs.mark = false
- }
- func (epcs *epClientSet) setMark() {
- epcs.mark = true
- }
- func (epcs *epClientSet) getMark() bool {
- return epcs.mark
- }
- func (epcs *epClientSet) stop(ctx context.Context) {
- for _, client := range epcs.clients {
- client.Stop(ctx)
- }
- }
- type epClients map[string]*epClientSet // key: epKey
- type ClientSet struct {
- epClients epClients
- }
- func NewClientSet() *ClientSet {
- cs := &ClientSet{
- epClients: epClients{},
- }
- return cs
- }
- func (cs *ClientSet) ClearAllMark() {
- for _, epcs := range cs.epClients {
- epcs.clearMark()
- }
- }
- func (cs *ClientSet) ResetIfChanged(ctx context.Context, epKey string, cc ssh_util.ClientConfig) bool {
- epcs, ok := cs.epClients[epKey]
- if ok {
- if epcs.cc != cc {
- epcs.stop(ctx)
- delete(cs.epClients, epKey)
- cs.AddIfNotExist(ctx, epKey, cc)
- return true
- }
- epcs.setMark()
- }
- return false
- }
- func (cs *ClientSet) AddIfNotExist(ctx context.Context, epKey string, cc ssh_util.ClientConfig) bool {
- epcs, ok := cs.epClients[epKey]
- if !ok {
- epcs := &epClientSet{
- cc: cc,
- }
- epcs.setMark()
- cs.epClients[epKey] = epcs
- return true
- }
- epcs.setMark()
- return false
- }
- func (cs *ClientSet) ResetUnmarked(ctx context.Context) {
- for epKey, epcs := range cs.epClients {
- if !epcs.getMark() {
- epcs.stop(ctx)
- delete(cs.epClients, epKey)
- }
- }
- }
- func (cs *ClientSet) ForwardKeySet() ForwardKeySet {
- fks := ForwardKeySet{}
- for epKey, epcs := range cs.epClients {
- for _, client := range epcs.clients {
- fks.addByPortMap(epKey, ForwardKeyTypeL, client.localForwards)
- fks.addByPortMap(epKey, ForwardKeyTypeR, client.remoteForwards)
- }
- }
- return fks
- }
- func (cs *ClientSet) LocalForward(ctx context.Context, epKey string, req LocalForwardReq) {
- client, created := cs.getOrCreateClient(epKey, ForwardKeyTypeL)
- if created {
- go client.Start(ctx)
- }
- client.LocalForward(ctx, req)
- }
- func (cs *ClientSet) RemoteForward(ctx context.Context, epKey string, req RemoteForwardReq) {
- client, created := cs.getOrCreateClient(epKey, ForwardKeyTypeR)
- if created {
- go client.Start(ctx)
- }
- client.RemoteForward(ctx, req)
- }
- func (cs *ClientSet) CloseForward(ctx context.Context, fk ForwardKey) {
- client := cs.getClient(fk.EpKey, fk.Type)
- if client == nil {
- return
- }
- switch fk.Type {
- case ForwardKeyTypeL:
- client.LocalForwardClose(ctx, LocalForwardReq{
- LocalAddr: fk.KeyAddr,
- LocalPort: fk.KeyPort,
- })
- case ForwardKeyTypeR:
- client.RemoteForwardClose(ctx, RemoteForwardReq{
- RemoteAddr: fk.KeyAddr,
- RemotePort: fk.KeyPort,
- })
- }
- }
- /*
- func (cs *ClientSet) LocalForwardClose(ctx context.Context, epKey string, req LocalForwardReq) {
- client := cs.getClient(epKey, ForwardKeyTypeL)
- client.LocalForwardClose(ctx, req)
- }
- func (cs *ClientSet) RemoteForwardClose(ctx context.Context, epKey string, req RemoteForwardReq) {
- client := cs.getClient(epKey, ForwardKeyTypeR)
- client.RemoteForwardClose(ctx, req)
- }
- */
- func (cs *ClientSet) getOrCreateClient(epKey string, typ string) (*Client, bool) {
- return cs.getClient_(epKey, typ, true)
- }
- func (cs *ClientSet) getClient(epKey string, typ string) *Client {
- client, _ := cs.getClient_(epKey, typ, false)
- return client
- }
- func (cs *ClientSet) getClient_(epKey string, typ string, create bool) (*Client, bool) {
- var client *Client
- clients, ok := cs.epClients[epKey]
- if !ok || len(clients.clients) == 0 {
- if !ok || !create {
- return nil, false
- }
- client = NewClient(&clients.cc)
- clients.clients = append(clients.clients, client)
- cs.epClients[epKey] = clients
- return client, true
- } else {
- client = clients.clients[0]
- return client, false
- }
- }
|