Integrating With Physical Networks

U is not only intended to be used in isolation. The event system provides a mechanism in which the user can register to be notified in a normal TEMU event that data is available on a socket. The API for this is declared in temu-c/Support/Events.h and includes the functions: temu_asyncSocketAdd(), temu_asyncSocketRemove(), temu_asyncTimerAdd() and temu_asyncTimerRemove(). The socket functions allows for the registration of a socket listening function that is scheduled in the main emulator loop. The functions actually handles any file descriptor (including pipes). The use of this function is that the provided callback will be executed when other emulator events are executed, and thus everything that is safe to do there will be safe to do in the provided callback. Internally, the async APIs uses the epoll mechanism on LINUX and kqueue on macOS and other BSD based systems. It is relatively straight forward to extend the serial port device example with a device that speaks to a telnet connection instead of printing messages to stdout. This can be done by opening a TCP socket and then waiting for a connection when the time source has been connected (by implementing the relevant function in temu_ObjectIface (see temu-c/Support/Objsys.h)). This will block the timesource-set command until you have connected the telnet client). Note that sockets should be made non-blocking, or you risk hanging the read access.

static
void asyncCb(void *data)
{
  MySerialDevice *d = (MySerialDevice*)data;
  uint8_t ch = 0;
  int res;
  do {
    res = read(d->fd, &ch, 1);
  } while (res < 0 && errno == EINTR);

  if (res == 1) d->uart.Iface->write(d->uart.Obj, ch);
}
static void
timeSourceSet(void *obj)
{
  MySerialDevice *d = (MySerialDevice*)obj;
  if (d->super.TimeSource) {
    // Open socket
    // d->fd = ...
    fcntl(d->fd, F_SETFL, O_NONBLOCK);
    if (temu_asyncSocketAdd(d->super.TimeSource, d->fd, TEMU_ASYNC_READ,
      asyncCb, d) != d->fd) {
      temu_logError(d, "could not add async listner");
    }
  }
}