tcp2.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  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. "git.me9.top/git/tinymq/util/pool"
  16. )
  17. const PROTO string = "tcp"
  18. const VERSION uint8 = 2
  19. // 第一级数据包的最大长度,如果超过则自动增加一个地址位到4个字节
  20. const MAX_LENGTH = 0xFFFF
  21. // 由于都是内部使用,感觉没有必要加这个限制
  22. // const MAX2_LENGTH = 0x1FFFFFFF // 500 M,避免申请过大内存
  23. type Tcp2 struct {
  24. cf *config.Config
  25. conn net.Conn
  26. cipher *util.Cipher // 记录当前的加解密类
  27. compress bool // 是否启用压缩
  28. }
  29. // 服务端
  30. // hash 格式 encryptMethod:encryptKey
  31. func Server(cf *config.Config, bind string, hash string, fn conn.ServerConnectFunc) (err error) {
  32. var ci *util.CipherInfo
  33. var encryptKey string
  34. if hash != "" {
  35. i := strings.Index(hash, ":")
  36. if i <= 0 {
  37. err = errors.New("hash is invalid")
  38. return
  39. }
  40. encryptMethod := hash[0:i]
  41. encryptKey = hash[i+1:]
  42. if c, ok := util.CipherMethod[encryptMethod]; ok {
  43. ci = c
  44. } else {
  45. return errors.New("Unsupported encryption method: " + encryptMethod)
  46. }
  47. }
  48. log.Printf("Listening and serving tcp on %s\n", bind)
  49. l, err := net.Listen("tcp", bind)
  50. if err != nil {
  51. log.Println("[tcp2 Server ERROR]", err)
  52. return
  53. }
  54. go func(l net.Listener) {
  55. defer l.Close()
  56. for {
  57. conn, err := l.Accept()
  58. if err != nil {
  59. log.Println("[accept ERROR]", err)
  60. return
  61. }
  62. go func(conn net.Conn) {
  63. if ci == nil {
  64. c := &Tcp2{
  65. cf: cf,
  66. conn: conn,
  67. }
  68. fn(c)
  69. return
  70. }
  71. var eiv []byte
  72. var div []byte
  73. if ci.IvLen > 0 {
  74. // 服务端 IV
  75. eiv = pool.Get(ci.IvLen)
  76. defer pool.Put(eiv)
  77. _, err = rand.Read(eiv)
  78. if err != nil {
  79. log.Println("[tcp2 Server rand.Read ERROR]", err)
  80. return
  81. }
  82. // 发送 IV
  83. conn.SetWriteDeadline(time.Now().Add(time.Duration(cf.WriteWait) * time.Millisecond))
  84. if _, err := conn.Write(eiv); err != nil {
  85. log.Println("[tcp2 Server conn.Write ERROR]", err)
  86. return
  87. }
  88. // 读取 IV
  89. err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(cf.ReadWait)))
  90. if err != nil {
  91. log.Println("[tcp2 Server SetReadDeadline ERROR]", err)
  92. return
  93. }
  94. div = pool.Get(ci.IvLen)
  95. defer pool.Put(div)
  96. _, err := io.ReadFull(conn, div)
  97. if err != nil {
  98. log.Println("[tcp2 Server ReadFull ERROR]", err)
  99. return
  100. }
  101. }
  102. cipher, err := util.NewCipher(ci, encryptKey, eiv, div)
  103. if err != nil {
  104. log.Println("[tcp2 NewCipher ERROR]", err)
  105. return
  106. }
  107. // 初始化
  108. c := &Tcp2{
  109. cf: cf,
  110. conn: conn,
  111. cipher: cipher,
  112. }
  113. fn(c)
  114. }(conn)
  115. }
  116. }(l)
  117. return
  118. }
  119. // 客户端,新建一个连接
  120. func Dial(cf *config.Config, addr string, hash string) (conn.Connect, error) {
  121. // 没有加密的情况
  122. if hash == "" {
  123. conn, err := net.DialTimeout("tcp", addr, time.Duration(cf.ConnectTimeout)*time.Millisecond)
  124. if err != nil {
  125. return nil, err
  126. }
  127. c := &Tcp2{
  128. cf: cf,
  129. conn: conn,
  130. }
  131. return c, nil
  132. }
  133. i := strings.Index(hash, ":")
  134. if i <= 0 {
  135. return nil, errors.New("hash is invalid")
  136. }
  137. encryptMethod := hash[0:i]
  138. encryptKey := hash[i+1:]
  139. ci, ok := util.CipherMethod[encryptMethod]
  140. if !ok {
  141. return nil, errors.New("Unsupported encryption method: " + encryptMethod)
  142. }
  143. conn, err := net.DialTimeout("tcp", addr, time.Duration(cf.ConnectTimeout)*time.Millisecond)
  144. if err != nil {
  145. return nil, err
  146. }
  147. var eiv []byte
  148. var div []byte
  149. if ci.IvLen > 0 {
  150. // 客户端 IV
  151. eiv = pool.Get(ci.IvLen)
  152. defer pool.Put(eiv)
  153. _, err = rand.Read(eiv)
  154. if err != nil {
  155. log.Println("[tcp2 Client rand.Read ERROR]", err)
  156. return nil, err
  157. }
  158. // 发送 IV
  159. conn.SetWriteDeadline(time.Now().Add(time.Duration(cf.WriteWait) * time.Millisecond))
  160. if _, err := conn.Write(eiv); err != nil {
  161. log.Println("[tcp2 Client conn.Write ERROR]", err)
  162. return nil, err
  163. }
  164. // 读取 IV
  165. err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(cf.ReadWait)))
  166. if err != nil {
  167. log.Println("[tcp2 Client SetReadDeadline ERROR]", err)
  168. return nil, err
  169. }
  170. div = pool.Get(ci.IvLen)
  171. defer pool.Put(div)
  172. _, err := io.ReadFull(conn, div)
  173. if err != nil {
  174. log.Println("[tcp2 Client ReadFull ERROR]", err)
  175. return nil, err
  176. }
  177. }
  178. cipher, err := util.NewCipher(ci, encryptKey, eiv, div)
  179. if err != nil {
  180. log.Println("[tcp2 NewCipher ERROR]", err)
  181. return nil, err
  182. }
  183. // 初始化
  184. c := &Tcp2{
  185. cf: cf,
  186. conn: conn,
  187. cipher: cipher,
  188. compress: true,
  189. }
  190. return c, nil
  191. }
  192. // 发送数据包到网络
  193. // recycle 指示是否需要将raw放回内存池
  194. func (c *Tcp2) WriteRawPackage(raw []byte, recycle bool) (err error) {
  195. var buf []byte
  196. var index int
  197. dlen := len(raw)
  198. if dlen >= MAX_LENGTH {
  199. buf = pool.Get(dlen + 2 + 4 + 1)
  200. index = 2 + 4
  201. binary.BigEndian.PutUint16(buf[:2], MAX_LENGTH)
  202. binary.BigEndian.PutUint32(buf[2:6], uint32(dlen))
  203. } else {
  204. buf = pool.Get(dlen + 2 + 1)
  205. index = 2
  206. binary.BigEndian.PutUint16(buf[:2], uint16(dlen))
  207. }
  208. copy(buf[index:index+dlen], raw)
  209. index += dlen
  210. buf[index] = util.CRC8(raw)
  211. if recycle {
  212. pool.Put(raw)
  213. }
  214. defer pool.Put(buf)
  215. if c.cipher != nil {
  216. c.cipher.Encrypt(buf, buf)
  217. }
  218. c.conn.SetWriteDeadline(time.Now().Add(time.Duration(c.cf.WriteWait) * time.Millisecond))
  219. for {
  220. n, err := c.conn.Write(buf)
  221. if err != nil {
  222. return err
  223. }
  224. if n < len(buf) {
  225. buf = buf[n:]
  226. } else {
  227. return nil
  228. }
  229. }
  230. }
  231. // 从连接中读取数据包,已经剥离了头部长度和尾部crc
  232. // recycle 指示是否需要手动将缓存放回内存池
  233. func (c *Tcp2) ReadRawPackage(deadline int) (buf []byte, recycle bool, err error) {
  234. err = c.conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(deadline)))
  235. if err != nil {
  236. return nil, false, err
  237. }
  238. buf = pool.Get(2)
  239. // 读取数据流长度
  240. _, err = io.ReadFull(c.conn, buf)
  241. if err != nil {
  242. pool.Put(buf)
  243. return nil, false, err
  244. }
  245. // 将读出来的数据进行解密
  246. if c.cipher != nil {
  247. c.cipher.Decrypt(buf, buf)
  248. }
  249. dlen := uint32(binary.BigEndian.Uint16(buf))
  250. pool.Put(buf)
  251. if dlen < 2 {
  252. return nil, false, errors.New("length is less to 2")
  253. }
  254. if dlen >= MAX_LENGTH {
  255. // 数据包比较大,通过后面的4位长度来表示实际长度
  256. buf := pool.Get(4)
  257. _, err := io.ReadFull(c.conn, buf)
  258. if err != nil {
  259. pool.Put(buf)
  260. return nil, false, err
  261. }
  262. if c.cipher != nil {
  263. c.cipher.Decrypt(buf, buf)
  264. }
  265. dlen = binary.BigEndian.Uint32(buf)
  266. pool.Put(buf)
  267. if dlen < MAX_LENGTH {
  268. return nil, false, errors.New("wrong length in read message")
  269. }
  270. }
  271. // 读取指定长度的数据
  272. buf = pool.Get(int(dlen) + 1) // 最后一个是crc的值
  273. _, err = io.ReadFull(c.conn, buf)
  274. if err != nil {
  275. pool.Put(buf)
  276. return nil, false, err
  277. }
  278. if c.cipher != nil {
  279. c.cipher.Decrypt(buf, buf)
  280. }
  281. // 检查CRC8
  282. if util.CRC8(buf[:dlen]) != buf[dlen] {
  283. pool.Put(buf)
  284. return nil, false, errors.New("CRC error")
  285. }
  286. return buf[:dlen], true, nil
  287. }
  288. // 发送Auth信息
  289. // 建立连接后第一个发送的消息
  290. func (c *Tcp2) WriteAuthInfo(channel string, auth []byte) (err error) {
  291. buf := conn.AuthPackageEncode(PROTO, VERSION, channel, auth, c.compress)
  292. return c.WriteRawPackage(buf, true)
  293. }
  294. // 获取Auth信息
  295. func (c *Tcp2) ReadAuthInfo() (proto string, version uint8, channel string, auth []byte, err error) {
  296. defer func() {
  297. if r := recover(); r != nil {
  298. err = fmt.Errorf("recovered from panic: %v", r)
  299. return
  300. }
  301. }()
  302. msg, recycle, err := c.ReadRawPackage(c.cf.ReadWait)
  303. if err != nil {
  304. return
  305. }
  306. var compress bool
  307. proto, version, compress, channel, auth, err = conn.AuthPackageDecode(msg, recycle)
  308. if err != nil {
  309. return
  310. }
  311. if proto != PROTO {
  312. err = fmt.Errorf("wrong proto: %s", proto)
  313. return
  314. }
  315. if version != VERSION {
  316. err = fmt.Errorf("require version %d, get version: %d", VERSION, version)
  317. return
  318. }
  319. c.compress = compress
  320. return
  321. }
  322. // 发送请求数据包到网络
  323. func (c *Tcp2) WriteRequest(id uint16, cmd string, data []byte) error {
  324. buf := conn.RequestPackageEncode(id, cmd, data, c.compress, c.cf)
  325. return c.WriteRawPackage(buf, true)
  326. }
  327. // 发送响应数据包到网络
  328. // 网络格式:[id, stateCode, data]
  329. func (c *Tcp2) WriteResponse(id uint16, state uint8, data []byte) error {
  330. buf := conn.ResponsePackageEncode(id, state, data, c.compress, c.cf)
  331. return c.WriteRawPackage(buf, true)
  332. }
  333. // 发送ping包
  334. func (c *Tcp2) WritePing(id uint16) error {
  335. buf := conn.PingPackageEncode(id)
  336. return c.WriteRawPackage(buf, true)
  337. }
  338. // 获取信息
  339. func (c *Tcp2) ReadMessage(deadline int) (msgType conn.MsgType, id uint16, cmd string, state uint8, data []byte, err error) {
  340. msg, recycle, err := c.ReadRawPackage(deadline)
  341. if err != nil {
  342. return
  343. }
  344. return conn.PackageDecode(msg, recycle, c.compress, c.cf)
  345. }
  346. // 获取远程的地址
  347. func (c *Tcp2) RemoteIP() net.IP {
  348. return util.AddrToIP(c.conn.RemoteAddr())
  349. }
  350. // 获取本地的地址
  351. func (c *Tcp2) LocalIP() net.IP {
  352. return util.AddrToIP(c.conn.LocalAddr())
  353. }
  354. func (c *Tcp2) Close() error {
  355. return c.conn.Close()
  356. }