1 package OpenSRF::DomainObject::oilsMessage;
2 use base 'OpenSRF::DomainObject';
3 use OpenSRF::AppSession;
4 use OpenSRF::DomainObject::oilsResponse qw/:status/;
5 use OpenSRF::Utils::Logger qw/:level/;
6 use warnings; use strict;
7 use OpenSRF::EX qw/:try/;
11 OpenSRF::DomainObject::oilsMessage
15 use OpenSRF::DomainObject::oilsMessage;
17 my $msg = OpenSRF::DomainObject::oilsMessage->new( type => 'CONNECT' );
19 $msg->userAuth( $userAuth_element );
21 $msg->payload( $domain_object );
25 OpenSRF::DomainObject::oilsMessage is used internally to wrap data sent
26 between client and server. It provides the structure needed to authenticate
27 session data, and also provides the logic needed to unwrap session data and
28 pass this information along to the Application Layer.
32 my $log = 'OpenSRF::Utils::Logger';
36 =head2 OpenSRF::DomainObject::oilsMessage->type( [$new_type] )
40 Used to specify the type of message. One of
41 B<CONNECT, REQUEST, RESULT, STATUS, ERROR, or DISCONNECT>.
49 return $self->_attr_get_set( type => shift );
52 =head2 OpenSRF::DomainObject::oilsMessage->api_level( [$new_api_level] )
56 Used to specify the api_level of message. Currently, only api_level C<1> is
57 supported. This will be used to check that messages are well-formed, and as
58 a hint to the Application as to which version of a method should fulfill a
67 return $self->_attr_get_set( api_level => shift );
70 =head2 OpenSRF::DomainObject::oilsMessage->threadTrace( [$new_threadTrace] );
74 Sets or gets the current message sequence identifier, or thread trace number,
75 for a message. Useful as a debugging aid, but that's about it.
83 return $self->_attr_get_set( threadTrace => shift );
86 =head2 OpenSRF::DomainObject::oilsMessage->update_threadTrace
90 Increments the threadTrace component of a message. This is automatic when
91 using the normal session processing stack.
97 sub update_threadTrace {
99 my $tT = $self->threadTrace;
104 $log->debug("Setting threadTrace to $tT",DEBUG);
106 $self->threadTrace($tT);
111 =head2 OpenSRF::DomainObject::oilsMessage->payload( [$new_payload] )
115 Sets or gets the payload of a message. This should be exactly one object
116 of (sub)type domainObject or domainObjectCollection.
126 my ($payload) = $self->getChildrenByTagName('oils:domainObjectCollection') ||
127 $self->getChildrenByTagName('oils:domainObject');
129 $payload = $self->removeChild($payload) if ($payload);
130 $self->appendChild($new_pl);
131 return $new_pl unless ($payload);
134 return OpenSRF::DOM::upcast($payload)->upcast if ($payload);
137 =head2 OpenSRF::DomainObject::oilsMessage->userAuth( [$new_userAuth_element] )
141 Sets or gets the userAuth element for this message. This is used internally by the
152 my ($ua) = $self->getChildrenByTagName('oils:userAuth');
154 $ua = $self->removeChild($ua) if ($ua);
155 $self->appendChild($new_ua);
156 return $new_ua unless ($ua);
162 =head2 OpenSRF::DomainObject::oilsMessage->handler( $session_id )
166 Used by the message processing stack to set session state information from the current
167 message, and then sends control (via the payload) to the Application layer.
177 my $mtype = $self->type;
178 my $api_level = $self->api_level || 1;;
179 my $tT = $self->threadTrace;
181 $session->last_message_type($mtype);
182 $session->last_message_api_level($api_level);
183 $session->last_threadTrace($tT);
185 $log->debug(" Received api_level => [$api_level], MType => [$mtype], ".
186 "from [".$session->remote_id."], threadTrace[".$self->threadTrace."]", INFO);
187 $log->debug("endpoint => [".$session->endpoint."]", DEBUG);
188 $log->debug("OpenSRF::AppSession->SERVER => [".$session->SERVER()."]", DEBUG);
190 $log->debug("Before ALL", DEBUG);
193 if ( $session->endpoint == $session->SERVER() ) {
194 $val = $self->do_server( $session, $mtype, $api_level, $tT );
196 } elsif ($session->endpoint == $session->CLIENT()) {
197 $val = $self->do_client( $session, $mtype, $api_level, $tT );
201 return OpenSRF::Application->handler($session, $self->payload);
210 # handle server side message processing
212 # !!! Returning 0 means that we don't want to pass ourselves up to the message layer !!!
214 my( $self, $session, $mtype, $api_level, $tT ) = @_;
216 # A Server should never receive STATUS messages. If so, we drop them.
217 # This is to keep STATUS's from dead client sessions from creating new server
218 # sessions which send mangled session exceptions to backends for messages
219 # that they are not aware of any more.
220 if( $mtype eq 'STATUS' ) { return 0; }
223 if ($mtype eq 'DISCONNECT') {
224 $session->state( $session->DISCONNECTED );
229 if ($session->state == $session->CONNECTING()) {
231 # the transport layer thinks this is a new connection. is it?
232 unless ($mtype eq 'CONNECT') {
233 $log->error("Connection seems to be mangled: Got $mtype instead of CONNECT");
235 my $res = OpenSRF::DomainObject::oilsBrokenSession->new(
236 status => "Connection seems to be mangled: Got $mtype instead of CONNECT",
239 $session->status($res);
245 #unless ($self->userAuth ) {
246 # $log->debug( "No Authentication information was provided with the initial packet", ERROR );
247 # my $res = OpenSRF::DomainObject::oilsConnectException->new(
248 # status => "No Authentication info was provided with initial message" );
249 # $session->status($res);
254 #unless( $self->userAuth->authenticate( $session ) ) {
255 # my $res = OpenSRF::DomainObject::oilsAuthException->new(
256 # status => "Authentication Failed for " . $self->userAuth->getAttribute('username') );
257 # $session->status($res) if $res;
262 #$session->client_auth( $self->userAuth );
264 $log->debug("We're a server and the user is authenticated",DEBUG);
266 my $res = OpenSRF::DomainObject::oilsConnectStatus->new;
267 $session->status($res);
268 $session->state( $session->CONNECTED );
274 $log->debug("Passing to Application::handler()", INFO);
275 $log->debug($self->toString(1), DEBUG);
282 # Handle client side message processing. Return 1 when the the message should be pushed
283 # up to the application layer. return 0 otherwise.
286 my( $self, $session , $mtype, $api_level, $tT) = @_;
289 if ($mtype eq 'STATUS') {
291 if ($self->payload->statusCode == STATUS_OK) {
292 $session->state($session->CONNECTED);
293 $log->debug("We connected successfully to ".$session->app, INFO);
297 if ($self->payload->statusCode == STATUS_TIMEOUT) {
298 $session->state( $session->DISCONNECTED );
300 $session->push_resend( $session->app_request($self->threadTrace) );
301 $log->debug("Disconnected because of timeout", WARN);
304 } elsif ($self->payload->statusCode == STATUS_REDIRECTED) {
305 $session->state( $session->DISCONNECTED );
307 $session->push_resend( $session->app_request($self->threadTrace) );
308 $log->debug("Disconnected because of redirect", WARN);
311 } elsif ($self->payload->statusCode == STATUS_EXPFAILED) {
312 $session->state( $session->DISCONNECTED );
313 $log->debug("Disconnected because of mangled session", WARN);
315 $session->push_resend( $session->app_request($self->threadTrace) );
318 } elsif ($self->payload->statusCode == STATUS_CONTINUE) {
321 } elsif ($self->payload->statusCode == STATUS_COMPLETE) {
322 my $req = $session->app_request($self->threadTrace);
323 $req->complete(1) if ($req);
327 # add more STATUS handling code here (as 'elsif's), for Message layer status stuff
329 } elsif ($session->state == $session->CONNECTING()) {
330 # This should be changed to check the type of response (is it a connectException?, etc.)
333 if( $self->payload->class->isa( "OpenSRF::EX" ) ) {
334 $self->payload->throw();
337 if( $self->payload ) {
338 $log->debug("Passing to OpenSRF::Application::handler()\n" . $self->payload->toString(1), INTERNAL);
340 $log->debug("oilsMessage passing to Application: " . $self->type." : ".$session->remote_id, INFO );