manager.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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.Warn("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.Warn("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.Warn("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. } else {
  142. return nil
  143. }
  144. }
  145. func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
  146. if len(m.pingPlugins) == 0 {
  147. return content, nil
  148. }
  149. var (
  150. res = &Response{
  151. Reject: false,
  152. Unchange: true,
  153. }
  154. retContent interface{}
  155. err error
  156. )
  157. reqid, _ := util.RandID()
  158. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  159. ctx := xlog.NewContext(context.Background(), xl)
  160. ctx = NewReqidContext(ctx, reqid)
  161. for _, p := range m.pingPlugins {
  162. res, retContent, err = p.Handle(ctx, OpPing, *content)
  163. if err != nil {
  164. xl.Warn("send Ping request to plugin [%s] error: %v", p.Name(), err)
  165. return nil, errors.New("send Ping request to plugin error")
  166. }
  167. if res.Reject {
  168. return nil, fmt.Errorf("%s", res.RejectReason)
  169. }
  170. if !res.Unchange {
  171. content = retContent.(*PingContent)
  172. }
  173. }
  174. return content, nil
  175. }
  176. func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent, error) {
  177. if len(m.newWorkConnPlugins) == 0 {
  178. return content, nil
  179. }
  180. var (
  181. res = &Response{
  182. Reject: false,
  183. Unchange: true,
  184. }
  185. retContent interface{}
  186. err error
  187. )
  188. reqid, _ := util.RandID()
  189. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  190. ctx := xlog.NewContext(context.Background(), xl)
  191. ctx = NewReqidContext(ctx, reqid)
  192. for _, p := range m.newWorkConnPlugins {
  193. res, retContent, err = p.Handle(ctx, OpPing, *content)
  194. if err != nil {
  195. xl.Warn("send NewWorkConn request to plugin [%s] error: %v", p.Name(), err)
  196. return nil, errors.New("send NewWorkConn request to plugin error")
  197. }
  198. if res.Reject {
  199. return nil, fmt.Errorf("%s", res.RejectReason)
  200. }
  201. if !res.Unchange {
  202. content = retContent.(*NewWorkConnContent)
  203. }
  204. }
  205. return content, nil
  206. }
  207. func (m *Manager) NewUserConn(content *NewUserConnContent) (*NewUserConnContent, error) {
  208. if len(m.newUserConnPlugins) == 0 {
  209. return content, nil
  210. }
  211. var (
  212. res = &Response{
  213. Reject: false,
  214. Unchange: true,
  215. }
  216. retContent interface{}
  217. err error
  218. )
  219. reqid, _ := util.RandID()
  220. xl := xlog.New().AppendPrefix("reqid: " + reqid)
  221. ctx := xlog.NewContext(context.Background(), xl)
  222. ctx = NewReqidContext(ctx, reqid)
  223. for _, p := range m.newUserConnPlugins {
  224. res, retContent, err = p.Handle(ctx, OpNewUserConn, *content)
  225. if err != nil {
  226. xl.Info("send NewUserConn request to plugin [%s] error: %v", p.Name(), err)
  227. return nil, errors.New("send NewUserConn request to plugin error")
  228. }
  229. if res.Reject {
  230. return nil, fmt.Errorf("%s", res.RejectReason)
  231. }
  232. if !res.Unchange {
  233. content = retContent.(*NewUserConnContent)
  234. }
  235. }
  236. return content, nil
  237. }