PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/linkedfs/usr/lib/perl5/vendor_perl/5.8.4/Net/Jabber/Client.pm

https://bitbucket.org/harakiri/trk
Perl | 517 lines | 359 code | 95 blank | 63 comment | 57 complexity | 26a1fefd185e479b32eb059b0fa5e804 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-3.0
  1. ##############################################################################
  2. #
  3. # This library is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU Library General Public
  5. # License as published by the Free Software Foundation; either
  6. # version 2 of the License, or (at your option) any later version.
  7. #
  8. # This library is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. # Library General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU Library General Public
  14. # License along with this library; if not, write to the
  15. # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16. # Boston, MA 02111-1307, USA.
  17. #
  18. # Jabber
  19. # Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
  20. #
  21. ##############################################################################
  22. package Net::Jabber::Client;
  23. =head1 NAME
  24. Net::Jabber::Client - Jabber Client Library
  25. =head1 SYNOPSIS
  26. Net::Jabber::Client is a module that provides a developer easy access
  27. to the Jabber Instant Messaging protocol.
  28. =head1 DESCRIPTION
  29. Client.pm uses Protocol.pm to provide enough high level APIs and
  30. automation of the low level APIs that writing a Jabber Client in
  31. Perl is trivial. For those that wish to work with the low level
  32. you can do that too, but those functions are covered in the
  33. documentation for each module.
  34. Net::Jabber::Client provides functions to connect to a Jabber server,
  35. login, send and receive messages, set personal information, create
  36. a new user account, manage the roster, and disconnect. You can use
  37. all or none of the functions, there is no requirement.
  38. For more information on how the details for how Net::Jabber is written
  39. please see the help for Net::Jabber itself.
  40. For a full list of high level functions available please see
  41. Net::Jabber::Protocol.
  42. =head2 Basic Functions
  43. use Net::Jabber qw(Client);
  44. $Con = new Net::Jabber::Client();
  45. $Con->Connect(hostname=>"jabber.org");
  46. if ($Con->Connected()) {
  47. print "We are connected to the server...\n";
  48. }
  49. $status = $Con->Process();
  50. $status = $Con->Process(5);
  51. #
  52. # For the list of available function see Net::Jabber::Protocol.
  53. #
  54. $Con->Disconnect();
  55. =head1 METHODS
  56. =head2 Basic Functions
  57. new(debuglevel=>0|1|2, - creates the Client object. debugfile
  58. debugfile=>string, should be set to the path for the debug
  59. debugtime=>0|1) log to be written. If set to "stdout"
  60. then the debug will go there. debuglevel
  61. controls the amount of debug. For more
  62. information about the valid setting for
  63. debuglevel, debugfile, and debugtime see
  64. Net::Jabber::Debug.
  65. Connect(hostname=>string, - opens a connection to the server
  66. port=>integer, listed in the hostname (default
  67. timeout=>int localhost), on the port (default
  68. connectiontype=>string, 5222) listed, using the
  69. ssl=>0|1) connectiontype listed (default
  70. tcpip). The two connection types
  71. available are:
  72. tcpip standard TCP socket
  73. http TCP socket, but with the
  74. headers needed to talk
  75. through a web proxy
  76. If you specify ssl, then it will
  77. be used to connect.
  78. Execute(hostname=>string, - Generic inner loop to handle
  79. port=>int, connecting to the server, calling
  80. ssl=>0|1, Process, and reconnecting if the
  81. username=>string, connection is lost. There are
  82. password=>string, five callbacks available that are
  83. resource=>string, called at various places:
  84. register=>0|1, onconnect - when the client has
  85. connectiontype=>string, made a connection.
  86. connecttimeout=>string, onauth - when the connection is
  87. connectattempts=>int, made and user has been
  88. connectsleep=>int, authed. Essentially,
  89. processtimeout=>int) this is when you can
  90. start doing things
  91. as a Client. Like
  92. send presence, get your
  93. roster, etc...
  94. onprocess - this is the most
  95. inner loop and so
  96. gets called the most.
  97. Be very very careful
  98. what you put here
  99. since it can
  100. *DRASTICALLY* affect
  101. performance.
  102. ondisconnect - when the client
  103. disconnects from
  104. the server.
  105. onexit - when the function gives
  106. up trying to connect and
  107. exits.
  108. The arguments are passed straight on
  109. to the Connect function, except for
  110. connectattempts and connectsleep.
  111. connectattempts is the number of
  112. times that the Component should try
  113. to connect before giving up. -1
  114. means try forever. The default is
  115. -1. connectsleep is the number of
  116. seconds to sleep between each
  117. connection attempt.
  118. If you specify register=>1, then the
  119. Client will attempt to register the
  120. sepecified account for you, if it
  121. does not exist.
  122. Process(integer) - takes the timeout period as an argument. If no
  123. timeout is listed then the function blocks until
  124. a packet is received. Otherwise it waits that
  125. number of seconds and then exits so your program
  126. can continue doing useful things. NOTE: This is
  127. important for GUIs. You need to leave time to
  128. process GUI commands even if you are waiting for
  129. packets. The following are the possible return
  130. values, and what they mean:
  131. 1 - Status ok, data received.
  132. 0 - Status ok, no data received.
  133. undef - Status not ok, stop processing.
  134. IMPORTANT: You need to check the output of every
  135. Process. If you get an undef then the connection
  136. died and you should behave accordingly.
  137. Disconnect() - closes the connection to the server.
  138. Connected() - returns 1 if the Transport is connected to the server,
  139. and 0 if not.
  140. =head1 AUTHOR
  141. By Ryan Eatmon in May of 2000 for http://jabber.org.
  142. =head1 COPYRIGHT
  143. This module is free software; you can redistribute it and/or modify
  144. it under the same terms as Perl itself.
  145. =cut
  146. use strict;
  147. use Carp;
  148. use base qw( Net::Jabber::Protocol );
  149. use vars qw( $VERSION );
  150. $VERSION = "1.30";
  151. sub new
  152. {
  153. my $proto = shift;
  154. my $self = { };
  155. my %args;
  156. while($#_ >= 0) { $args{ lc(pop(@_)) } = pop(@_); }
  157. bless($self, $proto);
  158. $self->{DEBUG} =
  159. new Net::Jabber::Debug(level=>exists($args{debuglevel}) ? $args{debuglevel} : -1,
  160. file=>exists($args{debugfile}) ? $args{debugfile} : "stdout",
  161. time=>exists($args{debugtime}) ? $args{debugtime} : 0,
  162. setdefault=>1,
  163. header=>"NJ::Client"
  164. );
  165. $self->{SERVER} = {hostname => "localhost",
  166. port => 5222 ,
  167. ssl=>(exists($args{ssl}) ? $args{ssl} : 0),
  168. connectiontype=>(exists($args{connectiontype}) ? $args{connectiontype} : "tcpip")
  169. };
  170. $self->{CONNECTED} = 0;
  171. $self->{DISCONNECTED} = 0;
  172. $self->{STREAM} = new XML::Stream(style=>"node",
  173. debugfh=>$self->{DEBUG}->GetHandle(),
  174. debuglevel=>$self->{DEBUG}->GetLevel(),
  175. debugtime=>$self->{DEBUG}->GetTime());
  176. $self->{VERSION} = $VERSION;
  177. $self->{LIST}->{currentID} = 0;
  178. $self->callbackInit();
  179. return $self;
  180. }
  181. ###########################################################################
  182. #
  183. # Connect - Takes a has and opens the connection to the specified server.
  184. # Registers CallBack as the main callback for all packets from
  185. # the server.
  186. #
  187. # NOTE: Need to add some error handling if the connection is
  188. # not made because the server hostname is wrong or whatnot.
  189. #
  190. ###########################################################################
  191. sub Connect
  192. {
  193. my $self = shift;
  194. while($#_ >= 0) { $self->{SERVER}{ lc pop(@_) } = pop(@_); }
  195. $self->{DEBUG}->Log1("Connect: hostname($self->{SERVER}->{hostname})");
  196. $self->{SERVER}->{timeout} = 10 unless exists($self->{SERVER}->{timeout});
  197. delete($self->{SESSION});
  198. $self->{SESSION} =
  199. $self->{STREAM}->
  200. Connect(hostname=>$self->{SERVER}->{hostname},
  201. port=>$self->{SERVER}->{port},
  202. namespace=>"jabber:client",
  203. connectiontype=>$self->{SERVER}->{connectiontype},
  204. ssl=>$self->{SERVER}->{ssl},
  205. timeout=>$self->{SERVER}->{timeout},
  206. );
  207. if ($self->{SESSION}) {
  208. $self->{DEBUG}->Log1("Connect: connection made");
  209. $self->{STREAM}->SetCallBacks(node=>sub{ $self->CallBack(@_) });
  210. $self->{CONNECTED} = 1;
  211. if (exists($self->{SESSION}->{version}) &&
  212. ($self->{SESSION}->{version} ne ""))
  213. {
  214. my $tls = $self->{STREAM}->GetStreamFeature($self->{SESSION}->{id},"xmpp-tls");
  215. if ($tls && $self->{SERVER}->{ssl})
  216. {
  217. $self->{SESSION} =
  218. $self->{STREAM}->StartTLS(
  219. $self->{SESSION}->{id},
  220. $self->{SERVER}->{timeout}
  221. );
  222. }
  223. }
  224. return 1;
  225. } else {
  226. $self->SetErrorCode($self->{STREAM}->GetErrorCode());
  227. return;
  228. }
  229. }
  230. ###############################################################################
  231. #
  232. # Process - If a timeout value is specified then the function will wait
  233. # that long before returning. This is useful for apps that
  234. # need to handle other processing while still waiting for
  235. # packets. If no timeout is listed then the function waits
  236. # until a packet is returned. Either way the function exits
  237. # as soon as a packet is returned.
  238. #
  239. ###############################################################################
  240. sub Process
  241. {
  242. my $self = shift;
  243. my ($timeout) = @_;
  244. my %status;
  245. if (exists($self->{PROCESSERROR}) && ($self->{PROCESSERROR} == 1))
  246. {
  247. croak("There was an error in the last call to Process that you did not check for and\nhandle. You should always check the output of the Process call. If it was\nundef then there was a fatal error that you need to check. There is an error\nin your program");
  248. }
  249. $self->{DEBUG}->Log1("Process: timeout($timeout)") if defined($timeout);
  250. if (!defined($timeout) || ($timeout eq ""))
  251. {
  252. while(1)
  253. {
  254. %status = $self->{STREAM}->Process();
  255. $self->{DEBUG}->Log1("Process: status($status{$self->{SESSION}->{id}})");
  256. last if ($status{$self->{SESSION}->{id}} != 0);
  257. select(undef,undef,undef,.25);
  258. }
  259. $self->{DEBUG}->Log1("Process: return($status{$self->{SESSION}->{id}})");
  260. if ($status{$self->{SESSION}->{id}} == -1)
  261. {
  262. $self->{PROCESSERROR} = 1;
  263. return;
  264. }
  265. else
  266. {
  267. return $status{$self->{SESSION}->{id}};
  268. }
  269. }
  270. else
  271. {
  272. %status = $self->{STREAM}->Process($timeout);
  273. if ($status{$self->{SESSION}->{id}} == -1)
  274. {
  275. $self->{PROCESSERROR} = 1;
  276. return;
  277. }
  278. else
  279. {
  280. return $status{$self->{SESSION}->{id}};
  281. }
  282. }
  283. }
  284. ###########################################################################
  285. #
  286. # Disconnect - Sends the string to close the connection cleanly.
  287. #
  288. ###########################################################################
  289. sub Disconnect
  290. {
  291. my $self = shift;
  292. $self->{STREAM}->Disconnect($self->{SESSION}->{id})
  293. if ($self->{CONNECTED} == 1);
  294. $self->{CONNECTED} = 0;
  295. $self->{DISCONNECTED} = 1;
  296. $self->{DEBUG}->Log1("Disconnect: bye bye");
  297. }
  298. ###########################################################################
  299. #
  300. # Connected - returns 1 if the Transport is connected to the server, 0
  301. # otherwise.
  302. #
  303. ###########################################################################
  304. sub Connected
  305. {
  306. my $self = shift;
  307. $self->{DEBUG}->Log1("Connected: ($self->{CONNECTED})");
  308. return $self->{CONNECTED};
  309. }
  310. ###########################################################################
  311. #
  312. # Execute - generic inner loop to listen for incoming messages, stay
  313. # connected to the server, and do all the right things. It
  314. # calls a couple of callbacks for the user to put hooks into
  315. # place if they choose to.
  316. #
  317. ###########################################################################
  318. sub Execute
  319. {
  320. my $self = shift;
  321. my %args;
  322. while($#_ >= 0) { $args{ lc pop(@_) } = pop(@_); }
  323. $args{connectattempts} = -1 unless exists($args{connectattempts});
  324. $args{connectsleep} = 5 unless exists($args{connectsleep});
  325. $args{register} = 0 unless exists($args{register});
  326. my %connect;
  327. $connect{hostname} = $args{hostname};
  328. $connect{port} = $args{port}
  329. if exists($args{port});
  330. $connect{connectiontype} = $args{connectiontype}
  331. if exists($args{connectiontype});
  332. $connect{timeout} = $args{connecttimeout}
  333. if exists($args{connecttimeout});
  334. $connect{ssl} = $args{ssl} if exists($args{ssl});
  335. $self->{DEBUG}->Log1("Execute: begin");
  336. my $connectAttempt = $args{connectattempts};
  337. while(($connectAttempt == -1) || ($connectAttempt > 0))
  338. {
  339. $self->{DEBUG}->Log1("Execute: Attempt to connect ($connectAttempt)");
  340. my $status = $self->Connect(%connect);
  341. if (!(defined($status)))
  342. {
  343. $self->{DEBUG}->Log1("Execute: Jabber server is not answering. (".$self->GetErrorCode().")");
  344. $self->{CONNECTED} = 0;
  345. $connectAttempt-- unless ($connectAttempt == -1);
  346. sleep($args{connectsleep});
  347. next;
  348. }
  349. $self->{DEBUG}->Log1("Execute: Connected...");
  350. &{$self->{CB}->{onconnect}}() if exists($self->{CB}->{onconnect});
  351. my @result = $self->AuthSend(username=>$args{username},
  352. password=>$args{password},
  353. resource=>$args{resource}
  354. );
  355. if ($result[0] ne "ok")
  356. {
  357. $self->{DEBUG}->Log1("Execute: Could not auth with server: ($result[0]: $result[1])");
  358. &{$self->{CB}->{onauthfail}}()
  359. if exists($self->{CB}->{onauthfail});
  360. if ($args{register} == 0)
  361. {
  362. $self->{DEBUG}->Log1("Execute: Register turned off. Exiting.");
  363. $self->Disconnect();
  364. &{$self->{CB}->{ondisconnect}}()
  365. if exists($self->{CB}->{ondisconnect});
  366. $connectAttempt = 0;
  367. }
  368. else
  369. {
  370. my %fields = $self->RegisterRequest();
  371. $fields{username} = $args{username};
  372. $fields{password} = $args{password};
  373. $self->RegisterSend(%fields);
  374. @result = $self->AuthSend(username=>$args{username},
  375. password=>$args{password},
  376. resource=>$args{resource}
  377. );
  378. if ($result[0] ne "ok")
  379. {
  380. $self->{DEBUG}->Log1("Execute: Register failed. Exiting.");
  381. &{$self->{CB}->{onregisterfail}}()
  382. if exists($self->{CB}->{onregisterfail});
  383. $self->Disconnect();
  384. &{$self->{CB}->{ondisconnect}}()
  385. if exists($self->{CB}->{ondisconnect});
  386. $connectAttempt = 0;
  387. }
  388. else
  389. {
  390. &{$self->{CB}->{onauth}}()
  391. if exists($self->{CB}->{onauth});
  392. }
  393. }
  394. }
  395. else
  396. {
  397. &{$self->{CB}->{onauth}}()
  398. if exists($self->{CB}->{onauth});
  399. }
  400. while($self->Connected())
  401. {
  402. while(defined($status = $self->Process($args{processtimeout})))
  403. {
  404. &{$self->{CB}->{onprocess}}()
  405. if exists($self->{CB}->{onprocess});
  406. }
  407. if (!defined($status))
  408. {
  409. $self->Disconnect();
  410. $self->{DEBUG}->Log1("Execute: Connection to server lost...");
  411. &{$self->{CB}->{ondisconnect}}()
  412. if exists($self->{CB}->{ondisconnect});
  413. $connectAttempt = $args{connectattempts};
  414. next;
  415. }
  416. }
  417. last if $self->{DISCONNECTED};
  418. }
  419. $self->{DEBUG}->Log1("Execute: end");
  420. &{$self->{CB}->{onexit}}() if exists($self->{CB}->{onexit});
  421. }
  422. 1;