File Coverage

lib/Data/Send/Local.pm
Criterion Covered Total %
statement 49 60 81.6
branch 14 34 41.1
condition 1 4 25.0
subroutine 10 11 90.9
pod 2 4 50.0
total 76 113 67.2


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             #-------------------------------------------------------------------------------
3             # Send a block of data from one process to another on the local machine
4             # Philip R Brenan at gmail dot com, Appa Apps Ltd Inc, 2016-2017
5             #-------------------------------------------------------------------------------
6              
7             package Data::Send::Local;
8             our $VERSION = 20180405;
9 2     2   746 use v5.8.0;
  2         14  
10 2     2   8 use warnings FATAL => qw(all);
  2         2  
  2         48  
11 2     2   6 use strict;
  2         2  
  2         56  
12 2     2   10 use Carp qw(confess);
  2         2  
  2         126  
13 2     2   838 use Data::Dump qw(dump);
  2         11488  
  2         92  
14 2     2   1364 use Data::Table::Text qw(:all);
  2         98382  
  2         724  
15 2     2   1074 use Socket;
  2         5342  
  2         1350  
16              
17             #1 Send and receive
18              
19             sub sendLocal($$;$) #S Send a block of data locally. Returns B on success otherwise an error message
20 1     1 1 28 {my ($socketName, $data, $timeOut) = @_; # Socket name (a socket file name that already exists), data, optional timeout for socket to be created - defaults to 10 seconds
21              
22 1 50       63 if (!-S $socketName) # Wait for a bit if necessary for the socket to be created
23 0 0 0     0 {for(1..($timeOut//10)) {sleep 1; last if -S $socketName}
  0         0  
  0         0  
24             }
25 1 50       18 -S $socketName or return "No such socket: $socketName"; # Socket not available
26              
27 1 50       171 socket(my $socket, AF_UNIX, SOCK_DGRAM, 0) or return $!;
28 1 50       86 connect($socket, sockaddr_un($socketName)) or return $!;
29 1 50       79 send($socket, dump($data), 0) or return $!;
30 1         394 close($socket);
31              
32             undef # Return without errors
33 1         28 }
34              
35             sub recvLocal($;$$) #S Receive a block of data sent locally. Returns the data received.
36 1     1 1 23 {my ($socketName, $user, $length) = @_; # Socket name (a socket file name that is created), optional username of the owner of the socket, maximum length to receive - defaults to one megabyte.
37              
38 1         32 unlink $socketName; # Remove existing socket to avoid 'already in use';
39 1         45 makePath($socketName); # Create socket directory
40 1 50       179 socket(my $socket, AF_UNIX, SOCK_DGRAM, 0) or confess $!;
41 1 50       33 bind($socket, sockaddr_un($socketName)) or confess $!;
42              
43 1 50       413 if ($user) # Do this to make the socket writable by some one else
44 0         0 {qx(chown $user:$user $socketName);
45             }
46              
47 1   50     532 recv($socket, my $read, $length // 1e6, 0);
48 1         24 close($socket);
49 1         49 unlink $socketName; # Remove existing socket to force send to wait while the socket is created
50              
51 1         179 my $r = eval $read; # Reconstitute data
52 1 50       5 $@ and confess $@; # Bad data block
53              
54 1         29 $r # Return data
55             }
56              
57             #-------------------------------------------------------------------------------
58             # Tests
59             #-------------------------------------------------------------------------------
60              
61             sub test2()
62 2     2 0 14 {my $socket = 'socket'; # Socket name
63 2         4 my $data = 'hello'; # Data
64 2         22 autoflush STDOUT 1;
65              
66 2 50       102 if ($^O !~ m/\AMSWin32\Z/) # Ignore windows
67 2         18 {say STDOUT "1..2";
68 2 100       2074 if (fork())
69 1 50       55 {say STDOUT "ok" if Data::Send::Local::recvLocal($socket) eq $data; # Receive data
70             }
71             else
72 1         98 {autoflush STDOUT 1;
73 1 50       215 say STDOUT "ok" unless Data::Send::Local::sendLocal($socket, $data); # Send data without error
74             }
75             }
76             }
77              
78             test2 unless caller;
79              
80             # podDocumentation
81              
82             =pod
83              
84             =encoding utf-8
85              
86             =head1 Name
87              
88             Data::Send::Local - Send and receive a block of data between processes on the
89             local machine.
90              
91             =head1 Synopsis
92              
93             Send B between two processes running on the same machine over the
94             socket named B.
95              
96             use Test2::Bundle::More;
97              
98             my $socket = 'socket'; # Socket name
99             my $data = 'hello'; # Data
100              
101             if (fork())
102             {ok Data::Send::Local::recvLocal($socket) eq $data; # Receive data
103             }
104             else
105             {ok !Data::Send::Local::sendLocal($socket, $data); # Send data without error
106             }
107              
108             done_testing;
109              
110             =head1 Description
111              
112             The following sections describe the methods in each functional area of this
113             module. For an alphabetic listing of all methods by name see L.
114              
115              
116              
117             =head1 Send and receive
118              
119             =head2 sendLocal($$$)
120              
121             Send a block of data locally. Returns B on success otherwise an error message
122              
123             1 $socketName Socket name (a socket file name that already exists)
124             2 $data Data
125             3 $timeOut Optional timeout for socket to be created - defaults to 10 seconds
126              
127             This is a static method and so should be invoked as:
128              
129             Data::Send::Local::sendLocal
130              
131              
132             =head2 recvLocal($$)
133              
134             Receive a block of data sent locally. Returns the data received.
135              
136             1 $socketName Socket name (a socket file name that is created)
137             2 $length Optional maximum length to receive - defaults to one megabyte.
138              
139             This is a static method and so should be invoked as:
140              
141             Data::Send::Local::recvLocal
142              
143              
144              
145             =head1 Index
146              
147              
148             1 L
149              
150             2 L
151              
152             =head1 Installation
153              
154             This module is written in 100% Pure Perl and, thus, it is easy to read, use,
155             modify and install.
156              
157             Standard L process for building and installing modules:
158              
159             perl Build.PL
160             ./Build
161             ./Build test
162             ./Build install
163              
164             =head1 Author
165              
166             L
167              
168             L
169              
170             =head1 Copyright
171              
172             Copyright (c) 2016-2017 Philip R Brenan.
173              
174             This module is free software. It may be used, redistributed and/or modified
175             under the same terms as Perl itself.
176              
177             =cut
178              
179              
180              
181             # Tests and documentation
182              
183             sub test
184 0     0 0   {my $p = __PACKAGE__;
185 0           binmode($_, ":utf8") for *STDOUT, *STDERR;
186 0 0         return if eval "eof(${p}::DATA)";
187 0           my $s = eval "join('', <${p}::DATA>)";
188 0 0         $@ and die $@;
189 0           eval $s;
190 0 0         $@ and die $@;
191             }
192              
193             test unless caller;
194              
195             1;
196             __DATA__