他人の空似自作物置場

udp4th123.zip/udp_server.cpp

#include <winsock2.h>
#include <windows.h>
#include <vector>
#include <stdio.h>



class IPacketFilter {
protected:
	std::vector<bool (*)(struct sockaddr_in, char *)> filters;

	virtual bool CheckFilter(char *buffer) = 0;
public:
	bool recv(char *buffer, int size) {
		int _readSize;
		return this->recv(buffer, size, &_readSize);
	}

	bool recv(char *buffer, int size, int *readSize) {
		int _errorCode;
		return this->recv(buffer, size, readSize, &_errorCode);
	}

	bool recv(char *buffer, int size, int *readSize, int *errorCode) {
		while(true){
			if(!receive(buffer, size, readSize, errorCode)){
				return false;
			}
			if(*readSize == 0){
				return true;
			}
			if(CheckFilter(buffer)){
				return true;
			}
		}
	}

	virtual bool receive(char *buffer, int size, int *readSize, int *errorCode) = 0;

	virtual void AddFilter(bool (*filter)(struct sockaddr_in, char *)) {
		filters.push_back(filter);
	}
};



class PacketFilter : public IPacketFilter {
protected:
	SOCKET sock;
	struct sockaddr_in saddr;

	bool CheckFilter(char *buffer) {
		std::vector<bool (*)(struct sockaddr_in, char *)>::iterator p = filters.begin();
		while(p != filters.end()){
			if(!(*p)(saddr, buffer)) {
				return false;
			}
			++p;
		}
		return true;
	}
public:
	PacketFilter(u_long addr){
		SetAddr(addr);
	}

	PacketFilter(const PacketFilter &obj) {
		SetAddr(obj.saddr.sin_addr.s_addr);
	}

	void SetAddr(u_long addr){
		DWORD flag = 1;
		sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
		if(sock == INVALID_SOCKET){
			printf("ソケットの取得に失敗しました");
		}

		memset(&saddr,0,sizeof(saddr));
		saddr.sin_family = AF_INET;
		saddr.sin_addr.s_addr = addr;
		saddr.sin_port = htons(0);
		if(bind(sock,(struct sockaddr *)&saddr,sizeof(struct sockaddr)) == SOCKET_ERROR){
			printf("bind error\n");
		}
		if(0!=ioctlsocket(sock,0x98000001,&flag)){
			printf("ioctlsocket error(0x98000001)\n");
		}
		if(0!=ioctlsocket(sock, FIONBIO, &flag)) {
			printf("ioctlsocket error(FIONBIO)\n");
		}
	}

	~PacketFilter() {
		closesocket(sock);
	}


	bool receive(char *buffer, int size, int *readSize, int *errorCode) {
		int recvRet;
		int ret;
		WSASetLastError(0);
		recvRet = ::recv(sock, buffer, size, 0);
		if(recvRet > 0){
			ret = true;
			*readSize = recvRet;
			*errorCode = 0;
		} else {
			*readSize = 0;
			*errorCode = WSAGetLastError();
			if(*errorCode == WSAEWOULDBLOCK || *errorCode == 0){
				*errorCode = 0;
				ret = true;
			} else {
				ret = false;
			}
		}
		return ret;
	}
};


class FilterList : public IPacketFilter {
protected:
	std::vector<PacketFilter> list;
	bool CheckFilter(char *buffer) {
		return true;
	}
public:
	void add(PacketFilter &filter) {
		list.push_back(filter);
	}
	bool receive(char *buffer, int size, int *readSize, int *errorCode) {
		std::vector<PacketFilter>::iterator p = list.begin();
		while(p != list.end()){
			const bool ret = p->recv(buffer, size, readSize, errorCode);
			if(!ret) {
				return false;
			} else if(readSize > 0){
				return true;
			}
			++p;
		}
		return true;
	}
	virtual void AddFilter(bool (*filter)(struct sockaddr_in, char *)) {
		std::vector<PacketFilter>::iterator p = list.begin();
		while(p != list.end()){
			p->AddFilter(filter);
			++p;
		}
	}
};


class NetworkAdapter {
private:
	union {
		u_long addr;
		unsigned char addr_c[4];
	};
	char addr_s[17];
public:
	NetworkAdapter(u_long _addr) {
		addr = _addr;
		sprintf(addr_s,"%d.%d.%d.%d",addr_c[0],addr_c[1],addr_c[2],addr_c[3]);
	}

	u_long GetAddr() {
		return addr;
	}

	char *ToString() {
		return addr_s;
	}

	PacketFilter CreatePacketFilter(){
		PacketFilter pf(addr);
		return pf;
	}
};

