[xiph-cvs] cvs commit: libshout/src Makefile.am shout.c shout_private.h util.c util.h

Michael Smith msmith at xiph.org
Fri Aug 16 07:22:16 PDT 2002



msmith      02/08/16 10:22:16

  Modified:    .        configure.in
               include/shout shout.h
               src      Makefile.am shout.c shout_private.h util.c util.h
  Log:
  HTTP Basic authentication for libshout.

Revision  Changes    Path
1.6       +4 -4      libshout/configure.in

Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/libshout/configure.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- configure.in	23 Jan 2002 03:08:38 -0000	1.5
+++ configure.in	16 Aug 2002 14:22:16 -0000	1.6
@@ -29,9 +29,9 @@
 else
         case $host in 
         *-*-linux*)
-                DEBUG="-g -Wall -W -fsigned-char -D_REENTRANT"
-                CFLAGS="-Wall -W -O20 -ffast-math -fsigned-char -D_REENTRANT"
-                PROFILE="-Wall -W -pg -g -O20 -ffast-math -fsigned-char -D_REENTRANT"
+                DEBUG="-g -Wall -W -fsigned-char -D_REENTRANT -D_GNU_SOURCE"
+                CFLAGS="-Wall -W -O20 -ffast-math -fsigned-char -D_REENTRANT -D_GNU_SOURCE"
+                PROFILE="-Wall -W -pg -g -O20 -ffast-math -fsigned-char -D_REENTRANT -D_GNU_SOURCE"
                 ;;
         sparc-sun-*)
                 DEBUG="-g -Wall -fsigned-char -mv8"
@@ -93,4 +93,4 @@
 AC_SUBST(CFLAGS)
 AC_SUBST(PROFILE)
 
-AC_OUTPUT(Makefile include/Makefile include/shout/Makefile src/Makefile src/net/Makefile src/timing/Makefile examples/Makefile)
+AC_OUTPUT(Makefile include/Makefile include/shout/Makefile src/Makefile src/net/Makefile src/timing/Makefile src/thread/Makefile src/avl/Makefile src/httpp/Makefile examples/Makefile)

<p><p>1.9       +5 -0      libshout/include/shout/shout.h

Index: shout.h
===================================================================
RCS file: /usr/local/cvsroot/libshout/include/shout/shout.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- shout.h	4 Aug 2002 02:29:12 -0000	1.8
+++ shout.h	16 Aug 2002 14:22:16 -0000	1.9
@@ -17,6 +17,7 @@
 #define SHOUTERR_CONNECTED	(7)
 #define SHOUTERR_UNCONNECTED	(8)
 #define SHOUTERR_UNSUPPORTED	(9)
+#define SHOUTERR_REFUSED    (10)
 
 #define SHOUT_FORMAT_VORBIS	(0)
 #define SHOUT_FORMAT_MP3	(1)
@@ -24,6 +25,7 @@
 #define SHOUT_PROTOCOL_ICE		(0)
 #define SHOUT_PROTOCOL_XAUDIOCAST	(1)
 #define SHOUT_PROTOCOL_ICY		(2)
+#define SHOUT_PROTOCOL_HTTP	    (3)
 
 typedef struct shout shout_t;
 typedef struct shout_metadata shout_metadata_t;
@@ -74,6 +76,9 @@
 
 int shout_set_genre(shout_t *self, const char *genre);
 const char *shout_get_genre(shout_t *self);
+
+int shout_set_user(shout_t *self, const char *username);
+const char *shout_get_user(shout_t *self);
 
 int shout_set_description(shout_t *self, const char *description);
 const char *shout_get_description(shout_t *self);

<p><p>1.4       +4 -3      libshout/src/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/libshout/src/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Makefile.am	14 May 2002 05:14:34 -0000	1.3
+++ Makefile.am	16 Aug 2002 14:22:16 -0000	1.4
@@ -2,16 +2,17 @@
 
 AUTOMAKE_OPTIONS = foreign
 
-SUBDIRS = net timing
+SUBDIRS = avl net timing httpp thread
 
 lib_LTLIBRARIES = libshout.la
 
 noinst_HEADERS = shout_private.h util.h
 libshout_la_SOURCES = shout.c util.c vorbis.c mp3.c
 
