Proxy.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*******************************************************************************
  2. * Copyright (c) 2009, 2021 Diehl Metering.
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License v2.0
  6. * and Eclipse Distribution License v1.0 which accompany this distribution.
  7. *
  8. * The Eclipse Public License is available at
  9. * https://www.eclipse.org/legal/epl-2.0/
  10. * and the Eclipse Distribution License is available at
  11. * http://www.eclipse.org/org/documents/edl-v10.php.
  12. *
  13. * Contributors:
  14. * Keith Holman - initial implementation and documentation
  15. * Sven Gambel - move WebSocket proxy support to generic proxy support
  16. *******************************************************************************/
  17. #include <stdio.h>
  18. #include <string.h>
  19. // for timeout process in Proxy_connect()
  20. #include <time.h>
  21. #if defined(_WIN32) || defined(_WIN64)
  22. #include <windows.h>
  23. #if defined(_MSC_VER) && _MSC_VER < 1900
  24. #define snprintf _snprintf
  25. #endif
  26. #else
  27. #include <unistd.h>
  28. #endif
  29. #include "Log.h"
  30. #include "MQTTProtocolOut.h"
  31. #include "StackTrace.h"
  32. #include "Heap.h"
  33. #if defined(OPENSSL)
  34. #include "SSLSocket.h"
  35. #include <openssl/rand.h>
  36. #endif /* defined(OPENSSL) */
  37. #include "Socket.h"
  38. /**
  39. * Notify the IP address and port of the endpoint to proxy, and wait connection to endpoint.
  40. *
  41. * @param[in] net network connection to proxy.
  42. * @param[in] ssl enable ssl.
  43. * @param[in] hostname hostname of endpoint.
  44. *
  45. * @retval SOCKET_ERROR failed to network connection
  46. * @retval 0 connection to endpoint
  47. *
  48. */
  49. int Proxy_connect(networkHandles *net, int ssl, const char *hostname)
  50. {
  51. int port, i, rc = 0, buf_len=0;
  52. char *buf = NULL;
  53. size_t hostname_len, actual_len = 0;
  54. time_t current, timeout;
  55. PacketBuffers nulbufs = {0, NULL, NULL, NULL, {0, 0, 0, 0}};
  56. FUNC_ENTRY;
  57. hostname_len = MQTTProtocol_addressPort(hostname, &port, NULL, PROXY_DEFAULT_PORT);
  58. for ( i = 0; i < 2; ++i ) {
  59. #if defined(OPENSSL)
  60. if(ssl) {
  61. if (net->https_proxy_auth) {
  62. buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
  63. "Host: %.*s\r\n"
  64. "Proxy-authorization: Basic %s\r\n"
  65. "\r\n",
  66. (int)hostname_len, hostname, port,
  67. (int)hostname_len, hostname, net->https_proxy_auth);
  68. }
  69. else {
  70. buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
  71. "Host: %.*s\r\n"
  72. "\r\n",
  73. (int)hostname_len, hostname, port,
  74. (int)hostname_len, hostname);
  75. }
  76. }
  77. else {
  78. #endif
  79. if (net->http_proxy_auth) {
  80. buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
  81. "Host: %.*s\r\n"
  82. "Proxy-authorization: Basic %s\r\n"
  83. "\r\n",
  84. (int)hostname_len, hostname, port,
  85. (int)hostname_len, hostname, net->http_proxy_auth);
  86. }
  87. else {
  88. buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
  89. "Host: %.*s\r\n"
  90. "\r\n",
  91. (int)hostname_len, hostname, port,
  92. (int)hostname_len, hostname);
  93. }
  94. #if defined(OPENSSL)
  95. }
  96. #endif
  97. if ( i==0 && buf_len > 0 ) {
  98. ++buf_len;
  99. if ((buf = malloc( buf_len )) == NULL)
  100. {
  101. rc = PAHO_MEMORY_ERROR;
  102. goto exit;
  103. }
  104. }
  105. }
  106. Log(TRACE_PROTOCOL, -1, "Proxy_connect: \"%s\"", buf);
  107. Socket_putdatas(net->socket, buf, buf_len, nulbufs);
  108. free(buf);
  109. buf = NULL;
  110. time(&timeout);
  111. timeout += (time_t)10;
  112. while(1) {
  113. buf = Socket_getdata(net->socket, (size_t)12, &actual_len, &rc);
  114. if(actual_len) {
  115. if ( (strncmp( buf, "HTTP/1.0 200", 12 ) != 0) && (strncmp( buf, "HTTP/1.1 200", 12 ) != 0) )
  116. rc = SOCKET_ERROR;
  117. break;
  118. }
  119. else {
  120. time(&current);
  121. if(current > timeout) {
  122. rc = SOCKET_ERROR;
  123. break;
  124. }
  125. #if defined(_WIN32) || defined(_WIN64)
  126. Sleep(250);
  127. #else
  128. usleep(250000);
  129. #endif
  130. }
  131. }
  132. /* flush the SocketBuffer */
  133. actual_len = 1;
  134. while (actual_len)
  135. {
  136. int rc1;
  137. buf = Socket_getdata(net->socket, (size_t)1, &actual_len, &rc1);
  138. }
  139. exit:
  140. FUNC_EXIT_RC(rc);
  141. return rc;
  142. }