char const* Authenticator::computeDigestResponse(char const* cmd, char const* url) const { // The "response" field is computed as: // md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>)) // or, if "fPasswordIsMD5" is True: // md5(<password>:<nonce>:md5(<cmd>:<url>)) char ha1Buf[33]; if (fPasswordIsMD5) { strncpy(ha1Buf, password(), 32); ha1Buf[32] = '\0'; // just in case } else { unsigned const ha1DataLen = strlen(username()) + 1 + strlen(realm()) + 1 + strlen(password()); unsigned char* ha1Data = new unsigned char[ha1DataLen+1]; sprintf((char*)ha1Data, "%s:%s:%s", username(), realm(), password()); our_MD5Data(ha1Data, ha1DataLen, ha1Buf); delete[] ha1Data; } unsigned const ha2DataLen = strlen(cmd) + 1 + strlen(url); unsigned char* ha2Data = new unsigned char[ha2DataLen+1]; sprintf((char*)ha2Data, "%s:%s", cmd, url); char ha2Buf[33]; our_MD5Data(ha2Data, ha2DataLen, ha2Buf); delete[] ha2Data; unsigned const digestDataLen = 32 + 1 + strlen(nonce()) + 1 + 32; unsigned char* digestData = new unsigned char[digestDataLen+1]; sprintf((char*)digestData, "%s:%s:%s", ha1Buf, nonce(), ha2Buf); char const* result = our_MD5Data(digestData, digestDataLen, NULL); delete[] digestData; return result; }
QXmppSaslServer::Response QXmppSaslServerDigestMd5::respond(const QByteArray &request, QByteArray &response) { if (m_step == 0) { QMap<QByteArray, QByteArray> output; output["nonce"] = m_nonce; if (!realm().isEmpty()) output["realm"] = realm().toUtf8(); output["qop"] = "auth"; output["charset"] = "utf-8"; output["algorithm"] = "md5-sess"; m_step++; response = QXmppSaslDigestMd5::serializeMessage(output); return Challenge; } else if (m_step == 1) { const QMap<QByteArray, QByteArray> input = QXmppSaslDigestMd5::parseMessage(request); const QByteArray realm = input.value("realm"); const QByteArray digestUri = input.value("digest-uri"); if (input.value("qop") != "auth") { warning("QXmppSaslServerDigestMd5 : Invalid quality of protection"); return Failed; } setUsername(QString::fromUtf8(input.value("username"))); if (password().isEmpty() && passwordDigest().isEmpty()) return InputNeeded; m_nc = input.value("nc"); m_cnonce = input.value("cnonce"); if (!password().isEmpty()) { m_secret = QCryptographicHash::hash( username().toUtf8() + ":" + realm + ":" + password().toUtf8(), QCryptographicHash::Md5); } else { m_secret = passwordDigest(); } if (input.value("response") != calculateDigest("AUTHENTICATE", digestUri, m_secret, m_nonce, m_cnonce, m_nc)) return Failed; QMap<QByteArray, QByteArray> output; output["rspauth"] = calculateDigest(QByteArray(), digestUri, m_secret, m_nonce, m_cnonce, m_nc); m_step++; response = QXmppSaslDigestMd5::serializeMessage(output); return Challenge; } else if (m_step == 2) { m_step++; response = QByteArray(); return Succeeded; } else { warning("QXmppSaslServerDigestMd5 : Invalid step"); return Failed; } }
std::string Authenticator::getAuthHeader(std::string method, std::string uri) { std::string result = "Authorization: "; if (fAuthMethod == AUTH_BASIC) { result += "Basic " + base64Encode( username() + ":" + password() ); } else if (fAuthMethod == AUTH_DIGEST) { result += std::string("Digest ") + "username=\"" + quote(username()) + "\", realm=\"" + quote(realm()) + "\", " + "nonce=\"" + quote(nonce()) + "\", uri=\"" + quote(uri) + "\""; if ( ! fQop.empty() ) { result += ", qop=" + fQop; result += ", nc=" + stringtf("%08x",nc); result += ", cnonce=\"" + fCnonce + "\""; } result += ", response=\"" + computeDigestResponse(method, uri) + "\""; result += ", algorithm=\"MD5\""; //Authorization: Digest username="******", // realm="NC-336PW-HD-1080P", // nonce="de8859d97609a6fcc16eaba490dcfd80", // uri="rtsp://10.192.16.8:554/live/0/h264.sdp", // response="4092120557d3099a163bd51a0d59744d", // algorithm=MD5, // opaque="5ccc069c403ebaf9f0171e9517f40e41", // qop="auth", // cnonce="c8051140765877dc", // nc=00000001 } result += "\r\n"; return result; }
void YfrogUpload::upload(const QString& filename) { QString realm("http://api.twitter.com/"); QString authProviderUrl("https://api.twitter.com/1/account/verify_credentials.xml"); QUrl url("http://yfrog.com/api/xauth_upload"); QHttpMultiPart* mp = new QHttpMultiPart(QHttpMultiPart::FormDataType); // Add the image data. QFile file(filename); file.open(QIODevice::ReadOnly); QHttpPart imagePart; imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"media\"; filename=\"" + file.fileName() + "\""); imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); imagePart.setBody(file.readAll()); mp->append(imagePart); // key QHttpPart keyPart; keyPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"key\""); keyPart.setBody(m_yfrogApiKey.toLatin1()); mp->append(keyPart); QByteArray oauthHeader = m_oauthTwitter->generateAuthorizationHeader(authProviderUrl, OAuth::GET, realm); QNetworkRequest req(url); req.setRawHeader("X-Auth-Service-Provider", authProviderUrl.toLatin1()); req.setRawHeader("X-Verify-Credentials-Authorization", oauthHeader); // Post it! QNetworkReply* reply = m_oauthTwitter->networkAccessManager()->post(req, mp); mp->setParent(reply); connect(reply, SIGNAL(finished()), this, SLOT(reply())); }
void Test_Realm::toIndex() { Realm realm(1); QVERIFY(realm.toIndex() == 1); Realm line(createUintVec()); try { unsigned int_value = line.toIndex(); } catch (std::logic_error e) { return; } QFAIL("expected logic_error"); }
int main(int argc, char** argv) { try { boost::asio::io_service io_service; auto parameters = get_parameters(argc, argv); auto endpoint = parameters->rawsocket_endpoint(); auto realm = parameters->realm(); auto debug = parameters->debug(); boost::future<void> started; boost::future<void> called; boost::future<void> stopped; std::unique_ptr<autobahn::wamp_tcp_component> component( new autobahn::wamp_tcp_component( io_service, endpoint, realm, debug)); started = component->start().then([&](boost::future<void>) { autobahn::wamp_call_options call_options; call_options.set_timeout(std::chrono::seconds(10)); auto session = component->session(); std::tuple<uint64_t, uint64_t> arguments(23, 777); called = session->call("com.examples.calculator.add", arguments, call_options).then( [&](boost::future<autobahn::wamp_call_result> result) { try { uint64_t sum = result.get().argument<uint64_t>(0); std::cerr << "call result: " << sum << std::endl; } catch (const std::exception& e) { std::cerr << "call failed: " << e.what() << std::endl; } stopped = component->stop().then([&](boost::future<void>) { io_service.stop(); }); }); }); io_service.run(); stopped.wait(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return -1; } return 0; }
std::string Authenticator::computeDigestResponse(std::string &method, std::string &uri) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT // The "response" field is computed as: // md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>)) size_t md5len = 16; unsigned char md5buf[md5len]; char md5HexBuf[md5len*2+1]; // Step 1: md5(<username>:<realm>:<password>) std::string ha1Data = username() + ":" + realm() + ":" + password(); Debug( 2, "HA1 pre-md5: %s", ha1Data.c_str() ); #if HAVE_DECL_MD5 MD5((unsigned char*)ha1Data.c_str(), ha1Data.length(), md5buf); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5dataha1 = { (unsigned char*)ha1Data.c_str(), ha1Data.length() }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len ); #endif for ( unsigned int j = 0; j < md5len; j++ ) { sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] ); } md5HexBuf[md5len*2]='\0'; std::string ha1Hash = md5HexBuf; // Step 2: md5(<cmd>:<url>) std::string ha2Data = method + ":" + uri; Debug( 2, "HA2 pre-md5: %s", ha2Data.c_str() ); #if HAVE_DECL_MD5 MD5((unsigned char*)ha2Data.c_str(), ha2Data.length(), md5buf ); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5dataha2 = { (unsigned char*)ha2Data.c_str(), ha2Data.length() }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len ); #endif for ( unsigned int j = 0; j < md5len; j++ ) { sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); } md5HexBuf[md5len*2]='\0'; std::string ha2Hash = md5HexBuf; // Step 3: md5(ha1:<nonce>:ha2) std::string digestData = ha1Hash + ":" + nonce(); if ( ! fQop.empty() ) { digestData += ":" + stringtf("%08x", nc) + ":"+fCnonce + ":" + fQop; nc ++; // if qop was specified, then we have to include t and a cnonce and an nccount } digestData += ":" + ha2Hash; Debug( 2, "pre-md5: %s", digestData.c_str() ); #if HAVE_DECL_MD5 MD5((unsigned char*)digestData.c_str(), digestData.length(), md5buf); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5datadigest = { (unsigned char*)digestData.c_str(), digestData.length() }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len ); #endif for ( unsigned int j = 0; j < md5len; j++ ) { sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); } md5HexBuf[md5len*2]='\0'; return md5HexBuf; #else // HAVE_DECL_MD5 Error( "You need to build with gnutls or openssl installed to use digest authentication" ); return( 0 ); #endif // HAVE_DECL_MD5 }
QgsOracleConn::QgsOracleConn( QgsDataSourceURI uri ) : mRef( 1 ) , mCurrentUser( QString::null ) , mHasSpatial( -1 ) { QgsDebugMsg( QString( "New Oracle connection for " ) + uri.connectionInfo() ); QString database = databaseName( uri.database(), uri.host(), uri.port() ); QgsDebugMsg( QString( "New Oracle database " ) + database ); mDatabase = QSqlDatabase::addDatabase( "QOCISPATIAL", QString( "oracle%1" ).arg( snConnections++ ) ); mDatabase.setDatabaseName( database ); mDatabase.setConnectOptions( "OCI_ATTR_PREFETCH_ROWS=1000" ); mDatabase.setUserName( uri.username() ); mDatabase.setPassword( uri.password() ); if ( !mDatabase.open() ) { QString username = uri.username(); QString password = uri.password(); QString realm( database ); if ( !username.isEmpty() ) realm.prepend( username + "@" ); QgsCredentials::instance()->lock(); while ( !mDatabase.open() ) { bool ok = QgsCredentials::instance()->get( realm, username, password, mDatabase.lastError().text() ); if ( !ok ) break; if ( !username.isEmpty() ) { uri.setUsername( username ); realm = username + "@" + database; } if ( !password.isEmpty() ) uri.setPassword( password ); QgsDebugMsg( "Connecting to " + database ); mDatabase.setUserName( username ); mDatabase.setPassword( password ); } if ( mDatabase.isOpen() ) QgsCredentials::instance()->put( realm, username, password ); QgsCredentials::instance()->unlock(); } if ( !mDatabase.isOpen() ) { mDatabase.close(); QgsMessageLog::logMessage( tr( "Connection to database failed" ), tr( "Oracle" ) ); mRef = 0; return; } }
int main(int argc, char** argv) { std::cerr << "Boost: " << BOOST_VERSION << std::endl; try { auto parameters = get_parameters(argc, argv); boost::asio::io_service io; bool debug = parameters->debug(); auto transport = std::make_shared<autobahn::wamp_tcp_transport>( io, parameters->rawsocket_endpoint(), debug); // create a WAMP session that talks WAMP-RawSocket over TCP // auto session = std::make_shared<autobahn::wamp_session>(io, debug); transport->attach(std::static_pointer_cast<autobahn::wamp_transport_handler>(session)); // Make sure the continuation futures we use do not run out of scope prematurely. // Since we are only using one thread here this can cause the io service to block // as a future generated by a continuation will block waiting for its promise to be // fulfilled when it goes out of scope. This would prevent the session from receiving // responses from the router. boost::future<void> connect_future; boost::future<void> start_future; boost::future<void> join_future; boost::future<void> leave_future; boost::future<void> stop_future; connect_future = transport->connect().then([&](boost::future<void> connected) { try { connected.get(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } std::cerr << "transport connected" << std::endl; start_future = session->start().then([&](boost::future<void> started) { try { started.get(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } std::cerr << "session started" << std::endl; join_future = session->join(parameters->realm()).then([&](boost::future<uint64_t> joined) { try { std::cerr << "joined realm: " << joined.get() << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } std::tuple<std::string> arguments(std::string("hello")); session->publish("com.examples.subscriptions.topic1", arguments); std::cerr << "event published" << std::endl; leave_future = session->leave().then([&](boost::future<std::string> reason) { try { std::cerr << "left session (" << reason.get() << ")" << std::endl; } catch (const std::exception& e) { std::cerr << "failed to leave session: " << e.what() << std::endl; io.stop(); return; } stop_future = session->stop().then([&](boost::future<void> stopped) { std::cerr << "stopped session" << std::endl; io.stop(); }); }); }); }); }); std::cerr << "starting io service" << std::endl; io.run(); std::cerr << "stopped io service" << std::endl; transport->detach(); } catch (const std::exception& e) { std::cerr << "exception: " << e.what() << std::endl; return 1; } return 0; }
int main(int argc, char** argv) { std::cerr << "Boost: " << BOOST_VERSION << std::endl; try { auto parameters = get_parameters(argc, argv); std::cerr << "Connecting to realm: " << parameters->realm() << std::endl; boost::asio::io_service io; bool debug = parameters->debug(); auto transport = std::make_shared<autobahn::wamp_tcp_transport>( io, parameters->rawsocket_endpoint(), debug); auto session = std::make_shared<autobahn::wamp_session>(io, debug); transport->attach(std::static_pointer_cast<autobahn::wamp_transport_handler>(session)); // Make sure the continuation futures we use do not run out of scope prematurely. // Since we are only using one thread here this can cause the io service to block // as a future generated by a continuation will block waiting for its promise to be // fulfilled when it goes out of scope. This would prevent the session from receiving // responses from the router. boost::future<void> connect_future; boost::future<void> start_future; boost::future<void> join_future; boost::future<void> provide_future; connect_future = transport->connect().then([&](boost::future<void> connected) { try { connected.get(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } std::cerr << "transport connected" << std::endl; start_future = session->start().then([&](boost::future<void> started) { try { started.get(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } std::cerr << "session started" << std::endl; join_future = session->join(parameters->realm()).then([&](boost::future<uint64_t> joined) { try { std::cerr << "joined realm: " << joined.get() << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } provide_future = session->provide("com.examples.calculator.add2", &add2).then( [&](boost::future<autobahn::wamp_registration> registration) { try { std::cerr << "registered procedure:" << registration.get().id() << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } }); provide_future = session->provide("com.myapp.longop", &longop).then( [&](boost::future<autobahn::wamp_registration> registration) { try { std::cerr << "registered procedure:" << registration.get().id() << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; io.stop(); return; } }); }); }); }); std::cerr << "starting io service" << std::endl; io.run(); std::cerr << "stopped io service" << std::endl; } catch (const std::exception& e) { std::cerr << "exception: " << e.what() << std::endl; return -1; } return 0; }
int main(int argc, char** argv) { std::cerr << "Boost: " << BOOST_VERSION << std::endl; try { auto parameters = get_parameters(argc, argv); std::cerr << "Connecting to realm: " << parameters->realm() << std::endl; boost::asio::io_service io; boost::asio::ip::tcp::socket socket(io); // create a WAMP session that talks WAMP-RawSocket over TCP // bool debug = parameters->debug(); auto session = std::make_shared< autobahn::wamp_session<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket>>(io, socket, socket, debug); // Make sure the continuation futures we use do not run out of scope prematurely. // Since we are only using one thread here this can cause the io service to block // as a future generated by a continuation will block waiting for its promise to be // fulfilled when it goes out of scope. This would prevent the session from receiving // responses from the router. boost::future<void> start_future; boost::future<void> join_future; socket.async_connect(parameters->rawsocket_endpoint(), [&](boost::system::error_code ec) { if (!ec) { std::cerr << "connected to server" << std::endl; start_future = session->start().then([&](boost::future<bool> started) { if (started.get()) { std::cerr << "session started" << std::endl; join_future = session->join(parameters->realm()).then([&](boost::future<uint64_t> s) { std::cerr << "joined realm: " << s.get() << std::endl; session->provide("com.example.add2", &add2); }); } else { std::cerr << "failed to start session" << std::endl; io.stop(); } }); } else { std::cerr << "connect failed: " << ec.message() << std::endl; } } ); std::cerr << "starting io service" << std::endl; io.run(); std::cerr << "stopped io service" << std::endl; } catch (const std::exception& e) { std::cerr << "exception: " << e.what() << std::endl; return 1; } return 0; }
QgsOracleConn::QgsOracleConn( QgsDataSourceUri uri ) : mRef( 1 ) , mCurrentUser( QString::null ) , mHasSpatial( -1 ) { QgsDebugMsg( QString( "New Oracle connection for " ) + uri.connectionInfo() ); QString database = databaseName( uri.database(), uri.host(), uri.port() ); QgsDebugMsg( QString( "New Oracle database " ) + database ); mDatabase = QSqlDatabase::addDatabase( "QOCISPATIAL", QString( "oracle%1" ).arg( snConnections++ ) ); mDatabase.setDatabaseName( database ); QString options = uri.hasParam( "dboptions" ) ? uri.param( "dboptions" ) : "OCI_ATTR_PREFETCH_ROWS=1000"; QString workspace = uri.hasParam( "dbworkspace" ) ? uri.param( "dbworkspace" ) : QString::null; mDatabase.setConnectOptions( options ); mDatabase.setUserName( uri.username() ); mDatabase.setPassword( uri.password() ); QgsDebugMsg( QString( "Connecting with options: " ) + options ); if ( !mDatabase.open() ) { QString username = uri.username(); QString password = uri.password(); QString realm( database ); if ( !username.isEmpty() ) realm.prepend( username + "@" ); QgsCredentials::instance()->lock(); while ( !mDatabase.open() ) { bool ok = QgsCredentials::instance()->get( realm, username, password, mDatabase.lastError().text() ); if ( !ok ) break; if ( !username.isEmpty() ) { uri.setUsername( username ); realm = username + "@" + database; } if ( !password.isEmpty() ) uri.setPassword( password ); QgsDebugMsg( "Connecting to " + database ); mDatabase.setUserName( username ); mDatabase.setPassword( password ); } if ( mDatabase.isOpen() ) QgsCredentials::instance()->put( realm, username, password ); QgsCredentials::instance()->unlock(); } if ( !mDatabase.isOpen() ) { mDatabase.close(); QgsMessageLog::logMessage( tr( "Connection to database failed" ), tr( "Oracle" ) ); mRef = 0; return; } if ( !workspace.isNull() ) { QSqlQuery qry( mDatabase ); if ( !qry.exec( QString( "BEGIN\nDBMS_WM.GotoWorkspace(%1);\nEND;" ).arg( quotedValue( workspace ) ) ) ) { mDatabase.close(); QgsMessageLog::logMessage( tr( "Could not switch to workspace %1 [%2]" ).arg( workspace, qry.lastError().databaseText() ), tr( "Oracle" ) ); mRef = 0; return; } } }
int main(int argc, char** argv) { try { auto parameters = get_parameters(argc, argv); boost::asio::io_service io; auto transport = std::make_shared<autobahn::wamp_tcp_transport>( io, parameters->rawsocket_endpoint()); bool debug = parameters->debug(); auto session = std::make_shared<autobahn::wamp_session>( io, transport, transport, debug); // Make sure the continuation futures we use do not run out of scope prematurely. // Since we are only using one thread here this can cause the io service to block // as a future generated by a continuation will block waiting for its promise to be // fulfilled when it goes out of scope. This would prevent the session from receiving // responses from the router. boost::future<void> start_future; boost::future<void> join_future; boost::future<void> leave_future; boost::future<void> stop_future; transport->async_connect([&](boost::system::error_code ec) { if (!ec) { std::cerr << "connected to server" << std::endl; start_future = session->start().then([&](boost::future<bool> started) { if (started.get()) { std::cerr << "session started" << std::endl; join_future = session->join(parameters->realm()).then([&](boost::future<uint64_t> joined) { std::cerr << "joined realm: " << joined.get() << std::endl; std::tuple<std::string> arguments(std::string("hello")); session->publish("com.examples.subscriptions.topic1", arguments); std::cerr << "event published" << std::endl; leave_future = session->leave().then([&](boost::future<std::string> reason) { std::cerr << "left session (" << reason.get() << ")" << std::endl; stop_future = session->stop().then([&](boost::future<void> stopped) { std::cerr << "stopped session" << std::endl; io.stop(); }); }); }); } else { std::cerr << "failed to start session" << std::endl; io.stop(); } }); } else { std::cerr << "connect failed: " << ec.message() << std::endl; io.stop(); } } ); std::cerr << "starting io service" << std::endl; io.run(); std::cerr << "stopped io service" << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 1; } return 0; }
int main(int argc, char** argv) { std::cerr << "Boost: " << BOOST_VERSION << std::endl; try { auto parameters = get_parameters(argc, argv); std::cerr << "realm: " << parameters->realm() << std::endl; boost::asio::io_service io; boost::asio::ip::tcp::socket socket(io); bool debug = parameters->debug(); std::vector<std::string> auth_methods; auth_methods.push_back("wampcra"); std::string authid = "homer"; std::string secret = "secret123"; auto session = std::make_shared< auth_wamp_session<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket>>(io, socket, socket, debug, secret); // Make sure the continuation futures we use do not run out of scope prematurely. // Since we are only using one thread here this can cause the io service to block // as a future generated by a continuation will block waiting for its promise to be // fulfilled when it goes out of scope. This would prevent the session from receiving // responses from the router. boost::future<void> start_future; boost::future<void> join_future; socket.async_connect(parameters->rawsocket_endpoint(), [&](boost::system::error_code ec) { if (!ec) { std::cerr << "connected to server" << std::endl; start_future = session->start().then([&](boost::future<bool> started) { if (started.get()) { std::cerr << "session started" << std::endl; join_future = session->join(parameters->realm(), auth_methods, authid).then([&](boost::future<uint64_t> s) { std::cerr << "joined realm: " << s.get() << std::endl; io.stop(); }); } else { std::cerr << "failed to start session" << std::endl; io.stop(); } }); } else { std::cerr << "connect failed: " << ec.message() << std::endl; io.stop(); } } ); std::cerr << "starting io service" << std::endl; io.run(); std::cerr << "stopped io service" << std::endl; } catch (std::exception& e) { std::cerr << e.what() << std::endl; return 1; } return 0; }