1+ /*
2+ * Copyright (c) 2018 https://www.thecoderscorner.com (Nutricherry LTD).
3+ * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4+ */
5+
6+ /* *
7+ * Ethernet remote capability plugin. This file is a plugin file and should not be directly edited,
8+ * it will be replaced each time the project is built. If you want to edit this file in place,
9+ * make sure to rename it first.
10+ */
11+
12+
13+ #include " MBedEthernetTransport.h"
14+
15+ MBedEthernetTransport::~MBedEthernetTransport () {
16+ serdebugF (" destroy socket" );
17+ if (socket) {
18+ socket->close ();
19+ }
20+ }
21+
22+ void MBedEthernetTransport::flush () {
23+ if (writePos == 0 || socket == nullptr ) return ;
24+
25+ int written = socket->send (writeBuf, writePos);
26+ if (written == NSAPI_ERROR_WOULD_BLOCK) return ;
27+ if (written > 0 ) {
28+ int left = writePos - written;
29+ if (left > 0 ) {
30+ memmove (writeBuf, &writeBuf[written], left);
31+ writePos = left;
32+ }
33+ else writePos = 0 ;
34+ }
35+ else {
36+ close ();
37+ }
38+ }
39+
40+ int MBedEthernetTransport::writeChar (char data) {
41+ if (writePos >= sizeof (writeBuf)) {
42+ flush ();
43+ }
44+ if (writePos < sizeof (writeBuf)) {
45+ writeBuf[writePos] = data;
46+ writePos++;
47+ return 1 ;
48+ }
49+ else return 0 ;
50+ }
51+
52+ int MBedEthernetTransport::writeStr (const char *data) {
53+ int len = strlen (data);
54+ for (int i=0 ; i<len; i++) {
55+ if (writeChar (data[i]) == 0 ) return 0 ;
56+ }
57+ return len;
58+ }
59+
60+ uint8_t MBedEthernetTransport::readByte () {
61+ return (readAvailable ()) ? readBuf[readPos++] : -1 ;
62+ }
63+
64+ bool MBedEthernetTransport::readAvailable () {
65+ if (socket == nullptr ) return false ;
66+
67+ if (readPos >= lastReadAmt) {
68+
69+ int amt = socket->recv (readBuf, sizeof (readBuf));
70+ if (amt == NSAPI_ERROR_WOULD_BLOCK) return false ;
71+ if (amt > 0 ) {
72+ readPos = 0 ;
73+ lastReadAmt = amt;
74+ return true ;
75+ }
76+ else {
77+ close ();
78+ lastReadAmt =0 ;
79+ readPos = 0 ;
80+ return false ;
81+ }
82+ } else return true ;
83+ }
84+
85+ bool MBedEthernetTransport::available () {
86+ if (socket == nullptr ) return false ;
87+
88+ if (readPos >= sizeof (writeBuf)) {
89+ flush ();
90+ }
91+ return (readPos < sizeof (writeBuf));
92+ }
93+
94+ void MBedEthernetTransport::close () {
95+ if (socket == nullptr ) return ;
96+ serdebugF (" closing socket" );
97+
98+ isOpen = false ;
99+ socket->close ();
100+ // socket is now a dangling pointer and must be cleared
101+ socket = nullptr ;
102+ }
103+
104+ void MBedEthernetTransport::endMsg () {
105+ TagValueTransport::endMsg ();
106+ flush ();
107+ }
108+
109+ // ----------------- Ethernet Remote Server --------------
110+
111+ EthernetTagValServer remoteServer;
112+
113+ void EthernetTagValServer::begin (int bindingPort, const ConnectorLocalInfo* localInfo) {
114+ if (defNetwork == NULL ) {
115+ serdebugF (" No network interface found, not initialising network" );
116+ return ;
117+ }
118+ listenPort = bindingPort;
119+
120+ connector.initialise (&transport, &messageProcessor, localInfo);
121+
122+ defNetwork->set_blocking (false );
123+ server.set_blocking (false );
124+
125+ // this is the message ticker
126+ taskManager.scheduleOnce (TICK_INTERVAL, this , TIME_MILLIS);
127+ // this does some very basic caching of messages to try and group them up on the wire
128+ }
129+
130+ void EthernetTagValServer::exec () {
131+ if (!boundToAddr) {
132+ if (defNetwork->connect () != NSAPI_ERROR_IS_CONNECTED) {
133+ taskManager.scheduleOnce (250 , this );
134+ return ;
135+ }
136+
137+ serdebugF (" Connected to network " );
138+ if (server.open (defNetwork) != 0 ) {
139+ serdebugF (" Could not open socket" );
140+ taskManager.scheduleOnce (1 ,this , TIME_SECONDS);
141+ return ;
142+ }
143+ if (server.bind (listenPort) != 0 || server.listen (1 ) != 0 ) {
144+ serdebugF2 (" Could not bind to " , listenPort);
145+ taskManager.scheduleOnce (1 , this , TIME_SECONDS);
146+ return ;
147+ }
148+ boundToAddr = true ;
149+
150+ taskManager.scheduleFixedRate (TICK_INTERVAL, this , TIME_MILLIS);
151+ // secondly we provide a low speed writer task that just flushes the buffer a five times a second.
152+ taskManager.scheduleFixedRate (WRITE_DELAY, &transport, TIME_MILLIS);
153+
154+ serdebugF2 (" Listen fully bound to " , listenPort);
155+
156+ return ;
157+ }
158+ if (!transport.connected ()) {
159+ nsapi_error_t acceptErr;
160+ auto tcpSock = server.accept (&acceptErr);
161+ if (acceptErr == NSAPI_ERROR_OK) {
162+ serdebugF (" Client found" );
163+ transport.setSocket (tcpSock);
164+ }
165+ else if (acceptErr != NSAPI_ERROR_WOULD_BLOCK) {
166+ serdebugF2 (" Error code " , acceptErr);
167+ }
168+ }
169+ else {
170+ connector.tick ();
171+ }
172+ }
0 commit comments