-libshout_la_LIBADD = net/libicenet.la timing/libicetiming.la
+libshout_la_LIBADD = net/libicenet.la timing/libicetiming.la avl/libiceavl.la\
+		httpp/libicehttpp.la thread/libicethread.la
 
-INCLUDES = -I$(top_srcdir)/include/shout -I$(srcdir)/net -I$(srcdir)/timing
+INCLUDES = -I$(top_srcdir)/include/shout -I$(srcdir)/net -I$(srcdir)/timing -I$(srcdir)/avl -I$(srcdir)/thread -I$(srcdir)/httpp
 
 debug:
         $(MAKE) all CFLAGS="@DEBUG@"

<p><p>1.7       +171 -7    libshout/src/shout.c

Index: shout.c
===================================================================
RCS file: /usr/local/cvsroot/libshout/src/shout.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- shout.c	4 Aug 2002 02:29:13 -0000	1.6
+++ shout.c	16 Aug 2002 14:22:16 -0000	1.7
@@ -11,11 +11,13 @@
 #include "sock.h"
 #include "timing.h"
 #include "util.h"
+#include "httpp/httpp.h"
 
 /* -- local prototypes -- */
 static int login_ice(shout_t *self);
 static int login_xaudiocast(shout_t *self);
 static int login_icy(shout_t *self);
+static int login_http_basic(shout_t *self);
 
 /* -- public functions -- */
 
@@ -50,6 +52,7 @@
         if (self->url) free(self->url);
         if (self->genre) free(self->genre);
         if (self->description) free(self->description);
+	if (self->user) free(self->user);
 
         free(self);
 }
@@ -63,14 +66,19 @@
         if (!self->host || !self->password || !self->port || self->connected)
                 return self->error = SHOUTERR_INSANE;
 
-	if (self->format == SHOUT_FORMAT_VORBIS && self->protocol != SHOUT_PROTOCOL_ICE)
+	if (self->format == SHOUT_FORMAT_VORBIS && self->protocol != SHOUT_PROTOCOL_ICE && self->protocol != SHOUT_PROTOCOL_HTTP)
                 return self->error = SHOUTERR_UNSUPPORTED;
 
