summaryrefslogtreecommitdiff
path: root/lib/server/makeprotocol.pl.in
diff options
context:
space:
mode:
Diffstat (limited to 'lib/server/makeprotocol.pl.in')
-rwxr-xr-xlib/server/makeprotocol.pl.in1142
1 files changed, 613 insertions, 529 deletions
diff --git a/lib/server/makeprotocol.pl.in b/lib/server/makeprotocol.pl.in
index 91ba55b0..da4b9447 100755
--- a/lib/server/makeprotocol.pl.in
+++ b/lib/server/makeprotocol.pl.in
@@ -30,24 +30,19 @@ my %log_display_types =
'string' => ['%s', 'VAR.c_str()']
);
-
-
-my ($type, $file) = @ARGV;
-
-if($type ne 'Server' && $type ne 'Client')
+if (@ARGV != 1)
{
- die "Neither Server or Client is specified on command line\n";
+ die "Usage: $0 <protocol-txt-file>\n";
}
+my ($file) = @ARGV;
+
open IN, $file or die "Can't open input file $file\n";
-print "Making $type protocol classes from $file...\n";
+print "Making protocol classes from $file...\n";
my @extra_header_files;
-my $implement_syslog = 0;
-my $implement_filelog = 0;
-
# read attributes
my %attr;
while(<IN>)
@@ -59,41 +54,18 @@ while(<IN>)
my ($k,$v) = split /\s+/,$l,2;
- if($k eq 'ClientType')
- {
- add_type($v) if $type eq 'Client';
- }
- elsif($k eq 'ServerType')
+ if($k eq 'AddType')
{
- add_type($v) if $type eq 'Server';
+ add_type($v);
}
elsif($k eq 'ImplementLog')
{
- my ($log_if_type,$log_type) = split /\s+/,$v;
- if($type eq $log_if_type)
- {
- if($log_type eq 'syslog')
- {
- $implement_syslog = 1;
- }
- elsif($log_type eq 'file')
- {
- $implement_filelog = 1;
- }
- else
- {
- printf("ERROR: Unknown log type for implementation: $log_type\n");
- exit(1);
- }
- }
+ # Always implement logging
}
elsif($k eq 'LogTypeToText')
{
- my ($log_if_type,$type_name,$printf_format,$arg_template) = split /\s+/,$v;
- if($type eq $log_if_type)
- {
- $log_display_types{$type_name} = [$printf_format,$arg_template]
- }
+ my ($type_name,$printf_format,$arg_template) = split /\s+/,$v;
+ $log_display_types{$type_name} = [$printf_format,$arg_template]
}
else
{
@@ -169,10 +141,12 @@ close IN;
# open files
-my $h_filename = 'autogen_'.$protocol_name.'Protocol'.$type.'.h';
-open CPP,'>autogen_'.$protocol_name.'Protocol'.$type.'.cpp';
+my $h_filename = 'autogen_'.$protocol_name.'Protocol.h';
+open CPP,'>autogen_'.$protocol_name.'Protocol.cpp';
open H,">$h_filename";
+my $guardname = uc 'AUTOGEN_'.$protocol_name.'Protocol_H';
+
print CPP <<__E;
// Auto-generated file -- do not edit
@@ -183,149 +157,125 @@ print CPP <<__E;
#include "$h_filename"
#include "IOStream.h"
-
__E
-if($implement_syslog)
-{
- print H <<EOF;
-#ifndef WIN32
-#include <syslog.h>
-#endif
-EOF
-}
-
-
-my $guardname = uc 'AUTOGEN_'.$protocol_name.'Protocol'.$type.'_H';
print H <<__E;
-
// Auto-generated file -- do not edit
#ifndef $guardname
#define $guardname
+#include <cstdio>
+#include <list>
+
+#ifndef WIN32
+#include <syslog.h>
+#endif
+
#include "Protocol.h"
-#include "ProtocolObject.h"
+#include "Message.h"
#include "ServerException.h"
class IOStream;
-__E
-if($implement_filelog)
-{
- print H qq~#include <stdio.h>\n~;
-}
+__E
# extra headers
for(@extra_header_files)
{
- print H qq~#include "$_"\n~
+ print H qq@#include "$_"\n@;
}
-print H "\n";
-if($type eq 'Server')
-{
- # need utils file for the server
- print H '#include "Utils.h"',"\n\n"
-}
+print H <<__E;
+
+// need utils file for the server
+#include "Utils.h"
+__E
-my $derive_objects_from = 'ProtocolObject';
+my $message_base_class = "${protocol_name}ProtocolMessage";
my $objects_extra_h = '';
my $objects_extra_cpp = '';
-if($type eq 'Server')
-{
- # define the context
- print H "class $context_class;\n\n";
- print CPP "#include \"$context_class_inc\"\n\n";
-
- # change class we derive the objects from
- $derive_objects_from = $protocol_name.'ProtocolObject';
-
- $objects_extra_h = <<__E;
- virtual std::auto_ptr<ProtocolObject> DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext);
-__E
- $objects_extra_cpp = <<__E;
-std::auto_ptr<ProtocolObject> ${derive_objects_from}::DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext)
-{
- THROW_EXCEPTION(ConnectionException, Conn_Protocol_TriedToExecuteReplyCommand)
-}
+
+# define the context
+print H "class $context_class;\n\n";
+print CPP <<__E;
+#include "$context_class_inc"
+#include "MemLeakFindOn.h"
__E
-}
-print CPP qq~#include "MemLeakFindOn.h"\n~;
+my $request_base_class = "${protocol_name}ProtocolRequest";
+my $reply_base_class = "${protocol_name}ProtocolReply";
+# the abstract protocol interface
+my $protocol_base_class = $protocol_name."ProtocolBase";
+my $replyable_base_class = $protocol_name."ProtocolReplyable";
-if($type eq 'Client' && ($implement_syslog || $implement_filelog))
-{
- # change class we derive the objects from
- $derive_objects_from = $protocol_name.'ProtocolObjectCl';
-}
-if($implement_syslog)
-{
- $objects_extra_h .= <<__E;
- virtual void LogSysLog(const char *Action) const = 0;
-__E
-}
-if($implement_filelog)
-{
- $objects_extra_h .= <<__E;
- virtual void LogFile(const char *Action, FILE *file) const = 0;
-__E
-}
+print H <<__E;
+class $protocol_base_class;
+class $replyable_base_class;
+class $reply_base_class;
-if($derive_objects_from ne 'ProtocolObject')
-{
- # output a definition for the protocol object derived class
- print H <<__E;
-class ${protocol_name}ProtocolServer;
-
-class $derive_objects_from : public ProtocolObject
+class $message_base_class : public Message
{
public:
- $derive_objects_from();
- virtual ~$derive_objects_from();
- $derive_objects_from(const $derive_objects_from &rToCopy);
-
-$objects_extra_h
+ virtual std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext) const;
};
-__E
- # and some cpp definitions
- print CPP <<__E;
-${derive_objects_from}::${derive_objects_from}()
+class $reply_base_class
{
-}
-${derive_objects_from}::~${derive_objects_from}()
+};
+
+class $request_base_class
{
-}
-${derive_objects_from}::${derive_objects_from}(const $derive_objects_from &rToCopy)
+};
+
+__E
+
+print CPP <<__E;
+std::auto_ptr<$message_base_class> $message_base_class\::DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext) const
{
+ THROW_EXCEPTION(ConnectionException, Conn_Protocol_TriedToExecuteReplyCommand)
}
-$objects_extra_cpp
__E
-}
-
-
-my $classname_base = $protocol_name.'Protocol'.$type;
+my %cmd_class;
# output the classes
-for my $cmd (@cmd_list)
+foreach my $cmd (@cmd_list)
{
+ my @cmd_base_classes = ($message_base_class);
+
+ if(obj_is_type($cmd, 'Command'))
+ {
+ push @cmd_base_classes, $request_base_class;
+ }
+
+ if(obj_is_type($cmd, 'Reply'))
+ {
+ push @cmd_base_classes, $reply_base_class;
+ }
+
+ my $cmd_base_class = join(", ", map {"public $_"} @cmd_base_classes);
+ my $cmd_class = $protocol_name."ProtocolClient".$cmd;
+ $cmd_class{$cmd} = $cmd_class;
+
print H <<__E;
-class $classname_base$cmd : public $derive_objects_from
+class $cmd_class : $cmd_base_class
{
public:
- $classname_base$cmd();
- $classname_base$cmd(const $classname_base$cmd &rToCopy);
- ~$classname_base$cmd();
+ $cmd_class();
+ $cmd_class(const $cmd_class &rToCopy);
+ ~$cmd_class();
int GetType() const;
enum
{
TypeID = $cmd_id{$cmd}
};
__E
+
# constants
if(exists $cmd_constants{$cmd})
{
@@ -333,72 +283,63 @@ __E
print H join(",\n\t\t",@{$cmd_constants{$cmd}});
print H "\n\t};\n";
}
+
# flags
if(obj_is_type($cmd,'EndsConversation'))
{
print H "\tbool IsConversationEnd() const;\n";
}
+
if(obj_is_type($cmd,'IsError'))
{
print H "\tbool IsError(int &rTypeOut, int &rSubTypeOut) const;\n";
print H "\tstd::string GetMessage() const;\n";
}
- if($type eq 'Server' && obj_is_type($cmd, 'Command'))
+
+ if(obj_is_type($cmd, 'Command'))
{
- print H "\tstd::auto_ptr<ProtocolObject> DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext); // IMPLEMENT THIS\n"
+ print H <<__E;
+ std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext) const; // IMPLEMENT THIS\n
+__E
}
# want to be able to read from streams?
- my $read_from_streams = (obj_is_type($cmd,'Command') && $type eq 'Server') || (obj_is_type($cmd,'Reply') && $type eq 'Client');
- my $write_to_streams = (obj_is_type($cmd,'Command') && $type eq 'Client') || (obj_is_type($cmd,'Reply') && $type eq 'Server');
+ print H "\tvoid SetPropertiesFromStreamData(Protocol &rProtocol);\n";
- if($read_from_streams)
+ # write Get functions
+ for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
{
- print H "\tvoid SetPropertiesFromStreamData(Protocol &rProtocol);\n";
+ my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
- # write Get functions
- for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
- {
- my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-
- print H "\t".translate_type_to_arg_type($ty)." Get$nm() {return m$nm;}\n";
- }
+ print H "\t".translate_type_to_arg_type($ty)." Get$nm() {return m$nm;}\n";
}
+
my $param_con_args = '';
- if($write_to_streams)
+ # extra constructor?
+ if($#{$cmd_contents{$cmd}} >= 0)
{
- # extra constructor?
- if($#{$cmd_contents{$cmd}} >= 0)
- {
- my @a;
- for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
- {
- my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-
- push @a,translate_type_to_arg_type($ty)." $nm";
- }
- $param_con_args = join(', ',@a);
- print H "\t$classname_base$cmd(".$param_con_args.");\n";
- }
- print H "\tvoid WritePropertiesToStreamData(Protocol &rProtocol) const;\n";
- # set functions
+ my @a;
for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
{
my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-
- print H "\tvoid Set$nm(".translate_type_to_arg_type($ty)." $nm) {m$nm = $nm;}\n";
- }
- }
-
- if($implement_syslog)
- {
- print H "\tvirtual void LogSysLog(const char *Action) const;\n";
+
+ push @a,translate_type_to_arg_type($ty)." $nm";
+ }
+ $param_con_args = join(', ',@a);
+ print H "\t$cmd_class(".$param_con_args.");\n";
}
- if($implement_filelog)
+ print H "\tvoid WritePropertiesToStreamData(Protocol &rProtocol) const;\n";
+ # set functions
+ for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
{
- print H "\tvirtual void LogFile(const char *Action, FILE *file) const;\n";
+ my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
+
+ print H "\tvoid Set$nm(".translate_type_to_arg_type($ty)." $nm) {m$nm = $nm;}\n";
}
-
+
+ print H "\tvirtual void LogSysLog(const char *Action) const;\n";
+ print H "\tvirtual void LogFile(const char *Action, FILE *file) const;\n";
# write member variables and setup for cpp file
my @def_constructor_list;
@@ -432,77 +373,73 @@ __E
my $param_con_vars = join(",\n\t ",@param_constructor_list);
$param_con_vars = "\n\t: ".$param_con_vars if $param_con_vars ne '';
- my $class = "$classname_base$cmd".'::';
print CPP <<__E;
-$class$classname_base$cmd()$def_con_vars
+$cmd_class\::$cmd_class()$def_con_vars
{
}
-$class$classname_base$cmd(const $classname_base$cmd &rToCopy)$copy_con_vars
+$cmd_class\::$cmd_class(const $cmd_class &rToCopy)$copy_con_vars
{
}
-$class~$classname_base$cmd()
+$cmd_class\::~$cmd_class()
{
}
-int ${class}GetType() const
+int $cmd_class\::GetType() const
{
return $cmd_id{$cmd};
}
__E
- if($read_from_streams)
+ print CPP "void $cmd_class\::SetPropertiesFromStreamData(Protocol &rProtocol)\n{\n";
+ for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
{
- print CPP "void ${class}SetPropertiesFromStreamData(Protocol &rProtocol)\n{\n";
- for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
+ my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
+ if($ty =~ m/\Avector/)
{
- my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
- if($ty =~ m/\Avector/)
- {
- print CPP "\trProtocol.ReadVector(m$nm);\n";
- }
- else
- {
- print CPP "\trProtocol.Read(m$nm);\n";
- }
+ print CPP "\trProtocol.ReadVector(m$nm);\n";
+ }
+ else
+ {
+ print CPP "\trProtocol.Read(m$nm);\n";
}
- print CPP "}\n";
}
- if($write_to_streams)
+ print CPP "}\n";
+
+ # implement extra constructor?
+ if($param_con_vars ne '')
+ {
+ print CPP "$cmd_class\::$cmd_class($param_con_args)$param_con_vars\n{\n}\n";
+ }
+ print CPP "void $cmd_class\::WritePropertiesToStreamData(Protocol &rProtocol) const\n{\n";
+ for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
{
- # implement extra constructor?
- if($param_con_vars ne '')
+ my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
+ if($ty =~ m/\Avector/)
{
- print CPP "$class$classname_base$cmd($param_con_args)$param_con_vars\n{\n}\n";
+ print CPP "\trProtocol.WriteVector(m$nm);\n";
}
- print CPP "void ${class}WritePropertiesToStreamData(Protocol &rProtocol) const\n{\n";
- for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
+ else
{
- my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
- if($ty =~ m/\Avector/)
- {
- print CPP "\trProtocol.WriteVector(m$nm);\n";
- }
- else
- {
- print CPP "\trProtocol.Write(m$nm);\n";
- }
+ print CPP "\trProtocol.Write(m$nm);\n";
}
- print CPP "}\n";
}
+ print CPP "}\n";
+
if(obj_is_type($cmd,'EndsConversation'))
{
- print CPP "bool ${class}IsConversationEnd() const\n{\n\treturn true;\n}\n";
+ print CPP "bool $cmd_class\::IsConversationEnd() const\n{\n\treturn true;\n}\n";
}
+
if(obj_is_type($cmd,'IsError'))
{
# get parameters
my ($mem_type,$mem_subtype) = split /,/,obj_get_type_params($cmd,'IsError');
print CPP <<__E;
-bool ${class}IsError(int &rTypeOut, int &rSubTypeOut) const
+bool $cmd_class\::IsError(int &rTypeOut, int &rSubTypeOut) const
{
rTypeOut = m$mem_type;
rSubTypeOut = m$mem_subtype;
return true;
}
-std::string ${class}GetMessage() const
+std::string $cmd_class\::GetMessage() const
{
switch(m$mem_subtype)
{
@@ -526,21 +463,13 @@ __E
__E
}
- if($implement_syslog)
- {
- my ($log) = make_log_strings_framework($cmd);
- print CPP <<__E;
-void ${class}LogSysLog(const char *Action) const
+ my ($log) = make_log_strings_framework($cmd);
+ print CPP <<__E;
+void $cmd_class\::LogSysLog(const char *Action) const
{
BOX_TRACE($log);
}
-__E
- }
- if($implement_filelog)
- {
- my ($log) = make_log_strings_framework($cmd);
- print CPP <<__E;
-void ${class}LogFile(const char *Action, FILE *File) const
+void $cmd_class\::LogFile(const char *Action, FILE *File) const
{
std::ostringstream oss;
oss << $log;
@@ -548,208 +477,476 @@ void ${class}LogFile(const char *Action, FILE *File) const
::fflush(File);
}
__E
- }
}
-# finally, the protocol object itself
+my $error_class = $protocol_name."ProtocolError";
+
+# the abstract protocol interface
print H <<__E;
-class $classname_base : public Protocol
+class $protocol_base_class
{
public:
- $classname_base(IOStream &rStream);
- virtual ~$classname_base();
+ $protocol_base_class();
+ virtual ~$protocol_base_class();
+ virtual const char *GetIdentString();
+ bool GetLastError(int &rTypeOut, int &rSubTypeOut);
+
+protected:
+ void CheckReply(const std::string& requestCommand,
+ const $message_base_class &rReply, int expectedType);
+ void SetLastError(int Type, int SubType)
+ {
+ mLastErrorType = Type;
+ mLastErrorSubType = SubType;
+ }
+
+private:
+ $protocol_base_class(const $protocol_base_class &rToCopy); /* do not call */
+ int mLastErrorType;
+ int mLastErrorSubType;
+};
+
+class $replyable_base_class : public virtual $protocol_base_class
+{
+public:
+ $replyable_base_class();
+ virtual ~$replyable_base_class();
+
+ /*
+ virtual std::auto_ptr<$message_base_class> Receive() = 0;
+ virtual void Send(const ${message_base_class} &rObject) = 0;
+ */
+
+ virtual std::auto_ptr<IOStream> ReceiveStream() = 0;
+ virtual int GetTimeout() = 0;
+ void SendStreamAfterCommand(IOStream *pStream);
+
+protected:
+ std::list<IOStream*> mStreamsToSend;
+ void DeleteStreamsToSend();
+
+private:
+ $replyable_base_class(const $replyable_base_class &rToCopy); /* do not call */
+};
- std::auto_ptr<$derive_objects_from> Receive();
- void Send(const ${derive_objects_from} &rObject);
__E
-if($implement_syslog)
+
+print CPP <<__E;
+$protocol_base_class\::$protocol_base_class()
+: mLastErrorType(Protocol::NoError),
+ mLastErrorSubType(Protocol::NoError)
+{ }
+
+$protocol_base_class\::~$protocol_base_class()
+{ }
+
+const char *$protocol_base_class\::GetIdentString()
{
- print H "\tvoid SetLogToSysLog(bool Log = false) {mLogToSysLog = Log;}\n";
+ return "$ident_string";
}
-if($implement_filelog)
+
+$replyable_base_class\::$replyable_base_class()
+{ }
+
+$replyable_base_class\::~$replyable_base_class()
+{ }
+
+void $replyable_base_class\::SendStreamAfterCommand(IOStream *pStream)
{
- print H "\tvoid SetLogToFile(FILE *File = 0) {mLogToFile = File;}\n";
+ ASSERT(pStream != NULL);
+ mStreamsToSend.push_back(pStream);
}
-if($type eq 'Server')
+
+void $replyable_base_class\::DeleteStreamsToSend()
{
- # need to put in the conversation function
- print H "\tvoid DoServer($context_class &rContext);\n\n";
- # and the send vector thing
- print H "\tvoid SendStreamAfterCommand(IOStream *pStream);\n\n";
+ for(std::list<IOStream*>::iterator i(mStreamsToSend.begin()); i != mStreamsToSend.end(); ++i)
+ {
+ delete (*i);
+ }
+ mStreamsToSend.clear();
}
-if($type eq 'Client')
+
+void $protocol_base_class\::CheckReply(const std::string& requestCommand,
+ const $message_base_class &rReply, int expectedType)
{
- # add plain object taking query functions
- my $with_params;
- for my $cmd (@cmd_list)
+ if(rReply.GetType() == expectedType)
+ {
+ // Correct response, do nothing
+ }
+ else
{
- if(obj_is_type($cmd,'Command'))
+ // Set protocol error
+ int type, subType;
+
+ if(rReply.IsError(type, subType))
{
- my $has_stream = obj_is_type($cmd,'StreamWithCommand');
- my $argextra = $has_stream?', IOStream &rStream':'';
- my $queryextra = $has_stream?', rStream':'';
- my $reply = obj_get_type_params($cmd,'Command');
- print H "\tstd::auto_ptr<$classname_base$reply> Query(const $classname_base$cmd &rQuery$argextra);\n";
- my @a;
- my @na;
- for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
- {
- my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
- push @a,translate_type_to_arg_type($ty)." $nm";
- push @na,"$nm";
- }
- my $ar = join(', ',@a);
- my $nar = join(', ',@na);
- $nar = "($nar)" if $nar ne '';
-
- $with_params .= "\tinline std::auto_ptr<$classname_base$reply> Query$cmd($ar$argextra)\n\t{\n";
- $with_params .= "\t\t$classname_base$cmd send$nar;\n";
- $with_params .= "\t\treturn Query(send$queryextra);\n";
- $with_params .= "\t}\n";
+ SetLastError(type, subType);
+ BOX_WARNING(requestCommand << " command failed: "
+ "received error " <<
+ (($error_class&)rReply).GetMessage());
+ }
+ else
+ {
+ SetLastError(Protocol::UnknownError, Protocol::UnknownError);
+ BOX_WARNING(requestCommand << " command failed: "
+ "received unexpected response type " <<
+ rReply.GetType());
}
+
+ // Throw an exception
+ THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnexpectedReply)
}
- # quick hack to correct bad argument lists for commands with zero paramters but with streams
- $with_params =~ s/\(, /(/g;
- print H "\n",$with_params,"\n";
}
-print H <<__E;
-private:
- $classname_base(const $classname_base &rToCopy);
-__E
-if($type eq 'Server')
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: Protocol::GetLastError(int &, int &)
+// Purpose: Returns true if there was an error, and type and subtype if there was.
+// Created: 2003/08/19
+//
+// --------------------------------------------------------------------------
+bool $protocol_base_class\::GetLastError(int &rTypeOut, int &rSubTypeOut)
{
- # need to put the streams to send vector
- print H "\tstd::vector<IOStream*> mStreamsToSend;\n\tvoid DeleteStreamsToSend();\n";
+ if(mLastErrorType == Protocol::NoError)
+ {
+ // no error.
+ return false;
+ }
+
+ // Return type and subtype in args
+ rTypeOut = mLastErrorType;
+ rSubTypeOut = mLastErrorSubType;
+
+ // and unset them
+ mLastErrorType = Protocol::NoError;
+ mLastErrorSubType = Protocol::NoError;
+
+ return true;
}
-if($implement_filelog || $implement_syslog)
-{
- print H <<__E;
- virtual void InformStreamReceiving(u_int32_t Size);
- virtual void InformStreamSending(u_int32_t Size);
__E
-}
-if($implement_syslog)
+# the callable protocol interface (implemented by Client and Local classes)
+# with Query methods that don't take a context parameter
+my $callable_base_class = $protocol_name."ProtocolCallable";
+print H <<__E;
+class $callable_base_class : public virtual $protocol_base_class
{
- print H "private:\n\tbool mLogToSysLog;\n";
-}
-if($implement_filelog)
+public:
+ virtual std::auto_ptr<IOStream> ReceiveStream() = 0;
+ virtual int GetTimeout() = 0;
+__E
+
+# add plain object taking query functions
+my $with_params;
+for my $cmd (@cmd_list)
{
- print H "private:\n\tFILE *mLogToFile;\n";
+ if(obj_is_type($cmd,'Command'))
+ {
+ my $has_stream = obj_is_type($cmd,'StreamWithCommand');
+ my $argextra = $has_stream?', IOStream &rStream':'';
+ my $queryextra = $has_stream?', rStream':'';
+ my $request_class = $cmd_class{$cmd};
+ my $reply_class = $cmd_class{obj_get_type_params($cmd,'Command')};
+
+ print H "\tvirtual std::auto_ptr<$reply_class> Query(const $request_class &rQuery$argextra) = 0;\n";
+ my @a;
+ my @na;
+ for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
+ {
+ my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
+ push @a,translate_type_to_arg_type($ty)." $nm";
+ push @na,"$nm";
+ }
+ my $ar = join(', ',@a);
+ my $nar = join(', ',@na);
+ $nar = "($nar)" if $nar ne '';
+
+ $with_params .= <<__E;
+ inline std::auto_ptr<$reply_class> Query$cmd($ar$argextra)
+ {
+ $request_class send$nar;
+ return Query(send$queryextra);
+ }
+__E
+ }
}
+
+# quick hack to correct bad argument lists for commands with zero parameters but with streams
+$with_params =~ s/\(, /(/g;
+
print H <<__E;
-protected:
- virtual std::auto_ptr<ProtocolObject> MakeProtocolObject(int ObjType);
- virtual const char *GetIdentString();
+$with_params
};
-
__E
-my $constructor_extra = '';
-$constructor_extra .= ', mLogToSysLog(false)' if $implement_syslog;
-$constructor_extra .= ', mLogToFile(0)' if $implement_filelog;
+# standard remote protocol objects
+foreach my $type ('Client', 'Server', 'Local')
+{
+ my $writing_client = ($type eq 'Client');
+ my $writing_server = ($type eq 'Server');
+ my $writing_local = ($type eq 'Local');
+
+ my $server_or_client_class = $protocol_name."Protocol".$type;
+ my @base_classes;
-my $destructor_extra = ($type eq 'Server')?"\n\tDeleteStreamsToSend();":'';
+ if (not $writing_client)
+ {
+ push @base_classes, $replyable_base_class;
+ }
+ if (not $writing_server)
+ {
+ push @base_classes, $callable_base_class;
+ }
+ if (not $writing_local)
+ {
+ push @base_classes, "Protocol";
+ }
-my $prefix = $classname_base.'::';
-print CPP <<__E;
-$prefix$classname_base(IOStream &rStream)
- : Protocol(rStream)$constructor_extra
+ my $base_classes_str = join(", ", map {"public $_"} @base_classes);
+
+ print H <<__E;
+class $server_or_client_class : $base_classes_str
{
-}
-$prefix~$classname_base()
+public:
+__E
+
+ if($writing_local)
+ {
+ print H <<__E;
+ $server_or_client_class($context_class &rContext);
+__E
+ }
+ else
+ {
+ print H <<__E;
+ $server_or_client_class(IOStream &rStream);
+ std::auto_ptr<$message_base_class> Receive();
+ void Send(const $message_base_class &rObject);
+__E
+ }
+
+ print H <<__E;
+ virtual ~$server_or_client_class();
+__E
+
+ if($writing_server)
+ {
+ # need to put in the conversation function
+ print H <<__E;
+ void DoServer($context_class &rContext);
+
+__E
+ }
+
+ if($writing_client or $writing_local)
+ {
+ # add plain object taking query functions
+ for my $cmd (@cmd_list)
+ {
+ if(obj_is_type($cmd,'Command'))
+ {
+ my $has_stream = obj_is_type($cmd,'StreamWithCommand');
+ my $argextra = $has_stream?', IOStream &rStream':'';
+ my $queryextra = $has_stream?', rStream':'';
+ my $request_class = $cmd_class{$cmd};
+ my $reply_class = $cmd_class{obj_get_type_params($cmd,'Command')};
+ print H "\tstd::auto_ptr<$reply_class> Query(const $request_class &rQuery$argextra);\n";
+ }
+ }
+ }
+
+ if($writing_local)
+ {
+ print H <<__E;
+private:
+ $context_class &mrContext;
+__E
+ }
+
+ print H <<__E;
+
+protected:
+ virtual std::auto_ptr<Message> MakeMessage(int ObjType);
+
+__E
+
+ if($writing_local)
+ {
+ print H <<__E;
+ virtual void InformStreamReceiving(u_int32_t Size) { }
+ virtual void InformStreamSending(u_int32_t Size) { }
+
+public:
+ virtual std::auto_ptr<IOStream> ReceiveStream()
+ {
+ std::auto_ptr<IOStream> apStream(mStreamsToSend.front());
+ mStreamsToSend.pop_front();
+ return apStream;
+ }
+__E
+ }
+ else
+ {
+ print H <<__E;
+ virtual void InformStreamReceiving(u_int32_t Size)
+ {
+ this->Protocol::InformStreamReceiving(Size);
+ }
+ virtual void InformStreamSending(u_int32_t Size)
+ {
+ this->Protocol::InformStreamSending(Size);
+ }
+
+public:
+ virtual std::auto_ptr<IOStream> ReceiveStream()
+ {
+ return this->Protocol::ReceiveStream();
+ }
+__E
+ }
+
+ print H <<__E;
+ virtual const char *GetProtocolIdentString()
+ {
+ return GetIdentString();
+ }
+__E
+
+ if($writing_local)
+ {
+ print H <<__E;
+ virtual int GetTimeout()
+ {
+ return IOStream::TimeOutInfinite;
+ }
+__E
+ }
+ else
+ {
+ print H <<__E;
+ virtual int GetTimeout()
+ {
+ return this->Protocol::GetTimeout();
+ }
+__E
+ }
+
+ print H <<__E;
+ /*
+ virtual void Handshake()
+ {
+ this->Protocol::Handshake();
+ }
+ virtual bool GetLastError(int &rTypeOut, int &rSubTypeOut)
+ {
+ return this->Protocol::GetLastError(rTypeOut, rSubTypeOut);
+ }
+ */
+
+private:
+ $server_or_client_class(const $server_or_client_class &rToCopy); /* no copies */
+};
+
+__E
+
+ my $destructor_extra = ($writing_server) ? "\n\tDeleteStreamsToSend();"
+ : '';
+
+ if($writing_local)
+ {
+ print CPP <<__E;
+$server_or_client_class\::$server_or_client_class($context_class &rContext)
+: mrContext(rContext)
+{ }
+__E
+ }
+ else
+ {
+ print CPP <<__E;
+$server_or_client_class\::$server_or_client_class(IOStream &rStream)
+: Protocol(rStream)
+{ }
+__E
+ }
+
+ print CPP <<__E;
+$server_or_client_class\::~$server_or_client_class()
{$destructor_extra
}
-const char *${prefix}GetIdentString()
-{
- return "$ident_string";
-}
-std::auto_ptr<ProtocolObject> ${prefix}MakeProtocolObject(int ObjType)
+__E
+
+ # write receive and send functions
+ print CPP <<__E;
+std::auto_ptr<Message> $server_or_client_class\::MakeMessage(int ObjType)
{
switch(ObjType)
{
__E
-# do objects within this
-for my $cmd (@cmd_list)
-{
- print CPP <<__E;
+ # do objects within this
+ for my $cmd (@cmd_list)
+ {
+ print CPP <<__E;
case $cmd_id{$cmd}:
- return std::auto_ptr<ProtocolObject>(new $classname_base$cmd);
+ return std::auto_ptr<Message>(new $cmd_class{$cmd}());
break;
__E
-}
+ }
-print CPP <<__E;
+ print CPP <<__E;
default:
THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnknownCommandRecieved)
}
}
__E
-# write receive and send functions
-print CPP <<__E;
-std::auto_ptr<$derive_objects_from> ${prefix}Receive()
-{
- std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(Protocol::Receive().release()));
-__E
- if($implement_syslog)
+ if(not $writing_local)
{
print CPP <<__E;
- if(mLogToSysLog)
+std::auto_ptr<$message_base_class> $server_or_client_class\::Receive()
+{
+ std::auto_ptr<$message_base_class> preply(($message_base_class *)
+ Protocol::ReceiveInternal().release());
+
+ if(GetLogToSysLog())
{
preply->LogSysLog("Receive");
}
-__E
- }
- if($implement_filelog)
- {
- print CPP <<__E;
- if(mLogToFile != 0)
+
+ if(GetLogToFile() != 0)
{
- preply->LogFile("Receive", mLogToFile);
+ preply->LogFile("Receive", GetLogToFile());
}
-__E
- }
-print CPP <<__E;
return preply;
}
-void ${prefix}Send(const ${derive_objects_from} &rObject)
+void $server_or_client_class\::Send(const $message_base_class &rObject)
{
-__E
- if($implement_syslog)
- {
- print CPP <<__E;
- if(mLogToSysLog)
+ if(GetLogToSysLog())
{
rObject.LogSysLog("Send");
}
-__E
- }
- if($implement_filelog)
- {
- print CPP <<__E;
- if(mLogToFile != 0)
+
+ if(GetLogToFile() != 0)
{
- rObject.LogFile("Send", mLogToFile);
- }
-__E
+ rObject.LogFile("Send", GetLogToFile());
}
-print CPP <<__E;
- Protocol::Send(rObject);
+ Protocol::SendInternal(rObject);
}
__E
-# write server function?
-if($type eq 'Server')
-{
- print CPP <<__E;
-void ${prefix}DoServer($context_class &rContext)
+ }
+
+ # write server function?
+ if($writing_server)
+ {
+ print CPP <<__E;
+void $server_or_client_class\::DoServer($context_class &rContext)
{
// Handshake with client
Handshake();
@@ -759,20 +956,22 @@ void ${prefix}DoServer($context_class &rContext)
while(inProgress)
{
// Get an object from the conversation
- std::auto_ptr<${derive_objects_from}> pobj(Receive());
+ std::auto_ptr<$message_base_class> pobj = Receive();
// Run the command
- std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(pobj->DoCommand(*this, rContext).release()));
+ std::auto_ptr<$message_base_class> preply = pobj->DoCommand(*this, rContext);
// Send the reply
- Send(*(preply.get()));
+ Send(*preply);
// Send any streams
- for(unsigned int s = 0; s < mStreamsToSend.size(); s++)
+ for(std::list<IOStream*>::iterator
+ i = mStreamsToSend.begin();
+ i != mStreamsToSend.end(); ++i)
{
- // Send the streams
- SendStream(*mStreamsToSend[s]);
+ SendStream(**i);
}
+
// Delete these streams
DeleteStreamsToSend();
@@ -784,161 +983,82 @@ void ${prefix}DoServer($context_class &rContext)
}
}
-void ${prefix}SendStreamAfterCommand(IOStream *pStream)
-{
- ASSERT(pStream != NULL);
- mStreamsToSend.push_back(pStream);
-}
-
-void ${prefix}DeleteStreamsToSend()
-{
- for(std::vector<IOStream*>::iterator i(mStreamsToSend.begin()); i != mStreamsToSend.end(); ++i)
- {
- delete (*i);
- }
- mStreamsToSend.clear();
-}
-
-__E
-}
-
-# write logging functions?
-if($implement_filelog || $implement_syslog)
-{
- my ($fR,$fS);
-
- if($implement_syslog)
- {
- $fR .= <<__E;
- if(mLogToSysLog)
- {
- if(Size==Protocol::ProtocolStream_SizeUncertain)
- {
- BOX_TRACE("Receiving stream, size uncertain");
- }
- else
- {
- BOX_TRACE("Receiving stream, size " << Size);
- }
- }
-__E
-
- $fS .= <<__E;
- if(mLogToSysLog)
- {
- if(Size==Protocol::ProtocolStream_SizeUncertain)
- {
- BOX_TRACE("Sending stream, size uncertain");
- }
- else
- {
- BOX_TRACE("Sending stream, size " << Size);
- }
- }
-__E
- }
-
- if($implement_filelog)
- {
- $fR .= <<__E;
- if(mLogToFile)
- {
- ::fprintf(mLogToFile,
- (Size==Protocol::ProtocolStream_SizeUncertain)
- ?"Receiving stream, size uncertain\\n"
- :"Receiving stream, size %d\\n", Size);
- ::fflush(mLogToFile);
- }
-__E
- $fS .= <<__E;
- if(mLogToFile)
- {
- ::fprintf(mLogToFile,
- (Size==Protocol::ProtocolStream_SizeUncertain)
- ?"Sending stream, size uncertain\\n"
- :"Sending stream, size %d\\n", Size);
- ::fflush(mLogToFile);
- }
__E
}
- print CPP <<__E;
-
-void ${prefix}InformStreamReceiving(u_int32_t Size)
-{
-$fR}
-
-void ${prefix}InformStreamSending(u_int32_t Size)
-{
-$fS}
-
-__E
-}
-
-
-# write client Query functions?
-if($type eq 'Client')
-{
- for my $cmd (@cmd_list)
+ # write client Query functions?
+ if($writing_client or $writing_local)
{
- if(obj_is_type($cmd,'Command'))
+ for my $cmd (@cmd_list)
{
- my $reply = obj_get_type_params($cmd,'Command');
- my $reply_id = $cmd_id{$reply};
- my $has_stream = obj_is_type($cmd,'StreamWithCommand');
- my $argextra = $has_stream?', IOStream &rStream':'';
- my $send_stream_extra = '';
- if($has_stream)
+ if(obj_is_type($cmd,'Command'))
{
- $send_stream_extra = <<__E;
-
+ my $request_class = $cmd_class{$cmd};
+ my $reply_msg = obj_get_type_params($cmd,'Command');
+ my $reply_class = $cmd_class{$reply_msg};
+ my $reply_id = $cmd_id{$reply_msg};
+ my $has_stream = obj_is_type($cmd,'StreamWithCommand');
+ my $argextra = $has_stream?', IOStream &rStream':'';
+ my $send_stream_extra = '';
+ my $send_stream_method = $writing_client ? "SendStream"
+ : "SendStreamAfterCommand";
+
+ if($writing_client)
+ {
+ if($has_stream)
+ {
+ $send_stream_extra = <<__E;
// Send stream after the command
SendStream(rStream);
__E
- }
- print CPP <<__E;
-std::auto_ptr<$classname_base$reply> ${classname_base}::Query(const $classname_base$cmd &rQuery$argextra)
+ }
+
+ print CPP <<__E;
+std::auto_ptr<$reply_class> $server_or_client_class\::Query(const $request_class &rQuery$argextra)
{
// Send query
Send(rQuery);
$send_stream_extra
+
// Wait for the reply
- std::auto_ptr<${derive_objects_from}> preply(Receive().release());
+ std::auto_ptr<$message_base_class> preply = Receive();
+
+ CheckReply("$cmd", *preply, $reply_id);
- if(preply->GetType() == $reply_id)
- {
- // Correct response
- return std::auto_ptr<$classname_base$reply>(($classname_base$reply*)preply.release());
- }
- else
- {
- // Set protocol error
- int type, subType;
- if(preply->IsError(type, subType))
- {
- SetError(type, subType);
- BOX_WARNING("$cmd command failed: received error " <<
- ((${classname_base}Error&)*preply).GetMessage());
- }
- else
- {
- SetError(Protocol::UnknownError, Protocol::UnknownError);
- BOX_WARNING("$cmd command failed: received "
- "unexpected response type " <<
- preply->GetType());
- }
-
- // Throw an exception
- THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnexpectedReply)
- }
+ // Correct response, if no exception thrown by CheckReply
+ return std::auto_ptr<$reply_class>(($reply_class *)preply.release());
+}
+__E
+ }
+ elsif($writing_local)
+ {
+ if($has_stream)
+ {
+ $send_stream_extra = <<__E;
+ // Send stream after the command
+ SendStreamAfterCommand(&rStream);
+__E
+ }
+
+ print CPP <<__E;
+std::auto_ptr<$reply_class> $server_or_client_class\::Query(const $request_class &rQuery$argextra)
+{
+ // Send query
+ $send_stream_extra
+ std::auto_ptr<$message_base_class> preply = rQuery.DoCommand(*this, mrContext);
+
+ CheckReply("$cmd", *preply, $reply_id);
+
+ // Correct response, if no exception thrown by CheckReply
+ return std::auto_ptr<$reply_class>(($reply_class *)preply.release());
}
__E
+ }
+ }
}
}
}
-
-
print H <<__E;
#endif // $guardname
@@ -948,8 +1068,7 @@ __E
close H;
close CPP;
-
-sub obj_is_type
+sub obj_is_type ($$)
{
my ($c,$ty) = @_;
for(@{$cmd_attributes{$c}})
@@ -1003,40 +1122,6 @@ sub translate_type_to_member_type
return $typename
}
-sub make_log_strings
-{
- my ($cmd) = @_;
-
- my @str;
- my @arg;
- for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
- {
- my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-
- if(exists $log_display_types{$ty})
- {
- # need to translate it
- my ($format,$arg) = @{$log_display_types{$ty}};
- $arg =~ s/VAR/m$nm/g;
-
- if ($format eq "0x%llx" and $target_windows)
- {
- $format = "0x%I64x";
- $arg = "(uint64_t)$arg";
- }
-
- push @str,$format;
- push @arg,$arg;
- }
- else
- {
- # is opaque
- push @str,'OPAQUE';
- }
- }
- return ($cmd.'('.join(',',@str).')', join(',','',@arg));
-}
-
sub make_log_strings_framework
{
my ($cmd) = @_;
@@ -1053,7 +1138,7 @@ sub make_log_strings_framework
my ($format,$arg) = @{$log_display_types{$ty}};
$arg =~ s/VAR/m$nm/g;
- if ($format eq '\\"%s\\"')
+ if ($format eq '"%s"')
{
$arg = "\"\\\"\" << $arg << \"\\\"\"";
}
@@ -1090,4 +1175,3 @@ sub make_log_strings_framework
return $log_cmd;
}
-