UdpLogger.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 //
00003 // UdpLogger.cpp: implementation of a simple UDP Logger object.
00004 //
00005 // Author: FESA team
00007 //
00008 //  May 2007
00009 //      - added to the FESA Framework for the DIAGNOSTIC protoyping
00010 //
00011 #include <fesa-core/Exception/FesaException.h>
00012 #include <fesa-core/Diagnostic/UdpLogger.h>
00013 #include <signal.h>
00014 #include <string>
00015 #include <cstring>
00016 
00017 namespace fesa
00018 {
00019 
00020     UdpLogger::UdpLogger(const char* hostname, unsigned short& port, const bool connectMode) : udpConn(connectMode)
00021     {
00022 
00023         // init of the UDP channel
00024         hostent* host = gethostbyname(const_cast<char *> (hostname));
00025         if (strlen(hostname) && (host != NULL))
00026         {
00027 
00028             if ((udpSock = socket(AF_INET, SOCK_DGRAM, 0)) != -1)
00029             {
00030 
00031                 if (port == 0)
00032                 {
00033                     //Dynamic allocation: need to find a port number
00034 
00035                     udpAttr.sin_addr.s_addr = htonl(INADDR_ANY);
00036                     udpAttr.sin_family = AF_INET;
00037                     udpAttr.sin_port = htons(port);
00038 
00039                     if (bind(udpSock, (struct sockaddr *) &udpAttr, sizeof(udpAttr)) != -1)
00040                     {
00041 
00042                         socklen_t slen = sizeof(udpAttr);
00043                         if (getsockname(udpSock, (struct sockaddr*) &udpAttr, &slen) != -1)
00044                         {
00045                             port = udpAttr.sin_port; // retrieve allocated port number
00046                         }
00047                         else
00048                         {
00049                             std::string errMsg("UdpLogger constructor/ getsockname failed: " + std::string(strerror(
00050                                             errno)));
00051                             throw FesaException(__FILE__, __LINE__, "FESA_FWK");
00052                         }
00053                     }
00054                     else
00055                     {
00056                         std::string errMsg("UdpLogger constructor/ bind failed: " + std::string(strerror(errno)));
00057                         throw FesaException(__FILE__, __LINE__, "FESA_FWK");
00058                     }
00059                 }
00060 
00061                 udpAttr.sin_addr.s_addr = (int32_t) *((int32_t *) host->h_addr);
00062                 udpAttr.sin_family = AF_INET;
00063                 udpAttr.sin_port = htons(port);
00064 
00065                 // TODO change these exceptions
00066                 // to receive ICMP "not reachable" if nobody is listening
00067                 if (udpConn)
00068                 {
00069                     if (connect(udpSock, (struct sockaddr *) &udpAttr, sizeof(udpAttr)) < 0)
00070                     {
00071                         std::string errMsg("UdpLogger constructor/ connect failed: " + std::string(strerror(errno)));
00072                         throw FesaException(__FILE__, __LINE__, "FESA_FWK");
00073                     }
00074                 }
00075             }
00076             else
00077             {
00078                 std::string errMsg("UdpLogger constructor/ socket failed: " + std::string(strerror(errno)));
00079                 throw FesaException(__FILE__, __LINE__, "FESA_FWK");
00080             }
00081         }
00082         else
00083         { //host unknown
00084             throw FesaException(__FILE__, __LINE__, "FESA_FWK");
00085         }
00086     }
00087     ;
00088 
00089     UdpLogger::~UdpLogger()
00090     {
00091 
00092         if (close(udpSock) < 0)
00093         {
00094             std::string errMsg("UdpLogger destructor/ close failed: " + std::string(strerror(errno)));
00095             throw FesaException(__FILE__, __LINE__, "FESA_FWK");
00096         }
00097     }
00098     ;
00099 
00100     int32_t UdpLogger::sendStr(const char* msg)
00101     {
00102 
00103         //This method send a UDP frame which should not excedd 8Kb to garantee atomic send.
00104         //Iterative send (size > MAX_UDP_SEND_SIZE(~8Kb)) is not safe but can be tolerate
00105         //for rare case of large config/state files.
00106 
00107         //sendStr expects string format (null terminated buffer)
00108         /*send will fail (<0) if no listener or bad UDP channel*/
00109         if (udpConn)
00110         {
00111             //catch SIGPIPE to prevent process exit when client disconnect during sending!
00112             //be careful: this protection could interfer with middle-ware if connected mode is used!
00113             void (*sigpipeHandler)(int32_t);
00114             sigpipeHandler = signal(SIGPIPE, (void(*)(int32_t)) SIG_IGN);
00115 
00116             //connected mode
00117             if (send(udpSock, msg, strlen(msg) + 1, 0) < 0)
00118                 return (errno);
00119 
00120             //restore old handler
00121             signal(SIGPIPE, (void(*)(int32_t)) sigpipeHandler);
00122         }
00123         else
00124         {
00125             //not-connected mode
00126             if (sendto(udpSock, msg, strlen(msg) + 1, 0, (struct sockaddr *) &udpAttr, sizeof(udpAttr)) < 0)
00127                 return (errno);
00128         }
00129 
00130         return 0;
00131     }
00132     ;
00133 }
00134 

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1