protohackers

My solutions to the protohackers.com challenges.
git clone git://henryandlizzy.uk/protohackers
Log | Files | Refs

protohack-4.cpp (1234B)


      1 #include <poll.h>
      2 
      3 #include <iostream>
      4 #include <sstream>
      5 #include <map>
      6 #include <vector>
      7 
      8 #include "inet.hpp"
      9 
     10 using namespace std;
     11 
     12 std::map<string, string> database = {{"version", "m3henry-protohack-4"}};
     13 
     14 string recv_udp(descriptor& d, sockaddr_in& a)
     15 {
     16 	char buf[1024];
     17 	socklen_t addr_size = sizeof a;
     18 
     19 	ssize_t n = ::recvfrom(d, buf, sizeof buf, 0, (sockaddr*)&a, &addr_size);
     20 	if (n > 0)
     21 		return {buf, (size_t)n};
     22 	else
     23 		return {};
     24 }
     25 
     26 int send_udp(descriptor& d, sockaddr_in const& a, string const& s)
     27 {
     28 	return ::sendto(d, s.data(), s.size(), 0, (sockaddr const*)&a, sizeof a);
     29 }
     30 
     31 int main()
     32 {
     33 	auto incoming = inet::listen(SOCK_DGRAM);
     34 
     35 	for (;;)
     36 	{
     37 		struct sockaddr_in addr;
     38 		socklen_t addr_size = sizeof addr;
     39 		char buf[1024];
     40 
     41 		auto len = ::recvfrom(incoming, buf, sizeof buf, 0, (sockaddr*)&addr, &addr_size);
     42 		if (len < 0)
     43 			return 1;
     44 		string msg{buf, (size_t)len};
     45 		string ip = inet_ntoa(addr.sin_addr);
     46 		cout << ip << ":" << addr.sin_port << " '" << msg << "'\n";
     47 
     48 		auto split = msg.find('=');
     49 		if (split == string::npos)
     50 		{
     51 			send_udp(incoming, addr, msg + '=' + database[msg]);
     52 			continue;
     53 		}
     54 		auto key = msg.substr(0, split);
     55 		if (key != "version")
     56 			database[key] = msg.substr(split+1);
     57 	}
     58 }