Simutrans Chat Room
Where cool people of Simutrans can meet up.

Experimenting with remote access

Started by hreintke, January 01, 2013, 06:08:14 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.



I am experimenting getting simutrans accessible and/or updatable by webbrowser.
First for this I took the mongoose package which provides http/webserver fuctionality and added mongoose.c to the simutans project.

Now updated simworld.h with the following :

class karte_t

    struct mg_context *ctx;

  static void *karte_t::callback(enum mg_event event,
                      struct mg_connection *conn);

and then updated to use start the webserver and reply to requests.

  void *karte_t::callback(enum mg_event event,
                      struct mg_connection *conn) {
  const struct mg_request_info *request_info = mg_get_request_info(conn);
  if (event == MG_NEW_REQUEST) {
    char content[1024];
    int content_length = _snprintf(content, sizeof(content),
                                  "Hello from Simutrans! Remote port: %d ",
              "HTTP/1.1 200 OK\r\n"
              "Content-Type: text/plain\r\n"
              "Content-Length: %d\r\n"        // Always set Content-Length
              content_length, content);
    // Mark as processed
    return "";
  } else {
    return NULL;

karte_t::karte_t() :
const char *options[] = {"listening_ports", "8080", NULL};
ctx = mg_start( &callback, NULL, options);

// length of day and other time stuff

Works like a charm. Starting simutrans and using a browser to access localhost:8080 gives the expected result.

But now on to delivering some simutrans content. For that I exptected to be able to access the karte_t data and functions in the callback function but no luck there. Cannot acccess the data themself and also not using the this to get to there.

using this.get_fab_list().getcount()
gives the error 'this' : can only be referenced inside non-static member functions

using get_fab_list().getcount()
gives the error 'karte_t::get_fab_list' : illegal call of non-static member function

One thing to mention too is that I do need to have the callback function static, otherwise the usage of this in the ctx = mg_start( &callback, NULL, options); will not work.

Any hints to do further trials appreciated.

Kind regards,



The difficulty, I think, is with the requirement to have your callback function static. All the actual game data in Simutrans (including everything in karte_t), other than the settings, are instantiated objects, which cannot be accessed from static methods. The world itself is a non-static object of the class karte_t. (In theory, it would be possible to have multiple worlds with the same Simutrans process, but the code is not set up to cope with that, and there would be little point).
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.


Most callbacks take a context parameter where user data can be passed. The karte_t instance must be sent through that. This might mean that the callback must be reregistered when a new game is created/loaded.



The solution is indeed to pass the karte_t instance when starting the webservice.

karte_t::karte_t() :
const char *options[] = {"listening_ports", "8080", NULL};
ctx = mg_start( &callback, this, options);

and retrieving this userdata in the callback function.

void *karte_t::callback(enum mg_event event,
                      struct mg_connection *conn) {
  const struct mg_request_info *request_info = mg_get_request_info(conn);
  karte_t *myworld = (karte_t*) request_info->user_data;

In that way I do have access to the "welt".

Now further exerimenting with retrieving data using the web.