PageRenderTime 96ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/src/common/socket.c

https://github.com/TyRoXx/webserver
C | 170 lines | 142 code | 28 blank | 0 comment | 13 complexity | b2b0d2dc809b9698680010b194cb99cb MD5 | raw file
  1. #include "socket.h"
  2. #include <stdio.h>
  3. #ifdef WS_UNIX
  4. #include <sys/socket.h>
  5. #include <arpa/inet.h>
  6. #include <netinet/in.h>
  7. #include <unistd.h>
  8. #endif
  9. #ifdef WS_WIN32
  10. static const socket_t InvalidSocket = INVALID_SOCKET;
  11. typedef int socket_size_t;
  12. #else
  13. static const socket_t InvalidSocket = -1;
  14. typedef size_t socket_size_t;
  15. #endif
  16. #ifdef WS_WIN32
  17. static bool wsa_increment()
  18. {
  19. WSADATA wsa;
  20. return WSAStartup(MAKEWORD(2, 2), &wsa) == 0;
  21. }
  22. static void wsa_decrement()
  23. {
  24. WSACleanup();
  25. }
  26. #endif
  27. bool socket_create(socket_t *socket_)
  28. {
  29. #ifdef WS_WIN32
  30. if (!wsa_increment())
  31. {
  32. return false;
  33. }
  34. #endif
  35. *socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  36. if (*socket_ == InvalidSocket)
  37. {
  38. #ifdef WS_WIN32
  39. wsa_decrement();
  40. #endif
  41. return false;
  42. }
  43. return true;
  44. }
  45. void socket_destroy(socket_t socket)
  46. {
  47. #ifdef WS_WIN32
  48. closesocket(socket);
  49. wsa_decrement();
  50. #else
  51. close(socket);
  52. #endif
  53. }
  54. bool socket_bind(socket_t socket, uint16_t port)
  55. {
  56. struct sockaddr_in address = {0};
  57. address.sin_family = AF_INET;
  58. address.sin_addr.s_addr = INADDR_ANY;
  59. address.sin_port = htons(port);
  60. return
  61. (bind(socket, (struct sockaddr *)&address, sizeof(address)) == 0) &&
  62. (listen(socket, 10) == 0);
  63. }
  64. bool socket_accept(socket_t socket, socket_t *accepted, socket_address_t *address)
  65. {
  66. typedef
  67. #ifdef WS_WIN32
  68. int
  69. #else
  70. socklen_t
  71. #endif
  72. address_size_t;
  73. struct sockaddr_in temp_address = {0};
  74. address_size_t temp_address_size = sizeof(temp_address);
  75. *accepted = accept(socket, (struct sockaddr *)&temp_address, &temp_address_size);
  76. if (*accepted == InvalidSocket)
  77. {
  78. return false;
  79. }
  80. #ifdef WS_WIN32
  81. if (!wsa_increment())
  82. {
  83. return false;
  84. }
  85. #endif
  86. if (address)
  87. {
  88. uint32_t const ip = temp_address.sin_addr.s_addr;
  89. memcpy(address->ip.digits, &ip, sizeof(address->ip.digits));
  90. address->port = ntohs(temp_address.sin_port);
  91. }
  92. return true;
  93. }
  94. bool socket_receive(socket_t socket, void *data, size_t size, size_t *received)
  95. {
  96. long const rc = recv(socket, data, (socket_size_t)size, 0);
  97. if (rc <= 0)
  98. {
  99. return false;
  100. }
  101. *received = (size_t)rc;
  102. return true;
  103. }
  104. bool socket_send(socket_t socket, const void *data, size_t size)
  105. {
  106. char const *remaining = data;
  107. char const * const end = (remaining + size);
  108. while (remaining < end)
  109. {
  110. const long rc = send(socket, remaining, (socket_size_t)(end - remaining), 0);
  111. if (rc <= 0)
  112. {
  113. return false;
  114. }
  115. remaining += rc;
  116. }
  117. return true;
  118. }
  119. void socket_shutdown(socket_t socket)
  120. {
  121. int const how =
  122. #ifdef _WIN32
  123. SD_BOTH
  124. #else
  125. SHUT_RDWR
  126. #endif
  127. ;
  128. shutdown(socket, how);
  129. }
  130. bool ip_address_to_string(string_t *dest, ip_address_t source)
  131. {
  132. char buffer[16];
  133. sprintf(
  134. buffer,
  135. "%u.%u.%u.%u",
  136. source.digits[0],
  137. source.digits[1],
  138. source.digits[2],
  139. source.digits[3]
  140. );
  141. return string_assign_c_str(dest, buffer);
  142. }