1 #include "SharedMemoryServer.h"
5 #include <machine/byte_order.h>
8 #include <security_utilities/crc.h>
10 static const char* kPrefix
= "/private/var/tmp/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/tmp/mds/messages", 0755);
22 // clean any old file away
23 unlink (mFileName
.c_str ());
26 int segmentDescriptor
= open (mFileName
.c_str (), O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
27 if (segmentDescriptor
< 0)
32 // set the segment size
33 ftruncate (segmentDescriptor
, segmentSize
);
36 mSegment
= (u_int8_t
*) mmap (NULL
, mSegmentSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, segmentDescriptor
, 0);
37 close (segmentDescriptor
);
39 if (mSegment
== (u_int8_t
*) -1) // can't map the memory?
42 unlink (mFileName
.c_str());
45 mDataPtr
= mDataArea
= mSegment
+ sizeof(SegmentOffsetType
);
46 mDataMax
= mSegment
+ segmentSize
;;
48 SetProducerOffset (0);
53 SharedMemoryServer::~SharedMemoryServer ()
62 munmap (mSegment
, mSegmentSize
);
64 // mark the segment for deletion
65 unlink (mFileName
.c_str ());
70 const SegmentOffsetType
72 kCRCOffset
= kSegmentLength
+ sizeof(SegmentOffsetType
),
73 kDomainOffset
= kCRCOffset
+ sizeof(SegmentOffsetType
),
74 kEventTypeOffset
= kDomainOffset
+ sizeof(SegmentOffsetType
),
75 kHeaderLength
= kEventTypeOffset
+ sizeof(SegmentOffsetType
) - kCRCOffset
;
77 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain
, SegmentOffsetType event
, const void *message
, SegmentOffsetType messageLength
)
79 // assemble the final message
80 ssize_t messageSize
= kHeaderLength
+ messageLength
;
81 u_int8_t finalMessage
[messageSize
];
82 SegmentOffsetType
*fm
= (SegmentOffsetType
*) finalMessage
;
83 fm
[0] = OSSwapHostToBigInt32(domain
);
84 fm
[1] = OSSwapHostToBigInt32(event
);
85 memcpy(&fm
[2], message
, messageLength
);
87 SegmentOffsetType crc
= CalculateCRC(finalMessage
, messageSize
);
90 WriteOffset(messageSize
);
96 WriteData (finalMessage
, messageSize
);
98 // write the data count
99 SetProducerOffset(mDataPtr
- mDataArea
);
104 const char* SharedMemoryServer::GetSegmentName ()
106 return mSegmentName
.c_str ();
111 size_t SharedMemoryServer::GetSegmentSize ()
118 SegmentOffsetType
SharedMemoryServer::GetProducerOffset ()
120 // the data is stored in the buffer in network byte order
121 u_int32_t pCount
= OSSwapBigToHostInt32 (*(u_int32_t
*) mSegment
);
122 return OSSwapHostToBigInt32 (pCount
);
127 void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount
)
129 *((SegmentOffsetType
*) mSegment
) = OSSwapHostToBigInt32 (producerCount
);
134 void SharedMemoryServer::WriteOffset(SegmentOffsetType offset
)
137 *((u_int32_t
*) buffer
) = OSSwapHostToBigInt32(offset
);
138 WriteData(buffer
, 4);
143 void SharedMemoryServer::WriteData(const void* data
, SegmentOffsetType length
)
145 // figure out where in the buffer we actually need to write the data
146 // figure out how many bytes we can write without overflowing the buffer
147 const u_int8_t
* dp
= (const u_int8_t
*) data
;
148 SegmentOffsetType bytesToEnd
= mDataMax
- mDataPtr
;
150 // figure out how many bytes we can write
151 SegmentOffsetType bytesToWrite
= (length
<= bytesToEnd
) ? length
: bytesToEnd
;
153 // move the first part of the data, making sure to skip the producer pointer
154 memcpy (mDataPtr
, dp
, bytesToWrite
);
155 mDataPtr
+= bytesToWrite
;
158 // deduct the bytes just written
159 length
-= bytesToWrite
;
161 if (length
!= 0) // did we wrap around?
163 mDataPtr
= mDataArea
;
164 memcpy (mDataPtr
, dp
, length
);