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.13 2006/01/25 22:47:15 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 case mp2:
00153 str = "audio/mpeg";
00154 break;
00155
00156 case oggVorbis:
00157 str = "application/ogg";
00158 break;
00159
00160 case aac:
00161 str = "audio/aac";
00162 break;
00163
00164 default:
00165 throw Exception( __FILE__, __LINE__,
00166 "unsupported stream format", format);
00167 break;
00168 }
00169 sink->write( str, strlen( str));
00170
00171
00172 str = "\nAuthorization: Basic ";
00173 sink->write( str, strlen(str));
00174 {
00175
00176 char * source = "source:";
00177 const char * pwd = getPassword();
00178 char * tmp = new char[Util::strLen(source) +
00179 Util::strLen(pwd) + 1];
00180 Util::strCpy( tmp, source);
00181 Util::strCat( tmp, pwd);
00182 char * base64 = Util::base64Encode( tmp);
00183 delete[] tmp;
00184 sink->write( base64, strlen(base64));
00185 delete[] base64;
00186 }
00187
00188
00189 str = "\nUser-Agent: DarkIce/" VERSION " (http://darkice.sourceforge.net/)";
00190 sink->write( str, strlen( str));
00191
00192
00193 str = "\nice-bitrate: ";
00194 sink->write( str, strlen( str));
00195 if ( log10(getBitRate()) >= (STRBUF_SIZE-2) ) {
00196 throw Exception( __FILE__, __LINE__,
00197 "bitrate does not fit string buffer", getBitRate());
00198 }
00199 sprintf( resp, "%d", getBitRate());
00200 sink->write( resp, strlen( resp));
00201
00202 str = "\nice-public: ";
00203 sink->write( str, strlen( str));
00204 str = getIsPublic() ? "1" : "0";
00205 sink->write( str, strlen( str));
00206
00207 if ( getName() ) {
00208 str = "\nice-name: ";
00209 sink->write( str, strlen( str));
00210 str = getName();
00211 sink->write( str, strlen( str));
00212 }
00213
00214 if ( getDescription() ) {
00215 str = "\nice-description: ";
00216 sink->write( str, strlen( str));
00217 str = getDescription();
00218 sink->write( str, strlen( str));
00219 }
00220
00221 if ( getUrl() ) {
00222 str = "\nice-url: ";
00223 sink->write( str, strlen( str));
00224 str = getUrl();
00225 sink->write( str, strlen( str));
00226 }
00227
00228 if ( getGenre() ) {
00229 str = "\nice-genre: ";
00230 sink->write( str, strlen( str));
00231 str = getGenre();
00232 sink->write( str, strlen( str));
00233 }
00234
00235 str = "\n\n";
00236 sink->write( str, strlen( str));
00237 sink->flush();
00238
00239
00240 lenExpected = Util::strLen( responseOK);
00241 if ( (len = source->read( resp, STRBUF_SIZE-1)) < lenExpected ) {
00242 return false;
00243 }
00244 resp[lenExpected] = 0;
00245 if ( !Util::strEq( resp, responseOK) ) {
00246 return false;
00247 }
00248
00249
00250 while ( source->canRead( 0, 0) &&
00251 (len = source->read( resp, STRBUF_SIZE-1)) );
00252
00253 return true;
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
00303
00304
00305
00306