connectlib.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* With adaptations by Espressif Systems
  2. *
  3. * Copyright (c) 2013 Tatsuhiro Tsujikawa
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #include <stdlib.h>
  25. #include <stdint.h>
  26. #include <stddef.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <ctype.h>
  32. #include <netdb.h>
  33. #include "connectlib.h"
  34. /* Basic parser from nghttp2/examples/client.c */
  35. int parse_uri(struct uri *res, const char *uri)
  36. {
  37. /* We only interested in https */
  38. size_t len, i, offset;
  39. int ipv6addr = 0;
  40. memset(res, 0, sizeof(struct uri));
  41. len = strlen(uri);
  42. if (len < 9 || memcmp("https://", uri, 8) != 0) {
  43. return -1;
  44. }
  45. offset = 8;
  46. res->host = res->hostport = &uri[offset];
  47. res->hostlen = 0;
  48. if (uri[offset] == '[') {
  49. /* IPv6 literal address */
  50. ++offset;
  51. ++res->host;
  52. ipv6addr = 1;
  53. for (i = offset; i < len; ++i) {
  54. if (uri[i] == ']') {
  55. res->hostlen = i - offset;
  56. offset = i + 1;
  57. break;
  58. }
  59. }
  60. } else {
  61. const char delims[] = ":/?#";
  62. for (i = offset; i < len; ++i) {
  63. if (strchr(delims, uri[i]) != NULL) {
  64. break;
  65. }
  66. }
  67. res->hostlen = i - offset;
  68. offset = i;
  69. }
  70. if (res->hostlen == 0) {
  71. return -1;
  72. }
  73. /* Assuming https */
  74. res->port = 443;
  75. if (offset < len) {
  76. if (uri[offset] == ':') {
  77. /* port */
  78. const char delims[] = "/?#";
  79. int port = 0;
  80. ++offset;
  81. for (i = offset; i < len; ++i) {
  82. if (strchr(delims, uri[i]) != NULL) {
  83. break;
  84. }
  85. if ('0' <= uri[i] && uri[i] <= '9') {
  86. port *= 10;
  87. port += uri[i] - '0';
  88. if (port > 65535) {
  89. return -1;
  90. }
  91. } else {
  92. return -1;
  93. }
  94. }
  95. if (port == 0) {
  96. return -1;
  97. }
  98. offset = i;
  99. res->port = (uint16_t)port;
  100. }
  101. }
  102. res->hostportlen = (size_t)(uri + offset + ipv6addr - res->host);
  103. for (i = offset; i < len; ++i) {
  104. if (uri[i] == '#') {
  105. break;
  106. }
  107. }
  108. if (i - offset == 0) {
  109. res->path = "/";
  110. res->pathlen = 1;
  111. } else {
  112. res->path = &uri[offset];
  113. res->pathlen = i - offset;
  114. }
  115. return 0;
  116. }
  117. int connect_to_host(const char *host, size_t hostlen, uint16_t port)
  118. {
  119. int ret;
  120. struct addrinfo hints = {
  121. .ai_family = AF_UNSPEC,
  122. .ai_socktype = SOCK_STREAM,
  123. };
  124. char service[6];
  125. snprintf(service, sizeof(service), "%u", port);
  126. char *use_host = calloc(1, hostlen + 1);
  127. if (!use_host) {
  128. return -1;
  129. }
  130. strncpy(use_host, host, hostlen);
  131. struct addrinfo *res;
  132. ret = getaddrinfo(use_host, service, &hints, &res);
  133. if (ret) {
  134. free(use_host);
  135. return -1;
  136. }
  137. free(use_host);
  138. ret = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  139. if (ret < 0) {
  140. goto err_freeaddr;
  141. }
  142. int fd = ret;
  143. ret = connect(fd, res->ai_addr, res->ai_addrlen);
  144. if (ret < 0) {
  145. goto err_freesocket;
  146. }
  147. return fd;
  148. err_freesocket:
  149. close(fd);
  150. err_freeaddr:
  151. freeaddrinfo(res);
  152. return -1;
  153. }