1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: rdt_ReceiverImpl.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 #include "stdafx.h"
17
18 #include "rdt_ReceiverImpl.h"
19
20 #include <nn/rdt/CTR/rdt_define.h>
21 #include <nn/rdt/CTR/rdt_Result.h>
22
23
24 namespace
25 {
26
27 } // End of anonymous namespace
28
29 namespace nn { namespace rdt { namespace CTR {
30
31
32 // Base class for "state."
33 class ReceiverStateBase{
34 public:
~ReceiverStateBase(void)35 virtual ~ReceiverStateBase(void){}
36
37 virtual void initialize(ReceiverImpl *pReceiver); // Called when this state begins
38 virtual void finalize (ReceiverImpl *pReceiver); // Called when this state ends
39 virtual void update (ReceiverImpl *pReceiver);
40 virtual enum ReceiverState getStatus(void) const = 0;
41
42 protected:
ReceiverStateBase(void)43 ReceiverStateBase(void){}
44 };
45
46
initialize(ReceiverImpl * pReceiver)47 void ReceiverStateBase::initialize(ReceiverImpl *pReceiver)
48 {
49 (void)pReceiver;
50 }
51
52
finalize(ReceiverImpl * pReceiver)53 void ReceiverStateBase::finalize(ReceiverImpl *pReceiver)
54 {
55 (void)pReceiver;
56 }
57
58
update(ReceiverImpl * pReceiver)59 void ReceiverStateBase::update(ReceiverImpl *pReceiver)
60 {
61 (void)pReceiver;
62 }
63
64
65 class ReceiverStateWaiting : public ReceiverStateBase{
66 public:
67 static ReceiverStateBase* getInstance(void);
68 virtual void update(ReceiverImpl *pReceiver);
69 virtual enum ReceiverState getStatus(void) const;
70
71 protected:
ReceiverStateWaiting(void)72 ReceiverStateWaiting(void){}
73 };
74
75
76 class ReceiverStateOpened : public ReceiverStateBase{
77 public:
78 static ReceiverStateBase* getInstance(void);
79 virtual void update(ReceiverImpl *pReceiver);
80 virtual enum ReceiverState getStatus(void) const;
81
82 protected:
ReceiverStateOpened(void)83 ReceiverStateOpened(void){}
84 };
85
86
87 class ReceiverStateWaitingFinished : public ReceiverStateBase{
88 public:
89 static ReceiverStateBase* getInstance(void);
90 virtual void update(ReceiverImpl *pReceiver);
91 virtual enum ReceiverState getStatus(void) const;
92
93 protected:
ReceiverStateWaitingFinished(void)94 ReceiverStateWaitingFinished(void){}
95 };
96
97
98 class ReceiverStateFinished : public ReceiverStateBase{
99 public:
100 static ReceiverStateBase* getInstance(void);
101 virtual void update(ReceiverImpl *pReceiver);
102 virtual enum ReceiverState getStatus(void) const;
103
104 protected:
ReceiverStateFinished(void)105 ReceiverStateFinished(void){}
106 };
107
108
109 class ReceiverStateClosed : public ReceiverStateBase{
110 public:
111 static ReceiverStateBase* getInstance(void);
112 virtual void initialize(ReceiverImpl *pReceiver);
113 virtual void update (ReceiverImpl *pReceiver);
114 virtual enum ReceiverState getStatus(void) const;
115
116 protected:
ReceiverStateClosed(void)117 ReceiverStateClosed(void){}
118 };
119
120
121 // Implement the derived class.
122
getInstance(void)123 ReceiverStateBase* ReceiverStateWaiting::getInstance(void)
124 {
125 static ReceiverStateWaiting s_instance;
126 return &s_instance;
127 }
128
129
getStatus(void) const130 enum ReceiverState ReceiverStateWaiting::getStatus(void) const
131 {
132 return RECEIVER_STATE_WAITING;
133 }
134
135
update(ReceiverImpl * pReceiver)136 void ReceiverStateWaiting::update(ReceiverImpl *pReceiver)
137 {
138 ASSERT(pReceiver!=NULL);
139
140 //Process here if a segment is received.
141 Segment seg;
142 if(pReceiver->pullSegment(&seg).IsSuccess())
143 {
144 if(seg.IsRst())
145 {
146 // According to TCP RFC, RST received while in a LISTEN state should be ignored.
147 // Therefore, nothing is done here.
148 }
149 else if(seg.IsSyn())
150 {
151 // Return ACK if a the connection request from the remote is correct.
152
153 // Set receive buffer
154 pReceiver->m_recvBuf.SetInitialSequenceNumber(seg.GetSeqNumber());
155
156 // Response to SYN.
157 pReceiver->putSynAckSegment(seg.GetSeqNumber() + 1);
158 pReceiver->setNextState(ReceiverStateOpened::getInstance());
159 }
160 }
161 }
162
163
getInstance(void)164 ReceiverStateBase* ReceiverStateOpened::getInstance(void)
165 {
166 static ReceiverStateOpened s_instance;
167 return &s_instance;
168 }
169
170
getStatus(void) const171 enum ReceiverState ReceiverStateOpened::getStatus(void) const
172 {
173 return RECEIVER_STATE_OPENED;
174 }
175
176
update(ReceiverImpl * pReceiver)177 void ReceiverStateOpened::update(ReceiverImpl *pReceiver)
178 {
179 ASSERT(pReceiver!=NULL);
180
181 //Process here if a segment is received.
182 Segment seg;
183 if(pReceiver->pullSegment(&seg).IsSuccess())
184 {
185 // First, RST bit check
186 if(seg.IsRst())
187 {
188 pReceiver->setNextState(ReceiverStateClosed::getInstance());
189 pReceiver->errorHandling(ResultResetReceived());
190 return;
191 }
192
193 // Has the segment of the anticipated sequence number arrived?
194 ReceiveBuffer &rBuf = pReceiver->m_recvBuf;
195 if(seg.GetSeqNumber()==rBuf.GetLatestSequenceNumber()+1)
196 {
197 if(seg.IsData())
198 {
199 bool result = rBuf.Push(seg.payload, seg.GetDataLength());
200 if(result)
201 {
202 // Data was stored in the receive buffer without any problems.
203 // Previous implementations returned ACKs, but this resulted in too many ACK packets from the receiver.
204 // So, we quit returning ACKs here.
205 }
206 else
207 {
208 LOG("Received data segment, but could not return ACK because receive buffer did not have enough space.\n");
209 }
210 }
211 else if(seg.IsFin())
212 {
213 // Send ACK for the FIN segment
214 pReceiver->putFinAckSegment(seg.GetSeqNumber() + 1);
215 pReceiver->setNextState(ReceiverStateWaitingFinished::getInstance());
216 }
217 else
218 {
219 seg.PrintDebugInfo();
220 PANIC("It seems that SEQ number is valid, but unexpected segment. It is not DATA, nor FIN.");
221 }
222 }
223 else if(seg.GetSeqNumber()==rBuf.GetLatestSequenceNumber())
224 {
225 // If the response for Syn does not arrive, it could be that the Sender resent a Syn request.
226 // Handling for that case.
227 if(seg.IsSyn())
228 {
229 // Response to SYN.
230 pReceiver->putSynAckSegment(seg.GetSeqNumber() + 1);
231 }
232 }
233
234 else
235 {
236 VERBOSE("Unexpected SEQ number. (%d)\n", seg.GetSeqNumber());
237 VERBOSE("SEQ number %d is expected.\n", rBuf.GetLatestSequenceNumber()+1);
238 VERBOSE("Received segment will be ignored.\n");
239
240 #if 0
241 // Because it was an unexpected segment, the possibility of a packet loss is suspect.
242 // For now, quickly return ACK for the portion received up to this point.
243 pReceiver->putAckSegment();
244
245 // If the above line of code is added, performance is slower. This is probably because a large number of ACK packets is issued.
246 #endif
247 }
248 }
249 }
250
251
getInstance(void)252 ReceiverStateBase* ReceiverStateWaitingFinished::getInstance(void)
253 {
254 static ReceiverStateWaitingFinished s_instance;
255 return &s_instance;
256 }
257
258
getStatus(void) const259 enum ReceiverState ReceiverStateWaitingFinished::getStatus(void) const
260 {
261 return RECEIVER_STATE_WAITING_FINISHED;
262 }
263
264
update(ReceiverImpl * pReceiver)265 void ReceiverStateWaitingFinished::update(ReceiverImpl *pReceiver)
266 {
267 // These return an ACK for FIN, and even if in a Finished state, that ACK may not have arrived to the other side.
268 //
269 // To determine if the ACK arrived at the other side, you must wait for some time and verify that no resend packets from the other side have arrived.
270 //
271
272 ASSERT(pReceiver!=NULL);
273
274 //Process here if a segment is received.
275 Segment seg;
276 if(pReceiver->pullSegment(&seg).IsSuccess())
277 {
278 // RST bit check
279 if(seg.IsRst())
280 {
281 pReceiver->setNextState(ReceiverStateClosed::getInstance());
282 pReceiver->errorHandling(ResultResetReceived());
283 return;
284 }
285
286 // Has the FIN segment arrived?
287 ReceiveBuffer &rBuf = pReceiver->m_recvBuf;
288 if(seg.GetSeqNumber()==rBuf.GetLatestSequenceNumber()+1)
289 {
290 if(seg.IsFin())
291 {
292 pReceiver->putFinAckSegment(seg.GetSeqNumber() + 1);
293 }
294 else
295 {
296 seg.PrintDebugInfo();
297 PANIC("Sequence number is valid, but FIN is not included.\n");
298 }
299 }
300 else
301 {
302 // seg.PrintDebugInfo();
303 LOG("Segment with unexpected sequence number. Ignored.\n");
304 }
305 }
306
307 // After determining a timeout, state transition.
308 if(pReceiver->isSenderClosed())
309 {
310 pReceiver->setNextState(ReceiverStateFinished::getInstance());
311 }
312 }
313
314
getInstance(void)315 ReceiverStateBase* ReceiverStateFinished::getInstance(void)
316 {
317 static ReceiverStateFinished s_instance;
318 return &s_instance;
319 }
320
321
getStatus(void) const322 enum ReceiverState ReceiverStateFinished::getStatus(void) const
323 {
324 return RECEIVER_STATE_FINISHED;
325 }
326
327
update(ReceiverImpl * pReceiver)328 void ReceiverStateFinished::update(ReceiverImpl *pReceiver)
329 {
330 ASSERT(pReceiver!=NULL);
331
332 //Process here if a segment is received.
333 Segment seg;
334 if(pReceiver->pullSegment(&seg).IsSuccess())
335 {
336 // For segments without RST, may should have sent RST.
337 // However, because compatibility with the previous RDT may be lost, there is concern that enbugging may happen due to specification changes, so, as in the past, "do nothing."
338 //
339 // However, replace PANIC() with LOG().
340 LOG("State is FINISHED, but received segment from remote!\n");
341 }
342 }
343
344
345
getInstance(void)346 ReceiverStateBase* ReceiverStateClosed::getInstance(void)
347 {
348 static ReceiverStateClosed s_instance;
349 return &s_instance;
350 }
351
352
getStatus(void) const353 enum ReceiverState ReceiverStateClosed::getStatus(void) const
354 {
355 return RECEIVER_STATE_CLOSED;
356 }
357
358
initialize(ReceiverImpl * pReceiver)359 void ReceiverStateClosed::initialize(ReceiverImpl *pReceiver)
360 {
361 ASSERT(pReceiver!=NULL);
362
363 pReceiver->clear();
364 }
365
366
update(ReceiverImpl * pReceiver)367 void ReceiverStateClosed::update(ReceiverImpl *pReceiver)
368 {
369 ASSERT(pReceiver!=NULL);
370
371 // Respond with RST to segments (without RST) received during CLOSED state
372 Segment seg;
373 if(pReceiver->pullSegment(&seg).IsSuccess() && !seg.IsRst())
374 {
375 LOG("Receiver is in CLOSED state, but received segment. RST will be sent.\n");
376 if(seg.IsAck())
377 {
378 pReceiver->sendRstSegment(seg.GetAckNumber());
379 }
380 else
381 {
382 const u32 SEQ = 0;
383 const u32 ACK = seg.GetSeqNumber() + seg.GetSegmentLength();
384 pReceiver->sendRstAckSegment(SEQ, ACK);
385 }
386 }
387 }
388
389
390
391 //
ReceiverImpl(void)392 ReceiverImpl::ReceiverImpl(void) throw()
393 :m_initialized(false)
394 {
395 }
396
397
398 //
~ReceiverImpl(void)399 ReceiverImpl::~ReceiverImpl(void)
400 {
401 Finalize();
402 }
403
404
405 #ifdef _WIN32
Initialize(SOCKET sock,void * pRecvBuf,u16 recvBufSize)406 nn::Result ReceiverImpl::Initialize(SOCKET sock, void *pRecvBuf, u16 recvBufSize)
407 #else
408 nn::Result ReceiverImpl::Initialize(u16 nodeId, u8 port, void *pRecvBuf, u16 recvBufSize)
409 #endif
410 {
411 if(m_initialized)
412 {
413 return ResultAlreadyInitialized();
414 }
415 else
416 {
417 if(pRecvBuf==NULL)
418 {
419 return ResultNullPointer();
420 }
421
422 if(recvBufSize==0)
423 {
424 return ResultInvalidSize();
425 }
426
427 #ifdef _WIN32
428 nn::Result result = HostBase::Initialize(sock);
429 #elif defined(NN_PLATFORM_CTR)
430 nn::Result result = HostBase::Initialize(nodeId, port);
431 #endif
432 if(result.IsFailure())
433 {
434 return result;
435 }
436 else
437 {
438 m_pState = ReceiverStateClosed::getInstance();
439 m_pNextState = NULL;
440 m_recvBuf.Initialize(pRecvBuf, recvBufSize);
441
442 clear();
443
444 m_initialized = true;
445 return ResultSuccess();
446 }
447 }
448 }
449
450
Finalize(void)451 void ReceiverImpl::Finalize(void)
452 {
453 if(m_initialized)
454 {
455 m_initialized = false;
456 m_recvBuf.Finalize();
457 HostBase::Finalize();
458 }
459 else
460 {
461 // Do nothing.
462 }
463 }
464
465
Wait(void)466 nn::Result ReceiverImpl::Wait(void)
467 {
468 ASSERT(m_initialized);
469
470 if(GetStatus()==RECEIVER_STATE_CLOSED)
471 {
472 setNextState(ReceiverStateWaiting::getInstance());
473 changeState();
474 return ResultSuccess();
475 }
476 else
477 {
478 return ResultUntimelyFunctionCall();
479 }
480 }
481
482
Close(void)483 nn::Result ReceiverImpl::Close(void)
484 {
485 ASSERT(m_initialized);
486
487 if(GetStatus()==RECEIVER_STATE_FINISHED)
488 {
489 setNextState(ReceiverStateClosed::getInstance());
490 changeState();
491 return ResultSuccess();
492 }
493 else
494 {
495 return ResultUntimelyFunctionCall();
496 }
497 }
498
499
Receive(void * pBuf,size_t * recvSize,size_t bufSize)500 nn::Result ReceiverImpl::Receive(void *pBuf, size_t *recvSize, size_t bufSize)
501 {
502 ASSERT(m_initialized);
503
504 if((pBuf==NULL) || (recvSize==NULL))
505 {
506 return ResultNullPointer();
507 }
508
509 if(bufSize==0)
510 {
511 return ResultDoNothing();
512 }
513
514 enum ReceiverState stat = GetStatus();
515 if((stat!=RECEIVER_STATE_OPENED) && (stat!=RECEIVER_STATE_WAITING_FINISHED) && (stat!=RECEIVER_STATE_FINISHED))
516 {
517 return ResultUntimelyFunctionCall();
518 }
519
520 *recvSize = m_recvBuf.Read(pBuf, bufSize);
521 if(*recvSize > 0)
522 {
523 m_recvBuf.Pop(*recvSize);
524 }
525
526 // Make Receive trigger, and notify the window remotely.
527 // Because there is space in the receive window, send segment with the purpose of notifying remotely.
528 // When trying to send a segment when the state is not OPENED, a state check is performed with an if statement because the connection may be disconnected.
529 //
530 if(GetStatus()==RECEIVER_STATE_OPENED)
531 {
532 putAckSegment();
533 }
534
535 return ResultSuccess();
536 }
537
538
Process(void)539 nn::Result ReceiverImpl::Process(void)
540 {
541 ASSERT(m_initialized);
542
543 // update() for each state.
544 if(m_pState)
545 {
546 m_pState->update(this);
547 }
548
549 // State Transitions
550 changeState();
551
552 // Errors are returned here.
553 // If returned, errors are reset.
554 nn::Result ret = GetErrorCode();
555 errorHandling(ResultSuccess());
556 return ret;
557 }
558
559
GetStatus(void) const560 enum ReceiverState ReceiverImpl::GetStatus(void) const
561 {
562 ASSERT(m_initialized);
563 ASSERTMSG(m_pState!=NULL, "It seems that state is not initialized.\n");
564
565 return m_pState->getStatus();
566 }
567
568
Cancel(void)569 void ReceiverImpl::Cancel(void)
570 {
571 ASSERT(m_initialized);
572
573 // Cancel processes are executed immediately without waiting for the Process() function.
574
575 // RST transmission
576 const u32 seq = 0;
577 sendRstSegment(seq);
578
579 // Immediately to Closed state.
580 setNextState(ReceiverStateClosed::getInstance());
581 changeState();
582 }
583
584
585 // State Transitions. Do nothing in particular if the next state is not set.
changeState(void)586 void ReceiverImpl::changeState(void)
587 {
588 if(m_pNextState)
589 {
590 if(m_pState)
591 {
592 m_pState->finalize(this);
593 }
594 m_pState = m_pNextState;
595 m_pNextState = NULL;
596 m_pState->initialize(this);
597 }
598 }
599
600
setNextState(ReceiverStateBase * p)601 void ReceiverImpl::setNextState(ReceiverStateBase *p)
602 {
603 ASSERT(p!=NULL);
604 ASSERT(m_pNextState==NULL);
605
606 m_pNextState = p;
607 }
608
609
putSynAckSegment(u32 ack)610 void ReceiverImpl::putSynAckSegment(u32 ack)
611 {
612 Segment a;
613 a.ClearHeader();
614 a.SetAckNumber(ack);
615 a.SetWindowSize(m_recvBuf.GetRestSize());
616 putSegment(a);
617 }
618
619
putAckSegment(void)620 void ReceiverImpl::putAckSegment(void)
621 {
622 Segment a;
623 a.ClearHeader();
624 a.SetAckNumber(m_recvBuf.GetLatestSequenceNumber()+1);
625 a.SetWindowSize(m_recvBuf.GetRestSize());
626 putSegment(a);
627 }
628
629
putFinAckSegment(u32 ack)630 void ReceiverImpl::putFinAckSegment(u32 ack)
631 {
632 Segment a;
633 a.ClearHeader();
634 a.SetAckNumber(ack);
635 a.SetWindowSize(m_recvBuf.GetRestSize());
636 putSegment(a);
637
638 m_finAckSentTime = GetCurrentTimeAsMillisecond();
639 }
640
641
isSenderClosed(void) const642 bool ReceiverImpl::isSenderClosed(void) const
643 {
644 ASSERT(m_finAckSentTime!=0);
645
646 // LOG("m_finAckSentTime = %lld\n", m_finAckSentTime);
647 // LOG("Current: %lld\n", GetCurrentTimeAsMillisecond());
648 return GetCurrentTimeAsMillisecond() - m_finAckSentTime > FIN_TIMEOUT;
649 }
650
651
clear(void)652 void ReceiverImpl::clear(void)
653 {
654 m_recvBuf.Clear();
655 m_finAckSentTime = 0;
656 }
657
658
PrintDebugInfo(void) const659 void ReceiverImpl::PrintDebugInfo(void) const
660 {
661 LOG("-- Receiver debug information --\n");
662 LOG("Current state: %d\n", GetStatus());
663 m_recvBuf.PrintDebugInfo();
664 LOG("\n");
665 }
666
667 }}} // namespace nn::rdt::CTR
668