summaryrefslogtreecommitdiffstats
path: root/brscan-key.pl
blob: 34f0ba83c8cf6cfb7e45d81a8347da29808587ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/perl
use warnings;
use strict;
use threads;

package BRscan::Config;
our $port = 54925;
our $printer = "192.168.4.42";
our $myip = "192.168.4.247";
our $debug = 1;
our $work_dir = "/mnt/levant/nfs/tmp";

package BRscan::Listener;
use IO::Socket;
use feature qw/switch/;
#use Data::Dumper;

sub run {
	my $max_len = 2048;
	our $debug = $BRscan::Config::debug;
	my $msg;
	my @processed;

	my $sock = IO::Socket::INET->new(LocalPort => $BRscan::Config::port, Proto => 'udp') or die "socket: $@";

	while ($sock->recv($msg, $max_len)) {
		my $cport = $sock->peerport();
		my $chost = $sock->peerhost();

		print STDERR "Client $chost:$cport said: $msg\n" if $debug;

		# discard first 4 bytes, probably not relevant
		# TODO: what do they mean?
		$msg = substr($msg, 4);

		my %fields;

		for my $field (split(/;/, $msg)) {
			my ($key, $value) = split(/=/, $field);
			next unless defined($key) and defined($value);

			print STDERR "key: \"$key\"; value:  \"$value\"\n" if $debug;

			$fields{$key} = $value;
		}

		# BR likely stands for "brother". use this to determine if it's really a request from a brother device
		next unless $fields{TYPE} eq "BR";

		# ignore multiple requests
		# TODO: clean up old ids
		my $id = $fields{REGID}."-".$fields{SEQ};
		if ($id ~~ @processed) {
			print STDERR "already processed $id. skipping...\n" if $debug;
			next;
		}

		# we only handle the scan button
		next unless $fields{BUTTON} eq "SCAN";

		print STDERR "got $fields{FUNC} scan request\n" if $debug;

		# possible values: FILE, IMAGE, OCR, EMAIL
		given ($fields{FUNC}) {
			when (/IMAGE/) {
				system("scan-multi");
			}
			when (/FILE/) {
				system("scan-multi --pdf");
			}
		}

		push @processed, $id;
		print STDERR "finished processing $id\n";
	}
}

package BRscan::RegWatcher;
use Net::SNMP;

sub run {
	our $debug = $BRscan::Config::debug;
	my ($session, $error) = Net::SNMP->session(
		-community => "internal", 
		-version => 1, 
		-hostname => $BRscan::Config::printer,
	);

	if (!defined $session) {
		printf STDERR "ERROR: %s.\n", $error;

		exit 1;
	}

	# unhandled are commented out
	my @apps = (
		{appnum => 1, func => "IMAGE"},
		#{appnum => 2, func => "EMAIL"},
		#{appnum => 3, func => "OCR"},
		{appnum => 5, func => "FILE"},
	);

	my @varbindlist;

	for my $app (@apps) {
		push @varbindlist, "1.3.6.1.4.1.2435.2.3.9.2.11.1.1.0";
		push @varbindlist, OCTET_STRING;
		push @varbindlist, "TYPE=BR;BUTTON=SCAN;USER=".$ENV{USER}.";FUNC=".$app->{"func"}.";HOST=".$BRscan::Config::myip.":".$BRscan::Config::port.";APPNUM=".$app->{"appnum"}.";DURATION=360;BRID=;";
	}

	@apps = undef;

	while (1) {
		print STDERR "sending snmp set_request\n" if $debug;

		my $result = $session->set_request(-varbindlist => \@varbindlist);

		if (!defined $result) {
			printf "ERROR in set_request: %s.\n", $session->error();
		}

		sleep 60;
	}
}

package main;
our $debug = $BRscan::Config::debug;

chdir("$BRscan::Config::work_dir");

threads->new("BRscan::Listener::run");
threads->new("BRscan::RegWatcher::run");

# wait for everyone before exiting
foreach my $thr (threads->list) { 
        if ($thr->tid && !threads::equal($thr, threads->self)) { 
                print "waiting for thread ".$thr->tid()." to finish\n" if $debug;
                $thr->join; 
        } 
}

__END__

=head1 NAME

brscan-key.pl - Deamon for brother scanner key

=head1 DESCRIPTION

This daemon registers itself with a brother scanner and accepts incoming scanning requests.

=cut