linux - C++ socket never ready for write with poll -
i writing c++ wrapper sockets on linux. can connect read/write http server poll function works reading reason won't work writing. have tried using gdb , appears poll sets fd.revents
0 when fd.events pollout
poll code:
/** *@brief assigns request.reply based on fd.revents */ static void translate_request(mizaru::pollrequest &request, pollfd &fd) { assert( (fd.revents & pollhup) == 0); assert( (fd.revents & pollerr) == 0); assert( (fd.revents & pollnval) == 0); switch(fd.revents) { case (pollin | pollout) : request.reply = mizaru::poll_reply_rw; break; case pollin : request.reply = mizaru::poll_reply_read; break; case pollout : request.reply = mizaru::poll_reply_write; default : request.reply = 0; } } /** * @fills in fd.events based on request.request * , fd.fd based on request.sock */ static void prep_request(mizaru::pollrequest &request, pollfd &fd) { fd.fd = request.sock.get_handle(); switch(request.request) { case mizaru::polltype::poll_read : fd.events = pollin; break; case mizaru::polltype::poll_write : fd.events = pollout; break; default : fd.events = pollin | pollout; } } void mizaru::trans::poll(mizaru::pollrequest &request,const std::chrono::milliseconds& wait_time) noexcept { pollfd fd; prep_request(request, fd); poll(&fd, 1, wait_time.count()); translate_request(request, fd); }
mizaru::pollrequest
struct :
struct pollrequest { pollrequest(polltype request, const syncsocket &sock) : sock(sock), request(request), reply(poll_reply_fail) {} const syncsocket & sock; polltype request; uint8_t reply; };
syncsocket.get_handle()
returns fd returned socket(int,int,int)
in sys/socket.h
test function :
bool test_poll() { mizaru::ipv4 ip ( "54.225.138.124" ); mizaru::syncsockettcp sock ( ip, 80 ,true); mizaru::pollrequest request{mizaru::polltype::poll_read, sock}; std::chrono::milliseconds time(1000); mizaru::poll(request, time); if(request.reply == mizaru::poll_reply_read) { std::cout << "fail test_poll first read" <<std::endl; return false; } request.request = mizaru::polltype::poll_write; mizaru::poll(request, time); if(request.reply != mizaru::poll_reply_write) { std::cout << "fail test_poll first write" << std::endl; return false; } std::string towrite ( "get / http/1.1\nhost: httpbin.org\n\n" ); mizaru::byte_buffer write_buff; ( char c : towrite ) { write_buff.push_back ( c ); } unsigned int r_value = sock.write ( write_buff ); if (r_value != towrite.size()) { std::cout << "fail test_poll r_value" << std::endl; return false; } request.request = mizaru::polltype::poll_read; mizaru::poll(request, time); if(request.reply != mizaru::poll_reply_read) { std::cout << "fail test_poll second read" << std::endl; return false; } request.request = mizaru::polltype::poll_write; mizaru::poll(request, time); if(request.reply != mizaru::poll_reply_write) { std::cout << "fail test_poll second write " << std::endl; return false; } return true; }
polltype
enum :
enum polltype {poll_read, poll_write, poll_rw};
poll_reply_*
constants :
constexpr uint8_t poll_reply_read = 0x01; constexpr uint8_t poll_reply_write = 0x02; constexpr uint8_t poll_reply_rw = poll_reply_read | poll_reply_write; constexpr uint8_t poll_reply_fail = 0;
i sorry sample code not directly compilable trying make short, since proper http 200 ok reply can assume connecting , read/write handled properly. test fails when polling write
in translate_request()
:
switch(fd.revents) { case (pollin | pollout) : request.reply = mizaru::poll_reply_rw; break; case pollin : request.reply = mizaru::poll_reply_read; break; case pollout : request.reply = mizaru::poll_reply_write; default : request.reply = 0; }
you missing break
in both pollout
, default
cases. pollout
falls through default
, erasing evidence pollout
occurred.
Comments
Post a Comment