Skip to content

Commit dfaa6ce

Browse files
committed
Add socket buffer to improve TCP socket read performance
1 parent 3d65bc5 commit dfaa6ce

File tree

4 files changed

+206
-64
lines changed

4 files changed

+206
-64
lines changed

src/GSMClient.cpp

Lines changed: 24 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20+
#include "utility/GSMSocketBuffer.h"
21+
2022
#include "GSMClient.h"
2123

2224
enum {
@@ -44,9 +46,7 @@ GSMClient::GSMClient(int socket, bool synch) :
4446
_host(NULL),
4547
_port(0),
4648
_ssl(false),
47-
_writeSync(true),
48-
_peek(-1),
49-
_available(0)
49+
_writeSync(true)
5050
{
5151
MODEM.addUrcHandler(this);
5252
}
@@ -199,6 +199,10 @@ int GSMClient::connectSSL(const char *host, uint16_t port)
199199

200200
int GSMClient::connect()
201201
{
202+
if (_socket != -1) {
203+
stop();
204+
}
205+
202206
if (_synch) {
203207
while (ready() == 0);
204208
} else if (ready() == 0) {
@@ -323,63 +327,19 @@ int GSMClient::read(uint8_t *buf, size_t size)
323327
return 0;
324328
}
325329

326-
if (size > 512) {
327-
size = 512;
328-
}
329-
330-
String response;
331-
332-
MODEM.sendf("AT+USORD=%d,%d", _socket, size);
333-
if (MODEM.waitForResponse(10000, &response) != 1) {
334-
return 0;
335-
}
330+
int avail = available();
336331

337-
if (!response.startsWith("+USORD: ")) {
332+
if (avail == 0) {
338333
return 0;
339334
}
340335

341-
int firstQuoteIndex = response.indexOf("\"");
342-
343-
response.remove(0, firstQuoteIndex + 1);
344-
response.remove(response.length() - 1);
345-
346-
size = response.length() / 2;
347-
348-
for (size_t i = 0; i < size; i++) {
349-
byte n1 = response[i * 2];
350-
byte n2 = response[i * 2 + 1];
351-
352-
if (n1 > '9') {
353-
n1 = (n1 - 'A') + 10;
354-
} else {
355-
n1 = (n1 - '0');
356-
}
357-
358-
if (n2 > '9') {
359-
n2 = (n2 - 'A') + 10;
360-
} else {
361-
n2 = (n2 - '0');
362-
}
363-
364-
buf[i] = (n1 << 4) | n2;
365-
}
366-
367-
_available = 0;
368-
MODEM.poll();
369-
370-
return size;
336+
return GSMSocketBuffer.read(_socket, buf, size);
371337
}
372338

373339
int GSMClient::read()
374340
{
375341
byte b;
376342

377-
if (_peek != -1) {
378-
b = _peek;
379-
_peek = -1;
380-
return b;
381-
}
382-
383343
if (read(&b, 1) == 1) {
384344
return b;
385345
}
@@ -399,18 +359,24 @@ int GSMClient::available()
399359
return 0;
400360
}
401361

402-
MODEM.poll();
362+
int avail = GSMSocketBuffer.available(_socket);
403363

404-
return _available;
364+
if (avail < 0) {
365+
stop();
366+
367+
return 0;
368+
}
369+
370+
return avail;
405371
}
406372

407373
int GSMClient::peek()
408374
{
409-
if (_peek == -1) {
410-
_peek = read();
375+
if (available() > 0) {
376+
return GSMSocketBuffer.peek(_socket);
411377
}
412378

413-
return _peek;
379+
return -1;
414380
}
415381

416382
void GSMClient::flush()
@@ -426,6 +392,7 @@ void GSMClient::stop()
426392
MODEM.sendf("AT+USOCL=%d", _socket);
427393
MODEM.waitForResponse(10000);
428394

395+
GSMSocketBuffer.close(_socket);
429396
_socket = -1;
430397
}
431398

@@ -436,8 +403,8 @@ void GSMClient::handleUrc(const String& urc)
436403

437404
if (socket == _socket) {
438405
// this socket closed
406+
GSMSocketBuffer.close(_socket);
439407
_socket = -1;
440-
_available = 0;
441408
}
442409
} else if (urc.startsWith("+UUSORD: ")) {
443410
int socket = urc.charAt(9) - '0';
@@ -446,13 +413,8 @@ void GSMClient::handleUrc(const String& urc)
446413
if (urc.endsWith(",4294967295")) {
447414
// SSL disconnect
448415
// this socket closed
416+
GSMSocketBuffer.close(_socket);
449417
_socket = -1;
450-
_available = 0;
451-
} else {
452-
int commaIndex = urc.indexOf(',');
453-
if (commaIndex != -1) {
454-
_available = urc.substring(commaIndex + 1).toInt();
455-
}
456418
}
457419
}
458420
}

