void zmq::stream_engine_t::out_event () { // If write buffer is empty, try to read new data from the encoder. if (!outsize) { outpos = NULL; encoder.get_data (&outpos, &outsize); // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitratily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. int nbytes = write (outpos, outsize); // IO error has occurred. We stop waiting for output events. // The engine is not terminated until we detect input error; // this is necessary to prevent losing incomming messages. if (nbytes == -1) { reset_pollout (handle); return; } outpos += nbytes; outsize -= nbytes; }
void xs::stream_engine_t::out_event (fd_t fd_) { bool more_data = true; // If protocol header was not yet sent... if (unlikely (!options.legacy_protocol && !header_sent)) { int hbytes = write (out_header, sizeof out_header); // It should always be possible to write the full protocol header to a // freshly connected TCP socket. Therefore, if we get an error or // partial write here the peer has disconnected. if (hbytes != sizeof out_header) { error (); return; } header_sent = true; } // If write buffer is empty, try to read new data from the encoder. if (!outsize) { outpos = NULL; more_data = encoder.get_data (&outpos, &outsize); // If IO handler has unplugged engine, flush transient IO handler. if (unlikely (!plugged)) { xs_assert (leftover_session); leftover_session->flush (); return; } // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitratily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. int nbytes = write (outpos, outsize); // Handle problems with the connection. if (nbytes == -1) { error (); return; } outpos += nbytes; outsize -= nbytes; // If the encoder reports that there are no more data to get from it // we can stop polling for POLLOUT immediately. if (!more_data && !outsize) reset_pollout (handle); }
void zmq::stream_engine_t::out_event () { // If write buffer is empty, try to read new data from the encoder. if (!outsize) { // Even when we stop polling as soon as there is no // data to send, the poller may invoke out_event one // more time due to 'speculative write' optimisation. if (unlikely (encoder == NULL)) { zmq_assert (handshaking); return; } outpos = NULL; encoder->get_data (&outpos, &outsize); // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitrarily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. int nbytes = write (outpos, outsize); // IO error has occurred. We stop waiting for output events. // The engine is not terminated until we detect input error; // this is necessary to prevent losing incoming messages. if (nbytes == -1) { reset_pollout (handle); if (unlikely (terminating)) terminate (); return; } outpos += nbytes; outsize -= nbytes; // If we are still handshaking and there are no data // to send, stop polling for output. if (unlikely (handshaking)) if (outsize == 0) reset_pollout (handle); if (unlikely (terminating)) if (outsize == 0) terminate (); }
void zmq::pgm_sender_t::out_event () { // POLLOUT event from send socket. If write buffer is empty, // try to read new data from the encoder. if (write_size == 0) { // First two bytes (sizeof uint16_t) are used to store message // offset in following steps. Note that by passing our buffer to // the get data function we prevent it from returning its own buffer. unsigned char *bf = out_buffer + sizeof (uint16_t); size_t bfsz = out_buffer_size - sizeof (uint16_t); int offset = -1; encoder.get_data (&bf, &bfsz, &offset); // If there are no data to write stop polling for output. if (!bfsz) { reset_pollout (handle); return; } // Put offset information in the buffer. write_size = bfsz + sizeof (uint16_t); put_uint16 (out_buffer, offset == -1 ? 0xffff : (uint16_t) offset); } // Send the data. size_t nbytes = pgm_socket.send (out_buffer, write_size); // We can write either all data or 0 which means rate limit reached. if (nbytes == write_size) write_size = 0; else zmq_assert (nbytes == 0); }
void zmq::zmq_engine_t::out_event () { // If write buffer is empty, try to read new data from the encoder. if (!outsize) { outpos = NULL; encoder.get_data (&outpos, &outsize); // If IO handler has unplugged engine, flush transient IO handler. if (unlikely (!plugged)) { zmq_assert (ephemeral_inout); ephemeral_inout->flush (); return; } // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. int nbytes = tcp_socket.write (outpos, outsize); // Handle problems with the connection. if (nbytes == -1) { error (); return; } outpos += nbytes; outsize -= nbytes; }
void zmq::zmq_engine_t::out_event () { // If write buffer is empty, try to read new data from the encoder. if (!outsize) { outpos = NULL; encoder.get_data (&outpos, &outsize); // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. int nbytes = tcp_socket.write (outpos, outsize); // Handle problems with the connection. if (nbytes == -1) { error (); return; } outpos += nbytes; outsize -= nbytes; }
void zmq::udp_engine_t::out_event() { msg_t group_msg; int rc = session->pull_msg (&group_msg); errno_assert (rc == 0 || (rc == -1 && errno == EAGAIN)); if (rc == 0) { msg_t body_msg; rc = session->pull_msg (&body_msg); size_t group_size = group_msg.size (); size_t body_size = body_msg.size (); size_t size; if (options.raw_socket) { rc = resolve_raw_address ((char*) group_msg.data(), group_size); // We discard the message if address is not valid if (rc != 0) { rc = group_msg.close (); errno_assert (rc == 0); body_msg.close (); errno_assert (rc == 0); return; } size = body_size; memcpy (out_buffer, body_msg.data (), body_size); } else { size = group_size + body_size + 1; // TODO: check if larger than maximum size out_buffer[0] = (unsigned char) group_size; memcpy (out_buffer + 1, group_msg.data (), group_size); memcpy (out_buffer + 1 + group_size, body_msg.data (), body_size); } rc = group_msg.close (); errno_assert (rc == 0); body_msg.close (); errno_assert (rc == 0); #ifdef ZMQ_HAVE_WINDOWS rc = sendto (fd, (const char *) out_buffer, (int) size, 0, out_address, (int) out_addrlen); wsa_assert (rc != SOCKET_ERROR); #else rc = sendto (fd, out_buffer, size, 0, out_address, out_addrlen); errno_assert (rc != -1); #endif } else reset_pollout (handle); }
void xs::stream_engine_t::out_event (fd_t fd_) { bool more_data = true; // If write buffer is empty, try to read new data from the encoder. if (!outsize) { outpos = NULL; more_data = encoder.get_data (&outpos, &outsize); // If IO handler has unplugged engine, flush transient IO handler. if (unlikely (!plugged)) { xs_assert (leftover_session); leftover_session->flush (); return; } // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitratily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. int nbytes = write (outpos, outsize); // Handle problems with the connection. if (nbytes == -1) { error (); return; } outpos += nbytes; outsize -= nbytes; // If the encoder reports that there are no more data to get from it // we can stop polling for POLLOUT immediately. if (!more_data) reset_pollout (handle); }
void zmq::socks_connecter_t::out_event () { zmq_assert (status == waiting_for_proxy_connection || status == sending_greeting || status == sending_request); if (status == waiting_for_proxy_connection) { const int rc = (int) check_proxy_connection (); if (rc == -1) error (); else { greeting_encoder.encode ( socks_greeting_t (socks_no_auth_required)); status = sending_greeting; } } else if (status == sending_greeting) { zmq_assert (greeting_encoder.has_pending_data ()); const int rc = greeting_encoder.output (s); if (rc == -1 || rc == 0) error (); else if (!greeting_encoder.has_pending_data ()) { reset_pollout (handle); set_pollin (handle); status = waiting_for_choice; } } else { zmq_assert (request_encoder.has_pending_data ()); const int rc = request_encoder.output (s); if (rc == -1 || rc == 0) error (); else if (!request_encoder.has_pending_data ()) { reset_pollout (handle); set_pollin (handle); status = waiting_for_response; } } }
void zmq::zmq_engine_t::out_event () { // If write buffer is empty, try to read new data from the encoder. if (!outsize) { outpos = NULL; encoder.get_data (&outpos, &outsize); // If IO handler has unplugged engine, flush transient IO handler. if (unlikely (!plugged)) { zmq_assert (ephemeral_inout); ephemeral_inout->flush (); return; } // If there is no data to send, stop polling for output. if (outsize == 0) { reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitratily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. int nbytes = tcp_socket.write (outpos, outsize); // Handle problems with the connection. if (nbytes == -1) { error (); return; } outpos += nbytes; outsize -= nbytes; }
void zmq::stream_engine_t::out_event () { zmq_assert (!io_error); // If write buffer is empty, try to read new data from the encoder. if (!outsize) { // Even when we stop polling as soon as there is no // data to send, the poller may invoke out_event one // more time due to 'speculative write' optimisation. if (unlikely (encoder == NULL)) { zmq_assert (handshaking); return; } outpos = NULL; outsize = encoder->encode (&outpos, 0); while (outsize < out_batch_size) { if ((this->*next_msg) (&tx_msg) == -1) break; encoder->load_msg (&tx_msg); unsigned char *bufptr = outpos + outsize; size_t n = encoder->encode (&bufptr, out_batch_size - outsize); zmq_assert (n > 0); if (outpos == NULL) outpos = bufptr; outsize += n; } // If there is no data to send, stop polling for output. if (outsize == 0) { output_stopped = true; reset_pollout (handle); return; } } // If there are any data to write in write buffer, write as much as // possible to the socket. Note that amount of data to write can be // arbitrarily large. However, we assume that underlying TCP layer has // limited transmission buffer and thus the actual number of bytes // written should be reasonably modest. const int nbytes = tcp_write (s, outpos, outsize); // IO error has occurred. We stop waiting for output events. // The engine is not terminated until we detect input error; // this is necessary to prevent losing incoming messages. if (nbytes == -1) { reset_pollout (handle); return; } outpos += nbytes; outsize -= nbytes; // If we are still handshaking and there are no data // to send, stop polling for output. if (unlikely (handshaking)) if (outsize == 0) reset_pollout (handle); }
void zmq::pgm_sender_t::out_event () { // POLLOUT event from send socket. If write buffer is empty, // try to read new data from the encoder. if (write_size == 0) { // First two bytes (sizeof uint16_t) are used to store message // offset in following steps. Note that by passing our buffer to // the get data function we prevent it from returning its own buffer. unsigned char *bf = out_buffer + sizeof (uint16_t); size_t bfsz = out_buffer_size - sizeof (uint16_t); uint16_t offset = 0xffff; size_t bytes = encoder.encode (&bf, bfsz); while (bytes < bfsz) { if (!more_flag && offset == 0xffff) offset = static_cast <uint16_t> (bytes); int rc = session->pull_msg (&msg); if (rc == -1) break; more_flag = msg.flags () & msg_t::more; encoder.load_msg (&msg); bf = out_buffer + sizeof (uint16_t) + bytes; bytes += encoder.encode (&bf, bfsz - bytes); } // If there are no data to write stop polling for output. if (bytes == 0) { reset_pollout (handle); return; } write_size = sizeof (uint16_t) + bytes; // Put offset information in the buffer. put_uint16 (out_buffer, offset); } if (has_tx_timer) { cancel_timer (tx_timer_id); set_pollout (handle); has_tx_timer = false; } // Send the data. size_t nbytes = pgm_socket.send (out_buffer, write_size); // We can write either all data or 0 which means rate limit reached. if (nbytes == write_size) write_size = 0; else { zmq_assert (nbytes == 0); if (errno == ENOMEM) { // Stop polling handle and wait for tx timeout const long timeout = pgm_socket.get_tx_timeout (); add_timer (timeout, tx_timer_id); reset_pollout (handle); has_tx_timer = true; } else errno_assert (errno == EBUSY); } }