Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5348)
+++ ChangeLog	(revision 5367)
@@ -7,4 +7,5 @@
 	* Removed old roarclients (See: #130)
 	* Improved plugin loader a lot (Closes: #190)
+	* Added VIO/DSTR for SOCKS proxy (See: #187)
 
 v. 0.4 - Fri Nov 11 2011 20:12 CET
Index: include/libroar/libroar.h
===================================================================
--- include/libroar/libroar.h	(revision 5317)
+++ include/libroar/libroar.h	(revision 5367)
@@ -150,4 +150,5 @@
 #include "vio_winsock.h"
 #include "vio_proto.h"
+#include "vio_proxy.h"
 #include "vio_rtp.h"
 #include "vio_select.h"
Index: include/libroar/vio_dstr.h
===================================================================
--- include/libroar/vio_dstr.h	(revision 5257)
+++ include/libroar/vio_dstr.h	(revision 5367)
@@ -190,5 +190,6 @@
                                     int (*openvio)(struct roar_vio_calls      * calls,
                                                    struct roar_vio_calls      * dst,
-                                                   struct roar_vio_dstr_chain * cur));
+                                                   struct roar_vio_dstr_chain * cur,
+                                                   struct roar_vio_dstr_chain * next));
 
 int     roar_vio_dstr_init_defaults (struct roar_vio_defaults * def, int type, int o_flags, mode_t o_mode);
Index: include/libroar/vio_proxy.h
===================================================================
--- include/libroar/vio_proxy.h	(revision 5367)
+++ include/libroar/vio_proxy.h	(revision 5367)
@@ -0,0 +1,74 @@
+//vio_proxy.h:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011
+ *
+ *  This file is part of libroar a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  libroar is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ *  NOTE for everyone want's to change something and send patches:
+ *  read README and HACKING! There a addition information on
+ *  the license of this document you need to read before you send
+ *  any patches.
+ *
+ *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
+ *  or libpulse*:
+ *  The libs libroaresd, libroararts and libroarpulse link this lib
+ *  and are therefore GPL. Because of this it may be illigal to use
+ *  them with any software that uses libesd, libartsc or libpulse*.
+ */
+
+#ifndef _LIBROARVIO_PROXY_H_
+#define _LIBROARVIO_PROXY_H_
+
+#include "libroar.h"
+
+enum roar_vio_proxy_type {
+ ROAR_VIO_PROXY_INVALID = -1,
+ ROAR_VIO_PROXY_NONE    = 0,
+#define ROAR_VIO_PROXY_NONE ROAR_VIO_PROXY_NONE
+ ROAR_VIO_PROXY_SOCKS   = 1, /* unknown version */
+#define ROAR_VIO_PROXY_SOCKS ROAR_VIO_PROXY_SOCKS
+ ROAR_VIO_PROXY_SOCKS4  = 2,
+#define ROAR_VIO_PROXY_SOCKS4 ROAR_VIO_PROXY_SOCKS4
+ ROAR_VIO_PROXY_SOCKS4a = 3,
+#define ROAR_VIO_PROXY_SOCKS4a ROAR_VIO_PROXY_SOCKS4a
+ ROAR_VIO_PROXY_SOCKS4d = 4,
+#define ROAR_VIO_PROXY_SOCKS4d ROAR_VIO_PROXY_SOCKS4d
+ ROAR_VIO_PROXY_SOCKS5  = 5,
+#define ROAR_VIO_PROXY_SOCKS5 ROAR_VIO_PROXY_SOCKS5
+ ROAR_VIO_PROXY_HTTP    = 6,
+#define ROAR_VIO_PROXY_HTTP ROAR_VIO_PROXY_HTTP
+ ROAR_VIO_PROXY_SSH     = 7
+#define ROAR_VIO_PROXY_SSH ROAR_VIO_PROXY_SSH
+};
+
+int roar_vio_proxy_init_def(struct roar_vio_defaults * def,
+                            char * dstr, enum roar_vio_proxy_type type,
+                            struct roar_vio_defaults * odef);
+int roar_vio_open_proxy    (struct roar_vio_calls * calls, struct roar_vio_calls * dst,
+                            enum roar_vio_proxy_type type, struct roar_vio_defaults * odef);
+
+// DSTR interface:
+struct roar_vio_dstr_chain;
+int roar_vio_proxy_setdef(struct roar_vio_dstr_chain * cur,   struct roar_vio_dstr_chain * next);
+int roar_vio_proxy_openvio(struct roar_vio_calls * calls, struct roar_vio_calls * dst, struct roar_vio_dstr_chain * cur, struct roar_vio_dstr_chain * next);
+
+#endif
+
+//ll
Index: libroar/Makefile
===================================================================
--- libroar/Makefile	(revision 5317)
+++ libroar/Makefile	(revision 5367)
@@ -7,5 +7,5 @@
 VIO_META=vio.o vio_select.o vio_ops.o vio_string.o
 VIO_BRIDGE=vio_bio.o vio_stdio.o
