Index: ChangeLog
===================================================================
--- ChangeLog	(revision 4625)
+++ ChangeLog	(revision 4626)
@@ -1,5 +1,5 @@
 v. 0.4beta2 - ?
 	* Announce standards via OpenSLP (Closes: #5)
-	* Updated VS API (Closes: #54, #3)
+	* Updated VS API (Closes: #54, #3, #2)
 	* Added support for CRC24 (RFC 4880)
 	* Added Base64 support.
Index: include/libroar/vs.h
===================================================================
--- include/libroar/vs.h	(revision 4622)
+++ include/libroar/vs.h	(revision 4626)
@@ -82,4 +82,7 @@
  */
 roar_vs_t * roar_vs_new_from_file(const char * server, const char * name, char * filename, int * error);
+
+int roar_vs_buffer(roar_vs_t * vss, size_t buffer, int * error);
+
 
 /* Boolean TRUE for VS functions */
@@ -228,4 +231,7 @@
 int     roar_vs_run           (roar_vs_t * vss, int * error);
 
+ssize_t roar_vs_get_avail_read(roar_vs_t * vss, int * error);
+ssize_t roar_vs_get_avail_write(roar_vs_t * vss, int * error);
+
 /* Misc controls.
  */
@@ -243,4 +249,5 @@
 int     roar_vs_ctl           (roar_vs_t * vss, roar_vs_ctlcmd cmd, void * argp, int * error);
 
+
 /* Get used connection object
  * This may be useful if you want to use functions from the main API.
Index: libroar/vs.c
===================================================================
--- libroar/vs.c	(revision 4622)
+++ libroar/vs.c	(revision 4626)
@@ -63,4 +63,5 @@
  struct roar_vio_calls    file_store;
  struct roar_vio_calls  * file;
+ struct roar_buffer     * readring, * writering;
 };
 
@@ -340,4 +341,27 @@
 }
 
+int roar_vs_buffer(roar_vs_t * vss, size_t buffer, int * error) {
+ _ckvss(-1);
+
+ if ( vss->flags & FLAG_BUFFERED )
+  return -1;
+
+ if ( roar_buffer_ring_new(&(vss->readring), buffer, 0) == -1 ) {
+  _seterrre();
+  return -1;
+ }
+
+ if ( roar_buffer_ring_new(&(vss->writering), buffer, 0) == -1 ) {
+  _seterrre();
+  roar_buffer_free(vss->readring);
+  vss->readring = NULL;
+  return -1;
+ }
+
+ vss->flags |= FLAG_BUFFERED;
+
+ return 0;
+}
+
 int roar_vs_close(roar_vs_t * vss, int killit, int * error) {
  if ( killit != ROAR_VS_TRUE && killit != ROAR_VS_FALSE ) {
@@ -353,4 +377,9 @@
   roar_buffer_free(vss->writebuffer);
 
+ if ( vss->readring != NULL )
+  roar_buffer_free(vss->readring);
+ if ( vss->writering != NULL )
+  roar_buffer_free(vss->writering);
+
  if ( vss->file != NULL && vss->flags & FLAG_CLOSEFILE )
   roar_vio_close(vss->file);
@@ -372,17 +401,6 @@
 }
 
-ssize_t roar_vs_write(roar_vs_t * vss, const void * buf, size_t len, int * error) {
- ssize_t ret;
-
- _ckvss(-1);
-
- if ( !(vss->flags & FLAG_STREAM) ) {
-  _seterr(ROAR_ERROR_INVAL);
-  return -1;
- }
-
- _initerr();
-
- ret = roar_vio_write(&(vss->vio), (void*)buf, len);
+static ssize_t roar_vs_write_direct(roar_vs_t * vss, const void * buf, size_t len, int * error) {
+ ssize_t ret = roar_vio_write(&(vss->vio), (void*)buf, len);
 
  if ( ret == -1 ) {
@@ -400,4 +418,34 @@
  } else {
   vss->writec += ret;
+ }
+
+ return ret;
+}
+
+ssize_t roar_vs_write(roar_vs_t * vss, const void * buf, size_t len, int * error) {
+ ssize_t ret;
+ size_t writelen;
+
+ _ckvss(-1);
+
+ if ( !(vss->flags & FLAG_STREAM) ) {
+  _seterr(ROAR_ERROR_INVAL);
+  return -1;
+ }
+
+ _initerr();
+
+ if ( vss->flags & FLAG_BUFFERED ) {
+  writelen = len;
+
+  if ( roar_buffer_ring_write(vss->writering, (void*)buf, &writelen) == -1 ) {
+   _seterrre();
+   return -1;
+  }
+
+  ret = writelen;
+  vss->writec += ret;
+ } else {
+  ret = roar_vs_write_direct(vss, buf, len, error);
  }
 
@@ -905,4 +953,7 @@
  int is_eof = 0;
  void * data;
+ size_t tmp;
+
+ // TODO: fix error handling below.
 
  _ckvss(-1);
@@ -938,7 +989,9 @@
 // part 2 of above hack:
 // emulate read handle.
-  vios[len].ud.vp   = vss->file;
-  vios[len].eventsa = ROAR_VIO_SELECT_WRITE|ROAR_VIO_SELECT_READ;;
-  len++;
+  if ( vss->file != NULL ) {
+   vios[len].ud.vp   = vss->file;
+   vios[len].eventsa = ROAR_VIO_SELECT_WRITE|ROAR_VIO_SELECT_READ;
+   len++;
+  }
 
  // no error here nor EOF.
@@ -960,5 +1013,5 @@
   } else if ( vios[i].ud.vp == vss->con ) {
    roar_sync(vss->con);
-  } else if ( vios[i].ud.vp == vss->file ) {
+  } else if ( vss->file != NULL && vios[i].ud.vp == vss->file ) {
    if ( vios[i].eventsa & ROAR_VIO_SELECT_READ )
     can_write++;
@@ -971,4 +1024,16 @@
  }
 
+ if ( vss->flags & FLAG_BUFFERED ) {
+  if ( roar_buffer_ring_avail(vss->readring, NULL, &tmp) != -1 )
+   if ( tmp > 0 )
+    can_read++;
+
+  if ( roar_buffer_ring_avail(vss->writering, &tmp, NULL) != -1 )
+   if ( tmp > 0 )
+    can_write++;
+ }
+
+ ROAR_DBG("roar_vs_iterate(vss=%p, wait=%i, error=%p): can_read=%i, can_write=%i", vss, wait, error, can_read, can_write);
+
  // TODO: FIXME: Need to correct error handling here!
 
@@ -980,5 +1045,5 @@
    return -1;
 
-  ret = roar_vs_write(vss, data, len, error);
+  ret = roar_vs_write_direct(vss, data, len, error);
 
   if ( ret == -1 ) {
@@ -1034,5 +1099,14 @@
     return -1;
 
-   ret = roar_vio_write(vss->file, data, len);
+   if ( vss->flags & FLAG_BUFFERED ) {
+    tmp = len;
+    if ( roar_buffer_ring_write(vss->readring, data, &tmp) == -1 ) {
+     ret = -1;
+    } else {
+     ret = tmp;
+    }
+   } else {
+    ret = roar_vio_write(vss->file, data, len);
+   }
 
    if ( ret == -1 ) {
@@ -1052,5 +1126,14 @@
    return -1;
 
-  ret = roar_vio_read(vss->file, data, len);
+  if ( vss->flags & FLAG_BUFFERED ) {
+   tmp = len;
+   if ( roar_buffer_ring_read(vss->writering, data, &tmp) == -1 ) {
+    ret = -1;
+   } else {
+    ret = tmp;
+   }
+  } else {
+   ret = roar_vio_read(vss->file, data, len);
+  }
 
   ROAR_DBG("roar_vs_iterate(vss=%p, wait=%i, error=%p): ret=%lli", vss, wait, error, (long long int)ret);
@@ -1079,5 +1162,5 @@
    ROAR_DBG("roar_vs_iterate(vss=%p, wait=%i, error=%p) = ?", vss, wait, error);
 
-   ret = roar_vs_write(vss, data, len, error);
+   ret = roar_vs_write_direct(vss, data, len, error);
 
    if ( ret == -1 ) {
@@ -1116,4 +1199,40 @@
 }
 
+ssize_t roar_vs_get_avail_read(roar_vs_t * vss, int * error) {
+ size_t len;
+
+ _ckvss(-1);
+
+ if ( !(vss->flags & FLAG_BUFFERED) ) {
+  _seterr(ROAR_ERROR_INVAL);
+  return -1;
+ }
+
+ if ( roar_buffer_ring_avail(vss->readring, &len, NULL) == -1 ) {
+  _seterrre();
+  return -1;
+ }
+
+ return len;
+}
+
+ssize_t roar_vs_get_avail_write(roar_vs_t * vss, int * error) {
+ size_t len;
+
+ _ckvss(-1);
+
+ if ( !(vss->flags & FLAG_BUFFERED) ) {
+  _seterr(ROAR_ERROR_INVAL);
+  return -1;
+ }
+
+ if ( roar_buffer_ring_avail(vss->writering, NULL, &len) == -1 ) {
+  _seterrre();
+  return -1;
+ }
+
+ return len;
+}
+
 int     roar_vs_ctl           (roar_vs_t * vss, roar_vs_ctlcmd cmd, void * argp, int * error) {
  _ckvss(-1);
