First Commit

This commit is contained in:
Kirigaya Kazuto 2020-10-21 18:35:54 +08:00
commit 8b13aa7d7a
4 changed files with 347 additions and 0 deletions

4
Readme.md Normal file
View File

@ -0,0 +1,4 @@
# SimpleSock
Simple Socket Utility

268
SimpleSock.cpp Normal file
View File

@ -0,0 +1,268 @@
#include "SimpleSock.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
namespace SimpleSock {
void FetchLastError(int& code, std::string& msg)
{
code = GetLastError();
LPSTR buffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0, (LPSTR)&buffer, 0, NULL);
msg = std::string(buffer, size);
LocalFree(buffer);
}
sock::sock()
{
fd = -1;
_code = 0;
}
sock::sock(sock&& s) noexcept
{
fd = s.fd;
s.fd = -1;
_code = 0;
}
sock::~sock()
{
close();
}
int sock::create_socket()
{
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
FetchLastError(_code, _msg);
return -1;
}
return 0;
}
int sock::connect(const std::string& ip, int port)
{
if (fd > 0)
{
_code = -1;
_msg = "[SimpleSock] Socket already connected.";
return -2;
}
if (create_socket() < 0) return -1;
struct sockaddr_in saddr;
memset(&saddr, 0, sizeof(saddr));
if (inet_pton(AF_INET, ip.c_str(), &(saddr.sin_addr.s_addr)) != 1)
{
FetchLastError(_code, _msg);
return -1;
}
saddr.sin_port = htons(port);
saddr.sin_family = AF_INET;
int ret = ::connect(fd, (sockaddr*)&saddr, sizeof(saddr));
if (ret < 0)
{
FetchLastError(_code, _msg);
return -1;
}
return 0;
}
int sock::bind(const std::string& ip, int port)
{
if (fd > 0)
{
_code = -1;
_msg = "[SimpleSock] Socket already binded.";
return -1;
}
struct sockaddr_in saddr;
memset(&saddr, 0, sizeof(saddr));
if (inet_pton(AF_INET, ip.c_str(), &(saddr.sin_addr.s_addr)) != 1)
{
FetchLastError(_code, _msg);
return -1;
}
saddr.sin_port = htons(port);
saddr.sin_family = AF_INET;
int ret = ::bind(fd, (sockaddr*)&saddr, sizeof(saddr));
if (ret < 0)
{
FetchLastError(_code, _msg);
return -1;
}
return 0;
}
int sock::listen(int backlog)
{
int ret = ::listen(fd, backlog);
if (ret < 0)
{
FetchLastError(_code, _msg);
return -1;
}
return 0;
}
sock sock::accept()
{
sockaddr_in saddr;
socklen_t saddrsz = sizeof(saddr);
int ret = ::accept(fd, (sockaddr*)&saddr, &saddrsz);
if (ret < 0)
{
FetchLastError(_code, _msg);
return sock();
}
else
{
sock s;
s.fd = ret;
return s;
}
}
int sock::send(const void* buffer, size_t length)
{
int ret = ::send(fd, (char*)buffer, length, 0);
if (ret <= 0)
{
FetchLastError(_code, _msg);
}
return ret;
}
int sock::sendall(const void* buffer, size_t length)
{
size_t done = 0;
while (done < length)
{
int ret = send((char*)buffer + done, length - done);
if (ret <= 0) return ret;
done += ret;
}
return done;
}
int sock::recv(void* buffer, size_t length)
{
int ret = ::recv(fd, (char*)buffer, length, 0);
if (ret <= 0)
{
FetchLastError(_code, _msg);
}
return ret;
}
void sock::close()
{
if (fd > 0)
{
closesocket(fd);
fd = -1;
}
}
bool sock::valid()
{
return fd >= 0;
}
int sock::getError()
{
return _code;
}
std::string sock::getErrorMessage()
{
return _msg;
}
std::tuple<std::vector<std::string>, int, std::string> DNSResolve(const std::string& host)
{
std::vector<std::string> vec;
int _code;
std::string _msg;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo* result = nullptr;
int ret = getaddrinfo(host.c_str(), NULL, &hints, &result);
if (ret)
{
FetchLastError(_code, _msg);
return std::make_tuple(vec, _code, _msg);
}
for (struct addrinfo* ptr = result; ptr; ptr = ptr->ai_next)
{
if (ptr->ai_family == AF_INET)
{
struct sockaddr_in* paddr = (struct sockaddr_in*)(ptr->ai_addr);
char ip_buff[128] = { 0 };
const char* ptr = inet_ntop(AF_INET, &(paddr->sin_addr), ip_buff, 128);
if (ptr)
{
vec.push_back(ptr);
}
else
{
FetchLastError(_code, _msg);
}
}
}
freeaddrinfo(result);
return std::make_tuple(vec, _code, _msg);
}
int ConnectWithHttpProxy(sock& s, const std::string& proxyIP, int proxyPort, const std::string& host, int port)
{
int ret = s.connect(proxyIP, proxyPort);
if (ret < 0) return -1;
char request[1024] = { 0 };
snprintf(request, sizeof(request), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n\r\n", host.c_str(), port, host.c_str(), port);
ret = s.sendall(request, strlen(request));
if (ret != strlen(request)) return -2;
char buffer[8] = { 0 };
std::string result;
while (1)
{
ret = s.recv(buffer, 1);
if (ret <= 0) return ret;
result.push_back(buffer[0]);
if (result.find("\r\n\r\n") != std::string::npos)
{
printf("%s\n===== HTTP PROXY CONNECT FINISHED =====\n", result.c_str());
break;
}
}
return 0;
}
int InitSimpleSock()
{
WORD wd;
WSAData wdt;
wd = MAKEWORD(2, 2);
return WSAStartup(wd, &wdt);
}
}

40
SimpleSock.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <string>
#include <tuple>
#include <vector>
namespace SimpleSock
{
class sock
{
public:
sock();
sock(sock&&) noexcept;
~sock();
sock(const sock&) = delete;
sock& operator = (const sock&) = delete;
int connect(const std::string& ip, int port);
int bind(const std::string& ip, int port);
int listen(int backlog = 0);
sock accept();
int send(const void* buffer, size_t length);
int sendall(const void* buffer, size_t length);
int recv(void* buffer, size_t length);
void close();
bool valid();
int getError();
std::string getErrorMessage();
private:
int create_socket();
int fd;
int _code;
std::string _msg;
};
std::tuple<std::vector<std::string>, int, std::string> DNSResolve(const std::string& host);
int ConnectWithHttpProxy(sock& s, const std::string& proxyIP, int proxyPort, const std::string& host, int port);
int InitSimpleSock();
}

35
test.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "SimpleSock.h"
#include <iostream>
using namespace std;
using namespace SimpleSock;
int main()
{
InitSimpleSock();
sock s;
if (ConnectWithHttpProxy(s, "127.0.0.1", 12759, "106.53.10.163", 80) < 0)
{
cout << "Failed Connect Http Proxy" << endl;
return 1;
}
const char* data = "GET / HTTP/1.1\r\nConnection: close\r\nHost: paste.kiritow.com\r\n\r\n";
if (s.sendall(data, strlen(data)) != strlen(data))
{
cout << "send failed" << endl;
return 1;
}
char buff[1024] = { 0 };
int ret;
while ((ret = s.recv(buff, 1024)) > 0)
{
string temp = string(buff, ret);
cout << temp << endl;
memset(buff, 0, 1024);
}
cout << "\nFinalCode: " << ret << " Errcode:" << s.getError() << " ErrMsg:" << s.getErrorMessage() << endl;
return 0;
}