-VIO=$(VIO_META) $(VIO_BRIDGE) vio_cmd.o vio_magic.o vio_pipe.o vio_socket.o vio_winsock.o vio_stack.o vio_jumbo.o vio_proto.o vio_dstr.o vio_tantalos.o vio_rtp.o vio_buffer.o vio_buffer_store.o vio_stdvios.o vio_misc.o vio_zlib.o vio_stream.o
+VIO=$(VIO_META) $(VIO_BRIDGE) vio_cmd.o vio_magic.o vio_pipe.o vio_socket.o vio_winsock.o vio_stack.o vio_jumbo.o vio_proto.o vio_dstr.o vio_tantalos.o vio_rtp.o vio_buffer.o vio_buffer_store.o vio_stdvios.o vio_misc.o vio_zlib.o vio_stream.o vio_proxy.o
 HASHES=hash.o hash_tiger.o
 PASSWORD=passwordapi.o pinentry.o sshaskpass.o
Index: libroar/vio_dstr.c
===================================================================
--- libroar/vio_dstr.c	(revision 5282)
+++ libroar/vio_dstr.c	(revision 5367)
@@ -41,5 +41,5 @@
  const char * name;
  int (* setdef) (struct roar_vio_dstr_chain * cur,   struct roar_vio_dstr_chain * next);
