fix server sockets; use patched lwip

This commit is contained in:
Thorsten von Eicken 2015-12-10 20:58:41 -08:00
parent c115a78988
commit 1f562156ca
5 changed files with 73 additions and 16 deletions

View File

@ -1337,7 +1337,7 @@ ifeq ($(FAMILY),ESP8266)
DEFINES += -DUSE_OPTIMIZE_PRINTF
DEFINES += -D__ETS__ -DICACHE_FLASH -DXTENSA -DUSE_US_TIMER
ESP8266=1
LIBS += -lc -lgcc -lhal -lphy -lpp -lnet80211 -llwip_536 -lwpa -lmain -lpwm -lcrypto
LIBS += -lc -lgcc -lhal -lphy -lpp -lnet80211 -llwip -lwpa -lmain -lpwm -lcrypto
CFLAGS+= -fno-builtin \
-Wno-maybe-uninitialized -Wno-old-style-declaration -Wno-conversion -Wno-unused-variable \
-Wno-unused-parameter -Wno-ignored-qualifiers -Wno-discarded-qualifiers -Wno-float-conversion \

View File

@ -31,7 +31,7 @@ typedef long long int64_t;
#include "esp8266_board_utils.h"
#include "pktbuf.h"
#define espconn_abort espconn_disconnect
//#define espconn_abort espconn_disconnect
// Set NET_DBG to 0 to disable debug printf's, to 1 for important printf's
#define NET_DBG 1
@ -417,12 +417,14 @@ static void releaseEspconn(
struct socketData *pSocketData
) {
if (pSocketData->pEspconn == NULL) return;
if (pSocketData->creationType == SOCKET_CREATED_INBOUND) return; // we did not allocate it
DBG("%s: freeing espconn %p/%p for socket %d\n", DBG_LIB,
pSocketData->pEspconn, pSocketData->pEspconn->proto.tcp, pSocketData->socketId);
os_free(pSocketData->pEspconn->proto.tcp);
pSocketData->pEspconn->proto.tcp = NULL;
os_free(pSocketData->pEspconn);
// if the socket is an inbound connection then espconn will free the struct, else we do it now
if (pSocketData->creationType != SOCKET_CREATED_INBOUND) {
DBG("%s: freeing espconn %p/%p for socket %d\n", DBG_LIB,
pSocketData->pEspconn, pSocketData->pEspconn->proto.tcp, pSocketData->socketId);
os_free(pSocketData->pEspconn->proto.tcp);
pSocketData->pEspconn->proto.tcp = NULL;
os_free(pSocketData->pEspconn);
}
pSocketData->pEspconn = NULL;
}
@ -808,7 +810,7 @@ int net_ESP8266_BOARD_recv(
// if we now have exactly one buffer enqueued we need to re-enable the flood
if (pSocketData->rxBufQ != NULL && pSocketData->rxBufQ->next == NULL)
espconn_recv_unhold(pSocketData->pEspconn);
DBG("%s: recv %d on socket %d\n", DBG_LIB, retLen, sckt);
DBG("%s: socket %d JS recv %d\n", DBG_LIB, sckt, retLen);
return retLen;
}
@ -823,7 +825,7 @@ int net_ESP8266_BOARD_recv(
uint16_t newLen = rxBuf->filled - len;
os_memmove(rxBuf->data, rxBuf->data + len, newLen);
rxBuf->filled = newLen;
DBG("%s: recv %d on socket %d\n", DBG_LIB, len, sckt);
DBG("%s: socket %d JS recv %d\n", DBG_LIB, sckt, len);
return len;
}
@ -892,7 +894,7 @@ int net_ESP8266_BOARD_send(
}
pSocketData->state = SOCKET_STATE_TRANSMITTING;
DBG("%s: socket %d sending %d\n", DBG_LIB, sckt, len);
DBG("%s: socket %d JS send %d\n", DBG_LIB, sckt, len);
return len;
}
@ -1086,6 +1088,8 @@ static int connectSocket(
releaseSocket(pSocketData);
return rc;
}
DBG("%s: listening socket %d on port %d\n", DBG_LIB,
pSocketData->socketId, pEspconn->proto.tcp->local_port);
}
return newSocket;

View File

@ -0,0 +1,19 @@
// Espruino esp8266 Socket tester - Copyright 2015 by Thorsten von Eicken
// HTTP client test from tests/test_http_*.js
test_host = "h.voneicken.com";
test_port = 4567;
var result = 0;
var http = require("http");
http.get("http://"+test_host+":"+test_port+"/ping", function(res) {
console.log("Got response: " + JSON.stringify(res));
res.on('data', function(data) {
console.log(">" + data +"<");
result = data=="pong\nEND";
if (result) console.log("*** TEST SUCCESSFUL");
});
});//.on('error', function(e) {
// console.log("Got error: " + e.message);
//});*/

