tcp2.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. package tcp2
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "log"
  9. "net"
  10. "slices"
  11. "strings"
  12. "time"
  13. "git.me9.top/git/tinymq/config"
  14. "git.me9.top/git/tinymq/conn"
  15. "git.me9.top/git/tinymq/util"
  16. "git.me9.top/git/tinymq/util/pool"
  17. )
  18. const PROTO string = "tcp"
  19. const VERSION uint8 = 2
  20. // 第一级数据包的最大长度,如果超过则自动增加一个地址位到4个字节
  21. const MAX_LENGTH = 0xFFFF
  22. // 由于都是内部使用,感觉没有必要加这个限制
  23. // const MAX2_LENGTH = 0x1FFFFFFF // 500 M,避免申请过大内存
  24. type Tcp2 struct {
  25. cf *config.Config
  26. conn net.Conn
  27. cipher *util.Cipher // 记录当前的加解密类
  28. compress bool // 是否启用压缩
  29. }
  30. // 服务端
  31. // hash 格式 encryptMethod:encryptKey
  32. func Server(cf *config.Config, bind string, hash string, fn conn.ServerConnectFunc) (err error) {
  33. var ci *util.CipherInfo
  34. var encryptKey string
  35. if hash != "" {
  36. i := strings.Index(hash, ":")
  37. if i <= 0 {
  38. err = errors.New("hash is invalid")
  39. return
  40. }
  41. encryptMethod := hash[0:i]
  42. encryptKey = hash[i+1:]
  43. if c, ok := util.CipherMethod[encryptMethod]; ok {
  44. ci = c
  45. } else {
  46. return errors.New("Unsupported encryption method: " + encryptMethod)
  47. }
  48. }
  49. log.Printf("Listening and serving tcp on %s\n", bind)
  50. l, err := net.Listen("tcp", bind)
  51. if err != nil {
  52. log.Println("[tcp2 Server ERROR]", err)
  53. return
  54. }
  55. go func(l net.Listener) {
  56. defer l.Close()
  57. for {
  58. conn, err := l.Accept()
  59. if err != nil {
  60. log.Println("[accept ERROR]", err)
  61. return
  62. }
  63. go func(conn net.Conn) {
  64. if ci == nil {
  65. c := &Tcp2{
  66. cf: cf,
  67. conn: conn,
  68. }
  69. fn(c)
  70. return
  71. }
  72. var eiv []byte
  73. var div []byte
  74. if ci.IvLen > 0 {
  75. // 服务端 IV
  76. eiv = pool.Get(ci.IvLen)
  77. defer pool.Put(eiv)
  78. _, err = rand.Read(eiv)
  79. if err != nil {
  80. log.Println("[tcp2 Server rand.Read ERROR]", err)
  81. return
  82. }
  83. // 发送 IV
  84. conn.SetWriteDeadline(time.Now().Add(time.Duration(cf.WriteWait) * time.Millisecond))
  85. if _, err := conn.Write(eiv); err != nil {
  86. log.Println("[tcp2 Server conn.Write ERROR]", err)
  87. return
  88. }
  89. // 读取 IV
  90. err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(cf.ReadWait)))
  91. if err != nil {
  92. log.Println("[tcp2 Server SetReadDeadline ERROR]", err)
  93. return
  94. }
  95. div = pool.Get(ci.IvLen)
  96. defer pool.Put(div)
  97. _, err := io.ReadFull(conn, div)
  98. if err != nil {
  99. log.Println("[tcp2 Server ReadFull ERROR]", err)
  100. return
  101. }
  102. }
  103. cipher, err := util.NewCipher(ci, encryptKey, eiv, div)
  104. if err != nil {
  105. log.Println("[tcp2 NewCipher ERROR]", err)
  106. return
  107. }
  108. // 初始化
  109. c := &Tcp2{
  110. cf: cf,
  111. conn: conn,
  112. cipher: cipher,
  113. }
  114. fn(c)
  115. }(conn)
  116. }
  117. }(l)
  118. return
  119. }
  120. // 客户端,新建一个连接
  121. func Dial(cf *config.Config, addr string, hash string) (conn.Connect, error) {
  122. // 没有加密的情况
  123. if hash == "" {
  124. conn, err := net.DialTimeout("tcp", addr, time.Duration(cf.ConnectTimeout)*time.Millisecond)
  125. if err != nil {
  126. return nil, err
  127. }
  128. c := &Tcp2{
  129. cf: cf,
  130. conn: conn,
  131. }
  132. return c, nil
  133. }
  134. i := strings.Index(hash, ":")
  135. if i <= 0 {
  136. return nil, errors.New("hash is invalid")
  137. }
  138. encryptMethod := hash[0:i]
  139. encryptKey := hash[i+1:]
  140. ci, ok := util.CipherMethod[encryptMethod]
  141. if !ok {
  142. return nil, errors.New("Unsupported encryption method: " + encryptMethod)
  143. }
  144. conn, err := net.DialTimeout("tcp", addr, time.Duration(cf.ConnectTimeout)*time.Millisecond)
  145. if err != nil {
  146. return nil, err
  147. }
  148. var eiv []byte
  149. var div []byte
  150. if ci.IvLen > 0 {
  151. // 客户端 IV
  152. eiv = pool.Get(ci.IvLen)
  153. defer pool.Put(eiv)
  154. _, err = rand.Read(eiv)
  155. if err != nil {
  156. log.Println("[tcp2 Client rand.Read ERROR]", err)
  157. return nil, err
  158. }
  159. // 发送 IV
  160. conn.SetWriteDeadline(time.Now().Add(time.Duration(cf.WriteWait) * time.Millisecond))
  161. if _, err := conn.Write(eiv); err != nil {
  162. log.Println("[tcp2 Client conn.Write ERROR]", err)
  163. return nil, err
  164. }
  165. // 读取 IV
  166. err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(cf.ReadWait)))
  167. if err != nil {
  168. log.Println("[tcp2 Client SetReadDeadline ERROR]", err)
  169. return nil, err
  170. }
  171. div = pool.Get(ci.IvLen)
  172. defer pool.Put(div)
  173. _, err := io.ReadFull(conn, div)
  174. if err != nil {
  175. log.Println("[tcp2 Client ReadFull ERROR]", err)
  176. return nil, err
  177. }
  178. }
  179. cipher, err := util.NewCipher(ci, encryptKey, eiv, div)
  180. if err != nil {
  181. log.Println("[tcp2 NewCipher ERROR]", err)
  182. return nil, err
  183. }
  184. // 初始化
  185. c := &Tcp2{
  186. cf: cf,
  187. conn: conn,
  188. cipher: cipher,
  189. compress: true,
  190. }
  191. return c, nil
  192. }
  193. // 发送数据包到网络
  194. // recycle 指示是否需要将raw放回内存池
  195. func (c *Tcp2) WriteRawPackage(raw []byte, recycle bool) (err error) {
  196. var buf []byte
  197. var index int
  198. dlen := len(raw)
  199. if dlen >= MAX_LENGTH {
  200. buf = pool.Get(dlen + 2 + 4 + 1)
  201. index = 2 + 4
  202. binary.BigEndian.PutUint16(buf[:2], MAX_LENGTH)
  203. binary.BigEndian.PutUint32(buf[2:6], uint32(dlen))
  204. } else {
  205. buf = pool.Get(dlen + 2 + 1)
  206. index = 2
  207. binary.BigEndian.PutUint16(buf[:2], uint16(dlen))
  208. }
  209. copy(buf[index:index+dlen], raw)
  210. index += dlen
  211. buf[index] = util.CRC8(raw)
  212. if recycle {
  213. pool.Put(raw)
  214. }
  215. defer pool.Put(buf)
  216. if c.cipher != nil {
  217. c.cipher.Encrypt(buf, buf)
  218. }
  219. c.conn.SetWriteDeadline(time.Now().Add(time.Duration(c.cf.WriteWait) * time.Millisecond))
  220. for {
  221. n, err := c.conn.Write(buf)
  222. if err != nil {
  223. return err
  224. }
  225. if n < len(buf) {
  226. buf = buf[n:]
  227. } else {
  228. return nil
  229. }
  230. }
  231. }
  232. // 从连接中读取数据包,已经剥离了头部长度和尾部crc
  233. // recycle 指示是否需要手动将缓存放回内存池
  234. func (c *Tcp2) ReadRawPackage(deadline int) (buf []byte, recycle bool, err error) {
  235. err = c.conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(deadline)))
  236. if err != nil {
  237. return nil, false, err
  238. }
  239. buf = pool.Get(2)
  240. // 读取数据流长度
  241. _, err = io.ReadFull(c.conn, buf)
  242. if err != nil {
  243. pool.Put(buf)
  244. return nil, false, err
  245. }
  246. // 将读出来的数据进行解密
  247. if c.cipher != nil {
  248. c.cipher.Decrypt(buf, buf)
  249. }
  250. dlen := uint32(binary.BigEndian.Uint16(buf))
  251. pool.Put(buf)
  252. if dlen < 2 {
  253. return nil, false, errors.New("length is less to 2")
  254. }
  255. if dlen >= MAX_LENGTH {
  256. // 数据包比较大,通过后面的4位长度来表示实际长度
  257. buf := pool.Get(4)
  258. _, err := io.ReadFull(c.conn, buf)
  259. if err != nil {
  260. pool.Put(buf)
  261. return nil, false, err
  262. }
  263. if c.cipher != nil {
  264. c.cipher.Decrypt(buf, buf)
  265. }
  266. dlen = binary.BigEndian.Uint32(buf)
  267. pool.Put(buf)
  268. if dlen < MAX_LENGTH {
  269. return nil, false, errors.New("wrong length in read message")
  270. }
  271. }
  272. // 读取指定长度的数据
  273. buf = pool.Get(int(dlen) + 1) // 最后一个是crc的值
  274. _, err = io.ReadFull(c.conn, buf)
  275. if err != nil {
  276. pool.Put(buf)
  277. return nil, false, err
  278. }
  279. if c.cipher != nil {
  280. c.cipher.Decrypt(buf, buf)
  281. }
  282. // 检查CRC8
  283. if util.CRC8(buf[:dlen]) != buf[dlen] {
  284. pool.Put(buf)
  285. return nil, false, errors.New("CRC error")
  286. }
  287. return buf[:dlen], true, nil
  288. }
  289. // 发送Auth信息
  290. // 建立连接后第一个发送的消息
  291. func (c *Tcp2) WriteAuthInfo(channel string, auth []byte) (err error) {
  292. protoLen := len(PROTO)
  293. if protoLen > 0xFF {
  294. return errors.New("length of protocol over")
  295. }
  296. channelLen := len(channel)
  297. if channelLen > 0xFFFF {
  298. return errors.New("length of channel over")
  299. }
  300. // id(65502)+proto(string)+version(uint8)+option(byte)+channel(string)+auth([]byte)
  301. dlen := 2 + 1 + protoLen + 1 + 1 + 2 + channelLen + len(auth)
  302. buf := pool.Get(dlen)
  303. index := 0
  304. binary.BigEndian.PutUint16(buf[index:index+2], config.ID_AUTH)
  305. index += 2
  306. buf[index] = byte(protoLen)
  307. index++
  308. copy(buf[index:index+protoLen], []byte(PROTO))
  309. index += protoLen
  310. buf[index] = VERSION
  311. index++
  312. if c.compress {
  313. buf[index] = 0x01
  314. } else {
  315. buf[index] = 0
  316. }
  317. index++
  318. binary.BigEndian.PutUint16(buf[index:index+2], uint16(channelLen))
  319. index += 2
  320. copy(buf[index:index+channelLen], []byte(channel))
  321. index += channelLen
  322. copy(buf[index:], auth)
  323. return c.WriteRawPackage(buf, true)
  324. }
  325. // 获取Auth信息
  326. // id(65502)+proto(string)+version(uint8)+option(byte)+channel(string)+auth([]byte)
  327. func (c *Tcp2) ReadAuthInfo() (proto string, version uint8, channel string, auth []byte, err error) {
  328. defer func() {
  329. if r := recover(); r != nil {
  330. err = fmt.Errorf("recovered from panic: %v", r)
  331. return
  332. }
  333. }()
  334. msg, recycle, err := c.ReadRawPackage(c.cf.ReadWait)
  335. if err != nil {
  336. return
  337. }
  338. if recycle {
  339. defer pool.Put(msg)
  340. }
  341. msgLen := len(msg)
  342. if msgLen < 9 {
  343. err = errors.New("wrong message length")
  344. return
  345. }
  346. index := 0
  347. id := binary.BigEndian.Uint16(msg[index : index+2])
  348. if id != config.ID_AUTH {
  349. err = fmt.Errorf("wrong message id: %d", id)
  350. return
  351. }
  352. index += 2
  353. protoLen := int(msg[index])
  354. if protoLen < 2 {
  355. err = errors.New("wrong proto length")
  356. return
  357. }
  358. index++
  359. proto = string(msg[index : index+protoLen])
  360. if proto != PROTO {
  361. err = fmt.Errorf("wrong proto: %s", proto)
  362. return
  363. }
  364. index += protoLen
  365. version = msg[index]
  366. if version != VERSION {
  367. err = fmt.Errorf("require version %d, get version: %d", VERSION, version)
  368. return
  369. }
  370. index++
  371. c.compress = (msg[index] & 0x01) != 0
  372. index++
  373. channelLen := int(binary.BigEndian.Uint16(msg[index : index+2]))
  374. if channelLen < 2 {
  375. err = errors.New("wrong channel length")
  376. return
  377. }
  378. index += 2
  379. channel = string(msg[index : index+channelLen])
  380. index += channelLen
  381. if recycle {
  382. auth = slices.Clone(msg[index:])
  383. } else {
  384. auth = msg[index:]
  385. }
  386. return
  387. }
  388. // 发送请求数据包到网络
  389. func (c *Tcp2) WriteRequest(id uint16, cmd string, data []byte) error {
  390. // 为了区分请求还是响应包,命令字符串不能超过127个字节
  391. cmdLen := len(cmd)
  392. if cmdLen > 0x7F {
  393. return errors.New("command length is more than 0x7F")
  394. }
  395. dlen := len(data)
  396. if c.compress && dlen > 0 {
  397. compressedData, ok, _ := util.CompressData(data)
  398. // id(uint16)+cmdLen(byte)+len(cmd)+option(byte)+len(data)
  399. ddlen := 2 + 1 + cmdLen + 1 + len(compressedData)
  400. buf := pool.Get(ddlen)
  401. index := 0
  402. binary.BigEndian.PutUint16(buf[index:index+2], id)
  403. index += 2
  404. buf[index] = byte(cmdLen)
  405. index++
  406. copy(buf[index:index+cmdLen], cmd)
  407. index += cmdLen
  408. if ok {
  409. buf[index] = 0x01
  410. if c.cf.PrintMsg {
  411. log.Println("[CompressData]", len(data), "->", len(compressedData))
  412. }
  413. } else {
  414. buf[index] = 0
  415. }
  416. index++
  417. copy(buf[index:], compressedData)
  418. return c.WriteRawPackage(buf, true)
  419. } else {
  420. ddlen := 2 + 1 + cmdLen + dlen
  421. buf := pool.Get(ddlen)
  422. index := 0
  423. binary.BigEndian.PutUint16(buf[index:index+2], id)
  424. index += 2
  425. buf[index] = byte(cmdLen)
  426. index++
  427. copy(buf[index:index+cmdLen], cmd)
  428. index += cmdLen
  429. copy(buf[index:], data)
  430. return c.WriteRawPackage(buf, true)
  431. }
  432. }
  433. // 发送响应数据包到网络
  434. // 网络格式:[id, stateCode, data]
  435. func (c *Tcp2) WriteResponse(id uint16, state uint8, data []byte) error {
  436. dlen := len(data)
  437. if c.compress && dlen > 0 {
  438. compressedData, ok, _ := util.CompressData(data)
  439. ddlen := 2 + 1 + 1 + len(compressedData)
  440. buf := pool.Get(ddlen)
  441. index := 0
  442. binary.BigEndian.PutUint16(buf[index:index+2], id)
  443. index += 2
  444. buf[index] = state | 0x80
  445. index++
  446. if ok {
  447. buf[index] = 0x001
  448. if c.cf.PrintMsg {
  449. log.Println("[CompressData]", len(data), "->", len(compressedData))
  450. }
  451. } else {
  452. buf[index] = 0
  453. }
  454. index++
  455. copy(buf[index:], compressedData)
  456. return c.WriteRawPackage(buf, true)
  457. } else {
  458. ddlen := 2 + 1 + len(data)
  459. buf := pool.Get(ddlen)
  460. index := 0
  461. binary.BigEndian.PutUint16(buf[index:index+2], id)
  462. index += 2
  463. buf[index] = state | 0x80
  464. index++
  465. copy(buf[index:], data)
  466. return c.WriteRawPackage(buf, true)
  467. }
  468. }
  469. // 发送ping包
  470. func (c *Tcp2) WritePing(id uint16) error {
  471. buf := pool.Get(2)
  472. index := 0
  473. binary.BigEndian.PutUint16(buf[index:index+2], id)
  474. return c.WriteRawPackage(buf, true)
  475. }
  476. // 获取信息
  477. func (c *Tcp2) ReadMessage(deadline int) (msgType conn.MsgType, id uint16, cmd string, state uint8, data []byte, err error) {
  478. msg, recycle, err := c.ReadRawPackage(deadline)
  479. if err != nil {
  480. return
  481. }
  482. if recycle {
  483. defer pool.Put(msg)
  484. }
  485. msgLen := len(msg)
  486. id = binary.BigEndian.Uint16(msg[0:2])
  487. // ping信息
  488. if msgLen == 2 {
  489. msgType = conn.PingMsg
  490. return
  491. }
  492. if id > config.ID_MAX {
  493. err = fmt.Errorf("wrong message id: %d", id)
  494. return
  495. }
  496. cmdx := msg[2]
  497. if (cmdx & 0x80) == 0 {
  498. // 请求包
  499. msgType = conn.RequestMsg
  500. cmdLen := int(cmdx)
  501. cmd = string(msg[3 : cmdLen+3])
  502. data = msg[cmdLen+3:]
  503. } else {
  504. // 响应数据包
  505. msgType = conn.ResponseMsg
  506. state = cmdx & 0x7F
  507. data = msg[3:]
  508. }
  509. dataLen := len(data)
  510. if c.compress && dataLen > 1 {
  511. var ok bool
  512. data, ok, err = util.UncompressData(data)
  513. if !ok && recycle {
  514. data = slices.Clone(data)
  515. }
  516. if ok && c.cf.PrintMsg {
  517. log.Println("[UncompressData]", dataLen, "->", len(data))
  518. }
  519. } else if recycle && dataLen > 0 {
  520. data = slices.Clone(data)
  521. }
  522. return
  523. }
  524. // 获取远程的地址
  525. func (c *Tcp2) RemoteIP() net.IP {
  526. return util.AddrToIP(c.conn.RemoteAddr())
  527. }
  528. // 获取本地的地址
  529. func (c *Tcp2) LocalIP() net.IP {
  530. return util.AddrToIP(c.conn.LocalAddr())
  531. }
  532. func (c *Tcp2) Close() error {
  533. return c.conn.Close()
  534. }