1 /*--------------------------------------------------------------------------
2 Project: HorizonSDK
3 File: rdt_ReceiverImpl.cpp
4
5 Copyright 2009 Nintendo. 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 $Date:: 2010-09-14#$
14 $Rev: 25753 $
15 $Author: hiratsu_daisuke $
16 *-------------------------------------------------------------------------*/
17
18 #include "stdafx.h"
19
20 #include "rdt_ReceiverImpl.h"
21
22 #include <nn/rdt/CTR/rdt_define.h>
23 #include <nn/rdt/CTR/rdt_Result.h>
24
25
26 namespace
27 {
28
29 } // end of anonymous namespace
30
31 namespace nn { namespace rdt { namespace CTR {
32
33
34 // 「状態」の基底クラス。
35 class ReceiverStateBase{
36 public:
~ReceiverStateBase(void)37 virtual ~ReceiverStateBase(void){}
38
39 virtual void initialize(ReceiverImpl *pReceiver); // この状態が開始されるときに呼ばれる
40 virtual void finalize (ReceiverImpl *pReceiver); // この状態が終了されるときに呼ばれる
41 virtual void update (ReceiverImpl *pReceiver);
42 virtual enum ReceiverState getStatus(void) const = 0;
43
44 protected:
ReceiverStateBase(void)45 ReceiverStateBase(void){}
46 };
47
48
initialize(ReceiverImpl * pReceiver)49 void ReceiverStateBase::initialize(ReceiverImpl *pReceiver)
50 {
51 (void)pReceiver;
52 }
53
54
finalize(ReceiverImpl * pReceiver)55 void ReceiverStateBase::finalize(ReceiverImpl *pReceiver)
56 {
57 (void)pReceiver;
58 }
59
60
update(ReceiverImpl * pReceiver)61 void ReceiverStateBase::update(ReceiverImpl *pReceiver)
62 {
63 (void)pReceiver;
64 }
65
66
67 class ReceiverStateWaiting : public ReceiverStateBase{
68 public:
69 static ReceiverStateBase* getInstance(void);
70 virtual void update(ReceiverImpl *pReceiver);
71 virtual enum ReceiverState getStatus(void) const;
72
73 protected:
ReceiverStateWaiting(void)74 ReceiverStateWaiting(void){}
75 };
76
77
78 class ReceiverStateOpened : public ReceiverStateBase{
79 public:
80 static ReceiverStateBase* getInstance(void);
81 virtual void update(ReceiverImpl *pReceiver);
82 virtual enum ReceiverState getStatus(void) const;
83
84 protected:
ReceiverStateOpened(void)85 ReceiverStateOpened(void){}
86 };
87
88
89 class ReceiverStateWaitingFinished : public ReceiverStateBase{
90 public:
91 static ReceiverStateBase* getInstance(void);
92 virtual void update(ReceiverImpl *pReceiver);
93 virtual enum ReceiverState getStatus(void) const;
94
95 protected:
ReceiverStateWaitingFinished(void)96 ReceiverStateWaitingFinished(void){}
97 };
98
99
100 class ReceiverStateFinished : public ReceiverStateBase{
101 public:
102 static ReceiverStateBase* getInstance(void);
103 virtual void update(ReceiverImpl *pReceiver);
104 virtual enum ReceiverState getStatus(void) const;
105
106 protected:
ReceiverStateFinished(void)107 ReceiverStateFinished(void){}
108 };
109
110
111 class ReceiverStateClosed : public ReceiverStateBase{
112 public:
113 static ReceiverStateBase* getInstance(void);
114 virtual void initialize(ReceiverImpl *pReceiver);
115 virtual void update (ReceiverImpl *pReceiver);
116 virtual enum ReceiverState getStatus(void) const;
117
118 protected:
ReceiverStateClosed(void)119 ReceiverStateClosed(void){}
120 };
121
122
123 // 以下、派生クラスの実装。
124
getInstance(void)125 ReceiverStateBase* ReceiverStateWaiting::getInstance(void)
126 {
127 static ReceiverStateWaiting s_instance;
128 return &s_instance;
129 }
130
131
getStatus(void) const132 enum ReceiverState ReceiverStateWaiting::getStatus(void) const
133 {
134 return RECEIVER_STATE_WAITING;
135 }
136
137
update(ReceiverImpl * pReceiver)138 void ReceiverStateWaiting::update(ReceiverImpl *pReceiver)
139 {
140 ASSERT(pReceiver!=NULL);
141
142 //セグメントを受信していれば、ここで処理。
143 Segment seg;
144 if(pReceiver->pullSegment(&seg).IsSuccess())
145 {
146 if(seg.IsRst())
147 {
148 // TCPのRFCによると、LISTEN状態の時に受信したRSTは
149 // 無視すべき、との記述があった。よって、ここでは何もしない。
150 }
151 else if(seg.IsSyn())
152 {
153 // リモートからの正しい接続要求であれば、ACKを返す。
154
155 // 受信バッファの設定
156 pReceiver->m_recvBuf.SetInitialSequenceNumber(seg.GetSeqNumber());
157
158 // SYNへの応答。
159 pReceiver->putSynAckSegment(seg.GetSeqNumber() + 1);
160 pReceiver->setNextState(ReceiverStateOpened::getInstance());
161 }
162 }
163 }
164
165
getInstance(void)166 ReceiverStateBase* ReceiverStateOpened::getInstance(void)
167 {
168 static ReceiverStateOpened s_instance;
169 return &s_instance;
170 }
171
172
getStatus(void) const173 enum ReceiverState ReceiverStateOpened::getStatus(void) const
174 {
175 return RECEIVER_STATE_OPENED;
176 }
177
178
update(ReceiverImpl * pReceiver)179 void ReceiverStateOpened::update(ReceiverImpl *pReceiver)
180 {
181 ASSERT(pReceiver!=NULL);
182
183 //セグメントを受信していれば、ここで処理。
184 Segment seg;
185 if(pReceiver->pullSegment(&seg).IsSuccess())
186 {
187 // まずはRSTビットチェック
188 if(seg.IsRst())
189 {
190 pReceiver->setNextState(ReceiverStateClosed::getInstance());
191 pReceiver->errorHandling(ResultResetReceived());
192 return;
193 }
194
195 // 期待しているシーケンス番号のセグメントが到着しているか?
196 ReceiveBuffer &rBuf = pReceiver->m_recvBuf;
197 if(seg.GetSeqNumber()==rBuf.GetLatestSequenceNumber()+1)
198 {
199 if(seg.IsData())
200 {
201 bool result = rBuf.Push(seg.payload, seg.GetDataLength());
202 if(result)
203 {
204 // データを無事に受信バッファに格納できた。
205 // 従来の実装ではACKを返していたが、それでは受信側のACKパケットばかりになってしまう。
206 // そこで、ここでACKを返すのはやめた。
207 }
208 else
209 {
210 LOG("Received data segment, but could not return ACK because receive buffer did not have enough space.\n");
211 }
212 }
213 else if(seg.IsFin())
214 {
215 // FINセグメントに対するACK送信
216 pReceiver->putFinAckSegment(seg.GetSeqNumber() + 1);
217 pReceiver->setNextState(ReceiverStateWaitingFinished::getInstance());
218 }
219 else
220 {
221 seg.PrintDebugInfo();
222 PANIC("It seems that SEQ number is valid, but unexpected segment. It is not DATA, nor FIN.");
223 }
224 }
225 else if(seg.GetSeqNumber()==rBuf.GetLatestSequenceNumber())
226 {
227 // Synに対する応答が届かなかった場合に、SenderはSyn要求を再送することが考えられる。
228 // その場合の対処。
229 if(seg.IsSyn())
230 {
231 // SYNへの応答。
232 pReceiver->putSynAckSegment(seg.GetSeqNumber() + 1);
233 }
234 }
235
236 else
237 {
238 VERBOSE("Unexpected SEQ number. (%d)\n", seg.GetSeqNumber());
239 VERBOSE("SEQ number %d is expected.\n", rBuf.GetLatestSequenceNumber()+1);
240 VERBOSE("Received segment will be ignored.\n");
241
242 #if 0
243 // 期待していないセグメントだったので、パケロスの可能性が疑われる。
244 // ひとまず今まで受信できた分には速やかにACKを返す。
245 pReceiver->putAckSegment();
246
247 // ↑このコードを入れると、返って遅くなってしまった。ACKパケットが大量発生したからだろうか…
248 #endif
249 }
250 }
251 }
252
253
getInstance(void)254 ReceiverStateBase* ReceiverStateWaitingFinished::getInstance(void)
255 {
256 static ReceiverStateWaitingFinished s_instance;
257 return &s_instance;
258 }
259
260
getStatus(void) const261 enum ReceiverState ReceiverStateWaitingFinished::getStatus(void) const
262 {
263 return RECEIVER_STATE_WAITING_FINISHED;
264 }
265
266
update(ReceiverImpl * pReceiver)267 void ReceiverStateWaitingFinished::update(ReceiverImpl *pReceiver)
268 {
269 // こちらがFINに対するACKを返し、Finished状態になったとしても、
270 // そのACKが向こうに届いているとは限らない。
271 // ACKが向こうに届いたと判断するためには、ある程度の時間をおき、
272 // 向こうから再送パケットが届かなくなることを確認する必要がある。
273
274 ASSERT(pReceiver!=NULL);
275
276 //セグメントを受信していれば、ここで処理。
277 Segment seg;
278 if(pReceiver->pullSegment(&seg).IsSuccess())
279 {
280 // RSTビットチェック
281 if(seg.IsRst())
282 {
283 pReceiver->setNextState(ReceiverStateClosed::getInstance());
284 pReceiver->errorHandling(ResultResetReceived());
285 return;
286 }
287
288 // FINのセグメントが到着しているか?
289 ReceiveBuffer &rBuf = pReceiver->m_recvBuf;
290 if(seg.GetSeqNumber()==rBuf.GetLatestSequenceNumber()+1)
291 {
292 if(seg.IsFin())
293 {
294 pReceiver->putFinAckSegment(seg.GetSeqNumber() + 1);
295 }
296 else
297 {
298 seg.PrintDebugInfo();
299 PANIC("Sequence number is valid, but FIN is not included.\n");
300 }
301 }
302 else
303 {
304 // seg.PrintDebugInfo();
305 LOG("Segment with unexpected sequence number. Ignored.\n");
306 }
307 }
308
309 // タイムアウト判定をしてから、状態遷移。
310 if(pReceiver->isSenderClosed())
311 {
312 pReceiver->setNextState(ReceiverStateFinished::getInstance());
313 }
314 }
315
316
getInstance(void)317 ReceiverStateBase* ReceiverStateFinished::getInstance(void)
318 {
319 static ReceiverStateFinished s_instance;
320 return &s_instance;
321 }
322
323
getStatus(void) const324 enum ReceiverState ReceiverStateFinished::getStatus(void) const
325 {
326 return RECEIVER_STATE_FINISHED;
327 }
328
329
update(ReceiverImpl * pReceiver)330 void ReceiverStateFinished::update(ReceiverImpl *pReceiver)
331 {
332 ASSERT(pReceiver!=NULL);
333
334 //セグメントを受信していれば、ここで処理。
335 Segment seg;
336 if(pReceiver->pullSegment(&seg).IsSuccess())
337 {
338 // TODO: RSTを含まないセグメントに対しては、RSTを送信すべき。
339 PANIC("State is FINISHED, but received segment from remote!\n");
340 }
341 }
342
343
344
getInstance(void)345 ReceiverStateBase* ReceiverStateClosed::getInstance(void)
346 {
347 static ReceiverStateClosed s_instance;
348 return &s_instance;
349 }
350
351
getStatus(void) const352 enum ReceiverState ReceiverStateClosed::getStatus(void) const
353 {
354 return RECEIVER_STATE_CLOSED;
355 }
356
357
initialize(ReceiverImpl * pReceiver)358 void ReceiverStateClosed::initialize(ReceiverImpl *pReceiver)
359 {
360 ASSERT(pReceiver!=NULL);
361
362 pReceiver->clear();
363 }
364
365
update(ReceiverImpl * pReceiver)366 void ReceiverStateClosed::update(ReceiverImpl *pReceiver)
367 {
368 ASSERT(pReceiver!=NULL);
369
370 // CLOSED状態の時に受信した(RSTを含まない)セグメントに対しては、RSTで返答
371 Segment seg;
372 if(pReceiver->pullSegment(&seg).IsSuccess() && !seg.IsRst())
373 {
374 LOG("Receiver is in CLOSED state, but received segment. RST will be sent.\n");
375 if(seg.IsAck())
376 {
377 pReceiver->sendRstSegment(seg.GetAckNumber());
378 }
379 else
380 {
381 const u32 SEQ = 0;
382 const u32 ACK = seg.GetSeqNumber() + seg.GetSegmentLength();
383 pReceiver->sendRstAckSegment(SEQ, ACK);
384 }
385 }
386 }
387
388
389
390 ///< コンストラクタ
ReceiverImpl(void)391 ReceiverImpl::ReceiverImpl(void) throw()
392 :m_initialized(false)
393 {
394 }
395
396
397 ///< デストラクタ
~ReceiverImpl(void)398 ReceiverImpl::~ReceiverImpl(void)
399 {
400 Finalize();
401 }
402
403
404 #ifdef _WIN32
Initialize(SOCKET sock,void * pRecvBuf,u16 recvBufSize)405 nn::Result ReceiverImpl::Initialize(SOCKET sock, void *pRecvBuf, u16 recvBufSize)
406 #else
407 nn::Result ReceiverImpl::Initialize(u16 nodeId, u8 port, void *pRecvBuf, u16 recvBufSize)
408 #endif
409 {
410 if(m_initialized)
411 {
412 return ResultAlreadyInitialized();
413 }
414 else
415 {
416 if(pRecvBuf==NULL)
417 {
418 return ResultNullPointer();
419 }
420
421 if(recvBufSize==0)
422 {
423 return ResultInvalidSize();
424 }
425
426 #ifdef _WIN32
427 nn::Result result = HostBase::Initialize(sock);
428 #elif defined(NN_PLATFORM_CTR)
429 nn::Result result = HostBase::Initialize(nodeId, port);
430 #endif
431 if(result.IsFailure())
432 {
433 return result;
434 }
435 else
436 {
437 m_pState = ReceiverStateClosed::getInstance();
438 m_pNextState = NULL;
439 m_recvBuf.Initialize(pRecvBuf, recvBufSize);
440
441 clear();
442
443 m_initialized = true;
444 return ResultSuccess();
445 }
446 }
447 }
448
449
Finalize(void)450 void ReceiverImpl::Finalize(void)
451 {
452 if(m_initialized)
453 {
454 m_initialized = false;
455 m_recvBuf.Finalize();
456 HostBase::Finalize();
457 }
458 else
459 {
460 // Do nothing.
461 }
462 }
463
464
Wait(void)465 nn::Result ReceiverImpl::Wait(void)
466 {
467 ASSERT(m_initialized);
468
469 if(GetStatus()==RECEIVER_STATE_CLOSED)
470 {
471 setNextState(ReceiverStateWaiting::getInstance());
472 changeState();
473 return ResultSuccess();
474 }
475 else
476 {
477 return ResultUntimelyFunctionCall();
478 }
479 }
480
481
Close(void)482 nn::Result ReceiverImpl::Close(void)
483 {
484 ASSERT(m_initialized);
485
486 if(GetStatus()==RECEIVER_STATE_FINISHED)
487 {
488 setNextState(ReceiverStateClosed::getInstance());
489 changeState();
490 return ResultSuccess();
491 }
492 else
493 {
494 return ResultUntimelyFunctionCall();
495 }
496 }
497
498
Receive(void * pBuf,size_t * recvSize,size_t bufSize)499 nn::Result ReceiverImpl::Receive(void *pBuf, size_t *recvSize, size_t bufSize)
500 {
501 ASSERT(m_initialized);
502
503 if((pBuf==NULL) || (recvSize==NULL))
504 {
505 return ResultNullPointer();
506 }
507
508 if(bufSize==0)
509 {
510 return ResultDoNothing();
511 }
512
513 enum ReceiverState stat = GetStatus();
514 if((stat!=RECEIVER_STATE_OPENED) && (stat!=RECEIVER_STATE_WAITING_FINISHED) && (stat!=RECEIVER_STATE_FINISHED))
515 {
516 return ResultUntimelyFunctionCall();
517 }
518
519 *recvSize = m_recvBuf.Read(pBuf, bufSize);
520 if(*recvSize > 0)
521 {
522 m_recvBuf.Pop(*recvSize);
523 }
524
525 // Receiveをトリガーにして、リモートにウィンドウを通知する。
526 // 受信ウィンドウに空きができたので、リモートに通知する目的でセグメントを送信する。
527 // OPENED状態でないときにセグメントを送ろうとすると、接続が断絶している可能性があるので、
528 // if文による状態チェックを行っている。
529 if(GetStatus()==RECEIVER_STATE_OPENED)
530 {
531 putAckSegment();
532 }
533
534 return ResultSuccess();
535 }
536
537
Process(void)538 nn::Result ReceiverImpl::Process(void)
539 {
540 ASSERT(m_initialized);
541
542 // 各状態のupdate()。
543 if(m_pState)
544 {
545 m_pState->update(this);
546 }
547
548 // 状態遷移
549 changeState();
550
551 // エラーはここで返る。
552 // 返したら、エラーはリセットする。
553 nn::Result ret = GetErrorCode();
554 errorHandling(ResultSuccess());
555 return ret;
556 }
557
558
GetStatus(void) const559 enum ReceiverState ReceiverImpl::GetStatus(void) const
560 {
561 ASSERT(m_initialized);
562 ASSERTMSG(m_pState!=NULL, "It seems that state is not initialized.\n");
563
564 return m_pState->getStatus();
565 }
566
567
Cancel(void)568 void ReceiverImpl::Cancel(void)
569 {
570 ASSERT(m_initialized);
571
572 // キャンセル処理は、Process()関数を待たずに即座に実行させる。
573
574 // RST送信
575 const u32 seq = 0;
576 sendRstSegment(seq);
577
578 // 即座にClosed状態へ。
579 setNextState(ReceiverStateClosed::getInstance());
580 changeState();
581 }
582
583
584 // 状態遷移。次の状態がセットされていないなら、特に何もしない。
changeState(void)585 void ReceiverImpl::changeState(void)
586 {
587 if(m_pNextState)
588 {
589 if(m_pState)
590 {
591 m_pState->finalize(this);
592 }
593 m_pState = m_pNextState;
594 m_pNextState = NULL;
595 m_pState->initialize(this);
596 }
597 }
598
599
setNextState(ReceiverStateBase * p)600 void ReceiverImpl::setNextState(ReceiverStateBase *p)
601 {
602 ASSERT(p!=NULL);
603 ASSERT(m_pNextState==NULL);
604
605 m_pNextState = p;
606 }
607
608
putSynAckSegment(u32 ack)609 void ReceiverImpl::putSynAckSegment(u32 ack)
610 {
611 Segment a;
612 a.ClearHeader();
613 a.SetAckNumber(ack);
614 a.SetWindowSize(m_recvBuf.GetRestSize());
615 putSegment(a);
616 }
617
618
putAckSegment(void)619 void ReceiverImpl::putAckSegment(void)
620 {
621 Segment a;
622 a.ClearHeader();
623 a.SetAckNumber(m_recvBuf.GetLatestSequenceNumber()+1);
624 a.SetWindowSize(m_recvBuf.GetRestSize());
625 putSegment(a);
626 }
627
628
putFinAckSegment(u32 ack)629 void ReceiverImpl::putFinAckSegment(u32 ack)
630 {
631 Segment a;
632 a.ClearHeader();
633 a.SetAckNumber(ack);
634 a.SetWindowSize(m_recvBuf.GetRestSize());
635 putSegment(a);
636
637 m_finAckSentTime = GetCurrentTimeAsMillisecond();
638 }
639
640
isSenderClosed(void) const641 bool ReceiverImpl::isSenderClosed(void) const
642 {
643 ASSERT(m_finAckSentTime!=0);
644
645 // LOG("m_finAckSentTime = %lld\n", m_finAckSentTime);
646 // LOG("Current: %lld\n", GetCurrentTimeAsMillisecond());
647 return GetCurrentTimeAsMillisecond() - m_finAckSentTime > FIN_TIMEOUT;
648 }
649
650
clear(void)651 void ReceiverImpl::clear(void)
652 {
653 m_recvBuf.Clear();
654 m_finAckSentTime = 0;
655 }
656
657
PrintDebugInfo(void) const658 void ReceiverImpl::PrintDebugInfo(void) const
659 {
660 LOG("-- Receiver debug information --\n");
661 LOG("Current state: %d\n", GetStatus());
662 m_recvBuf.PrintDebugInfo();
663 LOG("\n");
664 }
665
666 }}} // namespace nn::rdt::CTR
667