| 1418 | } |
| 1419 | |
| 1420 | U32 KNativeSocketObject::sendmsg(KThread* thread, const KFileDescriptorPtr& fd, U32 address, U32 flags) { |
| 1421 | MsgHdr hdr = {}; |
| 1422 | KMemory* memory = thread->memory; |
| 1423 | readMsgHdr(thread, address, &hdr); |
| 1424 | |
| 1425 | if (hdr.msg_control) { |
| 1426 | CMsgHdr cmsg; |
| 1427 | |
| 1428 | readCMsgHdr(thread, hdr.msg_control, &cmsg); |
| 1429 | if (cmsg.cmsg_level != K_SOL_SOCKET) { |
| 1430 | kwarn_fmt("KNativeSocketObject::sendmsg control level %d not implemented", cmsg.cmsg_level); |
| 1431 | } else if (cmsg.cmsg_type != K_SCM_RIGHTS) { |
| 1432 | kwarn_fmt("KNativeSocketObject::sendmsg control type %d not implemented", cmsg.cmsg_level); |
| 1433 | } else if ((cmsg.cmsg_len & 3) != 0) { |
| 1434 | kwarn_fmt("KNativeSocketObject::sendmsg control len %d not implemented", cmsg.cmsg_len); |
| 1435 | } |
| 1436 | if (hdr.msg_controllen>0) { |
| 1437 | kwarn("KNativeSocketObject::sendmsg does not support sending file handles"); |
| 1438 | } |
| 1439 | } |
| 1440 | U32 len = 0; |
| 1441 | for (U32 i=0;i<hdr.msg_iovlen;i++) { |
| 1442 | len += memory->readd(hdr.msg_iov + 8 * i + 4); |
| 1443 | } |
| 1444 | U8* buffer = new U8[len]; |
| 1445 | len = 0; |
| 1446 | for (U32 i = 0; i < hdr.msg_iovlen; i++) { |
| 1447 | U32 p = memory->readd(hdr.msg_iov + 8 * i); |
| 1448 | U32 toCopy = memory->readd(hdr.msg_iov + 8 * i + 4); |
| 1449 | memory->memcpy(buffer + len, p, toCopy); |
| 1450 | len += toCopy; |
| 1451 | } |
| 1452 | struct sockaddr_in dest = {0}; |
| 1453 | U32 destLen = 0; |
| 1454 | if (hdr.msg_namelen) { |
| 1455 | destLen = (U32)sizeof(struct sockaddr_in); |
| 1456 | readSockAddrIn(&dest, memory, hdr.msg_name); |
| 1457 | } |
| 1458 | |
| 1459 | U32 nativeFlags = 0; |
| 1460 | if (flags & K_MSG_OOB) |
| 1461 | nativeFlags |= MSG_OOB; |
| 1462 | flags &= ~K_MSG_NOSIGNAL; |
| 1463 | if (flags & (~1)) { |
| 1464 | kwarn_fmt("KNativeSocketObject::sendmsg unsupported flags: %d", flags); |
| 1465 | } |
| 1466 | |
| 1467 | U32 result; |
| 1468 | if (hdr.msg_namelen) { |
| 1469 | result = (U32)::sendto(this->nativeSocket, (const char*)buffer, len, nativeFlags, destLen == 0 ? nullptr : (struct sockaddr*)&dest, destLen); |
| 1470 | } else { |
| 1471 | result = (U32)::send(this->nativeSocket, (const char*)buffer, len, nativeFlags); |
| 1472 | } |
| 1473 | LOG_SOCK("%x native socket: %x sendmsg msg_name=%x msg_namelen=%x result=%x", thread->id, nativeSocket, hdr.msg_name, hdr.msg_namelen, result); |
| 1474 | delete[] buffer; |
| 1475 | if ((S32)result >= 0) { |
| 1476 | this->error = 0; |
| 1477 | return result; |
nothing calls this directly
no test coverage detected