// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301, USA.
//
// Author: Matas Fontanini
// Contact: matias.fontanini@gmail.com
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef SERVER_PORT
#define SERVER_PORT 5555
#endif
#define MAXPENDING 200
#define BUF_SIZE 256
#ifndef USERNAME
#define USERNAME "username"
#endif
#ifndef PASSWORD
#define PASSWORD "password"
#endif
using namespace std;
/* Command constants */
#define CMD_CONNECT 1
#define CMD_BIND 2
#define CMD_UDP_ASSOCIATIVE 3
/* Address type constants */
#define ATYP_IPV4 1
#define ATYP_DNAME 3
#define ATYP_IPV6 4
/* Connection methods */
#define METHOD_NOAUTH 0
#define METHOD_AUTH 2
#define METHOD_NOTAVAILABLE 0xff
/* Responses */
#define RESP_SUCCEDED 0
#define RESP_GEN_ERROR 1
/* Handshake */
struct MethodIdentificationPacket {
uint8_t version, nmethods;
/* uint8_t methods[nmethods]; */
} __attribute__((packed));
struct MethodSelectionPacket {
uint8_t version, method;
MethodSelectionPacket(uint8_t met) : version(5), method(met) {}
} __attribute__((packed));
/* Requests */
struct SOCKS5RequestHeader {
uint8_t version, cmd, rsv /* = 0x00 */, atyp;
} __attribute__((packed));
struct SOCK5IP4RequestBody {
uint32_t ip_dst;
uint16_t port;
} __attribute__((packed));
struct SOCK5DNameRequestBody {
uint8_t length;
/* uint8_t dname[length]; */
} __attribute__((packed));
/* Responses */
struct SOCKS5Response {
uint8_t version, cmd, rsv /* = 0x00 */, atyp;
uint32_t ip_src;
uint16_t port_src;
SOCKS5Response(bool succeded = true) : version(5), cmd(succeded ? RESP_SUCCEDED : RESP_GEN_ERROR), rsv(0), atyp(ATYP_IPV4) { }
} __attribute__((packed));
class Lock {
pthread_mutex_t mutex;
public:
Lock() {
pthread_mutex_init(&mutex, NULL);
}
~Lock() {
pthread_mutex_destroy(&mutex);
}
inline void lock() {
pthread_mutex_lock(&mutex);
}
inline void unlock() {
pthread_mutex_unlock(&mutex);
}
};
class Event {
pthread_mutex_t mutex;
pthread_cond_t condition;
public:
Event() {
pthread_mutex_init(&mutex, 0);
pthread_cond_init(&condition, 0);
}
~Event() {
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condition);
}
inline void lock() {
pthread_mutex_lock(&mutex);
}
inline void unlock() {
pthread_mutex_unlock(&mutex);
}
inline void signal() {
pthread_cond_signal(&condition);
}
inline void broadcastSignal() {
pthread_cond_broadcast(&condition);
}
inline void wait(){
pthread_cond_wait(&condition, &mutex);
}
};
Lock get_host_lock;
Event client_lock;
uint32_t client_count = 0, max_clients = 10;
void sig_handler(int signum) {
}
int create_listen_socket(struct sockaddr_in &echoclient) {
int serversock;
struct sockaddr_in echoserver;
/* Create the TCP socket */
if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
cout