Rework SRS to support multiple clients
authorAlexander Tarasikov <alexander.tarasikov@gmail.com>
Sun, 26 Aug 2012 21:05:35 +0000 (01:05 +0400)
committerAlexander Tarasikov <alexander.tarasikov@gmail.com>
Sun, 26 Aug 2012 21:05:35 +0000 (01:05 +0400)
This fixes deadlocks on Galaxy Nexus (Tuna)
when GPS/NFC libraries open the socket thus preventing
in-call audio from functioning

samsung-ril.c
samsung-ril.h
srs.c
srs.h

index 4b9b0ff..f3332be 100644 (file)
@@ -309,12 +309,12 @@ void ipc_rfs_dispatch(struct ipc_message_info *info)
        ril_unlock();
 }
 
-void srs_dispatch(struct srs_message *message)
+void srs_dispatch(int fd, struct srs_message *message)
 {
        ril_lock();
        switch(message->command) {
                case SRS_CONTROL_PING:
-                       srs_control_ping(message);
+                       srs_control_ping(fd, message);
                        break;
                case SRS_SND_SET_CALL_CLOCK_SYNC:
                        srs_snd_set_call_clock_sync(message);
index 493fb43..45e0e44 100644 (file)
@@ -200,7 +200,7 @@ int ril_modem_check(void);
 
 void ipc_fmt_dispatch(struct ipc_message_info *info);
 void ipc_rfs_dispatch(struct ipc_message_info *info);
-void srs_dispatch(struct srs_message *message);
+void srs_dispatch(int fd, struct srs_message *message);
 
 /* GEN */
 
diff --git a/srs.c b/srs.c
index 3c519ab..95815a5 100644 (file)
--- a/srs.c
+++ b/srs.c
 #include "samsung-ril.h"
 #include "util.h"
 
-struct srs_server *srs_server_new(void)
-{
-       struct srs_server *srs_server;
-
-       srs_server = malloc(sizeof(struct srs_server));
-       memset(srs_server, 0, sizeof(struct srs_server));
-       srs_server->server_fd = -1;
-       srs_server->client_fd = -1;
-
-       return srs_server;
-}
-
-void srs_server_free(struct srs_server *srs_server)
-{
-       if(srs_server == NULL)
-               return;
-
-       free(srs_server);
-}
-
-int srs_server_send_message(struct srs_server *srs_server, struct srs_message *message)
+static int srs_server_send_message(int client_fd, struct srs_message *message)
 {
        fd_set fds;
 
@@ -73,41 +53,39 @@ int srs_server_send_message(struct srs_server *srs_server, struct srs_message *m
                message->data, message->data_len);
 
        FD_ZERO(&fds);
-       FD_SET(srs_server->client_fd, &fds);
+       FD_SET(client_fd, &fds);
 
        select(FD_SETSIZE, NULL, &fds, NULL, NULL);
 
-       write(srs_server->client_fd, data, header.length);
+       write(client_fd, data, header.length);
 
        free(data);
 
        return 0;
 }
 
-int srs_server_send(unsigned short command, void *data, int data_len)
+static int srs_server_send(int fd, unsigned short command, void *data,
+       int data_len)
 {
-       struct srs_server *srs_server;
        struct srs_message message;
        int rc;
 
-       srs_server = (struct srs_server *) (srs_client->object);
-
        message.command = command;
        message.data = data;
        message.data_len = data_len;
 
-       rc = srs_server_send_message(srs_server, &message);
+       rc = srs_server_send_message(fd, &message);
 
        return rc;
 }
 
-int srs_server_recv(struct srs_server *srs_server, struct srs_message *message)
+static int srs_server_recv(int client_fd, struct srs_message *message)
 {
        void *raw_data = malloc(SRS_DATA_MAX_SIZE);
        struct srs_header *header;
        int rc;
 
-       rc = read(srs_server->client_fd, raw_data, SRS_DATA_MAX_SIZE);
+       rc = read(client_fd, raw_data, SRS_DATA_MAX_SIZE);
        if(rc < (int)sizeof(struct srs_header)) {
                return -1;
        }
@@ -126,31 +104,7 @@ int srs_server_recv(struct srs_server *srs_server, struct srs_message *message)
        return 0;
 }
 
-int srs_server_accept(struct srs_server *srs_server)
-{
-       int client_fd = -1;
-       struct sockaddr_un client_addr;
-       int client_addr_len;
-
-       if(srs_server->client_fd > 0) {
-               return 0;
-       }
-
-       client_fd = accept(srs_server->server_fd,
-               (struct sockaddr*) &client_addr, &client_addr_len);
-
-       if(client_fd > 0) {
-               srs_server->client_fd = client_fd;
-               srs_server->client_addr = client_addr;
-               srs_server->client_addr_len = client_addr_len;
-
-               return 0;
-       }
-
-       return -1;
-}
-
-void srs_control_ping(struct srs_message *message)
+void srs_control_ping(int fd, struct srs_message *message)
 {
        int caffe;
 
@@ -160,11 +114,11 @@ void srs_control_ping(struct srs_message *message)
        caffe=*((int *) message->data);
 
        if(caffe == SRS_CONTROL_CAFFE) {
-               srs_server_send(SRS_CONTROL_PING, &caffe, sizeof(caffe));
+               srs_server_send(fd, SRS_CONTROL_PING, &caffe, sizeof(caffe));
        }
 }
 
-int srs_server_open(struct srs_server *srs_server)
+static int srs_server_open(void)
 {
        int server_fd = -1;
 
@@ -174,27 +128,69 @@ int srs_server_open(struct srs_server *srs_server)
                unlink(SRS_SOCKET_NAME);
                server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
 
-               if(server_fd > 0)
+               if(server_fd >= 0)
                        break;
 
                t++;
        }
-       
-       if(server_fd < 0)
-               return -1;
-
-       srs_server->server_fd = server_fd;
 
-       return 0;
+       return server_fd;
 }
 
-int srs_read_loop(struct ril_client *client)
+static void* srs_process_client(void *pfd)
 {
-       struct srs_server *srs_server;
        struct srs_message srs_message;
        fd_set fds;
+       int client_fd = -1;
+       if (!pfd) {
+               LOGE("SRS client data is NULL");
+               goto fail;
+       }
+
+       client_fd = ((int*)pfd)[0];
+
+       while (1) {
+               if (client_fd < 0)
+                       break;
+
+               FD_ZERO(&fds);
+               FD_SET(client_fd, &fds);
+
+               select(FD_SETSIZE, &fds, NULL, NULL, NULL);
+
+               if (FD_ISSET(client_fd, &fds)) {
+                       if (srs_server_recv(client_fd, &srs_message) < 0) {
+                               LOGE("SRS recv failed, aborting!");
+                               break;
+                       }
+
+                       LOGD("SRS recv: command=%d data_len=%d",
+                            srs_message.command, srs_message.data_len);
+                       hex_dump(srs_message.data, srs_message.data_len);
+
+                       srs_dispatch(client_fd, &srs_message);
+
+                       if (srs_message.data != NULL)
+                               free(srs_message.data);
+               }
+       }
+
+fail:
+       if(client_fd >= 0) {
+               close(client_fd);
+       }
+
+       LOGE("SRS server client ended!");
+       return NULL;
+}
+
+static int srs_read_loop(struct ril_client *client)
+{
        int rc;
 
+       struct sockaddr_un client_addr;
+       int client_addr_len;
+
        if(client == NULL) {
                LOGE("client is NULL, aborting!");
                return -1;
@@ -205,84 +201,82 @@ int srs_read_loop(struct ril_client *client)
                return -1;
        }
 
-       srs_server = (struct srs_server *) client->object;
+       int server_fd = ((int*)client->object)[0];
 
        while(1) {
-               if(srs_server->server_fd < 0) {
+               if(server_fd < 0) {
                        LOGE("SRS client server_fd is negative, aborting!");
                        return -1;
                }
 
-               rc = srs_server_accept(srs_server);
-
-               LOGE("SRS server accept!");
-
-               FD_ZERO(&fds);
-               FD_SET(srs_server->client_fd, &fds);
-
-               while(1) {
-                       if(srs_server->client_fd < 0)
-                               break;
-
-                       select(FD_SETSIZE, &fds, NULL, NULL, NULL);
-
-                       if(FD_ISSET(srs_server->client_fd, &fds)) {
-                               if(srs_server_recv(srs_server, &srs_message) < 0) {
-                                       LOGE("SRS recv failed, aborting!");
-                                       break;
-                               }
-
-                               LOGD("SRS recv: command=%d data_len=%d", srs_message.command, srs_message.data_len);
-                               hex_dump(srs_message.data, srs_message.data_len);
-
-                               srs_dispatch(&srs_message);
-
-                               if(srs_message.data != NULL)
-                                       free(srs_message.data);
-                       }
+               rc = accept(server_fd, (struct sockaddr*)&client_addr,
+                       &client_addr_len);
+               if (rc < 0) {
+                       LOGE("SRS Failed to accept errno %d error %s",
+                               errno, strerror(errno));
+                       return -1;
                }
-
-               if(srs_server->client_fd > 0) {
-                       close(srs_server->client_fd);
-                       srs_server->client_fd = -1;
+               LOGI("SRS accepted fd %d", rc);
+               int *pfd = (int*)malloc(sizeof(int));
+               if (!pfd) {
+                       LOGE("out of memory for the client socket");
+                       close(rc);
+                       return -1;
                }
+               *pfd = rc;
 
-               LOGE("SRS server client ended!");
+               pthread_t t;
+               if (pthread_create(&t, NULL, srs_process_client, pfd)) {
+                       LOGE("SRS failed to start client thread errno %d error %s",
+                               errno, strerror(errno));
+                       close(rc);
+                       return -1;
+               }
        }
 
        return 0;
 }
 
-int srs_create(struct ril_client *client)
+static int srs_create(struct ril_client *client)
 {
-       struct srs_server *srs_server;
+       int *srs_server = NULL;
 
        LOGD("Creating new SRS client");
 
-       srs_server = srs_server_new();
-       client->object = (void *) srs_server;
+       srs_server = malloc(sizeof(int));
+       if (!srs_server) {
+               LOGE("SRS out of memory for server fd");
+               goto fail;
+       }
 
-       if(srs_server_open(srs_server) < 0) {
+       client->object = (void *) srs_server;
+       if((*srs_server = srs_server_open()) < 0) {
                LOGE("%s: samsung-ril-socket server open failed", __FUNCTION__);
-               return -1;
+               goto fail;
        }
 
        return 0;
+
+fail:
+       if (srs_server) {
+               free(srs_server);
+       }
+       return -1;
 }
 
-int srs_destroy(struct ril_client *client)
+static int srs_destroy(struct ril_client *client)
 {
-       struct srs_server *srs_server = (struct srs_server *) client->object;
-       
-       if(srs_server == NULL)
+       if (!client) {
                return 0;
+       }
 
-       if(srs_server->client_fd)
-               close(srs_server->client_fd);
-       
-       close(srs_server->server_fd);
+       int *srs_server = (int*) client->object;
+       if (!srs_server) {
+               return 0;
+       }
 
-       srs_server_free(srs_server);
+       close(*srs_server);
+       free(srs_server);
 
        return 0;
 }
diff --git a/srs.h b/srs.h
index 2ef9c8c..5e01383 100644 (file)
--- a/srs.h
+++ b/srs.h
 
 #include <samsung-ril-socket.h>
 
-struct srs_server {
-       int server_fd;
-       int client_fd;
-       struct sockaddr_un client_addr;
-       int client_addr_len;
-};
-
 extern struct ril_client_funcs srs_client_funcs;
-
-struct srs_server *srs_server_new(void);
-int srs_server_send(unsigned short command, void *data, int data_len);
-int srs_server_recv(struct srs_server *srs_server, struct srs_message *message);
-int srs_server_accept(struct srs_server *srs_server);
-int srs_server_open(struct srs_server *srs_server);
-
-void srs_control_ping(struct srs_message *message);
+extern void srs_control_ping(int fd, struct srs_message *message);
 
 #endif