/src/libmanos/manos_socket.c

http://github.com/jacksonh/manos · C · 292 lines · 225 code · 67 blank · 0 comment · 33 complexity · 4ddc4ca952e1dac6485f12bbca6da623 MD5 · raw file

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10. #include <sys/types.h>
  11. #include <arpa/inet.h>
  12. #include <netdb.h>
  13. #include <netinet/in.h>
  14. #include <netinet/tcp.h>
  15. #ifdef HAVE_SYS_SENDFILE_H
  16. #include <sys/sendfile.h>
  17. #endif
  18. #include "manos.h"
  19. static int
  20. setup_socket (int fd)
  21. {
  22. int flags = 1;
  23. setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof (flags));
  24. return (fcntl (fd, F_SETFL, O_NONBLOCK) != -1);
  25. }
  26. static void
  27. parse_sockaddr (struct sockaddr_storage *addr, manos_ip_endpoint_t *ep)
  28. {
  29. struct sockaddr_in *in4;
  30. struct sockaddr_in6 *in6;
  31. switch (addr->ss_family) {
  32. case AF_INET:
  33. in4 = (struct sockaddr_in*) addr;
  34. ep->port = ntohs (in4->sin_port);
  35. memcpy (ep->address_bytes, &in4->sin_addr.s_addr, sizeof (struct in_addr));
  36. ep->is_ipv4 = 1;
  37. break;
  38. case AF_INET6:
  39. in6 = (struct sockaddr_in6*) addr;
  40. ep->port = ntohs (in6->sin6_port);
  41. memcpy (ep->address_bytes, in6->sin6_addr.s6_addr, sizeof (struct in6_addr));
  42. ep->is_ipv4 = 0;
  43. break;
  44. }
  45. }
  46. static socklen_t
  47. parse_endpoint (manos_ip_endpoint_t *ep, struct sockaddr_storage *addr)
  48. {
  49. struct sockaddr_in *in4;
  50. struct sockaddr_in6 *in6;
  51. if (ep->is_ipv4) {
  52. in4 = (struct sockaddr_in*) addr;
  53. in4->sin_family = AF_INET;
  54. in4->sin_port = htons (ep->port);
  55. memcpy (&in4->sin_addr.s_addr, ep->address_bytes, sizeof (struct in_addr));
  56. return sizeof (*in4);
  57. } else {
  58. in6 = (struct sockaddr_in6*) addr;
  59. in6->sin6_family = AF_INET6;
  60. in6->sin6_port = htons (ep->port);
  61. memcpy (in6->sin6_addr.s6_addr, ep->address_bytes, sizeof (struct in6_addr));
  62. return sizeof (*in6);
  63. }
  64. }
  65. int
  66. manos_socket_localname_ip (int fd, manos_ip_endpoint_t *ep, int *err)
  67. {
  68. struct sockaddr_storage addr;
  69. socklen_t len;
  70. int result;
  71. len = sizeof (addr);
  72. result = getsockname (fd, (struct sockaddr*) &addr, &len);
  73. parse_sockaddr (&addr, ep);
  74. *err = errno;
  75. return result;
  76. }
  77. int
  78. manos_socket_peername_ip (int fd, manos_ip_endpoint_t *ep, int *err)
  79. {
  80. struct sockaddr_storage addr;
  81. socklen_t len;
  82. int result;
  83. len = sizeof (addr);
  84. result = getpeername (fd, (struct sockaddr*) &addr, &len);
  85. parse_sockaddr (&addr, ep);
  86. *err = errno;
  87. return result;
  88. }
  89. int
  90. manos_socket_create (int addressFamily, int protocolFamily, int *err)
  91. {
  92. static int domains[] = { AF_INET, AF_INET6 };
  93. static int types[] = { SOCK_STREAM, SOCK_DGRAM };
  94. static int protocols[] = { IPPROTO_TCP, IPPROTO_UDP };
  95. int result = socket (domains[addressFamily], types[protocolFamily], protocols[protocolFamily]);
  96. if (result > 0 && setup_socket (result) < 0) {
  97. *err = errno;
  98. close (result);
  99. return -1;
  100. }
  101. *err = errno;
  102. return result;
  103. }
  104. int
  105. manos_socket_bind_ip (int fd, manos_ip_endpoint_t *ep, int *err)
  106. {
  107. struct sockaddr_storage addr;
  108. socklen_t len;
  109. int result;
  110. len = parse_endpoint (ep, &addr);
  111. result = bind (fd, (struct sockaddr*) &addr, len);
  112. *err = errno;
  113. return result;
  114. }
  115. int
  116. manos_socket_connect_ip (int fd, manos_ip_endpoint_t *ep, int *err)
  117. {
  118. struct sockaddr_storage addr;
  119. socklen_t len;
  120. int result;
  121. len = parse_endpoint (ep, &addr);
  122. result = connect (fd, (struct sockaddr*) &addr, len);
  123. if (result < 0 && errno == EINPROGRESS) {
  124. *err = 0;
  125. return 0;
  126. } else {
  127. *err = errno;
  128. return result;
  129. }
  130. }
  131. int
  132. manos_socket_listen (int fd, int backlog, int *err)
  133. {
  134. int result;
  135. result = listen (fd, backlog);
  136. *err = errno;
  137. return result;
  138. }
  139. int
  140. manos_socket_accept (int fd, manos_ip_endpoint_t *remote, int *err)
  141. {
  142. struct sockaddr_storage addr;
  143. socklen_t len = sizeof (struct sockaddr_storage);
  144. int result;
  145. result = accept (fd, (struct sockaddr*) &addr, &len);
  146. if (result < 0) {
  147. if (errno == EAGAIN || errno == ECONNABORTED) {
  148. *err = 0;
  149. return -1;
  150. }
  151. *err = errno;
  152. return -1;
  153. }
  154. if (!setup_socket (result)) {
  155. *err = errno;
  156. close (result);
  157. return -1;
  158. }
  159. parse_sockaddr (&addr, remote);
  160. return result;
  161. }
  162. int
  163. manos_socket_send (int fd, const char *buffer, int offset, int len, int* err)
  164. {
  165. ssize_t rc;
  166. rc = send (fd, buffer + offset, len, 0);
  167. if (rc < 0 && (errno == EAGAIN)) {
  168. *err = 0;
  169. } else {
  170. *err = errno;
  171. }
  172. return rc;
  173. }
  174. int
  175. manos_socket_receive (int fd, char* buffer, int len, int *err)
  176. {
  177. int result;
  178. result = recv (fd, buffer, len, 0);
  179. if (result < 0 && (errno == EAGAIN)) {
  180. *err = 0;
  181. } else {
  182. *err = errno;
  183. }
  184. return result;
  185. }
  186. int
  187. manos_socket_sendto_ip (int fd, const char *buffer, int offset, int len, manos_ip_endpoint_t *to, int *err)
  188. {
  189. int result;
  190. struct sockaddr_storage target;
  191. socklen_t slen;
  192. slen = parse_endpoint (to, &target);
  193. result = sendto (fd, buffer + offset, len, 0, (struct sockaddr*) &target, slen);
  194. if (result < 0 && (errno == EAGAIN)) {
  195. *err = 0;
  196. } else {
  197. *err = errno;
  198. }
  199. return result;
  200. }
  201. int
  202. manos_socket_receivefrom_ip (int fd, char* data, int len, manos_ip_endpoint_t *from, int *err)
  203. {
  204. int result;
  205. struct sockaddr_storage source;
  206. socklen_t slen = sizeof (source);
  207. result = recvfrom (fd, data, len, 0, (struct sockaddr*) &source, &slen);
  208. if (result < 0 && (errno == EAGAIN)) {
  209. *err = 0;
  210. return -1;
  211. } else {
  212. *err = errno;
  213. if (from) {
  214. parse_sockaddr (&source, from);
  215. }
  216. return result;
  217. }
  218. }
  219. int
  220. manos_socket_close (int fd, int *err)
  221. {
  222. int result = close (fd);
  223. *err = errno;
  224. return result;
  225. }