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

IOS/Network: Emulate socket fd table #5432

Merged
merged 9 commits into from Jun 4, 2017
Merged

Conversation

sepalani
Copy link
Contributor

@sepalani sepalani commented May 15, 2017

This PR tries to emulate a Wii fd table. Dolphin was using the host's fd when emulating sockets, while it shouldn't be a problem, it seems that in some cases (like the Netflix channel) there is a check against that fd value.

Regarding the Netflix channel, if the fd value is greater than 23 it returns a EBADF error (which consequently is sent to SO commands like CONNECT). I assume, it's probably using select/poll to monitor sockets and that it does a sanity check against a specified limit (max_fd?).

Currently, the fd values are computed empirically. It will need a hardware test to confirm that it matches the Wii's behaviour. It also assumes that it has a separate table for other (non-socket) fd generated. Otherwise, the fd table will need to be implemented somewhere else in IOS code. Not the case anymore, thanks to @shuffle2.

TODO

Based on @shuffle2's gist: https://gist.github.com/shuffle2/4541e4e96ba3e04a34bd36b0e07d3013#file-so_socket-c-L71

  • Create the socket fd table
  • Replace logs using host socket fd with wii fd
  • Handle SO_ENETRESET (39)
  • Handle SO_EAFNOSUPPORT (5)
  • Handle SO_EPROTONOSUPPORT (68)
  • Handle SO_EMFILE (33)
  • Handle SO_EPROTOTYPE (69)
  • Handle SO_ENOMEM (49)

Ready to be reviewed & merged.

{
if (fd >= 0)
{
WiiSocket& sock = WiiSockets[fd];
s32 wii_fd = 3;

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

@@ -231,6 +231,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
WiiSockMan::Convert(*wii_name, local_name);

int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
ret = WiiSockMan::GetInstance().AddSocket(ret);

This comment was marked as off-topic.

This comment was marked as off-topic.

return ret;
}

s32 WiiSockMan::GetHostSocket(s32 wii_fd)

This comment was marked as off-topic.

Copy link
Contributor

@riking riking left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error handling seems a bit suspect.

{
if (WiiSockets.count(wii_fd) > 0)
return WiiSockets.at(wii_fd).fd;
return EBADF;

This comment was marked as off-topic.

This comment was marked as off-topic.

}

WiiSockMan::GetInstance().AddSocket(ReturnValue);
ret = WiiSockMan::GetInstance().AddSocket(ret);

This comment was marked as off-topic.

This comment was marked as off-topic.

@shuffle2
Copy link
Contributor

shuffle2 commented Jun 1, 2017

Here is the related SO code from IOS56 which is used to lookup the object via fd:

  v15 = irq_disable();
  entry = 0;
  if ( fd <= 23 )
  {
    entry = &sock_fd_table[fd];
    if ( entry->refcount > 0 && (obj = entry->obj) != 0 )
    {
      ++entry->refcount;
      if ( pobj )
        *pobj = obj;
    }
    else
    {
      entry = 0;
    }
  }
  irq_restore(v15);
  return entry;

So the hardcoded size check seems correct.

@shuffle2
Copy link
Contributor

shuffle2 commented Jun 1, 2017

Here is how the fd is selected by IOCTL_SO_SOCKET: https://gist.github.com/shuffle2/4541e4e96ba3e04a34bd36b0e07d3013#file-so_socket-c-L101
basically, SO keeps it's own fd table, and it returns the first currently free (refcount==0) index into the table as the fd.

@shuffle2
Copy link
Contributor

shuffle2 commented Jun 1, 2017

I updated the above gist to clear up confusion around the "protocol" arg for SOSocket()...the params follow standard posix socket() https://gist.github.com/shuffle2/4541e4e96ba3e04a34bd36b0e07d3013#file-so_socket-c-L71

@sepalani sepalani changed the title [WIP] IOS/Network: Emulate fd table IOS/Network: Emulate fd table Jun 4, 2017
@sepalani sepalani changed the title IOS/Network: Emulate fd table IOS/Network: Emulate socket fd table Jun 4, 2017
@sepalani
Copy link
Contributor Author

sepalani commented Jun 4, 2017

@riking you were correct concerning the error values. It was a mistake from the original code because DeleteSocket returns the Wii error code via the CloseFd() member function. So I addressed your comment.

I tested this PR with games using NintendoWFC (with altwfc) and other channels and they don't hit the fd maximum limit. That is to say, they apparently don't forget to close sockets.

Otherwise, should I change the constants used with their respective define value such as AF_INET and so on or leave a comment about them?

Regardless, this PR is ready to be reviewed & merged.

@shuffle2
Copy link
Contributor

shuffle2 commented Jun 4, 2017

Otherwise, should I change the constants used with their respective define value such as AF_INET and so on or leave a comment about them?

What do you mean by that?

@sepalani
Copy link
Contributor Author

sepalani commented Jun 4, 2017

@shuffle2
Replace this:

if (type != 1 && type != 2)

With this or something along those lines:

if (type != 1 && type != 2)  // SOCK_STREAM && SOCK_DGRAM

Ditto, for the other constants.

@shuffle2
Copy link
Contributor

shuffle2 commented Jun 4, 2017

A comment would be fine - I'm not sure how much we have to care about those values differing on host platforms, best to be on the safe side I guess.

@shuffle2 shuffle2 merged commit a2bd95a into dolphin-emu:master Jun 4, 2017
@sepalani sepalani deleted the fd-table branch June 4, 2017 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
6 participants