forked from opsre/go-ldap-admin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ldap.go
159 lines (138 loc) · 3.36 KB
/
ldap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package common
import (
"fmt"
"log"
"math/rand"
"net"
"sync"
"time"
"github.com/eryajf/go-ldap-admin/config"
ldap "github.com/go-ldap/ldap/v3"
)
var ldapPool *LdapConnPool
var ldapInit = false
var ldapInitOne sync.Once
// Init 初始化连接
func InitLDAP() {
if ldapInit {
return
}
ldapInitOne.Do(func() {
ldapInit = true
})
// Dail有两个参数 network, address, 返回 (*Conn, error)
ldapConn, err := ldap.DialURL(config.Conf.Ldap.Url, ldap.DialWithDialer(&net.Dialer{Timeout: 5 * time.Second}))
if err != nil {
Log.Panicf("初始化ldap连接异常: %v", err)
panic(fmt.Errorf("初始化ldap连接异常: %v", err))
}
err = ldapConn.Bind(config.Conf.Ldap.AdminDN, config.Conf.Ldap.AdminPass)
if err != nil {
Log.Panicf("绑定admin账号异常: %v", err)
panic(fmt.Errorf("绑定admin账号异常: %v", err))
}
// 全局变量赋值
ldapPool = &LdapConnPool{
conns: make([]*ldap.Conn, 0),
reqConns: make(map[uint64]chan *ldap.Conn),
openConn: 0,
maxOpen: config.Conf.Ldap.MaxConn,
}
PutLADPConn(ldapConn)
// 隐藏密码
showDsn := fmt.Sprintf(
"%s:******@tcp(%s)",
config.Conf.Ldap.AdminDN,
config.Conf.Ldap.Url,
)
Log.Info("初始化ldap完成! dsn: ", showDsn)
}
// GetLDAPConn 获取 LDAP 连接
func GetLDAPConn() (*ldap.Conn, error) {
return ldapPool.GetConnection()
}
// PutLDAPConn 放回 LDAP 连接
func PutLADPConn(conn *ldap.Conn) {
ldapPool.PutConnection(conn)
}
type LdapConnPool struct {
mu sync.Mutex
conns []*ldap.Conn
reqConns map[uint64]chan *ldap.Conn
openConn int
maxOpen int
}
// 获取一个 ladp Conn
func (lcp *LdapConnPool) GetConnection() (*ldap.Conn, error) {
lcp.mu.Lock()
// 判断当前连接池内是否存在连接
connNum := len(lcp.conns)
if connNum > 0 {
lcp.openConn++
conn := lcp.conns[0]
copy(lcp.conns, lcp.conns[1:])
lcp.conns = lcp.conns[:connNum-1]
lcp.mu.Unlock()
// 发现连接已经 close 重新获取连接
if conn.IsClosing() {
return initLDAPConn()
}
return conn, nil
}
// 当现有连接池为空时,并且当前超过最大连接限制
if lcp.maxOpen != 0 && lcp.openConn > lcp.maxOpen {
// 创建一个等待队列
req := make(chan *ldap.Conn, 1)
reqKey := lcp.nextRequestKeyLocked()
lcp.reqConns[reqKey] = req
lcp.mu.Unlock()
// 等待请求归还
return <-req, nil
} else {
lcp.openConn++
lcp.mu.Unlock()
return initLDAPConn()
}
}
func (lcp *LdapConnPool) PutConnection(conn *ldap.Conn) {
log.Println("放回了一个连接")
lcp.mu.Lock()
defer lcp.mu.Unlock()
// 先判断是否存在等待的队列
if num := len(lcp.reqConns); num > 0 {
var req chan *ldap.Conn
var reqKey uint64
for reqKey, req = range lcp.reqConns {
break
}
delete(lcp.reqConns, reqKey)
req <- conn
return
} else {
lcp.openConn--
if !conn.IsClosing() {
lcp.conns = append(lcp.conns, conn)
}
}
}
// 获取下一个请求令牌
func (lcp *LdapConnPool) nextRequestKeyLocked() uint64 {
for {
reqKey := rand.Uint64()
if _, ok := lcp.reqConns[reqKey]; !ok {
return reqKey
}
}
}
// 获取 ladp 连接
func initLDAPConn() (*ldap.Conn, error) {
ldap, err := ldap.DialURL(config.Conf.Ldap.Url, ldap.DialWithDialer(&net.Dialer{Timeout: 5 * time.Second}))
if err != nil {
return nil, err
}
err = ldap.Bind(config.Conf.Ldap.AdminDN, config.Conf.Ldap.AdminPass)
if err != nil {
return nil, err
}
return ldap, err
}