//
//  psndselector.h
//  psdemux
//
//  Created by Luo Han on 16/1/21.
//  Copyright © 2016年 PowerInfo. All rights reserved.
//

#include "pzbc.h"

#ifndef psndselector_h
#define psndselector_h

#define PSDEFAULT_TIMEOUT   60 * 60 * 1000
#define PSDNS_FAIL_TIMEOUT  5 * 60 * 1000

#define NODE_SELECT_RESERVED    0   //0: 保留
#define NODE_SELECT_FASTWEB     1   //1: 启用节点优选，快网提供的fast-dns
#define NODE_SELECT_NULL        2   //2: 不启用节点优选，直接依赖DNS解析
#define NODE_SELECT_PZB         3   //3: 启用节点优选，PZB优选机制
#define NODE_SELECT_PZB_INKE    4   //4: 启用节点优选，PZB优选机制，inke的pzb服务器
#define NODE_SELECT_PZB_JP      5   //5: 启用节点优选，PZB优选机制，Japan的pzb服务器
#define NODE_SELECT_PZB_TEST    255 //255: 启用节点优选，PZB优选机制，Test（灰度）的pzb服务器

#define NODE_SELECT_DEFAULT     NODE_SELECT_FASTWEB
#define NODE_SELECT_MAX         3
#define MAX_SOLID_IP            16

#define	PZB_SERVICE_MODE_AUTO				0	//	pzb自行判断服务类型
#define	PZB_SERVICE_MODE_PUBLISH_USER		1	//	为user/主播提供普通推流服务
#define	PZB_SERVICE_MODE_PULL_USER			2	//	为user/主播提供普通收流服务
#define	PZB_SERVICE_MODE_PUBLISH_LINKUSER	3	//	为user/主播提供群聊推流服务
#define	PZB_SERVICE_MODE_PULL_LINKUSER		4	//	为user/主播提供群聊收流服务

//class PZBC;

#define NDSELECT_DOMAIN_LEN 64

int pzb_parseurl(const char* httpurl, char* domain, int domainlen, DWORD* port, char* uri, int urilen, int *mode);

int getndmodefromurl(char*url, const char* name, char* value, const int valuelen);

typedef struct PSDNSInfo
{
    char    domain[1024];
    int     request_type; // 0-invalid 1-fast dns, 2-basic dns, 3-pzb dns
    int     real_type;  // -1-invalid, 0-basic, 1-fast dns, 2-basic dns, 3-pzb dns
    int     solid_ip[MAX_SOLID_IP];
    int     basic_ip;
    int     number_solid_ip;
    bool    usableflag_solid_ip[MAX_SOLID_IP];
    int     usableflag_num;
    
    long long basic_refresh_time;
    long long solid_refresh_time;
    long long basic_fail_time;
    long long solid_fail_time;
} PSDNSInfo;

class PSNDSelector
{
public:
    //PSNDSelector *getInstance();
    
    int start(int timeout_ms = PSDEFAULT_TIMEOUT);
    int stop();
    int addURL_domain(const char *domain, int type);
    int addURL(const char *url, int type);
    int getIP(const char *url, int type, int *ip, int *real_type, char* desiredDomain, char* acturalDomain);
    int getIP_domain(const char *domain, int type, int *ip, int *real_type, char* desiredDomain, char* acturalDomain);
    
    int getIPV6(const char *url, int type, in6_addr *ip, int *real_type, char* desiredDomain, char* acturalDomain);
    int getIPV6_domain(const char *domain, int type, in6_addr *ip, int *real_type, char* desiredDomain, char* acturalDomain);
    
    /**
     @param iptype if PSL_IPV6_ONLY, then the type of ip is in6_addr*
                   if PSL_IPV4_ONLY, then the type of ip is int*
     @param ip if ip type is PSL_IPV4_ONLY, ip is network byte order
     */
    int setSolidIPunUsable(const char *domain, void*ip, int iptype);
    
    void selectorProc();
    
    void refresh();
    
    //private:
    PSNDSelector();
    ~PSNDSelector();
    
private:
    int basicIP(const char *domain, int *ip, int timeout_ms);
    int basicIPV6(const char *domain, in6_addr *ip, int timeout_ms);
    int solidIP(const char *domain, int *ip, int *ipnum, int timeout_ms);
    int getDomain(const char *url, char *domain);
    int addDomain(const char *domain, int type);
    int getDomainIP(const char *domain, int type, int *ip, int *real_type, in6_addr *ipv6, int *ipv6flag, char* desiredDomain, char* acturalDomain);
    int getDomainIPV4(const char *domain, int type, int *ip, int *real_type, char* desiredDomain, char* acturalDomain);
    
    //PSNDSelector *m_pInstance;
    PI_iLiveBase_Mutex m_Lock;
    
    PSDNSInfo *m_pInfo;
    void *m_pSelectorThread;
    
    int m_iStatus;  // 0-stop, 1-running
    int m_iStopFlag;  // 0-do nothing, 1-stop running
    int m_iDomainNumber;
    int m_iTimeout;  // ms
    int m_refreshflag;
    
    int m_ipvxflag;
    int m_iFastDNSIP;  // cache
    bool    m_bFastDNSIPV6Flag;
    char m_iFastDNSIPV6[128];
    long long m_llFastDNSIPRefreshTime;
};

#endif /* psndselector_h */
