1 #include "SharedMemoryServer.h"
5 #include <machine/byte_order.h>
8 #include <security_utilities/crc.h>
10 static const char* kPrefix
= "/private/var/db/mds/messages/se_";
12 SharedMemoryServer::SharedMemoryServer (const char* segmentName
, SegmentOffsetType segmentSize
) :
13 mSegmentName (segmentName
), mSegmentSize (segmentSize
)
16 mFileName
+= segmentName
;
18 // make the mds directory, just in case it doesn't exist
19 mkdir("/var/db/mds", 1777);
20 mkdir("/var/db/mds/messages", 0755);
23 // clean any old file away
24 unlink (mFileName
.c_str ());
27 int segmentDescriptor
= open (mFileName
.c_str (), O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
28 if (segmentDescriptor
< 0)
33 // set the segment size
34 ftruncate (segmentDescriptor
, segmentSize
);
37 mSegment
= (u_int8_t
*) mmap (NULL
, mSegmentSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, segmentDescriptor
, 0);
38 close (segmentDescriptor
);
40 if (mSegment
== (u_int8_t
*) -1) // can't map the memory?
43 unlink (mFileName
.c_str());
46 mDataPtr
= mDataArea
= mSegment
+ sizeof(SegmentOffsetType
);
47 mDataMax
= mSegment
+ segmentSize
;;
49 SetProducerOffset (0);
54 SharedMemoryServer::~SharedMemoryServer ()
63 munmap (mSegment
, mSegmentSize
);
65 // mark the segment for deletion
66 unlink (mFileName
.c_str ());
71 const SegmentOffsetType
73 kCRCOffset
= kSegmentLength
+ sizeof(SegmentOffsetType
),
74 kDomainOffset
= kCRCOffset
+ sizeof(SegmentOffsetType
),
75 kEventTypeOffset
= kDomainOffset
+ sizeof(SegmentOffsetType
),
76 kHeaderLength
= kEventTypeOffset
+ sizeof(SegmentOffsetType
) - kCRCOffset
;
78 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain
, SegmentOffsetType event
, const void *message
, SegmentOffsetType messageLength
)
80 // assemble the final message
81 ssize_t messageSize
= kHeaderLength
+ messageLength
;
82 u_int8_t finalMessage
[messageSize
];
83 SegmentOffsetType
*fm
= (SegmentOffsetType
*) finalMessage
;
84 fm
[0] = OSSwapHostToBigInt32(domain
);
85 fm
[1] = OSSwapHostToBigInt32(event
);
86 memcpy(&fm
[2], message
, messageLength
);
88 SegmentOffsetType crc
= CalculateCRC(finalMessage
, messageSize
);
91 WriteOffset(messageSize
);
97 WriteData (finalMessage
, messageSize
);
99 // write the data count
100 SetProducerOffset(mDataPtr
- mDataArea
);
105 const char* SharedMemoryServer::GetSegmentName ()
107 return mSegmentName
.c_str ();
112 size_t SharedMemoryServer::GetSegmentSize ()
119 SegmentOffsetType
SharedMemoryServer::GetProducerOffset ()
121 // the data is stored in the buffer in network byte order
122 u_int32_t pCount
= OSSwapBigToHostInt32 (*(u_int32_t
*) mSegment
);
123 return OSSwapHostToBigInt32 (pCount
);
128 void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount
)
130 *((SegmentOffsetType
*) mSegment
) = OSSwapHostToBigInt32 (producerCount
);
135 void SharedMemoryServer::WriteOffset(SegmentOffsetType offset
)
138 *((u_int32_t
*) buffer
) = OSSwapHostToBigInt32(offset
);
139 WriteData(buffer
, 4);
144 void SharedMemoryServer::WriteData(const void* data
, SegmentOffsetType length
)
146 // figure out where in the buffer we actually need to write the data
147 // figure out how many bytes we can write without overflowing the buffer
148 const u_int8_t
* dp
= (const u_int8_t
*) data
;
149 SegmentOffsetType bytesToEnd
= mDataMax
- mDataPtr
;
151 // figure out how many bytes we can write
152 SegmentOffsetType bytesToWrite
= (length
<= bytesToEnd
) ? length
: bytesToEnd
;
154 // move the first part of the data, making sure to skip the producer pointer
155 memcpy (mDataPtr
, dp
, bytesToWrite
);
156 mDataPtr
+= bytesToWrite
;
159 // deduct the bytes just written
160 length
-= bytesToWrite
;
162 if (length
!= 0) // did we wrap around?
164 mDataPtr
= mDataArea
;
165 memcpy (mDataPtr
, dp
, length
);