20 #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS // don't need them here 22 #include "modules/system/vfs/File.h" 23 #include "modules/system/vfs/VFS.h" 24 #include "pedigree/kernel/process/Process.h" 25 #include "pedigree/kernel/process/Scheduler.h" 26 #include "pedigree/kernel/processor/Processor.h" 27 #include "pedigree/kernel/processor/types.h" 28 #include "pedigree/kernel/syscallError.h" 29 #include "pedigree/kernel/utilities/Tree.h" 35 #include "pedigree/kernel/Subsystem.h" 36 #include "modules/subsys/posix/FileDescriptor.h" 37 #include "modules/subsys/posix/PosixSubsystem.h" 38 #include "modules/subsys/posix/UnixFilesystem.h" 40 #include "file-syscalls.h" 41 #include "net-syscalls.h" 47 #include <netinet/tcp.h> 51 #include <netinet/in.h> 55 #define LOG_SEND_RECV_BUFFERS 0 58 LwipSocketSyscalls::m_SyscallObjects;
64 static bool isSaneSocket(
FileDescriptor *f,
bool is_create =
false)
68 N_NOTICE(
" -> isSaneSocket: descriptor is null");
69 SYSCALL_ERROR(BadFileDescriptor);
80 N_NOTICE(
" -> isSaneSocket: no network implementation found");
81 SYSCALL_ERROR(BadFileDescriptor);
88 static err_t sockaddrToIpaddr(
89 const struct sockaddr *saddr, uint16_t &port, ip_addr_t *result,
92 ByteSet(result, 0,
sizeof(*result));
94 if (saddr->sa_family == AF_INET)
96 const struct sockaddr_in *sin =
97 reinterpret_cast<const struct sockaddr_in *
>(saddr);
98 result->u_addr.ip4.addr = sin->sin_addr.s_addr;
104 if (!sin->sin_addr.s_addr)
111 port = BIG_TO_HOST16(sin->sin_port);
117 ERROR(
"sockaddrToIpaddr: only AF_INET is supported at the moment.");
123 int posix_socket(
int domain,
int type,
int protocol)
125 N_NOTICE(
"socket(" << domain <<
", " << type <<
", " << protocol <<
")");
127 size_t fd = getAvailableDescriptor();
129 netconn_type connType = NETCONN_INVALID;
131 File *file =
nullptr;
132 struct netconn *conn =
nullptr;
137 if (domain == AF_UNIX)
155 addDescriptor(fd, f);
156 syscalls->associate(f);
158 N_NOTICE(
" -> " <<
Dec << fd <<
Hex);
159 return static_cast<int>(fd);
162 int posix_socketpair(
int domain,
int type,
int protocol,
int sv[2])
164 N_NOTICE(
"socketpair");
167 reinterpret_cast<uintptr_t>(sv),
sizeof(
int) * 2,
168 PosixSubsystem::SafeWrite))
170 N_NOTICE(
"socketpair -> invalid address");
171 SYSCALL_ERROR(BadAddress);
175 if (domain != AF_UNIX)
178 N_NOTICE(
" -> bad domain");
187 N_NOTICE(
" -> failed to create first socket");
197 N_NOTICE(
" -> failed to create second socket");
201 if (!syscallsA->
pairWith(syscallsB))
205 N_NOTICE(
" -> failed to pair");
212 size_t fdA = getAvailableDescriptor();
213 size_t fdB = getAvailableDescriptor();
220 addDescriptor(fdA, fA);
221 addDescriptor(fdB, fB);
223 syscallsA->associate(fA);
224 syscallsB->associate(fB);
226 sv[0] =
static_cast<int>(fdA);
227 sv[1] =
static_cast<int>(fdB);
229 N_NOTICE(
" -> " << sv[0] <<
", " << sv[1]);
233 int posix_connect(
int sock,
const struct sockaddr *address, socklen_t addrlen)
238 reinterpret_cast<uintptr_t>(address), addrlen,
239 PosixSubsystem::SafeRead))
241 N_NOTICE(
"connect -> invalid address");
242 SYSCALL_ERROR(InvalidArgument);
247 "connect(" << sock <<
", " << reinterpret_cast<uintptr_t>(address)
248 <<
", " << addrlen <<
")");
251 if (!isSaneSocket(f,
true))
256 if (address->sa_family != f->
networkImpl->getDomain())
259 N_NOTICE(
" -> incorrect address family passed to connect()");
266 ssize_t posix_send(
int sock,
const void *buff,
size_t bufflen,
int flags)
271 reinterpret_cast<uintptr_t>(buff), bufflen,
272 PosixSubsystem::SafeRead))
274 N_NOTICE(
"send -> invalid address");
275 SYSCALL_ERROR(InvalidArgument);
280 "send(" << sock <<
", " << buff <<
", " << bufflen <<
", " << flags
283 #if LOG_SEND_RECV_BUFFERS 287 debug.assign(reinterpret_cast<const char *>(buff), bufflen,
true);
288 N_NOTICE(
" -> sending: '" << debug <<
"'");
293 if (!isSaneSocket(f))
298 return f->
networkImpl->sendto(buff, bufflen, flags,
nullptr, 0);
301 ssize_t posix_sendto(
302 int sock,
const void *buff,
size_t bufflen,
int flags,
303 struct sockaddr *address, socklen_t addrlen)
308 reinterpret_cast<uintptr_t>(buff), bufflen,
309 PosixSubsystem::SafeRead))
311 N_NOTICE(
"sendto -> invalid address for transmission buffer");
312 SYSCALL_ERROR(InvalidArgument);
317 "sendto(" << sock <<
", " << buff <<
", " << bufflen <<
", " << flags
318 <<
", " << address <<
", " << addrlen <<
")");
320 #if LOG_SEND_RECV_BUFFERS 324 debug.assign(reinterpret_cast<const char *>(buff), bufflen,
true);
325 N_NOTICE(
" -> sending: '" << debug <<
"'");
330 if (!isSaneSocket(f))
335 return f->
networkImpl->sendto(buff, bufflen, flags, address, addrlen);
338 ssize_t posix_recv(
int sock,
void *buff,
size_t bufflen,
int flags)
343 reinterpret_cast<uintptr_t>(buff), bufflen,
344 PosixSubsystem::SafeWrite))
346 N_NOTICE(
"recv -> invalid address");
347 SYSCALL_ERROR(InvalidArgument);
352 "recv(" << sock <<
", " << buff <<
", " << bufflen <<
", " << flags
356 if (!isSaneSocket(f))
362 f->
networkImpl->recvfrom(buff, bufflen, flags,
nullptr,
nullptr);
364 #if LOG_SEND_RECV_BUFFERS 368 debug.assign(reinterpret_cast<const char *>(buff), n,
true);
369 N_NOTICE(
" -> received: '" << debug <<
"'");
373 N_NOTICE(
" -> " << n);
377 ssize_t posix_recvfrom(
378 int sock,
void *buff,
size_t bufflen,
int flags,
struct sockaddr *address,
381 N_NOTICE(
"recvfrom");
384 reinterpret_cast<uintptr_t>(buff), bufflen,
385 PosixSubsystem::SafeWrite) &&
387 reinterpret_cast<uintptr_t>(addrlen),
388 sizeof(socklen_t), PosixSubsystem::SafeWrite))))
390 N_NOTICE(
"recvfrom -> invalid address for receive buffer or addrlen " 392 SYSCALL_ERROR(InvalidArgument);
397 "recvfrom(" << sock <<
", " << buff <<
", " << bufflen <<
", " << flags
398 <<
", " << address <<
", " << addrlen);
401 if (!isSaneSocket(f))
407 f->
networkImpl->recvfrom(buff, bufflen, flags, address, addrlen);
409 #if LOG_SEND_RECV_BUFFERS 413 debug.assign(reinterpret_cast<const char *>(buff), n,
true);
414 N_NOTICE(
" -> received: '" << debug <<
"'");
418 N_NOTICE(
" -> " << n);
422 int posix_bind(
int sock,
const struct sockaddr *address, socklen_t addrlen)
427 reinterpret_cast<uintptr_t>(address), addrlen,
428 PosixSubsystem::SafeRead))
430 N_NOTICE(
"bind -> invalid address");
431 SYSCALL_ERROR(InvalidArgument);
435 N_NOTICE(
"bind(" << sock <<
", " << address <<
", " << addrlen <<
")");
438 if (!isSaneSocket(f,
true))
443 if (f->
networkImpl->getDomain() != address->sa_family)
452 int posix_listen(
int sock,
int backlog)
454 N_NOTICE(
"listen(" << sock <<
", " << backlog <<
")");
457 if (!isSaneSocket(f))
464 SYSCALL_ERROR(InvalidArgument);
471 int posix_accept(
int sock,
struct sockaddr *address, socklen_t *addrlen)
476 reinterpret_cast<uintptr_t>(address),
477 sizeof(
struct sockaddr_storage), PosixSubsystem::SafeWrite) &&
479 reinterpret_cast<uintptr_t>(addrlen),
sizeof(socklen_t),
480 PosixSubsystem::SafeWrite)))
482 N_NOTICE(
"accept -> invalid address");
483 SYSCALL_ERROR(InvalidArgument);
487 N_NOTICE(
"accept(" << sock <<
", " << address <<
", " << addrlen <<
")");
490 if (!isSaneSocket(f))
497 SYSCALL_ERROR(OperationNotSupported);
502 N_NOTICE(
" -> " <<
Dec << r);
506 int posix_shutdown(
int socket,
int how)
508 N_NOTICE(
"shutdown(" << socket <<
", " << how <<
")");
511 if (!isSaneSocket(f))
519 int posix_getpeername(
520 int socket,
struct sockaddr *address, socklen_t *address_len)
522 N_NOTICE(
"getpeername");
525 reinterpret_cast<uintptr_t>(address),
526 sizeof(
struct sockaddr_storage), PosixSubsystem::SafeWrite) &&
528 reinterpret_cast<uintptr_t>(address_len),
sizeof(socklen_t),
529 PosixSubsystem::SafeWrite)))
531 N_NOTICE(
"getpeername -> invalid address");
532 SYSCALL_ERROR(InvalidArgument);
537 "getpeername(" << socket <<
", " << address <<
", " << address_len
541 if (!isSaneSocket(f))
546 return f->
networkImpl->getpeername(address, address_len);
549 int posix_getsockname(
550 int socket,
struct sockaddr *address, socklen_t *address_len)
552 N_NOTICE(
"getsockname");
555 reinterpret_cast<uintptr_t>(address),
556 sizeof(
struct sockaddr_storage), PosixSubsystem::SafeWrite) &&
558 reinterpret_cast<uintptr_t>(address_len),
sizeof(socklen_t),
559 PosixSubsystem::SafeWrite)))
561 N_NOTICE(
"getsockname -> invalid address");
562 SYSCALL_ERROR(InvalidArgument);
567 "getsockname(" << socket <<
", " << address <<
", " << address_len
571 if (!isSaneSocket(f))
576 return f->
networkImpl->getsockname(address, address_len);
579 int posix_setsockopt(
580 int sock,
int level,
int optname,
const void *optvalue, socklen_t optlen)
583 "setsockopt(" << sock <<
", " << level <<
", " << optname <<
", " 584 << optvalue <<
", " << optlen <<
")");
587 reinterpret_cast<uintptr_t>(optvalue), optlen,
588 PosixSubsystem::SafeWrite)))
590 N_NOTICE(
"setsockopt -> invalid address");
591 SYSCALL_ERROR(InvalidArgument);
596 if (!isSaneSocket(f))
601 return f->
networkImpl->setsockopt(level, optname, optvalue, optlen);
604 int posix_getsockopt(
605 int sock,
int level,
int optname,
void *optvalue, socklen_t *optlen)
607 N_NOTICE(
"getsockopt(" << sock <<
", " << level <<
", " << optname <<
")");
611 reinterpret_cast<uintptr_t>(optlen),
sizeof(socklen_t),
612 PosixSubsystem::SafeRead) &&
614 reinterpret_cast<uintptr_t>(optlen),
sizeof(socklen_t),
615 PosixSubsystem::SafeWrite)))
617 N_NOTICE(
"getsockopt -> invalid address");
618 SYSCALL_ERROR(InvalidArgument);
622 reinterpret_cast<uintptr_t>(optvalue), *optlen,
623 PosixSubsystem::SafeWrite)))
625 N_NOTICE(
"getsockopt -> invalid address");
626 SYSCALL_ERROR(InvalidArgument);
631 if (!isSaneSocket(f))
636 return f->
networkImpl->getsockopt(level, optname, optvalue, optlen);
639 int posix_sethostname(
const char *name,
size_t len)
641 N_NOTICE(
"sethostname");
644 reinterpret_cast<uintptr_t>(name), len, PosixSubsystem::SafeRead)))
646 N_NOTICE(
" -> invalid address");
647 SYSCALL_ERROR(InvalidArgument);
651 N_NOTICE(
"sethostname(" <<
String(name, len) <<
")");
658 ssize_t posix_sendmsg(
int sockfd,
const struct msghdr *msg,
int flags)
660 N_NOTICE(
"sendmsg(" << sockfd <<
", " << msg <<
", " << flags <<
")");
665 if (!isSaneSocket(f))
671 N_NOTICE(
" -> " << n);
675 ssize_t posix_recvmsg(
int sockfd,
struct msghdr *msg,
int flags)
677 N_NOTICE(
"recvmsg(" << sockfd <<
", " << msg <<
", " << flags <<
")");
682 if (!isSaneSocket(f))
688 N_NOTICE(
" -> " << n);
692 NetworkSyscalls::NetworkSyscalls(
int domain,
int type,
int protocol)
693 : m_Domain(domain), m_Type(type), m_Protocol(protocol), m_Blocking(true),
698 NetworkSyscalls::~NetworkSyscalls()
707 ssize_t NetworkSyscalls::sendto(
708 const void *buffer,
size_t bufferlen,
int flags,
709 const struct sockaddr *address, socklen_t addrlen)
712 iov.iov_base =
const_cast<void *
>(buffer);
713 iov.iov_len = bufferlen;
716 msg.msg_name =
const_cast<struct sockaddr *
>(address);
717 msg.msg_namelen = addrlen;
720 msg.msg_control =
nullptr;
721 msg.msg_controllen = 0;
722 msg.msg_flags = flags;
724 return sendto_msg(&msg);
727 ssize_t NetworkSyscalls::recvfrom(
728 void *buffer,
size_t bufferlen,
int flags,
struct sockaddr *address,
732 iov.iov_base = buffer;
733 iov.iov_len = bufferlen;
736 msg.msg_name = address;
737 msg.msg_namelen = addrlen ? *addrlen : 0;
740 msg.msg_control =
nullptr;
741 msg.msg_controllen = 0;
742 msg.msg_flags = flags;
744 ssize_t result = recvfrom_msg(&msg);
750 *addrlen = msg.msg_namelen;
757 int NetworkSyscalls::shutdown(
int how)
762 bool NetworkSyscalls::canPoll()
const 767 bool NetworkSyscalls::poll(
768 bool &read,
bool &write,
bool &error,
Semaphore *waiter)
776 void NetworkSyscalls::unPoll(
Semaphore *waiter)
780 bool NetworkSyscalls::monitor(
Thread *pThread,
Event *pEvent)
785 bool NetworkSyscalls::unmonitor(
Event *pEvent)
795 bool NetworkSyscalls::isBlocking()
const 800 void NetworkSyscalls::setBlocking(
bool blocking)
802 m_Blocking = blocking;
805 LwipSocketSyscalls::LwipSocketSyscalls(
int domain,
int type,
int protocol)
806 :
NetworkSyscalls(domain, type, protocol), m_Socket(
nullptr), m_Metadata()
810 LwipSocketSyscalls::~LwipSocketSyscalls()
814 m_SyscallObjects.remove(m_Socket);
816 netconn_delete(m_Socket);
823 netconn_type connType = NETCONN_INVALID;
828 N_NOTICE(
"LwipSocketSyscalls: using default protocol for socket type");
829 if (m_Type == SOCK_DGRAM)
831 m_Protocol = IPPROTO_UDP;
833 else if (m_Type == SOCK_STREAM)
835 m_Protocol = IPPROTO_TCP;
839 if (m_Domain == AF_INET)
844 connType = NETCONN_TCP;
847 connType = NETCONN_UDP;
851 else if (m_Domain == AF_INET6)
856 connType = NETCONN_TCP_IPV6;
859 connType = NETCONN_UDP_IPV6;
863 else if (m_Domain == AF_PACKET)
865 connType = NETCONN_RAW;
869 WARNING(
"LwipSocketSyscalls: domain " << m_Domain <<
" is not known!");
870 SYSCALL_ERROR(InvalidArgument);
874 if (connType == NETCONN_INVALID)
876 N_NOTICE(
"LwipSocketSyscalls: invalid socket creation parameters");
877 SYSCALL_ERROR(InvalidArgument);
887 m_Socket = netconn_new_with_callback(connType, netconnCallback);
894 m_SyscallObjects.insert(m_Socket,
this);
900 const struct sockaddr *address, socklen_t addrlen)
904 ByteSet(&ipaddr, 0,
sizeof(ipaddr));
905 err_t err = netconn_bind(m_Socket, &ipaddr, 0);
908 N_NOTICE(
" -> lwip error when binding before connect");
909 lwipToSyscallError(err);
914 if ((err = sockaddrToIpaddr(address, port, &ipaddr,
false)) !=
ERR_OK)
916 N_NOTICE(
"failed to convert sockaddr");
917 lwipToSyscallError(err);
923 !((getFileDescriptor()->flflags & O_NONBLOCK) == O_NONBLOCK);
924 netconn_set_nonblocking(m_Socket, blocking ? 0 : 1);
926 N_NOTICE(
"using socket " << m_Socket <<
"!");
928 " -> connecting to remote " << ipaddr_ntoa(&ipaddr) <<
" on port " 931 err = netconn_connect(m_Socket, &ipaddr, port);
934 N_NOTICE(
" -> lwip error");
935 lwipToSyscallError(err);
941 if (NETCONNTYPE_GROUP(m_Socket->type) != NETCONN_TCP)
954 if (msghdr->msg_name)
957 SYSCALL_ERROR(Unimplemented);
962 if (!isBlocking() && !m_Metadata.send)
964 N_NOTICE(
" -> send queue full, would block");
965 SYSCALL_ERROR(NoMoreProcesses);
969 size_t bytesWritten = 0;
972 if (NETCONNTYPE_GROUP(m_Socket->type) == NETCONN_TCP)
974 for (
int i = 0; i < msghdr->msg_iovlen; ++i)
976 void *buffer = msghdr->msg_iov[i].iov_base;
977 size_t bufferlen = msghdr->msg_iov[i].iov_len;
979 size_t thisBytesWritten = 0;
980 err = netconn_write_partly(
981 m_Socket, buffer, bufferlen, NETCONN_COPY | NETCONN_MORE,
985 lwipToSyscallError(err);
990 bytesWritten += thisBytesWritten;
995 struct netbuf *buf = netbuf_new();
996 for (
int i = 0; i < msghdr->msg_iovlen; ++i)
999 buf, msghdr->msg_iov[i].iov_base, msghdr->msg_iov[i].iov_len);
1003 err = netconn_send(m_Socket, buf);
1006 lwipToSyscallError(err);
1011 bytesWritten += netbuf_len(buf);
1024 return bytesWritten;
1029 if (msghdr->msg_name)
1032 SYSCALL_ERROR(Unimplemented);
1039 if (!(m_Metadata.recv || m_Metadata.pb))
1046 N_NOTICE(
" -> no more data available, would block");
1047 SYSCALL_ERROR(NoMoreProcesses);
1055 struct pbuf *pb =
nullptr;
1056 struct netbuf *buf =
nullptr;
1060 if (NETCONNTYPE_GROUP(netconn_type(m_Socket)) == NETCONN_TCP)
1062 err = netconn_recv_tcp_pbuf(m_Socket, &pb);
1066 err = netconn_recv(m_Socket, &buf);
1071 N_NOTICE(
" -> lwIP error");
1072 lwipToSyscallError(err);
1076 if (pb ==
nullptr && buf !=
nullptr)
1081 m_Metadata.offset = 0;
1083 m_Metadata.buf = buf;
1086 size_t totalLen = 0;
1087 for (
int i = 0; i < msghdr->msg_iovlen; ++i)
1089 void *buffer = msghdr->msg_iov[i].iov_base;
1090 size_t bufferlen = msghdr->msg_iov[i].iov_len;
1093 size_t finalPos = m_Metadata.offset + bufferlen;
1094 if (finalPos > m_Metadata.pb->tot_len)
1096 bufferlen = m_Metadata.pb->
tot_len - m_Metadata.offset;
1104 totalLen += bufferlen;
1108 if ((m_Metadata.offset + totalLen) < m_Metadata.pb->tot_len)
1110 m_Metadata.offset += totalLen;
1114 if (m_Metadata.buf ==
nullptr)
1122 netbuf_free(m_Metadata.buf);
1125 m_Metadata.pb =
nullptr;
1126 m_Metadata.buf =
nullptr;
1127 m_Metadata.offset = 0;
1130 N_NOTICE(
" -> " << totalLen);
1134 int LwipSocketSyscalls::listen(
int backlog)
1136 err_t err = netconn_listen_with_backlog(m_Socket, backlog);
1139 N_NOTICE(
" -> lwIP error");
1140 lwipToSyscallError(err);
1147 int LwipSocketSyscalls::bind(
const struct sockaddr *address, socklen_t addrlen)
1151 sockaddrToIpaddr(address, port, &ipaddr);
1153 err_t err = netconn_bind(m_Socket, &ipaddr, port);
1156 N_NOTICE(
" -> lwIP error");
1157 lwipToSyscallError(err);
1166 struct netconn *new_conn;
1167 err_t err = netconn_accept(m_Socket, &new_conn);
1170 N_NOTICE(
" -> lwIP error");
1171 lwipToSyscallError(err);
1178 err = netconn_peer(new_conn, &peer, &port);
1181 netconn_delete(new_conn);
1182 lwipToSyscallError(err);
1187 struct sockaddr_in *sin =
reinterpret_cast<struct sockaddr_in *
>(address);
1188 sin->sin_family = AF_INET;
1189 sin->sin_port = HOST_TO_BIG16(port);
1190 sin->sin_addr.s_addr = peer.u_addr.ip4.addr;
1191 *addrlen =
sizeof(sockaddr_in);
1195 obj->m_Socket = new_conn;
1197 m_SyscallObjects.insert(new_conn, obj);
1199 size_t fd = getAvailableDescriptor();
1204 addDescriptor(fd, desc);
1205 obj->associate(desc);
1207 return static_cast<int>(fd);
1210 int LwipSocketSyscalls::shutdown(
int how)
1214 if (how == SHUT_RDWR)
1218 else if (how == SHUT_RD)
1227 err_t err = netconn_shutdown(m_Socket, rx, tx);
1230 lwipToSyscallError(err);
1238 struct sockaddr *address, socklen_t *address_len)
1242 err_t err = netconn_peer(m_Socket, &peer, &port);
1245 N_NOTICE(
" -> getpeername failed");
1246 lwipToSyscallError(err);
1251 struct sockaddr_in *sin =
reinterpret_cast<struct sockaddr_in *
>(address);
1252 sin->sin_family = AF_INET;
1253 sin->sin_port = HOST_TO_BIG16(port);
1254 sin->sin_addr.s_addr = peer.u_addr.ip4.addr;
1255 *address_len =
sizeof(sockaddr_in);
1261 struct sockaddr *address, socklen_t *address_len)
1265 err_t err = netconn_addr(m_Socket, &
self, &port);
1268 lwipToSyscallError(err);
1273 struct sockaddr_in *sin =
reinterpret_cast<struct sockaddr_in *
>(address);
1274 sin->sin_family = AF_INET;
1275 sin->sin_port = HOST_TO_BIG16(port);
1276 sin->sin_addr.s_addr =
self.u_addr.ip4.addr;
1277 *address_len =
sizeof(sockaddr_in);
1283 int level,
int optname,
const void *optvalue, socklen_t optlen)
1285 if (m_Protocol == IPPROTO_TCP && level == IPPROTO_TCP)
1288 #pragma GCC diagnostic push 1289 #pragma GCC diagnostic ignored "-Wold-style-cast" 1290 if (optname == TCP_NODELAY)
1292 N_NOTICE(
" -> TCP_NODELAY");
1293 const uint32_t *val =
reinterpret_cast<const uint32_t *
>(optvalue);
1294 N_NOTICE(
" --> val=" << *val);
1299 tcp_nagle_disable(m_Socket->pcb.tcp);
1303 tcp_nagle_enable(m_Socket->pcb.tcp);
1308 #pragma GCC diagnostic pop 1317 int level,
int optname,
void *optvalue, socklen_t *optlen)
1324 bool LwipSocketSyscalls::canPoll()
const 1330 bool &read,
bool &write,
bool &error,
Semaphore *waiter)
1334 if (!(read || write || error))
1341 m_Metadata.lock.acquire();
1346 write = m_Metadata.send != 0;
1352 read = m_Metadata.recv || m_Metadata.pb;
1358 error = m_Metadata.error;
1366 m_Metadata.semaphores.pushBack(waiter);
1370 m_Metadata.lock.release();
1376 void LwipSocketSyscalls::unPoll(
Semaphore *waiter)
1379 m_Metadata.lock.acquire();
1380 for (
auto it = m_Metadata.semaphores.begin();
1381 it != m_Metadata.semaphores.end();)
1383 if ((*it) == waiter)
1385 it = m_Metadata.semaphores.erase(it);
1392 m_Metadata.lock.release();
1397 struct netconn *conn,
enum netconn_evt evt, u16_t len)
1406 obj->m_Metadata.lock.
acquire();
1411 case NETCONN_EVT_RCVPLUS:
1413 ++(obj->m_Metadata.recv);
1415 case NETCONN_EVT_RCVMINUS:
1417 if (obj->m_Metadata.recv)
1419 --(obj->m_Metadata.recv);
1422 case NETCONN_EVT_SENDPLUS:
1424 obj->m_Metadata.send = 1;
1426 case NETCONN_EVT_SENDMINUS:
1428 obj->m_Metadata.send = 0;
1430 case NETCONN_EVT_ERROR:
1432 obj->m_Metadata.error =
1436 N_NOTICE(
"Unknown netconn callback error.");
1441 for (
auto &it : obj->m_Metadata.semaphores)
1446 obj->m_Metadata.lock.
release();
1450 void LwipSocketSyscalls::lwipToSyscallError(
err_t err)
1454 N_NOTICE(
" -> lwip strerror gives '" << lwip_strerr(err) <<
"'");
1462 SYSCALL_ERROR(OutOfMemory);
1465 SYSCALL_ERROR(NoMoreBuffers);
1468 SYSCALL_ERROR(TimedOut);
1471 SYSCALL_ERROR(HostUnreachable);
1474 SYSCALL_ERROR(InProgress);
1477 SYSCALL_ERROR(InvalidArgument);
1480 SYSCALL_ERROR(NoMoreProcesses);
1484 SYSCALL_ERROR(InvalidArgument);
1487 SYSCALL_ERROR(Already);
1490 SYSCALL_ERROR(IsConnected);
1493 SYSCALL_ERROR(NotConnected);
1499 SYSCALL_ERROR(ConnectionAborted);
1502 SYSCALL_ERROR(ConnectionReset);
1505 SYSCALL_ERROR(NotConnected);
1508 SYSCALL_ERROR(IoError);
1513 LwipSocketSyscalls::LwipMetadata::LwipMetadata()
1514 : recv(0),
send(0), error(
false), lock(
false), semaphores(), offset(0),
1515 pb(
nullptr), buf(
nullptr)
1519 UnixSocketSyscalls::UnixSocketSyscalls(
int domain,
int type,
int protocol)
1521 m_Remote(
nullptr), m_LocalPath(), m_RemotePath()
1528 N_NOTICE(
"UnixSocketSyscalls::~UnixSocketSyscalls");
1542 String(), g_pUnixFilesystem,
nullptr,
nullptr, getSocketType());
1548 const struct sockaddr *address, socklen_t addrlen)
1551 const struct sockaddr_un *un =
1552 reinterpret_cast<const struct sockaddr_un *
>(address);
1554 normalisePath(pathname, un->sun_path);
1556 N_NOTICE(
" -> unix connect: '" << pathname <<
"'");
1561 SYSCALL_ERROR(DoesNotExist);
1562 N_NOTICE(
" -> unix socket '" << pathname <<
"' doesn't exist");
1569 SYSCALL_ERROR(DoesNotExist);
1570 N_NOTICE(
" -> target '" << pathname <<
"' is not a unix socket");
1578 N_NOTICE(
" -> stream");
1582 String(), g_pUnixFilesystem,
nullptr,
nullptr,
1583 UnixSocket::Streaming);
1584 m_Remote->addSocket(remote);
1587 !((getFileDescriptor()->flflags & O_NONBLOCK) == O_NONBLOCK);
1590 N_NOTICE(
" -> stream is binding blocking=" << blocking);
1591 m_Socket->bind(remote, blocking);
1592 N_NOTICE(
" -> stream bound!");
1596 N_NOTICE(
" -> dgram");
1599 m_RemotePath = pathname;
1601 N_NOTICE(
" -> remote is now " << m_RemotePath);
1608 N_NOTICE(
"UnixSocketSyscalls::sendto_msg");
1611 if (
getType() == SOCK_STREAM && !remote)
1616 N_NOTICE(
" -> not connected");
1617 SYSCALL_ERROR(NotConnected);
1628 " -> sendto on streaming socket with no remote is invalid");
1631 else if (!msghdr->msg_name)
1634 N_NOTICE(
" -> sendto on unconnected socket with no address");
1639 const struct sockaddr_un *un =
1640 reinterpret_cast<const struct sockaddr_un *
>(msghdr->msg_name);
1642 normalisePath(pathname, un->sun_path);
1644 N_NOTICE(
" -> unix connect: '" << pathname <<
"'");
1649 SYSCALL_ERROR(DoesNotExist);
1650 N_NOTICE(
" -> unix socket '" << pathname <<
"' doesn't exist");
1657 SYSCALL_ERROR(DoesNotExist);
1658 N_NOTICE(
" -> target '" << pathname <<
"' is not a unix socket");
1665 N_NOTICE(
" -> transmitting!");
1667 uint64_t numWritten = 0;
1668 for (
int i = 0; i < msghdr->msg_iovlen; ++i)
1670 void *buffer = msghdr->msg_iov[i].iov_base;
1671 size_t bufferlen = msghdr->msg_iov[i].iov_len;
1673 uint64_t thisWrite = remote->
write(
1674 reinterpret_cast<uintptr_t>(static_cast<const char *>(m_LocalPath)),
1675 bufferlen, reinterpret_cast<uintptr_t>(buffer), isBlocking());
1683 numWritten += thisWrite;
1691 SYSCALL_ERROR(NoMoreProcesses);
1692 N_NOTICE(
" -> -1 (EAGAIN)");
1696 N_NOTICE(
" -> " << numWritten);
1703 uint64_t numRead = 0;
1704 for (
int i = 0; i < msghdr->msg_iovlen; ++i)
1706 void *buffer = msghdr->msg_iov[i].iov_base;
1707 size_t bufferlen = msghdr->msg_iov[i].iov_len;
1709 uint64_t thisRead = m_Socket->recvfrom(
1710 bufferlen, reinterpret_cast<uintptr_t>(buffer), isBlocking(),
1718 numRead += thisRead;
1721 if (numRead && msghdr->msg_name)
1723 struct sockaddr_un *un =
1724 reinterpret_cast<struct sockaddr_un *
>(msghdr->msg_name);
1725 un->sun_family = AF_UNIX;
1726 StringCopy(un->sun_path, remote);
1727 msghdr->msg_namelen =
sizeof(sa_family_t) + remote.length();
1731 msghdr->msg_flags = 0;
1738 SYSCALL_ERROR(NoMoreProcesses);
1739 N_NOTICE(
" -> -1 (EAGAIN)");
1743 N_NOTICE(
" -> " << numRead);
1749 if (m_Socket->getType() != UnixSocket::Streaming)
1757 m_Socket->markListening();
1766 const struct sockaddr_un *un =
1767 reinterpret_cast<const struct sockaddr_un *
>(address);
1769 if (SUN_LEN(un) ==
sizeof(sa_family_t))
1775 String adjusted_pathname;
1776 normalisePath(adjusted_pathname, un->sun_path);
1778 N_NOTICE(
" -> unix bind: '" << adjusted_pathname <<
"'");
1781 if (adjusted_pathname.
endswith(
'/'))
1784 SYSCALL_ERROR(IsADirectory);
1788 File *parentDirectory = cwd;
1790 const char *pDirname =
1791 DirectoryName(static_cast<const char *>(adjusted_pathname));
1792 const char *pBasename =
1793 BaseName(static_cast<const char *>(adjusted_pathname));
1795 String basename(pBasename);
1801 String dirname(pDirname);
1804 N_NOTICE(
" -> dirname=" << dirname);
1807 if (!parentDirectory)
1809 N_NOTICE(
" -> parent directory '" << dirname <<
"' doesn't exist");
1810 SYSCALL_ERROR(DoesNotExist);
1817 SYSCALL_ERROR(NotADirectory);
1825 basename, parentDirectory->getFilesystem(), parentDirectory,
nullptr,
1834 N_NOTICE(
" -> basename=" << basename);
1837 if (!m_LocalPath.length())
1844 m_LocalPath = adjusted_pathname;
1849 int UnixSocketSyscalls::accept(
struct sockaddr *address, socklen_t *addrlen)
1851 N_NOTICE(
"unix accept");
1852 UnixSocket *remote = m_Socket->getSocket(isBlocking());
1855 N_NOTICE(
"accept() failed");
1856 SYSCALL_ERROR(NoMoreProcesses);
1862 N_NOTICE(
"accept() got a socket");
1864 struct sockaddr_un *sun =
1865 reinterpret_cast<struct sockaddr_un *
>(address);
1867 if (remote->
getName().length())
1872 StringCopy(sun->sun_path, name);
1873 *addrlen =
sizeof(sa_family_t) + name.length();
1877 *addrlen =
sizeof(sa_family_t);
1880 sun->sun_family = AF_UNIX;
1884 obj->m_Socket = remote;
1885 obj->m_Remote = remote->getOther();
1886 obj->m_LocalPath =
String();
1887 obj->m_RemotePath = m_Socket->getFullPath();
1890 size_t fd = getAvailableDescriptor();
1895 addDescriptor(fd, desc);
1896 obj->associate(desc);
1898 return static_cast<int>(fd);
1907 N_NOTICE(
"UnixSocketSyscalls::shutdown");
1911 int UnixSocketSyscalls::getpeername(
1912 struct sockaddr *address, socklen_t *address_len)
1914 N_NOTICE(
"UNIX getpeername");
1915 struct sockaddr_un *sun =
reinterpret_cast<struct sockaddr_un *
>(address);
1916 sun->sun_family = AF_UNIX;
1917 StringCopy(sun->sun_path, m_RemotePath);
1918 *address_len =
sizeof(sa_family_t) + m_RemotePath.length();
1920 N_NOTICE(
" -> " << m_RemotePath);
1924 int UnixSocketSyscalls::getsockname(
1925 struct sockaddr *address, socklen_t *address_len)
1927 N_NOTICE(
"UNIX getsockname");
1928 struct sockaddr_un *sun =
reinterpret_cast<struct sockaddr_un *
>(address);
1929 sun->sun_family = AF_UNIX;
1930 StringCopy(sun->sun_path, m_LocalPath);
1931 *address_len =
sizeof(sa_family_t) + m_LocalPath.length();
1933 N_NOTICE(
" -> " << m_LocalPath);
1937 int UnixSocketSyscalls::setsockopt(
1938 int level,
int optname,
const void *optvalue, socklen_t optlen)
1944 int UnixSocketSyscalls::getsockopt(
1945 int level,
int optname,
void *optvalue, socklen_t *optlen)
1947 if (level == SOL_SOCKET)
1949 if (optname == SO_PEERCRED)
1951 N_NOTICE(
" -> SO_PEERCRED");
1954 struct ucred *targetCreds =
1955 reinterpret_cast<struct ucred *
>(optvalue);
1956 struct ucred sourceCreds = m_Socket->getPeerCredentials();
1958 N_NOTICE(
" --> pid=" <<
Dec << sourceCreds.pid);
1959 N_NOTICE(
" --> uid=" <<
Dec << sourceCreds.uid);
1960 N_NOTICE(
" --> gid=" <<
Dec << sourceCreds.gid);
1962 *targetCreds = sourceCreds;
1963 *optlen =
sizeof(sourceCreds);
1972 bool UnixSocketSyscalls::canPoll()
const 1974 return getRemote() || m_Socket;
1977 bool UnixSocketSyscalls::poll(
1978 bool &read,
bool &write,
bool &error,
Semaphore *waiter)
1986 "UnixSocketSyscalls::poll - no local socket to poll for reading!");
1988 if (write && !remote)
1991 "UnixSocketSyscalls::poll - no remote socket to poll for writing!");
1997 read = local->
select(
false, 0);
2000 if (waiter && !read)
2002 local->addWaiter(waiter);
2006 if (write && remote)
2008 write = remote->
select(
true, 0);
2011 if (waiter && !write)
2013 remote->addWaiter(waiter);
2021 void UnixSocketSyscalls::unPoll(
Semaphore *waiter)
2029 remote->removeWaiter(waiter);
2033 local->removeWaiter(waiter);
2037 bool UnixSocketSyscalls::monitor(
Thread *pThread,
Event *pEvent)
2042 if (remote != local)
2044 remote->addWaiter(pThread, pEvent);
2047 local->addWaiter(pThread, pEvent);
2052 bool UnixSocketSyscalls::unmonitor(
Event *pEvent)
2057 if (remote != local)
2059 remote->removeWaiter(pEvent);
2062 local->removeWaiter(pEvent);
2069 if (!m_Socket->bind(other->m_Socket))
2075 other->m_Socket->acknowledgeBind();
2077 m_Remote = other->m_Socket;
2078 other->m_Remote = m_Socket;
2082 UnixSocket *UnixSocketSyscalls::getRemote()
const 2087 if (!m_Socket->getOther())
2098 UnixSocket::SocketType UnixSocketSyscalls::getSocketType()
const 2102 return UnixSocket::Streaming;
2105 return UnixSocket::Datagram;
virtual int getsockname(struct sockaddr *address, socklen_t *address_len)
virtual int bind(const struct sockaddr *address, socklen_t addrlen)
File * find(const String &path, File *pStartNode=0)
bool pairWith(UnixSocketSyscalls *other)
virtual bool poll(bool &read, bool &write, bool &error, Semaphore *waiter)
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
SharedPointer< class NetworkSyscalls > networkImpl
Network syscall implementation for this descriptor (if it's a socket).
virtual int accept(struct sockaddr *address, socklen_t *addrlen)
static Directory * fromFile(File *pF)
size_t fd
Descriptor number.
virtual bool create()
Implementation-specific final socket creation logic.
virtual ssize_t recvfrom_msg(struct msghdr *msghdr)
virtual ssize_t recvfrom_msg(struct msghdr *msghdr)
virtual int listen(int backlog)
virtual ssize_t sendto_msg(const struct msghdr *msghdr)
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
virtual ~UnixSocketSyscalls()
virtual ssize_t sendto_msg(const struct msghdr *msghdr)
virtual int shutdown(int how)
virtual int setsockopt(int level, int optname, const void *optvalue, socklen_t optlen)
virtual String getFullPath(bool bWithLabel=true)
static Scheduler & instance()
virtual bool isSocket() const
virtual int getsockopt(int level, int optname, void *optvalue, socklen_t *optlen)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
virtual int getpeername(struct sockaddr *address, socklen_t *address_len)
static void netconnCallback(struct netconn *conn, enum netconn_evt evt, uint16_t len)
virtual bool create()
Implementation-specific final socket creation logic.
virtual int connect(const struct sockaddr *address, socklen_t addrlen)
virtual int connect(const struct sockaddr *address, socklen_t addrlen)
bool addEphemeralFile(File *pFile)
Add an ephemeral file to the directory.
u8_t pbuf_free(struct pbuf *p)
virtual bool isDirectory()
bool endswith(const char c) const
virtual bool send(size_t nBytes, uintptr_t buffer)
virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
virtual int select(bool bWriting=false, int timeout=0)