patternMinor
Terminal Chat Room
Viewed 0 times
chatterminalroom
Problem
Summary
I have written a pair of Perl scripts that form a UDP chat room allowing users to send messages over the internet with RSA encryption, making the messages imune to MITM attacks. The scripts include a server script and a client script, and works as would be expected with the clients connecting to the server with a user specified address and port number. As many clients can connect to one server as the server can keep in one hash. Once connected, each client is given a randomly generated nickname whick can be changed later. Users can interact by simply sending plaintext messages, or they can use the built-in commands.
This program is an updated version of the one found here. Since this version I have added many updates including:
Usage
perl server.pl -p 1337
perl client.pl -h localhost -p 1337
Built-in commands
Once connected, a public key exchange takes place and if it is successful the server adds you and your public key to the hash of users. Once connected, you can interact by sending plain text messages, or by using some of the built-in commands. These commands include:
/users - Lists all users currently connected to the server.
/exit - Allows for clean disconnect by removing client from server-side database.
/nick [name] - Changes the current users nickname (visible to all users) to [name]
/whisper [name] [message] - Send a message so it is only visible to one user
server.pl
```
#!/usr/bin/perl
# server.pl
use strict;
use warnings;
use IO::Socket::INET;
use Getopt::Long;
use Crypt::OpenSSL::RSA;
use Try::Tiny;
sub server_log {
print " [", scalar localtime, "] ", join(" ", @_), "\n";
}
sub main {
my %clients;
my %clients_by_nick;
my $MAXLEN = 1024;
my $PORTNO;
my $message;
my @nick_cha
I have written a pair of Perl scripts that form a UDP chat room allowing users to send messages over the internet with RSA encryption, making the messages imune to MITM attacks. The scripts include a server script and a client script, and works as would be expected with the clients connecting to the server with a user specified address and port number. As many clients can connect to one server as the server can keep in one hash. Once connected, each client is given a randomly generated nickname whick can be changed later. Users can interact by simply sending plaintext messages, or they can use the built-in commands.
This program is an updated version of the one found here. Since this version I have added many updates including:
- Cleanly handle users disconnecting
- 1024-bit RSA encryption of all messages
- Various built-in commands (listed below)
- Removed redundancies and tidied up code
- Unique nicknames for all clients
- Non-fatal error handling
Usage
perl server.pl -p 1337
perl client.pl -h localhost -p 1337
Built-in commands
Once connected, a public key exchange takes place and if it is successful the server adds you and your public key to the hash of users. Once connected, you can interact by sending plain text messages, or by using some of the built-in commands. These commands include:
/users - Lists all users currently connected to the server.
/exit - Allows for clean disconnect by removing client from server-side database.
/nick [name] - Changes the current users nickname (visible to all users) to [name]
/whisper [name] [message] - Send a message so it is only visible to one user
server.pl
```
#!/usr/bin/perl
# server.pl
use strict;
use warnings;
use IO::Socket::INET;
use Getopt::Long;
use Crypt::OpenSSL::RSA;
use Try::Tiny;
sub server_log {
print " [", scalar localtime, "] ", join(" ", @_), "\n";
}
sub main {
my %clients;
my %clients_by_nick;
my $MAXLEN = 1024;
my $PORTNO;
my $message;
my @nick_cha
Solution
After a quick glance, I think there are a few things you can improve. This is by far not a complete list.
Are there any redundancies I can remove?
Am I using any bad Perl practices here?
-
You should not explicitly use
-
You are also escaping
Instead, use
-
In the same example as above, you are using the ampersand
-
You have
If you add
I am not sure why in your case it works without breaking. I believe it should break.
How can I make my code look less messy?
See above. Besides that, a dispatch table instead of the huge
Are there any redundancies I can remove?
- There are no real redundancies that I can see, but I think the code would benefit greatly from using a bunch of subs instead of this huge
mainthing.
Am I using any bad Perl practices here?
-
You should not explicitly use
$_. Either indent the code better and just put the expression in directly, or use a different variable. I prefer this.$sock->send(
$client->{pub_key}->encrypt($message),
0,
$client->{address}
) or die "send: $!";-
You are also escaping
/ in your regular expression in this code:if($_ =~ /\/exit/) {
&terminate;
}Instead, use
m// explicitly, and use a different quote delimiter. Pick one of below, or any other you like. There is also no need to mention $_ here, as it will implicitly match on $_ anyway.m!/!;
m|/|;
m{/};
m(/);
m m/m; # don't do that one!-
In the same example as above, you are using the ampersand
& to call your function. That tells Perl to ignore prototypes on the sub. Since you don't have any, you don't need it. Even if you had them, you'd probably not want it either. Don't use that. You can do terminate() to make it more readable (though the parens are optional).-
You have
$main::sock and others, that are neither declared with my nor our. I have not run your code, but that looks wrong. I think you want to make package variables, which would be done with our. But since there is no package defined, everything is in the main package anyway, so you don't really need $main::foo or $::foo. It's the same as $foo.$ perl -E '$foo=1; say $main::foo;'
1If you add
use strict; to that, it will fail.$ perl -wE 'use strict; $foo=1; say $main::foo;'
Global symbol "$foo" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.I am not sure why in your case it works without breaking. I believe it should break.
How can I make my code look less messy?
See above. Besides that, a dispatch table instead of the huge
if/elseif/else block would be nice. Take a look at Higher Order Perl by Mark Jason Dominus, it's available as a free pdf file nowadays. There is a whole chapter about those.Code Snippets
$sock->send(
$client->{pub_key}->encrypt($message),
0,
$client->{address}
) or die "send: $!";if($_ =~ /\/exit/) {
&terminate;
}m!/!;
m|/|;
m{/};
m(/);
m m/m; # don't do that one!$ perl -E '$foo=1; say $main::foo;'
1$ perl -wE 'use strict; $foo=1; say $main::foo;'
Global symbol "$foo" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.Context
StackExchange Code Review Q#122323, answer score: 6
Revisions (0)
No revisions yet.