Commit 4e0d8669 authored by Wandenberg Peixoto's avatar Wandenberg Peixoto

refactor on directives and docs

parent f0f2b472
h2. Version 0.3.0
* Adding Event Source support
* Adding Polling support * Adding Polling support
* Adding Long Polling support * Adding Long Polling support
* Moving some directives to be used on http context instead of location
** push_stream_min_message_buffer_timeout
** push_stream_max_message_buffer_length
** push_stream_max_channel_id_length
** push_stream_ping_message_interval
** push_stream_subscriber_connection_timeout
** push_stream_broadcast_channel_prefix
** push_stream_max_number_of_channels
** push_stream_max_number_of_broadcast_channels
* Renaming some directives
** push_stream_max_reserved_memory -> push_stream_shared_memory_size
** push_stream_memory_cleanup_timeout -> push_stream_shared_memory_cleanup_objects_ttl
** push_stream_min_message_buffer_timeout -> push_stream_message_ttl
** push_stream_max_message_buffer_length -> push_stream_max_messages_stored_per_channel
** push_stream_subscriber_connection_timeout -> push_stream_subscriber_connection_ttl
h2. Version 0.2.7 h2. Version 0.2.7
......
...@@ -6,32 +6,77 @@ Comet made easy and *really scalable*. ...@@ -6,32 +6,77 @@ Comet made easy and *really scalable*.
h2(#changelog). Changelog h2(#changelog). Changelog
Always take a look at "CHANGELOG.textile":changelog. Always take a look at "CHANGELOG.textile":changelog to see what's new.
h2(#donate). Donate
After you try this module and like it, feel free to give something back, and help in the maintenance of the project ;)
"Donate":donate
h2(#installing). Installing h2(#installing). Installing
You may use @build.sh@ script inside the project:
<pre> <pre>
<code> <code>
# clone # clone the project
git clone http://github.com/wandenberg/nginx-push-stream-module.git git clone http://github.com/wandenberg/nginx-push-stream-module.git
NGINX_PUSH_STREAM_MODULE_PATH=$PWD/nginx-push-stream-module
cd nginx-push-stream-module cd nginx-push-stream-module
# build with 1.0.x, 0.9.x, 0.8.x series # build with 1.0.x, 0.9.x, 0.8.x series
./build.sh master 1.0.0 ./build.sh master 1.0.5
cd build/nginx-1.0.0 cd build/nginx-1.0.5
# finish # install and finish
sudo make install sudo make install
# check # check
sudo /usr/local/nginx/sbin/nginx -v sudo /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.0.0 nginx version: nginx/1.0.5
sudo /usr/local/nginx/sbin/nginx -c nginx-push-stream-module/misc/nginx.conf -t
the configuration file nginx-push-stream-module/misc/nginx.conf syntax is ok # test configuration
configuration file nginx-push-stream-module/misc/nginx.conf test is successful sudo /usr/local/nginx/sbin/nginx -c $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf -t
the configuration file $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf syntax is ok
configuration file $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf test is successful
# run
sudo /usr/local/nginx/sbin/nginx -c $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf
</code>
</pre>
Or you may do by yourself:
<pre>
<code>
# clone the project
git clone http://github.com/wandenberg/nginx-push-stream-module.git
NGINX_PUSH_STREAM_MODULE_PATH=$PWD/nginx-push-stream-module
# get desired nginx version (works with 1.0.x, 0.9.x, 0.8.x series)
wget http://nginx.org/download/nginx-1.0.5.tar.gz
# unpack, configure and build
tar xzvf nginx-1.0.5.tar.gz
cd nginx-1.0.5
./configure --add-module=../nginx-push-stream-module
make
# install and finish
sudo make install
# check
sudo /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.0.5
# test configuration
sudo /usr/local/nginx/sbin/nginx -c $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf -t
the configuration file $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf syntax is ok
configuration file $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf test is successful
# run # run
sudo /usr/local/nginx/sbin/nginx -c nginx-push-stream-module/misc/nginx.conf sudo /usr/local/nginx/sbin/nginx -c $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf
</code> </code>
</pre> </pre>
...@@ -48,53 +93,19 @@ h2(#basic-configuration). Basic Configuration ...@@ -48,53 +93,19 @@ h2(#basic-configuration). Basic Configuration
} }
location /pub { location /pub {
# activate publisher mode for this location # activate publisher (admin) mode for this location
push_stream_publisher; push_stream_publisher admin;
# query string based channel id # query string based channel id
set $push_stream_channel_id $arg_id; set $push_stream_channel_id $arg_id;
push_stream_max_channel_id_length 200;
# message template
push_stream_message_template "<script>p(~id~,'~channel~','~text~');</script>";
# store messages in memory
push_stream_store_messages on;
# max messages to store in memory
push_stream_max_message_buffer_length 20;
# message ttl
push_stream_min_message_buffer_timeout 5m;
# Message size limit
# client_max_body_size MUST be equal to client_body_buffer_size or
# you will be sorry.
client_max_body_size 32k;
client_body_buffer_size 32k;
} }
location ~ /sub/(.*) { location ~ /sub/(.*) {
# activate subscriber mode for this location # activate subscriber (streaming) mode for this location
push_stream_subscriber; push_stream_subscriber;
# positional channel path # positional channel path
set $push_stream_channels_path $1; set $push_stream_channels_path $1;
push_stream_max_channel_id_length 200;
# header to be sent when receiving new subscriber connection
push_stream_header_template "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta http-equiv=\"Cache-Control\" content=\"no-store\">\r\n<meta http-equiv=\"Cache-Control\" content=\"no-cache\">\r\n<meta http-equiv=\"Pragma\" content=\"no-cache\">\r\n<meta http-equiv=\"Expires\" content=\"Thu, 1 Jan 1970 00:00:00 GMT\">\r\n<script type=\"text/javascript\">\r\nwindow.onError = null;\r\ndocument.domain = 'localhost';\r\nparent.PushStream.register(this);\r\n</script>\r\n</head>\r\n<body onload=\"try { parent.PushStream.reset(this) } catch (e) {}\">";
# message template
push_stream_message_template "<script>p(~id~,'~channel~','~text~');</script>";
# footer to be sent when finishing subscriber connection
push_stream_footer_template "</body></html>";
# content-type
push_stream_content_type "text/html; charset=utf-8";
# subscriber may create channels on demand or only authorized
# (publisher) may do it?
push_stream_authorized_channels_only off;
# ping frequency
push_stream_ping_message_interval 10s;
# connection ttl to enable recycle
push_stream_subscriber_connection_timeout 15m;
# broadcast
push_stream_broadcast_channel_prefix "broad_";
push_stream_broadcast_channel_max_qtd 3;
} }
</code> </code>
</pre> </pre>
...@@ -106,15 +117,17 @@ one terminal and start playing http pubsub: ...@@ -106,15 +117,17 @@ one terminal and start playing http pubsub:
<pre> <pre>
<code> <code>
# Pub # Pubs
curl -s -v -X POST 'http://localhost/pub?id=my_channel_1' -d 'Hello World!' curl -s -v -X POST 'http://localhost/pub?id=my_channel_1' -d 'Hello World!'
curl -s -v -X POST 'http://localhost/pub?id=your_channel_1' -d 'Hi everybody!' curl -s -v -X POST 'http://localhost/pub?id=your_channel_1' -d 'Hi everybody!'
curl -s -v -X POST 'http://localhost/pub?id=your_channel_2' -d 'Goodbye!' curl -s -v -X POST 'http://localhost/pub?id=your_channel_2' -d 'Goodbye!'
# Sub # Subs
curl -s -v 'http://localhost/sub/my_channel_1.b20' curl -s -v 'http://localhost/sub/my_channel_1.b20'
curl -s -v 'http://localhost/sub/your_channel_1.b20'
curl -s -v 'http://localhost/sub/your_channel_2.b20'
# Channel Stats for publisher (json format) # Channels Stats for publisher (json format)
curl -s -v 'http://localhost/pub?id=my_channel_1' curl -s -v 'http://localhost/pub?id=my_channel_1'
# All Channels Stats summarized (json format) # All Channels Stats summarized (json format)
...@@ -128,6 +141,9 @@ one terminal and start playing http pubsub: ...@@ -128,6 +141,9 @@ one terminal and start playing http pubsub:
# Channels Stats (json format) # Channels Stats (json format)
curl -s -v 'http://localhost/channels-stats?id=my_channel_1' curl -s -v 'http://localhost/channels-stats?id=my_channel_1'
# Delete Channels
curl -s -v -X DELETE 'http://localhost/pub?id=my_channel_1'
</code> </code>
</pre> </pre>
...@@ -156,7 +172,7 @@ h4(#push_stream_channels_path). push_stream_channels_path ...@@ -156,7 +172,7 @@ h4(#push_stream_channels_path). push_stream_channels_path
A string representing a set of channels id and backtrack desired messages separated by slash, example _/channel1.b3/channel2.b5/channel3.b2_. A string representing a set of channels id and backtrack desired messages separated by slash, example _/channel1.b3/channel2.b5/channel3.b2_.
The backtrack means the amount of old messages from each of the channels that will be delivered to the subscriber. On the example will be 3 messages from channel1, 5 from channel2 and 2 from channel3. The backtrack means the amount of old messages from each of the channels that will be delivered to the subscriber. On the example will be 3 messages from channel1, 5 from channel2 and 2 from channel3.
Backtrack isn't needed, you can only sign channels without get old messages, or you can mix things. Backtrack isn't needed, you can only sign channels without get old messages, or you can mix things.
More accepted examples: _/channel1_, _/channel1/channel2_, _/channel1.b5/channel2_, _/channel1/channel2.b6_, ... More accepted examples: _/channel1_ , _/channel1/channel2_ , _/channel1.b5/channel2_ , _/channel1/channel2.b6_ , ...
Must be present on location of the push_stream_subscriber. Must be present on location of the push_stream_subscriber.
<pre> <pre>
...@@ -173,36 +189,38 @@ h3(#directives). Directives ...@@ -173,36 +189,38 @@ h3(#directives). Directives
(head). | directive | default value | values | context | location | (head). | directive | default value | values | context | location |
|push_stream_channels_statistics|-|-|location|-| |push_stream_channels_statistics|-|-|location|-|
|push_stream_publisher|-|-|location|-| |push_stream_publisher|normal|normal, admin|location|-|
|push_stream_subscriber|streaming|streaming, polling, long-polling|location|-| |push_stream_subscriber|streaming|streaming, polling, long-polling|location|-|
|push_stream_max_reserved_memory|16 * ngx_pagesize|size greater than 16 * ngx_pagesize|http|main nginx configuration| |push_stream_shared_memory_size|16 * ngx_pagesize|size greater than 16 * ngx_pagesize|http|main nginx configuration|
|push_stream_memory_cleanup_timeout|30 seconds|time constant|http|main nginx configuration| |push_stream_shared_memory_cleanup_objects_ttl|30 seconds|time constant|http|main nginx configuration|
|push_stream_channel_deleted_message_text|"Channel deleted"|any string|http|main nginx configuration| |push_stream_channel_deleted_message_text|"Channel deleted"|any string|http|main nginx configuration|
|push_stream_ping_message_text|""|any string|http|main nginx configuration| |push_stream_ping_message_text|""|any string|http|main nginx configuration|
|push_stream_ping_message_interval|unset|time constant|http|main nginx configuration|
|push_stream_message_ttl|unset|time constant|http|main nginx configuration|
|push_stream_max_messages_stored_per_channel|unset|number|http|main nginx configuration|
|push_stream_max_channel_id_length|unset|number|http|main nginx configuration|
|push_stream_subscriber_connection_ttl|unset|time constant|http|main nginx configuration|
|push_stream_max_number_of_channels|unset|number|http|main nginx configuration|
|push_stream_max_number_of_broadcast_channels|unset|number|http|main nginx configuration|
|push_stream_broadcast_channel_prefix|unset|any string|http|main nginx configuration|
|push_stream_store_messages|off|on, off|location|push_stream_publisher| |push_stream_store_messages|off|on, off|location|push_stream_publisher|
|push_stream_min_message_buffer_timeout|unset|time constant|location|push_stream_publisher| |push_stream_keepalive|off|on, off|http, location|push_stream_publisher, push_stream_channels_statistics|
|push_stream_max_message_buffer_length|unset|number|location|push_stream_publisher|
|push_stream_authorized_channels_only|off|on, off|location|push_stream_subscriber| |push_stream_authorized_channels_only|off|on, off|location|push_stream_subscriber|
|push_stream_header_template|unset|any string|location|push_stream_subscriber| |push_stream_header_template|unset|any string|location|push_stream_subscriber|
|push_stream_message_template|==~text~==|any string|http, location|push_stream_subscriber|
|push_stream_footer_template|unset|any string|location|push_stream_subscriber| |push_stream_footer_template|unset|any string|location|push_stream_subscriber|
|push_stream_content_type|text/plain|any valid content type|location|push_stream_subscriber| |push_stream_content_type|text/plain|any valid content type|location|push_stream_subscriber|
|push_stream_ping_message_interval|unset|time constant|location|push_stream_subscriber|
|push_stream_subscriber_connection_timeout|unset|time constant|location|push_stream_subscriber|
|push_stream_broadcast_channel_max_qtd|unset|number|location|push_stream_subscriber| |push_stream_broadcast_channel_max_qtd|unset|number|location|push_stream_subscriber|
|push_stream_max_channel_id_length|unset|number|http, location|(push_stream_subscriber and push_stream_publisher) or main nginx configuration| |push_stream_eventsource_support|off|on, off|location|push_stream_subscriber|
|push_stream_broadcast_channel_prefix|unset|any string|http, location|(push_stream_subscriber and push_stream_publisher) or main nginx configuration|
|push_stream_message_template|==~text~==|any string|http, location|(push_stream_subscriber and push_stream_publisher) or main nginx configuration| h3(#location_handlers). Location Handlers
|push_stream_max_number_of_channels|unset|number|http, location|(push_stream_subscriber and push_stream_publisher) or main nginx configuration|
|push_stream_max_number_of_broadcast_channels|unset|number|http, location|(push_stream_subscriber and push_stream_publisher) or main nginx configuration|
|push_stream_keepalive|off|on, off|http, location|(push_stream_publisher and push_stream_channels_statistics) or main nginx configuration|
|push_stream_publisher_admin|off|on, off|location|push_stream_publisher|
h4(#push_stream_channels_statistics). push_stream_channels_statistics h4(#push_stream_channels_statistics). push_stream_channels_statistics
New in version 0.2.0 New in version 0.2.0
context: location context: location
Defines a location as a source of statistics. You can use this location to get statistics about a specific channel, or about all channels, in a resumed ou summarized way. Defines a location as a source of statistics. You can use this location to get statistics about a specific, group or all channels, in a resumed ou summarized way.
To get statistics about all channels in a summarized way you have to make a GET in this location without specify a name in the push_stream_channel_id variable. To get statistics about all channels in a summarized way you have to make a GET in this location without specify a name in the push_stream_channel_id variable.
To get statistics about all channels in a detailed way you have to specify "ALL" in the push_stream_channel_id. To get statistics about all channels in a detailed way you have to specify "ALL" in the push_stream_channel_id.
To get statistics about prefixed channels in a detailed way you have to specify "_prefix_*" in the push_stream_channel_id. To get statistics about prefixed channels in a detailed way you have to specify "_prefix_*" in the push_stream_channel_id.
...@@ -226,15 +244,19 @@ You can get statistics in the formats plain, xml, yaml and json. The default is ...@@ -226,15 +244,19 @@ You can get statistics in the formats plain, xml, yaml and json. The default is
h4(#push_stream_publisher). push_stream_publisher h4(#push_stream_publisher). push_stream_publisher
default: normal
context: location context: location
values: normal, admin
Defines a location as a message publisher. Requests to a publisher location are treated as messages to be sent to subscribers. Defines a location as a message publisher. Requests to a publisher location are treated as messages to be sent to subscribers.
This location supports two http methods: This location supports three http methods:
GET, make possible to get statistics about the channel GET, make possible to get statistics about the channel
POST, publish a message to the channel POST, publish a message to the channel
DELETE, remove any existent stored messages, disconnect any subscriber, and delete the channel. Available only if _admin_ value is used in this directive.
<pre> <pre>
<code> <code>
# normal publisher location
location /pub { location /pub {
push_stream_publisher; push_stream_publisher;
set $push_stream_channel_id $arg_id; set $push_stream_channel_id $arg_id;
...@@ -242,6 +264,16 @@ POST, publish a message to the channel ...@@ -242,6 +264,16 @@ POST, publish a message to the channel
# GET /pub?id=channel_id -> get statistics about a channel # GET /pub?id=channel_id -> get statistics about a channel
# POST /pub?id=channel_id -> publish a message to the channel # POST /pub?id=channel_id -> publish a message to the channel
# admin publisher location
location /pub_admin {
push_stream_publisher admin;
set $push_stream_channel_id $arg_id;
}
# GET /pub_admin?id=channel_id -> get statistics about a channel
# POST /pub_admin?id=channel_id -> publish a message to the channel
# DELETE /pub_admin?id=channel_id -> delete the channel
</code> </code>
</pre> </pre>
...@@ -254,10 +286,11 @@ values: streaming, polling, long-polling ...@@ -254,10 +286,11 @@ values: streaming, polling, long-polling
Defines a location as a subscriber. This location represents a subscriber's interface to a channel's message queue. Defines a location as a subscriber. This location represents a subscriber's interface to a channel's message queue.
This location only supports GET http method to receive published messages. This location only supports GET http method to receive published messages.
And has three possible values to set push mode: streaming, polling, long-polling. The default values is streaming. And has three possible values to set push mode: streaming, polling, long-polling. The default values is streaming.
The polling and long-polling modes could be set by the request header *X-Nginx-PushStream-Mode* overriding push_stream_subscriber directive. The polling and long-polling modes could be set by the request header *X-Nginx-PushStream-Mode* overriding push_stream_subscriber directive value.
<pre> <pre>
<code> <code>
# streaming subscriber location
location /sub/(.*) { location /sub/(.*) {
push_stream_subscriber; push_stream_subscriber;
# positional channel path # positional channel path
...@@ -267,6 +300,7 @@ The polling and long-polling modes could be set by the request header *X-Nginx-P ...@@ -267,6 +300,7 @@ The polling and long-polling modes could be set by the request header *X-Nginx-P
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:polling' #polling request on a streaming location curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:polling' #polling request on a streaming location
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:long-polling' #long-polling request on a streaming location curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:long-polling' #long-polling request on a streaming location
# polling subscriber location
location /sub/(.*) { location /sub/(.*) {
push_stream_subscriber polling; push_stream_subscriber polling;
# positional channel path # positional channel path
...@@ -276,6 +310,7 @@ The polling and long-polling modes could be set by the request header *X-Nginx-P ...@@ -276,6 +310,7 @@ The polling and long-polling modes could be set by the request header *X-Nginx-P
curl localhost/sub/ch1 #polling request curl localhost/sub/ch1 #polling request
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:long-polling' #long-polling request on a polling location curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:long-polling' #long-polling request on a polling location
# long polling subscriber location
location /sub/(.*) { location /sub/(.*) {
push_stream_subscriber long-polling; push_stream_subscriber long-polling;
# positional channel path # positional channel path
...@@ -287,112 +322,114 @@ The polling and long-polling modes could be set by the request header *X-Nginx-P ...@@ -287,112 +322,114 @@ The polling and long-polling modes could be set by the request header *X-Nginx-P
</code> </code>
</pre> </pre>
h3(#functionality). Functionality h4(#push_stream_shared_memory_size). push_stream_shared_memory_size [ size ]
h4(#push_stream_header_template). push_stream_header_template [ string ]
default: - default: 32M
context: location context: http
location: push_stream_subscriber
The text that will be sended to subscribers when they arrive. The size of the memory chunk this module will use to store published messages, channels and other shared structures.
When this memory is full any new request for publish a message or subscribe a channel will receive an 500 Internal Server Error response.
h4(#push_stream_footer_template). push_stream_footer_template [ string ] h4(#push_stream_shared_memory_cleanup_objects_ttl). push_stream_shared_memory_cleanup_objects_ttl [ time ]
New in version 0.2.6 default: 30 seconds
default: - context: http
context: location location: main nginx configuration
location: push_stream_subscriber
The text that will be sended to subscribers before connection is closed (channel deleted ou subscriber timeout). The length of time a message or a channel will stay on garbage collection area before it is completly discarded, freeing the shared memory. The minimum length is 30 seconds to ensure that no one is using these elements.
This operation is very important to help Nginx recycle memory consumed to create messages and channels, so do not use a large time.
h4(#push_stream_message_template). push_stream_message_template [ string ] h4(#push_stream_channel_deleted_message_text). push_stream_channel_deleted_message_text [ string ]
default: ==~text~== New in version 0.2.5
context: location default: "Channel deleted"
location: (push_stream_subscriber and push_stream_publisher) or main nginx configuration context: http
location: main nginx configuration
The text template that will be used to format the message before be sended to subscribers. The template can contain any number of the reserved words: ==~id~, ~text~ and ~channel~, example: "&lt;script&gt;p(~id~,'~channel~','~text~');&lt;/script&gt;"== The string used on channel deleted message sent to subscribers when the channel is deleted by a publisher.
h4(#push_stream_content_type). push_stream_content_type [ string ] h4(#push_stream_ping_message_text). push_stream_ping_message_text [ string ]
default: text/plain New in version 0.2.5
context: location default: ""
location: push_stream_subscriber context: http
location: main nginx configuration
The content type used on responses to subscribers. Must be complient with push_stream_header_template, push_stream_message_template and push_stream_footer_template. The string used on ping message sent to subscribers.
h4(#push_stream_ping_message_interval). push_stream_ping_message_interval [ time ] h4(#push_stream_message_ttl). push_stream_message_ttl [ time ]
default: - default: -
context: location context: http
location: push_stream_subscriber location: main nginx configuration
The time interval in which a keepalive message is sent to subscribers.
h3(#message_channel_storage). Message/Channel Storage The length of time a message may be queued before it is considered expired. If you do not want messages to expire, just not set this directive.
h4(#push_stream_max_reserved_memory). push_stream_max_reserved_memory [ size ] h4(#push_stream_max_messages_stored_per_channel). push_stream_max_messages_stored_per_channel [ number ]
default: 32M default: -
context: http context: http
location: main nginx configuration
The size of the memory chunk this module will use to store published messages, channels and other shared structures. The maximum number of messages to store per channel. A channel's message buffer will retain at most this many most recent messages. If you do not want messages to be discarded by length, just not set this directive.
When this memory is full any new request for publish a message or subscribe a channel will receive an 500 Internal Server Error response.
h4(#push_stream_memory_cleanup_timeout). push_stream_memory_cleanup_timeout [ time ] h4(#push_stream_max_channel_id_length). push_stream_max_channel_id_length [ number ]
default: 30 seconds default: -
context: http context: http
location: main nginx configuration location: main nginx configuration
The length of time a message or a channel will stay on garbage collection area before it is completly discarded, freeing the shared memory. The minimum length is 30 seconds to ensure that no one is using these elements. Maximum permissible channel id length (number of characters). Longer ids will receive an 400 Bad Request response. If you do not want to limit channel id length, just not set this directive.
This operation is very important to help Nginx recycle memory consumed to create messages and channels, so do not use a large time.
h4(#push_stream_channel_deleted_message_text). push_stream_channel_deleted_message_text [ string ] h4(#push_stream_ping_message_interval). push_stream_ping_message_interval [ time ]
New in version 0.2.5 default: -
default: "Channel deleted"
context: http context: http
location: main nginx configuration location: main nginx configuration
The string used on channel deleted message sent to subscribers when the channel is deleted by a publisher. The time interval in which a keepalive message is sent to subscribers. If you do not want to send ping messages, just not set this directive.
h4(#push_stream_ping_message_text). push_stream_ping_message_text [ string ] h4(#push_stream_subscriber_connection_ttl). push_stream_subscriber_connection_ttl [ time ]
New in version 0.2.5 default: -
default: ""
context: http context: http
location: main nginx configuration location: main nginx configuration
The string used on ping message sent to subscribers. The length of time a subscriber will stay connected before it is considered expired and disconnected. If you do not want subscribers to be automatically disconnected, just not set this directive.
But, this operation is very important to help Nginx recycle memory consumed to send messages to susbscriber, allocated at pool request.
h4(#push_stream_store_messages). push_stream_store_messages [ on | off ] h4(#push_stream_max_number_of_channels). push_stream_max_number_of_channels [ number ]
default: off default: -
context: location context: http
location: push_stream_publisher location: main nginx configuration
Whether or not message queuing is enabled. The maximum number of concurrent channels on the server. If you do not want to limit the number of channels, just not set this directive.
If store messages is "On" is needed to set at least one of these two directives push_stream_min_message_buffer_timeout or push_stream_max_message_buffer_length.
h4(#push_stream_min_message_buffer_timeout). push_stream_min_message_buffer_timeout [ time ] h4(#push_stream_max_number_of_broadcast_channels). push_stream_max_number_of_broadcast_channels [ number ]
default: - default: -
context: location context: http
location: push_stream_publisher location: main nginx configuration
The length of time a message may be queued before it is considered expired. If you do not want messages to expire, just not set this directive. The maximum number of concurrent broadcats channels on the server. If you do not want to limit the number of broadcast channels, just not set this directive.
h4(#push_stream_max_message_buffer_length). push_stream_max_message_buffer_length [ number ] h4(#push_stream_broadcast_channel_prefix). push_stream_broadcast_channel_prefix [ string ]
default: - default: -
context: http
location: main nginx configuration
The string prefix used to identify when a channel is a normal or broadcast channel, example: when you set this directive as "bd_", "bd_ch1" will be a broadcast channel
h4(#push_stream_store_messages). push_stream_store_messages [ on | off ]
default: off
context: location context: location
location: push_stream_publisher location: push_stream_publisher
The maximum number of messages to store per channel. A channel's message buffer will retain at most this many most recent messages. If you do not want messages to be discarded by length, just not set this directive. Whether or not message queuing is enabled.
If store messages is "on" is needed to set at least one of these two directives push_stream_message_ttl or push_stream_max_messages_stored_per_channel.
h3(#security). Security
h4(#push_stream_authorized_channels_only). push_stream_authorized_channels_only [ on | off ] h4(#push_stream_authorized_channels_only). push_stream_authorized_channels_only [ on | off ]
...@@ -403,92 +440,65 @@ location: push_stream_subscriber ...@@ -403,92 +440,65 @@ location: push_stream_subscriber
Whether or not a subscriber may create a channel by making a request to a push_stream_subscriber location. If set to on, a publisher must send a POST request before a subscriber can request messages on the channel. Otherwise, all subscriber requests to nonexistent channels will get a 403 Forbidden response. Whether or not a subscriber may create a channel by making a request to a push_stream_subscriber location. If set to on, a publisher must send a POST request before a subscriber can request messages on the channel. Otherwise, all subscriber requests to nonexistent channels will get a 403 Forbidden response.
This restriction is not applied to broadcast channels, but to subscribe to a broadcast channel is necessary to subscribe at least to one normal channel, and if this directive is set to on this channel has to be created before. This restriction is not applied to broadcast channels, but to subscribe to a broadcast channel is necessary to subscribe at least to one normal channel, and if this directive is set to on this channel has to be created before.
h4(#push_stream_subscriber_connection_timeout). push_stream_subscriber_connection_timeout [ time ] h4(#push_stream_header_template). push_stream_header_template [ string ]
default: - default: -
context: location context: location
location: push_stream_subscriber location: push_stream_subscriber
The length of time a subscriber will stay connected before it is considered expired and disconnected. If you do not want subscribers to be automatically disconnected, just not set this directive. The text that will be sended to subscribers when they arrive.
But, this operation is very important to help Nginx recycle memory consumed to send messages to susbscriber, allocated at pool request.
h4(#push_stream_max_channel_id_length). push_stream_max_channel_id_length [ number ]
default: -
context: location
location: (push_stream_subscriber and push_stream_publisher) or main nginx configuration
Maximum permissible channel id length (number of characters). Longer ids will receive an 400 Bad Request response.
h4(#push_stream_broadcast_channel_prefix). push_stream_broadcast_channel_prefix [ string ] h4(#push_stream_message_template). push_stream_message_template [ string ]
default: - default: ==~text~==
context: location context: location
location: (push_stream_subscriber and push_stream_publisher) or main nginx configuration location: push_stream_subscriber
The string prefix used to identify when a channel is as normal or broadcast channel, example: when you set this directive as "bd_", "bd_ch1" will be a broadcast channel The text template that will be used to format the message before be sended to subscribers. The template can contain any number of the reserved words: ==~id~, ~text~, ~channel~ and ~event-id~, example: "&lt;script&gt;p(~id~,'~channel~','~text~');&lt;/script&gt;"==
h4(#push_stream_broadcast_channel_max_qtd). push_stream_broadcast_channel_max_qtd [ number ] h4(#push_stream_footer_template). push_stream_footer_template [ string ]
New in version 0.2.6
default: - default: -
context: location context: location
location: (push_stream_subscriber and push_stream_publisher) or main nginx configuration location: push_stream_subscriber
The maximum number of broadcast channels that a subscriber may sign on the request. The text that will be sended to subscribers before connection is closed (channel deleted ou subscriber timeout).
This directive works in conjunction with push_stream_authorized_channels_only to preserve the server from a kind of attack where a subscriber sign one normal channel and many nonexistent broadcast channels.
h4(#push_stream_max_number_of_channels). push_stream_max_number_of_channels [ number ] h4(#push_stream_content_type). push_stream_content_type [ string ]
default: - default: text/plain
context: location context: location
location: (push_stream_subscriber and push_stream_publisher) or main nginx configuration location: push_stream_subscriber
The maximum number of concurrent channels on the server. If you do not want to limit the number of channels, just not set this directive. The content type used on responses to subscribers. Must be complient with push_stream_header_template, push_stream_message_template and push_stream_footer_template.
h4(#push_stream_max_number_of_broadcast_channels). push_stream_max_number_of_broadcast_channels [ number ] h4(#push_stream_broadcast_channel_max_qtd). push_stream_broadcast_channel_max_qtd [ number ]
default: - default: -
context: location context: location
location: (push_stream_subscriber and push_stream_publisher) or main nginx configuration location: push_stream_subscriber
The maximum number of concurrent broadcats channels on the server. If you do not want to limit the number of broadcast channels, just not set this directive. The maximum number of broadcast channels that a subscriber may sign on the request.
This directive works in conjunction with push_stream_authorized_channels_only to preserve the server from a kind of attack where a subscriber sign one normal channel and many nonexistent broadcast channels.
h4(#push_stream_keepalive). push_stream_keepalive [ on | off ] h4(#push_stream_keepalive). push_stream_keepalive [ on | off ]
New in version 0.2.4 New in version 0.2.4
default: off default: off
context: http, location context: location
location: (push_stream_publisher and push_stream_channels_statistics) or main nginx configuration location: push_stream_publisher, push_stream_channels_statistics
Enable keepalive connections, on publisher or channels statistics locations. Enable keepalive connections, on publisher or channels statistics locations.
h4(#push_stream_eventsource_support). push_stream_eventsource_support [ on | off ]
h4(#push_stream_publisher_admin). push_stream_publisher_admin [ on | off ] New in version 0.3.0
New in version 0.2.5
default: off default: off
context: location context: location
location: push_stream_publisher location: push_stream_subscriber
Enable admin features for publishers.
They can delete channels removing any existent subscribers using DELETE http method.
<pre>
<code>
# Pub create channel 1
curl -s -v -X POST "http://localhost/pub?id=my_channel_1" -d "Hello World 1!"
# Pub create channel 2
curl -s -v -X POST "http://localhost/pub?id=my_channel_2" -d "Hello World 2!"
# Sub on both channels
curl -s -v "http://localhost/sub/my_channel_1.b1/my_channel_2.b1"
# Pub delete channel 2
curl -s -v -X DELETE "http://localhost/pub?id=my_channel_2"
</code>
</pre>
Enable "Event Source":eventsource support for subscribers.
h2(#attention). Attention h2(#attention). Attention
...@@ -509,6 +519,7 @@ To run them is needed to have an environment with: ...@@ -509,6 +519,7 @@ To run them is needed to have an environment with:
** em-http-request >= 0.2.14 ** em-http-request >= 0.2.14
** json >= 1.4.3 ** json >= 1.4.3
** ruby-debug >= 0.10.4 ** ruby-debug >= 0.10.4
** jasmine >= 1.0.2.1
You can install these gems with bundler (bundler is required to be installed before, _gem install bundler_) You can install these gems with bundler (bundler is required to be installed before, _gem install bundler_)
...@@ -527,23 +538,24 @@ gem install POpen4 -v 0.1.4 ...@@ -527,23 +538,24 @@ gem install POpen4 -v 0.1.4
gem install em-http-request -v 0.2.14 gem install em-http-request -v 0.2.14
gem install json -v 1.4.3 gem install json -v 1.4.3
gem install ruby-debug -v 0.10.4 gem install ruby-debug -v 0.10.4
gem install jasmine -v 1.0.2.1
</code> </code>
</pre> </pre>
Then issue <code>rake tests</code>. Then issue @rake tests@.
This command run the tests using nginx *executable* located at _/usr/local/nginx/sbin/nginx_ with _1_ *worker* responding at *host* _localhost_ and *port* _9990_. This command run the tests using nginx *executable* located at _/usr/local/nginx/sbin/nginx_ with _1_ *worker* responding at *host* _localhost_ and *port* _9990_.
To change this behavior use the commands bellow To change this behavior use the commands bellow
<pre> <pre>
<code> <code>
rake tests executable="../build/nginx-1.0.0/objs/nginx" # to change default path for nginx executable rake tests executable="../build/nginx-1.0.5/objs/nginx" # to change default path for nginx executable
rake tests host=localhost # to change default hostname rake tests host=my_machine # to change default hostname
rake tests port=9889 # to change default port rake tests port=9889 # to change default port
rake tests workers=2 # to change dafault number of workers used rake tests workers=2 # to change dafault number of workers used
and can combine any of these parameters, like: and can combine any of these parameters, like:
rake tests port=9889 executable="../build/nginx-1.0.0/objs/nginx" rake tests port=9889 executable="../build/nginx-1.0.5/objs/nginx"
</code> </code>
</pre> </pre>
...@@ -555,12 +567,8 @@ h2(#contributors). Contributors ...@@ -555,12 +567,8 @@ h2(#contributors). Contributors
"People":contributors "People":contributors
h2(#donate). Donate
Feel free to give something back ;)
"Donate":donate
[changelog]https://github.com/wandenberg/nginx-push-stream-module/blob/master/CHANGELOG.textile [changelog]https://github.com/wandenberg/nginx-push-stream-module/blob/master/CHANGELOG.textile
[contributors]https://github.com/wandenberg/nginx-push-stream-module/contributors [contributors]https://github.com/wandenberg/nginx-push-stream-module/contributors
[discussion]https://groups.google.com/group/nginxpushstream [discussion]https://groups.google.com/group/nginxpushstream
[donate]https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4LP6P9A7BC37S [donate]https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4LP6P9A7BC37S
[eventsource]http://dev.w3.org/html5/eventsource/
...@@ -42,37 +42,37 @@ typedef struct { ...@@ -42,37 +42,37 @@ typedef struct {
typedef struct { typedef struct {
size_t shm_size; size_t shm_size;
ngx_msec_t memory_cleanup_interval; ngx_msec_t memory_cleanup_interval;
time_t memory_cleanup_timeout; time_t shm_cleanup_objects_ttl;
ngx_str_t channel_deleted_message_text; ngx_str_t channel_deleted_message_text;
ngx_str_t ping_message_text; ngx_str_t ping_message_text;
ngx_uint_t qtd_templates; ngx_uint_t qtd_templates;
ngx_str_t broadcast_channel_prefix;
ngx_uint_t max_number_of_channels;
ngx_uint_t max_number_of_broadcast_channels;
ngx_msec_t ping_message_interval;
ngx_msec_t subscriber_disconnect_interval;
time_t subscriber_connection_ttl;
ngx_msec_t buffer_cleanup_interval;
time_t message_ttl;
ngx_uint_t max_messages_stored_per_channel;
ngx_uint_t max_channel_id_length;
ngx_http_push_stream_template_queue_t msg_templates; ngx_http_push_stream_template_queue_t msg_templates;
} ngx_http_push_stream_main_conf_t; } ngx_http_push_stream_main_conf_t;
typedef struct { typedef struct {
ngx_int_t index_channel_id; ngx_int_t index_channel_id;
ngx_int_t index_channels_path; ngx_int_t index_channels_path;
time_t buffer_timeout;
ngx_uint_t max_messages;
ngx_uint_t authorized_channels_only; ngx_uint_t authorized_channels_only;
ngx_uint_t store_messages; ngx_flag_t store_messages;
ngx_uint_t max_channel_id_length;
ngx_str_t header_template; ngx_str_t header_template;
ngx_str_t message_template; ngx_str_t message_template;
ngx_int_t message_template_index; ngx_int_t message_template_index;
ngx_str_t footer_template; ngx_str_t footer_template;
ngx_str_t content_type; ngx_str_t content_type;
ngx_msec_t ping_message_interval;
ngx_msec_t subscriber_disconnect_interval;
time_t subscriber_connection_timeout;
ngx_str_t broadcast_channel_prefix;
ngx_uint_t broadcast_channel_max_qtd; ngx_uint_t broadcast_channel_max_qtd;
ngx_uint_t max_number_of_channels;
ngx_uint_t max_number_of_broadcast_channels;
ngx_msec_t buffer_cleanup_interval;
ngx_uint_t keepalive; ngx_uint_t keepalive;
ngx_uint_t publisher_admin; ngx_uint_t publisher_admin;
ngx_flag_t subscriber_eventsource; ngx_flag_t eventsource_support;
ngx_uint_t subscriber_mode; ngx_uint_t subscriber_mode;
} ngx_http_push_stream_loc_conf_t; } ngx_http_push_stream_loc_conf_t;
...@@ -231,6 +231,8 @@ static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_ETAG = ngx_string("Etag"); ...@@ -231,6 +231,8 @@ static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_ETAG = ngx_string("Etag");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_IF_NONE_MATCH = ngx_string("If-None-Match"); static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_IF_NONE_MATCH = ngx_string("If-None-Match");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_VARY = ngx_string("Vary"); static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_VARY = ngx_string("Vary");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_NORMAL = ngx_string("normal");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_ADMIN = ngx_string("admin");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_MODE_STREAMING = ngx_string("streaming"); static const ngx_str_t NGX_HTTP_PUSH_STREAM_MODE_STREAMING = ngx_string("streaming");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_MODE_POLLING = ngx_string("polling"); static const ngx_str_t NGX_HTTP_PUSH_STREAM_MODE_POLLING = ngx_string("polling");
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <ngx_http_push_stream_module_subscriber.h> #include <ngx_http_push_stream_module_subscriber.h>
#define NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_SIZE 33554432 // 32 megs #define NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_SIZE 33554432 // 32 megs
static time_t NGX_HTTP_PUSH_STREAM_DEFAULT_MEMORY_CLEANUP_TIMEOUT = 30; // 30 seconds static time_t NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_MEMORY_CLEANUP_OBJECTS_TTL = 30; // 30 seconds
#define NGX_HTTP_PUSH_STREAM_DEFAULT_HEADER_TEMPLATE "" #define NGX_HTTP_PUSH_STREAM_DEFAULT_HEADER_TEMPLATE ""
#define NGX_HTTP_PUSH_STREAM_DEFAULT_MESSAGE_TEMPLATE "~text~" #define NGX_HTTP_PUSH_STREAM_DEFAULT_MESSAGE_TEMPLATE "~text~"
......
...@@ -187,10 +187,10 @@ static ngx_http_push_stream_content_subtype_t subtypes[] = { ...@@ -187,10 +187,10 @@ static ngx_http_push_stream_content_subtype_t subtypes[] = {
}; };
static const ngx_int_t NGX_HTTP_PUSH_STREAM_PING_MESSAGE_ID = -1; static const ngx_int_t NGX_HTTP_PUSH_STREAM_PING_MESSAGE_ID = -1;
static const ngx_str_t NGX_HTTP_PUSH_STREAM_PING_MESSAGE_TEXT = ngx_string(""); #define NGX_HTTP_PUSH_STREAM_PING_MESSAGE_TEXT ""
static const ngx_int_t NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_ID = -2; static const ngx_int_t NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_ID = -2;
static const ngx_str_t NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_TEXT = ngx_string("Channel deleted"); #define NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_TEXT "Channel deleted"
static const ngx_str_t NGX_HTTP_PUSH_STREAM_TOKEN_MESSAGE_ID = ngx_string("~id~"); static const ngx_str_t NGX_HTTP_PUSH_STREAM_TOKEN_MESSAGE_ID = ngx_string("~id~");
static const ngx_str_t NGX_HTTP_PUSH_STREAM_TOKEN_MESSAGE_EVENT_ID = ngx_string("~event-id~"); static const ngx_str_t NGX_HTTP_PUSH_STREAM_TOKEN_MESSAGE_EVENT_ID = ngx_string("~event-id~");
...@@ -228,21 +228,21 @@ static ngx_int_t ngx_http_push_stream_send_response_content_header(ng ...@@ -228,21 +228,21 @@ static ngx_int_t ngx_http_push_stream_send_response_content_header(ng
static void ngx_http_push_stream_send_response_message(ngx_http_request_t *r, ngx_http_push_stream_channel_t *channel, ngx_http_push_stream_msg_t *msg); static void ngx_http_push_stream_send_response_message(ngx_http_request_t *r, ngx_http_push_stream_channel_t *channel, ngx_http_push_stream_msg_t *msg);
static ngx_int_t ngx_http_push_stream_send_response_text(ngx_http_request_t *r, const u_char *text, uint len, ngx_flag_t last_buffer); static ngx_int_t ngx_http_push_stream_send_response_text(ngx_http_request_t *r, const u_char *text, uint len, ngx_flag_t last_buffer);
static void ngx_http_push_stream_send_response_finalize(ngx_http_request_t *r); static void ngx_http_push_stream_send_response_finalize(ngx_http_request_t *r);
static ngx_int_t ngx_http_push_stream_send_ping(ngx_log_t *log, ngx_http_push_stream_loc_conf_t *pslcf); static ngx_int_t ngx_http_push_stream_memory_cleanup();
static ngx_int_t ngx_http_push_stream_memory_cleanup(ngx_log_t *log, ngx_http_push_stream_main_conf_t *psmcf); static ngx_int_t ngx_http_push_stream_buffer_cleanup();
static ngx_int_t ngx_http_push_stream_buffer_cleanup(ngx_log_t *log, ngx_http_push_stream_loc_conf_t *pslcf);
static void ngx_http_push_stream_ping_timer_wake_handler(ngx_event_t *ev); static void ngx_http_push_stream_ping_timer_wake_handler(ngx_event_t *ev);
static void ngx_http_push_stream_ping_timer_set(ngx_http_push_stream_loc_conf_t *pslcf);
static void ngx_http_push_stream_disconnect_timer_wake_handler(ngx_event_t *ev); static void ngx_http_push_stream_disconnect_timer_wake_handler(ngx_event_t *ev);
static void ngx_http_push_stream_disconnect_timer_set(ngx_http_push_stream_loc_conf_t *pslcf);
static void ngx_http_push_stream_memory_cleanup_timer_wake_handler(ngx_event_t *ev); static void ngx_http_push_stream_memory_cleanup_timer_wake_handler(ngx_event_t *ev);
static void ngx_http_push_stream_memory_cleanup_timer_set(ngx_http_push_stream_main_conf_t *psmcf);
static void ngx_http_push_stream_buffer_timer_wake_handler(ngx_event_t *ev); static void ngx_http_push_stream_buffer_timer_wake_handler(ngx_event_t *ev);
static void ngx_http_push_stream_buffer_cleanup_timer_set(ngx_http_push_stream_loc_conf_t *pslcf);
static void ngx_http_push_stream_timer_set(ngx_msec_t timer_interval, ngx_event_t *event, ngx_event_handler_pt event_handler, ngx_flag_t start_timer);
static void ngx_http_push_stream_timer_reset(ngx_msec_t timer_interval, ngx_event_t *timer_event); static void ngx_http_push_stream_timer_reset(ngx_msec_t timer_interval, ngx_event_t *timer_event);
#define ngx_http_push_stream_ping_timer_set() ngx_http_push_stream_timer_set(ngx_http_push_stream_module_main_conf->ping_message_interval, &ngx_http_push_stream_ping_event, ngx_http_push_stream_ping_timer_wake_handler, 1);
#define ngx_http_push_stream_disconnect_timer_set() ngx_http_push_stream_timer_set(ngx_http_push_stream_module_main_conf->subscriber_disconnect_interval, &ngx_http_push_stream_disconnect_event, ngx_http_push_stream_disconnect_timer_wake_handler, 1);
#define ngx_http_push_stream_memory_cleanup_timer_set() ngx_http_push_stream_timer_set(ngx_http_push_stream_module_main_conf->memory_cleanup_interval, &ngx_http_push_stream_memory_cleanup_event, ngx_http_push_stream_memory_cleanup_timer_wake_handler, 1);
#define ngx_http_push_stream_buffer_cleanup_timer_set(pslcf) ngx_http_push_stream_timer_set(ngx_http_push_stream_module_main_conf->buffer_cleanup_interval, &ngx_http_push_stream_buffer_cleanup_event, ngx_http_push_stream_buffer_timer_wake_handler, pslcf->store_messages);
static void ngx_http_push_stream_worker_subscriber_cleanup_locked(ngx_http_push_stream_worker_subscriber_t *worker_subscriber); static void ngx_http_push_stream_worker_subscriber_cleanup_locked(ngx_http_push_stream_worker_subscriber_t *worker_subscriber);
static ngx_str_t * ngx_http_push_stream_create_str(ngx_pool_t *pool, uint len); static ngx_str_t * ngx_http_push_stream_create_str(ngx_pool_t *pool, uint len);
......
...@@ -30,8 +30,19 @@ http { ...@@ -30,8 +30,19 @@ http {
client_max_body_size 1k; client_max_body_size 1k;
client_body_buffer_size 1k; client_body_buffer_size 1k;
ignore_invalid_headers on; ignore_invalid_headers on;
client_body_in_single_buffer on;
push_stream_max_reserved_memory 10m; push_stream_shared_memory_size 10m;
push_stream_max_channel_id_length 200;
# max messages to store in memory
push_stream_max_messages_stored_per_channel 20;
# message ttl
push_stream_message_ttl 5m;
# ping frequency
push_stream_ping_message_interval 10s;
# connection ttl to enable recycle
push_stream_subscriber_connection_ttl 15m;
# broadcast
push_stream_broadcast_channel_prefix "broad_";
server { server {
listen 80; listen 80;
...@@ -46,18 +57,13 @@ http { ...@@ -46,18 +57,13 @@ http {
} }
location /pub { location /pub {
# activate publisher mode for this location # activate publisher mode for this location, with admin support
push_stream_publisher; push_stream_publisher admin;
# query string based channel id # query string based channel id
set $push_stream_channel_id $arg_id; set $push_stream_channel_id $arg_id;
push_stream_max_channel_id_length 200;
# store messages in memory # store messages in memory
push_stream_store_messages on; push_stream_store_messages on;
# max messages to store in memory
push_stream_max_message_buffer_length 20;
# message ttl
push_stream_min_message_buffer_timeout 5m;
# Message size limit # Message size limit
# client_max_body_size MUST be equal to client_body_buffer_size or # client_max_body_size MUST be equal to client_body_buffer_size or
...@@ -72,7 +78,6 @@ http { ...@@ -72,7 +78,6 @@ http {
# positional channel path # positional channel path
set $push_stream_channels_path $1; set $push_stream_channels_path $1;
push_stream_max_channel_id_length 200;
# header to be sent when receiving new subscriber connection # header to be sent when receiving new subscriber connection
push_stream_header_template "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta http-equiv=\"Cache-Control\" content=\"no-store\">\r\n<meta http-equiv=\"Cache-Control\" content=\"no-cache\">\r\n<meta http-equiv=\"Pragma\" content=\"no-cache\">\r\n<meta http-equiv=\"Expires\" content=\"Thu, 1 Jan 1970 00:00:00 GMT\">\r\n<script type=\"text/javascript\">\r\nwindow.onError = null;\r\ndocument.domain = 'localhost';\r\nparent.PushStream.register(this);\r\n</script>\r\n</head>\r\n<body onload=\"try { parent.PushStream.reset(this) } catch (e) {}\">"; push_stream_header_template "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta http-equiv=\"Cache-Control\" content=\"no-store\">\r\n<meta http-equiv=\"Cache-Control\" content=\"no-cache\">\r\n<meta http-equiv=\"Pragma\" content=\"no-cache\">\r\n<meta http-equiv=\"Expires\" content=\"Thu, 1 Jan 1970 00:00:00 GMT\">\r\n<script type=\"text/javascript\">\r\nwindow.onError = null;\r\ndocument.domain = 'localhost';\r\nparent.PushStream.register(this);\r\n</script>\r\n</head>\r\n<body onload=\"try { parent.PushStream.reset(this) } catch (e) {}\">";
# message template # message template
...@@ -84,12 +89,6 @@ http { ...@@ -84,12 +89,6 @@ http {
# subscriber may create channels on demand or only authorized # subscriber may create channels on demand or only authorized
# (publisher) may do it? # (publisher) may do it?
push_stream_authorized_channels_only off; push_stream_authorized_channels_only off;
# ping frequency
push_stream_ping_message_interval 10s;
# connection ttl to enable recycle
push_stream_subscriber_connection_timeout 15m;
# broadcast
push_stream_broadcast_channel_prefix "broad_";
push_stream_broadcast_channel_max_qtd 3; push_stream_broadcast_channel_max_qtd 3;
} }
} }
......
...@@ -42,7 +42,7 @@ ngx_http_push_stream_get_channel_id(ngx_http_request_t *r, ngx_http_push_stream_ ...@@ -42,7 +42,7 @@ ngx_http_push_stream_get_channel_id(ngx_http_request_t *r, ngx_http_push_stream_
} }
// maximum length limiter for channel id // maximum length limiter for channel id
if ((cf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (vv->len > cf->max_channel_id_length)) { if ((ngx_http_push_stream_module_main_conf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (vv->len > ngx_http_push_stream_module_main_conf->max_channel_id_length)) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: channel id is larger than allowed %d", vv->len); ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: channel id is larger than allowed %d", vv->len);
return NGX_HTTP_PUSH_STREAM_TOO_LARGE_CHANNEL_ID; return NGX_HTTP_PUSH_STREAM_TOO_LARGE_CHANNEL_ID;
} }
......
...@@ -315,7 +315,7 @@ ngx_http_push_stream_send_worker_ping_message(void) ...@@ -315,7 +315,7 @@ ngx_http_push_stream_send_worker_ping_message(void)
while ((cur = (ngx_http_push_stream_worker_subscriber_t *) ngx_queue_next(&cur->queue)) != sentinel) { while ((cur = (ngx_http_push_stream_worker_subscriber_t *) ngx_queue_next(&cur->queue)) != sentinel) {
if (cur->request != NULL) { if (cur->request != NULL) {
ngx_http_push_stream_loc_conf_t *pslcf = ngx_http_get_module_loc_conf(cur->request, ngx_http_push_stream_module); ngx_http_push_stream_loc_conf_t *pslcf = ngx_http_get_module_loc_conf(cur->request, ngx_http_push_stream_module);
if (pslcf->subscriber_eventsource) { if (pslcf->eventsource_support) {
ngx_http_push_stream_send_response_text(cur->request, NGX_HTTP_PUSH_STREAM_EVENTSOURCE_PING_MESSAGE_CHUNK.data, NGX_HTTP_PUSH_STREAM_EVENTSOURCE_PING_MESSAGE_CHUNK.len, 0); ngx_http_push_stream_send_response_text(cur->request, NGX_HTTP_PUSH_STREAM_EVENTSOURCE_PING_MESSAGE_CHUNK.data, NGX_HTTP_PUSH_STREAM_EVENTSOURCE_PING_MESSAGE_CHUNK.len, 0);
} else { } else {
ngx_http_push_stream_send_response_message(cur->request, NULL, ngx_http_push_stream_ping_msg); ngx_http_push_stream_send_response_message(cur->request, NULL, ngx_http_push_stream_ping_msg);
......
...@@ -211,12 +211,12 @@ ngx_http_push_stream_publisher_body_handler(ngx_http_request_t *r) ...@@ -211,12 +211,12 @@ ngx_http_push_stream_publisher_body_handler(ngx_http_request_t *r)
msg->time = ngx_time(); msg->time = ngx_time();
msg->tag = (msg->time == channel->last_message_time) ? (channel->last_message_tag + 1) : 0; msg->tag = (msg->time == channel->last_message_time) ? (channel->last_message_tag + 1) : 0;
// set message expiration time // set message expiration time
msg->expires = (cf->buffer_timeout == NGX_CONF_UNSET ? 0 : (ngx_time() + cf->buffer_timeout)); msg->expires = (ngx_http_push_stream_module_main_conf->message_ttl == NGX_CONF_UNSET ? 0 : (ngx_time() + ngx_http_push_stream_module_main_conf->message_ttl));
ngx_queue_insert_tail(&channel->message_queue.queue, &msg->queue); ngx_queue_insert_tail(&channel->message_queue.queue, &msg->queue);
channel->stored_messages++; channel->stored_messages++;
// now see if the queue is too big // now see if the queue is too big
ngx_http_push_stream_ensure_qtd_of_messages_locked(channel, cf->max_messages, 0); ngx_http_push_stream_ensure_qtd_of_messages_locked(channel, ngx_http_push_stream_module_main_conf->max_messages_stored_per_channel, 0);
channel->last_message_time = msg->time; channel->last_message_time = msg->time;
channel->last_message_tag = msg->tag; channel->last_message_tag = msg->tag;
......
...@@ -27,34 +27,36 @@ ...@@ -27,34 +27,36 @@
static ngx_command_t ngx_http_push_stream_commands[] = { static ngx_command_t ngx_http_push_stream_commands[] = {
{ ngx_string("push_stream_channels_statistics"), { ngx_string("push_stream_channels_statistics"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_push_stream_channels_statistics, ngx_http_push_stream_channels_statistics,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
0, 0,
NULL }, NULL },
{ ngx_string("push_stream_publisher"), { ngx_string("push_stream_publisher"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
ngx_http_push_stream_publisher, ngx_http_push_stream_publisher,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
0, offsetof(ngx_http_push_stream_loc_conf_t, publisher_admin),
NULL }, NULL },
{ ngx_string("push_stream_subscriber"), { ngx_string("push_stream_subscriber"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1, NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
ngx_http_push_stream_subscriber, ngx_http_push_stream_subscriber,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, subscriber_mode), offsetof(ngx_http_push_stream_loc_conf_t, subscriber_mode),
NULL }, NULL },
{ ngx_string("push_stream_max_reserved_memory"),
/* Main directives*/
{ ngx_string("push_stream_shared_memory_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot, ngx_conf_set_size_slot,
NGX_HTTP_MAIN_CONF_OFFSET, NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, shm_size), offsetof(ngx_http_push_stream_main_conf_t, shm_size),
NULL }, NULL },
{ ngx_string("push_stream_memory_cleanup_timeout"), { ngx_string("push_stream_shared_memory_cleanup_objects_ttl"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_sec_slot, ngx_conf_set_sec_slot,
NGX_HTTP_MAIN_CONF_OFFSET, NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, memory_cleanup_timeout), offsetof(ngx_http_push_stream_main_conf_t, shm_cleanup_objects_ttl),
NULL }, NULL },
{ ngx_string("push_stream_channel_deleted_message_text"), { ngx_string("push_stream_channel_deleted_message_text"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
...@@ -68,29 +70,61 @@ static ngx_command_t ngx_http_push_stream_commands[] = { ...@@ -68,29 +70,61 @@ static ngx_command_t ngx_http_push_stream_commands[] = {
NGX_HTTP_MAIN_CONF_OFFSET, NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, ping_message_text), offsetof(ngx_http_push_stream_main_conf_t, ping_message_text),
NULL }, NULL },
{ ngx_string("push_stream_store_messages"), { ngx_string("push_stream_message_ttl"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, store_messages),
NULL },
{ ngx_string("push_stream_min_message_buffer_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_sec_slot, ngx_conf_set_sec_slot,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, buffer_timeout), offsetof(ngx_http_push_stream_main_conf_t, message_ttl),
NULL }, NULL },
{ ngx_string("push_stream_max_message_buffer_length"), { ngx_string("push_stream_max_messages_stored_per_channel"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot, ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, max_messages), offsetof(ngx_http_push_stream_main_conf_t, max_messages_stored_per_channel),
NULL }, NULL },
{ ngx_string("push_stream_max_channel_id_length"), { ngx_string("push_stream_max_channel_id_length"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, max_channel_id_length),
NULL },
{ ngx_string("push_stream_ping_message_interval"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, ping_message_interval),
NULL },
{ ngx_string("push_stream_subscriber_connection_ttl"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_sec_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, subscriber_connection_ttl),
NULL },
{ ngx_string("push_stream_max_number_of_channels"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot, ngx_conf_set_num_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, max_number_of_channels),
NULL },
{ ngx_string("push_stream_max_number_of_broadcast_channels"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, max_number_of_broadcast_channels),
NULL },
{ ngx_string("push_stream_broadcast_channel_prefix"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_push_stream_main_conf_t, broadcast_channel_prefix),
NULL },
/* Location directives */
{ ngx_string("push_stream_store_messages"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, max_channel_id_length), offsetof(ngx_http_push_stream_loc_conf_t, store_messages),
NULL }, NULL },
{ ngx_string("push_stream_authorized_channels_only"), { ngx_string("push_stream_authorized_channels_only"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
...@@ -122,59 +156,23 @@ static ngx_command_t ngx_http_push_stream_commands[] = { ...@@ -122,59 +156,23 @@ static ngx_command_t ngx_http_push_stream_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, content_type), offsetof(ngx_http_push_stream_loc_conf_t, content_type),
NULL }, NULL },
{ ngx_string("push_stream_ping_message_interval"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, ping_message_interval),
NULL },
{ ngx_string("push_stream_subscriber_connection_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_sec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, subscriber_connection_timeout),
NULL },
{ ngx_string("push_stream_broadcast_channel_prefix"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, broadcast_channel_prefix),
NULL },
{ ngx_string("push_stream_broadcast_channel_max_qtd"), { ngx_string("push_stream_broadcast_channel_max_qtd"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot, ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, broadcast_channel_max_qtd), offsetof(ngx_http_push_stream_loc_conf_t, broadcast_channel_max_qtd),
NULL }, NULL },
{ ngx_string("push_stream_max_number_of_channels"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, max_number_of_channels),
NULL },
{ ngx_string("push_stream_max_number_of_broadcast_channels"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, max_number_of_broadcast_channels),
NULL },
{ ngx_string("push_stream_keepalive"), { ngx_string("push_stream_keepalive"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, keepalive), offsetof(ngx_http_push_stream_loc_conf_t, keepalive),
NULL }, NULL },
{ ngx_string("push_stream_publisher_admin"), { ngx_string("push_stream_eventsource_support"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, publisher_admin), offsetof(ngx_http_push_stream_loc_conf_t, eventsource_support),
NULL },
{ ngx_string("push_stream_subscriber_eventsource"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, subscriber_eventsource),
NULL }, NULL },
ngx_null_command ngx_null_command
}; };
...@@ -239,7 +237,7 @@ ngx_http_push_stream_init_worker(ngx_cycle_t *cycle) ...@@ -239,7 +237,7 @@ ngx_http_push_stream_init_worker(ngx_cycle_t *cycle)
thisworker_data->pid = ngx_pid; thisworker_data->pid = ngx_pid;
// turn on timer to cleanup memory of old messages and channels // turn on timer to cleanup memory of old messages and channels
ngx_http_push_stream_memory_cleanup_timer_set(ngx_http_push_stream_module_main_conf); ngx_http_push_stream_memory_cleanup_timer_set();
return ngx_http_push_stream_register_worker_message_handler(cycle); return ngx_http_push_stream_register_worker_message_handler(cycle);
} }
...@@ -301,7 +299,7 @@ ngx_http_push_stream_postconfig(ngx_conf_t *cf) ...@@ -301,7 +299,7 @@ ngx_http_push_stream_postconfig(ngx_conf_t *cf)
// initialize shared memory // initialize shared memory
shm_size = ngx_align(conf->shm_size, ngx_pagesize); shm_size = ngx_align(conf->shm_size, ngx_pagesize);
if (shm_size < 16 * ngx_pagesize) { if (shm_size < 16 * ngx_pagesize) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The push_stream_max_reserved_memory value must be at least %udKiB", (16 * ngx_pagesize) >> 10); ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The push_stream_shared_memory_size value must be at least %udKiB", (16 * ngx_pagesize) >> 10);
shm_size = 16 * ngx_pagesize; shm_size = 16 * ngx_pagesize;
} }
if (ngx_http_push_stream_shm_zone && ngx_http_push_stream_shm_zone->shm.size != shm_size) { if (ngx_http_push_stream_shm_zone && ngx_http_push_stream_shm_zone->shm.size != shm_size) {
...@@ -324,9 +322,20 @@ ngx_http_push_stream_create_main_conf(ngx_conf_t *cf) ...@@ -324,9 +322,20 @@ ngx_http_push_stream_create_main_conf(ngx_conf_t *cf)
} }
mcf->shm_size = NGX_CONF_UNSET_SIZE; mcf->shm_size = NGX_CONF_UNSET_SIZE;
mcf->memory_cleanup_timeout = NGX_CONF_UNSET; mcf->memory_cleanup_interval = NGX_CONF_UNSET_MSEC;
mcf->shm_cleanup_objects_ttl = NGX_CONF_UNSET;
mcf->channel_deleted_message_text.data = NULL; mcf->channel_deleted_message_text.data = NULL;
mcf->ping_message_text.data = NULL; mcf->ping_message_text.data = NULL;
mcf->broadcast_channel_prefix.data = NULL;
mcf->max_number_of_channels = NGX_CONF_UNSET_UINT;
mcf->max_number_of_broadcast_channels = NGX_CONF_UNSET_UINT;
mcf->buffer_cleanup_interval = NGX_CONF_UNSET_MSEC;
mcf->message_ttl = NGX_CONF_UNSET;
mcf->max_channel_id_length = NGX_CONF_UNSET_UINT;
mcf->ping_message_interval = NGX_CONF_UNSET_MSEC;
mcf->subscriber_disconnect_interval = NGX_CONF_UNSET_MSEC;
mcf->subscriber_connection_ttl = NGX_CONF_UNSET;
mcf->max_messages_stored_per_channel = NGX_CONF_UNSET_UINT;
mcf->qtd_templates = 0; mcf->qtd_templates = 0;
ngx_queue_init(&mcf->msg_templates.queue); ngx_queue_init(&mcf->msg_templates.queue);
...@@ -341,34 +350,79 @@ ngx_http_push_stream_init_main_conf(ngx_conf_t *cf, void *parent) ...@@ -341,34 +350,79 @@ ngx_http_push_stream_init_main_conf(ngx_conf_t *cf, void *parent)
{ {
ngx_http_push_stream_main_conf_t *conf = parent; ngx_http_push_stream_main_conf_t *conf = parent;
if (conf->memory_cleanup_timeout == NGX_CONF_UNSET) { ngx_conf_init_value(conf->shm_cleanup_objects_ttl, NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_MEMORY_CLEANUP_OBJECTS_TTL);
conf->memory_cleanup_timeout = NGX_HTTP_PUSH_STREAM_DEFAULT_MEMORY_CLEANUP_TIMEOUT; ngx_conf_init_size_value(conf->shm_size, NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_SIZE);
ngx_conf_merge_str_value(conf->channel_deleted_message_text, conf->channel_deleted_message_text, NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_TEXT);
ngx_conf_merge_str_value(conf->ping_message_text, conf->ping_message_text, NGX_HTTP_PUSH_STREAM_PING_MESSAGE_TEXT);
ngx_conf_merge_str_value(conf->broadcast_channel_prefix, conf->broadcast_channel_prefix, NGX_HTTP_PUSH_STREAM_DEFAULT_BROADCAST_CHANNEL_PREFIX);
// sanity checks
// ping message interval cannot be zero
if ((conf->ping_message_interval != NGX_CONF_UNSET_MSEC) && (conf->ping_message_interval == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_ping_message_interval cannot be zero.");
return NGX_CONF_ERROR;
}
// memory cleanup objects ttl cannot't be small
if (conf->shm_cleanup_objects_ttl < NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_MEMORY_CLEANUP_OBJECTS_TTL) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "memory cleanup objects ttl cannot't be less than %d.", NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_MEMORY_CLEANUP_OBJECTS_TTL);
return NGX_CONF_ERROR;
}
// max number of channels cannot be zero
if ((conf->max_number_of_channels != NGX_CONF_UNSET_UINT) && (conf->max_number_of_channels == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_number_of_channels cannot be zero.");
return NGX_CONF_ERROR;
}
// max number of broadcast channels cannot be zero
if ((conf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (conf->max_number_of_broadcast_channels == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_number_of_broadcast_channels cannot be zero.");
return NGX_CONF_ERROR;
} }
if (conf->shm_size == NGX_CONF_UNSET_SIZE) { // subscriber connection ttl cannot be zero
conf->shm_size = NGX_HTTP_PUSH_STREAM_DEFAULT_SHM_SIZE; if ((conf->subscriber_connection_ttl != NGX_CONF_UNSET) && (conf->subscriber_connection_ttl == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_subscriber_connection_ttl cannot be zero.");
return NGX_CONF_ERROR;
} }
if (conf->channel_deleted_message_text.data == NULL) { // message ttl cannot be zero
conf->channel_deleted_message_text.data = NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_TEXT.data; if ((conf->message_ttl != NGX_CONF_UNSET) && (conf->message_ttl == 0)) {
conf->channel_deleted_message_text.len = NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_TEXT.len; ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_message_ttl cannot be zero.");
return NGX_CONF_ERROR;
} }
if (conf->ping_message_text.data == NULL) { // max messages stored per channel cannot be zero
conf->ping_message_text.data = NGX_HTTP_PUSH_STREAM_PING_MESSAGE_TEXT.data; if ((conf->max_messages_stored_per_channel != NGX_CONF_UNSET_UINT) && (conf->max_messages_stored_per_channel == 0)) {
conf->ping_message_text.len = NGX_HTTP_PUSH_STREAM_PING_MESSAGE_TEXT.len; ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_messages_stored_per_channel cannot be zero.");
return NGX_CONF_ERROR;
} }
// memory cleanup timeout cannot't be small // max channel id length cannot be zero
if (conf->memory_cleanup_timeout < NGX_HTTP_PUSH_STREAM_DEFAULT_MEMORY_CLEANUP_TIMEOUT) { if ((conf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (conf->max_channel_id_length == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "memory cleanup timeout cannot't be less than %d.", NGX_HTTP_PUSH_STREAM_DEFAULT_MEMORY_CLEANUP_TIMEOUT); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_channel_id_length cannot be zero.");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
// calc memory cleanup interval // calc memory cleanup interval
ngx_uint_t interval = conf->memory_cleanup_timeout / 3; ngx_uint_t interval = conf->shm_cleanup_objects_ttl / 3;
conf->memory_cleanup_interval = (interval * 1000) + 1000; // min 11 seconds (((30 / 3) * 1000) + 1000) conf->memory_cleanup_interval = (interval * 1000) + 1000; // min 11 seconds (((30 / 3) * 1000) + 1000)
// calc buffer cleanup interval
if (conf->message_ttl != NGX_CONF_UNSET) {
ngx_uint_t interval = conf->message_ttl / 3;
conf->buffer_cleanup_interval = (interval > 1) ? (interval * 1000) + 1000 : 1000; // min 1 second
} else if (conf->buffer_cleanup_interval == NGX_CONF_UNSET_MSEC) {
conf->buffer_cleanup_interval = 1000; // 1 second
}
// calc subscriber disconnect interval
if (conf->subscriber_connection_ttl != NGX_CONF_UNSET) {
ngx_uint_t interval = conf->subscriber_connection_ttl / 3;
conf->subscriber_disconnect_interval = (interval > 1) ? (interval * 1000) + 1000 : 1000; // min 1 second
}
return NGX_CONF_OK; return NGX_CONF_OK;
} }
...@@ -383,27 +437,17 @@ ngx_http_push_stream_create_loc_conf(ngx_conf_t *cf) ...@@ -383,27 +437,17 @@ ngx_http_push_stream_create_loc_conf(ngx_conf_t *cf)
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
lcf->buffer_timeout = NGX_CONF_UNSET;
lcf->max_messages = NGX_CONF_UNSET_UINT;
lcf->authorized_channels_only = NGX_CONF_UNSET_UINT; lcf->authorized_channels_only = NGX_CONF_UNSET_UINT;
lcf->store_messages = NGX_CONF_UNSET_UINT; lcf->store_messages = NGX_CONF_UNSET_UINT;
lcf->max_channel_id_length = NGX_CONF_UNSET_UINT;
lcf->message_template_index = -1; lcf->message_template_index = -1;
lcf->message_template.data = NULL; lcf->message_template.data = NULL;
lcf->header_template.data = NULL; lcf->header_template.data = NULL;
lcf->footer_template.data = NULL; lcf->footer_template.data = NULL;
lcf->ping_message_interval = NGX_CONF_UNSET_MSEC;
lcf->content_type.data = NULL; lcf->content_type.data = NULL;
lcf->subscriber_disconnect_interval = NGX_CONF_UNSET_MSEC;
lcf->subscriber_connection_timeout = NGX_CONF_UNSET;
lcf->broadcast_channel_prefix.data = NULL;
lcf->broadcast_channel_max_qtd = NGX_CONF_UNSET_UINT; lcf->broadcast_channel_max_qtd = NGX_CONF_UNSET_UINT;
lcf->max_number_of_channels = NGX_CONF_UNSET_UINT;
lcf->max_number_of_broadcast_channels = NGX_CONF_UNSET_UINT;
lcf->buffer_cleanup_interval = NGX_CONF_UNSET_MSEC;
lcf->keepalive = NGX_CONF_UNSET_UINT; lcf->keepalive = NGX_CONF_UNSET_UINT;
lcf->publisher_admin = NGX_CONF_UNSET_UINT; lcf->publisher_admin = NGX_CONF_UNSET_UINT;
lcf->subscriber_eventsource = NGX_CONF_UNSET_UINT; lcf->eventsource_support = NGX_CONF_UNSET_UINT;
lcf->subscriber_mode = NGX_CONF_UNSET_UINT; lcf->subscriber_mode = NGX_CONF_UNSET_UINT;
return lcf; return lcf;
...@@ -415,29 +459,19 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ...@@ -415,29 +459,19 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{ {
ngx_http_push_stream_loc_conf_t *prev = parent, *conf = child; ngx_http_push_stream_loc_conf_t *prev = parent, *conf = child;
ngx_conf_merge_sec_value(conf->buffer_timeout, prev->buffer_timeout, NGX_CONF_UNSET);
ngx_conf_merge_uint_value(conf->max_messages, prev->max_messages, NGX_CONF_UNSET_UINT);
ngx_conf_merge_uint_value(conf->authorized_channels_only, prev->authorized_channels_only, 0); ngx_conf_merge_uint_value(conf->authorized_channels_only, prev->authorized_channels_only, 0);
ngx_conf_merge_uint_value(conf->store_messages, prev->store_messages, 0); ngx_conf_merge_value(conf->store_messages, prev->store_messages, 0);
ngx_conf_merge_uint_value(conf->max_channel_id_length, prev->max_channel_id_length, NGX_CONF_UNSET_UINT);
ngx_conf_merge_str_value(conf->header_template, prev->header_template, NGX_HTTP_PUSH_STREAM_DEFAULT_HEADER_TEMPLATE); ngx_conf_merge_str_value(conf->header_template, prev->header_template, NGX_HTTP_PUSH_STREAM_DEFAULT_HEADER_TEMPLATE);
ngx_conf_merge_str_value(conf->message_template, prev->message_template, NGX_HTTP_PUSH_STREAM_DEFAULT_MESSAGE_TEMPLATE); ngx_conf_merge_str_value(conf->message_template, prev->message_template, NGX_HTTP_PUSH_STREAM_DEFAULT_MESSAGE_TEMPLATE);
ngx_conf_merge_str_value(conf->footer_template, prev->footer_template, NGX_HTTP_PUSH_STREAM_DEFAULT_FOOTER_TEMPLATE); ngx_conf_merge_str_value(conf->footer_template, prev->footer_template, NGX_HTTP_PUSH_STREAM_DEFAULT_FOOTER_TEMPLATE);
ngx_conf_merge_msec_value(conf->ping_message_interval, prev->ping_message_interval, NGX_CONF_UNSET_MSEC);
ngx_conf_merge_str_value(conf->content_type, prev->content_type, NGX_HTTP_PUSH_STREAM_DEFAULT_CONTENT_TYPE); ngx_conf_merge_str_value(conf->content_type, prev->content_type, NGX_HTTP_PUSH_STREAM_DEFAULT_CONTENT_TYPE);
ngx_conf_merge_msec_value(conf->subscriber_disconnect_interval, prev->subscriber_disconnect_interval, NGX_CONF_UNSET_MSEC); ngx_conf_merge_uint_value(conf->broadcast_channel_max_qtd, prev->broadcast_channel_max_qtd, ngx_http_push_stream_module_main_conf->max_number_of_broadcast_channels);
ngx_conf_merge_sec_value(conf->subscriber_connection_timeout, prev->subscriber_connection_timeout, NGX_CONF_UNSET);
ngx_conf_merge_str_value(conf->broadcast_channel_prefix, prev->broadcast_channel_prefix, NGX_HTTP_PUSH_STREAM_DEFAULT_BROADCAST_CHANNEL_PREFIX);
ngx_conf_merge_uint_value(conf->broadcast_channel_max_qtd, prev->broadcast_channel_max_qtd, NGX_CONF_UNSET_UINT);
ngx_conf_merge_uint_value(conf->max_number_of_channels, prev->max_number_of_channels, NGX_CONF_UNSET_UINT);
ngx_conf_merge_uint_value(conf->max_number_of_broadcast_channels, prev->max_number_of_broadcast_channels, NGX_CONF_UNSET_UINT);
ngx_conf_merge_uint_value(conf->buffer_cleanup_interval, prev->buffer_cleanup_interval, NGX_CONF_UNSET_MSEC);
ngx_conf_merge_uint_value(conf->keepalive, prev->keepalive, 0); ngx_conf_merge_uint_value(conf->keepalive, prev->keepalive, 0);
ngx_conf_merge_uint_value(conf->publisher_admin, prev->publisher_admin, 0); ngx_conf_merge_uint_value(conf->publisher_admin, prev->publisher_admin, 0);
ngx_conf_merge_value(conf->subscriber_eventsource, prev->subscriber_eventsource, 0); ngx_conf_merge_value(conf->eventsource_support, prev->eventsource_support, 0);
// changing properties for event source support // changing properties for event source support
if (conf->subscriber_eventsource) { if (conf->eventsource_support) {
conf->content_type.data = NGX_HTTP_PUSH_STREAM_EVENTSOURCE_CONTENT_TYPE.data; conf->content_type.data = NGX_HTTP_PUSH_STREAM_EVENTSOURCE_CONTENT_TYPE.data;
conf->content_type.len = NGX_HTTP_PUSH_STREAM_EVENTSOURCE_CONTENT_TYPE.len; conf->content_type.len = NGX_HTTP_PUSH_STREAM_EVENTSOURCE_CONTENT_TYPE.len;
...@@ -481,48 +515,12 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ...@@ -481,48 +515,12 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
// sanity checks // sanity checks
// ping message interval cannot be zero
if ((conf->ping_message_interval != NGX_CONF_UNSET_MSEC) && (conf->ping_message_interval == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_ping_message_interval cannot be zero.");
return NGX_CONF_ERROR;
}
// message template cannot be blank // message template cannot be blank
if (conf->message_template.len == 0) { if (conf->message_template.len == 0) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_message_template cannot be blank."); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_message_template cannot be blank.");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
// subscriber connection timeout cannot be zero
if ((conf->subscriber_connection_timeout != NGX_CONF_UNSET) && (conf->subscriber_connection_timeout == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_subscriber_connection_timeout cannot be zero.");
return NGX_CONF_ERROR;
}
// buffer timeout cannot be zero
if ((conf->buffer_timeout != NGX_CONF_UNSET) && (conf->buffer_timeout == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_min_message_buffer_timeout cannot be zero.");
return NGX_CONF_ERROR;
}
// max buffer message cannot be zero
if ((conf->max_messages != NGX_CONF_UNSET_UINT) && (conf->max_messages == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_message_buffer_length cannot be zero.");
return NGX_CONF_ERROR;
}
// store messages cannot be set without buffer timeout or max messages
if ((conf->store_messages != NGX_CONF_UNSET_UINT) && (conf->store_messages) && (conf->buffer_timeout == NGX_CONF_UNSET) && (conf->max_messages == NGX_CONF_UNSET_UINT)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_store_messages cannot be set without set max message buffer length or min message buffer timeout.");
return NGX_CONF_ERROR;
}
// max channel id length cannot be zero
if ((conf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (conf->max_channel_id_length == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_channel_id_length cannot be zero.");
return NGX_CONF_ERROR;
}
// broadcast channel max qtd cannot be zero // broadcast channel max qtd cannot be zero
if ((conf->broadcast_channel_max_qtd != NGX_CONF_UNSET_UINT) && (conf->broadcast_channel_max_qtd == 0)) { if ((conf->broadcast_channel_max_qtd != NGX_CONF_UNSET_UINT) && (conf->broadcast_channel_max_qtd == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_broadcast_channel_max_qtd cannot be zero."); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_broadcast_channel_max_qtd cannot be zero.");
...@@ -530,32 +528,20 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ...@@ -530,32 +528,20 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
} }
// broadcast channel max qtd cannot be set without a channel prefix // broadcast channel max qtd cannot be set without a channel prefix
if ((conf->broadcast_channel_max_qtd != NGX_CONF_UNSET_UINT) && (conf->broadcast_channel_max_qtd > 0) && (conf->broadcast_channel_prefix.len == 0)) { if ((conf->broadcast_channel_max_qtd != NGX_CONF_UNSET_UINT) && (conf->broadcast_channel_max_qtd > 0) && (ngx_http_push_stream_module_main_conf->broadcast_channel_prefix.len == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "cannot set broadcast channel max qtd if push_stream_broadcast_channel_prefix is not set or blank."); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "cannot set broadcast channel max qtd if push_stream_broadcast_channel_prefix is not set or blank.");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
// broadcast channel prefix cannot be set without a channel max qtd // max number of broadcast channels cannot be smaller than value in broadcast channel max qtd
if ((conf->broadcast_channel_prefix.len > 0) && (conf->broadcast_channel_max_qtd == NGX_CONF_UNSET_UINT)) { if ((ngx_http_push_stream_module_main_conf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (conf->broadcast_channel_max_qtd != NGX_CONF_UNSET_UINT) && (ngx_http_push_stream_module_main_conf->max_number_of_broadcast_channels < conf->broadcast_channel_max_qtd)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "cannot set broadcast channel prefix if push_stream_broadcast_channel_max_qtd is not set."); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "max number of broadcast channels cannot be smaller than value in push_stream_broadcast_channel_max_qtd.");
return NGX_CONF_ERROR;
}
// max number of channels cannot be zero
if ((conf->max_number_of_channels != NGX_CONF_UNSET_UINT) && (conf->max_number_of_channels == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_number_of_channels cannot be zero.");
return NGX_CONF_ERROR;
}
// max number of broadcast channels cannot be zero
if ((conf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (conf->max_number_of_broadcast_channels == 0)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_max_number_of_broadcast_channels cannot be zero.");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
// max number of broadcast channels cannot be smaller than value in broadcast channel max qtd // store messages cannot be set without buffer timeout or max messages
if ((conf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (conf->broadcast_channel_max_qtd != NGX_CONF_UNSET_UINT) && (conf->max_number_of_broadcast_channels < conf->broadcast_channel_max_qtd)) { if (conf->store_messages && (ngx_http_push_stream_module_main_conf->message_ttl == NGX_CONF_UNSET) && (ngx_http_push_stream_module_main_conf->max_messages_stored_per_channel == NGX_CONF_UNSET_UINT)) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "max number of broadcast channels cannot be smaller than value in push_stream_broadcast_channel_max_qtd."); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_stream_store_messages cannot be set without set max message buffer length or min message buffer timeout.");
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
...@@ -580,21 +566,7 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ...@@ -580,21 +566,7 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->footer_template.len = aux->len; conf->footer_template.len = aux->len;
} }
conf->message_template_index = ngx_http_push_stream_find_or_add_template(cf, conf->message_template, conf->subscriber_eventsource); conf->message_template_index = ngx_http_push_stream_find_or_add_template(cf, conf->message_template, conf->eventsource_support);
// calc buffer cleanup interval
if (conf->buffer_timeout != NGX_CONF_UNSET) {
ngx_uint_t interval = conf->buffer_timeout / 3;
conf->buffer_cleanup_interval = (interval > 1) ? (interval * 1000) + 1000 : 1000; // min 1 second
} else if (conf->buffer_cleanup_interval == NGX_CONF_UNSET_MSEC) {
conf->buffer_cleanup_interval = 1000; // 1 second
}
// calc subscriber disconnect interval
if (conf->subscriber_connection_timeout != NGX_CONF_UNSET) {
ngx_uint_t interval = conf->subscriber_connection_timeout / 3;
conf->subscriber_disconnect_interval = (interval > 1) ? (interval * 1000) + 1000 : 1000; // min 1 second
}
return NGX_CONF_OK; return NGX_CONF_OK;
} }
...@@ -634,6 +606,24 @@ ngx_http_push_stream_channels_statistics(ngx_conf_t *cf, ngx_command_t *cmd, voi ...@@ -634,6 +606,24 @@ ngx_http_push_stream_channels_statistics(ngx_conf_t *cf, ngx_command_t *cmd, voi
static char * static char *
ngx_http_push_stream_publisher(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_push_stream_publisher(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ {
ngx_int_t *field = (ngx_int_t *) ((char *) conf + cmd->offset);
if (*field != NGX_CONF_UNSET) {
return "is duplicate";
}
*field = 0; //default
if(cf->args->nelts > 1) {
ngx_str_t value = (((ngx_str_t *) cf->args->elts)[1]);
if ((value.len == NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_NORMAL.len) && (ngx_strncasecmp(value.data, NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_NORMAL.data, NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_NORMAL.len) == 0)) {
*field = 0;
} else if ((value.len == NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_ADMIN.len) && (ngx_strncasecmp(value.data, NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_ADMIN.data, NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_ADMIN.len) == 0)) {
*field = 1;
} else {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "invalid push_stream_publisher mode value: %V, accepted values (%s, %s)", &value, NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_NORMAL.data, NGX_HTTP_PUSH_STREAM_PUBLISHER_MODE_ADMIN.data);
return NGX_CONF_ERROR;
}
}
char *rc = ngx_http_push_stream_setup_handler(cf, conf, &ngx_http_push_stream_publisher_handler); char *rc = ngx_http_push_stream_setup_handler(cf, conf, &ngx_http_push_stream_publisher_handler);
if (rc == NGX_CONF_OK) { if (rc == NGX_CONF_OK) {
......
...@@ -51,6 +51,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) ...@@ -51,6 +51,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
ngx_str_t *last_event_id; ngx_str_t *last_event_id;
ngx_str_t *push_mode; ngx_str_t *push_mode;
ngx_flag_t polling, longpolling; ngx_flag_t polling, longpolling;
ngx_http_push_stream_main_conf_t *mcf = ngx_http_push_stream_module_main_conf;
// only accept GET method // only accept GET method
if (!(r->method & NGX_HTTP_GET)) { if (!(r->method & NGX_HTTP_GET)) {
...@@ -67,7 +68,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) ...@@ -67,7 +68,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
//get channels ids and backtracks from path //get channels ids and backtracks from path
channels_ids = ngx_http_push_stream_parse_channels_ids_from_path(r, temp_pool); channels_ids = ngx_http_push_stream_parse_channels_ids_from_path(r, temp_pool);
if ((channels_ids == NULL) || ngx_queue_empty(&channels_ids->queue)) { if ((channels_ids == NULL) || ngx_queue_empty(&channels_ids->queue)) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: the $push_stream_channel_path variable is required but is not set"); ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: the $push_stream_channels_path variable is required but is not set");
ngx_destroy_pool(temp_pool); ngx_destroy_pool(temp_pool);
return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_NO_CHANNEL_ID_MESSAGE); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_NO_CHANNEL_ID_MESSAGE);
} }
...@@ -82,7 +83,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) ...@@ -82,7 +83,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
} }
// could not have a large size // could not have a large size
if ((cf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (cur->id->len > cf->max_channel_id_length)) { if ((mcf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (cur->id->len > mcf->max_channel_id_length)) {
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: channel id is larger than allowed %d", cur->id->len); ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: channel id is larger than allowed %d", cur->id->len);
ngx_destroy_pool(temp_pool); ngx_destroy_pool(temp_pool);
return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_TOO_LARGE_CHANNEL_ID_MESSAGE); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_TOO_LARGE_CHANNEL_ID_MESSAGE);
...@@ -91,7 +92,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) ...@@ -91,7 +92,7 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
// count subscribed channel and broadcasts // count subscribed channel and broadcasts
subscribed_channels_qtd++; subscribed_channels_qtd++;
is_broadcast_channel = 0; is_broadcast_channel = 0;
if ((cf->broadcast_channel_prefix.len > 0) && (ngx_strncmp(cur->id->data, cf->broadcast_channel_prefix.data, cf->broadcast_channel_prefix.len) == 0)) { if ((mcf->broadcast_channel_prefix.len > 0) && (ngx_strncmp(cur->id->data, mcf->broadcast_channel_prefix.data, mcf->broadcast_channel_prefix.len) == 0)) {
is_broadcast_channel = 1; is_broadcast_channel = 1;
subscribed_broadcast_channels_qtd++; subscribed_broadcast_channels_qtd++;
} }
...@@ -170,8 +171,8 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) ...@@ -170,8 +171,8 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
} }
// setting disconnect and ping timer // setting disconnect and ping timer
ngx_http_push_stream_disconnect_timer_set(cf); ngx_http_push_stream_disconnect_timer_set();
ngx_http_push_stream_ping_timer_set(cf); ngx_http_push_stream_ping_timer_set();
ngx_destroy_pool(temp_pool); ngx_destroy_pool(temp_pool);
return NGX_DONE; return NGX_DONE;
...@@ -443,7 +444,7 @@ ngx_http_push_stream_subscriber_prepare_request_to_keep_connected(ngx_http_reque ...@@ -443,7 +444,7 @@ ngx_http_push_stream_subscriber_prepare_request_to_keep_connected(ngx_http_reque
worker_subscriber->request = r; worker_subscriber->request = r;
worker_subscriber->worker_subscribed_pid = ngx_pid; worker_subscriber->worker_subscribed_pid = ngx_pid;
worker_subscriber->expires = (cf->subscriber_connection_timeout == NGX_CONF_UNSET) ? 0 : (ngx_time() + cf->subscriber_connection_timeout); worker_subscriber->expires = (ngx_http_push_stream_module_main_conf->subscriber_connection_ttl == NGX_CONF_UNSET) ? 0 : (ngx_time() + ngx_http_push_stream_module_main_conf->subscriber_connection_ttl);
ngx_queue_init(&worker_subscriber->queue); ngx_queue_init(&worker_subscriber->queue);
ngx_queue_init(&worker_subscriber->subscriptions_sentinel.queue); ngx_queue_init(&worker_subscriber->subscriptions_sentinel.queue);
......
...@@ -32,6 +32,10 @@ static ngx_inline void ...@@ -32,6 +32,10 @@ static ngx_inline void
ngx_http_push_stream_ensure_qtd_of_messages_locked(ngx_http_push_stream_channel_t *channel, ngx_uint_t max_messages, ngx_flag_t expired) { ngx_http_push_stream_ensure_qtd_of_messages_locked(ngx_http_push_stream_channel_t *channel, ngx_uint_t max_messages, ngx_flag_t expired) {
ngx_http_push_stream_msg_t *sentinel, *msg; ngx_http_push_stream_msg_t *sentinel, *msg;
if (max_messages == NGX_CONF_UNSET_UINT) {
return;
}
sentinel = &channel->message_queue; sentinel = &channel->message_queue;
while (!ngx_queue_empty(&sentinel->queue) && ((channel->stored_messages > max_messages) || expired)) { while (!ngx_queue_empty(&sentinel->queue) && ((channel->stored_messages > max_messages) || expired)) {
...@@ -359,7 +363,7 @@ ngx_http_push_stream_send_response_message(ngx_http_request_t *r, ngx_http_push_ ...@@ -359,7 +363,7 @@ ngx_http_push_stream_send_response_message(ngx_http_request_t *r, ngx_http_push_
{ {
ngx_http_push_stream_loc_conf_t *pslcf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module); ngx_http_push_stream_loc_conf_t *pslcf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module);
if (pslcf->subscriber_eventsource && (msg->event_id_message != NULL)) { if (pslcf->eventsource_support && (msg->event_id_message != NULL)) {
ngx_http_push_stream_send_response_text(r, msg->event_id_message->data, msg->event_id_message->len, 0); ngx_http_push_stream_send_response_text(r, msg->event_id_message->data, msg->event_id_message->len, 0);
} }
...@@ -430,16 +434,6 @@ ngx_http_push_stream_send_response_finalize(ngx_http_request_t *r) ...@@ -430,16 +434,6 @@ ngx_http_push_stream_send_response_finalize(ngx_http_request_t *r)
ngx_http_finalize_request(r, NGX_HTTP_OK); ngx_http_finalize_request(r, NGX_HTTP_OK);
} }
static ngx_int_t
ngx_http_push_stream_send_ping(ngx_log_t *log, ngx_http_push_stream_loc_conf_t *pslcf)
{
if (pslcf->message_template.len > 0) {
ngx_http_push_stream_alert_worker_send_ping(ngx_pid, ngx_process_slot, ngx_cycle->log);
}
return NGX_OK;
}
static void static void
ngx_http_push_stream_delete_channel(ngx_str_t *id, ngx_pool_t *temp_pool) { ngx_http_push_stream_delete_channel(ngx_str_t *id, ngx_pool_t *temp_pool) {
...@@ -508,7 +502,7 @@ ngx_http_push_stream_collect_expired_messages_and_empty_channels(ngx_http_push_s ...@@ -508,7 +502,7 @@ ngx_http_push_stream_collect_expired_messages_and_empty_channels(ngx_http_push_s
if ((channel->stored_messages == 0) && (channel->subscribers == 0)) { if ((channel->stored_messages == 0) && (channel->subscribers == 0)) {
channel->deleted = 1; channel->deleted = 1;
channel->expires = ngx_time() + ngx_http_push_stream_module_main_conf->memory_cleanup_timeout; channel->expires = ngx_time() + ngx_http_push_stream_module_main_conf->shm_cleanup_objects_ttl;
(channel->broadcast) ? NGX_HTTP_PUSH_STREAM_DECREMENT_COUNTER(data->broadcast_channels) : NGX_HTTP_PUSH_STREAM_DECREMENT_COUNTER(data->channels); (channel->broadcast) ? NGX_HTTP_PUSH_STREAM_DECREMENT_COUNTER(data->broadcast_channels) : NGX_HTTP_PUSH_STREAM_DECREMENT_COUNTER(data->channels);
// move the channel to trash tree // move the channel to trash tree
...@@ -596,7 +590,7 @@ nxg_http_push_stream_free_channel_memory_locked(ngx_slab_pool_t *shpool, ngx_htt ...@@ -596,7 +590,7 @@ nxg_http_push_stream_free_channel_memory_locked(ngx_slab_pool_t *shpool, ngx_htt
static ngx_int_t static ngx_int_t
ngx_http_push_stream_memory_cleanup(ngx_log_t *log, ngx_http_push_stream_main_conf_t *psmcf) ngx_http_push_stream_memory_cleanup()
{ {
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data; ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data;
...@@ -609,7 +603,7 @@ ngx_http_push_stream_memory_cleanup(ngx_log_t *log, ngx_http_push_stream_main_co ...@@ -609,7 +603,7 @@ ngx_http_push_stream_memory_cleanup(ngx_log_t *log, ngx_http_push_stream_main_co
static ngx_int_t static ngx_int_t
ngx_http_push_stream_buffer_cleanup(ngx_log_t *log, ngx_http_push_stream_loc_conf_t *pslcf) ngx_http_push_stream_buffer_cleanup()
{ {
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data; ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data;
...@@ -673,82 +667,24 @@ ngx_http_push_stream_mark_message_to_delete_locked(ngx_http_push_stream_msg_t *m ...@@ -673,82 +667,24 @@ ngx_http_push_stream_mark_message_to_delete_locked(ngx_http_push_stream_msg_t *m
ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data; ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data;
msg->deleted = 1; msg->deleted = 1;
msg->expires = ngx_time() + ngx_http_push_stream_module_main_conf->memory_cleanup_timeout; msg->expires = ngx_time() + ngx_http_push_stream_module_main_conf->shm_cleanup_objects_ttl;
ngx_queue_insert_tail(&data->messages_to_delete.queue, &msg->queue); ngx_queue_insert_tail(&data->messages_to_delete.queue, &msg->queue);
} }
static void static void
ngx_http_push_stream_ping_timer_set(ngx_http_push_stream_loc_conf_t *pslcf) ngx_http_push_stream_timer_set(ngx_msec_t timer_interval, ngx_event_t *event, ngx_event_handler_pt event_handler, ngx_flag_t start_timer)
{
if (pslcf->ping_message_interval != NGX_CONF_UNSET_MSEC) {
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
if (ngx_http_push_stream_ping_event.handler == NULL) {
ngx_shmtx_lock(&shpool->mutex);
if (ngx_http_push_stream_ping_event.handler == NULL) {
ngx_http_push_stream_ping_event.handler = ngx_http_push_stream_ping_timer_wake_handler;
ngx_http_push_stream_ping_event.data = pslcf;
ngx_http_push_stream_ping_event.log = ngx_cycle->log;
ngx_http_push_stream_timer_reset(pslcf->ping_message_interval, &ngx_http_push_stream_ping_event);
}
ngx_shmtx_unlock(&shpool->mutex);
}
}
}
static void
ngx_http_push_stream_disconnect_timer_set(ngx_http_push_stream_loc_conf_t *pslcf)
{ {
if (pslcf->subscriber_disconnect_interval != NGX_CONF_UNSET_MSEC) { if ((timer_interval != NGX_CONF_UNSET_MSEC) && start_timer) {
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
if (ngx_http_push_stream_disconnect_event.handler == NULL) { if (event->handler == NULL) {
ngx_shmtx_lock(&shpool->mutex); ngx_shmtx_lock(&shpool->mutex);
if (ngx_http_push_stream_disconnect_event.handler == NULL) { if (event->handler == NULL) {
ngx_http_push_stream_disconnect_event.handler = ngx_http_push_stream_disconnect_timer_wake_handler; event->handler = event_handler;
ngx_http_push_stream_disconnect_event.data = pslcf; event->data = NULL;
ngx_http_push_stream_disconnect_event.log = ngx_cycle->log; event->log = ngx_cycle->log;
ngx_http_push_stream_timer_reset(pslcf->subscriber_disconnect_interval, &ngx_http_push_stream_disconnect_event); ngx_http_push_stream_timer_reset(timer_interval, event);
}
ngx_shmtx_unlock(&shpool->mutex);
}
}
}
static void
ngx_http_push_stream_memory_cleanup_timer_set(ngx_http_push_stream_main_conf_t *psmcf)
{
if (psmcf->memory_cleanup_interval != NGX_CONF_UNSET_MSEC) {
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
if (ngx_http_push_stream_memory_cleanup_event.handler == NULL) {
ngx_shmtx_lock(&shpool->mutex);
if (ngx_http_push_stream_memory_cleanup_event.handler == NULL) {
ngx_http_push_stream_memory_cleanup_event.handler = ngx_http_push_stream_memory_cleanup_timer_wake_handler;
ngx_http_push_stream_memory_cleanup_event.data = psmcf;
ngx_http_push_stream_memory_cleanup_event.log = ngx_cycle->log;
ngx_http_push_stream_timer_reset(psmcf->memory_cleanup_interval, &ngx_http_push_stream_memory_cleanup_event);
}
ngx_shmtx_unlock(&shpool->mutex);
}
}
}
static void
ngx_http_push_stream_buffer_cleanup_timer_set(ngx_http_push_stream_loc_conf_t *pslcf)
{
if ((pslcf->buffer_cleanup_interval != NGX_CONF_UNSET_MSEC) && pslcf->store_messages) {
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
if (ngx_http_push_stream_buffer_cleanup_event.handler == NULL) {
ngx_shmtx_lock(&shpool->mutex);
if (ngx_http_push_stream_buffer_cleanup_event.handler == NULL) {
ngx_http_push_stream_buffer_cleanup_event.handler = ngx_http_push_stream_buffer_timer_wake_handler;
ngx_http_push_stream_buffer_cleanup_event.data = pslcf;
ngx_http_push_stream_buffer_cleanup_event.log = ngx_cycle->log;
ngx_http_push_stream_timer_reset(pslcf->buffer_cleanup_interval, &ngx_http_push_stream_buffer_cleanup_event);
} }
ngx_shmtx_unlock(&shpool->mutex); ngx_shmtx_unlock(&shpool->mutex);
} }
...@@ -775,38 +711,29 @@ ngx_http_push_stream_timer_reset(ngx_msec_t timer_interval, ngx_event_t *timer_e ...@@ -775,38 +711,29 @@ ngx_http_push_stream_timer_reset(ngx_msec_t timer_interval, ngx_event_t *timer_e
static void static void
ngx_http_push_stream_ping_timer_wake_handler(ngx_event_t *ev) ngx_http_push_stream_ping_timer_wake_handler(ngx_event_t *ev)
{ {
ngx_http_push_stream_loc_conf_t *pslcf = ev->data; ngx_http_push_stream_alert_worker_send_ping(ngx_pid, ngx_process_slot, ngx_cycle->log);
ngx_http_push_stream_timer_reset(ngx_http_push_stream_module_main_conf->ping_message_interval, &ngx_http_push_stream_ping_event);
ngx_http_push_stream_send_ping(ev->log, pslcf);
ngx_http_push_stream_timer_reset(pslcf->ping_message_interval, &ngx_http_push_stream_ping_event);
} }
static void static void
ngx_http_push_stream_disconnect_timer_wake_handler(ngx_event_t *ev) ngx_http_push_stream_disconnect_timer_wake_handler(ngx_event_t *ev)
{ {
ngx_http_push_stream_loc_conf_t *pslcf = ev->data;
ngx_http_push_stream_alert_worker_disconnect_subscribers(ngx_pid, ngx_process_slot, ngx_cycle->log); ngx_http_push_stream_alert_worker_disconnect_subscribers(ngx_pid, ngx_process_slot, ngx_cycle->log);
ngx_http_push_stream_timer_reset(pslcf->subscriber_disconnect_interval, &ngx_http_push_stream_disconnect_event); ngx_http_push_stream_timer_reset(ngx_http_push_stream_module_main_conf->subscriber_disconnect_interval, &ngx_http_push_stream_disconnect_event);
} }
static void static void
ngx_http_push_stream_memory_cleanup_timer_wake_handler(ngx_event_t *ev) ngx_http_push_stream_memory_cleanup_timer_wake_handler(ngx_event_t *ev)
{ {
ngx_http_push_stream_main_conf_t *psmcf = ev->data; ngx_http_push_stream_memory_cleanup();
ngx_http_push_stream_timer_reset(ngx_http_push_stream_module_main_conf->memory_cleanup_interval, &ngx_http_push_stream_memory_cleanup_event);
ngx_http_push_stream_memory_cleanup(ev->log, psmcf);
ngx_http_push_stream_timer_reset(psmcf->memory_cleanup_interval, &ngx_http_push_stream_memory_cleanup_event);
} }
static void static void
ngx_http_push_stream_buffer_timer_wake_handler(ngx_event_t *ev) ngx_http_push_stream_buffer_timer_wake_handler(ngx_event_t *ev)
{ {
ngx_http_push_stream_loc_conf_t *pslcf = ev->data; ngx_http_push_stream_buffer_cleanup();
ngx_http_push_stream_timer_reset(ngx_http_push_stream_module_main_conf->buffer_cleanup_interval, &ngx_http_push_stream_buffer_cleanup_event);
ngx_http_push_stream_buffer_cleanup(ev->log, pslcf);
ngx_http_push_stream_timer_reset(pslcf->buffer_cleanup_interval, &ngx_http_push_stream_buffer_cleanup_event);
} }
static u_char * static u_char *
......
...@@ -174,6 +174,7 @@ ngx_http_push_stream_find_channel_locked(ngx_str_t *id, ngx_log_t *log) ...@@ -174,6 +174,7 @@ ngx_http_push_stream_find_channel_locked(ngx_str_t *id, ngx_log_t *log)
static ngx_http_push_stream_channel_t * static ngx_http_push_stream_channel_t *
ngx_http_push_stream_get_channel(ngx_str_t *id, ngx_log_t *log, ngx_http_push_stream_loc_conf_t *cf) ngx_http_push_stream_get_channel(ngx_str_t *id, ngx_log_t *log, ngx_http_push_stream_loc_conf_t *cf)
{ {
ngx_http_push_stream_main_conf_t *mcf = ngx_http_push_stream_module_main_conf;
ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data; ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data;
ngx_http_push_stream_channel_t *channel; ngx_http_push_stream_channel_t *channel;
ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
...@@ -193,12 +194,12 @@ ngx_http_push_stream_get_channel(ngx_str_t *id, ngx_log_t *log, ngx_http_push_st ...@@ -193,12 +194,12 @@ ngx_http_push_stream_get_channel(ngx_str_t *id, ngx_log_t *log, ngx_http_push_st
return channel; return channel;
} }
if ((cf->broadcast_channel_prefix.len > 0) && (ngx_strncmp(id->data, cf->broadcast_channel_prefix.data, cf->broadcast_channel_prefix.len) == 0)) { if ((mcf->broadcast_channel_prefix.len > 0) && (ngx_strncmp(id->data, mcf->broadcast_channel_prefix.data, mcf->broadcast_channel_prefix.len) == 0)) {
is_broadcast_channel = 1; is_broadcast_channel = 1;
} }
if (((!is_broadcast_channel) && (cf->max_number_of_channels != NGX_CONF_UNSET_UINT) && (cf->max_number_of_channels == data->channels)) || if (((!is_broadcast_channel) && (mcf->max_number_of_channels != NGX_CONF_UNSET_UINT) && (mcf->max_number_of_channels == data->channels)) ||
((is_broadcast_channel) && (cf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (cf->max_number_of_broadcast_channels == data->broadcast_channels))) { ((is_broadcast_channel) && (mcf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (mcf->max_number_of_broadcast_channels == data->broadcast_channels))) {
ngx_shmtx_unlock(&shpool->mutex); ngx_shmtx_unlock(&shpool->mutex);
return NGX_HTTP_PUSH_STREAM_NUMBER_OF_CHANNELS_EXCEEDED; return NGX_HTTP_PUSH_STREAM_NUMBER_OF_CHANNELS_EXCEEDED;
} }
......
...@@ -151,11 +151,11 @@ module BaseTestCase ...@@ -151,11 +151,11 @@ module BaseTestCase
@memory_cleanup_timeout = '5m' @memory_cleanup_timeout = '5m'
@config_template = nil @config_template = nil
@keepalive = 'off' @keepalive = 'off'
@publisher_admin = 'off'
@channel_deleted_message_text = nil @channel_deleted_message_text = nil
@ping_message_text = nil @ping_message_text = nil
@subscriber_eventsource = 'off' @subscriber_eventsource = 'off'
@subscriber_mode = nil @subscriber_mode = nil
@publisher_mode = nil
self.send(:global_configuration) if self.respond_to?(:global_configuration) self.send(:global_configuration) if self.respond_to?(:global_configuration)
end end
...@@ -234,10 +234,23 @@ http { ...@@ -234,10 +234,23 @@ http {
ignore_invalid_headers on; ignore_invalid_headers on;
client_body_in_single_buffer on; client_body_in_single_buffer on;
client_body_temp_path <%= @client_body_temp %>; client_body_temp_path <%= @client_body_temp %>;
<%= "push_stream_max_reserved_memory #{@max_reserved_memory};" unless @max_reserved_memory.nil? %> <%= "push_stream_shared_memory_size #{@max_reserved_memory};" unless @max_reserved_memory.nil? %>
<%= "push_stream_memory_cleanup_timeout #{@memory_cleanup_timeout};" unless @memory_cleanup_timeout.nil? %> <%= "push_stream_shared_memory_cleanup_objects_ttl #{@memory_cleanup_timeout};" unless @memory_cleanup_timeout.nil? %>
<%= %{push_stream_channel_deleted_message_text "#{@channel_deleted_message_text}";} unless @channel_deleted_message_text.nil? %> <%= %{push_stream_channel_deleted_message_text "#{@channel_deleted_message_text}";} unless @channel_deleted_message_text.nil? %>
<%= %{push_stream_ping_message_text "#{@ping_message_text}";} unless @ping_message_text.nil? %> <%= %{push_stream_ping_message_text "#{@ping_message_text}";} unless @ping_message_text.nil? %>
<%= %{push_stream_broadcast_channel_prefix "#{@broadcast_channel_prefix}";} unless @broadcast_channel_prefix.nil? %>
<%= "push_stream_max_number_of_channels #{@max_number_of_channels};" unless @max_number_of_channels.nil? %>
<%= "push_stream_max_number_of_broadcast_channels #{@max_number_of_broadcast_channels};" unless @max_number_of_broadcast_channels.nil? %>
# max messages to store in memory
<%= "push_stream_max_messages_stored_per_channel #{@max_message_buffer_length};" unless @max_message_buffer_length.nil? %>
# message ttl
<%= "push_stream_message_ttl #{@min_message_buffer_timeout};" unless @min_message_buffer_timeout.nil? %>
<%= "push_stream_max_channel_id_length #{@max_channel_id_length};" unless @max_channel_id_length.nil? %>
# ping frequency
<%= "push_stream_ping_message_interval #{@ping_message_interval};" unless @ping_message_interval.nil? %>
# connection ttl to enable recycle
<%= "push_stream_subscriber_connection_ttl #{@subscriber_connection_timeout};" unless @subscriber_connection_timeout.nil? %>
server { server {
listen <%=nginx_port%>; listen <%=nginx_port%>;
...@@ -256,28 +269,15 @@ http { ...@@ -256,28 +269,15 @@ http {
location /pub { location /pub {
# activate publisher mode for this location # activate publisher mode for this location
push_stream_publisher; push_stream_publisher <%= @publisher_mode unless @publisher_mode.nil? || @publisher_mode == "normal" %>;
# activate publisher admin mode for this location
<%= "push_stream_publisher_admin #{@publisher_admin};" unless @publisher_admin.nil? %>
# query string based channel id # query string based channel id
set $push_stream_channel_id $arg_id; set $push_stream_channel_id $arg_id;
# store messages # store messages
<%= "push_stream_store_messages #{@store_messages};" unless @store_messages.nil? %> <%= "push_stream_store_messages #{@store_messages};" unless @store_messages.nil? %>
# max messages to store in memory
<%= "push_stream_max_message_buffer_length #{@max_message_buffer_length};" unless @max_message_buffer_length.nil? %>
# message ttl
<%= "push_stream_min_message_buffer_timeout #{@min_message_buffer_timeout};" unless @min_message_buffer_timeout.nil? %>
# keepalive # keepalive
<%= "push_stream_keepalive #{@keepalive};" unless @keepalive.nil? %> <%= "push_stream_keepalive #{@keepalive};" unless @keepalive.nil? %>
<%= "push_stream_max_channel_id_length #{@max_channel_id_length};" unless @max_channel_id_length.nil? %>
<%= %{push_stream_broadcast_channel_prefix "#{@broadcast_channel_prefix}";} unless @broadcast_channel_prefix.nil? %>
<%= "push_stream_broadcast_channel_max_qtd #{@broadcast_channel_max_qtd};" unless @broadcast_channel_max_qtd.nil? %>
<%= "push_stream_max_number_of_channels #{@max_number_of_channels};" unless @max_number_of_channels.nil? %>
<%= "push_stream_max_number_of_broadcast_channels #{@max_number_of_broadcast_channels};" unless @max_number_of_broadcast_channels.nil? %>
# client_max_body_size MUST be equal to client_body_buffer_size or # client_max_body_size MUST be equal to client_body_buffer_size or
# you will be sorry. # you will be sorry.
client_max_body_size <%= @client_max_body_size.nil? ? '32k' : @client_max_body_size %>; client_max_body_size <%= @client_max_body_size.nil? ? '32k' : @client_max_body_size %>;
...@@ -289,11 +289,10 @@ http { ...@@ -289,11 +289,10 @@ http {
push_stream_subscriber <%= @subscriber_mode unless @subscriber_mode.nil? || @subscriber_mode == "streaming" %>; push_stream_subscriber <%= @subscriber_mode unless @subscriber_mode.nil? || @subscriber_mode == "streaming" %>;
# activate event source support for this location # activate event source support for this location
<%= "push_stream_subscriber_eventsource #{@subscriber_eventsource};" unless @subscriber_eventsource.nil? %> <%= "push_stream_eventsource_support #{@subscriber_eventsource};" unless @subscriber_eventsource.nil? %>
# positional channel path # positional channel path
set $push_stream_channels_path $1; set $push_stream_channels_path $1;
<%= "push_stream_max_channel_id_length #{@max_channel_id_length};" unless @max_channel_id_length.nil? %>
# header to be sent when receiving new subscriber connection # header to be sent when receiving new subscriber connection
<%= %{push_stream_header_template "#{@header_template}";} unless @header_template.nil? %> <%= %{push_stream_header_template "#{@header_template}";} unless @header_template.nil? %>
# message template # message template
...@@ -305,15 +304,7 @@ http { ...@@ -305,15 +304,7 @@ http {
# subscriber may create channels on demand or only authorized # subscriber may create channels on demand or only authorized
# (publisher) may do it? # (publisher) may do it?
<%= "push_stream_authorized_channels_only #{@authorized_channels_only};" unless @authorized_channels_only.nil? %> <%= "push_stream_authorized_channels_only #{@authorized_channels_only};" unless @authorized_channels_only.nil? %>
# ping frequency
<%= "push_stream_ping_message_interval #{@ping_message_interval};" unless @ping_message_interval.nil? %>
# connection ttl to enable recycle
<%= "push_stream_subscriber_connection_timeout #{@subscriber_connection_timeout};" unless @subscriber_connection_timeout.nil? %>
<%= %{push_stream_broadcast_channel_prefix "#{@broadcast_channel_prefix}";} unless @broadcast_channel_prefix.nil? %>
<%= "push_stream_broadcast_channel_max_qtd #{@broadcast_channel_max_qtd};" unless @broadcast_channel_max_qtd.nil? %> <%= "push_stream_broadcast_channel_max_qtd #{@broadcast_channel_max_qtd};" unless @broadcast_channel_max_qtd.nil? %>
<%= "push_stream_max_number_of_channels #{@max_number_of_channels};" unless @max_number_of_channels.nil? %>
<%= "push_stream_max_number_of_broadcast_channels #{@max_number_of_broadcast_channels};" unless @max_number_of_broadcast_channels.nil? %>
} }
<%= @extra_location %> <%= @extra_location %>
......
...@@ -4,7 +4,7 @@ class TestPublisherAdmin < Test::Unit::TestCase ...@@ -4,7 +4,7 @@ class TestPublisherAdmin < Test::Unit::TestCase
include BaseTestCase include BaseTestCase
def global_configuration def global_configuration
@publisher_admin = 'on' @publisher_mode = 'admin'
end end
def test_admin_access_whithout_channel_id def test_admin_access_whithout_channel_id
......
...@@ -3,8 +3,7 @@ require File.expand_path('base_test_case', File.dirname(__FILE__)) ...@@ -3,8 +3,7 @@ require File.expand_path('base_test_case', File.dirname(__FILE__))
class TestSetuParameters < Test::Unit::TestCase class TestSetuParameters < Test::Unit::TestCase
include BaseTestCase include BaseTestCase
def initialize(opts) def global_configuration
super(opts)
@disable_start_stop_server = true @disable_start_stop_server = true
end end
...@@ -27,7 +26,7 @@ class TestSetuParameters < Test::Unit::TestCase ...@@ -27,7 +26,7 @@ class TestSetuParameters < Test::Unit::TestCase
end end
def test_subscriber_connection_timeout_cannot_be_zero def test_subscriber_connection_timeout_cannot_be_zero
expected_error_message = "push_stream_subscriber_connection_timeout cannot be zero" expected_error_message = "push_stream_subscriber_connection_ttl cannot be zero"
@subscriber_connection_timeout = 0 @subscriber_connection_timeout = 0
self.create_config_file self.create_config_file
...@@ -45,7 +44,7 @@ class TestSetuParameters < Test::Unit::TestCase ...@@ -45,7 +44,7 @@ class TestSetuParameters < Test::Unit::TestCase
end end
def test_min_message_buffer_timeout_cannot_be_zero def test_min_message_buffer_timeout_cannot_be_zero
expected_error_message = "push_stream_min_message_buffer_timeout cannot be zero" expected_error_message = "push_stream_message_ttl cannot be zero"
@min_message_buffer_timeout = 0 @min_message_buffer_timeout = 0
self.create_config_file self.create_config_file
...@@ -54,7 +53,7 @@ class TestSetuParameters < Test::Unit::TestCase ...@@ -54,7 +53,7 @@ class TestSetuParameters < Test::Unit::TestCase
end end
def test_max_message_buffer_length_cannot_be_zero def test_max_message_buffer_length_cannot_be_zero
expected_error_message = "push_stream_max_message_buffer_length cannot be zero" expected_error_message = "push_stream_max_messages_stored_per_channel cannot be zero"
@max_message_buffer_length = 0 @max_message_buffer_length = 0
self.create_config_file self.create_config_file
...@@ -101,16 +100,6 @@ class TestSetuParameters < Test::Unit::TestCase ...@@ -101,16 +100,6 @@ class TestSetuParameters < Test::Unit::TestCase
assert(stderr_msg.include?(expected_error_message), "Message error not founded: '#{ expected_error_message }' recieved '#{ stderr_msg }'") assert(stderr_msg.include?(expected_error_message), "Message error not founded: '#{ expected_error_message }' recieved '#{ stderr_msg }'")
end end
def test_broadcast_channel_prefix_cannot_be_set_without_broadcast_channel_max_qtd
expected_error_message = "cannot set broadcast channel prefix if push_stream_broadcast_channel_max_qtd is not set"
@broadcast_channel_prefix = "broad_"
@broadcast_channel_max_qtd = nil
self.create_config_file
stderr_msg = self.start_server
assert(stderr_msg.include?(expected_error_message), "Message error not founded: '#{ expected_error_message }' recieved '#{ stderr_msg }'")
end
def test_max_number_of_channels_cannot_be_zero def test_max_number_of_channels_cannot_be_zero
expected_error_message = "push_stream_max_number_of_channels cannot be zero" expected_error_message = "push_stream_max_number_of_channels cannot be zero"
@max_number_of_channels = 0 @max_number_of_channels = 0
...@@ -141,7 +130,7 @@ class TestSetuParameters < Test::Unit::TestCase ...@@ -141,7 +130,7 @@ class TestSetuParameters < Test::Unit::TestCase
end end
def test_memory_cleanup_timeout def test_memory_cleanup_timeout
expected_error_message = "memory cleanup timeout cannot't be less than 30." expected_error_message = "memory cleanup objects ttl cannot't be less than 30."
@memory_cleanup_timeout = '15s' @memory_cleanup_timeout = '15s'
self.create_config_file self.create_config_file
...@@ -221,4 +210,42 @@ class TestSetuParameters < Test::Unit::TestCase ...@@ -221,4 +210,42 @@ class TestSetuParameters < Test::Unit::TestCase
self.stop_server self.stop_server
end end
def test_invalid_publisher_mode
expected_error_message = "invalid push_stream_publisher mode value: unknown, accepted values (normal, admin)"
@publisher_mode = "unknown"
self.create_config_file
stderr_msg = self.start_server
assert(stderr_msg.include?(expected_error_message), "Message error not founded: '#{ expected_error_message }' recieved '#{ stderr_msg }'")
end
def test_valid_publisher_mode
expected_error_message = "invalid push_stream_publisher mode value"
@publisher_mode = ""
self.create_config_file
stderr_msg = self.start_server
assert(!stderr_msg.include?(expected_error_message), "Message error founded: '#{ stderr_msg }'")
self.stop_server
@publisher_mode = "normal"
self.create_config_file
stderr_msg = self.start_server
assert(!stderr_msg.include?(expected_error_message), "Message error founded: '#{ stderr_msg }'")
self.stop_server
@publisher_mode = "admin"
self.create_config_file
stderr_msg = self.start_server
assert(!stderr_msg.include?(expected_error_message), "Message error founded: '#{ stderr_msg }'")
self.stop_server
end
end end
...@@ -679,6 +679,7 @@ class TestSubscriber < Test::Unit::TestCase ...@@ -679,6 +679,7 @@ class TestSubscriber < Test::Unit::TestCase
def config_test_different_message_templates def config_test_different_message_templates
@message_template = '{\"text\":\"~text~\"}' @message_template = '{\"text\":\"~text~\"}'
@header_template = nil @header_template = nil
@subscriber_connection_timeout = '1s'
@extra_location = %q{ @extra_location = %q{
location ~ /sub2/(.*)? { location ~ /sub2/(.*)? {
# activate subscriber mode for this location # activate subscriber mode for this location
...@@ -688,7 +689,6 @@ class TestSubscriber < Test::Unit::TestCase ...@@ -688,7 +689,6 @@ class TestSubscriber < Test::Unit::TestCase
set $push_stream_channels_path $1; set $push_stream_channels_path $1;
# message template # message template
push_stream_message_template "{\"msg\":\"~text~\"}"; push_stream_message_template "{\"msg\":\"~text~\"}";
push_stream_subscriber_connection_timeout 1s;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment