Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5606)
+++ ChangeLog	(revision 5608)
@@ -18,4 +18,5 @@
 	* Typo corrections (Closes: #282) (pr1)
 	* Updated common protocol interface (Closes: #257, #256) (pr1)
+	* Handle super long client names well (Closes: #286) (pr1)
 
 v. 1.0beta3 - Sun Jul 15 2012 26:08 CEST
Index: include/libroar/ctl.h
===================================================================
--- include/libroar/ctl.h	(revision 5381)
+++ include/libroar/ctl.h	(revision 5608)
@@ -82,4 +82,6 @@
 int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c);
 int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c);
+int roar_ctl_c2m2     (struct roar_message * m, struct roar_client * c, void ** data);
+int roar_ctl_m2c2     (struct roar_message * m, struct roar_client * c, void  * data);
 
 int    roar_str2proto (const char * proto) _LIBROAR_ATTR_USE_RESULT _LIBROAR_ATTR_PURE;
Index: libroar/basic.c
===================================================================
--- libroar/basic.c	(revision 5471)
+++ libroar/basic.c	(revision 5608)
@@ -510,5 +510,5 @@
   return -1;
 
- // specal hack to set an ilegal value used internaly in libroar:
+ // specal hack to set an illegal value used internaly in libroar:
  if ( fh == -2 )
   fh = -1;
@@ -516,4 +516,6 @@
  if ( roar_vio_open_fh_socket(con->viocon, fh) != -1 ) {
   con->flags |= ROAR_CON_FLAGS_VIO;
+ } else {
+  return -1;
  }
 
@@ -543,6 +545,8 @@
 
 struct roar_vio_calls * roar_get_connection_vio2 (struct roar_connection * con) {
- if ( con == NULL )
+ if ( con == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
   return NULL;
+ }
 
  if ( con->flags & ROAR_CON_FLAGS_VIO )
@@ -551,4 +555,5 @@
 // TODO: try to open the VIO.
 
+ roar_err_set(ROAR_ERROR_BADFH);
  return NULL;
 }
Index: libroar/ctl.c
===================================================================
--- libroar/ctl.c	(revision 5462)
+++ libroar/ctl.c	(revision 5608)
@@ -161,4 +161,6 @@
 int roar_get_client   (struct roar_connection * con, struct roar_client * client, int id) {
  struct roar_message m;
+ char * data = NULL;
+ int ret;
 
  memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
@@ -171,5 +173,5 @@
  ROAR_DBG("roar_get_client(*): id = %i", id);
 
- if ( roar_req(con, &m, NULL) == -1 )
+ if ( roar_req(con, &m, &data) == -1 )
   return -1;
 
@@ -179,5 +181,10 @@
  ROAR_DBG("roar_get_client(*): got ok");
 
- return roar_ctl_m2c(&m, client);
+ ret = roar_ctl_m2c2(&m, client, data);
+
+ if ( data != NULL )
+  roar_mm_free(data);
+
+ return ret;
 }
 
@@ -376,29 +383,58 @@
 }
 
-int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
- int cur = 0;
+int roar_ctl_c2m2     (struct roar_message * m, struct roar_client * c, void ** data) {
+ char * d;
+ size_t cur = 0;
  int h;
  int i;
  int max_len;
  uint32_t pid;
- signed long int len_rest;
  size_t nnode_len;
+ size_t needed_len = 3 + 5*4 + 18 /* 18 = current max size for blob */;
 
  if ( c == NULL )
   return -1;
 
- m->data[cur++] = 0;                       // 0: Version
- m->data[cur++] = c->execed;               // 1: execed
+ if ( data != NULL )
+  *data = NULL;
+
+ max_len = strlen(c->name);
+ needed_len += max_len;
+
+ for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
+  if ( c->streams[i] != -1 )
+   needed_len++;
+
+ if ( needed_len > sizeof(m->data) ) {
+  if ( data == NULL ) {
+   needed_len -= max_len;
+   if ( needed_len > sizeof(m->data) ) {
+    roar_panic(ROAR_FATAL_ERROR_CPU_FAILURE, "needed_len > sizeof(m->data) happend.");
+    roar_err_set(ROAR_ERROR_BADCKSUM);
+    return -1;
+   }
+   max_len = sizeof(m->data) - needed_len;
+   needed_len = sizeof(m->data);
+   d = m->data;
+  } else {
+   d = roar_mm_malloc(needed_len);
+   if ( d == NULL )
+    return -1;
+   *data = d;
+  }
+ } else {
+  d = m->data;
+ }
+
+ d[cur++] = 0;                       // 0: Version
+ d[cur++] = c->execed;               // 1: execed
 
  h = 0;
- for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
+ for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
   if ( c->streams[i] != -1 )
-   m->data[cur+1+h++] = c->streams[i];
- }
-
- m->data[cur++] = h;                       // 2: num of streams
+   d[cur+1+h++] = c->streams[i];
+
+ d[cur++] = h;                       // 2: num of streams
  cur += h;
