tcp2.go 13 KB

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