class NetworkAdapters {
private:
	std::vector<NetworkAdapter> Adapter;
public:
	NetworkAdapters() {
		SOCKET sock;
		char buffer[1024];
		SOCKET_ADDRESS_LIST *addressList = (SOCKET_ADDRESS_LIST *)buffer;
		DWORD d;

		if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP))) {
			printf("INVALID_SOCKET\n");
			exit(0);
		}

		if (WSAIoctl(sock, SIO_ADDRESS_LIST_QUERY, NULL, 0, buffer, sizeof(buffer), &d, NULL, NULL) != 0) {
			printf("WSAIoctl error\n");
			exit(0);
		}

		int i = 0;
		while(i < addressList->iAddressCount) {
			NetworkAdapter item(((SOCKADDR_IN*)addressList->Address[i].lpSockaddr)->sin_addr.s_addr);
			Adapter.push_back(item);
			i++;
		}
	}

	FilterList CreatePacketFilter(){
		FilterList pf;
		std::vector<NetworkAdapter>::iterator p = Adapter.begin();
		while(p != Adapter.end()){
			pf.add(p->CreatePacketFilter());
			++p;
		}
		return pf;
	}
};


bool IsUDP(char *buffer) {
	if((buffer[0]&0xF0) != 0x40){
		return false;
	}
	if(((unsigned char *)buffer)[9] != 17) {
		return false;
	}
	return true;
}

bool IsTCP(char *buffer) {
	if((buffer[0]&0xF0) != 0x40){
		return false;
	}
	if(((unsigned char *)buffer)[9] != 6) {
		return false;
	}
	return true;
}

bool RecvAddressEqual(u_long addr, char *buffer) {
	if(addr != *(u_long *)&buffer[16]) {
		return false;
	}
	return true;
}

bool SendAddressEqual(u_long addr, char *buffer) {
	if(addr != *(u_long *)&buffer[12]) {
		return false;
	}
	return true;
}

bool RecvPortEqual(unsigned short port, char *buffer) {
	int addr;
	addr = (((unsigned char *)buffer)[0] & 0x0F) * 4;
	addr = addr + 2;
	if(port != ((*(unsigned char *)&buffer[addr]) << 8) + *(unsigned char *)&buffer[addr+1]) {
		return false;
	}
	return true;
}

bool SendPortEqual(unsigned short port, char *buffer) {
	int addr;
	addr = (((unsigned char *)buffer)[0] & 0x0F) * 4;
	if(port != ((*(unsigned char *)&buffer[addr]) << 8) + *(unsigned char *)&buffer[addr+1]) {
		return false;
	}
	return true;
}

bool MyFilter(struct sockaddr_in addr, char *buffer) {
	return IsUDP(buffer) && RecvAddressEqual(addr.sin_addr.s_addr, buffer) && RecvPortEqual(10800, buffer);
}

char *GetBody(char *buffer) {
	int addr;
	addr = (((unsigned char *)buffer)[0] & 0x0F) * 4;
	if(IsUDP(buffer)){
		addr += 8;
	} else if(IsTCP(buffer)){
		addr += ((((unsigned char *)buffer)[addr + 12] & 0xF0) >> 4) * 4;
	}
	return &buffer[addr];
}

class ToolUseChecker {
protected:
	FilterList pf;
public:
	ToolUseChecker() {
		NetworkAdapters na;
		pf = na.CreatePacketFilter();
		pf.AddFilter(MyFilter);
	}

	bool Check() {
		char checkBuf[] = {
			0x01,
			0x02, 0x00, 0x2A, 0x31, 0x56, 0x6F, 0x69, 0x63, 0x65, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72,
			0x02, 0x00, 0x2A, 0x31, 0x56, 0x6F, 0x69, 0x63, 0x65, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72,
			0x00, 0x00, 0x00, 0x00
		};
		char buffer[4096];
		int RecvSize;

		while(TRUE){
			if(pf.recv(buffer, sizeof(buffer), &RecvSize)) {
				if(RecvSize == 0){
					return false;
				}
				if(!IsUDP(buffer)){
					continue;
				}
				if(0 != memcmp(GetBody(buffer),checkBuf,sizeof(checkBuf))){
					continue;
				}
				break;
			}
			return false;
		}
		return true;
	}
};

int main(){
	WSADATA wsad;

	if(WSAStartup(MAKEWORD(2,1),&wsad)){
		printf("初期化に失敗しました");
		return -1;
	}
	if(wsad.wVersion != MAKEWORD(2,1)){
		printf("未対応のバージョンです");
		return -1;
	}

	ToolUseChecker checker;

	while(true) {
		if(checker.Check()) {
			puts("success\n");
		}
		Sleep(1000);
	}

	return 0;
}