#pragma once

#ifdef COMPILING_FLOWSSHC
	#define FLOWSSHC_FUNC extern "C" __declspec(dllexport)
#else
	#ifdef __cplusplus
		#define FLOWSSHC_FUNC extern "C" __declspec(dllimport)
	#else
		#define FLOWSSHC_FUNC
	#endif
	#ifdef _WIN64
		#pragma comment(lib, "FlowSshC64.lib")
	#else
		#pragma comment(lib, "FlowSshC32.lib")
	#endif
#endif

#ifdef _WIN64
	#pragma pack (push, 16)
#else
	#pragma pack (push, 8)
#endif

#define FLOWSSHC_PORT_UNIXSOCKET ((unsigned int)(-1))


// Windows
#define NOMINMAX
#include <WTypes.h>


#ifdef __cplusplus
	#define FLOWSSHC_OPAQUE(NAME) typedef struct _##NAME {} NAME
	#define FLOWSSHC_BOOL bool
#else
	#define FLOWSSHC_OPAQUE(NAME) typedef struct _##NAME NAME
	#define FLOWSSHC_BOOL char
#endif


typedef struct _FlowSshC_Version
{
	unsigned short m_major;
	unsigned short m_minor;
} FlowSshC_Version;

FLOWSSHC_FUNC FlowSshC_Version					__cdecl FlowSshC_GetVersion();



enum FlowSshC_ErrorFlags {
	// Notes:
	// - Error (exception) has occurred during FlowSshC function call.
	// - Handler implementation may throw exceptions with this flag.
	// - InCall and InHandler flags are always exclusive.
	FlowSshC_ErrorFlags_InCall		= 0x01,
	// Notes:
	// - Error has occurred in one of the user provided FlowSshC handlers.
	// - Handler implementation must not throw exceptions with this type.
	// - InCall and InHandler flags are always exclusive.
	FlowSshC_ErrorFlags_InHandler	= 0x02
 };

typedef void (__cdecl* FlowSshC_ErrorHandler)(void* handlerData, unsigned int flags, wchar_t const* desc);



// Notes:
// - FlowSshC needs to be initialized before calling any of the functions below this one.
// - Resources acquired through initialization can be freed with FlowSshC_Shutdown call.
// - The function may be called multiple times for the purpose of changing the error 
//   handler. Calling the function multiple times has no other effects - shutdown will
//   always be performed with the first call to FlowSshC_Shutdown.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Initialize(FlowSshC_ErrorHandler handler, void* handlerData);



// Notes:
// - Call this function with the activation code received from Bitvise once a FlowSsh license has been purchased.
// - Setting a valid activation code will remove the "Welcome to FlowSsh evaluation!" message box shown by the library.
// - The activation code is normally provided as two long lines of hexadecimal characters.
//   Concatenate the two lines of the activation code into a single string before passing it to this function.
FLOWSSHC_FUNC void								__cdecl FlowSshC_SetActCode(wchar_t const* actCodeHex);



enum FlowSshC_TaskState {
	FlowSshC_TaskState_InProgress	= 100,
	FlowSshC_TaskState_Completed	= 200,
	FlowSshC_TaskState_Failed		= 300
};

// Notes:
// - Task specific step is provided for InProgress and Failed states only.
// - In-progress steps are registered right before they are to be processed. 
// - Auxilary info may be NULL; it normally is NULL for InProgress and Completed states.
typedef void (__cdecl* FlowSshC_ProgressHandler)(void* handlerData, unsigned int taskState, unsigned int taskSpecificStep, wchar_t const* auxInfo);



FLOWSSHC_OPAQUE(FlowSshC_Keypair);
// Notes:
// - Supported key algorithms:
//     ssh-rsa - includes support for signature algorithms rsa-sha2-256 and rsa-sha2-512;
//     ssh-dss - 1024-bit keys only; there is no commonly accepted standard for larger DSA keys in SSH;
//     ssh-ed25519; ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ecdsa-sha2-1.3.132.0.10
// - Bit count parameter is ignored with ecdsa-ssh2-* algorithms.
FLOWSSHC_FUNC FlowSshC_Keypair*					__cdecl FlowSshC_Keypair_CreateNew(wchar_t const* alg, unsigned int bitCount);
// Notes:
// - Returns NULL if keypair (private key) cannot be decoded (e.g. bad data or passphrase).
// - Supported formats: OpenSSH, Bitvise (regular, WinSSHD, and legacy wcfg), Putty.
// - Passphrase parameter can be NULL if passphrase is not required.
FLOWSSHC_FUNC FlowSshC_Keypair*					__cdecl FlowSshC_Keypair_CreateFromData(unsigned char const* data, unsigned int dataBytes, wchar_t const* passphrase);
FLOWSSHC_FUNC FlowSshC_Keypair*					__cdecl FlowSshC_Keypair_CreateCopy(FlowSshC_Keypair* keypair);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Keypair_AddRef(FlowSshC_Keypair* keypair);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Keypair_Release(FlowSshC_Keypair* keypair);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Keypair_SetPassphrase(FlowSshC_Keypair* keypair, wchar_t const* passphrase);
// Note for the remaining FlowSshC_Keypair_* functions:
// - Caller needs to release the returned BSTR with SysFreeString().
// - Returns NULL if the algorithm is not supported in format requested.
// - OpenSsh format suports the following algorithms: ssh-rsa, ssh-dss,
//   ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, and ecdsa-sha2-nistp521.
// - Putty format supports ssh-rsa and ssh-dss algorithms only.
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_Keypair_GetBitviseData(FlowSshC_Keypair* keypair);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_Keypair_GetOpenSshData(FlowSshC_Keypair* keypair);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_Keypair_GetPuttyData(FlowSshC_Keypair* keypair);


