embkernel
 All Classes Functions Variables Typedefs Groups Pages
NetTcpSocket.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "NetTcpSocket.hpp"
7 #include "NetTcp.hpp"
8 #include "NetArp.hpp"
9 #include "Net.hpp"
10 
11 uint32_t NetTcpSocket::sStartSequenceCounter = 0x80000000;
12 uint16_t NetTcpSocket::sAutomaticPort = 0xC070;
13 
14 NetTcpSocket::NetTcpSocket() :
15  mSemaEvent(1, 0) {
16  mState = STATE_CLOSED;
17  mWindowSize = 1024;
18  mMaxTxSegmentDataLen = 512;
19  mRxCurrentSegment = 0;
20  mTxFirstSegment = 0;
21  mTxCurrentSegment = 0;
22  mIsAutoListenAndAccept = false;
23 }
24 
25 NetTcpSocket::~NetTcpSocket() {
26  if (mState != STATE_CLOSED) {
27  close();
28  }
29 }
30 
31 bool NetTcpSocket::connect(NetDefs::IP_ADDR& remoteIpAddr, uint16_t remotePort, uint16_t localPort) {
32  if (!NetArp::resolve(remoteIpAddr, mRemoteMacAddr)) {
33  return false;
34  }
35 
36  mRemoteIpAddr = remoteIpAddr;
37  mRemotePort = remotePort;
38  if (localPort == 0) {
39  mLocalPort = sAutomaticPort++;
40  if (sAutomaticPort == 0) {
41  sAutomaticPort = 0xC000;
42  }
43  }
44  else {
45  mLocalPort = localPort;
46  }
47  mState = STATE_SYN_SENT;
48  mRetries = NetTcp::MAX_RETRIES_SYN_SENT;
49  mTimer = NetTcp::TIMER_SYN_SENT;
50  mSentCount = sStartSequenceCounter;
51  sStartSequenceCounter -= 0x1000;
52  NetTcp::lock();
53  NetTcp::addSocket(*this);
54  NetTcp::unlock();
55  NetTcp::sendControlPacket(*this, NetDefs::TCP_FLAG_SYN);
56  mSentCount++;
57 
58  mSemaEvent.take(Rtos::TICK_INFINITE);
59 
60  if (mState == STATE_EST) {
61  mIsRxDataFinished = false;
62  return true;
63  }
64 
65  return false;
66 }
67 
68 void NetTcpSocket::listen(NetDefs::TCP_PORT localPort) {
69  if (mState != STATE_CLOSED) {
70  close();
71  }
72  mState = STATE_LISTEN;
73  mLocalPort = localPort;
74  mSentCount = sStartSequenceCounter;
75  sStartSequenceCounter -= 0x1000;
76  NetTcp::lock();
77  NetTcp::addSocket(*this);
78  NetTcp::unlock();
79 }
80 
81 bool NetTcpSocket::accept(Rtos::TICK timeout) {
82  if (mSemaEvent.take(timeout)) {
83  mIsRxDataFinished = false;
84  return true;
85  }
86  return false;
87 }
88 
89 void NetTcpSocket::autoListenAndAccept(NetDefs::TCP_PORT localPort) {
90  mIsAutoListenAndAccept = true;
91  listen(localPort);
92 }
93 
94 bool NetTcpSocket::isConnected() {
95  return (mState == STATE_EST);
96 }
97 
98 int NetTcpSocket::read(void* buffer, int len, Rtos::TICK timeout) {
99  if (mIsRxDataFinished) {
100  return -1;
101  }
102 
103  int dstIndex = 0;
104  while (true) {
105  if (mRxCurrentSegment == 0) {
106  if (!mRxMsgBox.take(mRxCurrentSegment, timeout)) {
107  return dstIndex;
108  }
109  if (mRxCurrentSegment == 0) {
110  mIsRxDataFinished = true;
111  return dstIndex;
112  }
113  mRxCurrentSegment->hdr.index = 0;
114  }
115 
116  uint16_t available = mRxCurrentSegment->hdr.dataLen - mRxCurrentSegment->hdr.index;
117  if (available < len) {
118  if (buffer) {
119  memcpy(&((uint8_t*) buffer)[dstIndex], &mRxCurrentSegment->data[mRxCurrentSegment->hdr.index], available);
120  }
121  len -= available;
122  dstIndex += available;
123  NetTcp::lock();
124  if (mWindowSize < 16) {
125  mWindowSize += mRxCurrentSegment->hdr.dataLen;
126  NetTcp::sendControlPacket(*this, NetDefs::TCP_FLAG_ACK);
127  }
128  else {
129  mWindowSize += mRxCurrentSegment->hdr.dataLen;
130  }
131  NetTcp::unlock();
132  Net::freeFrame((NetDefs::FRAME&) *mRxCurrentSegment);
133  mRxCurrentSegment = 0;
134  }
135  else if (available == len) {
136  if (buffer) {
137  memcpy(&((uint8_t*) buffer)[dstIndex], &mRxCurrentSegment->data[mRxCurrentSegment->hdr.index], len);
138  }
139  NetTcp::lock();
140  if (mWindowSize < 16) {
141  mWindowSize += mRxCurrentSegment->hdr.dataLen;
142  NetTcp::sendControlPacket(*this, NetDefs::TCP_FLAG_ACK);
143  }
144  else {
145  mWindowSize += mRxCurrentSegment->hdr.dataLen;
146  }
147  NetTcp::unlock();
148  Net::freeFrame((NetDefs::FRAME&) *mRxCurrentSegment);
149  mRxCurrentSegment = 0;
150  return dstIndex + len;
151  }
152  else { //available > len
153  if (buffer) {
154  memcpy(&((uint8_t*) buffer)[dstIndex], &mRxCurrentSegment->data[mRxCurrentSegment->hdr.index], len);
155  }
156  mRxCurrentSegment->hdr.index += len;
157  return dstIndex + len;
158  }
159  }
160 }
161 
162 int NetTcpSocket::skip(int len, Rtos::TICK timeout) {
163  return read(0, len, timeout);
164 }
165 
166 int NetTcpSocket::write(const void* buffer, int len, Rtos::TICK timeout) {
167  if (mState != STATE_EST) {
168  return -1;
169  }
170 
171  RtosTimer timer;
172  timer.set(timeout);
173 
174  int written = 0;
175  int left = len;
176  bool continueLoop = true;
177 
178  while (left && (continueLoop || !timer.isEllapsed()) && (mState == STATE_EST)) {
179  continueLoop = true;
180 
181  NetTcp::lock();
182 
183  if (mTxCurrentSegment == 0) {
184  //Don't add a new segment if MAX_QUEUED_TX_SEGMENTS reached
185  {
186  int queuedSegments = 0;
187  for (TX_SEGMENT* iterator = mTxFirstSegment; iterator != 0; iterator = iterator->next) {
188  queuedSegments++;
189  }
190  if (queuedSegments >= MAX_QUEUED_TX_SEGMENTS) {
191  NetTcp::unlock();
192  Rtos::sleep(2);
193  continueLoop = false;
194  continue;
195  }
196  }
197 
198  //Create segment
199  TX_SEGMENT* segment = (TX_SEGMENT*) Net::allocFrame(
200  sizeof(tagTX_SEGMENT*) + sizeof(TX_SEGMENT_HEADER) + sizeof(NetDefs::MAC_HEADER) + sizeof(NetDefs::IP_HEADER) + sizeof(NetDefs::TCP_HEADER)
201  + mMaxTxSegmentDataLen);
202 
203  if (segment == 0) {
204  NetTcp::unlock();
205  Rtos::sleep(2);
206  continueLoop = false;
207  continue;
208  }
209 
210  segment->next = 0;
211  segment->hdr.flushed = false;
212  segment->hdr.len = 0;
213  segment->hdr.maxLen = mMaxTxSegmentDataLen;
214  segment->hdr.retries = NetTcp::MAX_RETRIES_SEGMENT_RETRY;
215  segment->hdr.timeout = NetTcp::TIMER_SEGMENT_FLUSH;
216 
217  if (mTxFirstSegment == 0) {
218  mTxFirstSegment = segment;
219  segment->hdr.seq = mSentCount;
220  }
221  else {
222  TX_SEGMENT* iterator;
223  for (iterator = mTxFirstSegment; iterator->next != 0; iterator = iterator->next)
224  ;
225  iterator->next = segment;
226  segment->hdr.seq = iterator->hdr.seq + iterator->hdr.len;
227  }
228  mTxCurrentSegment = segment;
229  }
230 
231  uint16_t writable = mTxCurrentSegment->hdr.maxLen - mTxCurrentSegment->hdr.len;
232 
233  if (writable > left) {
234  writable = left;
235  }
236 
237  memcpy(&mTxCurrentSegment->frame.types.tcp.data[mTxCurrentSegment->hdr.len], &((uint8_t*) buffer)[written], writable);
238  left -= writable;
239  written += writable;
240  mTxCurrentSegment->hdr.len += writable;
241  if (mTxCurrentSegment->hdr.len >= mTxCurrentSegment->hdr.maxLen) {
242  NetTcp::flushSegment(*this, *mTxCurrentSegment);
243  }
244 
245  NetTcp::unlock();
246  }
247  return written;
248 }
249 
250 void NetTcpSocket::close() {
251  if (mState == STATE_CLOSED) {
252  return;
253  }
254 
255  NetTcp::lock();
256 
257  //See TCP/IP State Transition Diagram (RFC793)
258  switch (mState) {
259  case STATE_LISTEN:
260  case STATE_SYN_SENT:
261  break;
262  case STATE_SYN_RCVD:
263  NetTcp::sendControlPacket(*this, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
264  break;
265  case STATE_EST: {
266  discardAllRxSegments();
267  flush();
268  NetTcpSocket* socket = new NetTcpSocket();
269  if (socket != 0) {
270  *socket = *this;
271  socket->mState = STATE_FIN_WAIT_1;
272  socket->mRetries = NetTcp::MAX_RETRIES_FIN_WAIT_1;
273  socket->mTimer = NetTcp::TIMER_FIN_WAIT_1;
274  NetTcp::addSocket(*socket);
275  NetTcp::sendControlPacket(*socket, NetDefs::TCP_FLAG_FIN | NetDefs::TCP_FLAG_ACK);
276  socket->mSentCount++;
277  }
278  else {
279  NetTcp::sendControlPacket(*this, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
280  discardAllTxSegments();
281  }
282  break;
283  }
284  case STATE_CLOSE_WAIT: {
285  discardAllRxSegments();
286  NetTcpSocket* socket = new NetTcpSocket();
287  if (socket != 0) {
288  *socket = *this;
289  socket->mState = STATE_LAST_ACK;
290  socket->mRetries = NetTcp::MAX_RETRIES_LAST_ACK;
291  socket->mTimer = NetTcp::TIMER_LAST_ACK;
292  NetTcp::addSocket(*socket);
293  NetTcp::sendControlPacket(*socket, NetDefs::TCP_FLAG_FIN | NetDefs::TCP_FLAG_ACK);
294  socket->mSentCount++;
295  }
296  else {
297  NetTcp::sendControlPacket(*this, NetDefs::TCP_FLAG_PSH | NetDefs::TCP_FLAG_RST);
298  discardAllTxSegments();
299  }
300  break;
301  }
302  case STATE_RESET:
303  discardAllRxSegments();
304  break;
305  default:
306  break;
307  }
308 
309  NetTcp::removeSocket(*this);
310  mState = STATE_CLOSED;
311  mTxFirstSegment = 0;
312  mTxCurrentSegment = 0;
313  mIsAutoListenAndAccept = false;
314  NetTcp::unlock();
315 }
316 
317 void NetTcpSocket::setWindowSize(uint16_t windowsSize) {
318  mWindowSize = windowsSize;
319 }
320 
321 void NetTcpSocket::setMaxTxSegmentDataLen(uint16_t maxTxSegmentDataLen) {
322  mMaxTxSegmentDataLen = maxTxSegmentDataLen;
323 }
324 
325 void NetTcpSocket::flush() {
326  for (NetTcpSocket::TX_SEGMENT* segment = mTxFirstSegment; segment != 0; segment = segment->next) {
327  NetTcp::flushSegment(*this, *segment);
328  }
329 }
330 
331 void NetTcpSocket::discardAllTxSegments() {
332  for (NetTcpSocket::TX_SEGMENT* segment = mTxFirstSegment; segment != 0;) {
333  NetTcpSocket::TX_SEGMENT* next = segment->next;
334  Net::freeFrame((NetDefs::FRAME&) *segment);
335  segment = next;
336  }
337  mTxCurrentSegment = 0;
338  mTxFirstSegment = 0;
339 }
340 
341 void NetTcpSocket::discardAllRxSegments() {
342  while (mRxMsgBox.take(mRxCurrentSegment, 0)) {
343  mWindowSize += mRxCurrentSegment->hdr.dataLen;
344  if (mRxCurrentSegment) {
345  Net::freeFrame((NetDefs::FRAME&) *mRxCurrentSegment);
346  }
347  }
348  mRxCurrentSegment = 0;
349 }
350