Anoncoin  0.9.4
P2P Digital Currency
i2psam.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 "i2psam.h"
13 
14 #include <iostream>
15 #include <stdio.h>
16 #include <string.h> // for memset
17 #include <stdlib.h>
18 #include <time.h>
19 #include <stdarg.h>
20 
21 #ifndef WIN32
22 #include <errno.h>
23 #include <unistd.h>
24 #endif
25 
26 #ifndef WIN32
27 #define closesocket close
28 #endif
29 
30 #define SAM_BUFSIZE 65536
31 #define I2P_DESTINATION_SIZE 516
32 
33 // Define this, if you want more of the original standard output diagnostics
34 // #define DEBUG_ON_STDOUT
35 
36 namespace SAM
37 {
38 
39 static void print_error(const std::string& err)
40 {
41  // ToDo: GR Note: We've got to get these std:cout errors and messages off the console, and into the coin logfile, however
42  // my first attempt to do that, ended in failure. Primarily because adding 'util.h' to this source causes all kinds of compile time errors
43  // due to it's inclusion of 'compat.h' mostly, where socket stuff is also defined. All that lost hair, over just trying to get
44  // the LogPrintf function here in this submodule. Added to the todo list...
45  //
46  // After thinking about this some, the i2pwrapper is isolated from all this socket stuff, perhaps we could report to the log file from there
47  // if we simple pipe these messages somewhere else that std::cout, and have the i2pwrapper pick them up and report them for us. Just an idea.
48 // #ifdef DEBUG_ON_STDOUT
49 #ifdef WIN32
50  std::cout << err << "(" << WSAGetLastError() << ")" << std::endl;
51 #else
52  std::cout << err << "(" << errno << ")" << std::endl;
53 #endif
54 // #endif // DEBUG_ON_STDOUT
55 }
56 
57 #ifdef WIN32
58 int Socket::instances_ = 0;
59 
60 void Socket::initWSA()
61 {
62  WSADATA wsadata;
63  int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
64  if (ret != NO_ERROR)
65  print_error("Failed to initialize winsock library");
66 }
67 
68 void Socket::freeWSA()
69 {
70  WSACleanup();
71 }
72 #endif
73 
74 Socket::Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string& minVer, const std::string &maxVer)
75  : socket_(SAM_INVALID_SOCKET), SAMHost_(SAMHost), SAMPort_(SAMPort), minVer_(minVer), maxVer_(maxVer)
76 {
77 #ifdef WIN32
78  if (instances_++ == 0)
79  initWSA();
80 #endif
81 
82  memset(&servAddr_, 0, sizeof(servAddr_));
83 
84  servAddr_.sin_family = AF_INET;
85  servAddr_.sin_addr.s_addr = inet_addr(SAMHost.c_str());
86  servAddr_.sin_port = htons(SAMPort);
87  bootstrapI2P();
88 }
89 
90 Socket::Socket(const sockaddr_in& addr, const std::string &minVer, const std::string& maxVer)
91  : socket_(SAM_INVALID_SOCKET), servAddr_(addr), minVer_(minVer), maxVer_(maxVer)
92 {
93 #ifdef WIN32
94  if (instances_++ == 0)
95  initWSA();
96 #endif
97  bootstrapI2P();
98 }
99 
101  : socket_(SAM_INVALID_SOCKET), servAddr_(rhs.servAddr_), minVer_(rhs.minVer_), maxVer_(rhs.maxVer_)
102 {
103 #ifdef WIN32
104  if (instances_++ == 0)
105  initWSA();
106 #endif
107  bootstrapI2P();
108 }
109 
111 {
112  close();
113 
114 #ifdef WIN32
115  if (--instances_ == 0)
116  freeWSA();
117 #endif
118 }
119 
121 {
122  init();
123  if (isOk())
124  handshake();
125 }
126 
128 {
129  socket_ = socket(AF_INET, SOCK_STREAM, 0);
131  {
132  print_error("Failed to create socket");
133  return;
134  }
135 
136  if (connect(socket_, (const sockaddr*)&servAddr_, sizeof(servAddr_)) == SAM_SOCKET_ERROR)
137  {
138  close();
139  print_error("Failed to connect to SAM");
140  return;
141  }
142 }
143 
145 {
146  SOCKET temp = socket_;
148  return temp;
149 }
150 
151 // If the handshake works, we're talking to a valid I2P router.
153 {
155  const std::string answer = this->read();
156  const Message::eStatus answerStatus = Message::checkAnswer(answer);
157  if (answerStatus == Message::OK)
158  version_ = Message::getValue(answer, "VERSION");
159  else
160  print_error("Handshake failed");
161 }
162 
163 void Socket::write(const std::string& msg)
164 {
165  if (!isOk())
166  {
167  print_error("Failed to send data because socket is closed");
168  return;
169  }
170 #ifdef DEBUG_ON_STDOUT
171  std::cout << "Send: " << msg << std::endl;
172 #endif
173  ssize_t sentBytes = send(socket_, msg.c_str(), msg.length(), 0);
174  if (sentBytes == SAM_SOCKET_ERROR)
175  {
176  close();
177  print_error("Failed to send data");
178  return;
179  }
180  if (sentBytes == 0)
181  {
182  close();
183  print_error("Socket was closed");
184  return;
185  }
186 }
187 
188 std::string Socket::read()
189 {
190  if (!isOk())
191  {
192  print_error("Failed to read data because socket is closed");
193  return std::string();
194  }
195  char buffer[SAM_BUFSIZE];
196  memset(buffer, 0, SAM_BUFSIZE);
197  ssize_t recievedBytes = recv(socket_, buffer, SAM_BUFSIZE, 0);
198  if (recievedBytes == SAM_SOCKET_ERROR)
199  {
200  close();
201  print_error("Failed to receive data");
202  return std::string();
203  }
204  if (recievedBytes == 0)
205  {
206  close();
207  print_error("Socket was closed");
208  }
209 #ifdef DEBUG_ON_STDOUT
210  std::cout << "Reply: " << buffer << std::endl;
211 #endif
212  return std::string(buffer);
213 }
214 
216 {
220 }
221 
222 bool Socket::isOk() const
223 {
224  return socket_ != SAM_INVALID_SOCKET;
225 }
226 
227 const std::string& Socket::getHost() const
228 {
229  return SAMHost_;
230 }
231 
232 uint16_t Socket::getPort() const
233 {
234  return SAMPort_;
235 }
236 
237 const std::string& Socket::getVersion() const
238 {
239  return version_;
240 }
241 
242 const std::string& Socket::getMinVer() const
243 {
244  return minVer_;
245 }
246 
247 const std::string& Socket::getMaxVer() const
248 {
249  return maxVer_;
250 }
251 
252 const sockaddr_in& Socket::getAddress() const
253 {
254  return servAddr_;
255 }
256 
257 
258 //--------------------------------------------------------------------------------------------------
259 
261  const std::string& nickname,
262  const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/,
263  uint16_t SAMPort /*= SAM_DEFAULT_PORT*/,
264  const std::string& destination /*= SAM_GENERATE_MY_DESTINATION*/,
265  const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/,
266  const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/,
267  const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/)
268  : socket_(SAMHost, SAMPort, minVer, maxVer)
269  , nickname_(nickname)
270  , sessionID_(generateSessionID())
271  , i2pOptions_(i2pOptions)
272  , isSick_(false)
273 {
274  myDestination_ = createStreamSession(destination);
275 #ifdef DEBUG_ON_STDOUT
276  std::cout << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl;
277 #endif
278 }
279 
281  : socket_(rhs.socket_)
282  , nickname_(rhs.nickname_)
283  , sessionID_(generateSessionID())
284  , myDestination_(rhs.myDestination_)
285  , i2pOptions_(rhs.i2pOptions_)
286  , isSick_(false)
287 {
288  rhs.fallSick();
289  rhs.socket_.close();
291 
292  for(ForwardedStreamsContainer::const_iterator it = rhs.forwardedStreams_.begin(), end = rhs.forwardedStreams_.end(); it != end; ++it)
293  forward(it->host, it->port, it->silent);
294 
295 // #ifdef DEBUG_ON_STDOUT
296  std::cout << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl;
297 // #endif
298 }
299 
301 {
303 #ifdef DEBUG_ON_STDOUT
304  std::cout << "Closing SAM session (" << sessionID_ << ") ..." << std::endl;
305 #endif
306 }
307 
308 /*static*/
310 {
311  static const int minSessionIDLength = 5;
312  static const int maxSessionIDLength = 9;
313  static const char sessionIDAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
314  int length = minSessionIDLength - 1;
315  std::string result;
316 
317  srand(time(NULL));
318 
319  while(length < minSessionIDLength)
320  length = rand() % maxSessionIDLength;
321 
322  while (length-- > 0)
323  result += sessionIDAlphabet[rand() % (sizeof(sessionIDAlphabet)-1)];
324 
325  return result;
326 }
327 
329 {
330  typedef RequestResult<std::auto_ptr<Socket> > ResultType;
331 
332  std::auto_ptr<Socket> streamSocket(new Socket(socket_));
333  const Message::eStatus status = accept(*streamSocket, sessionID_, silent);
334  switch(status)
335  {
336  case Message::OK:
337  return RequestResult<std::auto_ptr<Socket> >(streamSocket);
340  case Message::INVALID_ID:
341  case Message::I2P_ERROR:
342  fallSick();
343  break;
344  default:
345  break;
346  }
347  return ResultType();
348 }
349 
350 RequestResult<std::auto_ptr<Socket> > StreamSession::connect(const std::string& destination, bool silent)
351 {
352  typedef RequestResult<std::auto_ptr<Socket> > ResultType;
353 
354  std::auto_ptr<Socket> streamSocket(new Socket(socket_));
355  const Message::eStatus status = connect(*streamSocket, sessionID_, destination, silent);
356  switch(status)
357  {
358  case Message::OK:
359  return ResultType(streamSocket);
362  case Message::INVALID_ID:
363  case Message::I2P_ERROR:
364  fallSick();
365  break;
366  default:
367  break;
368  }
369  return ResultType();
370 }
371 
372 RequestResult<void> StreamSession::forward(const std::string& host, uint16_t port, bool silent)
373 {
374  typedef RequestResult<void> ResultType;
375 
376  std::auto_ptr<Socket> newSocket(new Socket(socket_));
377  const Message::eStatus status = forward(*newSocket, sessionID_, host, port, silent);
378  switch(status)
379  {
380  case Message::OK:
381  forwardedStreams_.push_back(ForwardedStream(newSocket.get(), host, port, silent));
382  newSocket.release(); // release after successful push_back only
383  return ResultType(true);
386  case Message::INVALID_ID:
387  case Message::I2P_ERROR:
388  fallSick();
389  break;
390  default:
391  break;
392  }
393  return ResultType();
394 }
395 
397 {
398  typedef RequestResult<const std::string> ResultType;
399  typedef Message::Answer<const std::string> AnswerType;
400 
401  std::auto_ptr<Socket> newSocket(new Socket(socket_));
402  const AnswerType answer = namingLookup(*newSocket, name);
403  switch(answer.status)
404  {
405  case Message::OK:
406  return ResultType(answer.value);
409  fallSick();
410  break;
411  default:
412  break;
413  }
414  return ResultType();
415 }
416 
418 {
419  typedef RequestResult<const FullDestination> ResultType;
420  typedef Message::Answer<const FullDestination> AnswerType;
421 
422  std::auto_ptr<Socket> newSocket(new Socket(socket_));
423  const AnswerType answer = destGenerate(*newSocket);
424  switch(answer.status)
425  {
426  case Message::OK:
427  return ResultType(answer.value);
430  fallSick();
431  break;
432  default:
433  break;
434  }
435  return ResultType();
436 }
437 
439 {
440  typedef Message::Answer<const std::string> AnswerType;
441 
442  const AnswerType answer = createStreamSession(socket_, sessionID_, nickname_, destination, i2pOptions_);
443  if (answer.status != Message::OK)
444  {
445  fallSick();
446  return FullDestination();
447  }
448  return FullDestination(answer.value.substr(0, I2P_DESTINATION_SIZE), answer.value, (destination == SAM_GENERATE_MY_DESTINATION));
449 }
450 
452 {
453  isSick_ = true;
454 }
455 
456 void StreamSession::stopForwarding(const std::string& host, uint16_t port)
457 {
458  for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); )
459  {
460  if (it->port == port && it->host == host)
461  {
462  delete (it->socket);
463  it = forwardedStreams_.erase(it);
464  }
465  else
466  ++it;
467  }
468 }
469 
471 {
472  for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); ++it)
473  delete (it->socket);
474  forwardedStreams_.clear();
475 }
476 
477 /*static*/
479 {
480  typedef Message::Answer<const std::string> AnswerType;
481 
482  if (!socket.isOk())
483  return AnswerType(Message::CLOSED_SOCKET);
484  socket.write(requestStr);
485  const std::string answer = socket.read();
486  const Message::eStatus status = Message::checkAnswer(answer);
487  return AnswerType(status, answer);
488 }
489 
490 /*static*/
491 Message::Answer<const std::string> StreamSession::request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess)
492 {
493  typedef Message::Answer<const std::string> AnswerType;
494 
495  const AnswerType answer = rawRequest(socket, requestStr);
496  return (answer.status == Message::OK) ?
497  AnswerType(answer.status, Message::getValue(answer.value, keyOnSuccess)) :
498  answer;
499 }
500 
501 /*static*/
502 Message::eStatus StreamSession::request(Socket& socket, const std::string& requestStr)
503 {
504  return rawRequest(socket, requestStr).status;
505 }
506 
507 /*static*/
508 Message::Answer<const std::string> StreamSession::createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination, const std::string& options)
509 {
510  return request(socket, Message::sessionCreate(Message::sssStream, sessionID, nickname, destination, options), "DESTINATION");
511 }
512 
513 /*static*/
515 {
516  return request(socket, Message::namingLookup(name), "VALUE");
517 }
518 
519 /*static*/
521 {
522 // while answer for a DEST GENERATE request doesn't contain a "RESULT" field we parse it manually
523  typedef Message::Answer<const FullDestination> ResultType;
524 
525  if (!socket.isOk())
526  return ResultType(Message::CLOSED_SOCKET, FullDestination());
527  socket.write(Message::destGenerate());
528  const std::string answer = socket.read();
529  const std::string pub = Message::getValue(answer, "PUB");
530  const std::string priv = Message::getValue(answer, "PRIV");
531  return (!pub.empty() && !priv.empty()) ? ResultType(Message::OK, FullDestination(pub, priv, /*isGenerated*/ true)) : ResultType(Message::EMPTY_ANSWER, FullDestination());
532 }
533 
534 /*static*/
535 Message::eStatus StreamSession::accept(Socket& socket, const std::string& sessionID, bool silent)
536 {
537  return request(socket, Message::streamAccept(sessionID, silent));
538 }
539 
540 /*static*/
541 Message::eStatus StreamSession::connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent)
542 {
543  return request(socket, Message::streamConnect(sessionID, destination, silent));
544 }
545 
546 /*static*/
547 Message::eStatus StreamSession::forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent)
548 {
549  return request(socket, Message::streamForward(sessionID, host, port, silent));
550 }
551 
552 const std::string& StreamSession::getNickname() const
553 {
554  return nickname_;
555 }
556 
557 const std::string& StreamSession::getSessionID() const
558 {
559  return sessionID_;
560 }
561 
562 const std::string& StreamSession::getOptions() const
563 {
564  return i2pOptions_;
565 }
566 
568 {
569  return myDestination_;
570 }
571 
573 {
574  return isSick_;
575 }
576 
577 const sockaddr_in& StreamSession::getSAMAddress() const
578 {
579  return socket_.getAddress();
580 }
581 
582 const std::string& StreamSession::getSAMHost() const
583 {
584  return socket_.getHost();
585 }
586 
588 {
589  return socket_.getPort();
590 }
591 
592 const std::string& StreamSession::getSAMMinVer() const
593 {
594  return socket_.getMinVer();
595 }
596 
597 const std::string& StreamSession::getSAMMaxVer() const
598 {
599  return socket_.getMaxVer();
600 }
601 
602 const std::string& StreamSession::getSAMVersion() const
603 {
604  return socket_.getVersion();
605 }
606 
607 //--------------------------------------------------------------------------------------------------
608 
609 
610 std::string Message::createSAMRequest(const char* format, ...)
611 {
612  char buffer[SAM_BUFSIZE];
613  // ToDo: GR note: Creating a 65K byte buffer on the stack, and then wasting the time to zero it out
614  // before using it. Just to send a 30 byte string?, seems really wasteful to me, time more than storage, many mSec...
615  memset(buffer, 0, SAM_BUFSIZE);
616 
617  va_list args;
618  va_start (args, format);
619  const int sizeToSend = vsnprintf(buffer, SAM_BUFSIZE, format, args);
620  va_end(args);
621 
622  if (sizeToSend < 0)
623  {
624  print_error("Failed to format message");
625  return std::string();
626  }
627  return std::string(buffer);
628 }
629 
630 std::string Message::hello(const std::string &minVer, const std::string &maxVer)
631 {
633 //
634 // -> HELLO VERSION
635 // MIN=$min
636 // MAX=$max
637 //
638 // <- HELLO REPLY
639 // RESULT=OK
640 // VERSION=$version
641 //
643 
644  static const char* helloFormat = "HELLO VERSION MIN=%s MAX=%s\n";
645  return createSAMRequest(helloFormat, minVer.c_str(), maxVer.c_str());
646 }
647 
648 std::string Message::sessionCreate(SessionStyle style, const std::string& sessionID, const std::string& nickname, const std::string& destination /*= SAM_GENERATE_MY_DESTINATION*/, const std::string& options /*= ""*/)
649 {
651 //
652 // -> SESSION CREATE
653 // STYLE={STREAM,DATAGRAM,RAW}
654 // ID={$nickname}
655 // DESTINATION={$private_destination_key,TRANSIENT}
656 // [option=value]*
657 //
658 // <- SESSION STATUS
659 // RESULT=OK
660 // DESTINATION=$private_destination_key
661 //
663 
664  std::string sessionStyle;
665  switch(style)
666  {
667  case sssStream: sessionStyle = "STREAM"; break;
668  case sssDatagram: sessionStyle = "DATAGRAM"; break;
669  case sssRaw: sessionStyle = "RAW"; break;
670  }
671 
672  static const char* sessionCreateFormat = "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s inbound.nickname=%s %s\n"; // we add inbound.nickname option
673  return createSAMRequest(sessionCreateFormat, sessionStyle.c_str(), sessionID.c_str(), destination.c_str(), nickname.c_str(), options.c_str());
674 }
675 
676 std::string Message::streamAccept(const std::string& sessionID, bool silent /*= false*/)
677 {
679 //
680 // -> STREAM ACCEPT
681 // ID={$nickname}
682 // [SILENT={true,false}]
683 //
684 // <- STREAM STATUS
685 // RESULT=$result
686 // [MESSAGE=...]
687 //
689 
690  static const char* streamAcceptFormat = "STREAM ACCEPT ID=%s SILENT=%s\n";
691  return createSAMRequest(streamAcceptFormat, sessionID.c_str(), silent ? "true" : "false");
692 }
693 
694 std::string Message::streamConnect(const std::string& sessionID, const std::string& destination, bool silent /*= false*/)
695 {
697 //
698 // -> STREAM CONNECT
699 // ID={$nickname}
700 // DESTINATION=$peer_public_base64_key
701 // [SILENT={true,false}]
702 //
703 // <- STREAM STATUS
704 // RESULT=$result
705 // [MESSAGE=...]
706 //
708 
709  static const char* streamConnectFormat = "STREAM CONNECT ID=%s DESTINATION=%s SILENT=%s\n";
710  return createSAMRequest(streamConnectFormat, sessionID.c_str(), destination.c_str(), silent ? "true" : "false");
711 }
712 
713 std::string Message::streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent /*= false*/)
714 {
716 //
717 // -> STREAM FORWARD
718 // ID={$nickname}
719 // PORT={$port}
720 // [HOST={$host}]
721 // [SILENT={true,false}]
722 //
723 // <- STREAM STATUS
724 // RESULT=$result
725 // [MESSAGE=...]
726 //
728  static const char* streamForwardFormat = "STREAM FORWARD ID=%s PORT=%u HOST=%s SILENT=%s\n";
729  return createSAMRequest(streamForwardFormat, sessionID.c_str(), (unsigned)port, host.c_str(), silent ? "true" : "false");
730 }
731 
732 std::string Message::namingLookup(const std::string& name)
733 {
735 //
736 // -> NAMING LOOKUP
737 // NAME=$name
738 //
739 // <- NAMING REPLY
740 // RESULT=OK
741 // NAME=$name
742 // VALUE=$base64key
743 //
745 
746  static const char* namingLookupFormat = "NAMING LOOKUP NAME=%s\n";
747  return createSAMRequest(namingLookupFormat, name.c_str());
748 }
749 
751 {
753 //
754 // -> DEST GENERATE
755 //
756 // <- DEST REPLY
757 // PUB=$pubkey
758 // PRIV=$privkey
759 //
761 
762  static const char* destGenerateFormat = "DEST GENERATE\n";
763  return createSAMRequest(destGenerateFormat);
764 }
765 
766 #define SAM_MAKESTRING(X) SAM_MAKESTRING2(X)
767 #define SAM_MAKESTRING2(X) #X
768 
769 #define SAM_CHECK_RESULT(value) \
770  if (result == SAM_MAKESTRING(value)) return value
771 
772 Message::eStatus Message::checkAnswer(const std::string& answer)
773 {
774  if (answer.empty())
775  return EMPTY_ANSWER;
776 
777  const std::string result = getValue(answer, "RESULT");
778 
791 
792  return CANNOT_PARSE_ERROR;
793 }
794 
795 #undef SAM_CHECK_RESULT
796 #undef SAM_MAKESTRING2
797 #undef SAM_MAKESTRING
798 
799 std::string Message::getValue(const std::string& answer, const std::string& key)
800 {
801  if (key.empty())
802  return std::string();
803 
804  const std::string keyPattern = key + "=";
805  size_t valueStart = answer.find(keyPattern);
806  if (valueStart == std::string::npos)
807  return std::string();
808 
809  valueStart += keyPattern.length();
810  size_t valueEnd = answer.find_first_of(' ', valueStart);
811  if (valueEnd == std::string::npos)
812  valueEnd = answer.find_first_of('\n', valueStart);
813  return answer.substr(valueStart, valueEnd - valueStart);
814 }
815 
816 
817 } // namespace SAM
const std::string & getMaxVer() const
Definition: i2psam.cpp:247
SOCKET socket_
Definition: i2psam.h:240
const std::string sessionID_
Definition: i2psam.h:397
bool isSick() const
Definition: i2psam.cpp:572
const std::string & getSAMVersion() const
Definition: i2psam.cpp:602
std::string read()
Definition: i2psam.cpp:188
static std::string streamAccept(const std::string &sessionID, bool silent=false)
Definition: i2psam.cpp:676
RequestResult< std::auto_ptr< Socket > > accept(bool silent)
Definition: i2psam.cpp:328
const std::string & getOptions() const
Definition: i2psam.cpp:562
const std::string & getSAMMaxVer() const
Definition: i2psam.cpp:597
int SOCKET
Definition: i2psam.h:69
std::string version_
Definition: i2psam.h:246
uint16_t getPort() const
Definition: i2psam.cpp:232
#define SAM_INVALID_SOCKET
Definition: i2psam.h:25
const std::string & getVersion() const
Definition: i2psam.cpp:237
#define closesocket
Definition: i2psam.cpp:27
uint16_t getSAMPort() const
Definition: i2psam.cpp:587
RequestResult< void > forward(const std::string &host, uint16_t port, bool silent)
Definition: i2psam.cpp:372
const std::string maxVer_
Definition: i2psam.h:245
uint16_t SAMPort_
Definition: i2psam.h:243
#define SAM_CHECK_RESULT(value)
Definition: i2psam.cpp:769
static std::string destGenerate()
Definition: i2psam.cpp:750
static Message::Answer< const std::string > rawRequest(Socket &socket, const std::string &requestStr)
Definition: i2psam.cpp:478
#define I2P_DESTINATION_SIZE
Definition: i2psam.cpp:31
const std::string & getSAMMinVer() const
Definition: i2psam.cpp:592
FullDestination myDestination_
Definition: i2psam.h:398
void init()
Definition: i2psam.cpp:127
#define WSAGetLastError()
Definition: compat.h:50
static Message::Answer< const std::string > request(Socket &socket, const std::string &requestStr, const std::string &keyOnSuccess)
Definition: i2psam.cpp:491
Socket(const std::string &SAMHost, uint16_t SAMPort, const std::string &minVer, const std::string &maxVer)
Definition: i2psam.cpp:74
Definition: i2psam.cpp:36
FullDestination createStreamSession(const std::string &destination)
Definition: i2psam.cpp:438
const std::string nickname_
Definition: i2psam.h:396
const std::string & getHost() const
Definition: i2psam.cpp:227
static std::string createSAMRequest(const char *format,...)
Definition: i2psam.cpp:610
static std::string streamForward(const std::string &sessionID, const std::string &host, uint16_t port, bool silent=false)
Definition: i2psam.cpp:713
void close()
Definition: i2psam.cpp:215
const std::string minVer_
Definition: i2psam.h:244
std::string SAMHost_
Definition: i2psam.h:242
RequestResult< const std::string > namingLookup(const std::string &name) const
Definition: i2psam.cpp:396
RequestResult< std::auto_ptr< Socket > > connect(const std::string &destination, bool silent)
Definition: i2psam.cpp:350
static eStatus checkAnswer(const std::string &answer)
Definition: i2psam.cpp:772
const FullDestination & getMyDestination() const
Definition: i2psam.cpp:567
#define SAM_BUFSIZE
Definition: i2psam.cpp:30
const std::string i2pOptions_
Definition: i2psam.h:399
static std::string hello(const std::string &minVer, const std::string &maxVer)
Definition: i2psam.cpp:630
#define SAM_GENERATE_MY_DESTINATION
Definition: i2psam.h:32
StreamSession(const std::string &nickname, const std::string &SAMHost=SAM_DEFAULT_ADDRESS, uint16_t SAMPort=SAM_DEFAULT_PORT, const std::string &destination=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: i2psam.cpp:260
static std::string streamConnect(const std::string &sessionID, const std::string &destination, bool silent=false)
Definition: i2psam.cpp:694
const sockaddr_in & getSAMAddress() const
Definition: i2psam.cpp:577
const std::string & getSessionID() const
Definition: i2psam.cpp:557
void stopForwardingAll()
Definition: i2psam.cpp:470
static std::string generateSessionID()
Definition: i2psam.cpp:309
const sockaddr_in & getAddress() const
Definition: i2psam.cpp:252
void bootstrapI2P()
Definition: i2psam.cpp:120
static std::string namingLookup(const std::string &name)
Definition: i2psam.cpp:732
static std::string sessionCreate(SessionStyle style, const std::string &sessionID, const std::string &nickname, const std::string &destination=SAM_GENERATE_MY_DESTINATION, const std::string &options="")
Definition: i2psam.cpp:648
std::string priv
Definition: i2psam.h:263
static std::string getValue(const std::string &answer, const std::string &key)
Definition: i2psam.cpp:799
const std::string & getSAMHost() const
Definition: i2psam.cpp:582
void fallSick() const
Definition: i2psam.cpp:451
void write(const std::string &msg)
Definition: i2psam.cpp:163
ForwardedStreamsContainer forwardedStreams_
Definition: i2psam.h:400
sockaddr_in servAddr_
Definition: i2psam.h:241
const std::string & getMinVer() const
Definition: i2psam.cpp:242
#define SAM_SOCKET_ERROR
Definition: i2psam.h:26
SOCKET release()
Definition: i2psam.cpp:144
const std::string & getNickname() const
Definition: i2psam.cpp:552
void stopForwarding(const std::string &host, uint16_t port)
Definition: i2psam.cpp:456
bool isOk() const
Definition: i2psam.cpp:222
Socket socket_
Definition: i2psam.h:395
void format(FormatIterator &fmtIter)
Definition: tinyformat.h:870
void handshake()
Definition: i2psam.cpp:152
RequestResult< const FullDestination > destGenerate() const
Definition: i2psam.cpp:417