#ifndef _STRUCTS_H_344737a8_ #define _STRUCTS_H_344737a8_ /* This file is in the public domain. */ #include #include /* * Data structures and types shared by enough places we prefer to keep * them in a common file. */ /* * What kinds of data a repository can store: integer or float. */ typedef enum { DT_INT = 1, DT_FLOAT, } DATATYPE; /* * Return values from a section parse routine: GOOD meaning "recognized * and parsed" and UNKNOWN meaning "I don't recognize this". * ("Recognized but parse failed" is not a return status; that's * handled by calling config_err, which throws.) */ typedef enum { SPRV_GOOD = 1, SPRV_UNKNOWN, } SPRV; /* * Return values from a map's match routine. NOMATCH is "doesn't match * me"; MATCH is "matches me"; ERROR is "this is an error". */ typedef enum { MATCH_NOMATCH = 1, MATCH_MATCH, MATCH_ERROR, } MAPMATCH; /* * TIMEINTVL is a time interval; TIMESTAMP is, well, a timestamp. * Units are nanoseconds. */ typedef signed long long int TIMEINTVL; typedef unsigned long long int TIMESTAMP; typedef struct config CONFIG; typedef struct repo REPO; typedef struct listen LISTEN; typedef struct lep LEP; typedef struct lepfd LEPFD; typedef struct lep_ops LEP_OPS; typedef struct map MAP; typedef struct map_ops MAP_OPS; typedef struct sect_ops SECT_OPS; typedef struct pairlist PAIRLIST; typedef struct config_parse_temp CONFIG_PARSE_TEMP; /* * A generic list of ordererd pairs of pointers, as used by (eg) the * config-file switchover code. */ struct pairlist { PAIRLIST *link; void *a; void *b; } ; /* * A configuration. repos and listens are lists of the reposotry and * listen sections. confstat is fstat() on the config file (for fast * detection of unchanged config files). pt is normally nil, but is * used by config.c during parsing (the details of CONFIG_PARSE_TEMP * are private to config.c). */ struct config { REPO *repos; LISTEN *listens; struct stat confstat; CONFIG_PARSE_TEMP *pt; } ; /* * A listen section. link is the link field for the linked list they * are kept in by the CONFIG; conf is a backpointer to the config (a * LISTEN needs to match things against its config's list of repos). * These are refcounted, since a connection may hold a reference to * one across a config-file reload; refs is the refcount. permit is a * bitmask saying what operations the listen point permits. endpoints * is the listen section's list of listening endpoints; mappings is * its list of mappings. */ struct listen { LISTEN *link; CONFIG *conf; int refs; unsigned int permit; #define OP_NEW 0x00000001 #define OP_FETCH 0x00000002 LEP *endpoints; MAP *mappings; } ; /* * A LEP is a listener endpoint. These correspond more or less * one-to-one to endpoint lines like `local' or `ip' in the config * file. These are pretty much pure OO, being just an operations * dispatch vector and an instance-private data blob. * * If an endpoint line corresponds to multiple OS-level endpoints (as, * eg, an `ip' line can if the name has multiple addresses), it is the * LEP's implementation's responsibility to hide this fact within * itself. * * See lep-*.c. */ struct lep { LEP *link; const LEP_OPS *ops; void *priv; } ; /* * A MAP is a mapping for a listener. These correspond more or less * one-to-one to `map' lines in the config file. There are a few * common variables, notably the priority and a flags field used when * matching, but otherwise they are OO, being just an operations * dispatch vector and an instance-private data blob. */ struct map { MAP *link; int pri; unsigned int flags; #define MF_MATCHED 0x00000001 const MAP_OPS *ops; void *priv; } ; /* * The method pointers for a LEP. */ struct lep_ops { /* * (*add)() is a class method. It checks whether a line is * appropriate for this LEP class; if so, it adds it to the LISTEN * and returns 1, otherwise it does nothing and returns 0. Besides * the CONFIG and the LISTEN, the args: the first word on the line, * the length of that word, and a pointer to the first non-space * character after that first word. * * This is responsible for creating not only the instance-private * data blob but the LEP as well. The LEP's priv field, as set up * by this, is what's passed to the rest of the methods. */ int (*add)(CONFIG *, LISTEN *, const char *, int, const char *); /* * Free up the private data blob. The rest of the LEP is freed by * common code. */ void (*free)(void *); /* * The next four methods are support for migrating between old and * new configs on a reload. When a transfer is about to be tried, * (*pre_transfer)() is called on every LEP in the old config; this * is intended as a chance to clear internal flags or the like. * (The new config's LEPs are assumed to be set up correctly by the * add method.) Then (*setup_transfer)() is called for every pair * of LEPs (first arg is the old LEP, second arg is the new); it is * called only when the LEPs are of the same class, as determined by * comparing their ops pointers. It should figure out whether any * resources (typically file descriptors) can be moved from the old * LEP to the new, and, if so, record enough information to either * do so or back out. It needs to be careful that it doesn't try * to, for example, send one old LEP's resource to two new LEPs * (unless, of course, the resource is one that can be shared); * transfers will probably need to be recorded by both the old and * new LEPs involved. Then, if the transfer is to be done, * (*do_transfer)() is called on every LEP in the_new config; * otherwise, (*no_transfer)() is called on every LEP in the old * config. do_transfer and no_transfer need to take care that they * do nothing when called on LEPs for which no transfer is set up. * * Note that pre_transfer and no_transfer are called on the old * config's LEPs, whereas do_transfer is called on the new. */ void (*pre_transfer)(void *); void (*setup_transfer)(void *, void *); void (*do_transfer)(void *); void (*no_transfer)(void *); /* * When migrating to a new config, this is called for every LEP in * the new config. It returns true on error and false on success. * It is called after (*setup_transfer)() (see above) has been * called with the new LEP and every possible old LEP; if a transfer * has been set up for the new LEP, (*openfds)() should take this * into account in figuring out how much to do for it (this * probably means doing nothing). */ int (*openfds)(void *); /* * This is called (after the do_transfer call) on every new LEP when * a config is being taken into service. It should make add_poll_fd * and add_block_fn calls as appropriate. */ void (*setup_poll)(void *); } ; /* * Initializer for a LEP_OPS, assuming a regular function naming * scheme. */ #define LEP_OPS_INIT(name) { \ &lep_##name##_add, \ &lep_##name##_free, \ &lep_##name##_pre_transfer, \ &lep_##name##_setup_transfer, \ &lep_##name##_do_transfer, \ &lep_##name##_no_transfer, \ &lep_##name##_openfds, \ &lep_##name##_setup_poll, \ } /* * The method pointers for a MAP. */ struct map_ops { /* * (*add)() is a class method. It checks whether a map line is * appropriate for this MAP class; if so, it adds it to the LISTEN * and returns 1, otherwise it does nothing and returns 0. Besides * the CONFIG and the LISTEN, the args: the priority, the map type * keyword (the first word after the priority), the length of that * word, and a pointer to the first non-space character after that * word. * * This is responsible for creating not only the instance-private * data blob but the MAP as well, including the common fields. The * MAP's priv field, as set up by this, is what's passed to the rest * of the methods. */ int (*add)(CONFIG *, LISTEN *, int, const char *, int, const char *); /* * Match a repository name as received from the client against this * MAP. See the MAPMATCH definition, above. */ MAPMATCH (*match)(void *, const char *); /* * Actually map a received repository name to its internal name. * This is called only when the match method returns MATCH_MATCH. */ char *(*map)(void *, const char *); /* * Free up the private data blob. The rest of the MAP is freed by * common code. */ void (*free)(void *); } ; /* * Initializer for a MAP_OPS, assuming a regular function naming * scheme. */ #define MAP_OPS_INIT(name) { \ &map_##name##_add, \ &map_##name##_match, \ &map_##name##_map, \ &map_##name##_free, \ } /* * The method pointers for a section. */ struct sect_ops { /* * (*start)() is passed a line (and a CONFIG pointer). It must test * whether the line is a suitable start line for its section. If * so, it should parse the line, set up its instance private data * blob, and return the blob pointer. If not, it should return nil. * (The case where the line is recognized but the parse fails is * handled with config_err(), which throws; start does not return in * that case.) */ void *(*start)(const char *, CONFIG *); /* * (*parse)() is called to parse a line. If the section does not * recognize the line, it should return SPRV_UNKNOWN. If the line * is recognized and the parse succeeds, it should return SPRV_GOOD. * If the line is recognized but the parse fails, it should call * config_err(), which throws, and thus will not return at all. */ SPRV (*parse)(void *, const char *); /* * Called when the section ends, either at the beginning of the next * section or at EOF. Any errors are reported through config_err(), * which throws, so there is no meaningful return value. * * Note that it is too late to avoid closing the section. Even on * error, it should free up its internal structures (this may mean * using config_err_post). */ void (*done)(void *); } ; /* * Initializer for a SECT_OPS, assuming a regular function naming * scheme. */ #define SECT_OPS_INIT(name) { \ §_##name##_start, \ §_##name##_parse, \ §_##name##_done, \ } #endif