1
0

tcp_proxy_server.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * tcp proxy server
  3. *
  4. * @build: make examples
  5. * @http_server: bin/httpd -d
  6. * @proxy_server: bin/tcp_proxy_server 1234 127.0.0.1:8080
  7. * bin/tcp_proxy_server 1234 www.baidu.com
  8. * @client: bin/curl -v 127.0.0.1:1234
  9. * bin/nc 127.0.0.1 1234
  10. * > GET / HTTP/1.1
  11. * > Connection: close
  12. * > [Enter]
  13. * > GET / HTTP/1.1
  14. * > Connection: keep-alive
  15. * > [Enter]
  16. */
  17. #include "hloop.h"
  18. #include "hsocket.h"
  19. // hloop_create_tcp_server
  20. // on_accept(connio) => proxyio = hloop_create_tcp_client
  21. // on_proxy_connect(proxyio) => hio_read(connio) hio_read(proxyio)
  22. // on_recv(connio) => hio_write(proxyio)
  23. // on_proxy_recv(proxyio) => hio_write(connio)
  24. // on_close(connio) => hio_close(proxyio)
  25. // on_proxy_close(proxyio) => hio_close(connio)
  26. static char proxy_host[64] = "127.0.0.1";
  27. static int proxy_port = 80;
  28. static void on_proxy_close(hio_t* proxyio) {
  29. hio_t* connio = (hio_t*)hevent_userdata(proxyio);
  30. if (connio) {
  31. hevent_set_userdata(proxyio, NULL);
  32. hio_close(connio);
  33. }
  34. }
  35. static void on_proxy_recv(hio_t* proxyio, void* buf, int readbytes) {
  36. hio_t* connio = (hio_t*)hevent_userdata(proxyio);
  37. assert(connio != NULL);
  38. hio_write(connio, buf, readbytes);
  39. }
  40. static void on_proxy_connect(hio_t* proxyio) {
  41. hio_t* connio = (hio_t*)hevent_userdata(proxyio);
  42. assert(connio != NULL);
  43. hio_read(connio);
  44. hio_setcb_close(proxyio, on_proxy_close);
  45. hio_setcb_read(proxyio, on_proxy_recv);
  46. hio_read(proxyio);
  47. }
  48. static void on_close(hio_t* io) {
  49. printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
  50. hio_t* proxyio = (hio_t*)hevent_userdata(io);
  51. if (proxyio) {
  52. hevent_set_userdata(io, NULL);
  53. hio_close(proxyio);
  54. }
  55. }
  56. static void on_recv(hio_t* io, void* buf, int readbytes) {
  57. printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
  58. char localaddrstr[SOCKADDR_STRLEN] = {0};
  59. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  60. printf("[%s] <=> [%s]\n",
  61. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  62. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  63. printf("< %.*s", readbytes, (char*)buf);
  64. hio_t* proxyio = (hio_t*)hevent_userdata(io);
  65. assert(proxyio != NULL);
  66. hio_write(proxyio, buf, readbytes);
  67. }
  68. static void on_accept(hio_t* io) {
  69. printf("on_accept connfd=%d\n", hio_fd(io));
  70. char localaddrstr[SOCKADDR_STRLEN] = {0};
  71. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  72. printf("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
  73. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  74. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  75. hio_t* proxyio = hloop_create_tcp_client(hevent_loop(io), proxy_host, proxy_port, on_proxy_connect);
  76. if (proxyio == NULL) {
  77. hio_close(io);
  78. return;
  79. }
  80. hio_setcb_read(io, on_recv);
  81. hio_setcb_close(io, on_close);
  82. hevent_set_userdata(io, proxyio);
  83. hevent_set_userdata(proxyio, io);
  84. }
  85. int main(int argc, char** argv) {
  86. if (argc < 3) {
  87. printf("Usage: tcp port proxy_host:proxy_port\n");
  88. return -10;
  89. }
  90. int port = atoi(argv[1]);
  91. char* pos = strchr(argv[2], ':');
  92. if (pos) {
  93. int len = pos - argv[2];
  94. if (len > 0) {
  95. memcpy(proxy_host, argv[2], len);
  96. proxy_host[len] = '\0';
  97. }
  98. proxy_port = atoi(pos + 1);
  99. } else {
  100. strncpy(proxy_host, argv[2], sizeof(proxy_host));
  101. }
  102. if (proxy_port == 0) proxy_port = 80;
  103. printf("proxy: [%s:%d]\n", proxy_host, proxy_port);
  104. hloop_t* loop = hloop_new(0);
  105. hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
  106. if (listenio == NULL) {
  107. return -20;
  108. }
  109. printf("listenfd=%d\n", hio_fd(listenio));
  110. hloop_run(loop);
  111. hloop_free(&loop);
  112. return 0;
  113. }