int DNS::connect( const std::string& host, unsigned short port, const LogSink& logInstance ) { int fd = getSocket(); if( fd < 0 ) return fd; struct hostent* h; if( ( h = gethostbyname( host.c_str() ) ) == 0 ) { cleanup(); return -ConnDnsError; } struct sockaddr_in target; target.sin_family = AF_INET; target.sin_port = htons( port ); if( h->h_length != sizeof( struct in_addr ) ) { cleanup(); return -ConnDnsError; } else { memcpy( &target.sin_addr, h->h_addr, sizeof( struct in_addr ) ); } #ifndef _WIN32_WCE std::ostringstream oss; #endif memset( target.sin_zero, '\0', 8 ); if( ::connect( fd, (struct sockaddr *)&target, sizeof( struct sockaddr ) ) == 0 ) { #ifndef _WIN32_WCE oss << "connecting to " << host.c_str() << " (" << inet_ntoa( target.sin_addr ) << ":" << port << ")"; logInstance.dbg( LogAreaClassDns, oss.str() ); #endif return fd; } #ifndef _WIN32_WCE oss << "connection to " << host.c_str() << " (" << inet_ntoa( target.sin_addr ) << ":" << port << ") failed"; logInstance.dbg( LogAreaClassDns, oss.str() ); #endif closeSocket( fd ); return -ConnConnectionRefused; }
int DNS::connect( const std::string& host, int port, const LogSink& logInstance ) { struct addrinfo hints, *servinfo, *p; int rv = 0; int fd = 0; memset( &hints, 0, sizeof( hints ) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if( ( rv = getaddrinfo( host.c_str(), util::int2string( port ).c_str(), &hints, &servinfo ) ) != 0 ) { logInstance.dbg( LogAreaClassDns, "getaddrinfo() failed for " + host + "." ); return -ConnDnsError; } for( p = servinfo; p != 0; p = p->ai_next ) { if( ( fd = getSocket( p->ai_family, p->ai_socktype, p->ai_protocol, logInstance ) ) == -1 ) { continue; } if( ::connect( fd, p->ai_addr, p->ai_addrlen ) == -1 ) { closeSocket( fd, logInstance ); continue; } break; } if( p == 0 ) { freeaddrinfo( servinfo ); std::string message = "Connection to " + host + ":" + util::int2string( port ) + " failed. " #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) "WSAGetLastError: " + util::int2string( ::WSAGetLastError() ); #else "errno: " + util::int2string( errno ) + ": " + strerror( errno ); #endif logInstance.dbg( LogAreaClassDns, message ); return -ConnConnectionRefused; } freeaddrinfo( servinfo ); return fd; }
DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { logInstance.warn( LogAreaClassDns, "notice: gloox does not support SRV " "records on this platform. Using A records instead." ); return defaultHostMap( domain, logInstance ); }
int DNS::connect( const std::string& host, const LogSink& logInstance ) { struct addrinfo* results = 0; resolve( &results, host, logInstance ); if( !results ) { logInstance.err( LogAreaClassDns, "host not found: " + host ); return -ConnDnsError; } struct addrinfo* runp = results; while( runp ) { int fd = DNS::connect( runp, logInstance ); if( fd >= 0 ) return fd; runp = runp->ai_next; } freeaddrinfo( results ); return -ConnConnectionRefused; }
int DNS::getSocket( int af, int socktype, int proto, const LogSink& logInstance ) { #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) SOCKET fd; #else int fd; #endif if( ( fd = socket( af, socktype, proto ) ) == INVALID_SOCKET ) { std::string message = "getSocket( " + util::int2string( af ) + ", " + util::int2string( socktype ) + ", " + util::int2string( proto ) + " ) failed. " #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) "WSAGetLastError: " + util::int2string( ::WSAGetLastError() ); #else "errno: " + util::int2string( errno ) + ": " + strerror( errno ); #endif logInstance.dbg( LogAreaClassDns, message ); cleanup( logInstance ); return -ConnConnectionRefused; } #ifdef HAVE_SETSOCKOPT int timeout = 5000; int reuseaddr = 1; setsockopt( fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof( timeout ) ); setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof( reuseaddr ) ); #endif return (int)fd; }
int DNS::connect( const std::string& domain, const LogSink& logInstance ) { logInstance.log( LogLevelWarning, LogAreaClassDns, "note: gloox does not support SRV records on this platform." ); return DNS::connect( domain, XMPP_PORT, logInstance ); }
int DNS::connect( const std::string& domain, int port, const LogSink& logInstance ) { #ifdef WIN32 WSADATA wsaData; if( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) != 0 ) return -DNS_COULD_NOT_RESOLVE; #endif struct protoent* prot; if( ( prot = getprotobyname( "tcp" ) ) == 0 ) { cleanup(); return -DNS_COULD_NOT_RESOLVE; } int fd; if( ( fd = socket( PF_INET, SOCK_STREAM, prot->p_proto ) ) == -1 ) { cleanup(); return -DNS_COULD_NOT_CONNECT; } struct hostent *h; if( ( h = gethostbyname( domain.c_str() ) ) == 0 ) { cleanup(); return -DNS_COULD_NOT_RESOLVE; } struct sockaddr_in target; target.sin_family = AF_INET; target.sin_port = htons( port ); if( h->h_length != sizeof( struct in_addr ) ) { cleanup(); return -DNS_COULD_NOT_RESOLVE; } else { memcpy( &target.sin_addr, h->h_addr, sizeof( struct in_addr ) ); } std::ostringstream oss; oss << "resolved " << domain.c_str() << " to: " << inet_ntoa( target.sin_addr ); logInstance.log( LogLevelDebug, LogAreaClassDns, oss.str() ); memset( target.sin_zero, '\0', 8 ); if( ::connect( fd, (struct sockaddr *)&target, sizeof( struct sockaddr ) ) == 0 ) return fd; #ifndef WIN32 close( fd ); #else closesocket( fd ); cleanup(); #endif return -DNS_COULD_NOT_CONNECT; }
void test_single_thread(int count) { Log::createIt(logSink); test_log(*Log::it(), count); std::time_t time = std::time(0); time += 3600*24; logSink->rotate(time); test_log(*Log::it(), count); time += 3600*24; logSink->rotate(time); test_log(*Log::it(), count); Log::destroyIt(); }
int DNS::connect( const std::string& domain, const LogSink& logInstance ) { HostMap hosts = resolve( domain ); if( hosts.size() == 0 ) return -DNS_NO_HOSTS_FOUND; struct protoent* prot; if( ( prot = getprotobyname( "tcp" ) ) == 0) return -DNS_COULD_NOT_RESOLVE; int fd; if( ( fd = socket( PF_INET, SOCK_STREAM, prot->p_proto ) ) == -1 ) return -DNS_COULD_NOT_RESOLVE; struct hostent *h; struct sockaddr_in target; target.sin_family = AF_INET; int ret = 0; HostMap::const_iterator it = hosts.begin(); for( ; it != hosts.end(); ++it ) { int port; if( (*it).second == 0 ) port = XMPP_PORT; else port = (*it).second; target.sin_port = htons( port ); if( ( h = gethostbyname( (*it).first.c_str() ) ) == 0 ) { ret = -DNS_COULD_NOT_RESOLVE; continue; } in_addr *addr = (in_addr*)malloc( sizeof( in_addr ) ); memcpy( addr, h->h_addr, sizeof( in_addr ) ); char *tmp = inet_ntoa( *addr ); free( addr ); std::ostringstream oss; oss << "resolved " << (*it).first.c_str() << " to: " << tmp << ":" << port; logInstance.log( LogLevelDebug, LogAreaClassDns, oss.str() ); if( inet_aton( tmp, &(target.sin_addr) ) == 0 ) continue; memset( target.sin_zero, '\0', 8 ); if( ::connect( fd, (struct sockaddr *)&target, sizeof( struct sockaddr ) ) == 0 ) return fd; close( fd ); } if( ret ) return ret; return -DNS_COULD_NOT_CONNECT; }
int DNS::connect( struct addrinfo* res, const LogSink& logInstance ) { if( !res ) return -1; int fd = getSocket( res->ai_family, res->ai_socktype, res->ai_protocol, logInstance ); if( fd < 0 ) return fd; if( ::connect( fd, res->ai_addr, res->ai_addrlen ) == 0 ) { char ip[NI_MAXHOST]; char port[NI_MAXSERV]; if( getnameinfo( res->ai_addr, res->ai_addrlen, ip, sizeof( ip ), port, sizeof( port ), NI_NUMERICHOST | NI_NUMERICSERV ) ) { //FIXME do we need to handle this? How? Can it actually happen at all? // printf( "could not get numeric hostname"); } if( res->ai_canonname ) logInstance.dbg( LogAreaClassDns, std::string( "Connecting to " ).append( res->ai_canonname ).append( " (" ).append( ip ).append( "), port " ).append( port ) ); else logInstance.dbg( LogAreaClassDns, std::string( "Connecting to " ).append( ip ).append( ":" ).append( port ) ); return fd; } std::string message = "connect() failed. " #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) "WSAGetLastError: " + util::int2string( ::WSAGetLastError() ); #else "errno: " + util::int2string( errno ) + ": " + strerror( errno ); #endif logInstance.dbg( LogAreaClassDns, message ); closeSocket( fd, logInstance ); return -ConnConnectionRefused; }
void DNS::resolve( struct addrinfo** res, const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { logInstance.dbg( LogAreaClassDns, "Resolving: _" + service + "._" + proto + "." + domain ); struct addrinfo hints; if( proto == "tcp" ) hints.ai_socktype = SOCK_STREAM; else if( proto == "udp" ) hints.ai_socktype = SOCK_DGRAM; else { logInstance.err( LogAreaClassDns, "Unknown/Invalid protocol: " + proto ); } memset( &hints, '\0', sizeof( hints ) ); hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; int e = getaddrinfo( domain.c_str(), service.c_str(), &hints, res ); if( e ) logInstance.err( LogAreaClassDns, "getaddrinfo() failed" ); }
int main( int /*argc*/, char** /*argv*/ ) { int fail = 0; std::string name; LogSink ls; FakeConnection* fc = new FakeConnection(); ConnectionBOSH* cb = new ConnectionBOSH( fc, ls, "example.net" ,"example.net" ); FakeClientBase* fcb = new FakeClientBase( cb ); ls.registerLogHandler( LogLevelDebug, LogAreaAll, fcb ); // ------- name = "connect"; fc->setTest( 1 ); cb->connect(); fcb->doLoop(); if( 1 ) { ++fail; // printf( "test '%s' failed\n", name.c_str() ); } delete cb; delete fcb; if( fail == 0 ) { printf( "ConnectionBOSH: OK\n" ); return 0; } else { printf( "ConnectionBOSH: %d test(s) failed\n", fail ); return 1; } }
void DNS::cleanup( const LogSink& logInstance ) { #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) if( WSACleanup() != 0 ) { logInstance.dbg( LogAreaClassDns, "WSACleanup() failed. WSAGetLastError: " + util::int2string( ::WSAGetLastError() ) ); } #else (void)logInstance; #endif }
static void GLAPIENTRY _gl_debug_proc( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* user_param) { LogSink* self = static_cast<LogSink*>(user_param); assert(self); if(self->_callback) { CallbackData data; data.source = DebugOutputARBSource(source); data.type = DebugOutputARBType(type); data.id = id; data.severity = DebugOutputARBSeverity(severity); data.length = length; data.message = message; self->_callback(data); } }
DNS::HostMap DNS::defaultHostMap( const std::string& domain, const LogSink& logInstance ) { HostMap server; logInstance.warn( LogAreaClassDns, "notice: no SRV record found for " + domain + ", using default port." ); if( !domain.empty() ) server[domain] = XMPP_PORT; return server; }
int DNS::getSocket( const LogSink& logInstance ) { #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) WSADATA wsaData; if( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) != 0 ) { logInstance.dbg( LogAreaClassDns, "WSAStartup() failed. WSAGetLastError: " + util::int2string( ::WSAGetLastError() ) ); return -ConnDnsError; } #endif int protocol = IPPROTO_TCP; #if !defined( __APPLE__ ) // Sandboxing on Apple doesn't like you to use getprotobyname struct protoent* prot; if( ( prot = getprotobyname( "tcp" ) ) != 0 ) { protocol = prot->p_proto; } else { std::string message = "getprotobyname( \"tcp\" ) failed. " #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) "WSAGetLastError: " + util::int2string( ::WSAGetLastError() ) #else "errno: " + util::int2string( errno ) + ": " + strerror( errno ); #endif + ". Falling back to IPPROTO_TCP: " + util::int2string( IPPROTO_TCP ); logInstance.dbg( LogAreaClassDns, message ); // Do not return an error. We'll fall back to IPPROTO_TCP. } #endif // !defined( __APPLE__ ) return getSocket( PF_INET, SOCK_STREAM, protocol, logInstance ); }
int main() { logSink = LogSinkImpl::create("/tmp", "testnew"); logSink->start(); // logSink->write_direct('E', "[TEST] ", "This is\nmultiline\nprotobuf error"); Timer start; # ifdef LINKO_LOG_MT test_multi_thread(); # else test_single_thread(10000); test_single_thread_old(10000); # endif int dur = Timer::now() - start; std::cout << "Test finished in " << dur << " usec" << std::endl; }
void DNS::closeSocket( int fd, const LogSink& logInstance ) { #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) int result = closesocket( fd ); #else int result = close( fd ); #endif if( result != 0 ) { std::string message = "closeSocket() failed. " #if defined( _WIN32 ) && !defined( __SYMBIAN32__ ) "WSAGetLastError: " + util::int2string( ::WSAGetLastError() ); #else "errno: " + util::int2string( errno ) + ": " + strerror( errno ); #endif logInstance.dbg( LogAreaClassDns, message ); } }
int DNS::connect( struct addrinfo* res, const LogSink& logInstance ) { if( !res ) return -1; int fd = getSocket( res->ai_family, res->ai_socktype, res->ai_protocol ); if( fd < 0 ) return fd; if( ::connect( fd, res->ai_addr, res->ai_addrlen ) == 0 ) { char ip[NI_MAXHOST]; char port[NI_MAXSERV]; if( getnameinfo( res->ai_addr, sizeof( sockaddr ), ip, sizeof( ip ), port, sizeof( port ), NI_NUMERICHOST | NI_NUMERICSERV ) ) { //FIXME do we need to handle this? How? Can it actually happen at all? // printf( "could not get numeric hostname"); } std::ostringstream oss; oss << "Connecting to "; if( res->ai_canonname ) { oss << res->ai_canonname; oss << " (" << ip << "), port " << port; } else { oss << ip << ":" << port; } logInstance.dbg( LogAreaClassDns, oss.str() ); return fd; } closeSocket( fd ); return -ConnConnectionRefused; }
DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { const std::string dname = "_" + service + "._" + proto + "." + domain; bool error = false; DNS::HostMap servers; DNS_RECORD* pRecord = NULL; DNS_STATUS status = DnsQuery_UTF8( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL ); if( status == ERROR_SUCCESS ) { // NOTE: DnsQuery_UTF8 and DnsQuery_A really should have been defined with // PDNS_RECORDA instead of PDNS_RECORD, since that's what it is (even with _UNICODE defined). // We'll correct for that mistake with a cast. DNS_RECORDA* pRec = (DNS_RECORDA*)pRecord; do { if( pRec->wType == DNS_TYPE_SRV ) { servers[pRec->Data.SRV.pNameTarget] = pRec->Data.SRV.wPort; } pRec = pRec->pNext; } while( pRec != NULL ); DnsRecordListFree( pRecord, DnsFreeRecordList ); } else { logInstance.warn( LogAreaClassDns, "DnsQuery_UTF8() failed: " + util::int2string( status ) ); error = true; } if( error || !servers.size() ) { servers = defaultHostMap( domain, logInstance ); } return servers; }
void test_multi_thread() { boost::thread thr1(mt_test_proc); # if 1 boost::thread thr2(mt_test_proc); boost::thread thr3(mt_test_proc); boost::thread thr4(mt_test_proc); boost::thread thr5(mt_test_proc); sleep(4); std::time_t time = std::time(0); time += 3600*24; logSink->rotate(time); thr5.join(); thr4.join(); thr3.join(); thr2.join(); # endif thr1.join(); }
TEST(Logger, Basic) { InterlinkedTestNodesWithSysClock nodes; uavcan::Logger logger(nodes.a); ASSERT_EQ(uavcan::protocol::debug::LogLevel::ERROR, logger.getLevel()); LogSink sink; // Will fail - types are not registered uavcan::GlobalDataTypeRegistry::instance().reset(); ASSERT_GT(0, logger.logError("foo", "Error (fail - type is not registered)")); ASSERT_EQ(0, logger.logDebug("foo", "Debug (ignored - low logging level)")); ASSERT_FALSE(logger.getExternalSink()); logger.setExternalSink(&sink); ASSERT_EQ(&sink, logger.getExternalSink()); uavcan::GlobalDataTypeRegistry::instance().reset(); uavcan::DefaultDataTypeRegistrator<uavcan::protocol::debug::LogMessage> _reg1; SubscriberWithCollector<uavcan::protocol::debug::LogMessage> log_sub(nodes.b); ASSERT_LE(0, log_sub.start()); // Sink test ASSERT_EQ(0, logger.logDebug("foo", "Debug (ignored due to low logging level)")); ASSERT_TRUE(sink.msgs.empty()); sink.level = uavcan::protocol::debug::LogLevel::DEBUG; ASSERT_EQ(0, logger.logDebug("foo", "Debug (sink only)")); ASSERT_TRUE(sink.popMatchByLevelAndText(uavcan::protocol::debug::LogLevel::DEBUG, "foo", "Debug (sink only)")); ASSERT_LE(0, logger.logError("foo", "Error")); nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(10)); ASSERT_TRUE(log_sub.collector.msg.get()); ASSERT_EQ(log_sub.collector.msg->level.value, uavcan::protocol::debug::LogLevel::ERROR); ASSERT_EQ(log_sub.collector.msg->source, "foo"); ASSERT_EQ(log_sub.collector.msg->text, "Error"); logger.setLevel(uavcan::protocol::debug::LogLevel::DEBUG); ASSERT_LE(0, logger.logWarning("foo", "Warning")); nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(10)); ASSERT_EQ(log_sub.collector.msg->level.value, uavcan::protocol::debug::LogLevel::WARNING); ASSERT_EQ(log_sub.collector.msg->source, "foo"); ASSERT_EQ(log_sub.collector.msg->text, "Warning"); ASSERT_LE(0, logger.logInfo("foo", "Info")); nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(10)); ASSERT_EQ(log_sub.collector.msg->level.value, uavcan::protocol::debug::LogLevel::INFO); ASSERT_EQ(log_sub.collector.msg->source, "foo"); ASSERT_EQ(log_sub.collector.msg->text, "Info"); ASSERT_LE(0, logger.logDebug("foo", "Debug")); nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(10)); ASSERT_EQ(log_sub.collector.msg->level.value, uavcan::protocol::debug::LogLevel::DEBUG); ASSERT_EQ(log_sub.collector.msg->source, "foo"); ASSERT_EQ(log_sub.collector.msg->text, "Debug"); ASSERT_TRUE(sink.popMatchByLevelAndText(uavcan::protocol::debug::LogLevel::ERROR, "foo", "Error")); ASSERT_TRUE(sink.popMatchByLevelAndText(uavcan::protocol::debug::LogLevel::WARNING, "foo", "Warning")); ASSERT_TRUE(sink.popMatchByLevelAndText(uavcan::protocol::debug::LogLevel::INFO, "foo", "Info")); ASSERT_TRUE(sink.popMatchByLevelAndText(uavcan::protocol::debug::LogLevel::DEBUG, "foo", "Debug")); }
VOID ServLog::Refresh() { LOG_SINK_TYPE OldActiveLogSinks = 0; LOG_SINK_TYPE NewActiveLogSinks = Config::GetActiveLogSinks(); ULONG Index; ServLog *Inst = ServLog::GetInstance(); // // Save off the original active log sinks // OldActiveLogSinks = Inst->ActiveSinkTypes; // // Walk each individual type, checking to see whether or not it's been // enabled. // for (Index = 0; Index < (sizeof(LogSinkTypes) / sizeof(LOG_SINK_TYPE)); Index++) { // // If this log sink type is enabled and was not previously enabled, we // instantiate it and add it to the list of active sinks. // if ((NewActiveLogSinks & LogSinkTypes[Index]) && (!(OldActiveLogSinks & LogSinkTypes[Index]))) { LogSink *Sink = LogSink::create( LogSinkTypes[Index]); Log(LOG_SEV_INFO, TEXT("Enabling log sink type %lu."), LogSinkTypes[Index]); // // Add it to the list. // if (Sink) Inst->SinkList.push_back( Sink); } // // Otherwise, if the original log sink had this sink type enabled, we may // either need to remove it from the list of active sinks (if it's no // longer in the new set), or we may need to refresh its settings. // else if (OldActiveLogSinks & LogSinkTypes[Index]) { std::list<LogSink *>::iterator It; for (It = Inst->SinkList.begin(); It != Inst->SinkList.end(); It++) { // // Did we find the type we're looking for? If not, continue. // if ((*It)->GetType() != LogSinkTypes[Index]) continue; LogSink *Sink = (*It); // // If this log sink type is no longer in the active set, then we // must remove it from the list of active log sinks. // if (!(NewActiveLogSinks & LogSinkTypes[Index])) { Inst->SinkList.erase(It); Log(LOG_SEV_INFO, TEXT("Disabling log sink type %lu."), LogSinkTypes[Index]); LogSink::destroy( Sink); break; } // // Otherwise, if it's been enabled and is still enabled, refresh it to // make sure everything is still good to go. // else { Log(LOG_SEV_INFO, TEXT("Refreshing log sink type %lu."), LogSinkTypes[Index]); Sink->Refresh(); } } } } // // Update the active log sinks bitvector. // Inst->ActiveSinkTypes = NewActiveLogSinks; }