User | Revision | Line number | New contents of line |
mbed714 |
0:d616ece2d859
|
1
|
|
mbed714 |
0:d616ece2d859
|
2
|
/*
|
mbed714 |
0:d616ece2d859
|
3
|
Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
|
mbed714 |
0:d616ece2d859
|
4
|
|
mbed714 |
0:d616ece2d859
|
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
mbed714 |
0:d616ece2d859
|
6
|
of this software and associated documentation files (the "Software"), to deal
|
mbed714 |
0:d616ece2d859
|
7
|
in the Software without restriction, including without limitation the rights
|
mbed714 |
0:d616ece2d859
|
8
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
mbed714 |
0:d616ece2d859
|
9
|
copies of the Software, and to permit persons to whom the Software is
|
mbed714 |
0:d616ece2d859
|
10
|
furnished to do so, subject to the following conditions:
|
mbed714 |
0:d616ece2d859
|
11
|
|
mbed714 |
0:d616ece2d859
|
12
|
The above copyright notice and this permission notice shall be included in
|
mbed714 |
0:d616ece2d859
|
13
|
all copies or substantial portions of the Software.
|
mbed714 |
0:d616ece2d859
|
14
|
|
mbed714 |
0:d616ece2d859
|
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
mbed714 |
0:d616ece2d859
|
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
mbed714 |
0:d616ece2d859
|
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
mbed714 |
0:d616ece2d859
|
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
mbed714 |
0:d616ece2d859
|
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
mbed714 |
0:d616ece2d859
|
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
mbed714 |
0:d616ece2d859
|
21
|
THE SOFTWARE.
|
mbed714 |
0:d616ece2d859
|
22
|
*/
|
mbed714 |
0:d616ece2d859
|
23
|
|
mbed714 |
0:d616ece2d859
|
24
|
#include "lwipNetTcpSocket.h"
|
mbed714 |
0:d616ece2d859
|
25
|
#include "lwip/tcp.h"
|
mbed714 |
0:d616ece2d859
|
26
|
|
mbed714 |
0:d616ece2d859
|
27
|
//#define __DEBUG
|
mbed714 |
0:d616ece2d859
|
28
|
#include "dbg/dbg.h"
|
mbed714 |
0:d616ece2d859
|
29
|
|
mbed714 |
0:d616ece2d859
|
30
|
#include "netCfg.h"
|
mbed714 |
0:d616ece2d859
|
31
|
#if NET_LWIP_STACK
|
mbed714 |
0:d616ece2d859
|
32
|
|
mbed714 |
0:d616ece2d859
|
33
|
LwipNetTcpSocket::LwipNetTcpSocket(tcp_pcb* pPcb /*= NULL*/) : NetTcpSocket(), m_pPcb(pPcb), m_lpInNetTcpSocket(), //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
|
mbed714 |
0:d616ece2d859
|
34
|
m_pReadPbuf(NULL)
|
mbed714 |
0:d616ece2d859
|
35
|
{
|
mbed714 |
0:d616ece2d859
|
36
|
DBG("New NetTcpSocket %p\n", (void*)this);
|
mbed714 |
0:d616ece2d859
|
37
|
if(!m_pPcb)
|
mbed714 |
0:d616ece2d859
|
38
|
{
|
mbed714 |
0:d616ece2d859
|
39
|
m_pPcb = tcp_new();
|
mbed714 |
0:d616ece2d859
|
40
|
DBG("Creating new PCB %p\n", m_pPcb);
|
mbed714 |
0:d616ece2d859
|
41
|
}
|
mbed714 |
0:d616ece2d859
|
42
|
if(m_pPcb)
|
mbed714 |
0:d616ece2d859
|
43
|
{
|
mbed714 |
0:d616ece2d859
|
44
|
//Setup callbacks
|
mbed714 |
0:d616ece2d859
|
45
|
tcp_arg( (tcp_pcb*) m_pPcb, (void*) this ); //this will be passed to each static callback
|
mbed714 |
0:d616ece2d859
|
46
|
|
mbed714 |
0:d616ece2d859
|
47
|
tcp_recv( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sRecvCb );
|
mbed714 |
0:d616ece2d859
|
48
|
tcp_sent((tcp_pcb*) m_pPcb, LwipNetTcpSocket::sSentCb );
|
mbed714 |
0:d616ece2d859
|
49
|
tcp_err( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sErrCb );
|
mbed714 |
0:d616ece2d859
|
50
|
//Connected callback is defined in connect()
|
mbed714 |
0:d616ece2d859
|
51
|
//Accept callback is defined in listen()
|
mbed714 |
0:d616ece2d859
|
52
|
DBG("NetTcpSocket created.\n");
|
mbed714 |
0:d616ece2d859
|
53
|
}
|
mbed714 |
0:d616ece2d859
|
54
|
}
|
mbed714 |
0:d616ece2d859
|
55
|
|
mbed714 |
0:d616ece2d859
|
56
|
LwipNetTcpSocket::~LwipNetTcpSocket()
|
mbed714 |
0:d616ece2d859
|
57
|
{
|
mbed714 |
0:d616ece2d859
|
58
|
/* if(m_pPcb)
|
mbed714 |
0:d616ece2d859
|
59
|
tcp_close( (tcp_pcb*) m_pPcb); //Disconnect & free pcb*/
|
mbed714 |
0:d616ece2d859
|
60
|
close();
|
mbed714 |
0:d616ece2d859
|
61
|
}
|
mbed714 |
0:d616ece2d859
|
62
|
|
mbed714 |
0:d616ece2d859
|
63
|
NetTcpSocketErr LwipNetTcpSocket::bind(const Host& me)
|
mbed714 |
0:d616ece2d859
|
64
|
{
|
mbed714 |
0:d616ece2d859
|
65
|
if(!m_pPcb)
|
mbed714 |
0:d616ece2d859
|
66
|
return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry
|
mbed714 |
0:d616ece2d859
|
67
|
|
mbed714 |
0:d616ece2d859
|
68
|
err_t err = tcp_bind( (tcp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
|
mbed714 |
0:d616ece2d859
|
69
|
if(err)
|
mbed714 |
0:d616ece2d859
|
70
|
return NETTCPSOCKET_INUSE;
|
mbed714 |
0:d616ece2d859
|
71
|
|
mbed714 |
0:d616ece2d859
|
72
|
return NETTCPSOCKET_OK;
|
mbed714 |
0:d616ece2d859
|
73
|
}
|
mbed714 |
0:d616ece2d859
|
74
|
|
mbed714 |
0:d616ece2d859
|
75
|
NetTcpSocketErr LwipNetTcpSocket::listen()
|
mbed714 |
0:d616ece2d859
|
76
|
{
|
mbed714 |
0:d616ece2d859
|
77
|
if(!m_pPcb)
|
mbed714 |
0:d616ece2d859
|
78
|
return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry
|
mbed714 |
0:d616ece2d859
|
79
|
/*
|
mbed714 |
0:d616ece2d859
|
80
|
From doc/rawapi.txt :
|
mbed714 |
0:d616ece2d859
|
81
|
|
mbed714 |
0:d616ece2d859
|
82
|
The tcp_listen() function returns a new connection identifier, and
|
mbed714 |
0:d616ece2d859
|
83
|
the one passed as an argument to the function will be
|
mbed714 |
0:d616ece2d859
|
84
|
deallocated. The reason for this behavior is that less memory is
|
mbed714 |
0:d616ece2d859
|
85
|
needed for a connection that is listening, so tcp_listen() will
|
mbed714 |
0:d616ece2d859
|
86
|
reclaim the memory needed for the original connection and allocate a
|
mbed714 |
0:d616ece2d859
|
87
|
new smaller memory block for the listening connection.
|
mbed714 |
0:d616ece2d859
|
88
|
*/
|
mbed714 |
0:d616ece2d859
|
89
|
|
mbed714 |
0:d616ece2d859
|
90
|
// tcp_pcb* pNewPcb = tcp_listen(m_pPcb);
|
mbed714 |
0:d616ece2d859
|
91
|
tcp_pcb* pNewPcb = tcp_listen_with_backlog((tcp_pcb*)m_pPcb, 5);
|
mbed714 |
0:d616ece2d859
|
92
|
if( !pNewPcb ) //Not enough memory to create the listening pcb
|
mbed714 |
0:d616ece2d859
|
93
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
94
|
|
mbed714 |
0:d616ece2d859
|
95
|
m_pPcb = pNewPcb;
|
mbed714 |
0:d616ece2d859
|
96
|
|
mbed714 |
0:d616ece2d859
|
97
|
tcp_accept( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sAcceptCb );
|
mbed714 |
0:d616ece2d859
|
98
|
|
mbed714 |
0:d616ece2d859
|
99
|
return NETTCPSOCKET_OK;
|
mbed714 |
0:d616ece2d859
|
100
|
}
|
mbed714 |
0:d616ece2d859
|
101
|
|
mbed714 |
0:d616ece2d859
|
102
|
NetTcpSocketErr LwipNetTcpSocket::connect(const Host& host)
|
mbed714 |
0:d616ece2d859
|
103
|
{
|
mbed714 |
0:d616ece2d859
|
104
|
if(!m_pPcb)
|
mbed714 |
0:d616ece2d859
|
105
|
return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry
|
mbed714 |
0:d616ece2d859
|
106
|
|
mbed714 |
0:d616ece2d859
|
107
|
ip_addr_t ip = host.getIp().getStruct();
|
mbed714 |
0:d616ece2d859
|
108
|
err_t err = tcp_connect( (tcp_pcb*) m_pPcb, &ip, host.getPort(), LwipNetTcpSocket::sConnectedCb );
|
mbed714 |
0:d616ece2d859
|
109
|
|
mbed714 |
0:d616ece2d859
|
110
|
if(err)
|
mbed714 |
0:d616ece2d859
|
111
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
112
|
|
mbed714 |
0:d616ece2d859
|
113
|
return NETTCPSOCKET_OK;
|
mbed714 |
0:d616ece2d859
|
114
|
}
|
mbed714 |
0:d616ece2d859
|
115
|
|
mbed714 |
0:d616ece2d859
|
116
|
NetTcpSocketErr LwipNetTcpSocket::accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket)
|
mbed714 |
0:d616ece2d859
|
117
|
{
|
mbed714 |
0:d616ece2d859
|
118
|
if( !m_pPcb ) //Pcb doesn't exist (anymore)
|
mbed714 |
0:d616ece2d859
|
119
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
120
|
//Dequeue a connection
|
mbed714 |
0:d616ece2d859
|
121
|
//if( m_lpInPcb.empty() )
|
mbed714 |
0:d616ece2d859
|
122
|
if( m_lpInNetTcpSocket.empty() )
|
mbed714 |
0:d616ece2d859
|
123
|
return NETTCPSOCKET_EMPTY;
|
mbed714 |
0:d616ece2d859
|
124
|
|
mbed714 |
0:d616ece2d859
|
125
|
tcp_accepted( ((tcp_pcb*) m_pPcb) ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb)
|
mbed714 |
0:d616ece2d859
|
126
|
|
mbed714 |
0:d616ece2d859
|
127
|
/* tcp_pcb* pInPcb = m_lpInPcb.front();
|
mbed714 |
0:d616ece2d859
|
128
|
m_lpInPcb.pop();*/
|
mbed714 |
0:d616ece2d859
|
129
|
|
mbed714 |
0:d616ece2d859
|
130
|
if( (m_lpInNetTcpSocket.front()) == NULL )
|
mbed714 |
0:d616ece2d859
|
131
|
{
|
mbed714 |
0:d616ece2d859
|
132
|
m_lpInNetTcpSocket.pop();
|
mbed714 |
0:d616ece2d859
|
133
|
return NETTCPSOCKET_RST;
|
mbed714 |
0:d616ece2d859
|
134
|
}
|
mbed714 |
0:d616ece2d859
|
135
|
|
mbed714 |
0:d616ece2d859
|
136
|
if( (m_lpInNetTcpSocket.front())->m_closed )
|
mbed714 |
0:d616ece2d859
|
137
|
{
|
mbed714 |
0:d616ece2d859
|
138
|
Net::releaseTcpSocket(m_lpInNetTcpSocket.front());
|
mbed714 |
0:d616ece2d859
|
139
|
m_lpInNetTcpSocket.pop();
|
mbed714 |
0:d616ece2d859
|
140
|
return NETTCPSOCKET_RST;
|
mbed714 |
0:d616ece2d859
|
141
|
}
|
mbed714 |
0:d616ece2d859
|
142
|
|
mbed714 |
0:d616ece2d859
|
143
|
ip_addr_t* ip = (ip_addr_t*) &( (m_lpInNetTcpSocket.front()->m_pPcb)->remote_ip);
|
mbed714 |
0:d616ece2d859
|
144
|
|
mbed714 |
0:d616ece2d859
|
145
|
*ppNewNetTcpSocket = m_lpInNetTcpSocket.front();
|
mbed714 |
0:d616ece2d859
|
146
|
*pClient = Host(
|
mbed714 |
0:d616ece2d859
|
147
|
IpAddr(
|
mbed714 |
0:d616ece2d859
|
148
|
ip
|
mbed714 |
0:d616ece2d859
|
149
|
),
|
mbed714 |
0:d616ece2d859
|
150
|
m_lpInNetTcpSocket.front()->m_pPcb->remote_port
|
mbed714 |
0:d616ece2d859
|
151
|
);
|
mbed714 |
0:d616ece2d859
|
152
|
m_lpInNetTcpSocket.pop();
|
mbed714 |
0:d616ece2d859
|
153
|
// *pClient = Host( IpAddr(pInPcb->remote_ip), pInPcb->remote_port );
|
mbed714 |
0:d616ece2d859
|
154
|
|
mbed714 |
0:d616ece2d859
|
155
|
//Return a new socket
|
mbed714 |
0:d616ece2d859
|
156
|
// *ppNewNetTcpSocket = (NetTcpSocket*) new LwipNetTcpSocket(pInPcb);
|
mbed714 |
0:d616ece2d859
|
157
|
|
mbed714 |
0:d616ece2d859
|
158
|
//tcp_accepted( ((tcp_pcb*) m_pPcb) ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb)
|
mbed714 |
0:d616ece2d859
|
159
|
|
mbed714 |
0:d616ece2d859
|
160
|
/* if(*ppNewNetTcpSocket == NULL)
|
mbed714 |
0:d616ece2d859
|
161
|
{
|
mbed714 |
0:d616ece2d859
|
162
|
DBG("Not enough mem, socket dropped in LwipNetTcpSocket::accept.\n");
|
mbed714 |
0:d616ece2d859
|
163
|
tcp_abort(pInPcb);
|
mbed714 |
0:d616ece2d859
|
164
|
}*/
|
mbed714 |
0:d616ece2d859
|
165
|
|
mbed714 |
0:d616ece2d859
|
166
|
return NETTCPSOCKET_OK;
|
mbed714 |
0:d616ece2d859
|
167
|
}
|
mbed714 |
0:d616ece2d859
|
168
|
|
mbed714 |
0:d616ece2d859
|
169
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
mbed714 |
0:d616ece2d859
|
170
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
mbed714 |
0:d616ece2d859
|
171
|
|
mbed714 |
0:d616ece2d859
|
172
|
int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::send(const char* buf, int len)
|
mbed714 |
0:d616ece2d859
|
173
|
{
|
mbed714 |
0:d616ece2d859
|
174
|
if( !m_pPcb ) //Pcb doesn't exist (anymore)
|
mbed714 |
0:d616ece2d859
|
175
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
176
|
int outLen = MIN( len, tcp_sndbuf( (tcp_pcb*) m_pPcb) );
|
mbed714 |
0:d616ece2d859
|
177
|
//tcp_sndbuf() returns the number of bytes available in the output queue, so never go above it
|
mbed714 |
0:d616ece2d859
|
178
|
err_t err = tcp_write( (tcp_pcb*) m_pPcb, (void*) buf, outLen, TCP_WRITE_FLAG_COPY );
|
mbed714 |
0:d616ece2d859
|
179
|
//Flags are TCP_WRITE_FLAG_COPY & TCP_WRITE_FLAG_MORE (see tcp_out.c) :
|
mbed714 |
0:d616ece2d859
|
180
|
//If TCP_WRITE_FLAG_MORE is not set ask client to push buffered data to app
|
mbed714 |
0:d616ece2d859
|
181
|
if(err)
|
mbed714 |
0:d616ece2d859
|
182
|
{
|
mbed714 |
0:d616ece2d859
|
183
|
switch( err )
|
mbed714 |
0:d616ece2d859
|
184
|
{
|
mbed714 |
0:d616ece2d859
|
185
|
case ERR_CONN:
|
mbed714 |
0:d616ece2d859
|
186
|
return (int) NETTCPSOCKET_SETUP; //Not connected properly
|
mbed714 |
0:d616ece2d859
|
187
|
case ERR_ARG:
|
mbed714 |
0:d616ece2d859
|
188
|
return (int) NETTCPSOCKET_SETUP; //Wrong args ! (like buf pointing to NULL)
|
mbed714 |
0:d616ece2d859
|
189
|
case ERR_MEM:
|
mbed714 |
0:d616ece2d859
|
190
|
default:
|
mbed714 |
0:d616ece2d859
|
191
|
return (int) NETTCPSOCKET_MEM; //Not enough memory
|
mbed714 |
0:d616ece2d859
|
192
|
}
|
mbed714 |
0:d616ece2d859
|
193
|
}
|
mbed714 |
0:d616ece2d859
|
194
|
return outLen;
|
mbed714 |
0:d616ece2d859
|
195
|
}
|
mbed714 |
0:d616ece2d859
|
196
|
|
mbed714 |
0:d616ece2d859
|
197
|
int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::recv(char* buf, int len)
|
mbed714 |
0:d616ece2d859
|
198
|
{
|
mbed714 |
0:d616ece2d859
|
199
|
if( !m_pPcb ) //Pcb doesn't exist (anymore)
|
mbed714 |
0:d616ece2d859
|
200
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
201
|
int inLen = 0;
|
mbed714 |
0:d616ece2d859
|
202
|
int cpyLen = 0;
|
mbed714 |
0:d616ece2d859
|
203
|
|
mbed714 |
0:d616ece2d859
|
204
|
static int rmgLen = 0;
|
mbed714 |
0:d616ece2d859
|
205
|
//Contains the remaining len in this pbuf
|
mbed714 |
0:d616ece2d859
|
206
|
|
mbed714 |
0:d616ece2d859
|
207
|
if( !m_pReadPbuf )
|
mbed714 |
0:d616ece2d859
|
208
|
{
|
mbed714 |
0:d616ece2d859
|
209
|
rmgLen = 0;
|
mbed714 |
0:d616ece2d859
|
210
|
return 0;
|
mbed714 |
0:d616ece2d859
|
211
|
}
|
mbed714 |
0:d616ece2d859
|
212
|
|
mbed714 |
0:d616ece2d859
|
213
|
if ( !rmgLen ) //We did not know m_pReadPbuf->len last time we called this fn
|
mbed714 |
0:d616ece2d859
|
214
|
{
|
mbed714 |
0:d616ece2d859
|
215
|
rmgLen = m_pReadPbuf->len;
|
mbed714 |
0:d616ece2d859
|
216
|
}
|
mbed714 |
0:d616ece2d859
|
217
|
|
mbed714 |
0:d616ece2d859
|
218
|
while ( inLen < len )
|
mbed714 |
0:d616ece2d859
|
219
|
{
|
mbed714 |
0:d616ece2d859
|
220
|
cpyLen = MIN( (len - inLen), rmgLen ); //Remaining len to copy, remaining len in THIS pbuf
|
mbed714 |
0:d616ece2d859
|
221
|
memcpy((void*)buf, (void*)((char*)(m_pReadPbuf->payload) + (m_pReadPbuf->len - rmgLen)), cpyLen);
|
mbed714 |
0:d616ece2d859
|
222
|
inLen += cpyLen;
|
mbed714 |
0:d616ece2d859
|
223
|
buf += cpyLen;
|
mbed714 |
0:d616ece2d859
|
224
|
|
mbed714 |
0:d616ece2d859
|
225
|
rmgLen = rmgLen - cpyLen; //Update rmgLen
|
mbed714 |
0:d616ece2d859
|
226
|
|
mbed714 |
0:d616ece2d859
|
227
|
if( rmgLen > 0 )
|
mbed714 |
0:d616ece2d859
|
228
|
{
|
mbed714 |
0:d616ece2d859
|
229
|
//We did not read this pbuf completely, so let's save it's pos & return
|
mbed714 |
0:d616ece2d859
|
230
|
break;
|
mbed714 |
0:d616ece2d859
|
231
|
}
|
mbed714 |
0:d616ece2d859
|
232
|
|
mbed714 |
0:d616ece2d859
|
233
|
if(m_pReadPbuf->next)
|
mbed714 |
0:d616ece2d859
|
234
|
{
|
mbed714 |
0:d616ece2d859
|
235
|
pbuf* pNextPBuf = m_pReadPbuf->next;
|
mbed714 |
0:d616ece2d859
|
236
|
m_pReadPbuf->next = NULL; //So that it is not freed as well
|
mbed714 |
0:d616ece2d859
|
237
|
//We get the reference to pNextPBuf from m_pReadPbuf
|
mbed714 |
0:d616ece2d859
|
238
|
pbuf_free((pbuf*)m_pReadPbuf);
|
mbed714 |
0:d616ece2d859
|
239
|
m_pReadPbuf = pNextPBuf;
|
mbed714 |
0:d616ece2d859
|
240
|
rmgLen = m_pReadPbuf->len;
|
mbed714 |
0:d616ece2d859
|
241
|
}
|
mbed714 |
0:d616ece2d859
|
242
|
else
|
mbed714 |
0:d616ece2d859
|
243
|
{
|
mbed714 |
0:d616ece2d859
|
244
|
pbuf_free((pbuf*)m_pReadPbuf);
|
mbed714 |
0:d616ece2d859
|
245
|
m_pReadPbuf = NULL;
|
mbed714 |
0:d616ece2d859
|
246
|
rmgLen = 0;
|
mbed714 |
0:d616ece2d859
|
247
|
break; //No more data to read
|
mbed714 |
0:d616ece2d859
|
248
|
}
|
mbed714 |
0:d616ece2d859
|
249
|
|
mbed714 |
0:d616ece2d859
|
250
|
}
|
mbed714 |
0:d616ece2d859
|
251
|
|
mbed714 |
0:d616ece2d859
|
252
|
//tcp_recved(m_pPcb, inLen); //Acknowledge the reception
|
mbed714 |
0:d616ece2d859
|
253
|
|
mbed714 |
0:d616ece2d859
|
254
|
return inLen;
|
mbed714 |
0:d616ece2d859
|
255
|
}
|
mbed714 |
0:d616ece2d859
|
256
|
|
mbed714 |
0:d616ece2d859
|
257
|
NetTcpSocketErr LwipNetTcpSocket::close()
|
mbed714 |
0:d616ece2d859
|
258
|
{
|
mbed714 |
0:d616ece2d859
|
259
|
//DBG("LwipNetTcpSocket::close() : Closing...\n");
|
mbed714 |
0:d616ece2d859
|
260
|
|
mbed714 |
0:d616ece2d859
|
261
|
if(m_closed)
|
mbed714 |
0:d616ece2d859
|
262
|
return NETTCPSOCKET_OK; //Already being closed
|
mbed714 |
0:d616ece2d859
|
263
|
m_closed = true;
|
mbed714 |
0:d616ece2d859
|
264
|
|
mbed714 |
0:d616ece2d859
|
265
|
if( !m_pPcb ) //Pcb doesn't exist (anymore)
|
mbed714 |
0:d616ece2d859
|
266
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
267
|
|
mbed714 |
0:d616ece2d859
|
268
|
//Cleanup incoming data
|
mbed714 |
0:d616ece2d859
|
269
|
cleanUp();
|
mbed714 |
0:d616ece2d859
|
270
|
|
mbed714 |
0:d616ece2d859
|
271
|
if( !!tcp_close( (tcp_pcb*) m_pPcb) )
|
mbed714 |
0:d616ece2d859
|
272
|
{
|
mbed714 |
0:d616ece2d859
|
273
|
DBG("LwipNetTcpSocket::close() could not close properly, abort.\n");
|
mbed714 |
0:d616ece2d859
|
274
|
tcp_abort( (tcp_pcb*) m_pPcb);
|
mbed714 |
0:d616ece2d859
|
275
|
m_pPcb = NULL;
|
mbed714 |
0:d616ece2d859
|
276
|
return NETTCPSOCKET_MEM;
|
mbed714 |
0:d616ece2d859
|
277
|
}
|
mbed714 |
0:d616ece2d859
|
278
|
|
mbed714 |
0:d616ece2d859
|
279
|
DBG("LwipNetTcpSocket::close() : connection closed successfully.\n");
|
mbed714 |
0:d616ece2d859
|
280
|
|
mbed714 |
0:d616ece2d859
|
281
|
m_pPcb = NULL;
|
mbed714 |
0:d616ece2d859
|
282
|
return NETTCPSOCKET_OK;
|
mbed714 |
0:d616ece2d859
|
283
|
}
|
mbed714 |
0:d616ece2d859
|
284
|
|
mbed714 |
0:d616ece2d859
|
285
|
NetTcpSocketErr LwipNetTcpSocket::poll()
|
mbed714 |
0:d616ece2d859
|
286
|
{
|
mbed714 |
0:d616ece2d859
|
287
|
NetTcpSocket::flushEvents();
|
mbed714 |
0:d616ece2d859
|
288
|
return NETTCPSOCKET_OK;
|
mbed714 |
0:d616ece2d859
|
289
|
}
|
mbed714 |
0:d616ece2d859
|
290
|
|
mbed714 |
0:d616ece2d859
|
291
|
// Callbacks events
|
mbed714 |
0:d616ece2d859
|
292
|
|
mbed714 |
0:d616ece2d859
|
293
|
err_t LwipNetTcpSocket::acceptCb(struct tcp_pcb *newpcb, err_t err)
|
mbed714 |
0:d616ece2d859
|
294
|
{
|
mbed714 |
0:d616ece2d859
|
295
|
if(err)
|
mbed714 |
0:d616ece2d859
|
296
|
{
|
mbed714 |
0:d616ece2d859
|
297
|
DBG("Error %d in LwipNetTcpSocket::acceptCb.\n", err);
|
mbed714 |
0:d616ece2d859
|
298
|
return err;
|
mbed714 |
0:d616ece2d859
|
299
|
}
|
mbed714 |
0:d616ece2d859
|
300
|
//FIXME: MEM Errs
|
mbed714 |
0:d616ece2d859
|
301
|
//m_lpInPcb.push(newpcb); //Add connection to the queue
|
mbed714 |
0:d616ece2d859
|
302
|
LwipNetTcpSocket* pNewNetTcpSocket = new LwipNetTcpSocket(newpcb);
|
mbed714 |
0:d616ece2d859
|
303
|
|
mbed714 |
0:d616ece2d859
|
304
|
if(pNewNetTcpSocket == NULL)
|
mbed714 |
0:d616ece2d859
|
305
|
{
|
mbed714 |
0:d616ece2d859
|
306
|
DBG("Not enough mem, socket dropped in LwipNetTcpSocket::acceptCb.\n");
|
mbed714 |
0:d616ece2d859
|
307
|
tcp_abort(newpcb);
|
mbed714 |
0:d616ece2d859
|
308
|
return ERR_ABRT;
|
mbed714 |
0:d616ece2d859
|
309
|
}
|
mbed714 |
0:d616ece2d859
|
310
|
|
mbed714 |
0:d616ece2d859
|
311
|
pNewNetTcpSocket->m_refs++;
|
mbed714 |
0:d616ece2d859
|
312
|
m_lpInNetTcpSocket.push( pNewNetTcpSocket );
|
mbed714 |
0:d616ece2d859
|
313
|
|
mbed714 |
0:d616ece2d859
|
314
|
// tcp_accepted(newpcb);
|
mbed714 |
0:d616ece2d859
|
315
|
// tcp_accepted( m_pPcb ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb)
|
mbed714 |
0:d616ece2d859
|
316
|
queueEvent(NETTCPSOCKET_ACCEPT);
|
mbed714 |
0:d616ece2d859
|
317
|
return ERR_OK;
|
mbed714 |
0:d616ece2d859
|
318
|
}
|
mbed714 |
0:d616ece2d859
|
319
|
|
mbed714 |
0:d616ece2d859
|
320
|
err_t LwipNetTcpSocket::connectedCb(struct tcp_pcb *tpcb, err_t err)
|
mbed714 |
0:d616ece2d859
|
321
|
{
|
mbed714 |
0:d616ece2d859
|
322
|
queueEvent(NETTCPSOCKET_CONNECTED);
|
mbed714 |
0:d616ece2d859
|
323
|
return ERR_OK;
|
mbed714 |
0:d616ece2d859
|
324
|
}
|
mbed714 |
0:d616ece2d859
|
325
|
|
mbed714 |
0:d616ece2d859
|
326
|
void LwipNetTcpSocket::errCb(err_t err)
|
mbed714 |
0:d616ece2d859
|
327
|
{
|
mbed714 |
0:d616ece2d859
|
328
|
DBG("NetTcpSocket %p - Error %d in LwipNetTcpSocket::errCb.\n", (void*)this, err);
|
mbed714 |
0:d616ece2d859
|
329
|
//WARN: At this point, m_pPcb has been freed by lwIP
|
mbed714 |
0:d616ece2d859
|
330
|
m_pPcb = NULL;
|
mbed714 |
0:d616ece2d859
|
331
|
//These errors are fatal, discard all events queued before so that the errors are handled first
|
mbed714 |
0:d616ece2d859
|
332
|
discardEvents();
|
mbed714 |
0:d616ece2d859
|
333
|
m_closed = true;
|
mbed714 |
0:d616ece2d859
|
334
|
cleanUp();
|
mbed714 |
0:d616ece2d859
|
335
|
if( err == ERR_ABRT)
|
mbed714 |
0:d616ece2d859
|
336
|
queueEvent(NETTCPSOCKET_CONABRT);
|
mbed714 |
0:d616ece2d859
|
337
|
else //if( err == ERR_RST)
|
mbed714 |
0:d616ece2d859
|
338
|
queueEvent(NETTCPSOCKET_CONRST);
|
mbed714 |
0:d616ece2d859
|
339
|
}
|
mbed714 |
0:d616ece2d859
|
340
|
|
mbed714 |
0:d616ece2d859
|
341
|
err_t LwipNetTcpSocket::sentCb(tcp_pcb* tpcb, u16_t len)
|
mbed714 |
0:d616ece2d859
|
342
|
{
|
mbed714 |
0:d616ece2d859
|
343
|
// DBG("%d bytes ACKed by host.\n", len);
|
mbed714 |
0:d616ece2d859
|
344
|
queueEvent(NETTCPSOCKET_WRITEABLE);
|
mbed714 |
0:d616ece2d859
|
345
|
return ERR_OK;
|
mbed714 |
0:d616ece2d859
|
346
|
}
|
mbed714 |
0:d616ece2d859
|
347
|
|
mbed714 |
0:d616ece2d859
|
348
|
err_t LwipNetTcpSocket::recvCb(tcp_pcb* tpcb, pbuf *p, err_t err)
|
mbed714 |
0:d616ece2d859
|
349
|
{
|
mbed714 |
0:d616ece2d859
|
350
|
//Store pbuf ptr
|
mbed714 |
0:d616ece2d859
|
351
|
// DBG("Receive CB with err = %d & len = %d.\n", err, p->tot_len);
|
mbed714 |
0:d616ece2d859
|
352
|
// tcp_recved( (tcp_pcb*) m_pPcb, p->tot_len); //Acknowledge the reception
|
mbed714 |
0:d616ece2d859
|
353
|
|
mbed714 |
0:d616ece2d859
|
354
|
if(err)
|
mbed714 |
0:d616ece2d859
|
355
|
{
|
mbed714 |
0:d616ece2d859
|
356
|
queueEvent(NETTCPSOCKET_ERROR);
|
mbed714 |
0:d616ece2d859
|
357
|
return ERR_OK; //FIXME: More robust error handling there
|
mbed714 |
0:d616ece2d859
|
358
|
}
|
mbed714 |
0:d616ece2d859
|
359
|
else if(!p)
|
mbed714 |
0:d616ece2d859
|
360
|
{
|
mbed714 |
0:d616ece2d859
|
361
|
DBG("NetTcpSocket %p - Connection closed by remote host (LwipNetTcpSocket::recvCb).\n", (void*)this);
|
mbed714 |
0:d616ece2d859
|
362
|
//Buf is NULL, that means that the connection has been closed by remote host
|
mbed714 |
0:d616ece2d859
|
363
|
|
mbed714 |
0:d616ece2d859
|
364
|
//FIX: 27/05/2010: We do not want to deallocate the socket while some data might still be readable
|
mbed714 |
0:d616ece2d859
|
365
|
//REMOVED: close();
|
mbed714 |
0:d616ece2d859
|
366
|
|
mbed714 |
0:d616ece2d859
|
367
|
//However we do not want to close the socket yet
|
mbed714 |
0:d616ece2d859
|
368
|
|
mbed714 |
0:d616ece2d859
|
369
|
queueEvent(NETTCPSOCKET_DISCONNECTED);
|
mbed714 |
0:d616ece2d859
|
370
|
return ERR_OK;
|
mbed714 |
0:d616ece2d859
|
371
|
}
|
mbed714 |
0:d616ece2d859
|
372
|
|
mbed714 |
0:d616ece2d859
|
373
|
//We asserted that p is a valid pointer
|
mbed714 |
0:d616ece2d859
|
374
|
|
mbed714 |
0:d616ece2d859
|
375
|
//New data processing
|
mbed714 |
0:d616ece2d859
|
376
|
tcp_recved( tpcb, p->tot_len); //Acknowledge the reception
|
mbed714 |
0:d616ece2d859
|
377
|
if(!m_pReadPbuf)
|
mbed714 |
0:d616ece2d859
|
378
|
{
|
mbed714 |
0:d616ece2d859
|
379
|
m_pReadPbuf = p;
|
mbed714 |
0:d616ece2d859
|
380
|
queueEvent(NETTCPSOCKET_READABLE);
|
mbed714 |
0:d616ece2d859
|
381
|
}
|
mbed714 |
0:d616ece2d859
|
382
|
else
|
mbed714 |
0:d616ece2d859
|
383
|
{
|
mbed714 |
0:d616ece2d859
|
384
|
pbuf_cat((pbuf*)m_pReadPbuf, p); //m_pReadPbuf is not empty, tail p to it and drop our ref
|
mbed714 |
0:d616ece2d859
|
385
|
//No need to queue an event in that case since the read buf has not been processed yet
|
mbed714 |
0:d616ece2d859
|
386
|
}
|
mbed714 |
0:d616ece2d859
|
387
|
return ERR_OK;
|
mbed714 |
0:d616ece2d859
|
388
|
}
|
mbed714 |
0:d616ece2d859
|
389
|
|
mbed714 |
0:d616ece2d859
|
390
|
|
mbed714 |
0:d616ece2d859
|
391
|
void LwipNetTcpSocket::cleanUp() //Flush input buffer
|
mbed714 |
0:d616ece2d859
|
392
|
{
|
mbed714 |
0:d616ece2d859
|
393
|
//Ensure that further error won't be followed to this inst (which can be destroyed)
|
mbed714 |
0:d616ece2d859
|
394
|
if( m_pPcb )
|
mbed714 |
0:d616ece2d859
|
395
|
{
|
mbed714 |
0:d616ece2d859
|
396
|
tcp_arg( (tcp_pcb*) m_pPcb, (void*) NULL );
|
mbed714 |
0:d616ece2d859
|
397
|
tcp_recv( (tcp_pcb*) m_pPcb, NULL );
|
mbed714 |
0:d616ece2d859
|
398
|
tcp_sent((tcp_pcb*) m_pPcb, NULL );
|
mbed714 |
0:d616ece2d859
|
399
|
tcp_err( (tcp_pcb*) m_pPcb, NULL );
|
mbed714 |
0:d616ece2d859
|
400
|
}
|
mbed714 |
0:d616ece2d859
|
401
|
|
mbed714 |
0:d616ece2d859
|
402
|
if( m_pReadPbuf )
|
mbed714 |
0:d616ece2d859
|
403
|
{
|
mbed714 |
0:d616ece2d859
|
404
|
DBG("Deallocating unread data.\n");
|
mbed714 |
0:d616ece2d859
|
405
|
pbuf_free((pbuf*)m_pReadPbuf); //Free all unread data
|
mbed714 |
0:d616ece2d859
|
406
|
m_pReadPbuf = NULL;
|
mbed714 |
0:d616ece2d859
|
407
|
recv(NULL,0); //Update recv ptr position
|
mbed714 |
0:d616ece2d859
|
408
|
}
|
mbed714 |
0:d616ece2d859
|
409
|
}
|
mbed714 |
0:d616ece2d859
|
410
|
|
mbed714 |
0:d616ece2d859
|
411
|
// Static callbacks from LwIp
|
mbed714 |
0:d616ece2d859
|
412
|
|
mbed714 |
0:d616ece2d859
|
413
|
err_t LwipNetTcpSocket::sAcceptCb(void *arg, struct tcp_pcb *newpcb, err_t err)
|
mbed714 |
0:d616ece2d859
|
414
|
{
|
mbed714 |
0:d616ece2d859
|
415
|
LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
|
mbed714 |
0:d616ece2d859
|
416
|
return pMe->acceptCb( newpcb, err );
|
mbed714 |
0:d616ece2d859
|
417
|
}
|
mbed714 |
0:d616ece2d859
|
418
|
|
mbed714 |
0:d616ece2d859
|
419
|
err_t LwipNetTcpSocket::sConnectedCb(void *arg, struct tcp_pcb *tpcb, err_t err)
|
mbed714 |
0:d616ece2d859
|
420
|
{
|
mbed714 |
0:d616ece2d859
|
421
|
LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
|
mbed714 |
0:d616ece2d859
|
422
|
return pMe->connectedCb( tpcb, err );
|
mbed714 |
0:d616ece2d859
|
423
|
}
|
mbed714 |
0:d616ece2d859
|
424
|
|
mbed714 |
0:d616ece2d859
|
425
|
void LwipNetTcpSocket::sErrCb(void *arg, err_t err)
|
mbed714 |
0:d616ece2d859
|
426
|
{
|
mbed714 |
0:d616ece2d859
|
427
|
if( !arg )
|
mbed714 |
0:d616ece2d859
|
428
|
{
|
mbed714 |
0:d616ece2d859
|
429
|
DBG("NetTcpSocket - Error %d in LwipNetTcpSocket::sErrCb.\n", err);
|
mbed714 |
0:d616ece2d859
|
430
|
return; //The socket has been destroyed, discard error
|
mbed714 |
0:d616ece2d859
|
431
|
}
|
mbed714 |
0:d616ece2d859
|
432
|
LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
|
mbed714 |
0:d616ece2d859
|
433
|
return pMe->errCb( err );
|
mbed714 |
0:d616ece2d859
|
434
|
}
|
mbed714 |
0:d616ece2d859
|
435
|
|
mbed714 |
0:d616ece2d859
|
436
|
err_t LwipNetTcpSocket::sSentCb(void *arg, struct tcp_pcb *tpcb, u16_t len)
|
mbed714 |
0:d616ece2d859
|
437
|
{
|
mbed714 |
0:d616ece2d859
|
438
|
LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
|
mbed714 |
0:d616ece2d859
|
439
|
return pMe->sentCb( tpcb, len );
|
mbed714 |
0:d616ece2d859
|
440
|
}
|
mbed714 |
0:d616ece2d859
|
441
|
|
mbed714 |
0:d616ece2d859
|
442
|
err_t LwipNetTcpSocket::sRecvCb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
mbed714 |
0:d616ece2d859
|
443
|
{
|
mbed714 |
0:d616ece2d859
|
444
|
if( tpcb->flags & TF_RXCLOSED )
|
mbed714 |
0:d616ece2d859
|
445
|
{
|
mbed714 |
0:d616ece2d859
|
446
|
//The Pcb is in a closing state
|
mbed714 |
0:d616ece2d859
|
447
|
//Discard that data here since we might have destroyed the corresponding socket object
|
mbed714 |
0:d616ece2d859
|
448
|
tcp_recved( tpcb, p->tot_len);
|
mbed714 |
0:d616ece2d859
|
449
|
pbuf_free( p );
|
mbed714 |
0:d616ece2d859
|
450
|
return ERR_OK;
|
mbed714 |
0:d616ece2d859
|
451
|
}
|
mbed714 |
0:d616ece2d859
|
452
|
LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
|
mbed714 |
0:d616ece2d859
|
453
|
return pMe->recvCb( tpcb, p, err );
|
mbed714 |
0:d616ece2d859
|
454
|
}
|
mbed714 |
0:d616ece2d859
|
455
|
|
mbed714 |
0:d616ece2d859
|
456
|
#endif
|