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<Socket> openClientSocket(const SocketOptions& options, int socketType, int protocol) { |
127 template<class SocketClass> static std::shared_ptr<SocketClass> openClientSocket(const SocketOptions& options, int socketType, int protocol) { |
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); |
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 |
141 |
141 public: |
142 public: |
142 |
143 |
143 UDPClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress) { |
144 UDPClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress) { |
144 } |
145 } |
145 |
146 |
146 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
147 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
147 bool sctp = findOption(options, OPTION_PROTOCOL) == PROTOCOL_SCTP; |
148 bool sctp = findOption(options, OPTION_PROTOCOL) == PROTOCOL_SCTP; |
148 return openClientSocket<UDPClientSocket>(options, sctp ? SOCK_SEQPACKET : SOCK_DGRAM, sctp ? IPPROTO_SCTP : 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")); |
|
151 return socket; |
149 } |
152 } |
150 |
153 |
151 void send(const std::string& message) override { |
154 void send(const std::string& message) override { |
152 auto ai = remoteAddress.ai; |
155 auto ai = remoteAddress.ai; |
153 FD s(::socket(AF_INET, ai->ai_socktype, ai->ai_protocol)); |
156 FD s(::socket(AF_INET, ai->ai_socktype, ai->ai_protocol)); |
154 sendto(s.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); |
155 } |
159 } |
156 |
160 |
157 const std::string receive() override { |
161 const std::string receive() override { |
158 // TODO: TCP receive() |
162 // TODO: TCP receive() |
159 return "TODO: receive() a message"; |
163 return "TODO: receive() a message"; |