1/*
2 Copyright (c) 2013 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 <BridgeClient.h>
20
21BridgeClient::BridgeClient(uint8_t _h, BridgeClass &_b) :
22 bridge(_b), handle(_h), opened(true), buffered(0) {
23}
24
25BridgeClient::BridgeClient(BridgeClass &_b) :
26 bridge(_b), handle(0), opened(false), buffered(0) {
27}
28
29BridgeClient::~BridgeClient() {
30}
31
32BridgeClient& BridgeClient::operator=(const BridgeClient &_x) {
33 opened = _x.opened;
34 handle = _x.handle;
35 return *this;
36}
37
38void BridgeClient::stop() {
39 if (opened) {
40 uint8_t cmd[] = {'j', handle};
41 bridge.transfer(cmd, 2);
42 }
43 opened = false;
44 buffered = 0;
45 readPos = 0;
46}
47
48void BridgeClient::doBuffer() {
49 // If there are already char in buffer exit
50 if (buffered > 0)
51 return;
52
53 // Try to buffer up to 32 characters
54 readPos = 0;
55 uint8_t cmd[] = {'K', handle, sizeof(buffer)};
56 buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer));
57}
58
59int BridgeClient::available() {
60 // Look if there is new data available
61 doBuffer();
62 return buffered;
63}
64
65int BridgeClient::read() {
66 doBuffer();
67 if (buffered == 0)
68 return -1; // no chars available
69 else {
70 buffered--;
71 return buffer[readPos++];
72 }
73}
74
75int BridgeClient::read(uint8_t *buff, size_t size) {
76 size_t readed = 0;
77 do {
78 if (buffered == 0) {
79 doBuffer();
80 if (buffered == 0)
81 return readed;
82 }
83 buff[readed++] = buffer[readPos++];
84 buffered--;
85 } while (readed < size);
86 return readed;
87}
88
89int BridgeClient::peek() {
90 doBuffer();
91 if (buffered == 0)
92 return -1; // no chars available
93 else
94 return buffer[readPos];
95}
96
97size_t BridgeClient::write(uint8_t c) {
98 if (!opened)
99 return 0;
100 uint8_t cmd[] = {'l', handle, c};
101 bridge.transfer(cmd, 3);
102 return 1;
103}
104
105size_t BridgeClient::write(const uint8_t *buf, size_t size) {
106 if (!opened)
107 return 0;
108 uint8_t cmd[] = {'l', handle};
109 bridge.transfer(cmd, 2, buf, size, NULL, 0);
110 return size;
111}
112
113void BridgeClient::flush() {
114}
115
116uint8_t BridgeClient::connected() {
117 if (!opened)
118 return false;
119 // Client is "connected" if it has unread bytes
120 if (available())
121 return true;
122
123 uint8_t cmd[] = {'L', handle};
124 uint8_t res[1];
125 bridge.transfer(cmd, 2, res, 1);
126 return (res[0] == 1);
127}
128
129int BridgeClient::connect(IPAddress ip, uint16_t port) {
130 String address;
131 address.reserve(18);
132 address += ip[0];
133 address += '.';
134 address += ip[1];
135 address += '.';
136 address += ip[2];
137 address += '.';
138 address += ip[3];
139 return connect(address.c_str(), port);
140}
141
142int BridgeClient::connect(const char *host, uint16_t port) {
143 uint8_t tmp[] = {
144 'C',
145 static_cast<uint8_t>(port >> 8),
146 static_cast<uint8_t>(port)
147 };
148 uint8_t res[1];
149 int l = bridge.transfer(tmp, 3, (const uint8_t *)host, strlen(host), res, 1);
150 if (l == 0)
151 return 0;
152 handle = res[0];
153
154 // wait for connection
155 uint8_t tmp2[] = { 'c', handle };
156 uint8_t res2[1];
157 while (true) {
158 bridge.transfer(tmp2, 2, res2, 1);
159 if (res2[0] == 0)
160 break;
161 delay(1);
162 }
163 opened = true;
164
165 // check for successful connection
166 if (connected())
167 return 1;
168
169 stop();
170 handle = 0;
171 return 0;
172}
173
174int BridgeClient::connectSSL(const char *host, uint16_t port) {
175 if (bridge.getBridgeVersion() < 161)
176 return -1;
177
178 uint8_t tmp[] = {
179 'Z',
180 static_cast<uint8_t>(port >> 8),
181 static_cast<uint8_t>(port)
182 };
183 uint8_t res[1];
184 int l = bridge.transfer(tmp, 3, (const uint8_t *)host, strlen(host), res, 1);
185 if (l == 0)
186 return 0;
187 handle = res[0];
188
189 // wait for connection
190 uint8_t tmp2[] = { 'c', handle };
191 uint8_t res2[1];
192 while (true) {
193 bridge.transfer(tmp2, 2, res2, 1);
194 if (res2[0] == 0)
195 break;
196 delay(1);
197 }
198 opened = true;
199
200 // check for successful connection
201 if (connected())
202 return 1;
203
204 stop();
205 handle = 0;
206 return 0;
207}