File: | blib/lib/FUSE/Server.pm |
Coverage: | 9.2% |
line | stmt | bran | cond | sub | time | code |
---|---|---|---|---|---|---|
1 | package FUSE::Server; | |||||
2 | ||||||
3 | require 5; | |||||
4 | 1 1 1 | 8 3 8 | use strict; | |||
5 | ||||||
6 | 1 1 1 | 9 3 9 | use vars qw($VERSION @ISA @EXPORT); | |||
7 | ||||||
8 | 1 1 1 | 13 4 7 | use IO::Socket; | |||
9 | 1 1 1 | 13 4 16 | use IO::Select; | |||
10 | ||||||
11 | require Exporter; | |||||
12 | ||||||
13 | @ISA = qw(Exporter); | |||||
14 | @EXPORT = qw(); | |||||
15 | $VERSION = '1.19'; | |||||
16 | ||||||
17 | my $nextid = 0; | |||||
18 | ||||||
19 | sub new { | |||||
20 | 0 | my ($class,$params) = @_; | ||||
21 | 0 | my $self = {}; | ||||
22 | 0 | bless $self,ref $class || $class; | ||||
23 | 0 0 | $self->{quiet} = ${$params}{Quiet}; | ||||
24 | 0 0 | $self->{port} = ${$params}{Port} || 1024; | ||||
25 | 0 0 | $self->{maxc} = ${$params}{MaxClients} || SOMAXCONN; | ||||
26 | 0 | $self->{max_msglen} = 1024; | ||||
27 | 0 | $self->{server_sock} = 0; | ||||
28 | 0 | $self->{sel} = 0; | ||||
29 | 0 | $self->{users} = {}; | ||||
30 | 0 | return $self; | ||||
31 | } | |||||
32 | ||||||
33 | sub bind { | |||||
34 | 0 | my ($self) = @_; | ||||
35 | ||||||
36 | 0 | $self->{server_sock} = IO::Socket::INET->new(Proto=>"tcp", LocalPort=>$self->{port}, Listen=>$self->{maxc}, Reuse=>1); | ||||
37 | 0 | $self->{sel} = IO::Select->new($self->{server_sock}); | ||||
38 | ||||||
39 | 0 | return $self->{server_sock}->sockhost(); | ||||
40 | } | |||||
41 | ||||||
42 | sub start { | |||||
43 | 0 | my ($self) = @_; | ||||
44 | ||||||
45 | 0 | while (my @ready = $self->{sel}->can_read) { | ||||
46 | ||||||
47 | 0 | foreach my $client (@ready) { | ||||
48 | ||||||
49 | 0 | if ($client == $self->{server_sock}) { | ||||
50 | ||||||
51 | 0 | my $add = $client->accept; | ||||
52 | 0 | $add->blocking(0); | ||||
53 | 0 | $self->{sel}->add($add); | ||||
54 | 0 | $self->newsession($add); | ||||
55 | }else{ | |||||
56 | ||||||
57 | 0 | my ($in,$msg,$nread,$nsafe); | ||||
58 | ||||||
59 | 0 | do { | ||||
60 | 0 | $nread = sysread($client, $in, 1024); | ||||
61 | 0 | $msg .= $in; | ||||
62 | 0 | $nsafe = 0; | ||||
63 | 0 | if (defined($nread)){ | ||||
64 | 0 | $nsafe = $nread; | ||||
65 | } | |||||
66 | } while ($nsafe == 1024); | |||||
67 | ||||||
68 | 0 | if (defined($nread)) { | ||||
69 | 0 | if ($nread == 0){ | ||||
70 | 0 | $self->{sel}->remove($client); | ||||
71 | 0 | $self->endsession($client); | ||||
72 | 0 | close($client); | ||||
73 | } | |||||
74 | } | |||||
75 | ||||||
76 | 0 | if (defined($msg)){ | ||||
77 | 0 | if ($msg){ | ||||
78 | 0 | $self->incoming($client, $msg); | ||||
79 | } | |||||
80 | } | |||||
81 | } | |||||
82 | } | |||||
83 | } | |||||
84 | } | |||||
85 | ||||||
86 | sub stop{ | |||||
87 | 0 | my ($self) = @_; | ||||
88 | ||||||
89 | 0 | close($self->{server_sock}); | ||||
90 | } | |||||
91 | ||||||
92 | sub addCallback{ | |||||
93 | 0 | my ($self,$msg,$coderef) = @_; | ||||
94 | 0 | $self->{callbacks}{$msg} = $coderef; | ||||
95 | } | |||||
96 | ||||||
97 | sub defaultCallback{ | |||||
98 | 0 | my ($self,$coderef) = @_; | ||||
99 | 0 | $self->{def_callback} = $coderef; | ||||
100 | } | |||||
101 | ||||||
102 | sub send{ | |||||
103 | 0 | my ($self,$uid,$msg,$params) = @_; | ||||
104 | ||||||
105 | 0 0 | for (keys %{$self->{users}}){ | ||||
106 | 0 | if ($self->{users}{$_}{id} == $uid){ | ||||
107 | 0 | my $sock = $self->{users}{$_}{sock}; | ||||
108 | 0 | print $sock "# $msg\cM"; | ||||
109 | 0 | print $sock "$params\cM"; | ||||
110 | 0 | print $sock "##\cM\cJ"; | ||||
111 | 0 | last; | ||||
112 | } | |||||
113 | } | |||||
114 | } | |||||
115 | ||||||
116 | sub sendAll{ | |||||
117 | 0 | my ($self,$msg,$params) = @_; | ||||
118 | 0 0 | for (keys %{$self->{users}}){ | ||||
119 | 0 | $self->send($self->{users}{$_}{id},$msg,$params); | ||||
120 | } | |||||
121 | } | |||||
122 | ||||||
123 | ||||||
124 | ########## | |||||
125 | ||||||
126 | sub newsession { | |||||
127 | 0 | my ($self,$sock) = @_; | ||||
128 | 0 | $nextid++; | ||||
129 | 0 | $self->{users}{$sock}{sock} = $sock; | ||||
130 | 0 | $self->{users}{$sock}{host} = $sock->peerhost; | ||||
131 | 0 | $self->{users}{$sock}{id} = $nextid; | ||||
132 | 0 | $self->{users}{$sock}{buffer} = ''; | ||||
133 | ||||||
134 | 0 | unless ($self->{quiet}){ | ||||
135 | 0 | print "new connection: "; | ||||
136 | 0 | print $self->{users}{$sock}{id}; | ||||
137 | 0 | print " ("; | ||||
138 | 0 | print $self->{users}{$sock}{host}; | ||||
139 | 0 | print ")\n"; | ||||
140 | } | |||||
141 | ||||||
142 | 0 | $self->packet($sock, 'client_start', ''); | ||||
143 | } | |||||
144 | ||||||
145 | sub endsession { | |||||
146 | 0 | my ($self,$sock) = @_; | ||||
147 | ||||||
148 | 0 | unless ($self->{quiet}){ | ||||
149 | 0 | print "connection closed: "; | ||||
150 | 0 | print $self->{users}{$sock}{id}; | ||||
151 | 0 | print "\n"; | ||||
152 | } | |||||
153 | ||||||
154 | 0 | $self->packet($sock, 'client_stop', ''); | ||||
155 | ||||||
156 | 0 | delete $self->{users}{$sock}; | ||||
157 | } | |||||
158 | ||||||
159 | sub incoming{ | |||||
160 | 0 | my ($self,$sock,$data) = @_; | ||||
161 | ||||||
162 | 0 | my $id = $self->{users}{$sock}{id}; | ||||
163 | 0 | $self->{users}{$sock}{buffer} .= $data; | ||||
164 | ||||||
165 | 0 | my $ok = 1; | ||||
166 | 0 | my $buffer = $self->{users}{$sock}{buffer}; | ||||
167 | 0 | while ($ok){ | ||||
168 | 0 | $ok = 0; | ||||
169 | 0 | if (length($buffer) > 4){ | ||||
170 | 0 | my $size = substr($buffer,0,4); | ||||
171 | 0 | $size =~ s/[^0-9]//g; | ||||
172 | 0 | $size += 0; | ||||
173 | 0 | if (length($buffer) >= 4 + $size){ | ||||
174 | 0 | my $packet = substr($buffer,4,$size); | ||||
175 | 0 | my $a = index($packet,' '); | ||||
176 | 0 | my $msg = substr($packet,0,$a); | ||||
177 | 0 | my $param = substr($packet,$a+1); | ||||
178 | 0 | $self->packet($sock,$msg,$param); | ||||
179 | 0 | $buffer = substr($buffer,4+$size); | ||||
180 | 0 | $ok=1; | ||||
181 | } | |||||
182 | } | |||||
183 | } | |||||
184 | 0 | $self->{users}{$sock}{buffer} = $buffer; | ||||
185 | } | |||||
186 | ||||||
187 | sub packet { | |||||
188 | 0 | my ($self,$sock,$msg,$params) = @_; | ||||
189 | ||||||
190 | 0 | my $uid = $self->{users}{$sock}{id}; | ||||
191 | ||||||
192 | 0 | unless($self->{quiet}){ | ||||
193 | 0 | print "packet sent to $uid: $msg\n"; | ||||
194 | } | |||||
195 | ||||||
196 | 0 | if ($self->{callbacks}{$msg}){ | ||||
197 | 0 0 | &{$self->{callbacks}{$msg}}($uid,$msg,$params); | ||||
198 | }else{ | |||||
199 | 0 | if ($self->{def_callback}){ | ||||
200 | 0 0 | &{$self->{def_callback}}($uid,$msg,$params); | ||||
201 | } | |||||
202 | } | |||||
203 | } | |||||
204 | ||||||
205 | ||||||
206 | 1; |