00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035
00036 #ifdef HAVE_STDIO_H
00037 #include <stdio.h>
00038 #else
00039 #error need stdio.h
00040 #endif
00041
00042 #ifdef HAVE_STRING_H
00043 #include <string.h>
00044 #else
00045 #error need string.h
00046 #endif
00047
00048 #ifdef HAVE_MATH_H
00049 #include <math.h>
00050 #else
00051 #error need math.h
00052 #endif
00053
00054
00055 #include "Exception.h"
00056 #include "Source.h"
00057 #include "Sink.h"
00058 #include "Util.h"
00059 #include "IceCast2.h"
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 static const char fileid[] = "$Id: IceCast2.cpp,v 1.12 2005/04/16 21:57:34 darkeye Exp $";
00071
00072
00073
00074
00075
00076 #define STRBUF_SIZE 32
00077
00078
00079
00080
00081
00082 static const char responseOK[] = "HTTP/1.0 200";
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 void
00094 IceCast2 :: init ( StreamFormat format,
00095 const char * mountPoint,
00096 const char * description )
00097 throw ( Exception )
00098 {
00099 this->format = format;
00100 this->mountPoint = Util::strDup( mountPoint);
00101 this->description = description ? Util::strDup( description) : 0;
00102 }
00103
00104
00105
00106
00107
00108 void
00109 IceCast2 :: strip ( void ) throw ( Exception )
00110 {
00111 delete[] mountPoint;
00112 if ( description ) {
00113 delete[] description;
00114 }
00115 }
00116
00117
00118
00119
00120
00121 bool
00122 IceCast2 :: sendLogin ( void ) throw ( Exception )
00123 {
00124 Sink * sink = getSink();
00125 Source * source = getSocket();
00126 const char * str;
00127 char resp[STRBUF_SIZE];
00128 unsigned int len;
00129 unsigned int lenExpected;
00130
00131 if ( !source->isOpen() ) {
00132 return false;
00133 }
00134 if ( !sink->isOpen() ) {
00135 return false;
00136 }
00137
00138
00139
00140 str = "SOURCE /";
00141 sink->write( str, strlen( str));
00142 str = getMountPoint();
00143 sink->write( str, strlen( str));
00144 str = " HTTP/1.0";
00145 sink->write( str, strlen( str));
00146
00147
00148 str = "\nContent-type: ";
00149 sink->write( str, strlen( str));
00150 switch ( format ) {
00151 case mp3:
00152 str = "audio/mpeg";
00153 break;
00154
00155 case oggVorbis:
00156 str = "application/ogg";
00157 break;
00158
00159 case aac:
00160 str = "audio/aac";
00161 break;
00162
00163 default:
00164 throw Exception( __FILE__, __LINE__,
00165 "unsupported stream format", format);
00166 break;
00167 }
00168 sink->write( str, strlen( str));
00169
00170
00171 str = "\nAuthorization: Basic ";
00172 sink->write( str, strlen(str));
00173 {
00174
00175 char * source = "source:";
00176 const char * pwd = getPassword();
00177 char * tmp = new char[Util::strLen(source) +
00178 Util::strLen(pwd) + 1];
00179 Util::strCpy( tmp, source);
00180 Util::strCat( tmp, pwd);
00181 char * base64 = Util::base64Encode( tmp);
00182 delete[] tmp;
00183 sink->write( base64, strlen(base64));
00184 delete[] base64;
00185 }
00186
00187
00188 str = "\nUser-Agent: DarkIce/" VERSION " (http://darkice.sourceforge.net/)";
00189 sink->write( str, strlen( str));
00190
00191
00192 str = "\nice-bitrate: ";
00193 sink->write( str, strlen( str));
00194 if ( log10(getBitRate()) >= (STRBUF_SIZE-2) ) {
00195 throw Exception( __FILE__, __LINE__,
00196 "bitrate does not fit string buffer", getBitRate());
00197 }
00198 sprintf( resp, "%d", getBitRate());
00199 sink->write( resp, strlen( resp));
00200
00201 str = "\nice-public: ";
00202 sink->write( str, strlen( str));
00203 str = getIsPublic() ? "1" : "0";
00204 sink->write( str, strlen( str));
00205
00206 if ( getName() ) {
00207 str = "\nice-name: ";
00208 sink->write( str, strlen( str));
00209 str = getName();
00210 sink->write( str, strlen( str));
00211 }
00212
00213 if ( getDescription() ) {
00214 str = "\nice-description: ";
00215 sink->write( str, strlen( str));
00216 str = getDescription();
00217 sink->write( str, strlen( str));
00218 }
00219
00220 if ( getUrl() ) {
00221 str = "\nice-url: ";
00222 sink->write( str, strlen( str));
00223 str = getUrl();
00224 sink->write( str, strlen( str));
00225 }
00226
00227 if ( getGenre() ) {
00228 str = "\nice-genre: ";
00229 sink->write( str, strlen( str));
00230 str = getGenre();
00231 sink->write( str, strlen( str));
00232 }
00233
00234 str = "\n\n";
00235 sink->write( str, strlen( str));
00236 sink->flush();
00237
00238
00239 lenExpected = Util::strLen( responseOK);
00240 if ( (len = source->read( resp, STRBUF_SIZE-1)) < lenExpected ) {
00241 return false;
00242 }
00243 resp[lenExpected] = 0;
00244 if ( !Util::strEq( resp, responseOK) ) {
00245 return false;
00246 }
00247
00248
00249 while ( source->canRead( 0, 0) &&
00250 (len = source->read( resp, STRBUF_SIZE-1)) );
00251
00252 return true;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302