/*
 * Copyright 2014 Cloud Linux Zug GmbH
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 *
 * The part the support library for lsapi & proxy_lsapi Apache modules
 * author Alexander Demeshko <ademeshko@cloudlinux.com>
 *
 */

#ifndef _LSCAPI_UTIL_H_
#define _LSCAPI_UTIL_H_

#include <lscapi.h>

#include <httpd.h>
#include <http_config.h>
#include <http_core.h>
#include <http_log.h>
#include <http_protocol.h>
#include <unixd.h>
#include <apr_strings.h>

#define LSCAPI_WITH_DUMP_HEADER

#ifdef APACHE2_2

#define APLOGNO(n)              "AH" #n ": "

#define APLOG_USE_MODULE(foo) \
    extern module AP_MODULE_DECLARE_DATA foo##_module

#else

extern const int *lsapilog_module_index;

#ifdef APLOG_MODULE_INDEX
#undef APLOG_MODULE_INDEX
#endif

#define APLOG_MODULE_INDEX  \
    (aplog_module_index ? *aplog_module_index : (lsapilog_module_index ? *lsapilog_module_index : APLOG_NO_MODULE) )
#endif

#define LSCAPI_APLOGNO APLOGNO(01968)

struct lsapi_conn_t {
    request_rec *r;
    const module *m;
    lscapi_rec *lscapi;
    lsphp_conn_t *backend;
};
typedef struct lsapi_conn_t lsapi_conn_t;

struct lsapi_svr_conf_t {
    char *socket_path;
    char *phprc;
    char *selfstarter_socket_path;
    char *hostname_on_debug;
    uint32_t default_uid;
    uint32_t default_gid;

    lscapi_backend_info_t backend_info;
    
    unsigned lve_enabled:1;
    unsigned debug_enabled:1;
    unsigned terminate_backends_on_exit: 1;
    unsigned check_target_perm: 1;
    unsigned use_default_uid:1;
    unsigned selfstarter:1;
    unsigned backend_coredump: 1;
    
    unsigned debug_enabled_was_set:1;
    unsigned terminate_backends_was_set: 1;
    unsigned check_target_perm_was_set: 1;
    unsigned use_default_uid_was_set:1;
    unsigned selfstarter_was_set:1;
    unsigned backend_coredump_was_set: 1;
};
typedef struct lsapi_svr_conf_t lsapi_svr_conf_t;

struct php_param_t {
    char *value;
    size_t valueLen;
    int isAdmin;
    int htaccess;
};
typedef struct php_param_t php_param_t;

#ifdef LSCAPI_DEBUG_UID_GID
#undef LSCAPI_DEBUG_UID_GID
#endif

struct lsapi_dir_conf_t {
    apr_hash_t *phpParams;
#ifdef LSCAPI_DEBUG_UID_GID
    uint32_t lsapi_uids[16];
    uint32_t lsapi_gids[16];
    int lsapi_uid_num;
    
    uint32_t suphp_uids[16];
    uint32_t suphp_gids[16];
    int suphp_uid_num;
    
    uint32_t ruids[16];
    uint32_t rgids[16];
    int ruid_num;
    
    uint32_t itk_uids[16];
    uint32_t itk_gids[16];
    int itk_uid_num;
#else
    uint32_t lsapi_uid;
    uint32_t lsapi_gid;
    uint32_t suphp_uid;
    uint32_t suphp_gid;
    uint32_t ruid;
    uint32_t rgid;
    uint32_t itk_uid;
    uint32_t itk_gid;
#endif //LSCAPI_DEBUG_UID_GID
    
};
typedef struct lsapi_dir_conf_t lsapi_dir_conf_t;

lsapi_conn_t *lscapi_create_connection(request_rec *r, const char *backend_path,
                                       unsigned *flagsPtr, apr_status_t *statusPtr, 
                                       char *errbuf, size_t errlen,
                                       const module *m);
void lscapi_close_connection(lsapi_conn_t *conn);


int lscapi_parse_server_vars(request_rec *r, lscapi_var_t **varsPtr);
int lscapi_parse_special_vars(request_rec *r, apr_hash_t *cfgH, lscapi_var_t **varsPtr);

void lscapi_recreate_http_header(request_rec *r,
                                lsapi_http_header_index_t **hdrIndexPtr,
                                lsapi_header_offset_t **hdrOffsetsPtr, 
                                size_t *hdrOffsetsNumPtr,
                                size_t *contentLengthPtr,
                                char **bufPtr, size_t *bufLenPtr);

#ifdef lscapi_rlog
#undef lscapi_rlog
#endif

#define lscapi_rlog(level, status, r, fmt, ...)           \
    lscapi_log_rerror(__FILE__, __LINE__, level, status, r, fmt, __VA_ARGS__)


void lscapi_log_rerror(const char *file, int line, int level,
                       apr_status_t status,
                        const request_rec *r, const char *fmt, ...)
                        __attribute__((format(printf,6,7)));

#ifdef lscapi_log
#undef lscapi_log
#endif

#define lscapi_log(level, status, s, fmt, ...)           \
    lscapi_log_error(__FILE__, __LINE__, level, status, s, fmt, __VA_ARGS__)


void lscapi_log_error(const char *file, int line, int level,
                       apr_status_t status,
                        const server_rec *s, const char *fmt, ...)
                        __attribute__((format(printf,6,7)));

apr_status_t lscapi_do_request(lsapi_conn_t *conn, lsapi_svr_conf_t *svrcfg);

const char* lscapi_php_value_handler(cmd_parms* cmd, void *cfg,
                                    const char *name, const char *value,
                                    int isAdmin);
const char *lscapi_php_flag_handler(cmd_parms *cmd, void *cfg,
                                    const char *name, const char *value, int isAdmin);
void *lscapi_create_dir_config(apr_pool_t *pool, char *x);
void *lscapi_merge_dir_config(apr_pool_t *pool, void *base, void *cur);
void *lscapi_create_svr_config(apr_pool_t *pool, server_rec *s);
void *lscapi_merge_svr_config(apr_pool_t *pool, void *base, void *cur);


//int process_lve_error (request_rec * r, lsapi_dir_conf_t * cfg);

apr_status_t lscapi_mutex_register(const char *mutex_type,
                                  apr_pool_t *pconf);

apr_status_t lscapi_mutex_create(apr_global_mutex_t **mutex,
                                const char **lockfile,
                                const char *mutex_type,
                                apr_pool_t *pconf,
                                server_rec *s);


pid_t lscapi_starter_send_spawn_cmd(const lscapi_argvs_descr_t *argv_descr, const char *argv_buf, 
                                    const lscapi_envs_descr_t *env_descr, const char *env_buf, 
                                    request_rec *r, int force_start);


const char *lscapi_selfstarter_socketpath_handler(cmd_parms *cmd, const char *value, lsapi_svr_conf_t *cfg);

apr_status_t lscapi_starter_child_init(server_rec* main_server, apr_pool_t* config_pool, const char *prefix);
apr_status_t lscapi_starter_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp);
apr_status_t lscapi_starter_init(const char *prefix, server_rec *main_server, apr_pool_t *config_pool, lsapi_svr_conf_t *cfg); 


#endif //_LSCAPI_UTIL_H_

