transport.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*******************************************************************************
  2. * Copyright (c) 2014 IBM Corp.
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License v1.0
  6. * and Eclipse Distribution License v1.0 which accompany this distribution.
  7. *
  8. * The Eclipse Public License is available at
  9. * http://www.eclipse.org/legal/epl-v10.html
  10. * and the Eclipse Distribution License is available at
  11. * http://www.eclipse.org/org/documents/edl-v10.php.
  12. *
  13. * Contributors:
  14. * Ian Craggs - initial API and implementation and/or initial documentation
  15. * Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension
  16. *******************************************************************************/
  17. #include <sys/types.h>
  18. #if !defined(SOCKET_ERROR)
  19. /** error in socket operation */
  20. #define SOCKET_ERROR -1
  21. #endif
  22. #if defined(WIN32)
  23. /* default on Windows is 64 - increase to make Linux and Windows the same */
  24. #define FD_SETSIZE 1024
  25. #include <winsock2.h>
  26. #include <ws2tcpip.h>
  27. #define MAXHOSTNAMELEN 256
  28. #define EAGAIN WSAEWOULDBLOCK
  29. #define EINTR WSAEINTR
  30. #define EINVAL WSAEINVAL
  31. #define EINPROGRESS WSAEINPROGRESS
  32. #define EWOULDBLOCK WSAEWOULDBLOCK
  33. #define ENOTCONN WSAENOTCONN
  34. #define ECONNRESET WSAECONNRESET
  35. #define ioctl ioctlsocket
  36. #define socklen_t int
  37. #else
  38. #define INVALID_SOCKET SOCKET_ERROR
  39. #include <sys/socket.h>
  40. #include <sys/param.h>
  41. #include <sys/time.h>
  42. #include <netinet/in.h>
  43. #include <netinet/tcp.h>
  44. #include <arpa/inet.h>
  45. #include <netdb.h>
  46. #include <stdio.h>
  47. #include <unistd.h>
  48. #include <errno.h>
  49. #include <fcntl.h>
  50. #include <string.h>
  51. #include <stdlib.h>
  52. #endif
  53. #if defined(WIN32)
  54. #include <Iphlpapi.h>
  55. #else
  56. #include <sys/ioctl.h>
  57. #include <net/if.h>
  58. #endif
  59. /**
  60. This simple low-level implementation assumes a single connection for a single thread. Thus, a static
  61. variable is used for that connection.
  62. On other scenarios, the user must solve this by taking into account that the current implementation of
  63. MQTTPacket_read() has a function pointer for a function call to get the data to a buffer, but no provisions
  64. to know the caller or other indicator (the socket id): int (*getfn)(unsigned char*, int)
  65. */
  66. static int mysock = INVALID_SOCKET;
  67. int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen)
  68. {
  69. int rc = 0;
  70. rc = write(sock, buf, buflen);
  71. return rc;
  72. }
  73. int transport_getdata(unsigned char* buf, int count)
  74. {
  75. int rc = recv(mysock, buf, count, 0);
  76. //printf("received %d bytes count %d\n", rc, (int)count);
  77. return rc;
  78. }
  79. int transport_getdatanb(void *sck, unsigned char* buf, int count)
  80. {
  81. int sock = *((int *)sck); /* sck: pointer to whatever the system may use to identify the transport */
  82. /* this call will return after the timeout set on initialization if no bytes;
  83. in your system you will use whatever you use to get whichever outstanding
  84. bytes your socket equivalent has ready to be extracted right now, if any,
  85. or return immediately */
  86. int rc = recv(sock, buf, count, 0);
  87. if (rc == -1) {
  88. /* check error conditions from your system here, and return -1 */
  89. return 0;
  90. }
  91. return rc;
  92. }
  93. /**
  94. return >=0 for a socket descriptor, <0 for an error code
  95. @todo Basically moved from the sample without changes, should accomodate same usage for 'sock' for clarity,
  96. removing indirections
  97. */
  98. int transport_open(char* addr, int port)
  99. {
  100. int* sock = &mysock;
  101. int type = SOCK_STREAM;
  102. struct sockaddr_in address;
  103. #if defined(AF_INET6)
  104. struct sockaddr_in6 address6;
  105. #endif
  106. int rc = -1;
  107. #if defined(WIN32)
  108. short family;
  109. #else
  110. sa_family_t family = AF_INET;
  111. #endif
  112. struct addrinfo *result = NULL;
  113. struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};
  114. static struct timeval tv;
  115. *sock = -1;
  116. if (addr[0] == '[')
  117. ++addr;
  118. if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)
  119. {
  120. struct addrinfo* res = result;
  121. /* prefer ip4 addresses */
  122. while (res)
  123. {
  124. if (res->ai_family == AF_INET)
  125. {
  126. result = res;
  127. break;
  128. }
  129. res = res->ai_next;
  130. }
  131. #if defined(AF_INET6)
  132. if (result->ai_family == AF_INET6)
  133. {
  134. address6.sin6_port = htons(port);
  135. address6.sin6_family = family = AF_INET6;
  136. address6.sin6_addr = ((struct sockaddr_in6*)(result->ai_addr))->sin6_addr;
  137. }
  138. else
  139. #endif
  140. if (result->ai_family == AF_INET)
  141. {
  142. address.sin_port = htons(port);
  143. address.sin_family = family = AF_INET;
  144. address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
  145. }
  146. else
  147. rc = -1;
  148. freeaddrinfo(result);
  149. }
  150. if (rc == 0)
  151. {
  152. *sock = socket(family, type, 0);
  153. if (*sock != -1)
  154. {
  155. #if defined(NOSIGPIPE)
  156. int opt = 1;
  157. if (setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0)
  158. Log(TRACE_MIN, -1, "Could not set SO_NOSIGPIPE for socket %d", *sock);
  159. #endif
  160. if (family == AF_INET)
  161. rc = connect(*sock, (struct sockaddr*)&address, sizeof(address));
  162. #if defined(AF_INET6)
  163. else
  164. rc = connect(*sock, (struct sockaddr*)&address6, sizeof(address6));
  165. #endif
  166. }
  167. }
  168. if (mysock == INVALID_SOCKET)
  169. return rc;
  170. tv.tv_sec = 1; /* 1 second Timeout */
  171. tv.tv_usec = 0;
  172. setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
  173. return mysock;
  174. }
  175. int transport_close(int sock)
  176. {
  177. int rc;
  178. rc = shutdown(sock, SHUT_WR);
  179. rc = recv(sock, NULL, (size_t)0, 0);
  180. rc = close(sock);
  181. return rc;
  182. }