#!/usr/bin/perl -w
use
EMDIS::ECS
qw($ECS_CFG $ECS_NODE_TBL load_ecs_config log_info
move_to_dir format_doc_filename format_msg_filename send_admin_email)
;
use
vars
qw($err $filename $message_content $msg $msg_type $node $sender)
;
open
STDERR,
">&STDOUT"
or
die
"Unable to dup STDOUT: $!\n"
;
select
STDERR; $| = 1;
select
STDOUT; $| = 1;
my
$prg
= basename $0;
my
$usage
=
"Usage: $prg [--config ecs_cfg] <filename> <sender>\n"
.
"For help, start $prg with the option -help\n"
;
my
$opt_config
=
'ecs.cfg'
;
my
$opt_help
= 0;
GetOptions(
'config=s'
=> \
$opt_config
,
'help'
=> \
$opt_help
)
or
die
"Error: unrecognized command line option.\n$usage"
;
pod2usage(
-verbose
=>2)
if
$opt_help
;
die
"Invalid number of command line arguments.\n$usage"
if
$#ARGV
!= 1;
(
$filename
,
$sender
) =
@ARGV
;
print
"filename: $filename\nsender: $sender\n"
;
$err
= load_ecs_config(
$opt_config
);
die
"ecs_proc_meta: $err\nUnable to initialize ECS.\n"
if
$err
;
$ECS_NODE_TBL
->
lock
()
or
die
"ecs_proc_meta: unable to lock node_tbl: "
.
$ECS_NODE_TBL
->ERROR .
"\n"
;
$node
=
$ECS_NODE_TBL
->
read
(
$sender
);
$err
=
$ECS_NODE_TBL
->ERROR;
$ECS_NODE_TBL
->unlock();
if
(
$err
or not
$node
) {
my
$err2
= move_to_dir(
$filename
,
$ECS_CFG
->ECS_MBX_TRASH_DIR);
warn
"ecs_proc_meta: $err\n"
if
$err2
;
die
"ecs_proc_meta: unable to read node $sender from node_tbl: $err\n"
if
$err
;
die
"ecs_proc_meta: node not found: $sender\n"
;
}
if
(
$node
->{encr_meta} !~ /true/i) {
$msg
= EMDIS::ECS::Message::read_from_file(
$filename
);
$message_content
=
$msg
->body
if
ref
$msg
;
}
else
{
$msg
= EMDIS::ECS::Message::read_from_encrypted_file(
$filename
);
$message_content
=
$msg
->cleartext
if
ref
$msg
;
}
die
"ecs_proc_meta: $msg\n"
unless
ref
$msg
;
die
"ecs_proc_meta: file does not contain a meta-message: $filename\n"
unless
$msg
->is_meta_message;
$msg_type
=
''
;
if
(
$message_content
=~ /msg_type\s*=\s*(\S+)/i) {
$msg_type
= $1;
}
if
(
$msg_type
=~ /^READY/i)
{
$ECS_NODE_TBL
->
lock
()
or
die
"ecs_proc_meta: unable to lock node_tbl: "
.
$ECS_NODE_TBL
->ERROR .
"\n"
;
$node
=
$ECS_NODE_TBL
->
read
(
$sender
);
if
(
$node
)
{
$node
->{last_in} =
time
;
$ECS_NODE_TBL
->
write
(
$sender
,
$node
);
}
$ECS_NODE_TBL
->unlock();
if
(not
$node
)
{
$err
= move_to_dir(
$filename
,
$ECS_CFG
->ECS_MBX_TRASH_DIR);
warn
"ecs_proc_meta: $err\n"
if
$err
;
die
"ecs_proc_meta: node not found: $sender\n"
;
}
unlink
$filename
;
exit
0;
}
if
(
$msg_type
=~ /^RE_SEND/i)
{
my
$seq_num
=
''
;
my
$part_num
=
''
;
if
(
$message_content
=~ /seq_num\s*=\s*(\d+):(\d+)/i)
{
$seq_num
= $1;
$part_num
= $2;
}
if
(
$message_content
=~ /seq_num\s*=\s*(\d+)/i)
{
$seq_num
= $1;
}
else
{
die
"ecs_proc_meta: seq_num not specified in RE_SEND message: "
.
"$filename\n"
;
}
$ECS_NODE_TBL
->
lock
()
or
die
"ecs_proc_meta: unable to lock node_tbl: "
.
$ECS_NODE_TBL
->ERROR .
"\n"
;
$node
=
$ECS_NODE_TBL
->
read
(
$sender
);
if
(
$node
)
{
$node
->{last_in} =
time
;
$ECS_NODE_TBL
->
write
(
$sender
,
$node
);
}
$ECS_NODE_TBL
->unlock();
if
(not
$node
)
{
$err
= move_to_dir(
$filename
,
$ECS_CFG
->ECS_MBX_TRASH_DIR);
warn
"ecs_proc_meta: $err\n"
if
$err
;
die
"ecs_proc_meta: node not found: $sender\n"
;
}
if
(
$seq_num
>
$node
->{out_seq})
{
die
"ecs_proc_meta: node requested RE_SEND of unsent message "
.
"($sender,$seq_num)\n"
;
}
my
$msg_filename
= format_msg_filename(
$sender
,
$seq_num
);
die
"ecs_proc_meta: requested FML message file not found: $msg_filename\n"
unless
-e
$msg_filename
;
my
$msg
= new EMDIS::ECS::FileBackedMessage(
$msg_filename
);
die
"ecs_proc_meta: unable to load FML message from file $msg_filename: "
.
"$msg\n"
unless
ref
$msg
;
die
"ecs_proc_meta: found unexpected seq_num "
.
$msg
->seq_num .
", expected $seq_num\n"
unless
$msg
->seq_num ==
$seq_num
;
$err
=
$msg
->send_this_message(
$sender
, 1,
$part_num
);
if
(
$err
){
send_admin_email(
"An error occurred while trying to resend ecs msg!"
,
" Email from $sender with sequence number $seq_num "
,
(
$part_num
?
"(part_num $part_num) "
:
''
) .
"could not be resent."
);
die
"ecs_proc_meta: error sending email: $err\n"
}
unlink
$filename
;
log_info(
"\nFinished processing $sender RE_SEND request $seq_num"
.
(
$part_num
?
":$part_num"
:
''
) .
"\n"
);
exit
0;
}
if
(
$msg_type
=~ /^DOC_RE_SEND/i)
{
my
$seq_num
=
''
;
if
(
$message_content
=~ /seq_num\s*=\s*(\d+)/i)
{
$seq_num
= $1;
}
else
{
die
"ecs_proc_meta: seq_num not specified in DOC_RE_SEND message: "
.
"$filename\n"
;
}
$ECS_NODE_TBL
->
lock
()
or
die
"ecs_proc_meta: unable to lock node_tbl: "
.
$ECS_NODE_TBL
->ERROR .
"\n"
;
$node
=
$ECS_NODE_TBL
->
read
(
$sender
);
if
(
$node
)
{
$node
->{last_in} =
time
;
$ECS_NODE_TBL
->
write
(
$sender
,
$node
);
}
$ECS_NODE_TBL
->unlock();
if
(not
$node
)
{
$err
= move_to_dir(
$filename
,
$ECS_CFG
->ECS_MBX_TRASH_DIR);
warn
"ecs_proc_meta: $err\n"
if
$err
;
die
"ecs_proc_meta: node not found: $sender\n"
;
}
if
(
$seq_num
>
$node
->{doc_out_seq})
{
die
"ecs_proc_meta: node requested DOC_RE_SEND of unsent document "
.
"($sender,$seq_num)\n"
;
}
my
$doc_filename
= format_doc_filename(
$sender
,
$seq_num
);
die
"ecs_proc_meta: requested document file not found: $doc_filename\n"
unless
-e
$doc_filename
;
my
$msg
= new EMDIS::ECS::FileBackedMessage(
$doc_filename
);
die
"ecs_proc_meta: unable to load document from file $doc_filename: "
.
"$msg\n"
unless
ref
$msg
;
die
"ecs_proc_meta: found unexpected seq_num "
.
$msg
->seq_num .
", expected $seq_num\n"
unless
$msg
->seq_num ==
$seq_num
;
$err
=
$msg
->send_this_message(
$sender
, 1,
''
);
if
(
$err
){
send_admin_email(
"An error occurred while trying to resend ecs document!"
,
" Email from $sender with sequence number $seq_num "
,
"could not be resent."
);
die
"ecs_proc_meta: error sending email: $err\n"
}
unlink
$filename
;
log_info(
"\nFinished processing $sender DOC_RE_SEND request $seq_num\n"
);
exit
0;
}
if
(
$msg_type
=~ /^MSG_ACK/i)
{
my
$ack_seq
=
''
;
if
(
$message_content
=~ /seq_num\s*=\s*(\d+)/i)
{
$ack_seq
= $1;
}
else
{
die
"ecs_proc_meta: seq_num not specified in MSG_ACK message: "
.
"$filename\n"
;
}
$ECS_NODE_TBL
->
lock
()
or
die
"ecs_proc_meta: unable to lock node_tbl: "
.
$ECS_NODE_TBL
->ERROR .
"\n"
;
$node
=
$ECS_NODE_TBL
->
read
(
$sender
);
if
(
$node
)
{
if
((not
$node
->{ack_seq}) or
$node
->{ack_seq} <
$ack_seq
and
$ack_seq
<=
$node
->{out_seq})
{
$node
->{ack_seq} =
$ack_seq
;
}
$node
->{last_in} =
time
;
$ECS_NODE_TBL
->
write
(
$sender
,
$node
);
}
$ECS_NODE_TBL
->unlock();
if
(not
$node
)
{
$err
= move_to_dir(
$filename
,
$ECS_CFG
->ECS_MBX_TRASH_DIR);
warn
"ecs_proc_meta: $err\n"
if
$err
;
die
"ecs_proc_meta: node not found: $sender\n"
;
}
if
(
$ack_seq
>
$node
->{out_seq})
{
die
"ecs_proc_meta: node acknowledged unsent message "
.
"($sender,$ack_seq)\n"
;
}
unlink
$filename
;
exit
0;
}
if
(
$msg_type
=~ /^DOC_MSG_ACK/i)
{
my
$ack_seq
=
''
;
if
(
$message_content
=~ /seq_num\s*=\s*(\d+)/i)
{
$ack_seq
= $1;
}
else
{
die
"ecs_proc_meta: seq_num not specified in DOC_MSG_ACK message: "
.
"$filename\n"
;
}
$ECS_NODE_TBL
->
lock
()
or
die
"ecs_proc_meta: unable to lock node_tbl: "
.
$ECS_NODE_TBL
->ERROR .
"\n"
;
$node
=
$ECS_NODE_TBL
->
read
(
$sender
);
if
(
$node
)
{
if
((not
$node
->{doc_ack_seq}) or
$node
->{doc_ack_seq} <
$ack_seq
and
$ack_seq
<=
$node
->{doc_out_seq})
{
$node
->{doc_ack_seq} =
$ack_seq
;
}
$node
->{last_in} =
time
;
$ECS_NODE_TBL
->
write
(
$sender
,
$node
);
}
$ECS_NODE_TBL
->unlock();
if
(not
$node
)
{
$err
= move_to_dir(
$filename
,
$ECS_CFG
->ECS_MBX_TRASH_DIR);
warn
"ecs_proc_meta: $err\n"
if
$err
;
die
"ecs_proc_meta: node not found: $sender\n"
;
}
if
(
$ack_seq
>
$node
->{doc_out_seq})
{
die
"ecs_proc_meta: node acknowledged unsent document "
.
"($sender,$ack_seq)\n"
;
}
unlink
$filename
;
exit
0;
}
die
"ecs_proc_meta: unrecognized msg_type: '$msg_type'\n"
;