1 #include "SharedMemoryServer.h"
5 #include <machine/byte_order.h>
8 #include <security_utilities/crc.h>
11 static const char* kPrefix
= "/private/var/db/mds/messages/se_";
13 SharedMemoryServer::SharedMemoryServer (const char* segmentName
, SegmentOffsetType segmentSize
) :
14 mSegmentName (segmentName
), mSegmentSize (segmentSize
)
17 mFileName
+= segmentName
;
19 // make the mds directory, just in case it doesn't exist
20 mkdir("/var/db/mds", 1777);
21 mkdir("/var/db/mds/messages", 0755);
24 // clean any old file away
25 unlink (mFileName
.c_str ());
28 int segmentDescriptor
= open (mFileName
.c_str (), O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
29 if (segmentDescriptor
< 0)
34 // set the segment size
35 ftruncate (segmentDescriptor
, segmentSize
);
38 mSegment
= (u_int8_t
*) mmap (NULL
, mSegmentSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, segmentDescriptor
, 0);
39 close (segmentDescriptor
);
41 if (mSegment
== (u_int8_t
*) -1) // can't map the memory?
44 unlink (mFileName
.c_str());
47 mDataPtr
= mDataArea
= mSegment
+ sizeof(SegmentOffsetType
);
48 mDataMax
= mSegment
+ segmentSize
;;
50 SetProducerOffset (0);
55 SharedMemoryServer::~SharedMemoryServer ()
64 munmap (mSegment
, mSegmentSize
);
66 // mark the segment for deletion
67 unlink (mFileName
.c_str ());
72 const SegmentOffsetType
74 kCRCOffset
= kSegmentLength
+ sizeof(SegmentOffsetType
),
75 kDomainOffset
= kCRCOffset
+ sizeof(SegmentOffsetType
),
76 kEventTypeOffset
= kDomainOffset
+ sizeof(SegmentOffsetType
),
77 kHeaderLength
= kEventTypeOffset
+ sizeof(SegmentOffsetType
) - kCRCOffset
;
79 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain
, SegmentOffsetType event
, const void *message
, SegmentOffsetType messageLength
)
81 // assemble the final message
82 ssize_t messageSize
= kHeaderLength
+ messageLength
;
83 u_int8_t finalMessage
[messageSize
];
84 SegmentOffsetType
*fm
= (SegmentOffsetType
*) finalMessage
;
85 fm
[0] = OSSwapHostToBigInt32(domain
);
86 fm
[1] = OSSwapHostToBigInt32(event
);
87 memcpy(&fm
[2], message
, messageLength
);
89 SegmentOffsetType crc
= CalculateCRC(finalMessage
, messageSize
);
92 WriteOffset(messageSize
);
98 WriteData (finalMessage
, messageSize
);
100 // write the data count
101 SetProducerOffset(mDataPtr
- mDataArea
);
106 const char* SharedMemoryServer::GetSegmentName ()
108 return mSegmentName
.c_str ();
113 size_t SharedMemoryServer::GetSegmentSize ()
120 SegmentOffsetType
SharedMemoryServer::GetProducerOffset ()
122 // the data is stored in the buffer in network byte order
123 u_int32_t pCount
= OSSwapBigToHostInt32 (*(u_int32_t
*) mSegment
);
124 return OSSwapHostToBigInt32 (pCount
);
129 void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount
)
131 *((SegmentOffsetType
*) mSegment
) = OSSwapHostToBigInt32 (producerCount
);
136 void SharedMemoryServer::WriteOffset(SegmentOffsetType offset
)
139 *((u_int32_t
*) buffer
) = OSSwapHostToBigInt32(offset
);
140 WriteData(buffer
, 4);
145 void SharedMemoryServer::WriteData(const void* data
, SegmentOffsetType length
)
147 // figure out where in the buffer we actually need to write the data
148 // figure out how many bytes we can write without overflowing the buffer
149 const u_int8_t
* dp
= (const u_int8_t
*) data
;
150 SegmentOffsetType bytesToEnd
= mDataMax
- mDataPtr
;
152 // figure out how many bytes we can write
153 SegmentOffsetType bytesToWrite
= (length
<= bytesToEnd
) ? length
: bytesToEnd
;
155 // move the first part of the data, making sure to skip the producer pointer
156 memcpy (mDataPtr
, dp
, bytesToWrite
);
157 mDataPtr
+= bytesToWrite
;
160 // deduct the bytes just written
161 length
-= bytesToWrite
;
163 if (length
!= 0) // did we wrap around?
165 mDataPtr
= mDataArea
;
166 memcpy (mDataPtr
, dp
, length
);