libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

extractor_ipc.h (12959B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2012 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19  */
     20 /**
     21  * @file main/extractor_ipc.h
     22  * @brief IPC with plugin (OS-independent API)
     23  * @author Christian Grothoff
     24  *
     25  * @detail
     26  * The IPC communication between plugins and the main library works
     27  * as follows.  Each message begins with a 1-character opcode which
     28  * specifies the message type.  The main library starts the plugins
     29  * by forking the helper process and establishes two pipes for
     30  * communication in both directions.
     31  * First, the main library send an 'INIT_STATE' message
     32  * to the plugin.  The start message specifies the name (and size)
     33  * of a shared memory segment which will contain parts of the (uncompressed)
     34  * data of the file that is being processed.  The same shared memory
     35  * segment is used throughout the lifetime of the plugin.
     36  *
     37  * Then, the following messages are exchanged for each file.
     38  * First, an EXTRACT_START message is sent with the specific
     39  * size of the file (or -1 if unknown) and the number of bytes
     40  * ready in the shared memory segment.  The plugin then answers
     41  * with either:
     42  * 1) MESSAGE_DONE to indicate that no further processing is
     43  *    required for this file; the IPC continues with the
     44  *    EXTRACT_START message for the next file afterwards;
     45  * 2) MESSAGE_SEEK to indicate that the plugin would like to
     46  *    read data at a different offset; the main library can
     47  *    then either
     48  *    a) respond with a MESSAGE_DISCARD_STATE to
     49  *       tell the plugin to abort processing (the next message will
     50  *       then be another EXTRACT_START)
     51  *    b) respond with a MESSAGE_UPDATED_SHM which notifies the
     52  *       plugin that the shared memory segment was moved to a
     53  *       different location in the overall file; the target of the
     54  *       seek should now be within the new range (but does NOT have
     55  *       to be at the beginning of the seek)
     56  * 3) MESSAGE_META to provide extracted meta data to the main
     57  *    library.  The main library can then either:
     58  *    a) respond with a MESSAGE_DISCARD_STATE to
     59  *       tell the plugin to abort processing (the next message will
     60  *       then be another EXTRACT_START)
     61  *    b) respond with a MESSAGE_CONTINUE_EXTRACTING to
     62  *       tell the plugin to continue extracting meta data; in this
     63  *       case, the plugin is then expected to produce another
     64  *       MESSAGE_DONE, MESSAGE_SEEK or MESSAGE_META round of messages.
     65  */
     66 #ifndef EXTRACTOR_IPC_H
     67 #define EXTRACTOR_IPC_H
     68 
     69 #include "extractor_datasource.h"
     70 
     71 
     72 /**
     73  * How long do we allow an individual meta data object to be?
     74  * Used to guard against (broken) plugns causing us to use
     75  * excessive amounts of memory.
     76  */
     77 #define MAX_META_DATA 32 * 1024 * 1024
     78 
     79 /**
     80  * Maximum length of a shared memory object name
     81  */
     82 #define MAX_SHM_NAME 255
     83 
     84 /**
     85  * Sent from LE to a plugin to initialize it (opens shm).
     86  */
     87 #define MESSAGE_INIT_STATE 0x00
     88 
     89 /**
     90  * IPC message send to plugin to initialize SHM.
     91  */
     92 struct InitMessage
     93 {
     94   /**
     95    * Set to #MESSAGE_INIT_STATE.
     96    */
     97   unsigned char opcode;
     98 
     99   /**
    100    * Always zero.
    101    */
    102   unsigned char reserved;
    103 
    104   /**
    105    * Always zero.
    106    */
    107   uint16_t reserved2;
    108 
    109   /**
    110    * Name of the shared-memory name.
    111    */
    112   uint32_t shm_name_length;
    113 
    114   /**
    115    * Maximum size of the shm map.
    116    */
    117   uint32_t shm_map_size;
    118 
    119   /* followed by name of the SHM */
    120 };
    121 
    122 
    123 /**
    124  * Sent from LE to a plugin to tell it extracting
    125  * can now start.  The SHM will point to offset 0
    126  * of the file.
    127  */
    128 #define MESSAGE_EXTRACT_START 0x01
    129 
    130 /**
    131  * IPC message send to plugin to start extracting.
    132  */
    133 struct StartMessage
    134 {
    135   /**
    136    * Set to #MESSAGE_EXTRACT_START.
    137    */
    138   unsigned char opcode;
    139 
    140   /**
    141    * Always zero.
    142    */
    143   unsigned char reserved;
    144 
    145   /**
    146    * Always zero.
    147    */
    148   uint16_t reserved2;
    149 
    150   /**
    151    * Number of bytes ready in SHM.
    152    */
    153   uint32_t shm_ready_bytes;
    154 
    155   /**
    156    * Overall size of the file.
    157    */
    158   uint64_t file_size;
    159 
    160 };
    161 
    162 /**
    163  * Sent from LE to a plugin to tell it that shm contents
    164  * were updated.
    165  */
    166 #define MESSAGE_UPDATED_SHM 0x02
    167 
    168 /**
    169  * IPC message send to plugin to notify it about a change in the SHM.
    170  */
    171 struct UpdateMessage
    172 {
    173   /**
    174    * Set to #MESSAGE_UPDATED_SHM.
    175    */
    176   unsigned char opcode;
    177 
    178   /**
    179    * Always zero.
    180    */
    181   unsigned char reserved;
    182 
    183   /**
    184    * Always zero.
    185    */
    186   uint16_t reserved2;
    187 
    188   /**
    189    * Number of bytes ready in SHM.
    190    */
    191   uint32_t shm_ready_bytes;
    192 
    193   /**
    194    * Offset of the shm in the overall file.
    195    */
    196   uint64_t shm_off;
    197 
    198   /**
    199    * Overall size of the file.
    200    */
    201   uint64_t file_size;
    202 
    203 };
    204 
    205 /**
    206  * Sent from plugin to LE to tell LE that plugin is done
    207  * analyzing current file and will send no more data.
    208  * No message format as this is only one byte.
    209  */
    210 #define MESSAGE_DONE 0x03
    211 
    212 /**
    213  * Sent from plugin to LE to tell LE that plugin needs
    214  * to read a different part of the source file.
    215  */
    216 #define MESSAGE_SEEK 0x04
    217 
    218 /**
    219  * IPC message send to plugin to start extracting.
    220  */
    221 struct SeekRequestMessage
    222 {
    223   /**
    224    * Set to #MESSAGE_SEEK.
    225    */
    226   unsigned char opcode;
    227 
    228   /**
    229    * Always zero.
    230    */
    231   unsigned char reserved;
    232 
    233   /**
    234    * 'whence' value for the seek operation;
    235    * 0 = SEEK_SET, 1 = SEEK_CUR, 2 = SEEK_END.
    236    * Note that 'SEEK_CUR' is never used here.
    237    */
    238   uint16_t whence;
    239 
    240   /**
    241    * Number of bytes requested for SHM.
    242    */
    243   uint32_t requested_bytes;
    244 
    245   /**
    246    * Requested offset; a positive value from the end of the
    247    * file is used of 'whence' is SEEK_END; a postive value
    248    * from the start is used of 'whence' is SEEK_SET.
    249    * 'SEEK_CUR' is never used.
    250    */
    251   uint64_t file_offset;
    252 
    253 };
    254 
    255 /**
    256  * Sent from plugin to LE to tell LE about metadata discovered.
    257  */
    258 #define MESSAGE_META 0x05
    259 
    260 /**
    261  * Plugin to parent: metadata discovered
    262  */
    263 struct MetaMessage
    264 {
    265   /**
    266    * Set to #MESSAGE_META.
    267    */
    268   unsigned char opcode;
    269 
    270   /**
    271    * Always zero.
    272    */
    273   unsigned char reserved;
    274 
    275   /**
    276    * An 'enum EXTRACTOR_MetaFormat' in 16 bits.
    277    */
    278   uint16_t meta_format;
    279 
    280   /**
    281    * An 'enum EXTRACTOR_MetaType' in 16 bits.
    282    */
    283   uint16_t meta_type;
    284 
    285   /**
    286    * Length of the mime type string.
    287    */
    288   uint16_t mime_length;
    289 
    290   /**
    291    * Size of the value.
    292    */
    293   uint32_t value_size;
    294 
    295   /* followed by mime_length bytes of 0-terminated
    296      mime-type (unless mime_length is 0) */
    297 
    298   /* followed by value_size bytes of value */
    299 
    300 };
    301 
    302 /**
    303  * Sent from LE to plugin to make plugin discard its state
    304  * (extraction aborted by application).  Only one byte.
    305  * Plugin should get ready for next 'StartMessage' after this.
    306  * (sent in response to META data or SEEK requests).
    307  */
    308 #define MESSAGE_DISCARD_STATE 0x06
    309 
    310 /**
    311  * Sent from LE to plugin to make plugin continue extraction.
    312  * (sent in response to META data).
    313  */
    314 #define MESSAGE_CONTINUE_EXTRACTING 0x07
    315 
    316 /**
    317  * Sent from plugin to LE to show that the plugin is still making
    318  * progress although it has not read, sought or reported anything for a
    319  * while (LE closes channels that stay silent for too long).  Only one
    320  * byte, no reply.  The plugin side sends it (rate-limited) whenever the
    321  * plugin calls `seek (cls, 0, SEEK_CUR)`.
    322  */
    323 #define MESSAGE_ALIVE 0x08
    324 
    325 
    326 /**
    327  * Definition of an IPC communication channel with
    328  * some plugin.
    329  */
    330 struct EXTRACTOR_Channel;
    331 
    332 /**
    333  * Definition of a shared memory area.
    334  */
    335 struct EXTRACTOR_SharedMemory;
    336 
    337 
    338 /**
    339  * Create a shared memory area.
    340  *
    341  * @param size size of the shared area
    342  * @return NULL on error
    343  */
    344 struct EXTRACTOR_SharedMemory *
    345 EXTRACTOR_IPC_shared_memory_create_ (size_t size);
    346 
    347 
    348 /**
    349  * Destroy shared memory area.
    350  *
    351  * @param shm memory area to destroy
    352  * @return NULL on error
    353  */
    354 void
    355 EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm);
    356 
    357 
    358 /**
    359  * Change the reference counter for this shm instance.
    360  *
    361  * @param shm instance to update
    362  * @param delta value to change RC by
    363  * @return new RC
    364  */
    365 unsigned int
    366 EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm,
    367                                         int delta);
    368 
    369 
    370 /**
    371  * Initialize shared memory area from data source.
    372  *
    373  * @param shm memory area to initialize
    374  * @param ds data source to use for initialization
    375  * @param off offset to use in data source
    376  * @param size number of bytes to copy
    377  * @return -1 on error, otherwise number of bytes copied
    378  */
    379 ssize_t
    380 EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm,
    381                                   struct EXTRACTOR_Datasource *ds,
    382                                   uint64_t off,
    383                                   size_t size);
    384 
    385 
    386 /**
    387  * Query datasource for current position
    388  *
    389  * @param ds data source to query
    390  * @return current position in the datasource or UINT64_MAX on error
    391  */
    392 uint64_t
    393 EXTRACTOR_datasource_get_pos_ (struct EXTRACTOR_Datasource *ds);
    394 
    395 
    396 /**
    397  * Create a channel to communicate with a process wrapping
    398  * the plugin of the given name.  Starts the process as well.
    399  *
    400  * @param plugin the plugin
    401  * @param shm memory to share with the process
    402  * @return NULL on error, otherwise IPC channel
    403  */
    404 struct EXTRACTOR_Channel *
    405 EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
    406                                struct EXTRACTOR_SharedMemory *shm);
    407 
    408 
    409 /**
    410  * Destroy communication channel with a plugin/process.  Also
    411  * destroys the process.
    412  *
    413  * @param channel channel to communicate with the plugin
    414  */
    415 void
    416 EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel);
    417 
    418 
    419 /**
    420  * Send data via the given IPC channel (blocking).
    421  *
    422  * @param channel channel to communicate with the plugin
    423  * @param buf data to send
    424  * @param size number of bytes in buf to send
    425  * @return -1 on error, number of bytes sent on success
    426  *           (never does partial writes)
    427  */
    428 ssize_t
    429 EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
    430                              const void *data,
    431                              size_t size);
    432 
    433 
    434 /**
    435  * Handler for a message from one of the plugins.
    436  *
    437  * @param cls closure
    438  * @param plugin plugin of the channel sending the message
    439  * @param meta_type type of the meta data
    440  * @param meta_format format of the meta data
    441  * @param mime mime string send from the plugin
    442  * @param value 'data' send from the plugin
    443  * @param value_len number of bytes in 'value'
    444  */
    445 typedef void (*EXTRACTOR_ChannelMessageProcessor) (void *cls,
    446                                                    struct EXTRACTOR_PluginList *
    447                                                    plugin,
    448                                                    enum EXTRACTOR_MetaType
    449                                                    meta_type,
    450                                                    enum EXTRACTOR_MetaFormat
    451                                                    meta_format,
    452                                                    const char *mime,
    453                                                    const void *value,
    454                                                    size_t value_len);
    455 
    456 
    457 /**
    458  * Process a reply from channel (seek request, metadata and done message)
    459  *
    460  * @param plugin plugin this communication is about
    461  * @param buf buffer with data from IPC channel
    462  * @param size number of bytes in buffer
    463  * @param proc metadata callback
    464  * @param proc_cls callback cls
    465  * @return number of bytes processed, -1 on error
    466  */
    467 ssize_t
    468 EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin,
    469                               const void *data,
    470                               size_t size,
    471                               EXTRACTOR_ChannelMessageProcessor proc,
    472                               void *proc_cls);
    473 
    474 
    475 /**
    476  * Receive data from any of the given IPC channels (blocking).
    477  * Wait for one of the plugins to reply.
    478  *
    479  * @param channels array of channels, channels that break may be set to NULL
    480  * @param num_channels length of the 'channels' array
    481  * @param proc function to call to process messages (may be called
    482  *             more than once)
    483  * @param proc_cls closure for 'proc'
    484  * @return -1 on error (i.e. no response in 10s), 1 on success
    485  */
    486 int
    487 EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
    488                              unsigned int num_channels,
    489                              EXTRACTOR_ChannelMessageProcessor proc,
    490                              void *proc_cls);
    491 
    492 
    493 #endif