client_windows.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. //go:build windows
  2. package yu_hpsocket
  3. import (
  4. yu_proxy "gogs.qqck.cn/s/tools/proxy"
  5. yu_sys "gogs.qqck.cn/s/tools/sys"
  6. )
  7. // Client
  8. //
  9. // @Description: Client 系列组件底层实现
  10. type Client[T any] struct {
  11. hListener uintptr
  12. hClient uintptr
  13. SSL bool
  14. Extra any // 附加数据
  15. // exdata----------------------------------
  16. socket uintptr
  17. // 事件----------------------------------
  18. onPrepareConnect func(t *T, Sender, ConnID, socket uintptr) HR
  19. onConnect func(t *T, Sender, ConnID uintptr) HR
  20. onHandShake func(t *T, Sender, ConnID uintptr) HR
  21. onSend func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR
  22. onReceive func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR
  23. onClose func(t *T, Sender, ConnID uintptr, Operation SO, ErrorCode int) HR
  24. // 扩展----------------------------------------------------------------
  25. _RemoteAddress string
  26. _Port int
  27. proxy_info *yu_proxy.Info
  28. proxy_connect bool
  29. }
  30. // isValid
  31. //
  32. // @Description: 对象是否有效
  33. func (t *Client[T]) isValid() bool {
  34. return t.hListener != 0 && t.hClient != 0
  35. }
  36. // Start
  37. //
  38. // @Description: 启动通信组件(并指定【可选】绑定地址)
  39. // @param RemoteAddress 服务端地址
  40. // @param Port 服务端端口
  41. // @param AsyncConnect 是否采用异步 Connect
  42. // @param BindAddress 绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)
  43. // @param LocalPort 本地端口(默认:0)
  44. // @return bool 是否启动成功
  45. func (t *Client[T]) Start(RemoteAddress string, Port int, AsyncConnect bool, BindAddress string, LocalPort int) bool {
  46. if !t.isValid() {
  47. return false
  48. }
  49. // -------------------------------------------------------------------------------关联必要事件
  50. if t.onPrepareConnect == nil {
  51. t.OnPrepareConnect(func(t *T, Sender, ConnID, socket uintptr) HR {
  52. return HR_IGNORE
  53. })
  54. }
  55. // -------------------------------------------------------------------------------关联必要事件------end
  56. if t.proxy_info.Host == "" {
  57. return HP_Client_StartWithBindAddressAndLocalPort.CallBool(t.hClient,
  58. yu_sys.S{yu_sys.Gbk, RemoteAddress}, Port,
  59. AsyncConnect,
  60. yu_sys.S{yu_sys.Gbk, BindAddress}, LocalPort,
  61. )
  62. }
  63. // -------------------------------------------------------------------------------判断代理是否有效
  64. if !t.proxy_info.IsValid() || t.proxy_info.IsTimeout() {
  65. return false
  66. }
  67. // -------------------------------------------------------------------------------关联必要事件
  68. if t.onConnect == nil {
  69. t.OnConnect(func(t *T, Sender, ConnID uintptr) HR {
  70. return HR_IGNORE
  71. })
  72. }
  73. // -------------------------------------------------------------------------------关联必要事件------end
  74. t._RemoteAddress, t._Port = RemoteAddress, Port
  75. return HP_Client_StartWithBindAddressAndLocalPort.CallBool(t.hClient,
  76. yu_sys.S{yu_sys.Gbk, t.proxy_info.Host}, t.proxy_info.Port,
  77. AsyncConnect,
  78. yu_sys.S{yu_sys.Gbk, BindAddress}, LocalPort,
  79. )
  80. }
  81. // Stop
  82. //
  83. // @Description: 关闭客户端通信组件,关闭完成后断开与服务端的连接并释放所有资源
  84. // @return bool 是否成功关闭
  85. func (t *Client[T]) Stop() bool {
  86. if !t.isValid() {
  87. return false
  88. }
  89. return HP_Client_Stop.CallBool(t.hClient)
  90. }
  91. // Wait
  92. //
  93. // @Description: 等待通信组件停止运行
  94. // @param Milliseconds 超时时间(毫秒,默认:-1,永不超时)
  95. // @return bool 超时返回 false
  96. func (t *Client[T]) Wait(Milliseconds int) bool {
  97. if !t.isValid() {
  98. return false
  99. }
  100. return HP_Client_Wait.CallBool(t.hClient, Milliseconds)
  101. }
  102. // Send
  103. //
  104. // @Description: 向服务端发送数据
  105. // @param buf 欲发送的数据
  106. // @return bool 是否发送成功
  107. func (t *Client[T]) Send(buf []byte) bool {
  108. if !t.isValid() {
  109. return false
  110. }
  111. if len(buf) == 0 {
  112. return true
  113. }
  114. return HP_Client_Send.CallBool(t.hClient, buf, len(buf))
  115. }
  116. // SendS
  117. //
  118. // @Description: 向服务端发送数据
  119. // @param buf 欲发送的数据
  120. // @return bool 是否发送成功
  121. func (t *Client[T]) SendS(buf string) bool {
  122. if !t.isValid() {
  123. return false
  124. }
  125. if len(buf) == 0 {
  126. return true
  127. }
  128. return HP_Client_Send.CallBool(t.hClient, buf, len(buf))
  129. }
  130. // IsSecure
  131. //
  132. // @Description: 检测是否为安全连接(SSL/HTTPS)
  133. func (t *Client[T]) IsSecure() bool {
  134. if !t.isValid() {
  135. return false
  136. }
  137. return HP_Client_IsSecure.CallBool(t.hClient)
  138. }
  139. // SetExtra
  140. //
  141. // @Description: 设置连接的附加数据
  142. func (t *Client[T]) SetExtra(extra uintptr) *Client[T] {
  143. if !t.isValid() {
  144. return t
  145. }
  146. HP_Client_SetExtra.Call(t.hClient, extra)
  147. return t
  148. }
  149. // GetExtra
  150. //
  151. // @Description: 获取连接的附加数据
  152. func (t *Client[T]) GetExtra() uintptr {
  153. if !t.isValid() {
  154. return 0
  155. }
  156. return HP_Client_GetExtra.CallUintptr(t.hClient)
  157. }
  158. // HasStarted
  159. //
  160. // @Description: 检查通信组件是否已启动
  161. func (t *Client[T]) HasStarted() bool {
  162. if !t.isValid() {
  163. return false
  164. }
  165. return HP_Client_HasStarted.CallBool(t.hClient)
  166. }
  167. // GetState
  168. //
  169. // @Description: 查看通信组件当前状态,SS_ 开头常量
  170. func (t *Client[T]) GetState() SS {
  171. if !t.isValid() {
  172. return SS_STOPPED
  173. }
  174. return SS(HP_Client_GetState.CallUintptr(t.hClient))
  175. }
  176. // GetLastError
  177. //
  178. // @Description: 获取最近一次失败操作的错误代码
  179. func (t *Client[T]) GetLastError() int {
  180. if !t.isValid() {
  181. return 0
  182. }
  183. return HP_Client_GetLastError.CallInt(t.hClient)
  184. }
  185. // GetLastErrorDesc
  186. //
  187. // @Description: 获取最近一次失败操作的错误描述
  188. func (t *Client[T]) GetLastErrorDesc() string {
  189. if !t.isValid() {
  190. return "Not Object"
  191. }
  192. return HP_Client_GetLastErrorDesc.CallGbkToUtf8(t.hClient)
  193. }
  194. // GetConnectionID
  195. //
  196. // @Description: 获取该组件对象的连接 ID
  197. func (t *Client[T]) GetConnectionID() uintptr {
  198. if !t.isValid() {
  199. return 0
  200. }
  201. return HP_Client_GetConnectionID.CallUintptr(t.hClient)
  202. }
  203. // GetLocalAddress
  204. //
  205. // @Description: 获取连接的本地绑定信息
  206. func (t *Client[T]) GetLocalAddress() (address string, port int) {
  207. if !t.isValid() {
  208. return
  209. }
  210. j_address_len := 128
  211. j_address := make([]byte, 64)
  212. if !HP_Client_GetLocalAddress.CallBool(t.hClient, j_address, &j_address_len, &port) {
  213. return
  214. }
  215. j_address_len -= 1 // 有结束符 {0}
  216. j_unicode_len := j_address_len * 2
  217. j_unicode := make([]byte, j_unicode_len)
  218. yu_sys.MultiByteToWideChar.Call(936, 0, j_address, j_address_len, j_unicode, j_unicode_len)
  219. j_utf8_size := j_unicode_len * 2
  220. j_utf8 := make([]byte, j_utf8_size)
  221. address = string(j_utf8[:yu_sys.WideCharToMultiByte.CallInt(65001, 0, j_unicode, j_address_len, j_utf8, j_utf8_size, 0, 0)])
  222. return
  223. }
  224. // GetRemoteHost
  225. //
  226. // @Description: 获取连接的远程主机信息
  227. func (t *Client[T]) GetRemoteHost() (address string, port int) {
  228. if !t.isValid() {
  229. return
  230. }
  231. j_address_len := 128
  232. j_address := make([]byte, 64)
  233. if !HP_Client_GetRemoteHost.CallBool(t.hClient, j_address, &j_address_len, &port) {
  234. return
  235. }
  236. j_address_len -= 1 // 有结束符 {0}
  237. j_unicode_len := j_address_len * 2
  238. j_unicode := make([]byte, j_unicode_len)
  239. yu_sys.MultiByteToWideChar.Call(936, 0, j_address, j_address_len, j_unicode, j_unicode_len)
  240. j_utf8_size := j_unicode_len * 2
  241. j_utf8 := make([]byte, j_utf8_size)
  242. address = string(j_utf8[:yu_sys.WideCharToMultiByte.CallInt(65001, 0, j_unicode, j_address_len, j_utf8, j_utf8_size, 0, 0)])
  243. return
  244. }
  245. // GetPendingDataLength
  246. //
  247. // @Description: 获取连接中未发出数据的长度
  248. func (t *Client[T]) GetPendingDataLength() (length int) {
  249. if !t.isValid() {
  250. return
  251. }
  252. HP_Client_GetPendingDataLength.Call(t.hClient, &length)
  253. return
  254. }
  255. // SetFreeBufferPoolSize
  256. //
  257. // @Description: 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 )
  258. func (t *Client[T]) SetFreeBufferPoolSize(FreeBufferPoolSize int) *Client[T] {
  259. if !t.isValid() {
  260. return t
  261. }
  262. HP_Client_SetFreeBufferPoolSize.Call(t.hClient, FreeBufferPoolSize)
  263. return t
  264. }
  265. // SetFreeBufferPoolHold
  266. //
  267. // @Description: 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍)
  268. func (t *Client[T]) SetFreeBufferPoolHold(FreeBufferPoolHold int) *Client[T] {
  269. if !t.isValid() {
  270. return t
  271. }
  272. HP_Client_SetFreeBufferPoolHold.Call(t.hClient, FreeBufferPoolHold)
  273. return t
  274. }
  275. // GetFreeBufferPoolSize
  276. //
  277. // @Description: 获取内存块缓存池大小
  278. func (t *Client[T]) GetFreeBufferPoolSize() int {
  279. if !t.isValid() {
  280. return 0
  281. }
  282. return HP_Client_GetFreeBufferPoolSize.CallInt(t.hClient)
  283. }
  284. // GetFreeBufferPoolHold
  285. //
  286. // @Description: 获取内存块缓存池回收阀值
  287. func (t *Client[T]) GetFreeBufferPoolHold() int {
  288. if !t.isValid() {
  289. return 0
  290. }
  291. return HP_Client_GetFreeBufferPoolHold.CallInt(t.hClient)
  292. }
  293. // SetupSSLContext
  294. //
  295. // @Description: 初始化通信组件 SSL环境参数,SSL环境参数必须在 SSL通信组件启动前完成初始化,否则启动失败
  296. // @param VerifyMode SSL_VM_ 开头常量,SSL验证模式
  297. // @param PemCertFile 证书文件
  298. // @param PemKeyFile 私钥文件
  299. // @param KeyPasswod 私钥密码(没有密码则为空)
  300. // @param CAPemCertFileOrPath CA 证书文件或目录(单向验证或客户端可选)
  301. func (t *Client[T]) SetupSSLContext(VerifyMode SSL_VM, PemCertFile, PemKeyFile, KeyPasswod, CAPemCertFileOrPath string) bool {
  302. if !t.isValid() {
  303. return false
  304. }
  305. return HP_SSLClient_SetupSSLContext.CallBool(t.hClient, uintptr(VerifyMode),
  306. yu_sys.S{yu_sys.Gbk, PemCertFile}, yu_sys.S{yu_sys.Gbk, PemKeyFile},
  307. yu_sys.S{yu_sys.Gbk, KeyPasswod}, yu_sys.S{yu_sys.Gbk, CAPemCertFileOrPath},
  308. )
  309. }
  310. // SetupSSLContextByMemory
  311. //
  312. // @Description: 初始化通信组件 SSL环境参数,SSL环境参数必须在 SSL通信组件启动前完成初始化,否则启动失败
  313. // @param VerifyMode SSL_VM_ 开头常量,SSL验证模式
  314. // @param PemCert 证书内容
  315. // @param PemKey 私钥内容
  316. // @param KeyPasswod 私钥密码(没有密码则为空)
  317. // @param CAPemCert CA 证书内容(单向验证可选)
  318. func (t *Client[T]) SetupSSLContextByMemory(VerifyMode SSL_VM, PemCert, PemKey, KeyPasswod, CAPemCert string) bool {
  319. if !t.isValid() {
  320. return false
  321. }
  322. return HP_SSLClient_SetupSSLContextByMemory.CallBool(t.hClient, uintptr(VerifyMode),
  323. yu_sys.S{yu_sys.Gbk, PemCert}, yu_sys.S{yu_sys.Gbk, PemKey},
  324. yu_sys.S{yu_sys.Gbk, KeyPasswod}, yu_sys.S{yu_sys.Gbk, CAPemCert},
  325. )
  326. }
  327. // CleanupSSLContext
  328. //
  329. // @Description: 清理通信组件 SSL运行环境,回收 SSL相关内存
  330. func (t *Client[T]) CleanupSSLContext() *Client[T] {
  331. if !t.isValid() {
  332. return t
  333. }
  334. HP_SSLClient_CleanupSSLContext.Call(t.hClient)
  335. return t
  336. }
  337. // StartSSLHandShake
  338. //
  339. // @Description: 启动 SSL握手,当通信组件设置为非自动握手时,需要调用本方法启动 SSL握手
  340. func (t *Client[T]) StartSSLHandShake() bool {
  341. if !t.isValid() {
  342. return false
  343. }
  344. return HP_SSLClient_StartSSLHandShake.CallBool(t.hClient)
  345. }
  346. // SetSSLAutoHandShake
  347. //
  348. // @Description: 设置通信组件握手方式(默认:true,自动握手)
  349. func (t *Client[T]) SetSSLAutoHandShake(AutoHandShake bool) *Client[T] {
  350. if !t.isValid() {
  351. return t
  352. }
  353. HP_SSLClient_SetSSLAutoHandShake.Call(t.hClient, AutoHandShake)
  354. return t
  355. }
  356. // IsSSLAutoHandShake
  357. //
  358. // @Description: 获取通信组件握手方式
  359. func (t *Client[T]) IsSSLAutoHandShake() bool {
  360. if !t.isValid() {
  361. return false
  362. }
  363. return HP_SSLClient_IsSSLAutoHandShake.CallBool(t.hClient)
  364. }
  365. // SetSSLCipherList
  366. //
  367. // @Description: 设置 SSL加密算法列表
  368. func (t *Client[T]) SetSSLCipherList(CipherList string) *Client[T] {
  369. if !t.isValid() {
  370. return t
  371. }
  372. HP_SSLClient_SetSSLCipherList.Call(t.hClient, yu_sys.S{yu_sys.Gbk, CipherList})
  373. return t
  374. }
  375. // GetSSLCipherList
  376. //
  377. // @Description: 获取 SSL加密算法列表
  378. func (t *Client[T]) GetSSLCipherList() string {
  379. if !t.isValid() {
  380. return ""
  381. }
  382. return HP_SSLClient_GetSSLCipherList.CallGbkToUtf8(t.hClient)
  383. }
  384. // GetSSLSessionInfo
  385. //
  386. // @Description: 获取指定类型的 SSLSession 信息(输出类型参考:SSL_SSI_)
  387. // @param enInfo SSL_SSI_ 开头常量
  388. func (t *Client[T]) GetSSLSessionInfo(enInfo SSL_SSI) (Info uintptr) {
  389. if !t.isValid() {
  390. return
  391. }
  392. HP_SSLClient_GetSSLSessionInfo.Call(t.hClient, uintptr(enInfo), &Info)
  393. return
  394. }
  395. // IsPauseReceive
  396. //
  397. // @Description: 获取连接的数据接收状态
  398. func (t *Client[T]) IsPauseReceive() (Paused bool) {
  399. if !t.isValid() {
  400. return
  401. }
  402. HP_Client_IsPauseReceive.Call(t.hClient, &Paused)
  403. return
  404. }
  405. // IsConnected
  406. //
  407. // @Description: 检测是否有效连接
  408. func (t *Client[T]) IsConnected() bool {
  409. if !t.isValid() {
  410. return false
  411. }
  412. return HP_Client_IsConnected.CallBool(t.hClient)
  413. }
  414. // SetReuseAddressPolicy
  415. //
  416. // @Description: 设置地址重用选项
  417. // @param enReusePolicy RAP_ 开头常量
  418. func (t *Client[T]) SetReuseAddressPolicy(ReusePolicy RAP) *Client[T] {
  419. if !t.isValid() {
  420. return t
  421. }
  422. HP_Client_SetReuseAddressPolicy.Call(t.hClient, uintptr(ReusePolicy))
  423. return t
  424. }
  425. // GetReuseAddressPolicy
  426. //
  427. // @Description: 获取地址重用选项 RAP_ 开头常量
  428. func (t *Client[T]) GetReuseAddressPolicy() RAP {
  429. if !t.isValid() {
  430. return RAP_NONE
  431. }
  432. return RAP(HP_Client_GetReuseAddressPolicy.CallUintptr(t.hClient))
  433. }
  434. // PauseReceive
  435. //
  436. // @Description: 暂停/恢复某个连接的数据接收工作
  437. func (t *Client[T]) PauseReceive(Paused bool) bool {
  438. if !t.isValid() {
  439. return false
  440. }
  441. return HP_Client_PauseReceive.CallBool(t.hClient, Paused)
  442. }
  443. // OnPrepareConnect
  444. //
  445. // @Description: 【可选】绑定准备连接事件
  446. // @param call->return HR_ 开头常量
  447. func (t *Client[T]) OnPrepareConnect(call func(t *T, Sender, ConnID, socket uintptr) HR) *Client[T] {
  448. if !t.isValid() {
  449. return t
  450. }
  451. if call == nil {
  452. HP_Set_FN_Client_OnPrepareConnect.Call(t.hListener, 0)
  453. } else {
  454. t.onPrepareConnect = call
  455. HP_Set_FN_Client_OnPrepareConnect.Call(t.hListener, client_callback_OnPrepareConnect_ptr)
  456. }
  457. return t
  458. }
  459. // OnConnect
  460. //
  461. // @Description: 【可选】绑定连接事件
  462. // @param call->return HR_ 开头常量
  463. func (t *Client[T]) OnConnect(call func(t *T, Sender, ConnID uintptr) HR) *Client[T] {
  464. if !t.isValid() {
  465. return t
  466. }
  467. if call == nil {
  468. HP_Set_FN_Client_OnConnect.Call(t.hListener, 0)
  469. } else {
  470. t.onConnect = call
  471. HP_Set_FN_Client_OnConnect.Call(t.hListener, client_callback_OnConnect_ptr)
  472. }
  473. return t
  474. }
  475. // OnHandShake
  476. //
  477. // @Description: 【可选】绑定握手事件
  478. // @param call->return HR_ 开头常量
  479. func (t *Client[T]) OnHandShake(call func(t *T, Sender, ConnID uintptr) HR) *Client[T] {
  480. if !t.isValid() {
  481. return t
  482. }
  483. if call == nil {
  484. HP_Set_FN_Client_OnHandShake.Call(t.hListener, 0)
  485. } else {
  486. t.onHandShake = call
  487. HP_Set_FN_Client_OnHandShake.Call(t.hListener, client_callback_OnHandShake_ptr)
  488. }
  489. return t
  490. }
  491. // OnSend
  492. //
  493. // @Description: 【可选】绑定发送事件
  494. // @param call->return HR_ 开头常量
  495. func (t *Client[T]) OnSend(call func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR) *Client[T] {
  496. if !t.isValid() {
  497. return t
  498. }
  499. if call == nil {
  500. HP_Set_FN_Client_OnSend.Call(t.hListener, 0)
  501. } else {
  502. t.onSend = call
  503. HP_Set_FN_Client_OnSend.Call(t.hListener, client_callback_OnSend_ptr)
  504. }
  505. return t
  506. }
  507. // OnReceive
  508. //
  509. // @Description: 【必选】绑定数据接收事件
  510. // @param call->return HR_ 开头常量
  511. func (t *Client[T]) OnReceive(call func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR) *Client[T] {
  512. if !t.isValid() {
  513. return t
  514. }
  515. if call == nil {
  516. HP_Set_FN_Client_OnReceive.Call(t.hListener, 0)
  517. } else {
  518. t.onReceive = call
  519. HP_Set_FN_Client_OnReceive.Call(t.hListener, client_callback_OnReceive_ptr)
  520. }
  521. return t
  522. }
  523. // OnClose
  524. //
  525. // @Description: 【必选】绑定断开事件
  526. // @param call->Operation 通过该参数标识是哪种操作导致的错误 SO_ 开头常量
  527. // @param call->return HR_ 开头常量
  528. func (t *Client[T]) OnClose(call func(t *T, Sender, ConnID uintptr, Operation SO, ErrorCode int) HR) *Client[T] {
  529. if !t.isValid() {
  530. return t
  531. }
  532. if call == nil {
  533. HP_Set_FN_Client_OnClose.Call(t.hListener, 0)
  534. } else {
  535. t.onClose = call
  536. HP_Set_FN_Client_OnClose.Call(t.hListener, client_callback_OnClose_ptr)
  537. }
  538. return t
  539. }
  540. // OnDefault
  541. //
  542. // @Description: 【可选】绑定所有【必选】事件
  543. func (t *Client[T]) OnDefault() *Client[T] {
  544. if !t.isValid() {
  545. return t
  546. }
  547. if t.onReceive == nil {
  548. t.OnReceive(func(t *T, Sender, ConnID, Data uintptr, Length uintptr) HR {
  549. return HR_OK
  550. })
  551. }
  552. if t.onClose == nil {
  553. t.OnClose(func(t *T, Sender, ConnID uintptr, Operation SO, ErrorCode int) HR {
  554. return HR_OK
  555. })
  556. }
  557. return t
  558. }