Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
6.2 KiB

  1. # ======================================================================
  2. #
  3. # Copyright (C) 2000-2001 Paul Kulchenko ([email protected])
  4. # SOAP::Lite is free software; you can redistribute it
  5. # and/or modify it under the same terms as Perl itself.
  6. #
  7. # $Id: SOAP::Transport::TCP.pm,v 0.51 2001/07/18 15:15:14 $
  8. #
  9. # ======================================================================
  10. package SOAP::Transport::TCP;
  11. use strict;
  12. use vars qw($VERSION);
  13. $VERSION = '0.51';
  14. use URI;
  15. use IO::Socket;
  16. use IO::Select;
  17. use IO::SessionData;
  18. use SOAP::Lite;
  19. # ======================================================================
  20. package URI::tcp; # ok, lets do 'tcp://' scheme
  21. require URI::_server;
  22. @URI::tcp::ISA=qw(URI::_server);
  23. # ======================================================================
  24. package SOAP::Transport::TCP::Client;
  25. use vars qw(@ISA);
  26. @ISA = qw(SOAP::Client);
  27. sub DESTROY { SOAP::Trace::objects('()') }
  28. sub new {
  29. my $self = shift;
  30. unless (ref $self) {
  31. my $class = ref($self) || $self;
  32. my(@params, @methods);
  33. while (@_) { $class->can($_[0]) ? push(@methods, shift() => shift) : push(@params, shift) }
  34. $self = bless {@params} => $class;
  35. while (@methods) { my($method, $params) = splice(@methods,0,2);
  36. $self->$method(ref $params eq 'ARRAY' ? @$params : $params)
  37. }
  38. # use SSL if there is any parameter with SSL_* in the name
  39. $self->SSL(1) if !$self->SSL && grep /^SSL_/, keys %$self;
  40. SOAP::Trace::objects('()');
  41. }
  42. return $self;
  43. }
  44. sub SSL {
  45. my $self = shift->new;
  46. @_ ? ($self->{_SSL} = shift, return $self) : return $self->{_SSL};
  47. }
  48. sub io_socket_class { shift->SSL ? 'IO::Socket::SSL' : 'IO::Socket::INET' }
  49. sub syswrite {
  50. my($self, $sock, $data) = @_;
  51. my $timeout = $sock->timeout;
  52. my $select = IO::Select->new($sock);
  53. my $len = length $data;
  54. while (length $data > 0) {
  55. return unless $select->can_write($timeout);
  56. local $SIG{PIPE} = 'IGNORE';
  57. my $wc = syswrite($sock, $data);
  58. if (defined $wc) {
  59. substr($data, 0, $wc) = '';
  60. } elsif (!IO::SessionData::WOULDBLOCK($!)) {
  61. return;
  62. }
  63. }
  64. return $len;
  65. }
  66. sub sysread {
  67. my($self, $sock) = @_;
  68. my $timeout = $sock->timeout;
  69. my $select = IO::Select->new($sock);
  70. my $result = '';
  71. my $data;
  72. while (1) {
  73. return unless $select->can_read($timeout);
  74. my $rc = sysread($sock, $data, 4096);
  75. if ($rc) {
  76. $result .= $data;
  77. } elsif (defined $rc) {
  78. return $result;
  79. } elsif (!IO::SessionData::WOULDBLOCK($!)) {
  80. return;
  81. }
  82. }
  83. }
  84. sub send_receive {
  85. my($self, %parameters) = @_;
  86. my($envelope, $endpoint, $action) =
  87. @parameters{qw(envelope endpoint action)};
  88. $endpoint ||= $self->endpoint;
  89. warn "URLs with 'tcp:' scheme are deprecated. Use 'tcp://'. Still continue\n"
  90. if $endpoint =~ s!^tcp:(//)?!tcp://!i && !$1;
  91. my $uri = URI->new($endpoint);
  92. local($^W, $@, $!);
  93. my $sock = $self->io_socket_class->new (
  94. PeerAddr => $uri->host, PeerPort => $uri->port, Proto => $uri->scheme, %$self
  95. );
  96. SOAP::Trace::debug($envelope);
  97. my $result;
  98. if ($sock) {
  99. $sock->blocking(0);
  100. $self->syswrite($sock, $envelope) and
  101. $sock->shutdown(1) and # stop writing
  102. $result = $self->sysread($sock);
  103. }
  104. SOAP::Trace::debug($result);
  105. my $code = $@ || $!;
  106. $self->code($code);
  107. $self->message($code);
  108. $self->is_success(!defined $code || $code eq '');
  109. $self->status($code);
  110. return $result;
  111. }
  112. # ======================================================================
  113. package SOAP::Transport::TCP::Server;
  114. use IO::SessionSet;
  115. use Carp ();
  116. use vars qw($AUTOLOAD @ISA);
  117. @ISA = qw(SOAP::Server);
  118. sub DESTROY { SOAP::Trace::objects('()') }
  119. sub new {
  120. my $self = shift;
  121. unless (ref $self) {
  122. my $class = ref($self) || $self;
  123. my(@params, @methods);
  124. while (@_) { $class->can($_[0]) ? push(@methods, shift() => shift) : push(@params, shift) }
  125. $self = $class->SUPER::new(@methods);
  126. # use SSL if there is any parameter with SSL_* in the name
  127. $self->SSL(1) if !$self->SSL && grep /^SSL_/, @params;
  128. my $socket = $self->io_socket_class;
  129. eval "require $socket" or Carp::croak $@ unless UNIVERSAL::can($socket => 'new');
  130. $self->{_socket} = $socket->new(Proto => 'tcp', @params)
  131. or Carp::croak "Can't open socket: $!";
  132. SOAP::Trace::objects('()');
  133. }
  134. return $self;
  135. }
  136. sub SSL {
  137. my $self = shift->new;
  138. @_ ? ($self->{_SSL} = shift, return $self) : return $self->{_SSL};
  139. }
  140. sub io_socket_class { shift->SSL ? 'IO::Socket::SSL' : 'IO::Socket::INET' }
  141. sub AUTOLOAD {
  142. my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2);
  143. return if $method eq 'DESTROY';
  144. no strict 'refs';
  145. *$AUTOLOAD = sub { shift->{_socket}->$method(@_) };
  146. goto &$AUTOLOAD;
  147. }
  148. sub handle {
  149. my $self = shift->new;
  150. my $sock = $self->{_socket};
  151. my $session_set = IO::SessionSet->new($sock);
  152. my %data;
  153. while (1) {
  154. my @ready = $session_set->wait($sock->timeout);
  155. for my $session (@ready) {
  156. my $data;
  157. if (my $rc = $session->read($data, 4096)) {
  158. $data{$session} .= $data if $rc > 0;
  159. } else {
  160. $session->write($self->SUPER::handle(delete $data{$session}));
  161. $session->close;
  162. }
  163. }
  164. }
  165. }
  166. # ======================================================================
  167. 1;
  168. __END__
  169. =head1 NAME
  170. SOAP::Transport::TCP - Server/Client side TCP support for SOAP::Lite
  171. =head1 SYNOPSIS
  172. use SOAP::Transport::TCP;
  173. my $daemon = SOAP::Transport::TCP::Server
  174. -> new (LocalAddr => 'localhost', LocalPort => 82, Listen => 5, Reuse => 1)
  175. -> objects_by_reference(qw(My::PersistentIterator My::SessionIterator My::Chat))
  176. -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
  177. ;
  178. print "Contact to SOAP server at ", join(':', $daemon->sockhost, $daemon->sockport), "\n";
  179. $daemon->handle;
  180. =head1 DESCRIPTION
  181. =head1 COPYRIGHT
  182. Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.
  183. This library is free software; you can redistribute it and/or modify
  184. it under the same terms as Perl itself.
  185. =head1 AUTHOR
  186. Paul Kulchenko (paulclinger@yahoo.com)
  187. =cut