MainServer.pm
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:5k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. package Bus::Server::MainServer;
  2. use strict;
  3. use warnings;
  4. use Time::HiRes qw(sleep);
  5. use Bus::Server::AbstractServer;
  6. use base qw(Bus::Server::AbstractServer);
  7. use encoding 'utf8';
  8. # Client state constants.
  9. use constant NOT_IDENTIFIED => 1;
  10. use constant IDENTIFIED => 2;
  11. # Special message arguments, generated by the bus server:
  12. # - FROM - The ID of the client who sent the message.
  13. #
  14. # Special message arguments, generated by the client:
  15. # - TO - The ID of the client who is to receive this message.
  16. #        If specified, it indicates that this message is a private message.
  17. #        If not specified, then this is a global message, and will be
  18. #        broadcasted to all clients.
  19. # - SEQ - A sequence number, used to map reply messages to the original
  20. #         query message. Reply messages MUST have the same SEQ.
  21. # - IRY - Specifies that this message is a reply to a query.
  22. sub new {
  23. my $class = shift;
  24. my $port = shift;
  25. my $bind = shift;
  26. my %args = @_;
  27. my $self = $class->SUPER::new($port, $bind);
  28. $self->{quiet} = $args{quiet};
  29. return $self;
  30. }
  31. sub log {
  32. my ($self, $message) = @_;
  33. print $message if (!$self->{quiet});
  34. }
  35. # New client connected to network
  36. sub onClientNew {
  37. my ($self, $client, $index) = @_;
  38. $self->SUPER::onClientNew($client, $index);
  39. # Initiate handshake.
  40. $self->log("New client connected: $client->{ID}n");
  41. $self->send($client->{ID}, "HELLO", { yourID => $client->{ID} });
  42. $client->{userAgent} = "Unknown";
  43. $client->{name}      = "Unknown:$client->{ID}";
  44. $client->{state}     = NOT_IDENTIFIED;
  45. }
  46. # A client disconnected.
  47. sub onClientExit {
  48. my ($self, $client) = @_;
  49. $self->SUPER::onClientExit($client);
  50. $self->log("Client exited: $client->{ID}n");
  51. if ($client->{state} == IDENTIFIED) {
  52. $self->broadcast('LEAVE', { clientID  => $client->{ID} });
  53. }
  54. }
  55. # A client sent a message
  56. sub messageReceived {
  57. my ($self, $client, $MID, $args) = @_;
  58. $self->log("Message: $MID (from $client->{name})n");
  59. # Process known messages internally.
  60. # Deliver unknown messages to client(s).
  61. if (my $handler = $self->can("process$MID")) {
  62. $handler->($self, $client, $args);
  63. } elsif (exists $args->{TO}) {
  64. # Deliver private message.
  65. my $recepient = $self->getBusClient($args->{TO});
  66. if ($recepient) {
  67. my $recepientName = $recepient->{name};
  68. print "Delivering message from $client->{name} to $recepientNamen";
  69. $args->{FROM} = $client->{ID};
  70. if ($self->send($args->{TO}, $MID, $args) != 1) {
  71. # Delivery failed for some reason. Notify the client.
  72. my %args2 = ( clientID => $args->{TO} );
  73. $args2{SEQ} = $args->{SEQ} if (exists $args->{SEQ});
  74. $args2{IRY} = 1;
  75. $self->send($client->{ID}, 'DELIVERY_FAILED', %args2);
  76. }
  77. } else {
  78. # Unable to deliver the message because the specified client doesn't exist.
  79. # Notify the sender.
  80. my %args2 = ( clientID => $args->{TO} );
  81. $args2{SEQ} = $args->{SEQ} if (exists $args->{SEQ});
  82. $args2{IRY} = 1;
  83. $self->send($client->{ID}, 'CLIENT_NOT_FOUND', %args2);
  84. }
  85. } else {
  86. # Broadcast global message.
  87. $args->{FROM} = $client->{ID};
  88. $self->broadcast($MID, $args, { exclude => $client->{ID} });
  89. }
  90. }
  91. # broadcast(String messageID, args, Hash* options)
  92. #
  93. # Broadcast a message to all clients on the bus, except:
  94. # - Clients which are in the NOT_IDENTIFIED state.
  95. # - Clients which have privateOnly turned on.
  96. # - The client with the ID as specified in the 'exclude' option.
  97. #
  98. # Allowed options:
  99. # - exclude - The ID of a client, for which this message will not be sent to.
  100. sub broadcast {
  101. my ($self, $MID, $args, $options) = @_;
  102. foreach my $client (@{$self->clients()}) {
  103. if ($client->{state} != NOT_IDENTIFIED
  104. && !$client->{privateOnly}
  105. && (!defined $options->{exclude} || $client->{ID} ne $options->{exclude})) {
  106. $self->send($client->{ID}, $MID, $args);
  107. }
  108. }
  109. }
  110. ########### Internal message processors ###########
  111. sub processHELLO {
  112. my ($self, $client, $args) = @_;
  113. if (ref($args) ne 'HASH') {
  114. # Arguments must be a hash.
  115. $self->log("Client $client->{ID} didn't sent HELLO arguments as map.");
  116. $client->close();
  117. } elsif ($client->{state} == NOT_IDENTIFIED) {
  118. # A new client just connected.
  119. $client->{userAgent}   = $args->{userAgent} || "Unknown";
  120. $client->{privateOnly} = $args->{privateOnly};
  121. $client->{name}        = $args->{userAgent} . ":" . $client->{ID};
  122. $client->{state}       = IDENTIFIED;
  123. # Broadcast a JOIN message about this client.
  124. $self->log("Client identified as $client->{name}; broadcasting JOINn");
  125. my %args = (
  126. clientID  => $client->{ID},
  127. name      => $client->{name},
  128. userAgent => $client->{userAgent},
  129. host      => $client->getIP()
  130. );
  131. $self->broadcast("JOIN", %args, { exclude => $client->{ID} });
  132. } else {
  133. # The client sent HELLO even though it has already done that.
  134. $self->log("Client $client->{ID} sent invalid HELLO.n");
  135. $client->close();
  136. }
  137. }
  138. sub processLIST_CLIENTS {
  139. my ($self, $client, $args) = @_;
  140. if (ref($args) ne 'HASH') {
  141. # Arguments must be a hash.
  142. $self->log("Client $client->{ID} didn't sent LIST_CLIENTS arguments as map.");
  143. $client->close();
  144. } else {
  145. my %args2;
  146. my $i = 0;
  147. foreach my $client (@{$self->clients()}) {
  148. if ($client->{state} == IDENTIFIED) {
  149. $args2{"client$i"} = $client->{ID};
  150. $args2{"clientUserAgent$i"} = $client->{userAgent};
  151. $i++;
  152. }
  153. }
  154. $args2{count} = $i;
  155. $args2{SEQ} = $args->{SEQ} if (exists $args->{SEQ});
  156. $args2{IRY} = 1;
  157. $self->send($client->{ID}, "LIST_CLIENTS", %args2);
  158. }
  159. }
  160. 1;