-	self->socket = sock_connect(self->host, self->port);
-	if (self->socket <= 0)
-		return self->error = SHOUTERR_NOCONNECT;
-
-	if (self->protocol == SHOUT_PROTOCOL_ICE) {
+    if(self->protocol != SHOUT_PROTOCOL_HTTP) {
+    	self->socket = sock_connect(self->host, self->port);
+	    if (self->socket <= 0)
+		    return self->error = SHOUTERR_NOCONNECT;
+    }
+
+    if (self->protocol == SHOUT_PROTOCOL_HTTP) {
+        return login_http_basic(self);
+    }
+    else if (self->protocol == SHOUT_PROTOCOL_ICE) {
                 if ((self->error = login_ice(self)) != SHOUTERR_SUCCESS) {
                         sock_close(self->socket);
                         return self->error;
@@ -388,6 +396,31 @@
         return self->genre;
 }
 
+int shout_set_user(shout_t *self, const char *username)
+{
+	if (!self)
+		return SHOUTERR_INSANE;
+
+	if (self->connected)
+		return self->error = SHOUTERR_CONNECTED;
+
+	if (self->user)
+		free(self->user);
+
+	if (! (self->user = util_strdup (username)))
+		return self->error = SHOUTERR_MALLOC;
+
+	return self->error = SHOUTERR_SUCCESS;
+}
+
+const char *shout_get_user(shout_t *self)
+{
+    if (!self)
+        return NULL;
+
+    return self->user;
+}
+
 int shout_set_description(shout_t *self, const char *description)
 {
         if (!self)
@@ -489,7 +522,8 @@
 
         if (protocol != SHOUT_PROTOCOL_ICE &&
             protocol != SHOUT_PROTOCOL_XAUDIOCAST &&
-	    protocol != SHOUT_PROTOCOL_ICY)
+	    protocol != SHOUT_PROTOCOL_ICY &&
+        protocol != SHOUT_PROTOCOL_HTTP)
                 return self->error = SHOUTERR_UNSUPPORTED;
 
         self->protocol = protocol;
@@ -506,6 +540,136 @@
 }
 
 /* -- static function definitions -- */
+
+static int send_http_request(shout_t *self, char *username, char *password)
+{
+    if (!sock_write(self->socket, "SOURCE %s HTTP/1.0\r\n", self->mount))
+		return SHOUTERR_SOCKET;
+
+	if (!sock_write(self->socket, "ice-name: %s\r\n", self->name != NULL ? self->name : "no name"))
+		return SHOUTERR_SOCKET;
+	if (self->url) {
+		if (!sock_write(self->socket, "ice-url: %s\r\n", self->url))
+			return SHOUTERR_SOCKET;
+	}
+	if (self->genre) {
+		if (!sock_write(self->socket, "ice-genre: %s\r\n", self->genre))
+			return SHOUTERR_SOCKET;
+	}
+	if (!sock_write(self->socket, "ice-bitrate: %d\r\n", self->bitrate))
+		return SHOUTERR_SOCKET;
+	if (!sock_write(self->socket, "ice-public: %d\r\n", self->public))
+		return SHOUTERR_SOCKET;
+	if (self->description) {
+		if (!sock_write(self->socket, "ice-description: %s\r\n", self->description))
+			return SHOUTERR_SOCKET;
+	}
+	if (self->format == SHOUT_FORMAT_VORBIS) {
+		if (!sock_write(self->socket, "Content-Type: application/x-ogg\r\n"))
+			return SHOUTERR_SOCKET;
+	} else if (self->format == SHOUT_FORMAT_MP3) {
+		if (!sock_write(self->socket, "Content-Type: audio/mpeg\r\n"))
+			return SHOUTERR_SOCKET;
+	}
+    if (username && password) {
+        char *data;
+        int len = strlen(username) + strlen(password) + 1;
+        char *orig = malloc(len+1);
+        strcpy(orig, username);
+        strcat(orig, ":");
+        strcat(orig, password);
+
+        data = util_base64_encode(orig);
+
+        if(!sock_write(self->socket, "Authorization: Basic %s\r\n", data)) {
+            free(data);
+            return SHOUTERR_SOCKET;
+        }
+        free(data);
+    }
+
+	if (!sock_write(self->socket, "\r\n"))
+		return SHOUTERR_SOCKET;
+
+	return SHOUTERR_SUCCESS;
+}
+
+
+static int login_http_basic(shout_t *self)
+{
+    char header[4096];
+    http_parser_t *parser;
+    int code;
+    char *retcode, *realm;
+    
+    self->error = SHOUTERR_SOCKET;
+
+   	self->socket = sock_connect(self->host, self->port);
+    if (self->socket <= 0) {
+	    return self->error = SHOUTERR_NOCONNECT;
+    }
+
+    if(send_http_request(self, NULL, NULL) != 0) {
+        sock_close(self->socket);
+        return self->error = SHOUTERR_SOCKET;
+    }
+
+    if (util_read_header(self->socket, header, 4096) == 0) {
+        /* either we didn't get a complete header, or we timed out */
+        sock_close(self->socket);
+	    return self->error = SHOUTERR_SOCKET;
+    }
+
+    parser = httpp_create_parser();
+    httpp_initialize(parser, NULL);
+    if (httpp_parse_response(parser, header, strlen(header), self->mount)) {
+        retcode = httpp_getvar(parser, HTTPP_VAR_ERROR_CODE);
+        code = atoi(retcode);
+        if(code >= 200 && code < 300) {
+            httpp_destroy(parser);
+	        return SHOUTERR_SUCCESS;
+        }
+        else if(code == 401) {
+            /* Don't really use this right now other than to check that it's
+             * present.
+             */
+            realm = httpp_getvar(parser, "www-authenticate");
+            if(realm) {
+                httpp_destroy(parser);
+                sock_close(self->socket);
+
+   	            self->socket = sock_connect(self->host, self->port);
+                if (self->socket <= 0)
+            	    return self->error = SHOUTERR_NOCONNECT;
+
+                if(send_http_request(self, self->user, self->password) != 0) {
+                    sock_close(self->socket);
+                    return self->error = SHOUTERR_SOCKET;
+                }
+
+                if (util_read_header(self->socket, header, 4096) == 0) {
+                    /* either we didn't get a complete header, or we timed out */
+                    sock_close(self->socket);
+	                return self->error = SHOUTERR_SOCKET;
+                }
+                parser = httpp_create_parser();
+                httpp_initialize(parser, NULL);
+                if (httpp_parse_response(parser, header, strlen(header), self->mount)) {
+                    retcode = httpp_getvar(parser, HTTPP_VAR_ERROR_CODE);
+                    code = atoi(retcode);
+                    if(code >= 200 && code < 300) {
+                        httpp_destroy(parser);
+            	        return SHOUTERR_SUCCESS;
+                    }
+                }
+            }
+        }
+    }
+
+    httpp_destroy(parser);
+    sock_close(self->socket);
+    return self->error = SHOUTERR_REFUSED;
+}
 
 static int login_ice(shout_t *self)
 {

<p><p>1.2       +2 -0      libshout/src/shout_private.h

Index: shout_private.h
===================================================================
RCS file: /usr/local/cvsroot/libshout/src/shout_private.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- shout_private.h	23 Jan 2002 03:08:39 -0000	1.1
+++ shout_private.h	16 Aug 2002 14:22:16 -0000	1.2
@@ -58,6 +58,8 @@
         char *genre;
         /* description of the stream */
         char *description;
+    /* username to use for HTTP auth. */
+    char *user;
         /* bitrate of this stream */
         int bitrate;
         /* is this stream private? */

<p><p>1.2       +74 -0     libshout/src/util.c

Index: util.c
===================================================================
RCS file: /usr/local/cvsroot/libshout/src/util.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- util.c	23 Jan 2002 03:08:39 -0000	1.1
+++ util.c	16 Aug 2002 14:22:16 -0000	1.2
@@ -2,6 +2,10 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
 
 #include "util.h"
 
@@ -10,3 +14,73 @@
         if (!s) return NULL;
         return strdup(s);
 }
+
+int util_read_header(int sock, char *buff, unsigned long len)
+{
+    int read_bytes, ret;
+    unsigned long pos;
+    char c;
+
+    read_bytes = 1;
+    pos = 0;
+    ret = 0;
+
+    while ((read_bytes == 1) && (pos < (len - 1))) {
+        read_bytes = 0;
+
+        if ((read_bytes = recv(sock, &c, 1, 0))) {
+            if (c != '\r') buff[pos++] = c;
+            if ((pos > 1) && (buff[pos - 1] == '\n' && buff[pos - 2] == '\n')) {
+                ret = 1;
+                break;
+            }
+        } else {
+            break;
+        }
+    }
+
+    if (ret) buff[pos] = '\0';
+
+    return ret;
+}
+
+static char base64table[64] = {
+    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+/* This isn't efficient, but it doesn't need to be */
+char *util_base64_encode(char *data)
+{
+    int len = strlen(data);
+    char *out = malloc(len*4/3 + 4);
+    char *result = out;
+    int chunk;
+
+    while(len > 0) {
+        chunk = (len >3)?3:len;
+        *out++ = base64table[(*data & 0xFC)>>2];
+        *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];
+        switch(chunk) {
+            case 3:
+                *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];
+                *out++ = base64table[(*(data+2)) & 0x3F];
+                break;
+            case 2:
+                *out++ = base64table[((*(data+1) & 0x0F)<<2)];
+                *out++ = '=';
+                break;
+            case 1:
+                *out++ = '=';
+                *out++ = '=';
+                break;
+        }
+        data += chunk;
+        len -= chunk;
+    }
+
+    return result;
+}
+

<p><p>1.2       +2 -0      libshout/src/util.h

Index: util.h
===================================================================
RCS file: /usr/local/cvsroot/libshout/src/util.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- util.h	23 Jan 2002 03:08:39 -0000	1.1
+++ util.h	16 Aug 2002 14:22:16 -0000	1.2
@@ -4,5 +4,7 @@
 #define __LIBSHOUT_UTIL_H__
 
 char *util_strdup(const char *s);
+char *util_base64_encode(char *data);
+int util_read_header(int sock, char *buff, unsigned long len);
 
 #endif /* __LIBSHOUT_UTIL_H__ */

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list