DatagramPeerIO.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /**
  2. * @file DatagramPeerIO.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stdint.h>
  23. #include <misc/debug.h>
  24. #include <system/BLog.h>
  25. #include <client/DatagramPeerIO.h>
  26. #include <generated/blog_channel_DatagramPeerIO.h>
  27. #define DATAGRAMPEERIO_MODE_NONE 0
  28. #define DATAGRAMPEERIO_MODE_CONNECT 1
  29. #define DATAGRAMPEERIO_MODE_BIND 2
  30. #define DATAGRAMPEERIO_COMPONENT_SINK 1
  31. #define DATAGRAMPEERIO_COMPONENT_SOURCE 2
  32. static int init_persistent_io (DatagramPeerIO *o, btime_t latency, int num_frames, PacketPassInterface *recv_userif);
  33. static void free_persistent_io (DatagramPeerIO *o);
  34. static void init_sending (DatagramPeerIO *o, BAddr addr, BIPAddr local_addr);
  35. static void free_sending (DatagramPeerIO *o);
  36. static void init_receiving (DatagramPeerIO *o);
  37. static void free_receiving (DatagramPeerIO *o);
  38. static void error_handler (DatagramPeerIO *o, int component, const void *data);
  39. static void reset_mode (DatagramPeerIO *o);
  40. static void recv_decoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len);
  41. static void send_encoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len);
  42. int init_persistent_io (DatagramPeerIO *o, btime_t latency, int num_frames, PacketPassInterface *recv_userif)
  43. {
  44. // init error domain
  45. FlowErrorDomain_Init(&o->domain, (FlowErrorDomain_handler)error_handler, o);
  46. // init receiving
  47. // init assembler
  48. if (!FragmentProtoAssembler_Init(&o->recv_assembler, o->spproto_payload_mtu, recv_userif, num_frames, fragmentproto_max_chunks_for_frame(o->spproto_payload_mtu, o->payload_mtu), BReactor_PendingGroup(o->reactor))) {
  49. BLog(BLOG_ERROR, "FragmentProtoAssembler_Init failed");
  50. goto fail0;
  51. }
  52. // init notifier
  53. PacketPassNotifier_Init(&o->recv_notifier, FragmentProtoAssembler_GetInput(&o->recv_assembler), BReactor_PendingGroup(o->reactor));
  54. // init decoder
  55. if (!SPProtoDecoder_Init(&o->recv_decoder, PacketPassNotifier_GetInput(&o->recv_notifier), o->sp_params, 2, BReactor_PendingGroup(o->reactor))) {
  56. BLog(BLOG_ERROR, "SPProtoDecoder_Init failed");
  57. goto fail1;
  58. }
  59. // init connector
  60. PacketRecvConnector_Init(&o->recv_connector, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
  61. // init buffer
  62. if (!SinglePacketBuffer_Init(&o->recv_buffer, PacketRecvConnector_GetOutput(&o->recv_connector), SPProtoDecoder_GetInput(&o->recv_decoder), BReactor_PendingGroup(o->reactor))) {
  63. BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed");
  64. goto fail2;
  65. }
  66. // init sending base
  67. // init disassembler
  68. FragmentProtoDisassembler_Init(&o->send_disassembler, o->reactor, o->payload_mtu, o->spproto_payload_mtu, -1, latency);
  69. // init encoder
  70. if (!SPProtoEncoder_Init(&o->send_encoder, FragmentProtoDisassembler_GetOutput(&o->send_disassembler), o->sp_params, BReactor_PendingGroup(o->reactor))) {
  71. BLog(BLOG_ERROR, "SPProtoEncoder_Init failed");
  72. goto fail3;
  73. }
  74. // init notifier
  75. PacketRecvNotifier_Init(&o->send_notifier, SPProtoEncoder_GetOutput(&o->send_encoder), BReactor_PendingGroup(o->reactor));
  76. if (SPPROTO_HAVE_OTP(o->sp_params)) {
  77. PacketRecvNotifier_SetHandler(&o->send_notifier, (PacketRecvNotifier_handler_notify)send_encoder_notifier_handler, o);
  78. }
  79. // init connector
  80. PacketPassConnector_Init(&o->send_connector, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
  81. // init buffer
  82. if (!SinglePacketBuffer_Init(&o->send_buffer, PacketRecvNotifier_GetOutput(&o->send_notifier), PacketPassConnector_GetInput(&o->send_connector), BReactor_PendingGroup(o->reactor))) {
  83. BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed");
  84. goto fail4;
  85. }
  86. return 1;
  87. fail4:
  88. PacketPassConnector_Free(&o->send_connector);
  89. PacketRecvNotifier_Free(&o->send_notifier);
  90. SPProtoEncoder_Free(&o->send_encoder);
  91. fail3:
  92. FragmentProtoDisassembler_Free(&o->send_disassembler);
  93. SinglePacketBuffer_Free(&o->recv_buffer);
  94. fail2:
  95. PacketRecvConnector_Free(&o->recv_connector);
  96. SPProtoDecoder_Free(&o->recv_decoder);
  97. fail1:
  98. PacketPassNotifier_Free(&o->recv_notifier);
  99. FragmentProtoAssembler_Free(&o->recv_assembler);
  100. fail0:
  101. return 0;
  102. }
  103. void free_persistent_io (DatagramPeerIO *o)
  104. {
  105. // free sending base
  106. SinglePacketBuffer_Free(&o->send_buffer);
  107. PacketPassConnector_Free(&o->send_connector);
  108. PacketRecvNotifier_Free(&o->send_notifier);
  109. SPProtoEncoder_Free(&o->send_encoder);
  110. FragmentProtoDisassembler_Free(&o->send_disassembler);
  111. // free receiving
  112. SinglePacketBuffer_Free(&o->recv_buffer);
  113. PacketRecvConnector_Free(&o->recv_connector);
  114. SPProtoDecoder_Free(&o->recv_decoder);
  115. PacketPassNotifier_Free(&o->recv_notifier);
  116. FragmentProtoAssembler_Free(&o->recv_assembler);
  117. }
  118. void init_sending (DatagramPeerIO *o, BAddr addr, BIPAddr local_addr)
  119. {
  120. // init sink
  121. DatagramSocketSink_Init(&o->send_sink, FlowErrorReporter_Create(&o->domain, DATAGRAMPEERIO_COMPONENT_SINK), &o->sock, o->effective_socket_mtu, addr, local_addr, BReactor_PendingGroup(o->reactor));
  122. // connect sink
  123. PacketPassConnector_ConnectOutput(&o->send_connector, DatagramSocketSink_GetInput(&o->send_sink));
  124. }
  125. void free_sending (DatagramPeerIO *o)
  126. {
  127. // disconnect sink
  128. PacketPassConnector_DisconnectOutput(&o->send_connector);
  129. // free sink
  130. DatagramSocketSink_Free(&o->send_sink);
  131. }
  132. void init_receiving (DatagramPeerIO *o)
  133. {
  134. // init source
  135. DatagramSocketSource_Init(&o->recv_source, FlowErrorReporter_Create(&o->domain, DATAGRAMPEERIO_COMPONENT_SOURCE), &o->sock, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
  136. // connect source
  137. PacketRecvConnector_ConnectInput(&o->recv_connector, DatagramSocketSource_GetOutput(&o->recv_source));
  138. }
  139. void free_receiving (DatagramPeerIO *o)
  140. {
  141. // disconnect source
  142. PacketRecvConnector_DisconnectInput(&o->recv_connector);
  143. // free source
  144. DatagramSocketSource_Free(&o->recv_source);
  145. }
  146. void error_handler (DatagramPeerIO *o, int component, const void *data)
  147. {
  148. ASSERT(o->mode == DATAGRAMPEERIO_MODE_CONNECT || o->mode == DATAGRAMPEERIO_MODE_BIND)
  149. DebugObject_Access(&o->d_obj);
  150. int error = *((int *)data);
  151. switch (component) {
  152. case DATAGRAMPEERIO_COMPONENT_SINK:
  153. switch (error) {
  154. case DATAGRAMSOCKETSINK_ERROR_BSOCKET:
  155. BLog(BLOG_NOTICE, "sink BSocket error %d", BSocket_GetError(&o->sock));
  156. break;
  157. case DATAGRAMSOCKETSINK_ERROR_WRONGSIZE:
  158. BLog(BLOG_NOTICE, "sink wrong size error");
  159. break;
  160. default:
  161. ASSERT(0);
  162. }
  163. break;
  164. case DATAGRAMPEERIO_COMPONENT_SOURCE:
  165. switch (error) {
  166. case DATAGRAMSOCKETSOURCE_ERROR_BSOCKET:
  167. BLog(BLOG_NOTICE, "source BSocket error %d", BSocket_GetError(&o->sock));
  168. break;
  169. default:
  170. ASSERT(0);
  171. }
  172. break;
  173. default:
  174. ASSERT(0);
  175. }
  176. }
  177. void reset_mode (DatagramPeerIO *o)
  178. {
  179. switch (o->mode) {
  180. case DATAGRAMPEERIO_MODE_NONE:
  181. break;
  182. case DATAGRAMPEERIO_MODE_CONNECT:
  183. // set default mode
  184. o->mode = DATAGRAMPEERIO_MODE_NONE;
  185. // free receiving
  186. free_receiving(o);
  187. // free sending
  188. free_sending(o);
  189. // free socket
  190. BSocket_Free(&o->sock);
  191. break;
  192. case DATAGRAMPEERIO_MODE_BIND:
  193. // set default mode
  194. o->mode = DATAGRAMPEERIO_MODE_NONE;
  195. // remove recv notifier handler
  196. PacketPassNotifier_SetHandler(&o->recv_notifier, NULL, NULL);
  197. // free receiving
  198. free_receiving(o);
  199. // free sending
  200. if (o->bind_sending_up) {
  201. free_sending(o);
  202. }
  203. // free socket
  204. BSocket_Free(&o->sock);
  205. break;
  206. default:
  207. ASSERT(0);
  208. }
  209. }
  210. void recv_decoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len)
  211. {
  212. ASSERT(o->mode == DATAGRAMPEERIO_MODE_BIND)
  213. DebugObject_Access(&o->d_obj);
  214. // obtain addresses from last received packet
  215. BAddr addr;
  216. BIPAddr local_addr;
  217. DatagramSocketSource_GetLastAddresses(&o->recv_source, &addr, &local_addr);
  218. if (!o->bind_sending_up) {
  219. // init sending
  220. init_sending(o, addr, local_addr);
  221. // set sending up
  222. o->bind_sending_up = 1;
  223. } else {
  224. // update addresses
  225. DatagramSocketSink_SetAddresses(&o->send_sink, addr, local_addr);
  226. }
  227. }
  228. void send_encoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len)
  229. {
  230. ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
  231. DebugObject_Access(&o->d_obj);
  232. if (o->handler_otp_warning && SPProtoEncoder_GetOTPPosition(&o->send_encoder) == o->handler_otp_warning_num_used) {
  233. o->handler_otp_warning(o->handler_otp_warning_user);
  234. return;
  235. }
  236. }
  237. int DatagramPeerIO_Init (DatagramPeerIO *o, BReactor *reactor, int payload_mtu, int socket_mtu, struct spproto_security_params sp_params, btime_t latency, int num_frames, PacketPassInterface *recv_userif)
  238. {
  239. ASSERT(payload_mtu >= 0)
  240. ASSERT(socket_mtu >= 0)
  241. spproto_assert_security_params(sp_params);
  242. ASSERT(num_frames > 0)
  243. ASSERT(PacketPassInterface_GetMTU(recv_userif) >= payload_mtu)
  244. // set parameters
  245. o->reactor = reactor;
  246. o->payload_mtu = payload_mtu;
  247. o->sp_params = sp_params;
  248. // check payload MTU (for FragmentProto)
  249. if (o->payload_mtu > UINT16_MAX) {
  250. BLog(BLOG_ERROR, "payload MTU is too big");
  251. goto fail1;
  252. }
  253. // calculate SPProto payload MTU
  254. if ((o->spproto_payload_mtu = spproto_payload_mtu_for_carrier_mtu(o->sp_params, socket_mtu)) <= (int)sizeof(struct fragmentproto_chunk_header)) {
  255. BLog(BLOG_ERROR, "socket MTU is too small");
  256. goto fail1;
  257. }
  258. // calculate effective socket MTU
  259. if ((o->effective_socket_mtu = spproto_carrier_mtu_for_payload_mtu(o->sp_params, o->spproto_payload_mtu)) < 0) {
  260. BLog(BLOG_ERROR, "spproto_carrier_mtu_for_payload_mtu failed !?");
  261. goto fail1;
  262. }
  263. // set no OTP warning handler
  264. if (SPPROTO_HAVE_OTP(o->sp_params)) {
  265. o->handler_otp_warning = NULL;
  266. }
  267. // set mode none
  268. o->mode = DATAGRAMPEERIO_MODE_NONE;
  269. // init persistent I/O objects
  270. if (!init_persistent_io(o, latency, num_frames, recv_userif)) {
  271. goto fail1;
  272. }
  273. DebugObject_Init(&o->d_obj);
  274. return 1;
  275. fail1:
  276. return 0;
  277. }
  278. void DatagramPeerIO_Free (DatagramPeerIO *o)
  279. {
  280. DebugObject_Free(&o->d_obj);
  281. // reset mode
  282. reset_mode(o);
  283. // free persistent I/O objects
  284. free_persistent_io(o);
  285. }
  286. PacketPassInterface * DatagramPeerIO_GetSendInput (DatagramPeerIO *o)
  287. {
  288. DebugObject_Access(&o->d_obj);
  289. return FragmentProtoDisassembler_GetInput(&o->send_disassembler);
  290. }
  291. int DatagramPeerIO_Connect (DatagramPeerIO *o, BAddr addr)
  292. {
  293. ASSERT(!BAddr_IsInvalid(&addr))
  294. DebugObject_Access(&o->d_obj);
  295. // reset mode
  296. reset_mode(o);
  297. // init socket
  298. if (BSocket_Init(&o->sock, o->reactor, addr.type, BSOCKET_TYPE_DGRAM) < 0) {
  299. BLog(BLOG_ERROR, "BSocket_Init failed");
  300. goto fail1;
  301. }
  302. // connect the socket
  303. // Windows needs this or receive will fail
  304. if (BSocket_Connect(&o->sock, &addr) < 0) {
  305. BLog(BLOG_ERROR, "BSocket_Connect failed");
  306. goto fail2;
  307. }
  308. // init receiving
  309. init_receiving(o);
  310. // init sending
  311. BIPAddr local_addr;
  312. BIPAddr_InitInvalid(&local_addr);
  313. init_sending(o, addr, local_addr);
  314. // set mode
  315. o->mode = DATAGRAMPEERIO_MODE_CONNECT;
  316. return 1;
  317. fail2:
  318. BSocket_Free(&o->sock);
  319. fail1:
  320. return 0;
  321. }
  322. int DatagramPeerIO_Bind (DatagramPeerIO *o, BAddr addr)
  323. {
  324. ASSERT(!BAddr_IsInvalid(&addr))
  325. DebugObject_Access(&o->d_obj);
  326. // reset mode
  327. reset_mode(o);
  328. // init socket
  329. if (BSocket_Init(&o->sock, o->reactor, addr.type, BSOCKET_TYPE_DGRAM) < 0) {
  330. BLog(BLOG_ERROR, "BSocket_Init failed");
  331. goto fail1;
  332. }
  333. // bind socket
  334. if (BSocket_Bind(&o->sock, &addr) < 0) {
  335. BLog(BLOG_INFO, "BSocket_Bind failed");
  336. goto fail2;
  337. }
  338. // init receiving
  339. init_receiving(o);
  340. // set recv notifier handler
  341. PacketPassNotifier_SetHandler(&o->recv_notifier, (PacketPassNotifier_handler_notify)recv_decoder_notifier_handler, o);
  342. // set mode
  343. o->mode = DATAGRAMPEERIO_MODE_BIND;
  344. // set sending not up
  345. o->bind_sending_up = 0;
  346. return 1;
  347. fail2:
  348. BSocket_Free(&o->sock);
  349. fail1:
  350. return 0;
  351. }
  352. void DatagramPeerIO_SetEncryptionKey (DatagramPeerIO *o, uint8_t *encryption_key)
  353. {
  354. ASSERT(o->sp_params.encryption_mode != SPPROTO_ENCRYPTION_MODE_NONE)
  355. DebugObject_Access(&o->d_obj);
  356. // set sending key
  357. SPProtoEncoder_SetEncryptionKey(&o->send_encoder, encryption_key);
  358. // set receiving key
  359. SPProtoDecoder_SetEncryptionKey(&o->recv_decoder, encryption_key);
  360. }
  361. void DatagramPeerIO_RemoveEncryptionKey (DatagramPeerIO *o)
  362. {
  363. ASSERT(o->sp_params.encryption_mode != SPPROTO_ENCRYPTION_MODE_NONE)
  364. DebugObject_Access(&o->d_obj);
  365. // remove sending key
  366. SPProtoEncoder_RemoveEncryptionKey(&o->send_encoder);
  367. // remove receiving key
  368. SPProtoDecoder_RemoveEncryptionKey(&o->recv_decoder);
  369. }
  370. void DatagramPeerIO_SetOTPSendSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv)
  371. {
  372. ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
  373. DebugObject_Access(&o->d_obj);
  374. // set sending seed
  375. SPProtoEncoder_SetOTPSeed(&o->send_encoder, seed_id, key, iv);
  376. }
  377. void DatagramPeerIO_RemoveOTPSendSeed (DatagramPeerIO *o)
  378. {
  379. ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
  380. DebugObject_Access(&o->d_obj);
  381. // remove sending seed
  382. SPProtoEncoder_RemoveOTPSeed(&o->send_encoder);
  383. }
  384. void DatagramPeerIO_AddOTPRecvSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv)
  385. {
  386. ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
  387. DebugObject_Access(&o->d_obj);
  388. // add receiving seed
  389. SPProtoDecoder_AddOTPSeed(&o->recv_decoder, seed_id, key, iv);
  390. }
  391. void DatagramPeerIO_RemoveOTPRecvSeeds (DatagramPeerIO *o)
  392. {
  393. ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
  394. DebugObject_Access(&o->d_obj);
  395. // remove receiving seeds
  396. SPProtoDecoder_RemoveOTPSeeds(&o->recv_decoder);
  397. }
  398. void DatagramPeerIO_SetOTPWarningHandler (DatagramPeerIO *o, DatagramPeerIO_handler_otp_warning handler, void *user, int num_used)
  399. {
  400. ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
  401. ASSERT(!handler || num_used > 0)
  402. DebugObject_Access(&o->d_obj);
  403. o->handler_otp_warning = handler;
  404. o->handler_otp_warning_user = user;
  405. o->handler_otp_warning_num_used = num_used;
  406. }