michael@0: // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef CHROME_COMMON_FILE_DESCRIPTOR_SET_POSIX_H_ michael@0: #define CHROME_COMMON_FILE_DESCRIPTOR_SET_POSIX_H_ michael@0: michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "base/file_descriptor_posix.h" michael@0: #include "base/ref_counted.h" michael@0: michael@0: // ----------------------------------------------------------------------------- michael@0: // A FileDescriptorSet is an ordered set of POSIX file descriptors. These are michael@0: // associated with IPC messages so that descriptors can be transmitted over a michael@0: // UNIX domain socket. michael@0: // ----------------------------------------------------------------------------- michael@0: class FileDescriptorSet : public base::RefCountedThreadSafe { michael@0: public: michael@0: FileDescriptorSet(); michael@0: ~FileDescriptorSet(); michael@0: michael@0: // This is the maximum number of descriptors per message. We need to know this michael@0: // because the control message kernel interface has to be given a buffer which michael@0: // is large enough to store all the descriptor numbers. Otherwise the kernel michael@0: // tells us that it truncated the control data and the extra descriptors are michael@0: // lost. michael@0: // michael@0: // In debugging mode, it's a fatal error to try and add more than this number michael@0: // of descriptors to a FileDescriptorSet. michael@0: enum { michael@0: MAX_DESCRIPTORS_PER_MESSAGE = 4 michael@0: }; michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // Interfaces for building during message serialisation... michael@0: michael@0: // Add a descriptor to the end of the set. Returns false iff the set is full. michael@0: bool Add(int fd); michael@0: // Add a descriptor to the end of the set and automatically close it after michael@0: // transmission. Returns false iff the set is full. michael@0: bool AddAndAutoClose(int fd); michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // Interfaces for accessing during message deserialisation... michael@0: michael@0: // Return the number of descriptors michael@0: unsigned size() const { return descriptors_.size(); } michael@0: // Return true if no unconsumed descriptors remain michael@0: bool empty() const { return descriptors_.empty(); } michael@0: // Fetch the nth descriptor from the beginning of the set. Code using this michael@0: // /must/ access the descriptors in order, except that it may wrap from the michael@0: // end to index 0 again. michael@0: // michael@0: // This interface is designed for the deserialising code as it doesn't michael@0: // support close flags. michael@0: // returns: file descriptor, or -1 on error michael@0: int GetDescriptorAt(unsigned n) const; michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // Interfaces for transmission... michael@0: michael@0: // Fill an array with file descriptors without 'consuming' them. CommitAll michael@0: // must be called after these descriptors have been transmitted. michael@0: // buffer: (output) a buffer of, at least, size() integers. michael@0: void GetDescriptors(int* buffer) const; michael@0: // This must be called after transmitting the descriptors returned by michael@0: // GetDescriptors. It marks all the descriptors as consumed and closes those michael@0: // which are auto-close. michael@0: void CommitAll(); michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // Interfaces for receiving... michael@0: michael@0: // Set the contents of the set from the given buffer. This set must be empty michael@0: // before calling. The auto-close flag is set on all the descriptors so that michael@0: // unconsumed descriptors are closed on destruction. michael@0: void SetDescriptors(const int* buffer, unsigned count); michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: private: michael@0: // A vector of descriptors and close flags. If this message is sent, then michael@0: // these descriptors are sent as control data. After sending, any descriptors michael@0: // with a true flag are closed. If this message has been received, then these michael@0: // are the descriptors which were received and all close flags are true. michael@0: std::vector descriptors_; michael@0: michael@0: // This contains the index of the next descriptor which should be consumed. michael@0: // It's used in a couple of ways. Firstly, at destruction we can check that michael@0: // all the descriptors have been read (with GetNthDescriptor). Secondly, we michael@0: // can check that they are read in order. michael@0: mutable unsigned consumed_descriptor_highwater_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(FileDescriptorSet); michael@0: }; michael@0: michael@0: #endif // CHROME_COMMON_FILE_DESCRIPTOR_SET_POSIX_H_