Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement getsockopt for GameCube #105

Merged
merged 2 commits into from
Jan 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gc/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ s32 net_recvfrom(s32 s,void *mem,s32 len,u32 flags,struct sockaddr *from,socklen
s32 net_read(s32 s,void *mem,s32 len);
s32 net_close(s32 s);
s32 net_select(s32 maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout);
s32 net_getsockopt(s32 s,u32 level,u32 optname,const void *optval,socklen_t optlen);
s32 net_setsockopt(s32 s,u32 level,u32 optname,const void *optval,socklen_t optlen);
s32 net_ioctl(s32 s, u32 cmd, void *argp);
s32 net_fcntl(s32 s, u32 cmd, u32 flags);
Expand Down
111 changes: 111 additions & 0 deletions lwip/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -2116,6 +2116,117 @@ s32 net_select(s32 maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,st
return nready;
}

s32 net_getsockopt(s32 s,u32 level,u32 optname,const void *optval,socklen_t optlen)
{
s32 err = 0;
struct netsocket *sock;

sock = get_socket(s);
if(sock==NULL) return -ENOTSOCK;
if(optval==NULL) return -EINVAL;

switch(level) {
case SOL_SOCKET:
{
switch(optname) {
case SO_ERROR:
case SO_BROADCAST:
case SO_KEEPALIVE:
case SO_REUSEADDR:
case SO_REUSEPORT:
if(optlen<sizeof(u32)) err = EINVAL;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("net_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
}
}
break;

case IPPROTO_IP:
{
switch(optname) {
case IP_TTL:
case IP_TOS:
if(optlen<sizeof(u32)) err = EINVAL;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("net_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
}
}
break;

case IPPROTO_TCP:
{
if(optlen<sizeof(u32)) {
err = EINVAL;
break;
}
if(sock->conn->type!=NETCONN_TCP) return 0;
switch(optname) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("net_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
}
}
break;

default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("net_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
}
if(err) return -err;

switch(level) {
case SOL_SOCKET:
{
switch(optname) {
case SO_ERROR:
(*(u32*)optval) = sock->conn->err;
sock->conn->err = 0;
break;
case SO_BROADCAST:
case SO_KEEPALIVE:
case SO_REUSEADDR:
case SO_REUSEPORT:
(*(u32*)optval) = sock->conn->pcb.tcp->so_options & optname;
break;
}
}
break;

case IPPROTO_IP:
{
switch(optname) {
case IP_TTL:
(*(u32*)optval) = sock->conn->pcb.tcp->ttl;
break;
case IP_TOS:
(*(u32*)optval) = sock->conn->pcb.tcp->tos;
break;
}
}
break;

case IPPROTO_TCP:
{
switch(optname) {
case TCP_NODELAY:
(*(u32*)optval) = sock->conn->pcb.tcp->flags & TF_NODELAY;
bendmorris marked this conversation as resolved.
Show resolved Hide resolved
break;
case TCP_KEEPALIVE:
(*(u32*)optval) = sock->conn->pcb.tcp->keepalive;
break;
}
}
}
return 0;
}

s32 net_setsockopt(s32 s,u32 level,u32 optname,const void *optval,socklen_t optlen)
{
s32 err = 0;
Expand Down