-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
169 lines (145 loc) · 5.17 KB
/
server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include "espmissingincludes.h"
#include "c_types.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "osapi.h"
#include "server.h"
#include "config.h"
static struct espconn serverConn;
static esp_tcp serverTcp;
//Connection pool
static char txbuffer[MAX_CONN][MAX_TXBUFFER];
serverConnData tcpconnData[MAX_CONN];
static serverConnData ICACHE_FLASH_ATTR *serverFindConnData(void *arg) {
int i;
for (i=0; i<MAX_CONN; i++) {
if (tcpconnData[i].conn==(struct espconn *)arg)
return &tcpconnData[i];
}
//os_printf("FindConnData: Huh? Couldn't find connection for %p\n", arg);
return NULL; //WtF?
}
//send all data in conn->txbuffer
//returns result from espconn_sent if data in buffer or ESPCONN_OK (0)
//only internal used by espbuffsent, serverSentCb
static sint8 ICACHE_FLASH_ATTR sendtxbuffer(serverConnData *conn) {
sint8 result = ESPCONN_OK;
if (conn->txbufferlen != 0) {
conn->readytosend = false;
result= espconn_sent(conn->conn, (uint8_t*)conn->txbuffer, conn->txbufferlen);
conn->txbufferlen = 0;
if (result != ESPCONN_OK)
os_printf("sendtxbuffer: espconn_sent error %d on conn %p\n", result, conn);
}
return result;
}
//send formatted output to transmit buffer and call sendtxbuffer, if ready (previous espconn_sent is completed)
sint8 ICACHE_FLASH_ATTR espbuffsentprintf(serverConnData *conn, const char *format, ...) {
uint16 len;
va_list al;
va_start(al, format);
len = ets_vsnprintf(conn->txbuffer + conn->txbufferlen, MAX_TXBUFFER - conn->txbufferlen - 1, format, al);
va_end(al);
if (len <0) {
os_printf("espbuffsentprintf: txbuffer full on conn %p\n", conn);
return len;
}
conn->txbufferlen += len;
if (conn->readytosend)
return sendtxbuffer(conn);
return ESPCONN_OK;
}
//send string through espbuffsent
sint8 ICACHE_FLASH_ATTR espbuffsentstring(serverConnData *conn, const char *data) {
return espbuffsent(conn, data, strlen(data));
}
//use espbuffsent instead of espconn_sent
//It solve problem: the next espconn_sent must after espconn_sent_callback of the pre-packet.
//Add data to the send buffer and send if previous send was completed it call sendtxbuffer and espconn_sent
//Returns ESPCONN_OK (0) for success, -128 if buffer is full or error from espconn_sent
sint8 ICACHE_FLASH_ATTR espbuffsent(serverConnData *conn, const char *data, uint16 len) {
if (conn->txbufferlen + len > MAX_TXBUFFER) {
os_printf("espbuffsent: txbuffer full on conn %p\n", conn);
return -128;
}
os_memcpy(conn->txbuffer + conn->txbufferlen, data, len);
conn->txbufferlen += len;
if (conn->readytosend)
return sendtxbuffer(conn);
return ESPCONN_OK;
}
//callback after the data are sent
static void ICACHE_FLASH_ATTR serverSentCb(void *arg) {
serverConnData *conn = serverFindConnData(arg);
//os_printf("Sent callback on conn %p\n", conn);
if (conn==NULL) return;
conn->readytosend = true;
sendtxbuffer(conn); // send possible new data in txbuffer
}
static void ICACHE_FLASH_ATTR serverRecvCb(void *arg, char *data, unsigned short len) {
int x;
char *p, *e;
serverConnData *conn = serverFindConnData(arg);
//os_printf("Receive callback on conn %p\n", conn);
if (conn == NULL) return;
if (len >= 2 && data[0] == 'A' && data[1] == 'T') {
config_parse(conn, data, len);
}
}
static void ICACHE_FLASH_ATTR serverReconCb(void *arg, sint8 err) {
serverConnData *conn=serverFindConnData(arg);
// os_printf("server.c - serverRecnCb - on conn %p\n", conn);
if (conn==NULL) return;
//Yeah... No idea what to do here. ToDo: figure something out.
}
static void ICACHE_FLASH_ATTR serverDisconCb(void *arg) {
serverConnData *conn=serverFindConnData(arg);
// os_printf("server.c - serverDisconCb - on conn %p\n", conn);
//Just look at all the sockets and kill the slot if needed.
int i;
for (i=0; i<MAX_CONN; i++) {
if (tcpconnData[i].conn!=NULL) {
// os_printf(" udpconnData[i].conn->state conn %p\n", udpconnData[i].conn->state);
if (tcpconnData[i].conn->state==ESPCONN_NONE || tcpconnData[i].conn->state==ESPCONN_CLOSE) {
tcpconnData[i].conn=NULL;
}
}
}
}
static void ICACHE_FLASH_ATTR serverConnectCb(void *arg) {
struct espconn *conn = arg;
int i;
//Find empty conndata in pool
for (i=0; i<MAX_CONN; i++) if (tcpconnData[i].conn==NULL) break;
os_printf("Con req, conn=%p, pool slot %d\n", conn, i);
if (i==MAX_CONN) {
os_printf("Aiee, conn pool overflow!\n");
espconn_disconnect(conn);
return;
}
tcpconnData[i].conn=conn;
tcpconnData[i].txbufferlen = 0;
tcpconnData[i].readytosend = true;
espconn_regist_recvcb(conn, serverRecvCb);
espconn_regist_reconcb(conn, serverReconCb);
espconn_regist_disconcb(conn, serverDisconCb);
espconn_regist_sentcb(conn, serverSentCb);
}
void ICACHE_FLASH_ATTR serverInit(int port) {
int i;
for (i = 0; i < MAX_CONN; i++) {
tcpconnData[i].conn = NULL;
tcpconnData[i].txbuffer = txbuffer[i];
tcpconnData[i].txbufferlen = 0;
tcpconnData[i].readytosend = true;
}
serverConn.type=ESPCONN_TCP;
serverConn.state=ESPCONN_NONE;
serverTcp.local_port=port;
serverConn.proto.tcp=&serverTcp;
espconn_regist_connectcb(&serverConn, serverConnectCb);
espconn_accept(&serverConn);
espconn_regist_time(&serverConn, SERVER_TIMEOUT, 0);
espconn_tcp_set_max_con_allow(&serverConn, 1); //Allow 1 connection max
}