src/GSMClient.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,6 @@ class GSMClient : public Client, public ModemUrcHandler {
144144

145145
bool _writeSync;
146146
String _response;
147-
int _peek;
148-
int _available;
149147
};
150148

151149
#endif

src/utility/GSMSocketBuffer.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
This file is part of the MKR GSM library.
3+
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include <stdlib.h>
21+
#include <string.h>
22+
23+
#include "Modem.h"
24+
25+
#include "GSMSocketBuffer.h"
26+
27+
#define GSM_SOCKET_NUM_BUFFERS (sizeof(_buffers) / sizeof(_buffers[0]))
28+
29+
#define GSM_SOCKET_BUFFER_SIZE 512
30+
31+
GSMSocketBufferClass::GSMSocketBufferClass()
32+
{
33+
memset(&_buffers, 0x00, sizeof(_buffers));
34+
}
35+
36+
GSMSocketBufferClass::~GSMSocketBufferClass()
37+
{
38+
for (unsigned int i = 0; i < GSM_SOCKET_NUM_BUFFERS; i++) {
39+
close(i);
40+
}
41+
}
42+
43+
void GSMSocketBufferClass::close(int socket)
44+
{
45+
if (_buffers[socket].data) {
46+
free(_buffers[socket].data);
47+
_buffers[socket].data = _buffers[socket].head = NULL;
48+
_buffers[socket].length = 0;
49+
}
50+
}
51+
52+
int GSMSocketBufferClass::available(int socket)
53+
{
54+
if (_buffers[socket].length == 0) {
55+
if (_buffers[socket].data == NULL) {
56+
_buffers[socket].data = _buffers[socket].head = (uint8_t*)malloc(GSM_SOCKET_BUFFER_SIZE);
57+
_buffers[socket].length = 0;
58+
}
59+
60+
String response;
61+
62+
MODEM.sendf("AT+USORD=%d,%d", socket, GSM_SOCKET_BUFFER_SIZE);
63+
int status = MODEM.waitForResponse(10000, &response);
64+
if (status != 1) {
65+
return -1;
66+
}
67+
68+
if (!response.startsWith("+USORD: ")) {
69+
return 0;
70+
}
71+
72+
int firstQuoteIndex = response.indexOf("\"");
73+
74+
response.remove(0, firstQuoteIndex + 1);
75+
response.remove(response.length() - 1);
76+
77+
size_t size = response.length() / 2;
78+
79+
for (size_t i = 0; i < size; i++) {
80+
byte n1 = response[i * 2];
81+
byte n2 = response[i * 2 + 1];
82+
83+
if (n1 > '9') {
84+
n1 = (n1 - 'A') + 10;
85+
} else {
86+
n1 = (n1 - '0');
87+
}
88+
89+
if (n2 > '9') {
90+
n2 = (n2 - 'A') + 10;
91+
} else {
92+
n2 = (n2 - '0');
93+
}
94+
95+
_buffers[socket].data[i] = (n1 << 4) | n2;
96+
}
97+
98+
_buffers[socket].head = _buffers[socket].data;
99+
_buffers[socket].length = size;
100+
}
101+
102+
return _buffers[socket].length;
103+
}
104+
105+
int GSMSocketBufferClass::peek(int socket)
106+
{
107+
if (!available(socket)) {
108+
return -1;
109+
}
110+
111+
return *_buffers[socket].head;
112+
}
113+
114+
int GSMSocketBufferClass::read(int socket, uint8_t* data, size_t length)
115+
{
116+
int avail = available(socket);
117+
118+
if (!avail) {
119+
return 0;
120+
}
121+
122+
if (avail < (int)length) {
123+
length = avail;
124+
}
125+
126+
memcpy(data, _buffers[socket].head, length);
127+
_buffers[socket].head += length;
128+
_buffers[socket].length -= length;
129+
130+
return length;
131+
}
132+
133+
GSMSocketBufferClass GSMSocketBuffer;

src/utility/GSMSocketBuffer.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
This file is part of the MKR GSM library.
3+
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#ifndef _GSMSOCKET_BUFFER_H_INCLUDED
21+
#define _GSMSOCKET_BUFFER_H_INCLUDED
22+
23+
#include <stddef.h>
24+
#include <stdint.h>
25+
26+
class GSMSocketBufferClass {
27+
28+
public:
29+
public:
30+
GSMSocketBufferClass();
31+
virtual ~GSMSocketBufferClass();
32+
33+
void close(int socket);
34+
35+
int available(int socket);
36+
int peek(int socket);
37+
int read(int socket, uint8_t* data, size_t length);
38+
39+
private:
40+
struct {
41+
uint8_t* data;
42+
uint8_t* head;
43+
int length;
44+
} _buffers[7];
45+
};
46+
47+
extern GSMSocketBufferClass GSMSocketBuffer;
48+
49+
#endif

0 commit comments

Comments
 (0)