#include "WorkerSendInfo.h" #include "Logger.h" #include "ProcessRename.h" #include "ShmManager.h" #include "ProcessConfig.h" #include "AliveFhsCacheThread.h" #include "SocketSendInfo.h" #include #include #include #include #include #include #include #include #include // ¿äû ¼ö½Å °ü·Ã ÃÖ´ë ´ë±â ½Ã°£. (sec) #define MAX_REQUEST_TIMEOUT 60 // °øÀ¯¸Þ¸ð¸®¿¡ Data Set, Get À» ´ã´çÇÒ °´Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅÍ. // Main.cpp ¿¡ Àü¿ªº¯¼ö·Î Á¤ÀÇ µÇ¾î ÀÖ´Ù. extern CShmManager * g_pShmManager; // FHS ÀÇ vmasd °¡ Broadcasting ÇÏ´Â °¢ FHS ÀÇ »óÅ Á¤º¸¸¦ ¼ö½Å¹Þ±â À§ÇÑ UDP Socket.... // Main.cpp ¿¡ Àü¿ªº¯¼ö·Î Á¤ÀÇ µÇ¾î ÀÖ´Ù. extern int g_sockVmasdRecv; // FHS csagentd °¡ Àü¼ÛÇÏ´Â ½Ã½ºÅÛ »óÅ Á¤º¸ ¼ö½ÅÀ» À§ÇÑ TCP Socket // Main.cpp ¿¡ Àü¿ªº¯¼ö·Î Á¤ÀÇ µÇ¾î ÀÖ´Ù. extern int g_sockSystemRecv; // FHS csagentd °¡ Àü¼ÛÇÏ´Â ¼­ºñ½º »óÅ üũ Á¤º¸ ¼ö½ÅÀ» À§ÇÑ TCP Socket // Main.cpp ¿¡ Àü¿ªº¯¼ö·Î Á¤ÀÇ µÇ¾î ÀÖ´Ù. extern int g_sockCheckRecv; // fimngd µî°ú °°Àº ¿ÜºÎ ¸ðµâ°ú Åë½ÅÀ» ÅëÇØ Á¤º¸¸¦ Àü´ÞÇϱâ À§ÇÑ TCP Socket »ý¼º. // Main.cpp ¿¡ Àü¿ªº¯¼ö·Î Á¤ÀÇ µÇ¾î ÀÖ´Ù. extern int g_sockInfoSend; // Alive FHS Cache Thread °´Ã¼ ´ëÇÑ Æ÷ÀÎÅÍ. CAliveFhsCacheThread * g_pThreadAliveFhs = NULL; // °¢ Client ¸¦ ó¸®ÇÒ Thread ¿¡ Àü´ÞÇÒ ±¸Á¶Ã¼ struct stSendInfoThreadArg { // client socket descriptor int clientSocketDesc; // Client ÀÇ IP ÁÖ¼Ò Á¤º¸¸¦ ÀúÀåÇÑ º¯¼ö // - °øÀ¯¸Þ¸ð¸® client_ip Ç׸ñ Å©±â¿Í µ¿ÀÏÇÑ Å©±â·Î ¼³Á¤. char szClientAddress[IP_ADDR_LENGTH]; }; // ÇÁ·Î¼¼½º Á¾·á Àü ó¸®ÇÒ Á¾·á °ü·Ã °¢ ÀÛ¾÷À» Àϰý·Î ó¸®Çϱâ À§ÇÑ ÇÔ¼ö. void ReadyToExitWorkerSendInfo() { // open µÈ socket °ü·Ã Close ó¸® if( g_sockInfoSend != -1 ) close( g_sockInfoSend ); // Logger °´Ã¼ Á¾·á ó¸®. CLogger::Exit(); return; } // Worker SendInfo ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ´ëÇÑ Á¾·á ó¸® ¼ö½Å½Ã. static void SignalWorkerSendInfoTerminate( int nSignalNumber ) { // Signal Number ¿¡ µû¸¥ ·Î±ëó¸®. if( nSignalNumber == SIGTERM ) { _LOG( LINF, "[SendInfo:%d] Process exit by SIGTERM signal. Good Bye..", getpid() ); } else { _LOG( LWAR, "[SendInfo:%d] Process exit by abnormal signal[%d], Good Bye..", getpid(), nSignalNumber ); } ReadyToExitWorkerSendInfo(); // Á¾·áÀü Àá½Ã ´ë±â struct timespec sleep; sleep.tv_sec = 0; sleep.tv_nsec = 500000000; // 0.5 sec nanosleep( &sleep, NULL ); exit( EXIT_SUCCESS ); } // Worker::SendInfo Process ÀÇ signal 󸮱â... void SetWorkerSendInfoSignalHandler() { sigset_t set; struct sigaction act; memset( &act, 0x00, sizeof( act ) ); sigfillset( &set ); sigprocmask( SIG_SETMASK, &set, NULL ); sigfillset( &act.sa_mask ); // ¹«½Ã ó¸® signal act.sa_handler = SIG_IGN; sigaction( SIGPIPE, &act, NULL ); /* desciptor ¿À·ù ¹ß»ý½Ã Process°¡ Á×´Â °ÍÀº ¹æÁöÇϱâ À§ÇÏ¿© ¼³Á¤ */ sigaction( SIGHUP, &act, NULL ); /* process¸¦ ±âµ¿½ÃŲ °ü¸®ÀÚÀÇ ·Î±×¾Æ¿ô½Ã, ¶Ç´Â config reload µîÀÇ Ã³¸® signal*/ sigaction( SIGINT, &act, NULL ); /* ^C ۸¦ ´©¸¥ °æ¿ì ¹Þ´Â ½ÅÈ£ => demon À¸·Î ±âµ¿µÇ±â ¶«½Ã ÀÌ ½ÅÈ£ ¸ø¹ÞÀ½ */ sigaction( SIGQUIT, &act, NULL ); /* Űº¸µå¿¡ ÀÇÇÑ Abort ½ÅÈ£ ó¸® => ? */ // Worker ÇÁ·Î¼¼½º´Â ÀÚ½Ä ÇÁ·Î¼¼½º°¡ Á¸ÀçÇÏÁö ¾ÊÀ¸¹Ç·Î ±×³É ¹«½Ãó¸®ÇÔ. act.sa_handler = SIG_IGN; sigaction( SIGCHLD, &act, NULL ); /* °¢Á¾ ¿¡·¯³ª »ç¿ëÀÚÀÇ Á¾·á ½ÅÈ£ ó¸® */ act.sa_handler = SignalWorkerSendInfoTerminate; sigaction( SIGTERM, &act, NULL ); /* kill -TERM ¿¡ ÀÇÇÑ ÇÁ·Î¼¼½º Á¾·á½Ã */ // ³ª¸ÓÁö ½ÅÈ£´Â default ó¸®. sigemptyset( &set ); /* ½ÅÈ£ 󸮱â ó¸® ¼³Á¤ À§ÇÑ ºí·Ï ÇØÁ¦ */ sigprocmask( SIG_SETMASK, &set, NULL ); } // Worker::SendInfo ¿¡¼­ °¢ Client ¿¡ ´ëÇÑ Ã³¸®¸¦ ¼öÇàÇϱâ À§ÇÑ Thread. void * WorkerSendInfoClientThread( void * arg ) { // Àü´Þ¹ÞÀº º¯¼ö¸¦ ³»ºÎ º¯¼ö¿¡ ÀúÀå ó¸®. // client socket °ü·Ã ó¸® º¯¼ö »ý¼º CSocketSendInfo clientSocket( ( ( struct stSendInfoThreadArg * ) arg )->clientSocketDesc ); // client ÁÖ¼Ò Ã³¸® °ü·Ã char szClientAddress[IP_ADDR_LENGTH]; memcpy( szClientAddress, ( ( struct stSendInfoThreadArg * ) arg )->szClientAddress, IP_ADDR_LENGTH ); // malloc ·Î »ý¼ºµÈ º¯¼ö ÇØÁ¦ ó¸® free( arg ); // º» thead ´Â client ¿¬°á »óÅ¿¡ µû¶ó Á¾·áµÇ¹Ç·Î.. process ¿¡¼­ ºÐ¸® ó¸® pthread_detach( pthread_self() ); _LOG( LINF, "[SendInfo:%d] client thread start. [%s]", getpid(), szClientAddress ); // ¼Û¼ö½Å ó¸® °ü·Ã º¯¼ö int nResult; char command; // hostname ¼ö½Å Á¤º¸¸¦ ÀúÀåÇϱâ À§ÇÑ º¯¼ö. std::string strHostname; // Alive FHS ¸ñ·ÏÁ¤º¸ ÀúÀå 󸮸¦ À§ÇÑ vector std::vector vecAliveFhs; // socket ¼ö½Å ´ë±â while( 1 ) { // ¿äû ¼ö½Å ´ë±â nResult = clientSocket.GetPacketHeader( command, MAX_REQUEST_TIMEOUT ); if( nResult == 0 ) { // timeout ¹ß»ý½Ã... // - server ¸ðµå·Î µ¿ÀÛÇϹǷÎ... ÁöÁ¤µÈ ½Ã°£µ¿¾È ¿äûÀÌ ¾ø´Â °æ¿ì ¼¼¼ÇÀ» Á¾·á ó¸®ÇÑ´Ù. _LOG( LINF, "[SendInfo:%d] client[%s] request timeout[%d]. session close.", getpid(), szClientAddress, MAX_REQUEST_TIMEOUT ); break; } else if( nResult < 0 ) { // Socket Á¾·á, ¿À·ù ¶Ç´Â Á¤ÀǵÇÁö ¾ÊÀº Çü½ÄÀÇ ÆÐŶ header ¼ö½Å½Ã... // ¿À·ù ³»¿ªÀº socket ¸ðµâ¿¡¼­ ·Î±ëÇϹǷÎ... ±×³É Á¾·á ó¸®. break; } else { // Á¤»ó header ¼ö½Å½Ã. // - ¼ö½ÅµÈ command ¿¡ µû¸¥ ó¸®. if( command == COMMAND_ALIVE_FHS ) { // Alive FHS ¸ñ·Ï ¿äûÀÎ °æ¿ì.. // Body ºÎºÐ¿¡ ´ëÇÑ Ã³¸®. // - °¢ protocol version º° ó¸®. if( clientSocket.GetPacketBodyAliveFhs( strHostname ) == false ) { // Data ¼ö½Å ½ÇÆÐ, Áö¿øÇÏÁö ¾Ê´Â protocol version ¶Ç´Â RC ID Á¤º¸°¡ ´Ù¸¥ °æ¿ì.... // - ¼¼¼Ç Á¾·á ó¸®. // - ¿À·ù ³»¿ªÀº À§ÀÇ ÇØ´ç ÇÔ¼ö¿¡¼­ client ·Î Àü¼Û ó¸®ÇÔ. LOG( LERR, "[SendInfo:%d] client[%s] alive fhs request body fail. session close.", getpid(), szClientAddress ); break; } // Alive FHS ¸ñ·Ï Á¶È¸. vecAliveFhs.clear(); if( g_pThreadAliveFhs->GetAliveFhs( vecAliveFhs ) == -1 ) { // °øÀ¯¸Þ¸ð¸®ÀÇ FHS Á¤º¸°¡ ¾ÆÁ÷ ºÒ¿ÏÀüÇÏ¿© SKIP ó¸®ÇØ¾ß ÇÏ´Â °æ¿ì. if( clientSocket.SendResultAliveFhsSkip() == false ) { // Àü¼Û ½ÇÆÐ ¹ß»ý½Ã. LOG( LERR, "[SendInfo:%d] client[%s][%s] alive fhs skip send error. session close." , getpid(), szClientAddress, strHostname.c_str() ); break; } } else { // Alive FHS ¸ñ·Ï Àü¼Û ó¸®. if( clientSocket.SendResultAliveFhs( vecAliveFhs ) == false ) { // Àü¼Û ½ÇÆÐ ¹ß»ý½Ã. LOG( LERR, "[SendInfo:%d] client[%s][%s] alive fhs send error. session close." , getpid(), szClientAddress, strHostname.c_str() ); break; } else { // Àü¼Û ¼º°ø½Ã _LOG( LDBG, "[SendInfo:%d] client[%s][%s] alive fhs send ok. fhs count[%zu]" , getpid(), szClientAddress, strHostname.c_str(), vecAliveFhs.size() ); } } } else { // Á¤ÀǵÇÁö ¾ÊÀº command ÀÎ °æ¿ì.. // - ¿À·ù ·Î±ë ÈÄ ¼¼¼Ç Á¾·á ó¸®. LOG( LERR, "[SendInfo:%d] client[%s] request type not defined. session close.", getpid(), szClientAddress ); clientSocket.PrintHeaderToLog(); break; } } } // client ¿Í ¿¬°á Á¾·á ó¸®. clientSocket.Close(); _LOG( LINF, "[SendInfo:%d] client connection closed. [%s]", getpid(), szClientAddress ); // Thread Á¾·á °ü·Ã ó¸®. return NULL; } // Worker::SendInfo ÇÁ·Î¼¼½ºÀÇ Main ¿ªÈ°À» ¼öÇàÇϱâ À§ÇÑ ÇÔ¼ö. int WorkerSendInfoMain() { // Àü¿ª º¯¼ö·Î ¼³Á¤µÈ socket Áß ÇØ´ç worker ¿¡¼­ »ç¿ëÇÏÁö ¾Ê´Â socket Àº close ó¸®ÇÑ´Ù. if( g_sockVmasdRecv != -1 ) { close( g_sockVmasdRecv ); g_sockVmasdRecv = -1; } if( g_sockSystemRecv != -1 ) { close( g_sockSystemRecv ); g_sockSystemRecv = -1; } if( g_sockCheckRecv != -1 ) { close( g_sockCheckRecv ); g_sockCheckRecv = -1; } // Process Rename.. set_ps_display( PROG_NAME": SendInfo", false ); // Set Signal Handler SetWorkerSendInfoSignalHandler(); // »ç¿ëÇÒ °´Ã¼ ÃʱâÈ­ ó¸® // Alive FHS ¸ñ·ÏÀ» ÁÖ±âÀûÀ¸·Î ÃßÃâÇÒ Thread ¸ðµâ ÃʱâÈ­ ¹× ±âµ¿ ó¸®. CAliveFhsCacheThread threadAliveFhsCache( g_pShmManager ); if( threadAliveFhsCache.Start() == false ) { _LOG( LWAR, "[SendInfo:%d] alive fhs cache thread create failed. => Process Exit", getpid() ); ReadyToExitWorkerSendInfo(); return EXIT_FAILURE; // EXIT_FAILURE ¸¦ ¹ÝȯÇÏ¿© Àç»ý¼º ó¸® ¹æÁö... } // °¢ Client thread ¿¡¼­ ÇØ´ç °´Ã¼ Á¢±ÙÀÌ °¡´ÉÅä·Ï Àü¿ª Æ÷ÀÎÅÍ¿¡ ÀúÀå ó¸®. g_pThreadAliveFhs = &threadAliveFhsCache; // Á¢¼Ó Client ¿¡ ´ëÇÑ Ã³¸®. int clientSock; struct sockaddr_in clientSockAddr; socklen_t clientSockLen = sizeof( clientSockAddr ); pthread_t clientThreadId; struct stSendInfoThreadArg * pThreadArg = NULL; while( 1 ) { clientSock = accept( g_sockInfoSend, ( struct sockaddr * ) &clientSockAddr, &clientSockLen ); if( clientSock == -1 ) { // ¿À·ù ¹ß»ý½Ã.... ÇØ´ç ³»¿ª ·Î±ë ó¸®. int errorNum = errno; LOG( LERR, "[SendInfo:%d] client accept failed [%d][%s]", getpid(), errorNum, strerror( errorNum ) ); } else { // Á¤»óÀûÀÎ Client ÀÎ °æ¿ì... // ó¸® Thread ·Î Àü´ÞÇÒ º¯¼ö¸¦ malloc ·Î »ý¼º ó¸® pThreadArg = ( struct stSendInfoThreadArg * ) malloc( sizeof( struct stSendInfoThreadArg ) ); if( pThreadArg == NULL ) { int errorNum = errno; close( clientSock ); // client Á¢¼Ó Á¾·á ó¸®. char tempBuffer[IP_ADDR_LENGTH]; memset( tempBuffer, 0x00, sizeof( tempBuffer ) ); if( inet_ntop( AF_INET, &( clientSockAddr.sin_addr ), tempBuffer, sizeof( tempBuffer ) ) != NULL ) { LOG( LERR, "[SendInfo:%d] client[%s] thread malloc failed [%d][%s]", getpid(), tempBuffer, errorNum, strerror( errorNum ) ); } else { LOG( LERR, "[SendInfo:%d] client thread malloc failed [%d][%s] and inet_ntop error[%d][%s]" , getpid(), errorNum, strerror( errorNum ), errno, strerror( errno ) ); } continue; } else { // ÀÎÀÚ·Î Àü´ÞÇÒ º¯¼öÁ¤º¸ ¼³Á¤. pThreadArg->clientSocketDesc = clientSock; char tempBuffer[IP_ADDR_LENGTH]; memset( tempBuffer, 0x00, sizeof( tempBuffer ) ); if( inet_ntop( AF_INET, &( clientSockAddr.sin_addr ), tempBuffer, sizeof( tempBuffer ) ) != NULL ) { memcpy( pThreadArg->szClientAddress, tempBuffer, sizeof( tempBuffer ) ); } else { // inet_ntop ¿À·ù ¹ß»ý½Ã // - IP Á¤º¸´Â ±×³É ·Î±ë ¸ñÀûµîÀ¸·Î Àü´ÞµÇ´Â Á¤º¸À̹ǷÎ.. 0.0.0.0 À¸·Î ¼³Á¤ ó¸®ÇÑ´Ù. int errorNum = errno; LOG( LERR, "[SendInfo:%d] client ip not valid. inet_ntop error[%d][%s]", getpid(), errorNum, strerror( errorNum ) ); snprintf( pThreadArg->szClientAddress, IP_ADDR_LENGTH - 1, "0.0.0.0" ); } // Client 󸮸¦ ´ã´çÇÒ Thread »ý¼º ó¸® if( pthread_create( &clientThreadId, NULL, WorkerSendInfoClientThread, (void *)pThreadArg ) != 0 ) { // »ý¼º ½ÇÆÐ½Ã... // - ·Î±ë // - client socket close // - malloc ·Î »ý¼ºµÈ Àü´Þ º¯¼ö free ó¸®. int errorNum = errno; LOG( LERR, "[SendInfo:%d] client[%s] thread create failed [%d][%s]" , getpid(), pThreadArg->szClientAddress, errorNum, strerror( errorNum ) ); close( clientSock ); free( pThreadArg ); } else { _LOG( LDBG, "[SendInfo:%d] client[%s] accept & client thread create ok.", getpid(), pThreadArg->szClientAddress ); } } } } // while(1) // Á¾·á½Ã Á¤¸® ÀÛ¾÷ ¼öÇà ReadyToExitWorkerSendInfo(); return EXIT_SUCCESS; }