1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     rdt_ReceiveBuffer.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_ReceiveBuffer.h"
19 
20 #include "Test.h"
21 
22 #include "rdt_Utility.h"
23 
24 
25 namespace
26 {
27 
28 }  // End of anonymous namespace
29 
30 namespace nn { namespace rdt { namespace CTR {
31 
32 //
ReceiveBuffer(void)33 ReceiveBuffer::ReceiveBuffer(void)
34      :m_initialized(false)
35 {
36 }
37 
38 
39 //
~ReceiveBuffer(void)40 ReceiveBuffer::~ReceiveBuffer(void)
41 {
42     Finalize();
43 }
44 
45 
46 
Initialize(void * pBuf,u16 bufSize)47 void ReceiveBuffer::Initialize(void *pBuf, u16 bufSize)
48 {
49     ASSERT(pBuf!=NULL);
50     ASSERT(bufSize > 0);
51 
52     if(m_initialized)
53     {
54         LOG("ReceiveBuffer object is already initialized.\n");
55     }
56     else
57     {
58         m_ringBuf.Initialize(pBuf, bufSize);
59         Clear();
60         m_initialized  = true;
61     }
62 }
63 
64 
Finalize(void)65 void ReceiveBuffer::Finalize(void)
66 {
67     if(m_initialized)
68     {
69         m_initialized = false;
70         m_ringBuf.Finalize();
71     }
72 }
73 
74 
SetInitialSequenceNumber(u32 num)75 void ReceiveBuffer::SetInitialSequenceNumber(u32 num)
76 {
77     m_initSeqNum   = num;
78     m_latestSeqNum = num;
79 }
80 
81 
Pop(size_t n)82 void ReceiveBuffer::Pop(size_t n)
83 {
84     ASSERT(m_initialized);
85 
86     ASSERT(n >= 0);
87     m_ringBuf.Pop(n);
88 }
89 
90 
Push(const void * pBuf,size_t len)91 bool ReceiveBuffer::Push(const void *pBuf, size_t len)
92 {
93     ASSERT(m_initialized);
94     ASSERT(pBuf!=NULL);
95     ASSERT(len > 0);
96 
97     bool ret = m_ringBuf.Push(pBuf, len);
98     if(ret)
99     {
100         m_latestSeqNum += len;  // Update most recent octet sequence number
101     }
102     return ret;
103 }
104 
105 
Read(void * pBuf,size_t len)106 size_t ReceiveBuffer::Read(void *pBuf, size_t len)
107 {
108     ASSERT(m_initialized);
109     ASSERT(pBuf!=NULL);
110     ASSERT(len > 0);
111 
112     return m_ringBuf.Read(pBuf, len);
113 }
114 
115 
GetLatestSequenceNumber(void) const116 u32 ReceiveBuffer::GetLatestSequenceNumber(void) const
117 {
118     ASSERT(m_initialized);
119 
120     return m_latestSeqNum;
121 }
122 
123 
GetRestSize(void) const124 size_t ReceiveBuffer::GetRestSize(void) const
125 {
126     ASSERT(m_initialized);
127 
128     size_t ret = m_ringBuf.GetRestSize();
129 
130     // With the Initialize function, because the size can be specified only as u16, it would be odd if it did not fit within this range.
131     //
132     ASSERT((0 <= ret) && (ret <= USHRT_MAX));
133 
134     return ret;
135 }
136 
137 
Clear(void)138 void ReceiveBuffer::Clear(void)
139 {
140     m_ringBuf.Clear();
141     m_initSeqNum   = 0;
142     m_latestSeqNum = 0;
143 }
144 
145 
IsEmpty(void) const146 bool ReceiveBuffer::IsEmpty(void) const
147 {
148     return m_ringBuf.IsEmpty();
149 }
150 
151 
PrintDebugInfo(void) const152 void ReceiveBuffer::PrintDebugInfo(void) const
153 {
154     if(m_initialized)
155     {
156         LOG("Initialized.\n");
157         LOG("Initial sequecne number: %u\n", m_initSeqNum);
158         LOG("Latest octet sequence nubmer: %u\n",  m_latestSeqNum);
159     }
160     else
161     {
162         LOG("Not initialized.\n");
163     }
164 }
165 
166 
167 #ifdef _WIN32
168 // Standalone test with CUnit.
Test(void)169 void ReceiveBuffer::Test(void)
170 {
171     ReceiveBuffer w;
172 
173     const int BUFSIZE = 4096;
174     u8 windowBuf[BUFSIZE];
175     const u32 SEQ_NUM = 100;
176 
177     w.Initialize(windowBuf, BUFSIZE);
178     w.SetInitialSequenceNumber(SEQ_NUM);
179     CU_ASSERT(w.GetRestSize()==BUFSIZE);
180     CU_ASSERT(w.GetLatestSequenceNumber()==SEQ_NUM);
181 
182     char buf[BUFSIZE*2];
183     CU_ASSERT(!w.Push(buf, sizeof(buf)));  // Should fail because trying to Push too much data.
184 
185     CU_ASSERT(w.Push("Hello", 5));
186     CU_ASSERT(w.Read(buf, 5)==5);
187     CU_ASSERT(strncmp(buf, "Hello", 5)==0);
188     CU_ASSERT(w.GetLatestSequenceNumber()==SEQ_NUM+5);
189     CU_ASSERT(w.GetRestSize()==BUFSIZE-5);
190 
191     w.Pop(3);
192     CU_ASSERT(w.GetRestSize()==BUFSIZE-2);
193     CU_ASSERT(w.GetLatestSequenceNumber()==SEQ_NUM+5);
194     CU_ASSERT(w.Read(buf, 5)==2);
195 
196     CU_ASSERT(w.Push("ading", 5));
197     CU_ASSERT(w.GetRestSize()==BUFSIZE-7);
198     CU_ASSERT(w.Read(buf, 100)==7);
199     CU_ASSERT(w.GetLatestSequenceNumber()==SEQ_NUM+10);
200 }
201 #endif // end of _WIN32
202 
203 }}} // namespace nn::rdt::CTR
204