- int (* openvio)(struct roar_vio_calls      * calls, struct roar_vio_calls      * dst, struct roar_vio_dstr_chain * cur);
+ int (* openvio)(struct roar_vio_calls      * calls, struct roar_vio_calls      * dst, struct roar_vio_dstr_chain * cur, struct roar_vio_dstr_chain * next);
  int    pdeftype[16];
 } _roar_vio_dstr_objs[] = {
@@ -105,20 +105,20 @@
 
  {ROAR_VIO_DSTR_OBJT_SOCKS,      "socks",
-      NULL, NULL,
+      roar_vio_proxy_setdef, roar_vio_proxy_openvio,
       {ROAR_VIO_DEF_TYPE_EOL}},
  {ROAR_VIO_DSTR_OBJT_SOCKS4,     "socks4",
-      NULL, NULL,
+      roar_vio_proxy_setdef, roar_vio_proxy_openvio,
       {ROAR_VIO_DEF_TYPE_EOL}},
  {ROAR_VIO_DSTR_OBJT_SOCKS4A,    "socks4a",
-      NULL, NULL,
+      roar_vio_proxy_setdef, roar_vio_proxy_openvio,
       {ROAR_VIO_DEF_TYPE_EOL}},
  {ROAR_VIO_DSTR_OBJT_SOCKS4D,    "socks4d",
-      NULL, NULL,
+      roar_vio_proxy_setdef, roar_vio_proxy_openvio,
       {ROAR_VIO_DEF_TYPE_EOL}},
  {ROAR_VIO_DSTR_OBJT_SOCKS5,     "socks5",
-      NULL, NULL,
+      roar_vio_proxy_setdef, roar_vio_proxy_openvio,
       {ROAR_VIO_DEF_TYPE_EOL}},
  {ROAR_VIO_DSTR_OBJT_SSH,        "ssh",
-      NULL, NULL,
+      roar_vio_proxy_setdef, roar_vio_proxy_openvio,
       {ROAR_VIO_DEF_TYPE_EOL}},
 
@@ -265,5 +265,6 @@
                                     int (*openvio)(struct roar_vio_calls      * calls,
                                                    struct roar_vio_calls      * dst,
-                                                   struct roar_vio_dstr_chain * cur)) {
+                                                   struct roar_vio_dstr_chain * cur,
+                                                   struct roar_vio_dstr_chain * next)) {
  struct _roar_vio_dstr_type * ret;
 
@@ -362,7 +363,9 @@
  switch (def->type) {
   case ROAR_VIO_DEF_TYPE_NONE:
+    ROAR_DBG("roar_vio_open_default(calls=%p, def=%p, opts='%s'): def->type=%i, dummy open", calls, def, opts, (int)def->type);
    break;
 #ifdef ROAR_HAVE_IO_POSIX
   case ROAR_VIO_DEF_TYPE_FILE:
+    ROAR_DBG("roar_vio_open_default(calls=%p, def=%p, opts='%s'): def->type=%i, file open", calls, def, opts, (int)def->type);
     if ( _open_file(calls, def->d.file, def->o_flags, def->o_mode) == -1 ) {
      ROAR_DBG("roar_vio_open_default(*): Can not open file: %i", roar_error);
@@ -372,16 +375,20 @@
 #endif
   case ROAR_VIO_DEF_TYPE_SOCKET:
+    ROAR_DBG("roar_vio_open_default(calls=%p, def=%p, opts='%s'): def->type=%i, socket open", calls, def, opts, (int)def->type);
      if ( roar_vio_open_def_socket(calls, def, opts) == -1 )
       return -1;
    break;
   case ROAR_VIO_DEF_TYPE_FH:
+    ROAR_DBG("roar_vio_open_default(calls=%p, def=%p, opts='%s'): def->type=%i, fh open", calls, def, opts, (int)def->type);
     if ( roar_vio_open_fh(calls, def->d.fh) == -1 )
      return -1;
    break;
   case ROAR_VIO_DEF_TYPE_SOCKETFH:
+    ROAR_DBG("roar_vio_open_default(calls=%p, def=%p, opts='%s'): def->type=%i, socket fh open", calls, def, opts, (int)def->type);
     if ( roar_vio_open_fh_socket(calls, def->d.fh) == -1 )
      return -1;
    break;
   default:
+    ROAR_DBG("roar_vio_open_default(calls=%p, def=%p, opts='%s') = -1 // error=NOTSUP", calls, def, opts, (int)def->type);
     roar_err_set(ROAR_ERROR_NOTSUP);
     return -1;
@@ -849,7 +856,7 @@
  }
 
- for (i = 0; (c = &chain[i])->type != ROAR_VIO_DSTR_OBJT_EOL; i++) {
-  ROAR_DBG("roar_vio_dstr_build_chain(*): i=%i, c->type=0x%.4x(%s): need_vio=%i, def->o_flags=%i", i,
-                   c->type & 0xFFFF, roar_vio_dstr_get_name(c->type), c->need_vio, c->def->o_flags);
+ for (i = 0; (c = &(chain[i]))->type != ROAR_VIO_DSTR_OBJT_EOL; i++) {
+  ROAR_DBG("roar_vio_dstr_build_chain(*): i=%i, c->type=0x%.4x(%s): need_vio=%i, def(%p)->o_flags=%i", i,
+                   c->type & 0xFFFF, roar_vio_dstr_get_name(c->type), c->need_vio, c->def, c->def != NULL ? c->def->o_flags : -1);
 
   if ( c->need_vio ) {
@@ -881,5 +888,4 @@
 #ifdef ROAR_HAVE_LIBZ
     case ROAR_VIO_DSTR_OBJT_GZIP:
-      //if ( roar_vio_open_gzip(tc, prev, -1) == -1 ) {
       if ( roar_vio_open_zlib(tc, prev, -1, 1) == -1 ) {
        _ret(-1);
@@ -887,5 +893,4 @@
      break;
     case ROAR_VIO_DSTR_OBJT_ZLIB:
-      //if ( roar_vio_open_gzip(tc, prev, -1) == -1 ) {
       if ( roar_vio_open_zlib(tc, prev, -1, 0) == -1 ) {
        _ret(-1);
@@ -960,5 +965,5 @@
       }
 
-      if ( type->openvio(tc, prev, c) == -1 ) {
+      if ( type->openvio(tc, prev, c, &(chain[i+1])) == -1 ) {
        _ret(-1);
       }
Index: libroar/vio_proxy.c
===================================================================
--- libroar/vio_proxy.c	(revision 5367)
+++ libroar/vio_proxy.c	(revision 5367)
@@ -0,0 +1,226 @@
+//vio_proxy.c:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011
+ *
+ *  This file is part of libroar a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  libroar is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ *  NOTE for everyone want's to change something and send patches:
+ *  read README and HACKING! There a addition information on
+ *  the license of this document you need to read before you send
+ *  any patches.
+ *
+ *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
+ *  or libpulse*:
+ *  The libs libroaresd, libroararts and libroarpulse link this lib
+ *  and are therefore GPL. Because of this it may be illigal to use
+ *  them with any software that uses libesd, libartsc or libpulse*.
+ */
+
+#include "libroar.h"
+
+int roar_vio_proxy_init_def(struct roar_vio_defaults * def,
+                            char * dstr, enum roar_vio_proxy_type type,
+                            struct roar_vio_defaults * odef) {
+ int hint = -1;
+
+ (void)type; // TODO: generate hints from type.
+
+ ROAR_DBG("roar_vio_proxy_init_def(def=%p, dstr='%s', type=%i, odef=%p) = ?", def, dstr, (int)type, odef);
+
+ if ( roar_vio_dstr_init_defaults(def, ROAR_VIO_DEF_TYPE_SOCKET, O_RDWR, 0644) == -1 )
+  return -1;
+
+ if ( roar_vio_socket_init_dstr_def(def, dstr, hint, odef == NULL ? SOCK_STREAM : odef->d.socket.type, odef) == -1 ) {
+  ROAR_DBG("roar_vio_proxy_init_def(def=%p, dstr='%s', type=%i, odef=%p) = -1", def, dstr, (int)type, odef);
+  return -1;
+ }
+
+ ROAR_DBG("roar_vio_proxy_init_def(def=%p, dstr='%s', type=%i, odef=%p) = 0", def, dstr, (int)type, odef);
+ return 0;
+}
+
+static int roar_vio_proxy_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
+ if ( cmd == ROAR_VIO_CTL_GET_NAME ) {
+  *(char **)data = "proxy";
+  return 0;
+ }
+
+ return roar_vio_pass_ctl(vio, cmd, data);
+}
+
+static int init_socks4(struct roar_vio_calls * dst, enum roar_vio_proxy_type type, struct roar_vio_defaults * odef) {
+ char buf[9] = {
+  0x04,       // [0] Version
+  0x01,       // [1] mode=connect (listen is 0x02)
+  0, 0, 0, 0, // [2..5] host IP
+  0,          // [6] Port MSB
+  0,          // [7] Port LSB
+  0x00        // [8] EOS (\0) of username
+ };
+ enum roar_vio_proxy_type needed_type = ROAR_VIO_PROXY_INVALID;
+
+ ROAR_DBG("init_socks4(dst=%p, type=%i, odef=%p{.d.socket={.domain=%i, .type=%i, .host='%s'}}) = ?", dst, (int)type, odef, odef->d.socket.domain, odef->d.socket.type, odef->d.socket.host);
+
+ switch (odef->d.socket.domain) {
+#ifdef ROAR_HAVE_IPV4
+  case AF_INET: needed_type = ROAR_VIO_PROXY_SOCKS4; break;
+#endif
+#ifdef ROAR_HAVE_LIBDNET
+  case AF_DECnet:
+    if ( odef->d.socket.sa.dn.sdn_objnum == 0 ) {
+     needed_type = ROAR_VIO_PROXY_SOCKS4d;
+    } else {
+     needed_type = ROAR_VIO_PROXY_SOCKS4;
+    }
+   break;
+#endif
+#ifdef ROAR_HAVE_IPV6
+  case AF_INET6:
+#endif
+#ifdef ROAR_HAVE_IPX
+  case AF_IPX:
+#endif
+#ifdef ROAR_HAVE_UNIX
+  case AF_UNIX:
+#endif
+  default:
+    roar_err_set(ROAR_ERROR_AFNOTSUP);
+    return -1;
+   break;
+ }
+
+ if ( needed_type == ROAR_VIO_PROXY_SOCKS4 && type != needed_type )
+  needed_type = type;
+
+ if ( needed_type != type ) {
+  roar_err_set(ROAR_ERROR_INVAL);
+  return -1;
+ }
+
+ switch (odef->d.socket.domain) {
+#ifdef ROAR_HAVE_IPV4
+  case AF_INET:
+    if ( roar_vio_socket_init_inet4host_def(odef) == -1 )
+     return -1;
+    buf[2] = ((char*)&(odef->d.socket.sa.in.sin_port))[0];
+    buf[3] = ((char*)&(odef->d.socket.sa.in.sin_port))[1];
+    buf[4] = ((char*)&(odef->d.socket.sa.in.sin_addr.s_addr))[0];
+    buf[5] = ((char*)&(odef->d.socket.sa.in.sin_addr.s_addr))[1];
+    buf[6] = ((char*)&(odef->d.socket.sa.in.sin_addr.s_addr))[2];
+    buf[7] = ((char*)&(odef->d.socket.sa.in.sin_addr.s_addr))[3];
+    ROAR_DBG("init_socks4(dst=%p, type=%i, odef=%p{.d.socket={.domain=%i, .type=%i, .host='%s'}}): buf[]={%i, %i, %i, %i, %i, %i, %i, %i, %i}",
+             dst, (int)type, odef, odef->d.socket.domain, odef->d.socket.type, odef->d.socket.host,
+             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]);
+   break;
+#endif
+#ifdef ROAR_HAVE_LIBDNET
+  case AF_DECnet:
+    if ( type == ROAR_VIO_PROXY_SOCKS4 ) {
+     buf[2] = 0;
+     buf[3] = odef->d.socket.sa.dn.sdn_objnum;
+     buf[4] = 0;
+     buf[5] = 2;
+     buf[6] = odef->d.socket.sa.dn.sdn_nodeaddr[0];
+     buf[7] = odef->d.socket.sa.dn.sdn_nodeaddr[1];
+    } else {
+     roar_err_set(ROAR_ERROR_NOTSUP);
+     return -1;
+    }
+   break;
+#endif
+ }
+
+ if ( roar_vio_write(dst, buf, sizeof(buf)) != (ssize_t)sizeof(buf) )
+  return -1;
+
+ if ( roar_vio_read(dst, buf, 8) != (ssize_t)8 )
+  return -1;
+
+ if ( buf[1] != 0x5a ) {
+  roar_err_set(ROAR_ERROR_UNKNOWN);
+  return -1;
+ }
+
+ return 0;
+}
+
+int roar_vio_open_proxy    (struct roar_vio_calls * calls, struct roar_vio_calls * dst,
+                            enum roar_vio_proxy_type type, struct roar_vio_defaults * odef) {
+ int init_only = -1;
+ int (*init)(struct roar_vio_calls * dst, enum roar_vio_proxy_type type, struct roar_vio_defaults * odef) = NULL;
+
+ ROAR_DBG("roar_vio_open_proxy(calls=%p, dst=%p, type=%i, odef=%p{.type=%i}) = ?", calls, dst, (int)type, odef, (int)odef->type);
+
+ if ( odef->type != ROAR_VIO_DEF_TYPE_SOCKET ) {
+  roar_err_set(ROAR_ERROR_NOTSOCK);
+  return -1;
+ }
+
+ switch (type) {
+  case ROAR_VIO_PROXY_NONE: init_only = 1; init = NULL; break;
+  case ROAR_VIO_PROXY_SOCKS:
+  case ROAR_VIO_PROXY_SOCKS4:
+  case ROAR_VIO_PROXY_SOCKS4a:
+  case ROAR_VIO_PROXY_SOCKS4d:
+    init_only = 1;
+    init = init_socks4;
+   break;
+ }
+
+ if ( init_only == 1 ) {
+  if ( init != NULL )
+   if ( init(dst, type, odef) == -1 )
+    return -1;
+  if ( roar_vio_open_pass(calls, dst) == -1 )
+   return -1;
+
+  calls->ctl = roar_vio_proxy_ctl;
+
+  return 0;
+ } else {
+  roar_err_set(ROAR_ERROR_NOTSUP);
+  return -1;
+ }
+}
+
+// DSTR interface:
+static enum roar_vio_proxy_type _dstrtype2proxytype(struct roar_vio_dstr_chain * chainelement) {
+ switch (chainelement->type) {
+  case ROAR_VIO_DSTR_OBJT_SOCKS:   return ROAR_VIO_PROXY_SOCKS;   break;
+  case ROAR_VIO_DSTR_OBJT_SOCKS4:  return ROAR_VIO_PROXY_SOCKS4;  break;
+  case ROAR_VIO_DSTR_OBJT_SOCKS4A: return ROAR_VIO_PROXY_SOCKS4a; break;
+  case ROAR_VIO_DSTR_OBJT_SOCKS4D: return ROAR_VIO_PROXY_SOCKS4d; break;
+  case ROAR_VIO_DSTR_OBJT_SOCKS5:  return ROAR_VIO_PROXY_SOCKS5;  break;
+  default:
+    return ROAR_VIO_PROXY_INVALID;
+   break;
+ }
+}
+
+int roar_vio_proxy_setdef(struct roar_vio_dstr_chain * cur,   struct roar_vio_dstr_chain * next) {
+ next->def = &(next->store_def);
+ return roar_vio_proxy_init_def(next->def, cur->dst, _dstrtype2proxytype(cur), cur->def);
+}
+
+int roar_vio_proxy_openvio(struct roar_vio_calls * calls, struct roar_vio_calls * dst, struct roar_vio_dstr_chain * cur, struct roar_vio_dstr_chain * next) {
+ return roar_vio_open_proxy(calls, dst, _dstrtype2proxytype(cur), cur->def);
+}
+
+//ll
