//====================================================================================================================== // Send message through the socket, return true if successful, false o/w //====================================================================================================================== bool SipConnection::send_message(SipMessage &message) { if(pfd.fd == -1) { connect(); } time_t start_time = time(nullptr); int timeout = 3; while(time(nullptr) <= start_time + timeout) { try_poll(); if(pfd.revents & POLLOUT) { long bytes_to_write; message.write_to_buffer(buf, bytes_to_write); long bytes_writen = ::write(pfd.fd, buf, bytes_to_write); if(bytes_writen != bytes_to_write) { throw string("write() error"); } message.print(); return true; } usleep(1000); } return false; }
value ml_select(value fd_list, value timeout) { #if defined(HAVE_POLL) && defined(HAVE_SYS_POLL_H) && !defined(__MINGW32__) if (use_poll) return try_poll(fd_list, timeout); else return try_select(fd_list, timeout); #else return try_select(fd_list, timeout); #endif }
//====================================================================================================================== // If optional is false return a message regardless of the kind. // If optional is true return a message only if it matches the given kind. // If reconnect is false, don't try to reconnect if the connection is closed. //====================================================================================================================== SipMessage* SipConnection::get_message(string kind, bool optional, int timeout, bool should_reconnect) { if(pfd.fd == -1) { if(should_reconnect) { connect(); } else { return nullptr; } } time_t start_time = time(nullptr); long old_size = msg_queue.size(); while(msg_queue.empty() && time(nullptr) <= start_time + timeout) { try_poll(); // Check that there are no errors on the socket and update the pfd.revents field long num_bytes = 0; if(pfd.revents & POLLIN) // Socket is ready { num_bytes = ::read(pfd.fd, buf, CONNECTION_BUFFER_SIZE); if(num_bytes < 0) { throw string("read() error"); } else if(num_bytes == 0) // Other side issued a close of the TCP connection { if(should_reconnect) { // This might be the close of the connection from a previous test, because get_message() is called // on demand only. So reconnect and continue to try and receive a message. reconnect(); continue; } else { return nullptr; } } else // Successful read { buf[num_bytes] = '\0'; // Make buf a null-terminated string to enable printing etc. // The buffer might contain more than one sip message, extract all of them into the messages queue for(long offset = 0; num_bytes > 0; num_bytes -= offset) { msg_queue.push_back(new SipMessage(buf + offset, offset, num_bytes)); } break; } } usleep(1000); } if(!msg_queue.empty()) { for(long i = old_size; i < msg_queue.size(); ++i) { msg_queue[i]->print(); } SipMessage* front = msg_queue.front(); if(!optional || front->get_kind() == kind) { msg_queue.pop_front(); return front; } } return nullptr; } // get_message()