Connection.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // Connection.cpp
  3. //
  4. // Library: MongoDB
  5. // Package: MongoDB
  6. // Module: Connection
  7. //
  8. // Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
  9. // and Contributors.
  10. //
  11. // SPDX-License-Identifier: BSL-1.0
  12. //
  13. #include "Poco/Net/SocketStream.h"
  14. #include "Poco/MongoDB/Connection.h"
  15. #include "Poco/MongoDB/Database.h"
  16. #include "Poco/URI.h"
  17. #include "Poco/Format.h"
  18. #include "Poco/NumberParser.h"
  19. #include "Poco/Exception.h"
  20. namespace Poco {
  21. namespace MongoDB {
  22. Connection::SocketFactory::SocketFactory()
  23. {
  24. }
  25. Connection::SocketFactory::~SocketFactory()
  26. {
  27. }
  28. Poco::Net::StreamSocket Connection::SocketFactory::createSocket(const std::string& host, int port, Poco::Timespan connectTimeout, bool secure)
  29. {
  30. if (!secure)
  31. {
  32. Poco::Net::SocketAddress addr(host, port);
  33. Poco::Net::StreamSocket socket;
  34. if (connectTimeout > 0)
  35. socket.connect(addr, connectTimeout);
  36. else
  37. socket.connect(addr);
  38. return socket;
  39. }
  40. else throw Poco::NotImplementedException("Default SocketFactory implementation does not support SecureStreamSocket");
  41. }
  42. Connection::Connection():
  43. _address(),
  44. _socket()
  45. {
  46. }
  47. Connection::Connection(const std::string& hostAndPort):
  48. _address(hostAndPort),
  49. _socket()
  50. {
  51. connect();
  52. }
  53. Connection::Connection(const std::string& uri, SocketFactory& socketFactory):
  54. _address(),
  55. _socket()
  56. {
  57. connect(uri, socketFactory);
  58. }
  59. Connection::Connection(const std::string& host, int port):
  60. _address(host, port),
  61. _socket()
  62. {
  63. connect();
  64. }
  65. Connection::Connection(const Poco::Net::SocketAddress& addrs):
  66. _address(addrs),
  67. _socket()
  68. {
  69. connect();
  70. }
  71. Connection::Connection(const Poco::Net::StreamSocket& socket):
  72. _address(socket.peerAddress()),
  73. _socket(socket)
  74. {
  75. }
  76. Connection::~Connection()
  77. {
  78. try
  79. {
  80. disconnect();
  81. }
  82. catch (...)
  83. {
  84. }
  85. }
  86. void Connection::connect()
  87. {
  88. _socket.connect(_address);
  89. }
  90. void Connection::connect(const std::string& hostAndPort)
  91. {
  92. _address = Poco::Net::SocketAddress(hostAndPort);
  93. connect();
  94. }
  95. void Connection::connect(const std::string& host, int port)
  96. {
  97. _address = Poco::Net::SocketAddress(host, port);
  98. connect();
  99. }
  100. void Connection::connect(const Poco::Net::SocketAddress& addrs)
  101. {
  102. _address = addrs;
  103. connect();
  104. }
  105. void Connection::connect(const Poco::Net::StreamSocket& socket)
  106. {
  107. _address = socket.peerAddress();
  108. _socket = socket;
  109. }
  110. void Connection::connect(const std::string& uri, SocketFactory& socketFactory)
  111. {
  112. Poco::URI theURI(uri);
  113. if (theURI.getScheme() != "mongodb") throw Poco::UnknownURISchemeException(uri);
  114. std::string userInfo = theURI.getUserInfo();
  115. std::string host = theURI.getHost();
  116. Poco::UInt16 port = theURI.getPort();
  117. if (port == 0) port = 27017;
  118. std::string databaseName = theURI.getPath();
  119. if (!databaseName.empty() && databaseName[0] == '/') databaseName.erase(0, 1);
  120. if (databaseName.empty()) databaseName = "admin";
  121. bool ssl = false;
  122. Poco::Timespan connectTimeout;
  123. Poco::Timespan socketTimeout;
  124. std::string authMechanism = Database::AUTH_SCRAM_SHA1;
  125. Poco::URI::QueryParameters params = theURI.getQueryParameters();
  126. for (Poco::URI::QueryParameters::const_iterator it = params.begin(); it != params.end(); ++it)
  127. {
  128. if (it->first == "ssl")
  129. {
  130. ssl = (it->second == "true");
  131. }
  132. else if (it->first == "connectTimeoutMS")
  133. {
  134. connectTimeout = static_cast<Poco::Timespan::TimeDiff>(1000)*Poco::NumberParser::parse(it->second);
  135. }
  136. else if (it->first == "socketTimeoutMS")
  137. {
  138. socketTimeout = static_cast<Poco::Timespan::TimeDiff>(1000)*Poco::NumberParser::parse(it->second);
  139. }
  140. else if (it->first == "authMechanism")
  141. {
  142. authMechanism = it->second;
  143. }
  144. }
  145. connect(socketFactory.createSocket(host, port, connectTimeout, ssl));
  146. if (socketTimeout > 0)
  147. {
  148. _socket.setSendTimeout(socketTimeout);
  149. _socket.setReceiveTimeout(socketTimeout);
  150. }
  151. if (!userInfo.empty())
  152. {
  153. std::string username;
  154. std::string password;
  155. std::string::size_type pos = userInfo.find(':');
  156. if (pos != std::string::npos)
  157. {
  158. username.assign(userInfo, 0, pos++);
  159. password.assign(userInfo, pos, userInfo.size() - pos);
  160. }
  161. else username = userInfo;
  162. Database database(databaseName);
  163. if (!database.authenticate(*this, username, password, authMechanism))
  164. throw Poco::NoPermissionException(Poco::format("Access to MongoDB database %s denied for user %s", databaseName, username));
  165. }
  166. }
  167. void Connection::disconnect()
  168. {
  169. _socket.close();
  170. }
  171. void Connection::sendRequest(RequestMessage& request)
  172. {
  173. Poco::Net::SocketOutputStream sos(_socket);
  174. request.send(sos);
  175. }
  176. void Connection::sendRequest(RequestMessage& request, ResponseMessage& response)
  177. {
  178. sendRequest(request);
  179. Poco::Net::SocketInputStream sis(_socket);
  180. response.read(sis);
  181. }
  182. } } // Poco::MongoDB