FLOWSSHC_OPAQUE(FlowSshC_PublicKey);
FLOWSSHC_FUNC FlowSshC_PublicKey*				__cdecl FlowSshC_PublicKey_CreateFromKeypair(FlowSshC_Keypair* keypair);
// Notes:
// - Returns NULL if public key cannot be decoded.
// - Supported formats: SSH2, OpenSSH, Bitvise, hex-encoded bytes, plain bytes.
FLOWSSHC_FUNC FlowSshC_PublicKey*				__cdecl FlowSshC_PublicKey_CreateFromData(unsigned char const* data, unsigned int dataBytes);
FLOWSSHC_FUNC FlowSshC_PublicKey*				__cdecl FlowSshC_PublicKey_CreateCopy(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC void								__cdecl FlowSshC_PublicKey_AddRef(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC void								__cdecl FlowSshC_PublicKey_Release(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC unsigned int						__cdecl FlowSshC_PublicKey_GetBitCount(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC unsigned int						__cdecl FlowSshC_PublicKey_GetEffectiveSecurity(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC FLOWSSHC_BOOL						__cdecl FlowSshC_PublicKey_IsEqual(FlowSshC_PublicKey* publicKey, FlowSshC_PublicKey* other);
// Note for the remaining FlowSshC_PublicKey_* functions:
// - Caller needs to release the returned BSTR with SysFreeString().
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PublicKey_GetAlg(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PublicKey_GetMd5(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PublicKey_GetBubbleBabble(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PublicKey_GetSha256(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PublicKey_GetSsh2Data(FlowSshC_PublicKey* publicKey);
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PublicKey_GetOpenSshData(FlowSshC_PublicKey* publicKey);



FLOWSSHC_OPAQUE(FlowSshC_FurtherAuth);
FLOWSSHC_FUNC void								__cdecl FlowSshC_FurtherAuth_SetUserName(FlowSshC_FurtherAuth* furtherAuth, wchar_t const* userName);
FLOWSSHC_FUNC void								__cdecl FlowSshC_FurtherAuth_SetPassword(FlowSshC_FurtherAuth* furtherAuth, wchar_t const* password);
FLOWSSHC_FUNC void								__cdecl FlowSshC_FurtherAuth_SetKeypair(FlowSshC_FurtherAuth* furtherAuth, FlowSshC_Keypair* keypair);
// Note:
// - Whether any of the previous authentication attempts have succeeded, but at the same
//   time, more authentication is required by the server. Partial success flag is reset
//   each time further authentication continues.
FLOWSSHC_FUNC FLOWSSHC_BOOL						__cdecl FlowSshC_FurtherAuth_HavePartialSuccess(FlowSshC_FurtherAuth* furtherAuth);
// Notes for the remaining FlowSshC_FurtherAuth_* functions:
// - Whether the server will accept 'password' or 'publickey' authentication methods.
// - Some servers accept password through 'keyboard-interactive' authentication method.
//   Password remaining flag takes that into account as well.
// - Results of these functions are irrelevant if user name is changed.
FLOWSSHC_FUNC FLOWSSHC_BOOL						__cdecl FlowSshC_FurtherAuth_IsPasswordRemaining(FlowSshC_FurtherAuth* furtherAuth);
FLOWSSHC_FUNC FLOWSSHC_BOOL						__cdecl FlowSshC_FurtherAuth_IsPublicKeyRemaining(FlowSshC_FurtherAuth* furtherAuth);



FLOWSSHC_OPAQUE(FlowSshC_PasswordChange);
FLOWSSHC_FUNC void								__cdecl FlowSshC_PasswordChange_SetNewPassword(FlowSshC_PasswordChange* passwordChange, wchar_t const* password);
// Note:
// - Caller needs to release the returned BSTR with SysFreeString().
FLOWSSHC_FUNC BSTR								__cdecl FlowSshC_PasswordChange_GetPrompt(FlowSshC_PasswordChange* passwordChange);



enum FlowSshC_ConnectStep {
	FlowSshC_ConnectStep_ConnectToProxy		= 100,	// Skipped when connecting directly.
	FlowSshC_ConnectStep_ConnectToSshServer	= 200,
	FlowSshC_ConnectStep_SshVersionString	= 300,
	FlowSshC_ConnectStep_SshKeyExchange		= 400,
	FlowSshC_ConnectStep_SshUserAuth		= 500
};

enum FlowSshC_DisconnectReason {
	FlowSshC_DisconnectReason_Exception			= 0,
	FlowSshC_DisconnectReason_FlowError			= 1,
	FlowSshC_DisconnectReason_ConnectionError	= 2,
	FlowSshC_DisconnectReason_ConnectionLost	= 3,
	FlowSshC_DisconnectReason_ByServer			= 4,
	FlowSshC_DisconnectReason_ByClient			= 5
};

enum FlowSshC_ProxyType {
	FlowSshC_ProxyType_None			= 0,
	FlowSshC_ProxyType_Socks4		= 1,
	FlowSshC_ProxyType_Socks5		= 2,
	FlowSshC_ProxyType_HttpConnect	= 3
};


// Notes for FlowSshC_*Algs structures:
// - Algorithm is enabled if it holds a non-zero value.
// - Algorithms with lower non-zero values precede algorithms with higher values.
// - Algorithms holding the same non-zero values are ordered by the declaration order.

typedef struct _FlowSshC_KeyExchangeAlgs
{
	byte         m_mlkem1024nistp384;	// mlkem1024nistp384-sha384
	byte         m_mlkem768x25519;		// mlkem768x25519-sha256

	byte         m_curve25519;			// curve25519-sha256, curve25519-sha256@libssh.org
	byte         m_ecdhSecp256k1;		// ecdh-sha2-1.3.132.0.10
	byte         m_ecdhNistp512;		// ecdh-sha2-nistp521
	byte         m_ecdhNistp384;		// ecdh-sha2-nistp384
	byte         m_ecdhNistp256;		// ecdh-sha2-nistp256

	unsigned int m_gexBitsMin;			// Pass 0 to use default (2047)
	unsigned int m_gexBitsOpt;			// Pass 0 to use default (3072)
	unsigned int m_gexBitsMax;			// Pass 0 to use default (4096)
	byte         m_dhG16Sha512;			// diffie-hellman-group16-sha512
	byte         m_dhG15Sha512;			// diffie-hellman-group15-sha512
	byte         m_dhG14Sha256;			// diffie-hellman-group14-sha256
	byte         m_dhG14Sha1;			// diffie-hellman-group14-sha1
	byte         m_dhG1Sha1;			// diffie-hellman-group1-sha1 (disabled by default)
	byte         m_dhGexSha256;			// diffie-hellman-group-exchange-sha256
	byte         m_dhGexSha1;			// diffie-hellman-group-exchange-sha1
} FlowSshC_KeyExchangeAlgs;

typedef struct _FlowSshC_HostKeyAlgs
{
	byte m_rsaSha2_512;		// rsa-sha2-512
	byte m_rsaSha2_256;		// rsa-sha2-256
	byte m_ed25519;			// ssh-ed25519
	byte m_ecdsaSecp256k1;	// ecdsa-sha2-1.3.132.0.10
	byte m_ecdsaNistp521;	// ecdsa-sha2-nistp521
	byte m_ecdsaNistp384;	// ecdsa-sha2-nistp384
	byte m_ecdsaNistp256;	// ecdsa-sha2-nistp256
	byte m_sshRsa;			// ssh-rsa
	byte m_sshDss;			// ssh-dsa
} FlowSshC_HostKeyAlgs;

typedef struct _FlowSshC_EncryptionAlgs
{
	byte m_chacha20Poly1305;	// chacha20-poly1305@openssh.com
	byte m_aes256Gcm;			// aes256-gcm@openssh.com
	byte m_aes128Gcm;			// aes128-gcm@openssh.com
	byte m_aes256Ctr;			// aes256-ctr
	byte m_aes192Ctr;			// aes192-ctr
	byte m_aes128Ctr;			// aes128-ctr
	byte m_tripleDesCtr;		// 3des-ctr
	byte m_aes256Cbc;			// aes256-cbc
	byte m_aes192Cbc;			// aes192-cbc
	byte m_aes128Cbc;			// aes128-cbc
	byte m_tripleDesCbc;		// 3des-cbc
} FlowSshC_EncryptionAlgs;

typedef struct _FlowSshC_MacAlgs
{
	byte m_hmacSha2_256_etm;	// hmac-sha2-256-etm@openssh.com
	byte m_hmacSha2_512_etm;	// hmac-sha2-512-etm@openssh.com
	byte m_hmacSha1_etm;		// hmac-sha1-etm@openssh.com
	byte m_hmacSha2_256;		// hmac-sha2-256
	byte m_hmacSha2_512;		// hmac-sha2-512
	byte m_hmacSha1;			// hmac-sha1
} FlowSshC_MacAlgs;

typedef struct _FlowSshC_CompressionAlgs
{
	byte m_none;			// none
	byte m_zlib;			// zlib
} FlowSshC_CompressionAlgs;

typedef struct _FlowSshC_Options
{
	bool m_startKeyReExchange;
	int m_sendBasedKeepAliveTimeoutMs;
	int m_recvBasedKeepAliveTimeoutMs;
	int m_recvBasedKeepAliveRelaxedTimeoutMs;
	int m_recvBasedUnresponsivenessTimeoutMs;
} FlowSshC_Options;

inline void FlowSshC_Options_Initialize(FlowSshC_Options* options)
{
	options->m_startKeyReExchange = true;
	options->m_sendBasedKeepAliveTimeoutMs = -1;
	options->m_recvBasedKeepAliveTimeoutMs = -1;
	options->m_recvBasedKeepAliveRelaxedTimeoutMs = -1;
	options->m_recvBasedUnresponsivenessTimeoutMs = -1;
}

enum FlowSshC_SendExtInfo {
	FlowSshC_SendExtInfo_Default		= 0,
	FlowSshC_SendExtInfo_Yes			= 1,
	FlowSshC_SendExtInfo_No				= 2,
};

enum FlowSshC_Elevation {
	FlowSshC_Elevation_Default			= 0,
	FlowSshC_Elevation_Yes				= 1,
	FlowSshC_Elevation_No				= 2,
};

enum FlowSshC_NoFlowControl {
	FlowSshC_NoFlowControl_Unsupported	= 0,
	FlowSshC_NoFlowControl_Supported	= 1,
	FlowSshC_NoFlowControl_Preferred	= 2,
};

enum FlowSshC_GlobalRequests {
	FlowSshC_GlobalRequests_AutoDetect	= 0,
	FlowSshC_GlobalRequests_Supported	= 1,
	FlowSshC_GlobalRequests_Unsupported	= 2,
};

typedef struct _FlowSshC_Options2
{
	unsigned int m_elevation;		// FlowSshC_Elevation
	unsigned int m_sendExtInfo;		// FlowSshC_SendExtInfo
	unsigned int m_noFlowControl;	// FlowSshC_NoFlowControl
	unsigned int m_globalRequests;	// FlowSshC_GlobalRequests
} FlowSshC_Options2;

inline void FlowSshC_Options2_Initialize(FlowSshC_Options2* options2)
{
	options2->m_elevation      = FlowSshC_Elevation_Default;
	options2->m_sendExtInfo    = FlowSshC_SendExtInfo_Default;
	options2->m_noFlowControl  = FlowSshC_NoFlowControl_Unsupported;
	options2->m_globalRequests = FlowSshC_GlobalRequests_AutoDetect;
}


enum FlowSshC_SocketProvider {
	FlowSshC_SocketProvider_Any		= 0,
	FlowSshC_SocketProvider_Trusted	= 1
};


enum FlowSshC_IPVersion {
	FlowSshC_IP4 = 0,
	FlowSshC_IP6 = 1
};


enum FlowSshC_SessionIdReplyCode {
	// Note:
	// - The following are descriptions for each code:
	//   0 - The server accepted our client-session-id request without disclosing further information.
	//   1 - The server accepted our client-session-id request without taking further actions.
	//   2 - The server disconnected one or more other connections logged into the same account with a matching client session ID.
	//   3 - The server has begun disconnecting one or more other sessions logged into the same account with a matching client session ID.
	FlowSshC_SessionIdReplyCode_Undisclosed				= 0,
	FlowSshC_SessionIdReplyCode_SessionUnique			= 1,
	FlowSshC_SessionIdReplyCode_ConnectionsTerminated	= 2,
	FlowSshC_SessionIdReplyCode_TimeoutExpired			= 3,
};


enum FlowSshC_ServerNoticeSeverity {
	FlowSshC_ServerNoticeSeverity_Error   = 0,
	FlowSshC_ServerNoticeSeverity_Warning = 1,
	FlowSshC_ServerNoticeSeverity_Info 	  = 2,
	FlowSshC_ServerNoticeSeverity_Trace   = 3
};


enum FlowSshC_ForwardingErrCode {
	FlowSshC_ForwardingErrCode_GeneralError			= 2,
	FlowSshC_ForwardingErrCode_ClientNotConnected	= 3,
	// Notes:
	// - Listening address is already in use.
	// - Used when adding client-to-server forwarding
	//   and when enabling proxy forwarding.
	FlowSshC_ForwardingErrCode_AddressInUse			= 4,
	// Notes:
	// - SSH global request has been rejected by the server.
	// - This error can occur while adding server-to-client
	//   forwardings or inviting (server-side) forwardings.
	FlowSshC_ForwardingErrCode_RejectedByServer		= 5,
	// Note:
	// - Used only when canceling forwardings.
	FlowSshC_ForwardingErrCode_RuleNotFound			= 6,
	// Note:
	// - Used only when inviting (server-side) forwardings.
	FlowSshC_ForwardingErrCode_AlreadyInvited		= 7,
	// Note:
	// - Used only when disabling proxy forwarding.
	FlowSshC_ForwardingErrCode_AlreadyDisabled		= 8
};

typedef struct _FlowSshC_ForwardingErr
{
	// Note:
	// - Auxiliary info is optional and may be set to NULL.
	unsigned int   m_errCode; // FlowSshC_ForwardingErrCode
	wchar_t const* m_auxInfo;
	wchar_t const* m_desc;
} FlowSshC_ForwardingErr;

typedef struct _FlowSshC_ForwardingRule
{
	// Note:
	// - When forwarding from or to a Unix socket, m_listInterface (S2C) or m_destHost (C2S)
	//   must start with '/' (for example, "/var/demo.uxsocket") and the corresponding port
	//   (m_listPort or m_destPort) must be set to FLOWSSHC_PORT_UNIXSOCKET.
	FLOWSSHC_BOOL m_clientToServer;
	wchar_t const* m_listInterface;
	unsigned int   m_listPort;
	// Note about the m_dest* variables:
	// - When canceling a forwarding, destination host and port are not used.
	wchar_t const* m_destHost;
	unsigned int   m_destPort;
} FlowSshC_ForwardingRule;

typedef struct _FlowSshC_ForwardingRuleExt
{
	FlowSshC_ForwardingRule m_rule;
	// Notes:
	// - An additional entry relevant only for server-to-client rules that overrides
	//   connect-from interface set with FlowSshC_Client_SetConnectInterface.
	// - See FlowSshC_Client_SetConnectInterface for more info.
	wchar_t const* m_connectInterface;
} FlowSshC_ForwardingRuleExt;

typedef struct _FlowSshC_ProxyForwarding
{
	wchar_t const* m_listInterface;
	unsigned int   m_listPort;
	// Notes about the m_bind* variables:
	// - They are all optional and may be set to NULL.
	// - Used with SOCKSv4 and SOCKSv5 BIND request only; SOCKSv4 supports IPv4 only.
	// - Server public IP address is required when doing a BIND request. IPv4/6 BIND request
	//   fails if server's public IPv4/6 address is not available. When one or both public
	//   addresses are not set (when set to NULL), FlowSsh will try to use the SSH server
	//   address it originally connected to.
	// - The default BIND listening interfaces are 0.0.0.0 (for IPv4) and :: (for IPv6).
	// - It's OK to set an IP4 address to the IP6 entry and vice versa - that will be taken
	//   care of automatically.
	wchar_t const* m_bindPublicAddressIP4;
	wchar_t const* m_bindPublicAddressIP6;
	wchar_t const* m_bindListInterfaceIP4;
	wchar_t const* m_bindListInterfaceIP6;
} FlowSshC_ProxyForwarding;

enum FlowSshC_ForwardingEvent
{
	// Note:
	// - All types of client-to-server forwarding events.
	FlowSshC_ForwardingEvent_C2SOpenSent			= 1,	// FlowSshC_ForwardingLog_C2S
	FlowSshC_ForwardingEvent_C2SOpenFailed			= 2,	// FlowSshC_ForwardingLog_C2SOpenFailed
	FlowSshC_ForwardingEvent_C2SOpened				= 3,	// FlowSshC_ForwardingLog_C2S
	FlowSshC_ForwardingEvent_C2SClosed				= 4,	// FlowSshC_ForwardingLog_C2SClosed

	// Note:
	// - All types of server-to-client forwarding events.
	FlowSshC_ForwardingEvent_S2COpenIgnored			= 11,	// FlowSshC_ForwardingLog_S2C
	FlowSshC_ForwardingEvent_S2COpenReceived		= 12,	// FlowSshC_ForwardingLog_S2C
	FlowSshC_ForwardingEvent_S2COpenFailed			= 13,	// FlowSshC_ForwardingLog_S2COpenFaile
	FlowSshC_ForwardingEvent_S2COpened				= 14,	// FlowSshC_ForwardingLog_S2C
	FlowSshC_ForwardingEvent_S2CClosed				= 15,	// FlowSshC_ForwardingLog_S2CClosed

	// Note:
	// - Server-side client-to-server management events.
	FlowSshC_ForwardingEvent_ServerSideC2SAdded		= 31,	// FlowSshC_ForwardingLog_ServerSideC2S
	FlowSshC_ForwardingEvent_ServerSideC2SAddFailed	= 32,	// FlowSshC_ForwardingLog_ServerSideC2SAddFailedC2S
	FlowSshC_ForwardingEvent_ServerSideC2SCanceled	= 33,	// FlowSshC_ForwardingLog_ServerSideC2S

	// Note:
	// - Proxy forwarding setup events
	FlowSshC_ForwardingEvent_ProxyAccepted			= 51,	// FlowSshC_ForwardingLog_Proxy
	FlowSshC_ForwardingEvent_ProxyDecodeFailed		= 52,	// FlowSshC_ForwardingLog_ProxyDecodeFailed
	FlowSshC_ForwardingEvent_ProxyConnectStarted	= 53,	// FlowSshC_ForwardingLog_ProxyStarted
	FlowSshC_ForwardingEvent_ProxyBindFailed		= 54,	// FlowSshC_ForwardingLog_ProxyBindFailed
	FlowSshC_ForwardingEvent_ProxyBindStarted		= 55,	// FlowSshC_ForwardingLog_ProxyBindStarted
	FlowSshC_ForwardingEvent_ProxyBindAborted		= 56	// FlowSshC_ForwardingLog_ProxyBindAborted
};

typedef struct _FlowSshC_ForwardingLog
{
	// Notes:
	// - Event holds one of the FlowSshC_ForwardingEvent's values.
	// - To get more information, downcast this structure according to the event value.
	//   See notes in the following structures for more information.
	unsigned int   m_event; // FlowSshC_ForwardingEvent
	wchar_t const* m_desc;
} FlowSshC_ForwardingLog;

enum FlowSshC_ForwardingType
{
	FlowSshC_ForwardingType_ProxySocks4			= 1,
	FlowSshC_ForwardingType_ProxySocks5			= 2,
	FlowSshC_ForwardingType_ProxyHttpConnect	= 3,
	FlowSshC_ForwardingType_ClientSide			= 9,
	FlowSshC_ForwardingType_ServerSide			= 10
};

typedef struct _FlowSshC_ForwardingLog_C2S
{
	// Notes:
	// - Used with all FlowSshC_ForwardingEvent_C2S* events.
	// - Type holds one of the FlowSshC_ForwardingType's values.
	// - Destination address and port are not valid for ServerSide events.
	// - SrvSideRuleDesc is meaningful only for server-side rules.
	FlowSshC_ForwardingLog m_base;
	unsigned int   m_type; // FlowSshC_ForwardingType
	wchar_t const* m_srvSideRuleDesc;
	wchar_t const* m_listInterface;
	unsigned int   m_listPort;
	wchar_t const* m_origAddress;
	unsigned int   m_origPort;
	wchar_t const* m_destAddress;
	unsigned int   m_destPort;
} FlowSshC_ForwardingLog_C2S;

typedef struct _FlowSshC_ForwardingLog_C2SOpenFailed
{
	// Notes:
	// - Used only with FlowSshC_ForwardingEvent_C2SOpenFailed event.
	// - Auxiliary info is optional and may be set to NULL.
	FlowSshC_ForwardingLog_C2S m_base;
	wchar_t const* m_auxInfo;
} FlowSshC_ForwardingLog_C2SOpenFailed;

typedef struct _FlowSshC_ForwardingLog_C2SClosed
{
	// Note:
	// - Used only with FlowSshC_ForwardingEvent_C2SClosed event.
	FlowSshC_ForwardingLog_C2S m_base;
	unsigned __int64 m_bytesSent;
	unsigned __int64 m_bytesReceived;
} FlowSshC_ForwardingLog_C2SClosed;

typedef struct _FlowSshC_ForwardingLog_S2C
{
	// Notes:
	// - Used with all FlowSshC_ForwardingEvent_S2C* events.
	// - Type holds one of the FlowSshC_ForwardingType's values.
	// - Listening interface and port are not valid for ServerSide events.
	// - SrvSideRuleDesc is meaningful only for server-side rules.
	FlowSshC_ForwardingLog m_base;
	unsigned int   m_type; // FlowSshC_ForwardingType
	wchar_t const* m_srvSideRuleDesc;
	wchar_t const* m_listInterface;
	unsigned int   m_listPort;
	wchar_t const* m_origAddress;
	unsigned int   m_origPort;
	wchar_t const* m_destAddress;
	unsigned int   m_destPort;
} FlowSshC_ForwardingLog_S2C;

typedef struct _FlowSshC_ForwardingLog_S2COpenFailed
{
	// Notes:
	// - Used only with FlowSshC_ForwardingEvent_S2COpenFailed event.
	// - Auxiliary info is optional and may be set to NULL.
	FlowSshC_ForwardingLog_S2C m_base;
	wchar_t const* m_auxInfo;
} FlowSshC_ForwardingLog_S2COpenFailed;

typedef struct _FlowSshC_ForwardingLog_S2CClosed
{
	// Note:
	// - Used only with FlowSshC_ForwardingEvent_S2CClosed event.
	FlowSshC_ForwardingLog_S2C m_base;
	unsigned __int64 m_bytesSent;
	unsigned __int64 m_bytesReceived;
} FlowSshC_ForwardingLog_S2CClosed;

typedef struct _FlowSshC_ForwardingLog_ServerSideC2S
{
	// Note:
	// - Used with all FlowSshC_ForwardingEvent_ServerSideC2S* events.
	FlowSshC_ForwardingLog m_base;
	wchar_t const* m_listInterface;
	unsigned int   m_listPort;
	wchar_t const* m_ruleDesc;
} FlowSshC_ForwardingLog_ServerSideC2S;

enum FlowSshC_ForwardingErrCode_ServerSideC2SAddFailed
{
	FlowSshC_ForwardingErrCode_ServerSideC2SAddFailed_GeneralError	= 2,
	FlowSshC_ForwardingErrCode_ServerSideC2SAddFailed_AddressInUse	= 4,
	FlowSshC_ForwardingErrCode_ServerSideC2SAddFailed_NoInvitation	= 100
};

typedef struct _FlowSshC_ForwardingLog_ServerSideC2SAddFailed
{
	// Notes:
	// - Used only with FlowSshC_ForwardingEvent_ServerSideC2SAddFailed event.
	// - Error code holds one of the FlowSshC_ForwardingErrCode_ServerSideC2SAddFailed's values.
	// - Auxiliary info is optional and may be set to NULL.
	FlowSshC_ForwardingLog_ServerSideC2S m_base;
	unsigned int   m_errCode; // FlowSshC_ForwardingErrCode_ServerSideC2SAddFailed
	wchar_t const* m_auxInfo;
} FlowSshC_ForwardingLog_ServerSideC2SAddFailed;

typedef struct _FlowSshC_ForwardingLog_Proxy
{
	// Notes:
	// - Used with all FlowSshC_ForwardingEvent_Proxy* events.
	FlowSshC_ForwardingLog m_base;
	wchar_t const* m_proxyListInterface;
	unsigned int   m_proxyListPort;
	wchar_t const* m_proxyOrigAddress;
	unsigned int   m_proxyOrigPort;
} FlowSshC_ForwardingLog_Proxy;

enum FlowSshC_ForwardingErrCode_ProxyDecodeFailed
{
	FlowSshC_ForwardingErrCode_ProxyDecodeFailed_ConnectionEof		= 0,
	FlowSshC_ForwardingErrCode_ProxyDecodeFailed_ConnectionError	= 1,
	FlowSshC_ForwardingErrCode_ProxyDecodeFailed_DecodeError		= 2
};

typedef struct _FlowSshC_ForwardingLog_ProxyDecodeFailed
{
	// Notes:
	// - Used only with FlowSshC_ForwardingEvent_ProxyDecodeFailed event.
	// - Error code holds one of the FlowSshC_ForwardingErrCode_ProxyDecodeFailed's values.
	// - Auxiliary info is optional and may be set to NULL.
	FlowSshC_ForwardingLog_Proxy m_base;
	unsigned int   m_errCode; // FlowSshC_ForwardingErrCode_ProxyDecodeFailed
	wchar_t const* m_auxInfo;
} FlowSshC_ForwardingLog_ProxyDecodeFailed;

typedef struct _FlowSshC_ForwardingLog_ProxyStarted
{
	// Notes:
	// - Used with FlowSshC_ForwardingEvent_ProxyConnectStarted and 
	//   FlowSshC_ForwardingEvent_ProxyBind* events.
	// - Proxy type holds one of the following values: FlowSshC_ForwardingType_ProxySocks4,
	//   FlowSshC_ForwardingType_ProxySocks5, and FlowSshC_ForwardingType_ProxyHttpConnect.
	FlowSshC_ForwardingLog_Proxy m_base;
	unsigned int   m_proxyType;
	wchar_t const* m_proxyReqAddress;
	unsigned int   m_proxyReqPort;
} FlowSshC_ForwardingLog_ProxyStarted;

enum FlowSshC_ForwardingErrCode_ProxyBindFailed
{
	FlowSshC_ForwardingErrCode_ProxyBindFailed_NoServerAddress		= 0,
	FlowSshC_ForwardingErrCode_ProxyBindFailed_NoIp4ServerAddress	= 1,
	FlowSshC_ForwardingErrCode_ProxyBindFailed_AddressResolveError	= 2,
	FlowSshC_ForwardingErrCode_ProxyBindFailed_NoIp4AddressResolved	= 3,
	FlowSshC_ForwardingErrCode_ProxyBindFailed_NoIpAddressTypeMatch	= 4,
	FlowSshC_ForwardingErrCode_ProxyBindFailed_ProxyS2CAddFailed	= 5
};

typedef struct _FlowSshC_ForwardingLog_ProxyBindFailed
{
	// Notes:
	// - Used only with FlowSshC_ForwardingEvent_ProxyBindFailed event.
	// - Error code holds one of the FlowSshC_ForwardingErrCode_ProxyBindFailed's values.
	// - Auxiliary info is optional and may be set to NULL.
	FlowSshC_ForwardingLog_ProxyStarted m_base;
	unsigned int   m_errCode; // FlowSshC_ForwardingErrCode_ProxyBindFailed
	wchar_t const* m_auxInfo;
} FlowSshC_ForwardingLog_ProxyBindFailed;

typedef struct _FlowSshC_ForwardingLog_ProxyBindStarted
{
	// Note:
	// - Used with FlowSshC_ForwardingEvent_ProxyBindStarted and
	//   FlowSshC_ForwardingAbrtCode_ProxyBindAborted events.
	FlowSshC_ForwardingLog_ProxyStarted m_base;
	wchar_t const* m_bindPublicAddress;
	unsigned int   m_bindPublicPort;
	wchar_t const* m_bindListInterface;
	unsigned int   m_bindListPort;
} FlowSshC_ForwardingLog_ProxyBindStarted;

enum FlowSshC_ForwardingAbrtCode_ProxyBindAborted
{
	FlowSshC_ForwardingAbrtCode_ProxyBindAborted_ConnectionEof		= 0,
	FlowSshC_ForwardingAbrtCode_ProxyBindAborted_ConnectionError	= 1,
	FlowSshC_ForwardingAbrtCode_ProxyBindAborted_AcceptTimeout		= 2
};

typedef struct _FlowSshC_ForwardingLog_ProxyBindAborted
{
	// Notes:
	// - Used only with FlowSshC_ForwardingEvent_ProxyBindAborted event.
	// - Abort code holds one of the FlowSshC_ForwardingAbrtCode_ProxyBindAborted's values.
	// - Auxiliary info is optional and may be set to NULL.
	FlowSshC_ForwardingLog_ProxyBindStarted m_base;
	unsigned int   m_abrtCode; // FlowSshC_ForwardingAbrtCode_ProxyBindAborted
	wchar_t const* m_auxInfo;
} FlowSshC_ForwardingLog_ProxyBindAborted;


// Note:
// - SSH version string received from the remote is passed through this handler.
typedef void (__cdecl* FlowSshC_SshVersionHandler)(void* handlerData, wchar_t const* version);
// Note:
// - Return false to reject host key and disconnect.
typedef FLOWSSHC_BOOL (__cdecl* FlowSshC_HostKeyHandler)(void* handlerData, FlowSshC_PublicKey* publicKey);
// Note:
// - Called each time a key exchange is completed. May be called multiple times per session.
// - Reports negotiated encryption, MAC and compression algorithms. These are unlikely to change,
//   but may change in successive key exchanges.
typedef void (__cdecl* FlowSshC_KexDoneHandler)(void* handlerData, unsigned __int64 kexNr, FLOWSSHC_BOOL incoming, wchar_t const* kexAlg, wchar_t const* encAlg, wchar_t const* macAlg, wchar_t const* cmprAlg);
// Notes:
// - FurtherAuth and PasswordChange are always exclusive - one will be NULL.
// - When doing FurtherAuth: return false to stop user authentication and disconnect.
// - When doing PasswordChange: return false to abort password change and continue with
//   user authentication (most likely raising FurtherAuth in the process).
typedef FLOWSSHC_BOOL (__cdecl* FlowSshC_UserAuthHandler)(void* handlerData, FlowSshC_FurtherAuth* furtherAuth, FlowSshC_PasswordChange* passwordChange);
typedef void (__cdecl* FlowSshC_BannerHandler)(void* handlerData, wchar_t const* banner);
// Note:
// - See FlowSshC_SessionIdReplyCode for possible code values.
typedef void (__cdecl *FlowSshC_SessionIdReplyHandler)(void* handlerData, unsigned int code);
// Notes:
// - Bitvise SSH Server can send this message to inform a client about channels it refused to open.
//   Future versions may support additional notices.
// - See FlowSshC_ServerNoticeSeverity for possible severity values.
// - Possible facility values: "s2cForwarding", "sshAgentForwarding", ..
// - Possible status   values: "channelLimitReached", "noFlowControlExtensionInEffect", ..
typedef void(__cdecl* FlowSshC_ServerNoticeHandler)(void* handlerData, unsigned int severity, wchar_t const* facility, wchar_t const* status, wchar_t const* description);
// Notes:
// - Host key synchronization is performed after user authentication. A server supporting
//   this functionality will first send the list of available host keys; the handler will
//   be called for each key, at first with unverified ownership. For keys where the handler
//   returns true, FlowSsh will ask the server to provide a proof of ownership (a signature).
//   Subsequently, the handler will be called again for each key with verified ownership.
// - When the handler is called for keys with verified ownership, the return value has no effect.
// - Keys that use host key algorithms disabled by the application are automatically ignored.
// - Any new key received during key exchange and verified using FlowSshC_HostKeyHandler is ignored.
// - A server may not be able to provide proof of ownership for each key. A possible reason is that
//   the server may use a signature algorithm that's not enabled by the application or supported by FlowSsh.
// - This handler may also be called during key re-exchange if a new host key is received at that time.
//   In this case, there will be only one call where the key will already have its ownership verified.
typedef bool (__cdecl* FlowSshC_HostKeySyncHandler)(void* handlerData, FlowSshC_PublicKey* publicKey, bool keyVerified);
// Notes:
// - Error pointer is NULL on success. 
// - Listening port is meaningful only when the forwarding has successfully been added,
//   and when the original forwarding rule had listening port set to 0 (use any port).
typedef void (__cdecl* FlowSshC_ForwardingHandler)(void* handlerData, unsigned int listPort, FlowSshC_ForwardingErr const* error);
// Note:
// - The log parameter can be downcast according to the value of log->m_event.
typedef void (__cdecl* FlowSshC_ForwardingLogHandler)(void* handlerData, FlowSshC_ForwardingLog const* log);
// Notes:
// - Disconnect handler can be called only on successfully connected clients.
// - Except for disconnect progress handler (when disconnect is pending), no 
//   client's handlers can be called after this handler.
typedef void (__cdecl* FlowSshC_DisconnectHandler)(void* handlerData, unsigned int reason, wchar_t const* desc);


FLOWSSHC_OPAQUE(FlowSshC_Client);
FLOWSSHC_FUNC FlowSshC_Client*					__cdecl FlowSshC_Client_Create();
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_AddRef(FlowSshC_Client* client);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_Release(FlowSshC_Client* client);
// Notes for all FlowSshC_Client_Set*Handler functions:
// - All handlers can be set NULL, in fact, handlers are NULL by default.
// - Host key handler must not be NULL, otherwise host key verification will always fail.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetVersionHandler(FlowSshC_Client* client, FlowSshC_SshVersionHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetHostKeyHandler(FlowSshC_Client* client, FlowSshC_HostKeyHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetKexDoneHandler(FlowSshC_Client* client, FlowSshC_KexDoneHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetUserAuthHandler(FlowSshC_Client* client, FlowSshC_UserAuthHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetBannerHandler(FlowSshC_Client* client, FlowSshC_BannerHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetSessionIdReplyHandler(FlowSshC_Client* client, FlowSshC_SessionIdReplyHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetServerNoticeHandler(FlowSshC_Client* client, FlowSshC_ServerNoticeHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetHostKeySyncHandler(FlowSshC_Client* client, FlowSshC_HostKeySyncHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetForwardingLogHandler(FlowSshC_Client* client, FlowSshC_ForwardingLogHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetDisconnectHandler(FlowSshC_Client* client, FlowSshC_DisconnectHandler handler, void* handlerData);
// Notes:
// - Application name (and version) must be set before attempting to connect the client.
// - Client version string: "SSH-2.0-" + <FlowSshVersion> + " FlowSsh: " + <AppNameAndVersion>.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetAppName(FlowSshC_Client* client, wchar_t const* appNameAndVersion);
// Notes:
// - If the file already exists, it will be appended to.
// - Use event mask 0xF0000 (decimal 983040) for the most common events desired (FlowSshDebug::{VersionIn, VersionOut, PacketIn, PacketOut}).
// - Event mask 0 will result in no debug output.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetDebugFile(FlowSshC_Client* client, wchar_t const* debugFile, unsigned int debugEventMask);
// Notes for all FlowSshC_Client_SetProxy_* functions:
// - Use of proxy server is disabled by default (ProxyType = FlowSshC_ProxyType::None).
// - Default proxy host is empty string while proxy port is set to 1080 by default. 
// - Resolve (DNS name) locally is enabled by default (ProxyOptions: resolveLocally = true).
// - SOCKSv4 supports DNS names starting with SOCKSv4a extension. Therefore, if your SOCKSv4 
//   proxy does not support SOCKSv4a extension, resolve (DNS name) locally must be enabled.
// - SOCKSv4 (including SOCKSv4a) does not support authentication.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetProxyType(FlowSshC_Client* client, unsigned int type);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetProxyHost(FlowSshC_Client* client, wchar_t const* host);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetProxyPort(FlowSshC_Client* client, unsigned int port);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetProxyUserName(FlowSshC_Client* client, wchar_t const* userName);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetProxyPassword(FlowSshC_Client* client, wchar_t const* password);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetProxyOptions(FlowSshC_Client* client, FLOWSSHC_BOOL resolveLocally);
// Notes for the remaning FlowSshC_Client_Set* functions.
// - Host and user name are empty strings by default, while default port value is 22.
// - Obfuscation keyword is optional - may be NULL, and it's irrelevant when obfuscation is disabled.
// - Password and keypair are NULL by default - are not set by default.
// - Authentication procedure:
//    - If neither password and keypair are set, 'none' authentication method will be attempted.
//    - If both password and keypair are set, 'publickey' authentication will be performed first.
//    - If password is set and 'password' authentication method either fails or is not available,
//      then password through 'keyboard-interactive' will be attempted. Conditions for a successful
//      password through 'keyboard-interactive' authentication are the following:
//       - Kbdi info request must contain exactly one prompt.
//       - One of the kbdi info request strings must contain a case-insensitive "password" substring.
//    - If further authentication is required, user auth handler will be called. If such handler is not 
//      set or if the handler returns false, client will disconnect with user authentication failure.
//    - If password change is requested during 'password' authentication, user auth handler will be
//      called. If such handler is not set, if it returns false, or if the server rejects new password,
//      the original 'password' authentication attempt will fail.
// - Client session ID is an optional client-generated string that helps a server which supports it to
//   identify a reconnecting session. Set to null or an empty string to disable any previously set ID.
//   The millisecond timeout parameter instructs the server on how long the server should wait for any
//   matching sessions to fully terminate.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetHost(FlowSshC_Client* client, wchar_t const* host);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetPort(FlowSshC_Client* client, unsigned int port);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetObfuscation(FlowSshC_Client* client, FLOWSSHC_BOOL enable, wchar_t const* keyword);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetUserName(FlowSshC_Client* client, wchar_t const* userName);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetPassword(FlowSshC_Client* client, wchar_t const* password);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetKeypair(FlowSshC_Client* client, FlowSshC_Keypair* keypair);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetSessionId(FlowSshC_Client* client, wchar_t const* clientSessionId, unsigned int timeoutMs);
// Notes for all FlowSshC_Client_Set*Algs functions:
// - By default:
//    - all key exchange algorithms are enabled and ordered by their declaration order,
//    - both host key algorithms are enabled and ordered by their declaration order,
//    - all encryption algorithms except none are enabled and ordered by their declaration order,
//    - all MAC algorithms except none are enabled and ordered by their declaration order,
//    - zlib compression is disabled while none is enabled.
// - Compression will be used only if both the client and server have it enabled.
// - Compression may deteriorate transfer rate on connections with high throughput. 
// - Changing algorithms have no effect on active clients past the initial key exchange.
// - Passing a null algorithm pointer will load default values.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetKeyExchangeAlgs(FlowSshC_Client* client, FlowSshC_KeyExchangeAlgs const* algs);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetHostKeyAlgs(FlowSshC_Client* client, FlowSshC_HostKeyAlgs const* algs);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetEncryptionAlgs(FlowSshC_Client* client, FlowSshC_EncryptionAlgs const* algs);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetMacAlgs(FlowSshC_Client* client, FlowSshC_MacAlgs const* algs);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetCompressionAlgs(FlowSshC_Client* client, FlowSshC_CompressionAlgs const* algs);
// Notes:
// - Both start key re-exchange and keep-alive are set/enabled by default.
// - If start key re-echange is set, the client will initiate key re-exchange after every
//   1 hour of connection time, or after every 1 GB of exchanged data. If disabled, the client 
//   will still correctly respond to key re-exchange requests started by the server.
// - If keep-alive is enabled, the client will periodically generate network traffic when idle.
// - The relaxed recv-based keep-alive timeout is used only during initial key exchange and user
//   authentication.
// - Set any of the keep-alive values to:
//     0 to disable it;
//     -1 to use the default value built into FlowSsh;
//     or provide your own value in milliseconds.
// - Changing options has no efect on active clients past the initial key exchange.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetOptions(FlowSshC_Client* client, FlowSshC_Options const* opts);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetOptions2(FlowSshC_Client* client, FlowSshC_Options2 const* opts2);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetRequireStrictKex(FlowSshC_Client* client, bool value);
// Notes:
// - When set to use trusted socket providers, FlowSshC will use only a narrow selection of
//   trusted LSP providers, promoting stability, but at a possible expense of connectivity.
// - When set to use any socket provider, FlowSshC will use whatever LSPs are installed, 
//   promoting connectivity, but at a possible expense of stability.
// - By default, FlowSshC is set to use trusted socket providers (FlowSshC_SocketProvider_Trusted).
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetSocketProvider(FlowSshC_Client* client, unsigned int socketProvider);
// Note:
// - A value from FlowSshC_IPVersion.
// - By default, FlowSshC will prefer IPv4 (FlowSshC_IP4).
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetPreferredIPVersion(FlowSshC_Client* client, unsigned int version);
// Notes:
// - An optional interface list from which this FlowSshC client will make its TCP/IP connection.
// - The interface list is a comma-separated list that may contain one IPv4 and/or one IPv6
//   interface. Additional or invalid entries will be ignored. 
// - When both IPv4 and IPv6 interfaces are specified, whichever appears first will be the preferred
//   IP version. If a single IPv4 or IPv6 interface is specified, then the client will be limited
//   to the specified IP version when making outgoing TCP/IP connections.
// - Pass NULL or empty interface list to remove any specific interfaces set previously.
// - By default, a specific interface list is not set. In this case, the client will connect from
//   a suitable interface selected by the OS.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_SetConnectInterface(FlowSshC_Client* client, wchar_t const* interfaceList);
// Notes:
// - Connect will fail (through the progress handler) when called on an active client.
// - Connect will fail (through the progress handler) if application name (and version) is not set.
// - If client gets disconnected while connecting, the disconnect handler will not be
//   called. Instead, failure will be relayed through the connect's progress handler.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_Connect(FlowSshC_Client* client, FlowSshC_ProgressHandler handler, void* handlerData);
// Notes:
// - Disconnect will fail (through progress handler) if client is already disconnecting.
// - Disconnecting an already disconnected client will yield success.
// - If client is connecting, then issuing disconnect will abort the connection.
// - No client's handlers can be called past the successfully completed disconnect.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_Disconnect(FlowSshC_Client* client, FlowSshC_ProgressHandler handler, void* handlerData);
// Notes for all FlowSshC_Client_*Forwarding* functions:
// - Forwarding instructions will fail immediately if the client is not connected or connecting,
//   and if the client is connecting they will be delayed until connect operation is completed.
// - The invite forwardings instruction will enable server-side forwardings, that's server-configured
//   forwardings, which are available only on Bitvise SSH Server (WinSSHD).
// - There can only be one proxy forwarding enabled at the time. Enabling proxy forwarding automatically
//   disables any previously set up proxy forwarding.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_AddForwarding(FlowSshC_Client* client, FlowSshC_ForwardingRule const* rule, FlowSshC_ForwardingHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_AddForwardingExt(FlowSshC_Client* client, FlowSshC_ForwardingRuleExt const* rule, FlowSshC_ForwardingHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_CancelForwarding(FlowSshC_Client* client, FlowSshC_ForwardingRule const* rule, FlowSshC_ForwardingHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_InviteForwardings(FlowSshC_Client* client, FLOWSSHC_BOOL clientToServer, FlowSshC_ForwardingHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_EnableProxyForwarding(FlowSshC_Client* client, FlowSshC_ProxyForwarding const* settings, FlowSshC_ForwardingHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_Client_DisableProxyForwarding(FlowSshC_Client* client, FlowSshC_ForwardingHandler handler, void* handlerData);



typedef struct _FlowSshC_ExitStatus
{
	unsigned int m_code;
} FlowSshC_ExitStatus;

typedef struct _FlowSshC_ExitSignal
{
	wchar_t const* m_name; 
	FLOWSSHC_BOOL m_coreDumped;
	wchar_t const* m_errMsg;
} FlowSshC_ExitSignal;


// Notes:
// - Close handler can be called only on successfully opened channels.
// - No channel's handlers can be called after this handler.
typedef void (__cdecl* FlowSshC_ChannelCloseHandler)(void* handlerData);
// Note:
// - ExitStatus and ExitSignal are always exclusive - one will be NULL.
typedef void (__cdecl* FlowSshC_ExitHandler)(void* handlerData, FlowSshC_ExitStatus const* status, FlowSshC_ExitSignal const* signal);
// Note:
// - Receive handler with all parameter set to zero (stdErr=false, data=NULL, dataBytes=0, eof=false)
//   is called when the associated channel is or gets closed.
typedef void (__cdecl* FlowSshC_ReceiveHandler)(void* handlerData, FLOWSSHC_BOOL stdErr, unsigned char const* data, unsigned int dataBytes, FLOWSSHC_BOOL eof);
	
 
FLOWSSHC_OPAQUE(FlowSshC_ClientSessionChannel);
// Notes:
// - Returns NULL on fatal error only (after fatal error handler is called).
// - Channel can be created even if the associated client is not yet connected.
// - Channel keeps the associated client alive throughout channel's lifetime.
// - Channel is closed immediately if FlowSshC_ClientSessionChannel_Close is called.
//   Otherwise, if channel is closed by the server or due to client disconnection,
//   then channel will linger (channel close handler will be delayed) until all data 
//   (and/or EOF) received is retrieved through FlowSshC_ClientSessionChannel_Receive.
//   Sending data, EOF, or requests at this point will fail with the following message:
//   "Session channel is closing."
FLOWSSHC_FUNC FlowSshC_ClientSessionChannel*	__cdecl FlowSshC_ClientSessionChannel_Create(FlowSshC_Client* client);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_AddRef(FlowSshC_ClientSessionChannel* channel);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_Release(FlowSshC_ClientSessionChannel* channel);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_SetExitHandler(FlowSshC_ClientSessionChannel* channel, FlowSshC_ExitHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_SetCloseHandler(FlowSshC_ClientSessionChannel* channel, FlowSshC_ChannelCloseHandler handler, void* handlerData);
// Notes:
// - Client must be connected before sending open request, otherwise the request will
//   fail immediately through the supplied progress handler.
// - A closed channel can be re-opened at any time.
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_OpenRequest(FlowSshC_ClientSessionChannel* channel, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_PtyRequest(FlowSshC_ClientSessionChannel* channel, wchar_t const* term, unsigned int widthCols, unsigned int heightRows, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_ExecRequest(FlowSshC_ClientSessionChannel* channel, wchar_t const* command, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_ShellRequest(FlowSshC_ClientSessionChannel* channel, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_Receive(FlowSshC_ClientSessionChannel* channel, unsigned int maxBytes, FlowSshC_ReceiveHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_Send(FlowSshC_ClientSessionChannel* channel, unsigned char const* data, unsigned int dataBytes, FLOWSSHC_BOOL eof, FlowSshC_ProgressHandler handler, void* handlerData);
// Notes:
// - SSH defines the following signals names: ABRT, ALRM, FPE, HUP, ILL, INT, KILL,
//   PIPE, QUIT, SEGV, TERM, USR1, USR2. These are POSIX signals without the SIG prefix.
// - There are two ways to send the Ctrl+C signal: either by sending 0x03 data byte or
//   by issuing the INT signal.
// - Bitvise SSH Server (WinSSHD) will accept INT and a custom BREAK@bitvise.com
//   (Ctrl+Break) signal.
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_Signal(FlowSshC_ClientSessionChannel* channel, wchar_t const* signalName, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSessionChannel_Close(FlowSshC_ClientSessionChannel* channel, FlowSshC_ProgressHandler handler, void* handlerData);



enum FlowSshC_FileType {
	FlowSshC_FileType_Regular		= 1,
    FlowSshC_FileType_Directory		= 2,
    FlowSshC_FileType_Symlink		= 3,
    FlowSshC_FileType_Special		= 4,
    FlowSshC_FileType_Unknown		= 5,
	// SFTPv6+
    FlowSshC_FileType_Socket		= 6,
    FlowSshC_FileType_CharDevice	= 7,
    FlowSshC_FileType_BlockDevice	= 8,
    FlowSshC_FileType_Fifo			= 9
};

enum FlowSshC_AttrFlags {
	FlowSshC_AttrFlags_Size			= 0x00000001,
	FlowSshC_AttrFlags_UidGid		= 0x00000002, // SFTPv3-
	FlowSshC_AttrFlags_Permissions	= 0x00000004,
	// SFTPv4+
	FlowSshC_AttrFlags_AccessTime	= 0x00000008, // Available in SFTPv3- together with ModifyTime
	FlowSshC_AttrFlags_CreateTime	= 0x00000010, 
	FlowSshC_AttrFlags_ModifyTime	= 0x00000020, // Available in SFTPv3- together with AccessTime
	FlowSshC_AttrFlags_OwnerGroup	= 0x00000080,	
	FlowSshC_AttrFlags_Subseconds	= 0x00000100,
	// SFTPv6+
	FlowSshC_AttrFlags_AllocSize	= 0x00000400, 
	FlowSshC_AttrFlags_TextHint		= 0x00000800
};

enum FlowSshC_TextHint {
	FlowSshC_TextHint_KnownText		= 0,
	FlowSshC_TextHint_GuessedText	= 1,
    FlowSshC_TextHint_KnownBinary	= 2,
    FlowSshC_TextHint_GuessedBinary	= 3
};

typedef struct _FlowSshC_FileAttrs
{
	unsigned int m_validAttrFlags;					// FlowSshC_AttrFlags mask of file attributes available
	unsigned char m_type;							// Always present
	unsigned __int64 m_size;						// FlowSshC_AttrFlags::Size
	unsigned int m_uid; unsigned int m_gid;			// FlowSshC_AttrFlags::UidGid
	unsigned int m_permissions;						// FlowSshC_AttrFlags::Permissions
	unsigned __int64 m_accessTime;					// FlowSshC_AttrFlags::AccessTime
	unsigned int m_accessTimeNs;					// FlowSshC_AttrFlags::AccessTime && FlowSshC_AttrFlags::Subseconds
	unsigned __int64 m_createTime;					// FlowSshC_AttrFlags::CreateTime
	unsigned int m_createTimeNs;					// FlowSshC_AttrFlags::CreateTime && FlowSshC_AttrFlags::Subseconds
	unsigned __int64 m_modifyTime;					// FlowSshC_AttrFlags::ModifyTime
	unsigned int m_modifyTimeNs;					// FlowSshC_AttrFlags::ModifyTime && FlowSshC_AttrFlags::Subseconds
	wchar_t const* m_owner; wchar_t const* m_group;	// FlowSshC_AttrFlags::OwnerGroup
	unsigned __int64 m_allocSize;					// FlowSshC_AttrFlags::AllocSize
	unsigned char m_textHint;						// FlowSshC_AttrFlags::TextHint
} FlowSshC_FileAttrs;

typedef struct _FlowSshC_FileInfo
{
	wchar_t const* m_name;
	FlowSshC_FileAttrs m_attrs;
} FlowSshC_FileInfo;

enum FlowSshC_SftpErrCode {
	FlowSshC_SftpErrCode_Eof						= 1,
	FlowSshC_SftpErrCode_NoSuchFile					= 2,
	FlowSshC_SftpErrCode_PermissionDenied			= 3,
	FlowSshC_SftpErrCode_Failure					= 4,
	FlowSshC_SftpErrCode_BadMessage					= 5,
	FlowSshC_SftpErrCode_NoConnection				= 6,
	FlowSshC_SftpErrCode_ConnectionLost				= 7,
	FlowSshC_SftpErrCode_OpUnsupported				= 8,
	// SFTP4+
	FlowSshC_SftpErrCode_InvalidHandle				= 9,
	FlowSshC_SftpErrCode_NoSuchPath					= 10,
	FlowSshC_SftpErrCode_FileAlreadyExists			= 11,
	FlowSshC_SftpErrCode_WriteProtect				= 12,
	FlowSshC_SftpErrCode_NoMedia					= 13,
	// SFTP5+
	FlowSshC_SftpErrCode_NoSpaceOnFilesystem		= 14,
	FlowSshC_SftpErrCode_QuotaExceeded				= 15,
	FlowSshC_SftpErrCode_UnknownPrincipal			= 16,
	FlowSshC_SftpErrCode_LockConflict				= 17,
	// SFTP6+
	FlowSshC_SftpErrCode_DirNotEmpty				= 18,
	FlowSshC_SftpErrCode_NotADirectory				= 19,
	FlowSshC_SftpErrCode_InvalidFilename			= 20,
	FlowSshC_SftpErrCode_LinkLoop					= 21,
	FlowSshC_SftpErrCode_CannotDelete				= 22,
	FlowSshC_SftpErrCode_InvalidParameter			= 23,
	FlowSshC_SftpErrCode_FileIsADirectory			= 24,
	FlowSshC_SftpErrCode_ByteRangeLockConflict		= 25,
	FlowSshC_SftpErrCode_ByteRangeLockRefused		= 26,
	FlowSshC_SftpErrCode_DeletePending				= 27,
	FlowSshC_SftpErrCode_FileCorrupt				= 28,
	FlowSshC_SftpErrCode_OwnerInvalid				= 29,
	FlowSshC_SftpErrCode_GroupInvalid				= 30,
	FlowSshC_SftpErrCode_NoMatchingByteRangeLock	= 31
};

typedef struct _FlowSshC_SftpErr
{
	unsigned int m_errCode;
	wchar_t const* m_errMsg;
} FlowSshC_SftpErr;

enum FlowSshC_ListOp {
	// Codeless errors
	FlowSshC_ListOp_Exception		= 0,
	// SFTP errors - FlowSshC_SftpErrCode
	FlowSshC_ListOp_ListDir			= 100,
	FlowSshC_ListOp_ChannelNotOpen	= 150	// If channel is closed, closing, or opening.
};

typedef struct _FlowSshC_ListErr
{
	unsigned int m_listOp;
	unsigned int m_errCode; 
	wchar_t const* m_errMsg;
} FlowSshC_ListErr;

enum FlowSshC_TransferOp {
	// Codeless errors
	FlowSshC_TransferOp_Exception				  = 0,
	// SFTP errors - FlowSshC_SftpErrCode
	FlowSshC_TransferOp_MakeRemoteDir			  = 100,		// Obsolete
	FlowSshC_TransferOp_OpenRemoteFile			  = 101,
	FlowSshC_TransferOp_ReadRemoteFile			  = 102,
	FlowSshC_TransferOp_WriteRemoteFile			  = 103,
	FlowSshC_TransferOp_ReOpenRemoteFile		  = 104,
	FlowSshC_TransferOp_SetFileSizeRemoteFile	  = 105,
	FlowSshC_TransferOp_ChannelNotOpen			  = 150,		// If channel is closed, closing, or opening.
	// WinAPI errors - see MSDN
	FlowSshC_TransferOp_MakeLocalDir			  = 200,		// Obsolete
	FlowSshC_TransferOp_OpenLocalFile			  = 201,
	FlowSshC_TransferOp_ReadLocalFile			  = 202,
	FlowSshC_TransferOp_WriteLocalFile			  = 203,
	FlowSshC_TransferOp_ReOpenLocalFile			  = 204,
	FlowSshC_TransferOp_SetFileSizeLocalFile	  = 205,		// Not currently used - a generic file operation exception is thrown
	// Resume errors - FlowSshC_ResumeErrCode
	FlowSshC_TransferOp_ResumeLocalFile			  = 300,
	FlowSshC_TransferOp_ResumeRemoteFile		  = 301
}; 

enum FlowSshC_ResumeErrCode {
	FlowSshC_ResumeErrCode_TextMode			= 1,		// Files opened in text mode cannot be resumed.
	FlowSshC_ResumeErrCode_FileSize			= 2,		// Target file is already larger than source file.
	FlowSshC_ResumeErrCode_Conversion		= 3,		// Text files for which conversion is required cannot be resumed.
	FlowSshC_ResumeErrCode_Content			= 4,		// Target and source files differ.
	FlowSshC_ResumeErrCode_FileSizeError	= 5			// Unable to retrieve file size.
};

typedef struct _FlowSshC_TransferErr
{
	unsigned int m_transferOp;
	unsigned int m_errCode; 
	wchar_t const* m_errMsg;
} FlowSshC_TransferErr;
	
typedef struct _FlowSshC_TransferStat
{
	unsigned __int64 m_bytesTransferred;
	unsigned __int64 m_timeElapsedMs;
	unsigned __int64 m_currentFileSize;
	unsigned __int64 m_finalFileSize; // May change during transfer due to text conversion.
	// Note:
	// - Final file size will be invalid if source file size cannot be retrieved.
	//   Furthermore, final size will go invalid if transfer reaches final size 
	//   without also reaching EOF. When final size is invalid, it will hold the
	//   same value as current file size. A successfully completed file transfer
	//   will always hold a valid final size that will be equal to current file
	//   size; however, that is not necessarily true the other way around.
	FLOWSSHC_BOOL m_finalFileSizeValid;
} FlowSshC_TransferStat;


// Note for all FlowSshC_Client* handlers:
// - Error pointer is NULL on success. On error, handler's variables other than
//   error pointer must not be accessed (they may be NULL or uninitialized).
typedef void (__cdecl* FlowSshC_SftpVersionHandler)(void* handlerData, unsigned int version);
typedef void (__cdecl* FlowSshC_RealPathHandler)(void* handlerData, wchar_t const* realPath, FlowSshC_SftpErr const* error);
typedef void (__cdecl* FlowSshC_StatHandler)(void* handlerData, FlowSshC_FileAttrs const* fileAttrs, FlowSshC_SftpErr const* error);
typedef void (__cdecl* FlowSshC_SftpHandler)(void* handlerData, FlowSshC_SftpErr const* error);
// Notes:
// - Return false to cancel the listing.
// - List handler can be called multiple times. The last call will have 
//   endOfList=true, error!=NULL, or it will return false (cancels listing).
typedef FLOWSSHC_BOOL (__cdecl* FlowSshC_ListHandler)(void* handlerData, FlowSshC_FileInfo const* fileInfos, unsigned int nrFileInfos, FLOWSSHC_BOOL endOfList, FlowSshC_ListErr const* error);
// Notes:
// - Return false to cancel the transfer.
// - Transfer handler can be called multiple times. The last call will have  
//   done=true, error!=NULL, or it will return false (cancels transfer).
typedef FLOWSSHC_BOOL (__cdecl* FlowSshC_TransferHandler)(void* handlerData, FLOWSSHC_BOOL done, FlowSshC_TransferStat const* transferStat, FlowSshC_TransferErr const* error);


enum FlowSshC_TransferFlags {
	// Note:
	// - Transfer files without any modifications in SFTP binary mode.
	FlowSshC_TransferFlags_Binary           = 0x00000000,
	// Notes:
	// - Detects text files and applies client-side newline conversions. 
	// - When a text file is detected, works same as TextLf mode.
	// - When a binary file is detected, works same as Binary mode.
	FlowSshC_TransferFlags_AutoLf           = 0x00000001,
	// Notes:
	// - Detects text files and applies server-side newline conversions.
	// - When downloading, uses the server's text hint to determine whether to use Binary or text mode.
	//   If text hint is unavailable or is holding a guessed value, the file is opened in SFTP binary
	//   mode and tested for text content same way as in AutoLf mode. If text is detected, file is
	//   re-opened in SFTP text mode. 
	// - When uploading Windows text files, this mode behaves like TextStd. When uploading other
	//   files, it behaves like Binary.
	// - Requires SFTP version 4 or higher.
	FlowSshC_TransferFlags_AutoStd          = 0x00000002, // SFTPv4+
	// Notes:
	// - No auto-detection of file type.
	// - Uses SFTP text mode to apply server-side newline conversions to all files. 
	// - Requires SFTP version 4 or higher.
	FlowSshC_TransferFlags_TextStd          = 0x00000003, // SFTPv4+
	FlowSshC_TransferFlags_Text             = 0x00000003, // SFTPv4+. Alias for TextStd
	// Note:
	// - No auto-detection of file type. Applies client-side newline conversions to all files.
	// - When downloading, converts UNIX newlines to Windows format (LF to CRLF).
	// - When uploading, converts Windows newlines to UNIX format (CRLF to LF).
	// - As far as the server can tell, the files are transferred as binary.
	FlowSshC_TransferFlags_TextLf           = 0x00000004,
	// Note for Resume and Overwrite: 
	// - When both are set resume has priority.
	FlowSshC_TransferFlags_Resume           = 0x00000010,
	FlowSshC_TransferFlags_Overwrite        = 0x00000020,
	// Note:
	// - If enabled, source file will be erased upon successfully completed transfer.
	FlowSshC_TransferFlags_Move             = 0x00000040,
	// Note:
	// - Automatically create the missing directory structure for the target file.
	FlowSshC_TransferFlags_AutoMkDir        = 0x00000080,
	// Note:
	// - Resume, but only if verifiable. This means, if the server supports synchronization.
	//   If passed, implies Resume. This flag is incompatible with FlowSshC_TransferFlags_NoSync.
	FlowSshC_TransferFlags_ResumeVerifiable = 0x00000100,
	// Note:
	// - Disable block-by-block synchronization if supported by the server.
	//   Incompatible with FlowSshC_TransferFlags_ResumeVerifiable.
	FlowSshC_TransferFlags_NoSync           = 0x00000200,
	// Note:
	// - If the server supports the extended attribute "no-buffering@bitvise.com", the client can
	//   express a preference whether the server should open files for unbuffered I/O. Unbuffered
	//   I/O can improve performance for uploads to non-local storage, such as Windows file shares.
	FlowSshC_TransferFlags_NoBuf_PreferYes  = 0x00000400,
	FlowSshC_TransferFlags_NoBuf_PreferNo   = 0x00000800,
};


enum FlowSshC_ClientSftpChannelOpenStep {
	FlowSshC_ClientSftpChannelOpenStep_OpenRequest		= 100,
	FlowSshC_ClientSftpChannelOpenStep_SftpRequest		= 200,
	FlowSshC_ClientSftpChannelOpenStep_InitPacket		= 300
};


FLOWSSHC_OPAQUE(FlowSshC_ClientSftpChannel);
// Notes:
// - Returns NULL on fatal error only (after fatal error handler is called).
// - Channel can be created even if the associated client is not yet connected.
// - Channel keeps the associated client alive throughout channel's lifetime.
FLOWSSHC_FUNC FlowSshC_ClientSftpChannel*		__cdecl FlowSshC_ClientSftpChannel_Create(FlowSshC_Client* client);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_AddRef(FlowSshC_ClientSftpChannel* channel);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Release(FlowSshC_ClientSftpChannel* channel);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_SetVersionHandler(FlowSshC_ClientSftpChannel* channel, FlowSshC_SftpVersionHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_SetCloseHandler(FlowSshC_ClientSftpChannel* channel, FlowSshC_ChannelCloseHandler handler, void* handlerData);
// Notes:
// - Client must be connected before sending open request, otherwise the request will
//   fail immediately through the supplied progress handler.
// - A closed channel can be re-opened at any time.
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Open(FlowSshC_ClientSftpChannel* channel, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Open2(FlowSshC_ClientSftpChannel* channel, wchar_t const* subsystem, FlowSshC_ProgressHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_RealPath(FlowSshC_ClientSftpChannel* channel, wchar_t const* queryPath, FlowSshC_RealPathHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Stat(FlowSshC_ClientSftpChannel* channel, wchar_t const* path, unsigned int desiredAttrFlags, FlowSshC_StatHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_SetStat(FlowSshC_ClientSftpChannel* channel, wchar_t const* path, FlowSshC_FileAttrs const* attrs, FlowSshC_SftpHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_MkDir(FlowSshC_ClientSftpChannel* channel, wchar_t const* path, FlowSshC_FileAttrs const* attrs, FlowSshC_SftpHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_RmDir(FlowSshC_ClientSftpChannel* channel, wchar_t const* path, FlowSshC_SftpHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Remove(FlowSshC_ClientSftpChannel* channel, wchar_t const* path, FlowSshC_SftpHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Rename(FlowSshC_ClientSftpChannel* channel, wchar_t const* oldPath, wchar_t const* newPath, FlowSshC_SftpHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_List(FlowSshC_ClientSftpChannel* channel, wchar_t const* path, FlowSshC_ListHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Upload(FlowSshC_ClientSftpChannel* channel, wchar_t const* localPath, wchar_t const* remotePath, unsigned int transferFlags, FlowSshC_TransferHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Upload2(FlowSshC_ClientSftpChannel* channel, wchar_t const* localPath, wchar_t const* remotePath, unsigned int transferFlags, unsigned int pipelineSize, FlowSshC_TransferHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Download(FlowSshC_ClientSftpChannel* channel, wchar_t const* remotePath, wchar_t const* localPath, unsigned int transferFlags, FlowSshC_TransferHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Download2(FlowSshC_ClientSftpChannel* channel, wchar_t const* remotePath, wchar_t const* localPath, unsigned int transferFlags, unsigned int pipelineSize, FlowSshC_TransferHandler handler, void* handlerData);
FLOWSSHC_FUNC void								__cdecl FlowSshC_ClientSftpChannel_Close(FlowSshC_ClientSftpChannel* channel, FlowSshC_ProgressHandler handler, void* handlerData);



// Notes:
// - Shutdown should be called before exiting the process or unloading FlowSshC.dll.
//    - C/C++: Shutdown should be called before returning from the main function or,
//      if FlowSshC.dll is loaded dynamically, before calling FreeLibrary() on it.
// - Handlers may be called during shutdown, however, no handler can be called once
//   shutdown is complete. FlowSshC_ErrorHandler will never be called during shutdown
//   though; or in other words, shudown will never raise a FlowSshC error.
// - What shutdown does is disconnect/abort any connected/connecting FlowSshC_Client,
//   closes all opened channels, and then and then waits for all FlowSshC threads to
//   finish gracefully. Furthermore, it frees resources acquired via initialization.
//   What shutdown does NOT do is destroy FlowSshC objects that haven't properly been
//   disposed of. The following functions create a new FlowSshC thread:
//    - FlowSshC_Client_Connect,
//    - FlowSshC_ClientSessionChannel_OpenRequest,
//    - FlowSshC_ClientSftpChannel_Open,
//    - FlowSshC_ClientSftpChannel_List,
//    - FlowSshC_ClientSftpChannel_Upload,
//    - FlowSshC_ClientSftpChannel_Download.
// - After shutdown is completed, FlowSshC may continue be using normally if it is
//   initialized again with FlowSshC_Initialize call.
FLOWSSHC_FUNC void								__cdecl FlowSshC_Shutdown();


#pragma pack (pop)
