reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
PublicationPersistenceManager.hxx
Go to the documentation of this file.
1#if !defined(RESIP_PUBLICATIONPERSISTENCEMANAGER_HXX)
2#define RESIP_PUBLICATIONPERSISTENCEMANAGER_HXX
3
4#include <map>
5
6#include "rutil/XMLCursor.hxx"
9#include "rutil/Data.hxx"
10#include "rutil/Timer.hxx"
11
12#include <memory>
13
14namespace resip
15{
16
21{
22public:
23
25 {
27 PubDocument(const Data& eventType, const Data& documentKey, const Data& eTag, uint64_t expirationTime, const Contents* contents, const SecurityAttributes* securityAttributes, bool syncPublication = false) :
28 mEventType(eventType), mDocumentKey(documentKey), mETag(eTag), mExpirationTime(expirationTime), mLastUpdated(Timer::getTimeSecs()), mLingerTime(expirationTime), mSyncPublication(syncPublication)
29 {
30 if (contents)
31 {
32 mContents.reset(contents->clone());
33 }
34 if (securityAttributes)
35 {
37 *mSecurityAttributes = *securityAttributes;
38 }
39 }
40
41 void stream(std::iostream& s) const
42 {
44
45 // Note: for compatibility with RegSyncServer/Client, using pubinfo for tag name instead of pubdocument
46 s << "<pubinfo>" << Symbols::CRLF;
47 s << " <eventtype>" << mEventType.xmlCharDataEncode() << "</eventtype>" << Symbols::CRLF;
48 s << " <documentkey>" << mDocumentKey.xmlCharDataEncode() << "</documentkey>" << Symbols::CRLF;
49 s << " <etag>" << mETag.xmlCharDataEncode() << "</etag>" << Symbols::CRLF;
50 s << " <expires>" << (((mExpirationTime == 0) || (mExpirationTime <= now)) ? 0 : (mExpirationTime - now)) << "</expires>" << Symbols::CRLF;
51 s << " <lastupdate>" << now - mLastUpdated << "</lastupdate>" << Symbols::CRLF;
52 if (mExpirationTime != 0 && mContents.get()) // lingering records will have expirationTime as 0 - don't need to send contents - refreshes also have no body
53 {
54
55 Mime mimeType = mContents->getType();
56
57 // There is an assumption that the contenttype and contentsubtype tags will always occur
58 // before the content tag in the deserialization
59 s << " <contentstype>" << mimeType.type().xmlCharDataEncode() << "</contentstype>" << Symbols::CRLF;
60 s << " <contentssubtype>" << mimeType.subType().xmlCharDataEncode() << "</contentssubtype>" << Symbols::CRLF;
61 s << " <contents>" << mContents->getBodyData().xmlCharDataEncode() << "</contents>" << Symbols::CRLF;
62
63 if(mSecurityAttributes.get())
64 {
66 s << " <isencrypted>" << (mSecurityAttributes->isEncrypted() ? "true" : "false") << "</isencrypted>" << Symbols::CRLF;
67 if (mSecurityAttributes->isEncrypted())
68 {
69 s << " <sigstatus>";
70 switch (mSecurityAttributes->getSignatureStatus())
71 {
72 case SignatureNone:
73 s << "none";
74 break;
75 case SignatureIsBad:
76 s << "bad";
77 break;
79 s << "trusted";
80 break;
82 s << "catrusted";
83 break;
85 s << "nottrusted";
86 break;
88 s << "selfsigned";
89 break;
90 default:
91 resip_assert(false);
92 s << "unknown";
93 break;
94 }
95 s << "</sigstatus>" << Symbols::CRLF;
96 if (!mSecurityAttributes->getSigner().empty())
97 {
98 s << " <signer>" << mSecurityAttributes->getSigner().xmlCharDataEncode() << "</signer>" << Symbols::CRLF;
99 }
100 if (!mSecurityAttributes->getIdentity().empty())
101 {
102 s << " <identity>" << mSecurityAttributes->getIdentity().xmlCharDataEncode() << "</identity>" << Symbols::CRLF;
103 s << " <identitystrength>";
104 switch (mSecurityAttributes->getIdentityStrength())
105 {
107 s << "from";
108 break;
110 s << "failedidentity";
111 break;
113 s << "identity";
114 break;
115 default:
116 resip_assert(false);
117 s << "unknown";
118 break;
119 }
120 s << "</identitystrength>" << Symbols::CRLF;
121 }
122 // Note: intentionally not syncing mLevel and mEncryptionPerformed from SecurityAttributes since they are for outbound messages only
123 }
124 }
125 }
126 s << "</pubinfo>" << Symbols::CRLF;
127 }
128
130 {
131 bool success = false;
132 *this = PubDocument();
133 if(now <= 0)
134 {
135 now = Timer::getTimeSecs();
136 }
137 Data mimeTypeString;
138 Data mimeSubtypeString;
139
140 if(isEqualNoCase(xml.getTag(), "pubinfo"))
141 {
142 if(xml.firstChild())
143 {
144 do
145 {
146 if(isEqualNoCase(xml.getTag(), "eventtype"))
147 {
148 if(xml.firstChild())
149 {
151 xml.parent();
152 }
153 }
154 else if(isEqualNoCase(xml.getTag(), "documentkey"))
155 {
156 if(xml.firstChild())
157 {
159 xml.parent();
160 }
161 }
162 else if(isEqualNoCase(xml.getTag(), "etag"))
163 {
164 if(xml.firstChild())
165 {
167 xml.parent();
168 }
169 }
170 else if(isEqualNoCase(xml.getTag(), "expires"))
171 {
172 if(xml.firstChild())
173 {
174 uint64_t expires = xml.getValue().convertUInt64();
175 mExpirationTime = (expires == 0 ? 0 : now + expires);
177 xml.parent();
178 }
179 }
180 else if(isEqualNoCase(xml.getTag(), "lastupdated"))
181 {
182 if(xml.firstChild())
183 {
184 mLastUpdated = now - xml.getValue().convertUInt64();
185 xml.parent();
186 }
187 }
188 else if(isEqualNoCase(xml.getTag(), "contentstype"))
189 {
190 if(xml.firstChild())
191 {
192 mimeTypeString = xml.getValue().xmlCharDataDecode();
193 xml.parent();
194 }
195 }
196 else if(isEqualNoCase(xml.getTag(), "contentssubtype"))
197 {
198 if(xml.firstChild())
199 {
200 mimeSubtypeString = xml.getValue().xmlCharDataDecode();
201 xml.parent();
202 }
203 }
204 else if(isEqualNoCase(xml.getTag(), "contents"))
205 {
206 if(xml.firstChild())
207 {
208 // There is an assumption that the contenttype and contentsubtype tags will always occur
209 // before the content tag
210 Mime mimeType(mimeTypeString, mimeSubtypeString);
211 // Need explicit Data decodedBody as serializedContents refers to it in parser
212 Data decodedBody(xml.getValue().xmlCharDataDecode());
213 Contents* serializedContents = Contents::createContents(mimeType, decodedBody);
214 // Need to clone, as serializedContents is still referring to decodedBody, via the LazyParser,
215 // which will go out of scope.
216 mContents.reset(serializedContents->clone());
217 delete serializedContents;
218 serializedContents = 0;
219 xml.parent();
220 success = true;
221 }
222 }
223 else if (isEqualNoCase(xml.getTag(), "isencrypted"))
224 {
225 if (xml.firstChild())
226 {
227 if (mSecurityAttributes.get() == 0)
228 {
230 }
231 if (isEqualNoCase(xml.getValue(), "true"))
232 {
233 mSecurityAttributes->setEncrypted();
234 }
235 xml.parent();
236 }
237 }
238 else if (isEqualNoCase(xml.getTag(), "sigstatus"))
239 {
240 if (xml.firstChild())
241 {
242 if (mSecurityAttributes.get() == 0)
243 {
245 }
246 if (isEqualNoCase(xml.getValue(), "none"))
247 {
248 mSecurityAttributes->setSignatureStatus(SignatureNone);
249 }
250 else if (isEqualNoCase(xml.getValue(), "bad"))
251 {
252 mSecurityAttributes->setSignatureStatus(SignatureIsBad);
253 }
254 else if (isEqualNoCase(xml.getValue(), "trusted"))
255 {
256 mSecurityAttributes->setSignatureStatus(SignatureTrusted);
257 }
258 else if (isEqualNoCase(xml.getValue(), "catrusted"))
259 {
260 mSecurityAttributes->setSignatureStatus(SignatureCATrusted);
261 }
262 else if (isEqualNoCase(xml.getValue(), "nottrusted"))
263 {
264 mSecurityAttributes->setSignatureStatus(SignatureNotTrusted);
265 }
266 else if (isEqualNoCase(xml.getValue(), "selfsigned"))
267 {
268 mSecurityAttributes->setSignatureStatus(SignatureSelfSigned);
269 }
270 xml.parent();
271 }
272 }
273 else if (isEqualNoCase(xml.getTag(), "signer"))
274 {
275 if (xml.firstChild())
276 {
277 if (mSecurityAttributes.get() == 0)
278 {
280 }
282 xml.parent();
283 }
284 }
285 else if (isEqualNoCase(xml.getTag(), "identity"))
286 {
287 if (xml.firstChild())
288 {
289 if (mSecurityAttributes.get() == 0)
290 {
292 }
293 mSecurityAttributes->setIdentity(xml.getValue().xmlCharDataDecode());
294 xml.parent();
295 }
296 }
297 else if (isEqualNoCase(xml.getTag(), "identitystrength"))
298 {
299 if (xml.firstChild())
300 {
301 if (mSecurityAttributes.get() == 0)
302 {
304 }
305 if (isEqualNoCase(xml.getValue(), "from"))
306 {
307 mSecurityAttributes->setIdentityStrength(SecurityAttributes::From);
308 }
309 else if (isEqualNoCase(xml.getValue(), "failedidentity"))
310 {
312 }
313 else if (isEqualNoCase(xml.getValue(), "identity"))
314 {
316 }
317 xml.parent();
318 }
319 }
320
321 } while(xml.nextSibling());
322 xml.parent();
323 }
324 }
325
326 return(success);
327 }
328
329
335 uint64_t mLingerTime; // No need to sync this - this is essentially the latest expiration time we have seen for this ETag
336 std::shared_ptr<Contents> mContents;
337 std::shared_ptr<SecurityAttributes> mSecurityAttributes;
338 bool mSyncPublication; // No need to sync this
339 };
340
341 typedef std::map<resip::Data, PubDocument> ETagToDocumentMap;
342 typedef std::map<resip::Data, ETagToDocumentMap> KeyToETagMap;
343
345 {
346 public:
347 virtual ~ETagMerger() = default;
348 virtual bool mergeETag(Contents* eTagDest, Contents* eTagSrc, bool isFirst) = 0;
349 };
350
353
354 virtual void addUpdateDocument(const PubDocument& document) = 0;
355 virtual void addUpdateDocument(const Data& eventType, const Data& documentKey, const Data& eTag, uint64_t expirationTime, const Contents* contents, const SecurityAttributes* securityAttributes, bool syncPublication = false)
356 {
357 addUpdateDocument(PubDocument(eventType, documentKey, eTag, expirationTime, contents, securityAttributes, syncPublication));
358 }
359 virtual bool removeDocument(const Data& eventType, const Data& documentKey, const Data& eTag, uint64_t lastUpdated, bool syncPublication = false) = 0;
360 virtual bool getMergedETags(const Data& eventType, const Data& documentKey, ETagMerger& merger, Contents* destination) = 0;
361 virtual bool documentExists(const Data& eventType, const Data& documentKey, const Data& eTag) = 0;
362 virtual bool getDocument(const resip::Data& eventType, const resip::Data& documentKey, const resip::Data& eTag, PubDocument& document) { return false; }
363 virtual bool checkExpired(const Data& eventType, const Data& documentKey, const Data& eTag, uint64_t lastUpdated) = 0;
364 virtual void lockDocuments() = 0;
365 virtual KeyToETagMap& getDocuments() = 0; // Ensure you lock before calling this and unlock when done
366 virtual void unlockDocuments() = 0;
367};
368}
369
370#endif
371
372/* ====================================================================
373*
374* Copyright (c) 2015 SIP Spectrum, Inc. All rights reserved.
375*
376* Redistribution and use in source and binary forms, with or without
377* modification, are permitted provided that the following conditions
378* are met:
379*
380* 1. Redistributions of source code must retain the above copyright
381* notice, this list of conditions and the following disclaimer.
382*
383* 2. Redistributions in binary form must reproduce the above copyright
384* notice, this list of conditions and the following disclaimer in
385* the documentation and/or other materials provided with the
386* distribution.
387*
388* 3. Neither the name of the author(s) nor the names of any contributors
389* may be used to endorse or promote products derived from this software
390* without specific prior written permission.
391*
392* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
393* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
394* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
395* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
396* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
397* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
398* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
399* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
400* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
401* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
402* SUCH DAMAGE.
403*
404* ====================================================================
405*
406*/
407/*
408* vi: set shiftwidth=3 expandtab:
409*/
#define resip_assert(x)
This file needs to work for both C and C++ code.
Base class for all SIP body types.
Definition Contents.hxx:51
static Contents * createContents(const Mime &contentType, const Data &contents)
factory method to create a Contents object from a mime type and a payload
Definition Contents.cxx:148
virtual Contents * clone() const =0
returns a copy of a Contents object
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Data xmlCharDataDecode() const
Performs in-place XML Character Data un-escaping of a Data.
Definition Data.cxx:1464
Data xmlCharDataEncode() const
Performs in-place XML Character Data escaping of a Data.
Definition Data.cxx:1454
uint64_t convertUInt64() const
Takes the contents of the Data and converts them to an unsigned 64-bit integer.
Definition Data.cxx:1758
Represents the "media-type" element in the RFC 3261 grammar.
Definition Mime.hxx:20
const Data & subType() const
Definition Mime.cxx:100
const Data & type() const
Definition Mime.cxx:94
virtual bool mergeETag(Contents *eTagDest, Contents *eTagSrc, bool isFirst)=0
Abstract interface of a datastore of all publication documents processed by DUM.
virtual bool getDocument(const resip::Data &eventType, const resip::Data &documentKey, const resip::Data &eTag, PubDocument &document)
virtual ~PublicationPersistenceManager()=default
std::map< resip::Data, ETagToDocumentMap > KeyToETagMap
virtual KeyToETagMap & getDocuments()=0
virtual void addUpdateDocument(const Data &eventType, const Data &documentKey, const Data &eTag, uint64_t expirationTime, const Contents *contents, const SecurityAttributes *securityAttributes, bool syncPublication=false)
virtual void addUpdateDocument(const PubDocument &document)=0
virtual bool getMergedETags(const Data &eventType, const Data &documentKey, ETagMerger &merger, Contents *destination)=0
virtual bool checkExpired(const Data &eventType, const Data &documentKey, const Data &eTag, uint64_t lastUpdated)=0
virtual bool removeDocument(const Data &eventType, const Data &documentKey, const Data &eTag, uint64_t lastUpdated, bool syncPublication=false)=0
virtual bool documentExists(const Data &eventType, const Data &documentKey, const Data &eTag)=0
std::map< resip::Data, PubDocument > ETagToDocumentMap
static const char * CRLF
Definition Symbols.hxx:21
This class is used to get the current system time.
Definition Timer.hxx:31
static uint64_t getTimeSecs()
Returns the current clock time in seconds.
Definition Timer.hxx:78
const Data & getValue() const
const Data & getTag() const
dcm! – add UnusedChecking(_enum) below;
bool isEqualNoCase(const Data &left, const Data &right)
Definition Data.hxx:1116
unsigned long long uint64_t
Definition Stun.hxx:39
PubDocument(const Data &eventType, const Data &documentKey, const Data &eTag, uint64_t expirationTime, const Contents *contents, const SecurityAttributes *securityAttributes, bool syncPublication=false)
bool deserialize(resip::XMLCursor &xml, uint64_t now=0)