Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
spr0cketeer
Icecast-Server
Commits
c806e47a
Commit
c806e47a
authored
Feb 01, 2015
by
Philipp Schafft
🦁
Browse files
Fix: allow Keep-Alive connections on normal error pages
parent
78213fe3
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/client.c
View file @
c806e47a
...
...
@@ -92,12 +92,35 @@ int client_create(client_t **c_ptr, connection_t *con, http_parser_t *parser)
return
ret
;
}
static
inline
void
client_reuseconnection
(
client_t
*
client
)
{
connection_t
*
con
;
reuse_t
reuse
;
if
(
!
client
)
return
;
con
=
client
->
con
;
con
=
connection_create
(
con
->
sock
,
con
->
serversock
,
strdup
(
con
->
ip
));
reuse
=
client
->
reuse
;
client
->
con
->
sock
=
-
1
;
/* TODO: do not use magic */
client
->
reuse
=
ICECAST_REUSE_CLOSE
;
client_destroy
(
client
);
connection_queue
(
con
);
}
void
client_destroy
(
client_t
*
client
)
{
ICECAST_LOG_DEBUG
(
"Called to destory client %p"
,
client
);
if
(
client
==
NULL
)
return
;
if
(
client
->
reuse
!=
ICECAST_REUSE_CLOSE
)
{
client_reuseconnection
(
client
);
return
;
}
/* release the buffer now, as the buffer could be on the source queue
* and may of disappeared after auth completes */
if
(
client
->
refbuf
)
{
...
...
@@ -163,16 +186,23 @@ int client_read_bytes(client_t *client, void *buf, unsigned len)
void
client_send_error
(
client_t
*
client
,
int
status
,
int
plain
,
const
char
*
message
)
{
ssize_t
ret
;
refbuf_t
*
data
;
if
(
status
==
500
)
{
client_send_500
(
client
,
message
);
return
;
}
data
=
refbuf_new
(
PER_CLIENT_REFBUF_SIZE
);
if
(
!
data
)
{
client_send_500
(
client
,
message
);
return
;
}
ret
=
util_http_build_header
(
client
->
refbuf
->
data
,
PER_CLIENT_REFBUF_SIZE
,
0
,
0
,
status
,
NULL
,
plain
?
"text/plain"
:
"text/html"
,
"utf-8"
,
plain
?
message
:
""
,
NULL
,
client
);
NULL
,
NULL
,
client
);
if
(
ret
==
-
1
||
ret
>=
PER_CLIENT_REFBUF_SIZE
)
{
ICECAST_LOG_ERROR
(
"Dropping client as we can not build response headers."
);
...
...
@@ -180,13 +210,26 @@ void client_send_error(client_t *client, int status, int plain, const char *mess
return
;
}
if
(
!
plain
)
snprintf
(
client
->
refbuf
->
data
+
ret
,
PER_CLIENT_REFBUF_SIZE
-
ret
,
if
(
plain
)
{
strncpy
(
data
->
data
,
message
,
data
->
len
);
data
->
data
[
data
->
len
-
1
]
=
0
;
}
else
{
snprintf
(
data
->
data
,
data
->
len
,
"<html><head><title>Error %i</title></head><body><b>%i - %s</b></body></html>
\r\n
"
,
status
,
status
,
message
);
}
data
->
len
=
strlen
(
data
->
data
);
snprintf
(
client
->
refbuf
->
data
+
ret
,
PER_CLIENT_REFBUF_SIZE
-
ret
,
"Content-Length: %llu
\r\n
Connection: Keep-Alive
\r\n\r\n
"
,
(
long
long
unsigned
int
)
data
->
len
);
client
->
respcode
=
status
;
client
->
refbuf
->
len
=
strlen
(
client
->
refbuf
->
data
);
client
->
refbuf
->
next
=
data
;
client
->
reuse
=
ICECAST_REUSE_KEEPALIVE
;
fserve_add_client
(
client
,
NULL
);
}
...
...
src/client.h
View file @
c806e47a
...
...
@@ -30,6 +30,13 @@ typedef enum _protocol_tag {
ICECAST_PROTOCOL_SHOUTCAST
}
protocol_t
;
typedef
enum
_reuse_tag
{
/* do not reuse */
ICECAST_REUSE_CLOSE
=
0
,
/* reuse */
ICECAST_REUSE_KEEPALIVE
}
reuse_t
;
typedef
struct
_client_tag
{
/* mode of operation for this client */
...
...
@@ -37,6 +44,10 @@ typedef struct _client_tag
/* the client's connection */
connection_t
*
con
;
/* Reuse this connection ... */
reuse_t
reuse
;
/* the client's http headers */
http_parser_t
*
parser
;
...
...
src/connection.c
View file @
c806e47a
...
...
@@ -685,6 +685,41 @@ static client_queue_t *create_client_node(client_t *client)
return
node
;
}
void
connection_queue
(
connection_t
*
con
)
{
client_queue_t
*
node
;
client_t
*
client
=
NULL
;
global_lock
();
if
(
client_create
(
&
client
,
con
,
NULL
)
<
0
)
{
global_unlock
();
client_send_error
(
client
,
403
,
1
,
"Icecast connection limit reached"
);
/* don't be too eager as this is an imposed hard limit */
thread_sleep
(
400000
);
return
;
}
/* setup client for reading incoming http */
client
->
refbuf
->
data
[
PER_CLIENT_REFBUF_SIZE
-
1
]
=
'\000'
;
if
(
sock_set_blocking
(
client
->
con
->
sock
,
0
)
||
sock_set_nodelay
(
client
->
con
->
sock
))
{
global_unlock
();
ICECAST_LOG_WARN
(
"failed to set tcp options on client connection, dropping"
);
client_destroy
(
client
);
return
;
}
node
=
create_client_node
(
client
);
global_unlock
();
if
(
node
==
NULL
)
{
client_destroy
(
client
);
return
;
}
_add_request_queue
(
node
);
stats_event_inc
(
NULL
,
"connections"
);
}
void
connection_accept_loop
(
void
)
{
connection_t
*
con
;
...
...
@@ -699,38 +734,7 @@ void connection_accept_loop(void)
con
=
_accept_connection
(
duration
);
if
(
con
)
{
client_queue_t
*
node
;
client_t
*
client
=
NULL
;
global_lock
();
if
(
client_create
(
&
client
,
con
,
NULL
)
<
0
)
{
global_unlock
();
client_send_error
(
client
,
403
,
1
,
"Icecast connection limit reached"
);
/* don't be too eager as this is an imposed hard limit */
thread_sleep
(
400000
);
continue
;
}
/* setup client for reading incoming http */
client
->
refbuf
->
data
[
PER_CLIENT_REFBUF_SIZE
-
1
]
=
'\000'
;
if
(
sock_set_blocking
(
client
->
con
->
sock
,
0
)
||
sock_set_nodelay
(
client
->
con
->
sock
))
{
global_unlock
();
ICECAST_LOG_WARN
(
"failed to set tcp options on client connection, dropping"
);
client_destroy
(
client
);
continue
;
}
node
=
create_client_node
(
client
);
global_unlock
();
if
(
node
==
NULL
)
{
client_destroy
(
client
);
continue
;
}
_add_request_queue
(
node
);
stats_event_inc
(
NULL
,
"connections"
);
connection_queue
(
con
);
duration
=
5
;
}
else
{
if
(
_req_queue
==
NULL
)
...
...
@@ -1569,6 +1573,9 @@ int connection_setup_sockets (ice_config_t *config)
void
connection_close
(
connection_t
*
con
)
{
if
(
!
con
)
return
;
sock_close
(
con
->
sock
);
if
(
con
->
ip
)
free
(
con
->
ip
);
...
...
src/connection.h
View file @
c806e47a
...
...
@@ -60,6 +60,7 @@ int connection_setup_sockets(struct ice_config_tag *config);
void
connection_close
(
connection_t
*
con
);
connection_t
*
connection_create
(
sock_t
sock
,
sock_t
serversock
,
char
*
ip
);
int
connection_complete_source
(
struct
source_tag
*
source
,
int
response
);
void
connection_queue
(
connection_t
*
con
);
extern
rwlock_t
_source_shutdown_rwlock
;
...
...
src/util.c
View file @
c806e47a
...
...
@@ -696,7 +696,7 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
config
=
config_get_config
();
extra_headers
=
_build_headers
(
status
,
config
,
source
);
ret
=
snprintf
(
out
,
len
,
"%sServer: %s
\r\n
Accept-Encoding: identity
\r\
n
Connection: close
\r\
n
Allow: %s
\r\n
%s%s%s%s%s%s%s"
,
ret
=
snprintf
(
out
,
len
,
"%sServer: %s
\r\n
Accept-Encoding: identity
\r\n
Allow: %s
\r\n
%s%s%s%s%s%s%s"
,
status_buffer
,
config
->
server_id
,
(
client
->
admin_command
==
ADMIN_COMMAND_ERROR
?
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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