merge with my changes
This commit is contained in:
759
i2psam.cpp
Normal file
759
i2psam.cpp
Normal file
@ -0,0 +1,759 @@
|
|||||||
|
// Copyright (c) 2012-2013 giv
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
#include "i2psam.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h> // for memset
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#define closesocket close
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SAM_BUFSIZE 65536
|
||||||
|
#define I2P_DESTINATION_SIZE 516
|
||||||
|
|
||||||
|
namespace SAM
|
||||||
|
{
|
||||||
|
|
||||||
|
static void print_error(const std::string& err)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
std::cout << err << "(" << WSAGetLastError() << ")" << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << err << "(" << errno << ")" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
int Socket::instances_ = 0;
|
||||||
|
|
||||||
|
void Socket::initWSA()
|
||||||
|
{
|
||||||
|
WSADATA wsadata;
|
||||||
|
int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
|
||||||
|
if (ret != NO_ERROR)
|
||||||
|
print_error("Failed to initialize winsock library");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::freeWSA()
|
||||||
|
{
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Socket::Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string& minVer, const std::string &maxVer)
|
||||||
|
: socket_(SAM_INVALID_SOCKET), SAMHost_(SAMHost), SAMPort_(SAMPort), minVer_(minVer), maxVer_(maxVer)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
if (instances_++ == 0)
|
||||||
|
initWSA();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(&servAddr_, 0, sizeof(servAddr_));
|
||||||
|
|
||||||
|
servAddr_.sin_family = AF_INET;
|
||||||
|
servAddr_.sin_addr.s_addr = inet_addr(SAMHost.c_str());
|
||||||
|
servAddr_.sin_port = htons(SAMPort);
|
||||||
|
|
||||||
|
init();
|
||||||
|
if (isOk())
|
||||||
|
handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::Socket(const sockaddr_in& addr, const std::string &minVer, const std::string& maxVer)
|
||||||
|
: socket_(SAM_INVALID_SOCKET), servAddr_(addr), minVer_(minVer), maxVer_(maxVer)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
if (instances_++ == 0)
|
||||||
|
initWSA();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
init();
|
||||||
|
if (isOk())
|
||||||
|
handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::Socket(const Socket& rhs)
|
||||||
|
: socket_(SAM_INVALID_SOCKET), servAddr_(rhs.servAddr_), minVer_(rhs.minVer_), maxVer_(rhs.maxVer_)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
if (instances_++ == 0)
|
||||||
|
initWSA();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
init();
|
||||||
|
if (isOk())
|
||||||
|
handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::~Socket()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
if (--instances_ == 0)
|
||||||
|
freeWSA();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::init()
|
||||||
|
{
|
||||||
|
socket_ = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (socket_ == SAM_INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
print_error("Failed to create socket");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(socket_, (const sockaddr*)&servAddr_, sizeof(servAddr_)) == SAM_SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
print_error("Failed to connect to SAM");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET Socket::release()
|
||||||
|
{
|
||||||
|
SOCKET temp = socket_;
|
||||||
|
socket_ = SAM_INVALID_SOCKET;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::handshake()
|
||||||
|
{
|
||||||
|
this->write(Message::hello(minVer_, maxVer_));
|
||||||
|
const std::string answer = this->read();
|
||||||
|
const Message::eStatus answerStatus = Message::checkAnswer(answer);
|
||||||
|
if (answerStatus == Message::OK)
|
||||||
|
version_ = Message::getValue(answer, "VERSION");
|
||||||
|
else
|
||||||
|
print_error("Handshake failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::write(const std::string& msg)
|
||||||
|
{
|
||||||
|
if (!isOk())
|
||||||
|
{
|
||||||
|
print_error("Failed to send data because socket is closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::cout << "Send: " << msg << std::endl;
|
||||||
|
ssize_t sentBytes = send(socket_, msg.c_str(), msg.length(), 0);
|
||||||
|
if (sentBytes == SAM_SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
print_error("Failed to send data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sentBytes == 0)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
print_error("Socket was closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Socket::read()
|
||||||
|
{
|
||||||
|
if (!isOk())
|
||||||
|
{
|
||||||
|
print_error("Failed to read data because socket is closed");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
char buffer[SAM_BUFSIZE];
|
||||||
|
memset(buffer, 0, SAM_BUFSIZE);
|
||||||
|
ssize_t recievedBytes = recv(socket_, buffer, SAM_BUFSIZE, 0);
|
||||||
|
if (recievedBytes == SAM_SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
print_error("Failed to recieve data");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
if (recievedBytes == 0)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
print_error("Socket was closed");
|
||||||
|
}
|
||||||
|
std::cout << "Reply: " << buffer << std::endl;
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::close()
|
||||||
|
{
|
||||||
|
if (socket_ != SAM_INVALID_SOCKET)
|
||||||
|
::closesocket(socket_);
|
||||||
|
socket_ = SAM_INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::isOk() const
|
||||||
|
{
|
||||||
|
return socket_ != SAM_INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& Socket::getHost() const
|
||||||
|
{
|
||||||
|
return SAMHost_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Socket::getPort() const
|
||||||
|
{
|
||||||
|
return SAMPort_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& Socket::getVersion() const
|
||||||
|
{
|
||||||
|
return version_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& Socket::getMinVer() const
|
||||||
|
{
|
||||||
|
return minVer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& Socket::getMaxVer() const
|
||||||
|
{
|
||||||
|
return maxVer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sockaddr_in& Socket::getAddress() const
|
||||||
|
{
|
||||||
|
return servAddr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
std::string StreamSession::generateSessionID()
|
||||||
|
{
|
||||||
|
static const int minSessionIDLength = 5;
|
||||||
|
static const int maxSessionIDLength = 9;
|
||||||
|
static const char sessionIDAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
int length = minSessionIDLength - 1;
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
while(length < minSessionIDLength)
|
||||||
|
length = rand() % maxSessionIDLength;
|
||||||
|
|
||||||
|
while (length-- > 0)
|
||||||
|
result += sessionIDAlphabet[rand() % (sizeof(sessionIDAlphabet)-1)];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamSession::StreamSession(
|
||||||
|
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& minVer /*= SAM_DEFAULT_MIN_VER*/,
|
||||||
|
const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/)
|
||||||
|
: socket_(new Socket(SAMHost, SAMPort, minVer, maxVer))/*,
|
||||||
|
reconnects_(0)*/
|
||||||
|
|
||||||
|
{
|
||||||
|
(void)createStreamSession(socket_, nickname, myDestination);
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamSession::~StreamSession()
|
||||||
|
{
|
||||||
|
for (ForwardedStreamsContainer::const_iterator it = forwardedStreams_.begin(), end = forwardedStreams_.end(); it != end; ++it)
|
||||||
|
delete (it->socket);
|
||||||
|
std::cout << "Closing SAM session..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Result StreamSession::request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess)
|
||||||
|
{
|
||||||
|
if (!socket.isOk())
|
||||||
|
return Message::Result(Message::CLOSED_SOCKET, std::string());
|
||||||
|
socket.write(requestStr);
|
||||||
|
const std::string answer = socket.read();
|
||||||
|
const Message::eStatus status = Message::checkAnswer(answer);
|
||||||
|
return Message::Result(status, (status == Message::OK) ? Message::getValue(answer, keyOnSuccess) : answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Result StreamSession::createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination)
|
||||||
|
{
|
||||||
|
return request(socket, Message::sessionCreate(Message::sssStream, sessionID, nickname, destination), "DESTINATION");
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Result StreamSession::namingLookup(Socket& socket, const std::string& name)
|
||||||
|
{
|
||||||
|
return request(socket, Message::namingLookup(name), "VALUE");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const Message::eStatus, std::pair<const std::string, const std::string> > StreamSession::destGenerate(Socket &socket)
|
||||||
|
{
|
||||||
|
// while answer for DEST GENERATE request doesn't contain a "RESULT" field we parse it manually
|
||||||
|
|
||||||
|
typedef std::pair<const std::string, const std::string> AnswerType;
|
||||||
|
typedef std::pair<const Message::eStatus, AnswerType> ResultType;
|
||||||
|
|
||||||
|
if (!socket.isOk())
|
||||||
|
return ResultType(Message::CLOSED_SOCKET, AnswerType());
|
||||||
|
socket.write(Message::destGenerate());
|
||||||
|
const std::string answer = socket.read();
|
||||||
|
const std::string pub = Message::getValue(answer, "PUB");
|
||||||
|
const std::string priv = Message::getValue(answer, "PRIV");
|
||||||
|
return (!pub.empty() && !priv.empty()) ? ResultType(Message::OK, AnswerType(pub, priv)) : ResultType(Message::EMPTY_ANSWER, AnswerType());
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Result StreamSession::accept(Socket& socket, const std::string& sessionID, bool silent)
|
||||||
|
{
|
||||||
|
return request(socket, Message::streamAccept(sessionID, silent), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Result StreamSession::connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent)
|
||||||
|
{
|
||||||
|
return request(socket, Message::streamConnect(sessionID, destination, silent), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Result StreamSession::forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent)
|
||||||
|
{
|
||||||
|
return request(socket, Message::streamForward(sessionID, host, port, silent), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamSession::createStreamSession(std::auto_ptr<Socket>& newSocket, const std::string& nickname, const std::string& myDestination /*= SAM_GENERATE_MY_DESTINATION*/)
|
||||||
|
{
|
||||||
|
const std::string newSessionID = generateSessionID();
|
||||||
|
const Message::Result result = createStreamSession(*newSocket, newSessionID, nickname, myDestination);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nickname_ = nickname;
|
||||||
|
myDestination_ = result.second;
|
||||||
|
sessionID_ = newSessionID;
|
||||||
|
socket_ = newSocket; // release and copy
|
||||||
|
|
||||||
|
if (!reforwardAll())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamSession::createStreamSession(
|
||||||
|
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& minVer /*= SAM_DEFAULT_MIN_VER*/,
|
||||||
|
const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/)
|
||||||
|
{
|
||||||
|
std::auto_ptr<Socket> newSocket(new Socket(SAMHost, SAMPort, minVer, maxVer));
|
||||||
|
return createStreamSession(newSocket, nickname, myDestination);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamSession::createStreamSession()
|
||||||
|
{
|
||||||
|
std::auto_ptr<Socket> newSocket(new Socket(*socket_));
|
||||||
|
return createStreamSession(newSocket, nickname_, myDestination_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamSession::reforwardAll()
|
||||||
|
{
|
||||||
|
for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(), end = forwardedStreams_.end(); it != end; ++it)
|
||||||
|
{
|
||||||
|
std::auto_ptr<Socket> newSocket(new Socket(*socket_));
|
||||||
|
const Message::Result result = forward(*newSocket, sessionID_, it->host, it->port, it->silent);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (it->socket);
|
||||||
|
it->socket = newSocket.release();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StreamSession::namingLookup(const std::string& name)
|
||||||
|
{
|
||||||
|
const Message::Result result = namingLookup(*socket_, name);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
return result.second;
|
||||||
|
case Message::EMPTY_ANSWER:
|
||||||
|
case Message::CLOSED_SOCKET:
|
||||||
|
return createStreamSession() ? namingLookup(name) : std::string();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StreamSession::getMyAddress()
|
||||||
|
{
|
||||||
|
// return namingLookup(SAM_MY_NAME);
|
||||||
|
return myDestination_.substr(0, I2P_DESTINATION_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const std::string, const std::string> StreamSession::destGenerate()
|
||||||
|
{
|
||||||
|
const std::pair<const Message::eStatus, std::pair<const std::string, const std::string> > result = destGenerate(*socket_);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
return result.second;
|
||||||
|
case Message::EMPTY_ANSWER:
|
||||||
|
case Message::CLOSED_SOCKET:
|
||||||
|
return createStreamSession() ? destGenerate() : std::pair<const std::string, const std::string>();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return std::pair<const std::string, const std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET StreamSession::accept(bool silent /*= false*/)
|
||||||
|
{
|
||||||
|
Socket streamSocket(*socket_);
|
||||||
|
const Message::Result result = accept(streamSocket, sessionID_, silent);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
return streamSocket.release();
|
||||||
|
case Message::EMPTY_ANSWER:
|
||||||
|
case Message::CLOSED_SOCKET:
|
||||||
|
case Message::INVALID_ID:
|
||||||
|
return createStreamSession() ? accept(silent) : SAM_INVALID_SOCKET;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return SAM_INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET StreamSession::connect(const std::string& destination, bool silent /*= false*/)
|
||||||
|
{
|
||||||
|
Socket streamSocket(*socket_);
|
||||||
|
const Message::Result result = connect(streamSocket, sessionID_, destination, silent);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
return streamSocket.release();
|
||||||
|
case Message::EMPTY_ANSWER:
|
||||||
|
case Message::CLOSED_SOCKET:
|
||||||
|
case Message::INVALID_ID:
|
||||||
|
return createStreamSession() ? connect(destination, silent) : SAM_INVALID_SOCKET;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return SAM_INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamSession::forward(const std::string& host, uint16_t port, bool silent /*= false*/)
|
||||||
|
{
|
||||||
|
std::auto_ptr<Socket> newSocket(new Socket(*socket_));
|
||||||
|
const Message::Result result = forward(*newSocket, sessionID_, host, port, silent);
|
||||||
|
switch(result.first)
|
||||||
|
{
|
||||||
|
case Message::OK:
|
||||||
|
break;
|
||||||
|
case Message::EMPTY_ANSWER:
|
||||||
|
case Message::CLOSED_SOCKET:
|
||||||
|
case Message::INVALID_ID:
|
||||||
|
return createStreamSession() ? forward(host, port, silent) : false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ForwardedStream fwdStream;
|
||||||
|
fwdStream.host = host;
|
||||||
|
fwdStream.port = port;
|
||||||
|
fwdStream.silent = silent;
|
||||||
|
fwdStream.socket = newSocket.release();
|
||||||
|
|
||||||
|
forwardedStreams_.push_back(fwdStream);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamSession::stopForwarding(const std::string& host, uint16_t port)
|
||||||
|
{
|
||||||
|
for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); )
|
||||||
|
{
|
||||||
|
if (it->port == port && it->host == host)
|
||||||
|
{
|
||||||
|
delete (it->socket);
|
||||||
|
it = forwardedStreams_.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getNickname() const
|
||||||
|
{
|
||||||
|
return nickname_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getSessionID() const
|
||||||
|
{
|
||||||
|
return sessionID_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getMyDestination() const
|
||||||
|
{
|
||||||
|
return myDestination_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getHost() const
|
||||||
|
{
|
||||||
|
return socket_->getHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t StreamSession::getPort() const
|
||||||
|
{
|
||||||
|
return socket_->getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getMinVer() const
|
||||||
|
{
|
||||||
|
return socket_->getMinVer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getMaxVer() const
|
||||||
|
{
|
||||||
|
return socket_->getMaxVer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& StreamSession::getVersion() const
|
||||||
|
{
|
||||||
|
return socket_->getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
const sockaddr_in& StreamSession::getAddress() const
|
||||||
|
{
|
||||||
|
return socket_->getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
std::string Message::createSAMRequest(const char* format, ...)
|
||||||
|
{
|
||||||
|
char buffer[SAM_BUFSIZE];
|
||||||
|
memset(buffer, 0, SAM_BUFSIZE);
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start (args, format);
|
||||||
|
int sizeToSend = vsnprintf(buffer, SAM_BUFSIZE, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (sizeToSend < 0)
|
||||||
|
{
|
||||||
|
print_error("Failed to format message");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Message::hello(const std::string &minVer, const std::string &maxVer)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> HELLO VERSION
|
||||||
|
// MIN=$min
|
||||||
|
// MAX=$max
|
||||||
|
//
|
||||||
|
// <- HELLO REPLY
|
||||||
|
// RESULT=OK
|
||||||
|
// VERSION=$version
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const char* helloFormat = "HELLO VERSION MIN=%s MAX=%s\n";
|
||||||
|
return createSAMRequest(helloFormat, minVer.c_str(), maxVer.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
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 /*= ""*/)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> SESSION CREATE
|
||||||
|
// STYLE={STREAM,DATAGRAM,RAW}
|
||||||
|
// ID={$nickname}
|
||||||
|
// DESTINATION={$private_destination_key,TRANSIENT}
|
||||||
|
// [option=value]*
|
||||||
|
//
|
||||||
|
// <- SESSION STATUS
|
||||||
|
// RESULT=OK
|
||||||
|
// DESTINATION=$private_destination_key
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string sessionStyle;
|
||||||
|
switch(style)
|
||||||
|
{
|
||||||
|
case sssStream: sessionStyle = "STREAM"; break;
|
||||||
|
case sssDatagram: sessionStyle = "DATAGRAM"; break;
|
||||||
|
case sssRaw: sessionStyle = "RAW"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* sessionCreateFormat = "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s inbound.nickname=%s %s\n"; // we add inbound.nickname option
|
||||||
|
return createSAMRequest(sessionCreateFormat, sessionStyle.c_str(), sessionID.c_str(), destination.c_str(), nickname.c_str(), options.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Message::streamAccept(const std::string& sessionID, bool silent /*= false*/)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> STREAM ACCEPT
|
||||||
|
// ID={$nickname}
|
||||||
|
// [SILENT={true,false}]
|
||||||
|
//
|
||||||
|
// <- STREAM STATUS
|
||||||
|
// RESULT=$result
|
||||||
|
// [MESSAGE=...]
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const char* streamAcceptFormat = "STREAM ACCEPT ID=%s SILENT=%s\n";
|
||||||
|
return createSAMRequest(streamAcceptFormat, sessionID.c_str(), silent ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Message::streamConnect(const std::string& sessionID, const std::string& destination, bool silent /*= false*/)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> STREAM CONNECT
|
||||||
|
// ID={$nickname}
|
||||||
|
// DESTINATION=$peer_public_base64_key
|
||||||
|
// [SILENT={true,false}]
|
||||||
|
//
|
||||||
|
// <- STREAM STATUS
|
||||||
|
// RESULT=$result
|
||||||
|
// [MESSAGE=...]
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const char* streamConnectFormat = "STREAM CONNECT ID=%s DESTINATION=%s SILENT=%s\n";
|
||||||
|
return createSAMRequest(streamConnectFormat, sessionID.c_str(), destination.c_str(), silent ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Message::streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent /*= false*/)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> STREAM FORWARD
|
||||||
|
// ID={$nickname}
|
||||||
|
// PORT={$port}
|
||||||
|
// [HOST={$host}]
|
||||||
|
// [SILENT={true,false}]
|
||||||
|
//
|
||||||
|
// <- STREAM STATUS
|
||||||
|
// RESULT=$result
|
||||||
|
// [MESSAGE=...]
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
static const char* streamForwardFormat = "STREAM FORWARD ID=%s PORT=%u HOST=%s SILENT=%s\n";
|
||||||
|
return createSAMRequest(streamForwardFormat, sessionID.c_str(), (unsigned)port, host.c_str(), silent ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Message::namingLookup(const std::string& name)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> NAMING LOOKUP
|
||||||
|
// NAME=$name
|
||||||
|
//
|
||||||
|
// <- NAMING REPLY
|
||||||
|
// RESULT=OK
|
||||||
|
// NAME=$name
|
||||||
|
// VALUE=$base64key
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const char* namingLookupFormat = "NAMING LOOKUP NAME=%s\n";
|
||||||
|
return createSAMRequest(namingLookupFormat, name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Message::destGenerate()
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// -> DEST GENERATE
|
||||||
|
//
|
||||||
|
// <- DEST REPLY
|
||||||
|
// PUB=$pubkey
|
||||||
|
// PRIV=$privkey
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const char* destGenerateFormat = "DEST GENERATE\n";
|
||||||
|
return createSAMRequest(destGenerateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SAM_MAKESTRING(X) SAM_MAKESTRING2(X)
|
||||||
|
#define SAM_MAKESTRING2(X) #X
|
||||||
|
|
||||||
|
#define SAM_CHECK_RESULT(value) \
|
||||||
|
if (result == SAM_MAKESTRING(value)) return value
|
||||||
|
|
||||||
|
Message::eStatus Message::checkAnswer(const std::string& answer)
|
||||||
|
{
|
||||||
|
if (answer.empty())
|
||||||
|
return EMPTY_ANSWER;
|
||||||
|
|
||||||
|
const std::string result = getValue(answer, "RESULT");
|
||||||
|
|
||||||
|
SAM_CHECK_RESULT(OK);
|
||||||
|
SAM_CHECK_RESULT(DUPLICATED_DEST);
|
||||||
|
SAM_CHECK_RESULT(DUPLICATED_ID);
|
||||||
|
SAM_CHECK_RESULT(I2P_ERROR);
|
||||||
|
SAM_CHECK_RESULT(INVALID_ID);
|
||||||
|
SAM_CHECK_RESULT(INVALID_KEY);
|
||||||
|
SAM_CHECK_RESULT(CANT_REACH_PEER);
|
||||||
|
SAM_CHECK_RESULT(TIMEOUT);
|
||||||
|
SAM_CHECK_RESULT(NOVERSION);
|
||||||
|
SAM_CHECK_RESULT(KEY_NOT_FOUND);
|
||||||
|
SAM_CHECK_RESULT(PEER_NOT_FOUND);
|
||||||
|
SAM_CHECK_RESULT(ALREADY_ACCEPTING);
|
||||||
|
|
||||||
|
return CANNOT_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SAM_CHECK_RESULT
|
||||||
|
#undef SAM_MAKESTRING2
|
||||||
|
#undef SAM_MAKESTRING
|
||||||
|
|
||||||
|
std::string Message::getValue(const std::string& answer, const std::string& key)
|
||||||
|
{
|
||||||
|
if (key.empty())
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
const std::string keyPattern = key + "=";
|
||||||
|
size_t valueStart = answer.find(keyPattern);
|
||||||
|
if (valueStart == std::string::npos)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
valueStart += keyPattern.length();
|
||||||
|
size_t valueEnd = answer.find_first_of(' ', valueStart);
|
||||||
|
if (valueEnd == std::string::npos)
|
||||||
|
valueEnd = answer.find_first_of('\n', valueStart);
|
||||||
|
return answer.substr(valueStart, valueEnd - valueStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SAM
|
292
i2psam.h
Normal file
292
i2psam.h
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
// Copyright (c) 2012-2013 giv
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// see full documentation at http://www.i2p2.i2p/samv3.html
|
||||||
|
#ifndef I2PSAM_H
|
||||||
|
#define I2PSAM_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
//#define _WIN32_WINNT 0x0501
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h> // for sockaddr_in
|
||||||
|
#include <arpa/inet.h> // for ntohs and htons
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SAM_INVALID_SOCKET (-1)
|
||||||
|
#define SAM_SOCKET_ERROR (-1)
|
||||||
|
|
||||||
|
#define SAM_DEFAULT_ADDRESS "127.0.0.1"
|
||||||
|
#define SAM_DEFAULT_PORT 7656
|
||||||
|
#define SAM_DEFAULT_MIN_VER "3.0"
|
||||||
|
#define SAM_DEFAULT_MAX_VER "3.0"
|
||||||
|
#define SAM_GENERATE_MY_DESTINATION "TRANSIENT"
|
||||||
|
#define SAM_MY_NAME "ME"
|
||||||
|
|
||||||
|
namespace SAM
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef int SOCKET;
|
||||||
|
|
||||||
|
class Message
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum SessionStyle
|
||||||
|
{
|
||||||
|
sssStream,
|
||||||
|
sssDatagram,
|
||||||
|
sssRaw
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eStatus
|
||||||
|
{
|
||||||
|
OK,
|
||||||
|
EMPTY_ANSWER,
|
||||||
|
CLOSED_SOCKET,
|
||||||
|
CANNOT_PARSE_ERROR,
|
||||||
|
|
||||||
|
// The destination is already in use
|
||||||
|
//
|
||||||
|
// -> SESSION CREATE ...
|
||||||
|
// <- SESSION STATUS RESULT=DUPLICATED_DEST
|
||||||
|
DUPLICATED_DEST,
|
||||||
|
|
||||||
|
// The nickname is already associated with a session
|
||||||
|
//
|
||||||
|
// -> SESSION CREATE ...
|
||||||
|
// <- SESSION STATUS RESULT=DUPLICATED_ID
|
||||||
|
DUPLICATED_ID,
|
||||||
|
|
||||||
|
// A generic I2P error (e.g. I2CP disconnection, etc.)
|
||||||
|
//
|
||||||
|
// -> HELLO VERSION ...
|
||||||
|
// <- HELLO REPLY RESULT=I2P_ERROR MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> SESSION CREATE ...
|
||||||
|
// <- SESSION STATUS RESULT=I2P_ERROR MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> STREAM CONNECT ...
|
||||||
|
// <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> STREAM ACCEPT ...
|
||||||
|
// <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> STREAM FORWARD ...
|
||||||
|
// <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> NAMING LOOKUP ...
|
||||||
|
// <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message}
|
||||||
|
I2P_ERROR,
|
||||||
|
|
||||||
|
// Stream session ID doesn't exist
|
||||||
|
//
|
||||||
|
// -> STREAM CONNECT ...
|
||||||
|
// <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> STREAM ACCEPT ...
|
||||||
|
// <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> STREAM FORWARD ...
|
||||||
|
// <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message}
|
||||||
|
INVALID_ID,
|
||||||
|
|
||||||
|
// The destination is not a valid private destination key
|
||||||
|
//
|
||||||
|
// -> SESSION CREATE ...
|
||||||
|
// <- SESSION STATUS RESULT=INVALID_KEY MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> STREAM CONNECT ...
|
||||||
|
// <- STREAM STATUS RESULT=INVALID_KEY MESSAGE={$message}
|
||||||
|
//
|
||||||
|
// -> NAMING LOOKUP ...
|
||||||
|
// <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message}
|
||||||
|
INVALID_KEY,
|
||||||
|
|
||||||
|
// The peer exists, but cannot be reached
|
||||||
|
//
|
||||||
|
// -> STREAM CONNECT ...
|
||||||
|
// <- STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE={$message}
|
||||||
|
CANT_REACH_PEER,
|
||||||
|
|
||||||
|
// Timeout while waiting for an event (e.g. peer answer)
|
||||||
|
//
|
||||||
|
// -> STREAM CONNECT ...
|
||||||
|
// <- STREAM STATUS RESULT=TIMEOUT MESSAGE={$message}
|
||||||
|
TIMEOUT,
|
||||||
|
|
||||||
|
// The SAM bridge cannot find a suitable version
|
||||||
|
//
|
||||||
|
// -> HELLO VERSION ...
|
||||||
|
// <- HELLO REPLY RESULT=NOVERSION MESSAGE={$message}
|
||||||
|
NOVERSION,
|
||||||
|
|
||||||
|
// The naming system can't resolve the given name
|
||||||
|
//
|
||||||
|
// -> NAMING LOOKUP ...
|
||||||
|
// <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message}
|
||||||
|
KEY_NOT_FOUND,
|
||||||
|
|
||||||
|
// The peer cannot be found on the network
|
||||||
|
//
|
||||||
|
// ??
|
||||||
|
PEER_NOT_FOUND,
|
||||||
|
|
||||||
|
// ??
|
||||||
|
//
|
||||||
|
// -> STREAM ACCEPT
|
||||||
|
// <- STREAM STATUS RESULT=ALREADY_ACCEPTING
|
||||||
|
ALREADY_ACCEPTING,
|
||||||
|
|
||||||
|
// ??
|
||||||
|
FAILED,
|
||||||
|
// ??
|
||||||
|
CLOSED
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::pair<const Message::eStatus, const std::string> Result;
|
||||||
|
|
||||||
|
static std::string hello(const std::string& minVer, const std::string& maxVer);
|
||||||
|
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 = "");
|
||||||
|
static std::string streamAccept(const std::string& sessionID, bool silent = false);
|
||||||
|
static std::string streamConnect(const std::string& sessionID, const std::string& destination, bool silent = false);
|
||||||
|
static std::string streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent = false);
|
||||||
|
|
||||||
|
static std::string namingLookup(const std::string& name);
|
||||||
|
static std::string destGenerate();
|
||||||
|
|
||||||
|
static eStatus checkAnswer(const std::string& answer);
|
||||||
|
static std::string getValue(const std::string& answer, const std::string& key);
|
||||||
|
private:
|
||||||
|
static std::string createSAMRequest(const char* format, ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Socket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SOCKET socket_;
|
||||||
|
sockaddr_in servAddr_;
|
||||||
|
std::string SAMHost_;
|
||||||
|
uint16_t SAMPort_;
|
||||||
|
const std::string minVer_;
|
||||||
|
const std::string maxVer_;
|
||||||
|
std::string version_;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
static int instances_;
|
||||||
|
static void initWSA();
|
||||||
|
static void freeWSA();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void handshake();
|
||||||
|
void init();
|
||||||
|
|
||||||
|
Socket& operator=(const Socket&);
|
||||||
|
public:
|
||||||
|
Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string &minVer, const std::string& maxVer);
|
||||||
|
Socket(const sockaddr_in& addr, const std::string& minVer, const std::string& maxVer);
|
||||||
|
Socket(const Socket& rhs); // creates a new socket with the same parameters
|
||||||
|
~Socket();
|
||||||
|
|
||||||
|
void write(const std::string& msg);
|
||||||
|
std::string read();
|
||||||
|
SOCKET release();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
bool isOk() const;
|
||||||
|
|
||||||
|
const std::string& getVersion() const;
|
||||||
|
const std::string& getHost() const;
|
||||||
|
uint16_t getPort() const;
|
||||||
|
const std::string& getMinVer() const;
|
||||||
|
const std::string& getMaxVer() const;
|
||||||
|
|
||||||
|
const sockaddr_in& getAddress() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StreamSession
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*mutable*/ std::auto_ptr<Socket> socket_;
|
||||||
|
std::string nickname_;
|
||||||
|
std::string sessionID_;
|
||||||
|
std::string myDestination_;
|
||||||
|
|
||||||
|
struct ForwardedStream
|
||||||
|
{
|
||||||
|
Socket* socket;
|
||||||
|
std::string host;
|
||||||
|
uint16_t port;
|
||||||
|
bool silent;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::list<ForwardedStream> ForwardedStreamsContainer;
|
||||||
|
ForwardedStreamsContainer forwardedStreams_;
|
||||||
|
|
||||||
|
bool createStreamSession(std::auto_ptr<Socket>& newSocket, const std::string& nickname, const std::string& myDestination = SAM_GENERATE_MY_DESTINATION);
|
||||||
|
bool reforwardAll();
|
||||||
|
|
||||||
|
static Message::Result request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess);
|
||||||
|
|
||||||
|
// commands
|
||||||
|
static Message::Result createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination);
|
||||||
|
static Message::Result namingLookup(Socket& socket, const std::string& name);
|
||||||
|
static std::pair<const Message::eStatus, std::pair<const std::string, const std::string> > destGenerate(Socket& socket);
|
||||||
|
static Message::Result accept(Socket& socket, const std::string& sessionID, bool silent);
|
||||||
|
static Message::Result connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent);
|
||||||
|
static Message::Result forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
StreamSession(
|
||||||
|
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& minVer = SAM_DEFAULT_MIN_VER,
|
||||||
|
const std::string& maxVer = SAM_DEFAULT_MAX_VER);
|
||||||
|
~StreamSession();
|
||||||
|
|
||||||
|
bool createStreamSession(
|
||||||
|
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& minVer = SAM_DEFAULT_MIN_VER,
|
||||||
|
const std::string& maxVer = SAM_DEFAULT_MAX_VER); // recreates with new parameters
|
||||||
|
|
||||||
|
bool createStreamSession(); // recreates with current parameters
|
||||||
|
|
||||||
|
std::string namingLookup(const std::string& name);
|
||||||
|
std::string getMyAddress();
|
||||||
|
std::pair<const std::string, const std::string> destGenerate(); // .first is a public key, .second is a private key
|
||||||
|
|
||||||
|
SOCKET accept(bool silent = false);
|
||||||
|
SOCKET connect(const std::string& destination, bool silent = false);
|
||||||
|
bool forward(const std::string& host, uint16_t port, bool silent = false); // forwards stream to a socket. the socket should be bound with the port, should listen and accept connections on that port
|
||||||
|
|
||||||
|
void stopForwarding(const std::string& host, uint16_t port);
|
||||||
|
|
||||||
|
static std::string generateSessionID();
|
||||||
|
|
||||||
|
const sockaddr_in& getAddress() const;
|
||||||
|
const std::string& getHost() const;
|
||||||
|
uint16_t getPort() const;
|
||||||
|
const std::string& getNickname() const;
|
||||||
|
const std::string& getSessionID() const;
|
||||||
|
const std::string& getMyDestination() const;
|
||||||
|
const std::string& getMinVer() const;
|
||||||
|
const std::string& getMaxVer() const;
|
||||||
|
const std::string& getVersion() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SAM
|
||||||
|
|
||||||
|
#endif // I2PSAM_H
|
23
i2psam.pro
Normal file
23
i2psam.pro
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#-------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project created by QtCreator 2013-01-06T03:07:13
|
||||||
|
#
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
QT -= core gui
|
||||||
|
|
||||||
|
TARGET = i2psam
|
||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += staticlib
|
||||||
|
|
||||||
|
SOURCES += i2psam.cpp
|
||||||
|
|
||||||
|
HEADERS += i2psam.h
|
||||||
|
unix:!symbian {
|
||||||
|
maemo5 {
|
||||||
|
target.path = /opt/usr/lib
|
||||||
|
} else {
|
||||||
|
target.path = /usr/lib
|
||||||
|
}
|
||||||
|
INSTALLS += target
|
||||||
|
}
|
78
makefile.linux-mingw
Normal file
78
makefile.linux-mingw
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#############################################################################
|
||||||
|
# Makefile for building: libi2psam
|
||||||
|
# Generated by qmake (2.01a) (Qt 4.8.3) on: ?? ????. 10 02:43:02 2013
|
||||||
|
# Project: i2psam.pro
|
||||||
|
# Template: lib
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
####### Compiler, tools and options
|
||||||
|
|
||||||
|
CC = i586-mingw32msvc-gcc
|
||||||
|
CXX = i586-mingw32msvc-g++
|
||||||
|
DEFINES = -D_MT -DWIN32 -D_WINDOWS
|
||||||
|
CFLAGS = -pipe -isystem /usr/i586-mingw32msvc/include/ -O2 -Wall -Wextra $(DEFINES)
|
||||||
|
CXXFLAGS = -O2 -fexceptions -Wall -Wextra $(DEFINES)
|
||||||
|
INCPATH = -I'../../dependencies/mingw32/qt/include' -I'../../dependencies/mingw32' -I'../../dependencies/mingw32/qt/include/ActiveQt' -I'../../dependencies/mingw32/qt/mkspecs/unsupported/win32-g++-cross'
|
||||||
|
LIB = i586-mingw32msvc-ar -ru
|
||||||
|
COPY = cp
|
||||||
|
SED = sed
|
||||||
|
COPY_FILE = $(COPY)
|
||||||
|
COPY_DIR = cp -R
|
||||||
|
DEL_FILE = rm -f
|
||||||
|
DEL_DIR = rmdir
|
||||||
|
MOVE = mv
|
||||||
|
CHK_DIR_EXISTS= test -d
|
||||||
|
MKDIR = mkdir -p
|
||||||
|
INSTALL_FILE = $(COPY_FILE)
|
||||||
|
INSTALL_PROGRAM = $(COPY_FILE)
|
||||||
|
INSTALL_DIR = $(COPY_DIR)
|
||||||
|
|
||||||
|
####### Files
|
||||||
|
|
||||||
|
SOURCES = i2psam.cpp
|
||||||
|
OBJECTS = i2psam.o
|
||||||
|
TARGET = libi2psam.a
|
||||||
|
|
||||||
|
####### Implicit rules
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp .cc .cxx .C .c
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
|
||||||
|
|
||||||
|
.cc.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
|
||||||
|
|
||||||
|
.cxx.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
|
||||||
|
|
||||||
|
.C.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
|
||||||
|
|
||||||
|
####### Build rules
|
||||||
|
|
||||||
|
first: all
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJECTS)
|
||||||
|
$(LIB) $(TARGET) $(OBJECTS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-$(DEL_FILE) release/$(TARGET)
|
||||||
|
-$(DEL_FILE) release/i2psam.o
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
-$(DEL_FILE) $(TARGET)
|
||||||
|
|
||||||
|
####### Compile
|
||||||
|
|
||||||
|
release/i2psam.o: i2psam.cpp i2psam.h
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/i2psam.o i2psam.cpp
|
||||||
|
|
||||||
|
####### Install
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
|
115
makefile.unix
Normal file
115
makefile.unix
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#############################################################################
|
||||||
|
# Makefile for building: libi2psam.a
|
||||||
|
# Generated by qmake (2.01a) (Qt 4.8.1) on: Wed Jan 30 13:00:04 2013
|
||||||
|
# Project: i2psam.pro
|
||||||
|
# Template: lib
|
||||||
|
# Command: /usr/bin/qmake -o Makefile i2psam.pro
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
####### Compiler, tools and options
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CXX = g++
|
||||||
|
CFLAGS = -m64 -pipe -O2 -fPIC -Wall -W -D_REENTRANT $(DEFINES)
|
||||||
|
CXXFLAGS = -m64 -pipe -O2 -fPIC -Wall -W -D_REENTRANT $(DEFINES)
|
||||||
|
AR = ar cqs
|
||||||
|
RANLIB =
|
||||||
|
TAR = tar -cf
|
||||||
|
COMPRESS = gzip -9f
|
||||||
|
COPY = cp -f
|
||||||
|
SED = sed
|
||||||
|
COPY_FILE = $(COPY)
|
||||||
|
COPY_DIR = $(COPY) -r
|
||||||
|
STRIP = strip
|
||||||
|
INSTALL_FILE = install -m 644 -p
|
||||||
|
INSTALL_DIR = $(COPY_DIR)
|
||||||
|
INSTALL_PROGRAM = install -m 755 -p
|
||||||
|
DEL_FILE = rm -f
|
||||||
|
SYMLINK = ln -f -s
|
||||||
|
DEL_DIR = rmdir
|
||||||
|
MOVE = mv -f
|
||||||
|
CHK_DIR_EXISTS= test -d
|
||||||
|
MKDIR = mkdir -p
|
||||||
|
|
||||||
|
####### Output directory
|
||||||
|
|
||||||
|
OBJECTS_DIR = ./
|
||||||
|
|
||||||
|
####### Files
|
||||||
|
|
||||||
|
SOURCES = i2psam.cpp
|
||||||
|
OBJECTS = i2psam.o
|
||||||
|
DESTDIR =
|
||||||
|
TARGET = libi2psam.a
|
||||||
|
|
||||||
|
first: all
|
||||||
|
####### Implicit rules
|
||||||
|
|
||||||
|
.SUFFIXES: .o .c .cpp .cc .cxx .C
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||||
|
|
||||||
|
.cc.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||||
|
|
||||||
|
.cxx.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||||
|
|
||||||
|
.C.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
|
||||||
|
|
||||||
|
####### Build rules
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
staticlib: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJECTS) $(OBJCOMP)
|
||||||
|
-$(DEL_FILE) $(TARGET)
|
||||||
|
$(AR) $(TARGET) $(OBJECTS)
|
||||||
|
|
||||||
|
|
||||||
|
dist:
|
||||||
|
@$(CHK_DIR_EXISTS) .tmp/i2psam1.0.0 || $(MKDIR) .tmp/i2psam1.0.0
|
||||||
|
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/i2psam1.0.0/ && $(COPY_FILE) --parents i2psam.h .tmp/i2psam1.0.0/ && $(COPY_FILE) --parents i2psam.cpp .tmp/i2psam1.0.0/ && (cd `dirname .tmp/i2psam1.0.0` && $(TAR) i2psam1.0.0.tar i2psam1.0.0 && $(COMPRESS) i2psam1.0.0.tar) && $(MOVE) `dirname .tmp/i2psam1.0.0`/i2psam1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/i2psam1.0.0
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-$(DEL_FILE) $(TARGET)
|
||||||
|
-$(DEL_FILE) $(OBJECTS)
|
||||||
|
|
||||||
|
|
||||||
|
####### Sub-libraries
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
-$(DEL_FILE) $(TARGET)
|
||||||
|
|
||||||
|
|
||||||
|
check: first
|
||||||
|
|
||||||
|
####### Compile
|
||||||
|
|
||||||
|
i2psam.o: i2psam.cpp i2psam.h
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o i2psam.o i2psam.cpp
|
||||||
|
|
||||||
|
####### Install
|
||||||
|
|
||||||
|
install_target: first FORCE
|
||||||
|
@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/usr/lib/ || $(MKDIR) $(INSTALL_ROOT)/usr/lib/
|
||||||
|
-$(INSTALL_FILE) "$(TARGET)" "$(INSTALL_ROOT)/usr/lib/$(TARGET)"
|
||||||
|
|
||||||
|
uninstall_target: FORCE
|
||||||
|
-$(DEL_FILE) "$(INSTALL_ROOT)/usr/lib/$(TARGET)"
|
||||||
|
-$(DEL_DIR) $(INSTALL_ROOT)/usr/lib/
|
||||||
|
|
||||||
|
|
||||||
|
install: install_target FORCE
|
||||||
|
|
||||||
|
uninstall: uninstall_target FORCE
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
|
Reference in New Issue
Block a user