1
1
#include " Devices/EthernetServer_TC.h"
2
2
3
+ #include < avr/wdt.h>
4
+
5
+ #include " DateTime_TC.h"
6
+ #include " SD_TC.h"
3
7
#include " Serial_TC.h"
8
+ #include " TankControllerLib.h"
4
9
5
10
// class variables
6
11
EthernetServer_TC* EthernetServer_TC::_instance = nullptr ;
@@ -22,24 +27,164 @@ EthernetServer_TC* EthernetServer_TC::instance() {
22
27
*/
23
28
EthernetServer_TC::EthernetServer_TC (uint16_t port) : EthernetServer(port) {
24
29
begin ();
25
- serial (F (" Ethernet Server is listening on port 80 of ?????? " ));
30
+ serial (F (" Ethernet Server is listening on port 80" ));
26
31
}
27
32
28
- /* *
29
- * Look for request from external client and handle it.
30
- * This (incomplete) code copied from HandleRequest()
31
- */
32
- void EthernetServer_TC::handleRequest () {
33
- // listen for incoming clients
34
- EthernetClient rpc_client = available (); // Raspberry Pi Client
35
- if (rpc_client) {
36
- // TODO: NEED TO IMPLEMENT
37
- // HandleRequest(rpc_client);
38
-
39
- // give the web browser time to receive the data
40
- // delay(ONE_SECOND_DELAY_IN_MILLIS);
41
- // close the connection:
42
- rpc_client.stop ();
43
- serial (F (" rpc_client disconnected" ));
33
+ void EthernetServer_TC::echo () {
34
+ serial (F (" echo() - \" %s\" " ), buffer + 19 );
35
+ int i = 19 ;
36
+ while (buffer[i] != ' ' && buffer[i] != ' \0 ' ) {
37
+ ++i;
38
+ }
39
+ serial (F (" echo() found space or null at %d" ), i);
40
+ if (memcmp_P (buffer + i - 3 , F (" %22" ), 3 )) {
41
+ serial (F (" bad" ));
42
+ } else {
43
+ buffer[i - 3 ] = ' \0 ' ;
44
+ serial (F (" echo \" %s\" " ), buffer + 19 );
45
+ sendHeadersWithSize (strnlen (buffer + 19 , sizeof (buffer) - 20 ));
46
+ client.write (buffer + 19 );
47
+ client.stop ();
48
+ state = NOT_CONNECTED;
49
+ }
50
+ }
51
+
52
+ bool EthernetServer_TC::file () {
53
+ // Buffer has something like "GET /path HTTP/1.1"
54
+ // and we want to put a null at the end of the path.
55
+ int i = 4 ;
56
+ while (buffer[i] != ' ' ) {
57
+ ++i;
58
+ }
59
+ buffer[i] = ' \0 ' ;
60
+ // Look for file in SD card.
61
+ if (!SD_TC::instance ()->exists (buffer + 4 )) {
62
+ serial (F (" file - \" %s\" not found!" ), buffer + 4 );
63
+ return false ;
64
+ }
65
+ // Open file and send headers with file size.
66
+ File file = SD_TC::instance ()->open (buffer + 4 );
67
+ uint32_t size = file.size ();
68
+ serial (F (" file \" %s\" has a size of %lu" ), buffer + 4 , size);
69
+ sendHeadersWithSize (size);
70
+ // Send file contents
71
+ uint32_t totalBytes = 0 ;
72
+ uint32_t timeInRead = 0 ;
73
+ uint32_t timeInWrite = 0 ;
74
+ uint32_t timeInFlush = 0 ;
75
+
76
+ wdt_disable ();
77
+ uint32_t flushCount = 0 ;
78
+ while (file.available32 ()) {
79
+ uint32_t startTime = millis ();
80
+ int readSize = file.read (buffer, sizeof (buffer)); // Flawfinder: ignore
81
+ timeInRead += millis () - startTime;
82
+ startTime = millis ();
83
+ int writeSize = client.write (buffer, readSize);
84
+ timeInWrite += millis () - startTime;
85
+ if (writeSize != readSize) {
86
+ serial (F (" totalBytes = %lu; read = %d; write = %d" ), totalBytes, readSize, writeSize);
87
+ break ;
88
+ }
89
+ totalBytes += writeSize;
90
+ if (totalBytes % 8196 == 0 ) {
91
+ startTime = millis ();
92
+ client.flush ();
93
+ timeInFlush += millis () - startTime;
94
+ ++flushCount;
95
+ }
96
+ }
97
+ file.close ();
98
+ client.stop ();
99
+ state = NOT_CONNECTED;
100
+ serial (F (" write = %lu; freeMemory = %i" ), totalBytes, TankControllerLib::instance ()->freeMemory ());
101
+ serial (F (" timeInRead = %lu; timeInWrite = %lu; timeInFlush = %lu" ), timeInRead, timeInWrite, timeInFlush);
102
+ wdt_enable (WDTO_8S);
103
+ return true ;
104
+ }
105
+
106
+ void EthernetServer_TC::get () {
107
+ if (memcmp_P (buffer + 4 , F (" /echo?value=%22" ), 15 ) == 0 ) {
108
+ echo ();
109
+ } else if (!file ()) {
110
+ // TODO: send an error response
111
+ serial (F (" get \" %s\" not recognized!" ), buffer + 4 );
112
+ client.stop ();
113
+ state = NOT_CONNECTED;
114
+ }
115
+ }
116
+
117
+ void EthernetServer_TC::loop () {
118
+ if (client || (client = accept ())) { // if we have a connection
119
+ if (state == NOT_CONNECTED) {
120
+ state = READ_REQUEST;
121
+ bufferContentsSize = 0 ;
122
+ connectedAt = millis (); // record start time (so we can do timeout)
123
+ }
124
+ // read request
125
+ int next;
126
+ while (state == READ_REQUEST && bufferContentsSize < sizeof (buffer) &&
127
+ (next = client.read ()) != -1 ) { // Flawfinder: ignore
128
+ buffer[bufferContentsSize++] = (char )(next & 0xFF );
129
+ if (bufferContentsSize > 1 && buffer[bufferContentsSize - 2 ] == ' \r ' && buffer[bufferContentsSize - 1 ] == ' \n ' ) {
130
+ buffer[bufferContentsSize - 2 ] = ' \0 ' ;
131
+ state = HAS_REQUEST;
132
+ if (memcmp_P (buffer, F (" GET " ), 4 ) == 0 ) {
133
+ state = GET_REQUEST;
134
+ break ;
135
+ }
136
+ break ;
137
+ }
138
+ }
139
+ switch (state) {
140
+ case GET_REQUEST:
141
+ get ();
142
+ break ;
143
+ default :
144
+ break ;
145
+ }
146
+ } else if (state != NOT_CONNECTED) { // existing connection has been closed
147
+ state = NOT_CONNECTED;
148
+ bufferContentsSize = 0 ;
149
+ client.stop ();
150
+ connectedAt = 0 ;
151
+ } else {
152
+ // no client and not recently connected
44
153
}
45
154
}
155
+
156
+ void EthernetServer_TC::sendHeadersWithSize (uint32_t size) {
157
+ char buffer[128 ];
158
+ static const char response[] PROGMEM =
159
+ " HTTP/1.1 200 OK\r\n "
160
+ " Content-Type: text/plain;charset=UTF-8\r\n "
161
+ " Content-Encoding: identity\r\n "
162
+ " Content-Language: en-US\r\n " ;
163
+ strncpy_P (buffer, (PGM_P)response, sizeof (buffer));
164
+ client.write (buffer);
165
+ snprintf_P (buffer, sizeof (buffer), (PGM_P)F (" Content-Length: %lu\r\n " ), (unsigned long )size);
166
+ client.write (buffer);
167
+
168
+ // TODO: add "Date: " header
169
+ // const __FlashStringHelper* weekdays[] = {F("Sun"), F("Mon"), F("Tue"), F("Wed"), F("Thu"), F("Fri"), F("Sat")};
170
+ // const __FlashStringHelper* months[] = {F("Jan"), F("Feb"), F("Mar"), F("Apr"), F("May"), F("Jun"),
171
+ // F("Jul"), F("Aug"), F("Sep"), F("Oct"), F("Nov"), F("Dec")};
172
+ // DateTime_TC now = DateTime_TC::now();
173
+ // int weekday = weekday(now.getYear(), now.getMonth(), now.getDay());
174
+ // snprintf_P(buffer, sizeof(buffer), F("Date: %s, %02d %s %04d %02d:%02d:%02d GMT\r\n"), );
175
+
176
+ // blank line indicates end of headers
177
+ client.write (' \r ' );
178
+ client.write (' \n ' );
179
+ }
180
+
181
+ int EthernetServer_TC::weekday (int year, int month, int day) {
182
+ // Calculate day of week in proleptic Gregorian calendar. Sunday == 0.
183
+ int adjustment, mm, yy;
184
+ if (year < 2000 )
185
+ year += 2000 ;
186
+ adjustment = (14 - month) / 12 ;
187
+ mm = month + 12 * adjustment - 2 ;
188
+ yy = year - adjustment;
189
+ return (day + (13 * mm - 1 ) / 5 + yy + yy / 4 - yy / 100 + yy / 400 ) % 7 ;
190
+ }
0 commit comments