diff options
| -rw-r--r-- | sesman/libscp_types.h | 24 | ||||
| -rw-r--r-- | sesman/libscp_v1c.c | 234 | ||||
| -rw-r--r-- | sesman/libscp_v1c.h | 38 | ||||
| -rw-r--r-- | sesman/libscp_v1s.c | 313 | ||||
| -rw-r--r-- | sesman/libscp_v1s.h | 52 | ||||
| -rw-r--r-- | sesman/scp_v1.c | 137 | ||||
| -rw-r--r-- | sesman/tools/Makefile | 7 | ||||
| -rw-r--r-- | sesman/tools/sestest.c | 73 | 
8 files changed, 643 insertions, 235 deletions
| diff --git a/sesman/libscp_types.h b/sesman/libscp_types.h index 5c835522..4aa16753 100644 --- a/sesman/libscp_types.h +++ b/sesman/libscp_types.h @@ -22,7 +22,7 @@   * @file libscp_types.h   * @brief libscp data types definitions   * @author Simone Fedele - *  + *   */  #ifndef LIBSCP_TYPES_H @@ -36,7 +36,7 @@  #include "arch.h"  #include "log.h" -//#warning sesman requires its own tcp streaming functions for threading safety +//sesman requires its own tcp streaming functions for threading safety  #include "tcp.h"  #define SCP_SID      uint32_t @@ -58,6 +58,8 @@  #define SCP_COMMAND_SET_MANAGE  0x0001  #define SCP_COMMAND_SET_RSR     0x0002 +#define SCP_SERVER_MAX_LIST_SIZE 100 +  #define free_session(s) {g_free((s)->username); g_free((s)->password); g_free((s)->hostname); g_free(s);}  struct SCP_CONNECTION @@ -89,13 +91,13 @@ struct SCP_SESSION  struct SCP_DISCONNECTED_SESSION  {    uint32_t SID; -  unsigned char type; +  uint8_t type;    uint16_t height;    uint16_t width; -  unsigned char bpp; -  unsigned char idle_days; -  unsigned char idle_hours; -  unsigned char idle_minutes; +  uint8_t bpp; +  uint8_t idle_days; +  uint8_t idle_hours; +  uint8_t idle_minutes;  };  enum SCP_CLIENT_STATES_E @@ -104,12 +106,16 @@ enum SCP_CLIENT_STATES_E    SCP_CLIENT_STATE_NETWORK_ERR,    SCP_CLIENT_STATE_VERSION_ERR,    SCP_CLIENT_STATE_SEQUENCE_ERR, +  SCP_CLIENT_STATE_SIZE_ERR,    SCP_CLIENT_STATE_INTERNAL_ERR,    SCP_CLIENT_STATE_SESSION_LIST, +  SCP_CLIENT_STATE_LIST_OK,    SCP_CLIENT_STATE_RESEND_CREDENTIALS,    SCP_CLIENT_STATE_CONNECTION_DENIED,    SCP_CLIENT_STATE_PWD_CHANGE_REQ, -  SCP_CLIENT_STATE_RECONNECT +  SCP_CLIENT_STATE_RECONNECT_SINGLE, +  SCP_CLIENT_STATE_SELECTION_CANCEL, +  SCP_CLIENT_STATE_END  };  enum SCP_SERVER_STATES_E @@ -121,6 +127,8 @@ enum SCP_SERVER_STATES_E    SCP_SERVER_STATE_INTERNAL_ERR,    SCP_SERVER_STATE_SESSION_TYPE_ERR,    SCP_SERVER_STATE_SIZE_ERR, +  SCP_SERVER_STATE_SELECTION_CANCEL, +  /*SCP_SERVER_STATE_FORCE_NEW,*/    SCP_SERVER_STATE_START_MANAGE,    SCP_SERVER_STATE_END  }; diff --git a/sesman/libscp_v1c.c b/sesman/libscp_v1c.c index 736a451a..17bfb0e0 100644 --- a/sesman/libscp_v1c.c +++ b/sesman/libscp_v1c.c @@ -18,19 +18,22 @@  */  /** - *  + *   * @file libscp_v1c.c   * @brief libscp version 1 client api code   * @author Simone Fedele - *  + *   */  #include "libscp_v1c.h" +#include <stdlib.h> +#include <stdio.h> +  static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s);  /* client API */ -/* 001 */  +/* 001 */  enum SCP_CLIENT_STATES_E scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s)  {    unsigned char sz; @@ -93,11 +96,11 @@ enum SCP_CLIENT_STATES_E scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SE      return SCP_CLIENT_STATE_NETWORK_ERR;    } -  /* wait for response */  +  /* wait for response */    return _scp_v1c_check_response(c, s);  } -/* 004 */  +/* 004 */  enum SCP_CLIENT_STATES_E scp_v1c_resend_credentials(struct SCP_CONNECTION* c, struct SCP_SESSION* s)  {    unsigned char sz; @@ -138,11 +141,208 @@ enum SCP_CLIENT_STATES_E scp_v1c_resend_credentials(struct SCP_CONNECTION* c, st  /* 021 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change(struct SCP_CONNECTION* c, char* newpass);  /* 022 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change_cancel(struct SCP_CONNECTION* c); -/* ... */ enum SCP_CLIENT_STATES_E scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, struct SCP_DISCONNECTED_SESSION** s); -/* 041 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session(struct SCP_CONNECTION* c, SCP_SID sid); -/* 042 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session_cancel(struct SCP_CONNECTION* c); +/* 041 */ +enum SCP_CLIENT_STATES_E +scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, struct SCP_DISCONNECTED_SESSION** s) +{ +  uint32_t version=1; +  uint32_t size=12; +  uint16_t cmd=41; +  uint32_t sescnt=0;     /* total session number */ +  uint32_t sestmp=0;     /* additional total session number */ +  uint8_t pktcnt=0;     /* packet session count */ +  uint32_t totalcnt=0;   /* session counter */ +  uint8_t continued=0;  /* continue flag */ +  int firstpkt=1;        /* "first packet" flag */ +  int idx; +  struct SCP_DISCONNECTED_SESSION* ds=0; + +  init_stream(c->out_s, c->out_s->size); + +  /* we request session list */ +  out_uint32_be(c->out_s, version);                 /* version */ +  out_uint32_be(c->out_s, size);                    /* size    */ +  out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset  */ +  out_uint16_be(c->out_s, cmd);                     /* cmd     */ + +  if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) +  { +    return SCP_CLIENT_STATE_NETWORK_ERR; +  } + +  do +  { +    /* then we wait for server response */ +    init_stream(c->in_s, c->in_s->size); +    if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8)) +    { +      return SCP_CLIENT_STATE_NETWORK_ERR; +    } + +    in_uint32_be(c->in_s, version); +    if (version!=1) +    { +      return SCP_CLIENT_STATE_VERSION_ERR; +    } + +    in_uint32_be(c->in_s, size); +    if (size<12) +    { +      return SCP_CLIENT_STATE_SIZE_ERR; +    } + +    init_stream(c->in_s, c->in_s->size); +    if (0!=tcp_force_recv(c->in_sck, c->in_s->data, size-8)) +    { +      return SCP_CLIENT_STATE_NETWORK_ERR; +    } + +    in_uint16_be(c->in_s, cmd); +    if (cmd!=SCP_COMMAND_SET_DEFAULT) +    { +      return SCP_CLIENT_STATE_SEQUENCE_ERR; +    } + +    in_uint16_be(c->in_s, cmd); +    if (cmd!=42) +    { +      return SCP_CLIENT_STATE_SEQUENCE_ERR; +    } + +    if (firstpkt) +    { +      firstpkt = 0; +      in_uint32_be(c->in_s, sescnt); +      sestmp = sescnt; + +      ds = g_malloc(sizeof(struct SCP_DISCONNECTED_SESSION)*sescnt, 0); +      if (ds == 0) +      { +        return SCP_CLIENT_STATE_INTERNAL_ERR; +      } +    } +    else +    { +      in_uint32_be(c->in_s, sestmp); +    } +    in_uint8(c->in_s, continued); +    in_uint8(c->in_s, pktcnt); + +    for (idx=0; idx<pktcnt; idx++) +    { +      in_uint32_be(c->in_s, (ds[totalcnt]).SID); /* session id */ +      in_uint8(c->in_s, (ds[totalcnt]).type); +      in_uint16_be(c->in_s, (ds[totalcnt]).height); +      in_uint16_be(c->in_s, (ds[totalcnt]).width); +      in_uint8(c->in_s, (ds[totalcnt]).bpp); +      in_uint8(c->in_s, (ds[totalcnt]).idle_days); +      in_uint8(c->in_s, (ds[totalcnt]).idle_hours); +      in_uint8(c->in_s, (ds[totalcnt]).idle_minutes); +      totalcnt++; +    } +  } +  while (continued); + +  printf("fine\n"); +  /* return data... */ +  (*scount) = sescnt; +  (*s) = ds; + +  return SCP_CLIENT_STATE_LIST_OK; +} + +/* 043 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s, SCP_SID sid) +{ +  uint32_t version = 1; +  uint32_t size = 16; +  uint16_t cmd = 43; + +  init_stream(c->out_s, c->out_s->size); + +  /* sending our selection */ +  out_uint32_be(c->out_s, version);                 /* version */ +  out_uint32_be(c->out_s, size);                    /* size    */ +  out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset  */ +  out_uint16_be(c->out_s, cmd);                     /* cmd     */ + +  out_uint32_be(c->out_s, sid); + +  if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) +  { +    return SCP_CLIENT_STATE_NETWORK_ERR; +  } + +  /* waiting for response.... */ +  init_stream(c->in_s, c->in_s->size); +  if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8)) +  { +    return SCP_CLIENT_STATE_NETWORK_ERR; +  } + +  in_uint32_be(c->in_s, version); +  if (version!=1) +  { +    return SCP_CLIENT_STATE_VERSION_ERR; +  } + +  in_uint32_be(c->in_s, size); +  if (size<12) +  { +    return SCP_CLIENT_STATE_SIZE_ERR; +  } -/* 03x */ enum SCP_CLIENT_STATES_E scp_v1c_retrieve_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s, struct SCP_DISCONNECTED_SESSION* ds); +  init_stream(c->in_s, c->in_s->size); +  /* read the rest of the packet */ +  if (0!=tcp_force_recv(c->in_sck, c->in_s->data, size-8)) +  { +    return SCP_CLIENT_STATE_NETWORK_ERR; +  } + +  in_uint16_be(c->in_s, cmd); +  if (cmd != SCP_COMMAND_SET_DEFAULT) +  { +    return SCP_CLIENT_STATE_SEQUENCE_ERR; +  } + +  in_uint16_be(c->in_s, cmd); +  if (cmd != 46) +  { +    return SCP_CLIENT_STATE_SEQUENCE_ERR; +  } + +  /* session display */ +  in_uint16_be(c->in_s, (s->display)); +  /*we don't need to return any data other than the display */ +  /*because we already sent that                            */ + +  return SCP_CLIENT_STATE_OK; +} + +/* 044 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session_cancel(struct SCP_CONNECTION* c) +{ +  uint32_t version = 1; +  uint32_t size = 12; +  uint16_t cmd = 44; + +  init_stream(c->out_s, c->out_s->size); + +  /* sending our selection */ +  out_uint32_be(c->out_s, version);                 /* version */ +  out_uint32_be(c->out_s, size);                    /* size    */ +  out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset  */ +  out_uint16_be(c->out_s, cmd);                     /* cmd     */ + +  if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) +  { +    return SCP_CLIENT_STATE_NETWORK_ERR; +  } + +  return SCP_CLIENT_STATE_END; +}  static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s)  { @@ -156,7 +356,7 @@ static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c    {      return SCP_CLIENT_STATE_NETWORK_ERR;    } -	 +    in_uint32_be(c->in_s, version);    if (version!=1)    { @@ -166,7 +366,7 @@ static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c    in_uint32_be(c->in_s, size);    init_stream(c->in_s, c->in_s->size); -  /* read the rest of the packet */  +  /* read the rest of the packet */    if (0!=tcp_force_recv(c->in_sck, c->in_s->data, size-8))    {      return SCP_CLIENT_STATE_NETWORK_ERR; @@ -236,10 +436,14 @@ static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c      return SCP_CLIENT_STATE_OK;    } -  else if (cmd==32) /* display of a disconnected session */ -  { -    return SCP_CLIENT_STATE_RECONNECT; -  } +  //else if (cmd==31) /* there's a disconnected session */ +  //{ +  //  return SCP_CLIENT_STATE_RECONNECT_SINGLE; +  //} +  //else if (cmd==33) /* display of a disconnected session */ +  //{ +  //  return SCP_CLIENT_STATE_RECONNECT; +  //}    else if (cmd==40) /* session list */    {      return SCP_CLIENT_STATE_SESSION_LIST; diff --git a/sesman/libscp_v1c.h b/sesman/libscp_v1c.h index 66464f45..c8be8445 100644 --- a/sesman/libscp_v1c.h +++ b/sesman/libscp_v1c.h @@ -18,11 +18,11 @@  */  /** - *  + *   * @file libscp_v1c.h   * @brief libscp version 1 client api declarations   * @author Simone Fedele - *  + *   */  #ifndef LIBSCP_V1C_H @@ -31,14 +31,34 @@  #include "libscp_types.h"  /* client API */ -/* 001 */ enum SCP_CLIENT_STATES_E scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s); -/* 004 */ enum SCP_CLIENT_STATES_E scp_v1c_resend_credentials(struct SCP_CONNECTION* c, struct SCP_SESSION* s); +/* 001 */ +enum SCP_CLIENT_STATES_E +scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s); -/* 021 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change(struct SCP_CONNECTION* c, char* newpass); -/* 022 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change_cancel(struct SCP_CONNECTION* c); +/* 004 */ +enum SCP_CLIENT_STATES_E +scp_v1c_resend_credentials(struct SCP_CONNECTION* c, struct SCP_SESSION* s); -/* ... */ enum SCP_CLIENT_STATES_E scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, struct SCP_DISCONNECTED_SESSION** s); -/* 041 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session(struct SCP_CONNECTION* c, SCP_SID sid); -/* 042 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session_cancel(struct SCP_CONNECTION* c); +/* 021 */ +enum SCP_CLIENT_STATES_E +scp_v1c_pwd_change(struct SCP_CONNECTION* c, char* newpass); + +/* 022 */ +enum SCP_CLIENT_STATES_E +scp_v1c_pwd_change_cancel(struct SCP_CONNECTION* c); + +/* 041 */ +enum SCP_CLIENT_STATES_E +scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, +                         struct SCP_DISCONNECTED_SESSION** s); + +/* 043 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s, +                       SCP_SID sid); + +/* 044 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session_cancel(struct SCP_CONNECTION* c);  #endif diff --git a/sesman/libscp_v1s.c b/sesman/libscp_v1s.c index 37932198..9a3e2df6 100644 --- a/sesman/libscp_v1s.c +++ b/sesman/libscp_v1s.c @@ -18,11 +18,11 @@  */  /** - *  + *   * @file libscp_v1s.c   * @brief libscp version 1 server api code   * @author Simone Fedele - *  + *   */  #ifndef LIBSCP_V1S_C @@ -39,7 +39,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES    uint16_t cmdset;    uint16_t cmd;    unsigned char sz; -   +    if (!skipVchk)    { @@ -60,14 +60,13 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES    {      version=1;    } -   +    in_uint32_be(c->in_s, size); -  LOG_DBG("size: %d",size); -  if (size<12)  +  if (size<12)    {      return SCP_SERVER_STATE_SIZE_ERR;    } -   +    init_stream(c->in_s, c->in_s->size);    if (0!=tcp_force_recv(c->in_sck, c->in_s->data, (size-8)))    { @@ -76,14 +75,13 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES    /* reading command set */    in_uint16_be(c->in_s, cmdset); -  LOG_DBG("command set: %d",cmdset); -   +    /* if we are starting a management session */    if (cmdset==SCP_COMMAND_SET_MANAGE)    {      return SCP_SERVER_STATE_START_MANAGE;    } -   +    /* if we started with resource sharing... */    if (cmdset==SCP_COMMAND_SET_RSR)    { @@ -92,7 +90,6 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES    /* reading command */    in_uint16_be(c->in_s, cmd); -  LOG_DBG("command: %d",cmd);    if (cmd != 1)    {      return SCP_SERVER_STATE_SEQUENCE_ERR; @@ -117,10 +114,8 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES    in_uint8(c->in_s, session->bpp);    in_uint8(c->in_s, session->rsr);    in_uint8a(c->in_s, session->locale, 17); -            session->locale[17]='\0'; +    session->locale[17]='\0'; -  LOG_DBG("locale: %s\n", session->locale); -     in_uint8(c->in_s, session->addr_type);    if (session->addr_type==SCP_ADDRESS_TYPE_IPV4)    { @@ -131,11 +126,8 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES      #warning how to handle ipv6 addresses?    } -  LOG_DBG("rest: %d\n",(unsigned char)*((c->in_s->p)+2)); -   -  /* reading hostname */  +  /* reading hostname */    in_uint8(c->in_s, sz); -  LOG_DBG("size read: %d", sz);    session->hostname=g_malloc(sz+1,1);    if (0==session->hostname)    { @@ -156,43 +148,40 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES    }    session->username[sz]='\0';    in_uint8a(c->in_s, session->username, sz); -   +    /* reading password */    in_uint8(c->in_s, sz); -  LOG_DBG("size read: %d", sz);    session->password=g_malloc(sz+1,1); -  if (0==session->password)  +  if (0==session->password)    {      g_free(session->username);      g_free(session->hostname); -    g_free(session);     +    g_free(session);      return SCP_SERVER_STATE_INTERNAL_ERR;    }    session->password[sz]='\0';    in_uint8a(c->in_s, session->password, sz); -  LOG_DBG("password: %s - size: %d - pointer: %x", session->password, sz, session->password); -      /* returning the struct */    (*s)=session; -   +    return SCP_SERVER_STATE_OK;  } -enum SCP_SERVER_STATES_E  +enum SCP_SERVER_STATES_E  scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason)  {    int rlen; -  +    init_stream(c->out_s,c->out_s->size); -   +    /* forcing message not to exceed 64k */    rlen = g_strlen(reason);    if (rlen > 65535)    {      rlen = 65535;    } -   +    out_uint32_be(c->out_s, 1);    /* packet size: 4 + 4 + 2 + 2 + 2 + strlen(reason)*/    /* version + size + cmdset + cmd + msglen + msg */ @@ -210,7 +199,7 @@ scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason)    return SCP_SERVER_STATE_END;  } -enum SCP_SERVER_STATES_E  +enum SCP_SERVER_STATES_E  scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* reason)  {    unsigned char sz; @@ -231,7 +220,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*    {      rlen = 65535;    } -   +    /* send password request */    version=1;    size=12; @@ -250,24 +239,22 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*    {      return SCP_SERVER_STATE_NETWORK_ERR;    } -   +    /* receive password & username */    if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8))    {      return SCP_SERVER_STATE_NETWORK_ERR;    } -   +    in_uint32_be(c->in_s, version); -  if (version!=1)  +  if (version!=1)    { -    LOG_DBG("version: %d",version);      return SCP_SERVER_STATE_VERSION_ERR;    }    in_uint32_be(c->in_s, size); -  if (size<12)  +  if (size<12)    { -    LOG_DBG("size: %d",size);      return SCP_SERVER_STATE_SIZE_ERR;    } @@ -277,9 +264,17 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*      return SCP_SERVER_STATE_NETWORK_ERR;    } -#warning check cmd seq    in_uint16_be(c->in_s, cmdset); +  if (cmdset != SCP_COMMAND_SET_DEFAULT) +  { +    return SCP_SERVER_STATE_SEQUENCE_ERR; +  } +    in_uint16_be(c->in_s, cmd); +  if (cmd != 4) +  { +    return SCP_SERVER_STATE_SEQUENCE_ERR; +  }    /* reading username */    in_uint8(c->in_s, sz); @@ -290,7 +285,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*    }    ubuf[sz]='\0';    in_uint8a(c->in_s, ubuf, sz); -   +    /* reading password */    in_uint8(c->in_s, sz);    pbuf=g_malloc(sz+1,1); @@ -311,22 +306,22 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*    return SCP_SERVER_STATE_OK;  } -/* 020 */  -enum SCP_SERVER_STATES_E  +/* 020 */ +enum SCP_SERVER_STATES_E  scp_v1s_request_pwd_change(struct SCP_CONNECTION* c, char* reason, char* npw)  {    return SCP_SERVER_STATE_INTERNAL_ERR;  } -/* 023 */  -enum SCP_SERVER_STATES_E  +/* 023 */ +enum SCP_SERVER_STATES_E  scp_v1s_pwd_change_error(struct SCP_CONNECTION* c, char* error, int retry, char* npw)  {    return SCP_SERVER_STATE_INTERNAL_ERR;  } -/* 030 */  -enum SCP_SERVER_STATES_E  +/* 030 */ +enum SCP_SERVER_STATES_E  scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d)  {    /* send password request */ @@ -346,22 +341,33 @@ scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d)    if (0!=tcp_force_send(c->in_sck, c->out_s->data, 14))    {      return SCP_SERVER_STATE_NETWORK_ERR; -  }	 -   +  } +    return SCP_SERVER_STATE_OK;  } -/* 031 */  -enum SCP_SERVER_STATES_E  -scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESSION* ds, -                          SCP_DISPLAY d) +/* 032 */ +enum SCP_SERVER_STATES_E +scp_v1s_connection_error(struct SCP_CONNECTION* c, char* error) +{ +  return SCP_SERVER_STATE_INTERNAL_ERR; +  return SCP_SERVER_STATE_END; +} + +/* 040 */ +enum SCP_SERVER_STATES_E +scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid)  {    uint32_t version=1;    uint32_t size=12; -  uint16_t cmd=32; -#warning FIXME check this command code - -  /* first we send a notice that we're reconnecting to an existing session */ +  uint16_t cmd=40; +  int pktcnt; +  int idx; +  int sidx; +  int pidx; +  struct SCP_DISCONNECTED_SESSION* cds; + +  /* first we send a notice that we have some disconnected sessions */    init_stream(c->out_s, c->out_s->size);    out_uint32_be(c->out_s, version);                 /* version */ @@ -369,27 +375,28 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESS    out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset  */    out_uint16_be(c->out_s, cmd);                     /* cmd     */ -  if (0!=tcp_force_send(c->in_sck, c->out_s->data, 14)) +  if (0!=tcp_force_send(c->in_sck, c->out_s->data, size))    {      return SCP_SERVER_STATE_NETWORK_ERR; -  }	 +  }    /* then we wait for client ack */ -#warning maybe this message could say if the session should be resized on  +#warning maybe this message could say if the session should be resized on  #warning server side or client side +  init_stream(c->in_s, c->in_s->size);    if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8))    {      return SCP_SERVER_STATE_NETWORK_ERR;    } -   +    in_uint32_be(c->in_s, version); -  if (version!=1)  +  if (version!=1)    {      return SCP_SERVER_STATE_VERSION_ERR;    }    in_uint32_be(c->in_s, size); -  if (size<12)  +  if (size<12)    {      return SCP_SERVER_STATE_SIZE_ERR;    } @@ -407,58 +414,186 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESS    }    in_uint16_be(c->in_s, cmd); -#warning FIXME check this command code -  if (cmd != 33) +  if (cmd != 41)    {      return SCP_SERVER_STATE_SEQUENCE_ERR;    } +  /* calculating the number of packets to send */ +  pktcnt=sescnt/SCP_SERVER_MAX_LIST_SIZE; +  if ((sescnt%SCP_SERVER_MAX_LIST_SIZE)!=0) +  { +    pktcnt++; +  } + +  for (idx=0; idx<pktcnt; idx++) +  { +    /* ok, we send session session list */ +    init_stream(c->out_s, c->out_s->size); + +    /* size: ver+size+cmdset+cmd+sescnt+continue+count */ +    size=4+4+2+2+4+1+1; + +    /* header */ +    cmd=42; +    s_push_layer(c->out_s, channel_hdr, 8); +    out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); +    out_uint16_be(c->out_s, cmd); + +    /* session count */ +    out_uint32_be(c->out_s, sescnt); + +    /* setting the continue flag */ +    if ((idx+1)*SCP_SERVER_MAX_LIST_SIZE >= sescnt) +    { +      out_uint8(c->out_s, 0); +      /* setting session count for this packet */ +      pidx=sescnt-(idx*SCP_SERVER_MAX_LIST_SIZE); +      out_uint8(c->out_s, pidx); +    } +    else +    { +      out_uint8(c->out_s, 1); +      /* setting session count for this packet */ +      pidx=SCP_SERVER_MAX_LIST_SIZE; +      out_uint8(c->out_s, pidx); +    } + +    /* adding session descriptors */ +    for (sidx=0; sidx<pidx; sidx++) +    { +      /* shortcut to the current session to send */ +      cds=ds+((idx)*SCP_SERVER_MAX_LIST_SIZE)+sidx; + +      /* session data */ +      out_uint32_be(c->out_s, cds->SID); /* session id */ +      out_uint8(c->out_s, cds->type); +      out_uint16_be(c->out_s, cds->height); +      out_uint16_be(c->out_s, cds->width); +      out_uint8(c->out_s, cds->bpp); +      out_uint8(c->out_s, cds->idle_days); +      out_uint8(c->out_s, cds->idle_hours); +      out_uint8(c->out_s, cds->idle_minutes); + +      size = size + 13; +    } + +    s_pop_layer(c->out_s, channel_hdr); +    out_uint32_be(c->out_s, version); +    out_uint32_be(c->out_s, size); + +    if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) +    { +      return SCP_SERVER_STATE_NETWORK_ERR; +    } +  } + +  /* we get the response */ +  init_stream(c->in_s, c->in_s->size); +  if (0!=tcp_force_recv(c->in_sck, c->in_s->data, (8))) +  { +    return SCP_SERVER_STATE_NETWORK_ERR; +  } + +  in_uint32_be(c->in_s, version); +  if (version!=1) +  { +    return SCP_SERVER_STATE_VERSION_ERR; +  } + +  in_uint32_be(c->in_s, size); +  if (size<12) +  { +    return SCP_SERVER_STATE_SIZE_ERR; +  } + +  /* rest of the packet */ +  init_stream(c->in_s, c->in_s->size); +  if (0!=tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) +  { +    return SCP_SERVER_STATE_NETWORK_ERR; +  } + +  in_uint16_be(c->in_s, cmd); +  if (cmd != SCP_COMMAND_SET_DEFAULT) +  { +    return SCP_SERVER_STATE_SEQUENCE_ERR; +  } + +  in_uint16_be(c->in_s, cmd); +  if (cmd == 43) +  { +    /* select session */ +    in_uint32_be(c->in_s, (*sid)); + +    /* checking sid value */ +    for (idx=0; idx<sescnt; idx++) +    { +      /* the sid is valid */ +      if (ds[idx].SID==(*sid)) +      { +        /* ok, session selected */ +        return SCP_SERVER_STATE_OK; +      } +    } + +    /* if we got here, the requested sid wasn't one from the list we sent */ +    /* we should kill the connection                                      */ +    return SCP_CLIENT_STATE_INTERNAL_ERR; +  } +  else if (cmd == 44) +  { +    /* cancel connection */ +    return SCP_SERVER_STATE_SELECTION_CANCEL; +  } +//  else if (cmd == 45) +//  { +//    /* force new connection */ +//    return SCP_SERVER_STATE_FORCE_NEW; +//  } +  else +  { +    /* wrong response */ +    return SCP_SERVER_STATE_SEQUENCE_ERR; +  } + +  return SCP_SERVER_STATE_OK; +} + +/* 046 was: 031 struct SCP_DISCONNECTED_SESSION* ds, */ +enum SCP_SERVER_STATES_E +scp_v1s_reconnect_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) +{ +  uint32_t version = 1; +  uint32_t size = 14; +  uint16_t cmd = 46; +    /* ok, we send session data and display */    init_stream(c->out_s, c->out_s->size); -  /* size */ -  size=4+4+2+2+ \ -       2+1+2+2+1+1+1+1; -      /* header */ -  cmd=31;    out_uint32_be(c->out_s, version);    out_uint32_be(c->out_s, size);    out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT);    out_uint16_be(c->out_s, cmd); -   +    /* session data */    out_uint16_be(c->out_s, d); /* session display */ -  out_uint8(c->out_s, ds->type); +  /*out_uint8(c->out_s, ds->type);    out_uint16_be(c->out_s, ds->height);    out_uint16_be(c->out_s, ds->width);    out_uint8(c->out_s, ds->bpp);    out_uint8(c->out_s, ds->idle_days);    out_uint8(c->out_s, ds->idle_hours); -  out_uint8(c->out_s, ds->idle_minutes); +  out_uint8(c->out_s, ds->idle_minutes);*/    /* these last three are not really needed... */ -   +    if (0!=tcp_force_send(c->in_sck, c->out_s->data, size))    {      return SCP_SERVER_STATE_NETWORK_ERR; -  }	 -   -  return SCP_SERVER_STATE_OK; -} - -/* 032 */  -enum SCP_SERVER_STATES_E  -scp_v1s_connection_error(struct SCP_CONNECTION* c, char* error) -{ -  return SCP_SERVER_STATE_INTERNAL_ERR; -  return SCP_SERVER_STATE_END; -} +  } -/* 040 */  -enum SCP_SERVER_STATES_E  -scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid) -{ -  return SCP_SERVER_STATE_INTERNAL_ERR; +  return SCP_SERVER_STATE_OK;  }  #endif diff --git a/sesman/libscp_v1s.h b/sesman/libscp_v1s.h index 34650920..6ea12fd8 100644 --- a/sesman/libscp_v1s.h +++ b/sesman/libscp_v1s.h @@ -18,11 +18,11 @@  */  /** - *  + *   * @file libscp_v1s.h   * @brief libscp version 1 server api declarations   * @author Simone Fedele - *  + *   */  #ifndef LIBSCP_V1S_H @@ -36,52 +36,52 @@   * @brief processes the stream using scp version 1   * @param c connection descriptor   * @param s pointer to session descriptor pointer - * @param skipVchk if set to !0 skips the version control (to be used after  + * @param skipVchk if set to !0 skips the version control (to be used after   *                 scp_vXs_accept() )   *   * this function places in *s the address of a newely allocated SCP_SESSION structure   * that should be free()d   */ -enum SCP_SERVER_STATES_E  -scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk);           +enum SCP_SERVER_STATES_E +scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk);  /**   *   * @brief denies connection to sesman   * @param c connection descriptor   * @param reason pointer to a string containinge the reason for denying connection + *   */ -/* 002 */  -enum SCP_SERVER_STATES_E  +/* 002 */ +enum SCP_SERVER_STATES_E  scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason); -enum SCP_SERVER_STATES_E  +enum SCP_SERVER_STATES_E  scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* reason); -	 -/* 020 */  -enum SCP_SERVER_STATES_E  + +/* 020 */ +enum SCP_SERVER_STATES_E  scp_v1s_request_pwd_change(struct SCP_CONNECTION* c, char* reason, char* npw); -/* 023 */  -enum SCP_SERVER_STATES_E  +/* 023 */ +enum SCP_SERVER_STATES_E  scp_v1s_pwd_change_error(struct SCP_CONNECTION* c, char* error, int retry, char* npw); -/* 030 */  -enum SCP_SERVER_STATES_E  +/* 030 */ +enum SCP_SERVER_STATES_E  scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d); -/* 031 */  -enum SCP_SERVER_STATES_E  -scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESSION* ds,  -		          SCP_DISPLAY d); - -/* 032 */  -enum SCP_SERVER_STATES_E  +/* 032 */ +enum SCP_SERVER_STATES_E  scp_v1s_connection_error(struct SCP_CONNECTION* c, char* error); -/* 040 */  -enum SCP_SERVER_STATES_E  -scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, -                      SCP_SID* sid); +/* 040 */ +enum SCP_SERVER_STATES_E +scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, +                      struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid); + +/* 046 was: 031 struct SCP_DISCONNECTED_SESSION* ds, */ +enum SCP_SERVER_STATES_E +scp_v1s_reconnect_session(struct SCP_CONNECTION* c, SCP_DISPLAY d);  #endif diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c index d2018da5..ed6dcde4 100644 --- a/sesman/scp_v1.c +++ b/sesman/scp_v1.c @@ -22,7 +22,7 @@   * @file scp_v1.c   * @brief scp version 1 implementation   * @author Jay Sorg, Simone Fedele - *  + *   */  #include "sesman.h" @@ -32,6 +32,8 @@  extern struct config_sesman g_cfg; +static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f); +  /******************************************************************************/  void DEFAULT_CC  scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) @@ -50,50 +52,31 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)    current_try = retries;    data = auth_userpass(s->username, s->password); -  LOG_DBG("user: %s\npass: %s", s->username, s->password); +  /*LOG_DBG("user: %s\npass: %s", s->username, s->password);*/    while ((!data) && ((retries == 0) || (current_try > 0)))    { -    LOG_DBG("data %d - retry %d - currenttry %d - expr %d", data, retries, -            current_try, ((!data) && ((retries == 0) || (current_try > 0)))); +    LOG_DBG("data %d - retry %d - currenttry %d - expr %d", data, retries, current_try, ((!data) && ((retries==0) || (current_try>0)))); -    e = scp_v1s_request_password(c, s, "Wrong username and/or password"); +    e=scp_v1s_request_password(c,s,"Wrong username and/or password");      switch (e)      {        case SCP_SERVER_STATE_OK:          /* all ok, we got new username and password */          data = auth_userpass(s->username, s->password); -        /* one try less */  +        /* one try less */          if (current_try > 0)          {            current_try--;          }          break; -      case SCP_SERVER_STATE_VERSION_ERR: -        LOG_DBG("version error", 0) -      case SCP_SERVER_STATE_SIZE_ERR: -        /* an unknown scp version was requested, so we shut down the */  -        /* connection (and log the fact)                             */  -        log_message(LOG_LEVEL_WARNING, -          "protocol violation. connection closed."); -        return; -      case SCP_SERVER_STATE_NETWORK_ERR: -        log_message(LOG_LEVEL_WARNING, "libscp network error."); -        return; -      case SCP_SERVER_STATE_SEQUENCE_ERR: -        log_message(LOG_LEVEL_WARNING, "libscp sequence error."); -        return; -      case SCP_SERVER_STATE_INTERNAL_ERR: -        /* internal error occurred (eg. malloc() error, ecc.) */ -        log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); -        return;        default: -        /* dummy: scp_v1s_request_password won't generate any other */ -        /* error other than the ones before                         */ -        log_message(LOG_LEVEL_ALWAYS, -          "unknown return from scp_v1s_request_password()"); +        /* we check the other errors */ +        parseCommonStates(e, "scp_v1s_list_sessions()"); +        free_session(s);          return; +        //break;      }    } @@ -106,7 +89,7 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)      return;    } -  /* testing if login is allowed*/	 +  /* testing if login is allowed*/    if (0 == access_login_allowed(s->username))    {      scp_v1s_deny_connection(c, "Access to Terminal Server not allowed."); @@ -123,7 +106,6 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)    if (scount == 0)    { -#warning FIXME we should check for MaxSessions      /* no disconnected sessions - start a new one */      log_message(LOG_LEVEL_INFO, "granted TS access to user %s", s->username);      if (SCP_SESSION_TYPE_XVNC == s->type) @@ -145,42 +127,48 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)        case SCP_SERVER_STATE_OK:          /* all ok, we got new username and password */          break; -      case SCP_SERVER_STATE_NETWORK_ERR: -        log_message(LOG_LEVEL_WARNING, "libscp network error."); -        return;        default: -	return; +        /* we check the other errors */ +        parseCommonStates(e, "scp_v1s_connect_new_session()"); +        break;      }    } -  else if (scount == 1) +  else    { -    /* there's only one session - returning that */ -    sitem = session_get_bypid(slist->SID);  #warning FIXME session_get_by*() should return a malloc()ated struct  #warning FIXME or at least lock the chain -    if (0 == sitem) -    { -      e = scp_v1s_connection_error(c, "Internal error"); -      log_message(LOG_LEVEL_INFO, "Cannot find session item on the chain"); -    } -    else -    { -      display = sitem->display; -      e = scp_v1s_reconnect_session(c, slist, display); -      log_message(LOG_LEVEL_INFO, -                  "User %s reconnected to session %d on port %d", -                  s->username, sitem->pid, display); -    } -    g_free(slist); -  } -  else -  { -    /* 2 or more disconnected sessions - listing */ -    //max session x packet = 100 => pkt size = 1300 (13x100) +    /* one or more disconnected sessions - listing */      e = scp_v1s_list_sessions(c, scount, slist, &sid); -    //CHECK RETURN - +    switch (e) +    { +      /*case SCP_SERVER_STATE_FORCE_NEW:*/ +      /* we should check for MaxSessions */ +      case SCP_SERVER_STATE_SELECTION_CANCEL: +        log_message(LOG_LEVEL_INFO, "Connection cancelled after session listing"); +        break; +      case SCP_SERVER_STATE_OK: +        /* ok, reconnecting... */ +        sitem=session_get_bypid(sid); +        if (0==sitem) +        { +          e=scp_v1s_connection_error(c, "Internal error"); +          log_message(LOG_LEVEL_INFO, "Cannot find session item on the chain"); +        } +        else +        { +          display=sitem->display; +          /*e=scp_v1s_reconnect_session(c, sitem, display);*/ +          e=scp_v1s_reconnect_session(c, display); +          log_message(LOG_LEVEL_INFO, "User %s reconnected to session %d on port %d", \ +                      s->username, sitem->pid, display); +        } +        break; +      default: +        /* we check the other errors */ +        parseCommonStates(e, "scp_v1s_list_sessions()"); +        break; +    }      g_free(slist);    } @@ -190,8 +178,37 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)      /* here goes scp resource sharing code */    } -  /* cleanup */  +  /* cleanup */    free_session(s); -  auth_end(data);  +  auth_end(data);  } +static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) +{ +  switch (e) +  { +    case SCP_SERVER_STATE_VERSION_ERR: +      LOG_DBG("version error", 0) +    case SCP_SERVER_STATE_SIZE_ERR: +      /* an unknown scp version was requested, so we shut down the */ +      /* connection (and log the fact)                             */ +      log_message(LOG_LEVEL_WARNING, +        "protocol violation. connection closed."); +      break; +    case SCP_SERVER_STATE_NETWORK_ERR: +      log_message(LOG_LEVEL_WARNING, "libscp network error."); +      break; +    case SCP_SERVER_STATE_SEQUENCE_ERR: +      log_message(LOG_LEVEL_WARNING, "libscp sequence error."); +      break; +    case SCP_SERVER_STATE_INTERNAL_ERR: +      /* internal error occurred (eg. malloc() error, ecc.) */ +      log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); +      break; +    default: +      /* dummy: scp_v1s_request_password won't generate any other */ +      /* error other than the ones before                         */ +      log_message(LOG_LEVEL_ALWAYS, "unknown return from %s", f); +      break; +  } +} diff --git a/sesman/tools/Makefile b/sesman/tools/Makefile index b4902ad5..51eda709 100644 --- a/sesman/tools/Makefile +++ b/sesman/tools/Makefile @@ -6,8 +6,9 @@ SESTESTOBJ = sestest.o tcp.o \  DEFINES = -DLIBSCP_CLIENT  CFLAGS = -Wall -O2 -I../../common -I../ -I/usr/include/nptl $(DEFINES) -LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES) -C_OS_FLAGS = $(CFLAGS) -c +#LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES)  +LDFLAGS = -L /usr/gnu/lib -ldl $(DEFINES)  +C_OS_FLAGS = $(CFLAGS) -c -g  CC = gcc  all: sestest  @@ -37,4 +38,4 @@ clean:  	rm $(SESTESTOBJ) sestest  install: -	#install:wq +	#install diff --git a/sesman/tools/sestest.c b/sesman/tools/sestest.c index 62629f3a..ae23f616 100644 --- a/sesman/tools/sestest.c +++ b/sesman/tools/sestest.c @@ -14,9 +14,14 @@ int main(int argc, char** argv)  {    struct SCP_SESSION s;    struct SCP_CONNECTION c; +  /*struct SCP_DISCONNECTED_SESSION ds;*/ +  struct SCP_DISCONNECTED_SESSION* dsl;    enum SCP_CLIENT_STATES_E e;    int end; -  +  int scnt; +  int idx; +  int sel; +    make_stream(c.in_s);    init_stream(c.in_s, 8192);    make_stream(c.out_s); @@ -28,7 +33,7 @@ int main(int argc, char** argv)      g_printf("error connecting");      return 1;    } -   +    g_printf("001 - send connect request\n");  /*struct SCP_SESSION @@ -36,7 +41,7 @@ int main(int argc, char** argv)    uint16_t display;    char* errstr;  };*/ -   +    s.type=SCP_SESSION_TYPE_XVNC;    s.version=1;    s.height=600; @@ -44,18 +49,18 @@ int main(int argc, char** argv)    s.bpp=8;    s.rsr=0;    g_strncpy(s.locale,"it_IT  0123456789",18); -   +    s.username=g_malloc(256, 1);    g_strncpy(s.username,"prog",255); -   +    s.password=g_malloc(256,1);    g_strncpy(s.password, "prog", 255);    g_printf("%s - %s\n", s.username, s.password); -   -   + +    s.hostname=g_malloc(256,1);    g_strncpy(s.hostname, "odin", 255); -   +    s.addr_type=SCP_ADDRESS_TYPE_IPV4;    s.ipv4addr=0;    s.errstr=0; @@ -68,34 +73,52 @@ int main(int argc, char** argv)      switch (e)      {        case SCP_CLIENT_STATE_OK: -        g_printf("OK : display is %d\n", (int)s.display); -	end=1; +        g_printf("OK : display is %d\n", (short int)s.display); +        end=1;          break;        case SCP_CLIENT_STATE_SESSION_LIST:          g_printf("OK : session list needed\n"); +        e=scp_v1c_get_session_list(&c, &scnt, &dsl); +        printf("Sessions: %d\n", scnt); +        for (idx=0; idx <scnt; idx++) +        { +          printf("Session \t%d - %d - %dx%dx%d - %d %d %d\n", (dsl[idx]).SID, (dsl[idx]).type, (dsl[idx]).height, (dsl[idx]).width, (dsl[idx]).bpp, (dsl[idx]).idle_days, (dsl[idx]).idle_hours, (dsl[idx]).idle_minutes); +        } +        break; +      case SCP_CLIENT_STATE_LIST_OK: +        g_printf("OK : selecting a session:\n"); +        sel = menuSelect(scnt); +        e=scp_v1c_select_session(&c, &s, dsl[sel-1].SID); +        g_printf("\n return: %d \n", e);          break;        case SCP_CLIENT_STATE_RESEND_CREDENTIALS:          g_printf("ERR: resend credentials - %s\n", s.errstr); -	g_printf("     username:"); -	scanf("%255s", s.username); -	g_printf("     password:"); -	scanf("%255s", s.password); -	e=scp_v1c_resend_credentials(&c,&s); +        g_printf("     username:"); +        scanf("%255s", s.username); +        g_printf("     password:"); +        scanf("%255s", s.password); +        e=scp_v1c_resend_credentials(&c,&s);          break;        case SCP_CLIENT_STATE_CONNECTION_DENIED:          g_printf("ERR: connection denied: %s\n", s.errstr); -	end=1; +        end=1;          break;        case SCP_CLIENT_STATE_PWD_CHANGE_REQ:          g_printf("OK : password change required\n"); -	break; +        break; +      /*case SCP_CLIENT_STATE_RECONNECT_SINGLE: +        g_printf("OK : reconnect to 1 disconnected session\n"); +        e=scp_v1c_retrieve_session(&c, &s, &ds); +        g_printf("Session Type: %d on %d\n", ds.type, s.display); +        g_printf("Session Screen: %dx%dx%d\n", ds.height, ds.width, ds.bpp);*/ +        break;        default:          g_printf("protocol error: %d\n", e); -	end=1; +        end=1;      }    } -  g_tcp_close(c.in_sck);   +  g_tcp_close(c.in_sck);    free_stream(c.in_s);    free_stream(c.out_s); @@ -105,14 +128,14 @@ int main(int argc, char** argv)  int inputSession(struct SCP_SESSION* s)  {    unsigned int integer; -   +    g_printf("username: ");    scanf("%255s", s->username);    g_printf("password:");    scanf("%255s", s->password);    g_printf("hostname:");    scanf("%255s", s->hostname); -   +    g_printf("session type:\n");    g_printf("0: Xvnc\n", SCP_SESSION_TYPE_XVNC);    g_printf("1: x11rdp\n", SCP_SESSION_TYPE_XRDP); @@ -125,7 +148,7 @@ int inputSession(struct SCP_SESSION* s)    {      s->type=SCP_SESSION_TYPE_XVNC;    } -   +    s->version=1;    s->height=600;    s->width=800; @@ -134,7 +157,7 @@ int inputSession(struct SCP_SESSION* s)    /* fixed for now */    s->rsr=0;    g_strncpy(s->locale,"it_IT  0123456789",18); -   +    return 0;  } @@ -142,9 +165,9 @@ unsigned int menuSelect(unsigned int choices)  {    unsigned int sel;    int ret; -   +    ret=scanf("%u", &sel); -	 +    while ((ret==0) || (sel > choices))    {      g_printf("invalid choice."); | 
