Instrument Neutral Distributed Interface INDI 2.2.5
SerializedMsgWithSharedBuffer.cpp
Go to the documentation of this file.
1/* INDI Server for protocol version 1.7.
2 * Copyright (C) 2007 Elwood C. Downey <[email protected]>
3 2013 Jasem Mutlaq <[email protected]>
4 2022 Ludovic Pollet
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
20
21#include "MsgChunck.hpp"
22#include "Utils.hpp"
23#include "Msg.hpp"
24#include "sharedblob.h"
25#include "base64.h"
26
27#include <unistd.h>
28
30{
31 for(auto blobContent : findBlobElements(owner->xmlContent))
32 {
33 // C'est pas trivial, dans ce cas, car il faut les réattacher
34 std::string attached = findXMLAttValu(blobContent, "attached");
35 if (attached != "true")
36 {
37 return true;
38 }
39 }
40 return false;
41}
42
44{
45 return owner->hasInlineBlobs;
46}
47
49{
50 // Convert every inline base64 blob from xml into an attached buffer
51 auto xmlContent = owner->xmlContent;
52
53 std::vector<int> sharedBuffers = owner->sharedBuffers;
54
55 std::unordered_map<XMLEle*, XMLEle*> replacement;
56 int blobPos = 0;
57 for(auto blobContent : findBlobElements(owner->xmlContent))
58 {
59 if (!pcdatalenXMLEle(blobContent))
60 {
61 continue;
62 }
63 std::string attached = findXMLAttValu(blobContent, "attached");
64 if (attached != "true")
65 {
66 // We need to replace.
67 XMLEle * clone = shallowCloneXMLEle(blobContent);
68 rmXMLAtt(clone, "enclen");
69 rmXMLAtt(clone, "attached");
70 addXMLAtt(clone, "attached", "true");
71
72 replacement[blobContent] = clone;
73
74 int base64datalen = pcdatalenXMLEle(blobContent);
75 char * base64data = pcdataXMLEle(blobContent);
76 // Shall we really trust the size here ?
77
78 ssize_t size;
79 if (!parseBlobSize(blobContent, size))
80 {
81 log("Missing size value for blob");
82 size = 1;
83 }
84
85 void * blob = IDSharedBlobAlloc(size);
86 if (blob == nullptr)
87 {
88 log(fmt("Unable to allocate shared buffer of size %d : %s\n", size, strerror(errno)));
89 ::exit(1);
90 }
91 log(fmt("Blob allocated at %p\n", blob));
92
93 int actualLen = from64tobits_fast((char*)blob, base64data, base64datalen);
94
95 if (actualLen != size)
96 {
97 // FIXME: WTF ? at least prevent overflow ???
98 log(fmt("Blob size mismatch after base64dec: %lld vs %lld\n", (long long int)actualLen, (long long int)size));
99 }
100
101 int newFd = IDSharedBlobGetFd(blob);
102 ownSharedBuffers.insert(newFd);
103
105
106 sharedBuffers.insert(sharedBuffers.begin() + blobPos, newFd);
107 }
108 blobPos++;
109 }
110
111 if (!replacement.empty())
112 {
113 // Work on a copy --- but we don't want to copy the blob !!!
114 xmlContent = cloneXMLEleWithReplacementMap(xmlContent, replacement);
115 }
116
117 // Now create a Chunk from xmlContent
118 MsgChunck chunck;
119
120 chunck.content = (char*)malloc(sprlXMLEle(xmlContent, 0) + 1);
121 ownBuffers.push_back(chunck.content);
122 chunck.contentLength = sprXMLEle(chunck.content, xmlContent, 0);
123 chunck.sharedBufferIdsToAttach = sharedBuffers;
124
125 async_pushChunck(chunck);
126
127 if (!replacement.empty())
128 {
129 delXMLEle(xmlContent);
130 }
131 async_done();
132}
133
137
139{
140 for(auto id : ownSharedBuffers)
141 {
142 close(id);
143 }
144}
void log(const std::string &log)
Definition Utils.cpp:161
XMLEle * cloneXMLEleWithReplacementMap(XMLEle *root, const std::unordered_map< XMLEle *, XMLEle * > &replacement)
Definition Utils.cpp:143
bool parseBlobSize(XMLEle *blobWithAttachedBuffer, ssize_t &size)
Definition Utils.cpp:114
std::string fmt(const char *fmt,...)
Definition Utils.cpp:241
std::vector< XMLEle * > findBlobElements(XMLEle *root)
Definition Utils.cpp:148
int from64tobits_fast(char *out, const char *in, int inlen)
Definition base64.c:122
Definition Msg.hpp:33
std::list< void * > ownBuffers
void async_pushChunck(const MsgChunck &m)
int errno
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
Definition lilxml.cpp:644
size_t sprXMLEle(char *s, XMLEle *ep, int level)
sample print ep to string s. N.B. s must be at least as large as that reported by sprlXMLEle()+1....
Definition lilxml.cpp:874
void rmXMLAtt(XMLEle *ep, const char *name)
Remove an XML attribute from an XML element.
Definition lilxml.cpp:715
size_t sprlXMLEle(XMLEle *ep, int level)
return number of bytes in a string guaranteed able to hold result of sprXLMEle(ep) (sans trailing \0@...
Definition lilxml.cpp:922
void delXMLEle(XMLEle *ep)
delXMLEle Delete XML element.
Definition lilxml.cpp:167
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition lilxml.cpp:606
XMLEle * shallowCloneXMLEle(XMLEle *ele)
return a surface copy of a node. Don't copy childs or cdata.
Definition lilxml.cpp:731
XMLAtt * addXMLAtt(XMLEle *ep, const char *name, const char *valu)
Add an XML attribute to an existing XML element.
Definition lilxml.cpp:706
int pcdatalenXMLEle(XMLEle *ep)
Return the number of characters in pcdata in an XML element.
Definition lilxml.cpp:612
void * IDSharedBlobAlloc(size_t size)
Allocate a buffer suitable for fast exchange over local links. Warning : the buffer will be sealed (r...
Definition sharedblob.c:73
void IDSharedBlobDettach(void *ptr)
Dettach a blob, but don't close its FD.
Definition sharedblob.c:165
int IDSharedBlobGetFd(void *ptr)
Return the filedescriptor backing up the given shared buffer.
Definition sharedblob.c:265