00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef __WOSCBUNDLE_H__
00040 #define __WOSCBUNDLE_H__
00041
00042 #include "WOscPriorityQueue.h"
00043 #include "WOscLib.h"
00044 #include "WOscMessage.h"
00045 #include "WOscPacket.h"
00046 #include "WOscException.h"
00047
00048 #include <string.h>
00049 #include "WOscUtil.h"
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #define WOSC_BUNDLE_TAG "#bundle"
00062 #define WOSC_BUNDLE_HEADER_SIZE (8 + sizeof(uint64_t))
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 class WOSC_EXPORT WOscBundleParser
00073 {
00074 private:
00075
00076 class WOscBundleRaw
00077 {
00078 public:
00079
00080 char m_tag[8];
00081
00082 char m_timeTag[sizeof(uint64_t)];
00083
00084
00085
00086 char m_bundleData[];
00087 };
00088
00089
00090 const WOscBundleRaw* m_bundle;
00091
00092 unsigned int m_bundleLen;
00093
00094 unsigned int m_nItems;
00095
00096
00097
00098 unsigned int m_nextItem;
00099
00100 unsigned int m_offset;
00101 public:
00102
00103 WOscBundleParser()
00104 {
00105 memset(this, 0, sizeof(WOscBundleParser));
00106 }
00107 void ResetStateMachine()
00108 {
00109 m_nextItem = 0;
00110 m_offset = 0;
00111 }
00112 void Clone(char** buffer, unsigned int* bufferLen) const
00113 {
00114 if ( m_bundle == NULL )
00115 throw WOscException(ERR_CAN_NOT_CLONE_UNINITIALIZED_BUNDLE, __FILE__, __LINE__);
00116
00117
00118 *buffer = new char[m_bundleLen];
00119 *bufferLen = m_bundleLen;
00120 memcpy(*buffer, m_bundle->m_bundleData, m_bundleLen);
00121 }
00122
00123
00124
00125 void Parse(const char* data, unsigned int len)
00126 {
00127
00128 memset(this, 0, sizeof(WOscBundleParser));
00129
00130 const WOscBundleRaw* bundle = reinterpret_cast<const WOscBundleRaw*>(data);
00131
00132 unsigned int dataLen = len - WOSC_BUNDLE_HEADER_SIZE;
00133 if ( dataLen > len )
00134 throw WOscException(ERR_TOO_SHORT, __FILE__, __LINE__);
00135 if ( dataLen == 0 )
00136 throw WOscException(ERR_EMPTY_BUNDLE, __FILE__, __LINE__);
00137 if ( strncmp(bundle->m_tag, WOSC_BUNDLE_TAG, sizeof(bundle->m_tag)) != 0 )
00138 throw WOscException(ERR_INVALID_TAG, __FILE__, __LINE__);
00139
00140
00141 unsigned int offset = 0;
00142 for ( ; offset + sizeof(int32_t) < dataLen; m_nItems++ ) {
00143 int itemLen = WOscUtil::BufferTo<int32_t>(bundle->m_bundleData+offset);
00144 offset += itemLen + sizeof(uint32_t);
00145 }
00146 if ( offset != dataLen ) {
00147 throw WOscException(ERR_CURRUPT_BUNDLE_LAYOUT, __FILE__, __LINE__);
00148 }
00149 if ( m_nItems == 0 )
00150 throw WOscException(ERR_NO_ITEMS_IN_BUNDLE, __FILE__, __LINE__);
00151 m_bundle = bundle;
00152 m_bundleLen = len;
00153 }
00154
00155 WOscTimeTag GetTimeTag() const
00156 {
00157 if ( m_bundle == NULL )
00158 return WOscTimeTag::GetImmediateTime();
00159 return WOscTimeTag(reinterpret_cast<const char*>(&m_bundle->m_timeTag));
00160 }
00161
00162 unsigned int GetItemCount() const { return m_nItems; }
00163
00164
00165
00166
00167
00168
00169
00170
00171 bool GetNextItem(const char** buffer, unsigned int* length)
00172 {
00173 unsigned int dataLen = m_bundleLen - WOSC_BUNDLE_HEADER_SIZE;
00174 if ( m_nextItem >= m_nItems || m_offset >= dataLen )
00175 return false;
00176
00177 *length = WOscUtil::BufferTo<int32_t>(m_bundle->m_bundleData + m_offset);
00178 *buffer = m_bundle->m_bundleData + m_offset + sizeof(uint32_t);
00179 m_offset += *length + sizeof(uint32_t);
00180 m_nextItem++;
00181
00182 return true;
00183 }
00184 };
00185
00186 class WOSC_EXPORT WOscQueueBundle : public WOscQueueItem
00187 {
00188 public:
00189 WOscQueueBundle(const WOscBundleParser& bundle, WOscNetReturn* ra) :
00190 WOscQueueItem(bundle.GetTimeTag(), ra)
00191 {
00192 m_bundleData = NULL;
00193 m_bundleDataLen = 0;
00194 bundle.Clone(&m_bundleData, &m_bundleDataLen);
00195 }
00196 virtual ~WOscQueueBundle()
00197 {
00198 delete [] m_bundleData;
00199 }
00200 const char* GetData() const { return m_bundleData; }
00201 unsigned int GetDataLen() const { return m_bundleDataLen; }
00202 private:
00203 WOscQueueBundle();
00204
00205
00206
00207 char* m_bundleData;
00208 unsigned int m_bundleDataLen;
00209 };
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 class WOSC_EXPORT WOscBundle: public WOscTimeTag, public WOscPacket
00226 {
00227
00228 public:
00229
00230 WOscBundle();
00231 WOscBundle(WOscTimeTag timeTag);
00232
00233 virtual ~WOscBundle();
00234 void Reset();
00235 void Add(WOscBundle* bundle);
00236 void Add(WOscMessage* message);
00237
00238 int GetNumMessages();
00239 int GetNumBundles();
00240
00241 WOscMessage* GetMessage(int idx);
00242 WOscBundle* GetBundle(int idx);
00243
00244 virtual void GetBuffer(char* buffer, int bufferLen);
00245 virtual const char* GetBuffer();
00246 virtual int GetBufferLen();
00247
00248
00249
00250 enum Constants{
00251 END_OF_BUFFER = -1,
00252 BUNDLE_HEADER_SIZE = 8,
00253 SIZE_SIZE = 4,
00254 };
00255
00256 private:
00257 void RemoveBundle(int idx);
00258 void RemoveMessage(int idx);
00259
00260 void InitEmpty();
00261 void GenerateBufferFromElements();
00262 int CheckSize(int relReadPos, int dataLen, const char* rawData);
00263
00264 WOscMessage** m_messages;
00265 int m_numMessages;
00266
00267 WOscBundle** m_bundles;
00268 int m_numBundles;
00269
00270 char* m_buffer;
00271 int m_bufferSize;
00272
00273 WOscBundle(WOscBundle& rhs);
00274 WOscBundle& operator=(const WOscBundle& rhs);
00275 };
00276
00277 #endif // #ifndef __WOSCBUNDLE_H__