////////////////////////////////////////////////////////////
//
//     	Declaration of classes
//	DceCallAttributes and
//	DceCall - a caller's wrapper of a DCE interface
//
//	No exception handling !
//
//      Copyright 2001 
//
////////////////////////////////////////////////////////////

#ifndef __DCECALL_H__
#define __DCECALL_H__

#include <dce/sec_login.h>
#include "DceInterface.h"


	// DceCallAttributes

class DceCallAttributes: public DceInterface
{
friend class DceCall;
public:
	 
	int status;
	
	DceCallAttributes();
	DceCallAttributes(const DceCallAttributes&);
	~DceCallAttributes();
	
	DceCallAttributes& operator=(const DceCallAttributes&);
	

	// syntax code read from an environment variable
	// or use DCE, if it is not set	
	int set_entry_name(const char *name);
	
	// takes precedence over linked interface id
	// (conflicts with polimorphic interfaces)
	int link_server_id(const char * string_id) // its length is UUID_STRING_LEN
	{ return linked_server_id.set(string_id); }	
			
	int set_secure()
	{security_is_set=true; return 0;}
		
	// default rpc_c_protect_level_default
	int set_protection_level( unsigned z=rpc_c_protect_level_none)
	{ protection_level=z; return 0;}
	
	// default rpc_c_authn_default
	int set_authentication_service( unsigned z=rpc_c_authn_none)
	{ authentication_service=z; return 0;}
	
	// default rpc_c_authz_none (!)
	int set_authorization_service( unsigned z)
	{ authorization_service=z; return 0;}
			
	// if not set - name is not checked
	int set_server_principal_name(const char *z);
			
	// login_context
	// if none is set - default login context is used
	
	// for nested calls, server's login context is automatically refreshed
	// default - current login context
	int use_server_login_context(const sec_login_handle_t *z)
	{ server_login_handle=z; login_type=server_context; return 0;}
	
	// default sec_login_auth_src_network
	// others: sec_login_auth_src_local, sec_login_auth_src_overridden
	int set_login_service(sec_login_auth_src_t z)
	{ login_service=z; return 0;}
	
			
private:
	enum LoginType
	{
	current_context,
	server_context
	};

	bool security_is_set;
	unsigned32 entry_name_syntax;
	unsigned_char_t *entry_name;
	unsigned_char_t *server_principal_name;
	unsigned32 	protection_level,
			authentication_service,
			authorization_service; 
	DceUuid linked_server_id;
	sec_login_flags_t login_flags;
	int login_type;
	sec_login_auth_src_t login_service;
	const sec_login_handle_t *server_login_handle;

}; 

	// DceCall
	// a base class for dce calls wrapers

class DceCall
{
DceCall(const DceCall&);		// forbidden
DceCall& operator=(const DceCall&);	// forbidden
public:

	DceCall(){initialize();} // for arrays
	DceCall(const DceCallAttributes& z)
	{initialize(); set_attributes(z);}
	virtual ~DceCall();
		
	int set_attributes(const DceCallAttributes& z);
		
	int set_instance_id(const char* z); // for logging
	
	// default is 3 times
	int set_retries(int z){rpc_retries=z; return 0;}
	
	int reset_binding(); // in case a deamon dced was interrupted
	
	int get_linked_id(DceUuid& z)
	{ return z.set(linked_id); }
	

protected:

	handle_t binding_handle;
	rpc_ns_handle_t import_context;
	
	DceCallAttributes dce_call_attributes;
	bool is_set, is_bound, secure;
	char * instance_id;	// for logging
	uuid_t linked_id;	// actual
	int rpc_retries;
		
	int initialize();
	int binding_begin();
	int binding_next();
	int binding_done();
	int start_binding();
	
	// default implementation writes to stdout
	// provide a custom logging function, if needed
	virtual int dce_log(const char *message, error_status_t status);
		
};

		

#endif

/* 

An implementation of a wraper MyDceCall of an interface 

int func(rpc_error_status* rpc_error_status,handle_t binding_handle,int z);

when rpc errors are passed through rpc_error_status with the help of ACF file.

Note that binding_handle is a member in DceCall class.

1.
class MyDceCall: public DceCall
{
public:

int func(int z);

...

}; 

2.
int MyDceCall::func(int z)
{
 error_status_t rpc_error_status=rpc_s_ok;
 int g=0;	
 if(start_binding()) return -1;			
 for(int count=0;count<rpc_retries;++count)	
 { 
  g=::func(rpc_error_status,binding_handle,z);
  if(rpc_error_status==rpc_s_ok) break; 		
  if( binding_next() ) break;				
 }						
 if(rpc_error_status!=rpc_s_ok) return -2;
 return g;
}

    ***************

A calling sequence:

DceCallAttributes call_attributes;

	// set attributes including Interface here

MyDceCall my_wraper(call_attributes); 

int g=my_wraper.func(0);


    ****************
    

For functionality presented to a client in a form

  int g=my_wraper.func(int z);
  
create an interface with two additional patameters 

  rpc_error_status and handle_t,
  
for example

 int func(rpc_error_status* rpc_error_status, handle_t binding_handle,int z).
 
and provide an ACF file for an idl compiler to pass rpc errors 
through rpc_error_status in addition to errors 
passed by this interface implementation

*/