Skip to content

Commit

Permalink
rtsp: do not race accept() and select()
Browse files Browse the repository at this point in the history
  • Loading branch information
abrasive committed Jun 7, 2013
1 parent e15614d commit f39b236
Showing 1 changed file with 24 additions and 27 deletions.
51 changes: 24 additions & 27 deletions rtsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static int please_shutdown = 0;
static pthread_t playing_thread = 0;

typedef struct {
int fd;
stream_cfg stream;
SOCKADDR remote;
} rtsp_conn_info;
Expand Down Expand Up @@ -634,33 +635,22 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
return 1;
}

static void *rtsp_conversation_thread_func(void *vfd) {
static void *rtsp_conversation_thread_func(void *pconn) {
// SIGUSR1 is used to interrupt this thread if blocked for read
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);

rtsp_conn_info conn;
memset(&conn, 0, sizeof(conn));

int fd = *(int*)vfd;
socklen_t slen = sizeof(conn.remote);

debug(1, "new RTSP connection\n");
fd = accept(fd, (struct sockaddr *)&conn.remote, &slen);
if (fd < 0) {
perror("failed to accept connection");
goto shutdown;
}
rtsp_conn_info *conn = pconn;

rtsp_message *req, *resp;
char *hdr, *auth_nonce = NULL;
while ((req = rtsp_read_request(fd))) {
while ((req = rtsp_read_request(conn->fd))) {
resp = msg_init();
resp->respcode = 400;

apple_challenge(fd, req, resp);
apple_challenge(conn->fd, req, resp);
hdr = msg_get_header(req, "CSeq");
if (hdr)
msg_add_header(resp, "CSeq", hdr);
Expand All @@ -672,21 +662,20 @@ static void *rtsp_conversation_thread_func(void *vfd) {
struct method_handler *mh;
for (mh=method_handlers; mh->method; mh++) {
if (!strcmp(mh->method, req->method)) {
mh->handler(&conn, req, resp);
mh->handler(conn, req, resp);
break;
}
}

respond:
msg_write_response(fd, resp);
msg_write_response(conn->fd, resp);
msg_free(req);
msg_free(resp);
}

shutdown:
debug(1, "closing RTSP connection\n");
if (fd > 0)
close(fd);
if (conn->fd > 0)
close(conn->fd);
if (rtsp_playing()) {
rtp_shutdown();
player_stop();
Expand All @@ -695,6 +684,7 @@ static void *rtsp_conversation_thread_func(void *vfd) {
}
if (auth_nonce)
free(auth_nonce);
free(conn);
debug(2, "terminating RTSP thread\n");
return NULL;
}
Expand Down Expand Up @@ -802,20 +792,27 @@ void rtsp_listen_loop(void) {
break;
}

debug(2, "new connection coming.\n");

for (i=0; i<nsock; i++) {
if (FD_ISSET(sockfd[i], &fds)) {
acceptfd = sockfd[i];
break;
}
}

// for now, we do not track these and let them die of natural causes.
// XXX: this leaks threads; they need to be culled with pthread_tryjoin_np.
// XXX: acceptfd could change before the thread is up. which should never happen, but still.
pthread_t rtsp_conversation_thread;
pthread_create(&rtsp_conversation_thread, NULL, rtsp_conversation_thread_func, &acceptfd);
rtsp_conn_info *conn = malloc(sizeof(rtsp_conn_info));
memset(conn, 0, sizeof(rtsp_conn_info));
socklen_t slen = sizeof(conn->remote);

debug(1, "new RTSP connection\n");
conn->fd = accept(acceptfd, (struct sockaddr *)&conn->remote, &slen);
if (conn->fd < 0) {
perror("failed to accept connection");
} else {
// for now, we do not track these and let them die of natural causes.
// XXX: this leaks threads; they need to be culled with pthread_tryjoin_np.
pthread_t rtsp_conversation_thread;
pthread_create(&rtsp_conversation_thread, NULL, rtsp_conversation_thread_func, conn);
}

for (i=0; i<nsock; i++)
FD_SET(sockfd[i], &fds);
Expand Down

0 comments on commit f39b236

Please sign in to comment.