6 #include <architecture/byte_order.h>
7 #include <security_cdsa_utilities/cssmdb.h>
8 #include "SharedMemoryClient.h"
10 #include <security_utilities/crc.h>
12 static const char* kPrefix
= "/var/db/mds/messages/se_";
14 using namespace Security
;
16 SharedMemoryClient::SharedMemoryClient (const char* segmentName
, SegmentOffsetType segmentSize
)
18 StLock
<Mutex
> _(mMutex
);
20 mSegmentName
= segmentName
;
21 mSegmentSize
= segmentSize
;
22 mSegment
= (u_int8_t
*) MAP_FAILED
;
23 mDataArea
= mDataPtr
= 0;
25 if (segmentSize
< sizeof(u_int32_t
))
29 int segmentDescriptor
;
31 std::string
name (kPrefix
);
34 // make a connection to the shared memory block
35 segmentDescriptor
= open (name
.c_str (), O_RDONLY
, S_IROTH
);
36 if (segmentDescriptor
< 0) // error on opening the shared memory segment?
38 // CssmError::throwMe (CSSM_ERRCODE_INTERNAL_ERROR);
43 // check the file size is large enough to support Operations
44 struct stat statResult
= {};
45 int result
= fstat(segmentDescriptor
, &statResult
);
47 UnixError::throwMe(errno
);
50 off_t sz
= statResult
.st_size
;
51 if(sz
< sizeof(SegmentOffsetType
)) {
52 close(segmentDescriptor
);
56 if(sz
> 4*segmentSize
) {
57 // File is too ridiculously large. Quit.
58 close(segmentDescriptor
);
62 // map the segment into place
63 mSegment
= (u_int8_t
*) mmap (NULL
, segmentSize
, PROT_READ
, MAP_SHARED
, segmentDescriptor
, 0);
64 close (segmentDescriptor
);
66 if (mSegment
== MAP_FAILED
)
71 mDataArea
= mSegment
+ sizeof (SegmentOffsetType
);
72 mDataMax
= mSegment
+ sz
;
73 mDataPtr
= mDataArea
+ GetProducerCount ();
78 SharedMemoryClient::~SharedMemoryClient ()
80 StLock
<Mutex
> _(mMutex
);
81 if (mSegment
== NULL
|| mSegment
== MAP_FAILED
) // error on opening the shared memory segment?
83 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
85 munmap (mSegment
, mSegmentSize
);
90 SegmentOffsetType
SharedMemoryClient::GetProducerCount ()
92 if (mSegment
== NULL
|| mSegment
== MAP_FAILED
) // error on opening the shared memory segment?
94 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
96 if( ((u_int8_t
*) (((u_int32_t
*) mSegment
) + 1)) > mDataMax
) {
97 // Check we can actually read this u_int32_t
98 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
101 SegmentOffsetType offset
= OSSwapBigToHostInt32 (*(u_int32_t
*) mSegment
);
102 if (&mSegment
[offset
] >= mDataMax
)
103 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
110 const char* SharedMemoryClient::GetSegmentName ()
112 return mSegmentName
.c_str ();
117 size_t SharedMemoryClient::GetSegmentSize ()
124 void SharedMemoryClient::ReadData (void* buffer
, SegmentOffsetType length
)
126 if (mSegment
== NULL
|| mSegment
== MAP_FAILED
) // error on opening the shared memory segment?
128 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
131 u_int8_t
* bptr
= (u_int8_t
*) buffer
;
133 SegmentOffsetType bytesToEnd
= (SegmentOffsetType
)(mDataMax
- mDataPtr
);
135 // figure out how many bytes we can read
136 SegmentOffsetType bytesToRead
= (length
<= bytesToEnd
) ? length
: bytesToEnd
;
138 // move the first part of the data
139 memcpy (bptr
, mDataPtr
, bytesToRead
);
142 // see if we have anything else to read
143 mDataPtr
+= bytesToRead
;
145 length
-= bytesToRead
;
148 mDataPtr
= mDataArea
;
149 memcpy(bptr
, mDataPtr
, length
);
156 SegmentOffsetType
SharedMemoryClient::ReadOffset()
158 SegmentOffsetType offset
;
159 ReadData(&offset
, sizeof(SegmentOffsetType
));
160 offset
= OSSwapBigToHostInt32 (offset
);
166 bool SharedMemoryClient::ReadMessage (void* message
, SegmentOffsetType
&length
, UnavailableReason
&ur
)
168 StLock
<Mutex
> _(mMutex
);
170 if (mSegment
== NULL
|| mSegment
== MAP_FAILED
) // error on opening the shared memory segment?
172 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
177 size_t offset
= mDataPtr
- mDataArea
;
178 if (offset
== GetProducerCount())
184 // get the length of the message in the buffer
185 length
= ReadOffset();
187 // we have the possibility that data is correct, figure out where the data is actually located
188 // get the length of the message stored there
189 if (length
== 0 || length
>= kPoolAvailableForData
)
197 ur
= kURBufferCorrupt
;
200 // something's gone wrong, reset.
201 mDataPtr
= mDataArea
+ GetProducerCount ();
206 SegmentOffsetType crc
= ReadOffset();
208 // read the data into the buffer
209 ReadData (message
, length
);
212 SegmentOffsetType crc2
= CalculateCRC((u_int8_t
*) message
, length
);
215 ur
= kURBufferCorrupt
;
216 mDataPtr
= mDataArea
+ GetProducerCount ();