blob: baa02dc3f62eca4029b4ae3b1d77126d51db26c1 [file] [log] [blame]
yuezonghec78e2ef2025-02-13 17:57:46 -08001/*******************************************************************************
2 * Copyright (c) 2014, 2017 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 * Allan Stockdill-Mander - initial API and implementation and/or initial documentation
15 * Ian Craggs - return codes from linux_read
16 *******************************************************************************/
17
18#include "MQTTLinux.h"
19
20void TimerInit(Timer* timer)
21{
22 timer->end_time = (struct timeval){0, 0};
23}
24
25char TimerIsExpired(Timer* timer)
26{
27 struct timeval now, res;
28 gettimeofday(&now, NULL);
29 timersub(&timer->end_time, &now, &res);
30 return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);
31}
32
33
34void TimerCountdownMS(Timer* timer, unsigned int timeout)
35{
36 struct timeval now;
37 gettimeofday(&now, NULL);
38 struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};
39 timeradd(&now, &interval, &timer->end_time);
40}
41
42
43void TimerCountdown(Timer* timer, unsigned int timeout)
44{
45 struct timeval now;
46 gettimeofday(&now, NULL);
47 struct timeval interval = {timeout, 0};
48 timeradd(&now, &interval, &timer->end_time);
49}
50
51
52int TimerLeftMS(Timer* timer)
53{
54 struct timeval now, res;
55 gettimeofday(&now, NULL);
56 timersub(&timer->end_time, &now, &res);
57 //printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);
58 return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
59}
60
61
62int linux_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
63{
64 struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
65 if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))
66 {
67 interval.tv_sec = 0;
68 interval.tv_usec = 100;
69 }
70
71 setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
72
73 int bytes = 0;
74 while (bytes < len)
75 {
76 int rc = recv(n->my_socket, &buffer[bytes], (size_t)(len - bytes), 0);
77 if (rc == -1)
78 {
79 if (errno != EAGAIN && errno != EWOULDBLOCK)
80 bytes = -1;
81 break;
82 }
83 else if (rc == 0)
84 {
85 bytes = 0;
86 break;
87 }
88 else
89 bytes += rc;
90 }
91 return bytes;
92}
93
94
95int linux_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
96{
97 struct timeval tv;
98
99 tv.tv_sec = 0; /* 30 Secs Timeout */
100 tv.tv_usec = timeout_ms * 1000; // Not init'ing this can cause strange errors
101
102 setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));
103 int rc = write(n->my_socket, buffer, len);
104 return rc;
105}
106
107
108void NetworkInit(Network* n)
109{
110 n->my_socket = 0;
111 n->mqttread = linux_read;
112 n->mqttwrite = linux_write;
113}
114
115
116int NetworkConnect(Network* n, char* addr, int port)
117{
118 int type = SOCK_STREAM;
119 struct sockaddr_in address;
120 int rc = -1;
121 sa_family_t family = AF_INET;
122 struct addrinfo *result = NULL;
123 struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};
124
125 if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)
126 {
127 struct addrinfo* res = result;
128
129 /* prefer ip4 addresses */
130 while (res)
131 {
132 if (res->ai_family == AF_INET)
133 {
134 result = res;
135 break;
136 }
137 res = res->ai_next;
138 }
139
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
149 freeaddrinfo(result);
150 }
151
152 if (rc == 0)
153 {
154 n->my_socket = socket(family, type, 0);
155 if (n->my_socket != -1)
156 rc = connect(n->my_socket, (struct sockaddr*)&address, sizeof(address));
157 }
158
159 return rc;
160}
161
162
163void NetworkDisconnect(Network* n)
164{
165 close(n->my_socket);
166}