Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Xiph.Org
Icecast-Server
Commits
2896db1f
Commit
2896db1f
authored
Jun 03, 2005
by
Karl Heyes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
merge intro file implementation
svn path=/icecast/trunk/icecast/; revision=9345
parent
72ad63f7
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
195 additions
and
63 deletions
+195
-63
doc/icecast2_config_file.html
doc/icecast2_config_file.html
+10
-0
src/cfgfile.c
src/cfgfile.c
+5
-0
src/cfgfile.h
src/cfgfile.h
+1
-0
src/client.c
src/client.c
+2
-0
src/client.h
src/client.h
+7
-0
src/connection.c
src/connection.c
+2
-0
src/format.c
src/format.c
+124
-0
src/format.h
src/format.h
+3
-6
src/format_mp3.c
src/format_mp3.c
+2
-15
src/format_ogg.c
src/format_ogg.c
+2
-12
src/source.c
src/source.c
+35
-30
src/source.h
src/source.h
+2
-0
No files found.
doc/icecast2_config_file.html
View file @
2896db1f
...
...
@@ -345,6 +345,7 @@ If you are relaying a Shoutcast stream, you need to specify this indicator to al
<
password
>
hackmemore
<
/password
>
<
max-listeners
>
1
<
/max-listeners
>
<
dump-file
>
/tmp/dump-example1.ogg
<
/dump-file
>
<
intro
>
/intro.ogg
<
/intro
>
<
fallback-mount
>
/example2.ogg
<
/fallback-mount
>
<
fallback-override
>
1
<
/fallback-override
>
<
public
>
1
<
/public
>
...
...
@@ -396,6 +397,15 @@ An optional value which will set the maximum number of listeners that can be att
<div
class=
"indentedbox"
>
An optional value which will set the filename which will be a dump of the stream coming through on this mountpoint.
</div>
<h4>
intro
</h4>
<div
class=
"indentedbox"
>
<p>
An optional value which will specify the file those contents will be sent to new listeners
when they connect but before the normal stream is sent. Make sure the format of the file
specified matches the streaming format. The specified file is appended to webroot before
being opened.
</p>
</div>
<h4>
fallback-mount
</h4>
<div
class=
"indentedbox"
>
This optional value specifies a mountpoint that clients are automatically moved to if the source
...
...
src/cfgfile.c
View file @
2896db1f
...
...
@@ -190,6 +190,7 @@ void config_clear(ice_config_t *c)
xmlFree
(
mount
->
username
);
xmlFree
(
mount
->
password
);
xmlFree
(
mount
->
dumpfile
);
xmlFree
(
mount
->
intro_filename
);
xmlFree
(
mount
->
fallback_mount
);
xmlFree
(
mount
->
stream_name
);
xmlFree
(
mount
->
stream_description
);
...
...
@@ -558,6 +559,10 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
mount
->
dumpfile
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
strcmp
(
node
->
name
,
"intro"
)
==
0
)
{
mount
->
intro_filename
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
strcmp
(
node
->
name
,
"fallback-mount"
)
==
0
)
{
mount
->
fallback_mount
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
...
...
src/cfgfile.h
View file @
2896db1f
...
...
@@ -46,6 +46,7 @@ typedef struct _mount_proxy {
char
*
dumpfile
;
/* Filename to dump this stream to (will be appended). NULL
to not dump. */
char
*
intro_filename
;
/* Send contents of file to client before the stream */
int
max_listeners
;
/* Max listeners for this mountpoint only. -1 to not
limit here (i.e. only use the global limit) */
char
*
fallback_mount
;
/* Fallback mountname */
...
...
src/client.c
View file @
2896db1f
...
...
@@ -30,6 +30,7 @@
#include "cfgfile.h"
#include "connection.h"
#include "refbuf.h"
#include "format.h"
#include "stats.h"
#include "client.h"
...
...
@@ -62,6 +63,7 @@ client_t *client_create(connection_t *con, http_parser_t *parser)
client
->
parser
=
parser
;
client
->
refbuf
=
NULL
;
client
->
pos
=
0
;
client
->
check_buffer
=
format_advance_queue
;
return
client
;
}
...
...
src/client.h
View file @
2896db1f
...
...
@@ -32,6 +32,9 @@ typedef struct _client_tag
/* http response code for this client */
int
respcode
;
/* is client getting intro data */
long
intro_offset
;
/* where in the queue the client is */
refbuf_t
*
refbuf
;
...
...
@@ -46,6 +49,10 @@ typedef struct _client_tag
/* function to call to release format specific resources */
void
(
*
free_client_data
)(
struct
_client_tag
*
client
);
/* function to check if refbuf needs updating */
int
(
*
check_buffer
)(
struct
source_tag
*
source
,
struct
_client_tag
*
client
);
}
client_t
;
client_t
*
client_create
(
connection_t
*
con
,
http_parser_t
*
parser
);
...
...
src/connection.c
View file @
2896db1f
...
...
@@ -952,6 +952,8 @@ static void _handle_get_request (client_t *client, char *passed_uri)
sock_set_blocking
(
client
->
con
->
sock
,
SOCK_NONBLOCK
);
sock_set_nodelay
(
client
->
con
->
sock
);
client
->
check_buffer
=
format_check_file_buffer
;
avl_tree_wlock
(
source
->
pending_tree
);
avl_insert
(
source
->
pending_tree
,
(
void
*
)
client
);
...
...
src/format.c
View file @
2896db1f
...
...
@@ -81,6 +81,130 @@ int format_get_plugin(format_type_t type, source_t *source)
return
ret
;
}
/* clients need to be start from somewhere in the queue so we will look for
* a refbuf which has been previously marked as a sync point.
*/
static
void
find_client_start
(
source_t
*
source
,
client_t
*
client
)
{
refbuf_t
*
refbuf
=
source
->
burst_point
;
/* we only want to attempt a burst at connection time, not midstream */
if
(
client
->
intro_offset
==
-
1
)
refbuf
=
source
->
stream_data_tail
;
else
{
long
size
=
0
;
refbuf
=
source
->
burst_point
;
size
=
source
->
burst_size
-
client
->
intro_offset
;
while
(
size
>
0
&&
refbuf
->
next
)
{
size
-=
refbuf
->
len
;
refbuf
=
refbuf
->
next
;
}
}
while
(
refbuf
)
{
if
(
refbuf
->
sync_point
)
{
client_set_queue
(
client
,
refbuf
);
client
->
check_buffer
=
format_advance_queue
;
client
->
intro_offset
=
-
1
;
break
;
}
refbuf
=
refbuf
->
next
;
}
}
static
int
get_file_data
(
FILE
*
intro
,
client_t
*
client
)
{
refbuf_t
*
refbuf
=
client
->
refbuf
;
int
bytes
;
if
(
intro
==
NULL
||
fseek
(
intro
,
client
->
intro_offset
,
SEEK_SET
)
<
0
)
return
0
;
bytes
=
fread
(
refbuf
->
data
,
1
,
4096
,
intro
);
if
(
bytes
==
0
)
return
0
;
refbuf
->
len
=
bytes
;
return
1
;
}
/* call to check the buffer contents for file reading. move the client
* to right place in the queue at end of file else repeat file if queue
* is not ready yet.
*/
int
format_check_file_buffer
(
source_t
*
source
,
client_t
*
client
)
{
refbuf_t
*
refbuf
=
client
->
refbuf
;
if
(
refbuf
==
NULL
)
{
if
(
source
->
intro_file
&&
client
->
intro_offset
==
0
)
{
refbuf
=
refbuf_new
(
4096
);
client
->
refbuf
=
refbuf
;
client
->
pos
=
refbuf
->
len
;
}
else
{
find_client_start
(
source
,
client
);
return
-
1
;
}
}
if
(
client
->
pos
==
refbuf
->
len
)
{
if
(
get_file_data
(
source
->
intro_file
,
client
))
{
client
->
pos
=
0
;
client
->
intro_offset
+=
refbuf
->
len
;
}
else
{
if
(
source
->
stream_data_tail
)
{
/* better find the right place in queue for this client */
client
->
intro_offset
=
-
1
;
client_set_queue
(
client
,
NULL
);
find_client_start
(
source
,
client
);
}
else
client
->
intro_offset
=
0
;
/* replay intro file */
return
-
1
;
}
}
return
0
;
}
/* This is the commonly used for source streams, here we just progress to
* the next buffer in the queue if there is no more left to be written from
* the existing buffer.
*/
int
format_advance_queue
(
source_t
*
source
,
client_t
*
client
)
{
refbuf_t
*
refbuf
=
client
->
refbuf
;
if
(
refbuf
==
NULL
)
return
-
1
;
if
(
refbuf
->
next
==
NULL
&&
client
->
pos
==
refbuf
->
len
)
return
-
1
;
/* move to the next buffer if we have finished with the current one */
if
(
refbuf
->
next
&&
client
->
pos
==
refbuf
->
len
)
{
client_set_queue
(
client
,
refbuf
->
next
);
refbuf
=
client
->
refbuf
;
}
return
0
;
}
void
format_send_general_headers
(
format_plugin_t
*
format
,
source_t
*
source
,
client_t
*
client
)
{
...
...
src/format.h
View file @
2896db1f
...
...
@@ -61,14 +61,11 @@ format_type_t format_get_type(char *contenttype);
char
*
format_get_mimetype
(
format_type_t
type
);
int
format_get_plugin
(
format_type_t
type
,
struct
source_tag
*
source
);
int
format_advance_queue
(
struct
source_tag
*
source
,
client_t
*
client
);
int
format_check_file_buffer
(
struct
source_tag
*
source
,
client_t
*
client
);
void
format_send_general_headers
(
format_plugin_t
*
format
,
struct
source_tag
*
source
,
client_t
*
client
);
#endif
/* __FORMAT_H__ */
src/format_mp3.c
View file @
2896db1f
...
...
@@ -326,21 +326,8 @@ static int format_mp3_write_buf_to_client (format_plugin_t *self, client_t *clie
int
ret
,
written
=
0
;
mp3_client_data
*
client_mp3
=
client
->
format_data
;
refbuf_t
*
refbuf
=
client
->
refbuf
;
char
*
buf
;
unsigned
int
len
;
if
(
refbuf
->
next
==
NULL
&&
client
->
pos
==
refbuf
->
len
)
return
0
;
/* move to the next buffer if we have finished with the current one */
if
(
refbuf
->
next
&&
client
->
pos
==
refbuf
->
len
)
{
client_set_queue
(
client
,
refbuf
->
next
);
refbuf
=
client
->
refbuf
;
}
buf
=
refbuf
->
data
+
client
->
pos
;
len
=
refbuf
->
len
-
client
->
pos
;
char
*
buf
=
refbuf
->
data
+
client
->
pos
;
unsigned
int
len
=
refbuf
->
len
-
client
->
pos
;
do
{
...
...
src/format_ogg.c
View file @
2896db1f
...
...
@@ -504,21 +504,11 @@ static int send_ogg_headers (client_t *client, refbuf_t *headers)
static
int
write_buf_to_client
(
format_plugin_t
*
self
,
client_t
*
client
)
{
refbuf_t
*
refbuf
=
client
->
refbuf
;
char
*
buf
;
unsigned
len
;
char
*
buf
=
refbuf
->
data
+
client
->
pos
;
unsigned
len
=
refbuf
->
len
-
client
->
pos
;
struct
ogg_client
*
client_data
=
client
->
format_data
;
int
ret
,
written
=
0
;
if
(
refbuf
->
next
==
NULL
&&
client
->
pos
==
refbuf
->
len
)
return
0
;
if
(
refbuf
->
next
&&
client
->
pos
==
refbuf
->
len
)
{
client_set_queue
(
client
,
refbuf
->
next
);
refbuf
=
client
->
refbuf
;
}
buf
=
refbuf
->
data
+
client
->
pos
;
len
=
refbuf
->
len
-
client
->
pos
;
do
{
if
(
client_data
->
headers
!=
refbuf
->
associated
)
...
...
src/source.c
View file @
2896db1f
...
...
@@ -48,6 +48,7 @@
#include "source.h"
#include "format.h"
#include "auth.h"
#include "os.h"
#undef CATMODULE
#define CATMODULE "source"
...
...
@@ -250,6 +251,12 @@ void source_clear_source (source_t *source)
free
(
source
->
dumpfilename
);
source
->
dumpfilename
=
NULL
;
if
(
source
->
intro_file
)
{
fclose
(
source
->
intro_file
);
source
->
intro_file
=
NULL
;
}
}
...
...
@@ -344,7 +351,8 @@ void source_move_clients (source_t *source, source_t *dest)
avl_delete
(
source
->
pending_tree
,
client
,
NULL
);
/* switch client to different queue */
client_set_queue
(
client
,
dest
->
stream_data_tail
);
client_set_queue
(
client
,
NULL
);
client
->
check_buffer
=
format_check_file_buffer
;
avl_insert
(
dest
->
pending_tree
,
(
void
*
)
client
);
}
...
...
@@ -359,7 +367,8 @@ void source_move_clients (source_t *source, source_t *dest)
avl_delete
(
source
->
client_tree
,
client
,
NULL
);
/* switch client to different queue */
client_set_queue
(
client
,
dest
->
stream_data_tail
);
client_set_queue
(
client
,
NULL
);
client
->
check_buffer
=
format_check_file_buffer
;
avl_insert
(
dest
->
pending_tree
,
(
void
*
)
client
);
}
source
->
listeners
=
0
;
...
...
@@ -374,25 +383,6 @@ void source_move_clients (source_t *source, source_t *dest)
}
/* clients need to be start from somewhere in the queue
* so we will look for a refbuf which has been previous
* marked as a sync point */
static
void
find_client_start
(
source_t
*
source
,
client_t
*
client
)
{
refbuf_t
*
refbuf
=
source
->
burst_point
;
while
(
refbuf
)
{
if
(
refbuf
->
sync_point
)
{
client_set_queue
(
client
,
refbuf
);
break
;
}
refbuf
=
refbuf
->
next
;
}
}
/* get some data from the source. The stream data is placed in a refbuf
* and sent back, however NULL is also valid as in the case of a short
* timeout and there's no data pending.
...
...
@@ -466,14 +456,6 @@ static void send_to_listener (source_t *source, client_t *client, int deletion_e
int
loop
=
10
;
/* max number of iterations in one go */
int
total_written
=
0
;
/* new users need somewhere to start from */
if
(
client
->
refbuf
==
NULL
)
{
find_client_start
(
source
,
client
);
if
(
client
->
refbuf
==
NULL
)
return
;
}
while
(
1
)
{
/* jump out if client connection has died */
...
...
@@ -490,6 +472,9 @@ static void send_to_listener (source_t *source, client_t *client, int deletion_e
loop
--
;
if
(
client
->
check_buffer
(
source
,
client
)
<
0
)
break
;
bytes
=
source
->
format
->
write_buf_to_client
(
source
->
format
,
client
);
if
(
bytes
<=
0
)
break
;
/* can't write any more */
...
...
@@ -500,7 +485,7 @@ static void send_to_listener (source_t *source, client_t *client, int deletion_e
/* the refbuf referenced at head (last in queue) may be marked for deletion
* if so, check to see if this client is still referring to it */
if
(
deletion_expected
&&
client
->
refbuf
==
source
->
stream_data
)
if
(
deletion_expected
&&
client
->
refbuf
&&
client
->
refbuf
==
source
->
stream_data
)
{
DEBUG0
(
"Client has fallen too far behind, removing"
);
client
->
con
->
error
=
1
;
...
...
@@ -1012,6 +997,24 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
else
source
->
dumpfilename
=
NULL
;
if
(
mountinfo
&&
mountinfo
->
intro_filename
&&
source
->
intro_file
==
NULL
)
{
ice_config_t
*
config
=
config_get_config_unlocked
();
unsigned
int
len
=
strlen
(
config
->
webroot_dir
)
+
strlen
(
mountinfo
->
intro_filename
)
+
2
;
char
*
path
=
malloc
(
len
);
if
(
path
)
{
snprintf
(
path
,
len
,
"%s"
PATH_SEPARATOR
"%s"
,
config
->
webroot_dir
,
mountinfo
->
intro_filename
);
source
->
intro_file
=
fopen
(
path
,
"rb"
);
if
(
source
->
intro_file
==
NULL
)
WARN2
(
"Cannot open intro file
\"
%s
\"
: %s"
,
path
,
strerror
(
errno
));
free
(
path
);
}
}
if
(
mountinfo
&&
mountinfo
->
queue_size_limit
)
source
->
queue_size_limit
=
mountinfo
->
queue_size_limit
;
...
...
@@ -1040,6 +1043,8 @@ void source_update_settings (ice_config_t *config, source_t *source, mount_proxy
if
(
source
->
fallback_mount
)
DEBUG1
(
"fallback %s"
,
source
->
fallback_mount
);
if
(
mountinfo
&&
mountinfo
->
intro_filename
)
DEBUG1
(
"intro file is %s"
,
mountinfo
->
intro_filename
);
if
(
source
->
dumpfilename
)
DEBUG1
(
"Dumping stream to %s"
,
source
->
dumpfilename
);
if
(
source
->
hidden
)
...
...
src/source.h
View file @
2896db1f
...
...
@@ -46,6 +46,8 @@ typedef struct source_tag
rwlock_t
*
shutdown_rwlock
;
util_dict
*
audio_info
;
FILE
*
intro_file
;
char
*
dumpfilename
;
/* Name of a file to dump incoming stream to */
FILE
*
dumpfile
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment