manager.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright 2019 fatedier, fatedier@gmail.com
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package plugin
  15. import (
  16. "context"
  17. "errors"
  18. "fmt"
  19. "strings"
  20. "github.com/fatedier/frp/pkg/util/util"
  21. "github.com/fatedier/frp/pkg/util/xlog"
  22. )
  23. type Manager struct {
  24. loginPlugins []Plugin
  25. newProxyPlugins []Plugin
  26. closeProxyPlugins []Plugin
  27. pingPlugins []Plugin
  28. newWorkConnPlugins []Plugin
  29. newUserConnPlugins []Plugin
  30. }
  31. func NewManager() *Manager {
  32. return &Manager{
  33. loginPlugins: make([]Plugin, 0),
  34. newProxyPlugins: make([]Plugin, 0),
  35. closeProxyPlugins: make([]Plugin, 0),
  36. pingPlugins: make([]Plugin, 0),
  37. newWorkConnPlugins: make([]Plugin, 0),
  38. newUserConnPlugins: make([]Plugin, 0),
  39. }
  40. }
  41. func (m *Manager) Register(p Plugin) {
  42. if p.IsSupport(OpLogin) {
  43. m.loginPlugins = append(m.loginPlugins, p)
  44. }
  45. if p.IsSupport(OpNewProxy) {
  46. m.newProxyPlugins = append(m.newProxyPlugins, p)
  47. }
  48. if p.IsSupport(OpCloseProxy) {
  49. m.closeProxyPlugins = append(m.closeProxyPlugins, p)
  50. }
  51. if p.IsSupport(OpPing) {
  52. m.pingPlugins = append(m.pingPlugins, p)
  53. }
  54. if p.IsSupport(OpNewWorkConn) {
  55. m.newWorkConnPlugins = append(m.newWorkConnPlugins, p)
  56. }
  57. if p.IsSupport(OpNewUserConn) {
  58. m.newUserConnPlugins = append(m.newUserConnPlugins, p)
  59. }
  60. }
  61. func (m *Manager) Login(content *LoginContent) (*LoginContent, error) {
  62. if len(m.loginPlugins) == 0 {
  63. return content, nil
  64. }
  65. var (
  66. res = &Response{
  67. Reject: false,
  68. Unchange: true,
  69. }
  70. retContent interface{}
  71. err error
  72. )
  73. reqid, _ := util.RandID()
  74. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  75. ctx := xlog.NewContext(context.Background(), xl)
  76. ctx = NewReqidContext(ctx, reqid)
  77. for _, p := range m.loginPlugins {
  78. res, retContent, err = p.Handle(ctx, OpLogin, *content)
  79. if err != nil {
  80. xl.Warnf("send Login request to plugin [%s] error: %v", p.Name(), err)
  81. return nil, errors.New("send Login request to plugin error")
  82. }
  83. if res.Reject {
  84. return nil, fmt.Errorf("%s", res.RejectReason)
  85. }
  86. if !res.Unchange {
  87. content = retContent.(*LoginContent)
  88. }
  89. }
  90. return content, nil
  91. }
  92. func (m *Manager) NewProxy(content *NewProxyContent) (*NewProxyContent, error) {
  93. if len(m.newProxyPlugins) == 0 {
  94. return content, nil
  95. }
  96. var (
  97. res = &Response{
  98. Reject: false,
  99. Unchange: true,
  100. }
  101. retContent interface{}
  102. err error
  103. )
  104. reqid, _ := util.RandID()
  105. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  106. ctx := xlog.NewContext(context.Background(), xl)
  107. ctx = NewReqidContext(ctx, reqid)
  108. for _, p := range m.newProxyPlugins {
  109. res, retContent, err = p.Handle(ctx, OpNewProxy, *content)
  110. if err != nil {
  111. xl.Warnf("send NewProxy request to plugin [%s] error: %v", p.Name(), err)
  112. return nil, errors.New("send NewProxy request to plugin error")
  113. }
  114. if res.Reject {
  115. return nil, fmt.Errorf("%s", res.RejectReason)
  116. }
  117. if !res.Unchange {
  118. content = retContent.(*NewProxyContent)
  119. }
  120. }
  121. return content, nil
  122. }
  123. func (m *Manager) CloseProxy(content *CloseProxyContent) error {
  124. if len(m.closeProxyPlugins) == 0 {
  125. return nil
  126. }
  127. errs := make([]string, 0)
  128. reqid, _ := util.RandID()
  129. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  130. ctx := xlog.NewContext(context.Background(), xl)
  131. ctx = NewReqidContext(ctx, reqid)
  132. for _, p := range m.closeProxyPlugins {
  133. _, _, err := p.Handle(ctx, OpCloseProxy, *content)
  134. if err != nil {
  135. xl.Warnf("send CloseProxy request to plugin [%s] error: %v", p.Name(), err)
  136. errs = append(errs, fmt.Sprintf("[%s]: %v", p.Name(), err))
  137. }
  138. }
  139. if len(errs) > 0 {
  140. return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
  141. }
  142. return nil
  143. }
  144. func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
  145. if len(m.pingPlugins) == 0 {
  146. return content, nil
  147. }
  148. var (
  149. res = &Response{
  150. Reject: false,
  151. Unchange: true,
  152. }
  153. retContent interface{}
  154. err error
  155. )
  156. reqid, _ := util.RandID()
  157. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  158. ctx := xlog.NewContext(context.Background(), xl)
  159. ctx = NewReqidContext(ctx, reqid)
  160. for _, p := range m.pingPlugins {
  161. res, retContent, err = p.Handle(ctx, OpPing, *content)
  162. if err != nil {
  163. xl.Warnf("send Ping request to plugin [%s] error: %v", p.Name(), err)
  164. return nil, errors.New("send Ping request to plugin error")
  165. }
  166. if res.Reject {
  167. return nil, fmt.Errorf("%s", res.RejectReason)
  168. }
  169. if !res.Unchange {
  170. content = retContent.(*PingContent)
  171. }
  172. }
  173. return content, nil
  174. }
  175. func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent, error) {
  176. if len(m.newWorkConnPlugins) == 0 {
  177. return content, nil
  178. }
  179. var (
  180. res = &Response{
  181. Reject: false,
  182. Unchange: true,
  183. }
  184. retContent interface{}
  185. err error
  186. )
  187. reqid, _ := util.RandID()
  188. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  189. ctx := xlog.NewContext(context.Background(), xl)
  190. ctx = NewReqidContext(ctx, reqid)
  191. for _, p := range m.newWorkConnPlugins {
  192. res, retContent, err = p.Handle(ctx, OpNewWorkConn, *content)
  193. if err != nil {
  194. xl.Warnf("send NewWorkConn request to plugin [%s] error: %v", p.Name(), err)
  195. return nil, errors.New("send NewWorkConn request to plugin error")
  196. }
  197. if res.Reject {
  198. return nil, fmt.Errorf("%s", res.RejectReason)
  199. }
  200. if !res.Unchange {
  201. content = retContent.(*NewWorkConnContent)
  202. }
  203. }
  204. return content, nil
  205. }
  206. func (m *Manager) NewUserConn(content *NewUserConnContent) (*NewUserConnContent, error) {
  207. if len(m.newUserConnPlugins) == 0 {
  208. return content, nil
  209. }
  210. var (
  211. res = &Response{
  212. Reject: false,
  213. Unchange: true,
  214. }
  215. retContent interface{}
  216. err error
  217. )
  218. reqid, _ := util.RandID()
  219. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  220. ctx := xlog.NewContext(context.Background(), xl)
  221. ctx = NewReqidContext(ctx, reqid)
  222. for _, p := range m.newUserConnPlugins {
  223. res, retContent, err = p.Handle(ctx, OpNewUserConn, *content)
  224. if err != nil {
  225. xl.Infof("send NewUserConn request to plugin [%s] error: %v", p.Name(), err)
  226. return nil, errors.New("send NewUserConn request to plugin error")
  227. }
  228. if res.Reject {
  229. return nil, fmt.Errorf("%s", res.RejectReason)
  230. }
  231. if !res.Unchange {
  232. content = retContent.(*NewUserConnContent)
  233. }
  234. }
  235. return content, nil
  236. }