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

phClientHandler.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004 
00005     Copyright (C) 2003 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008 
00009     This file is part of Phission.
00010 
00011  ---------------------------------------------------------------------------*/
00012 /* -------------------------------------------------------------------------- *
00013  * phClientHandler.cpp: Header for the client handler that the server spawns  *
00014  * to  handle multiple client requests.                                       *
00015  * -------------------------------------------------------------------------- */
00016 #include <phClientHandler.h>
00017 #include <sys/types.h>
00018 #include <unistd.h>
00019 
00020 /* -------------------------------------------------------------------------- *
00021  * phClientHandler constructor:
00022  * -------------------------------------------------------------------------- */
00023 phClientHandler::phClientHandler(uint32_t controller_id,
00024                                  phSocket *sock,
00025                                  phLamportSystem *system )
00026 {
00027     phFUNCTION("phClientHandler::phClientHandler")
00028     int locked = 0;
00029 
00030     /* lock the object so we can alter things without worrying about another
00031      * thread getting to it at the same time. */
00032     phTHIS_LOOSE_LOCK(locked);
00033 
00034     /* Initialize all the member variables to default values so they
00035      * can be more appropriately initialized later */
00036     this->m_sock            = NULL;
00037     this->m_controller_id   = phID_INVALID;
00038     this->m_client_id       = phID_INVALID;
00039 
00040     this->m_system          = NULL;
00041     
00042     rc = this->setSocket(sock);
00043     rc = this->setControllerId(controller_id);
00044     rc = this->setSystem(system); 
00045     
00046     /* Unlock the phClientHandler in case someone wants to do 
00047      * something with it or has been waiting to */
00048     phTHIS_LOOSE_UNLOCK(locked);
00049 }
00050 
00051 /* -------------------------------------------------------------------------- *
00052  * phClientHandler destructor:
00053  * -------------------------------------------------------------------------- */
00054 phClientHandler::~phClientHandler()
00055 {
00056     phFUNCTION("phClientHandler::~phClientHandler")
00057     int locked = 0;
00058 
00059     /* Lock the object and don't unlock because the object is being destroyed.
00060      * We don't unlock because we want the object locked all the way to the
00061      * destructor of the phMutex at which point anyone waiting for a mutex
00062      * will fail on the lock and won't try to access this information */
00063     phTHIS_LOOSE_LOCK(locked);
00064     
00065     /* Reset all the variables, free all the memory */
00066     phDelete(this->m_sock);
00067     this->m_controller_id   = phID_INVALID;
00068     this->m_client_id       = phID_INVALID;
00069 }
00070 
00071 /* -------------------------------------------------------------------------- */
00072 int phClientHandler::setSocket(phSocket *sock)
00073 {
00074     phFUNCTION("phClientHandler::setSocket")
00075     int locked = 0;
00076 
00077     /* lock the object so we can alter things without worrying about another
00078      * thread getting to it at the same time. If we succeed, set 'locked' so
00079      * the method knows to unlock should something go wrong. */
00080     phTHIS_LOCK(locked);
00081 
00082     this->m_sock = sock;
00083     
00084     /* Unlock the phClientHandler in case someone wants to do 
00085      * something with it or has been waiting to */
00086     phTHIS_UNLOCK(locked);
00087 
00088     return phSUCCESS;
00089 error:
00090     /* We're using 'locked' to tell whether we want to unlock
00091      * within this method. This thread could own it several times and
00092      * we don't want to unlock one this method doesn't own */
00093     phTHIS_ERROR_UNLOCK(locked);
00094 
00095     return phFAIL;
00096 }
00097 
00098 /* -------------------------------------------------------------------------- */
00099 phSocket *phClientHandler::getSocket()
00100 {
00101     return this->m_sock;
00102 }
00103 
00104 /* -------------------------------------------------------------------------- *
00105  * setControllerId:
00106  * -------------------------------------------------------------------------- */
00107 int phClientHandler::setControllerId(uint32_t controller_id)
00108 {
00109     phFUNCTION("phClientHandler::setControllerId")
00110     int locked = 0;
00111     
00112     phTHIS_LOCK(locked);
00113 
00114     this->m_controller_id = controller_id;
00115     
00116     phTHIS_UNLOCK(locked);
00117 
00118     return phSUCCESS;
00119 error:
00120     phTHIS_ERROR_UNLOCK(locked);
00121 
00122     return phFAIL;
00123 }
00124 
00125 /* -------------------------------------------------------------------------- *
00126  * getControllerId:
00127  * -------------------------------------------------------------------------- */
00128 uint32_t phClientHandler::getControllerId()
00129 {
00130     phFUNCTION("phClientHandler::getControllerId")
00131     int ret_id = 0;
00132     int locked = 0;
00133     
00134     phTHIS_LOCK(locked);
00135 
00136     ret_id = this->m_controller_id;
00137     
00138 error:
00139     phTHIS_ERROR_UNLOCK(locked);
00140 
00141     return ret_id;
00142 }
00143 
00144 /* -------------------------------------------------------------------------- *
00145  * setClientId:
00146  * -------------------------------------------------------------------------- */
00147 int phClientHandler::setClientId(uint32_t client_id)
00148 {
00149     phFUNCTION("phClientHandler::setClientId")
00150     int locked = 0;
00151     
00152     phTHIS_LOCK(locked);
00153 
00154     this->m_client_id = client_id;
00155     
00156     phTHIS_UNLOCK(locked);
00157 
00158     return phSUCCESS;
00159 error:
00160     phTHIS_ERROR_UNLOCK(locked);
00161 
00162     return phFAIL;
00163 }
00164 
00165 /* -------------------------------------------------------------------------- *
00166  * getClientId:
00167  * -------------------------------------------------------------------------- */
00168 uint32_t phClientHandler::getClientId()
00169 {
00170     phFUNCTION("phClientHandler::getClientId")
00171     uint32_t ret_id = 0;
00172     int locked = 0;
00173     
00174     phTHIS_LOCK(locked);
00175 
00176     ret_id = this->m_client_id;
00177     
00178 error:
00179     phTHIS_ERROR_UNLOCK(locked);
00180 
00181     return ret_id;
00182 }
00183 
00184 /* -------------------------------------------------------------------------- *
00185  * setSystem:
00186  * -------------------------------------------------------------------------- */
00187 int phClientHandler::setSystem(phLamportSystem *system)
00188 {
00189     phFUNCTION("phClientHandler::setSystem")
00190     int locked = 0;
00191     
00192     phTHIS_LOCK(locked);
00193 
00194     this->m_system = system;
00195 
00196     if (this->m_system != NULL)
00197     {
00198         rc = this->m_system->registerResource(this);
00199         phPRINT_RC(rc,NULL,"m_system.registerResource(this:%p) failed.",
00200              this);
00201     }
00202     
00203     phTHIS_UNLOCK(locked);
00204 
00205     return phSUCCESS;
00206 error:
00207     phTHIS_ERROR_UNLOCK(locked);
00208 
00209     return phFAIL;
00210 }
00211 
00212 /* -------------------------------------------------------------------------- *
00213  * getSystem:
00214  * -------------------------------------------------------------------------- */
00215 phLamportSystem *phClientHandler::getSystem()
00216 {
00217     phFUNCTION("phClientHandler::")
00218     phLamportSystem *system = 0;
00219     int locked = 0;
00220     
00221     phTHIS_LOCK(locked);
00222 
00223     system = this->m_system;
00224     
00225 error:
00226     phTHIS_ERROR_UNLOCK(locked);
00227 
00228     return system;
00229 }
00230 
00231 
00232 /* -------------------------------------------------------------------------- *
00233  * run:
00234  * -------------------------------------------------------------------------- */
00235 int phClientHandler::run()
00236 {
00237     phFUNCTION("phClientHandler::run")
00238 
00239     /* Do any setup here */
00240   
00241     /* make sure there is a mutual exclusion system to negotiate with */
00242     phCHECK_NULLPTR(this->m_system,NULL,
00243         "Bad parameter: this->m_system == NULL" );
00244     
00245     /* Make sure the socket isn't NULL */
00246     phCHECK_NULLPTR(this->getSocket(), NULL,
00247             "The client thread's socket is NULL.");
00248    
00249     /* run has the lock until here */
00250     rc = this->signal_running();
00251     phCHECK_RC(rc, NULL, "this->signal_running()");
00252 
00253     phPROGRESS("[C:%d<->NC:%d] Client connected and Running...\n\n", 
00254              this->m_client_id,this->m_controller_id );
00255 
00256     while (this->isRunning() && this->m_sock->isConnected())
00257     {
00258         rc = this->receive_message();
00259         phPRINT_RC(rc,NULL,"this->receive_message failed.");
00260 
00261         if (rc == phSUCCESS)
00262         {
00263             rc = this->dispatch();
00264             phPRINT_RC(rc,NULL,"this->dispatch() failed.");
00265         }
00266         
00267         phYield();
00268     }
00269     
00270     phPROGRESS("[C:%d<->NC:%d] client done.\n\n", 
00271              this->m_client_id,
00272              this->m_controller_id );
00273 
00274     return phSUCCESS;
00275 error:
00276     /* Signal the spawner thread that this thread hit an error condition
00277      * and it should be cleaned up immediately. */
00278     rc = this->signal_error();
00279     phCHECK_RC(rc, NULL, "this->signal_error()");
00280    
00281     return phFAIL;
00282 }
00283  
00284 /* ------------------------------------------------------------------------- *
00285  * receive_message: 
00286  * ------------------------------------------------------------------------- */
00287 int phClientHandler::receive_message()
00288 {
00289     phFUNCTION("phClientHandler::receive_message")
00290     int locked = 0;
00291     int received_length = 0;
00292     int offset = 0;
00293     int retrc = phSUCCESS;
00294     
00295     /* lock the object so we can alter things without worrying about another
00296      * thread getting to it at the same time. If we succeed, set 'locked' so
00297      * the method knows to unlock should something go wrong. */
00298     phTHIS_LOCK(locked);
00299 
00300 #if 0
00301     /* Turn on NON-BLOCKING socket receiving */
00302     rc = this->m_sock->setBlocking(phNONBLOCK);
00303     phPRINT_RC(rc,NULL,"m_sock->setBlocking(phNONBLOCK");
00304 #endif
00305     
00306     /* If there isn't a receive buffer allocated, allocate one and store the
00307      * size of it in a member variable for safe keeping */
00308     DEBUG_PRINT("call:m_message.receive\n");
00309     rc = this->m_message.receive(this->m_sock);
00310     phCHECK_RC(rc,NULL,"client_message.receive(%p) failed.",
00311              this->m_sock);
00312 
00313     /* 
00314     if (this->m_sock->isConnected())
00315     {
00316         this->m_message.print(stderr);
00317         DEBUG_PRINT("done:m_message.receive\n");
00318     }
00319     */
00320 
00321     /* propagate a non-blocking return code; just in case */
00322     if (rc == 1)
00323     {
00324         retrc = 1;
00325     }
00326     
00327     /* Unlock the phClientHandler in case someone wants to do 
00328      * something with it or has been waiting to */
00329     phTHIS_UNLOCK(locked);
00330     
00331     return retrc;
00332 error:
00333     /* We're using 'locked' to tell whether we want to unlock
00334      * within this method. This thread could own it several times and
00335      * we don't want to unlock one this method doesn't own */
00336     phTHIS_ERROR_UNLOCK(locked);
00337 
00338     return phFAIL;
00339 }
00340 
00341 /* ------------------------------------------------------------------------- *
00342  * dispatch: 
00343  * ------------------------------------------------------------------------- */
00344 int phClientHandler::dispatch()
00345 {
00346     phFUNCTION("phClientHandler::dispatch")
00347     int locked = 0;
00348     uint32_t message_id = phCLIENT_SUCCESS;
00349     
00350     /* lock the object so we can alter things without worrying about another
00351      * thread getting to it at the same time. If we succeed, set 'locked' so
00352      * the method knows to unlock should something go wrong. */
00353     phTHIS_LOCK(locked);
00354     
00355     if (this->m_message.getMessageId() == phCLIENT_HELLO)
00356     {
00357         DEBUG_PRINT("phCLIENT_HELLO\n");
00358         rc = this->handle_client_hello();
00359         phCHECK_RC(rc,NULL,"handle_client_hello() failed.");
00360     }
00361     else if (this->m_message.getMessageId() == phCLIENT_GOODBYE)
00362     {
00363         DEBUG_PRINT("phCLIENT_GOODBYE\n");
00364         rc = this->handle_client_goodbye();
00365         phCHECK_RC(rc,NULL,"handle_client_goodbye() failed.");
00366     }
00367     else if ((this->m_message.getMessageId() == phCLIENT_REQUEST) ||
00368              (this->m_message.getMessageId() == phCLIENT_RELEASE))
00369     {
00370         /* Only send the reply when it has been confirmed we got 
00371          * the mutex or failed to */
00372         rc = this->m_system->handle_message(this->m_message);
00373         phPRINT_RC(rc,NULL,"m_system->handle_message");
00374         
00375         if (rc != phSUCCESS)
00376         {
00377             message_id = phCLIENT_FAIL;
00378         }
00379 
00380         rc = this->send_client_message(message_id);
00381         phPRINT_RC(rc,NULL,
00382             "send_client_message(%d) failed.",
00383             message_id);
00384     }
00385     else
00386     {
00387         phPRINT_RC(-1,NULL,"Unrecognized message: %d",
00388                  this->m_message.getMessageId());
00389     }
00390 
00391     /* Unlock the phClientHandler in case someone wants to do 
00392      * something with it or has been waiting to */
00393     phTHIS_UNLOCK(locked);
00394     
00395     return phSUCCESS;
00396 error:
00397     /* We're using 'locked' to tell whether we want to unlock
00398      * within this method. This thread could own it several times and
00399      * we don't want to unlock one this method doesn't own */
00400     phTHIS_ERROR_UNLOCK(locked);
00401 
00402     return phFAIL;
00403 }
00404 
00405 /* ------------------------------------------------------------------------- *
00406  * handle_client_hello: 
00407  * ------------------------------------------------------------------------- */
00408 int phClientHandler::handle_client_hello()
00409 {
00410     phFUNCTION("phClientHandler::handle_client_hello")
00411     int locked = 0;
00412     
00413     phTHIS_LOCK(locked);
00414 
00415     /*
00416      * phPROGRESS("Received HELLO from client...\n");
00417      * this->m_message.print(stderr);    
00418      */
00419 
00420     /* This is an initialization step...
00421      * The sending of the phCLIENT_HELLO back to the client will send
00422      * this node's ID and the client's ID to be used from then on */
00423 
00424     rc = this->send_client_message();
00425     phPRINT_RC(rc,NULL,"this->send_client_message(phCLIENT_HELLO) failed.");
00426     
00427     phTHIS_UNLOCK(locked);
00428     
00429     return phSUCCESS;
00430 error:
00431    
00432     phTHIS_ERROR_UNLOCK(locked);
00433     
00434     return phFAIL;
00435 }
00436 
00437 /* ------------------------------------------------------------------------- *
00438  * handle_client_goodbye: 
00439  * ------------------------------------------------------------------------- */
00440 int phClientHandler::handle_client_goodbye()
00441 {
00442     phFUNCTION("phClientHandler::handle_client_goodbye")
00443     int locked = 0;
00444     
00445     phTHIS_LOCK(locked);
00446 
00447     /*
00448      * phPROGRESS("Received HELLO from client...\n");
00449      * this->m_message.print(stderr);    
00450      */
00451 
00452     /* This is an initialization step...
00453      * The sending of the phCLIENT_HELLO back to the client will send
00454      * this node's ID and the client's ID to be used from then on */
00455 
00456     rc = this->send_client_message();
00457     phPRINT_RC(rc,NULL,"this->send_client_message(phCLIENT_GOODBYE) failed.");
00458     
00459     phTHIS_UNLOCK(locked);
00460     
00461     return phSUCCESS;
00462 error:
00463    
00464     phTHIS_ERROR_UNLOCK(locked);
00465     
00466     return phFAIL;
00467 }
00468 
00469 /* ------------------------------------------------------------------------- *
00470  * : 
00471  * ------------------------------------------------------------------------- */
00472 int phClientHandler::send_client_message(uint32_t message, uint32_t mutex_id)
00473 {
00474     phFUNCTION("phClientHandler::send_client_message")
00475     int locked = 0;
00476     
00477     /* lock the object so we can alter things without worrying about another
00478      * thread getting to it at the same time. If we succeed, set 'locked' so
00479      * the method knows to unlock should something go wrong. */
00480     phTHIS_LOCK(locked);
00481 
00482     /* Set the source and destination ID and CLASSes */
00483     /* SOURCE INFO */
00484     rc = this->m_message.setSrcId(this->m_controller_id);
00485     phCHECK_RC(rc,NULL,"this->m_message.setSrcId() failed.");
00486     
00487     rc = this->m_message.setSrcClass(phCLASS_NODE);
00488     phCHECK_RC(rc,NULL,"this->m_message.setSrcClass() failed.");
00489    
00490     /* DESTINATION INFO */
00491     rc = this->m_message.setDstId(this->m_client_id);
00492     phCHECK_RC(rc,NULL,"this->m_message.setDstId() failed.");
00493     
00494     rc = this->m_message.setDstClass(phCLASS_CLIENT);
00495     phCHECK_RC(rc,NULL,"this->m_message.setDstClass() failed.");
00496     
00497     /* Set the id of the message */
00498     if (message != phCLIENT_INVALID_MSG)
00499     {
00500         /* Set the message */
00501         rc = this->m_message.setMessageId(message);
00502         phCHECK_RC(rc,NULL,"m_message.setMessage failed.");
00503     }
00504 
00505     /* set the Mutex id: The mutex is is already set because the handler
00506      * will only handle one mutex at a time */
00507     /* 
00508     rc = this->m_message.setMutexId(mutex_id);
00509     phCHECK_RC(rc,NULL,"m_message.setMutexId failed.");
00510     */
00511 
00512     /* send it to the client */
00513     DEBUG_PRINT("Sending message...\n");
00514      
00515     /* this->m_message.print(stderr); */
00516 
00517     rc = this->m_message.send(this->m_sock);
00518     phCHECK_RC(rc,NULL,"this->m_message.send(%p) failed.",
00519              this->m_sock );
00520     
00521     DEBUG_PRINT("Sent message.\n");
00522 
00523     /* Unlock the phClientHandler in case someone wants to do 
00524      * something with it or has been waiting to */
00525     phTHIS_UNLOCK(locked);
00526     
00527     return phSUCCESS;
00528 
00529 error:
00530     /* We're using 'locked' to tell whether we want to unlock
00531      * within this method. This thread could own it several times and
00532      * we don't want to unlock one this method doesn't own */
00533     phTHIS_ERROR_UNLOCK(locked);
00534   
00535     return phFAIL;
00536 }
00537 
00538 /* ------------------------------------------------------------------------- *
00539  * wakeup: 
00540  * ------------------------------------------------------------------------- */
00541 int phClientHandler::wakeup()
00542 {
00543     phFUNCTION("phClientHandler::wakeup")
00544     int locked = 0;
00545 
00546     /* Don't lock, we won't get through it if the handler is waiting
00547      * for messages */
00548     /* phTHIS_LOCK(locked); */
00549     
00550     phPROGRESS("client:%u\tcontroller:%u\n",
00551             this->m_client_id,
00552             this->m_controller_id );
00553     if (this->m_sock != NULL)
00554     {
00555         this->m_sock->wakeup();
00556     }
00557     
00558     /* phTHIS_UNLOCK(locked); */
00559     
00560     return phSUCCESS;
00561 }
00562   
00563 /* ------------------------------------------------------------------------- *
00564  * cleanup:
00565  * ------------------------------------------------------------------------- */
00566 int phClientHandler::cleanup()
00567 {
00568     phFUNCTION("phClientHandler::cleanup")
00569     int locked = 0;
00570 
00571     /* lock the object so we can alter things without worrying about another
00572      * thread getting to it at the same time. If we succeed, set 'locked' so
00573      * the method knows to unlock should something go wrong. */
00574     phTHIS_LOCK(locked);
00575     
00576     /* phPROGRESS("\n"); */
00577     if (this->m_sock != NULL)
00578     {
00579         if (this->m_sock->isConnected())
00580         {
00581             this->m_sock->disconnect();
00582         }
00583     }
00584     
00585     /* Free the phSocket class, it's the ClientHandler's responsibility */
00586     phDelete(this->m_sock);
00587     
00588     /* phPROGRESS("\n"); */
00589     
00590     /* Unlock the phClientHandler in case someone wants to do 
00591      * something with it or has been waiting to */
00592     phTHIS_UNLOCK(locked);
00593     
00594     return phSUCCESS;
00595 error:
00596     /* We're using 'locked' to tell whether we want to unlock
00597      * within this method. This thread could own it several times and
00598      * we don't want to unlock one this method doesn't own */
00599     phTHIS_ERROR_UNLOCK(locked);
00600     
00601     return phFAIL;
00602 }
00603     
00604 
00605 /* ------------------------------------------------------------------------- * 
00606  * error:
00607  * ------------------------------------------------------------------------- */
00608 int phClientHandler::error()
00609 {
00610     phFUNCTION("phClientHandler::error")
00611     int locked = 0;
00612 
00613     /* lock the object so we can alter things without worrying about another
00614      * thread getting to it at the same time. If we succeed, set 'locked' so
00615      * the method knows to unlock should something go wrong. */
00616     phTHIS_LOCK(locked);
00617 
00618     /* phPROGRESS("\n"); */
00619     
00620     /* Unlock the phClientHandler in case someone wants to do 
00621      * something with it or has been waiting to */
00622     phTHIS_UNLOCK(locked);
00623     
00624     return phSUCCESS;
00625 error:
00626     /* We're using 'locked' to tell whether we want to unlock
00627      * within this method. This thread could own it several times and
00628      * we don't want to unlock one this method doesn't own */
00629     phTHIS_ERROR_UNLOCK(locked);
00630     
00631     return phFAIL;
00632 }
00633 
00634 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:05 2007 for phission by  doxygen 1.4.4