-
- max_len = strlen(c->name);
 
  // TODO: add some code to check if this fits in the pkg
@@ -406,40 +442,43 @@
  //       and fully decieded about this function.
 
- m->data[cur++] = max_len;
-
- strncpy((m->data)+cur, c->name, max_len);
+ d[cur++] = max_len;
+
+ strncpy(d+cur, c->name, max_len);
 
  cur += max_len;
 
  pid = ROAR_HOST2NET32(c->pid);
- memcpy(&(m->data[cur]), &pid, 4);
+ memcpy(&(d[cur]), &pid, 4);
  cur += 4;
 
  pid = ROAR_HOST2NET32(c->uid);
- memcpy(&(m->data[cur]), &pid, 4);
+ memcpy(&(d[cur]), &pid, 4);
  cur += 4;
 
  pid = ROAR_HOST2NET32(c->gid);
- memcpy(&(m->data[cur]), &pid, 4);
+ memcpy(&(d[cur]), &pid, 4);
  cur += 4;
 
  pid = ROAR_HOST2NET32(c->proto);
- memcpy(&(m->data[cur]), &pid, 4);
+ memcpy(&(d[cur]), &pid, 4);
  cur += 4;
 
  pid = ROAR_HOST2NET32(c->byteorder);
- memcpy(&(m->data[cur]), &pid, 4);
+ memcpy(&(d[cur]), &pid, 4);
  cur += 4;
 
