/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

The IPC pipes are now file objects, not file descriptors:
* mandos (ClientDBus.CheckedOK): Reorder to group methods, signals and
                                 properties together.
  (ClientHandler.handle,
  ForkingMixInWithPipes.process_request,
  ForkingMixInWithPipes.add_pipe_fds,
  MandosServer.add_pipe_fds): IPC pipes are now file objects, not FDs.
  (MandosServer.handle_ipc): - '' -  Take additional argument "sender"
                             containing the client IPC file object;
                             all callers changed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
780
780
                                 dbus.Boolean(False, variant_level=1))
781
781
        return r
782
782
    
783
 
    ## D-Bus methods & signals
 
783
    ## D-Bus methods, signals & properties
784
784
    _interface = u"se.bsnet.fukt.Mandos.Client"
785
785
    
786
 
    # CheckedOK - method
787
 
    @dbus.service.method(_interface)
788
 
    def CheckedOK(self):
789
 
        return self.checked_ok()
 
786
    ## Signals
790
787
    
791
788
    # CheckerCompleted - signal
792
789
    @dbus.service.signal(_interface, signature=u"nxs")
818
815
        "D-Bus signal"
819
816
        pass
820
817
    
 
818
    ## Methods
 
819
    
 
820
    # CheckedOK - method
 
821
    @dbus.service.method(_interface)
 
822
    def CheckedOK(self):
 
823
        return self.checked_ok()
 
824
    
821
825
    # Enable - method
822
826
    @dbus.service.method(_interface)
823
827
    def Enable(self):
841
845
    def StopChecker(self):
842
846
        self.stop_checker()
843
847
    
 
848
    ## Properties
 
849
    
844
850
    # name - property
845
851
    @dbus_service_property(_interface, signature=u"s", access=u"read")
846
852
    def name_dbus_property(self):
989
995
    def handle(self):
990
996
        logger.info(u"TCP connection from: %s",
991
997
                    unicode(self.client_address))
992
 
        logger.debug(u"IPC Pipe FD: %d", self.server.child_pipe[1])
 
998
        logger.debug(u"IPC Pipe FD: %d",
 
999
                     self.server.child_pipe[1].fileno())
993
1000
        # Open IPC pipe to parent process
994
 
        with contextlib.nested(os.fdopen(self.server.child_pipe[1],
995
 
                                         u"w", 1),
996
 
                               os.fdopen(self.server.parent_pipe[0],
997
 
                                         u"r", 0)) as (ipc,
998
 
                                                       ipc_return):
 
1001
        with contextlib.nested(self.server.child_pipe[1],
 
1002
                               self.server.parent_pipe[0]
 
1003
                               ) as (ipc, ipc_return):
999
1004
            session = (gnutls.connection
1000
1005
                       .ClientSession(self.request,
1001
1006
                                      gnutls.connection
1142
1147
        
1143
1148
        This function creates a new pipe in self.pipe
1144
1149
        """
1145
 
        self.child_pipe = os.pipe() # Child writes here
1146
 
        self.parent_pipe = os.pipe() # Parent writes here
 
1150
        # Child writes to child_pipe
 
1151
        self.child_pipe = map(os.fdopen, os.pipe(), u"rw", (1, 0))
 
1152
        # Parent writes to parent_pipe
 
1153
        self.parent_pipe = map(os.fdopen, os.pipe(), u"rw", (1, 0))
1147
1154
        super(ForkingMixInWithPipes,
1148
1155
              self).process_request(request, client_address)
1149
1156
        # Close unused ends for parent
1150
 
        os.close(self.parent_pipe[0]) # close read end
1151
 
        os.close(self.child_pipe[1])  # close write end
 
1157
        self.parent_pipe[0].close() # close read end
 
1158
        self.child_pipe[1].close()  # close write end
1152
1159
        self.add_pipe_fds(self.child_pipe[0], self.parent_pipe[1])
1153
1160
    def add_pipe_fds(self, child_pipe_fd, parent_pipe_fd):
1154
1161
        """Dummy function; override as necessary"""
1155
 
        os.close(child_pipe_fd)
1156
 
        os.close(parent_pipe_fd)
 
1162
        child_pipe_fd.close()
 
1163
        parent_pipe_fd.close()
1157
1164
 
1158
1165
 
1159
1166
class IPv6_TCPServer(ForkingMixInWithPipes,
1249
1256
        self.enabled = True
1250
1257
    def add_pipe_fds(self, child_pipe_fd, parent_pipe_fd):
1251
1258
        # Call "handle_ipc" for both data and EOF events
1252
 
        gobject.io_add_watch(child_pipe_fd,
 
1259
        gobject.io_add_watch(child_pipe_fd.fileno(),
1253
1260
                             gobject.IO_IN | gobject.IO_HUP,
1254
1261
                             functools.partial(self.handle_ipc,
1255
 
                                               reply_fd
1256
 
                                               =parent_pipe_fd))
1257
 
    def handle_ipc(self, source, condition, reply_fd=None,
1258
 
                   file_objects={}):
 
1262
                                               reply = parent_pipe_fd,
 
1263
                                               sender= child_pipe_fd))
 
1264
    def handle_ipc(self, source, condition, reply=None, sender=None):
1259
1265
        condition_names = {
1260
1266
            gobject.IO_IN: u"IN",   # There is data to read.
1261
1267
            gobject.IO_OUT: u"OUT", # Data can be written (without
1273
1279
        logger.debug(u"Handling IPC: FD = %d, condition = %s", source,
1274
1280
                     conditions_string)
1275
1281
        
1276
 
        # Turn the pipe file descriptors into Python file objects
1277
 
        if source not in file_objects:
1278
 
            file_objects[source] = os.fdopen(source, u"r", 1)
1279
 
        if reply_fd not in file_objects:
1280
 
            file_objects[reply_fd] = os.fdopen(reply_fd, u"w", 0)
1281
 
        
1282
1282
        # Read a line from the file object
1283
 
        cmdline = file_objects[source].readline()
 
1283
        cmdline = sender.readline()
1284
1284
        if not cmdline:             # Empty line means end of file
1285
1285
            # close the IPC pipes
1286
 
            file_objects[source].close()
1287
 
            del file_objects[source]
1288
 
            file_objects[reply_fd].close()
1289
 
            del file_objects[reply_fd]
 
1286
            sender.close()
 
1287
            reply.close()
1290
1288
            
1291
1289
            # Stop calling this function
1292
1290
            return False
1331
1329
                if client.fingerprint == fpr:
1332
1330
                    attr_value = getattr(client, attr_name, None)
1333
1331
                    logger.debug("IPC reply: %r", attr_value)
1334
 
                    pickle.dump(attr_value, file_objects[reply_fd])
 
1332
                    pickle.dump(attr_value, reply)
1335
1333
                    break
1336
1334
            else:
1337
1335
                logger.error(u"Client %s on address %s requesting "
1338
1336
                             u"attribute %s not found", fpr, address,
1339
1337
                             attr_name)
1340
 
                pickle.dump(None, file_objects[reply_fd])
 
1338
                pickle.dump(None, reply)
1341
1339
        else:
1342
1340
            logger.error(u"Unknown IPC command: %r", cmdline)
1343
1341