Anoncoin  0.9.4
P2P Digital Currency
i2pwrapper.cpp
Go to the documentation of this file.
1 // Copyright (c) 2013-2015 The Anoncoin Core developers
2 // Copyright (c) 2012-2013 giv
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 //--------------------------------------------------------------------------------------------------
6 
7 // Many builder specific things set in the config file, don't forget to include it this way in your source files.
8 #if defined(HAVE_CONFIG_H)
10 #endif
11 
12 #include "i2pwrapper.h"
13 #include "util.h"
14 #include "hash.h"
15 
16 #include <boost/thread/shared_mutex.hpp>
17 
18 namespace SAM
19 {
20 
22  public:
23  explicit SessionHolder(std::auto_ptr<SAM::StreamSession> session);
24 
25  const SAM::StreamSession& getSession() const;
27  private:
28  void heal() const;
29  void reborn() const;
30 
31  mutable std::auto_ptr<SAM::StreamSession> session_;
32  typedef boost::shared_mutex mutex_type;
33  mutable mutex_type mtx_;
34  };
35 
36  StreamSessionAdapter::SessionHolder::SessionHolder(std::auto_ptr<SAM::StreamSession> session) : session_(session)
37  {}
38 
40  {
41  boost::upgrade_lock<mutex_type> lock(mtx_);
42  if (session_->isSick())
43  {
44  boost::upgrade_to_unique_lock<mutex_type> ulock(lock);
45  heal();
46  }
47  return *session_;
48  }
49 
51  {
52  boost::upgrade_lock<mutex_type> lock(mtx_);
53  if (session_->isSick())
54  {
55  boost::upgrade_to_unique_lock<mutex_type> ulock(lock);
56  heal();
57  }
58  return *session_;
59  }
60 
62  {
63  reborn(); // if we don't know how to heal it just reborn it
64  }
65 
67  {
68  if (!session_->isSick())
69  return;
70  std::auto_ptr<SAM::StreamSession> newSession(new SAM::StreamSession(*session_));
71  if (!newSession->isSick() && session_->isSick())
72  session_ = newSession;
73  }
74 
75  //--------------------------------------------------------------------------------------------------
76 
78  const std::string& nickname,
79  const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/,
80  uint16_t SAMPort /*= SAM_DEFAULT_PORT*/,
81  const std::string& myDestination /*= SAM_GENERATE_MY_DESTINATION*/,
82  const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/,
83  const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/,
84  const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/)
86  new SessionHolder(
87  std::auto_ptr<SAM::StreamSession>(
88  new SAM::StreamSession(nickname, SAMHost, SAMPort, myDestination, i2pOptions, minVer, maxVer))))
89  {}
90 
92  {}
93 
95  {
96  SAM::RequestResult<std::auto_ptr<SAM::Socket> > result = sessionHolder_->getSession().accept(silent);
97  // call Socket::release
98  return result.isOk ? result.value->release() : SAM_INVALID_SOCKET;
99  }
100 
101  SAM::SOCKET StreamSessionAdapter::connect(const std::string& destination, bool silent)
102  {
103  SAM::RequestResult<std::auto_ptr<SAM::Socket> > result = sessionHolder_->getSession().connect(destination, silent);
104  // call Socket::release
105  return result.isOk ? result.value->release() : SAM_INVALID_SOCKET;
106  }
107 
108  bool StreamSessionAdapter::forward(const std::string& host, uint16_t port, bool silent)
109  {
110  return sessionHolder_->getSession().forward(host, port, silent).isOk;
111  }
112 
113  std::string StreamSessionAdapter::namingLookup(const std::string& name) const
114  {
115  SAM::RequestResult<const std::string> result = sessionHolder_->getSession().namingLookup(name);
116  return result.isOk ? result.value : std::string();
117  }
118 
120  {
121  SAM::RequestResult<const SAM::FullDestination> result = sessionHolder_->getSession().destGenerate();
122  return result.isOk ? result.value : SAM::FullDestination();
123  }
124 
125  void StreamSessionAdapter::stopForwarding(const std::string& host, uint16_t port)
126  {
127  sessionHolder_->getSession().stopForwarding(host, port);
128  }
129 
131  {
132  sessionHolder_->getSession().stopForwardingAll();
133  }
134 
136  {
137  return sessionHolder_->getSession().getMyDestination();
138  }
139 
140  const sockaddr_in& StreamSessionAdapter::getSAMAddress() const
141  {
142  return sessionHolder_->getSession().getSAMAddress();
143  }
144 
145  const std::string& StreamSessionAdapter::getSAMHost() const
146  {
147  return sessionHolder_->getSession().getSAMHost();
148  }
149 
151  {
152  return sessionHolder_->getSession().getSAMPort();
153  }
154 
155  const std::string& StreamSessionAdapter::getNickname() const
156  {
157  return sessionHolder_->getSession().getNickname();
158  }
159 
160  const std::string& StreamSessionAdapter::getSAMMinVer() const
161  {
162  return sessionHolder_->getSession().getSAMMinVer();
163  }
164 
165  const std::string& StreamSessionAdapter::getSAMMaxVer() const
166  {
167  return sessionHolder_->getSession().getSAMMaxVer();
168  }
169 
170  const std::string& StreamSessionAdapter::getSAMVersion() const
171  {
172  return sessionHolder_->getSession().getSAMVersion();
173  }
174 
175  const std::string& StreamSessionAdapter::getOptions() const
176  {
177  return sessionHolder_->getSession().getOptions();
178  }
179 
180  const std::string& StreamSessionAdapter::getSessionID() const
181  {
182  return sessionHolder_->getSession().getSessionID();
183  }
184 
185 } // namespace SAM
186 
187 //--------------------------------------------------------------------------------------------------
188 static std::string sSession = I2P_SESSION_NAME_DEFAULT;
189 static std::string sHost = SAM_DEFAULT_ADDRESS;
190 static uint16_t uPort = SAM_DEFAULT_PORT;
191 static std::string sDestination = SAM_GENERATE_MY_DESTINATION;
192 static std::string sOptions;
193 
194 I2PSession::I2PSession() : SAM::StreamSessionAdapter( sSession, sHost, uPort, sDestination, sOptions )
195 {
196  ::sDestination = this->getMyDestination().priv;
197 }
198 
200 {}
201 
202 /*static*/
203 std::string I2PSession::GenerateB32AddressFromDestination(const std::string& destination)
204 {
206 }
207 
208 void static FormatBoolI2POptionsString( std::string& I2pOptions, const std::string& I2pSamName, const std::string& confParamName ) {
209  bool fConfigValue = GetArg( confParamName, true );
210 
211  if (!I2pOptions.empty()) I2pOptions += " "; // seperate the parameters with <whitespace>
212  I2pOptions += I2pSamName + "=" + (fConfigValue ? "true" : "false"); // I2P router wants the words...
213 }
214 
215 void static FormatIntI2POptionsString( std::string& I2pOptions, const std::string& I2pSamName, const std::string& confParamName ) {
216  int64_t i64ConfigValue = GetArg( confParamName, 0 );
217 
218  if (!I2pOptions.empty()) I2pOptions += " "; // seperate the parameters with <whitespace>
219  std::ostringstream oss;
220  oss << i64ConfigValue; // One way of converting a value to a string
221  I2pOptions += I2pSamName + "=" + oss.str(); // I2P router wants the chars....
222 }
223 
224 void static BuildI2pOptionsString( void ) {
225  std::string OptStr;
226 
227  FormatIntI2POptionsString(OptStr, SAM_NAME_INBOUND_QUANTITY , "-i2p.options.inbound.quantity" );
228  FormatIntI2POptionsString(OptStr, SAM_NAME_INBOUND_LENGTH , "-i2p.options.inbound.length" );
229  FormatIntI2POptionsString(OptStr, SAM_NAME_INBOUND_LENGTHVARIANCE , "-i2p.options.inbound.lengthvariance" );
230  FormatIntI2POptionsString(OptStr, SAM_NAME_INBOUND_BACKUPQUANTITY , "-i2p.options.inbound.backupquantity" );
231  FormatBoolI2POptionsString(OptStr, SAM_NAME_INBOUND_ALLOWZEROHOP , "-i2p.options.inbound.allowzerohop" );
232  FormatIntI2POptionsString(OptStr, SAM_NAME_INBOUND_IPRESTRICTION , "-i2p.options.inbound.iprestriction" );
233  FormatIntI2POptionsString(OptStr, SAM_NAME_OUTBOUND_QUANTITY , "-i2p.options.outbound.quantity" );
234  FormatIntI2POptionsString(OptStr, SAM_NAME_OUTBOUND_LENGTH , "-i2p.options.outbound.length" );
235  FormatIntI2POptionsString(OptStr, SAM_NAME_OUTBOUND_LENGTHVARIANCE, "-i2p.options.outbound.lengthvariance" );
236  FormatIntI2POptionsString(OptStr, SAM_NAME_OUTBOUND_BACKUPQUANTITY, "-i2p.options.outbound.backupquantity" );
237  FormatBoolI2POptionsString(OptStr, SAM_NAME_OUTBOUND_ALLOWZEROHOP , "-i2p.options.outbound.allowzerohop" );
238  FormatIntI2POptionsString(OptStr, SAM_NAME_OUTBOUND_IPRESTRICTION , "-i2p.options.outbound.iprestriction" );
239  FormatIntI2POptionsString(OptStr, SAM_NAME_OUTBOUND_PRIORITY , "-i2p.options.outbound.priority" );
240 
241  std::string ExtrasStr = GetArg( "-i2p.options.extra", "");
242  if( ExtrasStr.size() ) {
243  if (!OptStr.empty()) OptStr += " "; // seperate the parameters with <whitespace>
244  OptStr += ExtrasStr;
245  }
246  sOptions = OptStr; // Keep this globally for use later in opening the session
247 }
248 
249 // Initialize all the parameters with default values, if necessary.
250 // These should not override any loaded from the anoncoin.conf file,
251 // but if they are not set, then this insures that they are created with good values
252 // SoftSetArg will return a bool, if you care to know if the parameter was changed or not.
253 void InitializeI2pSettings( void ) {
254  SoftSetBoolArg( "-i2p.options.static", false );
255  SoftSetArg( "-i2p.options.samhost", SAM_DEFAULT_ADDRESS );
256  SoftSetArg( "-i2p.options.samport", "7656" ); /* SAM_DEFAULT_PORT */
257  SoftSetArg( "-i2p.options.sessionname", I2P_SESSION_NAME_DEFAULT );
258  SoftSetArg( "-i2p.options.inbound.quantity", "3" ); /* SAM_DEFAULT_INBOUND_QUANTITY */
259  SoftSetArg( "-i2p.options.inbound.length", "3" ); /* SAM_DEFAULT_INBOUND_LENGTH */
260  SoftSetArg( "-i2p.options.inbound.lengthvariance", "0" ); /* SAM_DEFAULT_INBOUND_LENGTHVARIANCE */
261  SoftSetArg( "-i2p.options.inbound.backupquantity", "1" ); /* SAM_DEFAULT_INBOUND_BACKUPQUANTITY */
262  SoftSetBoolArg( "-i2p.options.inbound.allowzerohop", SAM_DEFAULT_INBOUND_ALLOWZEROHOP );
263  SoftSetArg( "-i2p.options.inbound.iprestriction", "2" ); /* SAM_DEFAULT_INBOUND_IPRESTRICTION */
264  SoftSetArg( "-i2p.options.outbound.quantity", "3" ); /* SAM_DEFAULT_OUTBOUND_QUANTITY */
265  SoftSetArg( "-i2p.options.outbound.length", "3" ); /* SAM_DEFAULT_OUTBOUND_LENGTH */
266  SoftSetArg( "-i2p.options.outbound.lengthvariance", "0" ); /* SAM_DEFAULT_OUTBOUND_LENGTHVARIANCE */
267  SoftSetArg( "-i2p.options.outbound.backupquantity", "1" ); /* SAM_DEFAULT_OUTBOUND_BACKUPQUANTITY */
268  SoftSetBoolArg( "-i2p.options.outbound.allowzerohop", SAM_DEFAULT_OUTBOUND_ALLOWZEROHOP );
269  SoftSetArg( "-i2p.options.outbound.iprestriction", "2" ); /* SAM_DEFAULT_OUTBOUND_IPRESTRICTION */
270  SoftSetArg( "-i2p.options.outbound.priority", "0" ); /* SAM_DEFAULT_OUTBOUND_PRIORITY */
271 
272  // Setup parameters required to open a new SAM session
273  uPort = (uint16_t)GetArg( "-i2p.options.samport", SAM_DEFAULT_PORT );
274  sSession = GetArg( "-i2p.options.sessionname", I2P_SESSION_NAME_DEFAULT );
275  sHost = GetArg( "-i2p.options.samhost", SAM_DEFAULT_ADDRESS );
276  // Critical to check here, if we are in dynamic destination mode, the intial session destination MUSTBE default too.
277  // Which may not be what the user has set in the anoncoin.conf file.
278  if( GetBoolArg( "-i2p.options.static", false ) ) // GetBoolArg returns true if the .static variable is true
279  sDestination = GetArg( "-i2p.mydestination.privatekey", SAM_GENERATE_MY_DESTINATION );
280  // It's important here that sDestination be setup correctly, for soon when an initial Session object is about to be
281  // created. When that happens, this variable is used to create the SAM session, upon which, after it's opened,
282  // the variable is updated to reflect that ACTUAL destination being used. Whatever that value maybe,
283  // dynamically generated or statically set. ToDo: Move sDestination into the Session class
284 
285  BuildI2pOptionsString(); // Now build the I2P options string that's need to open a session
286 }
287 
288 // This test should pass for both public and private keys, as the first part of the private key is the public key.
289 bool isValidI2pAddress( const std::string& I2pAddr ) {
290  if( I2pAddr.size() < NATIVE_I2P_DESTINATION_SIZE ) return false;
291  return (I2pAddr.substr( NATIVE_I2P_DESTINATION_SIZE - 4, 4 ) == "AAAA");
292 }
293 
295 
296  // Perhaps we're given a I2P native public address, last 4 symbols of b64-destination must be AAAA
297  bool fPublic = ((DestKeys.pub.size() == NATIVE_I2P_DESTINATION_SIZE) && isValidI2pAddress( DestKeys.pub));
298  // ToDo: Add more checking on the private key, for now this will do...
299  bool fPrivate = ((DestKeys.priv.size() > NATIVE_I2P_DESTINATION_SIZE) && isValidI2pAddress( DestKeys.priv));
300  return fPublic && fPrivate;
301 }
302 
303 bool isValidI2pB32( const std::string& B32Address ) {
304  return (B32Address.size() == NATIVE_I2P_B32ADDR_SIZE) && (B32Address.substr(B32Address.size() - 8, 8) == ".b32.i2p");
305 }
306 
307 std::string B32AddressFromDestination(const std::string& destination)
308 {
309  std::string canonicalDest = destination;
310  for (size_t pos = canonicalDest.find_first_of('-'); pos != std::string::npos; pos = canonicalDest.find_first_of('-', pos))
311  canonicalDest[pos] = '+';
312  for (size_t pos = canonicalDest.find_first_of('~'); pos != std::string::npos; pos = canonicalDest.find_first_of('~', pos))
313  canonicalDest[pos] = '/';
314  std::string rawHash = DecodeBase64(canonicalDest);
315  uint256 hash;
316  SHA256((const unsigned char*)rawHash.c_str(), rawHash.size(), (unsigned char*)&hash);
317  std::string result = EncodeBase32(hash.begin(), hash.end() - hash.begin()) + ".b32.i2p";
318  for (size_t pos = result.find_first_of('='); pos != std::string::npos; pos = result.find_first_of('=', pos-1))
319  result.erase(pos, 1);
320  return result;
321 }
std::string namingLookup(const std::string &name) const
Definition: i2pwrapper.cpp:113
#define SAM_DEFAULT_ADDRESS
Definition: i2psam.h:28
#define SAM_NAME_OUTBOUND_BACKUPQUANTITY
Definition: i2psam.h:54
void stopForwarding(const std::string &host, uint16_t port)
Definition: i2pwrapper.cpp:125
const std::string & getNickname() const
Definition: i2pwrapper.cpp:155
std::string pub
Definition: i2psam.h:262
unsigned char * end()
Definition: uint256.h:351
const SAM::FullDestination & getMyDestination() const
Definition: i2pwrapper.cpp:135
int SOCKET
Definition: i2psam.h:69
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition: util.cpp:539
bool isValidI2pAddress(const std::string &I2pAddr)
Definition: i2pwrapper.cpp:289
#define SAM_INVALID_SOCKET
Definition: i2psam.h:25
unsigned char * begin()
Definition: uint256.h:346
const std::string & getOptions() const
Definition: i2pwrapper.cpp:175
#define SAM_NAME_INBOUND_BACKUPQUANTITY
Definition: i2psam.h:42
std::string B32AddressFromDestination(const std::string &destination)
Definition: i2pwrapper.cpp:307
const std::string & getSAMHost() const
Definition: i2pwrapper.cpp:145
SAM::SOCKET accept(bool silent)
Definition: i2pwrapper.cpp:94
#define SAM_NAME_OUTBOUND_ALLOWZEROHOP
Definition: i2psam.h:56
#define SAM_NAME_OUTBOUND_QUANTITY
Definition: i2psam.h:48
const std::string & getSAMMinVer() const
Definition: i2pwrapper.cpp:160
#define SAM_NAME_INBOUND_QUANTITY
Definition: i2psam.h:36
bool isValidI2pDestination(const SAM::FullDestination &DestKeys)
Definition: i2pwrapper.cpp:294
#define SAM_NAME_OUTBOUND_PRIORITY
Definition: i2psam.h:60
void InitializeI2pSettings(void)
Definition: i2pwrapper.cpp:253
uint16_t getSAMPort() const
Definition: i2pwrapper.cpp:150
Definition: i2psam.cpp:36
#define SAM_DEFAULT_OUTBOUND_ALLOWZEROHOP
Definition: i2psam.h:57
#define I2P_SESSION_NAME_DEFAULT
Definition: i2pwrapper.h:12
const std::string & getSAMVersion() const
Definition: i2pwrapper.cpp:170
SAM::SOCKET connect(const std::string &destination, bool silent)
Definition: i2pwrapper.cpp:101
const std::string & getSessionID() const
Definition: i2pwrapper.cpp:180
#define NATIVE_I2P_B32ADDR_SIZE
Definition: i2pwrapper.h:14
std::auto_ptr< SessionHolder > sessionHolder_
Definition: i2pwrapper.h:55
bool isValidI2pB32(const std::string &B32Address)
Definition: i2pwrapper.cpp:303
#define SAM_NAME_INBOUND_IPRESTRICTION
Definition: i2psam.h:46
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:520
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
Definition: util.cpp:531
#define SAM_NAME_INBOUND_ALLOWZEROHOP
Definition: i2psam.h:44
#define SAM_NAME_INBOUND_LENGTH
Definition: i2psam.h:38
#define NATIVE_I2P_DESTINATION_SIZE
Definition: i2pwrapper.h:13
#define SAM_NAME_INBOUND_LENGTHVARIANCE
Definition: i2psam.h:40
StreamSessionAdapter(const std::string &nickname, const std::string &SAMHost=SAM_DEFAULT_ADDRESS, uint16_t SAMPort=SAM_DEFAULT_PORT, const std::string &myDestination=SAM_GENERATE_MY_DESTINATION, const std::string &i2pOptions=SAM_DEFAULT_I2P_OPTIONS, const std::string &minVer=SAM_DEFAULT_MIN_VER, const std::string &maxVer=SAM_DEFAULT_MAX_VER)
Definition: i2pwrapper.cpp:77
string EncodeBase32(const unsigned char *pch, size_t len)
Definition: util.cpp:688
#define SAM_DEFAULT_INBOUND_ALLOWZEROHOP
Definition: i2psam.h:45
#define SAM_GENERATE_MY_DESTINATION
Definition: i2psam.h:32
const sockaddr_in & getSAMAddress() const
Definition: i2pwrapper.cpp:140
SessionHolder(std::auto_ptr< SAM::StreamSession > session)
Definition: i2pwrapper.cpp:36
256-bit unsigned integer
Definition: uint256.h:532
std::auto_ptr< SAM::StreamSession > session_
Definition: i2pwrapper.cpp:31
#define SAM_NAME_OUTBOUND_IPRESTRICTION
Definition: i2psam.h:58
#define SAM_DEFAULT_PORT
Definition: i2psam.h:29
std::string priv
Definition: i2psam.h:263
static std::string GenerateB32AddressFromDestination(const std::string &destination)
Definition: i2pwrapper.cpp:203
SAM::FullDestination destGenerate() const
Definition: i2pwrapper.cpp:119
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
Definition: util.cpp:506
vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)
Definition: util.cpp:599
bool forward(const std::string &host, uint16_t port, bool silent)
Definition: i2pwrapper.cpp:108
#define SAM_NAME_OUTBOUND_LENGTHVARIANCE
Definition: i2psam.h:52
const SAM::StreamSession & getSession() const
Definition: i2pwrapper.cpp:39
#define SAM_NAME_OUTBOUND_LENGTH
Definition: i2psam.h:50
const std::string & getSAMMaxVer() const
Definition: i2pwrapper.cpp:165