- len_rest = (long int)sizeof(m->data) - (long int)cur;
- if ( len_rest < 0 ) {
+ if ( cur > needed_len ) {
   roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
  }
 
- nnode_len = len_rest;
- if ( roar_nnode_to_blob(&(c->nnode), &(m->data[cur]), &nnode_len) == 0 ) {
+ nnode_len = needed_len - cur;
+ if ( roar_nnode_to_blob(&(c->nnode), &(d[cur]), &nnode_len) == 0 ) {
   cur += nnode_len;
  }
 
+ if ( cur > needed_len ) {
+  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
+ }
+
  m->datalen = cur;
 
@@ -447,5 +486,6 @@
 }
 
-int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
+int roar_ctl_m2c2      (struct roar_message * m, struct roar_client * c, void * data) {
+ char * d = data;
  uint32_t pid;
  size_t len;
@@ -463,7 +503,15 @@
  }
 
+ if ( d == NULL ) {
+  if ( m->datalen > sizeof(m->data) ) {
+   roar_err_set(ROAR_ERROR_FAULT);
+   return -1;
+  }
+  d = m->data;
+ }
+
  ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
 
- if ( m->data[0] != 0 ) {
+ if ( d[0] != 0 ) {
   ROAR_DBG("roar_ctl_m2c(*): wrong version!");
   roar_err_set(ROAR_ERROR_NSVERSION);
@@ -478,38 +526,39 @@
  ROAR_DBG("roar_ctl_m2c(*): have usable data!");
 
- c->execed = m->data[1];
+ c->execed = d[1];
 
  for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
   c->streams[i] = -1;
 
- if ( m->data[2] < 0 || m->data[2] > ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT ) {
+ if ( d[2] < 0 || d[2] > ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT ) {
   roar_err_set(ROAR_ERROR_TOOMANYARGS);
   return -1;
  }
 
- for (i = 0; i < m->data[2]; i++)
-  c->streams[i] = m->data[3+i];
-
- cur = 3 + m->data[2];
-
- strncpy(c->name, (m->data)+cur+1, m->data[cur]);
- c->name[(int)m->data[cur]] = 0;
-
- cur += m->data[cur] + 1;
-
- memcpy(&pid, &(m->data[cur]), 4);
+ for (i = 0; i < d[2]; i++)
+  c->streams[i] = d[3+i];
+
+ cur = 3 + d[2];
+
+ // check length here!
+ strncpy(c->name, d+cur+1, d[cur] > (sizeof(c->name)-1) ? sizeof(c->name)-1 : d[cur]);
+ c->name[(size_t)d[cur] > (sizeof(c->name)-1) ? sizeof(c->name)-1 : (size_t)d[cur]] = 0;
+
+ cur += d[cur] + 1;
+
+ memcpy(&pid, &(d[cur]), 4);
  c->pid = ROAR_NET2HOST32(pid);
  cur += 4;
 
- memcpy(&pid, &(m->data[cur]), 4);
+ memcpy(&pid, &(d[cur]), 4);
  c->uid = ROAR_NET2HOST32(pid);
  cur += 4;
 
- memcpy(&pid, &(m->data[cur]), 4);
+ memcpy(&pid, &(d[cur]), 4);
  c->gid = ROAR_NET2HOST32(pid);
  cur += 4;
 
  if ( m->datalen >= cur+4 ) {
-  memcpy(&pid, &(m->data[cur]), 4);
+  memcpy(&pid, &(d[cur]), 4);
   c->proto = ROAR_NET2HOST32(pid);
   cur += 4;
@@ -519,5 +568,5 @@
 
  if ( m->datalen >= cur+4 ) {
-  memcpy(&pid, &(m->data[cur]), 4);
+  memcpy(&pid, &(d[cur]), 4);
   c->byteorder = ROAR_NET2HOST32(pid);
   cur += 4;
@@ -528,5 +577,5 @@
  if ( m->datalen > cur ) {
   len = m->datalen - cur;
-  if ( roar_nnode_from_blob(&(c->nnode), &(m->data[cur]), &len) == 0 ) {
+  if ( roar_nnode_from_blob(&(c->nnode), &(d[cur]), &len) == 0 ) {
    cur += len;
   } else {
@@ -540,4 +589,11 @@
 
  return 0;
+}
+
+int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
+ return roar_ctl_c2m2(m, c, NULL);
+}
+int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
+ return roar_ctl_m2c2(m, c, NULL);
 }
 
Index: libroar/proto.c
===================================================================
--- libroar/proto.c	(revision 5467)
+++ libroar/proto.c	(revision 5608)
@@ -148,4 +148,24 @@
 }
 
+static inline int _libroar_msgresyncer(struct roar_vio_calls  * vio, size_t len) {
+ char buffer[2*LIBROAR_BUFFER_MSGDATA]; // this is always called with len > LIBROAR_BUFFER_MSGDATA.
+ ssize_t ret;
+ size_t errorc = 0;
+
+ while (len && errorc < 4) {
+  ret = roar_vio_read(vio, buffer, len > sizeof(buffer) ? sizeof(buffer) : len);
+  if ( ret == (size_t)-1 ) {
+   errorc++;
+  } else {
+   errorc = 0;
+   len -= ret;
+  }
+ }
+
+ if ( len )
+  return -1; // last error is still set.
+ return 0;
+}
+
 int roar_vrecv_message2(struct roar_vio_calls  * vio, struct roar_message * mes, char ** data,
                         struct roar_error_frame * errorframe) {
@@ -269,10 +289,18 @@
  } else {
   if ( data == NULL ) {
-   roar_err_set(ROAR_ERROR_MSGSIZE);
+   if ( _libroar_msgresyncer(vio, mes->datalen) == -1 ) {
+    roar_err_set(ROAR_ERROR_BADCKSUM);
+   } else {
+    roar_err_set(ROAR_ERROR_MSGSIZE);
+   }
    return -1;
   }
 
   if ( (*data = roar_mm_malloc(mes->datalen)) == NULL ) {
-   roar_err_set(ROAR_ERROR_NOMEM);
+   if ( _libroar_msgresyncer(vio, mes->datalen) == -1 ) {
+    roar_err_set(ROAR_ERROR_BADCKSUM);
+   } else {
+    roar_err_set(ROAR_ERROR_NOMEM);
+   }
    return -1;
   }
Index: roard/clients.c
===================================================================
--- roard/clients.c	(revision 5607)
+++ roard/clients.c	(revision 5608)
@@ -758,5 +758,7 @@
   return -1;
 
- roar_connect_fh(&con, ROAR_CLIENT(cs)->fh);
+ if ( roar_connect_fh(&con, ROAR_CLIENT(cs)->fh) == -1 ) {
+  ROAR_WARN("clients_check(id=%i): Can not create con object for client: %s", id, roar_errorstring);
+ }
 
  ROAR_DBG("clients_check(id=%i): c->proto=%i", id, ROAR_CLIENT(cs)->proto);
@@ -802,9 +804,14 @@
     } else {
      roar_notify_core_emit_simple(event, id, -1, -1, m.cmd, -1, NULL, 0);
-     roar_send_message(&con, &m, flags[1] & COMMAND_FLAG_OUT_LONGDATA ? data : NULL);
+     if ( roar_send_message(&con, &m, flags[1] & COMMAND_FLAG_OUT_LONGDATA ? data : NULL) == -1 ) {
+      ROAR_WARN("clients_check(id=%i): Can not send answer to client: %s", id, roar_errorstring);
+     }
     }
 
     if ( flags[1] & COMMAND_FLAG_OUT_CLOSECON )
      clients_close(id, 1);
+
+    if ( flags[1] & COMMAND_FLAG_OUT_DELETE )
+     clients_delete(id);
 
    break;
Index: roard/commands.c
===================================================================
--- roard/commands.c	(revision 5381)
+++ roard/commands.c	(revision 5608)
@@ -48,5 +48,5 @@
 
   {ROAR_CMD_EXEC_STREAM,  _NAME("EXEC_STREAM"),  req_on_exec_stream,  ACCLEV_PWRUSER},
-  {ROAR_CMD_QUIT,         _NAME("QUIT"),         (int(*)(int client, struct roar_message * mes, char ** data, uint32_t flags[2]))clients_delete, ACCLEV_NONE},
+  {ROAR_CMD_QUIT,         _NAME("QUIT"),         req_on_quit, ACCLEV_NONE},
 
   {ROAR_CMD_CON_STREAM,   _NAME("CON_STREAM"),   req_on_con_stream,   ACCLEV_PWRUSER},
Index: roard/include/commands.h
===================================================================
--- roard/include/commands.h	(revision 5381)
+++ roard/include/commands.h	(revision 5608)
@@ -36,4 +36,5 @@
 #define COMMAND_FLAG_OUT_LONGDATA  0x00000002
 #define COMMAND_FLAG_OUT_NOSEND    0x00000004
+#define COMMAND_FLAG_OUT_DELETE    0x00000008 /* delete the client */
 
 struct roar_command {
Index: roard/include/req.h
===================================================================
--- roard/include/req.h	(revision 5381)
+++ roard/include/req.h	(revision 5608)
@@ -30,4 +30,5 @@
 
 int req_on_noop        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]);
+int req_on_quit        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]);
 
 int req_on_identify    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]);
Index: roard/req.c
===================================================================
--- roard/req.c	(revision 5586)
+++ roard/req.c	(revision 5608)
@@ -81,4 +81,13 @@
 }
 
+int req_on_quit        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
+ (void)client, (void)data;
+ mes->cmd     = ROAR_CMD_OK;
+ mes->pos     = g_pos;
+ mes->datalen = 0;
+ flags[1] |= COMMAND_FLAG_OUT_DELETE;
+ return 0;
+}
+
 int req_on_identify    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
  struct roar_client_server * cs;
@@ -1067,8 +1076,13 @@
 int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
  struct roar_client * c;
+ int ret;
 
  if ( mes->datalen != 1 )
   return -1;
 
+ if ( *data != NULL )
+  roar_mm_free(*data);
+ *data = NULL;
+
  if ( clients_get(mes->data[0], &c) == -1 )
   return -1;
@@ -1076,5 +1090,10 @@
  mes->cmd = ROAR_CMD_OK;
 
- return roar_ctl_c2m(mes, c);
+ ret = roar_ctl_c2m2(mes, c, data);
+
+ if ( *data != NULL )
+  flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
+
+ return ret;
 }
 
