1. Janus启动及线程
1.1 线程处理代码
主入口main函数位于 janus.c
文件中,下面为线程部分:
其中:需要特别注意~~janus_sessions_watchdog
~~、janus_transport_requests
、janus_transport_task
几个处理函数
1.2 Session处理函数janus_sessions_watchdog
(非本文重点)
janus_sessions_watchdog
1.3 请求处理函数janus_transport_requests
1.4 异步请求处理函数janus_transport_task
2. Janus启动及组件
2.1 组件回调处理
2.1.1 Plugin回调处理
2.1.2 Transport回调处理
2.2 EventHandlers处理代码
详细代码:
/* Load event handlers */
const char *path = NULL;
DIR *dir = NULL;
/* Event handlers are disabled by default, though: they need to be enabled in the configuration */
item = janus_config_get(config, config_events, janus_config_type_item, "broadcast");
gboolean enable_events = FALSE;
if(item && item->value)
enable_events = janus_is_true(item->value);
if(!enable_events) {
JANUS_LOG(LOG_WARN, "Event handlers support disabled\n");
} else {
gchar **disabled_eventhandlers = NULL;
path = EVENTDIR;
item = janus_config_get(config, config_general, janus_config_type_item, "events_folder");
if(item && item->value)
path = (char *)item->value;
JANUS_LOG(LOG_INFO, "Event handler plugins folder: %s\n", path);
dir = opendir(path);
if(!dir) {
/* Not really fatal, we don't care and go on anyway: event handlers are not fundamental */
JANUS_LOG(LOG_FATAL, "\tCouldn't access event handler plugins folder...\n");
} else {
item = janus_config_get(config, config_events, janus_config_type_item, "stats_period");
if(item && item->value) {
/* Check if we need to use a larger period for pushing statistics to event handlers */
int period = atoi(item->value);
if(period < 0) {
JANUS_LOG(LOG_WARN, "Invalid event handlers statistics period, using default value (1 second)\n");
} else if(period == 0) {
janus_ice_set_event_stats_period(0);
JANUS_LOG(LOG_WARN, "Disabling event handlers statistics period, no media statistics will be pushed to event handlers\n");
} else {
janus_ice_set_event_stats_period(period);
JANUS_LOG(LOG_INFO, "Setting event handlers statistics period to %d seconds\n", period);
}
}
/* Any event handlers to ignore? */
item = janus_config_get(config, config_events, janus_config_type_item, "disable");
if(item && item->value)
disabled_eventhandlers = g_strsplit(item->value, ",", -1);
/* Open the shared objects */
struct dirent *eventent = NULL;
char eventpath[1024];
while((eventent = readdir(dir))) {
int len = strlen(eventent->d_name);
if (len < 4) {
continue;
}
if (strcasecmp(eventent->d_name+len-strlen(SHLIB_EXT), SHLIB_EXT)) {
continue;
}
/* Check if this event handler has been disabled in the configuration file */
if(disabled_eventhandlers != NULL) {
gchar *index = disabled_eventhandlers[0];
if(index != NULL) {
int i=0;
gboolean skip = FALSE;
while(index != NULL) {
while(isspace(*index))
index++;
if(strlen(index) && !strcmp(index, eventent->d_name)) {
JANUS_LOG(LOG_WARN, "Event handler plugin '%s' has been disabled, skipping...\n", eventent->d_name);
skip = TRUE;
break;
}
i++;
index = disabled_eventhandlers[i];
}
if(skip)
continue;
}
}
JANUS_LOG(LOG_INFO, "Loading event handler plugin '%s'...\n", eventent->d_name);
memset(eventpath, 0, 1024);
g_snprintf(eventpath, 1024, "%s/%s", path, eventent->d_name);
void *event = dlopen(eventpath, RTLD_NOW | RTLD_GLOBAL);
if (!event) {
JANUS_LOG(LOG_ERR, "\tCouldn't load event handler plugin '%s': %s\n", eventent->d_name, dlerror());
} else {
create_e *create = (create_e*) dlsym(event, "create");
const char *dlsym_error = dlerror();
if (dlsym_error) {
JANUS_LOG(LOG_ERR, "\tCouldn't load symbol 'create': %s\n", dlsym_error);
continue;
}
janus_eventhandler *janus_eventhandler = create();
if(!janus_eventhandler) {
JANUS_LOG(LOG_ERR, "\tCouldn't use function 'create'...\n");
continue;
}
/* Are all the mandatory methods and callbacks implemented? */
if(!janus_eventhandler->init || !janus_eventhandler->destroy ||
!janus_eventhandler->get_api_compatibility ||
!janus_eventhandler->get_version ||
!janus_eventhandler->get_version_string ||
!janus_eventhandler->get_description ||
!janus_eventhandler->get_package ||
!janus_eventhandler->get_name ||
!janus_eventhandler->incoming_event) {
JANUS_LOG(LOG_ERR, "\tMissing some mandatory methods/callbacks, skipping this event handler plugin...\n");
continue;
}
if(janus_eventhandler->get_api_compatibility() < JANUS_EVENTHANDLER_API_VERSION) {
JANUS_LOG(LOG_ERR, "The '%s' event handler plugin was compiled against an older version of the API (%d < %d), skipping it: update it to enable it again\n",
janus_eventhandler->get_package(), janus_eventhandler->get_api_compatibility(), JANUS_EVENTHANDLER_API_VERSION);
continue;
}
janus_eventhandler->init(configs_folder);
JANUS_LOG(LOG_VERB, "\tVersion: %d (%s)\n", janus_eventhandler->get_version(), janus_eventhandler->get_version_string());
JANUS_LOG(LOG_VERB, "\t [%s] %s\n", janus_eventhandler->get_package(), janus_eventhandler->get_name());
JANUS_LOG(LOG_VERB, "\t %s\n", janus_eventhandler->get_description());
JANUS_LOG(LOG_VERB, "\t Plugin API version: %d\n", janus_eventhandler->get_api_compatibility());
JANUS_LOG(LOG_VERB, "\t Subscriptions:");
if(janus_eventhandler->events_mask == 0) {
JANUS_LOG(LOG_VERB, " none");
} else {
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_SESSION))
JANUS_LOG(LOG_VERB, " sessions");
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_HANDLE))
JANUS_LOG(LOG_VERB, " handles");
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_JSEP))
JANUS_LOG(LOG_VERB, " jsep");
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_WEBRTC))
JANUS_LOG(LOG_VERB, " webrtc");
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_MEDIA))
JANUS_LOG(LOG_VERB, " media");
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_PLUGIN))
JANUS_LOG(LOG_VERB, " plugins");
if(janus_flags_is_set(&janus_eventhandler->events_mask, JANUS_EVENT_TYPE_TRANSPORT))
JANUS_LOG(LOG_VERB, " transports");
}
JANUS_LOG(LOG_VERB, "\n");
if(eventhandlers == NULL)
eventhandlers = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(eventhandlers, (gpointer)janus_eventhandler->get_package(), janus_eventhandler);
if(eventhandlers_so == NULL)
eventhandlers_so = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(eventhandlers_so, (gpointer)janus_eventhandler->get_package(), event);
}
}
}
closedir(dir);
if(disabled_eventhandlers != NULL)
g_strfreev(disabled_eventhandlers);
disabled_eventhandlers = NULL;
/* Initialize the event broadcaster */
if(janus_events_init(enable_events, (server_name ? server_name : (char *)JANUS_SERVER_NAME), eventhandlers) < 0) {
JANUS_LOG(LOG_FATAL, "Error initializing the Event handlers mechanism...\n");
exit(1);
}
}
其中,janus_events_init(enable_events, (server_name ? server_name : (char *)JANUS_SERVER_NAME), eventhandlers)
初始化启动了全局的事件处理线程 janus_events_thread
2.3 Plugins处理代码
详细代码:
/* Load plugins */
path = PLUGINDIR;
item = janus_config_get(config, config_general, janus_config_type_item, "plugins_folder");
if(item && item->value)
path = (char *)item->value;
JANUS_LOG(LOG_INFO, "Plugins folder: %s\n", path);
dir = opendir(path);
if(!dir) {
JANUS_LOG(LOG_FATAL, "\tCouldn't access plugins folder...\n");
exit(1);
}
/* Any plugin to ignore? */
gchar **disabled_plugins = NULL;
item = janus_config_get(config, config_plugins, janus_config_type_item, "disable");
if(item && item->value)
disabled_plugins = g_strsplit(item->value, ",", -1);
/* Open the shared objects */
struct dirent *pluginent = NULL;
char pluginpath[1024];
while((pluginent = readdir(dir))) {
int len = strlen(pluginent->d_name);
if (len < 4) {
continue;
}
if (strcasecmp(pluginent->d_name+len-strlen(SHLIB_EXT), SHLIB_EXT)) {
continue;
}
/* Check if this plugins has been disabled in the configuration file */
if(disabled_plugins != NULL) {
gchar *index = disabled_plugins[0];
if(index != NULL) {
int i=0;
gboolean skip = FALSE;
while(index != NULL) {
while(isspace(*index))
index++;
if(strlen(index) && !strcmp(index, pluginent->d_name)) {
JANUS_LOG(LOG_WARN, "Plugin '%s' has been disabled, skipping...\n", pluginent->d_name);
skip = TRUE;
break;
}
i++;
index = disabled_plugins[i];
}
if(skip)
continue;
}
}
JANUS_LOG(LOG_INFO, "Loading plugin '%s'...\n", pluginent->d_name);
memset(pluginpath, 0, 1024);
g_snprintf(pluginpath, 1024, "%s/%s", path, pluginent->d_name);
void *plugin = dlopen(pluginpath, RTLD_NOW | RTLD_GLOBAL);
if (!plugin) {
JANUS_LOG(LOG_ERR, "\tCouldn't load plugin '%s': %s\n", pluginent->d_name, dlerror());
} else {
create_p *create = (create_p*) dlsym(plugin, "create");
const char *dlsym_error = dlerror();
if (dlsym_error) {
JANUS_LOG(LOG_ERR, "\tCouldn't load symbol 'create': %s\n", dlsym_error);
continue;
}
janus_plugin *janus_plugin = create();
if(!janus_plugin) {
JANUS_LOG(LOG_ERR, "\tCouldn't use function 'create'...\n");
continue;
}
/* Are all the mandatory methods and callbacks implemented? */
if(!janus_plugin->init || !janus_plugin->destroy ||
!janus_plugin->get_api_compatibility ||
!janus_plugin->get_version ||
!janus_plugin->get_version_string ||
!janus_plugin->get_description ||
!janus_plugin->get_package ||
!janus_plugin->get_name ||
!janus_plugin->create_session ||
!janus_plugin->query_session ||
!janus_plugin->destroy_session ||
!janus_plugin->handle_message ||
!janus_plugin->setup_media ||
!janus_plugin->hangup_media) {
JANUS_LOG(LOG_ERR, "\tMissing some mandatory methods/callbacks, skipping this plugin...\n");
continue;
}
if(janus_plugin->get_api_compatibility() < JANUS_PLUGIN_API_VERSION) {
JANUS_LOG(LOG_ERR, "The '%s' plugin was compiled against an older version of the API (%d < %d), skipping it: update it to enable it again\n",
janus_plugin->get_package(), janus_plugin->get_api_compatibility(), JANUS_PLUGIN_API_VERSION);
continue;
}
if(janus_plugin->init(&janus_handler_plugin, configs_folder) < 0) {
JANUS_LOG(LOG_WARN, "The '%s' plugin could not be initialized\n", janus_plugin->get_package());
dlclose(plugin);
continue;
}
JANUS_LOG(LOG_VERB, "\tVersion: %d (%s)\n", janus_plugin->get_version(), janus_plugin->get_version_string());
JANUS_LOG(LOG_VERB, "\t [%s] %s\n", janus_plugin->get_package(), janus_plugin->get_name());
JANUS_LOG(LOG_VERB, "\t %s\n", janus_plugin->get_description());
JANUS_LOG(LOG_VERB, "\t Plugin API version: %d\n", janus_plugin->get_api_compatibility());
if(!janus_plugin->incoming_rtp && !janus_plugin->incoming_rtcp && !janus_plugin->incoming_data) {
JANUS_LOG(LOG_WARN, "The '%s' plugin doesn't implement any callback for RTP/RTCP/data... is this on purpose?\n",
janus_plugin->get_package());
}
if(!janus_plugin->incoming_rtp && !janus_plugin->incoming_rtcp && janus_plugin->incoming_data) {
JANUS_LOG(LOG_WARN, "The '%s' plugin will only handle data channels (no RTP/RTCP)... is this on purpose?\n",
janus_plugin->get_package());
}
if(plugins == NULL)
plugins = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(plugins, (gpointer)janus_plugin->get_package(), janus_plugin);
if(plugins_so == NULL)
plugins_so = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(plugins_so, (gpointer)janus_plugin->get_package(), plugin);
}
}
closedir(dir);
if(disabled_plugins != NULL)
g_strfreev(disabled_plugins);
disabled_plugins = NULL;
其中,janus_plugin->init(&janus_handler_plugin, configs_folder)
初始化设置了插件的回调处理 janus_handler_plugin
2.4 Transports处理代码
详细代码:
/* Load transports */
gboolean janus_api_enabled = FALSE, admin_api_enabled = FALSE;
path = TRANSPORTDIR;
item = janus_config_get(config, config_general, janus_config_type_item, "transports_folder");
if(item && item->value)
path = (char *)item->value;
JANUS_LOG(LOG_INFO, "Transport plugins folder: %s\n", path);
dir = opendir(path);
if(!dir) {
JANUS_LOG(LOG_FATAL, "\tCouldn't access transport plugins folder...\n");
exit(1);
}
/* Any transport to ignore? */
gchar **disabled_transports = NULL;
item = janus_config_get(config, config_transports, janus_config_type_item, "disable");
if(item && item->value)
disabled_transports = g_strsplit(item->value, ",", -1);
/* Open the shared objects */
struct dirent *transportent = NULL;
char transportpath[1024];
while((transportent = readdir(dir))) {
int len = strlen(transportent->d_name);
if (len < 4) {
continue;
}
if (strcasecmp(transportent->d_name+len-strlen(SHLIB_EXT), SHLIB_EXT)) {
continue;
}
/* Check if this transports has been disabled in the configuration file */
if(disabled_transports != NULL) {
gchar *index = disabled_transports[0];
if(index != NULL) {
int i=0;
gboolean skip = FALSE;
while(index != NULL) {
while(isspace(*index))
index++;
if(strlen(index) && !strcmp(index, transportent->d_name)) {
JANUS_LOG(LOG_WARN, "Transport plugin '%s' has been disabled, skipping...\n", transportent->d_name);
skip = TRUE;
break;
}
i++;
index = disabled_transports[i];
}
if(skip)
continue;
}
}
JANUS_LOG(LOG_INFO, "Loading transport plugin '%s'...\n", transportent->d_name);
memset(transportpath, 0, 1024);
g_snprintf(transportpath, 1024, "%s/%s", path, transportent->d_name);
void *transport = dlopen(transportpath, RTLD_NOW | RTLD_GLOBAL);
if (!transport) {
JANUS_LOG(LOG_ERR, "\tCouldn't load transport plugin '%s': %s\n", transportent->d_name, dlerror());
} else {
create_t *create = (create_t*) dlsym(transport, "create");
const char *dlsym_error = dlerror();
if (dlsym_error) {
JANUS_LOG(LOG_ERR, "\tCouldn't load symbol 'create': %s\n", dlsym_error);
continue;
}
janus_transport *janus_transport = create();
if(!janus_transport) {
JANUS_LOG(LOG_ERR, "\tCouldn't use function 'create'...\n");
continue;
}
/* Are all the mandatory methods and callbacks implemented? */
if(!janus_transport->init || !janus_transport->destroy ||
!janus_transport->get_api_compatibility ||
!janus_transport->get_version ||
!janus_transport->get_version_string ||
!janus_transport->get_description ||
!janus_transport->get_package ||
!janus_transport->get_name ||
!janus_transport->send_message ||
!janus_transport->is_janus_api_enabled ||
!janus_transport->is_admin_api_enabled ||
!janus_transport->session_created ||
!janus_transport->session_over ||
!janus_transport->session_claimed) {
JANUS_LOG(LOG_ERR, "\tMissing some mandatory methods/callbacks, skipping this transport plugin...\n");
continue;
}
if(janus_transport->get_api_compatibility() < JANUS_TRANSPORT_API_VERSION) {
JANUS_LOG(LOG_ERR, "The '%s' transport plugin was compiled against an older version of the API (%d < %d), skipping it: update it to enable it again\n",
janus_transport->get_package(), janus_transport->get_api_compatibility(), JANUS_TRANSPORT_API_VERSION);
continue;
}
if(janus_transport->init(&janus_handler_transport, configs_folder) < 0) {
JANUS_LOG(LOG_WARN, "The '%s' plugin could not be initialized\n", janus_transport->get_package());
dlclose(transport);
continue;
}
JANUS_LOG(LOG_VERB, "\tVersion: %d (%s)\n", janus_transport->get_version(), janus_transport->get_version_string());
JANUS_LOG(LOG_VERB, "\t [%s] %s\n", janus_transport->get_package(), janus_transport->get_name());
JANUS_LOG(LOG_VERB, "\t %s\n", janus_transport->get_description());
JANUS_LOG(LOG_VERB, "\t Plugin API version: %d\n", janus_transport->get_api_compatibility());
JANUS_LOG(LOG_VERB, "\t Janus API: %s\n", janus_transport->is_janus_api_enabled() ? "enabled" : "disabled");
JANUS_LOG(LOG_VERB, "\t Admin API: %s\n", janus_transport->is_admin_api_enabled() ? "enabled" : "disabled");
janus_api_enabled = janus_api_enabled || janus_transport->is_janus_api_enabled();
admin_api_enabled = admin_api_enabled || janus_transport->is_admin_api_enabled();
if(transports == NULL)
transports = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(transports, (gpointer)janus_transport->get_package(), janus_transport);
if(transports_so == NULL)
transports_so = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(transports_so, (gpointer)janus_transport->get_package(), transport);
}
}
closedir(dir);
if(disabled_transports != NULL)
g_strfreev(disabled_transports);
disabled_transports = NULL;
其中,janus_transport->init(&janus_handler_transport, configs_folder)
初始化设置了Transport的回调处理 janus_handler_transport
3. 请求处理过程
过程如下所述:
Janus客户端
连接Transport
发起请求;Transport
收到请求后,执行janus_xxx_handler处理,调用Janus主线程
的回调函数incoming_request;Janus主线程
的incoming_request将请求加入请求队列
;请求处理线程
从请求队列
中获取请求信息,执行janus_transport_requests处理;- 若请求需同步处理,
请求处理线程
执行janus_process_incoming_request,调用Plugin
的handle_message函数进行处理; - 若请求需异步处理,
请求处理线程
将请求加入任务列表
,任务处理线程池
执行janus_transport_task函数,执行janus_process_incoming_request,调用Plugin
的handle_message函数进行处理;
- 若请求需同步处理,
Plugin
的handle_message将处理结果加入Plugin消息队列
;Plugin消息处理线程
从Plugin消息队列
获取处理结果,执行janus_yyy_handler处理,调用Janus主线程
的回调函数push_event;Janus主线程
的push_event调用Transport
的send_message进行处理;Transport
将处理完的结果返回给Janus客户端
;
3.1 Transport启动服务时设置请求处理函数(以transport/janus_http.c为例)
janus_http_handler 详细代码:
/* WebServer requests handler */
int janus_http_handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr)
{
char *payload = NULL;
json_t *root = NULL;
struct MHD_Response *response = NULL;
int ret = MHD_NO;
gchar *session_path = NULL, *handle_path = NULL;
gchar **basepath = NULL, **path = NULL;
guint64 session_id = 0, handle_id = 0;
/* Is this the first round? */
int firstround = 0;
janus_transport_session *ts = (janus_transport_session *)*ptr;
janus_http_msg *msg = NULL;
if(ts == NULL) {
firstround = 1;
JANUS_LOG(LOG_DBG, "Got a HTTP %s request on %s...\n", method, url);
JANUS_LOG(LOG_DBG, " ... Just parsing headers for now...\n");
msg = g_malloc0(sizeof(janus_http_msg));
msg->connection = connection;
janus_mutex_init(&msg->wait_mutex);
janus_condition_init(&msg->wait_cond);
ts = janus_transport_session_create(msg, janus_http_msg_destroy);
janus_mutex_lock(&messages_mutex);
g_hash_table_insert(messages, ts, ts);
janus_mutex_unlock(&messages_mutex);
*ptr = ts;
MHD_get_connection_values(connection, MHD_HEADER_KIND, &janus_http_headers, msg);
ret = MHD_YES;
/* Notify handlers about this new transport instance */
if(notify_events && gateway->events_is_enabled()) {
json_t *info = json_object();
json_object_set_new(info, "event", json_string("request"));
json_object_set_new(info, "admin_api", json_false());
const union MHD_ConnectionInfo *conninfo = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
if(conninfo != NULL) {
janus_network_address addr;
janus_network_address_string_buffer addr_buf;
if(janus_network_address_from_sockaddr((struct sockaddr *)conninfo->client_addr, &addr) == 0 &&
janus_network_address_to_string_buffer(&addr, &addr_buf) == 0) {
const char *ip = janus_network_address_string_from_buffer(&addr_buf);
json_object_set_new(info, "ip", json_string(ip));
}
uint16_t port = janus_http_sockaddr_to_port((struct sockaddr *)conninfo->client_addr);
json_object_set_new(info, "port", json_integer(port));
}
gateway->notify_event(&janus_http_transport, ts, info);
}
} else {
JANUS_LOG(LOG_DBG, "Processing HTTP %s request on %s...\n", method, url);
msg = (janus_http_msg *)ts->transport_p;
}
/* Parse request */
if (strcasecmp(method, "GET") && strcasecmp(method, "POST") && strcasecmp(method, "OPTIONS")) {
ret = janus_http_return_error(ts, 0, NULL, JANUS_ERROR_TRANSPORT_SPECIFIC, "Unsupported method %s", method);
goto done;
}
if (!strcasecmp(method, "OPTIONS")) {
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
janus_http_add_cors_headers(msg, response);
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
}
/* Get path components */
if(strcasecmp(url, ws_path)) {
if(strlen(ws_path) > 1) {
basepath = g_strsplit(url, ws_path, -1);
} else {
/* The base path is the web server too itself, we process the url itself */
basepath = g_malloc_n(3, sizeof(char *));
basepath[0] = g_strdup("/");
basepath[1] = g_strdup(url);
basepath[2] = NULL;
}
if(basepath[0] == NULL || basepath[1] == NULL || basepath[1][0] != '/') {
JANUS_LOG(LOG_ERR, "Invalid url %s\n", url);
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
janus_http_add_cors_headers(msg, response);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);
}
if(firstround) {
g_strfreev(basepath);
return ret;
}
path = g_strsplit(basepath[1], "/", -1);
if(path == NULL || path[1] == NULL) {
JANUS_LOG(LOG_ERR, "Invalid path %s (%s)\n", basepath[1], path ? path[1] : "");
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
janus_http_add_cors_headers(msg, response);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);
g_strfreev(basepath);
g_strfreev(path);
return ret;
}
}
if(firstround) {
g_strfreev(basepath);
g_strfreev(path);
return ret;
}
JANUS_LOG(LOG_DBG, " ... parsing request...\n");
if(path != NULL && path[1] != NULL && strlen(path[1]) > 0) {
session_path = g_strdup(path[1]);
JANUS_LOG(LOG_HUGE, "Session: %s\n", session_path);
}
if(session_path != NULL && path[2] != NULL && strlen(path[2]) > 0) {
handle_path = g_strdup(path[2]);
JANUS_LOG(LOG_HUGE, "Handle: %s\n", handle_path);
}
if(session_path != NULL && handle_path != NULL && path[3] != NULL && strlen(path[3]) > 0) {
JANUS_LOG(LOG_ERR, "Too many components...\n");
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
janus_http_add_cors_headers(msg, response);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);
goto done;
}
/* Get payload, if any */
if(!strcasecmp(method, "POST")) {
JANUS_LOG(LOG_HUGE, "Processing POST data (%s) (%zu bytes)...\n", msg->contenttype, *upload_data_size);
if(*upload_data_size != 0) {
msg->payload = g_realloc(msg->payload, msg->len+*upload_data_size+1);
memcpy(msg->payload+msg->len, upload_data, *upload_data_size);
msg->len += *upload_data_size;
memset(msg->payload + msg->len, '\0', 1);
JANUS_LOG(LOG_DBG, " -- Data we have now (%zu bytes)\n", msg->len);
*upload_data_size = 0; /* Go on */
ret = MHD_YES;
goto done;
}
JANUS_LOG(LOG_DBG, "Done getting payload, we can answer\n");
if(msg->payload == NULL) {
JANUS_LOG(LOG_ERR, "No payload :-(\n");
ret = MHD_NO;
goto done;
}
payload = msg->payload;
JANUS_LOG(LOG_HUGE, "%s\n", payload);
}
/* Is this a generic request for info? */
if(session_path != NULL && !strcmp(session_path, "info")) {
/* The info REST endpoint, if contacted through a GET, provides information on the Janus core */
if(strcasecmp(method, "GET")) {
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
janus_http_add_cors_headers(msg, response);
ret = MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, response);
MHD_destroy_response(response);
goto done;
}
/* Turn this into a fake "info" request */
method = "POST";
char tr[12];
janus_http_random_string(12, (char *)&tr);
root = json_object();
json_object_set_new(root, "janus", json_string("info"));
json_object_set_new(root, "transaction", json_string(tr));
goto parsingdone;
}
/* Or maybe a long poll */
if(!strcasecmp(method, "GET") || !payload) {
session_id = session_path ? g_ascii_strtoull(session_path, NULL, 10) : 0;
if(session_id < 1) {
JANUS_LOG(LOG_ERR, "Invalid session %s\n", session_path);
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
janus_http_add_cors_headers(msg, response);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);