client: wait until the TEARDOWN response is sent to close the connection

Responses can be sent async so we need to wait until the TEARDOWN response has
been written before we close the connection to the client. This avoids the risk
of writing/polling closed sockets.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=688535
This commit is contained in:
Alessandro Decina 2012-11-17 14:51:52 +01:00 committed by Wim Taymans
parent 0996266342
commit 65042a9551
2 changed files with 24 additions and 18 deletions

View file

@ -174,6 +174,7 @@ static void
gst_rtsp_client_init (GstRTSPClient * client)
{
client->use_client_settings = DEFAULT_USE_CLIENT_SETTINGS;
client->teardown_response_seq = 0;
}
static void
@ -300,7 +301,7 @@ gst_rtsp_client_new (void)
static void
send_response (GstRTSPClient * client, GstRTSPSession * session,
GstRTSPMessage * response)
GstRTSPMessage * response, guint * id)
{
gst_rtsp_message_add_header (response, GST_RTSP_HDR_SERVER,
"GStreamer RTSP server");
@ -318,7 +319,7 @@ send_response (GstRTSPClient * client, GstRTSPSession * session,
gst_rtsp_message_dump (response);
}
gst_rtsp_watch_send_message (client->watch, response, NULL);
gst_rtsp_watch_send_message (client->watch, response, id);
gst_rtsp_message_unset (response);
}
@ -329,7 +330,7 @@ send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code,
gst_rtsp_message_init_response (state->response, code,
gst_rtsp_status_as_text (code), state->request);
send_response (client, NULL, state->response);
send_response (client, NULL, state->response, NULL);
}
static void
@ -344,7 +345,7 @@ handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth,
gst_rtsp_auth_setup_auth (auth, client, 0, state);
}
send_response (client, state->session, state->response);
send_response (client, state->session, state->response, NULL);
}
@ -603,14 +604,15 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONNECTION,
"close");
send_response (client, session, state->response);
/* send the response and store the seq number so we can wait until it's
* written to the client to close the connection */
send_response (client, session, state->response,
&client->teardown_response_seq);
/* we emit the signal before closing the connection */
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_TEARDOWN_REQUEST],
0, state);
close_connection (client);
return TRUE;
/* ERRORS */
@ -646,7 +648,7 @@ handle_get_param_request (GstRTSPClient * client, GstRTSPClientState * state)
if (res != GST_RTSP_OK)
goto bad_request;
send_response (client, state->session, state->response);
send_response (client, state->session, state->response, NULL);
}
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_GET_PARAMETER_REQUEST],
@ -682,7 +684,7 @@ handle_set_param_request (GstRTSPClient * client, GstRTSPClientState * state)
if (res != GST_RTSP_OK)
goto bad_request;
send_response (client, state->session, state->response);
send_response (client, state->session, state->response, NULL);
}
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SET_PARAMETER_REQUEST],
@ -731,7 +733,7 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
gst_rtsp_message_init_response (state->response, code,
gst_rtsp_status_as_text (code), state->request);
send_response (client, session, state->response);
send_response (client, session, state->response, NULL);
/* the state is now READY */
media->state = GST_RTSP_STATE_READY;
@ -853,7 +855,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
str = gst_rtsp_media_get_range_string (media->media, TRUE);
gst_rtsp_message_take_header (state->response, GST_RTSP_HDR_RANGE, str);
send_response (client, session, state->response);
send_response (client, session, state->response, NULL);
/* start playing after sending the request */
gst_rtsp_session_media_set_state (media, GST_STATE_PLAYING);
@ -1179,7 +1181,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
trans_str);
g_free (trans_str);
send_response (client, session, state->response);
send_response (client, session, state->response, NULL);
/* update the state */
switch (sessmedia->state) {
@ -1368,7 +1370,7 @@ handle_describe_request (GstRTSPClient * client, GstRTSPClientState * state)
gst_rtsp_message_take_body (state->response, (guint8 *) str, strlen (str));
gst_sdp_message_free (sdp);
send_response (client, state->session, state->response);
send_response (client, state->session, state->response, NULL);
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_DESCRIBE_REQUEST],
0, state);
@ -1410,7 +1412,7 @@ handle_options_request (GstRTSPClient * client, GstRTSPClientState * state)
gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_PUBLIC, str);
g_free (str);
send_response (client, state->session, state->response);
send_response (client, state->session, state->response, NULL);
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_OPTIONS_REQUEST],
0, state);
@ -1891,11 +1893,13 @@ message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
static GstRTSPResult
message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
{
/* GstRTSPClient *client; */
GstRTSPClient *client;
/* client = GST_RTSP_CLIENT (user_data); */
/* GST_INFO ("client %p: sent a message with cseq %d", client, cseq); */
client = GST_RTSP_CLIENT (user_data);
if (client->teardown_response_seq && client->teardown_response_seq == cseq) {
client->teardown_response_seq = 0;
close_connection (client);
}
return GST_RTSP_OK;
}

View file

@ -107,6 +107,8 @@ struct _GstRTSPClient {
GList *transports;
GList *sessions;
guint teardown_response_seq;
};
struct _GstRTSPClientClass {