SocksUdpClient.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. /*
  2. * Copyright (C) 2018 Jigsaw Operations LLC
  3. * Copyright (C) 2019 Ambroz Bizjak (modifications)
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * 3. Neither the name of the author nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <stddef.h>
  28. #include <stdint.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <misc/balloc.h>
  32. #include <misc/offset.h>
  33. #include <misc/byteorder.h>
  34. #include <misc/compare.h>
  35. #include <misc/socks_proto.h>
  36. #include <misc/debug.h>
  37. #include <misc/bsize.h>
  38. #include <base/BLog.h>
  39. #include <system/BAddr.h>
  40. #include <socks_udp_client/SocksUdpClient.h>
  41. #include <generated/blog_channel_SocksUdpClient.h>
  42. static const int DnsPort = 53;
  43. static int addr_comparator (void *unused, BAddr *v1, BAddr *v2);
  44. static struct SocksUdpClient_connection * find_connection (SocksUdpClient *o, BAddr addr);
  45. static void socks_state_handler (struct SocksUdpClient_connection *con, int event);
  46. static void datagram_state_handler (struct SocksUdpClient_connection *con, int event);
  47. static void send_monitor_handler (struct SocksUdpClient_connection *con);
  48. static void recv_if_handler_send (
  49. struct SocksUdpClient_connection *con, uint8_t *data, int data_len);
  50. static struct SocksUdpClient_connection * connection_init (
  51. SocksUdpClient *o, BAddr local_addr, BAddr first_remote_addr,
  52. const uint8_t *first_data, int first_data_len);
  53. static void connection_free (struct SocksUdpClient_connection *con);
  54. static void connection_send (struct SocksUdpClient_connection *con,
  55. BAddr remote_addr, const uint8_t *data, int data_len);
  56. static void first_job_handler (struct SocksUdpClient_connection *con);
  57. static int compute_socks_mtu (int udp_mtu);
  58. static int get_dns_id (BAddr *remote_addr, const uint8_t *data, int data_len);
  59. int addr_comparator (void *unused, BAddr *v1, BAddr *v2)
  60. {
  61. return BAddr_CompareOrder(v1, v2);
  62. }
  63. struct SocksUdpClient_connection * find_connection (SocksUdpClient *o, BAddr addr)
  64. {
  65. BAVLNode *tree_node = BAVL_LookupExact(&o->connections_tree, &addr);
  66. if (!tree_node) {
  67. return NULL;
  68. }
  69. return UPPER_OBJECT(tree_node, struct SocksUdpClient_connection, connections_tree_node);
  70. }
  71. void socks_state_handler (struct SocksUdpClient_connection *con, int event)
  72. {
  73. DebugObject_Access(&con->client->d_obj);
  74. switch (event) {
  75. case BSOCKSCLIENT_EVENT_UP: {
  76. // Figure out the localhost address.
  77. BIPAddr localhost;
  78. BIPAddr_InitLocalhost(&localhost, con->client->server_addr.type);
  79. // Get the address to send datagrams to from BSocksClient.
  80. BAddr remote_addr = BSocksClient_GetBindAddr(&con->socks);
  81. // Set the local/remote send address for BDatagram.
  82. // This will unblock the queue of outgoing packets.
  83. BDatagram_SetSendAddrs(&con->socket, remote_addr, localhost);
  84. } break;
  85. case BSOCKSCLIENT_EVENT_ERROR: {
  86. char local_buffer[BADDR_MAX_PRINT_LEN];
  87. BAddr_Print(&con->local_addr, local_buffer);
  88. BLog(BLOG_ERROR,
  89. "SOCKS error event for %s, removing connection.", local_buffer);
  90. connection_free(con);
  91. } break;
  92. case BSOCKSCLIENT_EVENT_ERROR_CLOSED: {
  93. char local_buffer[BADDR_MAX_PRINT_LEN];
  94. BAddr_Print(&con->local_addr, local_buffer);
  95. BLog(BLOG_WARNING,
  96. "SOCKS closed event for %s, removing connection.", local_buffer);
  97. connection_free(con);
  98. } break;
  99. default: {
  100. BLog(BLOG_ERROR, "Unknown SOCKS event");
  101. } break;
  102. }
  103. }
  104. void datagram_state_handler (struct SocksUdpClient_connection *con, int event)
  105. {
  106. DebugObject_Access(&con->client->d_obj);
  107. if (event == BDATAGRAM_EVENT_ERROR) {
  108. char local_buffer[BADDR_MAX_PRINT_LEN];
  109. BAddr_Print(&con->local_addr, local_buffer);
  110. BLog(BLOG_ERROR,
  111. "Low-level datagram error %s, removing connection.", local_buffer);
  112. // Remove the connection. Note that BDatagram requires that we free
  113. // the BDatagram after an error is reported.
  114. connection_free(con);
  115. }
  116. }
  117. void send_monitor_handler (struct SocksUdpClient_connection *con)
  118. {
  119. DebugObject_Access(&con->client->d_obj);
  120. char local_buffer[BADDR_MAX_PRINT_LEN];
  121. BAddr_Print(&con->local_addr, local_buffer);
  122. BLog(BLOG_INFO,
  123. "Removing connection for %s due to inactivity.", local_buffer);
  124. // The connection has passed its idle timeout. Remove it.
  125. connection_free(con);
  126. }
  127. void recv_if_handler_send (
  128. struct SocksUdpClient_connection *con, uint8_t *data, int data_len)
  129. {
  130. DebugObject_Access(&con->client->d_obj);
  131. SocksUdpClient *o = con->client;
  132. ASSERT(data_len >= 0)
  133. ASSERT(data_len <= o->socks_mtu)
  134. // accept packet
  135. PacketPassInterface_Done(&con->recv_if);
  136. // check header
  137. struct socks_udp_header header;
  138. if (data_len < sizeof(header)) {
  139. BLog(BLOG_ERROR, "Missing SOCKS-UDP header.");
  140. return;
  141. }
  142. memcpy(&header, data, sizeof(header));
  143. data += sizeof(header);
  144. data_len -= sizeof(header);
  145. // parse address
  146. BAddr remote_addr;
  147. switch (header.atyp) {
  148. case SOCKS_ATYP_IPV4: {
  149. struct socks_addr_ipv4 addr_ipv4;
  150. if (data_len < sizeof(addr_ipv4)) {
  151. BLog(BLOG_ERROR, "Missing IPv4 address.");
  152. return;
  153. }
  154. memcpy(&addr_ipv4, data, sizeof(addr_ipv4));
  155. data += sizeof(addr_ipv4);
  156. data_len -= sizeof(addr_ipv4);
  157. remote_addr.type = BADDR_TYPE_IPV4;
  158. remote_addr.ipv4.ip = addr_ipv4.addr;
  159. remote_addr.ipv4.port = addr_ipv4.port;
  160. } break;
  161. case SOCKS_ATYP_IPV6: {
  162. struct socks_addr_ipv6 addr_ipv6;
  163. if (data_len < sizeof(addr_ipv6)) {
  164. BLog(BLOG_ERROR, "Missing IPv6 address.");
  165. return;
  166. }
  167. memcpy(&addr_ipv6, data, sizeof(addr_ipv6));
  168. data += sizeof(addr_ipv6);
  169. data_len -= sizeof(addr_ipv6);
  170. remote_addr.type = BADDR_TYPE_IPV6;
  171. memcpy(remote_addr.ipv6.ip, addr_ipv6.addr, sizeof(remote_addr.ipv6.ip));
  172. remote_addr.ipv6.port = addr_ipv6.port;
  173. } break;
  174. default: {
  175. BLog(BLOG_ERROR, "Bad address type");
  176. return;
  177. } break;
  178. }
  179. // check remaining data
  180. if (data_len > o->udp_mtu) {
  181. BLog(BLOG_ERROR, "too much data");
  182. return;
  183. }
  184. // pass packet to user
  185. SocksUdpClient *client = con->client;
  186. client->handler_received(client->user, con->local_addr, remote_addr, data, data_len);
  187. // Was this connection used for a DNS query?
  188. if (con->dns_id >= 0) {
  189. // Get the DNS transaction ID of the response.
  190. int recv_dns_id = get_dns_id(&remote_addr, data, data_len);
  191. // Does the transaction ID matche that of the request?
  192. if (recv_dns_id == con->dns_id) {
  193. // We have now forwarded the response, so this connection is no longer needed.
  194. char local_buffer[BADDR_MAX_PRINT_LEN];
  195. BAddr_Print(&con->local_addr, local_buffer);
  196. BLog(BLOG_DEBUG,
  197. "Removing connection for %s after the DNS response.", local_buffer);
  198. connection_free(con);
  199. } else {
  200. BLog(BLOG_INFO, "DNS client port received an unexpected non-DNS packet, "
  201. "disabling DNS optimization.");
  202. con->dns_id = -1;
  203. }
  204. }
  205. }
  206. struct SocksUdpClient_connection * connection_init (
  207. SocksUdpClient *o, BAddr local_addr, BAddr first_remote_addr,
  208. const uint8_t *first_data, int first_data_len)
  209. {
  210. ASSERT(o->num_connections <= o->max_connections)
  211. ASSERT(!find_connection(o, local_addr))
  212. char local_buffer[BADDR_MAX_PRINT_LEN];
  213. BAddr_Print(&local_addr, local_buffer);
  214. BLog(BLOG_DEBUG, "Creating connection for %s.", local_buffer);
  215. // allocate structure
  216. struct SocksUdpClient_connection *con =
  217. (struct SocksUdpClient_connection *)BAlloc(sizeof(*con));
  218. if (!con) {
  219. BLog(BLOG_ERROR, "BAlloc connection failed");
  220. goto fail0;
  221. }
  222. // set basic things
  223. con->client = o;
  224. con->local_addr = local_addr;
  225. // store first outgoing packet
  226. con->first_data = BAlloc(first_data_len);
  227. if (!con->first_data) {
  228. BLog(BLOG_ERROR, "BAlloc first data failed");
  229. goto fail1;
  230. }
  231. memcpy(con->first_data, first_data, first_data_len);
  232. con->first_data_len = first_data_len;
  233. con->first_remote_addr = first_remote_addr;
  234. // Get the DNS transaction ID from the packet, if any.
  235. con->dns_id = get_dns_id(&first_remote_addr, first_data, first_data_len);
  236. BPendingGroup *pg = BReactor_PendingGroup(o->reactor);
  237. // Init first job, to send the first packet asynchronously. This has to happen
  238. // asynchronously because con->send_writer (a BufferWriter) cannot accept writes until
  239. // after it is linked with its PacketBuffer (con->send_buffer), which happens
  240. // asynchronously.
  241. BPending_Init(&con->first_job, pg, (BPending_handler)first_job_handler, con);
  242. // Add the first job to the pending set. BPending acts as a LIFO stack, and
  243. // first_job_handler needs to run after async actions that occur in PacketBuffer_Init,
  244. // so we need to put first_job on the stack first.
  245. BPending_Set(&con->first_job);
  246. // Create a datagram socket
  247. if (!BDatagram_Init(&con->socket, con->local_addr.type, o->reactor, con,
  248. (BDatagram_handler)datagram_state_handler))
  249. {
  250. BLog(BLOG_ERROR, "Failed to create a UDP socket");
  251. goto fail2;
  252. }
  253. // Bind to localhost, port 0 signals the kernel to choose an open port.
  254. BIPAddr localhost;
  255. BIPAddr_InitLocalhost(&localhost, local_addr.type);
  256. BAddr socket_addr = BAddr_MakeFromIpaddrAndPort(localhost, 0);
  257. if (!BDatagram_Bind(&con->socket, socket_addr)) {
  258. BLog(BLOG_ERROR, "Bind to localhost failed");
  259. goto fail3;
  260. }
  261. // Bind succeeded, so the kernel has found an open port.
  262. // Update socket_addr to the actual port that was bound.
  263. uint16_t port;
  264. if (!BDatagram_GetLocalPort(&con->socket, &port)) {
  265. BLog(BLOG_ERROR, "Failed to get bound port");
  266. goto fail3;
  267. }
  268. if (socket_addr.type == BADDR_TYPE_IPV4) {
  269. socket_addr.ipv4.port = port;
  270. } else {
  271. socket_addr.ipv6.port = port;
  272. }
  273. // Initiate connection to socks server
  274. if (!BSocksClient_Init(&con->socks, o->server_addr, o->auth_info, o->num_auth_info,
  275. socket_addr, true, (BSocksClient_handler)socks_state_handler, con, o->reactor))
  276. {
  277. BLog(BLOG_ERROR, "Failed to initialize SOCKS client");
  278. goto fail3;
  279. }
  280. // Since we use o->socks_mtu for send and receive pipelines, we can handle maximally
  281. // sized packets (o->udp_mtu) including the SOCKS-UDP header.
  282. // Send pipeline: send_writer -> send_buffer -> send_monitor -> send_if -> socket.
  283. BDatagram_SendAsync_Init(&con->socket, o->socks_mtu);
  284. PacketPassInactivityMonitor_Init(&con->send_monitor,
  285. BDatagram_SendAsync_GetIf(&con->socket), o->reactor, o->keepalive_time,
  286. (PacketPassInactivityMonitor_handler)send_monitor_handler, con);
  287. BufferWriter_Init(&con->send_writer, o->socks_mtu, pg);
  288. if (!PacketBuffer_Init(&con->send_buffer, BufferWriter_GetOutput(&con->send_writer),
  289. PacketPassInactivityMonitor_GetInput(&con->send_monitor), o->send_buf_size, pg))
  290. {
  291. BLog(BLOG_ERROR, "Send buffer init failed");
  292. goto fail4;
  293. }
  294. // Receive pipeline: socket -> recv_buffer -> recv_if
  295. BDatagram_RecvAsync_Init(&con->socket, o->socks_mtu);
  296. PacketPassInterface_Init(&con->recv_if, o->socks_mtu,
  297. (PacketPassInterface_handler_send)recv_if_handler_send, con, pg);
  298. if (!SinglePacketBuffer_Init(&con->recv_buffer,
  299. BDatagram_RecvAsync_GetIf(&con->socket), &con->recv_if, pg))
  300. {
  301. BLog(BLOG_ERROR, "Receive buffer init failed");
  302. goto fail5;
  303. }
  304. // Insert to connections tree, it must succeed because of the assert.
  305. int inserted = BAVL_Insert(&o->connections_tree, &con->connections_tree_node, NULL);
  306. ASSERT(inserted)
  307. B_USE(inserted)
  308. // increment number of connections
  309. o->num_connections++;
  310. return con;
  311. fail5:
  312. PacketPassInterface_Free(&con->recv_if);
  313. BDatagram_RecvAsync_Free(&con->socket);
  314. PacketBuffer_Free(&con->send_buffer);
  315. fail4:
  316. BufferWriter_Free(&con->send_writer);
  317. PacketPassInactivityMonitor_Free(&con->send_monitor);
  318. BDatagram_SendAsync_Free(&con->socket);
  319. BSocksClient_Free(&con->socks);
  320. fail3:
  321. BDatagram_Free(&con->socket);
  322. fail2:
  323. BPending_Free(&con->first_job);
  324. BFree(con->first_data);
  325. fail1:
  326. BFree(con);
  327. fail0:
  328. return NULL;
  329. }
  330. void connection_free (struct SocksUdpClient_connection *con)
  331. {
  332. SocksUdpClient *o = con->client;
  333. // decrement number of connections
  334. ASSERT(o->num_connections > 0)
  335. o->num_connections--;
  336. // remove from connections tree
  337. BAVL_Remove(&o->connections_tree, &con->connections_tree_node);
  338. // Free UDP receive pipeline components
  339. SinglePacketBuffer_Free(&con->recv_buffer);
  340. PacketPassInterface_Free(&con->recv_if);
  341. BDatagram_RecvAsync_Free(&con->socket);
  342. // Free UDP send pipeline components
  343. PacketBuffer_Free(&con->send_buffer);
  344. BufferWriter_Free(&con->send_writer);
  345. PacketPassInactivityMonitor_Free(&con->send_monitor);
  346. BDatagram_SendAsync_Free(&con->socket);
  347. // Free SOCKS client
  348. BSocksClient_Free(&con->socks);
  349. // Free UDP socket
  350. BDatagram_Free(&con->socket);
  351. // Free first job
  352. BPending_Free(&con->first_job);
  353. // Free first outgoing packet
  354. BFree(con->first_data);
  355. // Free structure
  356. BFree(con);
  357. }
  358. void connection_send (struct SocksUdpClient_connection *con,
  359. BAddr remote_addr, const uint8_t *data, int data_len)
  360. {
  361. ASSERT(data_len >= 0)
  362. ASSERT(data_len <= o->udp_mtu)
  363. if (con->dns_id >= 0) {
  364. // So far, this connection has only sent a single DNS query.
  365. int new_dns_id = get_dns_id(&remote_addr, data, data_len);
  366. if (new_dns_id != con->dns_id) {
  367. BLog(BLOG_DEBUG, "Client reused DNS query port. Disabling DNS optimization.");
  368. con->dns_id = -1;
  369. }
  370. }
  371. // Check if we're sending to an IPv4 or IPv6 destination.
  372. int atyp;
  373. size_t address_size;
  374. // write address
  375. switch (remote_addr.type) {
  376. case BADDR_TYPE_IPV4: {
  377. atyp = SOCKS_ATYP_IPV4;
  378. address_size = sizeof(struct socks_addr_ipv4);
  379. } break;
  380. case BADDR_TYPE_IPV6: {
  381. atyp = SOCKS_ATYP_IPV6;
  382. address_size = sizeof(struct socks_addr_ipv6);
  383. } break;
  384. default: {
  385. BLog(BLOG_ERROR, "Bad address type in outgoing packet.");
  386. return;
  387. } break;
  388. }
  389. // Determine total packet size in the buffer.
  390. // This cannot exceed o->socks_mtu because data_len is required to not exceed
  391. // o->udp_mtu and o->socks_mtu is calculated to accomodate any UDP packet not
  392. // not exceeding o->udp_mtu.
  393. size_t total_len = sizeof(struct socks_udp_header) + address_size + data_len;
  394. ASSERT(total_len <= o->socks_mtu)
  395. // Get a pointer to write the packet to.
  396. uint8_t *out_data_begin;
  397. if (!BufferWriter_StartPacket(&con->send_writer, &out_data_begin)) {
  398. BLog(BLOG_ERROR, "Send buffer is full.");
  399. return;
  400. }
  401. uint8_t *out_data = out_data_begin;
  402. // Write header
  403. struct socks_udp_header header;
  404. header.rsv = 0;
  405. header.frag = 0;
  406. header.atyp = atyp;
  407. memcpy(out_data, &header, sizeof(header));
  408. out_data += sizeof(header);
  409. // Write address
  410. switch (atyp) {
  411. case SOCKS_ATYP_IPV4: {
  412. struct socks_addr_ipv4 addr_ipv4;
  413. addr_ipv4.addr = remote_addr.ipv4.ip;
  414. addr_ipv4.port = remote_addr.ipv4.port;
  415. memcpy(out_data, &addr_ipv4, sizeof(addr_ipv4));
  416. out_data += sizeof(addr_ipv4);
  417. } break;
  418. case SOCKS_ATYP_IPV6: {
  419. struct socks_addr_ipv6 addr_ipv6;
  420. memcpy(addr_ipv6.addr, remote_addr.ipv6.ip, sizeof(addr_ipv6.addr));
  421. addr_ipv6.port = remote_addr.ipv6.port;
  422. memcpy(out_data, &addr_ipv6, sizeof(addr_ipv6));
  423. out_data += sizeof(addr_ipv6);
  424. } break;
  425. }
  426. // Write payload
  427. memcpy(out_data, data, data_len);
  428. out_data += data_len;
  429. ASSERT(out_data - out_data_begin == total_len)
  430. // Submit packet to buffer
  431. BufferWriter_EndPacket(&con->send_writer, total_len);
  432. }
  433. void first_job_handler (struct SocksUdpClient_connection *con)
  434. {
  435. DebugObject_Access(&con->client->d_obj);
  436. ASSERT(con->first_data)
  437. // Send the first packet.
  438. connection_send(con, con->first_remote_addr, con->first_data, con->first_data_len);
  439. // Release the first packet buffer.
  440. BFree(con->first_data);
  441. con->first_data = NULL;
  442. con->first_data_len = 0;
  443. }
  444. int compute_socks_mtu (int udp_mtu)
  445. {
  446. bsize_t bs = bsize_add(
  447. bsize_fromint(udp_mtu),
  448. bsize_add(
  449. bsize_fromsize(sizeof(struct socks_udp_header)),
  450. bsize_fromsize(sizeof(struct socks_addr_ipv6))
  451. )
  452. );
  453. int s;
  454. return bsize_toint(bs, &s) ? s : -1;
  455. }
  456. // Get the DNS transaction ID, or -1 if this does not look like a DNS packet.
  457. int get_dns_id (BAddr *remote_addr, const uint8_t *data, int data_len)
  458. {
  459. if (ntoh16(BAddr_GetPort(remote_addr)) == DnsPort && data_len >= 2) {
  460. return (data[0] << 8) | data[1];
  461. } else {
  462. return -1;
  463. }
  464. }
  465. int SocksUdpClient_Init (SocksUdpClient *o, int udp_mtu, int max_connections,
  466. int send_buf_size, btime_t keepalive_time, BAddr server_addr,
  467. const struct BSocksClient_auth_info *auth_info, size_t num_auth_info,
  468. BReactor *reactor, void *user, SocksUdpClient_handler_received handler_received)
  469. {
  470. ASSERT(udp_mtu >= 0)
  471. ASSERT(max_connections > 0)
  472. ASSERT(send_buf_size > 0)
  473. // init simple things
  474. o->server_addr = server_addr;
  475. o->auth_info = auth_info;
  476. o->num_auth_info = num_auth_info;
  477. o->num_connections = 0;
  478. o->max_connections = max_connections;
  479. o->send_buf_size = send_buf_size;
  480. o->udp_mtu = udp_mtu;
  481. o->keepalive_time = keepalive_time;
  482. o->reactor = reactor;
  483. o->user = user;
  484. o->handler_received = handler_received;
  485. // calculate full MTU with SOCKS header
  486. o->socks_mtu = compute_socks_mtu(udp_mtu);
  487. if (o->socks_mtu < 0) {
  488. BLog(BLOG_ERROR, "SocksUdpClient_Init: MTU too large.");
  489. goto fail0;
  490. }
  491. // init connections tree
  492. BAVL_Init(&o->connections_tree,
  493. OFFSET_DIFF(struct SocksUdpClient_connection, local_addr, connections_tree_node),
  494. (BAVL_comparator)addr_comparator, NULL);
  495. DebugObject_Init(&o->d_obj);
  496. return 1;
  497. fail0:
  498. return 0;
  499. }
  500. void SocksUdpClient_Free (SocksUdpClient *o)
  501. {
  502. DebugObject_Free(&o->d_obj);
  503. // free connections
  504. while (!BAVL_IsEmpty(&o->connections_tree)) {
  505. BAVLNode *node = BAVL_GetFirst(&o->connections_tree);
  506. struct SocksUdpClient_connection *con =
  507. UPPER_OBJECT(node, struct SocksUdpClient_connection, connections_tree_node);
  508. connection_free(con);
  509. }
  510. }
  511. void SocksUdpClient_SubmitPacket (SocksUdpClient *o,
  512. BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len)
  513. {
  514. DebugObject_Access(&o->d_obj);
  515. ASSERT(local_addr.type == BADDR_TYPE_IPV4 || local_addr.type == BADDR_TYPE_IPV6)
  516. ASSERT(remote_addr.type == BADDR_TYPE_IPV4 || remote_addr.type == BADDR_TYPE_IPV6)
  517. ASSERT(data_len >= 0)
  518. ASSERT(data_len <= o->udp_mtu)
  519. // lookup connection
  520. struct SocksUdpClient_connection *con = find_connection(o, local_addr);
  521. if (!con) {
  522. if (o->num_connections >= o->max_connections) {
  523. // Drop the packet.
  524. BLog(BLOG_WARNING, "Dropping UDP packet, reached max number of connections.");
  525. return;
  526. }
  527. // create new connection and enqueue the packet
  528. connection_init(o, local_addr, remote_addr, data, data_len);
  529. } else {
  530. // send packet
  531. connection_send(con, remote_addr, data, data_len);
  532. }
  533. }