16ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/******************************************************************************
266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
36ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  Copyright (C) 2009-2012 Broadcom Corporation
466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
56ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  Licensed under the Apache License, Version 2.0 (the "License");
66ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  you may not use this file except in compliance with the License.
76ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  You may obtain a copy of the License at:
866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
96ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  http://www.apache.org/licenses/LICENSE-2.0
1066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
116ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  Unless required by applicable law or agreed to in writing, software
126ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  distributed under the License is distributed on an "AS IS" BASIS,
136ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
146ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  See the License for the specific language governing permissions and
156ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  limitations under the License.
1666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
176ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/
1866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani/************************************************************************************
2066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
2166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *  Filename:      btif_sock_thread.c
2266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
2366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *  Description:   socket select thread
2466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
2566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani *
2666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani ***********************************************************************************/
2766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
2866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <hardware/bluetooth.h>
2966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <hardware/bt_sock.h>
3066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
3166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani//bta_jv_co_rfc_data
3266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <stdio.h>
3366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <stdlib.h>
3466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <errno.h>
3566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <string.h>
3666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <sys/types.h>
3766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <sys/socket.h>
3866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <sys/un.h>
3966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <time.h>
4066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <fcntl.h>
4166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <unistd.h>
4266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <signal.h>
4366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <pthread.h>
4466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <ctype.h>
4566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
4666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <sys/select.h>
4766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <sys/poll.h>
4866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <cutils/sockets.h>
4954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy#include <alloca.h>
5066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
5166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define LOG_TAG "BTIF_SOCK"
5266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "btif_common.h"
5366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "btif_util.h"
5466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
5566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "bd.h"
5666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
5766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "bta_api.h"
5866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "btif_sock.h"
5966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "btif_sock_thread.h"
6066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include "btif_sock_util.h"
6166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
6266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <cutils/log.h>
63a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie#define asrt(s) if(!(s)) APPL_TRACE_ERROR3("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
6466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define print_events(events) do { \
65a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG1("print poll event:%x", events); \
66a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLIN) APPL_TRACE_DEBUG0(  "   POLLIN "); \
67a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLPRI) APPL_TRACE_DEBUG0( "   POLLPRI "); \
68a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLOUT) APPL_TRACE_DEBUG0( "   POLLOUT "); \
69a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLERR) APPL_TRACE_DEBUG0( "   POLLERR "); \
70a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLHUP) APPL_TRACE_DEBUG0( "   POLLHUP "); \
71a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLNVAL) APPL_TRACE_DEBUG0("   POLLNVAL "); \
72a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (events & POLLRDHUP) APPL_TRACE_DEBUG0("   POLLRDHUP"); \
7366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    } while(0)
7466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
7566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define MAX_THREAD 8
7666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define MAX_POLL 64
7766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define POLL_EXCEPTION_EVENTS (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)
7866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define IS_EXCEPTION(e) ((e) & POLL_EXCEPTION_EVENTS)
7966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define IS_READ(e) ((e) & POLLIN)
8066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#define IS_WRITE(e) ((e) & POLLOUT)
8166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani/*cmd executes in socket poll thread */
8254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy#define CMD_WAKEUP       1
8354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy#define CMD_EXIT         2
8454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy#define CMD_ADD_FD       3
8554cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy#define CMD_USER_PRIVATE 4
8666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
8766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanitypedef struct {
8866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    struct pollfd pfd;
8966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    uint32_t user_id;
9066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int type;
9166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int flags;
9266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani} poll_slot_t;
9366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanitypedef struct {
9466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int cmd_fdr, cmd_fdw;
9566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int poll_count;
9666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    poll_slot_t ps[MAX_POLL];
9766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int psi[MAX_POLL]; //index of poll slot
9866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    volatile pid_t thread_id;
9966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    btsock_signaled_cb callback;
10054cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    btsock_cmd_cb cmd_callback;
10166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int used;
10266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani} thread_slot_t;
10366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic thread_slot_t ts[MAX_THREAD];
10466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
10566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
10666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
10766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void *sock_poll_thread(void *arg);
10866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void close_cmd_fd(int h);
10966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
11066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id);
11166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
11266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic pthread_mutex_t thread_slot_lock;
11366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
11466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
11566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void set_socket_blocking(int s, int blocking)
11666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
11766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int opts;
11866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    opts = fcntl(s, F_GETFL);
119a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    if (opts<0) APPL_TRACE_ERROR1("set blocking (%s)", strerror(errno));
12066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(blocking)
12166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        opts &= ~O_NONBLOCK;
12266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    else opts |= O_NONBLOCK;
12366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    fcntl(s, F_SETFL, opts);
12466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
12566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
12666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline int create_server_socket(const char* name)
12766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
12866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int s = socket(AF_LOCAL, SOCK_STREAM, 0);
129a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG1("covert name to android abstract name:%s", name);
13066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) >= 0)
13166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
13266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(listen(s, 5) == 0)
13366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
134a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie            APPL_TRACE_DEBUG2("listen to local socket:%s, fd:%d", name, s);
13566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return s;
13666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
137a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        else APPL_TRACE_ERROR3("listen to local socket:%s, fd:%d failed, errno:%d", name, s, errno);
13866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
139a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    else APPL_TRACE_ERROR3("create local socket:%s fd:%d, failed, errno:%d", name, s, errno);
14066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    close(s);
14166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return -1;
14266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
14366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline int connect_server_socket(const char* name)
14466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
14566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int s = socket(AF_LOCAL, SOCK_STREAM, 0);
14666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    set_socket_blocking(s, TRUE);
14766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(socket_local_client_connect(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) >= 0)
14866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
149a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_DEBUG2("connected to local socket:%s, fd:%d", name, s);
15066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return s;
15166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
152a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    else APPL_TRACE_ERROR3("connect to local socket:%s, fd:%d failed, errno:%d", name, s, errno);
15366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    close(s);
15466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return -1;
15566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
15666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline int accept_server_socket(int s)
15766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
15866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    struct sockaddr_un client_address;
15966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    socklen_t clen;
16066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int fd = accept(s, (struct sockaddr*)&client_address, &clen);
161a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG2("accepted fd:%d for server fd:%d", fd, s);
16266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return fd;
16366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
16466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline pthread_t create_thread(void *(*start_routine)(void *), void * arg)
16566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
16666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    pthread_attr_t thread_attr;
16766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    pthread_attr_init(&thread_attr);
16866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
16966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    pthread_t thread_id = -1;
17066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if( pthread_create(&thread_id, &thread_attr, start_routine, arg)!=0 )
17166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
172a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("pthread_create : %s", strerror(errno));
17366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return -1;
17466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
17566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return thread_id;
17666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
17766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void init_poll(int cmd_fd);
17866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic int alloc_thread_slot()
17966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
18066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int i;
18166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    //revserd order to save guard uninitialized access to 0 index
18266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    for(i = MAX_THREAD - 1; i >=0; i--)
1838e6e9356d5386501d5e0988ce23d0c9aaed31a64zzy    {
184a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_DEBUG2("ts[%d].used:%d", i, ts[i].used);
18566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(!ts[i].used)
1868e6e9356d5386501d5e0988ce23d0c9aaed31a64zzy        {
1878e6e9356d5386501d5e0988ce23d0c9aaed31a64zzy            ts[i].used = 1;
18866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return i;
1898e6e9356d5386501d5e0988ce23d0c9aaed31a64zzy        }
1908e6e9356d5386501d5e0988ce23d0c9aaed31a64zzy    }
191a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_ERROR0("execeeded max thread count");
19266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return -1;
19366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
19466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void free_thread_slot(int h)
19566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
19666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(0 <= h && h < MAX_THREAD)
19766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
19866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        close_cmd_fd(h);
19966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ts[h].used = 0;
20066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
201a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    else APPL_TRACE_ERROR1("invalid thread handle:%d", h);
20266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
20366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint btsock_thread_init()
20466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
20554cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    static int initialized;
206a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG1("in initialized:%d", initialized);
20754cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    if(!initialized)
20866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
20954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        initialized = 1;
21054cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        init_slot_lock(&thread_slot_lock);
21154cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        int h;
21254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        for(h = 0; h < MAX_THREAD; h++)
21354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        {
21454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].cmd_fdr = ts[h].cmd_fdw = -1;
21554cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].used = 0;
21654cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].thread_id = -1;
21754cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].poll_count = 0;
21854cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].callback = NULL;
21954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].cmd_callback = NULL;
22054cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        }
22166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
22266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return TRUE;
22366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
22454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzyint btsock_thread_create(btsock_signaled_cb callback, btsock_cmd_cb cmd_callback)
22566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
22666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int ret = FALSE;
22754cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    asrt(callback || cmd_callback);
22866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    lock_slot(&thread_slot_lock);
22966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int h = alloc_thread_slot();
23066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    unlock_slot(&thread_slot_lock);
231a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG1("alloc_thread_slot ret:%d", h);
23266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(h >= 0)
23366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
23466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        init_poll(h);
23566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if((ts[h].thread_id = create_thread(sock_poll_thread, (void*)h)) != -1)
23666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
237a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie            APPL_TRACE_DEBUG2("h:%d, thread id:%d", h, ts[h].thread_id);
23866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            ts[h].callback = callback;
23954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            ts[h].cmd_callback = cmd_callback;
24066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
24166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        else
24266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
24366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            free_thread_slot(h);
24466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            h = -1;
24566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
24666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
24766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return h;
24866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
24966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
25066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani/* create dummy socket pair used to wake up select loop */
25166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void init_cmd_fd(int h)
25266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
25366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    asrt(ts[h].cmd_fdr == -1 && ts[h].cmd_fdw == -1);
25466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(socketpair(AF_UNIX, SOCK_STREAM, 0, &ts[h].cmd_fdr) < 0)
25566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
256a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("socketpair failed: %s", strerror(errno));
25766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return;
25866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
259a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG3("h:%d, cmd_fdr:%d, cmd_fdw:%d", h, ts[h].cmd_fdr, ts[h].cmd_fdw);
26066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    //add the cmd fd for read & write
26166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    add_poll(h, ts[h].cmd_fdr, 0, SOCK_THREAD_FD_RD, 0);
26266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
26366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void close_cmd_fd(int h)
26466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
26566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(ts[h].cmd_fdr != -1)
26666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
26766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        close(ts[h].cmd_fdr);
26866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ts[h].cmd_fdr = -1;
26966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
27066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(ts[h].cmd_fdw != -1)
27166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
27266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        close(ts[h].cmd_fdw);
27366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ts[h].cmd_fdw = -1;
27466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
27566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
27666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanitypedef struct
27766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
27866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int id;
27966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int fd;
28066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int type;
28166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int flags;
28266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    uint32_t user_id;
28366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani} sock_cmd_t;
28466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint btsock_thread_add_fd(int h, int fd, int type, int flags, uint32_t user_id)
28566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
28666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(h < 0 || h >= MAX_THREAD)
28766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
288a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("invalid bt thread handle:%d", h);
28966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
29066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
29166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(ts[h].cmd_fdw == -1)
29266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
293a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR0("cmd socket is not created. socket thread may not initialized");
29466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
29566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
29666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(flags & SOCK_THREAD_ADD_FD_SYNC)
29766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
29866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //must executed in socket poll thread
2997f58927df0ee3f2f38367efe62c8901a760eeaa4zzy        if(ts[h].thread_id == pthread_self())
3007f58927df0ee3f2f38367efe62c8901a760eeaa4zzy        {
3017f58927df0ee3f2f38367efe62c8901a760eeaa4zzy            //cleanup one-time flags
3027f58927df0ee3f2f38367efe62c8901a760eeaa4zzy            flags &= ~SOCK_THREAD_ADD_FD_SYNC;
3037f58927df0ee3f2f38367efe62c8901a760eeaa4zzy            add_poll(h, fd, type, flags, user_id);
3047f58927df0ee3f2f38367efe62c8901a760eeaa4zzy            return TRUE;
3057f58927df0ee3f2f38367efe62c8901a760eeaa4zzy        }
306a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_DEBUG0("THREAD_ADD_FD_SYNC is not called in poll thread, fallback to async");
30766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
30866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id};
309a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG2("adding fd:%d, flags:0x%x", fd, flags);
31066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
31166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
31254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzyint btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id)
31354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy{
31454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    if(h < 0 || h >= MAX_THREAD)
31554cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    {
316a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("invalid bt thread handle:%d", h);
31754cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        return FALSE;
31854cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    }
31954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    if(ts[h].cmd_fdw == -1)
32054cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    {
321a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR0("cmd socket is not created. socket thread may not initialized");
32254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        return FALSE;
32354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    }
32454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    sock_cmd_t cmd = {CMD_USER_PRIVATE, 0, type, size, user_id};
325a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG3("post cmd type:%d, size:%d, h:%d, ", type, size, h);
32654cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    sock_cmd_t* cmd_send = &cmd;
32754cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    int size_send = sizeof(cmd);
32854cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    if(data && size)
32954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    {
33054cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        size_send = sizeof(cmd) + size;
33154cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        cmd_send = (sock_cmd_t*)alloca(size_send);
33254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        if(cmd_send)
33354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        {
33454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            *cmd_send = cmd;
33554cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            memcpy(cmd_send + 1, data, size);
33654cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        }
33754cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        else
33854cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        {
339a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie            APPL_TRACE_ERROR3("alloca failed at h:%d, cmd type:%d, size:%d", h, type, size_send);
34054cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            return FALSE;
34154cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        }
34254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    }
34354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    return send(ts[h].cmd_fdw, cmd_send, size_send, 0) == size_send;
34454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy}
34566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint btsock_thread_wakeup(int h)
34666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
34766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(h < 0 || h >= MAX_THREAD)
34866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
349a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("invalid bt thread handle:%d", h);
35066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
35166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
35266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(ts[h].cmd_fdw == -1)
35366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
354a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("thread handle:%d, cmd socket is not created", h);
35566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
35666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
35766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    sock_cmd_t cmd = {CMD_WAKEUP, 0, 0, 0, 0};
35866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
35966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
36066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint btsock_thread_exit(int h)
36166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
36266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(h < 0 || h >= MAX_THREAD)
36366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
364a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("invalid bt thread handle:%d", h);
36566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
36666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
36766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(ts[h].cmd_fdw == -1)
36866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
369a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR0("cmd socket is not created");
37066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
37166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
37266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    sock_cmd_t cmd = {CMD_EXIT, 0, 0, 0, 0};
37366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd))
37466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
37566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        pthread_join(ts[h].thread_id, 0);
37666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        lock_slot(&thread_slot_lock);
37766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        free_thread_slot(h);
37866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        unlock_slot(&thread_slot_lock);
37966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return TRUE;
38066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
38166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return FALSE;
38266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
38366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void init_poll(int h)
38466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
38566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int i;
38666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ts[h].poll_count = 0;
38766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ts[h].thread_id = -1;
38866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ts[h].callback = NULL;
38954cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy    ts[h].cmd_callback = NULL;
39066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    for(i = 0; i < MAX_POLL; i++)
39166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
39266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ts[h].ps[i].pfd.fd = -1;
39366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ts[h].psi[i] = -1;
39466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
39566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    init_cmd_fd(h);
39666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
39766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline unsigned int flags2pevents(int flags)
39866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
39966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    unsigned int pevents = 0;
40066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(flags & SOCK_THREAD_FD_WR)
40166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        pevents |= POLLOUT;
40266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(flags & SOCK_THREAD_FD_RD)
40366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        pevents |= POLLIN;
40466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    pevents |= POLL_EXCEPTION_EVENTS;
40566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return pevents;
40666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
40766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
40866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void set_poll(poll_slot_t* ps, int fd, int type, int flags, uint32_t user_id)
40966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
41066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ps->pfd.fd = fd;
41166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ps->user_id = user_id;
41266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(ps->type != 0 && ps->type != type)
413a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR2("poll socket type should not changed! type was:%d, type now:%d", ps->type, type);
41466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ps->type = type;
41566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ps->flags = flags;
41666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ps->pfd.events = flags2pevents(flags);
41766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ps->pfd.revents = 0;
41866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
41966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id)
42066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
42166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    asrt(fd != -1);
42266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int i;
42366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int empty = -1;
42466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    poll_slot_t* ps = ts[h].ps;
42566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
42666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    for(i = 0; i < MAX_POLL; i++)
42766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
42866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(ps[i].pfd.fd == fd)
42966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
43066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            asrt(ts[h].poll_count < MAX_POLL);
43166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
43266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            set_poll(&ps[i], fd, type, flags | ps[i].flags, user_id);
43366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return;
43466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
43566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        else if(empty < 0 && ps[i].pfd.fd == -1)
43666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            empty = i;
43766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
43866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(empty >= 0)
43966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
44066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        asrt(ts[h].poll_count < MAX_POLL);
44166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        set_poll(&ps[empty], fd, type, flags, user_id);
44266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ++ts[h].poll_count;
44366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return;
44466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
445a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_ERROR1("exceeded max poll slot:%d!", MAX_POLL);
44666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
44766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic inline void remove_poll(int h, poll_slot_t* ps, int flags)
44866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
44966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(flags == ps->flags)
45066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
45166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //all monitored events signaled. To remove it, just clear the slot
45266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        --ts[h].poll_count;
45366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        memset(ps, 0, sizeof(*ps));
45466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ps->pfd.fd = -1;
45566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
45666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    else
45766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
45866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //one read or one write monitor event signaled, removed the accordding bit
45966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ps->flags &= ~flags;
46066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //update the poll events mask
46166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ps->pfd.events = flags2pevents(ps->flags);
46266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
46366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
46466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic int process_cmd_sock(int h)
46566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
46666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    sock_cmd_t cmd = {-1, 0, 0, 0, 0};
46766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int fd = ts[h].cmd_fdr;
46866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
46966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
470a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        APPL_TRACE_ERROR1("recv cmd errno:%d", errno);
47166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return FALSE;
47266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
473a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG1("cmd.id:%d", cmd.id);
47466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    switch(cmd.id)
47566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
47666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        case CMD_ADD_FD:
47766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            add_poll(h, cmd.fd, cmd.type, cmd.flags, cmd.user_id);
47866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            break;
47966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        case CMD_WAKEUP:
48066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            break;
48154cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy        case CMD_USER_PRIVATE:
48254cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            asrt(ts[h].cmd_callback);
48354cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            if(ts[h].cmd_callback)
48454cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy                ts[h].cmd_callback(fd, cmd.type, cmd.flags, cmd.user_id);
48554cdfabe7c0ed98732d0641ffe8b19ff7284e7d4zzy            break;
48666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        case CMD_EXIT:
48766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return FALSE;
48866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        default:
489a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie            APPL_TRACE_DEBUG1("unknown cmd: %d", cmd.id);
49066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani             break;
49166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
49266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return TRUE;
49366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
49466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void process_data_sock(int h, struct pollfd *pfds, int count)
49566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
49666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    asrt(count <= ts[h].poll_count);
49766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int i;
49866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    for( i= 1; i < ts[h].poll_count; i++)
49966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
50066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(pfds[i].revents)
50166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
50266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            int ps_i = ts[h].psi[i];
50366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            asrt(pfds[i].fd == ts[h].ps[ps_i].pfd.fd);
50466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            uint32_t user_id = ts[h].ps[ps_i].user_id;
50566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            int type = ts[h].ps[ps_i].type;
50666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            int flags = 0;
50766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            print_events(pfds[i].revents);
50866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if(IS_READ(pfds[i].revents))
50966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            {
51066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                flags |= SOCK_THREAD_FD_RD;
51166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            }
51266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if(IS_WRITE(pfds[i].revents))
51366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            {
51466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                flags |= SOCK_THREAD_FD_WR;
51566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            }
51666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if(IS_EXCEPTION(pfds[i].revents))
51766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            {
51866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                flags |= SOCK_THREAD_FD_EXCEPTION;
51966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                //remove the whole slot not flags
52066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                remove_poll(h, &ts[h].ps[ps_i], ts[h].ps[ps_i].flags);
52166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            }
52266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            else if(flags)
52366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                 remove_poll(h, &ts[h].ps[ps_i], flags); //remove the monitor flags that already processed
52466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if(flags)
52566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                ts[h].callback(pfds[i].fd, type, flags, user_id);
52666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
52766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
52866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
529a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie
53066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void prepare_poll_fds(int h, struct pollfd* pfds)
53166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
53266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int count = 0;
53366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int ps_i = 0;
53466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int pfd_i = 0;
53566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    asrt(ts[h].poll_count <= MAX_POLL);
53666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    memset(pfds, 0, sizeof(pfds[0])*ts[h].poll_count);
53766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    while(count < ts[h].poll_count)
53866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
53966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(ps_i >= MAX_POLL)
54066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
541a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie            APPL_TRACE_ERROR4("exceed max poll range, ps_i:%d, MAX_POLL:%d, count:%d, ts[h].poll_count:%d",
54266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                    ps_i, MAX_POLL, count, ts[h].poll_count);
54366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return;
54466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
54566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(ts[h].ps[ps_i].pfd.fd >= 0)
54666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
54766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            pfds[pfd_i] =  ts[h].ps[ps_i].pfd;
54866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            ts[h].psi[pfd_i] = ps_i;
54966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            count++;
55066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            pfd_i++;
55166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
55266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        ps_i++;
55366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
55466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
55566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryanistatic void *sock_poll_thread(void *arg)
55666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
55766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    struct pollfd pfds[MAX_POLL];
55866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    memset(pfds, 0, sizeof(pfds));
55966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int h = (int)arg;
56066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    for(;;)
56166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
56266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        prepare_poll_fds(h, pfds);
56366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        int ret = poll(pfds, ts[h].poll_count, -1);
56466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(ret == -1)
56566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
566a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie            APPL_TRACE_ERROR2("poll ret -1, exit the thread, errno:%d, err:%s", errno, strerror(errno));
56766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            break;
56866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
56966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(ret != 0)
57066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
57166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            int need_process_data_fd = TRUE;
57266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if(pfds[0].revents) //cmd fd always is the first one
57366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            {
57466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                asrt(pfds[0].fd == ts[h].cmd_fdr);
57566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                if(!process_cmd_sock(h))
57666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                {
577a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie                    APPL_TRACE_DEBUG1("h:%d, process_cmd_sock return false, exit...", h);
57866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                    break;
57966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                }
58066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                if(ret == 1)
58166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                    need_process_data_fd = FALSE;
58266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                else ret--; //exclude the cmd fd
58366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            }
58466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if(need_process_data_fd)
58566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                process_data_sock(h, pfds, ret);
58666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
587a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie        else {APPL_TRACE_DEBUG1("no data, select ret: %d", ret)};
58866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
58966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    ts[h].thread_id = -1;
590a0d1575ab0b024b8198c27e69df6c9a0d55cbeeeMatthew Xie    APPL_TRACE_DEBUG1("socket poll thread exiting, h:%d", h);
59166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return 0;
59266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
59366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
594