commit 8b13aa7d7ada133b1f290cd4b9bd5639549c7b9f Author: Kiritow <1362050620@qq.com> Date: Wed Oct 21 18:35:54 2020 +0800 First Commit diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..4f886fe --- /dev/null +++ b/Readme.md @@ -0,0 +1,4 @@ +# SimpleSock + +Simple Socket Utility + diff --git a/SimpleSock.cpp b/SimpleSock.cpp new file mode 100644 index 0000000..5ea9095 --- /dev/null +++ b/SimpleSock.cpp @@ -0,0 +1,268 @@ +#include "SimpleSock.h" +#include +#include +#include +#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, int, std::string> DNSResolve(const std::string& host) + { + std::vector 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); + } +} diff --git a/SimpleSock.h b/SimpleSock.h new file mode 100644 index 0000000..57f971a --- /dev/null +++ b/SimpleSock.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include + +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, 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(); +} diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..4678a34 --- /dev/null +++ b/test.cpp @@ -0,0 +1,35 @@ +#include "SimpleSock.h" +#include +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; +}