1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: rdt_SenderImpl.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_SenderImpl.h"
19
20 #include <nn/rdt/CTR/rdt_define.h>
21 #include <nn/rdt/CTR/rdt_Result.h>
22
23 #include "rdt_Stopwatch.h"
24
25 #include "Test.h"
26
27
28 namespace
29 {
30
31 } // End of anonymous namespace
32
33
34 namespace nn { namespace rdt { namespace CTR {
35
36
37 // Base class for "state."
38 class SenderStateBase{
39 public:
~SenderStateBase(void)40 virtual ~SenderStateBase(void){}
41
42 virtual void initialize(SenderImpl *pSender); // Called when this state begins
43 virtual void finalize (SenderImpl *pSender); // Called when this state ends
44 void update (SenderImpl *pSender);
45 virtual void updatePrologue (SenderImpl *pSender);
46 virtual void updateCore (SenderImpl *pSender);
47 virtual void updateEpilogue (SenderImpl *pSender);
48 virtual enum SenderState getStatus(void) const = 0;
49
50 protected:
SenderStateBase(void)51 SenderStateBase(void){}
52 };
53
54
initialize(SenderImpl * pSender)55 void SenderStateBase::initialize(SenderImpl *pSender)
56 {
57 (void)pSender;
58 }
59
60
finalize(SenderImpl * pSender)61 void SenderStateBase::finalize(SenderImpl *pSender)
62 {
63 (void)pSender;
64 }
65
66
updatePrologue(SenderImpl * pSender)67 void SenderStateBase::updatePrologue(SenderImpl *pSender)
68 {
69 (void)pSender;
70 }
71
72
updateCore(SenderImpl * pSender)73 void SenderStateBase::updateCore(SenderImpl *pSender)
74 {
75 (void)pSender;
76 }
77
78
updateEpilogue(SenderImpl * pSender)79 void SenderStateBase::updateEpilogue(SenderImpl *pSender)
80 {
81 (void)pSender;
82 }
83
84
update(SenderImpl * pSender)85 void SenderStateBase::update(SenderImpl *pSender)
86 {
87 updatePrologue(pSender);
88 updateCore(pSender);
89 updateEpilogue(pSender);
90 }
91
92
93 class SenderStateOpenRequested : public SenderStateBase{
94 public:
95 static SenderStateBase* getInstance(void);
96
97 virtual void updateCore(SenderImpl *pSender);
98 virtual enum SenderState getStatus(void) const;
99
100 protected:
SenderStateOpenRequested(void)101 SenderStateOpenRequested(void){}
102 };
103
104
105 class SenderStateOpening : public SenderStateBase{
106 public:
107 static SenderStateBase* getInstance(void);
108
109 virtual void updateCore(SenderImpl *pSender);
110 virtual enum SenderState getStatus(void) const;
111
112 protected:
SenderStateOpening(void)113 SenderStateOpening(void){}
114 };
115
116
117 class SenderStateOpened : public SenderStateBase{
118 public:
119 static SenderStateBase* getInstance(void);
120
121 virtual void updateCore(SenderImpl *pSender);
122 virtual enum SenderState getStatus(void) const;
123
124 protected:
SenderStateOpened(void)125 SenderStateOpened(void){}
126 };
127
128
129 class SenderStateCloseRequested : public SenderStateBase{
130 public:
131 static SenderStateBase* getInstance(void);
132
133 virtual void updateCore(SenderImpl *pSender);
134 virtual enum SenderState getStatus(void) const;
135
136 protected:
SenderStateCloseRequested(void)137 SenderStateCloseRequested(void){}
138 };
139
140
141 class SenderStateClosing : public SenderStateBase{
142 public:
143 static SenderStateBase* getInstance(void);
144
145 virtual void updateCore(SenderImpl *pSender);
146 virtual enum SenderState getStatus(void) const;
147
148 protected:
SenderStateClosing(void)149 SenderStateClosing(void){}
150 };
151
152
153 class SenderStateClosed : public SenderStateBase{
154 public:
155 static SenderStateBase* getInstance(void);
156
157 virtual void initialize(SenderImpl *pSender);
158 virtual void updateCore(SenderImpl *pSender);
159 virtual enum SenderState getStatus(void) const;
160
161 protected:
SenderStateClosed(void)162 SenderStateClosed(void){}
163 };
164
165
166 // Below is the implementation of the State derived class.
getInstance(void)167 SenderStateBase* SenderStateClosed::getInstance(void)
168 {
169 static SenderStateClosed s_instance;
170 return &s_instance;
171 }
172
173
getStatus(void) const174 enum SenderState SenderStateClosed::getStatus(void) const
175 {
176 return SENDER_STATE_CLOSED;
177 }
178
179
initialize(SenderImpl * pSender)180 void SenderStateClosed::initialize(SenderImpl *pSender)
181 {
182 ASSERT(pSender!=NULL);
183
184 pSender->clear();
185 }
186
187
updateCore(SenderImpl * pSender)188 void SenderStateClosed::updateCore(SenderImpl *pSender)
189 {
190 ASSERT(pSender!=NULL);
191
192 // Respond with RST to segments without RST that were received during CLOSED state
193 Segment seg;
194 if(pSender->pullSegment(&seg).IsSuccess() && !seg.IsRst())
195 {
196 #if 0
197 LOG("The Sender is in a CLOSED state, but because the segment was received, responds with RST. \n");
198 LOG("The received segment contains \n.");
199 seg.PrintDebugInfo();
200 LOG(" \n");
201 const u32 SEQ = 0;
202 pSender->sendRstSegment(SEQ);
203 #else
204 LOG("Sender is in CLOSED state, but received segment. Ignored.\n");
205 #endif
206 }
207 }
208
209
getInstance(void)210 SenderStateBase* SenderStateOpenRequested::getInstance(void)
211 {
212 static SenderStateOpenRequested s_instance;
213 return &s_instance;
214 }
215
216
getStatus(void) const217 enum SenderState SenderStateOpenRequested::getStatus(void) const
218 {
219 return SENDER_STATE_OPEN_REQUESTED;
220 }
221
222
updateCore(SenderImpl * pSender)223 void SenderStateOpenRequested::updateCore(SenderImpl *pSender)
224 {
225 // Send connection request segment
226 pSender->sendSynSegment();
227
228 // Go to the next state.
229 pSender->setNextState(SenderStateOpening::getInstance());
230 }
231
232
getInstance(void)233 SenderStateBase* SenderStateOpening::getInstance(void)
234 {
235 static SenderStateOpening s_instance;
236 return &s_instance;
237 }
238
239
getStatus(void) const240 enum SenderState SenderStateOpening::getStatus(void) const
241 {
242 return SENDER_STATE_OPENING;
243 }
244
245
updateCore(SenderImpl * pSender)246 void SenderStateOpening::updateCore(SenderImpl *pSender)
247 {
248 ASSERT(pSender!=NULL);
249
250 // Check content of the received segment.
251 Segment seg;
252 if(pSender->pullSegment(&seg).IsSuccess())
253 {
254 pSender->processReceivedSegment(seg);
255
256 if(seg.IsRst())
257 {
258 // Check if the RST is for this SYN. If not, discard segment.
259 if(seg.IsAck() && seg.GetAckNumber()==pSender->getInitialSequenceNumber()+1)
260 {
261 // Treat as though the SYN was refused. To CLOSED.
262 LOG("SYN rejected. CLOSED... ack of segment = %u\n", seg.GetAckNumber());
263 pSender->setNextState(SenderStateClosed::getInstance());
264 pSender->errorHandling(ResultResetReceived());
265 return;
266 }
267 else
268 {
269 LOG("Ignored RST segment.\n");
270 }
271 }
272 else if(seg.IsAck())
273 {
274 if(seg.GetAckNumber()==pSender->getInitialSequenceNumber()+1)
275 {
276 // Transition to next state because an ACK was received for the SYN.
277 pSender->setNextState(SenderStateOpened::getInstance());
278 }
279 else
280 {
281 LOG("ack : %u\n", seg.GetAckNumber());
282 LOG("una : %u\n", pSender->getUnacknowledgeNumber());
283 LOG("nxt : %u\n", pSender->getNextSequenceNumber());
284 LOG("It seems that it isn't ACK for SYN. Ignored\n");
285 }
286 }
287 }
288
289 // Resend process.
290 pSender->processResending();
291 }
292
293
getInstance(void)294 SenderStateBase* SenderStateOpened::getInstance(void)
295 {
296 static SenderStateOpened s_instance;
297 return &s_instance;
298 }
299
300
getStatus(void) const301 enum SenderState SenderStateOpened::getStatus(void) const
302 {
303 return SENDER_STATE_OPENED;
304 }
305
306
updateCore(SenderImpl * pSender)307 void SenderStateOpened::updateCore(SenderImpl *pSender)
308 {
309 ASSERT(pSender!=NULL);
310
311 // Check content of the received segment.
312 Segment seg;
313 if(pSender->pullSegment(&seg).IsSuccess())
314 {
315 pSender->processReceivedSegment(seg);
316
317 if(seg.IsRst())
318 {
319 // Because it was RST, goes to CLOSED.
320 pSender->setNextState(SenderStateClosed::getInstance());
321 pSender->errorHandling(ResultResetReceived());
322 return;
323 }
324 }
325
326 bool bSent = false; // Set to TRUE if the send process has been executed.
327
328 // Resend process.
329 bSent = pSender->processResending();
330
331 // A chance for data transmission if the send process has not occurred even once.
332 if(!bSent)
333 {
334 if(!pSender->isSendBufferEmpty())
335 {
336 pSender->sendData();
337 bSent = true;
338 }
339 }
340 }
341
342
getInstance(void)343 SenderStateBase* SenderStateCloseRequested::getInstance(void)
344 {
345 static SenderStateCloseRequested s_instance;
346 return &s_instance;
347 }
348
349
getStatus(void) const350 enum SenderState SenderStateCloseRequested::getStatus(void) const
351 {
352 return SENDER_STATE_CLOSE_REQUESTED;
353 }
354
355
updateCore(SenderImpl * pSender)356 void SenderStateCloseRequested::updateCore(SenderImpl *pSender)
357 {
358 ASSERT(pSender!=NULL);
359
360 // Check content of the received segment. Around this is the same as the Opened state.
361 Segment seg;
362 if(pSender->pullSegment(&seg).IsSuccess())
363 {
364 pSender->processReceivedSegment(seg);
365
366 if(seg.IsRst())
367 {
368 // Because it was RST, goes to CLOSED.
369 pSender->setNextState(SenderStateClosed::getInstance());
370 pSender->errorHandling(ResultResetReceived());
371 return;
372 }
373 }
374
375 bool bSent = false; // Set to TRUE if the send process has been executed.
376
377 // Resend process.
378 bSent = pSender->processResending();
379
380 if(pSender->isSendBufferEmpty())
381 {
382 // Send FIN segment
383 if(!bSent)
384 {
385 pSender->sendFinSegment();
386 bSent = true;
387
388 // To CLOSING state.
389 pSender->setNextState(SenderStateClosing::getInstance());
390 }
391 }
392 else
393 {
394 // Releases the send buffer data
395 if(!bSent)
396 {
397 pSender->sendData();
398 bSent = true;
399 }
400 }
401
402 // A chance for data transmission if the send process has not occurred even once.
403 if(!bSent)
404 {
405 if(!pSender->isSendBufferEmpty())
406 {
407 pSender->sendData();
408 bSent = true;
409 }
410 }
411 }
412
413
getInstance(void)414 SenderStateBase* SenderStateClosing::getInstance(void)
415 {
416 static SenderStateClosing s_instance;
417 return &s_instance;
418 }
419
420
getStatus(void) const421 enum SenderState SenderStateClosing::getStatus(void) const
422 {
423 return SENDER_STATE_CLOSING;
424 }
425
426
updateCore(SenderImpl * pSender)427 void SenderStateClosing::updateCore(SenderImpl *pSender)
428 {
429 ASSERT(pSender!=NULL);
430
431 // Resend process.
432 pSender->processResending();
433
434 // Check content of the received segment.
435 Segment seg;
436 if(pSender->pullSegment(&seg).IsSuccess())
437 {
438 pSender->processReceivedSegment(seg);
439
440 if(seg.IsRst())
441 {
442 // Because it was RST, goes to CLOSED.
443 pSender->setNextState(SenderStateClosed::getInstance());
444 pSender->errorHandling(ResultResetReceived());
445 return;
446 }
447 else if(seg.IsAck() && seg.GetAckNumber()==pSender->m_sendBuffer.GetCurrentSequenceNumber()+1)
448 {
449 // Check content of the received segment. (FIN check.)
450 // Because an ACK was received for the FIN, goes to CLOSED.
451 pSender->setNextState(SenderStateClosed::getInstance());
452 }
453 else
454 {
455 VERBOSE("Although a segment was received, it does not seem to be an ACK segment to FIN. Destroy. \n");
456 }
457 }
458 }
459
460
461
462 //
SenderImpl(void)463 SenderImpl::SenderImpl(void) throw()
464 :m_initialized(false)
465 {
466 }
467
468
469 //
~SenderImpl(void)470 SenderImpl::~SenderImpl(void)
471 {
472 Finalize();
473 }
474
475
476 #ifdef _WIN32
Initialize(SOCKET sock,void * pSendBuf,u16 sendBufSize)477 nn::Result SenderImpl::Initialize(SOCKET sock, void *pSendBuf, u16 sendBufSize)
478 #else
479 nn::Result SenderImpl::Initialize(u16 nodeId, u8 port, void *pSendBuf, u16 sendBufSize)
480 #endif
481 {
482 if(m_initialized)
483 {
484 return ResultAlreadyInitialized();
485 }
486 else
487 {
488 if(pSendBuf==NULL)
489 {
490 return ResultNullPointer();
491 }
492
493 if(sendBufSize==0)
494 {
495 return ResultInvalidSize();
496 }
497
498 #ifdef _WIN32
499 nn::Result result = HostBase::Initialize(sock);
500 #elif defined(NN_PLATFORM_CTR)
501 nn::Result result = HostBase::Initialize(nodeId, port);
502 #endif
503 if(result.IsFailure())
504 {
505 return result;
506 }
507 else
508 {
509 m_sendBuffer.Initialize(pSendBuf, sendBufSize);
510 m_pState = SenderStateClosed::getInstance();
511 m_pNextState = NULL;
512
513 clear();
514
515 m_initialized = true;
516 return ResultSuccess();
517 }
518 }
519 }
520
521
Finalize(void)522 void SenderImpl::Finalize(void)
523 {
524 if(m_initialized)
525 {
526 m_initialized = false;
527 m_sendBuffer.Finalize();
528 HostBase::Finalize();
529 }
530 else
531 {
532 // Do nothing.
533 }
534 }
535
536
Process(void)537 nn::Result SenderImpl::Process(void)
538 {
539 ASSERT(m_initialized);
540
541 // The update function according to the state
542 if(m_pState)
543 {
544 m_pState->update(this);
545 }
546
547 // State Transitions
548 changeState();
549
550 // For debugging
551 // PrintDebugInfo();
552
553 // Errors are returned here.
554 // If returned, errors are reset.
555 nn::Result ret = GetErrorCode();
556 errorHandling(ResultSuccess());
557 return ret;
558 }
559
560
Open(void)561 nn::Result SenderImpl::Open(void)
562 {
563 ASSERT(m_initialized);
564
565 if(GetStatus()==SENDER_STATE_CLOSED)
566 {
567 setNextState(SenderStateOpenRequested::getInstance());
568 changeState();
569 return ResultSuccess();
570 }
571 else
572 {
573 return ResultUntimelyFunctionCall();
574 }
575 }
576
577
Close(void)578 nn::Result SenderImpl::Close(void)
579 {
580 ASSERT(m_initialized);
581
582 if(GetStatus()==SENDER_STATE_OPENED)
583 {
584 setNextState(SenderStateCloseRequested::getInstance());
585 changeState();
586 return ResultSuccess();
587 }
588 else
589 {
590 // Error if the Close function is called while in a CLOSED state.
591 // This behavior follows the TCP RFC, and this behavior is also included here.
592 return ResultUntimelyFunctionCall();
593 }
594 }
595
596
Send(const void * pBuf,size_t bufSize)597 nn::Result SenderImpl::Send(const void *pBuf, size_t bufSize)
598 {
599 ASSERT(m_initialized);
600
601 if(pBuf==NULL)
602 {
603 return ResultNullPointer();
604 }
605
606 if(bufSize==0)
607 {
608 return ResultDoNothing();
609 }
610
611 if(GetStatus()!=SENDER_STATE_OPENED)
612 {
613 return ResultUntimelyFunctionCall();
614 }
615
616 if(m_sendBuffer.Push(pBuf, bufSize))
617 {
618 return ResultSuccess();
619 }
620 else
621 {
622 return ResultSendBufferIsNotAvailable();
623 }
624 }
625
626
Cancel(void)627 void SenderImpl::Cancel(void)
628 {
629 ASSERT(m_initialized);
630
631 // Cancel processes execute immediately without waiting for the Process function.
632 // This way of implementing error handling might be easier for the application to use.
633 //
634
635 // RST transmission
636 sendRstSegment(m_sendBuffer.GetCurrentSequenceNumber());
637
638 // Immediately to Closed state.
639 setNextState(SenderStateClosed::getInstance());
640 changeState();
641 }
642
643
GetStatus(void) const644 enum SenderState SenderImpl::GetStatus(void) const
645 {
646 ASSERT(m_initialized);
647 ASSERT(m_pState!=NULL);
648
649 return m_pState->getStatus();
650 }
651
652
processResending(void)653 bool SenderImpl::processResending(void)
654 {
655 Segment seg;
656 // Either a segment that had met a timeout was found in the queue, or such a segment was found and is in a state to wait for the sending of the remaining segments to complete.
657 //
658 //
659 if(m_resendQueue.IsResendMode())
660 {
661 bool ret = m_resendQueue.Front(&seg);
662 ASSERT(ret);
663 VERBOSE("Execute the new send or resend process. \n");
664 VERBOSE("The send segment sequence number is: %d. \n", seg.GetSeqNumber());
665 putSegment(seg);
666
667 static detail::Stopwatch s_sp("ResendQueue::TryAgain()");
668 s_sp.Start();
669 m_resendQueue.TryAgain(); // Sends the first request in the queue to the end.
670 s_sp.Stop();
671 return true;
672 }
673 else
674 {
675 return false;
676 }
677 }
678
679
sendData(void)680 void SenderImpl::sendData(void)
681 {
682 if(m_sendBuffer.IsEmpty())
683 {
684 VERBOSE("The send buffer was empty, so the send process is not run. \n");
685 return;
686 }
687
688 u32 unackDataSize = m_resendQueue.GetTotalDataSize();
689 if(unackDataSize >= m_remoteWindowSize)
690 {
691 VERBOSE("The unconfirmed received data is larger than the receive window size, so the data send is skipped. \n");
692 return;
693 }
694
695 if(m_resendQueue.IsFull())
696 {
697 VERBOSE("The resend queue is full, so the send process is not run. \n");
698 return;
699 }
700
701 size_t vacant = m_remoteWindowSize - unackDataSize;
702 size_t pullSize = min(Segment::PAYLOAD_SIZE, vacant); // Amount taken from the send buffer.
703 ASSERT(pullSize > 0);
704
705 // The data send process.
706 Segment seg;
707 seg.ClearHeader();
708 u32 seq = 0;
709
710 // Runs the process to pack data in the segment.
711 size_t sz = m_sendBuffer.Pull(seg.payload, &seq, pullSize);
712 ASSERT(sz > 0);
713
714 // To get to here, the send process must be guaranteed to have been run (that is, the resend queue must have space).
715 //
716 seg.header.dataLength = sz;
717 seg.SetSeqNumber(seq);
718 putSegmentWithResend(seg);
719 }
720
721
sendSynSegment(void)722 void SenderImpl::sendSynSegment(void)
723 {
724 Segment seg;
725 seg.ClearHeader();
726 seg.SetSeqNumber(getInitialSequenceNumber());
727 seg.SetSyn();
728 putSegmentWithResend(seg);
729 }
730
731
sendFinSegment(void)732 void SenderImpl::sendFinSegment(void)
733 {
734 ASSERTMSG(m_sendBuffer.IsEmpty(), "You cannot request FIN if send buffer is not empty.");
735
736 VERBOSE("sendFinSegment() called.\n");
737
738 Segment seg;
739 seg.ClearHeader();
740 seg.SetFin();
741 seg.SetSeqNumber(m_sendBuffer.GetCurrentSequenceNumber());
742 putSegmentWithResend(seg);
743 }
744
745
clear(void)746 void SenderImpl::clear(void)
747 {
748 m_resendQueue.Clear();
749 m_remoteWindowSize = 0;
750 #if 1
751 m_iss = static_cast<u32>(0xffffffff & GetCurrentTimeAsMillisecond());
752 #else
753 m_iss = 0xffffffff - 100;
754 #endif
755 m_sendBuffer.Clear(m_iss);
756 m_una = m_iss;
757 m_nxt = m_iss;
758
759 m_arrivals = 0;
760 }
761
762
isValidAckNumber(u32 ack) const763 bool SenderImpl::isValidAckNumber(u32 ack) const
764 {
765 s32 s32_ack = static_cast<s32>(ack);
766 s32 s32_una = static_cast<s32>(getUnacknowledgeNumber());
767 s32 s32_nxt = static_cast<s32>(getNextSequenceNumber());
768
769 // The permission ACK inequality expresses snd.una < seg.ack <= snd.nxt.
770 if((0 <= s32_una - s32_ack) || (0 < s32_ack - s32_nxt))
771 {
772 return false;
773 }
774 else
775 {
776 return true;
777 }
778 }
779
780
781
782 // State Transitions. Do nothing in particular if the next state is not set.
changeState(void)783 void SenderImpl::changeState(void)
784 {
785 if(m_pNextState)
786 {
787 if(m_pState)
788 {
789 m_pState->finalize(this);
790 }
791 m_pState = m_pNextState;
792 m_pNextState = NULL;
793 m_pState->initialize(this);
794 }
795 }
796
797
setNextState(SenderStateBase * p)798 void SenderImpl::setNextState(SenderStateBase *p)
799 {
800 ASSERT(p!=NULL);
801 ASSERT(m_pNextState==NULL);
802
803 m_pNextState = p;
804 }
805
806
putSegmentWithResend(const Segment & seg)807 void SenderImpl::putSegmentWithResend(const Segment &seg)
808 {
809 // As long as the resend queue is full, reliable communication is not possible.
810 ASSERT(!m_resendQueue.IsFull());
811
812 putSegment(seg);
813
814 // All segments depend on being resend targets.
815 // If the SYN segment is removed from the resend target, it will not work.
816 //
817 m_nxt = seg.GetLastSeqNumber() + 1;
818
819 // Place a segment in the resend queue.
820 // The sender must resend if an "arrival" cannot be confirmed.
821 // The receiver does not track whether its response is received by the sender.
822 // If the receiver's response is not received by the sender, the sender must resend.
823 bool ret = m_resendQueue.Push(seg);
824 if(!ret)
825 {
826 errorHandling(ResultResendQueueIsFull());
827 PANIC("It seems that resend queue in RDT library is full.");
828 }
829 }
830
831
processReceivedSegment(const Segment & seg)832 void SenderImpl::processReceivedSegment(const Segment &seg)
833 {
834 // The processes that must be run when a segment arrives are summarized here.
835 //
836
837 ++m_arrivals;
838
839 // ACK field check
840 if(seg.IsAck())
841 {
842 const u32 ack = seg.GetAckNumber();
843 if(isValidAckNumber(ack))
844 {
845 m_una = ack;
846
847 // Packets for which distribution can be confirmed can be deleted from the resend queue.
848 VERBOSE("ACK number %d was received. \n", ack);
849 m_resendQueue.Remove(ack);
850
851 // Update window size
852 m_remoteWindowSize = seg.GetWindowSize();
853 }
854 else
855 {
856 VERBOSE("una : %d\n", getUnacknowledgeNumber());
857 VERBOSE("nxt : %d\n", getNextSequenceNumber());
858 VERBOSE("ACK number is not valid or has already been received. (%u)\n", ack);
859 }
860 }
861 }
862
863
PrintDebugInfo(void) const864 void SenderImpl::PrintDebugInfo(void) const
865 {
866 ASSERT(m_initialized);
867
868 m_resendQueue.PrintDebugInfo();
869 m_sendBuffer.PrintDebugInfo();
870 LOG("m_remoteWindowSize: %d\n", m_remoteWindowSize);
871 LOG("m_arrivals: %u\n", m_arrivals);
872 }
873
874
PrintProperty(void)875 void SenderImpl::PrintProperty(void)
876 {
877 LOG("m_sendBuffer: %d (%d)\n", offsetof(SenderImpl, m_sendBuffer), sizeof(SendBuffer));
878 LOG("m_remoteWindowSize: %d (%d)\n", offsetof(SenderImpl, m_remoteWindowSize), sizeof(u16));
879 LOG("m_resendQueue: %d (%d)\n", offsetof(SenderImpl, m_resendQueue), sizeof(ResendQueue));
880 LOG("m_pState: %d (%d)\n", offsetof(SenderImpl, m_pState), sizeof(SenderStateBase*));
881 LOG("m_pNextState: %d (%d)\n", offsetof(SenderImpl, m_pNextState), sizeof(SenderStateBase*));
882 LOG("m_arrivals: %d (%d)\n", offsetof(SenderImpl, m_arrivals), sizeof(u32));
883
884 LOG("sizeof(SenderImpl)=%ld\n", (long) sizeof(SenderImpl));
885 }
886
887
888 // This stand-alone test aims to be a test that can be run without a Receiver, but it is pending.
889 //
Test(void)890 void SenderImpl::Test(void)
891 {
892 /*
893 const int BUFSIZE = 1024;
894 char buf[BUFSIZE];
895 SenderImpl s;
896 const int SUCCESS = 0;
897 CU_ASSERT(s.GetStatus()==SENDER_STATE_CLOSED);
898 CU_ASSERT(s.Open()==SUCCESS);
899 for(int i=0; i10; ++i)
900 {
901 CU_ASSERT(s.Process()==SUCCESS);
902 CU_ASSERT(s.GetStatus()==SENDER_STATE_OPENING);
903 SleepCurrentThread(50);
904 }
905 CU_ASSERT(s.Cancel()==SUCCESS);
906 while(1)
907 {
908 CU_ASSERT(s.Process()==SUCCESS);
909 CU_ASSERT(s.GetStatus()==SENDER_STATE_CLOSED);
910 SleepCurrentThread(50);
911 }
912
913
914
915
916 */
917 }
918
919
920 }}} // namespace nn::rdt::CTR
921