/src/hev-socks5-session-udp.c

https://github.com/heiher/hev-socks5-tproxy · C · 302 lines · 228 code · 66 blank · 8 comment · 29 complexity · ce46c851dfcbf60b6b44801fd587d3d0 MD5 · raw file

  1. /*
  2. ============================================================================
  3. Name : hev-socks5-session-udp.c
  4. Author : Heiher <r@hev.cc>
  5. Copyright : Copyright (c) 2017 - 2021 hev
  6. Description : Socks5 Session UDP
  7. ============================================================================
  8. */
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <hev-task.h>
  13. #include <hev-task-io.h>
  14. #include <hev-task-io-socket.h>
  15. #include <hev-memory-allocator.h>
  16. #include <hev-socks5-udp.h>
  17. #include <hev-socks5-misc.h>
  18. #include <hev-socks5-client-udp.h>
  19. #include "hev-logger.h"
  20. #include "hev-compiler.h"
  21. #include "hev-config-const.h"
  22. #include "hev-tsocks-cache.h"
  23. #include "hev-socks5-session-udp.h"
  24. #define task_io_yielder hev_socks5_task_io_yielder
  25. typedef struct _HevSocks5UDPFrame HevSocks5UDPFrame;
  26. struct _HevSocks5UDPFrame
  27. {
  28. HevListNode node;
  29. struct sockaddr_in6 addr;
  30. void *data;
  31. size_t len;
  32. };
  33. static int
  34. hev_socks5_session_udp_fwd_f (HevSocks5SessionUDP *self)
  35. {
  36. HevSocks5UDPFrame *frame;
  37. struct sockaddr *addr;
  38. HevListNode *node;
  39. HevSocks5UDP *udp;
  40. int res;
  41. LOG_D ("%p socks5 session udp fwd f", self);
  42. node = hev_list_first (&self->frame_list);
  43. if (!node)
  44. return 0;
  45. frame = container_of (node, HevSocks5UDPFrame, node);
  46. addr = (struct sockaddr *)&frame->addr;
  47. udp = HEV_SOCKS5_UDP (self);
  48. res = hev_socks5_udp_sendto (udp, frame->data, frame->len, addr);
  49. if (res <= 0) {
  50. LOG_E ("%p socks5 session udp fwd f send", self);
  51. res = -1;
  52. }
  53. hev_list_del (&self->frame_list, node);
  54. hev_free (frame->data);
  55. hev_free (frame);
  56. self->frames--;
  57. return res;
  58. }
  59. static int
  60. hev_socks5_session_udp_fwd_b (HevSocks5SessionUDP *self)
  61. {
  62. struct sockaddr_in6 addr = { 0 };
  63. struct sockaddr *saddr;
  64. struct sockaddr *daddr;
  65. HevSocks5UDP *udp;
  66. uint8_t buf[UDP_BUF_SIZE];
  67. int res;
  68. int fd;
  69. LOG_D ("%p socks5 session udp fwd b", self);
  70. udp = HEV_SOCKS5_UDP (self);
  71. fd = HEV_SOCKS5 (udp)->fd;
  72. if (fd < 0) {
  73. LOG_E ("%p socks5 session udp fd", self);
  74. return -1;
  75. }
  76. res = recv (fd, buf, 1, MSG_PEEK);
  77. if (res <= 0) {
  78. if ((res < 0) && (errno == EAGAIN))
  79. return 0;
  80. LOG_E ("%p socks5 session udp fwd b peek", self);
  81. return -1;
  82. }
  83. addr.sin6_family = AF_INET6;
  84. saddr = (struct sockaddr *)&addr;
  85. daddr = (struct sockaddr *)&self->addr;
  86. res = hev_socks5_udp_recvfrom (udp, buf, sizeof (buf), saddr);
  87. if (res <= 0) {
  88. LOG_E ("%p socks5 session udp fwd b recv", self);
  89. return -1;
  90. }
  91. fd = hev_tsocks_cache_get (saddr);
  92. if (fd < 0) {
  93. LOG_E ("%p socks5 session udp tsocks get", self);
  94. return -1;
  95. }
  96. res = sendto (fd, buf, res, 0, daddr, sizeof (self->addr));
  97. if (res <= 0) {
  98. if ((res < 0) && (errno == EAGAIN))
  99. return 0;
  100. LOG_E ("%p socks5 session udp fwd b send", self);
  101. return -1;
  102. }
  103. return 1;
  104. }
  105. HevSocks5SessionUDP *
  106. hev_socks5_session_udp_new (struct sockaddr *addr)
  107. {
  108. HevSocks5SessionUDP *self;
  109. int res;
  110. self = hev_malloc0 (sizeof (HevSocks5SessionUDP));
  111. if (!self)
  112. return NULL;
  113. res = hev_socks5_session_udp_construct (self, addr);
  114. if (res < 0) {
  115. hev_free (self);
  116. return NULL;
  117. }
  118. LOG_D ("%p socks5 session udp new", self);
  119. return self;
  120. }
  121. int
  122. hev_socks5_session_udp_send (HevSocks5SessionUDP *self, void *data, size_t len,
  123. struct sockaddr *addr)
  124. {
  125. HevSocks5UDPFrame *frame;
  126. LOG_D ("%p socks5 session udp send", self);
  127. if (self->frames > UDP_POOL_SIZE)
  128. return -1;
  129. frame = hev_malloc (sizeof (HevSocks5UDPFrame));
  130. if (!frame)
  131. return -1;
  132. frame->len = len;
  133. frame->data = data;
  134. memset (&frame->node, 0, sizeof (frame->node));
  135. memcpy (&frame->addr, addr, sizeof (struct sockaddr_in6));
  136. self->frames++;
  137. hev_list_add_tail (&self->frame_list, &frame->node);
  138. hev_task_wakeup (self->task);
  139. return 0;
  140. }
  141. static void
  142. hev_socks5_session_udp_splice (HevSocks5Session *base)
  143. {
  144. HevSocks5SessionUDP *self = HEV_SOCKS5_SESSION_UDP (base);
  145. int res_f = 1;
  146. int res_b = 1;
  147. LOG_D ("%p socks5 session udp splice", self);
  148. for (;;) {
  149. HevTaskYieldType type;
  150. if (res_f >= 0)
  151. res_f = hev_socks5_session_udp_fwd_f (self);
  152. if (res_b >= 0)
  153. res_b = hev_socks5_session_udp_fwd_b (self);
  154. if (res_f < 0 || res_b < 0)
  155. break;
  156. else if (res_f > 0 || res_b > 0)
  157. type = HEV_TASK_YIELD;
  158. else
  159. type = HEV_TASK_WAITIO;
  160. if (task_io_yielder (type, base) < 0)
  161. break;
  162. }
  163. }
  164. static void
  165. hev_socks5_session_udp_terminate (HevSocks5Session *base)
  166. {
  167. HevSocks5SessionUDP *self = HEV_SOCKS5_SESSION_UDP (base);
  168. LOG_D ("%p socks5 session udp terminate", self);
  169. hev_socks5_set_timeout (HEV_SOCKS5 (self), 0);
  170. hev_task_wakeup (self->task);
  171. }
  172. static void
  173. hev_socks5_session_udp_set_task (HevSocks5Session *base, HevTask *task)
  174. {
  175. HevSocks5SessionUDP *self = HEV_SOCKS5_SESSION_UDP (base);
  176. self->task = task;
  177. }
  178. int
  179. hev_socks5_session_udp_construct (HevSocks5SessionUDP *self,
  180. struct sockaddr *addr)
  181. {
  182. int res;
  183. res = hev_socks5_client_udp_construct (&self->base);
  184. if (res < 0)
  185. return -1;
  186. LOG_D ("%p socks5 session udp construct", self);
  187. HEV_OBJECT (self)->klass = HEV_SOCKS5_SESSION_UDP_TYPE;
  188. memcpy (&self->addr, addr, sizeof (struct sockaddr_in6));
  189. return 0;
  190. }
  191. void
  192. hev_socks5_session_udp_destruct (HevObject *base)
  193. {
  194. HevSocks5SessionUDP *self = HEV_SOCKS5_SESSION_UDP (base);
  195. HevListNode *node;
  196. LOG_D ("%p socks5 session udp destruct", self);
  197. node = hev_list_first (&self->frame_list);
  198. while (node) {
  199. HevSocks5UDPFrame *frame;
  200. frame = container_of (node, HevSocks5UDPFrame, node);
  201. node = hev_list_node_next (node);
  202. hev_free (frame->data);
  203. hev_free (frame);
  204. }
  205. HEV_SOCKS5_CLIENT_UDP_TYPE->finalizer (base);
  206. }
  207. static void *
  208. hev_socks5_session_udp_iface (HevObject *base, void *type)
  209. {
  210. HevSocks5SessionUDPClass *klass = HEV_OBJECT_GET_CLASS (base);
  211. return &klass->session;
  212. }
  213. HevObjectClass *
  214. hev_socks5_session_udp_class (void)
  215. {
  216. static HevSocks5SessionUDPClass klass;
  217. HevSocks5SessionUDPClass *kptr = &klass;
  218. HevObjectClass *okptr = HEV_OBJECT_CLASS (kptr);
  219. if (!okptr->name) {
  220. HevSocks5SessionIface *siptr;
  221. HevTProxySessionIface *tiptr;
  222. void *ptr;
  223. ptr = HEV_SOCKS5_CLIENT_UDP_TYPE;
  224. memcpy (kptr, ptr, sizeof (HevSocks5ClientUDPClass));
  225. okptr->name = "HevSocks5SessionUDP";
  226. okptr->finalizer = hev_socks5_session_udp_destruct;
  227. okptr->iface = hev_socks5_session_udp_iface;
  228. siptr = &kptr->session;
  229. memcpy (siptr, HEV_SOCKS5_SESSION_TYPE, sizeof (HevSocks5SessionIface));
  230. siptr->splicer = hev_socks5_session_udp_splice;
  231. tiptr = &kptr->session.base;
  232. tiptr->set_task = hev_socks5_session_udp_set_task;
  233. tiptr->terminator = hev_socks5_session_udp_terminate;
  234. }
  235. return okptr;
  236. }