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)); |
134 return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0])); |
135 } |
135 } |
136 |
136 |
137 class UDPClientSocket : public Socket { |
137 class UDPClientSocket : public Socket { |
138 private: |
138 private: |
139 AddressInfos remoteAddresses; |
139 AddressInfos::AddressInfo remoteAddress; |
140 |
140 |
141 public: |
141 public: |
142 |
142 |
143 UDPClientSocket(AddressInfos remoteAddresses) : remoteAddresses(remoteAddresses) { |
143 UDPClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress) { |
144 } |
144 } |
145 |
145 |
146 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
146 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
147 bool sctp = findOption(options, OPTION_PROTOCOL) == PROTOCOL_SCTP; |
147 bool sctp = findOption(options, OPTION_PROTOCOL) == PROTOCOL_SCTP; |
148 return openClientSocket<UDPClientSocket>(options, sctp ? SOCK_SEQPACKET : SOCK_DGRAM, sctp ? IPPROTO_SCTP : IPPROTO_UDP); |
148 return openClientSocket<UDPClientSocket>(options, sctp ? SOCK_SEQPACKET : SOCK_DGRAM, sctp ? IPPROTO_SCTP : IPPROTO_UDP); |
149 } |
149 } |
150 |
150 |
151 void send(const std::string& message) override { |
151 void send(const std::string& message) override { |
152 auto ai = remoteAddresses[0].ai; |
152 auto ai = remoteAddress.ai; |
153 FD s(::socket(AF_INET, ai->ai_socktype, ai->ai_protocol)); |
153 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); |
154 sendto(s.getFD(), message.c_str(), message.size(), 0, ai->ai_addr, ai->ai_addrlen); |
155 } |
155 } |
156 |
156 |
157 const std::string receive() override { |
157 const std::string receive() override { |
161 |
161 |
162 }; |
162 }; |
163 |
163 |
164 class TCPClientSocket : public Socket { |
164 class TCPClientSocket : public Socket { |
165 private: |
165 private: |
166 AddressInfos remoteAddresses; |
166 AddressInfos::AddressInfo remoteAddress; |
167 |
167 |
168 public: |
168 public: |
169 |
169 |
170 TCPClientSocket(AddressInfos remoteAddresses) : remoteAddresses(remoteAddresses) { |
170 TCPClientSocket(AddressInfos::AddressInfo remoteAddress) : remoteAddress(remoteAddress) { |
171 } |
171 } |
172 |
172 |
173 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
173 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
174 return openClientSocket<TCPClientSocket>(options, SOCK_STREAM, IPPROTO_TCP); |
174 return openClientSocket<TCPClientSocket>(options, SOCK_STREAM, IPPROTO_TCP); |
175 } |
175 } |
176 |
176 |
177 void send(const std::string& message) override { |
177 void send(const std::string& message) override { |
178 auto ai = remoteAddresses[0].ai; |
178 auto ai = remoteAddress.ai; |
179 FD s(::socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)); |
179 FD s(::socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)); |
180 check(::connect(s.getFD(), ai->ai_addr, ai->ai_addrlen), "connect socket"); |
180 check(::connect(s.getFD(), ai->ai_addr, ai->ai_addrlen), "connect socket"); |
181 ssize_t written = ::write(s.getFD(), message.c_str(), message.size()); |
181 ssize_t written = ::write(s.getFD(), message.c_str(), message.size()); |
182 if (written != message.size()) throw std::logic_error("writing to the socket failed"); |
182 if (written != message.size()) throw std::logic_error("writing to the socket failed"); |
183 // TODO: partial writes, repeat |
183 // TODO: partial writes, repeat |