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