Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ippSimpleClient.cpp

Go to the documentation of this file.
00001 // 
00002 // DISCLAIMER: 
00003 //  This software was produced by the National Institute of Standards 
00004 //  and Technology (NIST), an agency of the U.S. government, and by statute is 
00005 //  not subject to copyright in the United States.  Recipients of this 
00006 //  software assume all responsibility associated with its operation,
00007 //  modification,maintenance, and subsequent redistribution. 
00008 //
00009 //  See NIST Administration Manual 4.09.07 b and Appendix I. 
00010 #include "stdafx.h"
00011 #include "ippdme/Server/ippSimpleClient.h"
00012 #include "ippdme/Response/ippErrorResponse.h"
00013 #include "ippdme/assert.h"
00014 
00015 ippSimpleClient::ippSimpleClient()
00016 :_state(disconnected)
00017 ,_ready_to_send(false)
00018 ,_in_error_state(false)
00019 ,_next_tag(1)
00020 {
00021   _pending_tag=0;
00022 }
00023 
00024 void ippSimpleClient::Connect(
00025   const char* hostname,
00026   int port
00027 )
00028 {
00029   IPP_ASSERT(_state== disconnected);
00030   
00031   if(_state != disconnected) {
00032     return;
00033   }
00034   
00035   
00036   while(!_pending_commands.empty()) {
00037     _pending_commands.pop();
00038   }
00039 
00040   bool bSuccess = _socket.Create();
00041   IPP_ASSERT(bSuccess);
00042  
00043 
00044   ippSocket::SERROR nRet =  _socket.Connect(hostname,port);
00045   if (nRet == ippSocket::SOCKET_WOULD_BLOCK) {
00046     //
00047     _state = trying_to_connect;
00048   } else  if (nRet == ippSocket::SOCKET_IS_CONNECTED) { 
00049     _state = connected;
00050     _in_error_state = false;
00051     _ready_to_send = true;
00052   } else {
00053     _state = disconnected;
00054     _socket.Close();
00055   }
00056 }
00057 
00058 ippSimpleClient::STATE ippSimpleClient::GetState() const
00059 {
00060   return _state;
00061 }
00062 
00063 bool ippSimpleClient::ReadyToSend() const
00064 {
00065   return _state == connected && _ready_to_send;
00066 }
00067 
00068 bool ippSimpleClient::NeedToSendClearAllErrors() const
00069 {
00070   return _in_error_state;
00071 }
00072 
00073 void ippSimpleClient::Disconnect()
00074 {
00075    ProbeConnection();
00076   _state = disconnected;
00077   _socket.Close();
00078   _ready_to_send = false;
00079   _in_error_state = false;
00080   
00081   LogMessage(" disconnected","");
00082 }
00083 
00084 
00085 void ippSimpleClient::HeartBeat()
00086 {
00087   ippSleep(1); // allow context switch
00088   switch(_state){
00089   case trying_to_connect:
00090     {
00091       switch(_socket.CanSendData()){ 
00092         case ippSocket::SOCKET_OK: 
00093           _ready_to_send = true;
00094           _in_error_state = false;
00095           _state = connected; 
00096         break;
00097         case ippSocket::SOCKET_WOULD_BLOCK:
00098           // this mean that the server is probably busy
00099           Disconnect();
00100           break;
00101         default:
00102           _state = disconnected;
00103           _socket.Close();
00104         }
00105       } break;
00106   case connected:
00107     {
00108       PerformRead();
00109     }
00110   }
00111 }
00112 
00113 
00114 
00115 
00116 #include "ippdme/Parser/ippResponseParser.h"
00117 
00118 void ippSimpleClient::ProcessLine(const char* inputline)
00119 {
00120   
00121   LogMessage("received:",inputline);
00122 
00123   ippResponseParser parser;
00124   parser.setInput(inputline);
00125   parser.parseTag();
00126   ipp::parserResErrorId         code = parser.getParserErr();                           
00127 
00128   if (code != ipp::OK) {
00129     // the parsing of the TAG of the received line has failed
00130     std::string errorMessage = parser.getErrorMessageString();
00131     char buf[IPPSIZE];
00132     sprintf(buf,"Response Error: %s", errorMessage.c_str());
00133     LogMessage("Response Error:",errorMessage.c_str());
00134   }
00135 
00136   // Check to see if this is an Event tag
00137   if ( parser.getTagType() == EventTag ) {
00138     // Event Tag
00139     // If message is E0000 this is an unsolicited event
00140     // such as as Error from the server because an illegal
00141     // tag was sent. 
00142     //
00143     // see $4.1 in ippdme spec. the tag E0000 is reserved
00144     //          for event with no relation to legal tags
00145     //
00146     //     $4.4 Server events use tag E0000. They are used to
00147     //          report manual hits, keystrokes, supported
00148     //          machine status changes...
00149     if ( std::string(inputline,7) == "E0000 !") { 
00150        // illegal tag probably
00151        ippResponsePtr response = parser.parseResponse();
00152        if(response) {
00153           ippErrorResponsePtr e = static_cast<ippErrorResponse*>(response.get());
00154           ippErrorNameType error= e->getTheError()->getName();    
00155           if (BufferFull ==error ||IllegalCharacter==error  || IllegalTag==error || NoSpaceAtPos6==error){
00156             _ready_to_send= true;
00157           } else {
00158             OnUnsollicitedEvent(response);
00159           }
00160        } else {
00161          IPP_ASSERT_FAIL("What should we do here ?");
00162        }
00163     }
00164   }
00165   char  response_char = inputline[6];
00166 
00167   ippResponsePtr response = parser.parseResponse();
00168  
00169   int read_tag = parser.getTag();
00170 
00171   // Check for the ACK from previous command
00172   if (response_char == '&')     {                        // acknowledge           
00173 
00174     if (_pending_tag == read_tag){      
00175       // we are now allowed to push a new command to the server      
00176       _ready_to_send= true; 
00177       
00178       _next_tag++;            
00179       // let put this tag to the uncompleted command queue
00180       if (response->getTag().getTagType() == CommandTag) { 
00181         _pending_commands.push(_pending_tag); 
00182       }
00183       _pending_tag = 0;
00184     } else {
00185       LogMessage("Response Error:","Tags do not match");
00186     }
00187 
00188   }     else if (response_char == '!') { // Error  !
00189   
00190     if (_pending_tag==read_tag) {
00191        // An Error was returned                                 
00192        _next_tag++;     
00193     }
00194 
00195     //xx LogMessage("Response Error:","ERROR Returned");
00196 
00197     // Have to parse the error to check severity
00198     // Anything larger than 1 requires ClearAllErros be sent
00199     if (inputline[9] != '1') {
00200       //xx LogMessage("Response Error:","ERROR - Must send ClearAllErrors()");
00201       _in_error_state = true;
00202     }
00203     ippResponsePtr response = parser.parseResponse();
00204     OnErrorResponse(response);
00205 
00206   } else if (response_char == '%'){
00207     
00208     // Transaction complete 
00209     ippResponsePtr response = parser.parseResponse();
00210     
00211     if (parser.getTagType() == EventTag) { 
00212       // completion of a command of the fast queue
00213       OnComnmandCompleted(response->getTag().getTagNumber());
00214     } else {
00215       
00216       // completion of a command of the slow queue
00217       tagIdType type = response->getTag().getTagType();
00218       if (type == CommandTag) { 
00219         // verify that the completion tag matches the tag of the currently executed command 
00220         if ( _pending_commands.size()>0 && _pending_commands.front()== response->getTag().getTagNumber() ) {
00221            _pending_commands.pop();
00222            OnComnmandCompleted(response->getTag().getTagNumber());
00223         } else {
00224           LogMessage("Unexpected completed command:","Tags do not match");
00225         }
00226       } else {
00227         OnComnmandCompleted(response->getTag().getTagNumber());
00228       }
00229     }
00230   
00231   }     else if (response_char == '#') { // Data follows
00232 
00233     ippResponsePtr response = parser.parseResponse();
00234     
00235     if(response) {
00236     
00237       if (response->getTag().getTagType() == CommandTag ) {  
00238         // process a response that belongs to the currently executed command
00239         if ( _pending_commands.front()== response->getTag().getTagNumber())  {
00240           OnResponse(response);
00241         } else {
00242           // this is a unexpected tag !
00243           LogMessage("unexpected response tag number:","Tags do not match");
00244         }
00245       } else {
00246         // process a event response ( from a daemon ) 
00247         // [TODO] verifies that the tag id must belongs to a existing daemon
00248         IPP_ASSERT_MSG(response->getTag().getTagNumber()!=0," should not be an unsollicited event");
00249         OnDaemonResponse(response);
00250       }
00251     } else {
00252       IPP_ASSERT_FAIL(" to do : be smart here ") ;
00253     }
00254   }     else {
00255     IPP_ASSERT_FAIL(" to do : be smart here ") ;
00256     // Bad value in response character
00257   }
00258 }
00259 
00260 void ippSimpleClient::ProcessMisformedLine(const char* inputline)
00261 {
00262   LogMessage("received malformed string:",inputline);
00263   // a malformed string has been received from the client 
00264   // we do need to disconnect !!!
00265   Disconnect();
00266 }
00267 
00268 bool ippSimpleClient::SendCommand(ippCommandConstPtr command)
00269 {
00270   SendCommand(command->getCommandString().c_str());
00271   return true;
00272 }
00273 
00274 void ippSimpleClient::OnConnectionLost()
00275 {
00276   LogMessage(" connection lost","");
00277   Disconnect();
00278 }
00279 
00280 void ippSimpleClient::SendCommand(const char* command)
00281 {
00282   IPP_ASSERT(_ready_to_send);
00283   LogMessage("     send :",command);
00284   
00285   if(command[0]=='E') {
00286     sscanf(command+1,"%4d",&_pending_tag);
00287   } else {
00288     sscanf(command,"%5d",&_pending_tag);
00289   }
00290  
00291   _socket.Write(command);
00292   
00293   // see if we need to send the line termination
00294   int l = strlen(command);
00295   if (l > 2 && command[l-1] != '\n' && command[l-2]!='\r') { 
00296      _socket.Write("\r\n");
00297   }
00298 
00299   _ready_to_send = false;
00300   // read the acknowledge tag
00301 }
00302 
00303 void ippSimpleClient::ClearAllErrors()
00304 {
00305   IPP_ASSERT(NeedToSendClearAllErrors());
00306   _pending_commands.empty(); 
00307   SendCommand(new ippCommand(_next_tag,ipp::ClearAllErrors));
00308   _in_error_state = false;
00309 }
00310 
00311 int ippSimpleClient::NumberOfUncompletedCommandsInQueue()
00312 {
00313   return _pending_commands.size();
00314 }
00315 
00316 void ippSimpleClient::OnErrorResponse(ippResponsePtr response)
00317 {
00318 
00319 }
00320 void ippSimpleClient::OnDaemonResponse(ippResponsePtr response)
00321 {
00322 
00323 }
00325 void ippSimpleClient::OnResponse(ippResponsePtr response)
00326 {
00327 
00328 }
00329 
00331 void ippSimpleClient::OnUnsollicitedEvent(ippResponsePtr response)
00332 {
00333 
00334 }
00336 void ippSimpleClient::OnComnmandCompleted(int tagNumber)
00337 {
00338 
00339 }

Generated on Wed Nov 8 00:20:06 2006 for IPPDME by  doxygen 1.4.1