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