1/*
2 Copyright (c) 2015 Arduino LLC. All right reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "BridgeUdp.h"
20
21BridgeUDP::BridgeUDP(BridgeClass &_b) :
22 bridge(_b), opened(false), avail(0), buffered(0), readPos(0) {
23}
24
25/* Start BridgeUDP socket, listening at local port PORT */
26uint8_t BridgeUDP::begin(uint16_t port) {
27 if (opened)
28 return 0;
29 uint8_t cmd[] = {'e', (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)};
30 uint8_t res[2];
31 bridge.transfer(cmd, 3, res, 2);
32 if (res[1] == 1) // Error...
33 return 0;
34 handle = res[0];
35 opened = true;
36 return 1;
37}
38
39/* Release any resources being used by this BridgeUDP instance */
40void BridgeUDP::stop()
41{
42 if (!opened)
43 return;
44 uint8_t cmd[] = {'q', handle};
45 bridge.transfer(cmd, 2);
46 opened = false;
47}
48
49int BridgeUDP::beginPacket(const char *host, uint16_t port)
50{
51 if (!opened)
52 return 0;
53 uint8_t cmd[] = {'E', handle, (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)};
54 uint8_t res[1];
55 bridge.transfer(cmd, 4, (const uint8_t *)host, strlen(host), res, 1);
56 return res[0]; // 1=Success, 0=Error
57}
58
59int BridgeUDP::beginBroadcastPacket(uint16_t port)
60{
61 if (!opened)
62 return 0;
63 uint8_t cmd[] = {'v', handle, (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)};
64 uint8_t res[1];
65 bridge.transfer(cmd, 4, res, 1);
66 return res[0]; // 1=Success, 0=Error
67}
68
69int BridgeUDP::beginPacket(IPAddress ip, uint16_t port)
70{
71 if (!opened)
72 return 0;
73 String address;
74 address.reserve(18);
75 address += ip[0];
76 address += '.';
77 address += ip[1];
78 address += '.';
79 address += ip[2];
80 address += '.';
81 address += ip[3];
82 return beginPacket(address.c_str(), port);
83}
84
85int BridgeUDP::endPacket()
86{
87 if (!opened)
88 return 0;
89 uint8_t cmd[] = {'H', handle};
90 uint8_t res[1];
91 bridge.transfer(cmd, 2, res, 1);
92 return res[0]; // 1=Success, 0=Error
93}
94
95size_t BridgeUDP::write(const uint8_t *buffer, size_t size)
96{
97 if (!opened)
98 return 0;
99 uint8_t cmd[] = {'h', handle};
100 uint8_t res[1];
101 bridge.transfer(cmd, 2, buffer, size, res, 1);
102 return res[0]; // 1=Success, 0=Error
103}
104
105int BridgeUDP::parsePacket()
106{
107 if (!opened)
108 return 0;
109 buffered = 0;
110 readPos = 0;
111 uint8_t cmd[] = {'Q', handle};
112 uint8_t res[3];
113 bridge.transfer(cmd, 2, res, 3);
114 if (res[0] == 0) {
115 // There aren't any packets available
116 return 0;
117 }
118 avail = (res[1] << 8) + res[2];
119 return 1;
120}
121
122void BridgeUDP::doBuffer() {
123 // If there are already char in buffer exit
124 if (buffered > 0)
125 return;
126 if (avail == 0)
127 return;
128
129 // Try to buffer up to 32 characters
130 readPos = 0;
131 uint8_t cmd[] = {'u', handle, sizeof(buffer)};
132 buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer));
133}
134
135int BridgeUDP::read()
136{
137 if (!opened)
138 return -1;
139 doBuffer();
140 if (buffered == 0) {
141 return -1; // no chars available
142 }
143 buffered--;
144 avail--;
145 return buffer[readPos++];
146}
147
148int BridgeUDP::read(unsigned char* buff, size_t size)
149{
150 if (!opened)
151 return -1;
152 size_t readed = 0;
153 do {
154 if (buffered == 0) {
155 doBuffer();
156 if (buffered == 0)
157 return readed;
158 }
159 buff[readed++] = buffer[readPos++];
160 buffered--;
161 avail--;
162 } while (readed < size);
163 return readed;
164}
165
166int BridgeUDP::peek()
167{
168 if (!opened)
169 return -1;
170 doBuffer();
171 if (buffered == 0)
172 return -1; // no chars available
173 return buffer[readPos];
174}
175
176IPAddress BridgeUDP::remoteIP()
177{
178 if (!opened)
179 return -1;
180 uint8_t cmd[] = {'T', handle};
181 uint8_t res[7];
182 bridge.transfer(cmd, 2, res, 7);
183 if (res[0] == 0)
184 return IPAddress(0,0,0,0);
185 return IPAddress(res[1], res[2], res[3], res[4]);
186}
187
188uint16_t BridgeUDP::remotePort()
189{
190 if (!opened)
191 return -1;
192 uint8_t cmd[] = {'T', handle};
193 uint8_t res[7];
194 bridge.transfer(cmd, 2, res, 7);
195 if (res[0] == 0)
196 return 0;
197 return (res[5] << 8) + res[6];
198}