Jump to content

Recommended Posts

Posted

I've done some reading and I think I understand the NAT punch-through problem now and I am preparing to solve it.

I'm looking for the simplest way possible to send a bunch of UDP packets to a specific IP address.  The packets don't need any format and will never even be read, I just need to spam an IP address with a bunch of nonsense data.

What's the simplest cross-platform method to do this?

Let's build cool stuff and have fun. :)

  • 2 weeks later...
Posted

Here's a rough first pass at a Socket class for doing exactly this:

#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <iostream>

#ifdef LEADWERKS_5
class Socket : public SharedObject
#else
class Socket : public Object
#endif
{
	Socket();
	virtual ~Socket();
	
	std::string ip;
	int port;
	int sock;
	
#ifndef LEADWERKS_5
	static Socket* Create(const std::string ip, const int port);
#endif	
	static int resolvehelper(const char* hostname, int family, const char* service, sockaddr_storage* pAddr);
};
#ifdef LEADWERKS_5
extern shared_ptr<Socket> CreateSocket(const std::string ip, const int port);
#endif

Socket::Socket() : sockaddr_storage addrDest ({}), port (0), sock(0) {}

Socket::~Socket()
{
	if (sock!=0) closesocket(sock);
	sock = 0;
}

int Socket::resolvehelper(const char* hostname, int family, const char* service, sockaddr_storage* pAddr)
{
    int result;
    addrinfo* result_list = NULL;
    addrinfo hints = {};
    hints.ai_family = family;
    hints.ai_socktype = SOCK_DGRAM; // without this flag, getaddrinfo will return 3x the number of addresses (one for each socket type).
    result = getaddrinfo(hostname, service, &hints, &result_list);
    if (result == 0)
    {
        //ASSERT(result_list->ai_addrlen <= sizeof(sockaddr_in));
        memcpy(pAddr, result_list->ai_addr, result_list->ai_addrlen);
        freeaddrinfo(result_list);
    }

    return result;
}

#ifdef LEADWERKS_5
shared_ptr<Socket> CreateSocket(const std::string& ip, const int port) {
	auto socket = make_shared<Socket>();
#else
Socket* Socket::Create(const std::string& ip, const int port) {
	auto socket = new Socket;	
#endif
    socket->sock = socket(AF_INET, SOCK_DGRAM, 0);
	
    sockaddr_in addrListen = {}; // zero-int, sin_port is 0, which picks a random port for bind.
    addrListen.sin_family = AF_INET;
    int result = bind(socket->sock, (sockaddr*)&addrListen, sizeof(addrListen));
    if (result == -1)
    {
       int lasterror = errno;
       std::cout << "error: " << lasterror;
       exit(1);
    }
    
    result = resolvehelper( ip, AF_INET, std::string(port), &socket->addrDest);
    if (result != 0)
    {
       int lasterror = errno;
       Print("Error: " + std::string(lasterror));
       return nullptr;
    }	
	
	return socket;
}

#ifdef LEADWERKS_5
bool Socket::Send(shared_ptr<Bank> data)
#else
bool Socket::Send(const Bank* data)
#endif
{
	Send(bank->buf,bank->GetSize());
}

bool Socket::Send(const void* data, const int size)
{
    return size == sendto(sock, data, size, 0, (sockaddr*)&addrDest, sizeof(addrDest));
}

 

Let's build cool stuff and have fun. :)

Posted

Alright, my socket class works now and I can spam random packets at any webhost or IP address:

#include "../Leadwerks.h"

namespace Leadwerks
{
	//http://www.binarytides.com/code-a-simple-socket-client-class-in-c/

	const int SOCKET_UDP = SOCK_DGRAM;
	const int SOCKET_TCP = SOCK_STREAM;

	bool Socket::Initialized = false;

	Socket::Socket() : port(0), sock(0) {}

	Socket::~Socket()
	{
#ifdef _WIN32
		if (sock != 0) closesocket(sock);
#else
		if (sock != 0) close(sock);
#endif
		sock = 0;
	}

#ifdef LEADWERKS_5
	shared_ptr<Socket> CreateSocket(const std::string ip, const int port, const int protocol)
#else
	Socket* Socket::Create(const std::string address, const int port, const int protocol)
#endif
	{
#ifdef _WIN32
		if (!Initialized)
		{
			WORD wVersionRequested;
			WSADATA wsaData;
			int err;
			wVersionRequested = MAKEWORD(2, 2);
			err = WSAStartup(wVersionRequested, &wsaData);
			if (err == 0)
			{
				Initialized = true;
			}
			else
			{
				return nullptr;
			}
		}
#endif
#ifdef LEADWERKS_5
		auto socket = make_shared<Socket>();
#else
		auto socket_ = new Socket;
#endif
		socket_->sock = socket(AF_INET, protocol, 0);
		socket_->address = address;
		socket_->port = port;
		
		if (inet_addr(address.c_str()) == -1)
		{
			struct hostent *he;
			struct in_addr **addr_list;

			//resolve the hostname, its not an ip address
			he = gethostbyname(address.c_str());
			if (he == NULL)
			{
				//gethostbyname failed
				//herror("gethostbyname");
				//cout << "Failed to resolve hostname\n";
#ifndef LEADWERKS_5
				socket_->Release();
#endif
				return nullptr;
			}

			//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
			addr_list = (struct in_addr **) he->h_addr_list;
			for (int i = 0; addr_list[i] != NULL; i++)
			{
				//strcpy(ip , inet_ntoa(*addr_list[i]) );
				socket_->server.sin_addr = *addr_list[i];
				//cout << address << " resolved to " << inet_ntoa(*addr_list[i]) << endl;
				break;
			}
		}
		else
		{
			socket_->server.sin_addr.s_addr = inet_addr(address.c_str());
		}

		socket_->server.sin_family = AF_INET;
		socket_->server.sin_port = htons(port);

		//Connect to remote server
		if (connect(socket_->sock, (struct sockaddr *)&socket_->server, sizeof(server)) < 0)
		{
#ifndef LEADWERKS_5
			socket_->Release();
#endif
			return nullptr;
		}
		return socket_;
	}

#ifdef LEADWERKS_5
	bool Socket::Send(shared_ptr<Bank> data)
#else
	bool Socket::Send(Bank* data)
#endif
	{
		return Send(data->buf, data->GetSize());
	}

#ifdef LEADWERKS_5
	int Socket::Receive(shared_ptr<Bank> data)
#else
	int Socket::Receive(Bank* data)
#endif
	{
		return Receive(data->buf, data->GetSize());
	}

	bool Socket::Send(const void* data, const int size)
	{
		return send(sock, (const char*)data, size, 0) == size;
	}

	int Socket::Receive(void* data, const int size)
	{
		return recv(sock, (char*)data, size, 0);
	}
}

 

Let's build cool stuff and have fun. :)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...