@@ -47,6 +47,71 @@ class RpcTransportTipcTrusty : public RpcTransport {
4747 return mHaveMessage ? OK : WOULD_BLOCK;
4848 }
4949
50+ void moveMsgStart (ipc_msg_t * msg, size_t msg_size, size_t offset) {
51+ LOG_ALWAYS_FATAL_IF (offset > msg_size, " tried to move message past its end %zd>%zd" , offset,
52+ msg_size);
53+ while (true ) {
54+ if (offset == 0 ) {
55+ break ;
56+ }
57+ if (offset >= msg->iov [0 ].iov_len ) {
58+ // Move to the next iov, this one was sent already
59+ offset -= msg->iov [0 ].iov_len ;
60+ msg->iov ++;
61+ msg->num_iov -= 1 ;
62+ } else {
63+ // We need to move the base of the current iov
64+ msg->iov [0 ].iov_len -= offset;
65+ msg->iov [0 ].iov_base = static_cast <char *>(msg->iov [0 ].iov_base ) + offset;
66+ offset = 0 ;
67+ }
68+ }
69+ // We only send handles on the first message. This can be changed in the future if we want
70+ // to send more handles than the maximum per message limit (which would require sending
71+ // multiple messages). The current code makes sure that we send less handles than the
72+ // maximum trusty allows.
73+ msg->num_handles = 0 ;
74+ }
75+
76+ status_t sendTrustyMsg (ipc_msg_t * msg, size_t msg_size) {
77+ do {
78+ ssize_t rc = send_msg (mSocket .fd .get (), msg);
79+ if (rc == ERR_NOT_ENOUGH_BUFFER) {
80+ // Peer is blocked, wait until it unblocks.
81+ // TODO: when tipc supports a send-unblocked handler,
82+ // save the message here in a queue and retry it asynchronously
83+ // when the handler gets called by the library
84+ uevent uevt;
85+ do {
86+ rc = ::wait (mSocket .fd .get (), &uevt, INFINITE_TIME);
87+ if (rc < 0 ) {
88+ return statusFromTrusty (rc);
89+ }
90+ if (uevt.event & IPC_HANDLE_POLL_HUP) {
91+ return DEAD_OBJECT;
92+ }
93+ } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
94+
95+ // Retry the send, it should go through this time because
96+ // sending is now unblocked
97+ rc = send_msg (mSocket .fd .get (), msg);
98+ }
99+ if (rc < 0 ) {
100+ return statusFromTrusty (rc);
101+ }
102+ size_t sent_bytes = static_cast <size_t >(rc);
103+ if (sent_bytes < msg_size) {
104+ moveMsgStart (msg, msg_size, static_cast <size_t >(sent_bytes));
105+ msg_size -= sent_bytes;
106+ } else {
107+ LOG_ALWAYS_FATAL_IF (static_cast <size_t >(rc) != msg_size,
108+ " Sent the wrong number of bytes %zd!=%zu" , rc, msg_size);
109+ break ;
110+ }
111+ } while (true );
112+ return OK;
113+ }
114+
50115 status_t interruptableWriteFully (
51116 FdTrigger* /* fdTrigger*/ , iovec* iovs, int niovs,
52117 const std::optional<SmallFunction<status_t ()>>& /* altPoll*/ ,
@@ -86,34 +151,7 @@ class RpcTransportTipcTrusty : public RpcTransport {
86151 msg.handles = msgHandles;
87152 }
88153
89- ssize_t rc = send_msg (mSocket .fd .get (), &msg);
90- if (rc == ERR_NOT_ENOUGH_BUFFER) {
91- // Peer is blocked, wait until it unblocks.
92- // TODO: when tipc supports a send-unblocked handler,
93- // save the message here in a queue and retry it asynchronously
94- // when the handler gets called by the library
95- uevent uevt;
96- do {
97- rc = ::wait (mSocket .fd .get (), &uevt, INFINITE_TIME);
98- if (rc < 0 ) {
99- return statusFromTrusty (rc);
100- }
101- if (uevt.event & IPC_HANDLE_POLL_HUP) {
102- return DEAD_OBJECT;
103- }
104- } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
105-
106- // Retry the send, it should go through this time because
107- // sending is now unblocked
108- rc = send_msg (mSocket .fd .get (), &msg);
109- }
110- if (rc < 0 ) {
111- return statusFromTrusty (rc);
112- }
113- LOG_ALWAYS_FATAL_IF (static_cast <size_t >(rc) != size,
114- " Sent the wrong number of bytes %zd!=%zu" , rc, size);
115-
116- return OK;
154+ return sendTrustyMsg (&msg, size);
117155 }
118156
119157 status_t interruptableReadFully (
0 commit comments