
/*---------------------------------------------------------------------------*/
/* appwebsocket.h                                                            */
/* copyright (c) innovaphone 2016 - 2020                                     */
/*                                                                           */
/*---------------------------------------------------------------------------*/

class AppWebsocket : public UWebsocket, public IJsonApiConnection {
    void WebsocketAcceptComplete(class IWebsocket * websocket) override;
    void WebsocketSendResult(class IWebsocket * websocket) override;
    void * WebsocketRecvBuffer(size_t len) override;
    void WebsocketRecvResult(class IWebsocket * websocket, void * buffer, size_t len, bool text, bool isFragmented) override;
    void WebsocketRecvCanceled(class IWebsocket * websocket, void * buffer) override;
    void WebsocketCloseComplete(class IWebsocket * websocket, ws_close_reason_t reason) override;
    void WebsocketMessage(IWebsocket * websocket, size_t messageSize) { };

    class IWebsocket * websocket;
    IInstanceLog * const log;
    JsonApiContext * const jsonApiContext;
    char challenge[17];
    char * digest;
    char * info;
    bool connected;
    char * fragmented;
    unsigned fragmentedLen;
    int sendCount;
    ulong64 unique;
    std::list<class JsonApi *> apis;
    class btree * srcTree;
    
    inline void CalculateKey(const char * password);
    inline bool CheckHash(const char * app, const char * domain, const char * sip, const char * guid, const char * dn, const char * digest, const char * infoText, size_t infoLen, const char * password, const char * challenge = 0);
    inline void ChallengeComplete(const char * nonce, const char * dn, class json_io & send, word & sendBase);
    inline char * UserAppWebsocketPassword();
    inline void UserAppWebsocketServiceInfo(const char * app, class json_io & msg, word base);
    inline void UserAppWebsocketAppInfo(const char * app, class json_io & msg, word base);
    inline const char * UserAppWebsocketDeviceAppType(const char * app);
    inline void UserAppWebsocketClosed();
    void QueueJsonApiResponseSent(JsonApi * response);

public:
    AppWebsocket(IWebserverPlugin * plugin, class IInstanceLog * const log, class JsonApiContext * jsonApiContext = 0);
    virtual ~AppWebsocket();

    virtual bool AppWebsocketChallenge(const char * user, const char * appObj) { return true; };
    virtual char * AppWebsocketPassword() { return 0; };
    virtual char * AppWebsocketPassword(const char * domain) { return NULL; };
    virtual const char * AppWebsocketInstanceDomain() { return NULL; };
    virtual void AppWebsocketMessage(class json_io & msg, word base, const char * mt, const char * src) = 0;
    virtual void AppWebsocketBinaryMessage(void * buffer, int len) { };
    virtual void AppWebsocketAppInfo(const char * app, class json_io & msg, word base) { }
    virtual void AppWebsocketServiceInfo(const char * app, class json_io & msg, word base) { }
    virtual const char * AppWebsocketDeviceAppType(const char * app) { return 0; }
    virtual void AppWebsocketLogin(class json_io & msg, word info) { };
    virtual bool AppWebsocketConnectComplete(class json_io & msg, word info) { return true; }
    virtual void AppWebsocketClosed() = 0;
    virtual bool AppWebsocketApiPermission(const char * api) { return true; }
    virtual void AppWebsocketSendResult() = 0;
    virtual void AppWebsocketCheckLogin(const char * src, const char * app, const char * domain, const char * challenge, const char * digest) { AppWebsocketCheckLoginComplete(src, app, domain, challenge, digest, AppWebsocketPassword()); };
    virtual const char * AppWebsocketBuildString() { return 0; }
    void AppWebsocketChallengeComplete(const char * nonce, const char * dn);
    bool AppWebsocketLoginComplete(const char * password, char * key = 0, unsigned keyLen = 0);
    void AppWebsocketCheckLoginComplete(const char * src, const char * app, const char * domain, const char * challenge, const char * digest, const char * password);
    void AppWebsocketMessageComplete();
    void AppWebsocketMessageSend(class json_io & msg, char * buffer);
    void AppWebsocketMessageSendText(const char * buffer);
    void AppWebsocketMessageSendBinary(char * buffer, int len);
    void AppWebsocketClose();
    bool AppWebsocketCheckPassword(const char* password);

    void AppWebsocketEncrypt(const char * seed, const char * data, char * out, size_t outLen) override;
    void AppWebsocketDecrypt(const char * seed, const char * data, char * out, size_t outLen) override;
    void AppWebsocketHash(const char * seed, const char * data, char * out, size_t outLen) override;

    bool AppWebsocketIsEncryptedConnection() { return (websocket ? websocket->IsEncryptedConnection() : false); }
    const char * AppWebsocketRemoteAddr() { return (websocket ? websocket->GetRemoteAddress() : nullptr); }
    const char * AppWebsocketXForwaredFor() { return (websocket ? websocket->GetHeaderFieldValue("X-Forwarded-For") : nullptr); }

    void RegisterJsonApi(class JsonApi * api, bool uniqueSrc = false) override;
    void UnRegisterJsonApi(class JsonApi * api) override;
    void JsonApiMessage(class json_io & msg, char * buffer, class JsonApi * response = 0) override;
    void JsonApiMessageText(const char * buffer, class JsonApi * response = 0) override;
    void JsonApiMessageComplete() override;
    bool JsonApiPermission(const char * api) override { return AppWebsocketApiPermission(api); };
    const char * JsonApiUserDomain() override { return domain; }
    const char * JsonApiUserSip() override { return sip; }
    const char * JsonApiUserDn() override { return dn; }
    const char * JsonApiUserGuid() override { return guid; }
    const char * JsonApiApp() override { return app; }
    const char * JsonApiInfo() override { return info; }
    const char * JsonApiRemoteAddr() { return AppWebsocketRemoteAddr(); };
    const char * JsonApiXForwaredFor() { return AppWebsocketXForwaredFor(); };
    bool JsonApiUnlicensed() override { return unlicensed; }
    
    char * domain;
    char * sip;
    char * guid;
    char * dn;
    char * app;
    char key[65];
    bool unlicensed;
    bool pbxConnection;
    bool pbxManagerConnection;
};