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 |