The below change updates the nethack nacl port from using nacl-mounts to nacl_io. In the nacl-mounts version a JSPipeMount is used to funnel messages from the browser into the nacl program's stdin. In the nacl_io version how is that accomplished?

https://chromium.googlesource.com/external/naclports/+/8ac229a6e3fddff3e061017a8eb85105874570b3%5E!/

有帮助吗?

解决方案

As described in the commit description: "Communication between the browser and the nexe is handled by a TtyNode using Pepper Simple."

I answered the same question with more detail on the native-client-discuss Google group here: https://groups.google.com/d/msg/native-client-discuss/nOKHWBhBPfs/i_gUYIFuBJAJ

Here is the contents of that post:

In nacl_io, this is just a node (MountNodeTty), not a new mount. You can access it by opening the file "/dev/tty".

The simplest way to use this is by using the "ppapi_simple" library. It does the following:

  • Set up pp::Instance::HandleMessage to forward data to the node, which can then be read by reading from "/dev/tty"
  • Writes to "/dev/tty" are turned into calls to pp::Instance::PostMessage.
  • If you want to map stdin and stdout to /dev/tty, you can set the PS_STDIN and PS_STDOUT arguments to "/dev/tty". You can do this by adding additional attributes to your embed tag:

    <embed src="..." type="application/x-pnacl" PS_STDIN="/dev/tty" PS_STDOUT=/dev/tty"...>

To do it yourself, you'll have to do what the ppapi_simple library does. Basically, to feed data into the node, you use a call to ioctl:

Here is the code from pepper_30 (src/ppapi_simple/ps_instance.cc:328). The code from pepper_32 is similar.

struct tioc_nacl_input_string ioctl_message;
ioctl_message.length = message_len;
ioctl_message.buffer = message_str.data();
int ret =
  ioctl(fd_tty_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message));

To have the node call pp::Instance::PostMessage when you write to it, you use a different call to ioctl:

In pepper_30, this is done automatically. All messages are prefixed so you can differentiate them, though. This can be set with an ioctl (src/ppapi_simple/ps_instance.cc:210):

const char* tty_prefix = getenv("PS_TTY_PREFIX");
if (tty_prefix) {
  fd_tty_ = open("/dev/tty", O_WRONLY);
  if (fd_tty_ >= 0) {
    ioctl(fd_tty_, TIOCNACLPREFIX, const_cast<char*>(tty_prefix));
  } else {
    Error("Failed to open /dev/tty.\n");
  }
}

In pepper_31 and later, you must explicitly set up a callback function for the tty node. You can do that with a third ioctl (src/ppapi_simple/ps_instance.cc:221):

  tioc_nacl_output handler;
  handler.handler = TtyOutputHandlerStatic;
  handler.user_data = this;
  ioctl(tty_fd_, TIOCNACLOUTPUT, reinterpret_cast<char*>(&handler));

Finally, if you want to remap stdin/stdout to /dev/tty, you'll have to do that manually as well. This is how ppapi_simple does it (src/ppapi_simple/ps_instance:201):

int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
dup2(fd0, 0);

int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
dup2(fd1, 1);

Again, the simplest way to implement this is to use ppapi_simple, or to copy the behavior from that library.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top