Exemplo n.º 1
0
Arquivo: rdp.c Projeto: ArvidNorr/xrdp
/* return error */
int DEFAULT_CC
lib_mod_connect(struct mod* mod)
{
  DEBUG(("in lib_mod_connect"));
  /* clear screen */
  mod->server_begin_update(mod);
  mod->server_set_fgcolor(mod, 0);
  mod->server_fill_rect(mod, 0, 0, mod->width, mod->height);
  mod->server_end_update(mod);
  /* connect */
  if (rdp_rdp_connect(mod->rdp_layer, mod->ip, mod->port) == 0)
  {
    mod->sck = mod->rdp_layer->sec_layer->mcs_layer->iso_layer->tcp_layer->sck;
    g_tcp_set_non_blocking(mod->sck);
    g_tcp_set_no_delay(mod->sck);
    mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0);
    DEBUG(("out lib_mod_connect"));
    return 0;
  }
  DEBUG(("out lib_mod_connect error"));
  return 1;
}
Exemplo n.º 2
0
/* wait for incoming connections */
int APP_CC
xrdp_listen_main_loop(struct xrdp_listen *self)
{
    int error;
    int robjs_count;
    int cont;
    int timeout = 0;
    char port[128];
    char address[256];
    tbus robjs[8];
    tbus term_obj;
    tbus sync_obj;
    tbus done_obj;
    int tcp_nodelay;
    int tcp_keepalive;
    int bytes;

    self->status = 1;

    if (xrdp_listen_get_port_address(port, sizeof(port),
                                     address, sizeof(address),
                                     &tcp_nodelay, &tcp_keepalive,
                                     self->startup_params) != 0)
    {
        log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed");
        self->status = -1;
        return 1;
    }

    if (port[0] == '/')
    {
        /* set UDS mode */
        self->listen_trans->mode = TRANS_MODE_UNIX;
        /* not valid with UDS */
        tcp_nodelay = 0;
    }

    /* Create socket */
    error = trans_listen_address(self->listen_trans, port, address);

    if (error == 0)
    {
        if (tcp_nodelay)
        {
            if (g_tcp_set_no_delay(self->listen_trans->sck))
            {
                log_message(LOG_LEVEL_ERROR,"Error setting tcp_nodelay");
            }
        }

        if (tcp_keepalive)
        {
            if (g_tcp_set_keepalive(self->listen_trans->sck))
            {
                log_message(LOG_LEVEL_ERROR,"Error setting tcp_keepalive");
            }
        }

        if (self->startup_params->send_buffer_bytes > 0)
        {
            bytes = self->startup_params->send_buffer_bytes;
            log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
                        bytes);
            if (g_sck_set_send_buffer_bytes(self->listen_trans->sck,
                                            bytes) != 0)
            {
                log_message(LOG_LEVEL_ERROR, "error setting send buffer");
            }
            else
            {
                if (g_sck_get_send_buffer_bytes(self->listen_trans->sck,
                                                &bytes) != 0)
                {
                    log_message(LOG_LEVEL_ERROR, "error getting send buffer");
                }
                else
                {
                    log_message(LOG_LEVEL_INFO, "send buffer set to %d bytes", bytes);
                }
            }
        }

        if (self->startup_params->recv_buffer_bytes > 0)
        {
            bytes = self->startup_params->recv_buffer_bytes;
            log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
                        bytes);
            if (g_sck_set_recv_buffer_bytes(self->listen_trans->sck,
                                            bytes) != 0)
            {
                log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
            }
            else
            {
                if (g_sck_get_recv_buffer_bytes(self->listen_trans->sck,
                                                &bytes) != 0)
                {
                    log_message(LOG_LEVEL_ERROR, "error getting recv buffer");
                }
                else
                {
                    log_message(LOG_LEVEL_INFO, "recv buffer set to %d bytes", bytes);
                }
            }
        }

        self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
        self->listen_trans->callback_data = self;
        term_obj = g_get_term_event(); /*Global termination event */
        sync_obj = g_get_sync_event();
        done_obj = self->pro_done_event;
        cont = 1;

        while (cont)
        {
            /* build the wait obj list */
            robjs_count = 0;
            robjs[robjs_count++] = term_obj;
            robjs[robjs_count++] = sync_obj;
            robjs[robjs_count++] = done_obj;
            timeout = -1;

            /* if (self->listen_trans != 0) */
            {
                if (trans_get_wait_objs(self->listen_trans, robjs,
                                        &robjs_count) != 0)
                {
                    log_message(LOG_LEVEL_ERROR,"Listening socket is in wrong state we "
                              "terminate listener");
                    break;
                }
            }

            /* wait - timeout -1 means wait indefinitely*/
            if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
            {
                /* error, should not get here */
                g_sleep(100);
            }

            if (g_is_wait_obj_set(term_obj)) /* termination called */
            {
                break;
            }

            /* some function must be processed by this thread */
            if (g_is_wait_obj_set(sync_obj))
            {
                g_reset_wait_obj(sync_obj);
                g_process_waiting_function(); /* run the function */
            }

            if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
            {
                g_reset_wait_obj(done_obj);
                /* a process has died remove it from lists*/
                xrdp_listen_delete_done_pro(self);
            }

            /* Run the callback when accept() returns a new socket*/
            if (trans_check_wait_objs(self->listen_trans) != 0)
            {
                break;
            }
        }

        /* stop listening */
        trans_delete(self->listen_trans);
        self->listen_trans = 0;
        /* second loop to wait for all process threads to close */
        cont = 1;

        while (cont)
        {
            if (self->process_list->count == 0)
            {
                break;
            }

            timeout = -1;
            /* build the wait obj list */
            robjs_count = 0;
            robjs[robjs_count++] = sync_obj;
            robjs[robjs_count++] = done_obj;

            /* wait - timeout -1 means wait indefinitely*/
            if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
            {
                /* error, should not get here */
                g_sleep(100);
            }

            /* some function must be processed by this thread */
            if (g_is_wait_obj_set(sync_obj))
            {
                g_reset_wait_obj(sync_obj);
                g_process_waiting_function(); /* run the function that is waiting*/
            }

            if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
            {
                g_reset_wait_obj(done_obj);
                xrdp_listen_delete_done_pro(self);
            }
        }
    }
    else
    {
        log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: listen error, possible port "
                  "already in use");
    }

    self->status = -1;
    return 0;
}
Exemplo n.º 3
0
int APP_CC
xrdp_process_main_loop(struct xrdp_process* self)
{
  int robjs_count;
  int wobjs_count;
  int cont;
  int timeout;
  tbus robjs[32];
  tbus wobjs[32];
  tbus term_obj;
  tbus sck_obj;

  self->status = 1;
  self->session = libxrdp_init((long)self, self->sck);
  /* this callback function is in xrdp_wm.c */
  self->session->callback = callback;
  /* this function is just above */
  self->session->is_term = xrdp_is_term;
  g_tcp_set_non_blocking(self->sck);
  g_tcp_set_no_delay(self->sck);
  if (libxrdp_process_incomming(self->session) == 0)
  {
    term_obj = g_get_term_event();
    sck_obj = g_create_wait_obj_from_socket(self->sck, 0);
    cont = 1;
    while (cont)
    {
      /* build the wait obj list */
      timeout = -1;
      robjs_count = 0;
      wobjs_count = 0;
      robjs[robjs_count++] = term_obj;
      robjs[robjs_count++] = sck_obj;
      robjs[robjs_count++] = self->self_term_event;
      xrdp_wm_get_wait_objs(self->wm, robjs, &robjs_count,
                            wobjs, &wobjs_count, &timeout);
      /* wait */
      if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(term_obj)) /* term */
      {
        break;
      }
      if (g_is_wait_obj_set(self->self_term_event))
      {
        break;
      }
      if (g_is_wait_obj_set(sck_obj)) /* incomming client data */
      {
        if (xrdp_process_loop(self) != 0)
        {
          break;
        }
      }
      if (xrdp_wm_check_wait_objs(self->wm) != 0)
      {
        break;
      }
    }
    g_delete_wait_obj_from_socket(sck_obj);
    libxrdp_disconnect(self->session);
  }
  xrdp_process_mod_end(self);
  libxrdp_exit(self->session);
  self->session = 0;
  g_tcp_close(self->sck);
  self->status = -1;
  g_set_wait_obj(self->done_event);
  return 0;
}
Exemplo n.º 4
0
/* return error */
int DEFAULT_CC
lib_mod_connect(struct mod *mod)
{
    int error;
    int len;
    int i;
    int index;
    int use_uds;
    struct stream *s;
    char con_port[256];
    int retry = 0;
    int send_error = 0;

    int rc = 0;
    unsigned int nbytes;
    char pidfile[128];
    char ip[16];

    char cookie[33];
    char sessionid[128];
    char sessiontoken[128];

    struct passwd pwd;
    struct passwd *pwdresult;
    char pwdbuffer[16384];
    char message[256];
    char reply[256];

    int sock;
    struct sockaddr_in server;

    json_t *request;
    json_t *response;
    json_t *display;
    json_error_t js_error;

    mod->server_msg(mod, "GoPCNX started connection", 0);

    sock = socket(AF_INET , SOCK_STREAM , 0);
    if (sock == -1) {
        mod->server_msg(mod, "Socket creation failed", 0);    
        return 1;
    }

    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(9999);

    if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) {
        mod->server_msg(mod, "Server connection failed", 0);
        return 1;
    }

    request = json_object();
    json_object_set(request, "username", json_string(mod->username));
    json_object_set(request, "password", json_string(mod->password));
    json_object_set(request, "ip", json_string("127.0.0.1"));
    json_object_set(request, "link", json_string("lan"));
    display = json_object();
    json_object_set(display, "width", json_integer(mod->width));
    json_object_set(display, "height", json_integer(mod->height));
    json_object_set(request, "display", display);
    json_decref(display);

    g_snprintf(message, sizeof(message)-1, "%s\n", json_dumps(request, 0));
    json_decref(request);

    if (send(sock, message, strlen(message), 0) < 0) {
        mod->server_msg(mod, "Server request failed", 0);
        return 1;
    }

    if (recv(sock, reply, sizeof(reply), 0) < 0) {
        mod->server_msg(mod, "Server reply failed", 0);
        return 1;
    }

    response = json_loads(reply, 0, &js_error);
        
    if (response == NULL) {
        mod->server_msg(mod, "Decoding response failed", 0);
        return 1;
    } else {
        json_t *nxsession = json_object_get(response, "session");
        json_t *err = json_object_get(response, "err");
        int resume = json_is_true(json_object_get(response, "resume"));

        if (err) {
            mod->server_msg(mod, json_string_value(err), 0);
            return 1;
        } else if (resume) {
            resize_nxproxy(mod);
        } else {
            char sessionstash[512];
            const char *cookie = json_string_value(json_object_get(nxsession, "cookie"));
            const char *host = json_string_value(json_object_get(nxsession, "host"));
            json_int_t port = json_integer_value(json_object_get(nxsession, "port"));            

            getpwnam_r(mod->username, &pwd, pwdbuffer, sizeof(pwdbuffer), &pwdresult);
            if (pwdresult == NULL) {
                mod->server_msg(mod, "Uid lookup failed", 0);
                return 1;
            }

            if (!start_nxproxy(mod, cookie, (int)port)) {
                mod->server_msg(mod, "nxproxy failed to start", 0);
                return 1;
            }

            json_decref(nxsession);
        }
    }

    json_decref(response);

    LIB_DEBUG(mod, "in lib_mod_connect");
    /* clear screen */
    mod->server_begin_update(mod);
    mod->server_set_fgcolor(mod, 0);
    mod->server_fill_rect(mod, 0, 0, mod->width, mod->height);
    mod->server_end_update(mod);
    mod->server_msg(mod, "started connecting", 0);

    /* only support 8, 15, 16, and 24 bpp connections from rdp client */
    if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24)
    {
        mod->server_msg(mod,
                        "error - only supporting 8, 15, 16, and 24 bpp rdp connections", 0);
        LIB_DEBUG(mod, "out lib_mod_connect error");
        return 1;
    }

    if (g_strcmp(mod->ip, "") == 0)
    {
        mod->server_msg(mod, "error - no ip set", 0);
        LIB_DEBUG(mod, "out lib_mod_connect error");
        return 1;
    }

    make_stream(s);

    g_snprintf(con_port, 255, "%s", mod->port);
    use_uds = 0;

    if (con_port[0] == '/')
    {
        use_uds = 1;
    }

    mod->sck_closed = 0;
    i = 0;

