| 753 | |
| 754 | |
| 755 | Future<size_t> LibeventSSLSocketImpl::send(const char* data, size_t size) |
| 756 | { |
| 757 | // Optimistically construct a 'SendRequest' and future. |
| 758 | Owned<SendRequest> request(new SendRequest(size)); |
| 759 | Future<size_t> future = request->promise.future(); |
| 760 | |
| 761 | // We don't add an 'onDiscard' continuation to send because we can |
| 762 | // not accurately detect how many bytes have been sent. Once we pass |
| 763 | // the data to the bufferevent, there is the possibility that parts |
| 764 | // of it have been sent. Another reason is that if we send partial |
| 765 | // messages (discard only a part of the data), then it is likely |
| 766 | // that the receiving end will fail parsing the message. |
| 767 | |
| 768 | // Assign 'send_request' under lock, fail on error. |
| 769 | synchronized (lock) { |
| 770 | if (send_request.get() != nullptr) { |
| 771 | return Failure("Socket is already sending"); |
| 772 | } |
| 773 | std::swap(request, send_request); |
| 774 | } |
| 775 | |
| 776 | evbuffer* buffer = CHECK_NOTNULL(evbuffer_new()); |
| 777 | |
| 778 | int result = evbuffer_add(buffer, data, size); |
| 779 | CHECK_EQ(0, result); |
| 780 | |
| 781 | // Extend the life-time of 'this' through the execution of the |
| 782 | // lambda in the event loop. Note: The 'self' needs to be explicitly |
| 783 | // captured because we're not using it in the body of the lambda. We |
| 784 | // can use a 'shared_ptr' because run_in_event_loop is guaranteed to |
| 785 | // execute. |
| 786 | auto self = shared(this); |
| 787 | |
| 788 | run_in_event_loop( |
| 789 | [self, buffer]() { |
| 790 | CHECK(__in_event_loop__); |
| 791 | CHECK(self); |
| 792 | |
| 793 | // Check if the socket is closed or the write end has |
| 794 | // encountered an error in the interim (i.e. we received |
| 795 | // a BEV_EVENT_ERROR with BEV_EVENT_WRITING). |
| 796 | bool write = false; |
| 797 | |
| 798 | synchronized (self->lock) { |
| 799 | if (self->send_request.get() != nullptr) { |
| 800 | write = true; |
| 801 | } |
| 802 | } |
| 803 | |
| 804 | if (write) { |
| 805 | int result = bufferevent_write_buffer(self->bev, buffer); |
| 806 | CHECK_EQ(0, result); |
| 807 | } |
| 808 | |
| 809 | evbuffer_free(buffer); |
| 810 | }, |
| 811 | DISALLOW_SHORT_CIRCUIT); |
| 812 |
nothing calls this directly
no test coverage detected