View File

@ -2,7 +2,7 @@
// Test error handling
test_host = "h.voneicken.com"; // <======= confirgure for your local server running the test_http.rb sinatra server
test_host = "h.voneicken.com"; // <======= configure for your local server running the test_http.rb sinatra server
test_port = 4567;
var test_ip = 0; // will be resolved

View File

@ -45,9 +45,12 @@
// Define the size of buffers/chunks that are transmitted or received
#ifdef ESP8266
#define CHUNK 536
#define CHUNK (536/2)
extern int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2)));
#define os_printf os_printf_plus
#else
#define CHUNK 64
#define os_printf(X) do { } while(0)
#endif
@ -291,12 +294,16 @@ bool socketServerConnectionsIdle(JsNetwork *net) {
int sckt = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
int error = 0;
if (!closeConnectionNow) {
int num = netRecv(net, sckt, buf,sizeof(buf));
if (num != 0) os_printf("netRecv on socket %d returned %d\n", sckt, num);
if (num<0) {
// we probably disconnected so just get rid of this
closeConnectionNow = true;
os_printf("Error from netRecv: %d\n", num);
error = num;
} else {
// add it to our request string
if (num>0) {
@ -334,15 +341,23 @@ bool socketServerConnectionsIdle(JsNetwork *net) {
JsVar *sendData = jsvObjectGetChild(socket,HTTP_NAME_SEND_DATA,0);
if (sendData) {
int sent = socketSendData(net, socket, sckt, &sendData);
// FIXME? checking for errors is a bit iffy. With the esp8266 network that returns
// varied error codes we'd want to skip SOCKET_ERR_CLOSED and let the recv side deal
// with normal closing so we don't miss the tail of what's received, but other drivers
// return -1 (which is the same value) for all errors. So we rely on the check ~12 lines
// down if(num>0)closeConnectionNow=false instead.
if (sent < 0) {
closeConnectionNow = true;
//error = sent;
os_printf("Error from netSend: %d\n", sent);
error = sent;
}
jsvObjectSetChild(socket, HTTP_NAME_SEND_DATA, sendData); // socketSendData prob updated sendData
}
// only close if we want to close, have no data to send, and aren't receiving data
if (jsvGetBoolAndUnLock(jsvObjectGetChild(socket,HTTP_NAME_CLOSE,0)) && !sendData && num<=0)
closeConnectionNow = true;
else if (num > 0)
closeConnectionNow = false; // guarantee that anything received is processed
jsvUnLock(sendData);
}
if (closeConnectionNow) {
@ -354,9 +369,25 @@ bool socketServerConnectionsIdle(JsNetwork *net) {
jswrap_stream_pushData(connection, receiveData, true);
}
jsvUnLock(receiveData);
// fire the error listeners
bool hadError = error < 0 && error != SOCKET_ERR_CLOSED;
JsVar *params[1];
if (hadError) {
params[0] = jsvNewWithFlags(JSV_OBJECT);
jsvObjectSetChildAndUnLock(params[0], "code", jsvNewFromInteger(error));
jsvObjectSetChildAndUnLock(params[0], "message",
jsvNewFromString(socketErrorString(error)));
jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_ERROR, params, 1);
jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_ERROR, params, 1);
jsvUnLock(params[0]);
}
// fire the close listeners
jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CLOSE, &connection, 1);
jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_CLOSE, &socket, 1);
params[0] = jsvNewFromBool(hadError);
jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CLOSE, params, 1);
jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_CLOSE, params, 1);
jsvUnLock(params[0]);
_socketConnectionKill(net, connection);
JsVar *connectionName = jsvObjectIteratorGetKey(&it);
@ -476,8 +507,10 @@ bool socketClientConnectionsIdle(JsNetwork *net) {
if (receiveData) { // could be out of memory
jsvAppendStringBuf(receiveData, buf, (size_t)num);
if ((socketType&ST_TYPE_MASK)==ST_HTTP && !hadHeaders) {
// for HTTP see whether we now have full response headers
JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
if (httpParseHeaders(&receiveData, resVar, false)) {
os_printf("Got http response headers\n");
hadHeaders = true;
jsvObjectSetChildAndUnLock(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders));
jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, &resVar, 1);
@ -494,6 +527,7 @@ bool socketClientConnectionsIdle(JsNetwork *net) {
}
if (closeConnectionNow) {
os_printf("Closing socket %d due to error %d\n", sckt, error);
socketClientPushReceiveData(connection, socket, &receiveData);
if (!receiveData) {
if ((socketType&ST_TYPE_MASK) != ST_HTTP)