RECONNECT:
    while (1)
    {
        if (use_uds)
        {
            mod->sck = g_tcp_local_socket();
        }
        else
        {
            mod->sck = g_tcp_socket();
            g_tcp_set_non_blocking(mod->sck);
            g_tcp_set_no_delay(mod->sck);
        }

        /* mod->server_msg(mod, "connecting...", 0); */

        if (use_uds)
        {
            error = g_tcp_local_connect(mod->sck, con_port);
        }
        else
        {
            error = g_tcp_connect(mod->sck, mod->ip, con_port);
        }

        if (error == -1)
        {
            if (g_tcp_last_error_would_block(mod->sck))
            {
                error = 0;
                index = 0;

                while (!g_tcp_can_send(mod->sck, 100))
                {
                    index++;

                    if ((index >= 30) || mod->server_is_term(mod))
                    {
                        mod->server_msg(mod, "connect timeout", 0);
                        error = 1;
                        break;
                    }
                }
            }
            else
            {
                /* mod->server_msg(mod, "connect error", 0); */
            }
        }

        if (error == 0)
        {
            break;
        }

        g_tcp_close(mod->sck);
        mod->sck = 0;
        i++;

        if (i >= 20)
        {
            mod->server_msg(mod, "connection problem, giving up", 0);
            break;
        }

        g_sleep(500);
    }

    if (error == 0)
    {
        if (use_uds)
        {
            lib_mod_log_peer(mod);
        }
    }

    if (error == 0)
    {
        /* send version message */
        init_stream(s, 8192);
        s_push_layer(s, iso_hdr, 4);
        out_uint16_le(s, 103);
        out_uint32_le(s, 301);
        out_uint32_le(s, 0);
        out_uint32_le(s, 0);
        out_uint32_le(s, 0);
        out_uint32_le(s, 1);
        s_mark_end(s);
        len = (int)(s->end - s->data);
        s_pop_layer(s, iso_hdr);
        out_uint32_le(s, len);
        lib_send(mod, s->data, len);
    }

    if (error == 0)
    {
        /* send screen size message */
        init_stream(s, 8192);
        s_push_layer(s, iso_hdr, 4);
        out_uint16_le(s, 103);
        out_uint32_le(s, 300);
        out_uint32_le(s, mod->width);
        out_uint32_le(s, mod->height);
        out_uint32_le(s, mod->bpp);
        out_uint32_le(s, 0);
        s_mark_end(s);
        len = (int)(s->end - s->data);
        s_pop_layer(s, iso_hdr);
        out_uint32_le(s, len);
        lib_send(mod, s->data, len);
    }

    if (error == 0)
    {
        /* send invalidate message */
        init_stream(s, 8192);
        s_push_layer(s, iso_hdr, 4);
        out_uint16_le(s, 103);
        out_uint32_le(s, 200);
        /* x and y */
        i = 0;
        out_uint32_le(s, i);
        /* width and height */
        i = ((mod->width & 0xffff) << 16) | mod->height;
        out_uint32_le(s, i);
        out_uint32_le(s, 0);
        out_uint32_le(s, 0);
        s_mark_end(s);
        len = (int)(s->end - s->data);
        s_pop_layer(s, iso_hdr);
        out_uint32_le(s, len);
        send_error = lib_send(mod, s->data, len);
    }

    if (send_error) {
        if (retry < 50) {
            g_tcp_close(mod->sck);
            mod->server_msg(mod, "Doing a retry", 0);
            retry++;
            g_sleep(1000);
            goto RECONNECT;
        }

        error = send_error;
    }

    free_stream(s);

    if (error != 0)
    {
        mod->server_msg(mod, "some problem", 0);
        LIB_DEBUG(mod, "out lib_mod_connect error");
        return 1;
    }
    else
    {
        mod->server_msg(mod, "connected ok", 0);
        mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0);
    }

    LIB_DEBUG(mod, "out lib_mod_connect");
    return 0;
}
Exemplo n.º 5
0
/* return error */
int DEFAULT_CC
lib_mod_connect(struct mod* mod)
{
  int error;
  int len;
  int i;
  int index;
  int use_uds;
  struct stream* s;
  char con_port[256];

  LIB_DEBUG(mod, "in lib_mod_connect");
  /* clear screen */
  mod->server_begin_update(mod);
  mod->server_set_fgcolor(mod, 0);
  mod->server_fill_rect(mod, 0, 0, mod->width, mod->height);
  mod->server_end_update(mod);
  mod->server_msg(mod, "started connecting", 0);
  /* only support 8, 15, 16, and 24 bpp connections from rdp client */
  if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24)
  {
    mod->server_msg(mod,
      "error - only supporting 8, 15, 16, and 24 bpp rdp connections", 0);
    LIB_DEBUG(mod, "out lib_mod_connect error");
    return 1;
  }
  if (g_strcmp(mod->ip, "") == 0)
  {
    mod->server_msg(mod, "error - no ip set", 0);
    LIB_DEBUG(mod, "out lib_mod_connect error");
    return 1;
  }
  make_stream(s);
  g_sprintf(con_port, "%s", mod->port);
  use_uds = 0;
  if (con_port[0] == '/')
  {
    use_uds = 1;
  }
  mod->sck_closed = 0;
  i = 0;
  while (1)
  {
    if (use_uds)
    {
      mod->sck = g_tcp_local_socket();
    }
    else
    {
      mod->sck = g_tcp_socket();
    }
    g_tcp_set_non_blocking(mod->sck);
    g_tcp_set_no_delay(mod->sck);
    mod->server_msg(mod, "connecting...", 0);
    if (use_uds)
    {
      error = g_tcp_local_connect(mod->sck, con_port);
    }
    else
    {
      error = g_tcp_connect(mod->sck, mod->ip, con_port);
    }
    if (error == -1)
    {
      if (g_tcp_last_error_would_block(mod->sck))
      {
        error = 0;
        index = 0;
        while (!g_tcp_can_send(mod->sck, 100))
        {
          index++;
          if ((index >= 30) || mod->server_is_term(mod))
          {
            mod->server_msg(mod, "connect timeout", 0);
            error = 1;
            break;
          }
        }
      }
      else
      {
        mod->server_msg(mod, "connect error", 0);
      }
    }
    if (error == 0)
    {
      break;
    }
    g_tcp_close(mod->sck);
    mod->sck = 0;
    i++;
    if (i >= 4)
    {
      mod->server_msg(mod, "connection problem, giving up", 0);
      break;
    }
    g_sleep(250);
  }
  if (error == 0)
  {
    init_stream(s, 8192);
    s_push_layer(s, iso_hdr, 4);
    out_uint16_le(s, 103);
    out_uint32_le(s, 300);
    out_uint32_le(s, mod->width);
    out_uint32_le(s, mod->height);
    out_uint32_le(s, mod->bpp);
    out_uint32_le(s, mod->rfx); /* send rfx flag */
    s_mark_end(s);
    len = (int)(s->end - s->data);
    s_pop_layer(s, iso_hdr);
    out_uint32_le(s, len);
    lib_send(mod, s->data, len);
  }
  if (error == 0)
  {
    init_stream(s, 8192);
    s_push_layer(s, iso_hdr, 4);
    out_uint16_le(s, 103);
    out_uint32_le(s, 200);
    /* x and y */
    i = 0;
    out_uint32_le(s, i);
    /* width and height */
    i = ((mod->width & 0xffff) << 16) | mod->height;
    out_uint32_le(s, i);
    out_uint32_le(s, 0);
    out_uint32_le(s, 0);
    s_mark_end(s);
    len = (int)(s->end - s->data);
    s_pop_layer(s, iso_hdr);
    out_uint32_le(s, len);
    lib_send(mod, s->data, len);
  }
  free_stream(s);
  if (error != 0)
  {
    mod->server_msg(mod, "some problem", 0);
    LIB_DEBUG(mod, "out lib_mod_connect error");
    return 1;
  }
  else
  {
    mod->server_msg(mod, "connected ok", 0);
    mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0);
  }
  LIB_DEBUG(mod, "out lib_mod_connect");
  return 0;
}
Exemplo n.º 6
0
enum SCP_CLIENT_STATES_E
scp_v0c_connect(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
{
    tui32 version;
    tui32 size;
    tui16 sz;

    init_stream(c->in_s, c->in_s->size);
    init_stream(c->out_s, c->in_s->size);

    LOG_DBG("[v0:%d] starting connection", __LINE__);
    g_tcp_set_non_blocking(c->in_sck);
    g_tcp_set_no_delay(c->in_sck);
    s_push_layer(c->out_s, channel_hdr, 8);

    /* code */
    if (s->type == SCP_SESSION_TYPE_XVNC)
    {
        out_uint16_be(c->out_s, 0);
    }
    else if (s->type == SCP_SESSION_TYPE_XRDP)
    {
        out_uint16_be(c->out_s, 10);
    }
    else if (s->type == SCP_SESSION_TYPE_XORG)
    {
        out_uint16_be(c->out_s, 20);
    }
    else
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
        return SCP_CLIENT_STATE_INTERNAL_ERR;
    }

    sz = g_strlen(s->username);
    out_uint16_be(c->out_s, sz);
    out_uint8a(c->out_s, s->username, sz);

    sz = g_strlen(s->password);
    out_uint16_be(c->out_s, sz);
    out_uint8a(c->out_s, s->password, sz);
    out_uint16_be(c->out_s, s->width);
    out_uint16_be(c->out_s, s->height);
    out_uint16_be(c->out_s, s->bpp);

    s_mark_end(c->out_s);
    s_pop_layer(c->out_s, channel_hdr);

    /* version */
    out_uint32_be(c->out_s, 0);
    /* size */
    out_uint32_be(c->out_s, c->out_s->end - c->out_s->data);

    if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data))
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
        return SCP_CLIENT_STATE_NETWORK_ERR;
    }

    if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
        return SCP_CLIENT_STATE_NETWORK_ERR;
    }

    in_uint32_be(c->in_s, version);

    if (0 != version)
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__);
        return SCP_CLIENT_STATE_VERSION_ERR;
    }

    in_uint32_be(c->in_s, size);

    if (size < 14)
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: packet size error", __LINE__);
        return SCP_CLIENT_STATE_SIZE_ERR;
    }

    /* getting payload */
    init_stream(c->in_s, c->in_s->size);

    if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8))
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
        return SCP_CLIENT_STATE_NETWORK_ERR;
    }

    /* check code */
    in_uint16_be(c->in_s, sz);

    if (3 != sz)
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__);
        return SCP_CLIENT_STATE_SEQUENCE_ERR;
    }

    /* message payload */
    in_uint16_be(c->in_s, sz);

    if (1 != sz)
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: connection denied", __LINE__);
        return SCP_CLIENT_STATE_CONNECTION_DENIED;
    }

    in_uint16_be(c->in_s, sz);
    s->display = sz;

    LOG_DBG("[v0:%d] connection terminated", __LINE__);
    return SCP_CLIENT_STATE_END;
}