src/Socket.cpp
branchv_0
changeset 21 1c6c86697837
parent 19 7a9a52e949b9
child 22 9a7c42cca24b
equal deleted inserted replaced
20:ad21bff45051 21:1c6c86697837
   122 		throw std::out_of_range("invalid index for AddressInfo: " + std::to_string(index));
   122 		throw std::out_of_range("invalid index for AddressInfo: " + std::to_string(index));
   123 	}
   123 	}
   124 
   124 
   125 };
   125 };
   126 
   126 
   127 template<class SocketClass> static std::shared_ptr<SocketClass> openClientSocket(const SocketOptions& options, int socketType, int protocol) {
   127 template<class SocketClass, class... MoreArgs> static std::shared_ptr<SocketClass> openClientSocket(const SocketOptions& options, int socketType, int protocol, MoreArgs... moreArgs) {
   128 	AddressInfos remoteAddresses = AddressInfos::getAddressInfos(
   128 	AddressInfos remoteAddresses = AddressInfos::getAddressInfos(
   129 			findOption(options, OPTION_HOST, true),
   129 			findOption(options, OPTION_HOST, true),
   130 			findOption(options, OPTION_PORT, true),
   130 			findOption(options, OPTION_PORT, true),
   131 			socketType,
   131 			socketType,
   132 			protocol);
   132 			protocol);
   133 
   133 
   134 	return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0]));
   134 	return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0], moreArgs...));
   135 }
   135 }
   136 
   136 
   137 class UDPClientSocket : public Socket {
   137 class UDPClientSocket : public Socket {
   138 private:
   138 private:
   139 	AddressInfos::AddressInfo remoteAddress;
   139 	AddressInfos::AddressInfo remoteAddress;
   140 	useconds_t delay = 0;
   140 	useconds_t delay = 0;
   141 
   141 	FD socket;
   142 public:
   142 
   143 
   143 public:
   144 	UDPClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress) {
   144 
       
   145 	UDPClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress), socket(::socket(remoteAddress.ai->ai_family, remoteAddress.ai->ai_socktype, remoteAddress.ai->ai_protocol)) {
   145 	}
   146 	}
   146 
   147 
   147 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
   148 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
   148 		bool sctp = findOption(options, OPTION_PROTOCOL) == PROTOCOL_SCTP;
   149 		auto socket = openClientSocket<UDPClientSocket>(options, SOCK_DGRAM, IPPROTO_UDP);
   149 		auto socket = openClientSocket<UDPClientSocket>(options, sctp ? SOCK_SEQPACKET : SOCK_DGRAM, sctp ? IPPROTO_SCTP : IPPROTO_UDP);
   150 		socket->delay = std::stol(findOption(options, OPTION_DELAY, false, "0")); // TODO: Move to SocketHandler? Or delete.
   150 		socket->delay = std::stol(findOption(options, OPTION_DELAY, false, "0"));
       
   151 		return socket;
   151 		return socket;
   152 	}
   152 	}
   153 
   153 
   154 	void send(const std::string& message) override {
   154 	void send(const std::string& message) override {
   155 		auto ai = remoteAddress.ai;
   155 		auto ai = remoteAddress.ai;
   156 		FD s(::socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol));
   156 		sendto(socket.getFD(), message.c_str(), message.size(), 0, ai->ai_addr, ai->ai_addrlen);
   157 		sendto(s.getFD(), message.c_str(), message.size(), 0, ai->ai_addr, ai->ai_addrlen);
       
   158 		if (delay) usleep(delay);
   157 		if (delay) usleep(delay);
   159 	}
   158 	}
   160 
   159 
   161 	const std::string receive() override {
   160 	const std::string receive() override {
   162 		// TODO: TCP receive()
   161 		// TODO: UDP receive()
   163 		return "TODO: receive() a message";
   162 		return "TODO: receive() a message";
   164 	}
   163 	}
   165 
       
   166 };
   164 };
   167 
   165 
   168 class TCPClientSocket : public Socket {
   166 class TCPClientSocket : public Socket {
   169 private:
   167 private:
   170 	AddressInfos::AddressInfo remoteAddress;
   168 	AddressInfos::AddressInfo remoteAddress;
   189 
   187 
   190 	const std::string receive() override {
   188 	const std::string receive() override {
   191 		// TODO: TCP receive()
   189 		// TODO: TCP receive()
   192 		return "TODO: receive() a message";
   190 		return "TODO: receive() a message";
   193 	}
   191 	}
   194 
   192 };
   195 
   193 
       
   194 class SCTPStreamClientSocket : public Socket {
       
   195 private:
       
   196 	AddressInfos::AddressInfo remoteAddress;
       
   197 
       
   198 public:
       
   199 
       
   200 	SCTPStreamClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress) {
       
   201 	}
       
   202 
       
   203 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
       
   204 		auto socket = openClientSocket<SCTPStreamClientSocket>(options, SOCK_STREAM, IPPROTO_SCTP);
       
   205 		return socket;
       
   206 	}
       
   207 
       
   208 	void send(const std::string& message) override {
       
   209 		auto ai = remoteAddress.ai;
       
   210 		FD s(::socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol));
       
   211 		check(::connect(s.getFD(), ai->ai_addr, ai->ai_addrlen), "connect socket");
       
   212 		ssize_t written = ::write(s.getFD(), message.c_str(), message.size());
       
   213 		if (written != message.size()) throw std::logic_error("writing to the socket failed");
       
   214 		// TODO: partial writes, repeat
       
   215 	}
       
   216 
       
   217 	const std::string receive() override {
       
   218 		// TODO: SCTP receive()
       
   219 		return "TODO: receive() a message";
       
   220 	}
   196 };
   221 };
   197 
   222 
   198 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
   223 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
   199 class TemplateSocketFactory : public SocketFactory {
   224 class TemplateSocketFactory : public SocketFactory {
   200 public:
   225 public:
   214 {
   239 {
   215 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
   240 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
   216 			std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
   241 			std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
   217 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
   242 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
   218 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   243 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   219 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   244 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, SCTPStreamClientSocket >> (), // TODO: do we need a stream-mode SCTP?
   220 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   245 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, SCTPStreamClientSocket >> (),
   221 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   246 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: do we need a stream-mode SCTP?
   222 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   247 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   223 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   248 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   224 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   249 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   225 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   250 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   226 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   251 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class