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
f1dc57ae
Commit
f1dc57ae
authored
Aug 05, 2002
by
Michael Smith
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleaned up version of Ciaran Anscomb's relaying patch.
svn path=/trunk/httpp/; revision=3760
parent
3727b2b3
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
437 additions
and
126 deletions
+437
-126
TODO
TODO
+4
-0
conf/icecast.xml
conf/icecast.xml
+10
-6
src/Makefile.am
src/Makefile.am
+2
-2
src/config.c
src/config.c
+22
-2
src/config.h
src/config.h
+3
-0
src/connection.c
src/connection.c
+83
-56
src/connection.h
src/connection.h
+8
-0
src/global.h
src/global.h
+4
-0
src/httpp/httpp.c
src/httpp/httpp.c
+133
-57
src/httpp/httpp.h
src/httpp/httpp.h
+2
-1
src/main.c
src/main.c
+5
-0
src/net/resolver.c
src/net/resolver.c
+1
-0
src/slave.c
src/slave.c
+135
-0
src/slave.h
src/slave.h
+7
-0
src/source.c
src/source.c
+2
-2
src/thread/thread.c
src/thread/thread.c
+14
-0
src/thread/thread.h
src/thread/thread.h
+2
-0
No files found.
TODO
View file @
f1dc57ae
...
...
@@ -27,3 +27,7 @@ FEATURES
- support W3C Extended Logging (http://www.w3.org/TR/WD-logfile.html)
toggle between this and Apache Combined Log Format in the config file.
default to apache style.
- allow using get_predata() stuff to send an "intro" to any newly-connected
user?
conf/icecast.xml
View file @
f1dc57ae
...
...
@@ -3,12 +3,12 @@
<admin>
jack@icecast.org
</admin>
<limits>
<clients>
1
00
</clients>
<clients>
20
00
</clients>
<sources>
2
</sources>
<threadpool>
5
</threadpool>
<client-timeout>
30
</client-timeout>
<header-timeout>
15
</header-timeout>
<source-timeout>
10
</source-timeout>
<source-timeout>
10
0
</source-timeout>
</limits>
<source-password>
hackme
</source-password>
...
...
@@ -25,8 +25,12 @@
<port>
8000
</port>
<!--<bind-address>127.0.0.1</bind-address>-->
<!--<master-server>127.0.0.1</master-server>-->
<!--<master-server-port>8001</master-server-port>-->
<!--<master-update-interval>120</master-update-interval>-->
<paths>
<basedir>
/
usr/local
/icecast
</basedir>
<basedir>
/
home/msmith/icecast
/icecast
</basedir>
<logdir>
/tmp
</logdir>
</paths>
...
...
@@ -37,9 +41,9 @@
<security>
<chroot>
0
</chroot>
<!--<changeowner>
<user>
nobody
</user>
<!--
<changeowner>
<user>
msmith
</user>
<group>nogroup</group>
</changeowner> -->
</changeowner>
-->
</security>
</icecast>
src/Makefile.am
View file @
f1dc57ae
...
...
@@ -7,10 +7,10 @@ SUBDIRS = avl thread httpp net log timing
bin_PROGRAMS
=
icecast
noinst_HEADERS
=
config.h os.h logging.h sighandler.h connection.h global.h
\
util.h source.h stats.h refbuf.h client.h format.h format_vorbis.h
\
util.h
slave.h
source.h stats.h refbuf.h client.h format.h format_vorbis.h
\
compat.h format_mp3.h
icecast_SOURCES
=
config.c main.c logging.c sighandler.c connection.c global.c
\
util.c source.c stats.c refbuf.c client.c format.c format_vorbis.c
\
util.c
slave.c
source.c stats.c refbuf.c client.c format.c format_vorbis.c
\
format_mp3.c
icecast_LDADD
=
net/libicenet.la thread/libicethread.la httpp/libicehttpp.la
\
...
...
src/config.c
View file @
f1dc57ae
...
...
@@ -23,6 +23,7 @@
#define CONFIG_DEFAULT_CHUID 0
#define CONFIG_DEFAULT_USER NULL
#define CONFIG_DEFAULT_GROUP NULL
#define CONFIG_MASTER_UPDATE_INTERVAL 120
#ifndef _WIN32
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
...
...
@@ -141,6 +142,9 @@ static void _set_defaults(void)
_configuration
.
hostname
=
(
char
*
)
strdup
(
CONFIG_DEFAULT_HOSTNAME
);
_configuration
.
port
=
CONFIG_DEFAULT_PORT
;
_configuration
.
bind_address
=
NULL
;
_configuration
.
master_server
=
NULL
;
_configuration
.
master_server_port
=
CONFIG_DEFAULT_PORT
;
_configuration
.
master_update_interval
=
CONFIG_MASTER_UPDATE_INTERVAL
;
_configuration
.
base_dir
=
(
char
*
)
strdup
(
CONFIG_DEFAULT_BASE_DIR
);
_configuration
.
log_dir
=
(
char
*
)
strdup
(
CONFIG_DEFAULT_LOG_DIR
);
_configuration
.
access_log
=
(
char
*
)
strdup
(
CONFIG_DEFAULT_ACCESS_LOG
);
...
...
@@ -166,8 +170,15 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
if
(
_configuration
.
admin
)
free
(
_configuration
.
admin
);
_configuration
.
admin
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
strcmp
(
node
->
name
,
"source-password"
)
==
0
)
{
if
(
_configuration
.
source_password
)
free
(
_configuration
.
source_password
);
_configuration
.
source_password
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
char
*
mount
,
*
pass
;
if
((
mount
=
(
char
*
)
xmlGetProp
(
node
,
"mount"
))
!=
NULL
)
{
pass
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
/* FIXME: This is a placeholder for per-mount passwords */
}
else
{
if
(
_configuration
.
source_password
)
free
(
_configuration
.
source_password
);
_configuration
.
source_password
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
}
else
if
(
strcmp
(
node
->
name
,
"hostname"
)
==
0
)
{
if
(
_configuration
.
hostname
)
free
(
_configuration
.
hostname
);
_configuration
.
hostname
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
...
...
@@ -178,6 +189,15 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
}
else
if
(
strcmp
(
node
->
name
,
"bind-address"
)
==
0
)
{
if
(
_configuration
.
bind_address
)
free
(
_configuration
.
bind_address
);
_configuration
.
bind_address
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
strcmp
(
node
->
name
,
"master-server"
)
==
0
)
{
if
(
_configuration
.
master_server
)
free
(
_configuration
.
master_server
);
_configuration
.
master_server
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
strcmp
(
node
->
name
,
"master-server-port"
)
==
0
)
{
tmp
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
_configuration
.
master_server_port
=
atoi
(
tmp
);
}
else
if
(
strcmp
(
node
->
name
,
"master-update-interval"
)
==
0
)
{
tmp
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
_configuration
.
master_update_interval
=
atoi
(
tmp
);
}
else
if
(
strcmp
(
node
->
name
,
"limits"
)
==
0
)
{
_parse_limits
(
doc
,
node
->
xmlChildrenNode
);
}
else
if
(
strcmp
(
node
->
name
,
"directory"
)
==
0
)
{
...
...
src/config.h
View file @
f1dc57ae
...
...
@@ -33,6 +33,9 @@ typedef struct ice_config_tag
char
*
hostname
;
int
port
;
char
*
bind_address
;
char
*
master_server
;
int
master_server_port
;
int
master_update_interval
;
char
*
base_dir
;
char
*
log_dir
;
...
...
src/connection.c
View file @
f1dc57ae
...
...
@@ -57,7 +57,7 @@ static mutex_t _queue_mutex;
static
thread_queue_t
*
_conhands
=
NULL
;
static
rwlock_t
_source_shutdown_rwlock
;
rwlock_t
_source_shutdown_rwlock
;
static
void
*
_handle_connection
(
void
*
arg
);
...
...
@@ -69,6 +69,7 @@ void connection_initialize(void)
thread_mutex_create
(
&
_queue_mutex
);
thread_rwlock_create
(
&
_source_shutdown_rwlock
);
thread_cond_create
(
&
_pool_cond
);
thread_cond_create
(
&
global
.
shutdown_cond
);
_initialized
=
1
;
}
...
...
@@ -77,6 +78,7 @@ void connection_shutdown(void)
{
if
(
!
_initialized
)
return
;
thread_cond_destroy
(
&
global
.
shutdown_cond
);
thread_cond_destroy
(
&
_pool_cond
);
thread_rwlock_destroy
(
&
_source_shutdown_rwlock
);
thread_mutex_destroy
(
&
_queue_mutex
);
...
...
@@ -85,16 +87,6 @@ void connection_shutdown(void)
_initialized
=
0
;
}
static
connection_t
*
_create_connection
(
void
)
{
connection_t
*
con
;
con
=
(
connection_t
*
)
malloc
(
sizeof
(
connection_t
));
memset
(
con
,
0
,
sizeof
(
connection_t
));
return
con
;
}
static
unsigned
long
_next_connection_id
(
void
)
{
unsigned
long
id
;
...
...
@@ -106,6 +98,17 @@ static unsigned long _next_connection_id(void)
return
id
;
}
connection_t
*
create_connection
(
sock_t
sock
,
char
*
ip
)
{
connection_t
*
con
;
con
=
(
connection_t
*
)
malloc
(
sizeof
(
connection_t
));
memset
(
con
,
0
,
sizeof
(
connection_t
));
con
->
sock
=
sock
;
con
->
con_time
=
time
(
NULL
);
con
->
id
=
_next_connection_id
();
con
->
ip
=
ip
;
return
con
;
}
static
connection_t
*
_accept_connection
(
void
)
{
int
sock
;
...
...
@@ -121,12 +124,7 @@ static connection_t *_accept_connection(void)
sock
=
sock_accept
(
global
.
serversock
,
ip
,
16
);
if
(
sock
>=
0
)
{
con
=
_create_connection
();
con
->
sock
=
sock
;
con
->
con_time
=
time
(
NULL
);
con
->
id
=
_next_connection_id
();
con
->
ip
=
ip
;
con
=
create_connection
(
sock
,
ip
);
return
con
;
}
...
...
@@ -246,6 +244,9 @@ void connection_accept_loop(void)
}
}
/* Give all the other threads notification to shut down */
thread_cond_broadcast
(
&
global
.
shutdown_cond
);
_destroy_pool
();
/* wait for all the sources to shutdown */
...
...
@@ -283,6 +284,44 @@ static connection_t *_get_connection(void)
return
con
;
}
int
connection_create_source
(
connection_t
*
con
,
http_parser_t
*
parser
,
char
*
mount
)
{
source_t
*
source
;
char
*
contenttype
;
/* check to make sure this source wouldn't
** be over the limit
*/
global_lock
();
if
(
global
.
sources
>=
config_get_config
()
->
source_limit
)
{
printf
(
"TOO MANY SOURCE, KICKING THIS ONE
\n
"
);
INFO1
(
"Source (%s) logged in, but there are too many sources"
,
mount
);
global_unlock
();
return
0
;
}
global
.
sources
++
;
global_unlock
();
stats_event_inc
(
NULL
,
"sources"
);
contenttype
=
httpp_getvar
(
parser
,
"content-type"
);
if
(
contenttype
!=
NULL
)
{
format_type_t
format
=
format_get_type
(
contenttype
);
if
(
format
<
0
)
{
WARN1
(
"Content-type
\"
%s
\"
not supported, dropping source"
,
contenttype
);
return
0
;
}
else
{
source
=
source_create
(
con
,
parser
,
mount
,
format
);
}
}
else
{
WARN0
(
"No content-type header, cannot handle source"
);
return
0
;
}
source
->
shutdown_rwlock
=
&
_source_shutdown_rwlock
;
sock_set_blocking
(
con
->
sock
,
SOCK_NONBLOCK
);
thread_create
(
"Source Thread"
,
source_main
,
(
void
*
)
source
,
THREAD_DETACHED
);
return
1
;
}
static
void
*
_handle_connection
(
void
*
arg
)
{
char
header
[
4096
];
...
...
@@ -327,8 +366,6 @@ static void *_handle_connection(void *arg)
}
if
(
parser
->
req_type
==
httpp_req_source
)
{
char
*
contenttype
;
printf
(
"DEBUG: source logging in
\n
"
);
stats_event_inc
(
NULL
,
"source_connections"
);
...
...
@@ -355,47 +392,11 @@ static void *_handle_connection(void *arg)
}
avl_tree_unlock
(
global
.
source_tree
);
/* check to make sure this source wouldn't
** be over the limit
*/
global_lock
();
if
(
global
.
sources
>=
config_get_config
()
->
source_limit
)
{
printf
(
"TOO MANY SOURCE, KICKING THIS ONE
\n
"
);
INFO1
(
"Source (%s) logged in, but there are too many sources"
,
httpp_getvar
(
parser
,
HTTPP_VAR_URI
));
if
(
!
connection_create_source
(
con
,
parser
,
httpp_getvar
(
parser
,
HTTPP_VAR_URI
)))
{
connection_close
(
con
);
httpp_destroy
(
parser
);
global_unlock
();
continue
;
}
global
.
sources
++
;
global_unlock
();
stats_event_inc
(
NULL
,
"sources"
);
contenttype
=
httpp_getvar
(
parser
,
"content-type"
);
if
(
contenttype
!=
NULL
)
{
format_type_t
format
=
format_get_type
(
contenttype
);
if
(
format
<
0
)
{
WARN1
(
"Content-type
\"
%s
\"
not supported, dropping source"
,
contenttype
);
connection_close
(
con
);
httpp_destroy
(
parser
);
continue
;
}
else
{
source
=
source_create
(
con
,
parser
,
httpp_getvar
(
parser
,
HTTPP_VAR_URI
),
format
);
}
}
else
{
WARN0
(
"No content-type header, cannot handle source"
);
connection_close
(
con
);
httpp_destroy
(
parser
);
continue
;
}
source
->
shutdown_rwlock
=
&
_source_shutdown_rwlock
;
sock_set_blocking
(
con
->
sock
,
SOCK_NONBLOCK
);
thread_create
(
"Source Thread"
,
source_main
,
(
void
*
)
source
,
THREAD_DETACHED
);
continue
;
}
else
if
(
parser
->
req_type
==
httpp_req_stats
)
{
printf
(
"DEBUG: stats connection...
\n
"
);
...
...
@@ -438,6 +439,32 @@ static void *_handle_connection(void *arg)
stats_sendxml
(
client
);
continue
;
}
if
(
strcmp
(
httpp_getvar
(
parser
,
HTTPP_VAR_URI
),
"/allstreams.txt"
)
==
0
)
{
if
(
strcmp
((
httpp_getvar
(
parser
,
"ice-password"
)
!=
NULL
)
?
httpp_getvar
(
parser
,
"ice-password"
)
:
""
,
(
config_get_config
()
->
source_password
!=
NULL
)
?
config_get_config
()
->
source_password
:
""
)
!=
0
)
{
printf
(
"DEBUG: bad password for allstreams.txt
\n
"
);
INFO0
(
"Client attempted to fetch allstreams.txt with bad password"
);
if
(
parser
->
req_type
==
httpp_req_get
)
{
client
->
respcode
=
404
;
bytes
=
sock_write
(
client
->
con
->
sock
,
"HTTP/1.0 404 Source Not Found
\r\n
Content-Type: text/html
\r\n\r\n
"
\
"<b>The source you requested could not be found.</b>
\r\n
"
);
if
(
bytes
>
0
)
client
->
con
->
sent_bytes
=
bytes
;
}
}
else
{
avl_node
*
node
;
source_t
*
s
;
avl_tree_rlock
(
global
.
source_tree
);
node
=
avl_get_first
(
global
.
source_tree
);
while
(
node
)
{
s
=
(
source_t
*
)
node
->
key
;
sock_write
(
client
->
con
->
sock
,
"%s
\r\n
"
,
s
->
mount
);
node
=
avl_get_next
(
node
);
}
avl_tree_unlock
(
global
.
source_tree
);
}
client_destroy
(
client
);
continue
;
}
global_lock
();
if
(
global
.
clients
>=
config_get_config
()
->
client_limit
)
{
...
...
src/connection.h
View file @
f1dc57ae
...
...
@@ -3,6 +3,9 @@
#include <sys/types.h>
#include "compat.h"
#include "httpp.h"
#include "thread.h"
#include "sock.h"
typedef
struct
connection_tag
{
...
...
@@ -22,5 +25,10 @@ void connection_initialize(void);
void
connection_shutdown
(
void
);
void
connection_accept_loop
(
void
);
void
connection_close
(
connection_t
*
con
);
connection_t
*
create_connection
(
sock_t
sock
,
char
*
ip
);
int
connection_create_source
(
connection_t
*
con
,
http_parser_t
*
parser
,
char
*
mount
);
extern
rwlock_t
_source_shutdown_rwlock
;
#endif
/* __CONNECTION_H__ */
src/global.h
View file @
f1dc57ae
...
...
@@ -6,6 +6,8 @@
#define ICE_RUNNING 1
#define ICE_HALTING 2
#include "thread/thread.h"
typedef
struct
ice_global_tag
{
int
serversock
;
...
...
@@ -16,6 +18,8 @@ typedef struct ice_global_tag
int
clients
;
avl_tree
*
source_tree
;
cond_t
shutdown_cond
;
}
ice_global_t
;
extern
ice_global_t
global
;
...
...
src/httpp/httpp.c
View file @
f1dc57ae
...
...
@@ -49,33 +49,12 @@ void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults)
}
}
int
httpp_parse
(
http_parser_t
*
parser
,
char
*
http_
data
,
unsigned
long
len
)
static
int
split_headers
(
char
*
data
,
unsigned
long
len
,
char
**
line
)
{
char
*
data
,
*
tmp
;
char
*
line
[
MAX_HEADERS
];
/* limited to 32 lines, should be more than enough */
int
i
,
l
,
retlen
;
int
lines
;
char
*
req_type
=
NULL
;
char
*
uri
=
NULL
;
char
*
version
=
NULL
;
char
*
name
=
NULL
;
char
*
value
=
NULL
;
int
whitespace
,
where
;
int
slen
;
if
(
http_data
==
NULL
)
return
0
;
/* make a local copy of the data, including 0 terminator */
data
=
(
char
*
)
malloc
(
len
+
1
);
if
(
data
==
NULL
)
return
0
;
memcpy
(
data
,
http_data
,
len
);
data
[
len
]
=
0
;
/* first we count how many lines there are
** and set up the line[] array
*/
lines
=
0
;
int
i
,
lines
=
0
;
line
[
lines
]
=
data
;
for
(
i
=
0
;
i
<
len
&&
lines
<
MAX_HEADERS
;
i
++
)
{
if
(
data
[
i
]
==
'\r'
)
...
...
@@ -93,7 +72,134 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
i
++
;
while
(
data
[
i
]
==
'\n'
)
i
++
;
retlen
=
i
;
return
lines
;
}
static
void
parse_headers
(
http_parser_t
*
parser
,
char
**
line
,
int
lines
)
{
int
i
,
l
;
int
whitespace
,
where
,
slen
;
char
*
name
=
NULL
;
char
*
value
=
NULL
;
/* parse the name: value lines. */
for
(
l
=
1
;
l
<
lines
;
l
++
)
{
where
=
0
;
whitespace
=
0
;
name
=
line
[
l
];
value
=
NULL
;
slen
=
strlen
(
line
[
l
]);
for
(
i
=
0
;
i
<
slen
;
i
++
)
{
if
(
line
[
l
][
i
]
==
':'
)
{
whitespace
=
1
;
line
[
l
][
i
]
=
'\0'
;
}
else
{
if
(
whitespace
)
{
whitespace
=
0
;
while
(
i
<
slen
&&
line
[
l
][
i
]
==
' '
)
i
++
;
if
(
i
<
slen
)
value
=
&
line
[
l
][
i
];
break
;
}
}
}
if
(
name
!=
NULL
&&
value
!=
NULL
)
{
httpp_setvar
(
parser
,
_lowercase
(
name
),
value
);
name
=
NULL
;
value
=
NULL
;
}
}
}
int
httpp_parse_response
(
http_parser_t
*
parser
,
char
*
http_data
,
unsigned
long
len
,
char
*
uri
)
{
char
*
data
;
char
*
line
[
MAX_HEADERS
];
int
lines
,
slen
,
i
,
whitespace
=
0
,
where
=
0
,
code
;
char
*
version
=
NULL
,
*
resp_code
=
NULL
,
*
message
=
NULL
;
if
(
http_data
==
NULL
)
return
0
;
/* make a local copy of the data, including 0 terminator */
data
=
(
char
*
)
malloc
(
len
+
1
);
if
(
data
==
NULL
)
return
0
;
memcpy
(
data
,
http_data
,
len
);
data
[
len
]
=
0
;
lines
=
split_headers
(
data
,
len
,
line
);
/* In this case, the first line contains:
* VERSION RESPONSE_CODE MESSAGE, such as
* HTTP/1.0 200 OK
*/
slen
=
strlen
(
line
[
0
]);
version
=
line
[
0
];
for
(
i
=
0
;
i
<
slen
;
i
++
)
{
if
(
line
[
0
][
i
]
==
' '
)
{
line
[
0
][
i
]
=
0
;
whitespace
=
1
;
}
else
if
(
whitespace
)
{
whitespace
=
0
;
where
++
;
if
(
where
==
1
)
resp_code
=
&
line
[
0
][
i
];
else
{
message
=
&
line
[
0
][
i
];
break
;
}
}
}
if
(
version
==
NULL
||
resp_code
==
NULL
||
message
==
NULL
)
{
free
(
data
);
return
0
;
}
code
=
atoi
(
resp_code
);
if
(
code
<
200
||
code
>=
300
)
{
httpp_setvar
(
parser
,
HTTPP_VAR_ERROR_MESSAGE
,
message
);
free
(
data
);
return
0
;
}
httpp_setvar
(
parser
,
HTTPP_VAR_URI
,
uri
);
httpp_setvar
(
parser
,
HTTPP_VAR_REQ_TYPE
,
"RELAY"
);
parse_headers
(
parser
,
line
,
lines
);
free
(
data
);
return
1
;
}
int
httpp_parse
(
http_parser_t
*
parser
,
char
*
http_data
,
unsigned
long
len
)
{
char
*
data
,
*
tmp
;
char
*
line
[
MAX_HEADERS
];
/* limited to 32 lines, should be more than enough */
int
i
;
int
lines
;
char
*
req_type
=
NULL
;
char
*
uri
=
NULL
;
char
*
version
=
NULL
;
int
whitespace
,
where
,
slen
;
if
(
http_data
==
NULL
)
return
0
;
/* make a local copy of the data, including 0 terminator */
data
=
(
char
*
)
malloc
(
len
+
1
);
if
(
data
==
NULL
)
return
0
;
memcpy
(
data
,
http_data
,
len
);
data
[
len
]
=
0
;
lines
=
split_headers
(
data
,
len
,
line
);
/* parse the first line special
** the format is:
...
...
@@ -189,48 +295,18 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
return
0
;
}
if
(
parser
->
uri
!=
NULL
)
{
if
(
parser
->
uri
!=
NULL
)
{
httpp_setvar
(
parser
,
HTTPP_VAR_URI
,
parser
->
uri
);
}
else
{
free
(
data
);
return
0
;
}
/* parse the name: value lines. */
for
(
l
=
1
;
l
<
lines
;
l
++
)
{
where
=
0
;
whitespace
=
0
;
name
=
line
[
l
];
value
=
NULL
;
slen
=
strlen
(
line
[
l
]);
for
(
i
=
0
;
i
<
slen
;
i
++
)
{
if
(
line
[
l
][
i
]
==
':'
)
{
whitespace
=
1
;
line
[
l
][
i
]
=
'\0'
;
}
else
{
if
(
whitespace
)
{
whitespace
=
0
;
while
(
i
<
slen
&&
line
[
l
][
i
]
==
' '
)
i
++
;
if
(
i
<
slen
)
value
=
&
line
[
l
][
i
];
break
;
}
}
}
if
(
name
!=
NULL
&&
value
!=
NULL
)
{
httpp_setvar
(
parser
,
_lowercase
(
name
),
value
);
name
=
NULL
;
value
=
NULL
;
}
}
parse_headers
(
parser
,
line
,
lines
);
free
(
data
);
return
retlen
;
return
1
;
}
void
httpp_setvar
(
http_parser_t
*
parser
,
char
*
name
,
char
*
value
)
...
...
src/httpp/httpp.h
View file @
f1dc57ae
...
...
@@ -12,6 +12,7 @@
#define HTTPP_VAR_VERSION "__version"
#define HTTPP_VAR_URI "__uri"
#define HTTPP_VAR_REQ_TYPE "__req_type"
#define HTTPP_VAR_ERROR_MESSAGE "__errormessage"
typedef
enum
httpp_request_type_tag
{
httpp_req_none
,
httpp_req_get
,
httpp_req_post
,
httpp_req_head
,
httpp_req_source
,
httpp_req_play
,
httpp_req_stats
,
httpp_req_unknown
...
...
@@ -30,13 +31,13 @@ typedef struct http_varlist_tag {
typedef
struct
http_parser_tag
{
httpp_request_type_e
req_type
;
char
*
uri
;
avl_tree
*
vars
;
}
http_parser_t
;
http_parser_t
*
httpp_create_parser
(
void
);
void
httpp_initialize
(
http_parser_t
*
parser
,
http_varlist_t
*
defaults
);
int
httpp_parse
(
http_parser_t
*
parser
,
char
*
http_data
,
unsigned
long
len
);
int
httpp_parse_response
(
http_parser_t
*
parser
,
char
*
http_data
,
unsigned
long
len
,
char
*
uri
);
void
httpp_setvar
(
http_parser_t
*
parser
,
char
*
name
,
char
*
value
);